webglimpse
Version:
Webglimpse is a data visualization library for the web.
215 lines • 33.5 kB
JavaScript
/*
* Copyright (c) 2014, Metron, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import { Notification } from './notification';
export function initSplitContainer(container) {
const tilesResized = new Notification();
_initSplitContainer(container, tilesResized);
window.addEventListener('resize', function () {
tilesResized.fire();
});
tilesResized.fire();
return tilesResized;
}
function _initSplitContainer(container, tilesResized) {
let tileA = null;
let tileB = null;
let sep = null;
const children = container.childNodes;
for (let n = 0; n < children.length; n++) {
const child = children[n];
if (child.nodeType === 1 && child.classList) {
const element = child;
if (tileA == null) {
if (element.classList.contains('splitContainerNS') || element.classList.contains('splitContainerEW') || element.classList.contains('splitTile')) {
tileA = element;
}
}
else if (sep == null) {
if (element.classList.contains('splitSep')) {
sep = element;
}
}
else if (tileB == null) {
if (element.classList.contains('splitContainerNS') || element.classList.contains('splitContainerEW') || element.classList.contains('splitTile')) {
tileB = element;
}
}
else {
break;
}
}
}
if (tileA == null) {
throw new Error('Failed to init split-container: could not find first tile');
}
if (sep == null) {
throw new Error('Failed to init split-container: could not find separator');
}
if (tileB == null) {
throw new Error('Failed to init split-container: could not find second tile');
}
if (container.classList.contains('splitContainerNS')) {
_initSplitNS(container, tileA, sep, tileB, tilesResized);
}
else if (container.classList.contains('splitContainerEW')) {
_initSplitEW(container, tileA, sep, tileB, tilesResized);
}
if (tileA.classList.contains('splitContainerNS') || tileA.classList.contains('splitContainerEW')) {
_initSplitContainer(tileA, tilesResized);
}
if (tileB.classList.contains('splitContainerNS') || tileB.classList.contains('splitContainerEW')) {
_initSplitContainer(tileB, tilesResized);
}
}
function _initSplitNS(container, tileA, sep, tileB, tilesResized) {
sep.classList.add('splitSepNS');
sep.style.left = '0px';
sep.style.right = '0px';
tileA.style.left = '0px';
tileA.style.right = '0px';
tileB.style.left = '0px';
tileB.style.right = '0px';
const minHeightA = 1;
const minHeightB = 1;
let recentFracA = null;
function layoutTiles(prelimHeightA) {
const heightSep = sep.getBoundingClientRect().height;
const heightContainer = container.getBoundingClientRect().height;
const heightContent = heightContainer - heightSep;
if (recentFracA == null) {
recentFracA = tileA.getBoundingClientRect().height / heightContent;
}
const keepFracA = (prelimHeightA == null);
if (keepFracA) {
prelimHeightA = Math.round(recentFracA * heightContent);
}
const maxHeightA = heightContainer - heightSep - minHeightB;
const topA = 0;
const heightA = Math.max(minHeightA, Math.min(maxHeightA, prelimHeightA));
tileA.style.top = topA + 'px';
tileA.style.height = heightA + 'px';
const topSep = topA + heightA;
sep.style.top = topSep + 'px';
sep.style.height = heightSep + 'px';
const topB = topSep + heightSep;
const heightB = Math.max(minHeightB, heightContainer - topB);
tileB.style.top = topB + 'px';
tileB.style.height = heightB + 'px';
if (!keepFracA && heightContent >= heightA && heightContent >= (minHeightA + minHeightB)) {
recentFracA = heightA / heightContent;
}
}
let sepGrab = null;
sep.addEventListener('mousedown', function (ev) {
if (ev.button === 0) {
sepGrab = ev.clientY - tileA.getBoundingClientRect().top - tileA.getBoundingClientRect().height;
ev.preventDefault();
}
});
// During a DRAG we want all move events, even ones that occur outside the canvas -- so subscribe to WINDOW's mousemove
window.addEventListener('mousemove', function (ev) {
if (sepGrab != null) {
layoutTiles(ev.clientY - tileA.getBoundingClientRect().top - sepGrab);
tilesResized.fire();
}
});
// The window always gets the mouse-up event at the end of a drag -- even if it occurs outside the browser window
window.addEventListener('mouseup', function (ev) {
if (sepGrab != null && ev.button === 0) {
layoutTiles(ev.clientY - tileA.getBoundingClientRect().top - sepGrab);
tilesResized.fire();
sepGrab = null;
}
});
tilesResized.on(layoutTiles);
}
function _initSplitEW(container, tileA, sep, tileB, tilesResized) {
sep.classList.add('splitSepEW');
sep.style.top = '0px';
sep.style.bottom = '0px';
tileA.style.top = '0px';
tileA.style.bottom = '0px';
tileB.style.top = '0px';
tileB.style.bottom = '0px';
const minWidthA = 1;
const minWidthB = 1;
let recentFracA = null;
function layoutTiles(prelimWidthA) {
const widthSep = sep.getBoundingClientRect().width;
const widthContainer = container.getBoundingClientRect().width;
const widthContent = widthContainer - widthSep;
if (recentFracA == null) {
recentFracA = tileA.getBoundingClientRect().width / widthContent;
}
const keepFracA = (prelimWidthA == null);
if (keepFracA) {
prelimWidthA = Math.round(recentFracA * widthContent);
}
const maxWidthA = widthContainer - widthSep - minWidthB;
const leftA = 0;
const widthA = Math.max(minWidthA, Math.min(maxWidthA, prelimWidthA));
tileA.style.left = leftA + 'px';
tileA.style.width = widthA + 'px';
const leftSep = leftA + widthA;
sep.style.left = leftSep + 'px';
sep.style.width = widthSep + 'px';
const leftB = leftSep + widthSep;
const widthB = Math.max(minWidthB, widthContainer - leftB);
tileB.style.left = leftB + 'px';
tileB.style.width = widthB + 'px';
if (!keepFracA && widthContent >= widthA && widthContent >= (minWidthA + minWidthB)) {
recentFracA = widthA / widthContent;
}
}
let sepGrab = null;
sep.addEventListener('mousedown', function (ev) {
if (ev.button === 0) {
sepGrab = ev.clientX - tileA.getBoundingClientRect().left - tileA.getBoundingClientRect().width;
ev.preventDefault();
}
});
// During a DRAG we want all move events, even ones that occur outside the canvas -- so subscribe to WINDOW's mousemove
window.addEventListener('mousemove', function (ev) {
if (sepGrab != null) {
layoutTiles(ev.clientX - tileA.getBoundingClientRect().left - sepGrab);
tilesResized.fire();
}
});
// The window always gets the mouse-up event at the end of a drag -- even if it occurs outside the browser window
window.addEventListener('mouseup', function (ev) {
if (sepGrab != null && ev.button === 0) {
layoutTiles(ev.clientX - tileA.getBoundingClientRect().left - sepGrab);
tilesResized.fire();
sepGrab = null;
}
});
tilesResized.on(layoutTiles);
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3BsaXQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvd2ViZ2xpbXBzZS91dGlsL3NwbGl0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBNEJHO0FBQ0gsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRTlDLE1BQU0sVUFBVSxrQkFBa0IsQ0FBQyxTQUFzQjtJQUNyRCxNQUFNLFlBQVksR0FBRyxJQUFJLFlBQVksRUFBRSxDQUFDO0lBRXhDLG1CQUFtQixDQUFDLFNBQVMsRUFBRSxZQUFZLENBQUMsQ0FBQztJQUU3QyxNQUFNLENBQUMsZ0JBQWdCLENBQUMsUUFBUSxFQUFFO1FBQzlCLFlBQVksQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUN4QixDQUFDLENBQUMsQ0FBQztJQUNILFlBQVksQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUVwQixPQUFPLFlBQVksQ0FBQztBQUN4QixDQUFDO0FBS0QsU0FBUyxtQkFBbUIsQ0FBQyxTQUFzQixFQUFFLFlBQTBCO0lBQzNFLElBQUksS0FBSyxHQUFnQixJQUFJLENBQUM7SUFDOUIsSUFBSSxLQUFLLEdBQWdCLElBQUksQ0FBQztJQUM5QixJQUFJLEdBQUcsR0FBZ0IsSUFBSSxDQUFDO0lBQzVCLE1BQU0sUUFBUSxHQUFHLFNBQVMsQ0FBQyxVQUFVLENBQUM7SUFDdEMsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLFFBQVEsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUU7UUFDdEMsTUFBTSxLQUFLLEdBQUcsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzFCLElBQUksS0FBSyxDQUFDLFFBQVEsS0FBSyxDQUFDLElBQVUsS0FBTSxDQUFDLFNBQVMsRUFBRTtZQUNoRCxNQUFNLE9BQU8sR0FBZ0IsS0FBSyxDQUFDO1lBQ25DLElBQUksS0FBSyxJQUFJLElBQUksRUFB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LElBQUksSUFBSSxJQUFJLEVBQUUsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFO1lBQ3BDLFdBQVcsQ0FBQyxFQUFFLENBQUMsT0FBTyxHQUFHLEtBQUssQ0FBQyxxQkFBcUIsRUFBRSxDQUFDLElBQUksR0FBRyxPQUFPLENBQUMsQ0FBQztZQUN2RSxZQUFZLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDcEIsT0FBTyxHQUFHLElBQUksQ0FBQztTQUNsQjtJQUNMLENBQUMsQ0FBQyxDQUFDO0lBRUgsWUFBWSxDQUFDLEVBQUUsQ0FBQyxXQUFXLENBQUMsQ0FBQztBQUNqQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLypcclxuICogQ29weXJpZ2h0IChjKSAyMDE0LCBNZXRyb24sIEluYy5cclxuICogQWxsIHJpZ2h0cyByZXNlcnZlZC5cclxuICpcclxuICogUmVkaXN0cmlidXRpb24gYW5kIHVzZSBpbiBzb3VyY2UgYW5kIGJpbmFyeSBmb3Jtcywgd2l0aCBvciB3aXRob3V0IG1vZGlmaWNhdGlvbixcclxuICogYXJlIHBlcm1pdHRlZCBwcm92aWRlZCB0aGF0IHRoZSBmb2xsb3dpbmcgY29uZGl0aW9ucyBhcmUgbWV0OlxyXG4gKlxyXG4gKiAxLiBSZWRpc3RyaWJ1dGlvbnMgb2Ygc291cmNlIGNvZGUgbXVzdCByZXRhaW4gdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UsIHRoaXNcclxuICogICAgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIuXHJcbiAqXHJcbiAqIDIuIFJlZGlzdHJpYnV0aW9ucyBpbiBiaW5hcnkgZm9ybSBtdXN0IHJlcHJvZHVjZSB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSxcclxuICogICAgdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lciBpbiB0aGUgZG9jdW1lbnRhdGlvblxyXG4gKiAgICBhbmQvb3Igb3RoZXIgbWF0ZXJpYWxzIHByb3ZpZGVkIHdpdGggdGhlIGRpc3RyaWJ1dGlvbi5cclxuICpcclxuICogMy4gTmVpdGhlciB0aGUgbmFtZSBvZiB0aGUgY29weXJpZ2h0IGhvbGRlciBub3IgdGhlIG5hbWVzIG9mIGl0cyBjb250cmlidXRvcnNcclxuICogICAgbWF5IGJlIHVzZWQgdG8gZW5kb3JzZSBvciBwcm9tb3RlIHByb2R1Y3RzIGRlcml2ZWQgZnJvbSB0aGlzIHNvZnR3YXJlIHdpdGhvdXRcclxuICogICAgc3BlY2lmaWMgcHJpb3Igd3JpdHRlbiBwZXJtaXNzaW9uLlxyXG4gKlxyXG4gKiBUSElTIFNPRlRXQVJFIElTIFBST1ZJREVEIEJZIFRIRSBDT1BZUklHSFQgSE9MREVSUyBBTkQgQ09OVFJJQlVUT1JTIFwiQVMgSVNcIiBBTkRcclxuICogQU5ZIEVYUFJFU1MgT1IgSU1QTElFRCBXQVJSQU5USUVTLCBJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgVEhFIElNUExJRURcclxuICogV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFkgQU5EIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFSRVxyXG4gKiBESVNDTEFJTUVELiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUgQ09QWVJJR0hUIEhPTERFUiBPUiBDT05UUklCVVRPUlMgQkUgTElBQkxFIEZPUlxyXG4gKiBBTlkgRElSRUNULCBJTkRJUkVDVCwgSU5DSURFTlRBTCwgU1BFQ0lBTCwgRVhFTVBMQVJZLCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVNcclxuICogKElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBQUk9DVVJFTUVOVCBPRiBTVUJTVElUVVRFIEdPT0RTIE9SIFNFUlZJQ0VTO1xyXG4gKiBMT1NTIE9GIFVTRSwgREFUQSwgT1IgUFJPRklUUzsgT1IgQlVTSU5FU1MgSU5URVJSVVBUSU9OKSBIT1dFVkVSIENBVVNFRCBBTkQgT05cclxuICogQU5ZIFRIRU9SWSBPRiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQ09OVFJBQ1QsIFNUUklDVCBMSUFCSUxJVFksIE9SIFRPUlRcclxuICogKElOQ0xVRElORyBORUdMSUdFTkNFIE9SIE9USEVSV0lTRSkgQVJJU0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFIE9GIFRISVNcclxuICogU09GVFdBUkUsIEVWRU4gSUYgQURWSVNFRCBPRiBUSEUgUE9TU0lCSUxJVFkgT0YgU1VDSCBEQU1BR0UuXHJcbiAqL1xyXG5pbXBvcnQgeyBOb3RpZmljYXRpb24gfSBmcm9tICcuL25vdGlmaWNhdGlvbic7XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gaW5pdFNwbGl0Q29udGFpbmVyKGNvbnRhaW5lcjogSFRNTEVsZW1lbnQpOiBOb3RpZmljYXRpb24ge1xyXG4gICAgY29uc3QgdGlsZXNSZXNpemVkID0gbmV3IE5vdGlmaWNhdGlvbigpO1xyXG5cclxuICAgIF9pbml0U3BsaXRDb250YWluZXIoY29udGFpbmVyLCB0aWxlc1Jlc2l6ZWQpO1xyXG5cclxuICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdyZXNpemUnLCBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgdGlsZXNSZXNpemVkLmZpcmUoKTtcclxuICAgIH0pO1xyXG4gICAgdGlsZXNSZXNpemVkLmZpcmUoKTtcclxuXHJcbiAgICByZXR1cm4gdGlsZXNSZXNpemVkO1xyXG59XHJcblxyXG5cclxuXHJcblxyXG5mdW5jdGlvbiBfaW5pdFNwbGl0Q29udGFpbmVyKGNvbnRhaW5lcjogSFRNTEVsZW1lbnQsIHRpbGVzUmVzaXplZDogTm90aWZpY2F0aW9uKSB7XHJcbiAgICBsZXQgdGlsZUE6IEhUTUxFbGVtZW50ID0gbnVsbDtcclxuICAgIGxldCB0aWxlQjogSFRNTEVsZW1lbnQgPSBudWxsO1xyXG4gICAgbGV0IHNlcDogSFRNTEVsZW1lbnQgPSBudWxsO1xyXG4gICAgY29uc3QgY2hpbGRyZW4gPSBjb250YWluZXIuY2hpbGROb2RlcztcclxuICAgIGZvciAobGV0IG4gPSAwOyBuIDwgY2hpbGRyZW4ubGVuZ3RoOyBuKyspIHtcclxuICAgICAgICBjb25zdCBjaGlsZCA9IGNoaWxkcmVuW25dO1xyXG4gICAgICAgIGlmIChjaGlsZC5ub2RlVHlwZSA9PT0gMSAmJiAoPGFueT5jaGlsZCkuY2xhc3NMaXN0KSB7XHJcbiAgICAgICAgICAgIGNvbnN0IGVsZW1lbnQgPSA8SFRNTEVsZW1lbnQ+Y2hpbGQ7XHJcbiAgICAgICAgICAgIGlmICh0aWxlQSA9PSBudWxsKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAoZWxlbWVudC5jbGFzc0xpc3QuY29udGFpbnMoJ3NwbGl0Q29udGFpbmVyTlMnKSB8fCBlbGVtZW50LmNsYXNzTGlzdC5jb250YWlucygnc3BsaXRDb250YWluZXJFVycpIHx8IGVsZW1lbnQuY2xhc3NMaXN0LmNvbnRhaW5zKCdzcGxpdFRpbGUnKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHRpbGVBID0gZWxlbWVudDtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBlbHNlIGlmIChzZXAgPT0gbnVsbCkge1xyXG4gICAgICAgICAgICAgICAgaWYgKGVsZW1lbnQuY2xhc3NMaXN0LmNvbnRhaW5zKCdzcGxpdFNlcCcpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgc2VwID0gZWxlbWVudDtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBlbHNlIGlmICh0aWxlQiA9PSBudWxsKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAoZWxlbWVudC5jbGFzc0xpc3QuY29udGFpbnMoJ3NwbGl0Q29udGFpbmVyTlMnKSB8fCBlbGVtZW50LmNsYXNzTGlzdC5jb250YWlucygnc3BsaXRDb250YWluZXJFVycpIHx8IGVsZW1lbnQuY2xhc3NMaXN0LmNvbnRhaW5zKCdzcGxpdFRpbGUnKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHRpbGVCID0gZWxlbWVudDtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG4gICAgaWYgKHRpbGVBID09IG51bGwpIHtcclxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZhaWxlZCB0byBpbml0IHNwbGl0LWNvbnRhaW5lcjogY291bGQgbm90IGZpbmQgZmlyc3QgdGlsZScpO1xyXG4gICAgfVxyXG4gICAgaWYgKHNlcCA9PSBudWxsKSB7XHJcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdGYWlsZWQgdG8gaW5pdCBzcGxpdC1jb250YWluZXI6IGNvdWxkIG5vdCBmaW5kIHNlcGFyYXRvcicpO1xyXG4gICAgfVxyXG4gICAgaWYgKHRpbGVCID09IG51bGwpIHtcclxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZhaWxlZCB0byBpbml0IHNwbGl0LWNvbnRhaW5lcjogY291bGQgbm90IGZpbmQgc2Vjb25kIHRpbGUnKTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAoY29udGFpbmVyLmNsYXNzTGlzdC5jb250YWlucygnc3BsaXRDb250YWluZXJOUycpKSB7XHJcbiAgICAgICAgX2luaXRTcGxpdE5TKGNvbnRhaW5lciwgdGlsZUEsIHNlcCwgdGlsZUIsIHRpbGVzUmVzaXplZCk7XHJcbiAgICB9XHJcbiAgICBlbHNlIGlmIChjb250YWluZXIuY2xhc3NMaXN0LmNvbnRhaW5zKCdzcGxpdENvbnRhaW5lckVXJykpIHtcclxuICAgICAgICBfaW5pdFNwbGl0RVcoY29udGFpbmVyLCB0aWxlQSwgc2VwLCB0aWxlQiwgdGlsZXNSZXNpemVkKTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodGlsZUEuY2xhc3NMaXN0LmNvbnRhaW5zKCdzcGxpdENvbnRhaW5lck5TJykgfHwgdGlsZUEuY2xhc3NMaXN0LmNvbnRhaW5zKCdzcGxpdENvbnRhaW5lckVXJykpIHtcclxuICAgICAgICBfaW5pdFNwbGl0Q29udGFpbmVyKHRpbGVBLCB0aWxlc1Jlc2l6ZWQpO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICh0aWxlQi5jbGFzc0xpc3QuY29udGFpbnMoJ3NwbGl0Q29udGFpbmVyTlMnKSB8fCB0aWxlQi5jbGFzc0xpc3QuY29udGFpbnMoJ3NwbGl0Q29udGFpbmVyRVcnKSkge1xyXG4gICAgICAgIF9pbml0U3BsaXRDb250YWluZXIodGlsZUIsIHRpbGVzUmVzaXplZCk7XHJcbiAgICB9XHJcbn1cclxuXHJcblxyXG5cclxuXHJcbmZ1bmN0aW9uIF9pbml0U3BsaXROUyhjb250YWluZXI6IEhUTUxFbGVtZW50LCB0aWxlQTogSFRNTEVsZW1lbnQsIHNlcDogSFRNTEVsZW1lbnQsIHRpbGVCOiBIVE1MRWxlbWVudCwgdGlsZXNSZXNpemVkOiBOb3RpZmljYXRpb24pOiB2b2lkIHtcclxuICAgIHNlcC5jbGFzc0xpc3QuYWRkKCdzcGxpdFNlcE5TJyk7XHJcbiAgICBzZXAuc3R5bGUubGVmdCA9ICcwcHgnO1xyXG4gICAgc2VwLnN0eWxlLnJpZ2h0ID0gJzBweCc7XHJcbiAgICB0aWxlQS5zdHlsZS5sZWZ0ID0gJzBweCc7XHJcbiAgICB0aWxlQS5zdHlsZS5yaWdodCA9ICcwcHgnO1xyXG4gICAgdGlsZUIuc3R5bGUubGVmdCA9ICcwcHgnO1xyXG4gICAgdGlsZUIuc3R5bGUucmlnaHQgPSAnMHB4JztcclxuXHJcbiAgICBjb25zdCBtaW5IZWlnaHRBID0gMTtcclxuICAgIGNvbnN0IG1pbkhlaWdodEIgPSAxO1xyXG4gICAgbGV0IHJlY2VudEZyYWNBOiBudW1iZXIgPSBudWxsO1xyXG5cclxuICAgIGZ1bmN0aW9uIGxheW91dFRpbGVzKHByZWxpbUhlaWdodEE/OiBudW1iZXIpIHtcclxuICAgICAgICBjb25zdCBoZWlnaHRTZXAgPSBzZXAuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkuaGVpZ2h0O1xyXG4gICAgICAgIGNvbnN0IGhlaWdodENvbnRhaW5lciA9IGNvbnRhaW5lci5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5oZWlnaHQ7XHJcbiAgICAgICAgY29uc3QgaGVpZ2h0Q29udGVudCA9IGhlaWdodENvbnRhaW5lciAtIGhlaWdodFNlcDtcclxuICAgICAgICBpZiAocmVjZW50RnJhY0EgPT0gbnVsbCkge1xyXG4gICAgICAgICAgICByZWNlbnRGcmFjQSA9IHRpbGVBLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLmhlaWdodCAvIGhlaWdodENvbnRlbnQ7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjb25zdCBrZWVwRnJhY0EgPSAocHJlbGltSGVpZ2h0QSA9PSBudWxsKTtcclxuICAgICAgICBpZiAoa2VlcEZyYWNBKSB7XHJcbiAgICAgICAgICAgIHByZWxpbUhlaWdodEEgPSBNYXRoLnJvdW5kKHJlY2VudEZyYWNBICogaGVpZ2h0Q29udGVudCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjb25zdCBtYXhIZWlnaHRBID0gaGVpZ2h0Q29udGFpbmVyIC0gaGVpZ2h0U2VwIC0gbWluSGVpZ2h0QjtcclxuXHJcbiAgICAgICAgY29uc3QgdG9wQSA9IDA7XHJcbiAgICAgICAgY29uc3QgaGVpZ2h0QSA9IE1hdGgubWF4KG1pbkhlaWdodEEsIE1hdGgubWluKG1heEhlaWdodEEsIHByZWxpbUhlaWdodEEpKTtcclxuICAgICAgICB0aWxlQS5zdHlsZS50b3AgPSB0b3BBICsgJ3B4JztcclxuICAgICAgICB0aWxlQS5zdHlsZS5oZWlnaHQgPSBoZWlnaHRBICsgJ3B4JztcclxuXHJcbiAgICAgICAgY29uc3QgdG9wU2VwID0gdG9wQSArIGhlaWdodEE7XHJcbiAgICAgICAgc2VwLnN0eWxlLnRvcCA9IHRvcFNlcCArICdweCc7XHJcbiAgICAgICAgc2VwLnN0eWxlLmhlaWdodCA9IGhlaWdodFNlcCArICdweCc7XHJcblxyXG4gICAgICAgIGNvbnN0IHRvcEIgPSB0b3BTZXAgKyBoZWlnaHRTZXA7XHJcbiAgICAgICAgY29uc3QgaGVpZ2h0QiA9IE1hdGgubWF4KG1pbkhlaWdodEIsIGhlaWdodENvbnRhaW5lciAtIHRvcEIpO1xyXG4gICAgICAgIHRpbGVCLnN0eWxlLnRvcCA9IHRvcEIgKyAncHgnO1xyXG4gICAgICAgIHRpbGVCLnN0eWxlLmhlaWdodCA9IGhlaWdodEIgKyAncHgnO1xyXG5cclxuICAgICAgICBpZiAoIWtlZXBGcmFjQSAmJiBoZWlnaHRDb250ZW50ID49IGhlaWdodEEgJiYgaGVpZ2h0Q29udGVudCA+PSAobWluSGVpZ2h0QSArIG1pbkhlaWdodEIpKSB7XHJcbiAgICAgICAgICAgIHJlY2VudEZyYWNBID0gaGVpZ2h0QSAvIGhlaWdodENvbnRlbnQ7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGxldCBzZXBHcmFiOiBudW1iZXIgPSBudWxsO1xyXG5cclxuICAgIHNlcC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZWRvd24nLCBmdW5jdGlvbiAoZXY6IE1vdXNlRXZlbnQpIHtcclxuICAgICAgICBpZiAoZXYuYnV0dG9uID09PSAwKSB7XHJcbiAgICAgICAgICAgIHNlcEdyYWIgPSBldi5jbGllbnRZIC0gdGlsZUEuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkudG9wIC0gdGlsZUEuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkuaGVpZ2h0O1xyXG4gICAgICAgICAgICBldi5wcmV2ZW50RGVmYXVsdCgpO1xyXG4gICAgICAgIH1cclxuICAgIH0pO1xyXG5cclxuICAgIC8vIER1cmluZyBhIERSQUcgd2Ugd2FudCBhbGwgbW92ZSBldmVudHMsIGV2ZW4gb25lcyB0aGF0IG9jY3VyIG91dHNpZGUgdGhlIGNhbnZhcyAtLSBzbyBzdWJzY3JpYmUgdG8gV0lORE9XJ3MgbW91c2Vtb3ZlXHJcbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJywgZnVuY3Rpb24gKGV2OiBNb3VzZUV2ZW50KSB7XHJcbiAgICAgICAgaWYgKHNlcEdyYWIgIT0gbnVsbCkge1xyXG4gICAgICAgICAgICBsYXlvdXRUaWxlcyhldi5jbGllbnRZIC0gdGlsZUEuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkudG9wIC0gc2VwR3JhYik7XHJcbiAgICAgICAgICAgIHRpbGVzUmVzaXplZC5maXJlKCk7XHJcbiAgICAgICAgfVxyXG4gICAgfSk7XHJcblxyXG4gICAgLy8gVGhlIHdpbmRvdyBhbHdheXMgZ2V0cyB0aGUgbW91c2UtdXAgZXZlbnQgYXQgdGhlIGVuZCBvZiBhIGRyYWcgLS0gZXZlbiBpZiBpdCBvY2N1cnMgb3V0c2lkZSB0aGUgYnJvd3NlciB3aW5kb3dcclxuICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgZnVuY3Rpb24gKGV2OiBNb3VzZUV2ZW50KSB7XHJcbiAgICAgICAgaWYgKHNlcEdyYWIgIT0gbnVsbCAmJiBldi5idXR0b24gPT09IDApIHtcclxuICAgICAgICAgICAgbGF5b3V0VGlsZXMoZXYuY2xpZW50WSAtIHRpbGVBLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLnRvcCAtIHNlcEdyYWIpO1xyXG4gICAgICAgICAgICB0aWxlc1Jlc2l6ZWQuZmlyZSgpO1xyXG4gICAgICAgICAgICBzZXBHcmFiID0gbnVsbDtcclxuICAgICAgICB9XHJcbiAgICB9KTtcclxuXHJcbiAgICB0aWxlc1Jlc2l6ZWQub24obGF5b3V0VGlsZXMpO1xyXG59XHJcblxyXG5cclxuXHJcblxyXG5mdW5jdGlvbiBfaW5pdFNwbGl0RVcoY29udGFpbmVyOiBIVE1MRWxlbWVudCwgdGlsZUE6IEhUTUxFbGVtZW50LCBzZXA6IEhUTUxFbGVtZW50LCB0aWxlQjogSFRNTEVsZW1lbnQsIHRpbGVzUmVzaXplZDogTm90aWZpY2F0aW9uKTogdm9pZCB7XHJcbiAgICBzZXAuY2xhc3NMaXN0LmFkZCgnc3BsaXRTZXBFVycpO1xyXG4gICAgc2VwLnN0eWxlLnRvcCA9ICcwcHgnO1xyXG4gICAgc2VwLnN0eWxlLmJvdHRvbSA9ICcwcHgnO1xyXG4gICAgdGlsZUEuc3R5bGUudG9wID0gJzBweCc7XHJcbiAgICB0aWxlQS5zdHlsZS5ib3R0b20gPSAnMHB4JztcclxuICAgIHRpbGVCLnN0eWxlLnRvcCA9ICcwcHgnO1xyXG4gICAgdGlsZUIuc3R5bGUuYm90dG9tID0gJzBweCc7XHJcblxyXG4gICAgY29uc3QgbWluV2lkdGhBID0gMTtcclxuICAgIGNvbnN0IG1pbldpZHRoQiA9IDE7XHJcbiAgICBsZXQgcmVjZW50RnJhY0E6IG51bWJlciA9IG51bGw7XHJcblxyXG4gICAgZnVuY3Rpb24gbGF5b3V0VGlsZXMocHJlbGltV2lkdGhBPzogbnVtYmVyKSB7XHJcbiAgICAgICAgY29uc3Qgd2lkdGhTZXAgPSBzZXAuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkud2lkdGg7XHJcbiAgICAgICAgY29uc3Qgd2lkdGhDb250YWluZXIgPSBjb250YWluZXIuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkud2lkdGg7XHJcbiAgICAgICAgY29uc3Qgd2lkdGhDb250ZW50ID0gd2lkdGhDb250YWluZXIgLSB3aWR0aFNlcDtcclxuICAgICAgICBpZiAocmVjZW50RnJhY0EgPT0gbnVsbCkge1xyXG4gICAgICAgICAgICByZWNlbnRGcmFjQSA9IHRpbGVBLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLndpZHRoIC8gd2lkdGhDb250ZW50O1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29uc3Qga2VlcEZyYWNBID0gKHByZWxpbVdpZHRoQSA9PSBudWxsKTtcclxuICAgICAgICBpZiAoa2VlcEZyYWNBKSB7XHJcbiAgICAgICAgICAgIHByZWxpbVdpZHRoQSA9IE1hdGgucm91bmQocmVjZW50RnJhY0EgKiB3aWR0aENvbnRlbnQpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29uc3QgbWF4V2lkdGhBID0gd2lkdGhDb250YWluZXIgLSB3aWR0aFNlcCAtIG1pbldpZHRoQjtcclxuXHJcbiAgICAgICAgY29uc3QgbGVmdEEgPSAwO1xyXG4gICAgICAgIGNvbnN0IHdpZHRoQSA9IE1hdGgubWF4KG1pbldpZHRoQSwgTWF0aC5taW4obWF4V2lkdGhBLCBwcmVsaW1XaWR0aEEpKTtcclxuICAgICAgICB0aWxlQS5zdHlsZS5sZWZ0ID0gbGVmdEEgKyAncHgnO1xyXG4gICAgICAgIHRpbGVBLnN0eWxlLndpZHRoID0gd2lkdGhBICsgJ3B4JztcclxuXHJcbiAgICAgICAgY29uc3QgbGVmdFNlcCA9IGxlZnRBICsgd2lkdGhBO1xyXG4gICAgICAgIHNlcC5zdHlsZS5sZWZ0ID0gbGVmdFNlcCArICdweCc7XHJcbiAgICAgICAgc2VwLnN0eWxlLndpZHRoID0gd2lkdGhTZXAgKyAncHgnO1xyXG5cclxuICAgICAgICBjb25zdCBsZWZ0QiA9IGxlZnRTZXAgKyB3aWR0aFNlcDtcclxuICAgICAgICBjb25zdCB3aWR0aEIgPSBNYXRoLm1heChtaW5XaWR0aEIsIHdpZHRoQ29udGFpbmVyIC0gbGVmdEIpO1xyXG4gICAgICAgIHRpbGVCLnN0eWxlLmxlZnQgPSBsZWZ0QiArICdweCc7XHJcbiAgICAgICAgdGlsZUIuc3R5bGUud2lkdGggPSB3aWR0aEIgKyAncHgnO1xyXG5cclxuICAgICAgICBpZiAoIWtlZXBGcmFjQSAmJiB3aWR0aENvbnRlbnQgPj0gd2lkdGhBICYmIHdpZHRoQ29udGVudCA+PSAobWluV2lkdGhBICsgbWluV2lkdGhCKSkge1xyXG4gICAgICAgICAgICByZWNlbnRGcmFjQSA9IHdpZHRoQSAvIHdpZHRoQ29udGVudDtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgbGV0IHNlcEdyYWI6IG51bWJlciA9IG51bGw7XHJcblxyXG4gICAgc2VwLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlZG93bicsIGZ1bmN0aW9uIChldjogTW91c2VFdmVudCkge1xyXG4gICAgICAgIGlmIChldi5idXR0b24gPT09IDApIHtcclxuICAgICAgICAgICAgc2VwR3JhYiA9IGV2LmNsaWVudFggLSB0aWxlQS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5sZWZ0IC0gdGlsZUEuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkud2lkdGg7XHJcbiAgICAgICAgICAgIGV2LnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICAgICAgfVxyXG4gICAgfSk7XHJcblxyXG4gICAgLy8gRHVyaW5nIGEgRFJBRyB3ZSB3YW50IGFsbCBtb3ZlIGV2ZW50cywgZXZlbiBvbmVzIHRoYXQgb2NjdXIgb3V0c2lkZSB0aGUgY2FudmFzIC0tIHNvIHN1YnNjcmliZSB0byBXSU5ET1cncyBtb3VzZW1vdmVcclxuICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtb3VzZW1vdmUnLCBmdW5jdGlvbiAoZXY6IE1vdXNlRXZlbnQpIHtcclxuICAgICAgICBpZiAoc2VwR3JhYiAhPSBudWxsKSB7XHJcbiAgICAgICAgICAgIGxheW91dFRpbGVzKGV2LmNsaWVudFggLSB0aWxlQS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5sZWZ0IC0gc2VwR3JhYik7XHJcbiAgICAgICAgICAgIHRpbGVzUmVzaXplZC5maXJlKCk7XHJcbiAgICAgICAgfVxyXG4gICAgfSk7XHJcblxyXG4gICAgLy8gVGhlIHdpbmRvdyBhbHdheXMgZ2V0cyB0aGUgbW91c2UtdXAgZXZlbnQgYXQgdGhlIGVuZCBvZiBhIGRyYWcgLS0gZXZlbiBpZiBpdCBvY2N1cnMgb3V0c2lkZSB0aGUgYnJvd3NlciB3aW5kb3dcclxuICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgZnVuY3Rpb24gKGV2OiBNb3VzZUV2ZW50KSB7XHJcbiAgICAgICAgaWYgKHNlcEdyYWIgIT0gbnVsbCAmJiBldi5idXR0b24gPT09IDApIHtcclxuICAgICAgICAgICAgbGF5b3V0VGlsZXMoZXYuY2xpZW50WCAtIHRpbGVBLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLmxlZnQgLSBzZXBHcmFiKTtcclxuICAgICAgICAgICAgdGlsZXNSZXNpemVkLmZpcmUoKTtcclxuICAgICAgICAgICAgc2VwR3JhYiA9IG51bGw7XHJcbiAgICAgICAgfVxyXG4gICAgfSk7XHJcblxyXG4gICAgdGlsZXNSZXNpemVkLm9uKGxheW91dFRpbGVzKTtcclxufVxyXG5cclxuXHJcblxyXG4iXX0=