toolshed-8.x-1.x-dev/js/Element.js

js/Element.js
"use strict";

(({
  Toolshed: ts
}) => {
  /**
   * Functionality wrapper for HTMLElements. Allows for more convienent creation
   * of HTMLElements and altering them.
   */
  ts.Element = class ToolshedElement {
    /**
     * Create a new instance of the ToolshedElement wrapper.
     *
     * @param {string|HTMLElement} element
     *   Either a HTML tag string or an HTML element to wrap. If value is a
     *   string then create an HTMLElement of that tag.
     * @param {Object=} attrs
     *   Attributes to apply to the HTMLElement wrapped by this object.
     * @param {ToolshedElement|HTMLElement=} appendTo
     *   A parent element to attach this new element to.
     */
    constructor(element, attrs, appendTo) {
      if (ts.isString(element)) {
        element = document.createElement(element.toUpperCase());
      }
      this.el = element;
      this.eventListeners = new Map();
      if (attrs) this.setAttrs(attrs);
      if (appendTo) this.attachTo(appendTo);
    }

    /* ------- getters / setters -------- */

    get id() {
      return this.el.id;
    }
    set id(value) {
      this.el.id = value;
    }
    get tagName() {
      return this.el.tagName;
    }
    get className() {
      return this.el.className;
    }
    set className(names) {
      this.el.className = names;
    }
    get classList() {
      return this.el.classList;
    }
    get style() {
      return this.el.style;
    }
    get dataset() {
      return this.el.dataset;
    }
    get parentNode() {
      return this.el.parentNode;
    }
    get parentElement() {
      return this.el.parentElement;
    }
    get innerHTML() {
      return this.el.innerHTML;
    }
    set innerHTML(html) {
      this.el.innerHTML = html;
    }
    get textContent() {
      return this.el.textContent;
    }
    set textContent(text) {
      this.el.textContent = text;
    }

    /* ------- element modifiers ------- */

    /**
     * Add CSS classes to the wrapped HTMLElement.
     *
     * @param {string|string[]} classes
     *   Either a single string to add, or an array of class names to add.
     */
    addClass(classes) {
      // Add array of classes one at a time for old IE compatibility.
      // Should this be removed now that IE is not supported anymore?
      Array.isArray(classes) ? classes.forEach(i => this.classList.add(i)) : this.classList.add(classes);
    }

    /**
     * Remove CSS classes from the wrapped HTMLElement.
     *
     * @param {string|string[]} classes
     *   Either a single class name or an array of class names to remove.
     */
    removeClass(classes) {
      Array.isArray(classes) ? classes.forEach(i => this.classList.remove(i)) : this.classList.remove(classes);
    }

    /**
     * Apply a keyed value list of style values to the wrapped HTMLElement.
     *
     * @param {Object} styles
     *   Keyed style values to apply to the element's style property.
     */
    setStyles(styles) {
      Object.assign(this.style, styles);
    }

    /**
     * Get the value of an attribute.
     *
     * @param {string} name
     *   Name of the attribute to fetch.
     *
     * @return {string|null}
     *   The value of the attribute if it exists. If there is no attribute with
     *   the requested name NULL is returned.
     */
    getAttr(name) {
      return this.el.hasAttribute(name) ? this.el.getAttribute(name) : null;
    }

    /**
     * Set value for a single HTML attribute.
     *
     * @param {string} name
     *   The name of the attribute to set.
     * @param {sting|array|object} value
     *   The value to set for the attribute. Style can be an object, class can
     *   be a array.
     */
    setAttr(name, value) {
      switch (name) {
        case 'class':
          this.addClass(value);
          break;
        case 'style':
          if (!ts.isString(value)) {
            this.setStyles(value);
            break;
          }
        case 'html':
          this.innerHTML = value;
          break;
        case 'text':
          this.textContent = value;

        // eslint-ignore-next-line no-fallthrough
        default:
          this.el.setAttribute(name, value);
      }
    }

    /**
     * Apply keyed attribute values to the wrapped HTMLElement.
     *
     * Most attributes should just be string values, but exceptions are:
     *  - class: can be a string or an array of class names
     *  - style: Can be a string or an Object of keyed style values.
     *
     * @param {Object} attrs
     *   Keyed values to apply as attributes to the wrapped HTMLElement.
     */
    setAttrs(attrs) {
      Object.entries(attrs).forEach(([k, v]) => this.setAttr(k, v));
    }

    /**
     * Remove specified attributes from the element.
     *
     * @param {string|string[]} attrs
     *   The names of the attributes to remove from the element.
     */
    removeAttrs(attrs) {
      if (ts.isString(attrs)) {
        attrs = [attrs];
      }
      attrs.forEach(i => this.el.removeAttribute(i));
    }

    /* --------- DOM Modifiers --------- */

    /**
     * Add an element to the start the wrapped HTMLElement's children nodes.
     *
     * @param {ToolshedElement|HTMLElement} item
     *   The child to prepend to the element.
     */
    prependChild(item) {
      this.insertBefore(item, this.el.firstElementChild);
    }

    /**
     * Append an element to this wrapped HTMLElement.
     *
     * @param {ToolshedElement|HTMLElement} item
     *   Element to append.
     */
    appendChild(item) {
      this.insertBefore(item);
    }

    /**
     * Insert an element as a child of the wrapped HTMLELement.
     *
     * @param {ToolshedElement|HTMLElement} item
     *   The element to insert as a child of the element.
     * @param {ToolshedElement|HTMLElement=} refNode
     *   Element to use as a reference point for insertion. If reference node
     *   is NULL then add the element after the last child element.
     */
    insertBefore(item, refNode) {
      item = item instanceof ToolshedElement ? item.el : item;
      refNode = refNode instanceof ToolshedElement ? refNode.el : refNode;
      this.el.insertBefore(item, refNode);
    }

    /**
     * Remove an element from this wrapped HTMLElement.
     *
     * @param {ToolshedElement|HTMLElement} item
     *   Element to remove.
     */
    removeChild(item) {
      this.el.removeChild(item instanceof ToolshedElement ? item.el : item);
    }

    /**
     * Remove all nodes and elements from this element.
     */
    empty() {
      while (this.el.firstChild) {
        this.el.removeChild(this.el.lastChild);
      }
    }

    /**
     * Insert this element into the DOM based on the reference node provided.
     * The type parameter is used to determine if the reference node is the
     * parent or sibling.
     *
     * @param {ToolshedElement|HTMLElement} refNode
     *   The element to use as a reference point for insertion. Could be the
     *   parent or the sibling depending on the value of "type".
     * @param {string=} type
     *   If type = "after" then element is inserted after the reference node,
     *   if type = "before" then element is inserted before. Otherwise, the
     *   element is appended to the reference node.
     */
    attachTo(refNode, type = 'parent') {
      if ('after' === type || 'before' === type) {
        (refNode.parentNode || document.body).insertBefore(this.el, 'before' === type ? refNode : refNode.nextSibling);
      } else {
        refNode.appendChild(this.el);
      }
    }

    /**
     * Detach this element from the DOM.
     */
    detach() {
      if (this.parentNode) this.parentNode.removeChild(this.el);
    }

    /**
     * Finds all descendent element matching a selector query.
     *
     * @param {string} query
     *   The selector query to use for matching descendent elements with.
     * @param {bool} multiple
     *   Return all matching elements? If true find all matching elements,
     *   otherwise only return the first matched element.
     *
     * @return {NodeList|Node}
     *   List of nodes matching the queried criteria when multipled are
     *   requested or just a single node if the multiple parameter is false.
     */
    find(query, multiple = true) {
      return multiple ? this.el.querySelectorAll(query) : this.el.querySelector(query);
    }

    /**
     * Find all child DOM elements with a class name.
     *
     * @param {string} className
     *   Class name to search for descendent elements for.
     *
     * @return {HTMLCollection}
     *   A collection of HTML element which are descendents of the element with
     *   the class name searched for.
     */
    findByClass(className) {
      return this.el.getElementsByClassName(className);
    }

    // -------- event listeners -------- //

    /**
     * Add an event listener to the element.
     *
     * @param {string} event
     *   Event to attach the event for.
     * @param {function} handler
     *   The callback event handler.
     * @param {AddEventListenerOptions=} options
     *   Event listener options to apply to the event listener.
     */
    on(event, handler, options = {}) {
      const map = this.eventListeners;
      if (map.has(event)) {
        map.get(event).push(handler);
      } else {
        map.set(event, [handler]);
      }
      this.el.addEventListener(event, handler, options);
    }

    /**
     * Removes event listeners from the element. If only event is provided then
     * all tracked event listeners are removed (listeners added with "on()").
     *
     * @param {string} event
     *   Name of the event to remove listeners from.
     * @param {function=} handler
     *   The listener to remove. If only the event name is provided, then
     *   all listeners for the event are removed.
     */
    off(event, handler) {
      const handlers = this.eventListeners.get(event);

      // If a handler was specified, only remove that specific handler.
      // otherwise remove all handlers registered for the event.
      if (handler) {
        if (handlers) {
          const i = handlers.indexOf(handler);
          if (i > -1) handlers.splice(i, 1);
        }
        this.el.removeEventListener(event, handler);
      } else if (handlers) {
        handlers.forEach(h => this.el.removeEventListener(h));
      }
    }

    // --------- house keeping --------- //

    /**
     * Clean-up element resources and event listeners.
     *
     * @param {bool} detach
     *   Should the element also be detached from the DOM parent.
     */
    destroy(detach) {
      this.eventListeners.forEach((v, k) => {
        v.forEach(f => this.el.removeEventListener(k, f));
      });
      if (detach) this.detach();
    }
  };

  /**
   * Wrapper for form input elements.
   */
  ts.FormElement = class FormElement extends ts.Element {
    /**
     * Get the current value for the form input element.
     *
     * @return {*}
     *   The current form input value.
     */
    get value() {
      return this.el.value;
    }

    /**
     * Set the value of this form element.
     *
     * @param {*} val
     *   The value to set for this form element.
     */
    set value(val) {
      this.el.value = val;
    }

    /**
     * Retrieve the form which this form element belongs to.
     *
     * @return {FormElement|null}
     *   The form element which owns this form element.
     */
    get form() {
      return this.el.form || this.el.closest('form');
    }
  };
})(Drupal);
//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRWxlbWVudC5qcyIsIm5hbWVzIjpbIlRvb2xzaGVkIiwidHMiLCJFbGVtZW50IiwiVG9vbHNoZWRFbGVtZW50IiwiY29uc3RydWN0b3IiLCJlbGVtZW50IiwiYXR0cnMiLCJhcHBlbmRUbyIsImlzU3RyaW5nIiwiZG9jdW1lbnQiLCJjcmVhdGVFbGVtZW50IiwidG9VcHBlckNhc2UiLCJlbCIsImV2ZW50TGlzdGVuZXJzIiwiTWFwIiwic2V0QXR0cnMiLCJhdHRhY2hUbyIsImlkIiwidmFsdWUiLCJ0YWdOYW1lIiwiY2xhc3NOYW1lIiwibmFtZXMiLCJjbGFzc0xpc3QiLCJzdHlsZSIsImRhdGFzZXQiLCJwYXJlbnROb2RlIiwicGFyZW50RWxlbWVudCIsImlubmVySFRNTCIsImh0bWwiLCJ0ZXh0Q29udGVudCIsInRleHQiLCJhZGRDbGFzcyIsImNsYXNzZXMiLCJBcnJheSIsImlzQXJyYXkiLCJmb3JFYWNoIiwiaSIsImFkZCIsInJlbW92ZUNsYXNzIiwicmVtb3ZlIiwic2V0U3R5bGVzIiwic3R5bGVzIiwiT2JqZWN0IiwiYXNzaWduIiwiZ2V0QXR0ciIsIm5hbWUiLCJoYXNBdHRyaWJ1dGUiLCJnZXRBdHRyaWJ1dGUiLCJzZXRBdHRyIiwic2V0QXR0cmlidXRlIiwiZW50cmllcyIsImsiLCJ2IiwicmVtb3ZlQXR0cnMiLCJyZW1vdmVBdHRyaWJ1dGUiLCJwcmVwZW5kQ2hpbGQiLCJpdGVtIiwiaW5zZXJ0QmVmb3JlIiwiZmlyc3RFbGVtZW50Q2hpbGQiLCJhcHBlbmRDaGlsZCIsInJlZk5vZGUiLCJyZW1vdmVDaGlsZCIsImVtcHR5IiwiZmlyc3RDaGlsZCIsImxhc3RDaGlsZCIsInR5cGUiLCJib2R5IiwibmV4dFNpYmxpbmciLCJkZXRhY2giLCJmaW5kIiwicXVlcnkiLCJtdWx0aXBsZSIsInF1ZXJ5U2VsZWN0b3JBbGwiLCJxdWVyeVNlbGVjdG9yIiwiZmluZEJ5Q2xhc3MiLCJnZXRFbGVtZW50c0J5Q2xhc3NOYW1lIiwib24iLCJldmVudCIsImhhbmRsZXIiLCJvcHRpb25zIiwibWFwIiwiaGFzIiwiZ2V0IiwicHVzaCIsInNldCIsImFkZEV2ZW50TGlzdGVuZXIiLCJvZmYiLCJoYW5kbGVycyIsImluZGV4T2YiLCJzcGxpY2UiLCJyZW1vdmVFdmVudExpc3RlbmVyIiwiaCIsImRlc3Ryb3kiLCJmIiwiRm9ybUVsZW1lbnQiLCJ2YWwiLCJmb3JtIiwiY2xvc2VzdCIsIkRydXBhbCJdLCJzb3VyY2VzIjpbIkVsZW1lbnQuZXM2LmpzIl0sInNvdXJjZXNDb250ZW50IjpbIigoeyBUb29sc2hlZDogdHMgfSkgPT4ge1xuICAvKipcbiAgICogRnVuY3Rpb25hbGl0eSB3cmFwcGVyIGZvciBIVE1MRWxlbWVudHMuIEFsbG93cyBmb3IgbW9yZSBjb252aWVuZW50IGNyZWF0aW9uXG4gICAqIG9mIEhUTUxFbGVtZW50cyBhbmQgYWx0ZXJpbmcgdGhlbS5cbiAgICovXG4gIHRzLkVsZW1lbnQgPSBjbGFzcyBUb29sc2hlZEVsZW1lbnQge1xuICAgIC8qKlxuICAgICAqIENyZWF0ZSBhIG5ldyBpbnN0YW5jZSBvZiB0aGUgVG9vbHNoZWRFbGVtZW50IHdyYXBwZXIuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ3xIVE1MRWxlbWVudH0gZWxlbWVudFxuICAgICAqICAgRWl0aGVyIGEgSFRNTCB0YWcgc3RyaW5nIG9yIGFuIEhUTUwgZWxlbWVudCB0byB3cmFwLiBJZiB2YWx1ZSBpcyBhXG4gICAgICogICBzdHJpbmcgdGhlbiBjcmVhdGUgYW4gSFRNTEVsZW1lbnQgb2YgdGhhdCB0YWcuXG4gICAgICogQHBhcmFtIHtPYmplY3Q9fSBhdHRyc1xuICAgICAqICAgQXR0cmlidXRlcyB0byBhcHBseSB0byB0aGUgSFRNTEVsZW1lbnQgd3JhcHBlZCBieSB0aGlzIG9iamVjdC5cbiAgICAgKiBAcGFyYW0ge1Rvb2xzaGVkRWxlbWVudHxIVE1MRWxlbWVudD19IGFwcGVuZFRvXG4gICAgICogICBBIHBhcmVudCBlbGVtZW50IHRvIGF0dGFjaCB0aGlzIG5ldyBlbGVtZW50IHRvLlxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKGVsZW1lbnQsIGF0dHJzLCBhcHBlbmRUbykge1xuICAgICAgaWYgKHRzLmlzU3RyaW5nKGVsZW1lbnQpKSB7XG4gICAgICAgIGVsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KGVsZW1lbnQudG9VcHBlckNhc2UoKSk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuZWwgPSBlbGVtZW50O1xuICAgICAgdGhpcy5ldmVudExpc3RlbmVycyA9IG5ldyBNYXAoKTtcblxuICAgICAgaWYgKGF0dHJzKSB0aGlzLnNldEF0dHJzKGF0dHJzKTtcbiAgICAgIGlmIChhcHBlbmRUbykgdGhpcy5hdHRhY2hUbyhhcHBlbmRUbyk7XG4gICAgfVxuXG4gICAgLyogLS0tLS0tLSBnZXR0ZXJzIC8gc2V0dGVycyAtLS0tLS0tLSAqL1xuXG4gICAgZ2V0IGlkKCkge1xuICAgICAgcmV0dXJuIHRoaXMuZWwuaWQ7XG4gICAgfVxuXG4gICAgc2V0IGlkKHZhbHVlKSB7XG4gICAgICB0aGlzLmVsLmlkID0gdmFsdWU7XG4gICAgfVxuXG4gICAgZ2V0IHRhZ05hbWUoKSB7XG4gICAgICByZXR1cm4gdGhpcy5lbC50YWdOYW1lO1xuICAgIH1cblxuICAgIGdldCBjbGFzc05hbWUoKSB7XG4gICAgICByZXR1cm4gdGhpcy5lbC5jbGFzc05hbWU7XG4gICAgfVxuXG4gICAgc2V0IGNsYXNzTmFtZShuYW1lcykge1xuICAgICAgdGhpcy5lbC5jbGFzc05hbWUgPSBuYW1lcztcbiAgICB9XG5cbiAgICBnZXQgY2xhc3NMaXN0KCkge1xuICAgICAgcmV0dXJuIHRoaXMuZWwuY2xhc3NMaXN0O1xuICAgIH1cblxuICAgIGdldCBzdHlsZSgpIHtcbiAgICAgIHJldHVybiB0aGlzLmVsLnN0eWxlO1xuICAgIH1cblxuICAgIGdldCBkYXRhc2V0KCkge1xuICAgICAgcmV0dXJuIHRoaXMuZWwuZGF0YXNldDtcbiAgICB9XG5cbiAgICBnZXQgcGFyZW50Tm9kZSgpIHtcbiAgICAgIHJldHVybiB0aGlzLmVsLnBhcmVudE5vZGU7XG4gICAgfVxuXG4gICAgZ2V0IHBhcmVudEVsZW1lbnQoKSB7XG4gICAgICByZXR1cm4gdGhpcy5lbC5wYXJlbnRFbGVtZW50O1xuICAgIH1cblxuICAgIGdldCBpbm5lckhUTUwoKSB7XG4gICAgICByZXR1cm4gdGhpcy5lbC5pbm5lckhUTUw7XG4gICAgfVxuXG4gICAgc2V0IGlubmVySFRNTChodG1sKSB7XG4gICAgICB0aGlzLmVsLmlubmVySFRNTCA9IGh0bWw7XG4gICAgfVxuXG4gICAgZ2V0IHRleHRDb250ZW50KCkge1xuICAgICAgcmV0dXJuIHRoaXMuZWwudGV4dENvbnRlbnQ7XG4gICAgfVxuXG4gICAgc2V0IHRleHRDb250ZW50KHRleHQpIHtcbiAgICAgIHRoaXMuZWwudGV4dENvbnRlbnQgPSB0ZXh0O1xuICAgIH1cblxuICAgIC8qIC0tLS0tLS0gZWxlbWVudCBtb2RpZmllcnMgLS0tLS0tLSAqL1xuXG4gICAgLyoqXG4gICAgICogQWRkIENTUyBjbGFzc2VzIHRvIHRoZSB3cmFwcGVkIEhUTUxFbGVtZW50LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd8c3RyaW5nW119IGNsYXNzZXNcbiAgICAgKiAgIEVpdGhlciBhIHNpbmdsZSBzdHJpbmcgdG8gYWRkLCBvciBhbiBhcnJheSBvZiBjbGFzcyBuYW1lcyB0byBhZGQuXG4gICAgICovXG4gICAgYWRkQ2xhc3MoY2xhc3Nlcykge1xuICAgICAgLy8gQWRkIGFycmF5IG9mIGNsYXNzZXMgb25lIGF0IGEgdGltZSBmb3Igb2xkIElFIGNvbXBhdGliaWxpdHkuXG4gICAgICAvLyBTaG91bGQgdGhpcyBiZSByZW1vdmVkIG5vdyB0aGF0IElFIGlzIG5vdCBzdXBwb3J0ZWQgYW55bW9yZT9cbiAgICAgIEFycmF5LmlzQXJyYXkoY2xhc3NlcylcbiAgICAgICAgPyBjbGFzc2VzLmZvckVhY2goKGkpID0+IHRoaXMuY2xhc3NMaXN0LmFkZChpKSlcbiAgICAgICAgOiB0aGlzLmNsYXNzTGlzdC5hZGQoY2xhc3Nlcyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlIENTUyBjbGFzc2VzIGZyb20gdGhlIHdyYXBwZWQgSFRNTEVsZW1lbnQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ3xzdHJpbmdbXX0gY2xhc3Nlc1xuICAgICAqICAgRWl0aGVyIGEgc2luZ2xlIGNsYXNzIG5hbWUgb3IgYW4gYXJyYXkgb2YgY2xhc3MgbmFtZXMgdG8gcmVtb3ZlLlxuICAgICAqL1xuICAgIHJlbW92ZUNsYXNzKGNsYXNzZXMpIHtcbiAgICAgIEFycmF5LmlzQXJyYXkoY2xhc3NlcylcbiAgICAgICAgPyBjbGFzc2VzLmZvckVhY2goKGkpID0+IHRoaXMuY2xhc3NMaXN0LnJlbW92ZShpKSlcbiAgICAgICAgOiB0aGlzLmNsYXNzTGlzdC5yZW1vdmUoY2xhc3Nlcyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQXBwbHkgYSBrZXllZCB2YWx1ZSBsaXN0IG9mIHN0eWxlIHZhbHVlcyB0byB0aGUgd3JhcHBlZCBIVE1MRWxlbWVudC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBzdHlsZXNcbiAgICAgKiAgIEtleWVkIHN0eWxlIHZhbHVlcyB0byBhcHBseSB0byB0aGUgZWxlbWVudCdzIHN0eWxlIHByb3BlcnR5LlxuICAgICAqL1xuICAgIHNldFN0eWxlcyhzdHlsZXMpIHtcbiAgICAgIE9iamVjdC5hc3NpZ24odGhpcy5zdHlsZSwgc3R5bGVzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIHZhbHVlIG9mIGFuIGF0dHJpYnV0ZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lXG4gICAgICogICBOYW1lIG9mIHRoZSBhdHRyaWJ1dGUgdG8gZmV0Y2guXG4gICAgICpcbiAgICAgKiBAcmV0dXJuIHtzdHJpbmd8bnVsbH1cbiAgICAgKiAgIFRoZSB2YWx1ZSBvZiB0aGUgYXR0cmlidXRlIGlmIGl0IGV4aXN0cy4gSWYgdGhlcmUgaXMgbm8gYXR0cmlidXRlIHdpdGhcbiAgICAgKiAgIHRoZSByZXF1ZXN0ZWQgbmFtZSBOVUxMIGlzIHJldHVybmVkLlxuICAgICAqL1xuICAgIGdldEF0dHIobmFtZSkge1xuICAgICAgcmV0dXJuIHRoaXMuZWwuaGFzQXR0cmlidXRlKG5hbWUpID8gdGhpcy5lbC5nZXRBdHRyaWJ1dGUobmFtZSkgOiBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldCB2YWx1ZSBmb3IgYSBzaW5nbGUgSFRNTCBhdHRyaWJ1dGUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZVxuICAgICAqICAgVGhlIG5hbWUgb2YgdGhlIGF0dHJpYnV0ZSB0byBzZXQuXG4gICAgICogQHBhcmFtIHtzdGluZ3xhcnJheXxvYmplY3R9IHZhbHVlXG4gICAgICogICBUaGUgdmFsdWUgdG8gc2V0IGZvciB0aGUgYXR0cmlidXRlLiBTdHlsZSBjYW4gYmUgYW4gb2JqZWN0LCBjbGFzcyBjYW5cbiAgICAgKiAgIGJlIGEgYXJyYXkuXG4gICAgICovXG4gICAgc2V0QXR0cihuYW1lLCB2YWx1ZSkge1xuICAgICAgc3dpdGNoIChuYW1lKSB7XG4gICAgICAgIGNhc2UgJ2NsYXNzJzpcbiAgICAgICAgICB0aGlzLmFkZENsYXNzKHZhbHVlKTtcbiAgICAgICAgICBicmVhaztcblxuICAgICAgICBjYXNlICdzdHlsZSc6XG4gICAgICAgICAgaWYgKCF0cy5pc1N0cmluZyh2YWx1ZSkpIHtcbiAgICAgICAgICAgIHRoaXMuc2V0U3R5bGVzKHZhbHVlKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cblxuICAgICAgICBjYXNlICdodG1sJzpcbiAgICAgICAgICB0aGlzLmlubmVySFRNTCA9IHZhbHVlO1xuICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgIGNhc2UgJ3RleHQnOlxuICAgICAgICAgIHRoaXMudGV4dENvbnRlbnQgPSB2YWx1ZTtcblxuICAgICAgICAvLyBlc2xpbnQtaWdub3JlLW5leHQtbGluZSBuby1mYWxsdGhyb3VnaFxuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIHRoaXMuZWwuc2V0QXR0cmlidXRlKG5hbWUsIHZhbHVlKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBcHBseSBrZXllZCBhdHRyaWJ1dGUgdmFsdWVzIHRvIHRoZSB3cmFwcGVkIEhUTUxFbGVtZW50LlxuICAgICAqXG4gICAgICogTW9zdCBhdHRyaWJ1dGVzIHNob3VsZCBqdXN0IGJlIHN0cmluZyB2YWx1ZXMsIGJ1dCBleGNlcHRpb25zIGFyZTpcbiAgICAgKiAgLSBjbGFzczogY2FuIGJlIGEgc3RyaW5nIG9yIGFuIGFycmF5IG9mIGNsYXNzIG5hbWVzXG4gICAgICogIC0gc3R5bGU6IENhbiBiZSBhIHN0cmluZyBvciBhbiBPYmplY3Qgb2Yga2V5ZWQgc3R5bGUgdmFsdWVzLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtPYmplY3R9IGF0dHJzXG4gICAgICogICBLZXllZCB2YWx1ZXMgdG8gYXBwbHkgYXMgYXR0cmlidXRlcyB0byB0aGUgd3JhcHBlZCBIVE1MRWxlbWVudC5cbiAgICAgKi9cbiAgICBzZXRBdHRycyhhdHRycykge1xuICAgICAgT2JqZWN0LmVudHJpZXMoYXR0cnMpLmZvckVhY2goKFtrLCB2XSkgPT4gdGhpcy5zZXRBdHRyKGssIHYpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmUgc3BlY2lmaWVkIGF0dHJpYnV0ZXMgZnJvbSB0aGUgZWxlbWVudC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfHN0cmluZ1tdfSBhdHRyc1xuICAgICAqICAgVGhlIG5hbWVzIG9mIHRoZSBhdHRyaWJ1dGVzIHRvIHJlbW92ZSBmcm9tIHRoZSBlbGVtZW50LlxuICAgICAqL1xuICAgIHJlbW92ZUF0dHJzKGF0dHJzKSB7XG4gICAgICBpZiAodHMuaXNTdHJpbmcoYXR0cnMpKSB7XG4gICAgICAgIGF0dHJzID0gW2F0dHJzXTtcbiAgICAgIH1cblxuICAgICAgYXR0cnMuZm9yRWFjaCgoaSkgPT4gdGhpcy5lbC5yZW1vdmVBdHRyaWJ1dGUoaSkpO1xuICAgIH1cblxuICAgIC8qIC0tLS0tLS0tLSBET00gTW9kaWZpZXJzIC0tLS0tLS0tLSAqL1xuXG4gICAgLyoqXG4gICAgICogQWRkIGFuIGVsZW1lbnQgdG8gdGhlIHN0YXJ0IHRoZSB3cmFwcGVkIEhUTUxFbGVtZW50J3MgY2hpbGRyZW4gbm9kZXMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1Rvb2xzaGVkRWxlbWVudHxIVE1MRWxlbWVudH0gaXRlbVxuICAgICAqICAgVGhlIGNoaWxkIHRvIHByZXBlbmQgdG8gdGhlIGVsZW1lbnQuXG4gICAgICovXG4gICAgcHJlcGVuZENoaWxkKGl0ZW0pIHtcbiAgICAgIHRoaXMuaW5zZXJ0QmVmb3JlKGl0ZW0sIHRoaXMuZWwuZmlyc3RFbGVtZW50Q2hpbGQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFwcGVuZCBhbiBlbGVtZW50IHRvIHRoaXMgd3JhcHBlZCBIVE1MRWxlbWVudC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7VG9vbHNoZWRFbGVtZW50fEhUTUxFbGVtZW50fSBpdGVtXG4gICAgICogICBFbGVtZW50IHRvIGFwcGVuZC5cbiAgICAgKi9cbiAgICBhcHBlbmRDaGlsZChpdGVtKSB7XG4gICAgICB0aGlzLmluc2VydEJlZm9yZShpdGVtKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJbnNlcnQgYW4gZWxlbWVudCBhcyBhIGNoaWxkIG9mIHRoZSB3cmFwcGVkIEhUTUxFTGVtZW50LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtUb29sc2hlZEVsZW1lbnR8SFRNTEVsZW1lbnR9IGl0ZW1cbiAgICAgKiAgIFRoZSBlbGVtZW50IHRvIGluc2VydCBhcyBhIGNoaWxkIG9mIHRoZSBlbGVtZW50LlxuICAgICAqIEBwYXJhbSB7VG9vbHNoZWRFbGVtZW50fEhUTUxFbGVtZW50PX0gcmVmTm9kZVxuICAgICAqICAgRWxlbWVudCB0byB1c2UgYXMgYSByZWZlcmVuY2UgcG9pbnQgZm9yIGluc2VydGlvbi4gSWYgcmVmZXJlbmNlIG5vZGVcbiAgICAgKiAgIGlzIE5VTEwgdGhlbiBhZGQgdGhlIGVsZW1lbnQgYWZ0ZXIgdGhlIGxhc3QgY2hpbGQgZWxlbWVudC5cbiAgICAgKi9cbiAgICBpbnNlcnRCZWZvcmUoaXRlbSwgcmVmTm9kZSkge1xuICAgICAgaXRlbSA9IGl0ZW0gaW5zdGFuY2VvZiBUb29sc2hlZEVsZW1lbnQgPyBpdGVtLmVsIDogaXRlbTtcbiAgICAgIHJlZk5vZGUgPSByZWZOb2RlIGluc3RhbmNlb2YgVG9vbHNoZWRFbGVtZW50ID8gcmVmTm9kZS5lbCA6IHJlZk5vZGU7XG5cbiAgICAgIHRoaXMuZWwuaW5zZXJ0QmVmb3JlKGl0ZW0sIHJlZk5vZGUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZSBhbiBlbGVtZW50IGZyb20gdGhpcyB3cmFwcGVkIEhUTUxFbGVtZW50LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtUb29sc2hlZEVsZW1lbnR8SFRNTEVsZW1lbnR9IGl0ZW1cbiAgICAgKiAgIEVsZW1lbnQgdG8gcmVtb3ZlLlxuICAgICAqL1xuICAgIHJlbW92ZUNoaWxkKGl0ZW0pIHtcbiAgICAgIHRoaXMuZWwucmVtb3ZlQ2hpbGQoaXRlbSBpbnN0YW5jZW9mIFRvb2xzaGVkRWxlbWVudCA/IGl0ZW0uZWwgOiBpdGVtKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmUgYWxsIG5vZGVzIGFuZCBlbGVtZW50cyBmcm9tIHRoaXMgZWxlbWVudC5cbiAgICAgKi9cbiAgICBlbXB0eSgpIHtcbiAgICAgIHdoaWxlICh0aGlzLmVsLmZpcnN0Q2hpbGQpIHtcbiAgICAgICAgdGhpcy5lbC5yZW1vdmVDaGlsZCh0aGlzLmVsLmxhc3RDaGlsZCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSW5zZXJ0IHRoaXMgZWxlbWVudCBpbnRvIHRoZSBET00gYmFzZWQgb24gdGhlIHJlZmVyZW5jZSBub2RlIHByb3ZpZGVkLlxuICAgICAqIFRoZSB0eXBlIHBhcmFtZXRlciBpcyB1c2VkIHRvIGRldGVybWluZSBpZiB0aGUgcmVmZXJlbmNlIG5vZGUgaXMgdGhlXG4gICAgICogcGFyZW50IG9yIHNpYmxpbmcuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1Rvb2xzaGVkRWxlbWVudHxIVE1MRWxlbWVudH0gcmVmTm9kZVxuICAgICAqICAgVGhlIGVsZW1lbnQgdG8gdXNlIGFzIGEgcmVmZXJlbmNlIHBvaW50IGZvciBpbnNlcnRpb24uIENvdWxkIGJlIHRoZVxuICAgICAqICAgcGFyZW50IG9yIHRoZSBzaWJsaW5nIGRlcGVuZGluZyBvbiB0aGUgdmFsdWUgb2YgXCJ0eXBlXCIuXG4gICAgICogQHBhcmFtIHtzdHJpbmc9fSB0eXBlXG4gICAgICogICBJZiB0eXBlID0gXCJhZnRlclwiIHRoZW4gZWxlbWVudCBpcyBpbnNlcnRlZCBhZnRlciB0aGUgcmVmZXJlbmNlIG5vZGUsXG4gICAgICogICBpZiB0eXBlID0gXCJiZWZvcmVcIiB0aGVuIGVsZW1lbnQgaXMgaW5zZXJ0ZWQgYmVmb3JlLiBPdGhlcndpc2UsIHRoZVxuICAgICAqICAgZWxlbWVudCBpcyBhcHBlbmRlZCB0byB0aGUgcmVmZXJlbmNlIG5vZGUuXG4gICAgICovXG4gICAgYXR0YWNoVG8ocmVmTm9kZSwgdHlwZSA9ICdwYXJlbnQnKSB7XG4gICAgICBpZiAoJ2FmdGVyJyA9PT0gdHlwZSB8fCAnYmVmb3JlJyA9PT0gdHlwZSkge1xuICAgICAgICAocmVmTm9kZS5wYXJlbnROb2RlIHx8IGRvY3VtZW50LmJvZHkpLmluc2VydEJlZm9yZSh0aGlzLmVsLCAoJ2JlZm9yZScgPT09IHR5cGUpID8gcmVmTm9kZSA6IHJlZk5vZGUubmV4dFNpYmxpbmcpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmVmTm9kZS5hcHBlbmRDaGlsZCh0aGlzLmVsKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBEZXRhY2ggdGhpcyBlbGVtZW50IGZyb20gdGhlIERPTS5cbiAgICAgKi9cbiAgICBkZXRhY2goKSB7XG4gICAgICBpZiAodGhpcy5wYXJlbnROb2RlKSB0aGlzLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQodGhpcy5lbCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRmluZHMgYWxsIGRlc2NlbmRlbnQgZWxlbWVudCBtYXRjaGluZyBhIHNlbGVjdG9yIHF1ZXJ5LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHF1ZXJ5XG4gICAgICogICBUaGUgc2VsZWN0b3IgcXVlcnkgdG8gdXNlIGZvciBtYXRjaGluZyBkZXNjZW5kZW50IGVsZW1lbnRzIHdpdGguXG4gICAgICogQHBhcmFtIHtib29sfSBtdWx0aXBsZVxuICAgICAqICAgUmV0dXJuIGFsbCBtYXRjaGluZyBlbGVtZW50cz8gSWYgdHJ1ZSBmaW5kIGFsbCBtYXRjaGluZyBlbGVtZW50cyxcbiAgICAgKiAgIG90aGVyd2lzZSBvbmx5IHJldHVybiB0aGUgZmlyc3QgbWF0Y2hlZCBlbGVtZW50LlxuICAgICAqXG4gICAgICogQHJldHVybiB7Tm9kZUxpc3R8Tm9kZX1cbiAgICAgKiAgIExpc3Qgb2Ygbm9kZXMgbWF0Y2hpbmcgdGhlIHF1ZXJpZWQgY3JpdGVyaWEgd2hlbiBtdWx0aXBsZWQgYXJlXG4gICAgICogICByZXF1ZXN0ZWQgb3IganVzdCBhIHNpbmdsZSBub2RlIGlmIHRoZSBtdWx0aXBsZSBwYXJhbWV0ZXIgaXMgZmFsc2UuXG4gICAgICovXG4gICAgZmluZChxdWVyeSwgbXVsdGlwbGUgPSB0cnVlKSB7XG4gICAgICByZXR1cm4gbXVsdGlwbGVcbiAgICAgICAgPyB0aGlzLmVsLnF1ZXJ5U2VsZWN0b3JBbGwocXVlcnkpXG4gICAgICAgIDogdGhpcy5lbC5xdWVyeVNlbGVjdG9yKHF1ZXJ5KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBGaW5kIGFsbCBjaGlsZCBET00gZWxlbWVudHMgd2l0aCBhIGNsYXNzIG5hbWUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gY2xhc3NOYW1lXG4gICAgICogICBDbGFzcyBuYW1lIHRvIHNlYXJjaCBmb3IgZGVzY2VuZGVudCBlbGVtZW50cyBmb3IuXG4gICAgICpcbiAgICAgKiBAcmV0dXJuIHtIVE1MQ29sbGVjdGlvbn1cbiAgICAgKiAgIEEgY29sbGVjdGlvbiBvZiBIVE1MIGVsZW1lbnQgd2hpY2ggYXJlIGRlc2NlbmRlbnRzIG9mIHRoZSBlbGVtZW50IHdpdGhcbiAgICAgKiAgIHRoZSBjbGFzcyBuYW1lIHNlYXJjaGVkIGZvci5cbiAgICAgKi9cbiAgICBmaW5kQnlDbGFzcyhjbGFzc05hbWUpIHtcbiAgICAgIHJldHVybiB0aGlzLmVsLmdldEVsZW1lbnRzQnlDbGFzc05hbWUoY2xhc3NOYW1lKTtcbiAgICB9XG5cbiAgICAvLyAtLS0tLS0tLSBldmVudCBsaXN0ZW5lcnMgLS0tLS0tLS0gLy9cblxuICAgIC8qKlxuICAgICAqIEFkZCBhbiBldmVudCBsaXN0ZW5lciB0byB0aGUgZWxlbWVudC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBldmVudFxuICAgICAqICAgRXZlbnQgdG8gYXR0YWNoIHRoZSBldmVudCBmb3IuXG4gICAgICogQHBhcmFtIHtmdW5jdGlvbn0gaGFuZGxlclxuICAgICAqICAgVGhlIGNhbGxiYWNrIGV2ZW50IGhhbmRsZXIuXG4gICAgICogQHBhcmFtIHtBZGRFdmVudExpc3RlbmVyT3B0aW9ucz19IG9wdGlvbnNcbiAgICAgKiAgIEV2ZW50IGxpc3RlbmVyIG9wdGlvbnMgdG8gYXBwbHkgdG8gdGhlIGV2ZW50IGxpc3RlbmVyLlxuICAgICAqL1xuICAgIG9uKGV2ZW50LCBoYW5kbGVyLCBvcHRpb25zID0ge30pIHtcbiAgICAgIGNvbnN0IG1hcCA9IHRoaXMuZXZlbnRMaXN0ZW5lcnM7XG5cbiAgICAgIGlmIChtYXAuaGFzKGV2ZW50KSkge1xuICAgICAgICBtYXAuZ2V0KGV2ZW50KS5wdXNoKGhhbmRsZXIpO1xuICAgICAgfVxuICAgICAgZWxzZSB7XG4gICAgICAgIG1hcC5zZXQoZXZlbnQsIFtoYW5kbGVyXSk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuZWwuYWRkRXZlbnRMaXN0ZW5lcihldmVudCwgaGFuZGxlciwgb3B0aW9ucyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBldmVudCBsaXN0ZW5lcnMgZnJvbSB0aGUgZWxlbWVudC4gSWYgb25seSBldmVudCBpcyBwcm92aWRlZCB0aGVuXG4gICAgICogYWxsIHRyYWNrZWQgZXZlbnQgbGlzdGVuZXJzIGFyZSByZW1vdmVkIChsaXN0ZW5lcnMgYWRkZWQgd2l0aCBcIm9uKClcIikuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gZXZlbnRcbiAgICAgKiAgIE5hbWUgb2YgdGhlIGV2ZW50IHRvIHJlbW92ZSBsaXN0ZW5lcnMgZnJvbS5cbiAgICAgKiBAcGFyYW0ge2Z1bmN0aW9uPX0gaGFuZGxlclxuICAgICAqICAgVGhlIGxpc3RlbmVyIHRvIHJlbW92ZS4gSWYgb25seSB0aGUgZXZlbnQgbmFtZSBpcyBwcm92aWRlZCwgdGhlblxuICAgICAqICAgYWxsIGxpc3RlbmVycyBmb3IgdGhlIGV2ZW50IGFyZSByZW1vdmVkLlxuICAgICAqL1xuICAgIG9mZihldmVudCwgaGFuZGxlcikge1xuICAgICAgY29uc3QgaGFuZGxlcnMgPSB0aGlzLmV2ZW50TGlzdGVuZXJzLmdldChldmVudCk7XG5cbiAgICAgIC8vIElmIGEgaGFuZGxlciB3YXMgc3BlY2lmaWVkLCBvbmx5IHJlbW92ZSB0aGF0IHNwZWNpZmljIGhhbmRsZXIuXG4gICAgICAvLyBvdGhlcndpc2UgcmVtb3ZlIGFsbCBoYW5kbGVycyByZWdpc3RlcmVkIGZvciB0aGUgZXZlbnQuXG4gICAgICBpZiAoaGFuZGxlcikge1xuICAgICAgICBpZiAoaGFuZGxlcnMpIHtcbiAgICAgICAgICBjb25zdCBpID0gaGFuZGxlcnMuaW5kZXhPZihoYW5kbGVyKTtcbiAgICAgICAgICBpZiAoaSA+IC0xKSBoYW5kbGVycy5zcGxpY2UoaSwgMSk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmVsLnJlbW92ZUV2ZW50TGlzdGVuZXIoZXZlbnQsIGhhbmRsZXIpO1xuICAgICAgfVxuICAgICAgZWxzZSBpZiAoaGFuZGxlcnMpIHtcbiAgICAgICAgaGFuZGxlcnMuZm9yRWFjaCgoaCkgPT4gdGhpcy5lbC5yZW1vdmVFdmVudExpc3RlbmVyKGgpKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyAtLS0tLS0tLS0gaG91c2Uga2VlcGluZyAtLS0tLS0tLS0gLy9cblxuICAgIC8qKlxuICAgICAqIENsZWFuLXVwIGVsZW1lbnQgcmVzb3VyY2VzIGFuZCBldmVudCBsaXN0ZW5lcnMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge2Jvb2x9IGRldGFjaFxuICAgICAqICAgU2hvdWxkIHRoZSBlbGVtZW50IGFsc28gYmUgZGV0YWNoZWQgZnJvbSB0aGUgRE9NIHBhcmVudC5cbiAgICAgKi9cbiAgICBkZXN0cm95KGRldGFjaCkge1xuICAgICAgdGhpcy5ldmVudExpc3RlbmVycy5mb3JFYWNoKCh2LCBrKSA9PiB7XG4gICAgICAgIHYuZm9yRWFjaCgoZikgPT4gdGhpcy5lbC5yZW1vdmVFdmVudExpc3RlbmVyKGssIGYpKTtcbiAgICAgIH0pO1xuXG4gICAgICBpZiAoZGV0YWNoKSB0aGlzLmRldGFjaCgpO1xuICAgIH1cbiAgfTtcblxuICAvKipcbiAgICogV3JhcHBlciBmb3IgZm9ybSBpbnB1dCBlbGVtZW50cy5cbiAgICovXG4gIHRzLkZvcm1FbGVtZW50ID0gY2xhc3MgRm9ybUVsZW1lbnQgZXh0ZW5kcyB0cy5FbGVtZW50IHtcbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIGN1cnJlbnQgdmFsdWUgZm9yIHRoZSBmb3JtIGlucHV0IGVsZW1lbnQuXG4gICAgICpcbiAgICAgKiBAcmV0dXJuIHsqfVxuICAgICAqICAgVGhlIGN1cnJlbnQgZm9ybSBpbnB1dCB2YWx1ZS5cbiAgICAgKi9cbiAgICBnZXQgdmFsdWUoKSB7XG4gICAgICByZXR1cm4gdGhpcy5lbC52YWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXQgdGhlIHZhbHVlIG9mIHRoaXMgZm9ybSBlbGVtZW50LlxuICAgICAqXG4gICAgICogQHBhcmFtIHsqfSB2YWxcbiAgICAgKiAgIFRoZSB2YWx1ZSB0byBzZXQgZm9yIHRoaXMgZm9ybSBlbGVtZW50LlxuICAgICAqL1xuICAgIHNldCB2YWx1ZSh2YWwpIHtcbiAgICAgIHRoaXMuZWwudmFsdWUgPSB2YWw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0cmlldmUgdGhlIGZvcm0gd2hpY2ggdGhpcyBmb3JtIGVsZW1lbnQgYmVsb25ncyB0by5cbiAgICAgKlxuICAgICAqIEByZXR1cm4ge0Zvcm1FbGVtZW50fG51bGx9XG4gICAgICogICBUaGUgZm9ybSBlbGVtZW50IHdoaWNoIG93bnMgdGhpcyBmb3JtIGVsZW1lbnQuXG4gICAgICovXG4gICAgZ2V0IGZvcm0oKSB7XG4gICAgICByZXR1cm4gdGhpcy5lbC5mb3JtIHx8IHRoaXMuZWwuY2xvc2VzdCgnZm9ybScpO1xuICAgIH1cbiAgfTtcbn0pKERydXBhbCk7XG4iXSwibWFwcGluZ3MiOiI7O0FBQUEsQ0FBQyxDQUFDO0VBQUVBLFFBQVEsRUFBRUM7QUFBRyxDQUFDLEtBQUs7RUFDckI7QUFDRjtBQUNBO0FBQ0E7RUFDRUEsRUFBRSxDQUFDQyxPQUFPLEdBQUcsTUFBTUMsZUFBZSxDQUFDO0lBQ2pDO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7SUFDSUMsV0FBVyxDQUFDQyxPQUFPLEVBQUVDLEtBQUssRUFBRUMsUUFBUSxFQUFFO01BQ3BDLElBQUlOLEVBQUUsQ0FBQ08sUUFBUSxDQUFDSCxPQUFPLENBQUMsRUFBRTtRQUN4QkEsT0FBTyxHQUFHSSxRQUFRLENBQUNDLGFBQWEsQ0FBQ0wsT0FBTyxDQUFDTSxXQUFXLEVBQUUsQ0FBQztNQUN6RDtNQUVBLElBQUksQ0FB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

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc