SharePoint里如何解决超长LookUp字段需要双击的问题

摘要:

    如果LookUp字段里引用的列表数据超过20条的时候,Lookup字段将不通过Select标记进行输出,而是通过Textbox进行输出,微软希望提供的Textbox可以为用户提供输入过滤的功能,但是相应带来的问题却是用户需要通过双击而不是单击来选择Lookup下拉列表的内容,用户体验上并不友好。本文将通过Javascript的方式提供用户单击选择超长列表的方案。还有两种思路,一种是写一个自己的Lookup字段,注意Lookup字段不能被继承;另一种思路是通过控件的Adapter来改变输出时的行为。

问题介绍:

    如下图所示,我们可以看到第一个Test1字段引用的列表只有19条数据,但是Test2引用的列表却又近百条数据,显而易见的是两个下拉列表的样式并不一样,而且选择Test2下拉列表内容的时候我们会发现需要点击两次相应两目才能选中。

image

解决思路:

    我们查看HTML代码回发现针对Test1字段输出内容如下,采用的是HTML Select元素:

image

    但针对Test2字段输出内容如下,采用的是类型为Text的Input元素:

image

    进一步的我们查看Test2字段的HTML代码,我们会发现有几点内容值得关注:

   

    optHid属性:此属性指定了存储选中项目ID的隐藏控件;

    choices属性:此属性包含了需要显示的文本以及背后ID的所有信息;

    match属性:此属性包含被选中的内容的信息;

   

    当点击下拉列表的小箭头时实际调用了一个叫做showdropdown的方法,此方法来源于core.js文件,进一步的查看showdropdown方法的代码我们会发现这个方法调用EnsureSelectElement来在当前文本框后面添加一个Select元素来实现的,紧接着通过FilterChoice方法来为Select元素添加选项值,最后Select内容选择好以后调用SetCtrlFromOpt方法将文本内容设置到Text元素的Match属性,此外在FilterChoice还会将文本内容对应的Value值设置到Text元素的OptHid属性指定的隐藏控件里。最后再在Js中将值设置到Text元素文本框中。

    因而我们的思路是在画面加载结束后通过Javascript脚本生成一个Select元素,并通过choices里的内容将其初始化,然后设置其onchange事件,确保新的内容被选择后相应的值会设置到原始的文本框里,这样保存的时候就能够存到SharePoint里去,最后我们通过属性设置隐藏掉原始的文本框。

解决步骤:

第一步,引入JQuery库(可至Jquey.com网站下载),通过SharePoint Designer上传到相关列表的文件夹内,再通过SharePoint Designer打开newform.aspx页面,在PlaceHolderMain里面加入对该库的引用,例如:

<script type="text/javascript" src="jquery-1.6.1.min.js" > </script>

第二步,添加代码如下:

<script type="text/javascript">
$(document).ready(function() { 
    var ctrl1 = $("input[title='Test2']") 
    var ctrl = document.getElementById(ctrl1.attr('id')); 
    ctrl.style.display="none"; 
    var select=document.createElement("SELECT"); 
    ctrl.parentNode.appendChild(select); 
    select.outerHTML="<select id='“+ ctrl.opt + “' ctrl='"+ctrl.id+"' class='ms-lookuptypeindropdown' name='” + ctrl.opt + “'></select>"; 
    var opt = document.getElementById(ctrl.opt); 
    FillChoice(opt, ctrl, "");    
});

    首先我们通过JQuery的选择器获得了对原始的Test2字段的引用,紧接着我们通过此ID获得了对文本框控件本身的引用(有兴趣的朋友可以直修改剩余的代码完全通过Jquery来操作,本人为了图省事,大多数代码沿用SharePoint core.js里的内容),然后隐藏了该文本框控件,接着创建了一个Select元素,然后调用自定义的FillChoice方法对Select元素进行了初始化,该方法的算法借鉴了core.js的ilterChoice方法。

function FillChoice(opt, ctrl, strVal) 
{ 
    var i;    var strName=opt.name; 
    var strHtml=""; 
    var strId=opt.id; 
    var strOpts=ctrl.choices; 
    var rgopt=strOpts.split("|"); 
    var x=AbsLeft(ctrl); 
    var y=AbsTop(ctrl)+ctrl.offsetHeight; 
    var iMac=rgopt.length - 1; 
    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 (strLowerOpt.indexOf(strLowerVal)==0) 
        { 
           strHtml+="<option value=\""+strValue+"\">"+STSHtmlEncode(strOpt)+"</option>";        } 
    } 
    var strHandler=" onchange=HandleClick()"; 
    var strOptHtml=""; 
    strOptHtml="<select tabIndex='-1' ctrl='"+ctrl.id+"' name='"+strName+"' id='"+strId+"'"+strHandler; 
    strOptHtml+=" style='position:absolute;z-index:2;left:"+x+"px;top:"+y+"px'>"+strHtml+"</select>"; 
    
    opt.outerHTML=strOptHtml; 
}

 

function HandleClick() 
{ 
var opt = event.srcElement; 
var ctrl = document.getElementById(opt.ctrl); 
SetCtrlFromOpt(ctrl, opt); 
} 

    FillChoice方法通过提取原始文本框控件的choices属性值初始化了自定义的Select列表选项,注意onchange事件指定为HandleClick处理器。HandleClick事件调用core.js的SetCtrlFromOpt方法进行值得设置。

效果查看:

    保存后我们可以发现第二个字段的样式已经与正常小于20条时的样式一致且可以正常保存列表。

image

说明:

     该解决方案没有针对Firefox进行测试。

原文地址:https://www.cnblogs.com/johnsonwong/p/2078930.html