]> git.ipfire.org Git - thirdparty/bugzilla.git/commitdiff
Bug 455810 - Add autocomplete support to the keywords field
authorReed Loden <reed@reedloden.com>
Mon, 5 Jul 2010 07:42:01 +0000 (02:42 -0500)
committerReed Loden <reed@reedloden.com>
Mon, 5 Jul 2010 07:42:01 +0000 (02:42 -0500)
* Special thanks to Guy Pyrzak for the original patch
[r=mkanat a=mkanat]

12 files changed:
Bugzilla/Constants.pm
Bugzilla/Field.pm
Bugzilla/Template.pm
js/field.js
skins/standard/IE-fixes.css
skins/standard/global.css
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/list/edit-multiple.html.tmpl
template/en/default/search/field.html.tmpl
template/en/default/search/search-advanced.html.tmpl

index d11736af1038d1f4c38afd2ece250fcecf932b63..a003ce7398859f0b90ff4e332f816862ae54d56a 100644 (file)
@@ -128,6 +128,7 @@ use File::Basename;
     FIELD_TYPE_DATETIME
     FIELD_TYPE_BUG_ID
     FIELD_TYPE_BUG_URLS
+    FIELD_TYPE_KEYWORDS
 
     EMPTY_DATETIME_REGEX
 
@@ -395,6 +396,7 @@ use constant FIELD_TYPE_TEXTAREA  => 4;
 use constant FIELD_TYPE_DATETIME  => 5;
 use constant FIELD_TYPE_BUG_ID  => 6;
 use constant FIELD_TYPE_BUG_URLS => 7;
+use constant FIELD_TYPE_KEYWORDS => 8;
 
 use constant EMPTY_DATETIME_REGEX => qr/^[0\-:\sA-Za-z]+$/; 
 
index 9ab5c49b9e0f8dc709348c20543b5d2cc49a2fb8..15b4947627493e45d02d85db2692f77a8c63382d 100644 (file)
@@ -182,7 +182,7 @@ use constant DEFAULT_FIELDS => (
     {name => 'status_whiteboard', desc => 'Status Whiteboard',
      in_new_bugmail => 1, buglist => 1},
     {name => 'keywords',     desc => 'Keywords',   in_new_bugmail => 1,
-     buglist => 1},
+     type => FIELD_TYPE_KEYWORDS, buglist => 1},
     {name => 'resolution',   desc => 'Resolution',
      type => FIELD_TYPE_SINGLE_SELECT, buglist => 1},
     {name => 'bug_severity', desc => 'Severity',   in_new_bugmail => 1,
@@ -322,7 +322,7 @@ sub _check_type {
     my $saved_type = $type;
     # The constant here should be updated every time a new,
     # higher field type is added.
-    (detaint_natural($type) && $type <= FIELD_TYPE_BUG_URLS)
+    (detaint_natural($type) && $type <= FIELD_TYPE_KEYWORDS)
       || ThrowCodeError('invalid_customfield_type', { type => $saved_type });
 
     my $custom = blessed($invocant) ? $invocant->custom : $params->{custom};
index a317bb7c708577a90589c0090accc24ce861c089..71ade2f0165744e2ca20763133e1047652503273 100644 (file)
@@ -765,6 +765,9 @@ sub create {
             # Whether or not keywords are enabled, in this Bugzilla.
             'use_keywords' => sub { return Bugzilla::Keyword->any_exist; },
 
+            # All the keywords.
+            'all_keywords' => sub { return Bugzilla::Keyword->get_all(); },
+
             'feature_enabled' => sub { return Bugzilla->feature(@_); },
 
             # field_descs can be somewhat slow to generate, so we generate
index 39b272f920474a0b223d252e74d3fe8639e8d85b..20485bcc8ca573c9b8a087da8f19f6981bc0228d 100644 (file)
@@ -16,6 +16,7 @@
  *
  * Contributor(s): Max Kanat-Alexander <mkanat@bugzilla.org>
  *                 Guy Pyrzak <guy.pyrzak@gmail.com>
+ *                 Reed Loden <reed@reedloden.com>
  */
 
 /* This library assumes that the needed YUI libraries have been loaded 
@@ -621,8 +622,8 @@ YAHOO.bugzilla.userAutocomplete = {
         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.queryDelay = 0.05;
+        userAutoComp.useIFrame = true;
         userAutoComp.resultTypeList = false;
         if( multiple == true ){
             userAutoComp.delimChar = [","," "];
@@ -631,3 +632,32 @@ YAHOO.bugzilla.userAutocomplete = {
     }
 };
 
+YAHOO.bugzilla.keywordAutocomplete = {
+    dataSource : null,
+    init_ds : function(){
+        this.dataSource = new YAHOO.util.LocalDataSource( YAHOO.bugzilla.keyword_array );
+    },
+    init : function( field, container ) {
+        if( this.dataSource == null ){
+            this.init_ds();
+        }
+        var keywordAutoComp = new YAHOO.widget.AutoComplete(field, container, this.dataSource);
+        keywordAutoComp.maxResultsDisplayed = YAHOO.bugzilla.keyword_array.length;
+        keywordAutoComp.minQueryLength = 0;
+        keywordAutoComp.useIFrame = true;
+        keywordAutoComp.delimChar = [","," "];
+        keywordAutoComp.resultTypeList = false;
+        keywordAutoComp.queryDelay = 0;
+        /*  Causes all the possibilities in the keyword to appear when a user 
+         *  focuses on the textbox 
+         */
+        keywordAutoComp.textboxFocusEvent.subscribe( function(){
+            var sInputValue = YAHOO.util.Dom.get('keywords').value;
+            if( sInputValue.length === 0 ){
+                this.sendQuery(sInputValue);
+                this.collapseContainer();
+                this.expandContainer();
+            }
+        });
+    }
+};
index 1b6b9929f8661c807016384206bea68df33a2a35..fc2225398512d997e913cfcb315a36d9a16a4794 100644 (file)
@@ -47,6 +47,10 @@ form#Create #comp_desc {
 
 #bug_id_container, .search_field_grid, 
 .search_email_fields, ul.bug_changes li { 
-  zoom: 1;
-  display: inline;
-}
\ No newline at end of file
+    zoom: 1;
+    display: inline;
+}
+
+#keyword_container .yui-ac-content {
+    _height: 30em; /* ie6 */
+}
index 5cc71ef533ef52fa4cb6307ccf3043518795f6a4..f0809c33a37415e2b27af10da6697ed7a170d1a1 100644 (file)
@@ -527,7 +527,21 @@ input.required, select.required, span.required_explanation {
     background-image: url(global/down.png);
 }
 
