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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
