From bc5617954a641620ccb6d3e654dd5e9bd09e1da4 Mon Sep 17 00:00:00 2001 From: epriestley Date: Mon, 28 Jan 2013 14:11:32 -0800 Subject: [PATCH] Make control + enter submit forms if a textarea is focused Summary: This is straightforward, except that `form.submit()` does not call onsubmit handlers. Create a `didSyntheticSubmit` event and have everything which listens for form submits listen for it too. Fixes T704. Test Plan: Hit control + enter in inline comments, main commetns, Pholio, conpherence. Verified it triggered appropriate JS (workflow / special behaviors). Reviewers: btrahan Reviewed By: btrahan CC: aran Maniphest Tasks: T704 Differential Revision: https://secure.phabricator.com/D4704 --- src/__celerity_resource_map__.php | 120 +++++++++--------- .../rsrc/js/application/core/behavior-form.js | 44 +++++-- .../js/application/core/behavior-workflow.js | 6 +- .../DifferentialInlineCommentEditor.js | 6 +- .../transactions/behavior-transaction-list.js | 29 +++-- 5 files changed, 121 insertions(+), 84 deletions(-) diff --git a/src/__celerity_resource_map__.php b/src/__celerity_resource_map__.php index a613d82359..2dd4e743a2 100644 --- a/src/__celerity_resource_map__.php +++ b/src/__celerity_resource_map__.php @@ -797,7 +797,7 @@ celerity_register_resource_map(array( ), 'differential-inline-comment-editor' => array( - 'uri' => '/res/1bc649b7/rsrc/js/application/differential/DifferentialInlineCommentEditor.js', + 'uri' => '/res/e0ad34ac/rsrc/js/application/differential/DifferentialInlineCommentEditor.js', 'type' => 'js', 'requires' => array( @@ -1057,7 +1057,7 @@ celerity_register_resource_map(array( ), 'javelin-behavior-aphront-form-disable-on-submit' => array( - 'uri' => '/res/ca54e8b9/rsrc/js/application/core/behavior-form.js', + 'uri' => '/res/f5cb51f1/rsrc/js/application/core/behavior-form.js', 'type' => 'js', 'requires' => array( @@ -1796,7 +1796,7 @@ celerity_register_resource_map(array( ), 'javelin-behavior-phabricator-transaction-list' => array( - 'uri' => '/res/307a71af/rsrc/js/application/transactions/behavior-transaction-list.js', + 'uri' => '/res/f1fbb474/rsrc/js/application/transactions/behavior-transaction-list.js', 'type' => 'js', 'requires' => array( @@ -1963,7 +1963,7 @@ celerity_register_resource_map(array( ), 'javelin-behavior-workflow' => array( - 'uri' => '/res/2b0e2754/rsrc/js/application/core/behavior-workflow.js', + 'uri' => '/res/2c99beaf/rsrc/js/application/core/behavior-workflow.js', 'type' => 'js', 'requires' => array( @@ -3404,7 +3404,7 @@ celerity_register_resource_map(array( 'uri' => '/res/pkg/5f46c4fd/core.pkg.css', 'type' => 'css', ), - '66dca903' => + '4bf2be0a' => array( 'name' => 'core.pkg.js', 'symbols' => @@ -3443,7 +3443,7 @@ celerity_register_resource_map(array( 31 => 'javelin-behavior-global-drag-and-drop', 32 => 'javelin-behavior-phabricator-home-reveal-tiles', ), - 'uri' => '/res/pkg/66dca903/core.pkg.js', + 'uri' => '/res/pkg/4bf2be0a/core.pkg.js', 'type' => 'js', ), '8edbada5' => @@ -3481,7 +3481,7 @@ celerity_register_resource_map(array( 'uri' => '/res/pkg/ec01d039/differential.pkg.css', 'type' => 'css', ), - '310cd201' => + '9dae5f20' => array( 'name' => 'differential.pkg.js', 'symbols' => @@ -3506,7 +3506,7 @@ celerity_register_resource_map(array( 17 => 'javelin-behavior-differential-toggle-files', 18 => 'javelin-behavior-differential-user-select', ), - 'uri' => '/res/pkg/310cd201/differential.pkg.js', + 'uri' => '/res/pkg/9dae5f20/differential.pkg.js', 'type' => 'js', ), 'c8ce2d88' => @@ -3606,7 +3606,7 @@ celerity_register_resource_map(array( 'aphront-typeahead-control-css' => '5f46c4fd', 'differential-changeset-view-css' => 'ec01d039', 'differential-core-view-css' => 'ec01d039', - 'differential-inline-comment-editor' => '310cd201', + 'differential-inline-comment-editor' => '9dae5f20', 'differential-local-commits-view-css' => 'ec01d039', 'differential-results-table-css' => 'ec01d039', 'differential-revision-add-comment-css' => 'ec01d039', @@ -3619,56 +3619,56 @@ celerity_register_resource_map(array( 'diffusion-icons-css' => 'c8ce2d88', 'global-drag-and-drop-css' => '5f46c4fd', 'inline-comment-summary-css' => 'ec01d039', - 'javelin-aphlict' => '66dca903', + 'javelin-aphlict' => '4bf2be0a', 'javelin-behavior' => 'fbeded59', - 'javelin-behavior-aphlict-dropdown' => '66dca903', - 'javelin-behavior-aphlict-listen' => '66dca903', - 'javelin-behavior-aphront-basic-tokenizer' => '66dca903', - 'javelin-behavior-aphront-drag-and-drop' => '310cd201', - 'javelin-behavior-aphront-drag-and-drop-textarea' => '310cd201', - 'javelin-behavior-aphront-form-disable-on-submit' => '66dca903', + 'javelin-behavior-aphlict-dropdown' => '4bf2be0a', + 'javelin-behavior-aphlict-listen' => '4bf2be0a', + 'javelin-behavior-aphront-basic-tokenizer' => '4bf2be0a', + 'javelin-behavior-aphront-drag-and-drop' => '9dae5f20', + 'javelin-behavior-aphront-drag-and-drop-textarea' => '9dae5f20', + 'javelin-behavior-aphront-form-disable-on-submit' => '4bf2be0a', 'javelin-behavior-audit-preview' => 'f96657b8', 'javelin-behavior-dark-console' => '8edbada5', 'javelin-behavior-dark-console-ajax' => '8edbada5', - 'javelin-behavior-device' => '66dca903', - 'javelin-behavior-differential-accept-with-errors' => '310cd201', - 'javelin-behavior-differential-add-reviewers-and-ccs' => '310cd201', - 'javelin-behavior-differential-comment-jump' => '310cd201', - 'javelin-behavior-differential-diff-radios' => '310cd201', - 'javelin-behavior-differential-dropdown-menus' => '310cd201', - 'javelin-behavior-differential-edit-inline-comments' => '310cd201', - 'javelin-behavior-differential-feedback-preview' => '310cd201', - 'javelin-behavior-differential-keyboard-navigation' => '310cd201', - 'javelin-behavior-differential-populate' => '310cd201', - 'javelin-behavior-differential-show-more' => '310cd201', - 'javelin-behavior-differential-toggle-files' => '310cd201', - 'javelin-behavior-differential-user-select' => '310cd201', + 'javelin-behavior-device' => '4bf2be0a', + 'javelin-behavior-differential-accept-with-errors' => '9dae5f20', + 'javelin-behavior-differential-add-reviewers-and-ccs' => '9dae5f20', + 'javelin-behavior-differential-comment-jump' => '9dae5f20', + 'javelin-behavior-differential-diff-radios' => '9dae5f20', + 'javelin-behavior-differential-dropdown-menus' => '9dae5f20', + 'javelin-behavior-differential-edit-inline-comments' => '9dae5f20', + 'javelin-behavior-differential-feedback-preview' => '9dae5f20', + 'javelin-behavior-differential-keyboard-navigation' => '9dae5f20', + 'javelin-behavior-differential-populate' => '9dae5f20', + 'javelin-behavior-differential-show-more' => '9dae5f20', + 'javelin-behavior-differential-toggle-files' => '9dae5f20', + 'javelin-behavior-differential-user-select' => '9dae5f20', 'javelin-behavior-diffusion-commit-graph' => 'f96657b8', 'javelin-behavior-diffusion-pull-lastmodified' => 'f96657b8', 'javelin-behavior-error-log' => '8edbada5', - 'javelin-behavior-global-drag-and-drop' => '66dca903', - 'javelin-behavior-konami' => '66dca903', - 'javelin-behavior-lightbox-attachments' => '66dca903', + 'javelin-behavior-global-drag-and-drop' => '4bf2be0a', + 'javelin-behavior-konami' => '4bf2be0a', + 'javelin-behavior-lightbox-attachments' => '4bf2be0a', 'javelin-behavior-maniphest-batch-selector' => '7707de41', 'javelin-behavior-maniphest-subpriority-editor' => '7707de41', 'javelin-behavior-maniphest-transaction-controls' => '7707de41', 'javelin-behavior-maniphest-transaction-expand' => '7707de41', 'javelin-behavior-maniphest-transaction-preview' => '7707de41', - 'javelin-behavior-phabricator-active-nav' => '66dca903', - 'javelin-behavior-phabricator-autofocus' => '66dca903', - 'javelin-behavior-phabricator-home-reveal-tiles' => '66dca903', - 'javelin-behavior-phabricator-keyboard-shortcuts' => '66dca903', - 'javelin-behavior-phabricator-nav' => '66dca903', - 'javelin-behavior-phabricator-object-selector' => '310cd201', - 'javelin-behavior-phabricator-oncopy' => '66dca903', - 'javelin-behavior-phabricator-remarkup-assist' => '66dca903', - 'javelin-behavior-phabricator-search-typeahead' => '66dca903', - 'javelin-behavior-phabricator-tooltips' => '66dca903', - 'javelin-behavior-phabricator-watch-anchor' => '66dca903', - 'javelin-behavior-refresh-csrf' => '66dca903', - 'javelin-behavior-repository-crossreference' => '310cd201', - 'javelin-behavior-toggle-class' => '66dca903', - 'javelin-behavior-workflow' => '66dca903', + 'javelin-behavior-phabricator-active-nav' => '4bf2be0a', + 'javelin-behavior-phabricator-autofocus' => '4bf2be0a', + 'javelin-behavior-phabricator-home-reveal-tiles' => '4bf2be0a', + 'javelin-behavior-phabricator-keyboard-shortcuts' => '4bf2be0a', + 'javelin-behavior-phabricator-nav' => '4bf2be0a', + 'javelin-behavior-phabricator-object-selector' => '9dae5f20', + 'javelin-behavior-phabricator-oncopy' => '4bf2be0a', + 'javelin-behavior-phabricator-remarkup-assist' => '4bf2be0a', + 'javelin-behavior-phabricator-search-typeahead' => '4bf2be0a', + 'javelin-behavior-phabricator-tooltips' => '4bf2be0a', + 'javelin-behavior-phabricator-watch-anchor' => '4bf2be0a', + 'javelin-behavior-refresh-csrf' => '4bf2be0a', + 'javelin-behavior-repository-crossreference' => '9dae5f20', + 'javelin-behavior-toggle-class' => '4bf2be0a', + 'javelin-behavior-workflow' => '4bf2be0a', 'javelin-dom' => 'fbeded59', 'javelin-event' => 'fbeded59', 'javelin-install' => 'fbeded59', @@ -3690,39 +3690,39 @@ celerity_register_resource_map(array( 'lightbox-attachment-css' => '5f46c4fd', 'maniphest-task-summary-css' => 'e30a3fa8', 'maniphest-transaction-detail-css' => 'e30a3fa8', - 'phabricator-busy' => '66dca903', + 'phabricator-busy' => '4bf2be0a', 'phabricator-content-source-view-css' => 'ec01d039', 'phabricator-core-buttons-css' => '5f46c4fd', 'phabricator-core-css' => '5f46c4fd', 'phabricator-crumbs-view-css' => '5f46c4fd', 'phabricator-directory-css' => '5f46c4fd', - 'phabricator-drag-and-drop-file-upload' => '310cd201', - 'phabricator-dropdown-menu' => '66dca903', - 'phabricator-file-upload' => '66dca903', + 'phabricator-drag-and-drop-file-upload' => '9dae5f20', + 'phabricator-dropdown-menu' => '4bf2be0a', + 'phabricator-file-upload' => '4bf2be0a', 'phabricator-filetree-view-css' => '5f46c4fd', 'phabricator-flag-css' => '5f46c4fd', 'phabricator-form-view-css' => '5f46c4fd', 'phabricator-header-view-css' => '5f46c4fd', 'phabricator-jump-nav' => '5f46c4fd', - 'phabricator-keyboard-shortcut' => '66dca903', - 'phabricator-keyboard-shortcut-manager' => '66dca903', + 'phabricator-keyboard-shortcut' => '4bf2be0a', + 'phabricator-keyboard-shortcut-manager' => '4bf2be0a', 'phabricator-main-menu-view' => '5f46c4fd', - 'phabricator-menu-item' => '66dca903', + 'phabricator-menu-item' => '4bf2be0a', 'phabricator-nav-view-css' => '5f46c4fd', - 'phabricator-notification' => '66dca903', + 'phabricator-notification' => '4bf2be0a', 'phabricator-notification-css' => '5f46c4fd', 'phabricator-notification-menu-css' => '5f46c4fd', 'phabricator-object-item-list-view-css' => '5f46c4fd', 'phabricator-object-selector-css' => 'ec01d039', - 'phabricator-paste-file-upload' => '66dca903', - 'phabricator-prefab' => '66dca903', + 'phabricator-paste-file-upload' => '4bf2be0a', + 'phabricator-prefab' => '4bf2be0a', 'phabricator-project-tag-css' => 'e30a3fa8', 'phabricator-remarkup-css' => '5f46c4fd', - 'phabricator-shaped-request' => '310cd201', + 'phabricator-shaped-request' => '9dae5f20', 'phabricator-side-menu-view-css' => '5f46c4fd', 'phabricator-standard-page-view' => '5f46c4fd', - 'phabricator-textareautils' => '66dca903', - 'phabricator-tooltip' => '66dca903', + 'phabricator-textareautils' => '4bf2be0a', + 'phabricator-tooltip' => '4bf2be0a', 'phabricator-transaction-view-css' => '5f46c4fd', 'phabricator-zindex-css' => '5f46c4fd', 'sprite-apps-large-css' => '5f46c4fd', diff --git a/webroot/rsrc/js/application/core/behavior-form.js b/webroot/rsrc/js/application/core/behavior-form.js index 25ebb59e74..5147e8d7ba 100644 --- a/webroot/rsrc/js/application/core/behavior-form.js +++ b/webroot/rsrc/js/application/core/behavior-form.js @@ -14,6 +14,39 @@ JX.behavior('aphront-form-disable-on-submit', function(config) { new_tab = (raw.altKey || raw.ctrlKey || raw.metaKey || raw.shiftKey); }); + + JX.Stratcom.listen('keypress', ['tag:form', 'tag:textarea'], function(e) { + var raw = e.getRawEvent(); + if (e.getSpecialKey() != 'return' || !raw.ctrlKey) { + return; + } + + e.kill(); + + var form = e.getNode('tag:form'); + + // This allows 'workflow' and similar actions to take effect. + var r = JX.DOM.invoke(form, 'didSyntheticSubmit'); + if (r.getPrevented()) { + return; + } + + // If nothing handled the synthetic submit, submit normally. + form.submit(); + }); + + function will_submit(root) { + root._disabled = true; + var buttons = JX.DOM.scry(root, 'button'); + for (var ii = 0; ii < buttons.length; ii++) { + if (!buttons[ii].disabled) { + buttons[ii].disabled = 'disabled'; + JX.DOM.alterClass(buttons[ii], 'disabled', true); + restore.push(buttons[ii]); + } + } + } + JX.Stratcom.listen('submit', 'tag:form', function(e) { if (e.getNode('workflow')) { // Don't activate for forms with workflow, the workflow behavior will @@ -34,15 +67,8 @@ JX.behavior('aphront-form-disable-on-submit', function(config) { if (root._disabled) { e.kill(); } - root._disabled = true; - var buttons = JX.DOM.scry(root, 'button'); - for (var ii = 0; ii < buttons.length; ii++) { - if (!buttons[ii].disabled) { - buttons[ii].disabled = 'disabled'; - JX.DOM.alterClass(buttons[ii], 'disabled', true); - restore.push(buttons[ii]); - } - } + + will_submit(root); }); JX.Stratcom.listen('unload', null, function(e) { diff --git a/webroot/rsrc/js/application/core/behavior-workflow.js b/webroot/rsrc/js/application/core/behavior-workflow.js index 82c0cfb0b8..c55c8e9317 100644 --- a/webroot/rsrc/js/application/core/behavior-workflow.js +++ b/webroot/rsrc/js/application/core/behavior-workflow.js @@ -7,8 +7,10 @@ */ JX.behavior('workflow', function() { + + // Listen for both real JX.Stratcom.listen( - 'submit', + ['submit', 'didSyntheticSubmit'], ['workflow', 'tag:form'], function(e) { if (JX.Stratcom.pass()) { @@ -18,6 +20,7 @@ JX.behavior('workflow', function() { e.prevent(); JX.Workflow.newFromForm(target).start(); }); + JX.Stratcom.listen( 'click', ['workflow', 'tag:a'], @@ -40,4 +43,5 @@ JX.behavior('workflow', function() { e.prevent(); JX.Workflow.newFromLink(target).start(); }); + }); diff --git a/webroot/rsrc/js/application/differential/DifferentialInlineCommentEditor.js b/webroot/rsrc/js/application/differential/DifferentialInlineCommentEditor.js index 6e544fe787..08339e1585 100644 --- a/webroot/rsrc/js/application/differential/DifferentialInlineCommentEditor.js +++ b/webroot/rsrc/js/application/differential/DifferentialInlineCommentEditor.js @@ -119,7 +119,11 @@ JX.install('DifferentialInlineCommentEditor', { JX.DOM.alterClass(drawn[0], 'differential-inline-loading', true); }); - JX.DOM.listen(drawn[0], 'submit', 'inline-edit-form', onsubmit); + JX.DOM.listen( + drawn[0], + ['submit', 'didSyntheticSubmit'], + 'inline-edit-form', + onsubmit); }, _didCompleteWorkflow : function(response) { var op = this.getOperation(); diff --git a/webroot/rsrc/js/application/transactions/behavior-transaction-list.js b/webroot/rsrc/js/application/transactions/behavior-transaction-list.js index 0658ac2ebf..64195ad18e 100644 --- a/webroot/rsrc/js/application/transactions/behavior-transaction-list.js +++ b/webroot/rsrc/js/application/transactions/behavior-transaction-list.js @@ -75,21 +75,24 @@ JX.behavior('phabricator-transaction-list', function(config) { e.kill(); }); - JX.Stratcom.listen('submit', 'transaction-append', function(e) { - var form = e.getTarget(); + JX.Stratcom.listen( + ['submit', 'didSyntheticSubmit'], + 'transaction-append', + function(e) { + var form = e.getTarget(); - JX.Workflow.newFromForm(form, {anchor: next_anchor}) - .setHandler(function(response) { - ontransactions(response); + JX.Workflow.newFromForm(form, {anchor: next_anchor}) + .setHandler(function(response) { + ontransactions(response); - var e = JX.DOM.invoke(form, 'willClear'); - if (!e.getPrevented()) { - form.reset(); - } - }) - .start(); + var e = JX.DOM.invoke(form, 'willClear'); + if (!e.getPrevented()) { + form.reset(); + } + }) + .start(); - e.kill(); - }); + e.kill(); + }); });