-/* custom styles for inline instances of autocomplete input fields*/
+/* custom styles for inline instances of autocomplete input fields */
 .yui-skin-sam .yui-ac-input { position:static !important; 
-                              vertical-align:middle !important;}
-.yui-skin-sam .yui-ac-container { left:0px !important;}
+                              vertical-align:middle !important;
+                              width:auto !important; }
+.yui-skin-sam .yui-ac-container { left:0px !important; }
+.yui-skin-sam .yui-ac { display: inline-block; }
+
+#keyword_container {
+    padding-bottom: 2em;
+    padding-top: .2em;
+}
+
+#keyword_container .yui-ac-content {
+    max-height: 19em;
+    overflow: auto;
+    overflow-x: hidden;
+    margin-left: -1px;
+}
index 0733de02a06f4244bba737484ccca9bf861b3591..fdac893c0740a7485a64cc210aee52ce2fdadb39 100644 (file)
@@ -630,14 +630,11 @@ TUI_hide_default('expert_fields');
   [% IF user.in_group('editbugs', product.id) %]
     [% IF use_keywords %]
       <tr>
-        [% INCLUDE "bug/field-label.html.tmpl"
-          field = bug_fields.keywords editable = 1 
-          desc_url = "describekeywords.cgi"
+        [% INCLUDE bug/field.html.tmpl
+           bug = default, field = bug_fields.keywords, editable = 1,
+           value = keywords, desc_url = "describekeywords.cgi",
+           value_span = 2
         %]
-        <td colspan="3">
-          <input id="keywords" name="keywords" size="40"
-                 value="[% keywords FILTER html %]"> (optional)
-        </td>
       </tr>
     [% END %]
 
index 0ef3cba8f46e9619deb96985c7f89c12a90698a7..5520e769966fa832482818688da185b8772021bb 100644 (file)
         <label for="keywords" accesskey="k">
           <b><a href="describekeywords.cgi"><u>K</u>eywords</a></b></label>:
       </td>
-      [% PROCESS input inputname => "keywords" size => 40 colspan => 2
-                       value => bug.keywords.join(', ') %]
+      <td class="field_value" colspan="2">
+        [% INCLUDE bug/field.html.tmpl
+           bug = bug, field = bug_fields.keywords, value = bug.keywords
+           editable = bug.check_can_change_field("keywords", 0, 1),
+           no_tds = 1
+        %]
+      </td>
     </tr>
   [% END %]
 [% END %]
index 97d38661c2e5d5ca6fedac987c0003e33d0bcd08..2417ce39b25e4d57d42c71b8e9a61ab4127af9c6 100644 (file)
@@ -18,6 +18,8 @@
   # Contributor(s): Myk Melez <myk@mozilla.org>
   #                 Max Kanat-Alexander <mkanat@bugzilla.org>
   #                 Elliotte Martin <elliotte_martin@yahoo.com>
+  #                 Guy Pyrzak <guy.pyrzak@gmail.com>
+  #                 Reed Loden <reed@reedloden.com>
   #%]
 
 [%# INTERFACE:
        [% FOREACH url = value %]
          <li>
            <a href="[% url FILTER html %]">[% url FILTER html %]</a>
-           [% IF editable %]
-             <label><input type="checkbox" value="[% url FILTER html %]"
-                           name="remove_[% field.name FILTER html %]">
-               Remove</label>
-           [% END %]
+           <label><input type="checkbox" value="[% url FILTER html %]"
+                         name="remove_[% field.name FILTER html %]">
+             Remove</label>
          </li>
        [% END %]
        [% '</ul>' IF value.size %]
 
-       [% IF editable && Param('use_see_also') %]
+       [% IF Param('use_see_also') %]
          <label for="[% field.name FILTER html %]">
            <strong>Add [% terms.Bug %] URLs:</strong>
          </label><br>
          <input type="text" id="[% field.name FILTER html %]" size="40"
                 class="text_input" name="[% field.name FILTER html %]">
        [% END %]
+     [% CASE constants.FIELD_TYPE_KEYWORDS %]
+       <div id="keyword_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="keyword_autocomplete"></div>
+       </div>
+       <script type="text/javascript" defer="defer">
+         YAHOO.bugzilla.keyword_array = [
+           [%- FOREACH keyword = all_keywords %]
+             [%-# %]"[% keyword.name FILTER js %]"
+             [%- "," IF NOT loop.last %][% END %]];
+         YAHOO.bugzilla.keywordAutocomplete.init('[% field.name FILTER js %]', 
+                                                 'keyword_autocomplete');
+       </script>
   [% END %]
 [% ELSIF field.type == constants.FIELD_TYPE_TEXTAREA %]
   <div class="uneditable_textarea">[% value FILTER wrap_comment(60)
index 619afe8ddd637e9e8d49c6dd64bbbe9306ffa97f..87eb0c7d45929d72b26e6dfbff547f6aca914c5b 100644 (file)
@@ -19,6 +19,7 @@
   #                 Max Kanat-Alexander <mkanat@bugzilla.org>
   #                 Frédéric Buclin <LpSolit@gmail.com>
   #                 Guy Pyrzak <guy.pyrzak@gmail.com>
+  #                 Reed Loden <reed@reedloden.com>
   #%]
 
 [% PROCESS global/variables.none.tmpl %]
            id => "assigned_to"
            name => "assigned_to"
            value => dontchange
-           size => 32
+           size => 40
       %]
       <input type="checkbox" id="set_default_assignee" name="set_default_assignee" value="1">
       <label for="set_default_assignee">Reset Assignee to default</label>
              id => "qa_contact"
              name => "qa_contact"
              value => dontchange
-             size => 32
+             size => 40
         %]
         <input type="checkbox" id="set_default_qa_contact" name="set_default_qa_contact" value="1">
         <label for="set_default_qa_contact">Reset QA Contact to default</label>
 
     <th><label for="masscc">CC List:</label></th>
     <td colspan="3">
-      <input id="masscc" name="masscc" size="32">
+      <input id="masscc" name="masscc" size="40">
       <select name="ccaction">
         <option value="add">Add these to the CC List</option>
         <option value="remove">Remove these from the CC List</option>
   [% IF use_keywords %]
     <tr>
 
-      <th>
-        <label for="keywords">
-          <a href="describekeywords.cgi">Keywords</a>:
-        </label>
-      </th>
+      [% INCLUDE "bug/field-label.html.tmpl"
+         field = bug_fields.keywords, editable = 1
+         desc_url = "describekeywords.cgi"
+      %]
       <td colspan="3">
-        <input id="keywords" name="keywords" size="32">
+        [% INCLUDE bug/field.html.tmpl
+           field = bug_fields.keywords, editable = 1, value = keywords
+           no_tds = 1
+        %]
         <select name="keywordaction">
           <option value="add">Add these keywords</option>
           <option value="delete">Delete these keywords</option>
       </label>
     </th>
     <td colspan="3">
-      <input id="dependson" name="dependson" size="32">
+      <input id="dependson" name="dependson" size="40">
       <select name="dependson_action">
           <option value="add">Add these IDs</option>
           <option value="remove">Delete these IDs</option>
       </label>
     </th>
     <td colspan="3">
-      <input id="blocked" name="blocked" size="32">
+      <input id="blocked" name="blocked" size="40">
       <select name="blocked_action">
           <option value="add">Add these IDs</option>
           <option value="remove">Delete these IDs</option>
index 50a2f0c066cd95e0ae435586937c014f8c6550ad..d4a1a30b7abce72591cce434c9369be275ddc252 100644 (file)
@@ -15,6 +15,7 @@
   # Initial Developer. All Rights Reserved.
   #
   # Contributor(s): Guy Pyrzak <guy.pyrzak@gmail.com>
+  #                 Reed Loden <reed@reedloden.com>
   #
   #%]
 [%# INTERFACE:
       tag_name = "span"
       editable = 1
     %]
-
     [% INCLUDE "search/type-select.html.tmpl"
        name = field.name _ "_type",
        types = types, 
-       selected = type_selected  %]
-       
+       selected = type_selected
+    %]    
     <input name="[% field.name FILTER html %]" 
            id="[% field.name FILTER html %]" size="40"
            [% IF onchange %] onchange="[% onchange FILTER html %]"[% END %]
            value="[% value FILTER html %]">              
+  [% CASE constants.FIELD_TYPE_KEYWORDS %]
+    [% INCLUDE "bug/field-label.html.tmpl"
+      field = field
+      tag_name = "span"
+      editable = 1
+    %]
+    [% INCLUDE "search/type-select.html.tmpl"
+       name = field.name _ "_type",
+       types = types, 
+       selected = type_selected
+    %]
+    <div id="keyword_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 %]">
+       <div id="keyword_autocomplete"></div>
+    </div>
+    <script type="text/javascript" defer="defer">
+      YAHOO.bugzilla.keyword_array = [
+        [%- FOREACH keyword = all_keywords %]
+          [%-# %]"[% keyword.name FILTER js %]"
+          [%- "," IF NOT loop.last %][% END %]];
+      YAHOO.bugzilla.keywordAutocomplete.init('[% field.name FILTER js %]',
+                                              'keyword_autocomplete');
+    </script>
   [% CASE constants.FIELD_TYPE_DATETIME %]
     [% INCLUDE "bug/field-label.html.tmpl"
       field = field
         [% END %]
       </select>
     </div>
-  [% END %]  
-  
\ No newline at end of file
+  [% END %]
index 1e0cc9251de637ffe5d1ed4a4ec5ddc17a920fa6..fa9819c35cb09282d0f3e9e92e68c013c1dd49c9 100644 (file)
@@ -38,7 +38,7 @@ var queryform = "queryform"
   title = "Search for $terms.bugs"
   onload = "doOnSelectProduct(0); enableHelp();"
   javascript = js_data
-  yui = [ 'calendar' ]
+  yui = [ 'autocomplete', 'calendar' ]
   javascript_urls = [ "js/productform.js", "js/util.js",
                       "js/help.js" , "js/TUI.js", "js/field.js"]
   style_urls = [ "skins/standard/help.css" , "skins/standard/search_form.css" ]