]> git.ipfire.org Git - thirdparty/bugzilla.git/commitdiff
Bug 1159589: migrate autocomplete from yui to jquery
authorByron Jones <glob@mozilla.com>
Thu, 7 May 2015 04:49:01 +0000 (12:49 +0800)
committerByron Jones <glob@mozilla.com>
Thu, 7 May 2015 04:49:01 +0000 (12:49 +0800)
r=dylan,a=glob

26 files changed:
js/comment-tagging.js
js/field.js
js/jquery/plugins/devbridgeAutocomplete/devbridgeAutocomplete-min.js [new file with mode: 0644]
js/jquery/plugins/devbridgeAutocomplete/license.txt [new file with mode: 0644]
skins/standard/global.css
skins/standard/throbber.gif [new file with mode: 0644]
template/en/default/account/prefs/prefs.html.tmpl
template/en/default/admin/components/create.html.tmpl
template/en/default/admin/components/edit.html.tmpl
template/en/default/admin/products/create.html.tmpl
template/en/default/attachment/create.html.tmpl
template/en/default/attachment/edit.html.tmpl
template/en/default/bug/create/create.html.tmpl
template/en/default/bug/edit.html.tmpl
template/en/default/bug/field.html.tmpl
template/en/default/bug/show-header.html.tmpl
template/en/default/global/header.html.tmpl
template/en/default/global/userselect.html.tmpl
template/en/default/list/list.html.tmpl
template/en/default/request/queue.html.tmpl
template/en/default/search/field.html.tmpl
template/en/default/search/form.html.tmpl
template/en/default/search/search-advanced.html.tmpl
template/en/default/search/search-create-series.html.tmpl
template/en/default/search/search-report-graph.html.tmpl
template/en/default/search/search-report-table.html.tmpl

index ff0f1333663d5596105d4037e8e39b0361dde2ba..f3ec33788ad2bd62659994e01a674b349ce685ff 100644 (file)
@@ -34,40 +34,27 @@ YAHOO.bugzilla.commentTagging = {
         });
         if (!can_edit) return;
 
