48 lines
18 KiB
JavaScript
48 lines
18 KiB
JavaScript
/*
|
|
ufd 0.6 : Unobtrusive Fast-filter Drop-down jQuery plugin.
|
|
|
|
Authors:
|
|
thetoolman@gmail.com
|
|
Kadalashvili.Vladimir@gmail.com
|
|
|
|
Version: 0.6
|
|
|
|
Website: http://code.google.com/p/ufd/
|
|
*/
|
|
|
|
(function(g){g.widget("ui.ufd",{_init:function(){this.created||this._create()},_create:function(){if(!this.created){this.created=true;if(this.element[0].tagName.toLowerCase()!="select"){this.destroy();return false}this.options=g.extend(true,{},this.options);this.visibleCount=0;this.selectbox=this.element;this.logNode=g(this.options.logSelector);this.overflowCSS=this.options.allowLR?"overflow":"overflowY";var a=this.selectbox.attr("name"),b=this.options.prefix+a;a=this.options.submitFreeText?a:b;var c=
|
|
"",d=this.selectbox.attr("id");if(d){c=this.options.prefix+d;this.labels=g("label[for='"+d+"']").attr("for",c)}this.options.submitFreeText&&this.selectbox.attr("name",b);if(this.options.calculateZIndex)this.options.zIndexPopup=this._calculateZIndex();this.css=b=this.options.css;this.options.useUiCss&&g.extend(this.css,this.options.uiCss);if(!b.skin)b.skin=this.options.skin;this.wrapper=g(['<span class="',b.wrapper," ",b.hidden," ",b.skin,'"><input type="text" id="',c,'" class="',b.input,'" name="',
|
|
a,'"/><button type="button" tabindex="-1" class="',b.button,'"><div class="',b.buttonIcon,'"/></button></span>'].join(""));this.dropdown=g(['<div class="',b.skin,'"><div class="',b.listWrapper," ",b.hidden,'"><div class="',b.listScroll,'"></div></div></div>'].join(""));this.selectbox.after(this.wrapper);this.getDropdownContainer().append(this.dropdown);this.input=this.wrapper.find("input");this.button=this.wrapper.find("button");this.listWrapper=this.dropdown.children(":first").css("z-index",this.options.zIndexPopup);
|
|
this.listScroll=this.listWrapper.children(":first");g.fn.bgiframe&&this.listWrapper.bgiframe();if(!this.options.listWidthFixed){this.listWrapper.css({width:50,"min-width":100});this.options.listWidthFixed=this.listWrapper.width()<100;this.listWrapper.css({width:null,"min-width":null})}this._populateFromMaster();this._initEvents()}},_initEvents:function(){var a=this,b=g.ui.keyCode,c,d,e,h=this.options.css;this.input.bind("keydown keypress keyup",function(f){d=f.type=="keypress";e=f.type=="keyup";c=
|
|
null;if(undefined===f.which)c=f.keyCode;else if(!d&&f.which!=0)c=f.keyCode;else return;switch(c){case b.HOME:case b.END:if(a.options.homeEndForCursor)return;case b.DOWN:case b.PAGE_DOWN:case b.UP:case b.PAGE_UP:case b.ENTER:a.stopEvent(f);default:}if(!e!=(c!=b.TAB&&c!=b.ENTER)){a.lastKey=c;switch(c){case b.SHIFT:case b.CONTROL:break;case b.DOWN:a.selectNext(false);break;case b.PAGE_DOWN:a.selectNext(true);break;case b.END:a.selectLast();break;case b.UP:a.selectPrev(false);break;case b.PAGE_UP:a.selectPrev(true);
|
|
break;case b.HOME:a.selectFirst();break;case b.ENTER:a.hideList();a.tryToSetMaster();a.inputFocus();break;case b.TAB:a.realLooseFocusEvent();break;case b.ESCAPE:a.hideList();a.revertSelected();break;default:a.showList();a.filter(false,true);break}}});this.input.bind("click",function(f){if(a.isDisabled)a.stopEvent(f);else if(!a.listVisible()){a.filter(true);a.inputFocus();a.showList()}});this.input.bind("focus",function(f){if(a.isDisabled)a.stopEvent(f);else a.internalFocus||a.realFocusEvent()});this.button.bind("mouseover",
|
|
function(){a.button.addClass(h.buttonHover)});this.button.bind("mouseout",function(){a.button.removeClass(h.buttonHover)});this.button.bind("mousedown",function(){a.button.addClass(h.buttonMouseDown)});this.button.bind("mouseup",function(){a.button.removeClass(h.buttonMouseDown)});this.button.bind("click",function(f){if(a.isDisabled)a.stopEvent(f);else if(a.listVisible()){a.hideList();a.inputFocus()}else{a.filter(true);a.inputFocus();a.showList()}});this.listScroll.bind("DOMMouseScroll mousewheel",
|
|
function(f){a.stopEvent(f);f=f?f:window.event;f=f.detail?f.detail*-1:f.wheelDelta/40;f=a.listScroll.scrollTop()+(f>0?-1*a.itemHeight:1*a.itemHeight);a.listScroll.scrollTop(f)});this.listScroll.bind("mouseover mouseout click",function(f){if("LI"==f.target.nodeName.toUpperCase()){a.setActiveTimeout&&clearTimeout(a.setActiveTimeout);if("mouseout"==f.type){g(f.target).removeClass(h.liActive);a.setActiveTimeout=setTimeout(function(){g(a.selectedLi).addClass(h.liActive)},a.options.delayYield)}else if("mouseover"==
|
|
f.type){a.selectedLi!=f.target&&g(a.selectedLi).removeClass(h.liActive);g(f.target).addClass(h.liActive)}else{a.stopEvent(f);var j=g.trim(g(f.target).text());a.input.val(j);a.setActive(f.target);if(a.tryToSetMaster()){a.hideList();a.filter(true)}a.inputFocus()}}return true});this.selectbox.bind("change.ui.ufd",function(){if(a.isUpdatingMaster){a.isUpdatingMaster=false;return true}a.revertSelected()});this._myDocClickHandler=function(f){a.button.get(0)==f.target||a.input.get(0)==f.target||a.internalFocus&&
|
|
a.realLooseFocusEvent()};g(document).bind("click.ui.ufd",this._myDocClickHandler);if(this.options.polling){a=this;this._myPollId=setInterval(function(){a.dimensioned||a.setDimensions();if(a.selectbox[0].disabled!=a.isDisabled)a.selectbox[0].disabled?a.disable():a.enable()},a.options.polling)}},realFocusEvent:function(){this.internalFocus=true;this._triggerEventOnMaster("focus");this.wrapper.addClass(this.options.css.skin+"-"+this.options.css.inputFocus);this.input.addClass(this.options.css.inputFocus);
|
|
this.button.addClass(this.options.css.inputFocus);this.filter(true);this.inputFocus();this.showList()},realLooseFocusEvent:function(){this.internalFocus=false;this.hideList();this.wrapper.removeClass(this.options.css.skin+"-"+this.options.css.inputFocus);this.input.removeClass(this.options.css.inputFocus);this.button.removeClass(this.options.css.inputFocus);this.tryToSetMaster();this._triggerEventOnMaster("blur")},_triggerEventOnMaster:function(a){if(document.createEvent){var b=document.createEvent("HTMLEvents");
|
|
b.initEvent(a,true,true);this.selectbox.get(0).dispatchEvent(b)}else document.createEventObject&&this.selectbox.get(0).fireEvent("on"+a)},inputFocus:function(){this.input.focus();this.getCurrentTextValue().length&&this.selectAll()},inputBlur:function(){this.input.blur()},showList:function(){if(!this.listVisible()){this.listWrapper.removeClass(this.css.hidden);this.setListDisplay()}},hideList:function(){if(this.listVisible()){this.listWrapper.addClass(this.css.hidden);this.listItems.removeClass(this.css.hidden)}},
|
|
filter:function(a,b){var c=this;this.updateOnTimeout&&clearTimeout(this.updateOnTimeout);this.filterOnTimeout&&clearTimeout(this.filterOnTimeout);this.filterOnTimeout=this.updateOnTimeout=null;var d=c.getCurrentTextValue(),e=function(){var f=c.trie.find(d);c.trie.matches=f.matches;c.trie.misses=f.misses;c.updateOnTimeout=setTimeout(function(){h()},c.options.delayYield)},h=function(){var f=c.getActive();c.options.addEmphasis&&c.emphasis(c.trie.matches,true,d);c.visibleCount=c.overwriteClass(c.trie.matches,
|
|
"");if(a||!c.trie.matches.length){c.visibleCount+=c.overwriteClass(c.trie.misses,"");c.options.addEmphasis&&c.emphasis(c.trie.misses,false,d)}else c.overwriteClass(c.trie.misses,c.css.hidden);if(!f.hasClass(c.css.hidden)&&f.length&&c.trie.matches.length)c.setActive(f.get(0));else{f=c.listItems.filter(":visible:first");c.setActive(f.get(0))}c.setListDisplay()};if(b)this.filterOnTimeout=setTimeout(function(){e()},this.options.delayFilter);else e()},_encodeDom:g("<div/>"),_encodeString:function(a){return g.trim(this._encodeDom.text(a).html())},
|
|
emphasis:function(a,b,c){var d,e,h,f,j;e=c.length||0;var k=this.selectbox.get(0).options;d=a.length;if(b=b&&e>0){j=this._encodeString(c).replace(/([\\\^\$*+[\]?{}.=!:(|)])/g,"\\$1");j=new RegExp("("+j+")","gi");this.hasEmphasis=true}for(;d--;){c=a[d];for(e=c.length;e--;){h=c[e];f=g.trim(k[h.getAttribute("name")].innerHTML);h.innerHTML=b?f.replace(j,"<em>$1</em>"):f}}},_timingMeasure_firebug:function(a,b){a?console.time(b):console.timeEnd(b)},_timingMeasure:function(a,b){this._timingMeasure_firebug(a,
|
|
b)},removeEmphasis:function(){if(this.hasEmphasis){this.hasEmphasis=false;for(var a=this.selectbox.get(0).options,b=this.list.get(0).getElementsByTagName("LI"),c=b.length,d;c--;){d=b[c];d.innerHTML=g.trim(a[d.getAttribute("name")].innerHTML)}}},tryToSetMaster:function(){var a=null,b=this.getActive();if(b.length)a=b.attr("name");if(a==null||a==""||a<0){this.options.submitFreeText||this.revertSelected();return false}b=this.selectbox.get(0);var c=b.selectedIndex,d=b.options[a];if(!this.options.submitFreeText||
|
|
this.input.val()==d.text){this.input.val(d.text);if(a!=c){this.isUpdatingMaster=true;b.selectedIndex=a;this._triggerEventOnMaster("change")}return true}return false},_populateFromMaster:function(){var a=!this.selectbox.filter("[disabled]").length;this.disable();this.trie=new i(this.options.infix,this.options.caseSensitive);this.trie.matches=[];this.trie.misses=[];var b=this,c=[];c.push("<ul>");var d=this.selectbox.get(0).options,e,h,f;h=d.length;for(f=0;h--;){e=d[f++];c.push('<li name="');c.push(e.index);
|
|
c.push('">');c.push(g.trim(e.innerHTML));c.push("</li>")}c.push("</ul>");this.listScroll.html(c.join(""));this.list=this.listScroll.find("ul:first");c=this.list.get(0).getElementsByTagName("LI");this.listItems=g(c);h=c.length;for(f=0;h--;){e=d[f];b.trie.add(g.trim(e.text),c[f++])}this.visibleCount=c.length;this.setInputFromMaster();this.selectedLi=null;this.dimensioned=false;this.setDimensions();a&&this.enable();this._moveAttrs(this.selectbox,this.input,this.options.moveAttrs)},_moveAttrs:function(a,
|
|
b,c){for(var d=0;d<c.length;++d){var e=c[d],h=a.attr(e);if(h){b.attr(e,h);a.removeAttr(e)}}},setDimensions:function(){if(this.selectIsWrapped||this.selectbox.filter(":visible").length)if(!(this.selectIsWrapped&&!this.wrapper.filter(":visible").length)){this.wrapper.addClass(this.css.hidden);if(this.selectIsWrapped&&(!this.options.manualWidth||this.options.unwrapForCSS)){this.wrapper.before(this.selectbox);this.selectIsWrapped=false}var a;if(this.options.manualWidth)a=this.options.manualWidth;else{a=
|
|
this.selectbox.outerWidth();if(a<this.options.minWidth)a=this.options.minWidth;else if(this.options.maxWidth&&a>this.options.maxWidth)a=this.options.maxWidth}var b=this.options.mimicCSS;for(propPtr in b){var c=b[propPtr];!b.hasOwnProperty(propPtr)||typeof c==="function"||this.wrapper.css(c,this.selectbox.css(c))}if(!this.selectIsWrapped){this.wrapper.get(0).appendChild(this.selectbox.get(0));this.selectIsWrapped=true}this.wrapper.removeClass(this.css.hidden);this.listWrapper.removeClass(this.css.hidden);
|
|
var d=this.button.outerWidth(true);b=this.wrapper.outerWidth()-this.wrapper.width();var e=this.input.outerWidth(true)-this.input.width();c=this.listScroll.outerWidth()-this.listScroll.width();this.input.width(a-d-e);this.wrapper.width(a);d=this.options.listWidthFixed?"width":"min-width";this.listWrapper.css(d,a+b);this.listScroll.css(d,a+b-c);this.listWrapper.addClass(this.css.hidden);this.dimensioned=true}},setInputFromMaster:function(){var a=this.selectbox.get(0),b="";try{b=a.options[a.selectedIndex].text}catch(c){}this.input.val(b)},
|
|
revertSelected:function(){this.setInputFromMaster();this.filter(true)},setListDisplay:function(){if(!this.itemHeight)this.itemHeight=this.listItems.filter("li:first").outerHeight(true);var a;if(this.visibleCount>this.options.listMaxVisible){a=this.options.listMaxVisible*this.itemHeight;this.listScroll.css(this.overflowCSS,"scroll")}else{a=this.visibleCount*this.itemHeight;this.listScroll.css(this.overflowCSS,"hidden")}this.listScroll.height(a);var b=this.listScroll.outerHeight();this.listWrapper.height(b);
|
|
var c=this.wrapper.offset(),d=this.wrapper.outerHeight(),e=c.top+d+b,h=g(window).height()+g(document).scrollTop(),f=c.left;if(e>h){this.listWrapper.addClass(this.css.listWrapperUp);b=c.top-b}else{this.listWrapper.removeClass(this.css.listWrapperUp);b=c.top+d}this.listWrapper.css("left",f);this.listWrapper.css("top",b);this.scrollTo();return a},getActive:function(){if(this.selectedLi==null)return g([]);return g(this.selectedLi)},setActive:function(a){g(this.selectedLi).removeClass(this.css.liActive);
|
|
this.selectedLi=a;g(this.selectedLi).addClass(this.css.liActive)},selectFirst:function(){this.afterSelect(this.listItems.filter(":not(.invisible):first"))},selectLast:function(){this.afterSelect(this.listItems.filter(":not(.invisible):last"))},selectPrev:function(a){this.afterSelect(this.searchRelativeVisible(false,a?this.options.pageLength:1))},selectNext:function(a){this.afterSelect(this.searchRelativeVisible(true,a?this.options.pageLength:1))},afterSelect:function(a){if(a!=null){this.setActive(a);
|
|
this.input.val(a.text());this.scrollTo();this.tryToSetMaster();this.inputFocus();this.removeEmphasis()}},searchRelativeVisible:function(a,b){var c=this.getActive();if(!c.length){this.selectFirst();return null}var d;do{d=c;do d=a?d.next():d.prev();while(d.length&&d.hasClass(this.css.hidden));if(d.length)c=d}while(--b);return c},scrollTo:function(){if("scroll"!=this.listScroll.css(this.overflowCSS))return false;var a=this.getActive();if(!a.length)return false;var b=Math.floor(a.position().top);a=a.outerHeight(true);
|
|
var c=this.listWrapper.height(),d=this.listScroll.scrollTop(),e=this.options.viewAhead*a;if(b<e)b=d+b-e;else if(b+a>=c-e)b=d+b-c+a+e;else return false;this.listScroll.scrollTop(b);return true},getCurrentTextValue:function(){return g.trim(this.input.val())},stopEvent:function(a){a=a?a:window.event;a.cancel=true;a.cancelBubble=true;a.returnValue=false;a.stopPropagation&&a.stopPropagation();a.preventDefault&&a.preventDefault()},overwriteClass:function(a,b){var c,d,e,h=0;for(d=a.length;d--;){c=a[d];e=
|
|
c.length;for(h+=e;e--;)c[e].setAttribute(g.ui.ufd.classAttr,b)}return h},listVisible:function(){return!this.listWrapper.hasClass(this.css.hidden)},disable:function(){this.hideList();this.isDisabled=true;this.button.addClass(this.css.buttonDisabled);this.input.addClass(this.css.inputDisabled);this.input.attr("disabled","disabled");this.selectbox.attr("disabled","disabled")},enable:function(){this.isDisabled=false;this.button.removeClass(this.css.buttonDisabled);this.input.removeClass(this.css.inputDisabled);
|
|
this.input.removeAttr("disabled");this.selectbox.removeAttr("disabled")},selectAll:function(){this.input.get(0).select()},getDropdownContainer:function(){var a=g("#"+this.options.dropDownID);a.length||(a=g("<div></div>").appendTo("body").css("height",0).attr("id",this.options.dropDownID));return a},log:function(a){if(this.options.log){window.console&&window.console.log&&console.log(a);this.logNode&&this.logNode.length&&this.logNode.prepend("<div>"+a+"</div>")}},_calculateZIndex:function(){var a,b=
|
|
this.options.zIndexPopup;this.selectbox.parents().each(function(){a=parseInt(g(this).css("zIndex"),10);if(a>b)b=a});return b+1},changeOptions:function(){this._populateFromMaster()},destroy:function(){this.selectIsWrapped&&this.wrapper.before(this.selectbox);this._moveAttrs(this.input,this.selectbox,this.options.moveAttrs);this.labels.attr("for",this.selectbox.attr("id"));this.labels=null;this.selectbox.unbind("change.ui.ufd");g(document).unbind("click.ui.ufd",this._myDocClickHandler);this._myPollId&&
|
|
clearInterval(this._myPollId);this.wrapper.remove();this.listWrapper.remove();if(g.ui.version<"1.8"){this.selectbox.unbind("setData.ui.ufd");this.selectbox.unbind("getData.ui.ufd");this.selectbox.unbind("remove");g.widget.prototype.destroy.apply(this,arguments)}else g.Widget.prototype.destroy.apply(this,arguments);this._encodeDom=this.selectbox=null},dimensioned:false,selectIsWrapped:false,internalFocus:false,lastKey:null,selectedLi:null,isUpdatingMaster:false,created:false,hasEmphasis:false,isDisabled:false});
|
|
var i=function(a,b){this.isInfix=!!a;this.isCaseSensitive=!!b;this.root=[null,{},false];this.infixRoots=a?{}:null};i.prototype.add=function(a,b){a=this.cleanString(a);for(var c=a.length,d=this.root,e,h=0;h<c;h++){e=a.charAt(h);d=d[1];if(e in d)d=d[e];else{d=d[e]=[null,{},this.root[2]];if(this.isInfix)if(e in this.infixRoots)this.infixRoots[e].push(d);else this.infixRoots[e]=[d]}}if(d[0])d[0].push(b);else d[0]=[b];return true};i.prototype.find=function(a){a=this.findNodeArray(a);var b=!this.root[2],
|
|
c=[],d=[],e;for(arrName in a){e=a[arrName];!a.hasOwnProperty(arrName)||typeof e==="function"||this.markAndRetrieve(c,e,b)}this.markAndRetrieve(d,this.root,b);return{matches:c,misses:d}};i.prototype.findNodeArray=function(a){a=this.cleanString(a);for(var b=[this.root],c=a.length,d,e=this.cache=this.cache||{},h=0;h<c;h++){d=a.charAt(h);if(e.chr==d)b=e.hit;else{b=this.mapNewArray(b,d);e.chr=d;e.hit=b;e.next={}}e=e.next}return b};i.prototype.mapNewArray=function(a,b){if(a.length&&a[0]==this.root)if(this.isInfix)return this.infixRoots[b]||
|
|
[];else return(a=this.root[1][b])?[a]:[];for(var c=[],d=a.length,e,h=0;h<d;h++){e=a[h][1];e.hasOwnProperty(b)&&c.push(e[b])}return c};i.prototype.markAndRetrieve=function(a,b,c){for(b=[b];b.length>0;){var d=b.pop();if(d[2]!=c){d[2]=c;d[0]&&a.unshift(d[0]);for(chr in d[1])d[1].hasOwnProperty(chr)&&b.push(d[1][chr])}}};i.prototype.cleanString=function(a){this.isCaseSensitive||(a=a.toLowerCase());return a};g.ui.ufd.getNewTrie=function(a,b){return new i(a,b)};g.extend(g.ui.ufd,{version:"0.6",getter:"",
|
|
classAttr:g.support.style?"class":"className",defaults:{skin:"plain",prefix:"ufd-",dropDownID:"ufd-container",logSelector:"#log",mimicCSS:["float","tabindex","marginLeft","marginTop","marginRight","marginBottom"],moveAttrs:["tabindex","title"],infix:true,addEmphasis:false,caseSensitive:false,submitFreeText:false,homeEndForCursor:false,allowLR:false,calculateZIndex:false,useUiCss:false,log:false,unwrapForCSS:false,listWidthFixed:true,polling:250,listMaxVisible:10,minWidth:50,maxWidth:null,manualWidth:null,
|
|
viewAhead:1,pageLength:10,delayFilter:g.support.style?1:150,delayYield:1,zIndexPopup:101,css:{input:"",inputDisabled:"disabled",inputFocus:"focus",button:"",buttonIcon:"icon",buttonDisabled:"disabled",buttonHover:"hover",buttonMouseDown:"mouseDown",li:"",liActive:"active",hidden:"invisible",wrapper:"ufd",listWrapper:"list-wrapper",listWrapperUp:"list-wrapper-up",listScroll:"list-scroll"},uiCss:{skin:"uiCss",input:"ui-widget-content",inputDisabled:"disabled",button:"ui-button",buttonIcon:"ui-icon ui-icon-triangle-1-s",
|
|
buttonDisabled:"disabled",buttonHover:"ui-state-focus",buttonMouseDown:"ui-state-active",li:"ui-menu-item",liActive:"ui-state-hover",hidden:"invisible",wrapper:"ufd ui-widget ui-widget-content",listWrapper:"list-wrapper ui-widget ui-widget",listWrapperUp:"list-wrapper-up",listScroll:"list-scroll ui-widget-content"}}});g.ui.ufd.prototype.options=g.ui.ufd.defaults})(jQuery);
|