Changeset View
Changeset View
Standalone View
Standalone View
webroot/rsrc/js/application/herald/PathTypeahead.js
| /** | /** | ||||
| * @requires javelin-install | * @requires javelin-install | ||||
| * javelin-typeahead | * javelin-typeahead | ||||
| * javelin-dom | * javelin-dom | ||||
| * javelin-request | * javelin-request | ||||
| * javelin-typeahead-ondemand-source | * javelin-typeahead-ondemand-source | ||||
| * javelin-util | * javelin-util | ||||
| * @provides path-typeahead | * @provides path-typeahead | ||||
| * @javelin | * @javelin | ||||
| */ | */ | ||||
| JX.install('PathTypeahead', { | JX.install('PathTypeahead', { | ||||
| construct : function(config) { | construct : function(config) { | ||||
| this._repositorySelect = config.repo_select; | this._repositoryTokenizer = config.repositoryTokenizer; | ||||
| this._hardpoint = config.hardpoint; | this._hardpoint = config.hardpoint; | ||||
| this._input = config.path_input; | this._input = config.path_input; | ||||
| this._completeURI = config.completeURI; | this._completeURI = config.completeURI; | ||||
| this._validateURI = config.validateURI; | this._validateURI = config.validateURI; | ||||
| this._errorDisplay = config.error_display; | this._errorDisplay = config.error_display; | ||||
| this._textInputValues = {}; | this._textInputValues = {}; | ||||
| this._icons = config.icons; | |||||
| this._initializeDatasource(); | this._initializeDatasource(); | ||||
| this._initializeTypeahead(this._input); | this._initializeTypeahead(this._input); | ||||
| }, | }, | ||||
| members : { | members : { | ||||
| /* | _repositoryTokenizer : null, | ||||
| * DOM <select> elem for choosing the repository of a path. | |||||
| */ | |||||
| _repositorySelect : null, | |||||
| /* | /* | ||||
| * DOM parent div "hardpoint" to be passed to the JX.Typeahead. | * DOM parent div "hardpoint" to be passed to the JX.Typeahead. | ||||
| */ | */ | ||||
| _hardpoint : null, | _hardpoint : null, | ||||
| /* | /* | ||||
| * DOM element to display errors. | * DOM element to display errors. | ||||
| */ | */ | ||||
| _errorDisplay : null, | _errorDisplay : null, | ||||
| Show All 36 Lines | members : { | ||||
| _validationInflight : null, | _validationInflight : null, | ||||
| /* | /* | ||||
| * Installs path-specific behaviors and then starts the underlying | * Installs path-specific behaviors and then starts the underlying | ||||
| * typeahead. | * typeahead. | ||||
| */ | */ | ||||
| start : function() { | start : function() { | ||||
| if (this._typeahead.getValue()) { | if (this._typeahead.getValue()) { | ||||
| this._textInputValues[this._repositorySelect.value] = | var phid = this._getRepositoryPHID(); | ||||
| this._typeahead.getValue(); | if (phid) { | ||||
| this._textInputValues[phid] = this._typeahead.getValue(); | |||||
| } | |||||
| } | } | ||||
| this._typeahead.listen( | this._typeahead.listen( | ||||
| 'change', | 'change', | ||||
| JX.bind(this, function(value) { | JX.bind(this, function(value) { | ||||
| this._textInputValues[this._repositorySelect.value] = value; | var phid = this._getRepositoryPHID(); | ||||
| this._validate(); | if (phid) { | ||||
| })); | this._textInputValues[phid] = value; | ||||
| } | |||||
| this._typeahead.listen( | this._validate(); | ||||
| 'choose', | |||||
| JX.bind(this, function() { | |||||
| setTimeout(JX.bind(this._typeahead, this._typeahead.refresh), 0); | |||||
| })); | })); | ||||
| var repo_set_input = JX.bind(this, this._onrepochange); | var repo_set_input = JX.bind(this, this._onrepochange); | ||||
| this._typeahead.listen('start', repo_set_input); | this._typeahead.listen('start', repo_set_input); | ||||
| JX.DOM.listen( | |||||
| this._repositorySelect, | this._repositoryTokenizer.listen('change', repo_set_input); | ||||
| 'change', | |||||
| null, | |||||
| repo_set_input); | |||||
| this._typeahead.start(); | this._typeahead.start(); | ||||
| this._validate(); | this._validate(); | ||||
| }, | }, | ||||
| _onrepochange : function() { | _onrepochange : function() { | ||||
| this._setPathInputBasedOnRepository( | this._setPathInputBasedOnRepository( | ||||
| this._typeahead, | this._typeahead, | ||||
| this._textInputValues); | this._textInputValues); | ||||
| this._datasource.setAuxiliaryData( | this._datasource.setAuxiliaryData( | ||||
| {repositoryPHID : this._repositorySelect.value} | { | ||||
| ); | repositoryPHID: this._getRepositoryPHID() | ||||
| }); | |||||
| // Since we've changed the repository, reset the results. | |||||
| this._datasource.resetResults(); | |||||
| }, | }, | ||||
| _setPathInputBasedOnRepository : function(typeahead, lookup) { | _setPathInputBasedOnRepository : function(typeahead, lookup) { | ||||
| if (lookup[this._repositorySelect.value]) { | var phid = this._getRepositoryPHID(); | ||||
| typeahead.setValue(lookup[this._repositorySelect.value]); | if (phid && lookup[phid]) { | ||||
| typeahead.setValue(lookup[phid]); | |||||
| } else { | } else { | ||||
| typeahead.setValue('/'); | typeahead.setValue('/'); | ||||
| } | } | ||||
| }, | }, | ||||
| _initializeDatasource : function() { | _initializeDatasource : function() { | ||||
| this._datasource = new JX.TypeaheadOnDemandSource(this._completeURI); | this._datasource = new JX.TypeaheadOnDemandSource(this._completeURI); | ||||
| this._datasource.setNormalizer(this._datasourceNormalizer); | this._datasource.setNormalizer(this._datasourceNormalizer); | ||||
| Show All 9 Lines | _initializeTypeahead : function(path_input) { | ||||
| this._datasource.setMaximumResultCount(15); | this._datasource.setMaximumResultCount(15); | ||||
| this._typeahead.setDatasource(this._datasource); | this._typeahead.setDatasource(this._datasource); | ||||
| }, | }, | ||||
| _datasourceNormalizer : function(str) { | _datasourceNormalizer : function(str) { | ||||
| return ('' + str).replace(/[\/]+/g, '\/'); | return ('' + str).replace(/[\/]+/g, '\/'); | ||||
| }, | }, | ||||
| _getRepositoryPHID: function() { | |||||
| var tokens = this._repositoryTokenizer.getTokens(); | |||||
| var keys = JX.keys(tokens); | |||||
| if (keys.length) { | |||||
| return keys[0]; | |||||
| } | |||||
| return null; | |||||
| }, | |||||
| _validate : function() { | _validate : function() { | ||||
| var repo_phid = this._getRepositoryPHID(); | |||||
| if (!repo_phid) { | |||||
| return; | |||||
| } | |||||
| var input = this._input; | var input = this._input; | ||||
| var repo_id = this._repositorySelect.value; | |||||
| var input_value = input.value; | var input_value = input.value; | ||||
| var error_display = this._errorDisplay; | var error_display = this._errorDisplay; | ||||
| if (!input_value.length) { | if (!input_value.length) { | ||||
| input.value = '/'; | input.value = '/'; | ||||
| input_value = '/'; | input_value = '/'; | ||||
| } | } | ||||
| if (this._validationInflight) { | if (this._validationInflight) { | ||||
| this._validationInflight.abort(); | this._validationInflight.abort(); | ||||
| this._validationInflight = null; | this._validationInflight = null; | ||||
| } | } | ||||
| var validation_request = new JX.Request( | var validation_request = new JX.Request( | ||||
| this._validateURI, | this._validateURI, | ||||
| function(payload) { | JX.bind(this, function(payload) { | ||||
| // Don't change validation display state if the input has been | // Don't change validation display state if the input has been | ||||
| // changed since we started validation | // changed since we started validation | ||||
| if (input.value === input_value) { | if (input.value !== input_value) { | ||||
| return; | |||||
| } | |||||
| if (payload.valid) { | if (payload.valid) { | ||||
| JX.DOM.alterClass(error_display, 'invalid', false); | JX.DOM.setContent(error_display, JX.$H(this._icons.okay)); | ||||
| JX.DOM.alterClass(error_display, 'valid', true); | |||||
| } else { | } else { | ||||
| JX.DOM.alterClass(error_display, 'invalid', true); | JX.DOM.setContent(error_display, JX.$H(this._icons.fail)); | ||||
| JX.DOM.alterClass(error_display, 'valid', false); | |||||
| } | } | ||||
| JX.DOM.setContent(error_display, payload.message); | })); | ||||
| } | |||||
| }); | |||||
| validation_request.listen('finally', function() { | validation_request.listen('finally', function() { | ||||
| JX.DOM.alterClass(error_display, 'validating', false); | |||||
| this._validationInflight = null; | this._validationInflight = null; | ||||
| }); | }); | ||||
| validation_request.setData( | validation_request.setData( | ||||
| { | { | ||||
| repositoryPHID : repo_id, | repositoryPHID : repo_phid, | ||||
| path : input_value | path : input_value | ||||
| }); | }); | ||||
| this._validationInflight = validation_request; | this._validationInflight = validation_request; | ||||
| JX.DOM.setContent(error_display, JX.$H(this._icons.test)); | |||||
| validation_request.setTimeout(750); | validation_request.setTimeout(750); | ||||
| validation_request.send(); | validation_request.send(); | ||||
| } | } | ||||
| } | } | ||||
| }); | }); | ||||