-        var ds = new YAHOO.util.XHRDataSource("jsonrpc.cgi");
-        ds.connTimeout = 30000;
-        ds.connMethodPost = true;
-        ds.connXhrMode = "cancelStaleRequests";
-        ds.maxCacheEntries = 5;
-        ds.responseSchema = {
-            metaFields : { error: "error", jsonRpcId: "id"},
-            resultsList : "result"
-        };
-
-        var ac = new YAHOO.widget.AutoComplete('bz_ctag_add', 'bz_ctag_autocomp', ds);
-        ac.maxResultsDisplayed = 7;
-        ac.generateRequest = function(query) {
-            query = YAHOO.lang.trim(query);
-            YAHOO.bugzilla.commentTagging.last_query = query;
-            YAHOO.bugzilla.commentTagging.counter = YAHOO.bugzilla.commentTagging.counter + 1;
-            YAHOO.util.Connect.setDefaultPostHeader('application/json', true);
-            return YAHOO.lang.JSON.stringify({
-                version: "1.1",
-                method : "Bug.search_comment_tags",
-                id : YAHOO.bugzilla.commentTagging.counter,
-                params : {
-                    Bugzilla_api_token: BUGZILLA.api_token,
-                    query : query,
-                    limit : 10
-                }
-            });
-        };
-        ac.minQueryLength = this.min_len;
-        ac.autoHighlight = false;
-        ac.typeAhead = true;
-        ac.queryDelay = 0.5;
-        ac.dataReturnEvent.subscribe(function(type, args) {
-            args[0].autoHighlight = args[2].length == 1;
+        $('#bz_ctag_add').devbridgeAutocomplete({
+            serviceUrl: function(query) {
+                return 'rest/bug/comment/tags/' + encodeURIComponent(query);
+            },
+            params: {
+                Bugzilla_api_token: BUGZILLA.api_token
+            },
+            deferRequestBy: 250,
+            minChars: 1,
+            tabDisabled: true,
+            transformResult: function(response) {
+                response = $.parseJSON(response);
+                return {
+                    suggestions: $.map(response, function(dataItem) {
+                        return {
+                            value: dataItem,
+                            data : null
+                        };
+                    })
+                };
+            }
         });
     },
 
index 167ab492ffe225a750a04c0b04f6fb2bb045af73..f55852671b216f4e0cdcbbdb6cff82eaae221833 100644 (file)
@@ -805,117 +805,95 @@ function browserCanHideOptions(aSelect) {
 /* (end) option hiding code */
 
 /**
- * The Autoselect
+ * Autocompletion
  */
-YAHOO.bugzilla.userAutocomplete = {
-    counter : 0,
-    dataSource : null,
-    generateRequest : function ( enteredText ){ 
-      YAHOO.bugzilla.userAutocomplete.counter = 
-                                   YAHOO.bugzilla.userAutocomplete.counter + 1;
-      YAHOO.util.Connect.setDefaultPostHeader('application/json', true);
-      var json_object = {
-          method : "User.get",
-          id : YAHOO.bugzilla.userAutocomplete.counter,
-          params : [ { 
+
+$(function() {
+
+    // single user
+
+    function searchComplete() {
+        var that = $(this);
+        that.data('counter', that.data('counter') - 1);
+        if (that.data('counter') === 0)
+            that.removeClass('autocomplete-running');
+        if (document.activeElement != this)
+            that.autocomplete('hide');
+    };
+
+    var options_user = {
+        serviceUrl: 'rest/user',
+        params: {
             Bugzilla_api_token: BUGZILLA.api_token,
-            match : [ decodeURIComponent(enteredText) ],
-            include_fields : [ "name", "real_name" ]
-          } ]
-      };
-      var stringified =  YAHOO.lang.JSON.stringify(json_object);
-      var debug = { msg: "json-rpc obj debug info", "json obj": json_object, 
-                    "param" : stringified}
-      YAHOO.bugzilla.userAutocomplete.debug_helper( debug );
-      return stringified;
-    },
-    resultListFormat : function(oResultData, enteredText, sResultMatch) {
-        return ( YAHOO.lang.escapeHTML(oResultData.real_name) + " ("
-                 + YAHOO.lang.escapeHTML(oResultData.name) + ")");
-    },
-    debug_helper : function ( ){
-        /* used to help debug any errors that might happen */
-        if( typeof(console) !== 'undefined' && console != null && arguments.length > 0 ){
-            console.log("debug helper info:", arguments);
-        }
-        return true;
-    },    
-    init_ds : function(){
-        this.dataSource = new YAHOO.util.XHRDataSource("jsonrpc.cgi");
-        this.dataSource.connTimeout = 30000;
-        this.dataSource.connMethodPost = true;
-        this.dataSource.connXhrMode = "cancelStaleRequests";
-        this.dataSource.maxCacheEntries = 5;
-        this.dataSource.responseSchema = {
-            resultsList : "result.users",
-            metaFields : { error: "error", jsonRpcId: "id"},
-            fields : [
-                { key : "name" },
-                { key : "real_name"}
-            ]
-        };
-    },
-    init : function( field, container, multiple ) {
-        if( this.dataSource == null ){
-            this.init_ds();  
-        }            
-        var userAutoComp = new YAHOO.widget.AutoComplete( field, container, 
-                                this.dataSource );
-        // other stuff we might want to do with the autocomplete goes here
-        userAutoComp.maxResultsDisplayed = BUGZILLA.param.maxusermatches;
-        userAutoComp.generateRequest = this.generateRequest;
-        userAutoComp.formatResult = this.resultListFormat;
-        userAutoComp.doBeforeLoadData = this.debug_helper;
-        userAutoComp.minQueryLength = 3;
-        userAutoComp.autoHighlight = false;
-        // this is a throttle to determine the delay of the query from typing
-        // set this higher to cause fewer calls to the server
-        userAutoComp.queryDelay = 0.05;
-        userAutoComp.useIFrame = true;
-        userAutoComp.resultTypeList = false;
-        if( multiple == true ){
-            userAutoComp.delimChar = [","];
-        }
-        
-    }
-};
+            include_fields: 'name,real_name',
+            limit: 100
+        },
+        paramName: 'match',
+        deferRequestBy: 250,
+        minChars: 3,
+        tabDisabled: true,
+        transformResult: function(response) {
+            response = $.parseJSON(response);
+            return {
+                suggestions: $.map(response.users, function(dataItem) {
+                    return {
+                        value: dataItem.name,
+                        data : { login: dataItem.name, name: dataItem.real_name }
+                    };
+                })
+            };
+        },
+        formatResult: function(suggestion, currentValue) {
+            return suggestion.data.name === '' ?
+                suggestion.data.login : suggestion.data.name + ' (' + suggestion.data.login + ')';
+        },
+        onSearchStart: function(params) {
+            var that = $(this);
+            params.match = $.trim(params.match);
+            that.addClass('autocomplete-running');
+            that.data('counter', that.data('counter') + 1);
+        },
+        onSearchComplete: searchComplete,
+        onSearchError: searchComplete
+    };
 
-YAHOO.bugzilla.fieldAutocomplete = {
-    dataSource : [],
-    init_ds : function( field ) {
-        this.dataSource[field] =
-          new YAHOO.util.LocalDataSource( YAHOO.bugzilla.field_array[field] );
-    },
-    init : function( field, container ) {
-        if( this.dataSource[field] == null ) {
-            this.init_ds( field );
-        }
-        var fieldAutoComp =
-          new YAHOO.widget.AutoComplete(field, container, this.dataSource[field]);
-        fieldAutoComp.maxResultsDisplayed = YAHOO.bugzilla.field_array[field].length;
-        fieldAutoComp.formatResult = fieldAutoComp.formatEscapedResult;
-        fieldAutoComp.minQueryLength = 0;
-        fieldAutoComp.useIFrame = true;
-        fieldAutoComp.delimChar = [","," "];
-        fieldAutoComp.resultTypeList = false;
-        fieldAutoComp.queryDelay = 0;
-        /*  Causes all the possibilities in the field to appear when a user
-         *  focuses on the textbox 
-         */
-        fieldAutoComp.textboxFocusEvent.subscribe( function(){
-            var sInputValue = YAHOO.util.Dom.get(field).value;
-            if( sInputValue.length === 0
-                && YAHOO.bugzilla.field_array[field].length > 0 ){
-                this.sendQuery(sInputValue);
-                this.collapseContainer();
-                this.expandContainer();
+    // multiple users (based on single user)
+    var options_users = {
+        delimiter: /,\s*/,
+        onSelect: function() {
+            this.focus();
+        },
+    };
+    $.extend(options_users, options_user);
+
+    // init user autocomplete fields
+    $('.bz_autocomplete_user')
+        .each(function() {
+            var that = $(this);
+            that.data('counter', 0);
+            if (that.data('multiple')) {
+                that.devbridgeAutocomplete(options_users);
+            }
+            else {
+                that.devbridgeAutocomplete(options_user);
             }
         });
-        fieldAutoComp.dataRequestEvent.subscribe( function(type, args) {
-            args[0].autoHighlight = args[1] != '';
+
+    // init autocomplete fields with array of values
+    $('.bz_autocomplete_values')
+        .each(function() {
+            var that = $(this);
+            that.devbridgeAutocomplete({
+                lookup: BUGZILLA.autocomplete_values[that.data('values')],
+                tabDisabled: true,
+                delimiter: /,\s*/,
+                minChars: 0,
+                onSelect: function() {
+                    this.focus();
+                }
+            });
         });
-    }
-};
+});
 
 /**
  * Set the disable email checkbox to true if the user has disabled text
diff --git a/js/jquery/plugins/devbridgeAutocomplete/devbridgeAutocomplete-min.js b/js/jquery/plugins/devbridgeAutocomplete/devbridgeAutocomplete-min.js
new file mode 100644 (file)
index 0000000..01623ab
--- /dev/null
@@ -0,0 +1,8 @@
+/**
+*  Ajax Autocomplete for jQuery, version 1.2.18
+*  (c) 2014 Tomas Kirda
+*
+*  Ajax Autocomplete for jQuery is freely distributable under the terms of an MIT-style license.
+*  For details, see the web site: https://github.com/devbridge/jQuery-Autocomplete
+*/
+!function(a){"use strict";"function"==typeof define&&define.amd?define(["jquery"],a):a("object"==typeof exports&&"function"==typeof require?require("jquery"):jQuery)}(function(a){"use strict";function b(c,d){var e=function(){},f=this,g={ajaxSettings:{},autoSelectFirst:!1,appendTo:document.body,serviceUrl:null,lookup:null,onSelect:null,width:"auto",minChars:1,maxHeight:300,deferRequestBy:0,params:{},formatResult:b.formatResult,delimiter:null,zIndex:9999,type:"GET",noCache:!1,onSearchStart:e,onSearchComplete:e,onSearchError:e,preserveInput:!1,containerClass:"autocomplete-suggestions",tabDisabled:!1,dataType:"text",currentRequest:null,triggerSelectOnValidInput:!0,preventBadQueries:!0,lookupFilter:function(a,b,c){return-1!==a.value.toLowerCase().indexOf(c)},paramName:"query",transformResult:function(b){return"string"==typeof b?a.parseJSON(b):b},showNoSuggestionNotice:!1,noSuggestionNotice:"No results",orientation:"bottom",forceFixPosition:!1};f.element=c,f.el=a(c),f.suggestions=[],f.badQueries=[],f.selectedIndex=-1,f.currentValue=f.element.value,f.intervalId=0,f.cachedResponse={},f.onChangeInterval=null,f.onChange=null,f.isLocal=!1,f.suggestionsContainer=null,f.noSuggestionsContainer=null,f.options=a.extend({},g,d),f.classes={selected:"autocomplete-selected",suggestion:"autocomplete-suggestion"},f.hint=null,f.hintValue="",f.selection=null,f.initialize(),f.setOptions(d)}var c=function(){return{escapeRegExChars:function(a){return a.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")},createNode:function(a){var b=document.createElement("div");return b.className=a,b.style.position="absolute",b.style.display="none",b}}}(),d={ESC:27,TAB:9,RETURN:13,LEFT:37,UP:38,RIGHT:39,DOWN:40};b.utils=c,a.Autocomplete=b,b.formatResult=function(a,b){var d="("+c.escapeRegExChars(b)+")";return a.value.replace(new RegExp(d,"gi"),"<strong>$1</strong>")},b.prototype={killerFn:null,initialize:function(){var c,d=this,e="."+d.classes.suggestion,f=d.classes.selected,g=d.options;d.element.setAttribute("autocomplete","off"),d.killerFn=function(b){0===a(b.target).closest("."+d.options.containerClass).length&&(d.killSuggestions(),d.disableKillerFn())},d.noSuggestionsContainer=a('<div class="autocomplete-no-suggestion"></div>').html(this.options.noSuggestionNotice).get(0),d.suggestionsContainer=b.utils.createNode(g.containerClass),c=a(d.suggestionsContainer),c.appendTo(g.appendTo),"auto"!==g.width&&c.width(g.width),c.on("mouseover.autocomplete",e,function(){d.activate(a(this).data("index"))}),c.on("mouseout.autocomplete",function(){d.selectedIndex=-1,c.children("."+f).removeClass(f)}),c.on("click.autocomplete",e,function(){d.select(a(this).data("index"))}),d.fixPositionCapture=function(){d.visible&&d.fixPosition()},a(window).on("resize.autocomplete",d.fixPositionCapture),d.el.on("keydown.autocomplete",function(a){d.onKeyPress(a)}),d.el.on("keyup.autocomplete",function(a){d.onKeyUp(a)}),d.el.on("blur.autocomplete",function(){d.onBlur()}),d.el.on("focus.autocomplete",function(){d.onFocus()}),d.el.on("change.autocomplete",function(a){d.onKeyUp(a)}),d.el.on("input.autocomplete",function(a){d.onKeyUp(a)})},onFocus:function(){var a=this;a.fixPosition(),a.options.minChars<=a.el.val().length&&a.onValueChange()},onBlur:function(){this.enableKillerFn()},setOptions:function(b){var c=this,d=c.options;a.extend(d,b),c.isLocal=a.isArray(d.lookup),c.isLocal&&(d.lookup=c.verifySuggestionsFormat(d.lookup)),d.orientation=c.validateOrientation(d.orientation,"bottom"),a(c.suggestionsContainer).css({"max-height":d.maxHeight+"px",width:d.width+"px","z-index":d.zIndex})},clearCache:function(){this.cachedResponse={},this.badQueries=[]},clear:function(){this.clearCache(),this.currentValue="",this.suggestions=[]},disable:function(){var a=this;a.disabled=!0,clearInterval(a.onChangeInterval),a.currentRequest&&a.currentRequest.abort()},enable:function(){this.disabled=!1},fixPosition:function(){var b=this,c=a(b.suggestionsContainer),d=c.parent().get(0);if(d===document.body||b.options.forceFixPosition){var e=b.options.orientation,f=c.outerHeight(),g=b.el.outerHeight(),h=b.el.offset(),i={top:h.top,left:h.left};if("auto"===e){var j=a(window).height(),k=a(window).scrollTop(),l=-k+h.top-f,m=k+j-(h.top+g+f);e=Math.max(l,m)===l?"top":"bottom"}if(i.top+="top"===e?-f:g,d!==document.body){var n,o=c.css("opacity");b.visible||c.css("opacity",0).show(),n=c.offsetParent().offset(),i.top-=n.top,i.left-=n.left,b.visible||c.css("opacity",o).hide()}"auto"===b.options.width&&(i.width=b.el.outerWidth()-2+"px"),c.css(i)}},enableKillerFn:function(){var b=this;a(document).on("click.autocomplete",b.killerFn)},disableKillerFn:function(){var b=this;a(document).off("click.autocomplete",b.killerFn)},killSuggestions:function(){var a=this;a.stopKillSuggestions(),a.intervalId=window.setInterval(function(){a.hide(),a.stopKillSuggestions()},50)},stopKillSuggestions:function(){window.clearInterval(this.intervalId)},isCursorAtEnd:function(){var a,b=this,c=b.el.val().length,d=b.element.selectionStart;return"number"==typeof d?d===c:document.selection?(a=document.selection.createRange(),a.moveStart("character",-c),c===a.text.length):!0},onKeyPress:function(a){var b=this;if(!b.disabled&&!b.visible&&a.which===d.DOWN&&b.currentValue)return void b.suggest();if(!b.disabled&&b.visible){switch(a.which){case d.ESC:b.el.val(b.currentValue),b.hide();break;case d.RIGHT:if(b.hint&&b.options.onHint&&b.isCursorAtEnd()){b.selectHint();break}return;case d.TAB:if(b.hint&&b.options.onHint)return void b.selectHint();if(-1===b.selectedIndex)return void b.hide();if(b.select(b.selectedIndex),b.options.tabDisabled===!1)return;break;case d.RETURN:if(-1===b.selectedIndex)return void b.hide();b.select(b.selectedIndex);break;case d.UP:b.moveUp();break;case d.DOWN:b.moveDown();break;default:return}a.stopImmediatePropagation(),a.preventDefault()}},onKeyUp:function(a){var b=this;if(!b.disabled){switch(a.which){case d.UP:case d.DOWN:return}clearInterval(b.onChangeInterval),b.currentValue!==b.el.val()&&(b.findBestHint(),b.options.deferRequestBy>0?b.onChangeInterval=setInterval(function(){b.onValueChange()},b.options.deferRequestBy):b.onValueChange())}},onValueChange:function(){var b,c=this,d=c.options,e=c.el.val(),f=c.getQuery(e);return c.selection&&c.currentValue!==f&&(c.selection=null,(d.onInvalidateSelection||a.noop).call(c.element)),clearInterval(c.onChangeInterval),c.currentValue=e,c.selectedIndex=-1,d.triggerSelectOnValidInput&&(b=c.findSuggestionIndex(f),-1!==b)?void c.select(b):void(f.length<d.minChars?c.hide():c.getSuggestions(f))},findSuggestionIndex:function(b){var c=this,d=-1,e=b.toLowerCase();return a.each(c.suggestions,function(a,b){return b.value.toLowerCase()===e?(d=a,!1):void 0}),d},getQuery:function(b){var c,d=this.options.delimiter;return d?(c=b.split(d),a.trim(c[c.length-1])):b},getSuggestionsLocal:function(b){var c,d=this,e=d.options,f=b.toLowerCase(),g=e.lookupFilter,h=parseInt(e.lookupLimit,10);return c={suggestions:a.grep(e.lookup,function(a){return g(a,b,f)})},h&&c.suggestions.length>h&&(c.suggestions=c.suggestions.slice(0,h)),c},getSuggestions:function(b){var c,d,e,f,g=this,h=g.options,i=h.serviceUrl;if(h.params[h.paramName]=b,d=h.ignoreParams?null:h.params,h.onSearchStart.call(g.element,h.params)!==!1){if(a.isFunction(h.lookup))return void h.lookup(b,function(a){g.suggestions=a.suggestions,g.suggest(),h.onSearchComplete.call(g.element,b,a.suggestions)});g.isLocal?c=g.getSuggestionsLocal(b):(a.isFunction(i)&&(i=i.call(g.element,b)),e=i+"?"+a.param(d||{}),c=g.cachedResponse[e]),c&&a.isArray(c.suggestions)?(g.suggestions=c.suggestions,g.suggest(),h.onSearchComplete.call(g.element,b,c.suggestions)):g.isBadQuery(b)?h.onSearchComplete.call(g.element,b,[]):(g.currentRequest&&g.currentRequest.abort(),f={url:i,data:d,type:h.type,dataType:h.dataType},a.extend(f,h.ajaxSettings),g.currentRequest=a.ajax(f).done(function(a){var c;g.currentRequest=null,c=h.transformResult(a),g.processResponse(c,b,e),h.onSearchComplete.call(g.element,b,c.suggestions)}).fail(function(a,c,d){h.onSearchError.call(g.element,b,a,c,d)}))}},isBadQuery:function(a){if(!this.options.preventBadQueries)return!1;for(var b=this.badQueries,c=b.length;c--;)if(0===a.indexOf(b[c]))return!0;return!1},hide:function(){var b=this,c=a(b.suggestionsContainer);a.isFunction(b.options.onHide)&&b.visible&&b.options.onHide.call(b.element,c),b.visible=!1,b.selectedIndex=-1,clearInterval(b.onChangeInterval),a(b.suggestionsContainer).hide(),b.signalHint(null)},suggest:function(){if(0===this.suggestions.length)return void(this.options.showNoSuggestionNotice?this.noSuggestions():this.hide());var b,c,d=this,e=d.options,f=e.groupBy,g=e.formatResult,h=d.getQuery(d.currentValue),i=d.classes.suggestion,j=d.classes.selected,k=a(d.suggestionsContainer),l=a(d.noSuggestionsContainer),m=e.beforeRender,n="",o=function(a){var c=a.data[f];return b===c?"":(b=c,'<div class="autocomplete-group"><strong>'+b+"</strong></div>")};return e.triggerSelectOnValidInput&&(c=d.findSuggestionIndex(h),-1!==c)?void d.select(c):(a.each(d.suggestions,function(a,b){f&&(n+=o(b,h,a)),n+='<div class="'+i+'" data-index="'+a+'">'+g(b,h)+"</div>"}),this.adjustContainerWidth(),l.detach(),k.html(n),a.isFunction(m)&&m.call(d.element,k),d.fixPosition(),k.show(),e.autoSelectFirst&&(d.selectedIndex=0,k.scrollTop(0),k.children("."+i).first().addClass(j)),d.visible=!0,void d.findBestHint())},noSuggestions:function(){var b=this,c=a(b.suggestionsContainer),d=a(b.noSuggestionsContainer);this.adjustContainerWidth(),d.detach(),c.empty(),c.append(d),b.fixPosition(),c.show(),b.visible=!0},adjustContainerWidth:function(){var b,c=this,d=c.options,e=a(c.suggestionsContainer);"auto"===d.width&&(b=c.el.outerWidth()-2,e.width(b>0?b:300))},findBestHint:function(){var b=this,c=b.el.val().toLowerCase(),d=null;c&&(a.each(b.suggestions,function(a,b){var e=0===b.value.toLowerCase().indexOf(c);return e&&(d=b),!e}),b.signalHint(d))},signalHint:function(b){var c="",d=this;b&&(c=d.currentValue+b.value.substr(d.currentValue.length)),d.hintValue!==c&&(d.hintValue=c,d.hint=b,(this.options.onHint||a.noop)(c))},verifySuggestionsFormat:function(b){return b.length&&"string"==typeof b[0]?a.map(b,function(a){return{value:a,data:null}}):b},validateOrientation:function(b,c){return b=a.trim(b||"").toLowerCase(),-1===a.inArray(b,["auto","bottom","top"])&&(b=c),b},processResponse:function(a,b,c){var d=this,e=d.options;a.suggestions=d.verifySuggestionsFormat(a.suggestions),e.noCache||(d.cachedResponse[c]=a,e.preventBadQueries&&0===a.suggestions.length&&d.badQueries.push(b)),b===d.getQuery(d.currentValue)&&(d.suggestions=a.suggestions,d.suggest())},activate:function(b){var c,d=this,e=d.classes.selected,f=a(d.suggestionsContainer),g=f.find("."+d.classes.suggestion);return f.find("."+e).removeClass(e),d.selectedIndex=b,-1!==d.selectedIndex&&g.length>d.selectedIndex?(c=g.get(d.selectedIndex),a(c).addClass(e),c):null},selectHint:function(){var b=this,c=a.inArray(b.hint,b.suggestions);b.select(c)},select:function(a){var b=this;b.hide(),b.onSelect(a)},moveUp:function(){var b=this;if(-1!==b.selectedIndex)return 0===b.selectedIndex?(a(b.suggestionsContainer).children().first().removeClass(b.classes.selected),b.selectedIndex=-1,b.el.val(b.currentValue),void b.findBestHint()):void b.adjustScroll(b.selectedIndex-1)},moveDown:function(){var a=this;a.selectedIndex!==a.suggestions.length-1&&a.adjustScroll(a.selectedIndex+1)},adjustScroll:function(b){var c=this,d=c.activate(b);if(d){var e,f,g,h=a(d).outerHeight();e=d.offsetTop,f=a(c.suggestionsContainer).scrollTop(),g=f+c.options.maxHeight-h,f>e?a(c.suggestionsContainer).scrollTop(e):e>g&&a(c.suggestionsContainer).scrollTop(e-c.options.maxHeight+h),c.options.preserveInput||c.el.val(c.getValue(c.suggestions[b].value)),c.signalHint(null)}},onSelect:function(b){var c=this,d=c.options.onSelect,e=c.suggestions[b];c.currentValue=c.getValue(e.value),c.currentValue===c.el.val()||c.options.preserveInput||c.el.val(c.currentValue),c.signalHint(null),c.suggestions=[],c.selection=e,a.isFunction(d)&&d.call(c.element,e)},getValue:function(a){var b,c,d=this,e=d.options.delimiter;return e?(b=d.currentValue,c=b.split(e),1===c.length?a:b.substr(0,b.length-c[c.length-1].length)+a):a},dispose:function(){var b=this;b.el.off(".autocomplete").removeData("autocomplete"),b.disableKillerFn(),a(window).off("resize.autocomplete",b.fixPositionCapture),a(b.suggestionsContainer).remove()}},a.fn.autocomplete=a.fn.devbridgeAutocomplete=function(c,d){var e="autocomplete";return 0===arguments.length?this.first().data(e):this.each(function(){var f=a(this),g=f.data(e);"string"==typeof c?g&&"function"==typeof g[c]&&g[c](d):(g&&g.dispose&&g.dispose(),g=new b(this,c),f.data(e,g))})}});
\ No newline at end of file
diff --git a/js/jquery/plugins/devbridgeAutocomplete/license.txt b/js/jquery/plugins/devbridgeAutocomplete/license.txt
new file mode 100644 (file)
index 0000000..11b3ff1
--- /dev/null
@@ -0,0 +1,21 @@
+Copyright 2012 DevBridge and other contributors
+http://www.devbridge.com/projects/autocomplete/jquery/
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
index 25622a6a4848342933f0eba78c067c8f3ab987af..e00ddd8194141430959e290d7df9a2ca1c6b39fd 100644 (file)
@@ -1069,3 +1069,31 @@ table.field_value_explanation {
 }
 
 /* duplicates.cgi (end) */
+
+
+/* autocomplete */
+
+.autocomplete-suggestions {
+    border: 1px solid #999;
+    background: #fff;
+    color: #000;
+    overflow: auto;
+    cursor: pointer;
+}
+
+.autocomplete-suggestion {
+    padding: 2px 5px;
+    white-space: nowrap;
+    overflow: hidden;
+}
+
+.autocomplete-selected {
+    background: #426fd9;
+    color: #FFF
+}
+
+.autocomplete-running {
+    background-image: url("throbber.gif") !important;
+    background-repeat: no-repeat !important;
+    background-position: right 8px center !important;
+}
diff --git a/skins/standard/throbber.gif b/skins/standard/throbber.gif
new file mode 100644 (file)
index 0000000..bc4fa65
Binary files /dev/null and b/skins/standard/throbber.gif differ
index 21a823fb647239a2bc67e0362f04f07fb1f6bd4e..8d90d7b6e9bde051ce2137525e24502036aed129 100644 (file)
@@ -59,7 +59,6 @@
    style_urls = ['skins/standard/admin.css']
    javascript_urls = ['js/util.js', 'js/field.js', 'js/TUI.js']
    doc_section = current_tab.doc_section
-   yui = ['autocomplete']
  %]
 
 [% WRAPPER global/tabs.html.tmpl
index 96c9ce384c2163783a8227afce1fe253bb017455..858df7102e9da4b29b65ee0efd28bb399f2f534e 100644 (file)
@@ -16,7 +16,6 @@
   title = title
   generate_api_token = 1
   style_urls = ['skins/standard/admin.css']
-  yui = [ 'autocomplete' ]
   javascript_urls = [ "js/field.js" ]
 %]
 
index c4da1181b42aaa4129b2661c4ded1db1a70d3e56..1e93542a5843392c8aa026771176ad29e9114751 100644 (file)
@@ -20,7 +20,6 @@
   title = title
   generate_api_token = 1
   style_urls = ['skins/standard/admin.css']
-  yui = [ 'autocomplete' ]
   javascript_urls = [ "js/field.js" ]
 %]
 
index 0dcfd7283d481fcaf41a4e41596e2d38e5865a35..0b116f480d77a0ffabbc60e5bdca8115ba52871e 100644 (file)
@@ -20,7 +20,6 @@
   generate_api_token = 1
   style_urls = ['skins/standard/admin.css']
   javascript_urls = ['js/util.js', 'js/field.js']
-  yui = [ 'autocomplete' ]
 %]
 
 [% DEFAULT
index 05223ede4b165df513f0a6ff4e2d45143f038afc..75c7702ccb5c3fc274dfb7a5d9a36dbc63188ac4 100644 (file)
@@ -18,7 +18,6 @@
   subheader = subheader
   generate_api_token = 1
   style_urls = ['skins/standard/bug.css']
-  yui = [ 'autocomplete' ]
   javascript_urls = [ "js/attachment.js", 'js/field.js', "js/util.js", "js/TUI.js" ]
   doc_section = "using/editing.html#attachments"
 %]
index d2554dfb82030af06d43bc205f7ec9db7086c984..b6f612f3fba430dfe9a83f7b41bd48a5655e52de 100644 (file)
@@ -25,7 +25,6 @@
   doc_section = "using/editing.html#attachments"
   javascript_urls = ['js/attachment.js', 'js/field.js']
   style_urls = ['skins/standard/bug.css']
-  yui = [ 'autocomplete' ]
   bodyclasses = "no_javascript"
 %]
 
index c9a7c7db99e596a4275e9ef0ed7a61fae32a24c2..23fb276c947949fb317dd2ae1c3387c9ff1b7f98 100644 (file)
@@ -12,7 +12,7 @@
 [% PROCESS global/header.html.tmpl
   title = title
   generate_api_token = 1
-  yui = [ 'autocomplete', 'calendar', 'datatable', 'button' ]
+  yui = [ 'calendar', 'datatable', 'button' ]
   style_urls = ['skins/standard/bug.css']
   javascript_urls = [ "js/attachment.js", "js/util.js",
                       "js/field.js", "js/TUI.js", "js/bug.js" ]
index 5402624f66412e84d0fb18b5eee330aa25de1daa..460b5b69747ad666a4f4540ee5143685bb9d790c 100644 (file)
   [% IF user.can_tag_comments %]
     <div id="bz_ctag_div" class="bz_default_hidden">
       <a href="javascript:void(0)" onclick="YAHOO.bugzilla.commentTagging.hideInput()">x</a>
-      <div>
+      <span>
         <input id="bz_ctag_add" size="10" placeholder="add tag"
               maxlength="[% constants.MAX_COMMENT_TAG_LENGTH FILTER html %]">
         <span id="bz_ctag_autocomp"></span>
-      </div>
+      </span>
       &nbsp;
     </div>
     <div id="bz_ctag_error" class="bz_default_hidden">
index f1ddf633fc8e66a0c726c99ed58df1d757002c0e..bfd385f9d91a0b1cdd15f2e07d5367f1da462eb9 100644 (file)
            </script>
          [% END %]
        [% END %]
-     [% CASE constants.FIELD_TYPE_KEYWORDS %]
-       <div id="[% field.name FILTER html %]_container">
-         <input type="text" id="[% field.name FILTER html %]" size="40"
-                class="text_input" name="[% field.name FILTER html %]"
-                value="[% value FILTER html %]">
-         <div id="[% field.name FILTER html %]_autocomplete"></div>
-       </div>
-       <script type="text/javascript">
-         if (typeof YAHOO.bugzilla.field_array === "undefined")
-           YAHOO.bugzilla.field_array = [];
-         YAHOO.bugzilla.field_array["[% field.name FILTER js %]"] = [
-           [%- FOREACH val = possible_values %]
-             [%-# %]"[% val FILTER js %]"
-             [%- "," IF NOT loop.last %][% END %]];
-         YAHOO.bugzilla.fieldAutocomplete.init('[% field.name FILTER js %]',
-                                               '[% field.name FILTER js %]_autocomplete');
-       </script>
+    [% CASE constants.FIELD_TYPE_KEYWORDS %]
+      <input type="text" id="[% field.name FILTER html %]" size="40"
+             class="text_input bz_autocomplete_values"
+             name="[% field.name FILTER html %]"
+             data-values="[% field.name FILTER html %]"
+             value="[% value FILTER html %]">
+      <script type="text/javascript">
+        if (typeof BUGZILLA.autocomplete_values === 'undefined')
+          BUGZILLA.autocomplete_values = [];
+        BUGZILLA.autocomplete_values['[% field.name FILTER js %]'] = [
+          [%- FOREACH val = possible_values %]
+            [%- %]"[% val FILTER js %]"
+            [%- "," IF NOT loop.last %][% END %]];
+      </script>
   [% END %]
 [% ELSE %]
   [% SWITCH field.type %]
index f18afed961578ac134b44372f94dc17dbfdb0c91..473df17dad412ac135cfbfbbea749f454f2068a3 100644 (file)
@@ -24,8 +24,8 @@
 [% END %]
 [% title = title _ filtered_desc %]
 [% generate_api_token = 1 %]
-[% yui = ['autocomplete', 'calendar'] %]
-[% yui.push('container') IF user.can_tag_comments %]
+[% yui = [ 'calendar' ] %]
+[% yui.push('json', 'connection', 'container') IF user.can_tag_comments %]
 [% javascript_urls = [ "js/util.js", "js/field.js", "js/comments.js" ] %]
 [% javascript_urls.push("js/bug.js") IF user.id  %]
 [% javascript_urls.push('js/comment-tagging.js')
index 65b96ec84e336876971dbeed78a63ee33a890f61..b05784ebe3ddfaa9ff6954ec631019f1a4f7a38e 100644 (file)
@@ -43,7 +43,6 @@
 
 [% IF NOT no_yui %]
   [% SET yui_css = {
-    autocomplete => 1,
     calendar     => 1,
     datatable    => 1,
     button       => 1,
@@ -54,8 +53,7 @@
     # if that module is going to be specified in "yui".
     #%]
   [% SET yui_deps = {
-    autocomplete => ['json', 'connection', 'datasource'],
-    datatable    => ['json', 'connection', 'datasource', 'element'],
+    datatable => ['json', 'connection', 'datasource', 'element'],
   } %]
 
   [%# When using certain YUI modules, we need to process certain
@@ -86,8 +84,8 @@
 ] %]
 [% style_urls.import(jquery_css, jq_css_urls) FILTER null %]
 
-[%# Add jQuery cookie support %]
-[% jquery.push("cookie") %]
+[%# Add our required jQuery plugins %]
+[% jquery.push("cookie", "devbridgeAutocomplete") %]
 
 [%# We should be able to set the default value of the header variable
   # to the value of the title variable using the DEFAULT directive,
index e2210c6f2deb5a5a61d6dc7647ddf572f1e6f241..67d9f8d481300177122977842a627657552fd3ac 100644 (file)
   [% END %]
 </select>
 [% ELSE %]
-  [% IF feature_enabled('jsonrpc') && Param('ajax_user_autocompletion') && id %]
-    <div id="[% id FILTER html %]_autocomplete" 
-         [% IF classes %] class="[% classes.join(' ') FILTER html %]" [% END %]>
-  [% END %]  
+  [%
+    IF id && feature_enabled('jsonrpc') && Param('ajax_user_autocompletion');
+      IF !classes.defined;
+        classes = [];
+      END;
+      classes.push("bz_autocomplete_user");
+    END;
+  %]
   <input
     name="[% name FILTER html %]"
     value="[% value FILTER html %]"
     [% IF size %] size="[% size FILTER html %]" [% END %]
     [% IF id %] id="[% id FILTER html %]" [% END %]
     [% IF mandatory %] required [% END %]
+    [% IF multiple %] data-multiple="1" [% END %]
   >
-  [% IF feature_enabled('jsonrpc') && Param('ajax_user_autocompletion') && id %]
-    <div id="[% id FILTER html %]_autocomplete_container"></div>
-    </div>  
-    <script type="text/javascript">
-      if( typeof(YAHOO.bugzilla.userAutocomplete) !== 'undefined' 
-          && YAHOO.bugzilla.userAutocomplete != null){
-        YAHOO.bugzilla.userAutocomplete.init( "[% id FILTER js %]", 
-                    "[% id FILTER js %]_autocomplete_container"
-                    [% IF multiple %], true[% END%]);        
-      }
-    </script>
-  [% END %]
 [% END %]
index 65065bf321ceaf9d4835a2833044e512efa9e613..c8750ffcd77bfe7b64a2e62d5474c31f8408ac49 100644 (file)
@@ -61,7 +61,7 @@
   title = title
   generate_api_token = dotweak
   atomlink = "buglist.cgi?$urlquerypart&title=$title&ctype=atom" 
-  yui = [ 'autocomplete', 'calendar' ]
+  yui = [ 'calendar' ]
   javascript_urls = [ "js/util.js", "js/field.js", "js/TUI.js" ]
   style_urls = [ "skins/standard/buglist.css" ]
   doc_section = "using/finding.html"
index 828bdba9f9ab62c87916f62794220f12ff5aed43..4e406190db6d8107b63a02f76977cfe8c8ef68ae 100644 (file)
@@ -15,7 +15,6 @@
   onload="var f = document.request_form; selectProduct(f.product, f.component, null, null, 'Any');"
   javascript_urls=["js/productform.js", "js/field.js"]
   style_urls = ['skins/standard/buglist.css']
-  yui = ['autocomplete']
 %]
 
 <script type="text/javascript">
index 5a95d67c15816513eb29ca85695108ea15b70c5c..b2013eff6407d4095a26d712596733c715bb06dd 100644 (file)
        types = types, 
        selected = type_selected
     %]
-    <div id="[% field.name FILTER html %]_container">
-       <input name="[% field.name FILTER html %]" 
-              id="[% field.name FILTER html %]" size="40"
-              [% IF onchange %] onchange="[% onchange FILTER html %]"[% END %]
-              value="[% value FILTER html %]" [% 'autofocus' IF focus %]>
-       <div id="[% field.name FILTER html %]_autocomplete"></div>
-    </div>
+    <input name="[% field.name FILTER html %]"
+           id="[% field.name FILTER html %]" size="40"
+           class="bz_autocomplete_values"
+           [% IF onchange %] onchange="[% onchange FILTER html %]"[% END %]
+           value="[% value FILTER html %]" [% 'autofocus' IF focus %]
+           data-values="[% field.name FILTER html %]">
     <script type="text/javascript">
-      if (typeof YAHOO.bugzilla.field_array === "undefined")
-        YAHOO.bugzilla.field_array = [];
-      YAHOO.bugzilla.field_array["[% field.name FILTER js %]"] = [
+      if (typeof BUGZILLA.autocomplete_values === 'undefined')
+        BUGZILLA.autocomplete_values = [];
+      BUGZILLA.autocomplete_values['[% field.name FILTER js %]'] = [
         [%- FOREACH val = possible_values %]
-          [%-# %]"[% val FILTER js %]"
+          [%- %]"[% val FILTER js %]"
           [%- "," IF NOT loop.last %][% END %]];
-      YAHOO.bugzilla.fieldAutocomplete.init('[% field.name FILTER js %]',
-                                            '[% field.name FILTER js %]_autocomplete');
     </script>
   [% CASE [constants.FIELD_TYPE_DATETIME, constants.FIELD_TYPE_DATE] %]
     [% INCLUDE "bug/field-label.html.tmpl"
index c9265f076ef10568a51f3457edddc18fb9dd3bdc..410bd2d20bb7d6b99d7674d049cfab7537e3c64a 100644 (file)
@@ -268,19 +268,11 @@ TUI_hide_default('information_query');
           [% " selected" IF default.emailtype.$n == qv.name %]>[% qv.description %]</option>
       [% END %]
       </select>
-      [% IF feature_enabled('jsonrpc') && Param('ajax_user_autocompletion') %]
-        <div id="email[% n %]_autocomplete">
-      [% END %]
-      <input name="email[% n %]" class="email" id="email[% n %]" 
-             value="[% default.email.$n FILTER html %]">
-      [% IF feature_enabled('jsonrpc') && Param('ajax_user_autocompletion') %]
-        <div id="email[% n %]_autocomplete_container"></div>
-        </div>
-        <script type="text/javascript">
-          YAHOO.bugzilla.userAutocomplete.init( "email[% n %]", 
-                    "email[% n %]_autocomplete_container");
-        </script>
-      [% END %]
+      <input
+        name="email[% n %]"
+        class="email [% "bz_autocomplete_user" IF feature_enabled('jsonrpc') && Param('ajax_user_autocompletion') %]"
+        id="email[% n %]"
+        value="[% default.email.$n FILTER html %]">
     </div>
   [% END %]
    [% Hook.process('email_numbering_end') %]
index 07c5fc52851afa6de1de730eef52202fcb44dde6..af07aa4759d67d605a1340355c2c4bcb45454eb4 100644 (file)
@@ -26,7 +26,8 @@ function remove_token() {
 
 [% PROCESS global/header.html.tmpl
   title = "Search for $terms.bugs"
-  yui = [ 'autocomplete', 'calendar' ]
+  generate_api_token = 1
+  yui = [ 'calendar' ]
   javascript = javascript
   javascript_urls = [ "js/util.js", "js/TUI.js", "js/field.js"]
   style_urls = ['skins/standard/buglist.css']
index 95750ebc02c2996f108a0826136dd49ea4edc82f..6df1a79d3c19e464ed267441763ba66f16aaff02 100644 (file)
@@ -19,7 +19,7 @@
 [% PROCESS global/header.html.tmpl 
   title = "Create New Data Set"
   onload = "doOnSelectProduct(0);"
-  yui = [ 'autocomplete', 'calendar' ]
+  yui = [ 'calendar' ]
   javascript = js_data 
   javascript_urls = [ "js/util.js", "js/TUI.js", "js/field.js" ]
   style_urls = ['skins/standard/buglist.css']
index b382edf95d30ba8c66616404c14f97104478323f..6cbafd11cbcda42da0013e652aad2b1dee1054c0 100644 (file)
@@ -18,7 +18,7 @@ var queryform = "reportform"
 [% PROCESS global/header.html.tmpl
   title = "Generate Graphical Report"
   onload = "doOnSelectProduct(0); chartTypeChanged()"
-  yui = [ 'autocomplete', 'calendar' ]
+  yui = [ 'calendar' ]
   javascript = js_data
   javascript_urls = [ "js/util.js", "js/TUI.js", "js/field.js" ]
   style_urls = ['skins/standard/buglist.css']
index 483fd5b07e1e4ef186c846b13fca0df4aa01be25..18c87131346537f708bcf79efb31c56cae819677 100644 (file)
@@ -18,7 +18,7 @@ var queryform = "reportform"
 [% PROCESS global/header.html.tmpl
   title = "Generate Tabular Report"
   onload = "doOnSelectProduct(0)"
-  yui = [ 'autocomplete', 'calendar' ]
+  yui = [ 'calendar' ]
   javascript = js_data
   javascript_urls = [ "js/util.js", "js/TUI.js", "js/field.js" ]
   style_urls = ['skins/standard/buglist.css']