Freitag, 23. November 2012

Issues with Lookup-Fields with each more than 20 items

If you have multiple lookup-fields in your form which reference to more than 20 items (hardcoded limit in the LookupField-Control!), you may notice to the display and behaviour of your control:

- The rendering of the field switches from select-tag to an input-tag and an img-tag. A click on the image shows a layer with the selectfield.
- This only occures to Internet Explorer, not to Firefox.

The naughty thing on this is the issue, that the selectfield-layer appears below the first-clicked lookup-field, no matter, which lookupfield you click afterwards.

Click on the first lookup:



Click on the second lookup:



This bug can be fixed by override a function in the core.js that must be loaded immediatly in the masterpage. A good piece of working code I found here today: http://dipaktele.blogspot.de/2012/07/two-lookup-field-with-more-than-20.html

I copied the code found on this page and added it here:


function FilterChoice(opt, ctrl, strVal, filterVal) {
if (typeof (opt) != "undefined") {
var i,
cOpt = 0,
bSelected = false,
strHtml = "",
strId = opt.id,
strName = opt.name,
strMatch = "",
strMatchVal = "",
strOpts = ctrl.choices,
rgopt = strOpts.split("|"),
offSet = $(ctrl).position(),
x = offSet.left,
y = offSet.top 15,
strHidden = ctrl.optHid,
iMac = rgopt.length - 1,
iMatch = -1,
unlimitedLength = false,
strSelectedLower = "";
if (opt != null && opt.selectedIndex >= 0) {
bSelected = true;
strSelectedLower = opt.options[opt.selectedIndex].innerText;
}
for (i = 0; i < rgopt.length; i = i 2) {
var strOpt = rgopt[i];
while (i < iMac - 1 && rgopt[i 1].length == 0) {
strOpt = strOpt "|";
i ;
if (i < iMac - 1) {
strOpt = strOpt rgopt[i 1];
}
i ;
}
var strValue = rgopt[i 1];
var strLowerOpt = strOpt.toLocaleLowerCase();
var strLowerVal = strVal.toLocaleLowerCase();
if (filterVal.length != 0)
bSelected = true;
if (strLowerOpt.indexOf(strLowerVal) == 0) {
var strLowerFilterVal = filterVal.toLocaleLowerCase();
if ((strLowerFilterVal.length != 0) && (strLowerOpt.indexOf(strLowerFilterVal) == 0) && (strMatch.length == 0))
bSelected = false;
if (strLowerOpt.length > 20) {
unlimitedLength = true;
}
if (!bSelected || strLowerOpt == strSelectedLower) {
strHtml = "<option selected value=\"" strValue "\">" STSHtmlEncode(strOpt) "</option>";
bSelected = true;
strMatch = strOpt;
strMatchVal = strValue;
iMatch = i;
}
else {
strHtml = "<option value=\"" strValue "\">" STSHtmlEncode(strOpt) "</option>";
}
cOpt ;
}
}
var strHandler = " onclick=\"HandleOptDblClick()\" onkeydown=\"HandleOptKeyDown()\"";
var strOptHtml = "";
if (unlimitedLength) {
strOptHtml = "<select tabIndex=\"-1\" ctrl=\"" ctrl.id "\" name=\"" strName "\" id=\"" strId "\"" strHandler;
}
else {
strOptHtml = "<select class=\"ms-lookuptypeindropdown\" tabIndex=\"-1\" ctrl=\"" ctrl.id "\" name=\"" strName "\" id=\"" strId "\"" strHandler;
}
if (cOpt == 0) {
strOptHtml = " style=\"display:none;position:absolute;z-index:2;left:" x "px;top:" y "px\" onfocusout=\"OptLoseFocus(this)\"></select>";
}
else {
strOptHtml = " style=\"position:absolute;z-index:2;left:" x "px;top:" y "px\"" " size=\"" (cOpt <= 8 ? cOpt : 8) "\"" (cOpt == 1 ? "multiple=\"true\"" : "") " onfocusout=\"OptLoseFocus(this)\">" strHtml "</select>";
}
opt.outerHTML = strOptHtml;
var hid = document.getElementById(strHidden);
if (iMatch != 0 || rgopt[1] != "0")
hid.value = strMatchVal;
else
hid.value = "0";
if (iMatch != 0 || rgopt[1] != "0")
return strMatch;
else return "";
}
}

_spBodyOnLoadFunctionNames.push("FilterChoice");
function EnsureSelectElement(ctrl, strId) {
$("#" strId).remove();
var select = document.getElementById(strId);
if (select == null) {
select = document.createElement("SELECT");
ctrl.parentNode.appendChild(select);
select.outerHTML = "<select id=\"" strId "\" ctrl=\"" ctrl.id "\" class=\"ms-lookuptypeindropdown\" name=\"" strId "\" style=\"display:none\" onfocusout=\"OptLoseFocus(this)\"></select>";
FilterChoice(select, ctrl, ctrl.value, "");
}
return document.getElementById(strId); ;
}


After that, the select is displayed correctly:



Please be sure to include there functions in your own js-file that's loaded after the core.js and avoid modifying the original core.js.