diff --git a/src/__celerity_resource_map__.php b/src/__celerity_resource_map__.php index ee146d88a5..dfd228376a 100644 --- a/src/__celerity_resource_map__.php +++ b/src/__celerity_resource_map__.php @@ -28,25 +28,11 @@ celerity_register_resource_map(array( 'disk' => '/rsrc/image/credit_cards.png', 'type' => 'png', ), - '/rsrc/image/custom/example_facebook.png' => + '/rsrc/image/glyph_sprite.png' => array( - 'hash' => '062911a848dd7b58159d4184488ecac4', - 'uri' => '/res/062911a8/rsrc/image/custom/example_facebook.png', - 'disk' => '/rsrc/image/custom/example_facebook.png', - 'type' => 'png', - ), - '/rsrc/image/custom/example_rainbow.png' => - array( - 'hash' => '7af08c16d969a2d63b4acdbd5cee2e8f', - 'uri' => '/res/7af08c16/rsrc/image/custom/example_rainbow.png', - 'disk' => '/rsrc/image/custom/example_rainbow.png', - 'type' => 'png', - ), - '/rsrc/image/custom/example_template.png' => - array( - 'hash' => '9971fe1adb16682a18f9b588c4fc051b', - 'uri' => '/res/9971fe1a/rsrc/image/custom/example_template.png', - 'disk' => '/rsrc/image/custom/example_template.png', + 'hash' => '0a1ea7c048be9f0b76ab2c807a9a1c0d', + 'uri' => '/res/0a1ea7c0/rsrc/image/glyph_sprite.png', + 'disk' => '/rsrc/image/glyph_sprite.png', 'type' => 'png', ), '/rsrc/image/grippy_texture.png' => @@ -888,18 +874,6 @@ celerity_register_resource_map(array( ), 'disk' => '/rsrc/js/application/core/behavior-buoyant.js', ), - 'javelin-behavior-burn-chart' => - array( - 'uri' => '/res/0bc23e4d/rsrc/js/application/maniphest/behavior-burn-chart.js', - 'type' => 'js', - 'requires' => - array( - 0 => 'javelin-behavior', - 1 => 'javelin-dom', - 2 => 'javelin-vector', - ), - 'disk' => '/rsrc/js/application/maniphest/behavior-burn-chart.js', - ), 'javelin-behavior-countdown-timer' => array( 'uri' => '/res/5ee9cb13/rsrc/js/application/countdown/timer.js', @@ -1221,7 +1195,7 @@ celerity_register_resource_map(array( ), 'javelin-behavior-line-chart' => array( - 'uri' => '/res/653743c8/rsrc/js/application/maniphest/behavior-line-chart.js', + 'uri' => '/res/1aa5ac88/rsrc/js/application/maniphest/behavior-line-chart.js', 'type' => 'js', 'requires' => array( @@ -1486,6 +1460,17 @@ celerity_register_resource_map(array( ), 'disk' => '/rsrc/js/application/phriction/phriction-document-preview.js', ), + 'javelin-behavior-placeholder' => + array( + 'uri' => '/res/7dc26990/rsrc/js/application/core/behavior-placeholder.js', + 'type' => 'js', + 'requires' => + array( + 0 => 'javelin-behavior', + 1 => 'javelin-dom', + ), + 'disk' => '/rsrc/js/application/core/behavior-placeholder.js', + ), 'javelin-behavior-projects-resource-editor' => array( 'uri' => '/res/ffdde7d9/rsrc/js/application/projects/projects-resource-editor.js', @@ -2179,6 +2164,15 @@ celerity_register_resource_map(array( ), 'disk' => '/rsrc/css/application/flag/flag.css', ), + 'phabricator-glyph-css' => + array( + 'uri' => '/res/52f0dc90/rsrc/css/application/base/glyph.css', + 'type' => 'css', + 'requires' => + array( + ), + 'disk' => '/rsrc/css/application/base/glyph.css', + ), 'phabricator-jump-nav' => array( 'uri' => '/res/8bdc0fc3/rsrc/css/application/directory/phabricator-jump-nav.css', @@ -2358,7 +2352,7 @@ celerity_register_resource_map(array( ), 'phabricator-standard-page-view' => array( - 'uri' => '/res/de559ba2/rsrc/css/application/base/standard-page-view.css', + 'uri' => '/res/48118f6f/rsrc/css/application/base/standard-page-view.css', 'type' => 'css', 'requires' => array( @@ -2613,7 +2607,7 @@ celerity_register_resource_map(array( ), array( 'packages' => array( - '78836d86' => + '12ecfc95' => array( 'name' => 'core.pkg.css', 'symbols' => @@ -2642,7 +2636,7 @@ celerity_register_resource_map(array( 21 => 'phabricator-flag-css', 22 => 'aphront-error-view-css', ), - 'uri' => '/res/pkg/78836d86/core.pkg.css', + 'uri' => '/res/pkg/12ecfc95/core.pkg.css', 'type' => 'css', ), 'f363b322' => @@ -2809,20 +2803,20 @@ celerity_register_resource_map(array( 'reverse' => array( 'aphront-attached-file-view-css' => '7839ae2d', - 'aphront-crumbs-view-css' => '78836d86', - 'aphront-dialog-view-css' => '78836d86', - 'aphront-error-view-css' => '78836d86', - 'aphront-form-view-css' => '78836d86', + 'aphront-crumbs-view-css' => '12ecfc95', + 'aphront-dialog-view-css' => '12ecfc95', + 'aphront-error-view-css' => '12ecfc95', + 'aphront-form-view-css' => '12ecfc95', 'aphront-headsup-action-list-view-css' => '96bc37d6', - 'aphront-headsup-view-css' => '78836d86', - 'aphront-list-filter-view-css' => '78836d86', - 'aphront-pager-view-css' => '78836d86', - 'aphront-panel-view-css' => '78836d86', - 'aphront-side-nav-view-css' => '78836d86', - 'aphront-table-view-css' => '78836d86', - 'aphront-tokenizer-control-css' => '78836d86', - 'aphront-tooltip-css' => '78836d86', - 'aphront-typeahead-control-css' => '78836d86', + 'aphront-headsup-view-css' => '12ecfc95', + 'aphront-list-filter-view-css' => '12ecfc95', + 'aphront-pager-view-css' => '12ecfc95', + 'aphront-panel-view-css' => '12ecfc95', + 'aphront-side-nav-view-css' => '12ecfc95', + 'aphront-table-view-css' => '12ecfc95', + 'aphront-tokenizer-control-css' => '12ecfc95', + 'aphront-tooltip-css' => '12ecfc95', + 'aphront-typeahead-control-css' => '12ecfc95', 'differential-changeset-view-css' => '96bc37d6', 'differential-core-view-css' => '96bc37d6', 'differential-inline-comment-editor' => 'f4bbbd84', @@ -2888,15 +2882,15 @@ celerity_register_resource_map(array( 'javelin-workflow' => 'f363b322', 'maniphest-task-summary-css' => '7839ae2d', 'maniphest-transaction-detail-css' => '7839ae2d', - 'phabricator-app-buttons-css' => '78836d86', + 'phabricator-app-buttons-css' => '12ecfc95', 'phabricator-content-source-view-css' => '96bc37d6', - 'phabricator-core-buttons-css' => '78836d86', - 'phabricator-core-css' => '78836d86', - 'phabricator-directory-css' => '78836d86', + 'phabricator-core-buttons-css' => '12ecfc95', + 'phabricator-core-css' => '12ecfc95', + 'phabricator-directory-css' => '12ecfc95', 'phabricator-drag-and-drop-file-upload' => 'f4bbbd84', 'phabricator-dropdown-menu' => 'f363b322', - 'phabricator-flag-css' => '78836d86', - 'phabricator-jump-nav' => '78836d86', + 'phabricator-flag-css' => '12ecfc95', + 'phabricator-jump-nav' => '12ecfc95', 'phabricator-keyboard-shortcut' => 'f363b322', 'phabricator-keyboard-shortcut-manager' => 'f363b322', 'phabricator-menu-item' => 'f363b322', @@ -2904,11 +2898,11 @@ celerity_register_resource_map(array( 'phabricator-paste-file-upload' => 'f363b322', 'phabricator-prefab' => 'f363b322', 'phabricator-project-tag-css' => '7839ae2d', - 'phabricator-remarkup-css' => '78836d86', + 'phabricator-remarkup-css' => '12ecfc95', 'phabricator-shaped-request' => 'f4bbbd84', - 'phabricator-standard-page-view' => '78836d86', + 'phabricator-standard-page-view' => '12ecfc95', 'phabricator-tooltip' => 'f363b322', - 'phabricator-transaction-view-css' => '78836d86', - 'syntax-highlighting-css' => '78836d86', + 'phabricator-transaction-view-css' => '12ecfc95', + 'syntax-highlighting-css' => '12ecfc95', ), )); diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 3b8cc94eb4..0de8f96484 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -467,6 +467,7 @@ phutil_register_library_map(array( 'HeraldValueTypeConfig' => 'applications/herald/config/HeraldValueTypeConfig.php', 'Javelin' => 'infrastructure/javelin/Javelin.php', 'JavelinReactorExample' => 'applications/uiexample/examples/JavelinReactorExample.php', + 'JavelinUIExample' => 'applications/uiexample/examples/JavelinUIExample.php', 'JavelinViewExample' => 'applications/uiexample/examples/JavelinViewExample.php', 'JavelinViewExampleServerView' => 'applications/uiexample/examples/JavelinViewExampleServerView.php', 'LiskDAO' => 'infrastructure/storage/lisk/LiskDAO.php', @@ -1525,6 +1526,7 @@ phutil_register_library_map(array( 'HeraldTranscriptController' => 'HeraldController', 'HeraldTranscriptListController' => 'HeraldController', 'JavelinReactorExample' => 'PhabricatorUIExample', + 'JavelinUIExample' => 'PhabricatorUIExample', 'JavelinViewExample' => 'PhabricatorUIExample', 'JavelinViewExampleServerView' => 'AphrontView', 'LiskEphemeralObjectException' => 'Exception', diff --git a/src/applications/uiexample/examples/JavelinUIExample.php b/src/applications/uiexample/examples/JavelinUIExample.php new file mode 100644 index 0000000000..81cfed8fb1 --- /dev/null +++ b/src/applications/uiexample/examples/JavelinUIExample.php @@ -0,0 +1,59 @@ +getRequest(); + $user = $request->getUser(); + + $placeholder_id = celerity_generate_unique_node_id(); + + Javelin::initBehavior( + 'placeholder', + array( + 'id' => $placeholder_id, + 'text' => 'This is a placeholder', + )); + + $form = id(new AphrontFormView()) + ->setUser($user) + ->appendChild( + id(new AphrontFormTextControl()) + ->setLabel('Placeholder') + ->setID($placeholder_id)) + ->appendChild( + id(new AphrontFormSubmitControl()) + ->setValue('Submit')); + + $panel = new AphrontPanelView(); + $panel->setHeader('A Form'); + $panel->setWidth(AphrontPanelView::WIDTH_FORM); + $panel->appendChild($form); + + return $panel; + } +} diff --git a/webroot/rsrc/css/application/base/standard-page-view.css b/webroot/rsrc/css/application/base/standard-page-view.css index 619f884f88..58546d42e9 100644 --- a/webroot/rsrc/css/application/base/standard-page-view.css +++ b/webroot/rsrc/css/application/base/standard-page-view.css @@ -304,3 +304,11 @@ a.handle-disabled { background: #eeeeee; border-top: 1px solid #dddddd; } + + +/** + * Placeholder text added to inputs by the "placeholder" behavior. + */ +.jx-placeholder { + color: #888888; +} diff --git a/webroot/rsrc/js/application/core/behavior-placeholder.js b/webroot/rsrc/js/application/core/behavior-placeholder.js new file mode 100644 index 0000000000..baff60482c --- /dev/null +++ b/webroot/rsrc/js/application/core/behavior-placeholder.js @@ -0,0 +1,60 @@ +/** + * @provides javelin-behavior-placeholder + * @requires javelin-behavior + * javelin-dom + */ + +/** + * Add placeholder text to an input. Config are: + * + * - `id` (Required) ID of the element to add placeholder text to. + * - `text` (Required) Text to show. + * + * While the element is displaying placeholder text, the class `jx-placeholder` + * is added to it. Normally, you use a lower-contrast color to indicate that + * this text is instructional: + * + * .jx-placeholder { + * color: #888888; + * } + * + * @group ui + */ +JX.behavior('placeholder', function(config) { + var input = JX.$(config.id); + var placeholder_visible = false; + + function update(show_placeholder) { + placeholder_visible = show_placeholder; + JX.DOM.alterClass(input, 'jx-placeholder', placeholder_visible); + } + + function onfocus() { + if (placeholder_visible) { + input.value = ''; + update(false); + } + } + + function onblur() { + if (!input.value) { + input.value = config.text; + update(true); + } + } + + JX.DOM.listen(input, 'focus', null, onfocus); + JX.DOM.listen(input, 'blur', null, onblur); + + // When the user submits the form, remove the placeholder text (so it doesn't + // get submitted to the server) and then restore it after the submit finishes. + JX.DOM.listen(input.form, 'submit', null, function() { + onfocus(); + setTimeout(onblur, 0); + }); + + // If the element isn't currently focused, show the placeholder text. + if (document.activeElement != input) { + onblur(); + } +});