/** * @requires multirow-row-manager * javelin-install * path-typeahead * javelin-dom * javelin-util * phabricator-prefab * @provides owners-path-editor * @javelin */ JX.install('OwnersPathEditor', { construct : function(config) { var root = JX.$(config.root); this._rowManager = new JX.MultirowRowManager( JX.DOM.find(root, 'table', config.table)); JX.DOM.listen( JX.DOM.find(root, 'a', config.add_button), 'click', null, JX.bind(this, this._onaddpath)); this._count = 0; this._repositories = config.repositories; this._inputTemplate = config.input_template; this._completeURI = config.completeURI; this._validateURI = config.validateURI; this._repositoryDefaultPaths = config.repositoryDefaultPaths; this._initializePaths(config.pathRefs); }, members : { /* * MultirowRowManager for controlling add/remove behavior */ _rowManager : null, /* * Array of objects with 'name' and 'repo_id' keys for * selecting the repository of a path. */ _repositories : null, /* * How many rows have been created, for form name generation. */ _count : 0, /* * URL for the typeahead datasource. */ _completeURI : null, /* * URL for path validation requests. */ _validateURI : null, /* * Template typeahead markup to be copied per row. */ _inputTemplate : null, /* * Most packages will be in one repository, so remember whenever * the user chooses a repository, and use that repository as the * default for future rows. */ _lastRepositoryChoice : null, _repositoryDefaultPaths : null, /* * Initialize with 0 or more rows. * Adds one initial row if none are given. */ _initializePaths : function(path_refs) { for (var k in path_refs) { this.addPath(path_refs[k]); } if (!JX.keys(path_refs).length) { this.addPath(); } }, /* * Build a row. */ addPath : function(path_ref) { // Smart default repository. See _lastRepositoryChoice. if (path_ref) { this._lastRepositoryChoice = path_ref.repositoryPHID; } path_ref = path_ref || {}; var selected_repository = path_ref.repositoryPHID || this._lastRepositoryChoice; var options = this._buildRepositoryOptions(selected_repository); var attrs = { name : 'repo[' + this._count + ']', className : 'owners-repo' }; var repo_select = JX.$N('select', attrs, options); JX.DOM.listen(repo_select, 'change', null, JX.bind(this, function() { this._lastRepositoryChoice = repo_select.value; })); var repo_cell = JX.$N('td', {}, repo_select); var typeahead_cell = JX.$N( 'td', JX.$H(this._inputTemplate)); // Text input for path. var path_input = JX.DOM.find(typeahead_cell, 'input'); JX.copy( path_input, { value : path_ref.path || '', name : 'path[' + this._count + ']' }); // The Typeahead requires a display div called hardpoint. var hardpoint = JX.DOM.find( typeahead_cell, 'div', 'typeahead-hardpoint'); var error_display = JX.$N( 'div', { className : 'error-display validating' }, 'Validating...'); var error_display_cell = JX.$N('td', {}, error_display); var exclude = JX.Prefab.renderSelect( {'0' : 'Include', '1' : 'Exclude'}, path_ref.excluded, {name : 'exclude[' + this._count + ']'}); var exclude_cell = JX.$N('td', {}, exclude); var row = this._rowManager.addRow( [exclude_cell, repo_cell, typeahead_cell, error_display_cell]); new JX.PathTypeahead({ repositoryDefaultPaths : this._repositoryDefaultPaths, repo_select : repo_select, path_input : path_input, hardpoint : hardpoint, error_display : error_display, completeURI : this._completeURI, validateURI : this._validateURI}).start(); this._count++; return row; }, _onaddpath : function(e) { e.kill(); this.addPath(); }, /** * Helper to build the options for the repository choice dropdown. */ _buildRepositoryOptions : function(selected) { var repos = this._repositories; var result = []; for (var k in repos) { var attr = { value : k, selected : (selected == k) }; result.push(JX.$N('option', attr, repos[k])); } return result; } } });