mirror of
https://github.com/google/nomulus.git
synced 2025-04-30 20:17:51 +02:00
Forward declares symbol. This is an indication to the compiler that the symbol may be used in the source yet is not required and may not be provided in compilation. The most common usage of forward declaration is code that takes a type as a function parameter but does not need to require it. By forward declaring instead of requiring, no hard dependency is made, and (if not required elsewhere) the namespace may never be required and thus, not be pulled into the JavaScript binary. If it is required elsewhere, it will be type checked as normal. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=127095620
212 lines
6.6 KiB
JavaScript
212 lines
6.6 KiB
JavaScript
// Copyright 2016 The Domain Registry Authors. 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');
|
|
|
|
goog.forwardDeclare('registry.Console');
|
|
|
|
|
|
|
|
/**
|
|
* Base component for UI.
|
|
*
|
|
* <pre>
|
|
* 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
|
|
* </pre>
|
|
*
|
|
* @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.<string, number>}
|
|
* @protected
|
|
*/
|
|
this.typeCounts = {};
|
|
|
|
/**
|
|
* Stateful UI/server session model.
|
|
* @type {?Object.<string, ?>}
|
|
*/
|
|
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:
|
|
*
|
|
* <ul>
|
|
* <li>an add button with id="domain-[type]-add-button".
|
|
* <li>a table row with id="domain-[type]s-footer".
|
|
* </ul>
|
|
*
|
|
* @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.<Element>|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));
|
|
});
|
|
};
|