// Copyright 2017 The Nomulus 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.util'); goog.require('goog.dom'); goog.require('goog.dom.classlist'); goog.require('goog.soy'); /** * Logging function that delegates to `console.log()`. * @param {...*} var_args */ registry.util.log = function(var_args) { if (goog.DEBUG) { if (goog.isDef(goog.global.console) && goog.isDef(goog.global.console['log'])) { goog.global.console.log.apply(goog.global.console, arguments); } } }; /** * CSS class for hiding an element whose visibility can be toggled. * @type {string} * @const */ registry.util.cssHidden = goog.getCssName('hidden'); /** * CSS class for showing an element whose visibility can be toggled. * @type {string} * @const */ registry.util.cssShown = goog.getCssName('shown'); /** * Changes element visibility by toggling CSS `shown` to `hidden`. * @param {!Element|string} element Element or id attribute of element. * @param {boolean} visible Shows `element` if true, or else hides it. */ registry.util.setVisible = function(element, visible) { goog.dom.classlist.addRemove( goog.dom.getElement(element), visible ? registry.util.cssHidden : registry.util.cssShown, visible ? registry.util.cssShown : registry.util.cssHidden); }; /** * Show a buttebar with the given message. A dismiss link will be added. * @param {string} message the message to show the user. * @param {boolean=} opt_isFatal indicates butterbar should be blood red. This * should only be used when an RPC returns a non-200 status. */ registry.util.butter = function(message, opt_isFatal) { goog.dom.setTextContent( goog.dom.getElementByClass(goog.getCssName('kd-butterbar-text')), message); var butterbar = goog.dom.getRequiredElementByClass(goog.getCssName('kd-butterbar')); registry.util.setVisible(butterbar, true); if (opt_isFatal) { goog.dom.classlist.add(butterbar, goog.getCssName('fatal')); } else { goog.dom.classlist.remove(butterbar, goog.getCssName('fatal')); } }; /** * Hides the butterbar. */ registry.util.unbutter = function() { registry.util.setVisible( goog.dom.getRequiredElementByClass(goog.getCssName('kd-butterbar')), false); }; /** * Renders the tmpl at and then moves it before the given elt. * @param {Element|string} id dom id of the refElt to render before. * @param {function()} tmpl template to render. * @param {!Object} tmplParams params to pass to the template. * @return {!Element} the rendered row. */ registry.util.renderBeforeRow = function(id, tmpl, tmplParams) { var refElt = goog.dom.getElement(id); goog.soy.renderElement(refElt, tmpl, tmplParams); var prevSib = goog.dom.getPreviousElementSibling(refElt); goog.dom.removeNode(refElt); refElt.removeAttribute('id'); goog.dom.insertSiblingAfter(refElt, prevSib); var newAnchorRefElt = goog.dom.createDom(refElt.tagName, {'id': id}); goog.dom.insertSiblingAfter(newAnchorRefElt, refElt); return refElt; }; /** * Turns an HTML form's named elements into a JSON data structure with * Pablo's black magick. * @param {string} formName the name of the form to be parsed. * @throws {Error} if `formName` couldn't be found. * @return {!Object} the parsed form values as an object. */ registry.util.parseForm = function(formName) { var form = /** @type {HTMLFormElement} */ (document.querySelector('form[name=' + formName + ']')); if (form == null) { throw new Error('No such form named ' + formName); } var obj = {}; // Find names first, since e.g. radio buttons have two elts with the // same name. var eltNames = {}; for (var i = 0; i < form.elements.length; i++) { var elt = form.elements[i]; if (elt.name == '') { continue; } eltNames[elt.name] = null; } for (var eltName in eltNames) { var elt = form.elements[eltName]; var val; if (elt.type == 'checkbox') { val = elt.checked; } else { val = elt.value; } registry.util.expandObject_(obj, eltName, val); } return obj; }; /** * Give the object a value at the given path. Paths are split on dot * and array elements are recognized. * * * * Yields the following object: *
 * {
 *   a: '1',
 *   'foo:a': '1.5',
 *   b: {
 *     c: '2',
 *     d: '3'
 *   },
 *   c: ['4','5'],
 *   d: [{a:'6'},{'foo:b':'7'},{'@b':'8'}]
 * }
 * 
* * @param {!Object} obj * @param {string} pathSpec * @param {string|Array.|null} val * @private */ registry.util.expandObject_ = function(obj, pathSpec, val) { var path = pathSpec.split('.'); for (var p = 0; p < path.length; p++) { var fieldName = path[p]; var arrElt = fieldName.match(/^([\w:]+)\[(\d+)\]$/); if (arrElt) { var arrName = arrElt[1]; var arrNdx = arrElt[2]; if (!obj[arrName]) { obj[arrName] = []; } obj = obj[arrName]; fieldName = arrNdx; if (!obj[arrNdx]) { obj[arrNdx] = {}; } } else { if (!obj[fieldName]) { obj[fieldName] = {}; } } if (p == path.length - 1) { obj[fieldName] = val; } else { obj = obj[fieldName]; } } };