Commit bf3e63a7 authored by Reed Loden's avatar Reed Loden

Bug 455810 - Add autocomplete support to the keywords field

* Special thanks to Guy Pyrzak for the original patch [r=mkanat a=mkanat]
parent e598bc84
......@@ -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]+$/;
......
......@@ -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};
......
......@@ -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
......
......@@ -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();
}
});
}
};
......@@ -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 */
}
......@@ -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;
}
......@@ -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 %]
......
......@@ -591,8 +591,13 @@
<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 %]
......
......@@ -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:
......@@ -165,22 +167,35 @@
[% 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)
......
......@@ -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 %]
......@@ -173,7 +174,7 @@
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>
......@@ -188,7 +189,7 @@
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>
......@@ -200,7 +201,7 @@
<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>
......@@ -212,13 +213,15 @@
[% 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>
......@@ -236,7 +239,7 @@
</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>
......@@ -251,7 +254,7 @@
</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>
......
......@@ -15,6 +15,7 @@
# Initial Developer. All Rights Reserved.
#
# Contributor(s): Guy Pyrzak <guy.pyrzak@gmail.com>
# Reed Loden <reed@reedloden.com>
#
#%]
[%# INTERFACE:
......@@ -35,16 +36,41 @@
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
......@@ -113,5 +139,4 @@
[% END %]
</select>
</div>
[% END %]
\ No newline at end of file
[% END %]
......@@ -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" ]
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment