[Rt-commit] rt branch, 4.6/inline-edit, updated. rt-4.4.1-151-g7dab12d

Shawn Moore shawn at bestpractical.com
Fri Sep 16 14:21:58 EDT 2016


The branch, 4.6/inline-edit has been updated
       via  7dab12d6b4a750a6076855041b73976a0ad94e81 (commit)
       via  116f73d0aaa5bf0c4080d57cc8a121962f5c9add (commit)
       via  8df33c9e683419df713fa2d9bb56bd86c1a0b6ee (commit)
       via  23a21abf1869cabde33978a6c3017338f3e34868 (commit)
       via  381f70340d6a5bd73f11390e3c7d07f4de41b7ea (commit)
       via  9d1ee367f94095999ddeba9197c3007b30031ea2 (commit)
      from  f444e0ea148fdd79143c1fae0c1860742f538a98 (commit)

Summary of changes:
 share/html/Elements/RT__Ticket/ColumnMap   |  16 ++---
 share/html/Elements/SelectDate             |   5 +-
 share/html/SelfService/Elements/MyRequests |  23 +++---
 share/static/js/util.js                    | 111 ++++++++++++++++++-----------
 4 files changed, 93 insertions(+), 62 deletions(-)

- Log -----------------------------------------------------------------
commit 9d1ee367f94095999ddeba9197c3007b30031ea2
Author: Shawn M Moore <shawn at bestpractical.com>
Date:   Fri Sep 16 17:21:48 2016 +0000

    Turn off inline edit for self-service
    
    Self-service users can't access the plumbing in the top-level /Helpers
    directory, so hide the porcelain too.

diff --git a/share/html/SelfService/Elements/MyRequests b/share/html/SelfService/Elements/MyRequests
index 8a988d0..d3291fd 100644
--- a/share/html/SelfService/Elements/MyRequests
+++ b/share/html/SelfService/Elements/MyRequests
@@ -46,16 +46,19 @@
 %#
 %# END BPS TAGGED BLOCK }}}
 <&| /Widgets/TitleBox, title => $title &>
-<& /Elements/CollectionList, Title   => $title,
-  Format  => $Format,
-  Query   => $Query,
-  Order   => @Order,
-  OrderBy => @OrderBy,
-  BaseURL => $BaseURL,
-  AllowSorting => 1,
-  Class   => 'RT::Tickets',
-  Rows    => $Rows,
-  Page    => $Page &>
+  <& /Elements/CollectionList,
+    Title        => $title,
+    Format       => $Format,
+    Query        => $Query,
+    Order        => @Order,
+    OrderBy      => @OrderBy,
+    BaseURL      => $BaseURL,
+    AllowSorting => 1,
+    Class        => 'RT::Tickets',
+    Rows         => $Rows,
+    Page         => $Page,
+    InlineEdit   => 0,
+  &>
 </&>
 
 <%INIT>

commit 381f70340d6a5bd73f11390e3c7d07f4de41b7ea
Author: Shawn M Moore <shawn at bestpractical.com>
Date:   Fri Sep 16 17:33:58 2016 +0000

    Factor out a submitInlineEdit function

diff --git a/share/static/js/util.js b/share/static/js/util.js
index 859a56e..d06e665 100644
--- a/share/static/js/util.js
+++ b/share/static/js/util.js
@@ -581,52 +581,11 @@ jQuery(function () {
         jQuery('.editable').removeClass('editing').removeClass('loading');
     };
 
-    // stop propagation when we click a hyperlink (e.g. ticket subject) so that
-    // the td.editable onclick handler doesn't also fire
-    jQuery(document).on('click', 'td.editable a', function (e) {
-        e.stopPropagation();
-    });
-
-    jQuery(document).on('click', 'td.editable', function (e) {
+    var submitInlineEdit = function (editor) {
         if (!inlineEditEnabled) {
             return;
         }
 
-        var cell = jQuery(this);
-        var value = cell.find('.value');
-        var editor = cell.find('.editor');
-
-        if (cell.hasClass('editing')) {
-            return;
-        }
-
-        var height = cell.height();
-
-        cell.addClass('editing');
-
-        if (editor.find('textarea').length || editor[0].clientWidth > cell[0].clientWidth) {
-            cell.attr('height', height);
-
-            var rect = editor[0].getBoundingClientRect();
-            editor.addClass('wide');
-            var top = rect.top - parseInt(editor.css('padding-top')) - parseInt(editor.css('border-top-width'));
-            var left = rect.left - parseInt(editor.css('padding-left')) - parseInt(editor.css('border-left-width'));
-            editor.css({ top: top, left: left });
-        }
-
-        editor.find(':input:visible:enabled:first').focus();
-    });
-
-    jQuery(document).on('change', 'td.editable.editing form :input', function () {
-        jQuery(this).closest('form').data('changed', true);
-    });
-
-    jQuery(document).on('focusout', 'td.editable.editing form', function () {
-        if (!inlineEditEnabled) {
-            return;
-        }
-
-        var editor = jQuery(this);
         var cell = editor.closest('td');
         var tbody = cell.closest('tbody');
         var table = tbody.closest('table');
@@ -670,6 +629,51 @@ jQuery(function () {
                 disableInlineEdit();
             }
         });
+    };
+
+    // stop propagation when we click a hyperlink (e.g. ticket subject) so that
+    // the td.editable onclick handler doesn't also fire
+    jQuery(document).on('click', 'td.editable a', function (e) {
+        e.stopPropagation();
+    });
+
+    jQuery(document).on('click', 'td.editable', function (e) {
+        if (!inlineEditEnabled) {
+            return;
+        }
+
+        var cell = jQuery(this);
+        var value = cell.find('.value');
+        var editor = cell.find('.editor');
+
+        if (cell.hasClass('editing')) {
+            return;
+        }
+
+        var height = cell.height();
+
+        cell.addClass('editing');
+
+        if (editor.find('textarea').length || editor[0].clientWidth > cell[0].clientWidth) {
+            cell.attr('height', height);
+
+            var rect = editor[0].getBoundingClientRect();
+            editor.addClass('wide');
+            var top = rect.top - parseInt(editor.css('padding-top')) - parseInt(editor.css('border-top-width'));
+            var left = rect.left - parseInt(editor.css('padding-left')) - parseInt(editor.css('border-left-width'));
+            editor.css({ top: top, left: left });
+        }
+
+        editor.find(':input:visible:enabled:first').focus();
+    });
+
+    jQuery(document).on('change', 'td.editable.editing form :input', function () {
+        jQuery(this).closest('form').data('changed', true);
+    });
+
+    jQuery(document).on('focusout', 'td.editable.editing form', function () {
+        var editor = jQuery(this);
+        submitInlineEdit(editor);
     });
 
     jQuery(document).on('submit', 'td.editable.editing form', function (e) {

commit 23a21abf1869cabde33978a6c3017338f3e34868
Author: Shawn M Moore <shawn at bestpractical.com>
Date:   Fri Sep 16 18:20:14 2016 +0000

    Add a way to omit id from date pickers
    
    Pass (id => '') to omit id from the datepicker field.
    
    jQuery UI's datepicker module gets very confused when ids are reused
    across different fields.
    
    Removing id from existant date picker fields would have back-compat
    implications, so this method is meant for new date picker fields (specifically
    inline edit)

diff --git a/share/html/Elements/SelectDate b/share/html/Elements/SelectDate
index eecae77..2e11d94 100644
--- a/share/html/Elements/SelectDate
+++ b/share/html/Elements/SelectDate
@@ -46,7 +46,7 @@
 %#
 %# END BPS TAGGED BLOCK }}}
 % $m->callback( %ARGS, Name => $Name, CallbackName => 'BeforeDateInput' );
-<input type="text" class="datepicker<% $ShowTime ? ' withtime' : '' %>" id="<% $Name %>" name="<% $Name %>" value="<% $Default %>" size="<% $Size %>" />
+<input type="text" class="datepicker<% $ShowTime ? ' withtime' : '' %>" <% $id ? qq[id="$id" ] : '' %>name="<% $Name %>" value="<% $Default %>" size="<% $Size %>" />
 % $m->callback( %ARGS, Name => $Name, CallbackName => 'AfterDateInput' );
 <%init>
 unless ((defined $Default) or ($current <= 0)) {
@@ -61,6 +61,8 @@ $Default ||= '';
 unless ($Name) {
     $Name = $menu_prefix. "_Date";
 }
+
+$id = $Name if !defined($id);
 </%init>
 
 <%args>
@@ -71,4 +73,5 @@ $current=>time
 $Default => ''
 $Name => undef
 $Size => 16
+$id => undef
 </%args>

commit 8df33c9e683419df713fa2d9bb56bd86c1a0b6ee
Author: Shawn M Moore <shawn at bestpractical.com>
Date:   Fri Sep 16 18:15:06 2016 +0000

    Fire update event off form submit, not form focusout
    
    focusout is a hint that we should submit, not the other way around

diff --git a/share/static/js/util.js b/share/static/js/util.js
index d06e665..df66470 100644
--- a/share/static/js/util.js
+++ b/share/static/js/util.js
@@ -671,14 +671,14 @@ jQuery(function () {
         jQuery(this).closest('form').data('changed', true);
     });
 
-    jQuery(document).on('focusout', 'td.editable.editing form', function () {
+    jQuery(document).on('submit', 'td.editable.editing form', function (e) {
+        e.preventDefault();
         var editor = jQuery(this);
         submitInlineEdit(editor);
     });
 
-    jQuery(document).on('submit', 'td.editable.editing form', function (e) {
-        e.preventDefault();
-        jQuery(this).find(':input:focus').blur();
+    jQuery(document).on('focusout', 'td.editable.editing form', function () {
+        jQuery(this).trigger('submit');
     });
 
     jQuery(document).on('change', 'td.editable.editing form select', function () {

commit 116f73d0aaa5bf0c4080d57cc8a121962f5c9add
Author: Shawn M Moore <shawn at bestpractical.com>
Date:   Fri Sep 16 18:16:07 2016 +0000

    Generate a datepicker:close event on datepicker close

diff --git a/share/static/js/util.js b/share/static/js/util.js
index df66470..0a8d5cd 100644
--- a/share/static/js/util.js
+++ b/share/static/js/util.js
@@ -227,7 +227,10 @@ jQuery(function() {
         changeYear: true,
         showOtherMonths: true,
         showOn: 'none',
-        selectOtherMonths: true
+        selectOtherMonths: true,
+        onClose: function() {
+            jQuery(this).trigger('datepicker:close');
+        }
     };
     jQuery(".datepicker").focus(function() {
         var val = jQuery(this).val();

commit 7dab12d6b4a750a6076855041b73976a0ad94e81
Author: Shawn M Moore <shawn at bestpractical.com>
Date:   Fri Sep 16 18:16:18 2016 +0000

    Better support inline edit of datepicker fields
    
    Focus leaves the inline edit form when interacting with the datepicker,
    as that element lives as a direct child of the <body> tag. So when we're
    using a datepicker, we can't use focusout as a hint that we should submit
    the inline edit.
    
    Instead we listen for the datepicker:close event for our hint that the user
    is done picking a date.
    
    Since the datepicker's DOM elements live outside of the inline edit <form>
    tag, we don't receive select onchange events for selecting the month/year,
    etc, so we don't have to filter out such events from our submit hint
    heuristics.
    
    Finally, because datepicker can't handle reused ids, we explicitly suppress
    them from inline edit datepicker fields. Since these fields are new there's
    less concern about backcompat.

diff --git a/share/html/Elements/RT__Ticket/ColumnMap b/share/html/Elements/RT__Ticket/ColumnMap
index 411aab4..15f587d 100644
--- a/share/html/Elements/RT__Ticket/ColumnMap
+++ b/share/html/Elements/RT__Ticket/ColumnMap
@@ -208,19 +208,19 @@ $COLUMN_MAP = {
         title     => 'Starts', # loc
         attribute => 'Starts',
         value     => sub { return $_[0]->StartsObj->AgeAsString },
-        edit      => sub { return \($m->scomp('/Elements/SelectDate', menu_prefix => 'Starts', current => 0, Default => $_[0]->StartsObj->Unix ? $_[0]->StartsObj->ISO( Timezone => 'user' ) : '')) },
+        edit      => sub { return \($m->scomp('/Elements/SelectDate', menu_prefix => 'Starts', id => '', current => 0, Default => $_[0]->StartsObj->Unix ? $_[0]->StartsObj->ISO( Timezone => 'user' ) : '')) },
     },
     StartedRelative => {
         title     => 'Started', # loc
         attribute => 'Started',
         value     => sub { return $_[0]->StartedObj->AgeAsString },
-        edit      => sub { return \($m->scomp('/Elements/SelectDate', menu_prefix => 'Started', current => 0, Default => $_[0]->StartedObj->Unix ? $_[0]->StartedObj->ISO( Timezone => 'user' ) : '')) },
+        edit      => sub { return \($m->scomp('/Elements/SelectDate', menu_prefix => 'Started', id => '', current => 0, Default => $_[0]->StartedObj->Unix ? $_[0]->StartedObj->ISO( Timezone => 'user' ) : '')) },
     },
     ToldRelative => {
         title     => 'Told', # loc
         attribute => 'Told',
         value     => sub { return $_[0]->ToldObj->AgeAsString },
-        edit      => sub { return \($m->scomp('/Elements/SelectDate', menu_prefix => 'Told', current => 0, Default => $_[0]->ToldObj->Unix ? $_[0]->ToldObj->ISO( Timezone => 'user' ) : '')) },
+        edit      => sub { return \($m->scomp('/Elements/SelectDate', menu_prefix => 'Told', id => '', current => 0, Default => $_[0]->ToldObj->Unix ? $_[0]->ToldObj->ISO( Timezone => 'user' ) : '')) },
     },
     DueRelative => {
         title     => 'Due', # loc
@@ -234,7 +234,7 @@ $COLUMN_MAP = {
                 return $date->AgeAsString;
             }
         },
-        edit      => sub { return \($m->scomp('/Elements/SelectDate', menu_prefix => 'Due', current => 0, Default => $_[0]->DueObj->Unix ? $_[0]->DueObj->ISO( Timezone => 'user' ) : '')) },
+        edit      => sub { return \($m->scomp('/Elements/SelectDate', menu_prefix => 'Due', id => '', current => 0, Default => $_[0]->DueObj->Unix ? $_[0]->DueObj->ISO( Timezone => 'user' ) : '')) },
     },
     ResolvedRelative => {
         title     => 'Resolved', # loc
@@ -245,19 +245,19 @@ $COLUMN_MAP = {
         title     => 'Starts', # loc
         attribute => 'Starts',
         value     => sub { return $_[0]->StartsObj->AsString },
-        edit      => sub { return \($m->scomp('/Elements/SelectDate', menu_prefix => 'Starts', current => 0, Default => $_[0]->StartsObj->Unix ? $_[0]->StartsObj->ISO( Timezone => 'user' ) : '')) },
+        edit      => sub { return \($m->scomp('/Elements/SelectDate', menu_prefix => 'Starts', id => '', current => 0, Default => $_[0]->StartsObj->Unix ? $_[0]->StartsObj->ISO( Timezone => 'user' ) : '')) },
     },
     Started => {
         title     => 'Started', # loc
         attribute => 'Started',
         value     => sub { return $_[0]->StartedObj->AsString },
-        edit      => sub { return \($m->scomp('/Elements/SelectDate', menu_prefix => 'Started', current => 0, Default => $_[0]->StartedObj->Unix ? $_[0]->StartedObj->ISO( Timezone => 'user' ) : '')) },
+        edit      => sub { return \($m->scomp('/Elements/SelectDate', menu_prefix => 'Started', id => '', current => 0, Default => $_[0]->StartedObj->Unix ? $_[0]->StartedObj->ISO( Timezone => 'user' ) : '')) },
     },
     Told => {
         title     => 'Told', # loc
         attribute => 'Told',
         value     => sub { return $_[0]->ToldObj->AsString },
-        edit      => sub { return \($m->scomp('/Elements/SelectDate', menu_prefix => 'Told', current => 0, Default => $_[0]->ToldObj->Unix ? $_[0]->ToldObj->ISO( Timezone => 'user' ) : '')) },
+        edit      => sub { return \($m->scomp('/Elements/SelectDate', menu_prefix => 'Told', id => '', current => 0, Default => $_[0]->ToldObj->Unix ? $_[0]->ToldObj->ISO( Timezone => 'user' ) : '')) },
     },
     Due => {
         title     => 'Due', # loc
@@ -271,7 +271,7 @@ $COLUMN_MAP = {
                 return $date->AsString;
             }
         },
-        edit      => sub { return \($m->scomp('/Elements/SelectDate', menu_prefix => 'Due', current => 0, Default => $_[0]->DueObj->Unix ? $_[0]->DueObj->ISO( Timezone => 'user' ) : '')) },
+        edit      => sub { return \($m->scomp('/Elements/SelectDate', menu_prefix => 'Due', id => '', current => 0, Default => $_[0]->DueObj->Unix ? $_[0]->DueObj->ISO( Timezone => 'user' ) : '')) },
     },
     Resolved => {
         title     => 'Resolved', # loc
diff --git a/share/static/js/util.js b/share/static/js/util.js
index 0a8d5cd..fb4bb83 100644
--- a/share/static/js/util.js
+++ b/share/static/js/util.js
@@ -584,6 +584,8 @@ jQuery(function () {
         jQuery('.editable').removeClass('editing').removeClass('loading');
     };
 
+    var inlineEditingDate = false;
+
     var submitInlineEdit = function (editor) {
         if (!inlineEditEnabled) {
             return;
@@ -602,6 +604,7 @@ jQuery(function () {
 
         var params = editor.serialize();
 
+        inlineEditingDate = false;
         editor.find(':input').attr('disabled', 'disabled');
         cell.removeClass('editing').addClass('loading');
         tbody.addClass('refreshing');
@@ -668,6 +671,12 @@ jQuery(function () {
         }
 
         editor.find(':input:visible:enabled:first').focus();
+
+        setTimeout(function () {
+            if (jQuery('#ui-datepicker-div').css('display') != 'none') {
+                inlineEditingDate = true;
+            }
+        }, 0);
     });
 
     jQuery(document).on('change', 'td.editable.editing form :input', function () {
@@ -681,13 +690,22 @@ jQuery(function () {
     });
 
     jQuery(document).on('focusout', 'td.editable.editing form', function () {
-        jQuery(this).trigger('submit');
+        if (!inlineEditingDate) {
+            jQuery(this).trigger('submit');
+        }
     });
 
     jQuery(document).on('change', 'td.editable.editing form select', function () {
         jQuery(this).closest('form').trigger('submit');
     });
 
+    jQuery(document).on('datepicker:close', 'td.editable.editing form .datepicker', function () {
+        var editor = jQuery(this);
+        setTimeout(function () {
+            editor.closest('form').trigger('submit');
+        }, 0);
+    });
+
     jQuery('table.collection-as-table').each(function () {
         var table = jQuery(this);
         var cols = table.find('colgroup col');

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


More information about the rt-commit mailing list