[Rt-commit] rt branch, 4.2/refactor-user-group-autocomplete, created. rt-4.1.8-574-g6491f65

? sunnavy sunnavy at bestpractical.com
Sun Jun 16 10:30:57 EDT 2013


The branch, 4.2/refactor-user-group-autocomplete has been created
        at  6491f65ac31b3dccd999553e15dc64b70bb2d74b (commit)

- Log -----------------------------------------------------------------
commit 6491f65ac31b3dccd999553e15dc64b70bb2d74b
Author: sunnavy <sunnavy at bestpractical.com>
Date:   Sun Jun 16 21:18:01 2013 +0800

    migrate old user/group autocomplete code to use data-complete* attributes instead
    
    one thing to note: old autocomplete code took inputs with name matching
    /WatcherAddressEmail[123]/ as multiple email addresses(they are used in
    /Ticket/ModifyPeope.html), but they are not actually(yet), so I chose to not
    make the change accordingly, i.e. I just took them as single ones.

diff --git a/share/html/Admin/Elements/EditRights b/share/html/Admin/Elements/EditRights
index 9f694e9..ec5ec69 100644
--- a/share/html/Admin/Elements/EditRights
+++ b/share/html/Admin/Elements/EditRights
@@ -135,6 +135,11 @@ for my $category (@$Principals) {
     <li class="addprincipal">
       <a href="#acl-AddPrincipal">
         <input type="text" value=""
+            data-autocomplete="<% lc $AddPrincipal eq 'user' ? 'Users' : 'Groups' %>"
+% if ( lc $AddPrincipal eq 'user' ) {
+            data-autocomplete-return="Name"
+            data-autocomplete-privileged="1"
+% }
                name="AddPrincipalForRights-<% lc $AddPrincipal %>"
                id="AddPrincipalForRights-<% lc $AddPrincipal %>" />
         <script type="text/javascript">
@@ -143,13 +148,8 @@ for my $category (@$Principals) {
                 toggle_addprincipal_validity(this, true);
             });
 
-% if (lc $AddPrincipal eq 'group') {
-            jQuery("#AddPrincipalForRights-"+<% lc $AddPrincipal |n,j%>).autocomplete({
-                source: RT.Config.WebPath + "/Helpers/Autocomplete/Groups",
-                select: addprincipal_onselect,
-                change: addprincipal_onchange
-            });
-% }
+            jQuery("#AddPrincipalForRights-"+<% lc $AddPrincipal |n,j%>).on("autocompleteselect", addprincipal_onselect);
+            jQuery("#AddPrincipalForRights-"+<% lc $AddPrincipal |n,j%>).on("autocompletechange", addprincipal_onchange);
         });
         </script>
 % my $type = lc $AddPrincipal eq 'user' ? loc('username') : loc($AddPrincipal);
