Dotclear

Changeset 2114:7f63aa8eeebf


Ignore:
Timestamp:
09/27/13 19:40:37 (11 years ago)
Author:
Nicolas <nikrou77@…>
Branch:
default
Message:

Upgrade jquery.autocomplete.js from agarzola fork ; addresses #1636
 https://github.com/agarzola/jQueryAutocompletePlugin/blob/master/jquery.autocomplete.js
A good idea should be to migrate to ui.autocomplete

Files:
2 edited

Legend:

Unmodified
Added
Removed
  • admin/js/jquery/jquery.autocomplete.js

    r1035 r2114  
    11/* 
    2  * jQuery Autocomplete plugin 1.1 
     2 * jQuery Autocomplete plugin 1.2.3 
    33 * 
    44 * Copyright (c) 2009 Jörn Zaefferer 
     
    88 *   http://www.gnu.org/licenses/gpl.html 
    99 * 
    10  * Revision: $Id: jquery.autocomplete.js 15 2009-08-22 10:30:27Z joern.zaefferer $ 
     10 * With small modifications by Alfonso Gómez-Arzola. 
     11 * See changelog for details. 
     12 * 
    1113 */ 
    1214 
    1315;(function($) { 
    14       
     16 
    1517$.fn.extend({ 
    1618     autocomplete: function(urlOrData, options) { 
     
    2022               data: isUrl ? null : urlOrData, 
    2123               delay: isUrl ? $.Autocompleter.defaults.delay : 10, 
    22                max: options && !options.scroll ? 10 : 150 
     24               max: options && !options.scroll ? 10 : 150, 
     25               noRecord: "No Records." 
    2326          }, options); 
    24            
     27 
    2528          // if highlight is set to false, replace it with a do-nothing function 
    2629          options.highlight = options.highlight || function(value) { return value; }; 
    27            
     30 
    2831          // if the formatMatch option is not specified, then use formatItem for backwards compatibility 
    2932          options.formatMatch = options.formatMatch || options.formatItem; 
    30            
     33 
    3134          return this.each(function() { 
    3235               new $.Autocompleter(this, options); 
     
    6568     }; 
    6669 
     70     var globalFailure = null; 
     71     if(options.failure != null && typeof options.failure == "function") { 
     72       globalFailure = options.failure; 
     73     } 
     74 
    6775     // Create $ object for input element 
    6876     var $input = $(input).attr("autocomplete", "off").addClass(options.inputClass); 
     
    7785     }; 
    7886     var select = $.Autocompleter.Select(options, input, selectCurrent, config); 
    79       
     87 
    8088     var blockSubmit; 
    81       
     89 
    8290     // prevent form submit in opera when selecting with return key 
    83      $.browser.opera && $(input.form).bind("submit.autocomplete", function() { 
     91  navigator.userAgent.indexOf("Opera") != -1 && $(input.form).bind("submit.autocomplete", function() { 
    8492          if (blockSubmit) { 
    8593               blockSubmit = false; 
     
    8795          } 
    8896     }); 
    89       
    90      // only opera doesn't trigger keydown multiple times while pressed, others don't work with keypress at all 
    91      $input.bind(($.browser.opera ? "keypress" : "keydown") + ".autocomplete", function(event) { 
     97 
     98     // older versions of opera don't trigger keydown multiple times while pressed, others don't work with keypress at all 
     99     $input.bind((navigator.userAgent.indexOf("Opera") != -1 && !'KeyboardEvent' in window ? "keypress" : "keydown") + ".autocomplete", function(event) { 
    92100          // a keypress means the input has focus 
    93101          // avoids issue where input had focus before the autocomplete was applied 
     
    96104          lastKeyPressCode = event.keyCode; 
    97105          switch(event.keyCode) { 
    98            
     106 
    99107               case KEY.UP: 
    100                     event.preventDefault(); 
    101108                    if ( select.visible() ) { 
     109                         event.preventDefault(); 
    102110                         select.prev(); 
    103111                    } else { 
     
    105113                    } 
    106114                    break; 
    107                      
     115 
    108116               case KEY.DOWN: 
    109                     event.preventDefault(); 
    110117                    if ( select.visible() ) { 
     118                         event.preventDefault(); 
    111119                         select.next(); 
    112120                    } else { 
     
    114122                    } 
    115123                    break; 
    116                      
     124 
    117125               case KEY.PAGEUP: 
    118                     event.preventDefault(); 
    119126                    if ( select.visible() ) { 
     127                    event.preventDefault(); 
    120128                         select.pageUp(); 
    121129                    } else { 
     
    123131                    } 
    124132                    break; 
    125                      
     133 
    126134               case KEY.PAGEDOWN: 
    127                     event.preventDefault(); 
    128135                    if ( select.visible() ) { 
     136                    event.preventDefault(); 
    129137                         select.pageDown(); 
    130138                    } else { 
     
    132140                    } 
    133141                    break; 
    134                 
     142 
    135143               // matches also semicolon 
    136144               case options.multiple && $.trim(options.multipleSeparator) == "," && KEY.COMMA: 
     
    144152                    } 
    145153                    break; 
    146                      
     154 
    147155               case KEY.ESC: 
    148156                    select.hide(); 
    149157                    break; 
    150                      
     158 
    151159               default: 
    152160                    clearTimeout(timeout); 
     
    159167          hasFocus++; 
    160168     }).blur(function() { 
    161           hasFocus = 0; 
     169       hasFocus = 0; 
    162170          if (!config.mouseDownOnSelect) { 
    163171               hideResults(); 
     
    165173     }).click(function() { 
    166174          // show select when clicking in a focused field 
    167           if ( hasFocus++ > 1 && !select.visible() ) { 
    168                onChange(0, true); 
     175          // but if clickFire is true, don't require field 
     176          // to be focused to begin with; just show select 
     177          if( options.clickFire ) { 
     178            if ( !select.visible() ) { 
     179               onChange(0, true); 
     180          } 
     181          } else { 
     182            if ( hasFocus++ > 1 && !select.visible() ) { 
     183               onChange(0, true); 
     184          } 
    169185          } 
    170186     }).bind("search", function() { 
     
    190206          cache.flush(); 
    191207     }).bind("setOptions", function() { 
    192           $.extend(options, arguments[1]); 
     208          $.extend(true, options, arguments[1]); 
    193209          // if we've updated the data, repopulate 
    194210          if ( "data" in arguments[1] ) 
     
    199215          $(input.form).unbind(".autocomplete"); 
    200216     }); 
    201       
    202       
     217 
     218 
    203219     function selectCurrent() { 
    204220          var selected = select.selected(); 
    205221          if( !selected ) 
    206222               return false; 
    207            
     223 
    208224          var v = selected.result; 
    209225          previousValue = v; 
    210            
     226 
    211227          if ( options.multiple ) { 
    212228               var words = trimWords($input.val()); 
     
    230246               v += options.multipleSeparator; 
    231247          } 
    232            
     248 
    233249          $input.val(v); 
    234250          hideResultsNow(); 
     
    236252          return true; 
    237253     } 
    238       
     254 
    239255     function onChange(crap, skipPrevCheck) { 
    240256          if( lastKeyPressCode == KEY.DEL ) { 
     
    242258               return; 
    243259          } 
    244            
     260 
    245261          var currentValue = $input.val(); 
    246            
     262 
    247263          if ( !skipPrevCheck && currentValue == previousValue ) 
    248264               return; 
    249            
     265 
    250266          previousValue = currentValue; 
    251            
     267 
    252268          currentValue = lastWord(currentValue); 
    253269          if ( currentValue.length >= options.minChars) { 
     
    261277          } 
    262278     }; 
    263       
     279 
    264280     function trimWords(value) { 
    265281          if (!value) 
     
    271287          }); 
    272288     } 
    273       
     289 
    274290     function lastWord(value) { 
    275291          if ( !options.multiple ) 
    276292               return value; 
    277293          var words = trimWords(value); 
    278           if (words.length == 1)  
     294          if (words.length == 1) 
    279295               return words[0]; 
    280296          var cursorAt = $(input).selection().start; 
     
    286302          return words[words.length - 1]; 
    287303     } 
    288       
     304 
    289305     // fills in the input box w/the first match (assumed to be the best match) 
    290306     // q: the term entered 
     
    347363          var data = cache.load(term); 
    348364          // recieve the cached data 
    349           if (data && data.length) { 
    350                success(term, data); 
     365          if (data) { 
     366               if(data.length)     { 
     367                    success(term, data); 
     368               } 
     369               else{ 
     370                    var parsed = options.parse && options.parse(options.noRecord) || parse(options.noRecord);  
     371                    success(term,parsed); 
     372               } 
    351373          // if an AJAX url has been supplied, try loading the data now 
    352374          } else if( (typeof options.url == "string") && (options.url.length > 0) ){ 
    353                 
     375 
    354376               var extraParams = { 
    355377                    timestamp: +new Date() 
     
    358380                    extraParams[key] = typeof param == "function" ? param() : param; 
    359381               }); 
    360                 
     382 
    361383               $.ajax({ 
    362384                    // try to leverage ajaxQueue plugin to abort previous requests 
     
    379401               // if we have a failure, we need to empty the list -- this prevents the the [TAB] key from selecting the last successful match 
    380402               select.emptyList(); 
    381                failure(term); 
    382           } 
    383      }; 
    384       
     403               if(globalFailure != null) { 
     404        globalFailure(); 
     405      } 
     406      else { 
     407        failure(term); 
     408               } 
     409          } 
     410     }; 
     411 
    385412     function parse(data) { 
    386413          var parsed = []; 
     
    415442     matchSubset: true, 
    416443     matchContains: false, 
    417      cacheLength: 10, 
    418      max: 100, 
     444     cacheLength: 100, 
     445     max: 1000, 
    419446     mustMatch: false, 
    420447     extraParams: {}, 
     
    425452     width: 0, 
    426453     multiple: false, 
    427      multipleSeparator: ", ", 
     454     multipleSeparator: " ", 
     455     inputFocus: true, 
     456     clickFire: false, 
    428457     highlight: function(value, term) { 
    429458          return value.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + term.replace(/([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi, "\\$1") + ")(?![^<>]*>)(?![^&;]+;)", "gi"), "<strong>$1</strong>"); 
    430459     }, 
    431460    scroll: true, 
    432     scrollHeight: 180 
     461    scrollHeight: 180, 
     462    scrollJumpPosition: true 
    433463}; 
    434464 
     
    437467     var data = {}; 
    438468     var length = 0; 
    439       
     469 
    440470     function matchSubset(s, sub) { 
    441           if (!options.matchCase)  
     471          if (!options.matchCase) 
    442472               s = s.toLowerCase(); 
    443473          var i = s.indexOf(sub); 
     
    448478          return i == 0 || options.matchContains; 
    449479     }; 
    450       
     480 
    451481     function add(q, value) { 
    452482          if (length > options.cacheLength){ 
    453483               flush(); 
    454484          } 
    455           if (!data[q]){  
     485          if (!data[q]){ 
    456486               length++; 
    457487          } 
    458488          data[q] = value; 
    459489     } 
    460       
     490 
    461491     function populate(){ 
    462492          if( !options.data ) return false; 
     
    467497          // no url was specified, we need to adjust the cache length to make sure it fits the local data store 
    468498          if( !options.url ) options.cacheLength = 1; 
    469            
     499 
    470500          // track all options for minChars = 0 
    471501          stMatchSets[""] = []; 
    472            
     502 
    473503          // loop through the array and create a lookup structure 
    474504          for ( var i = 0, ol = options.data.length; i < ol; i++ ) { 
     
    476506               // if rawValue is a string, make an array otherwise just reference the array 
    477507               rawValue = (typeof rawValue == "string") ? [rawValue] : rawValue; 
    478                 
     508 
    479509               var value = options.formatMatch(rawValue, i+1, options.data.length); 
    480                if ( value === false ) 
     510               if ( typeof(value) === 'undefined' || value === false ) 
    481511                    continue; 
    482                      
     512 
    483513               var firstChar = value.charAt(0).toLowerCase(); 
    484514               // if no lookup array for this character exists, look it up now 
    485                if( !stMatchSets[firstChar] )  
     515               if( !stMatchSets[firstChar] ) 
    486516                    stMatchSets[firstChar] = []; 
    487517 
     
    492522                    result: options.formatResult && options.formatResult(rawValue) || value 
    493523               }; 
    494                 
     524 
    495525               // push the current match into the set list 
    496526               stMatchSets[firstChar].push(row); 
     
    510540          }); 
    511541     } 
    512       
     542 
    513543     // populate any existing data 
    514544     setTimeout(populate, 25); 
    515       
     545 
    516546     function flush(){ 
    517547          data = {}; 
    518548          length = 0; 
    519549     } 
    520       
     550 
    521551     return { 
    522552          flush: flush, 
     
    526556               if (!options.cacheLength || !length) 
    527557                    return null; 
    528                /*  
     558               /* 
    529559                * if dealing w/local data and matchContains than we must make sure 
    530560                * to loop through all the data collections looking for matches 
     
    546576                              }); 
    547577                         } 
    548                     }                    
     578                    } 
    549579                    return csub; 
    550                } else  
     580               } else 
    551581               // if the exact item exists, use it 
    552582               if (data[q]){ 
     
    576606          ACTIVE: "ac_over" 
    577607     }; 
    578       
     608 
    579609     var listItems, 
    580610          active = -1, 
     
    584614          element, 
    585615          list; 
    586       
     616 
    587617     // Create results 
    588618     function init() { 
     
    593623          .addClass(options.resultsClass) 
    594624          .css("position", "absolute") 
    595           .appendTo(document.body); 
    596       
     625          .appendTo(document.body) 
     626          .hover(function(event) { 
     627            // Browsers except FF do not fire mouseup event on scrollbars, resulting in mouseDownOnSelect remaining true, and results list not always hiding. 
     628            if($(this).is(":visible")) { 
     629              input.focus(); 
     630            } 
     631            config.mouseDownOnSelect = false; 
     632          }); 
     633 
    597634          list = $("<ul/>").appendTo(element).mouseover( function(event) { 
    598635               if(target(event).nodeName && target(event).nodeName.toUpperCase() == 'LI') { 
    599636                 active = $("li", list).removeClass(CLASSES.ACTIVE).index(target(event)); 
    600                    $(target(event)).addClass(CLASSES.ACTIVE);             
     637                   $(target(event)).addClass(CLASSES.ACTIVE); 
    601638             } 
    602639          }).click(function(event) { 
    603640               $(target(event)).addClass(CLASSES.ACTIVE); 
    604641               select(); 
    605                // TODO provide option to avoid setting focus again after selection? useful for cleanup-on-focus 
    606                input.focus(); 
     642               if( options.inputFocus ) 
     643                 input.focus(); 
    607644               return false; 
    608645          }).mousedown(function() { 
     
    611648               config.mouseDownOnSelect = false; 
    612649          }); 
    613            
     650 
    614651          if( options.width > 0 ) 
    615652               element.css("width", options.width); 
    616                 
     653 
    617654          needsInit = false; 
    618      }  
    619       
     655     } 
     656 
    620657     function target(event) { 
    621658          var element = event.target; 
     
    644681        } 
    645682     }; 
    646       
     683 
    647684     function movePosition(step) { 
    648           active += step; 
    649           if (active < 0) { 
    650                active = listItems.size() - 1; 
    651           } else if (active >= listItems.size()) { 
    652                active = 0; 
    653           } 
    654      } 
    655       
     685          if (options.scrollJumpPosition || (!options.scrollJumpPosition && !((step < 0 && active == 0) || (step > 0 && active == listItems.size() - 1)) )) { 
     686               active += step; 
     687               if (active < 0) { 
     688                    active = listItems.size() - 1; 
     689               } else if (active >= listItems.size()) { 
     690                    active = 0; 
     691               } 
     692          } 
     693     } 
     694 
     695 
    656696     function limitNumberOfItems(available) { 
    657697          return options.max && options.max < available 
     
    659699               : available; 
    660700     } 
    661       
     701 
    662702     function fillList() { 
    663703          list.empty(); 
     
    681721               list.bgiframe(); 
    682722     } 
    683       
     723 
    684724     return { 
    685725          display: function(d, q) { 
     
    733773                         overflow: 'auto' 
    734774                    }); 
    735                      
    736                 if($.browser.msie && typeof document.body.style.maxHeight === "undefined") { 
     775 
     776                if(navigator.userAgent.indexOf("MSIE") != -1 && typeof document.body.style.maxHeight === "undefined") { 
    737777                         var listHeight = 0; 
    738778                         listItems.each(function() { 
     
    746786                         } 
    747787                } 
    748                  
     788 
    749789            } 
    750790          }, 
  • plugins/tags/js/jquery.autocomplete.js

    r738 r2114  
    11/* 
    2  * jQuery Autocomplete plugin 1.1 
     2 * jQuery Autocomplete plugin 1.2.3 
    33 * 
    44 * Copyright (c) 2009 Jörn Zaefferer 
     
    88 *   http://www.gnu.org/licenses/gpl.html 
    99 * 
    10  * Revision: $Id: jquery.autocomplete.js 15 2009-08-22 10:30:27Z joern.zaefferer $ 
     10 * With small modifications by Alfonso Gómez-Arzola. 
     11 * See changelog for details. 
     12 * 
    1113 */ 
    1214 
    1315;(function($) { 
    14       
     16 
    1517$.fn.extend({ 
    1618     autocomplete: function(urlOrData, options) { 
     
    2022               data: isUrl ? null : urlOrData, 
    2123               delay: isUrl ? $.Autocompleter.defaults.delay : 10, 
    22                max: options && !options.scroll ? 10 : 150 
     24               max: options && !options.scroll ? 10 : 150, 
     25               noRecord: "No Records." 
    2326          }, options); 
    24            
     27 
    2528          // if highlight is set to false, replace it with a do-nothing function 
    2629          options.highlight = options.highlight || function(value) { return value; }; 
    27            
     30 
    2831          // if the formatMatch option is not specified, then use formatItem for backwards compatibility 
    2932          options.formatMatch = options.formatMatch || options.formatItem; 
    30            
     33 
    3134          return this.each(function() { 
    3235               new $.Autocompleter(this, options); 
     
    6568     }; 
    6669 
     70     var globalFailure = null; 
     71     if(options.failure != null && typeof options.failure == "function") { 
     72       globalFailure = options.failure; 
     73     } 
     74 
    6775     // Create $ object for input element 
    6876     var $input = $(input).attr("autocomplete", "off").addClass(options.inputClass); 
     
    7785     }; 
    7886     var select = $.Autocompleter.Select(options, input, selectCurrent, config); 
    79       
     87 
    8088     var blockSubmit; 
    81       
     89 
    8290     // prevent form submit in opera when selecting with return key 
    83      $.browser.opera && $(input.form).bind("submit.autocomplete", function() { 
     91  navigator.userAgent.indexOf("Opera") != -1 && $(input.form).bind("submit.autocomplete", function() { 
    8492          if (blockSubmit) { 
    8593               blockSubmit = false; 
     
    8795          } 
    8896     }); 
    89       
    90      // only opera doesn't trigger keydown multiple times while pressed, others don't work with keypress at all 
    91      $input.bind(($.browser.opera ? "keypress" : "keydown") + ".autocomplete", function(event) { 
     97 
     98     // older versions of opera don't trigger keydown multiple times while pressed, others don't work with keypress at all 
     99     $input.bind((navigator.userAgent.indexOf("Opera") != -1 && !'KeyboardEvent' in window ? "keypress" : "keydown") + ".autocomplete", function(event) { 
    92100          // a keypress means the input has focus 
    93101          // avoids issue where input had focus before the autocomplete was applied 
     
    96104          lastKeyPressCode = event.keyCode; 
    97105          switch(event.keyCode) { 
    98            
     106 
    99107               case KEY.UP: 
    100                     event.preventDefault(); 
    101108                    if ( select.visible() ) { 
     109                         event.preventDefault(); 
    102110                         select.prev(); 
    103111                    } else { 
     
    105113                    } 
    106114                    break; 
    107                      
     115 
    108116               case KEY.DOWN: 
    109                     event.preventDefault(); 
    110117                    if ( select.visible() ) { 
     118                         event.preventDefault(); 
    111119                         select.next(); 
    112120                    } else { 
     
    114122                    } 
    115123                    break; 
    116                      
     124 
    117125               case KEY.PAGEUP: 
    118                     event.preventDefault(); 
    119126                    if ( select.visible() ) { 
     127                    event.preventDefault(); 
    120128                         select.pageUp(); 
    121129                    } else { 
     
    123131                    } 
    124132                    break; 
    125                      
     133 
    126134               case KEY.PAGEDOWN: 
    127                     event.preventDefault(); 
    128135                    if ( select.visible() ) { 
     136                    event.preventDefault(); 
    129137                         select.pageDown(); 
    130138                    } else { 
     
    132140                    } 
    133141                    break; 
    134                 
     142 
    135143               // matches also semicolon 
    136144               case options.multiple && $.trim(options.multipleSeparator) == "," && KEY.COMMA: 
     
    144152                    } 
    145153                    break; 
    146                      
     154 
    147155               case KEY.ESC: 
    148156                    select.hide(); 
    149157                    break; 
    150                      
     158 
    151159               default: 
    152160                    clearTimeout(timeout); 
     
    159167          hasFocus++; 
    160168     }).blur(function() { 
    161           hasFocus = 0; 
     169       hasFocus = 0; 
    162170          if (!config.mouseDownOnSelect) { 
    163171               hideResults(); 
     
    165173     }).click(function() { 
    166174          // show select when clicking in a focused field 
    167           if ( hasFocus++ > 1 && !select.visible() ) { 
    168                onChange(0, true); 
     175          // but if clickFire is true, don't require field 
     176          // to be focused to begin with; just show select 
     177          if( options.clickFire ) { 
     178            if ( !select.visible() ) { 
     179               onChange(0, true); 
     180          } 
     181          } else { 
     182            if ( hasFocus++ > 1 && !select.visible() ) { 
     183               onChange(0, true); 
     184          } 
    169185          } 
    170186     }).bind("search", function() { 
     
    190206          cache.flush(); 
    191207     }).bind("setOptions", function() { 
    192           $.extend(options, arguments[1]); 
     208          $.extend(true, options, arguments[1]); 
    193209          // if we've updated the data, repopulate 
    194210          if ( "data" in arguments[1] ) 
     
    199215          $(input.form).unbind(".autocomplete"); 
    200216     }); 
    201       
    202       
     217 
     218 
    203219     function selectCurrent() { 
    204220          var selected = select.selected(); 
    205221          if( !selected ) 
    206222               return false; 
    207            
     223 
    208224          var v = selected.result; 
    209225          previousValue = v; 
    210            
     226 
    211227          if ( options.multiple ) { 
    212228               var words = trimWords($input.val()); 
     
    230246               v += options.multipleSeparator; 
    231247          } 
    232            
     248 
    233249          $input.val(v); 
    234250          hideResultsNow(); 
     
    236252          return true; 
    237253     } 
    238       
     254 
    239255     function onChange(crap, skipPrevCheck) { 
    240256          if( lastKeyPressCode == KEY.DEL ) { 
     
    242258               return; 
    243259          } 
    244            
     260 
    245261          var currentValue = $input.val(); 
    246            
     262 
    247263          if ( !skipPrevCheck && currentValue == previousValue ) 
    248264               return; 
    249            
     265 
    250266          previousValue = currentValue; 
    251            
     267 
    252268          currentValue = lastWord(currentValue); 
    253269          if ( currentValue.length >= options.minChars) { 
     
    261277          } 
    262278     }; 
    263       
     279 
    264280     function trimWords(value) { 
    265281          if (!value) 
     
    271287          }); 
    272288     } 
    273       
     289 
    274290     function lastWord(value) { 
    275291          if ( !options.multiple ) 
    276292               return value; 
    277293          var words = trimWords(value); 
    278           if (words.length == 1)  
     294          if (words.length == 1) 
    279295               return words[0]; 
    280296          var cursorAt = $(input).selection().start; 
     
    286302          return words[words.length - 1]; 
    287303     } 
    288       
     304 
    289305     // fills in the input box w/the first match (assumed to be the best match) 
    290306     // q: the term entered 
     
    347363          var data = cache.load(term); 
    348364          // recieve the cached data 
    349           if (data && data.length) { 
    350                success(term, data); 
     365          if (data) { 
     366               if(data.length)     { 
     367                    success(term, data); 
     368               } 
     369               else{ 
     370                    var parsed = options.parse && options.parse(options.noRecord) || parse(options.noRecord);  
     371                    success(term,parsed); 
     372               } 
    351373          // if an AJAX url has been supplied, try loading the data now 
    352374          } else if( (typeof options.url == "string") && (options.url.length > 0) ){ 
    353                 
     375 
    354376               var extraParams = { 
    355377                    timestamp: +new Date() 
     
    358380                    extraParams[key] = typeof param == "function" ? param() : param; 
    359381               }); 
    360                 
     382 
    361383               $.ajax({ 
    362384                    // try to leverage ajaxQueue plugin to abort previous requests 
     
    379401               // if we have a failure, we need to empty the list -- this prevents the the [TAB] key from selecting the last successful match 
    380402               select.emptyList(); 
    381                failure(term); 
    382           } 
    383      }; 
    384       
     403               if(globalFailure != null) { 
     404        globalFailure(); 
     405      } 
     406      else { 
     407        failure(term); 
     408               } 
     409          } 
     410     }; 
     411 
    385412     function parse(data) { 
    386413          var parsed = []; 
     
    415442     matchSubset: true, 
    416443     matchContains: false, 
    417      cacheLength: 10, 
    418      max: 100, 
     444     cacheLength: 100, 
     445     max: 1000, 
    419446     mustMatch: false, 
    420447     extraParams: {}, 
     
    425452     width: 0, 
    426453     multiple: false, 
    427      multipleSeparator: ", ", 
     454     multipleSeparator: " ", 
     455     inputFocus: true, 
     456     clickFire: false, 
    428457     highlight: function(value, term) { 
    429458          return value.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + term.replace(/([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi, "\\$1") + ")(?![^<>]*>)(?![^&;]+;)", "gi"), "<strong>$1</strong>"); 
    430459     }, 
    431460    scroll: true, 
    432     scrollHeight: 180 
     461    scrollHeight: 180, 
     462    scrollJumpPosition: true 
    433463}; 
    434464 
     
    437467     var data = {}; 
    438468     var length = 0; 
    439       
     469 
    440470     function matchSubset(s, sub) { 
    441           if (!options.matchCase)  
     471          if (!options.matchCase) 
    442472               s = s.toLowerCase(); 
    443473          var i = s.indexOf(sub); 
     
    448478          return i == 0 || options.matchContains; 
    449479     }; 
    450       
     480 
    451481     function add(q, value) { 
    452482          if (length > options.cacheLength){ 
    453483               flush(); 
    454484          } 
    455           if (!data[q]){  
     485          if (!data[q]){ 
    456486               length++; 
    457487          } 
    458488          data[q] = value; 
    459489     } 
    460       
     490 
    461491     function populate(){ 
    462492          if( !options.data ) return false; 
     
    467497          // no url was specified, we need to adjust the cache length to make sure it fits the local data store 
    468498          if( !options.url ) options.cacheLength = 1; 
    469            
     499 
    470500          // track all options for minChars = 0 
    471501          stMatchSets[""] = []; 
    472            
     502 
    473503          // loop through the array and create a lookup structure 
    474504          for ( var i = 0, ol = options.data.length; i < ol; i++ ) { 
     
    476506               // if rawValue is a string, make an array otherwise just reference the array 
    477507               rawValue = (typeof rawValue == "string") ? [rawValue] : rawValue; 
    478                 
     508 
    479509               var value = options.formatMatch(rawValue, i+1, options.data.length); 
    480                if ( value === false ) 
     510               if ( typeof(value) === 'undefined' || value === false ) 
    481511                    continue; 
    482                      
     512 
    483513               var firstChar = value.charAt(0).toLowerCase(); 
    484514               // if no lookup array for this character exists, look it up now 
    485                if( !stMatchSets[firstChar] )  
     515               if( !stMatchSets[firstChar] ) 
    486516                    stMatchSets[firstChar] = []; 
    487517 
     
    492522                    result: options.formatResult && options.formatResult(rawValue) || value 
    493523               }; 
    494                 
     524 
    495525               // push the current match into the set list 
    496526               stMatchSets[firstChar].push(row); 
     
    510540          }); 
    511541     } 
    512       
     542 
    513543     // populate any existing data 
    514544     setTimeout(populate, 25); 
    515       
     545 
    516546     function flush(){ 
    517547          data = {}; 
    518548          length = 0; 
    519549     } 
    520       
     550 
    521551     return { 
    522552          flush: flush, 
     
    526556               if (!options.cacheLength || !length) 
    527557                    return null; 
    528                /*  
     558               /* 
    529559                * if dealing w/local data and matchContains than we must make sure 
    530560                * to loop through all the data collections looking for matches 
     
    546576                              }); 
    547577                         } 
    548                     }                    
     578                    } 
    549579                    return csub; 
    550                } else  
     580               } else 
    551581               // if the exact item exists, use it 
    552582               if (data[q]){ 
     
    576606          ACTIVE: "ac_over" 
    577607     }; 
    578       
     608 
    579609     var listItems, 
    580610          active = -1, 
     
    584614          element, 
    585615          list; 
    586       
     616 
    587617     // Create results 
    588618     function init() { 
     
    593623          .addClass(options.resultsClass) 
    594624          .css("position", "absolute") 
    595           .appendTo(document.body); 
    596       
     625          .appendTo(document.body) 
     626          .hover(function(event) { 
     627            // Browsers except FF do not fire mouseup event on scrollbars, resulting in mouseDownOnSelect remaining true, and results list not always hiding. 
     628            if($(this).is(":visible")) { 
     629              input.focus(); 
     630            } 
     631            config.mouseDownOnSelect = false; 
     632          }); 
     633 
    597634          list = $("<ul/>").appendTo(element).mouseover( function(event) { 
    598635               if(target(event).nodeName && target(event).nodeName.toUpperCase() == 'LI') { 
    599636                 active = $("li", list).removeClass(CLASSES.ACTIVE).index(target(event)); 
    600                    $(target(event)).addClass(CLASSES.ACTIVE);             
     637                   $(target(event)).addClass(CLASSES.ACTIVE); 
    601638             } 
    602639          }).click(function(event) { 
    603640               $(target(event)).addClass(CLASSES.ACTIVE); 
    604641               select(); 
    605                // TODO provide option to avoid setting focus again after selection? useful for cleanup-on-focus 
    606                input.focus(); 
     642               if( options.inputFocus ) 
     643                 input.focus(); 
    607644               return false; 
    608645          }).mousedown(function() { 
     
    611648               config.mouseDownOnSelect = false; 
    612649          }); 
    613            
     650 
    614651          if( options.width > 0 ) 
    615652               element.css("width", options.width); 
    616                 
     653 
    617654          needsInit = false; 
    618      }  
    619       
     655     } 
     656 
    620657     function target(event) { 
    621658          var element = event.target; 
     
    644681        } 
    645682     }; 
    646       
     683 
    647684     function movePosition(step) { 
    648           active += step; 
    649           if (active < 0) { 
    650                active = listItems.size() - 1; 
    651           } else if (active >= listItems.size()) { 
    652                active = 0; 
    653           } 
    654      } 
    655       
     685          if (options.scrollJumpPosition || (!options.scrollJumpPosition && !((step < 0 && active == 0) || (step > 0 && active == listItems.size() - 1)) )) { 
     686               active += step; 
     687               if (active < 0) { 
     688                    active = listItems.size() - 1; 
     689               } else if (active >= listItems.size()) { 
     690                    active = 0; 
     691               } 
     692          } 
     693     } 
     694 
     695 
    656696     function limitNumberOfItems(available) { 
    657697          return options.max && options.max < available 
     
    659699               : available; 
    660700     } 
    661       
     701 
    662702     function fillList() { 
    663703          list.empty(); 
     
    681721               list.bgiframe(); 
    682722     } 
    683       
     723 
    684724     return { 
    685725          display: function(d, q) { 
     
    733773                         overflow: 'auto' 
    734774                    }); 
    735                      
    736                 if($.browser.msie && typeof document.body.style.maxHeight === "undefined") { 
     775 
     776                if(navigator.userAgent.indexOf("MSIE") != -1 && typeof document.body.style.maxHeight === "undefined") { 
    737777                         var listHeight = 0; 
    738778                         listItems.each(function() { 
     
    746786                         } 
    747787                } 
    748                  
     788 
    749789            } 
    750790          }, 
Note: See TracChangeset for help on using the changeset viewer.

Sites map