// Copyright 2016 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. goog.provide('registry.Component'); goog.require('goog.dom'); goog.require('goog.dom.TagName'); goog.require('goog.dom.classlist'); goog.require('goog.events'); goog.require('goog.events.EventHandler'); goog.require('goog.events.EventType'); goog.require('registry.soy.forms'); goog.require('registry.util'); /** * Base component for UI. * *
 * ui/js/component.js - Base UI class.
 *       ^
 *       |
 *       edit_item.js - Common controls for editable items.
 *       ^
 *        \
 *         |-ui/js/resource_component.js - JSON resources
 *         |       ^
 *         |        \
 *         |         |- ui/js/registrar/settings.js
 *         |
 *         |-ui/js/registrar/xml_resource_component.js - EPP resources
 *                           ^
 *                            \
 *                            |- ui/js/registrar/contact.js
 *                            |- ui/js/registrar/domain.js
 *                            |- ui/js/registrar/host.js
 * 
* * @param {!registry.Console} cons the console singleton. * @constructor * @extends {goog.events.EventHandler} */ registry.Component = function(cons) { registry.Component.base(this, 'constructor'); /** @type {!registry.Console} */ this.console = cons; /** * The hashPath this component is mapped by. This is set by the * console after construction. * @type {string} */ this.basePath = ''; /** * Bean counter that's used by {@code addRemBtnHandlers}, * e.g. {@code typeCounts['host']++} when user adds or removes. * @type {!Object.} * @protected */ this.typeCounts = {}; /** * Stateful UI/server session model. * @type {?Object.} */ this.model = null; }; goog.inherits(registry.Component, goog.events.EventHandler); /** * Subclasses shold override this to implement panel display. * @param {string} id The target resource id. */ registry.Component.prototype.bindToDom = function(id) { registry.util.unbutter(); }; // XXX: Should clean up the many remove button handler setup funcs. /** * Shared functionality for contact and host add button click events * to add form elements for inputing a new item name. Requires the * template to have: * * * * @param {string} type e.g. 'contact', 'host'. * @param {function(): string} newFieldNameFn generates new form field's name. * @param {function(string): (?Element)=} opt_onAddFn currying further setup. * @param {function()=} opt_tmpl input element template. * @param {!Object=} opt_tmplArgs input element template parameter object. * @param {boolean=} opt_disable optionally disable the add button. * @protected */ registry.Component.prototype.addRemBtnHandlers = function( type, newFieldNameFn, opt_onAddFn, opt_tmpl, opt_tmplArgs, opt_disable) { var addBtnId = 'domain-' + type + '-add-button'; var addBtn = goog.dom.getRequiredElement(addBtnId); if (!opt_disable) { addBtn.removeAttribute('disabled'); } var addButtonClickCallback = function() { var fieldElts = []; var newFieldName = newFieldNameFn(); var tmpl = opt_tmpl ? opt_tmpl : registry.soy.forms.inputFieldRow; var tmplArgs = opt_tmplArgs ? opt_tmplArgs : { label: 'New ' + type, name: newFieldName + '.value' }; var newFieldInputRow = registry.util.renderBeforeRow( 'domain-' + type + 's-footer', tmpl, tmplArgs); fieldElts.push(newFieldInputRow); // Save the add/rem op type as a hidden elt for use by // determine EPP add/remove semantics in subclasses. // e.g. domain.js#saveItem() var opElt = goog.dom.createDom(goog.dom.TagName.INPUT, { 'type': 'hidden', 'name': newFieldName + '.op', 'value': 'add' }); newFieldInputRow.lastChild.appendChild(opElt); if (opt_onAddFn) { var elt = opt_onAddFn(newFieldName); if (elt) { fieldElts.push(elt); } } this.appendRemoveBtn( goog.dom.getLastElementChild(newFieldInputRow), fieldElts, goog.bind(function() { this.typeCounts[type]--; }, this)); this.typeCounts[type]++; }; goog.events.listen(goog.dom.getRequiredElement(addBtnId), goog.events.EventType.CLICK, goog.bind(addButtonClickCallback, this)); }; /** * Helper for making an element removable. * @param {Element} parent The element to append the remove button to. * @param {(Array.|function())=} opt_eltsToRemove * Elements to remove when the button is clicked or Function to do * the removing for full customization. * @param {function()=} opt_cb callback will be called if no * customized function is given. */ registry.Component.prototype.appendRemoveBtn = function(parent, opt_eltsToRemove, opt_cb) { var rmBtn = goog.dom.createDom(goog.dom.TagName.BUTTON, goog.getCssName('kd-button'), 'Remove'); goog.dom.appendChild(parent, rmBtn); var clickCb; if (opt_eltsToRemove instanceof Function) { clickCb = opt_eltsToRemove; } else { var eltsToRemove = opt_eltsToRemove ? opt_eltsToRemove : [parent]; clickCb = function() { for (var i = 0; i < eltsToRemove.length; i++) { goog.dom.removeNode(eltsToRemove[i]); } if (opt_cb) { opt_cb(); } }; } goog.events.listen(rmBtn, goog.events.EventType.CLICK, clickCb, true); }; /** * Bind the remove button action for the given container element. * @param {!Element} containerElt */ registry.Component.prototype.enableRemoveButton = function(containerElt) { var rmBtn = goog.dom.getElementByClass( goog.getCssName('remove'), containerElt); goog.dom.classlist.toggle(rmBtn, goog.getCssName('hidden')); goog.events.listen(rmBtn, goog.events.EventType.CLICK, function() { goog.dom.removeNode(goog.dom.getParentElement(rmBtn)); }); };