diff --git a/share/html/Admin/Elements/SelectNewGroupMembers b/share/html/Admin/Elements/SelectNewGroupMembers
index 3d79976..9731786 100644
--- a/share/html/Admin/Elements/SelectNewGroupMembers
+++ b/share/html/Admin/Elements/SelectNewGroupMembers
@@ -47,33 +47,27 @@
 %# END BPS TAGGED BLOCK }}}
 % if ( $Show ne 'Groups' ) {
 <label for="<% $Name %>Users"><&|/l&>Add user</&>:</label>
-<input type="text" value="" name="<% $Name %>Users" id="<% $Name %>Users" /><br />
+<input type="text" value="" name="<% $Name %>Users" id="<% $Name %>Users" data-autocomplete="Users" data-autocomplete-return="Name" data-autocomplete-privileged="1" data-autocomplete-exclude="<% $user_ids |n %>" /><br />
 <script type="text/javascript">
 jQuery(function(){
-    jQuery("#"+<% $Name |n,j%>+"Users").autocomplete({
-        source: RT.Config.WebPath + "/Helpers/Autocomplete/Users?return=Name;privileged=1;exclude="+<% $user_ids |n,u,j %>,
-        // Auto-submit once a user is chosen
-        select: function( event, ui ) {
-            jQuery(event.target).val(ui.item.value);
-            jQuery(event.target).closest("form").submit();
-        }
-    }).addClass("autocompletes-user");
+    // Auto-submit once a user is chosen
+    jQuery("#"+<% $Name |n,j%>+"Users").on("autocompleteselect", function( event, ui ) {
+        jQuery(event.target).val(ui.item.value);
+        jQuery(event.target).closest("form").submit();
+    });
 });
 </script>
 % }
 
 % if ( $Show ne 'Users' ) {
 <label for="<% $Name %>Groups"><&|/l&>Add group</&>:</label>
-<input type="text" value="" name="<% $Name %>Groups" id="<% $Name %>Groups" /><br />
+<input type="text" value="" name="<% $Name %>Groups" id="<% $Name %>Groups" data-autocomplete="Groups" data-autocomplete-exclude="<% $group_ids |n %>" /><br />
 <script type="text/javascript">
 jQuery(function(){
-    jQuery("#"+<% $Name |n,j%>+"Groups").autocomplete({
-        source: RT.Config.WebPath + "/Helpers/Autocomplete/Groups?exclude="+<% $group_ids |n,u,j %>,
-        // Auto-submit once a user is chosen
-        select: function( event, ui ) {
-            jQuery(event.target).val(ui.item.value);
-            jQuery(event.target).closest("form").submit();
-        }
+    // Auto-submit once a group is chosen
+    jQuery("#"+<% $Name |n,j%>+"Groups").on("autocompleteselect", function( event, ui ) {
+        jQuery(event.target).val(ui.item.value);
+        jQuery(event.target).closest("form").submit();
     });
 });
 </script>
diff --git a/share/html/Admin/Groups/index.html b/share/html/Admin/Groups/index.html
index bb5a23d..58ee1a5 100644
--- a/share/html/Admin/Groups/index.html
+++ b/share/html/Admin/Groups/index.html
@@ -53,16 +53,12 @@
 <input type="hidden" name="GroupField" value="Name" />
 <input type="hidden" name="GroupOp" value="LIKE" />
 <&|/l&>Go to group</&>
-<input type="text" name="GroupString" value="" id="autocomplete-GroupString" />
+<input type="text" name="GroupString" value="" data-autocomplete="Groups" id="autocomplete-GroupString" />
 <script type="text/javascript">
 jQuery(function(){
-    jQuery("#autocomplete-GroupString").autocomplete({
-        source: RT.Config.WebPath + "/Helpers/Autocomplete/Groups",
-        // Jump directly to the page if a group is chosen
-        select: function( event, ui ) {
-            document.location = RT.Config.WebPath + "/Admin/Groups/Modify.html?id="
-                + ui.item.id;
-        }
+    // Jump directly to the page if a group is chosen
+    jQuery("#autocomplete-GroupString").on("autocompleteselect", function( event, ui ) {
+        document.location = RT.Config.WebPath + "/Admin/Groups/Modify.html?id=" + ui.item.id;
     });
 });
 </script>
diff --git a/share/html/Admin/Users/index.html b/share/html/Admin/Users/index.html
index 3bd3758..a22895d 100644
--- a/share/html/Admin/Users/index.html
+++ b/share/html/Admin/Users/index.html
@@ -58,17 +58,13 @@
 <input type="hidden" name="UserField" value="Name" />
 <input type="hidden" name="UserOp" value="LIKE" />
 <&|/l&>Go to user</&>
-<input type="text" name="UserString" value="" id="autocomplete-UserString" />
+<input type="text" name="UserString" value="" data-autocomplete="Users" data-autocomplete-return="Name" id="autocomplete-UserString" />
 <script type="text/javascript">
 jQuery(function(){
-    jQuery("#autocomplete-UserString").autocomplete({
-        source: RT.Config.WebPath + "/Helpers/Autocomplete/Users?return=Name",
-        // Jump directly to the page if a user is chosen
-        select: function( event, ui ) {
-            document.location = RT.Config.WebPath + "/Admin/Users/Modify.html?id="
-                + ui.item.id;
-        }
-    }).addClass("autocompletes-user");
+    // Jump directly to the page if a user is chosen
+    jQuery("#autocomplete-UserString").on("autocompleteselect", function( event, ui ) {
+        document.location = RT.Config.WebPath + "/Admin/Users/Modify.html?id=" + ui.item.id;
+    });
 });
 </script>
 </form>
diff --git a/share/html/Elements/EmailInput b/share/html/Elements/EmailInput
index 7d79b2b..f0b9bdd 100644
--- a/share/html/Elements/EmailInput
+++ b/share/html/Elements/EmailInput
@@ -45,10 +45,11 @@
 %# those contributions and any derivatives thereof.
 %#
 %# END BPS TAGGED BLOCK }}}
-<input type="text" id="<% $Name %>" name="<% $Name %>" <% defined $Size ? qq{size="$Size"} : '' |n %> value="<% $Default || '' %>" <% $Autocomplete ? q{data-autocomplete="Users"} : '' |n%> />
+<input type="text" id="<% $Name %>" name="<% $Name %>" <% defined $Size ? qq{size="$Size"} : '' |n %> value="<% $Default || '' %>" <% $Autocomplete ? q{data-autocomplete="Users"} : '' |n%> <% $AutocompleteMultiple ? q{data-autocomplete-multiple} : '' |n%> />
 <%ARGS>
 $Name
 $Size    => 40
 $Default => ''
 $Autocomplete => 1
+$AutocompleteMultiple => 0
 </%ARGS>
diff --git a/share/html/Elements/GotoUser b/share/html/Elements/GotoUser
index df28120..63f31e9 100644
--- a/share/html/Elements/GotoUser
+++ b/share/html/Elements/GotoUser
@@ -46,17 +46,13 @@
 %#
 %# END BPS TAGGED BLOCK }}}
 <form name="UserSearch" method="post" action="<% RT->Config->Get('WebPath') %>/User/Search.html">
-<input type="text" name="UserString" value="<% $Default %>" id="autocomplete-UserString" />
+<input type="text" name="UserString" value="<% $Default %>" data-autocomplete="Users" data-autocomplete-return="Name" id="autocomplete-UserString" />
 <script type="text/javascript">
 jQuery(function(){
-    jQuery("#autocomplete-UserString").autocomplete({
-        source: RT.Config.WebPath + "/Helpers/Autocomplete/Users?return=Name",
-        // Jump directly to the page if a user is chosen
-        select: function( event, ui ) {
-            document.location = RT.Config.WebPath + "/User/Summary.html?id="
-                + ui.item.id;
-        }
-    }).addClass("autocompletes-user");
+    // Jump directly to the page if a user is chosen
+    jQuery("#autocomplete-UserString").on("autocompleteselect", function( event, ui ) {
+        document.location = RT.Config.WebPath + "/User/Summary.html?id=" + ui.item.id;
+    });
 });
 </script>
 <input type="submit" name="UserSearch" value="<&|/l&>Search</&>" class="button" />
diff --git a/share/html/Elements/QuickCreate b/share/html/Elements/QuickCreate
index 4925168..5c0ba41 100644
--- a/share/html/Elements/QuickCreate
+++ b/share/html/Elements/QuickCreate
@@ -68,7 +68,7 @@
 </tr>
 <tr class="input-row">
     <td class="label"><&|/l&>Requestors</&>:</td>
-    <td colspan="3" class="value"><& /Elements/EmailInput, Name => 'Requestors', Size => '40', Default => $ARGS{Requestors} || $session{CurrentUser}->EmailAddress &></td>
+    <td colspan="3" class="value"><& /Elements/EmailInput, Name => 'Requestors', Size => '40', Default => $ARGS{Requestors} || $session{CurrentUser}->EmailAddress, AutocompleteMultiple => 1 &></td>
 </tr>
 <tr class="input-row">
 <td class="labeltop"><&|/l&>Content</&>:</td>
diff --git a/share/html/Search/Bulk.html b/share/html/Search/Bulk.html
index 4c7894b..2858bc0 100644
--- a/share/html/Search/Bulk.html
+++ b/share/html/Search/Bulk.html
@@ -83,17 +83,17 @@
 <label>(<input type="checkbox" class="checkbox" name="ForceOwnerChange"
 <% $ARGS{ForceOwnerChange} ? 'checked="checked"' : '' %> /> <&|/l&>Force change</&>)</label></td></tr>
 <tr><td class="label"> <&|/l&>Add Requestor</&>: </td>
-<td class="value"> <input name="AddRequestor" size="20" value="<% $ARGS{AddRequestor} || '' %>" /> </td></tr>
+<td class="value"> <& /Elements/EmailInput, Name => "AddRequestor", Size=> 20, Default => $ARGS{AddRequestor} &> </td></tr>
 <tr><td class="label"> <&|/l&>Remove Requestor</&>: </td>
-<td class="value"> <input name="DeleteRequestor" size="20" value="<% $ARGS{DeleteRequestor} || '' %>"/> </td></tr>
+<td class="value"> <& /Elements/EmailInput, Name => "DeleteRequestor", Size=> 20, Default => $ARGS{DeleteRequestor} &> </td></tr>
 <tr><td class="label"> <&|/l&>Add Cc</&>: </td>
-<td class="value"> <input name="AddCc" size="20" value="<% $ARGS{AddCc} || '' %>" /> </td></tr>
+<td class="value"> <& /Elements/EmailInput, Name => "AddCc", Size=> 20, Default => $ARGS{AddCc} &> </td></tr>
 <tr><td class="label"> <&|/l&>Remove Cc</&>: </td>
-<td class="value"> <input name="DeleteCc" size="20" value="<% $ARGS{DeleteCc} || '' %>" /> </td></tr>
+<td class="value"> <& /Elements/EmailInput, Name => "DeleteCc", Size=> 20, Default => $ARGS{DeleteCc} &> </td></tr>
 <tr><td class="label"> <&|/l&>Add AdminCc</&>: </td>
-<td class="value"> <input name="AddAdminCc" size="20" value="<% $ARGS{AddAdminCc} || '' %>" /> </td></tr>
+<td class="value"> <& /Elements/EmailInput, Name => "AddAdminCc", Size=> 20, Default => $ARGS{AddAdminCc} &> </td></tr>
 <tr><td class="label"> <&|/l&>Remove AdminCc</&>: </td>
-<td class="value"> <input name="DeleteAdminCc" size="20" value="<% $ARGS{DeleteAdminCc} || '' %>" /> </td></tr>
+<td class="value"> <& /Elements/EmailInput, Name => "DeleteAdminCc", Size=> 20, Default => $ARGS{DeleteAdminCc} &> </td></tr>
 </table>
 </td>
 <td valign="top">
diff --git a/share/html/SelfService/Create.html b/share/html/SelfService/Create.html
index 750af4c..65cce33 100644
--- a/share/html/SelfService/Create.html
+++ b/share/html/SelfService/Create.html
@@ -68,7 +68,7 @@
 <&|/l&>Requestors</&>:
 </td>
 <td class="value">
-<& /Elements/EmailInput, Name => 'Requestors', Size => '20', Default => $ARGS{Requestors} || $session{CurrentUser}->EmailAddress &>
+<& /Elements/EmailInput, Name => 'Requestors', Size => '20', Default => $ARGS{Requestors} || $session{CurrentUser}->EmailAddress, AutocompleteMultiple => 1 &>
 </td>
 </tr>
 <tr>
diff --git a/share/html/Ticket/Create.html b/share/html/Ticket/Create.html
index ed9ad2a..b954721 100644
--- a/share/html/Ticket/Create.html
+++ b/share/html/Ticket/Create.html
@@ -127,7 +127,7 @@
 <&|/l&>Requestors</&>:
 </td>
 <td class="value" colspan="5">
-<& /Elements/EmailInput, Name => 'Requestors', Size => undef, Default => $ARGS{Requestors} || $session{CurrentUser}->EmailAddress &>
+<& /Elements/EmailInput, Name => 'Requestors', Size => undef, Default => $ARGS{Requestors} || $session{CurrentUser}->EmailAddress, AutocompleteMultiple => 1 &>
 % $m->callback( CallbackName => 'AfterRequestors', QueueObj => $QueueObj, ARGSRef => \%ARGS );
 </td>
 </tr>
@@ -135,7 +135,7 @@
 <td class="label">
 <&|/l&>Cc</&>:
 </td>
-<td class="value" colspan="5"><& /Elements/EmailInput, Name => 'Cc', Size => undef, Default => $ARGS{Cc} &></td>
+<td class="value" colspan="5"><& /Elements/EmailInput, Name => 'Cc', Size => undef, Default => $ARGS{Cc}, AutocompleteMultiple => 1 &></td>
 </tr>
 
 <tr>
@@ -151,7 +151,7 @@
 <td class="label">
 <&|/l&>Admin Cc</&>:
 </td>
-<td class="value" colspan="5"><& /Elements/EmailInput, Name => 'AdminCc', Size => undef, Default => $ARGS{AdminCc} &></td>
+<td class="value" colspan="5"><& /Elements/EmailInput, Name => 'AdminCc', Size => undef, Default => $ARGS{AdminCc}, AutocompleteMultiple => 1 &></td>
 </tr>
 
 <tr>
diff --git a/share/html/Ticket/Elements/UpdateCc b/share/html/Ticket/Elements/UpdateCc
index e586e23..e491427 100644
--- a/share/html/Ticket/Elements/UpdateCc
+++ b/share/html/Ticket/Elements/UpdateCc
@@ -47,7 +47,7 @@
 %# END BPS TAGGED BLOCK }}}
 % $m->callback(CallbackName => 'BeforeCc', ARGSRef => \%ARGS, Ticket => $TicketObj, one_time_Ccs => \@one_time_Ccs, txn_addresses => \%txn_addresses);
 
-<tr><td class="label"><&|/l&>One-time Cc</&>:</td><td><& /Elements/EmailInput, Name => 'UpdateCc', Size => undef, Default => $ARGS{UpdateCc} &>
+<tr><td class="label"><&|/l&>One-time Cc</&>:</td><td><& /Elements/EmailInput, Name => 'UpdateCc', Size => undef, Default => $ARGS{UpdateCc}, AutocompleteMultiple => 1 &>
 <input type="hidden" id="UpdateIgnoreAddressCheckboxes" name="UpdateIgnoreAddressCheckboxes" value="0">
         <br />
 
@@ -66,7 +66,7 @@
       <label for="UpdateCc-<%$addr%>"><& /Elements/ShowUser, Address => $txn_addresses{$addr}&></label>
 %}
 </td></tr>
-<tr><td class="label"><&|/l&>One-time Bcc</&>:</td><td><& /Elements/EmailInput, Name => 'UpdateBcc', Size => undef, Default => $ARGS{UpdateBcc} &><br />
+<tr><td class="label"><&|/l&>One-time Bcc</&>:</td><td><& /Elements/EmailInput, Name => 'UpdateBcc', Size => undef, Default => $ARGS{UpdateBcc}, AutocompleteMultiple => 1 &><br />
 %if (scalar @one_time_Ccs) {
 <i class="label">(<&|/l&>check to add</&>)</i>
 %}
diff --git a/share/static/js/userautocomplete.js b/share/static/js/userautocomplete.js
index bd39605..f000df0 100644
--- a/share/static/js/userautocomplete.js
+++ b/share/static/js/userautocomplete.js
@@ -1,44 +1,32 @@
 jQuery(function() {
-    // inputs that accept multiple email addresses
-    var multipleCompletion = new Array("Requestors", "To", "Bcc", "Cc", "AdminCc", "WatcherAddressEmail[123]", "UpdateCc", "UpdateBcc");
 
-    // inputs with only a single email address allowed
-    var singleCompletion   = new Array("(Add|Delete)Requestor", "(Add|Delete)Cc", "(Add|Delete)AdminCc");
+    var cssClassMap = {
+        Users: 'user',
+        Groups: 'group'
+    };
 
-    // inputs for only privileged users
-    var privilegedCompletion = new Array("AddPrincipalForRights-user");
-
-    // build up the regexps we'll use to match
-    var applyto  = new RegExp('^(' + multipleCompletion.concat(singleCompletion, privilegedCompletion).join('|') + ')$');
-    var acceptsMultiple = new RegExp('^(' + multipleCompletion.join('|') + ')$');
-    var onlyPrivileged = new RegExp('^(' + privilegedCompletion.join('|') + ')$');
-
-    var inputs = document.getElementsByTagName("input");
-
-    for (var i = 0; i < inputs.length; i++) {
-        var input = inputs[i];
-        var inputName = input.getAttribute("name");
+    jQuery("input[data-autocomplete]").each(function(){
+        var input = jQuery(this);
+        var what  = input.attr("data-autocomplete");
+        var wants = input.attr("data-autocomplete-return");
 
-        if (!inputName || !inputName.match(applyto))
-            continue;
+        if (!what || !what.match(/^(Users|Groups)$/))
+            return;
 
+        var queryargs = [];
         var options = {
-            source: RT.Config.WebHomePath + "/Helpers/Autocomplete/Users"
+            source: RT.Config.WebHomePath + "/Helpers/Autocomplete/" + what
         };
 
-        var queryargs = [];
-
-        if (inputName.match("AddPrincipalForRights-user")) {
-            queryargs.push("return=Name");
-            options.select = addprincipal_onselect;
-            options.change = addprincipal_onchange;
+        if ( wants ) {
+            queryargs.push("return=" + wants);
         }
 
-        if (inputName.match(onlyPrivileged)) {
+        if (input.is('[data-autocomplete-privileged]')) {
             queryargs.push("privileged=1");
         }
 
-        if (inputName.match(acceptsMultiple)) {
+        if (input.is('[data-autocomplete-multiple]')) {
             queryargs.push("delim=,");
 
             options.focus = function () {
@@ -55,11 +43,15 @@ jQuery(function() {
             }
         }
 
+        var exclude = input.attr('data-autocomplete-exclude');
+        if (exclude) {
+            queryargs.push("exclude="+exclude);
+        }
+
         if (queryargs.length)
             options.source += "?" + queryargs.join("&");
 
-        jQuery(input)
-            .addClass('autocompletes-user')
+        input.addClass('autocompletes-' + cssClassMap[what] )
             .autocomplete(options)
             .data("ui-autocomplete")
             ._renderItem = function(ul, item) {
@@ -75,20 +67,5 @@ jQuery(function() {
                     .append( rendered )
                     .appendTo( ul );
             };
-    }
-
-    jQuery("input[data-autocomplete]:not(.ui-autocomplete-input)").each(function(){
-        var input = jQuery(this);
-        var what  = input.attr("data-autocomplete");
-        var wants = input.attr("data-autocomplete-return");
-
-        if (!what || !what.match(/^(Users|Groups)$/))
-            return;
-
-        input.autocomplete({
-            source: RT.Config.WebPath + "/Helpers/Autocomplete/" + what
-                    + (wants ? "?return=" + wants : "")
-        });
     });
-
 });

-----------------------------------------------------------------------


More information about the Rt-commit mailing list