diff --git a/src/__celerity_resource_map__.php b/src/__celerity_resource_map__.php
index 8bb22a672d..0dcf0a58dd 100644
--- a/src/__celerity_resource_map__.php
+++ b/src/__celerity_resource_map__.php
@@ -788,7 +788,7 @@ celerity_register_resource_map(array(
),
'javelin-behavior-phabricator-keyboard-shortcuts' =>
array(
- 'uri' => '/res/94b009e2/rsrc/js/application/core/behavior-keyboard-shortcuts.js',
+ 'uri' => '/res/ea3ea05e/rsrc/js/application/core/behavior-keyboard-shortcuts.js',
'type' => 'js',
'requires' =>
array(
@@ -1542,7 +1542,7 @@ celerity_register_resource_map(array(
),
'phabricator-keyboard-shortcut-manager' =>
array(
- 'uri' => '/res/04767571/rsrc/js/application/core/KeyboardShortcutManager.js',
+ 'uri' => '/res/0be80136/rsrc/js/application/core/KeyboardShortcutManager.js',
'type' => 'js',
'requires' =>
array(
@@ -1984,28 +1984,6 @@ celerity_register_resource_map(array(
'uri' => '/res/pkg/8d8e1030/differential.pkg.js',
'type' => 'js',
),
- 'adcb05b5' =>
- array(
- 'name' => 'core.pkg.js',
- 'symbols' =>
- array(
- 0 => 'javelin-mask',
- 1 => 'javelin-workflow',
- 2 => 'javelin-behavior-workflow',
- 3 => 'javelin-behavior-aphront-form-disable-on-submit',
- 4 => 'phabricator-keyboard-shortcut-manager',
- 5 => 'phabricator-keyboard-shortcut',
- 6 => 'javelin-behavior-phabricator-keyboard-shortcuts',
- 7 => 'javelin-behavior-refresh-csrf',
- 8 => 'javelin-behavior-phabricator-watch-anchor',
- 9 => 'javelin-behavior-phabricator-autofocus',
- 10 => 'phabricator-paste-file-upload',
- 11 => 'phabricator-menu-item',
- 12 => 'phabricator-dropdown-menu',
- ),
- 'uri' => '/res/pkg/adcb05b5/core.pkg.js',
- 'type' => 'js',
- ),
'ae7ea233' =>
array(
'name' => 'typeahead.pkg.js',
@@ -2063,6 +2041,28 @@ celerity_register_resource_map(array(
'uri' => '/res/pkg/31583232/maniphest.pkg.css',
'type' => 'css',
),
+ 95944588 =>
+ array(
+ 'name' => 'core.pkg.js',
+ 'symbols' =>
+ array(
+ 0 => 'javelin-mask',
+ 1 => 'javelin-workflow',
+ 2 => 'javelin-behavior-workflow',
+ 3 => 'javelin-behavior-aphront-form-disable-on-submit',
+ 4 => 'phabricator-keyboard-shortcut-manager',
+ 5 => 'phabricator-keyboard-shortcut',
+ 6 => 'javelin-behavior-phabricator-keyboard-shortcuts',
+ 7 => 'javelin-behavior-refresh-csrf',
+ 8 => 'javelin-behavior-phabricator-watch-anchor',
+ 9 => 'javelin-behavior-phabricator-autofocus',
+ 10 => 'phabricator-paste-file-upload',
+ 11 => 'phabricator-menu-item',
+ 12 => 'phabricator-dropdown-menu',
+ ),
+ 'uri' => '/res/pkg/95944588/core.pkg.js',
+ 'type' => 'js',
+ ),
),
'reverse' =>
array(
@@ -2093,7 +2093,7 @@ celerity_register_resource_map(array(
'javelin-behavior-aphront-basic-tokenizer' => 'ae7ea233',
'javelin-behavior-aphront-drag-and-drop' => '8d8e1030',
'javelin-behavior-aphront-drag-and-drop-textarea' => '8d8e1030',
- 'javelin-behavior-aphront-form-disable-on-submit' => 'adcb05b5',
+ 'javelin-behavior-aphront-form-disable-on-submit' => '95944588',
'javelin-behavior-buoyant' => '8d8e1030',
'javelin-behavior-differential-accept-with-errors' => '8d8e1030',
'javelin-behavior-differential-add-reviewers-and-ccs' => '8d8e1030',
@@ -2109,17 +2109,17 @@ celerity_register_resource_map(array(
'javelin-behavior-maniphest-transaction-controls' => '0ed3e020',
'javelin-behavior-maniphest-transaction-expand' => '0ed3e020',
'javelin-behavior-maniphest-transaction-preview' => '0ed3e020',
- 'javelin-behavior-phabricator-autofocus' => 'adcb05b5',
- 'javelin-behavior-phabricator-keyboard-shortcuts' => 'adcb05b5',
+ 'javelin-behavior-phabricator-autofocus' => '95944588',
+ 'javelin-behavior-phabricator-keyboard-shortcuts' => '95944588',
'javelin-behavior-phabricator-object-selector' => '8d8e1030',
- 'javelin-behavior-phabricator-watch-anchor' => 'adcb05b5',
- 'javelin-behavior-refresh-csrf' => 'adcb05b5',
- 'javelin-behavior-workflow' => 'adcb05b5',
+ 'javelin-behavior-phabricator-watch-anchor' => '95944588',
+ 'javelin-behavior-refresh-csrf' => '95944588',
+ 'javelin-behavior-workflow' => '95944588',
'javelin-dom' => '4fbae2af',
'javelin-event' => '4fbae2af',
'javelin-install' => '4fbae2af',
'javelin-json' => '4fbae2af',
- 'javelin-mask' => 'adcb05b5',
+ 'javelin-mask' => '95944588',
'javelin-request' => '4fbae2af',
'javelin-stratcom' => '4fbae2af',
'javelin-tokenizer' => 'ae7ea233',
@@ -2131,7 +2131,7 @@ celerity_register_resource_map(array(
'javelin-uri' => '4fbae2af',
'javelin-util' => '4fbae2af',
'javelin-vector' => '4fbae2af',
- 'javelin-workflow' => 'adcb05b5',
+ 'javelin-workflow' => '95944588',
'maniphest-task-detail-css' => '31583232',
'maniphest-task-summary-css' => '31583232',
'maniphest-transaction-detail-css' => '31583232',
@@ -2141,13 +2141,13 @@ celerity_register_resource_map(array(
'phabricator-core-css' => 'e2934828',
'phabricator-directory-css' => 'e2934828',
'phabricator-drag-and-drop-file-upload' => '8d8e1030',
- 'phabricator-dropdown-menu' => 'adcb05b5',
+ 'phabricator-dropdown-menu' => '95944588',
'phabricator-jump-nav' => 'e2934828',
- 'phabricator-keyboard-shortcut' => 'adcb05b5',
- 'phabricator-keyboard-shortcut-manager' => 'adcb05b5',
- 'phabricator-menu-item' => 'adcb05b5',
+ 'phabricator-keyboard-shortcut' => '95944588',
+ 'phabricator-keyboard-shortcut-manager' => '95944588',
+ 'phabricator-menu-item' => '95944588',
'phabricator-object-selector-css' => '09c86840',
- 'phabricator-paste-file-upload' => 'adcb05b5',
+ 'phabricator-paste-file-upload' => '95944588',
'phabricator-remarkup-css' => 'e2934828',
'phabricator-shaped-request' => '8d8e1030',
'phabricator-standard-page-view' => 'e2934828',
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
index d4821baa1f..6263b4f642 100644
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -584,6 +584,7 @@ phutil_register_library_map(array(
'PhabricatorImageTransformer' => 'applications/files/transform',
'PhabricatorInfrastructureTestCase' => 'infrastructure/__tests__',
'PhabricatorJavelinLinter' => 'infrastructure/lint/linter/javelin',
+ 'PhabricatorJumpNavHandler' => 'applications/search/engine/jumpnav',
'PhabricatorLintEngine' => 'infrastructure/lint/engine',
'PhabricatorLiskDAO' => 'applications/base/storage/lisk',
'PhabricatorLocalDiskFileStorageEngine' => 'applications/files/engine/localdisk',
@@ -696,7 +697,6 @@ phutil_register_library_map(array(
'PhabricatorProjectProfileController' => 'applications/project/controller/profile',
'PhabricatorProjectProfileEditController' => 'applications/project/controller/profileedit',
'PhabricatorProjectQuery' => 'applications/project/query/project',
- 'PhabricatorProjectQueryUtil' => 'applications/project/query/util',
'PhabricatorProjectStatus' => 'applications/project/constants/status',
'PhabricatorProjectSubproject' => 'applications/project/storage/subproject',
'PhabricatorProjectTransaction' => 'applications/project/storage/transaction',
diff --git a/src/aphront/console/plugin/xhprof/api/DarkConsoleXHProfPluginAPI.php b/src/aphront/console/plugin/xhprof/api/DarkConsoleXHProfPluginAPI.php
index 9769b3a00b..020f122de7 100644
--- a/src/aphront/console/plugin/xhprof/api/DarkConsoleXHProfPluginAPI.php
+++ b/src/aphront/console/plugin/xhprof/api/DarkConsoleXHProfPluginAPI.php
@@ -1,7 +1,7 @@
isFormPost()) {
$jump = $request->getStr('jump');
- $jump = trim($jump);
- $help_href = PhabricatorEnv::getDocLink(
- 'article/Jump_Nav_User_Guide.html');
+ $response = PhabricatorJumpNavHandler::jumpPostResponse($jump);
+ if ($response) {
+ return $response;
+ } else {
+ $query = new PhabricatorSearchQuery();
+ $query->setQuery($jump);
+ $query->save();
- $patterns = array(
- '/^help/i' => 'uri:'.$help_href,
- '/^d$/i' => 'uri:/differential/',
- '/^r$/i' => 'uri:/diffusion/',
- '/^t$/i' => 'uri:/maniphest/',
- '/^p$/i' => 'uri:/project/',
- '/^u$/i' => 'uri:/people/',
- '/^r([A-Z]+)$/' => 'repository',
- '/^r([A-Z]+)(\S+)$/' => 'commit',
- '/^d(\d+)$/i' => 'revision',
- '/^t(\d+)$/i' => 'task',
- '/^p\s+(.+)$/i' => 'project',
- '/^u\s+(\S+)$/i' => 'user',
- '/^task:\s*(.+)/i' => 'create-task',
- '/^(?:s|symbol)\s+(\S+)/i' => 'find-symbol',
- );
-
-
- foreach ($patterns as $pattern => $effect) {
- $matches = null;
- if (preg_match($pattern, $jump, $matches)) {
- if (!strncmp($effect, 'uri:', 4)) {
- return id(new AphrontRedirectResponse())
- ->setURI(substr($effect, 4));
- } else {
- switch ($effect) {
- case 'repository':
- return id(new AphrontRedirectResponse())
- ->setURI('/diffusion/'.$matches[1].'/');
- case 'commit':
- return id(new AphrontRedirectResponse())
- ->setURI('/'.$matches[0]);
- case 'revision':
- return id(new AphrontRedirectResponse())
- ->setURI('/D'.$matches[1]);
- case 'task':
- return id(new AphrontRedirectResponse())
- ->setURI('/T'.$matches[1]);
- case 'user':
- return id(new AphrontRedirectResponse())
- ->setURI('/p/'.$matches[1].'/');
- case 'project':
- $project = PhabricatorProjectQueryUtil
- ::findCloselyNamedProject($matches[1]);
- if ($project) {
- return id(new AphrontRedirectResponse())
- ->setURI('/project/view/'.$project->getID().'/');
- } else {
- $jump = $matches[1];
- }
- break;
- case 'find-symbol':
- return id(new AphrontRedirectResponse())
- ->setURI('/diffusion/symbol/'.$matches[1].'/?jump=true');
- case 'create-task':
- return id(new AphrontRedirectResponse())
- ->setURI('/maniphest/task/create/?title='
- .phutil_escape_uri($matches[1]));
- default:
- throw new Exception("Unknown jump effect '{$effect}'!");
- }
- }
- }
+ return id(new AphrontRedirectResponse())
+ ->setURI('/search/'.$query->getQueryKey().'/');
}
-
- $query = new PhabricatorSearchQuery();
- $query->setQuery($jump);
- $query->save();
-
- return id(new AphrontRedirectResponse())
- ->setURI('/search/'.$query->getQueryKey().'/');
}
diff --git a/src/applications/directory/controller/main/__init__.php b/src/applications/directory/controller/main/__init__.php
index 8b9c63a804..8292e9a503 100644
--- a/src/applications/directory/controller/main/__init__.php
+++ b/src/applications/directory/controller/main/__init__.php
@@ -22,7 +22,7 @@ phutil_require_module('phabricator', 'applications/maniphest/query');
phutil_require_module('phabricator', 'applications/maniphest/view/tasklist');
phutil_require_module('phabricator', 'applications/phid/handle/data');
phutil_require_module('phabricator', 'applications/project/query/project');
-phutil_require_module('phabricator', 'applications/project/query/util');
+phutil_require_module('phabricator', 'applications/search/engine/jumpnav');
phutil_require_module('phabricator', 'applications/search/storage/query');
phutil_require_module('phabricator', 'infrastructure/celerity/api');
phutil_require_module('phabricator', 'infrastructure/env');
diff --git a/src/applications/project/query/util/PhabricatorProjectQueryUtil.php b/src/applications/project/query/util/PhabricatorProjectQueryUtil.php
deleted file mode 100644
index f07ebea7b5..0000000000
--- a/src/applications/project/query/util/PhabricatorProjectQueryUtil.php
+++ /dev/null
@@ -1,46 +0,0 @@
-loadOneWhere(
- 'name = %s',
- name);
- if ($project) {
- return $project;
- } else { // no exact match, try a fuzzy match
- $projects = id(new PhabricatorProject())->loadAllWhere(
- 'name LIKE %~',
- $name);
- if ($projects) {
- $min_name_length = PHP_INT_MAX;
- $best_project = null;
- foreach ($projects as $project) {
- $name_length = strlen($project->getName());
- if ($name_length <= $min_name_length) {
- $min_name_length = $name_length;
- $best_project = $project;
- }
- }
- return $best_project;
- } else {
- return null;
- }
- }
- }
-}
diff --git a/src/applications/search/controller/search/PhabricatorSearchController.php b/src/applications/search/controller/search/PhabricatorSearchController.php
index cae5508233..4531eaf202 100644
--- a/src/applications/search/controller/search/PhabricatorSearchController.php
+++ b/src/applications/search/controller/search/PhabricatorSearchController.php
@@ -20,7 +20,6 @@
* @group search
*/
class PhabricatorSearchController extends PhabricatorSearchBaseController {
-
private $key;
public function willProcessRequest(array $data) {
@@ -42,60 +41,66 @@ class PhabricatorSearchController extends PhabricatorSearchBaseController {
$query = new PhabricatorSearchQuery();
if ($request->isFormPost()) {
- $query->setQuery($request->getStr('query'));
-
- if ($request->getStr('scope')) {
- switch ($request->getStr('scope')) {
- case PhabricatorSearchScope::SCOPE_OPEN_REVISIONS:
- $query->setParameter('open', 1);
- $query->setParameter(
- 'type',
- PhabricatorPHIDConstants::PHID_TYPE_DREV);
- break;
- case PhabricatorSearchScope::SCOPE_OPEN_TASKS:
- $query->setParameter('open', 1);
- $query->setParameter(
- 'type',
- PhabricatorPHIDConstants::PHID_TYPE_TASK);
- break;
- case PhabricatorSearchScope::SCOPE_WIKI:
- $query->setParameter(
- 'type',
- PhabricatorPHIDConstants::PHID_TYPE_WIKI);
- break;
- case PhabricatorSearchScope::SCOPE_COMMITS:
- $query->setParameter(
- 'type',
- PhabricatorPHIDConstants::PHID_TYPE_CMIT);
- break;
- default:
- break;
- }
+ $query_str = $request->getStr('query');
+ $response = PhabricatorJumpNavHandler::jumpPostResponse($query_str);
+ if ($response) {
+ return $response;
} else {
- if (strlen($request->getStr('type'))) {
- $query->setParameter('type', $request->getStr('type'));
+ $query->setQuery($query_str);
+
+ if ($request->getStr('scope')) {
+ switch ($request->getStr('scope')) {
+ case PhabricatorSearchScope::SCOPE_OPEN_REVISIONS:
+ $query->setParameter('open', 1);
+ $query->setParameter(
+ 'type',
+ PhabricatorPHIDConstants::PHID_TYPE_DREV);
+ break;
+ case PhabricatorSearchScope::SCOPE_OPEN_TASKS:
+ $query->setParameter('open', 1);
+ $query->setParameter(
+ 'type',
+ PhabricatorPHIDConstants::PHID_TYPE_TASK);
+ break;
+ case PhabricatorSearchScope::SCOPE_WIKI:
+ $query->setParameter(
+ 'type',
+ PhabricatorPHIDConstants::PHID_TYPE_WIKI);
+ break;
+ case PhabricatorSearchScope::SCOPE_COMMITS:
+ $query->setParameter(
+ 'type',
+ PhabricatorPHIDConstants::PHID_TYPE_CMIT);
+ break;
+ default:
+ break;
+ }
+ } else {
+ if (strlen($request->getStr('type'))) {
+ $query->setParameter('type', $request->getStr('type'));
+ }
+
+ if ($request->getArr('author')) {
+ $query->setParameter('author', $request->getArr('author'));
+ }
+
+ if ($request->getArr('owner')) {
+ $query->setParameter('owner', $request->getArr('owner'));
+ }
+
+ if ($request->getInt('open')) {
+ $query->setParameter('open', $request->getInt('open'));
+ }
+
+ if ($request->getArr('project')) {
+ $query->setParameter('project', $request->getArr('project'));
+ }
}
- if ($request->getArr('author')) {
- $query->setParameter('author', $request->getArr('author'));
- }
-
- if ($request->getArr('owner')) {
- $query->setParameter('owner', $request->getArr('owner'));
- }
-
- if ($request->getInt('open')) {
- $query->setParameter('open', $request->getInt('open'));
- }
-
- if ($request->getArr('project')) {
- $query->setParameter('project', $request->getArr('project'));
- }
+ $query->save();
+ return id(new AphrontRedirectResponse())
+ ->setURI('/search/'.$query->getQueryKey().'/');
}
-
- $query->save();
- return id(new AphrontRedirectResponse())
- ->setURI('/search/'.$query->getQueryKey().'/');
}
}
diff --git a/src/applications/search/controller/search/__init__.php b/src/applications/search/controller/search/__init__.php
index 9285ceecd0..3855c34119 100644
--- a/src/applications/search/controller/search/__init__.php
+++ b/src/applications/search/controller/search/__init__.php
@@ -12,6 +12,7 @@ phutil_require_module('phabricator', 'applications/phid/constants');
phutil_require_module('phabricator', 'applications/phid/handle/data');
phutil_require_module('phabricator', 'applications/search/constants/scope');
phutil_require_module('phabricator', 'applications/search/controller/base');
+phutil_require_module('phabricator', 'applications/search/engine/jumpnav');
phutil_require_module('phabricator', 'applications/search/selector/base');
phutil_require_module('phabricator', 'applications/search/storage/query');
phutil_require_module('phabricator', 'applications/search/view/searchresult');
diff --git a/src/applications/search/engine/jumpnav/PhabricatorJumpNavHandler.php b/src/applications/search/engine/jumpnav/PhabricatorJumpNavHandler.php
new file mode 100644
index 0000000000..6d56995995
--- /dev/null
+++ b/src/applications/search/engine/jumpnav/PhabricatorJumpNavHandler.php
@@ -0,0 +1,118 @@
+ 'uri:'.$help_href,
+ '/^d$/i' => 'uri:/differential/',
+ '/^r$/i' => 'uri:/diffusion/',
+ '/^t$/i' => 'uri:/maniphest/',
+ '/^p$/i' => 'uri:/project/',
+ '/^u$/i' => 'uri:/people/',
+ '/^r([A-Z]+)$/' => 'repository',
+ '/^r([A-Z]+)(\S+)$/' => 'commit',
+ '/^d(\d+)$/i' => 'revision',
+ '/^t(\d+)$/i' => 'task',
+ '/^p\s+(.+)$/i' => 'project',
+ '/^u\s+(\S+)$/i' => 'user',
+ '/^task:\s*(.+)/i' => 'create-task',
+ '/^(?:s|symbol)\s+(\S+)/i' => 'find-symbol',
+ );
+
+
+ foreach ($patterns as $pattern => $effect) {
+ $matches = null;
+ if (preg_match($pattern, $jump, $matches)) {
+ if (!strncmp($effect, 'uri:', 4)) {
+ return id(new AphrontRedirectResponse())
+ ->setURI(substr($effect, 4));
+ } else {
+ switch ($effect) {
+ case 'repository':
+ return id(new AphrontRedirectResponse())
+ ->setURI('/diffusion/'.$matches[1].'/');
+ case 'commit':
+ return id(new AphrontRedirectResponse())
+ ->setURI('/'.$matches[0]);
+ case 'revision':
+ return id(new AphrontRedirectResponse())
+ ->setURI('/D'.$matches[1]);
+ case 'task':
+ return id(new AphrontRedirectResponse())
+ ->setURI('/T'.$matches[1]);
+ case 'user':
+ return id(new AphrontRedirectResponse())
+ ->setURI('/p/'.$matches[1].'/');
+ case 'project':
+ $project = static::findCloselyNamedProject($matches[1]);
+ if ($project) {
+ return id(new AphrontRedirectResponse())
+ ->setURI('/project/view/'.$project->getID().'/');
+ } else {
+ $jump = $matches[1];
+ }
+ break;
+ case 'find-symbol':
+ return id(new AphrontRedirectResponse())
+ ->setURI('/diffusion/symbol/'.$matches[1].'/?jump=true');
+ case 'create-task':
+ return id(new AphrontRedirectResponse())
+ ->setURI('/maniphest/task/create/?title='
+ .phutil_escape_uri($matches[1]));
+ default:
+ throw new Exception("Unknown jump effect '{$effect}'!");
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+
+ private static function findCloselyNamedProject($name) {
+ $project = id(new PhabricatorProject())->loadOneWhere(
+ 'name = %s',
+ name);
+ if ($project) {
+ return $project;
+ } else { // no exact match, try a fuzzy match
+ $projects = id(new PhabricatorProject())->loadAllWhere(
+ 'name LIKE %~',
+ $name);
+ if ($projects) {
+ $min_name_length = PHP_INT_MAX;
+ $best_project = null;
+ foreach ($projects as $project) {
+ $name_length = strlen($project->getName());
+ if ($name_length <= $min_name_length) {
+ $min_name_length = $name_length;
+ $best_project = $project;
+ }
+ }
+ return $best_project;
+ } else {
+ return null;
+ }
+ }
+ }
+}
diff --git a/src/applications/project/query/util/__init__.php b/src/applications/search/engine/jumpnav/__init__.php
similarity index 50%
rename from src/applications/project/query/util/__init__.php
rename to src/applications/search/engine/jumpnav/__init__.php
index 4685a31eb8..9d87596f4d 100644
--- a/src/applications/project/query/util/__init__.php
+++ b/src/applications/search/engine/jumpnav/__init__.php
@@ -6,9 +6,12 @@
+phutil_require_module('phabricator', 'aphront/response/redirect');
phutil_require_module('phabricator', 'applications/project/storage/project');
+phutil_require_module('phabricator', 'infrastructure/env');
+phutil_require_module('phutil', 'markup');
phutil_require_module('phutil', 'utils');
-phutil_require_source('PhabricatorProjectQueryUtil.php');
+phutil_require_source('PhabricatorJumpNavHandler.php');
diff --git a/src/view/page/standard/PhabricatorStandardPageView.php b/src/view/page/standard/PhabricatorStandardPageView.php
index f5796eaa38..370529a76d 100644
--- a/src/view/page/standard/PhabricatorStandardPageView.php
+++ b/src/view/page/standard/PhabricatorStandardPageView.php
@@ -288,7 +288,7 @@ class PhabricatorStandardPageView extends AphrontPageView {
'method' => 'post',
'style' => 'display: inline',
),
- ''.
+ ''.
' in '.
AphrontFormSelectControl::renderSelectTag(
$this->getSearchDefaultScope(),
diff --git a/webroot/rsrc/js/application/core/KeyboardShortcutManager.js b/webroot/rsrc/js/application/core/KeyboardShortcutManager.js
index e81071ed39..637fc1f8c3 100644
--- a/webroot/rsrc/js/application/core/KeyboardShortcutManager.js
+++ b/webroot/rsrc/js/application/core/KeyboardShortcutManager.js
@@ -122,6 +122,7 @@ JX.install('KeyboardShortcutManager', {
for (var jj = 0; jj < keys.length; jj++) {
if (keys[jj] == key) {
shortcuts[ii].getHandler()(this);
+ e.kill(); // Consume the event
return;
}
}
diff --git a/webroot/rsrc/js/application/core/behavior-keyboard-shortcuts.js b/webroot/rsrc/js/application/core/behavior-keyboard-shortcuts.js
index f01a382933..05be4a6171 100644
--- a/webroot/rsrc/js/application/core/behavior-keyboard-shortcuts.js
+++ b/webroot/rsrc/js/application/core/behavior-keyboard-shortcuts.js
@@ -28,4 +28,14 @@ JX.behavior('phabricator-keyboard-shortcuts', function(config) {
workflow.start();
})
.register();
+
+ desc = 'Give keyboard focus to the search box.';
+ new JX.KeyboardShortcut('/', desc)
+ .setHandler(function() {
+ var search = JX.$("standard-search-box");
+ search.focus();
+ search.select();
+ })
+ .register();
+
});