toolshed-8.x-1.x-dev/js/Dock.js
js/Dock.js
"use strict";
/* eslint no-bitwise: ["error", { "allow": ["^"] }] */
(($, Toolshed) => {
/**
* Define the namespace for defining docking libraries & tools.
*/
Toolshed.Dock = {
/**
* Creates a new instance of a docker for the edge and parses
* options from CSS class attributes.
*
* @param {jQuery} $elem
* HTML element that is being docked.
* @param {jQuery} $bounds
* HTML element which defines the bounds.
* @param {Object} settings
* Object containing the docker settings.
* {
* edge: {string} ['top'|'left'|'bottom'|'right'],
* offset: {int} 0
* collapsible: {bool} false,
* trackMutations: {bool} false,
* animate: {Object|bool} {
* type: {string} [slide],
* // Animation will last for 200 milliseconds.
* duration: {int} 200,
* // Animation starts after 250% of the element dimension.
* // This value is ignored of no animatable options are enabled.
* // NOTE: can be also be a constant pixel value.
* }
* }
*/
createItem($elem, $bounds, settings = {}) {
const config = {
edge: 'TOP',
offset: 0
};
/*
* Determine the set of active docker settings by parsing CSS class
* information. Options are classes that start with "tsdock-opt-{{option}}"
* or "tsdock-edge-[top|left|bottom|right]".
*
* Options can only get activated here, and will get applied with the
* current defaults for that option. For instance, "tsdock-opt-sticky"
* will make the docker, sticky using the default animation configurations.
*/
if (!settings || settings.detectOpts) {
let match = null;
const optRegex = /(?:^|\s)tsdock--(opt|edge)-([-\w]+)(?:\s|$)/g;
const elClasses = $elem.attr('class');
// eslint-disable-next-line no-cond-assign
while ((match = optRegex.exec(elClasses)) !== null) {
if (match[1] === 'opt') {
config[match[2]] = true;
} else if (match[1] === 'edge') {
[,, config.edge] = match;
}
}
}
// Build the docker now that all settings have been applied to it.
const docker = new Toolshed.Dock.DockItem($elem, $bounds, {
...config,
...settings
});
Toolshed.Dock.addDocker(config.edge.toUpperCase() || 'TOP', docker);
},
/**
* Add docker items into a docked container.
*
* @param {string} edge
* The edge to add the docking content to.
* @param {Drupal.Toolshed.Dock.DockItem} item
* The dockable item to place into the container.
*/
addDocker(edge, item) {
if (Toolshed.Dock.containers[edge]) {
Toolshed.Dock.containers[edge].addItem(item);
}
}
};
/**
* Containers for holding items that are docked to them. DockContainers
* will listen to Window events and manage the items that they wrap.
*/
Toolshed.Dock.DockContainer = class {
constructor() {
this.active = false;
this.container = null;
this.items = [];
}
isActive() {
return this.active;
}
/**
* Add a new docking item to this docking container.
*
* @param {Drupal.Toolshed.Dock.DockItem} item
* The DockItem to add to this container.
*/
addItem(item) {
item.dockTo = this;
this.items.push(item);
// Defer building and listening to events until a dockable item is added.
if (!this.active) {
this.init();
}
}
/**
* Remove the DockItem from this container.
*
* @param {Drupal.Toolshed.Dock.DockItem} item
* The DockItem to find and remove from the container.
*/
removeItem(item) {
this.items = this.items.filter(cmp => cmp !== item);
delete item.dockTo;
if (!this.items.length && this.container) {
this.container.hide();
}
}
/**
* Register events that may make changes to docking, and init positioning.
*/
init() {
this.container = $('<div class="tsdock-container"/>').appendTo($('body'));
this.initContainer();
this.active = true;
Toolshed.events.scroll.add(this);
Toolshed.events.resize.add(this);
// Initialize the positioning of the dock.
this.onResize(new Event('resize'), Toolshed.winRect);
}
/**
* Event handler for the window scroll change events.
*
* @param {Event} e
* The scroll event object for this event.
* @param {Drupal.Toolshed.Geom.Rect} win
* The current bounds of the window.
* @param {Object} scroll
* Object containing a top and left item to represent the current
* scroll offsets of the document in relation to the window.
*/
onScroll(e, win, scroll) {
const viewable = new Toolshed.Geom.Rect(win);
viewable.offset(scroll.left, scroll.top);
this.items.forEach(item => {
if (item.isDocked ^ this.isDocking(item, viewable)) {
return item.isDocked ? item.deactivateDock() : item.activateDock(this.container);
}
}, this);
}
onResize(e, rect) {
const offset = {
top: document.documentElement.scrollTop || document.body.scrollTop,
left: document.documentElement.scrollLeft || document.body.scrollLeft
};
if (rect.top !== this.container.offset().top) {
this.container.css({
top: rect.top
});
}
// Window resizes could change the scroll position, but won't trigger a
// scroll event on their own. Force a calculation of positioning.
this.onScroll(e, rect, offset);
}
destroy() {
// Unregister these event listeners, so these items are not lingering.
Toolshed.events.scroll.remove(this);
Toolshed.events.resize.remove(this);
if (this.container) {
this.container.remove();
}
}
};
Toolshed.Dock.TopDockContainer = class extends Toolshed.Dock.DockContainer {
/**
* Docking container specific handling of the docking container.
*/
initContainer() {
this.container.css({
position: 'fixed',
top: 0,
width: '100%',
boxSizing: 'border-box'
});
}
/**
* Determine if the content fits and is in the viewable window area.
*
* @param {Drupal.Toolshed.Geom.Rect} item
* Rect of the dockable content.
* @param {Drupal.Toolshed.Geom.Rect} win
* Viewable window space.
*
* @return {Boolean}
* TRUE if the docking content is outside the viewable window.
*/
isDocking(item, win) {
// eslint-disable-line class-methods-use-this
const cnt = item.getContainerRect();
let top = Math.floor(item.placeholder.offset().top + item.config.offset);
if (item.config.offset < 0) {
top += item.placeholder.height();
}
return top < win.top && cnt.bottom > win.top && item.elem.outerHeight() < cnt.getHeight();
}
};
/**
* A dockable item that goes into a dock container.
*/
Toolshed.Dock.DockItem = class {
/**
* Create a new instance of a dockable item.
*
* @param {jQuery} $elem
* The element that is being docked within this docking container.
* @param {jQuery} $bounds
* The DOM element that is used to determine the bounds of when
* this item is being docked.
* @param {Object} settings
* Settings that control how this item behaves while docking and
* undocking from a dock container.
*/
constructor($elem, $bounds, settings) {
this.elem = $elem;
this.bounds = $bounds;
this.config = settings;
this.elem.addClass('tsdock-item');
this.isDocked = false;
// Apply animation settings, or use the defaults if they are provided.
if (this.config.animate) {
this.mode = this.config.animate.type || 'slide';
}
this.init();
}
/**
* NULL function, meant to be a placeholder for edges that might
* need to have custom initialization.
*/
init() {
// Create a new placeholder, that will keep track of the space
// used by the docked element, while it's being docked to the container.
this.placeholder = this.elem.wrap('<div class="tsdock__placeholder"/>').parent();
this.placeholder.css({
position: this.elem.css('position')
});
this.height = this.elem.outerHeight();
// If available, try to track the size of the docked element
// and make updates to the docking system if dimensions change.
if (this.config.trackMutations && MutationObserver) {
this.observer = new MutationObserver(this._mutated.bind(this));
this.observer.observe(this.elem[0], {
attributes: true,
childList: true,
subtree: true,
characterData: true
});
}
}
/**
* Mutation event listener. Will be registered by relevant docker types
* and trigger when the docking element is modified in the appropriate ways.
*/
_mutations() {
// Disable mutation events while we process the current docking information.
this.observer.disconnect();
// In most cases we only care if the height has changed.
const height = this.elem.outerHeight();
if (this.height !== height) {
this.height = height || 0;
if (this.placeholder) {
this.placeholder.height(height);
}
const win = new Toolshed.Geom.Rect(Toolshed.winRect);
const scrollPos = document.documentElement.scrollTop || document.body.scrollTop;
this.scroll(scrollPos, win);
}
this.observer.observe(this.elem[0], {
attributes: true,
childList: true,
subtree: true,
characterData: true
});
}
getContainerRect() {
const {
top,
left
} = this.bounds.offset();
return new Toolshed.Geom.Rect(top, left, top + this.bounds.outerHeight(), left + this.bounds.outerWidth());
}
/**
* Turn on docking for this instance.
*
* This should make the element dock to the respective edge and set the
* correct behaviors for items when they are docked.
*
* @param {jQuery} addTo
* Element to add the docked item into.
*/
activateDock(addTo) {
if (!this.isDocked) {
this.isDocked = true;
this.placeholder.height(this.height);
addTo.append(this.elem);
this.elem.addClass('tsdock-item--docked');
this.elem.trigger('ToolshedDocking.docked');
}
}
/**
* Turn docking off for this docked item.
*/
deactivateDock() {
if (this.isDocked) {
this.isDocked = false;
this.placeholder.append(this.elem);
this.elem.removeClass('tsdock-item--docked');
// Reset the placeholder to size according to the placeholder.
this.placeholder.css({
height: ''
});
this.elem.trigger('ToolshedDocking.undocked');
}
}
destroy() {
if (this.observer) this.observer.disconnect();
this.deactivateDock();
if (this.placeholder) {
this.elem.unwrap('.tsdock__placeholder');
}
}
};
Toolshed.Dock.containers = {
TOP: new Toolshed.Dock.TopDockContainer()
};
})(jQuery, Drupal.Toolshed);
//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRG9jay5qcyIsIm5hbWVzIjpbIiQiLCJUb29sc2hlZCIsIkRvY2siLCJjcmVhdGVJdGVtIiwiJGVsZW0iLCIkYm91bmRzIiwic2V0dGluZ3MiLCJjb25maWciLCJlZGdlIiwib2Zmc2V0IiwiZGV0ZWN0T3B0cyIsIm1hdGNoIiwib3B0UmVnZXgiLCJlbENsYXNzZXMiLCJhdHRyIiwiZXhlYyIsImRvY2tlciIsIkRvY2tJdGVtIiwiYWRkRG9ja2VyIiwidG9VcHBlckNhc2UiLCJpdGVtIiwiY29udGFpbmVycyIsImFkZEl0ZW0iLCJEb2NrQ29udGFpbmVyIiwiY29uc3RydWN0b3IiLCJhY3RpdmUiLCJjb250YWluZXIiLCJpdGVtcyIsImlzQWN0aXZlIiwiZG9ja1RvIiwicHVzaCIsImluaXQiLCJyZW1vdmVJdGVtIiwiZmlsdGVyIiwiY21wIiwibGVuZ3RoIiwiaGlkZSIsImFwcGVuZFRvIiwiaW5pdENvbnRhaW5lciIsImV2ZW50cyIsInNjcm9sbCIsImFkZCIsInJlc2l6ZSIsIm9uUmVzaXplIiwiRXZlbnQiLCJ3aW5SZWN0Iiwib25TY3JvbGwiLCJlIiwid2luIiwidmlld2FibGUiLCJHZW9tIiwiUmVjdCIsImxlZnQiLCJ0b3AiLCJmb3JFYWNoIiwiaXNEb2NrZWQiLCJpc0RvY2tpbmciLCJkZWFjdGl2YXRlRG9jayIsImFjdGl2YXRlRG9jayIsInJlY3QiLCJkb2N1bWVudCIsImRvY3VtZW50RWxlbWVudCIsInNjcm9sbFRvcCIsImJvZHkiLCJzY3JvbGxMZWZ0IiwiY3NzIiwiZGVzdHJveSIsInJlbW92ZSIsIlRvcERvY2tDb250YWluZXIiLCJwb3NpdGlvbiIsIndpZHRoIiwiYm94U2l6aW5nIiwiY250IiwiZ2V0Q29udGFpbmVyUmVjdCIsIk1hdGgiLCJmbG9vciIsInBsYWNlaG9sZGVyIiwiaGVpZ2h0IiwiYm90dG9tIiwiZWxlbSIsIm91dGVySGVpZ2h0IiwiZ2V0SGVpZ2h0IiwiYm91bmRzIiwiYWRkQ2xhc3MiLCJhbmltYXRlIiwibW9kZSIsInR5cGUiLCJ3cmFwIiwicGFyZW50IiwidHJhY2tNdXRhdGlvbnMiLCJNdXRhdGlvbk9ic2VydmVyIiwib2JzZXJ2ZXIiLCJfbXV0YXRlZCIsImJpbmQiLCJvYnNlcnZlIiwiYXR0cmlidXRlcyIsImNoaWxkTGlzdCIsInN1YnRyZWUiLCJjaGFyYWN0ZXJEYXRhIiwiX211dGF0aW9ucyIsImRpc2Nvbm5lY3QiLCJzY3JvbGxQb3MiLCJvdXRlcldpZHRoIiwiYWRkVG8iLCJhcHBlbmQiLCJ0cmlnZ2VyIiwicmVtb3ZlQ2xhc3MiLCJ1bndyYXAiLCJUT1AiLCJqUXVlcnkiLCJEcnVwYWwiXSwic291cmNlcyI6WyJEb2NrLmVzNi5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKiBlc2xpbnQgbm8tYml0d2lzZTogW1wiZXJyb3JcIiwgeyBcImFsbG93XCI6IFtcIl5cIl0gfV0gKi9cbigoJCwgVG9vbHNoZWQpID0+IHtcbiAgLyoqXG4gICAqIERlZmluZSB0aGUgbmFtZXNwYWNlIGZvciBkZWZpbmluZyBkb2NraW5nIGxpYnJhcmllcyAmIHRvb2xzLlxuICAgKi9cbiAgVG9vbHNoZWQuRG9jayA9IHtcbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgbmV3IGluc3RhbmNlIG9mIGEgZG9ja2VyIGZvciB0aGUgZWRnZSBhbmQgcGFyc2VzXG4gICAgICogb3B0aW9ucyBmcm9tIENTUyBjbGFzcyBhdHRyaWJ1dGVzLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtqUXVlcnl9ICRlbGVtXG4gICAgICogICBIVE1MIGVsZW1lbnQgdGhhdCBpcyBiZWluZyBkb2NrZWQuXG4gICAgICogQHBhcmFtIHtqUXVlcnl9ICRib3VuZHNcbiAgICAgKiAgIEhUTUwgZWxlbWVudCB3aGljaCBkZWZpbmVzIHRoZSBib3VuZHMuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHNldHRpbmdzXG4gICAgICogICBPYmplY3QgY29udGFpbmluZyB0aGUgZG9ja2VyIHNldHRpbmdzLlxuICAgICAqICAge1xuICAgICAqICAgICBlZGdlOiB7c3RyaW5nfSBbJ3RvcCd8J2xlZnQnfCdib3R0b20nfCdyaWdodCddLFxuICAgICAqICAgICBvZmZzZXQ6IHtpbnR9IDBcbiAgICAgKiAgICAgY29sbGFwc2libGU6IHtib29sfSBmYWxzZSxcbiAgICAgKiAgICAgdHJhY2tNdXRhdGlvbnM6IHtib29sfSBmYWxzZSxcbiAgICAgKiAgICAgYW5pbWF0ZToge09iamVjdHxib29sfSB7XG4gICAgICogICAgICAgdHlwZToge3N0cmluZ30gW3NsaWRlXSxcbiAgICAgKiAgICAgICAvLyBBbmltYXRpb24gd2lsbCBsYXN0IGZvciAyMDAgbWlsbGlzZWNvbmRzLlxuICAgICAqICAgICAgIGR1cmF0aW9uOiB7aW50fSAyMDAsXG4gICAgICogICAgICAgLy8gQW5pbWF0aW9uIHN0YXJ0cyBhZnRlciAyNTAlIG9mIHRoZSBlbGVtZW50IGRpbWVuc2lvbi5cbiAgICAgKiAgICAgICAvLyBUaGlzIHZhbHVlIGlzIGlnbm9yZWQgb2Ygbm8gYW5pbWF0YWJsZSBvcHRpb25zIGFyZSBlbmFibGVkLlxuICAgICAqICAgICAgIC8vIE5PVEU6IGNhbiBiZSBhbHNvIGJlIGEgY29uc3RhbnQgcGl4ZWwgdmFsdWUuXG4gICAgICogICAgIH1cbiAgICAgKiAgIH1cbiAgICAgKi9cbiAgICBjcmVhdGVJdGVtKCRlbGVtLCAkYm91bmRzLCBzZXR0aW5ncyA9IHt9KSB7XG4gICAgICBjb25zdCBjb25maWcgPSB7IGVkZ2U6ICdUT1AnLCBvZmZzZXQ6IDAgfTtcblxuICAgICAgLypcbiAgICAgICAqIERldGVybWluZSB0aGUgc2V0IG9mIGFjdGl2ZSBkb2NrZXIgc2V0dGluZ3MgYnkgcGFyc2luZyBDU1MgY2xhc3NcbiAgICAgICAqIGluZm9ybWF0aW9uLiBPcHRpb25zIGFyZSBjbGFzc2VzIHRoYXQgc3RhcnQgd2l0aCBcInRzZG9jay1vcHQte3tvcHRpb259fVwiXG4gICAgICAgKiBvciBcInRzZG9jay1lZGdlLVt0b3B8bGVmdHxib3R0b218cmlnaHRdXCIuXG4gICAgICAgKlxuICAgICAgICogT3B0aW9ucyBjYW4gb25seSBnZXQgYWN0aXZhdGVkIGhlcmUsIGFuZCB3aWxsIGdldCBhcHBsaWVkIHdpdGggdGhlXG4gICAgICAgKiBjdXJyZW50IGRlZmF1bHRzIGZvciB0aGF0IG9wdGlvbi4gRm9yIGluc3RhbmNlLCBcInRzZG9jay1vcHQtc3RpY2t5XCJcbiAgICAgICAqIHdpbGwgbWFrZSB0aGUgZG9ja2VyLCBzdGlja3kgdXNpbmcgdGhlIGRlZmF1bHQgYW5pbWF0aW9uIGNvbmZpZ3VyYXRpb25zLlxuICAgICAgICovXG4gICAgICBpZiAoIXNldHRpbmdzIHx8IHNldHRpbmdzLmRldGVjdE9wdHMpIHtcbiAgICAgICAgbGV0IG1hdGNoID0gbnVsbDtcbiAgICAgICAgY29uc3Qgb3B0UmVnZXggPSAvKD86XnxcXHMpdHNkb2NrLS0ob3B0fGVkZ2UpLShbLVxcd10rKSg/Olxcc3wkKS9nO1xuICAgICAgICBjb25zdCBlbENsYXNzZXMgPSAkZWxlbS5hdHRyKCdjbGFzcycpO1xuXG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25kLWFzc2lnblxuICAgICAgICB3aGlsZSAoKG1hdGNoID0gb3B0UmVnZXguZXhlYyhlbENsYXNzZXMpKSAhPT0gbnVsbCkge1xuICAgICAgICAgIGlmIChtYXRjaFsxXSA9PT0gJ29wdCcpIHtcbiAgICAgICAgICAgIGNvbmZpZ1ttYXRjaFsyXV0gPSB0cnVlO1xuICAgICAgICAgIH1cbiAgICAgICAgICBlbHNlIGlmIChtYXRjaFsxXSA9PT0gJ2VkZ2UnKSB7XG4gICAgICAgICAgICBbLCwgY29uZmlnLmVkZ2VdID0gbWF0Y2g7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8vIEJ1aWxkIHRoZSBkb2NrZXIgbm93IHRoYXQgYWxsIHNldHRpbmdzIGhhdmUgYmVlbiBhcHBsaWVkIHRvIGl0LlxuICAgICAgY29uc3QgZG9ja2VyID0gbmV3IFRvb2xzaGVkLkRvY2suRG9ja0l0ZW0oJGVsZW0sICRib3VuZHMsIHsgLi4uY29uZmlnLCAuLi5zZXR0aW5ncyB9KTtcbiAgICAgIFRvb2xzaGVkLkRvY2suYWRkRG9ja2VyKGNvbmZpZy5lZGdlLnRvVXBwZXJDYXNlKCkgfHwgJ1RPUCcsIGRvY2tlcik7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEFkZCBkb2NrZXIgaXRlbXMgaW50byBhIGRvY2tlZCBjb250YWluZXIuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gZWRnZVxuICAgICAqICAgVGhlIGVkZ2UgdG8gYWRkIHRoZSBkb2NraW5nIGNvbnRlbnQgdG8uXG4gICAgICogQHBhcmFtIHtEcnVwYWwuVG9vbHNoZWQuRG9jay5Eb2NrSXRlbX0gaXRlbVxuICAgICAqICAgVGhlIGRvY2thYmxlIGl0ZW0gdG8gcGxhY2UgaW50byB0aGUgY29udGFpbmVyLlxuICAgICAqL1xuICAgIGFkZERvY2tlcihlZGdlLCBpdGVtKSB7XG4gICAgICBpZiAoVG9vbHNoZWQuRG9jay5jb250YWluZXJzW2VkZ2VdKSB7XG4gICAgICAgIFRvb2xzaGVkLkRvY2suY29udGFpbmVyc1tlZGdlXS5hZGRJdGVtKGl0ZW0pO1xuICAgICAgfVxuICAgIH0sXG4gIH07XG5cbiAgLyoqXG4gICAqIENvbnRhaW5lcnMgZm9yIGhvbGRpbmcgaXRlbXMgdGhhdCBhcmUgZG9ja2VkIHRvIHRoZW0uIERvY2tDb250YWluZXJzXG4gICAqIHdpbGwgbGlzdGVuIHRvIFdpbmRvdyBldmVudHMgYW5kIG1hbmFnZSB0aGUgaXRlbXMgdGhhdCB0aGV5IHdyYXAuXG4gICAqL1xuICBUb29sc2hlZC5Eb2NrLkRvY2tDb250YWluZXIgPSBjbGFzcyB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICB0aGlzLmFjdGl2ZSA9IGZhbHNlO1xuICAgICAgdGhpcy5jb250YWluZXIgPSBudWxsO1xuICAgICAgdGhpcy5pdGVtcyA9IFtdO1xuICAgIH1cblxuICAgIGlzQWN0aXZlKCkge1xuICAgICAgcmV0dXJuIHRoaXMuYWN0aXZlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFkZCBhIG5ldyBkb2NraW5nIGl0ZW0gdG8gdGhpcyBkb2NraW5nIGNvbnRhaW5lci5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7RHJ1cGFsLlRvb2xzaGVkLkRvY2suRG9ja0l0ZW19IGl0ZW1cbiAgICAgKiAgIFRoZSBEb2NrSXRlbSB0byBhZGQgdG8gdGhpcyBjb250YWluZXIuXG4gICAgICovXG4gICAgYWRkSXRlbShpdGVtKSB7XG4gICAgICBpdGVtLmRvY2tUbyA9IHRoaXM7XG4gICAgICB0aGlzLml0ZW1zLnB1c2goaXRlbSk7XG5cbiAgICAgIC8vIERlZmVyIGJ1aWxkaW5nIGFuZCBsaXN0ZW5pbmcgdG8gZXZlbnRzIHVudGlsIGEgZG9ja2FibGUgaXRlbSBpcyBhZGRlZC5cbiAgICAgIGlmICghdGhpcy5hY3RpdmUpIHtcbiAgICAgICAgdGhpcy5pbml0KCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlIHRoZSBEb2NrSXRlbSBmcm9tIHRoaXMgY29udGFpbmVyLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtEcnVwYWwuVG9vbHNoZWQuRG9jay5Eb2NrSXRlbX0gaXRlbVxuICAgICAqICAgVGhlIERvY2tJdGVtIHRvIGZpbmQgYW5kIHJlbW92ZSBmcm9tIHRoZSBjb250YWluZXIuXG4gICAgICovXG4gICAgcmVtb3ZlSXRlbShpdGVtKSB7XG4gICAgICB0aGlzLml0ZW1zID0gdGhpcy5pdGVtcy5maWx0ZXIoKGNtcCkgPT4gY21wICE9PSBpdGVtKTtcbiAgICAgIGRlbGV0ZSBpdGVtLmRvY2tUbztcblxuICAgICAgaWYgKCF0aGlzLml0ZW1zLmxlbmd0aCAmJiB0aGlzLmNvbnRhaW5lcikge1xuICAgICAgICB0aGlzLmNvbnRhaW5lci5oaWRlKCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVnaXN0ZXIgZXZlbnRzIHRoYXQgbWF5IG1ha2UgY2hhbmdlcyB0byBkb2NraW5nLCBhbmQgaW5pdCBwb3NpdGlvbmluZy5cbiAgICAgKi9cbiAgICBpbml0KCkge1xuICAgICAgdGhpcy5jb250YWluZXIgPSAkKCc8ZGl2IGNsYXNzPVwidHNkb2NrLWNvbnRhaW5lclwiLz4nKS5hcHBlbmRUbygkKCdib2R5JykpO1xuICAgICAgdGhpcy5pbml0Q29udGFpbmVyKCk7XG4gICAgICB0aGlzLmFjdGl2ZSA9IHRydWU7XG5cbiAgICAgIFRvb2xzaGVkLmV2ZW50cy5zY3JvbGwuYWRkKHRoaXMpO1xuICAgICAgVG9vbHNoZWQuZXZlbnRzLnJlc2l6ZS5hZGQodGhpcyk7XG5cbiAgICAgIC8vIEluaXRpYWxpemUgdGhlIHBvc2l0aW9uaW5nIG9mIHRoZSBkb2NrLlxuICAgICAgdGhpcy5vblJlc2l6ZShuZXcgRXZlbnQoJ3Jlc2l6ZScpLCBUb29sc2hlZC53aW5SZWN0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBFdmVudCBoYW5kbGVyIGZvciB0aGUgd2luZG93IHNjcm9sbCBjaGFuZ2UgZXZlbnRzLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtFdmVudH0gZVxuICAgICAqICAgVGhlIHNjcm9sbCBldmVudCBvYmplY3QgZm9yIHRoaXMgZXZlbnQuXG4gICAgICogQHBhcmFtIHtEcnVwYWwuVG9vbHNoZWQuR2VvbS5SZWN0fSB3aW5cbiAgICAgKiAgIFRoZSBjdXJyZW50IGJvdW5kcyBvZiB0aGUgd2luZG93LlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBzY3JvbGxcbiAgICAgKiAgIE9iamVjdCBjb250YWluaW5nIGEgdG9wIGFuZCBsZWZ0IGl0ZW0gdG8gcmVwcmVzZW50IHRoZSBjdXJyZW50XG4gICAgICogICBzY3JvbGwgb2Zmc2V0cyBvZiB0aGUgZG9jdW1lbnQgaW4gcmVsYXRpb24gdG8gdGhlIHdpbmRvdy5cbiAgICAgKi9cbiAgICBvblNjcm9sbChlLCB3aW4sIHNjcm9sbCkge1xuICAgICAgY29uc3Qgdmlld2FibGUgPSBuZXcgVG9vbHNoZWQuR2VvbS5SZWN0KHdpbik7XG4gICAgICB2aWV3YWJsZS5vZmZzZXQoc2Nyb2xsLmxlZnQsIHNjcm9sbC50b3ApO1xuXG4gICAgICB0aGlzLml0ZW1zLmZvckVhY2goKGl0ZW0pID0+IHtcbiAgICAgICAgaWYgKGl0ZW0uaXNEb2NrZWQgXiB0aGlzLmlzRG9ja2luZyhpdGVtLCB2aWV3YWJsZSkpIHtcbiAgICAgICAgICByZXR1cm4gaXRlbS5pc0RvY2tlZCA/IGl0ZW0uZGVhY3RpdmF0ZURvY2soKSA6IGl0ZW0uYWN0aXZhdGVEb2NrKHRoaXMuY29udGFpbmVyKTtcbiAgICAgICAgfVxuICAgICAgfSwgdGhpcyk7XG4gICAgfVxuXG4gICAgb25SZXNpemUoZSwgcmVjdCkge1xuICAgICAgY29uc3Qgb2Zmc2V0ID0ge1xuICAgICAgICB0b3A6IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zY3JvbGxUb3AgfHwgZG9jdW1lbnQuYm9keS5zY3JvbGxUb3AsXG4gICAgICAgIGxlZnQ6IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zY3JvbGxMZWZ0IHx8IGRvY3VtZW50LmJvZHkuc2Nyb2xsTGVmdCxcbiAgICAgIH07XG5cbiAgICAgIGlmIChyZWN0LnRvcCAhPT0gdGhpcy5jb250YWluZXIub2Zmc2V0KCkudG9wKSB7XG4gICAgICAgIHRoaXMuY29udGFpbmVyLmNzcyh7IHRvcDogcmVjdC50b3AgfSk7XG4gICAgICB9XG5cbiAgICAgIC8vIFdpbmRvdyByZXNpemVzIGNvdWxkIGNoYW5nZSB0aGUgc2Nyb2xsIHBvc2l0aW9uLCBidXQgd29uJ3QgdHJpZ2dlciBhXG4gICAgICAvLyBzY3JvbGwgZXZlbnQgb24gdGhlaXIgb3duLiBGb3JjZSBhIGNhbGN1bGF0aW9uIG9mIHBvc2l0aW9uaW5nLlxuICAgICAgdGhpcy5vblNjcm9sbChlLCByZWN0LCBvZmZzZXQpO1xuICAgIH1cblxuICAgIGRlc3Ryb3koKSB7XG4gICAgICAvLyBVbnJlZ2lzdGVyIHRoZXNlIGV2ZW50IGxpc3RlbmVycywgc28gdGhlc2UgaXRlbXMgYXJlIG5vdCBsaW5nZXJpbmcuXG4gICAgICBUb29sc2hlZC5ldmVudHMuc2Nyb2xsLnJlbW92ZSh0aGlzKTtcbiAgICAgIFRvb2xzaGVkLmV2ZW50cy5yZXNpemUucmVtb3ZlKHRoaXMpO1xuXG4gICAgICBpZiAodGhpcy5jb250YWluZXIpIHtcbiAgICAgICAgdGhpcy5jb250YWluZXIucmVtb3ZlKCk7XG4gICAgICB9XG4gICAgfVxuICB9O1xuXG4gIFRvb2xzaGVkLkRvY2suVG9wRG9ja0NvbnRhaW5lciA9IGNsYXNzIGV4dGVuZHMgVG9vbHNoZWQuRG9jay5Eb2NrQ29udGFpbmVyIHtcbiAgICAvKipcbiAgICAgKiBEb2NraW5nIGNvbnRhaW5lciBzcGVjaWZpYyBoYW5kbGluZyBvZiB0aGUgZG9ja2luZyBjb250YWluZXIuXG4gICAgICovXG4gICAgaW5pdENvbnRhaW5lcigpIHtcbiAgICAgIHRoaXMuY29udGFpbmVyLmNzcyh7XG4gICAgICAgIHBvc2l0aW9uOiAnZml4ZWQnLFxuICAgICAgICB0b3A6IDAsXG4gICAgICAgIHdpZHRoOiAnMTAwJScsXG4gICAgICAgIGJveFNpemluZzogJ2JvcmRlci1ib3gnLFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRGV0ZXJtaW5lIGlmIHRoZSBjb250ZW50IGZpdHMgYW5kIGlzIGluIHRoZSB2aWV3YWJsZSB3aW5kb3cgYXJlYS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7RHJ1cGFsLlRvb2xzaGVkLkdlb20uUmVjdH0gaXRlbVxuICAgICAqICAgUmVjdCBvZiB0aGUgZG9ja2FibGUgY29udGVudC5cbiAgICAgKiBAcGFyYW0ge0RydXBhbC5Ub29sc2hlZC5HZW9tLlJlY3R9IHdpblxuICAgICAqICAgVmlld2FibGUgd2luZG93IHNwYWNlLlxuICAgICAqXG4gICAgICogQHJldHVybiB7Qm9vbGVhbn1cbiAgICAgKiAgIFRSVUUgaWYgdGhlIGRvY2tpbmcgY29udGVudCBpcyBvdXRzaWRlIHRoZSB2aWV3YWJsZSB3aW5kb3cuXG4gICAgICovXG4gICAgaXNEb2NraW5nKGl0ZW0sIHdpbikgeyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIGNsYXNzLW1ldGhvZHMtdXNlLXRoaXNcbiAgICAgIGNvbnN0IGNudCA9IGl0ZW0uZ2V0Q29udGFpbmVyUmVjdCgpO1xuICAgICAgbGV0IHRvcCA9IE1hdGguZmxvb3IoaXRlbS5wbGFjZWhvbGRlci5vZmZzZXQoKS50b3AgKyBpdGVtLmNvbmZpZy5vZmZzZXQpO1xuXG4gICAgICBpZiAoaXRlbS5jb25maWcub2Zmc2V0IDwgMCkge1xuICAgICAgICB0b3AgKz0gaXRlbS5wbGFjZWhvbGRlci5oZWlnaHQoKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuICh0b3AgPCB3aW4udG9wKVxuICAgICAgICAmJiAoY250LmJvdHRvbSA+IHdpbi50b3ApXG4gICAgICAgICYmIGl0ZW0uZWxlbS5vdXRlckhlaWdodCgpIDwgY250LmdldEhlaWdodCgpO1xuICAgIH1cbiAgfTtcblxuICAvKipcbiAgICogQSBkb2NrYWJsZSBpdGVtIHRoYXQgZ29lcyBpbnRvIGEgZG9jayBjb250YWluZXIuXG4gICAqL1xuICBUb29sc2hlZC5Eb2NrLkRvY2tJdGVtID0gY2xhc3Mge1xuICAgIC8qKlxuICAgICAqIENyZWF0ZSBhIG5ldyBpbnN0YW5jZSBvZiBhIGRvY2thYmxlIGl0ZW0uXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge2pRdWVyeX0gJGVsZW1cbiAgICAgKiAgIFRoZSBlbGVtZW50IHRoYXQgaXMgYmVpbmcgZG9ja2VkIHdpdGhpbiB0aGlzIGRvY2tpbmcgY29udGFpbmVyLlxuICAgICAqIEBwYXJhbSB7alF1ZXJ5fSAkYm91bmRzXG4gICAgICogICBUaGUgRE9NIGVsZW1lbnQgdGhhdCBpcyB1c2VkIHRvIGRldGVybWluZSB0aGUgYm91bmRzIG9mIHdoZW5cbiAgICAgKiAgIHRoaXMgaXRlbSBpcyBiZWluZyBkb2NrZWQuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHNldHRpbmdzXG4gICAgICogICBTZXR0aW5ncyB0aGF0IGNvbnRyb2wgaG93IHRoaXMgaXRlbSBiZWhhdmVzIHdoaWxlIGRvY2tpbmcgYW5kXG4gICAgICogICB1bmRvY2tpbmcgZnJvbSBhIGRvY2sgY29udGFpbmVyLlxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKCRlbGVtLCAkYm91bmRzLCBzZXR0aW5ncykge1xuICAgICAgdGhpcy5lbGVtID0gJGVsZW07XG4gICAgICB0aGlzLmJvdW5kcyA9ICRib3VuZHM7XG4gICAgICB0aGlzLmNvbmZpZyA9IHNldHRpbmdzO1xuXG4gICAgICB0aGlzLmVsZW0uYWRkQ2xhc3MoJ3RzZG9jay1pdGVtJyk7XG4gICAgICB0aGlzLmlzRG9ja2VkID0gZmFsc2U7XG5cbiAgICAgIC8vIEFwcGx5IGFuaW1hdGlvbiBzZXR0aW5ncywgb3IgdXNlIHRoZSBkZWZhdWx0cyBpZiB0aGV5IGFyZSBwcm92aWRlZC5cbiAgICAgIGlmICh0aGlzLmNvbmZpZy5hbmltYXRlKSB7XG4gICAgICAgIHRoaXMubW9kZSA9IHRoaXMuY29uZmlnLmFuaW1hdGUudHlwZSB8fCAnc2xpZGUnO1xuICAgICAgfVxuXG4gICAgICB0aGlzLmluaXQoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBOVUxMIGZ1bmN0aW9uLCBtZWFudCB0byBiZSBhIHBsYWNlaG9sZGVyIGZvciBlZGdlcyB0aGF0IG1pZ2h0XG4gICAgICogbmVlZCB0byBoYXZlIGN1c3RvbSBpbml0aWFsaXphdGlvbi5cbiAgICAgKi9cbiAgICBpbml0KCkge1xuICAgICAgLy8gQ3JlYXRlIGEgbmV3IHBsYWNlaG9sZGVyLCB0aGF0IHdpbGwga2VlcCB0cmFjayBvZiB0aGUgc3BhY2VcbiAgICAgIC8vIHVzZWQgYnkgdGhlIGRvY2tlZCBlbGVtZW50LCB3aGlsZSBpdCdzIGJlaW5nIGRvY2tlZCB0byB0aGUgY29udGFpbmVyLlxuICAgICAgdGhpcy5wbGFjZWhvbGRlciA9IHRoaXMuZWxlbS53cmFwKCc8ZGl2IGNsYXNzPVwidHNkb2NrX19wbGFjZWhvbGRlclwiLz4nKS5wYXJlbnQoKTtcbiAgICAgIHRoaXMucGxhY2Vob2xkZXIuY3NzKHsgcG9zaXRpb246IHRoaXMuZWxlbS5jc3MoJ3Bvc2l0aW9uJykgfSk7XG4gICAgICB0aGlzLmhlaWdodCA9IHRoaXMuZWxlbS5vdXRlckhlaWdodCgpO1xuXG4gICAgICAvLyBJZiBhdmFpbGFibGUsIHRyeSB0byB0cmFjayB0aGUgc2l6ZSBvZiB0aGUgZG9ja2VkIGVsZW1lbnRcbiAgICAgIC8vIGFuZCBtYWtlIHVwZGF0ZXMgdG8gdGhlIGRvY2tpbmcgc3lzdGVtIGlmIGRpbWVuc2lvbnMgY2hhbmdlLlxuICAgICAgaWYgKHRoaXMuY29uZmlnLnRyYWNrTXV0YXRpb25zICYmIE11dGF0aW9uT2JzZXJ2ZXIpIHtcbiAgICAgICAgdGhpcy5vYnNlcnZlciA9IG5ldyBNdXRhdGlvbk9ic2VydmVyKHRoaXMuX211dGF0ZWQuYmluZCh0aGlzKSk7XG4gICAgICAgIHRoaXMub2JzZXJ2ZXIub2JzZXJ2ZSh0aGlzLmVsZW1bMF0sIHtcbiAgICAgICAgICBhdHRyaWJ1dGVzOiB0cnVlLFxuICAgICAgICAgIGNoaWxkTGlzdDogdHJ1ZSxcbiAgICAgICAgICBzdWJ0cmVlOiB0cnVlLFxuICAgICAgICAgIGNoYXJhY3RlckRhdGE6IHRydWUsXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE11dGF0aW9uIGV2ZW50IGxpc3RlbmVyLiBXaWxsIGJlIHJlZ2lzdGVyZWQgYnkgcmVsZXZhbnQgZG9ja2VyIHR5cGVzXG4gICAgICogYW5kIHRyaWdnZXIgd2hlbiB0aGUgZG9ja2luZyBlbGVtZW50IGlzIG1vZGlmaWVkIGluIHRoZSBhcHByb3ByaWF0ZSB3YXlzLlxuICAgICAqL1xuICAgIF9tdXRhdGlvbnMoKSB7XG4gICAgICAvLyBEaXNhYmxlIG11dGF0aW9uIGV2ZW50cyB3aGlsZSB3ZSBwcm9jZXNzIHRoZSBjdXJyZW50IGRvY2tpbmcgaW5mb3JtYXRpb24uXG4gICAgICB0aGlzLm9ic2VydmVyLmRpc2Nvbm5lY3QoKTtcblxuICAgICAgLy8gSW4gbW9zdCBjYXNlcyB3ZSBvbmx5IGNhcmUgaWYgdGhlIGhlaWdodCBoYXMgY2hhbmdlZC5cbiAgICAgIGNvbnN0IGhlaWdodCA9IHRoaXMuZWxlbS5vdXRlckhlaWdodCgpO1xuICAgICAgaWYgKHRoaXMuaGVpZ2h0ICE9PSBoZWlnaHQpIHtcbiAgICAgICAgdGhpcy5oZWlnaHQgPSBoZWlnaHQgfHwgMDtcblxuICAgICAgICBpZiAodGhpcy5wbGFjZWhvbGRlcikge1xuICAgICAgICAgIHRoaXMucGxhY2Vob2xkZXIuaGVpZ2h0KGhlaWdodCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB3aW4gPSBuZXcgVG9vbHNoZWQuR2VvbS5SZWN0KFRvb2xzaGVkLndpblJlY3QpO1xuICAgICAgICBjb25zdCBzY3JvbGxQb3MgPSAoZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnNjcm9sbFRvcCB8fCBkb2N1bWVudC5ib2R5LnNjcm9sbFRvcCk7XG4gICAgICAgIHRoaXMuc2Nyb2xsKHNjcm9sbFBvcywgd2luKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5vYnNlcnZlci5vYnNlcnZlKHRoaXMuZWxlbVswXSwge1xuICAgICAgICBhdHRyaWJ1dGVzOiB0cnVlLFxuICAgICAgICBjaGlsZExpc3Q6IHRydWUsXG4gICAgICAgIHN1YnRyZWU6IHRydWUsXG4gICAgICAgIGNoYXJhY3RlckRhdGE6IHRydWUsXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBnZXRDb250YWluZXJSZWN0KCkge1xuICAgICAgY29uc3QgeyB0b3AsIGxlZnQgfSA9IHRoaXMuYm91bmRzLm9mZnNldCgpO1xuICAgICAgcmV0dXJuIG5ldyBUb29sc2hlZC5HZW9tLlJlY3QoXG4gICAgICAgIHRvcCxcbiAgICAgICAgbGVmdCxcbiAgICAgICAgdG9wICsgdGhpcy5ib3VuZHMub3V0ZXJIZWlnaHQoKSxcbiAgICAgICAgbGVmdCArIHRoaXMuYm91bmRzLm91dGVyV2lkdGgoKSxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVHVybiBvbiBkb2NraW5nIGZvciB0aGlzIGluc3RhbmNlLlxuICAgICAqXG4gICAgICogVGhpcyBzaG91bGQgbWFrZSB0aGUgZWxlbWVudCBkb2NrIHRvIHRoZSByZXNwZWN0aXZlIGVkZ2UgYW5kIHNldCB0aGVcbiAgICAgKiBjb3JyZWN0IGJlaGF2aW9ycyBmb3IgaXRlbXMgd2hlbiB0aGV5IGFyZSBkb2NrZWQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge2pRdWVyeX0gYWRkVG9cbiAgICAgKiAgIEVsZW1lbnQgdG8gYWRkIHRoZSBkb2NrZWQgaXRlbSBpbnRvLlxuICAgICAqL1xuICAgIGFjdGl2YXRlRG9jayhhZGRUbykge1xuICAgICAgaWYgKCF0aGlzLmlzRG9ja2VkKSB7XG4gICAgICAgIHRoaXMuaXNEb2NrZWQgPSB0cnVlO1xuICAgICAgICB0aGlzLnBsYWNlaG9sZGVyLmhlaWdodCh0aGlzLmhlaWdodCk7XG5cbiAgICAgICAgYWRkVG8uYXBwZW5kKHRoaXMuZWxlbSk7XG4gICAgICAgIHRoaXMuZWxlbS5hZGRDbGFzcygndHNkb2NrLWl0ZW0tLWRvY2tlZCcpO1xuICAgICAgICB0aGlzLmVsZW0udHJpZ2dlcignVG9vbHNoZWREb2NraW5nLmRvY2tlZCcpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFR1cm4gZG9ja2luZyBvZmYgZm9yIHRoaXMgZG9ja2VkIGl0ZW0uXG4gICAgICovXG4gICAgZGVhY3RpdmF0ZURvY2soKSB7XG4gICAgICBpZiAodGhpcy5pc0RvY2tlZCkge1xuICAgICAgICB0aGlzLmlzRG9ja2VkID0gZmFsc2U7XG4gICAgICAgIHRoaXMucGxhY2Vob2xkZXIuYXBwZW5kKHRoaXMuZWxlbSk7XG4gICAgICAgIHRoaXMuZWxlbS5yZW1vdmVDbGFzcygndHNkb2NrLWl0ZW0tLWRvY2tlZCcpO1xuXG4gICAgICAgIC8vIFJlc2V0IHRoZSBwbGFjZWhvbGRlciB0byBzaXplIGFjY29yZGluZyB0byB0aGUgcGxhY2Vob2xkZXIuXG4gICAgICAgIHRoaXMucGxhY2Vob2xkZXIuY3NzKHsgaGVpZ2h0OiAnJyB9KTtcbiAgICAgICAgdGhpcy5lbGVtLnRyaWdnZXIoJ1Rvb2xzaGVkRG9ja2luZy51bmRvY2tlZCcpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGRlc3Ryb3koKSB7XG4gICAgICBpZiAodGhpcy5vYnNlcnZlcikgdGhpcy5vYnNlcnZlci5kaXNjb25uZWN0KCk7XG4gICAgICB0aGlzLmRlYWN0aXZhdGVEb2NrKCk7XG5cbiAgICAgIGlmICh0aGlzLnBsYWNlaG9sZGVyKSB7XG4gICAgICAgIHRoaXMuZWxlbS51bndyYXAoJy50c2RvY2tfX3BsYWNlaG9sZGVyJyk7XG4gICAgICB9XG4gICAgfVxuICB9O1xuXG4gIFRvb2xzaGVkLkRvY2suY29udGFpbmVycyA9IHtcbiAgICBUT1A6IG5ldyBUb29sc2hlZC5Eb2NrLlRvcERvY2tDb250YWluZXIoKSxcbiAgfTtcbn0pKGpRdWVyeSwgRHJ1cGFsLlRvb2xzaGVkKTtcbiJdLCJtYXBwaW5ncyI6Ijs7QUFBQTtBQUNBLENBQUMsQ0FBQ0EsQ0FBQyxFQUFFQyxRQUFRLEtBQUs7RUFDaEI7QUFDRjtBQUNBO0VBQ0VBLFFBQVEsQ0FBQ0MsSUFBSSxHQUFHO0lBQ2Q7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7SUFDSUMsVUFBVSxDQUFDQyxLQUFLLEVBQUVDLE9BQU8sRUFBRUMsUUFBUSxHQUFHLENBQUMsQ0FBQyxFQUFFO01BQ3hDLE1BQU1DLE1BQU0sR0FBRztRQUFFQyxJQUFJLEVBQUUsS0FBSztRQUFFQyxNQUFNLEVBQUU7TUFBRSxDQUFDOztNQUV6QztBQUNOO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7TUFDTSxJQUFJLENBQUNILFFBQVEsSUFBSUEsUUFBUSxDQUFDSSxVQUFVLEVBQUU7UUFDcEMsSUFBSUMsS0FBSyxHQUFHLElBQUk7UUFDaEIsTUFBTUMsUUFBUSxHQUFHLDhDQUE4QztRQUMvRCxNQUFNQyxTQUFTLEdBQUdULEtBQUssQ0FBQ1UsSUFBSSxDQUFDLE9BQU8sQ0FBQzs7UUFFckM7UUFDQSxPQUFPLENBQUNILEtBQUssR0FBR0MsUUFBUSxDQUFDRyxJQUFJLENBQUNGLFNBQVMsQ0FBQyxNQUFNLElBQUksRUFBRTtVQUNsRCxJQUFJRixLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssS0FBSyxFQUFFO1lBQ3RCSixNQUFNLENBQUNJLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUk7VUFDekIsQ0FBQyxNQUNJLElBQUlBLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxNQUFNLEVBQUU7WUFDNUIsSUFBSUosTUFBTSxDQUFDQyxJQUFJLENBQUMsR0FBR0csS0FBSztVQUMxQjtRQUNGO01BQ0Y7O01BRUE7TUFDQSxNQUFNSyxNQUFNLEdBQUcsSUFBSWYsUUFBUSxDQUFDQyxJQUFJLENBQUNlLFFBQVEsQ0FBQ2IsS0FBSyxFQUFFQyxPQUFPLEVBQUU7UUFBRSxHQUFHRSxNQUFNO1FBQUUsR0FBR0Q7TUFBUyxDQUFDLENBQUM7TUFDckZMLFFBQVEsQ0FBQ0MsSUFBSSxDQUFDZ0IsU0FBUyxDQUFDWCxNQUFNLENBQUNDLElBQUksQ0FBQ1csV0FBVyxFQUFFLElBQUksS0FBSyxFQUFFSCxNQUFNLENBQUM7SUFDckUsQ0FBQztJQUVEO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7SUFDSUUsU0FBUyxDQUFDVixJQUFJLEVBQUVZLElBQUksRUFBRTtNQUNwQixJQUFJbkIsUUFBUSxDQUFDQyxJQUFJLENBQUNtQixVQUFVLENBQUNiLElBQUksQ0FBQyxFQUFFO1FBQ2xDUCxRQUFRLENBQUNDLElBQUksQ0FBQ21CLFVBQVUsQ0FBQ2IsSUFBSSxDQUFDLENBQUNjLE9BQU8sQ0FBQ0YsSUFBSSxDQUFDO01BQzlDO0lBQ0Y7RUFDRixDQUFDOztFQUVEO0FBQ0Y7QUFDQTtBQUNBO0VBQ0VuQixRQUFRLENBQUNDLElBQUksQ0FBQ3FCLGFBQWEsR0FBRyxNQUFNO0lBQ2xDQyxXQUFXLEdBQUc7TUFDWixJQUFJLENBQUNDLE1BQU0sR0FBRyxLQUFLO01BQ25CLElBQUksQ0FBQ0MsU0FBUyxHQUFHLElBQUk7TUFDckIsSUFBSSxDQUFDQyxLQUFLLEdBQUcsRUFBRTtJQUNqQjtJQUVBQyxRQUFRLEdBQUc7TUFDVCxPQUFPLElBQUksQ0FBQ0gsTUFBTTtJQUNwQjs7SUFFQTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7SUFDSUgsT0FBTyxDQUFDRixJQUFJLEVBQUU7TUFDWkEsSUFBSSxDQUFDUyxNQUFNLEdBQUcsSUFBSTtNQUNsQixJQUFJLENBQUNGLEtBQUssQ0FBQ0csSUFBSSxDQUFDVixJQUFJLENBQUM7O01BRXJCO01BQ0EsSUFBSSxDQUFDLElBQUksQ0FBQ0ssTUFBTSxFQUFFO1FBQ2hCLElBQUksQ0FBQ00sSUFBSSxFQUFFO01BQ2I7SUFDRjs7SUFFQTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7SUFDSUMsVUFBVSxDQUFDWixJQUFJLEVBQUU7TUFDZixJQUFJLENBQUNPLEtBQUssR0FBRyxJQUFJLENBQUNBLEtBQUssQ0FBQ00sTUFBTSxDQUFFQyxHQUFHLElBQUtBLEdBQUcsS0FBS2QsSUFBSSxDQUFDO01BQ3JELE9BQU9BLElBQUksQ0FBQ1MsTUFBTTtNQUVsQixJQUFJLENBQUMsSUFBSSxDQUFDRixLQUFLLENBQUNRLE1BQU0sSUFBSSxJQUFJLENBQUNULFNBQVMsRUFBRTtRQUN4QyxJQUFJLENBQUNBLFNBQVMsQ0FBQ1UsSUFBSSxFQUFFO01BQ3ZCO0lBQ0Y7O0lBRUE7QUFDSjtBQUNBO0lBQ0lMLElBQUksR0FBRztNQUNMLElBQUksQ0FBQ0wsU0FBUyxHQUFHMUIsQ0FBQyxDQUFDLGlDQUFpQyxDQUFDLENBQUNxQyxRQUFRLENBQUNyQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUM7TUFDekUsSUFBSSxDQUFDc0MsYUFBYSxFQUFFO01BQ3BCLElBQUksQ0FBQ2IsTUFBTSxHQUFHLElBQUk7TUFFbEJ4QixRQUFRLENBQUNzQyxNQUFNLENBQUNDLE1BQU0sQ0FBQ0MsR0FBRyxDQUFDLElBQUksQ0FBQztNQUNoQ3hDLFFBQVEsQ0FBQ3NDLE1BQU0sQ0FBQ0csTUFBTSxDQUFDRCxHQUFHLENBQUMsSUFBSSxDQUFDOztNQUVoQztNQUNBLElBQUksQ0FBQ0UsUUFBUSxDQUFDLElBQUlDLEtBQUssQ0FBQyxRQUFRLENBQUMsRUFBRTNDLFFBQVEsQ0FBQzRDLE9BQU8sQ0FBQztJQUN0RDs7SUFFQTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0lBQ0lDLFFBQVEsQ0FBQ0MsQ0FBQyxFQUFFQyxHQUFHLEVBQUVSLE1BQU0sRUFBRTtNQUN2QixNQUFNUyxRQUFRLEdBQUcsSUFBSWhELFFBQVEsQ0FBQ2lELElBQUksQ0FBQ0MsSUFBSSxDQUFDSCxHQUFHLENBQUM7TUFDNUNDLFFBQVEsQ0FBQ3hDLE1BQU0sQ0FBQytCLE1BQU0sQ0FBQ1ksSUFBSSxFQUFFWixNQUFNLENBQUNhLEdBQUcsQ0FBQztNQUV4QyxJQUFJLENBQUMxQixLQUFLLENBQUMyQixPQUFPLENBQUVsQyxJQUFJLElBQUs7UUFDM0IsSUFBSUEsSUFBSSxDQUFDbUMsUUFBUSxHQUFHLElBQUksQ0FBQ0MsU0FBUyxDQUFDcEMsSUFBSSxFQUFFNkIsUUFBUSxDQUFDLEVBQUU7VUFDbEQsT0FBTzdCLElBQUksQ0FBQ21DLFFBQVEsR0FBR25DLElBQUksQ0FBQ3FDLGNBQWMsRUFBRSxHQUFHckMsSUFBSSxDQUFDc0MsWUFBWSxDQUFDLElBQUksQ0FBQ2hDLFNBQVMsQ0FBQztRQUNsRjtNQUNGLENBQUMsRUFBRSxJQUFJLENBQUM7SUFDVjtJQUVBaUIsUUFBUSxDQUFDSSxDQUFDLEVBQUVZLElBQUksRUFBRTtNQUNoQixNQUFNbEQsTUFBTSxHQUFHO1FBQ2I0QyxHQUFHLEVBQUVPLFFBQVEsQ0FBQ0MsZUFBZSxDQUFDQyxTQUFTLElBQUlGLFFBQVEsQ0FBQ0csSUFBSSxDQUFDRCxTQUFTO1FBQ2xFVixJQUFJLEVBQUVRLFFBQVEsQ0FBQ0MsZUFBZSxDQUFDRyxVQUFVLElBQUlKLFFBQVEsQ0FBQ0csSUFBSSxDQUFDQztNQUM3RCxDQUFDO01BRUQsSUFBSUwsSUFBSSxDQUFDTixHQUFHLEtBQUssSUFBSSxDQUFDM0IsU0FBUyxDQUFDakIsTUFBTSxFQUFFLENBQUM0QyxHQUFHLEVBQUU7UUFDNUMsSUFBSSxDQUFDM0IsU0FBUyxDQUFDdUMsR0FBRyxDQUFDO1VBQUVaLEdBQUcsRUFBRU0sSUFBSSxDQUFDTjtRQUFJLENBQUMsQ0FBQztNQUN2Qzs7TUFFQTtNQUNBO01BQ0EsSUFBSSxDQUFDUCxRQUFRLENBQUNDLENBQUMsRUFBRVksSUFBSSxFQUFFbEQsTUFBTSxDQUFDO0lBQ2hDO0lBRUF5RCxPQUFPLEdBQUc7TUFDUjtNQUNBakUsUUFBUSxDQUFDc0MsTUFBTSxDQUFDQyxNQUFNLENBQUMyQixNQUFNLENBQUMsSUFBSSxDQUFDO01BQ25DbEUsUUFBUSxDQUFDc0MsTUFBTSxDQUFDRyxNQUFNLENBQUN5QixNQUFNLENBQUMsSUFBSSxDQUFDO01BRW5DLElBQUksSUFBSSxDQUFDekMsU0FBUyxFQUFFO1FBQ2xCLElBQUksQ0FBQ0EsU0FBUyxDQUFDeUMsTUFBTSxFQUFFO01BQ3pCO0lBQ0Y7RUFDRixDQUFDO0VBRURsRSxRQUFRLENBQUNDLElBQUksQ0FBQ2tFLGdCQUFnQixHQUFHLGNBQWNuRSxRQUFRLENBQUNDLElBQUksQ0FBQ3FCLGFBQWEsQ0FBQztJQUN6RTtBQUNKO0FBQ0E7SUFDSWUsYUFBYSxHQUFHO01BQ2QsSUFBSSxDQUFDWixTQUFTLENBQUN1QyxHQUFHLENBQUM7UUFDakJJLFFBQVEsRUFBRSxPQUFPO1FBQ2pCaEIsR0FBRyxFQUFFLENBQUM7UUFDTmlCLEtBQUssRUFBRSxNQUFNO1FBQ2JDLFNBQVMsRUFBRTtNQUNiLENBQUMsQ0FBQztJQUNKOztJQUVBO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7SUFDSWYsU0FBUyxDQUFDcEMsSUFBSSxFQUFFNEIsR0FBRyxFQUFFO01BQUU7TUFDckIsTUFBTXdCLEdBQUcsR0FBR3BELElBQUksQ0FBQ3FELGdCQUFnQixFQUFFO01BQ25DLElBQUlwQixHQUFHLEdBQUdxQixJQUFJLENBQUNDLEtBQUssQ0FBQ3ZELElBQUksQ0FBQ3dELFdBQVcsQ0FBQ25FLE1BQU0sRUFBRSxDQUFDNEMsR0FBRyxHQUFHakMsSUFBSSxDQUFDYixNQUFNLENBQUNFLE1BQU0sQ0FBQztNQUV4RSxJQUFJVyxJQUFJLENBQUNiLE1BQU0sQ0FBQ0UsTUFBTSxHQUFHLENBQUMsRUFBRTtRQUMxQjRDLEdBQUcsSUFBSWpDLElBQUksQ0FBQ3dELFdBQVcsQ0FBQ0MsTUFBTSxFQUFFO01BQ2xDO01BRUEsT0FBUXhCLEdBQUcsR0FBR0wsR0FBRyxDQUFDSyxHQUFHLElBQ2ZtQixHQUFHLENBQUNNLE1BQU0sR0FBRzlCLEdBQUcsQ0FBQ0ssR0FBSSxJQUN0QmpDLElBQUksQ0FBQzJELElBQUksQ0FBQ0MsV0FBVyxFQUFFLEdBQUdSLEdBQUcsQ0FBQ1MsU0FBUyxFQUFFO0lBQ2hEO0VBQ0YsQ0FBQzs7RUFFRDtBQUNGO0FBQ0E7RUFDRWhGLFFBQVEsQ0FBQ0MsSUFBSSxDQUFDZSxRQUFRLEdBQUcsTUFBTTtJQUM3QjtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7SUFDSU8sV0FBVyxDQUFDcEIsS0FBSyxFQUFFQyxPQUFPLEVBQUVDLFFBQVEsRUFBRTtNQUNwQyxJQUFJLENBQUN5RSxJQUFJLEdBQUczRSxLQUFLO01BQ2pCLElBQUksQ0FBQzhFLE1BQU0sR0FBRzdFLE9BQU87TUFDckIsSUFBSSxDQUFDRSxNQUFNLEdBQUdELFFBQVE7TUFFdEIsSUFBSSxDQUFDeUUsSUFBSSxDQUFDSSxRQUFRLENBQUMsYUFBYSxDQUFDO01BQ2pDLElBQUksQ0FBQzVCLFFBQVEsR0FBRyxLQUFLOztNQUVyQjtNQUNBLElBQUksSUFBSSxDQUFDaEQsTUFBTSxDQUFDNkUsT0FBTyxFQUFFO1FBQ3ZCLElBQUksQ0FBQ0MsSUFBSSxHQUFHLElBQUksQ0FBQzlFLE1BQU0sQ0FBQzZFLE9BQU8sQ0FBQ0UsSUFBSSxJQUFJLE9BQU87TUFDakQ7TUFFQSxJQUFJLENBQUN2RCxJQUFJLEVBQUU7SUFDYjs7SUFFQTtBQUNKO0FBQ0E7QUFDQTtJQUNJQSxJQUFJLEdBQUc7TUFDTDtNQUNBO01BQ0EsSUFBSSxDQUFDNkMsV0FBVyxHQUFHLElBQUksQ0FBQ0csSUFBSSxDQUFDUSxJQUFJLENBQUMsb0NBQW9DLENBQUMsQ0FBQ0MsTUFBTSxFQUFFO01BQ2hGLElBQUksQ0FBQ1osV0FBVyxDQUFDWCxHQUFHLENBQUM7UUFBRUksUUFBUSxFQUFFLElBQUksQ0FBQ1UsSUFBSSxDQUFDZCxHQUFHLENBQUMsVUFBVTtNQUFFLENBQUMsQ0FBQztNQUM3RCxJQUFJLENBQUNZLE1BQU0sR0FBRyxJQUFJLENBQUNFLElBQUksQ0FBQ0MsV0FBVyxFQUFFOztNQUVyQztNQUNBO01BQ0EsSUFBSSxJQUFJLENBQUN6RSxNQUFNLENBQUNrRixjQUFjLElBQUlDLGdCQUFnQixFQUFFO1FBQ2xELElBQUksQ0FBQ0MsUUFBUSxHQUFHLElBQUlELGdCQUFnQixDQUFDLElBQUksQ0FBQ0UsUUFBUSxDQUFDQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDOUQsSUFBSSxDQUFDRixRQUFRLENBQUNHLE9BQU8sQ0FBQyxJQUFJLENBQUNmLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRTtVQUNsQ2dCLFVBQVUsRUFBRSxJQUFJO1VBQ2hCQyxTQUFTLEVBQUUsSUFBSTtVQUNmQyxPQUFPLEVBQUUsSUFBSTtVQUNiQyxhQUFhLEVBQUU7UUFDakIsQ0FBQyxDQUFDO01BQ0o7SUFDRjs7SUFFQTtBQUNKO0FBQ0E7QUFDQTtJQUNJQyxVQUFVLEdBQUc7TUFDWDtNQUNBLElBQUksQ0FBQ1IsUUFBUSxDQUFDUyxVQUFVLEVBQUU7O01BRTFCO01BQ0EsTUFBTXZCLE1BQU0sR0FBRyxJQUFJLENBQUNFLElBQUksQ0FBQ0MsV0FBVyxFQUFFO01BQ3RDLElBQUksSUFBSSxDQUFDSCxNQUFNLEtBQUtBLE1BQU0sRUFBRTtRQUMxQixJQUFJLENBQUNBLE1BQU0sR0FBR0EsTUFBTSxJQUFJLENBQUM7UUFFekIsSUFBSSxJQUFJLENBQUNELFdBQVcsRUFBRTtVQUNwQixJQUFJLENBQUNBLFdBQVcsQ0FBQ0MsTUFBTSxDQUFDQSxNQUFNLENBQUM7UUFDakM7UUFFQSxNQUFNN0IsR0FBRyxHQUFHLElBQUkvQyxRQUFRLENBQUNpRCxJQUFJLENBQUNDLElBQUksQ0FBQ2xELFFBQVEsQ0FBQzRDLE9BQU8sQ0FBQztRQUNwRCxNQUFNd0QsU0FBUyxHQUFJekMsUUFBUSxDQUFDQyxlQUFlLENBQUNDLFNBQVMsSUFBSUYsUUFBUSxDQUFDRyxJQUFJLENBQUNELFNBQVU7UUFDakYsSUFBSSxDQUFDdEIsTUFBTSxDQUFDNkQsU0FBUyxFQUFFckQsR0FBRyxDQUFDO01BQzdCO01BRUEsSUFBSSxDQUFDMkMsUUFBUSxDQUFDRyxPQUFPLENBQUMsSUFBSSxDQUFDZixJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUU7UUFDbENnQixVQUFVLEVBQUUsSUFBSTtRQUNoQkMsU0FBUyxFQUFFLElBQUk7UUFDZkMsT0FBTyxFQUFFLElBQUk7UUFDYkMsYUFBYSxFQUFFO01BQ2pCLENBQUMsQ0FBQztJQUNKO0lBRUF6QixnQkFBZ0IsR0FBRztNQUNqQixNQUFNO1FBQUVwQixHQUFHO1FBQUVEO01BQUssQ0FBQyxHQUFHLElBQUksQ0FBQzhCLE1BQU0sQ0FBQ3pFLE1BQU0sRUFBRTtNQUMxQyxPQUFPLElBQUlSLFFBQVEsQ0FBQ2lELElBQUksQ0FBQ0MsSUFBSSxDQUMzQkUsR0FBRyxFQUNIRCxJQUFJLEVBQ0pDLEdBQUcsR0FBRyxJQUFJLENBQUM2QixNQUFNLENBQUNGLFdBQVcsRUFBRSxFQUMvQjVCLElBQUksR0FBRyxJQUFJLENBQUM4QixNQUFNLENBQUNvQixVQUFVLEVBQUUsQ0FDaEM7SUFDSDs7SUFFQTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7SUFDSTVDLFlBQVksQ0FBQzZDLEtBQUssRUFBRTtNQUNsQixJQUFJLENBQUMsSUFBSSxDQUFDaEQsUUFBUSxFQUFFO1FBQ2xCLElBQUksQ0FBQ0EsUUFBUSxHQUFHLElBQUk7UUFDcEIsSUFBSSxDQUFDcUIsV0FBVyxDQUFDQyxNQUFNLENBQUMsSUFBSSxDQUFDQSxNQUFNLENBQUM7UUFFcEMwQixLQUFLLENBQUNDLE1BQU0sQ0FBQyxJQUFJLENBQUN6QixJQUFJLENBQUM7UUFDdkIsSUFBSSxDQUFDQSxJQUFJLENBQUNJLFFBQVEsQ0FBQyxxQkFBcUIsQ0FBQztRQUN6QyxJQUFJLENBQUNKLElBQUksQ0FBQzBCLE9BQU8sQ0FBQyx3QkFBd0IsQ0FBQztNQUM3QztJQUNGOztJQUVBO0FBQ0o7QUFDQTtJQUNJaEQsY0FBYyxHQUFHO01BQ2YsSUFBSSxJQUFJLENBQUNGLFFBQVEsRUFBRTtRQUNqQixJQUFJLENBQUNBLFFBQVEsR0FBRyxLQUFLO1FBQ3JCLElBQUksQ0FBQ3FCLFdBQVcsQ0FBQzRCLE1BQU0sQ0FBQyxJQUFJLENBQUN6QixJQUFJLENBQUM7UUFDbEMsSUFBSSxDQUFDQSxJQUFJLENBQUMyQixXQUFXLENBQUMscUJBQXFCLENBQUM7O1FBRTVDO1FBQ0EsSUFBSSxDQUFDOUIsV0FBVyxDQUFDWCxHQUFHLENBQUM7VUFBRVksTUFBTSxFQUFFO1FBQUcsQ0FBQyxDQUFDO1FBQ3BDLElBQUksQ0FBQ0UsSUFBSSxDQUFDMEIsT0FBTyxDQUFDLDBCQUEwQixDQUFDO01BQy9DO0lBQ0Y7SUFFQXZDLE9BQU8sR0FBRztNQUNSLElBQUksSUFBSSxDQUFDeUIsUUFBUSxFQUFFLElBQUksQ0FBQ0EsUUFBUSxDQUFDUyxVQUFVLEVBQUU7TUFDN0MsSUFBSSxDQUFDM0MsY0FBYyxFQUFFO01BRXJCLElBQUksSUFBSSxDQUFDbUIsV0FBVyxFQUFFO1FBQ3BCLElBQUksQ0FBQ0csSUFBSSxDQUFDNEIsTUFBTSxDQUFDLHNCQUFzQixDQUFDO01BQzFDO0lBQ0Y7RUFDRixDQUFDO0VBRUQxRyxRQUFRLENBQUNDLElBQUksQ0FBQ21CLFVBQVUsR0FBRztJQUN6QnVGLEdBQUcsRUFBRSxJQUFJM0csUUFBUSxDQUFDQyxJQUFJLENBQUNrRSxnQkFBZ0I7RUFDekMsQ0FBQztBQUNILENBQUMsRUFBRXlDLE1BQU0sRUFBRUMsTUFBTSxDQUFDN0csUUFBUSxDQUFDIn0=
