mirror of
https://we.phorge.it/source/phorge.git
synced 2025-01-15 09:11:07 +01:00
Add a typehaead filter to tokenizer browse views
Summary: Ref T5750. This adds a search filter which filters results (kind of: a lot of datasources don't do a great job with this right now -- but the correct data is sent to the server). Test Plan: {F372313} Reviewers: btrahan, chad Reviewed By: chad Subscribers: epriestley Maniphest Tasks: T5750 Differential Revision: https://secure.phabricator.com/D12426
This commit is contained in:
parent
06d79703d6
commit
f688181eaf
3 changed files with 103 additions and 2 deletions
|
@ -113,17 +113,49 @@ final class PhabricatorTypeaheadModularDatasourceController
|
||||||
$this->requireResource('typeahead-browse-css');
|
$this->requireResource('typeahead-browse-css');
|
||||||
$this->initBehavior('typeahead-browse');
|
$this->initBehavior('typeahead-browse');
|
||||||
|
|
||||||
$markup = phutil_tag(
|
$input_id = celerity_generate_unique_node_id();
|
||||||
|
$frame_id = celerity_generate_unique_node_id();
|
||||||
|
|
||||||
|
$config = array(
|
||||||
|
'inputID' => $input_id,
|
||||||
|
'frameID' => $frame_id,
|
||||||
|
'uri' => (string)$request->getRequestURI(),
|
||||||
|
);
|
||||||
|
$this->initBehavior('typeahead-search', $config);
|
||||||
|
|
||||||
|
$search = javelin_tag(
|
||||||
|
'input',
|
||||||
|
array(
|
||||||
|
'type' => 'text',
|
||||||
|
'id' => $input_id,
|
||||||
|
'class' => 'typeahead-browse-input',
|
||||||
|
'autocomplete' => 'off',
|
||||||
|
'placeholder' => $source->getPlaceholderText(),
|
||||||
|
));
|
||||||
|
|
||||||
|
$frame = phutil_tag(
|
||||||
'div',
|
'div',
|
||||||
array(
|
array(
|
||||||
'class' => 'typeahead-browse-frame',
|
'class' => 'typeahead-browse-frame',
|
||||||
|
'id' => $frame_id,
|
||||||
),
|
),
|
||||||
$markup);
|
$markup);
|
||||||
|
|
||||||
|
$browser = array(
|
||||||
|
phutil_tag(
|
||||||
|
'div',
|
||||||
|
array(
|
||||||
|
'class' => 'typeahead-browse-header',
|
||||||
|
),
|
||||||
|
$search),
|
||||||
|
$frame,
|
||||||
|
);
|
||||||
|
|
||||||
return $this->newDialog()
|
return $this->newDialog()
|
||||||
->setWidth(AphrontDialogView::WIDTH_FORM)
|
->setWidth(AphrontDialogView::WIDTH_FORM)
|
||||||
|
->setRenderDialogAsDiv(true)
|
||||||
->setTitle(get_class($source)) // TODO: Provide nice names.
|
->setTitle(get_class($source)) // TODO: Provide nice names.
|
||||||
->appendChild($markup)
|
->appendChild($browser)
|
||||||
->addCancelButton('/', pht('Close'));
|
->addCancelButton('/', pht('Close'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,3 +32,16 @@
|
||||||
height: 260px;
|
height: 260px;
|
||||||
border: 1px solid {$lightgreyborder};
|
border: 1px solid {$lightgreyborder};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.typeahead-browse-frame.loading {
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.typeahead-browse-header {
|
||||||
|
padding: 4px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
input.typeahead-browse-input {
|
||||||
|
margin: 0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
/**
|
||||||
|
* @provides javelin-behavior-typeahead-search
|
||||||
|
* @requires javelin-behavior
|
||||||
|
* javelin-stratcom
|
||||||
|
* javelin-workflow
|
||||||
|
* javelin-dom
|
||||||
|
*/
|
||||||
|
|
||||||
|
JX.behavior('typeahead-search', function(config) {
|
||||||
|
var input = JX.$(config.inputID);
|
||||||
|
var frame = JX.$(config.frameID);
|
||||||
|
var last = input.value;
|
||||||
|
|
||||||
|
function update() {
|
||||||
|
if (input.value == last) {
|
||||||
|
// This is some kind of non-input keypress like an arrow key. Don't
|
||||||
|
// send a query to the server.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call load() in a little while. If the user hasn't typed anything else,
|
||||||
|
// we'll send a request to get results.
|
||||||
|
setTimeout(JX.bind(null, load, input.value), 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
function load(value) {
|
||||||
|
if (value != input.value) {
|
||||||
|
// The user has typed some more text, so don't send a request yet. We
|
||||||
|
// want to wait for them to stop typing.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
JX.DOM.alterClass(frame, 'loading', true);
|
||||||
|
new JX.Workflow(config.uri, {q: value})
|
||||||
|
.setHandler(function(r) {
|
||||||
|
if (value != input.value) {
|
||||||
|
// The user typed some more stuff while the request was in flight,
|
||||||
|
// so ignore the response.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
last = input.value;
|
||||||
|
JX.DOM.setContent(frame, JX.$H(r.markup));
|
||||||
|
JX.DOM.alterClass(frame, 'loading', false);
|
||||||
|
})
|
||||||
|
.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
JX.DOM.listen(input, ['keydown', 'keypress', 'keyup'], null, function() {
|
||||||
|
// We need to delay this to actually read the value after the keypress.
|
||||||
|
setTimeout(update, 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
JX.DOM.focus(input);
|
||||||
|
|
||||||
|
});
|
Loading…
Reference in a new issue