element-resize-detector
Advanced tools
Comparing version 0.1.4 to 0.2.2
@@ -1,4 +0,41 @@ | ||
!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.elementResizeDetectorMaker=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ | ||
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.elementResizeDetectorMaker = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ | ||
"use strict"; | ||
var detector = module.exports = {}; | ||
detector.isIE = function(version) { | ||
function isAnyIeVersion() { | ||
var agent = navigator.userAgent.toLowerCase(); | ||
return agent.indexOf("msie") !== -1 || agent.indexOf("trident") !== -1; | ||
} | ||
if(!isAnyIeVersion()) { | ||
return false; | ||
} | ||
if(!version) { | ||
return true; | ||
} | ||
//Shamelessly stolen from https://gist.github.com/padolsey/527683 | ||
var ieVersion = (function(){ | ||
var undef, | ||
v = 3, | ||
div = document.createElement("div"), | ||
all = div.getElementsByTagName("i"); | ||
do { | ||
div.innerHTML = "<!--[if gt IE " + (++v) + "]><i></i><![endif]-->"; | ||
} | ||
while (all[0]); | ||
return v > 4 ? v : undef; | ||
}()); | ||
return version === ieVersion; | ||
}; | ||
},{}],2:[function(require,module,exports){ | ||
"use strict"; | ||
var utils = module.exports = {}; | ||
@@ -22,3 +59,3 @@ | ||
},{}],2:[function(require,module,exports){ | ||
},{}],3:[function(require,module,exports){ | ||
//Heavily inspired by http://www.backalleycoder.com/2013/03/18/cross-browser-event-based-element-resize-detection/ | ||
@@ -29,29 +66,100 @@ | ||
var forEach = require("./collection-utils").forEach; | ||
var elementUtils = require("./element-utils"); | ||
var elementUtilsMaker = require("./element-utils"); | ||
var listenerHandlerMaker = require("./listener-handler"); | ||
var idGeneratorMaker = require("./id-generator"); | ||
var listenerHandlerMaker = require("./listener-handler"); | ||
var idHandlerMaker = require("./id-handler"); | ||
var reporterMaker = require("./reporter"); | ||
/** | ||
* @typedef idHandler | ||
* @type {object} | ||
* @property {function} get Gets the resize detector id of the element. | ||
* @property {function} set Generate and sets the resize detector id of the element. | ||
*/ | ||
/** | ||
* @typedef Options | ||
* @type {object} | ||
* @property {boolean} callOnAdd Determines if listeners should be called when they are getting added. | ||
Default is true. If true, the listener is guaranteed to be called when it has been added. | ||
If false, the listener will not be guarenteed to be called when it has been added (does not prevent it from being called). | ||
* @property {idHandler} idHandler A custom id handler that is responsible for generating, setting and retrieving id's for elements. | ||
If not provided, a default id handler will be used. | ||
* @property {reporter} reporter A custom reporter that handles reporting logs, warnings and errors. | ||
If not provided, a default id handler will be used. | ||
If set to false, then nothing will be reported. | ||
*/ | ||
/** | ||
* Creates an element resize detector instance. | ||
* @public | ||
* @param {Options?} options Optional global options object that will decide how this instance will work. | ||
*/ | ||
module.exports = function(options) { | ||
options = options || {}; | ||
var allowMultipleListeners = options.allowMultipleListeners === undefined ? true : false; | ||
var eventListenerHandler = listenerHandlerMaker(); | ||
var idGenerator = idGeneratorMaker(); | ||
//Options to be used as default for the listenTo function. | ||
var globalOptions = {}; | ||
globalOptions.callOnAdd = !!getOption(options, "callOnAdd", true); | ||
//idHandler is currently not an option to the listenTo function, so it should not be added to globalOptions. | ||
var idHandler = options.idHandler; | ||
if(!idHandler) { | ||
var idGenerator = idGeneratorMaker(); | ||
var defaultIdHandler = idHandlerMaker(idGenerator); | ||
idHandler = defaultIdHandler; | ||
} | ||
//reporter is currently not an option to the listenTo function, so it should not be added to globalOptions. | ||
var reporter = options.reporter; | ||
if(!reporter) { | ||
//If options.reporter is false, then the reporter should be quiet. | ||
var quiet = reporter === false; | ||
reporter = reporterMaker(quiet); | ||
} | ||
var eventListenerHandler = listenerHandlerMaker(idHandler); | ||
var elementUtils = elementUtilsMaker(idHandler); | ||
/** | ||
* Makes the given elements resize-detectable and starts listening to resize events on the elements. Calls the event callback for each event for each element. | ||
* @public | ||
* @param {Options?} options Optional options object. These options will override the global options. Some options may not be overriden, such as idHandler. | ||
* @param {element[]|element} elements The given array of elements to detect resize events of. Single element is also valid. | ||
* @param {function} listener The callback to be executed for each resize event for each element. | ||
*/ | ||
function listenTo(elements, listener) { | ||
function isListenedTo(element) { | ||
return elementUtils.isDetectable(element) && eventListenerHandler.get(element).length; | ||
function listenTo(options, elements, listener) { | ||
function onResizeCallback(element) { | ||
var listeners = eventListenerHandler.get(element); | ||
forEach(listeners, function(listener) { | ||
listener(element); | ||
}); | ||
} | ||
function addListener(element, listener) { | ||
elementUtils.addListener(element, listener); | ||
function onElementReadyToAddListener(callOnAdd, element, listener) { | ||
eventListenerHandler.add(element, listener); | ||
if(callOnAdd) { | ||
listener(element); | ||
} | ||
} | ||
//Options object may be omitted. | ||
if(!listener) { | ||
listener = elements; | ||
elements = options; | ||
options = {}; | ||
} | ||
if(!elements) { | ||
throw new Error("At least one element required."); | ||
} | ||
if(!listener) { | ||
throw new Error("Listener required."); | ||
} | ||
if(elements.length === undefined) { | ||
@@ -61,8 +169,27 @@ elements = [elements]; | ||
var callOnAdd = getOption(options, "callOnAdd", globalOptions.callOnAdd); | ||
forEach(elements, function(element) { | ||
//The element may change size directly after the call to listenTo, which would be unable to detect it because | ||
//the async adding of the object. By checking the size before and after, the size change can still be detected | ||
//and the listener can be called accordingly. | ||
var preWidth = element.offsetWidth; | ||
var preHeight = element.offsetHeight; | ||
if(!elementUtils.isDetectable(element)) { | ||
//The element is not prepared to be detectable, so do prepare it and add a listener to it. | ||
var id = idGenerator.newId(); | ||
return elementUtils.makeDetectable(element, id, function(element) { | ||
addListener(element, listener); | ||
return elementUtils.makeDetectable(reporter, element, function(element) { | ||
elementUtils.addListener(element, onResizeCallback); | ||
onElementReadyToAddListener(callOnAdd, element, listener); | ||
//Only here the uncaught resize may occur (since this code is async). | ||
//Check if the size is the same as when adding the listener. | ||
var postWidth = element.offsetWidth; | ||
var postHeight = element.offsetHeight; | ||
//If callOnAdd is true, then the listener will have been called either way, so no need to call the listener manually then. | ||
if(!callOnAdd && (preWidth !== postWidth || preHeight !== postHeight)) { | ||
//The element was changed while the object was being added. Call the listener. | ||
listener(element); | ||
} | ||
}); | ||
@@ -72,10 +199,3 @@ } | ||
//The element has been prepared to be detectable and is ready to be listened to. | ||
if(isListenedTo(element) && !allowMultipleListeners) { | ||
//Since there is a listener and we disallow multiple listeners no listener should be added. | ||
return; | ||
} | ||
//Since multiple listeners is allowed, another listener is added to the element. | ||
return addListener(element, listener); | ||
onElementReadyToAddListener(callOnAdd, element, listener); | ||
}); | ||
@@ -89,105 +209,171 @@ } | ||
},{"./collection-utils":1,"./element-utils":3,"./id-generator":4,"./listener-handler":5}],3:[function(require,module,exports){ | ||
function getOption(options, name, defaultValue) { | ||
var value = options[name]; | ||
if((value === undefined || value === null) && defaultValue !== undefined) { | ||
return defaultValue; | ||
} | ||
return value; | ||
} | ||
},{"./collection-utils":2,"./element-utils":4,"./id-generator":5,"./id-handler":6,"./listener-handler":7,"./reporter":8}],4:[function(require,module,exports){ | ||
"use strict"; | ||
var forEach = require("./collection-utils").forEach; | ||
var browserDetector = require("./browser-detector"); | ||
var utils = module.exports = {}; | ||
module.exports = function(idHandler) { | ||
/** | ||
* Tells if the element has been made detectable and ready to be listened for resize events. | ||
* @public | ||
* @param {element} The element to check. | ||
* @returns {boolean} True or false depending on if the element is detectable or not. | ||
*/ | ||
function isDetectable(element) { | ||
if(browserDetector.isIE(8)) { | ||
//IE 8 does not use the object method. | ||
//Check only if the element has been given an id. | ||
return !!idHandler.get(element); | ||
} | ||
/** | ||
* Gets the elq id of the element. | ||
* @public | ||
* @param {element} The target element to get the id of. | ||
* @returns {string} The id of the element. | ||
*/ | ||
utils.getId = function(element) { | ||
return element.getAttribute("elq-target-id"); | ||
}; | ||
return !!getObject(element); | ||
} | ||
/** | ||
* Tells if the element has been made detectable and ready to be listened for resize events. | ||
* @public | ||
* @param {element} The element to check. | ||
* @returns {boolean} True or false depending on if the element is detectable or not. | ||
*/ | ||
utils.isDetectable = function(element) { | ||
return getObject(element); | ||
}; | ||
/** | ||
* Adds a resize event listener to the element. | ||
* @public | ||
* @param {element} element The element that should have the listener added. | ||
* @param {function} listener The listener callback to be called for each resize event of the element. The element will be given as a parameter to the listener callback. | ||
*/ | ||
function addListener(element, listener) { | ||
if(!isDetectable(element)) { | ||
throw new Error("Element is not detectable."); | ||
} | ||
/** | ||
* Adds a resize event listener to the element. | ||
* @public | ||
* @param {element} element The element that should have the listener added. | ||
* @param {function} listener The listener callback to be called for each resize event of the element. The element will be given as a parameter to the listener callback. | ||
*/ | ||
utils.addListener = function(element, listener) { | ||
if(!utils.isDetectable(element)) { | ||
throw new Error("Element is not detectable."); | ||
function listenerProxy() { | ||
listener(element); | ||
} | ||
if(browserDetector.isIE(8)) { | ||
//IE 8 does not support object, but supports the resize event directly on elements. | ||
element.attachEvent("onresize", listenerProxy); | ||
} else { | ||
var object = getObject(element); | ||
object.contentDocument.defaultView.addEventListener("resize", listenerProxy); | ||
} | ||
} | ||
var object = getObject(element); | ||
object.contentDocument.defaultView.addEventListener("resize", function() { | ||
listener(element); | ||
}); | ||
}; | ||
/** | ||
* Makes an element detectable and ready to be listened for resize events. Will call the callback when the element is ready to be listened for resize changes. | ||
* @private | ||
* @param {element} element The element to make detectable | ||
* @param {function} callback The callback to be called when the element is ready to be listened for resize changes. Will be called with the element as first parameter. | ||
*/ | ||
function makeDetectable(reporter, element, callback) { | ||
function injectObject(id, element, callback) { | ||
var OBJECT_STYLE = "display: block; position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: none; padding: 0; margin: 0; opacity: 0; z-index: -1000; pointer-events: none;"; | ||
/** | ||
* Makes an element detectable and ready to be listened for resize events. Will call the callback when the element is ready to be listened for resize changes. | ||
* @private | ||
* @param {element} element The element to make detectable | ||
* @param {*} id An unique id in the context of all detectable elements. | ||
* @param {function} callback The callback to be called when the element is ready to be listened for resize changes. Will be called with the element as first parameter. | ||
*/ | ||
utils.makeDetectable = function(element, id, callback) { | ||
function onObjectLoad() { | ||
/*jshint validthis:true */ | ||
function onObjectLoad() { | ||
/*jshint validthis:true */ | ||
//Create the style element to be added to the object. | ||
var objectDocument = this.contentDocument; | ||
var style = objectDocument.createElement("style"); | ||
style.innerHTML = "html, body { margin: 0; padding: 0 } div { -webkit-transition: opacity 0.01s; -ms-transition: opacity 0.01s; -o-transition: opacity 0.01s; transition: opacity 0.01s; opacity: 0; }"; | ||
//Create the style element to be added to the object. | ||
var objectDocument = this.contentDocument; | ||
var style = objectDocument.createElement("style"); | ||
style.innerHTML = "html, body { margin: 0; padding: 0 } div { -webkit-transition: opacity 0.01s; -ms-transition: opacity 0.01s; -o-transition: opacity 0.01s; transition: opacity 0.01s; opacity: 0; }"; | ||
//TODO: Remove any styles that has been set on the object. Only the style above should be styling the object. | ||
//TODO: Remove any styles that has been set on the object. Only the style above should be styling the object. | ||
//Append the style to the object. | ||
objectDocument.head.appendChild(style); | ||
//Append the style to the object. | ||
objectDocument.head.appendChild(style); | ||
this.style.cssText = "display: block; position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: none; padding: 0; margin: 0; opacity: 0; z-index: -1000; pointer-events: none;"; | ||
//TODO: Is this needed here? | ||
//this.style.cssText = OBJECT_STYLE; | ||
//Notify that the element is ready to be listened to. | ||
callback(element); | ||
} | ||
//Notify that the element is ready to be listened to. | ||
callback(element); | ||
} | ||
//Create an unique elq-target-id for the target element, so that event listeners can be identified to this element. | ||
element.setAttribute("elq-target-id", id); | ||
//The target element needs to be positioned (everything except static) so the absolute positioned object will be positioned relative to the target element. | ||
var style = getComputedStyle(element); | ||
if(style.position === "static") { | ||
element.style.position = "relative"; | ||
//The target element needs to be positioned (everything except static) so the absolute positioned object will be positioned relative to the target element. | ||
if(getComputedStyle(element).position === "static") { | ||
element.style.position = "relative"; | ||
var removeRelativeStyles = function(reporter, element, style, property) { | ||
function getNumericalValue(value) { | ||
return value.replace(/[^-\d\.]/g, ""); | ||
} | ||
var value = style[property]; | ||
if(value !== "auto" && getNumericalValue(value) !== "0") { | ||
reporter.warn("An element that is positioned static has style." + property + "=" + value + " which is ignored due to the static positioning. The element will need to be positioned relateive, so the style." + property + " will be set to 0. Element: ", element); | ||
element.style[property] = 0; | ||
} | ||
}; | ||
//Check so that there are no accidental styles that will make the element styled differently now that is is relative. | ||
//If there are any, set them to 0 (this should be okay with the user since the style properties did nothing before [since the element was positioned static] anyway). | ||
removeRelativeStyles(reporter, element, style, "top"); | ||
removeRelativeStyles(reporter, element, style, "right"); | ||
removeRelativeStyles(reporter, element, style, "bottom"); | ||
removeRelativeStyles(reporter, element, style, "left"); | ||
} | ||
//Add an object element as a child to the target element that will be listened to for resize events. | ||
var object = document.createElement("object"); | ||
object.type = "text/html"; | ||
object.style.cssText = OBJECT_STYLE; | ||
object.onload = onObjectLoad; | ||
object.setAttribute("erd-object-id", id); | ||
//Safari: This must occur before adding the object to the DOM. | ||
//IE: Does not like that this happens before, even if it is also added after. | ||
if(!browserDetector.isIE()) { | ||
object.data = "about:blank"; | ||
} | ||
element.appendChild(object); | ||
//IE: This must occur after adding the object to the DOM. | ||
if(browserDetector.isIE()) { | ||
object.data = "about:blank"; | ||
} | ||
} | ||
//Create an unique erd-target-id for the target element, so that event listeners can be identified to this element. | ||
var id = idHandler.set(element); | ||
if(browserDetector.isIE(8)) { | ||
//IE 8 does not support objects properly. Luckily they do support the resize event. | ||
//So do not inject the object and notify that the element is already ready to be listened to. | ||
//The event handler for the resize event is attached in the utils.addListener instead. | ||
callback(element); | ||
} else { | ||
injectObject(id, element, callback); | ||
} | ||
} | ||
//Add an object element as a child to the target element that will be listened to for resize events. | ||
var object = document.createElement("object"); | ||
object.type = "text/html"; | ||
object.data = "about:blank"; | ||
object.onload = onObjectLoad; | ||
object.setAttribute("elq-object-id", id); | ||
element.appendChild(object); | ||
/** | ||
* Returns the child object of the target element. | ||
* @private | ||
* @param {element} element The target element. | ||
* @returns The object element of the target. | ||
*/ | ||
function getObject(element) { | ||
return forEach(element.children, function(child) { | ||
if(child.hasAttribute("erd-object-id")) { | ||
return child; | ||
} | ||
}); | ||
} | ||
return { | ||
isDetectable: isDetectable, | ||
makeDetectable: makeDetectable, | ||
addListener: addListener, | ||
}; | ||
}; | ||
/** | ||
* Returns the child object of the target element. | ||
* @private | ||
* @param {element} element The target element. | ||
* @returns The object element of the target. | ||
*/ | ||
function getObject(element) { | ||
return forEach(element.children, function(child) { | ||
if(child.hasAttribute("elq-object-id")) { | ||
return child; | ||
} | ||
}); | ||
} | ||
},{"./collection-utils":1}],4:[function(require,module,exports){ | ||
},{"./browser-detector":1,"./collection-utils":2}],5:[function(require,module,exports){ | ||
"use strict"; | ||
@@ -203,3 +389,3 @@ | ||
*/ | ||
function newId() { | ||
function generate() { | ||
return idCount++; | ||
@@ -209,12 +395,49 @@ } | ||
return { | ||
newId: newId | ||
generate: generate | ||
}; | ||
}; | ||
},{}],5:[function(require,module,exports){ | ||
},{}],6:[function(require,module,exports){ | ||
"use strict"; | ||
var elementUtils = require("./element-utils"); | ||
module.exports = function(idGenerator) { | ||
module.exports = function() { | ||
/** | ||
* Gets the resize detector id of the element. | ||
* @public | ||
* @param {element} The target element to get the id of. | ||
* @returns {string|number} The id of the element. | ||
*/ | ||
function getId(element) { | ||
return element.getAttribute("erd-target-id"); | ||
} | ||
/** | ||
* Sets the resize detector id of the element. | ||
* @public | ||
* @param {element} The target element to set the id to. | ||
* @param {string?} An optional id to set to the element. If not specified, an id will be generated. All id's must be unique. | ||
* @returns {string|number} The id of the element. | ||
*/ | ||
function setId(element, id) { | ||
if(!id && id !== 0) { | ||
//Number should be generated. | ||
id = idGenerator.generate(); | ||
} | ||
element.setAttribute("erd-target-id", id); | ||
return id; | ||
} | ||
return { | ||
get: getId, | ||
set: setId | ||
}; | ||
}; | ||
},{}],7:[function(require,module,exports){ | ||
"use strict"; | ||
module.exports = function(idHandler) { | ||
var eventListeners = {}; | ||
@@ -229,3 +452,3 @@ | ||
function getListeners(element) { | ||
return eventListeners[elementUtils.getId(element)]; | ||
return eventListeners[idHandler.get(element)]; | ||
} | ||
@@ -240,3 +463,3 @@ | ||
function addListener(element, listener) { | ||
var id = elementUtils.getId(element); | ||
var id = idHandler.get(element); | ||
@@ -256,4 +479,33 @@ if(!eventListeners[id]) { | ||
},{"./element-utils":3}]},{},[2])(2) | ||
},{}],8:[function(require,module,exports){ | ||
"use strict"; | ||
/* global console: false */ | ||
/** | ||
* Reporter that handles the reporting of logs, warnings and errors. | ||
* @public | ||
* @param {boolean} quiet Tells if the reporter should be quiet or not. | ||
*/ | ||
module.exports = function(quiet) { | ||
var noop = function () { | ||
//Does nothing. | ||
}; | ||
var reporter = { | ||
log: noop, | ||
warn: noop, | ||
error: noop | ||
}; | ||
if(!quiet && window.console) { | ||
reporter.log = console.log; | ||
reporter.warn = console.warn; | ||
reporter.error = console.error; | ||
} | ||
return reporter; | ||
}; | ||
},{}]},{},[3])(3) | ||
}); | ||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9ncnVudC1icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJzcmMvY29sbGVjdGlvbi11dGlscy5qcyIsInNyYy9lbGVtZW50LXJlc2l6ZS1kZXRlY3Rvci5qcyIsInNyYy9lbGVtZW50LXV0aWxzLmpzIiwic3JjL2lkLWdlbmVyYXRvci5qcyIsInNyYy9saXN0ZW5lci1oYW5kbGVyLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FDQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsImZpbGUiOiJnZW5lcmF0ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uIGUodCxuLHIpe2Z1bmN0aW9uIHMobyx1KXtpZighbltvXSl7aWYoIXRbb10pe3ZhciBhPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7aWYoIXUmJmEpcmV0dXJuIGEobywhMCk7aWYoaSlyZXR1cm4gaShvLCEwKTt2YXIgZj1uZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK28rXCInXCIpO3Rocm93IGYuY29kZT1cIk1PRFVMRV9OT1RfRk9VTkRcIixmfXZhciBsPW5bb109e2V4cG9ydHM6e319O3Rbb11bMF0uY2FsbChsLmV4cG9ydHMsZnVuY3Rpb24oZSl7dmFyIG49dFtvXVsxXVtlXTtyZXR1cm4gcyhuP246ZSl9LGwsbC5leHBvcnRzLGUsdCxuLHIpfXJldHVybiBuW29dLmV4cG9ydHN9dmFyIGk9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtmb3IodmFyIG89MDtvPHIubGVuZ3RoO28rKylzKHJbb10pO3JldHVybiBzfSkiLCJcInVzZSBzdHJpY3RcIjtcblxudmFyIHV0aWxzID0gbW9kdWxlLmV4cG9ydHMgPSB7fTtcblxuLyoqXG4gKiBMb29wcyB0aHJvdWdoIHRoZSBjb2xsZWN0aW9uIGFuZCBjYWxscyB0aGUgY2FsbGJhY2sgZm9yIGVhY2ggZWxlbWVudC4gaWYgdGhlIGNhbGxiYWNrIHJldHVybnMgdHJ1dGh5LCB0aGUgbG9vcCBpcyBicm9rZW4gYW5kIHJldHVybnMgdGhlIHNhbWUgdmFsdWUuXG4gKiBAcHVibGljXG4gKiBAcGFyYW0geyp9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gbG9vcCB0aHJvdWdoLiBOZWVkcyB0byBoYXZlIGEgbGVuZ3RoIHByb3BlcnR5IHNldCBhbmQgaGF2ZSBpbmRpY2VzIHNldCBmcm9tIDAgdG8gbGVuZ3RoIC0gMS5cbiAqIEBwYXJhbSB7ZnVuY3Rpb259IGNhbGxiYWNrIFRoZSBjYWxsYmFjayB0byBiZSBjYWxsZWQgZm9yIGVhY2ggZWxlbWVudC4gVGhlIGVsZW1lbnQgd2lsbCBiZSBnaXZlbiBhcyBhIHBhcmFtZXRlciB0byB0aGUgY2FsbGJhY2suIElmIHRoaXMgY2FsbGJhY2sgcmV0dXJucyB0cnV0aHksIHRoZSBsb29wIGlzIGJyb2tlbiBhbmQgdGhlIHNhbWUgdmFsdWUgaXMgcmV0dXJuZWQuXG4gKiBAcmV0dXJucyB7Kn0gVGhlIHZhbHVlIHRoYXQgYSBjYWxsYmFjayBoYXMgcmV0dXJuZWQgKGlmIHRydXRoeSkuIE90aGVyd2lzZSBub3RoaW5nLlxuICovXG51dGlscy5mb3JFYWNoID0gZnVuY3Rpb24oY29sbGVjdGlvbiwgY2FsbGJhY2spIHtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgY29sbGVjdGlvbi5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgcmVzdWx0ID0gY2FsbGJhY2soY29sbGVjdGlvbltpXSk7XG4gICAgICAgIGlmKHJlc3VsdCkge1xuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuICAgIH1cbn07XG4iLCIvL0hlYXZpbHkgaW5zcGlyZWQgYnkgaHR0cDovL3d3dy5iYWNrYWxsZXljb2Rlci5jb20vMjAxMy8wMy8xOC9jcm9zcy1icm93c2VyLWV2ZW50LWJhc2VkLWVsZW1lbnQtcmVzaXplLWRldGVjdGlvbi9cblxuXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBmb3JFYWNoID0gcmVxdWlyZShcIi4vY29sbGVjdGlvbi11dGlsc1wiKS5mb3JFYWNoO1xudmFyIGVsZW1lbnRVdGlscyA9IHJlcXVpcmUoXCIuL2VsZW1lbnQtdXRpbHNcIik7XG52YXIgaWRHZW5lcmF0b3JNYWtlciA9IHJlcXVpcmUoXCIuL2lkLWdlbmVyYXRvclwiKTtcbnZhciBsaXN0ZW5lckhhbmRsZXJNYWtlciA9IHJlcXVpcmUoXCIuL2xpc3RlbmVyLWhhbmRsZXJcIik7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24ob3B0aW9ucykge1xuICAgIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuICAgIHZhciBhbGxvd011bHRpcGxlTGlzdGVuZXJzID0gb3B0aW9ucy5hbGxvd011bHRpcGxlTGlzdGVuZXJzID09PSB1bmRlZmluZWQgPyB0cnVlIDogZmFsc2U7XG5cbiAgICB2YXIgZXZlbnRMaXN0ZW5lckhhbmRsZXIgPSBsaXN0ZW5lckhhbmRsZXJNYWtlcigpO1xuICAgIHZhciBpZEdlbmVyYXRvciA9IGlkR2VuZXJhdG9yTWFrZXIoKTtcblxuICAgIC8qKlxuICAgICAqIE1ha2VzIHRoZSBnaXZlbiBlbGVtZW50cyByZXNpemUtZGV0ZWN0YWJsZSBhbmQgc3RhcnRzIGxpc3RlbmluZyB0byByZXNpemUgZXZlbnRzIG9uIHRoZSBlbGVtZW50cy4gQ2FsbHMgdGhlIGV2ZW50IGNhbGxiYWNrIGZvciBlYWNoIGV2ZW50IGZvciBlYWNoIGVsZW1lbnQuXG4gICAgICogQHB1YmxpY1xuICAgICAqIEBwYXJhbSB7ZWxlbWVudFtdfGVsZW1lbnR9IGVsZW1lbnRzIFRoZSBnaXZlbiBhcnJheSBvZiBlbGVtZW50cyB0byBkZXRlY3QgcmVzaXplIGV2ZW50cyBvZi4gU2luZ2xlIGVsZW1lbnQgaXMgYWxzbyB2YWxpZC5cbiAgICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBsaXN0ZW5lciBUaGUgY2FsbGJhY2sgdG8gYmUgZXhlY3V0ZWQgZm9yIGVhY2ggcmVzaXplIGV2ZW50IGZvciBlYWNoIGVsZW1lbnQuXG4gICAgICovXG4gICAgZnVuY3Rpb24gbGlzdGVuVG8oZWxlbWVudHMsIGxpc3RlbmVyKSB7XG4gICAgICAgIGZ1bmN0aW9uIGlzTGlzdGVuZWRUbyhlbGVtZW50KSB7XG4gICAgICAgICAgICByZXR1cm4gZWxlbWVudFV0aWxzLmlzRGV0ZWN0YWJsZShlbGVtZW50KSAmJiBldmVudExpc3RlbmVySGFuZGxlci5nZXQoZWxlbWVudCkubGVuZ3RoO1xuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gYWRkTGlzdGVuZXIoZWxlbWVudCwgbGlzdGVuZXIpIHtcbiAgICAgICAgICAgIGVsZW1lbnRVdGlscy5hZGRMaXN0ZW5lcihlbGVtZW50LCBsaXN0ZW5lcik7XG4gICAgICAgICAgICBldmVudExpc3RlbmVySGFuZGxlci5hZGQoZWxlbWVudCwgbGlzdGVuZXIpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoZWxlbWVudHMubGVuZ3RoID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGVsZW1lbnRzID0gW2VsZW1lbnRzXTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZvckVhY2goZWxlbWVudHMsIGZ1bmN0aW9uKGVsZW1lbnQpIHtcbiAgICAgICAgICAgIGlmKCFlbGVtZW50VXRpbHMuaXNEZXRlY3RhYmxlKGVsZW1lbnQpKSB7XG4gICAgICAgICAgICAgICAgLy9UaGUgZWxlbWVudCBpcyBub3QgcHJlcGFyZWQgdG8gYmUgZGV0ZWN0YWJsZSwgc28gZG8gcHJlcGFyZSBpdCBhbmQgYWRkIGEgbGlzdGVuZXIgdG8gaXQuXG4gICAgICAgICAgICAgICAgdmFyIGlkID0gaWRHZW5lcmF0b3IubmV3SWQoKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gZWxlbWVudFV0aWxzLm1ha2VEZXRlY3RhYmxlKGVsZW1lbnQsIGlkLCBmdW5jdGlvbihlbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIGFkZExpc3RlbmVyKGVsZW1lbnQsIGxpc3RlbmVyKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIFxuICAgICAgICAgICAgLy9UaGUgZWxlbWVudCBoYXMgYmVlbiBwcmVwYXJlZCB0byBiZSBkZXRlY3RhYmxlIGFuZCBpcyByZWFkeSB0byBiZSBsaXN0ZW5lZCB0by5cbiAgICAgICAgICAgIFxuICAgICAgICAgICAgaWYoaXNMaXN0ZW5lZFRvKGVsZW1lbnQpICYmICFhbGxvd011bHRpcGxlTGlzdGVuZXJzKSB7XG4gICAgICAgICAgICAgICAgLy9TaW5jZSB0aGVyZSBpcyBhIGxpc3RlbmVyIGFuZCB3ZSBkaXNhbGxvdyBtdWx0aXBsZSBsaXN0ZW5lcnMgbm8gbGlzdGVuZXIgc2hvdWxkIGJlIGFkZGVkLlxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy9TaW5jZSBtdWx0aXBsZSBsaXN0ZW5lcnMgaXMgYWxsb3dlZCwgYW5vdGhlciBsaXN0ZW5lciBpcyBhZGRlZCB0byB0aGUgZWxlbWVudC5cbiAgICAgICAgICAgIHJldHVybiBhZGRMaXN0ZW5lcihlbGVtZW50LCBsaXN0ZW5lcik7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICAgIGxpc3RlblRvOiBsaXN0ZW5Ub1xuICAgIH07XG59O1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBmb3JFYWNoID0gcmVxdWlyZShcIi4vY29sbGVjdGlvbi11dGlsc1wiKS5mb3JFYWNoO1xuXG52YXIgdXRpbHMgPSBtb2R1bGUuZXhwb3J0cyA9IHt9O1xuXG4vKipcbiAqIEdldHMgdGhlIGVscSBpZCBvZiB0aGUgZWxlbWVudC5cbiAqIEBwdWJsaWNcbiAqIEBwYXJhbSB7ZWxlbWVudH0gVGhlIHRhcmdldCBlbGVtZW50IHRvIGdldCB0aGUgaWQgb2YuXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgaWQgb2YgdGhlIGVsZW1lbnQuXG4gKi9cbnV0aWxzLmdldElkID0gZnVuY3Rpb24oZWxlbWVudCkge1xuICAgIHJldHVybiBlbGVtZW50LmdldEF0dHJpYnV0ZShcImVscS10YXJnZXQtaWRcIik7XG59O1xuXG4vKipcbiAqIFRlbGxzIGlmIHRoZSBlbGVtZW50IGhhcyBiZWVuIG1hZGUgZGV0ZWN0YWJsZSBhbmQgcmVhZHkgdG8gYmUgbGlzdGVuZWQgZm9yIHJlc2l6ZSBldmVudHMuXG4gKiBAcHVibGljXG4gKiBAcGFyYW0ge2VsZW1lbnR9IFRoZSBlbGVtZW50IHRvIGNoZWNrLlxuICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgb3IgZmFsc2UgZGVwZW5kaW5nIG9uIGlmIHRoZSBlbGVtZW50IGlzIGRldGVjdGFibGUgb3Igbm90LlxuICovXG51dGlscy5pc0RldGVjdGFibGUgPSBmdW5jdGlvbihlbGVtZW50KSB7XG4gICAgcmV0dXJuIGdldE9iamVjdChlbGVtZW50KTtcbn07XG5cbi8qKlxuICogQWRkcyBhIHJlc2l6ZSBldmVudCBsaXN0ZW5lciB0byB0aGUgZWxlbWVudC5cbiAqIEBwdWJsaWNcbiAqIEBwYXJhbSB7ZWxlbWVudH0gZWxlbWVudCBUaGUgZWxlbWVudCB0aGF0IHNob3VsZCBoYXZlIHRoZSBsaXN0ZW5lciBhZGRlZC5cbiAqIEBwYXJhbSB7ZnVuY3Rpb259IGxpc3RlbmVyIFRoZSBsaXN0ZW5lciBjYWxsYmFjayB0byBiZSBjYWxsZWQgZm9yIGVhY2ggcmVzaXplIGV2ZW50IG9mIHRoZSBlbGVtZW50LiBUaGUgZWxlbWVudCB3aWxsIGJlIGdpdmVuIGFzIGEgcGFyYW1ldGVyIHRvIHRoZSBsaXN0ZW5lciBjYWxsYmFjay5cbiAqL1xudXRpbHMuYWRkTGlzdGVuZXIgPSBmdW5jdGlvbihlbGVtZW50LCBsaXN0ZW5lcikge1xuICAgIGlmKCF1dGlscy5pc0RldGVjdGFibGUoZWxlbWVudCkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiRWxlbWVudCBpcyBub3QgZGV0ZWN0YWJsZS5cIik7XG4gICAgfVxuXG4gICAgdmFyIG9iamVjdCA9IGdldE9iamVjdChlbGVtZW50KTtcbiAgICBvYmplY3QuY29udGVudERvY3VtZW50LmRlZmF1bHRWaWV3LmFkZEV2ZW50TGlzdGVuZXIoXCJyZXNpemVcIiwgZnVuY3Rpb24oKSB7XG4gICAgICAgIGxpc3RlbmVyKGVsZW1lbnQpO1xuICAgIH0pO1xufTtcblxuLyoqXG4gKiBNYWtlcyBhbiBlbGVtZW50IGRldGVjdGFibGUgYW5kIHJlYWR5IHRvIGJlIGxpc3RlbmVkIGZvciByZXNpemUgZXZlbnRzLiBXaWxsIGNhbGwgdGhlIGNhbGxiYWNrIHdoZW4gdGhlIGVsZW1lbnQgaXMgcmVhZHkgdG8gYmUgbGlzdGVuZWQgZm9yIHJlc2l6ZSBjaGFuZ2VzLlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7ZWxlbWVudH0gZWxlbWVudCBUaGUgZWxlbWVudCB0byBtYWtlIGRldGVjdGFibGVcbiAqIEBwYXJhbSB7Kn0gaWQgQW4gdW5pcXVlIGlkIGluIHRoZSBjb250ZXh0IG9mIGFsbCBkZXRlY3RhYmxlIGVsZW1lbnRzLlxuICogQHBhcmFtIHtmdW5jdGlvbn0gY2FsbGJhY2sgVGhlIGNhbGxiYWNrIHRvIGJlIGNhbGxlZCB3aGVuIHRoZSBlbGVtZW50IGlzIHJlYWR5IHRvIGJlIGxpc3RlbmVkIGZvciByZXNpemUgY2hhbmdlcy4gV2lsbCBiZSBjYWxsZWQgd2l0aCB0aGUgZWxlbWVudCBhcyBmaXJzdCBwYXJhbWV0ZXIuXG4gKi9cbnV0aWxzLm1ha2VEZXRlY3RhYmxlID0gZnVuY3Rpb24oZWxlbWVudCwgaWQsIGNhbGxiYWNrKSB7XG4gICAgZnVuY3Rpb24gb25PYmplY3RMb2FkKCkge1xuICAgICAgICAvKmpzaGludCB2YWxpZHRoaXM6dHJ1ZSAqL1xuXG4gICAgICAgIC8vQ3JlYXRlIHRoZSBzdHlsZSBlbGVtZW50IHRvIGJlIGFkZGVkIHRvIHRoZSBvYmplY3QuXG4gICAgICAgIHZhciBvYmplY3REb2N1bWVudCA9IHRoaXMuY29udGVudERvY3VtZW50O1xuICAgICAgICB2YXIgc3R5bGUgPSBvYmplY3REb2N1bWVudC5jcmVhdGVFbGVtZW50KFwic3R5bGVcIik7XG4gICAgICAgIHN0eWxlLmlubmVySFRNTCA9IFwiaHRtbCwgYm9keSB7IG1hcmdpbjogMDsgcGFkZGluZzogMCB9IGRpdiB7IC13ZWJraXQtdHJhbnNpdGlvbjogb3BhY2l0eSAwLjAxczsgLW1zLXRyYW5zaXRpb246IG9wYWNpdHkgMC4wMXM7IC1vLXRyYW5zaXRpb246IG9wYWNpdHkgMC4wMXM7IHRyYW5zaXRpb246IG9wYWNpdHkgMC4wMXM7IG9wYWNpdHk6IDA7IH1cIjtcblxuICAgICAgICAvL1RPRE86IFJlbW92ZSBhbnkgc3R5bGVzIHRoYXQgaGFzIGJlZW4gc2V0IG9uIHRoZSBvYmplY3QuIE9ubHkgdGhlIHN0eWxlIGFib3ZlIHNob3VsZCBiZSBzdHlsaW5nIHRoZSBvYmplY3QuXG5cbiAgICAgICAgLy9BcHBlbmQgdGhlIHN0eWxlIHRvIHRoZSBvYmplY3QuXG4gICAgICAgIG9iamVjdERvY3VtZW50LmhlYWQuYXBwZW5kQ2hpbGQoc3R5bGUpO1xuXG4gICAgICAgIHRoaXMuc3R5bGUuY3NzVGV4dCA9IFwiZGlzcGxheTogYmxvY2s7IHBvc2l0aW9uOiBhYnNvbHV0ZTsgdG9wOiAwOyBsZWZ0OiAwOyB3aWR0aDogMTAwJTsgaGVpZ2h0OiAxMDAlOyBib3JkZXI6IG5vbmU7IHBhZGRpbmc6IDA7IG1hcmdpbjogMDsgb3BhY2l0eTogMDsgei1pbmRleDogLTEwMDA7IHBvaW50ZXItZXZlbnRzOiBub25lO1wiO1xuXG4gICAgICAgIC8vTm90aWZ5IHRoYXQgdGhlIGVsZW1lbnQgaXMgcmVhZHkgdG8gYmUgbGlzdGVuZWQgdG8uXG4gICAgICAgIGNhbGxiYWNrKGVsZW1lbnQpO1xuICAgIH1cblxuICAgIC8vQ3JlYXRlIGFuIHVuaXF1ZSBlbHEtdGFyZ2V0LWlkIGZvciB0aGUgdGFyZ2V0IGVsZW1lbnQsIHNvIHRoYXQgZXZlbnQgbGlzdGVuZXJzIGNhbiBiZSBpZGVudGlmaWVkIHRvIHRoaXMgZWxlbWVudC5cbiAgICBlbGVtZW50LnNldEF0dHJpYnV0ZShcImVscS10YXJnZXQtaWRcIiwgaWQpO1xuXG4gICAgLy9UaGUgdGFyZ2V0IGVsZW1lbnQgbmVlZHMgdG8gYmUgcG9zaXRpb25lZCAoZXZlcnl0aGluZyBleGNlcHQgc3RhdGljKSBzbyB0aGUgYWJzb2x1dGUgcG9zaXRpb25lZCBvYmplY3Qgd2lsbCBiZSBwb3NpdGlvbmVkIHJlbGF0aXZlIHRvIHRoZSB0YXJnZXQgZWxlbWVudC5cbiAgICBpZihnZXRDb21wdXRlZFN0eWxlKGVsZW1lbnQpLnBvc2l0aW9uID09PSBcInN0YXRpY1wiKSB7XG4gICAgICAgIGVsZW1lbnQuc3R5bGUucG9zaXRpb24gPSBcInJlbGF0aXZlXCI7XG4gICAgfVxuXG4gICAgLy9BZGQgYW4gb2JqZWN0IGVsZW1lbnQgYXMgYSBjaGlsZCB0byB0aGUgdGFyZ2V0IGVsZW1lbnQgdGhhdCB3aWxsIGJlIGxpc3RlbmVkIHRvIGZvciByZXNpemUgZXZlbnRzLlxuICAgIHZhciBvYmplY3QgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwib2JqZWN0XCIpO1xuICAgIG9iamVjdC50eXBlID0gXCJ0ZXh0L2h0bWxcIjtcbiAgICBvYmplY3QuZGF0YSA9IFwiYWJvdXQ6YmxhbmtcIjtcbiAgICBvYmplY3Qub25sb2FkID0gb25PYmplY3RMb2FkO1xuICAgIG9iamVjdC5zZXRBdHRyaWJ1dGUoXCJlbHEtb2JqZWN0LWlkXCIsIGlkKTtcbiAgICBlbGVtZW50LmFwcGVuZENoaWxkKG9iamVjdCk7XG59O1xuXG4vKipcbiAqIFJldHVybnMgdGhlIGNoaWxkIG9iamVjdCBvZiB0aGUgdGFyZ2V0IGVsZW1lbnQuXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtlbGVtZW50fSBlbGVtZW50IFRoZSB0YXJnZXQgZWxlbWVudC5cbiAqIEByZXR1cm5zIFRoZSBvYmplY3QgZWxlbWVudCBvZiB0aGUgdGFyZ2V0LlxuICovXG5mdW5jdGlvbiBnZXRPYmplY3QoZWxlbWVudCkge1xuICAgIHJldHVybiBmb3JFYWNoKGVsZW1lbnQuY2hpbGRyZW4sIGZ1bmN0aW9uKGNoaWxkKSB7XG4gICAgICAgIGlmKGNoaWxkLmhhc0F0dHJpYnV0ZShcImVscS1vYmplY3QtaWRcIikpIHtcbiAgICAgICAgICAgIHJldHVybiBjaGlsZDtcbiAgICAgICAgfVxuICAgIH0pO1xufVxuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGlkQ291bnQgPSAxO1xuXG4gICAgLyoqXG4gICAgICogR2VuZXJhdGVzIGEgbmV3IHVuaXF1ZSBpZCBpbiB0aGUgY29udGV4dC5cbiAgICAgKiBAcHVibGljXG4gICAgICogQHJldHVybnMge251bWJlcn0gQSB1bmlxdWUgaWQgaW4gdGhlIGNvbnRleHQuXG4gICAgICovXG4gICAgZnVuY3Rpb24gbmV3SWQoKSB7XG4gICAgICAgIHJldHVybiBpZENvdW50Kys7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgbmV3SWQ6IG5ld0lkXG4gICAgfTtcbn07XG4iLCJcInVzZSBzdHJpY3RcIjtcblxudmFyIGVsZW1lbnRVdGlscyA9IHJlcXVpcmUoXCIuL2VsZW1lbnQtdXRpbHNcIik7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGV2ZW50TGlzdGVuZXJzID0ge307XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGFsbCBsaXN0ZW5lcnMgZm9yIHRoZSBnaXZlbiBlbGVtZW50LlxuICAgICAqIEBwdWJsaWNcbiAgICAgKiBAcGFyYW0ge2VsZW1lbnR9IGVsZW1lbnQgVGhlIGVsZW1lbnQgdG8gZ2V0IGFsbCBsaXN0ZW5lcnMgZm9yLlxuICAgICAqIEByZXR1cm5zIEFsbCBsaXN0ZW5lcnMgZm9yIHRoZSBnaXZlbiBlbGVtZW50LlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldExpc3RlbmVycyhlbGVtZW50KSB7XG4gICAgICAgIHJldHVybiBldmVudExpc3RlbmVyc1tlbGVtZW50VXRpbHMuZ2V0SWQoZWxlbWVudCldO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFN0b3JlcyB0aGUgZ2l2ZW4gbGlzdGVuZXIgZm9yIHRoZSBnaXZlbiBlbGVtZW50LiBXaWxsIG5vdCBhY3R1YWxseSBhZGQgdGhlIGxpc3RlbmVyIHRvIHRoZSBlbGVtZW50LlxuICAgICAqIEBwdWJsaWNcbiAgICAgKiBAcGFyYW0ge2VsZW1lbnR9IGVsZW1lbnQgVGhlIGVsZW1lbnQgdGhhdCBzaG91bGQgaGF2ZSB0aGUgbGlzdGVuZXIgYWRkZWQuXG4gICAgICogQHBhcmFtIHtmdW5jdGlvbn0gbGlzdGVuZXIgVGhlIGNhbGxiYWNrIHRoYXQgdGhlIGVsZW1lbnQgaGFzIGFkZGVkLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGFkZExpc3RlbmVyKGVsZW1lbnQsIGxpc3RlbmVyKSB7XG4gICAgICAgIHZhciBpZCA9IGVsZW1lbnRVdGlscy5nZXRJZChlbGVtZW50KTtcblxuICAgICAgICBpZighZXZlbnRMaXN0ZW5lcnNbaWRdKSB7XG4gICAgICAgICAgICBldmVudExpc3RlbmVyc1tpZF0gPSBbXTtcbiAgICAgICAgfVxuXG4gICAgICAgIGV2ZW50TGlzdGVuZXJzW2lkXS5wdXNoKGxpc3RlbmVyKTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgICBnZXQ6IGdldExpc3RlbmVycyxcbiAgICAgICAgYWRkOiBhZGRMaXN0ZW5lclxuICAgIH07XG59O1xuIl19 | ||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9ncnVudC1icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJzcmMvYnJvd3Nlci1kZXRlY3Rvci5qcyIsInNyYy9jb2xsZWN0aW9uLXV0aWxzLmpzIiwic3JjL2VsZW1lbnQtcmVzaXplLWRldGVjdG9yLmpzIiwic3JjL2VsZW1lbnQtdXRpbHMuanMiLCJzcmMvaWQtZ2VuZXJhdG9yLmpzIiwic3JjL2lkLWhhbmRsZXIuanMiLCJzcmMvbGlzdGVuZXItaGFuZGxlci5qcyIsInNyYy9yZXBvcnRlci5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxSkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNUpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbiBlKHQsbixyKXtmdW5jdGlvbiBzKG8sdSl7aWYoIW5bb10pe2lmKCF0W29dKXt2YXIgYT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2lmKCF1JiZhKXJldHVybiBhKG8sITApO2lmKGkpcmV0dXJuIGkobywhMCk7dmFyIGY9bmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIitvK1wiJ1wiKTt0aHJvdyBmLmNvZGU9XCJNT0RVTEVfTk9UX0ZPVU5EXCIsZn12YXIgbD1uW29dPXtleHBvcnRzOnt9fTt0W29dWzBdLmNhbGwobC5leHBvcnRzLGZ1bmN0aW9uKGUpe3ZhciBuPXRbb11bMV1bZV07cmV0dXJuIHMobj9uOmUpfSxsLGwuZXhwb3J0cyxlLHQsbixyKX1yZXR1cm4gbltvXS5leHBvcnRzfXZhciBpPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7Zm9yKHZhciBvPTA7bzxyLmxlbmd0aDtvKyspcyhyW29dKTtyZXR1cm4gc30pIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBkZXRlY3RvciA9IG1vZHVsZS5leHBvcnRzID0ge307XG5cbmRldGVjdG9yLmlzSUUgPSBmdW5jdGlvbih2ZXJzaW9uKSB7XG4gICAgZnVuY3Rpb24gaXNBbnlJZVZlcnNpb24oKSB7XG4gICAgICAgIHZhciBhZ2VudCA9IG5hdmlnYXRvci51c2VyQWdlbnQudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgcmV0dXJuIGFnZW50LmluZGV4T2YoXCJtc2llXCIpICE9PSAtMSB8fCBhZ2VudC5pbmRleE9mKFwidHJpZGVudFwiKSAhPT0gLTE7XG4gICAgfVxuXG4gICAgaWYoIWlzQW55SWVWZXJzaW9uKCkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGlmKCF2ZXJzaW9uKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIC8vU2hhbWVsZXNzbHkgc3RvbGVuIGZyb20gaHR0cHM6Ly9naXN0LmdpdGh1Yi5jb20vcGFkb2xzZXkvNTI3NjgzXG4gICAgdmFyIGllVmVyc2lvbiA9IChmdW5jdGlvbigpe1xuICAgICAgICB2YXIgdW5kZWYsXG4gICAgICAgICAgICB2ID0gMyxcbiAgICAgICAgICAgIGRpdiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIiksXG4gICAgICAgICAgICBhbGwgPSBkaXYuZ2V0RWxlbWVudHNCeVRhZ05hbWUoXCJpXCIpO1xuXG4gICAgICAgIGRvIHtcbiAgICAgICAgICAgIGRpdi5pbm5lckhUTUwgPSBcIjwhLS1baWYgZ3QgSUUgXCIgKyAoKyt2KSArIFwiXT48aT48L2k+PCFbZW5kaWZdLS0+XCI7XG4gICAgICAgIH1cbiAgICAgICAgd2hpbGUgKGFsbFswXSk7XG5cbiAgICAgICAgcmV0dXJuIHYgPiA0ID8gdiA6IHVuZGVmO1xuICAgIH0oKSk7XG5cbiAgICByZXR1cm4gdmVyc2lvbiA9PT0gaWVWZXJzaW9uO1xufTtcbiIsIlwidXNlIHN0cmljdFwiO1xuXG52YXIgdXRpbHMgPSBtb2R1bGUuZXhwb3J0cyA9IHt9O1xuXG4vKipcbiAqIExvb3BzIHRocm91Z2ggdGhlIGNvbGxlY3Rpb24gYW5kIGNhbGxzIHRoZSBjYWxsYmFjayBmb3IgZWFjaCBlbGVtZW50LiBpZiB0aGUgY2FsbGJhY2sgcmV0dXJucyB0cnV0aHksIHRoZSBsb29wIGlzIGJyb2tlbiBhbmQgcmV0dXJucyB0aGUgc2FtZSB2YWx1ZS5cbiAqIEBwdWJsaWNcbiAqIEBwYXJhbSB7Kn0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBsb29wIHRocm91Z2guIE5lZWRzIHRvIGhhdmUgYSBsZW5ndGggcHJvcGVydHkgc2V0IGFuZCBoYXZlIGluZGljZXMgc2V0IGZyb20gMCB0byBsZW5ndGggLSAxLlxuICogQHBhcmFtIHtmdW5jdGlvbn0gY2FsbGJhY2sgVGhlIGNhbGxiYWNrIHRvIGJlIGNhbGxlZCBmb3IgZWFjaCBlbGVtZW50LiBUaGUgZWxlbWVudCB3aWxsIGJlIGdpdmVuIGFzIGEgcGFyYW1ldGVyIHRvIHRoZSBjYWxsYmFjay4gSWYgdGhpcyBjYWxsYmFjayByZXR1cm5zIHRydXRoeSwgdGhlIGxvb3AgaXMgYnJva2VuIGFuZCB0aGUgc2FtZSB2YWx1ZSBpcyByZXR1cm5lZC5cbiAqIEByZXR1cm5zIHsqfSBUaGUgdmFsdWUgdGhhdCBhIGNhbGxiYWNrIGhhcyByZXR1cm5lZCAoaWYgdHJ1dGh5KS4gT3RoZXJ3aXNlIG5vdGhpbmcuXG4gKi9cbnV0aWxzLmZvckVhY2ggPSBmdW5jdGlvbihjb2xsZWN0aW9uLCBjYWxsYmFjaykge1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBjb2xsZWN0aW9uLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciByZXN1bHQgPSBjYWxsYmFjayhjb2xsZWN0aW9uW2ldKTtcbiAgICAgICAgaWYocmVzdWx0KSB7XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9XG4gICAgfVxufTtcbiIsIi8vSGVhdmlseSBpbnNwaXJlZCBieSBodHRwOi8vd3d3LmJhY2thbGxleWNvZGVyLmNvbS8yMDEzLzAzLzE4L2Nyb3NzLWJyb3dzZXItZXZlbnQtYmFzZWQtZWxlbWVudC1yZXNpemUtZGV0ZWN0aW9uL1xuXG5cInVzZSBzdHJpY3RcIjtcblxudmFyIGZvckVhY2ggPSByZXF1aXJlKFwiLi9jb2xsZWN0aW9uLXV0aWxzXCIpLmZvckVhY2g7XG52YXIgZWxlbWVudFV0aWxzTWFrZXIgPSByZXF1aXJlKFwiLi9lbGVtZW50LXV0aWxzXCIpO1xudmFyIGxpc3RlbmVySGFuZGxlck1ha2VyID0gcmVxdWlyZShcIi4vbGlzdGVuZXItaGFuZGxlclwiKTtcbnZhciBpZEdlbmVyYXRvck1ha2VyID0gcmVxdWlyZShcIi4vaWQtZ2VuZXJhdG9yXCIpO1xudmFyIGlkSGFuZGxlck1ha2VyID0gcmVxdWlyZShcIi4vaWQtaGFuZGxlclwiKTtcbnZhciByZXBvcnRlck1ha2VyID0gcmVxdWlyZShcIi4vcmVwb3J0ZXJcIik7XG5cbi8qKlxuICogQHR5cGVkZWYgaWRIYW5kbGVyXG4gKiBAdHlwZSB7b2JqZWN0fVxuICogQHByb3BlcnR5IHtmdW5jdGlvbn0gZ2V0IEdldHMgdGhlIHJlc2l6ZSBkZXRlY3RvciBpZCBvZiB0aGUgZWxlbWVudC5cbiAqIEBwcm9wZXJ0eSB7ZnVuY3Rpb259IHNldCBHZW5lcmF0ZSBhbmQgc2V0cyB0aGUgcmVzaXplIGRldGVjdG9yIGlkIG9mIHRoZSBlbGVtZW50LlxuICovXG5cbi8qKlxuICogQHR5cGVkZWYgT3B0aW9uc1xuICogQHR5cGUge29iamVjdH1cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gY2FsbE9uQWRkICAgIERldGVybWluZXMgaWYgbGlzdGVuZXJzIHNob3VsZCBiZSBjYWxsZWQgd2hlbiB0aGV5IGFyZSBnZXR0aW5nIGFkZGVkLiBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIERlZmF1bHQgaXMgdHJ1ZS4gSWYgdHJ1ZSwgdGhlIGxpc3RlbmVyIGlzIGd1YXJhbnRlZWQgdG8gYmUgY2FsbGVkIHdoZW4gaXQgaGFzIGJlZW4gYWRkZWQuIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgSWYgZmFsc2UsIHRoZSBsaXN0ZW5lciB3aWxsIG5vdCBiZSBndWFyZW50ZWVkIHRvIGJlIGNhbGxlZCB3aGVuIGl0IGhhcyBiZWVuIGFkZGVkIChkb2VzIG5vdCBwcmV2ZW50IGl0IGZyb20gYmVpbmcgY2FsbGVkKS5cbiAqIEBwcm9wZXJ0eSB7aWRIYW5kbGVyfSBpZEhhbmRsZXIgIEEgY3VzdG9tIGlkIGhhbmRsZXIgdGhhdCBpcyByZXNwb25zaWJsZSBmb3IgZ2VuZXJhdGluZywgc2V0dGluZyBhbmQgcmV0cmlldmluZyBpZCdzIGZvciBlbGVtZW50cy5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIElmIG5vdCBwcm92aWRlZCwgYSBkZWZhdWx0IGlkIGhhbmRsZXIgd2lsbCBiZSB1c2VkLlxuICogQHByb3BlcnR5IHtyZXBvcnRlcn0gcmVwb3J0ZXIgICAgQSBjdXN0b20gcmVwb3J0ZXIgdGhhdCBoYW5kbGVzIHJlcG9ydGluZyBsb2dzLCB3YXJuaW5ncyBhbmQgZXJyb3JzLiBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIElmIG5vdCBwcm92aWRlZCwgYSBkZWZhdWx0IGlkIGhhbmRsZXIgd2lsbCBiZSB1c2VkLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgSWYgc2V0IHRvIGZhbHNlLCB0aGVuIG5vdGhpbmcgd2lsbCBiZSByZXBvcnRlZC5cbiAqL1xuXG4vKipcbiAqIENyZWF0ZXMgYW4gZWxlbWVudCByZXNpemUgZGV0ZWN0b3IgaW5zdGFuY2UuXG4gKiBAcHVibGljXG4gKiBAcGFyYW0ge09wdGlvbnM/fSBvcHRpb25zIE9wdGlvbmFsIGdsb2JhbCBvcHRpb25zIG9iamVjdCB0aGF0IHdpbGwgZGVjaWRlIGhvdyB0aGlzIGluc3RhbmNlIHdpbGwgd29yay5cbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihvcHRpb25zKSB7XG4gICAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG5cbiAgICAvL09wdGlvbnMgdG8gYmUgdXNlZCBhcyBkZWZhdWx0IGZvciB0aGUgbGlzdGVuVG8gZnVuY3Rpb24uXG4gICAgdmFyIGdsb2JhbE9wdGlvbnMgPSB7fTtcbiAgICBnbG9iYWxPcHRpb25zLmNhbGxPbkFkZCA9ICEhZ2V0T3B0aW9uKG9wdGlvbnMsIFwiY2FsbE9uQWRkXCIsIHRydWUpO1xuXG4gICAgLy9pZEhhbmRsZXIgaXMgY3VycmVudGx5IG5vdCBhbiBvcHRpb24gdG8gdGhlIGxpc3RlblRvIGZ1bmN0aW9uLCBzbyBpdCBzaG91bGQgbm90IGJlIGFkZGVkIHRvIGdsb2JhbE9wdGlvbnMuXG4gICAgdmFyIGlkSGFuZGxlciA9IG9wdGlvbnMuaWRIYW5kbGVyO1xuXG4gICAgaWYoIWlkSGFuZGxlcikge1xuICAgICAgICB2YXIgaWRHZW5lcmF0b3IgPSBpZEdlbmVyYXRvck1ha2VyKCk7XG4gICAgICAgIHZhciBkZWZhdWx0SWRIYW5kbGVyID0gaWRIYW5kbGVyTWFrZXIoaWRHZW5lcmF0b3IpO1xuICAgICAgICBpZEhhbmRsZXIgPSBkZWZhdWx0SWRIYW5kbGVyO1xuICAgIH1cblxuICAgIC8vcmVwb3J0ZXIgaXMgY3VycmVudGx5IG5vdCBhbiBvcHRpb24gdG8gdGhlIGxpc3RlblRvIGZ1bmN0aW9uLCBzbyBpdCBzaG91bGQgbm90IGJlIGFkZGVkIHRvIGdsb2JhbE9wdGlvbnMuXG4gICAgdmFyIHJlcG9ydGVyID0gb3B0aW9ucy5yZXBvcnRlcjtcblxuICAgIGlmKCFyZXBvcnRlcikge1xuICAgICAgICAvL0lmIG9wdGlvbnMucmVwb3J0ZXIgaXMgZmFsc2UsIHRoZW4gdGhlIHJlcG9ydGVyIHNob3VsZCBiZSBxdWlldC5cbiAgICAgICAgdmFyIHF1aWV0ID0gcmVwb3J0ZXIgPT09IGZhbHNlO1xuICAgICAgICByZXBvcnRlciA9IHJlcG9ydGVyTWFrZXIocXVpZXQpO1xuICAgIH1cblxuICAgIHZhciBldmVudExpc3RlbmVySGFuZGxlciA9IGxpc3RlbmVySGFuZGxlck1ha2VyKGlkSGFuZGxlcik7XG4gICAgdmFyIGVsZW1lbnRVdGlscyA9IGVsZW1lbnRVdGlsc01ha2VyKGlkSGFuZGxlcik7XG5cbiAgICAvKipcbiAgICAgKiBNYWtlcyB0aGUgZ2l2ZW4gZWxlbWVudHMgcmVzaXplLWRldGVjdGFibGUgYW5kIHN0YXJ0cyBsaXN0ZW5pbmcgdG8gcmVzaXplIGV2ZW50cyBvbiB0aGUgZWxlbWVudHMuIENhbGxzIHRoZSBldmVudCBjYWxsYmFjayBmb3IgZWFjaCBldmVudCBmb3IgZWFjaCBlbGVtZW50LlxuICAgICAqIEBwdWJsaWNcbiAgICAgKiBAcGFyYW0ge09wdGlvbnM/fSBvcHRpb25zIE9wdGlvbmFsIG9wdGlvbnMgb2JqZWN0LiBUaGVzZSBvcHRpb25zIHdpbGwgb3ZlcnJpZGUgdGhlIGdsb2JhbCBvcHRpb25zLiBTb21lIG9wdGlvbnMgbWF5IG5vdCBiZSBvdmVycmlkZW4sIHN1Y2ggYXMgaWRIYW5kbGVyLlxuICAgICAqIEBwYXJhbSB7ZWxlbWVudFtdfGVsZW1lbnR9IGVsZW1lbnRzIFRoZSBnaXZlbiBhcnJheSBvZiBlbGVtZW50cyB0byBkZXRlY3QgcmVzaXplIGV2ZW50cyBvZi4gU2luZ2xlIGVsZW1lbnQgaXMgYWxzbyB2YWxpZC5cbiAgICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBsaXN0ZW5lciBUaGUgY2FsbGJhY2sgdG8gYmUgZXhlY3V0ZWQgZm9yIGVhY2ggcmVzaXplIGV2ZW50IGZvciBlYWNoIGVsZW1lbnQuXG4gICAgICovXG4gICAgZnVuY3Rpb24gbGlzdGVuVG8ob3B0aW9ucywgZWxlbWVudHMsIGxpc3RlbmVyKSB7XG4gICAgICAgIGZ1bmN0aW9uIG9uUmVzaXplQ2FsbGJhY2soZWxlbWVudCkge1xuICAgICAgICAgICAgdmFyIGxpc3RlbmVycyA9IGV2ZW50TGlzdGVuZXJIYW5kbGVyLmdldChlbGVtZW50KTtcblxuICAgICAgICAgICAgZm9yRWFjaChsaXN0ZW5lcnMsIGZ1bmN0aW9uKGxpc3RlbmVyKSB7XG4gICAgICAgICAgICAgICAgbGlzdGVuZXIoZWxlbWVudCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIG9uRWxlbWVudFJlYWR5VG9BZGRMaXN0ZW5lcihjYWxsT25BZGQsIGVsZW1lbnQsIGxpc3RlbmVyKSB7XG4gICAgICAgICAgICBldmVudExpc3RlbmVySGFuZGxlci5hZGQoZWxlbWVudCwgbGlzdGVuZXIpO1xuICAgICAgICAgICAgXG4gICAgICAgICAgICBpZihjYWxsT25BZGQpIHtcbiAgICAgICAgICAgICAgICBsaXN0ZW5lcihlbGVtZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vT3B0aW9ucyBvYmplY3QgbWF5IGJlIG9taXR0ZWQuXG4gICAgICAgIGlmKCFsaXN0ZW5lcikge1xuICAgICAgICAgICAgbGlzdGVuZXIgPSBlbGVtZW50cztcbiAgICAgICAgICAgIGVsZW1lbnRzID0gb3B0aW9ucztcbiAgICAgICAgICAgIG9wdGlvbnMgPSB7fTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKCFlbGVtZW50cykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQXQgbGVhc3Qgb25lIGVsZW1lbnQgcmVxdWlyZWQuXCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoIWxpc3RlbmVyKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJMaXN0ZW5lciByZXF1aXJlZC5cIik7XG4gICAgICAgIH1cblxuICAgICAgICBpZihlbGVtZW50cy5sZW5ndGggPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgZWxlbWVudHMgPSBbZWxlbWVudHNdO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGNhbGxPbkFkZCA9IGdldE9wdGlvbihvcHRpb25zLCBcImNhbGxPbkFkZFwiLCBnbG9iYWxPcHRpb25zLmNhbGxPbkFkZCk7XG5cbiAgICAgICAgZm9yRWFjaChlbGVtZW50cywgZnVuY3Rpb24oZWxlbWVudCkge1xuICAgICAgICAgICAgLy9UaGUgZWxlbWVudCBtYXkgY2hhbmdlIHNpemUgZGlyZWN0bHkgYWZ0ZXIgdGhlIGNhbGwgdG8gbGlzdGVuVG8sIHdoaWNoIHdvdWxkIGJlIHVuYWJsZSB0byBkZXRlY3QgaXQgYmVjYXVzZVxuICAgICAgICAgICAgLy90aGUgYXN5bmMgYWRkaW5nIG9mIHRoZSBvYmplY3QuIEJ5IGNoZWNraW5nIHRoZSBzaXplIGJlZm9yZSBhbmQgYWZ0ZXIsIHRoZSBzaXplIGNoYW5nZSBjYW4gc3RpbGwgYmUgZGV0ZWN0ZWRcbiAgICAgICAgICAgIC8vYW5kIHRoZSBsaXN0ZW5lciBjYW4gYmUgY2FsbGVkIGFjY29yZGluZ2x5LlxuICAgICAgICAgICAgdmFyIHByZVdpZHRoID0gZWxlbWVudC5vZmZzZXRXaWR0aDtcbiAgICAgICAgICAgIHZhciBwcmVIZWlnaHQgPSBlbGVtZW50Lm9mZnNldEhlaWdodDtcblxuICAgICAgICAgICAgaWYoIWVsZW1lbnRVdGlscy5pc0RldGVjdGFibGUoZWxlbWVudCkpIHtcbiAgICAgICAgICAgICAgICAvL1RoZSBlbGVtZW50IGlzIG5vdCBwcmVwYXJlZCB0byBiZSBkZXRlY3RhYmxlLCBzbyBkbyBwcmVwYXJlIGl0IGFuZCBhZGQgYSBsaXN0ZW5lciB0byBpdC5cbiAgICAgICAgICAgICAgICByZXR1cm4gZWxlbWVudFV0aWxzLm1ha2VEZXRlY3RhYmxlKHJlcG9ydGVyLCBlbGVtZW50LCBmdW5jdGlvbihlbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIGVsZW1lbnRVdGlscy5hZGRMaXN0ZW5lcihlbGVtZW50LCBvblJlc2l6ZUNhbGxiYWNrKTtcbiAgICAgICAgICAgICAgICAgICAgb25FbGVtZW50UmVhZHlUb0FkZExpc3RlbmVyKGNhbGxPbkFkZCwgZWxlbWVudCwgbGlzdGVuZXIpO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vT25seSBoZXJlIHRoZSB1bmNhdWdodCByZXNpemUgbWF5IG9jY3VyIChzaW5jZSB0aGlzIGNvZGUgaXMgYXN5bmMpLlxuICAgICAgICAgICAgICAgICAgICAvL0NoZWNrIGlmIHRoZSBzaXplIGlzIHRoZSBzYW1lIGFzIHdoZW4gYWRkaW5nIHRoZSBsaXN0ZW5lci5cbiAgICAgICAgICAgICAgICAgICAgdmFyIHBvc3RXaWR0aCA9IGVsZW1lbnQub2Zmc2V0V2lkdGg7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwb3N0SGVpZ2h0ID0gZWxlbWVudC5vZmZzZXRIZWlnaHQ7XG5cbiAgICAgICAgICAgICAgICAgICAgLy9JZiBjYWxsT25BZGQgaXMgdHJ1ZSwgdGhlbiB0aGUgbGlzdGVuZXIgd2lsbCBoYXZlIGJlZW4gY2FsbGVkIGVpdGhlciB3YXksIHNvIG5vIG5lZWQgdG8gY2FsbCB0aGUgbGlzdGVuZXIgbWFudWFsbHkgdGhlbi5cbiAgICAgICAgICAgICAgICAgICAgaWYoIWNhbGxPbkFkZCAmJiAocHJlV2lkdGggIT09IHBvc3RXaWR0aCB8fCBwcmVIZWlnaHQgIT09IHBvc3RIZWlnaHQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvL1RoZSBlbGVtZW50IHdhcyBjaGFuZ2VkIHdoaWxlIHRoZSBvYmplY3Qgd2FzIGJlaW5nIGFkZGVkLiBDYWxsIHRoZSBsaXN0ZW5lci5cbiAgICAgICAgICAgICAgICAgICAgICAgIGxpc3RlbmVyKGVsZW1lbnQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBcbiAgICAgICAgICAgIC8vVGhlIGVsZW1lbnQgaGFzIGJlZW4gcHJlcGFyZWQgdG8gYmUgZGV0ZWN0YWJsZSBhbmQgaXMgcmVhZHkgdG8gYmUgbGlzdGVuZWQgdG8uXG4gICAgICAgICAgICBvbkVsZW1lbnRSZWFkeVRvQWRkTGlzdGVuZXIoY2FsbE9uQWRkLCBlbGVtZW50LCBsaXN0ZW5lcik7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICAgIGxpc3RlblRvOiBsaXN0ZW5Ub1xuICAgIH07XG59O1xuXG5mdW5jdGlvbiBnZXRPcHRpb24ob3B0aW9ucywgbmFtZSwgZGVmYXVsdFZhbHVlKSB7XG4gICAgdmFyIHZhbHVlID0gb3B0aW9uc1tuYW1lXTtcblxuICAgIGlmKCh2YWx1ZSA9PT0gdW5kZWZpbmVkIHx8IHZhbHVlID09PSBudWxsKSAmJiBkZWZhdWx0VmFsdWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICByZXR1cm4gZGVmYXVsdFZhbHVlO1xuICAgIH1cblxuICAgIHJldHVybiB2YWx1ZTtcbn1cbiIsIlwidXNlIHN0cmljdFwiO1xuXG52YXIgZm9yRWFjaCA9IHJlcXVpcmUoXCIuL2NvbGxlY3Rpb24tdXRpbHNcIikuZm9yRWFjaDtcbnZhciBicm93c2VyRGV0ZWN0b3IgPSByZXF1aXJlKFwiLi9icm93c2VyLWRldGVjdG9yXCIpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGlkSGFuZGxlcikge1xuICAgIC8qKlxuICAgICAqIFRlbGxzIGlmIHRoZSBlbGVtZW50IGhhcyBiZWVuIG1hZGUgZGV0ZWN0YWJsZSBhbmQgcmVhZHkgdG8gYmUgbGlzdGVuZWQgZm9yIHJlc2l6ZSBldmVudHMuXG4gICAgICogQHB1YmxpY1xuICAgICAqIEBwYXJhbSB7ZWxlbWVudH0gVGhlIGVsZW1lbnQgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgb3IgZmFsc2UgZGVwZW5kaW5nIG9uIGlmIHRoZSBlbGVtZW50IGlzIGRldGVjdGFibGUgb3Igbm90LlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzRGV0ZWN0YWJsZShlbGVtZW50KSB7XG4gICAgICAgIGlmKGJyb3dzZXJEZXRlY3Rvci5pc0lFKDgpKSB7XG4gICAgICAgICAgICAvL0lFIDggZG9lcyBub3QgdXNlIHRoZSBvYmplY3QgbWV0aG9kLlxuICAgICAgICAgICAgLy9DaGVjayBvbmx5IGlmIHRoZSBlbGVtZW50IGhhcyBiZWVuIGdpdmVuIGFuIGlkLlxuICAgICAgICAgICAgcmV0dXJuICEhaWRIYW5kbGVyLmdldChlbGVtZW50KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiAhIWdldE9iamVjdChlbGVtZW50KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBZGRzIGEgcmVzaXplIGV2ZW50IGxpc3RlbmVyIHRvIHRoZSBlbGVtZW50LlxuICAgICAqIEBwdWJsaWNcbiAgICAgKiBAcGFyYW0ge2VsZW1lbnR9IGVsZW1lbnQgVGhlIGVsZW1lbnQgdGhhdCBzaG91bGQgaGF2ZSB0aGUgbGlzdGVuZXIgYWRkZWQuXG4gICAgICogQHBhcmFtIHtmdW5jdGlvbn0gbGlzdGVuZXIgVGhlIGxpc3RlbmVyIGNhbGxiYWNrIHRvIGJlIGNhbGxlZCBmb3IgZWFjaCByZXNpemUgZXZlbnQgb2YgdGhlIGVsZW1lbnQuIFRoZSBlbGVtZW50IHdpbGwgYmUgZ2l2ZW4gYXMgYSBwYXJhbWV0ZXIgdG8gdGhlIGxpc3RlbmVyIGNhbGxiYWNrLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGFkZExpc3RlbmVyKGVsZW1lbnQsIGxpc3RlbmVyKSB7XG4gICAgICAgIGlmKCFpc0RldGVjdGFibGUoZWxlbWVudCkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkVsZW1lbnQgaXMgbm90IGRldGVjdGFibGUuXCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gbGlzdGVuZXJQcm94eSgpIHtcbiAgICAgICAgICAgIGxpc3RlbmVyKGVsZW1lbnQpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoYnJvd3NlckRldGVjdG9yLmlzSUUoOCkpIHtcbiAgICAgICAgICAgIC8vSUUgOCBkb2VzIG5vdCBzdXBwb3J0IG9iamVjdCwgYnV0IHN1cHBvcnRzIHRoZSByZXNpemUgZXZlbnQgZGlyZWN0bHkgb24gZWxlbWVudHMuXG4gICAgICAgICAgICBlbGVtZW50LmF0dGFjaEV2ZW50KFwib25yZXNpemVcIiwgbGlzdGVuZXJQcm94eSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2YXIgb2JqZWN0ID0gZ2V0T2JqZWN0KGVsZW1lbnQpO1xuICAgICAgICAgICAgb2JqZWN0LmNvbnRlbnREb2N1bWVudC5kZWZhdWx0Vmlldy5hZGRFdmVudExpc3RlbmVyKFwicmVzaXplXCIsIGxpc3RlbmVyUHJveHkpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWFrZXMgYW4gZWxlbWVudCBkZXRlY3RhYmxlIGFuZCByZWFkeSB0byBiZSBsaXN0ZW5lZCBmb3IgcmVzaXplIGV2ZW50cy4gV2lsbCBjYWxsIHRoZSBjYWxsYmFjayB3aGVuIHRoZSBlbGVtZW50IGlzIHJlYWR5IHRvIGJlIGxpc3RlbmVkIGZvciByZXNpemUgY2hhbmdlcy5cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7ZWxlbWVudH0gZWxlbWVudCBUaGUgZWxlbWVudCB0byBtYWtlIGRldGVjdGFibGVcbiAgICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBjYWxsYmFjayBUaGUgY2FsbGJhY2sgdG8gYmUgY2FsbGVkIHdoZW4gdGhlIGVsZW1lbnQgaXMgcmVhZHkgdG8gYmUgbGlzdGVuZWQgZm9yIHJlc2l6ZSBjaGFuZ2VzLiBXaWxsIGJlIGNhbGxlZCB3aXRoIHRoZSBlbGVtZW50IGFzIGZpcnN0IHBhcmFtZXRlci5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBtYWtlRGV0ZWN0YWJsZShyZXBvcnRlciwgZWxlbWVudCwgY2FsbGJhY2spIHtcbiAgICAgICAgZnVuY3Rpb24gaW5qZWN0T2JqZWN0KGlkLCBlbGVtZW50LCBjYWxsYmFjaykge1xuICAgICAgICAgICAgdmFyIE9CSkVDVF9TVFlMRSA9IFwiZGlzcGxheTogYmxvY2s7IHBvc2l0aW9uOiBhYnNvbHV0ZTsgdG9wOiAwOyBsZWZ0OiAwOyB3aWR0aDogMTAwJTsgaGVpZ2h0OiAxMDAlOyBib3JkZXI6IG5vbmU7IHBhZGRpbmc6IDA7IG1hcmdpbjogMDsgb3BhY2l0eTogMDsgei1pbmRleDogLTEwMDA7IHBvaW50ZXItZXZlbnRzOiBub25lO1wiO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBvbk9iamVjdExvYWQoKSB7XG4gICAgICAgICAgICAgICAgLypqc2hpbnQgdmFsaWR0aGlzOnRydWUgKi9cblxuICAgICAgICAgICAgICAgIC8vQ3JlYXRlIHRoZSBzdHlsZSBlbGVtZW50IHRvIGJlIGFkZGVkIHRvIHRoZSBvYmplY3QuXG4gICAgICAgICAgICAgICAgdmFyIG9iamVjdERvY3VtZW50ID0gdGhpcy5jb250ZW50RG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgdmFyIHN0eWxlID0gb2JqZWN0RG9jdW1lbnQuY3JlYXRlRWxlbWVudChcInN0eWxlXCIpO1xuICAgICAgICAgICAgICAgIHN0eWxlLmlubmVySFRNTCA9IFwiaHRtbCwgYm9keSB7IG1hcmdpbjogMDsgcGFkZGluZzogMCB9IGRpdiB7IC13ZWJraXQtdHJhbnNpdGlvbjogb3BhY2l0eSAwLjAxczsgLW1zLXRyYW5zaXRpb246IG9wYWNpdHkgMC4wMXM7IC1vLXRyYW5zaXRpb246IG9wYWNpdHkgMC4wMXM7IHRyYW5zaXRpb246IG9wYWNpdHkgMC4wMXM7IG9wYWNpdHk6IDA7IH1cIjtcblxuICAgICAgICAgICAgICAgIC8vVE9ETzogUmVtb3ZlIGFueSBzdHlsZXMgdGhhdCBoYXMgYmVlbiBzZXQgb24gdGhlIG9iamVjdC4gT25seSB0aGUgc3R5bGUgYWJvdmUgc2hvdWxkIGJlIHN0eWxpbmcgdGhlIG9iamVjdC5cblxuICAgICAgICAgICAgICAgIC8vQXBwZW5kIHRoZSBzdHlsZSB0byB0aGUgb2JqZWN0LlxuICAgICAgICAgICAgICAgIG9iamVjdERvY3VtZW50LmhlYWQuYXBwZW5kQ2hpbGQoc3R5bGUpO1xuXG4gICAgICAgICAgICAgICAgLy9UT0RPOiBJcyB0aGlzIG5lZWRlZCBoZXJlP1xuICAgICAgICAgICAgICAgIC8vdGhpcy5zdHlsZS5jc3NUZXh0ID0gT0JKRUNUX1NUWUxFO1xuXG4gICAgICAgICAgICAgICAgLy9Ob3RpZnkgdGhhdCB0aGUgZWxlbWVudCBpcyByZWFkeSB0byBiZSBsaXN0ZW5lZCB0by5cbiAgICAgICAgICAgICAgICBjYWxsYmFjayhlbGVtZW50KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy9UaGUgdGFyZ2V0IGVsZW1lbnQgbmVlZHMgdG8gYmUgcG9zaXRpb25lZCAoZXZlcnl0aGluZyBleGNlcHQgc3RhdGljKSBzbyB0aGUgYWJzb2x1dGUgcG9zaXRpb25lZCBvYmplY3Qgd2lsbCBiZSBwb3NpdGlvbmVkIHJlbGF0aXZlIHRvIHRoZSB0YXJnZXQgZWxlbWVudC5cbiAgICAgICAgICAgIHZhciBzdHlsZSA9IGdldENvbXB1dGVkU3R5bGUoZWxlbWVudCk7XG4gICAgICAgICAgICBpZihzdHlsZS5wb3NpdGlvbiA9PT0gXCJzdGF0aWNcIikge1xuICAgICAgICAgICAgICAgIGVsZW1lbnQuc3R5bGUucG9zaXRpb24gPSBcInJlbGF0aXZlXCI7XG5cbiAgICAgICAgICAgICAgICB2YXIgcmVtb3ZlUmVsYXRpdmVTdHlsZXMgPSBmdW5jdGlvbihyZXBvcnRlciwgZWxlbWVudCwgc3R5bGUsIHByb3BlcnR5KSB7XG4gICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGdldE51bWVyaWNhbFZhbHVlKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUucmVwbGFjZSgvW14tXFxkXFwuXS9nLCBcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IHN0eWxlW3Byb3BlcnR5XTtcblxuICAgICAgICAgICAgICAgICAgICBpZih2YWx1ZSAhPT0gXCJhdXRvXCIgJiYgZ2V0TnVtZXJpY2FsVmFsdWUodmFsdWUpICE9PSBcIjBcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVwb3J0ZXIud2FybihcIkFuIGVsZW1lbnQgdGhhdCBpcyBwb3NpdGlvbmVkIHN0YXRpYyBoYXMgc3R5bGUuXCIgKyBwcm9wZXJ0eSArIFwiPVwiICsgdmFsdWUgKyBcIiB3aGljaCBpcyBpZ25vcmVkIGR1ZSB0byB0aGUgc3RhdGljIHBvc2l0aW9uaW5nLiBUaGUgZWxlbWVudCB3aWxsIG5lZWQgdG8gYmUgcG9zaXRpb25lZCByZWxhdGVpdmUsIHNvIHRoZSBzdHlsZS5cIiArIHByb3BlcnR5ICsgXCIgd2lsbCBiZSBzZXQgdG8gMC4gRWxlbWVudDogXCIsIGVsZW1lbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5zdHlsZVtwcm9wZXJ0eV0gPSAwO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgIC8vQ2hlY2sgc28gdGhhdCB0aGVyZSBhcmUgbm8gYWNjaWRlbnRhbCBzdHlsZXMgdGhhdCB3aWxsIG1ha2UgdGhlIGVsZW1lbnQgc3R5bGVkIGRpZmZlcmVudGx5IG5vdyB0aGF0IGlzIGlzIHJlbGF0aXZlLlxuICAgICAgICAgICAgICAgIC8vSWYgdGhlcmUgYXJlIGFueSwgc2V0IHRoZW0gdG8gMCAodGhpcyBzaG91bGQgYmUgb2theSB3aXRoIHRoZSB1c2VyIHNpbmNlIHRoZSBzdHlsZSBwcm9wZXJ0aWVzIGRpZCBub3RoaW5nIGJlZm9yZSBbc2luY2UgdGhlIGVsZW1lbnQgd2FzIHBvc2l0aW9uZWQgc3RhdGljXSBhbnl3YXkpLlxuICAgICAgICAgICAgICAgIHJlbW92ZVJlbGF0aXZlU3R5bGVzKHJlcG9ydGVyLCBlbGVtZW50LCBzdHlsZSwgXCJ0b3BcIik7XG4gICAgICAgICAgICAgICAgcmVtb3ZlUmVsYXRpdmVTdHlsZXMocmVwb3J0ZXIsIGVsZW1lbnQsIHN0eWxlLCBcInJpZ2h0XCIpO1xuICAgICAgICAgICAgICAgIHJlbW92ZVJlbGF0aXZlU3R5bGVzKHJlcG9ydGVyLCBlbGVtZW50LCBzdHlsZSwgXCJib3R0b21cIik7XG4gICAgICAgICAgICAgICAgcmVtb3ZlUmVsYXRpdmVTdHlsZXMocmVwb3J0ZXIsIGVsZW1lbnQsIHN0eWxlLCBcImxlZnRcIik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vQWRkIGFuIG9iamVjdCBlbGVtZW50IGFzIGEgY2hpbGQgdG8gdGhlIHRhcmdldCBlbGVtZW50IHRoYXQgd2lsbCBiZSBsaXN0ZW5lZCB0byBmb3IgcmVzaXplIGV2ZW50cy5cbiAgICAgICAgICAgIHZhciBvYmplY3QgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwib2JqZWN0XCIpO1xuICAgICAgICAgICAgb2JqZWN0LnR5cGUgPSBcInRleHQvaHRtbFwiO1xuICAgICAgICAgICAgb2JqZWN0LnN0eWxlLmNzc1RleHQgPSBPQkpFQ1RfU1RZTEU7XG4gICAgICAgICAgICBvYmplY3Qub25sb2FkID0gb25PYmplY3RMb2FkO1xuICAgICAgICAgICAgb2JqZWN0LnNldEF0dHJpYnV0ZShcImVyZC1vYmplY3QtaWRcIiwgaWQpO1xuXG4gICAgICAgICAgICAvL1NhZmFyaTogVGhpcyBtdXN0IG9jY3VyIGJlZm9yZSBhZGRpbmcgdGhlIG9iamVjdCB0byB0aGUgRE9NLlxuICAgICAgICAgICAgLy9JRTogRG9lcyBub3QgbGlrZSB0aGF0IHRoaXMgaGFwcGVucyBiZWZvcmUsIGV2ZW4gaWYgaXQgaXMgYWxzbyBhZGRlZCBhZnRlci5cbiAgICAgICAgICAgIGlmKCFicm93c2VyRGV0ZWN0b3IuaXNJRSgpKSB7XG4gICAgICAgICAgICAgICAgb2JqZWN0LmRhdGEgPSBcImFib3V0OmJsYW5rXCI7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGVsZW1lbnQuYXBwZW5kQ2hpbGQob2JqZWN0KTtcblxuICAgICAgICAgICAgLy9JRTogVGhpcyBtdXN0IG9jY3VyIGFmdGVyIGFkZGluZyB0aGUgb2JqZWN0IHRvIHRoZSBET00uXG4gICAgICAgICAgICBpZihicm93c2VyRGV0ZWN0b3IuaXNJRSgpKSB7XG4gICAgICAgICAgICAgICAgb2JqZWN0LmRhdGEgPSBcImFib3V0OmJsYW5rXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvL0NyZWF0ZSBhbiB1bmlxdWUgZXJkLXRhcmdldC1pZCBmb3IgdGhlIHRhcmdldCBlbGVtZW50LCBzbyB0aGF0IGV2ZW50IGxpc3RlbmVycyBjYW4gYmUgaWRlbnRpZmllZCB0byB0aGlzIGVsZW1lbnQuXG4gICAgICAgIHZhciBpZCA9IGlkSGFuZGxlci5zZXQoZWxlbWVudCk7XG5cbiAgICAgICAgaWYoYnJvd3NlckRldGVjdG9yLmlzSUUoOCkpIHtcbiAgICAgICAgICAgIC8vSUUgOCBkb2VzIG5vdCBzdXBwb3J0IG9iamVjdHMgcHJvcGVybHkuIEx1Y2tpbHkgdGhleSBkbyBzdXBwb3J0IHRoZSByZXNpemUgZXZlbnQuXG4gICAgICAgICAgICAvL1NvIGRvIG5vdCBpbmplY3QgdGhlIG9iamVjdCBhbmQgbm90aWZ5IHRoYXQgdGhlIGVsZW1lbnQgaXMgYWxyZWFkeSByZWFkeSB0byBiZSBsaXN0ZW5lZCB0by5cbiAgICAgICAgICAgIC8vVGhlIGV2ZW50IGhhbmRsZXIgZm9yIHRoZSByZXNpemUgZXZlbnQgaXMgYXR0YWNoZWQgaW4gdGhlIHV0aWxzLmFkZExpc3RlbmVyIGluc3RlYWQuXG4gICAgICAgICAgICBjYWxsYmFjayhlbGVtZW50KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGluamVjdE9iamVjdChpZCwgZWxlbWVudCwgY2FsbGJhY2spO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgY2hpbGQgb2JqZWN0IG9mIHRoZSB0YXJnZXQgZWxlbWVudC5cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7ZWxlbWVudH0gZWxlbWVudCBUaGUgdGFyZ2V0IGVsZW1lbnQuXG4gICAgICogQHJldHVybnMgVGhlIG9iamVjdCBlbGVtZW50IG9mIHRoZSB0YXJnZXQuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0T2JqZWN0KGVsZW1lbnQpIHtcbiAgICAgICAgcmV0dXJuIGZvckVhY2goZWxlbWVudC5jaGlsZHJlbiwgZnVuY3Rpb24oY2hpbGQpIHtcbiAgICAgICAgICAgIGlmKGNoaWxkLmhhc0F0dHJpYnV0ZShcImVyZC1vYmplY3QtaWRcIikpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gY2hpbGQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICAgIGlzRGV0ZWN0YWJsZTogaXNEZXRlY3RhYmxlLFxuICAgICAgICBtYWtlRGV0ZWN0YWJsZTogbWFrZURldGVjdGFibGUsXG4gICAgICAgIGFkZExpc3RlbmVyOiBhZGRMaXN0ZW5lcixcbiAgICB9O1xufTtcbiIsIlwidXNlIHN0cmljdFwiO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBpZENvdW50ID0gMTtcblxuICAgIC8qKlxuICAgICAqIEdlbmVyYXRlcyBhIG5ldyB1bmlxdWUgaWQgaW4gdGhlIGNvbnRleHQuXG4gICAgICogQHB1YmxpY1xuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IEEgdW5pcXVlIGlkIGluIHRoZSBjb250ZXh0LlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdlbmVyYXRlKCkge1xuICAgICAgICByZXR1cm4gaWRDb3VudCsrO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICAgIGdlbmVyYXRlOiBnZW5lcmF0ZVxuICAgIH07XG59O1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oaWRHZW5lcmF0b3IpIHtcblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIHJlc2l6ZSBkZXRlY3RvciBpZCBvZiB0aGUgZWxlbWVudC5cbiAgICAgKiBAcHVibGljXG4gICAgICogQHBhcmFtIHtlbGVtZW50fSBUaGUgdGFyZ2V0IGVsZW1lbnQgdG8gZ2V0IHRoZSBpZCBvZi5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfG51bWJlcn0gVGhlIGlkIG9mIHRoZSBlbGVtZW50LlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldElkKGVsZW1lbnQpIHtcbiAgICAgICAgcmV0dXJuIGVsZW1lbnQuZ2V0QXR0cmlidXRlKFwiZXJkLXRhcmdldC1pZFwiKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSByZXNpemUgZGV0ZWN0b3IgaWQgb2YgdGhlIGVsZW1lbnQuXG4gICAgICogQHB1YmxpY1xuICAgICAqIEBwYXJhbSB7ZWxlbWVudH0gVGhlIHRhcmdldCBlbGVtZW50IHRvIHNldCB0aGUgaWQgdG8uXG4gICAgICogQHBhcmFtIHtzdHJpbmc/fSBBbiBvcHRpb25hbCBpZCB0byBzZXQgdG8gdGhlIGVsZW1lbnQuIElmIG5vdCBzcGVjaWZpZWQsIGFuIGlkIHdpbGwgYmUgZ2VuZXJhdGVkLiBBbGwgaWQncyBtdXN0IGJlIHVuaXF1ZS5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfG51bWJlcn0gVGhlIGlkIG9mIHRoZSBlbGVtZW50LlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHNldElkKGVsZW1lbnQsIGlkKSB7XG4gICAgICAgIGlmKCFpZCAmJiBpZCAhPT0gMCkge1xuICAgICAgICAgICAgLy9OdW1iZXIgc2hvdWxkIGJlIGdlbmVyYXRlZC5cbiAgICAgICAgICAgIGlkID0gaWRHZW5lcmF0b3IuZ2VuZXJhdGUoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGVsZW1lbnQuc2V0QXR0cmlidXRlKFwiZXJkLXRhcmdldC1pZFwiLCBpZCk7XG5cbiAgICAgICAgcmV0dXJuIGlkO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICAgIGdldDogZ2V0SWQsXG4gICAgICAgIHNldDogc2V0SWRcbiAgICB9O1xufTtcbiIsIlwidXNlIHN0cmljdFwiO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGlkSGFuZGxlcikge1xuICAgIHZhciBldmVudExpc3RlbmVycyA9IHt9O1xuXG4gICAgLyoqXG4gICAgICogR2V0cyBhbGwgbGlzdGVuZXJzIGZvciB0aGUgZ2l2ZW4gZWxlbWVudC5cbiAgICAgKiBAcHVibGljXG4gICAgICogQHBhcmFtIHtlbGVtZW50fSBlbGVtZW50IFRoZSBlbGVtZW50IHRvIGdldCBhbGwgbGlzdGVuZXJzIGZvci5cbiAgICAgKiBAcmV0dXJucyBBbGwgbGlzdGVuZXJzIGZvciB0aGUgZ2l2ZW4gZWxlbWVudC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRMaXN0ZW5lcnMoZWxlbWVudCkge1xuICAgICAgICByZXR1cm4gZXZlbnRMaXN0ZW5lcnNbaWRIYW5kbGVyLmdldChlbGVtZW50KV07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU3RvcmVzIHRoZSBnaXZlbiBsaXN0ZW5lciBmb3IgdGhlIGdpdmVuIGVsZW1lbnQuIFdpbGwgbm90IGFjdHVhbGx5IGFkZCB0aGUgbGlzdGVuZXIgdG8gdGhlIGVsZW1lbnQuXG4gICAgICogQHB1YmxpY1xuICAgICAqIEBwYXJhbSB7ZWxlbWVudH0gZWxlbWVudCBUaGUgZWxlbWVudCB0aGF0IHNob3VsZCBoYXZlIHRoZSBsaXN0ZW5lciBhZGRlZC5cbiAgICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBsaXN0ZW5lciBUaGUgY2FsbGJhY2sgdGhhdCB0aGUgZWxlbWVudCBoYXMgYWRkZWQuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYWRkTGlzdGVuZXIoZWxlbWVudCwgbGlzdGVuZXIpIHtcbiAgICAgICAgdmFyIGlkID0gaWRIYW5kbGVyLmdldChlbGVtZW50KTtcblxuICAgICAgICBpZighZXZlbnRMaXN0ZW5lcnNbaWRdKSB7XG4gICAgICAgICAgICBldmVudExpc3RlbmVyc1tpZF0gPSBbXTtcbiAgICAgICAgfVxuXG4gICAgICAgIGV2ZW50TGlzdGVuZXJzW2lkXS5wdXNoKGxpc3RlbmVyKTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgICBnZXQ6IGdldExpc3RlbmVycyxcbiAgICAgICAgYWRkOiBhZGRMaXN0ZW5lclxuICAgIH07XG59O1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbi8qIGdsb2JhbCBjb25zb2xlOiBmYWxzZSAqL1xuXG4vKipcbiAqIFJlcG9ydGVyIHRoYXQgaGFuZGxlcyB0aGUgcmVwb3J0aW5nIG9mIGxvZ3MsIHdhcm5pbmdzIGFuZCBlcnJvcnMuXG4gKiBAcHVibGljXG4gKiBAcGFyYW0ge2Jvb2xlYW59IHF1aWV0IFRlbGxzIGlmIHRoZSByZXBvcnRlciBzaG91bGQgYmUgcXVpZXQgb3Igbm90LlxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKHF1aWV0KSB7XG4gICAgdmFyIG5vb3AgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vRG9lcyBub3RoaW5nLlxuICAgIH07XG5cbiAgICB2YXIgcmVwb3J0ZXIgPSB7XG4gICAgICAgIGxvZzogbm9vcCxcbiAgICAgICAgd2Fybjogbm9vcCxcbiAgICAgICAgZXJyb3I6IG5vb3BcbiAgICB9O1xuXG4gICAgaWYoIXF1aWV0ICYmIHdpbmRvdy5jb25zb2xlKSB7XG4gICAgICAgIHJlcG9ydGVyLmxvZyA9IGNvbnNvbGUubG9nO1xuICAgICAgICByZXBvcnRlci53YXJuID0gY29uc29sZS53YXJuO1xuICAgICAgICByZXBvcnRlci5lcnJvciA9IGNvbnNvbGUuZXJyb3I7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlcG9ydGVyO1xufTsiXX0= |
/*! | ||
* element-resize-detector 0.1.4 (2015-02-02, 12:04) | ||
* element-resize-detector 0.2.1 (2015-03-23, 19:27) | ||
* https://github.com/wnr/element-resize-detector | ||
@@ -7,5 +7,42 @@ * Licensed under MIT | ||
!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.elementResizeDetectorMaker=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ | ||
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.elementResizeDetectorMaker = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ | ||
"use strict"; | ||
var detector = module.exports = {}; | ||
detector.isIE = function(version) { | ||
function isAnyIeVersion() { | ||
var agent = navigator.userAgent.toLowerCase(); | ||
return agent.indexOf("msie") !== -1 || agent.indexOf("trident") !== -1; | ||
} | ||
if(!isAnyIeVersion()) { | ||
return false; | ||
} | ||
if(!version) { | ||
return true; | ||
} | ||
//Shamelessly stolen from https://gist.github.com/padolsey/527683 | ||
var ieVersion = (function(){ | ||
var undef, | ||
v = 3, | ||
div = document.createElement("div"), | ||
all = div.getElementsByTagName("i"); | ||
do { | ||
div.innerHTML = "<!--[if gt IE " + (++v) + "]><i></i><![endif]-->"; | ||
} | ||
while (all[0]); | ||
return v > 4 ? v : undef; | ||
}()); | ||
return version === ieVersion; | ||
}; | ||
},{}],2:[function(require,module,exports){ | ||
"use strict"; | ||
var utils = module.exports = {}; | ||
@@ -29,3 +66,3 @@ | ||
},{}],2:[function(require,module,exports){ | ||
},{}],3:[function(require,module,exports){ | ||
//Heavily inspired by http://www.backalleycoder.com/2013/03/18/cross-browser-event-based-element-resize-detection/ | ||
@@ -36,29 +73,100 @@ | ||
var forEach = require("./collection-utils").forEach; | ||
var elementUtils = require("./element-utils"); | ||
var elementUtilsMaker = require("./element-utils"); | ||
var listenerHandlerMaker = require("./listener-handler"); | ||
var idGeneratorMaker = require("./id-generator"); | ||
var listenerHandlerMaker = require("./listener-handler"); | ||
var idHandlerMaker = require("./id-handler"); | ||
var reporterMaker = require("./reporter"); | ||
/** | ||
* @typedef idHandler | ||
* @type {object} | ||
* @property {function} get Gets the resize detector id of the element. | ||
* @property {function} set Generate and sets the resize detector id of the element. | ||
*/ | ||
/** | ||
* @typedef Options | ||
* @type {object} | ||
* @property {boolean} callOnAdd Determines if listeners should be called when they are getting added. | ||
Default is true. If true, the listener is guaranteed to be called when it has been added. | ||
If false, the listener will not be guarenteed to be called when it has been added (does not prevent it from being called). | ||
* @property {idHandler} idHandler A custom id handler that is responsible for generating, setting and retrieving id's for elements. | ||
If not provided, a default id handler will be used. | ||
* @property {reporter} reporter A custom reporter that handles reporting logs, warnings and errors. | ||
If not provided, a default id handler will be used. | ||
If set to false, then nothing will be reported. | ||
*/ | ||
/** | ||
* Creates an element resize detector instance. | ||
* @public | ||
* @param {Options?} options Optional global options object that will decide how this instance will work. | ||
*/ | ||
module.exports = function(options) { | ||
options = options || {}; | ||
var allowMultipleListeners = options.allowMultipleListeners === undefined ? true : false; | ||
var eventListenerHandler = listenerHandlerMaker(); | ||
var idGenerator = idGeneratorMaker(); | ||
//Options to be used as default for the listenTo function. | ||
var globalOptions = {}; | ||
globalOptions.callOnAdd = !!getOption(options, "callOnAdd", true); | ||
//idHandler is currently not an option to the listenTo function, so it should not be added to globalOptions. | ||
var idHandler = options.idHandler; | ||
if(!idHandler) { | ||
var idGenerator = idGeneratorMaker(); | ||
var defaultIdHandler = idHandlerMaker(idGenerator); | ||
idHandler = defaultIdHandler; | ||
} | ||
//reporter is currently not an option to the listenTo function, so it should not be added to globalOptions. | ||
var reporter = options.reporter; | ||
if(!reporter) { | ||
//If options.reporter is false, then the reporter should be quiet. | ||
var quiet = reporter === false; | ||
reporter = reporterMaker(quiet); | ||
} | ||
var eventListenerHandler = listenerHandlerMaker(idHandler); | ||
var elementUtils = elementUtilsMaker(idHandler); | ||
/** | ||
* Makes the given elements resize-detectable and starts listening to resize events on the elements. Calls the event callback for each event for each element. | ||
* @public | ||
* @param {Options?} options Optional options object. These options will override the global options. Some options may not be overriden, such as idHandler. | ||
* @param {element[]|element} elements The given array of elements to detect resize events of. Single element is also valid. | ||
* @param {function} listener The callback to be executed for each resize event for each element. | ||
*/ | ||
function listenTo(elements, listener) { | ||
function isListenedTo(element) { | ||
return elementUtils.isDetectable(element) && eventListenerHandler.get(element).length; | ||
function listenTo(options, elements, listener) { | ||
function onResizeCallback(element) { | ||
var listeners = eventListenerHandler.get(element); | ||
forEach(listeners, function(listener) { | ||
listener(element); | ||
}); | ||
} | ||
function addListener(element, listener) { | ||
elementUtils.addListener(element, listener); | ||
function onElementReadyToAddListener(callOnAdd, element, listener) { | ||
eventListenerHandler.add(element, listener); | ||
if(callOnAdd) { | ||
listener(element); | ||
} | ||
} | ||
//Options object may be omitted. | ||
if(!listener) { | ||
listener = elements; | ||
elements = options; | ||
options = {}; | ||
} | ||
if(!elements) { | ||
throw new Error("At least one element required."); | ||
} | ||
if(!listener) { | ||
throw new Error("Listener required."); | ||
} | ||
if(elements.length === undefined) { | ||
@@ -68,8 +176,27 @@ elements = [elements]; | ||
var callOnAdd = getOption(options, "callOnAdd", globalOptions.callOnAdd); | ||
forEach(elements, function(element) { | ||
//The element may change size directly after the call to listenTo, which would be unable to detect it because | ||
//the async adding of the object. By checking the size before and after, the size change can still be detected | ||
//and the listener can be called accordingly. | ||
var preWidth = element.offsetWidth; | ||
var preHeight = element.offsetHeight; | ||
if(!elementUtils.isDetectable(element)) { | ||
//The element is not prepared to be detectable, so do prepare it and add a listener to it. | ||
var id = idGenerator.newId(); | ||
return elementUtils.makeDetectable(element, id, function(element) { | ||
addListener(element, listener); | ||
return elementUtils.makeDetectable(reporter, element, function(element) { | ||
elementUtils.addListener(element, onResizeCallback); | ||
onElementReadyToAddListener(callOnAdd, element, listener); | ||
//Only here the uncaught resize may occur (since this code is async). | ||
//Check if the size is the same as when adding the listener. | ||
var postWidth = element.offsetWidth; | ||
var postHeight = element.offsetHeight; | ||
//If callOnAdd is true, then the listener will have been called either way, so no need to call the listener manually then. | ||
if(!callOnAdd && (preWidth !== postWidth || preHeight !== postHeight)) { | ||
//The element was changed while the object was being added. Call the listener. | ||
listener(element); | ||
} | ||
}); | ||
@@ -79,10 +206,3 @@ } | ||
//The element has been prepared to be detectable and is ready to be listened to. | ||
if(isListenedTo(element) && !allowMultipleListeners) { | ||
//Since there is a listener and we disallow multiple listeners no listener should be added. | ||
return; | ||
} | ||
//Since multiple listeners is allowed, another listener is added to the element. | ||
return addListener(element, listener); | ||
onElementReadyToAddListener(callOnAdd, element, listener); | ||
}); | ||
@@ -96,105 +216,171 @@ } | ||
},{"./collection-utils":1,"./element-utils":3,"./id-generator":4,"./listener-handler":5}],3:[function(require,module,exports){ | ||
function getOption(options, name, defaultValue) { | ||
var value = options[name]; | ||
if((value === undefined || value === null) && defaultValue !== undefined) { | ||
return defaultValue; | ||
} | ||
return value; | ||
} | ||
},{"./collection-utils":2,"./element-utils":4,"./id-generator":5,"./id-handler":6,"./listener-handler":7,"./reporter":8}],4:[function(require,module,exports){ | ||
"use strict"; | ||
var forEach = require("./collection-utils").forEach; | ||
var browserDetector = require("./browser-detector"); | ||
var utils = module.exports = {}; | ||
module.exports = function(idHandler) { | ||
/** | ||
* Tells if the element has been made detectable and ready to be listened for resize events. | ||
* @public | ||
* @param {element} The element to check. | ||
* @returns {boolean} True or false depending on if the element is detectable or not. | ||
*/ | ||
function isDetectable(element) { | ||
if(browserDetector.isIE(8)) { | ||
//IE 8 does not use the object method. | ||
//Check only if the element has been given an id. | ||
return !!idHandler.get(element); | ||
} | ||
/** | ||
* Gets the elq id of the element. | ||
* @public | ||
* @param {element} The target element to get the id of. | ||
* @returns {string} The id of the element. | ||
*/ | ||
utils.getId = function(element) { | ||
return element.getAttribute("elq-target-id"); | ||
}; | ||
return !!getObject(element); | ||
} | ||
/** | ||
* Tells if the element has been made detectable and ready to be listened for resize events. | ||
* @public | ||
* @param {element} The element to check. | ||
* @returns {boolean} True or false depending on if the element is detectable or not. | ||
*/ | ||
utils.isDetectable = function(element) { | ||
return getObject(element); | ||
}; | ||
/** | ||
* Adds a resize event listener to the element. | ||
* @public | ||
* @param {element} element The element that should have the listener added. | ||
* @param {function} listener The listener callback to be called for each resize event of the element. The element will be given as a parameter to the listener callback. | ||
*/ | ||
function addListener(element, listener) { | ||
if(!isDetectable(element)) { | ||
throw new Error("Element is not detectable."); | ||
} | ||
/** | ||
* Adds a resize event listener to the element. | ||
* @public | ||
* @param {element} element The element that should have the listener added. | ||
* @param {function} listener The listener callback to be called for each resize event of the element. The element will be given as a parameter to the listener callback. | ||
*/ | ||
utils.addListener = function(element, listener) { | ||
if(!utils.isDetectable(element)) { | ||
throw new Error("Element is not detectable."); | ||
function listenerProxy() { | ||
listener(element); | ||
} | ||
if(browserDetector.isIE(8)) { | ||
//IE 8 does not support object, but supports the resize event directly on elements. | ||
element.attachEvent("onresize", listenerProxy); | ||
} else { | ||
var object = getObject(element); | ||
object.contentDocument.defaultView.addEventListener("resize", listenerProxy); | ||
} | ||
} | ||
var object = getObject(element); | ||
object.contentDocument.defaultView.addEventListener("resize", function() { | ||
listener(element); | ||
}); | ||
}; | ||
/** | ||
* Makes an element detectable and ready to be listened for resize events. Will call the callback when the element is ready to be listened for resize changes. | ||
* @private | ||
* @param {element} element The element to make detectable | ||
* @param {function} callback The callback to be called when the element is ready to be listened for resize changes. Will be called with the element as first parameter. | ||
*/ | ||
function makeDetectable(reporter, element, callback) { | ||
function injectObject(id, element, callback) { | ||
var OBJECT_STYLE = "display: block; position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: none; padding: 0; margin: 0; opacity: 0; z-index: -1000; pointer-events: none;"; | ||
/** | ||
* Makes an element detectable and ready to be listened for resize events. Will call the callback when the element is ready to be listened for resize changes. | ||
* @private | ||
* @param {element} element The element to make detectable | ||
* @param {*} id An unique id in the context of all detectable elements. | ||
* @param {function} callback The callback to be called when the element is ready to be listened for resize changes. Will be called with the element as first parameter. | ||
*/ | ||
utils.makeDetectable = function(element, id, callback) { | ||
function onObjectLoad() { | ||
/*jshint validthis:true */ | ||
function onObjectLoad() { | ||
/*jshint validthis:true */ | ||
//Create the style element to be added to the object. | ||
var objectDocument = this.contentDocument; | ||
var style = objectDocument.createElement("style"); | ||
style.innerHTML = "html, body { margin: 0; padding: 0 } div { -webkit-transition: opacity 0.01s; -ms-transition: opacity 0.01s; -o-transition: opacity 0.01s; transition: opacity 0.01s; opacity: 0; }"; | ||
//Create the style element to be added to the object. | ||
var objectDocument = this.contentDocument; | ||
var style = objectDocument.createElement("style"); | ||
style.innerHTML = "html, body { margin: 0; padding: 0 } div { -webkit-transition: opacity 0.01s; -ms-transition: opacity 0.01s; -o-transition: opacity 0.01s; transition: opacity 0.01s; opacity: 0; }"; | ||
//TODO: Remove any styles that has been set on the object. Only the style above should be styling the object. | ||
//TODO: Remove any styles that has been set on the object. Only the style above should be styling the object. | ||
//Append the style to the object. | ||
objectDocument.head.appendChild(style); | ||
//Append the style to the object. | ||
objectDocument.head.appendChild(style); | ||
this.style.cssText = "display: block; position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: none; padding: 0; margin: 0; opacity: 0; z-index: -1000; pointer-events: none;"; | ||
//TODO: Is this needed here? | ||
//this.style.cssText = OBJECT_STYLE; | ||
//Notify that the element is ready to be listened to. | ||
callback(element); | ||
} | ||
//Notify that the element is ready to be listened to. | ||
callback(element); | ||
} | ||
//Create an unique elq-target-id for the target element, so that event listeners can be identified to this element. | ||
element.setAttribute("elq-target-id", id); | ||
//The target element needs to be positioned (everything except static) so the absolute positioned object will be positioned relative to the target element. | ||
var style = getComputedStyle(element); | ||
if(style.position === "static") { | ||
element.style.position = "relative"; | ||
//The target element needs to be positioned (everything except static) so the absolute positioned object will be positioned relative to the target element. | ||
if(getComputedStyle(element).position === "static") { | ||
element.style.position = "relative"; | ||
var removeRelativeStyles = function(reporter, element, style, property) { | ||
function getNumericalValue(value) { | ||
return value.replace(/[^-\d\.]/g, ""); | ||
} | ||
var value = style[property]; | ||
if(value !== "auto" && getNumericalValue(value) !== "0") { | ||
reporter.warn("An element that is positioned static has style." + property + "=" + value + " which is ignored due to the static positioning. The element will need to be positioned relateive, so the style." + property + " will be set to 0. Element: ", element); | ||
element.style[property] = 0; | ||
} | ||
}; | ||
//Check so that there are no accidental styles that will make the element styled differently now that is is relative. | ||
//If there are any, set them to 0 (this should be okay with the user since the style properties did nothing before [since the element was positioned static] anyway). | ||
removeRelativeStyles(reporter, element, style, "top"); | ||
removeRelativeStyles(reporter, element, style, "right"); | ||
removeRelativeStyles(reporter, element, style, "bottom"); | ||
removeRelativeStyles(reporter, element, style, "left"); | ||
} | ||
//Add an object element as a child to the target element that will be listened to for resize events. | ||
var object = document.createElement("object"); | ||
object.type = "text/html"; | ||
object.style.cssText = OBJECT_STYLE; | ||
object.onload = onObjectLoad; | ||
object.setAttribute("erd-object-id", id); | ||
//Safari: This must occur before adding the object to the DOM. | ||
//IE: Does not like that this happens before, even if it is also added after. | ||
if(!browserDetector.isIE()) { | ||
object.data = "about:blank"; | ||
} | ||
element.appendChild(object); | ||
//IE: This must occur after adding the object to the DOM. | ||
if(browserDetector.isIE()) { | ||
object.data = "about:blank"; | ||
} | ||
} | ||
//Create an unique erd-target-id for the target element, so that event listeners can be identified to this element. | ||
var id = idHandler.set(element); | ||
if(browserDetector.isIE(8)) { | ||
//IE 8 does not support objects properly. Luckily they do support the resize event. | ||
//So do not inject the object and notify that the element is already ready to be listened to. | ||
//The event handler for the resize event is attached in the utils.addListener instead. | ||
callback(element); | ||
} else { | ||
injectObject(id, element, callback); | ||
} | ||
} | ||
//Add an object element as a child to the target element that will be listened to for resize events. | ||
var object = document.createElement("object"); | ||
object.type = "text/html"; | ||
object.data = "about:blank"; | ||
object.onload = onObjectLoad; | ||
object.setAttribute("elq-object-id", id); | ||
element.appendChild(object); | ||
/** | ||
* Returns the child object of the target element. | ||
* @private | ||
* @param {element} element The target element. | ||
* @returns The object element of the target. | ||
*/ | ||
function getObject(element) { | ||
return forEach(element.children, function(child) { | ||
if(child.hasAttribute("erd-object-id")) { | ||
return child; | ||
} | ||
}); | ||
} | ||
return { | ||
isDetectable: isDetectable, | ||
makeDetectable: makeDetectable, | ||
addListener: addListener, | ||
}; | ||
}; | ||
/** | ||
* Returns the child object of the target element. | ||
* @private | ||
* @param {element} element The target element. | ||
* @returns The object element of the target. | ||
*/ | ||
function getObject(element) { | ||
return forEach(element.children, function(child) { | ||
if(child.hasAttribute("elq-object-id")) { | ||
return child; | ||
} | ||
}); | ||
} | ||
},{"./collection-utils":1}],4:[function(require,module,exports){ | ||
},{"./browser-detector":1,"./collection-utils":2}],5:[function(require,module,exports){ | ||
"use strict"; | ||
@@ -210,3 +396,3 @@ | ||
*/ | ||
function newId() { | ||
function generate() { | ||
return idCount++; | ||
@@ -216,12 +402,49 @@ } | ||
return { | ||
newId: newId | ||
generate: generate | ||
}; | ||
}; | ||
},{}],5:[function(require,module,exports){ | ||
},{}],6:[function(require,module,exports){ | ||
"use strict"; | ||
var elementUtils = require("./element-utils"); | ||
module.exports = function(idGenerator) { | ||
module.exports = function() { | ||
/** | ||
* Gets the resize detector id of the element. | ||
* @public | ||
* @param {element} The target element to get the id of. | ||
* @returns {string|number} The id of the element. | ||
*/ | ||
function getId(element) { | ||
return element.getAttribute("erd-target-id"); | ||
} | ||
/** | ||
* Sets the resize detector id of the element. | ||
* @public | ||
* @param {element} The target element to set the id to. | ||
* @param {string?} An optional id to set to the element. If not specified, an id will be generated. All id's must be unique. | ||
* @returns {string|number} The id of the element. | ||
*/ | ||
function setId(element, id) { | ||
if(!id && id !== 0) { | ||
//Number should be generated. | ||
id = idGenerator.generate(); | ||
} | ||
element.setAttribute("erd-target-id", id); | ||
return id; | ||
} | ||
return { | ||
get: getId, | ||
set: setId | ||
}; | ||
}; | ||
},{}],7:[function(require,module,exports){ | ||
"use strict"; | ||
module.exports = function(idHandler) { | ||
var eventListeners = {}; | ||
@@ -236,3 +459,3 @@ | ||
function getListeners(element) { | ||
return eventListeners[elementUtils.getId(element)]; | ||
return eventListeners[idHandler.get(element)]; | ||
} | ||
@@ -247,3 +470,3 @@ | ||
function addListener(element, listener) { | ||
var id = elementUtils.getId(element); | ||
var id = idHandler.get(element); | ||
@@ -263,3 +486,32 @@ if(!eventListeners[id]) { | ||
},{"./element-utils":3}]},{},[2])(2) | ||
},{}],8:[function(require,module,exports){ | ||
"use strict"; | ||
/* global console: false */ | ||
/** | ||
* Reporter that handles the reporting of logs, warnings and errors. | ||
* @public | ||
* @param {boolean} quiet Tells if the reporter should be quiet or not. | ||
*/ | ||
module.exports = function(quiet) { | ||
var noop = function () { | ||
//Does nothing. | ||
}; | ||
var reporter = { | ||
log: noop, | ||
warn: noop, | ||
error: noop | ||
}; | ||
if(!quiet && window.console) { | ||
reporter.log = console.log; | ||
reporter.warn = console.warn; | ||
reporter.error = console.error; | ||
} | ||
return reporter; | ||
}; | ||
},{}]},{},[3])(3) | ||
}); |
/*! | ||
* element-resize-detector 0.1.4 (2015-02-02, 12:04) | ||
* element-resize-detector 0.2.1 (2015-03-23, 19:27) | ||
* https://github.com/wnr/element-resize-detector | ||
@@ -7,2 +7,2 @@ * Licensed under MIT | ||
!function(a){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=a();else if("function"==typeof define&&define.amd)define([],a);else{var b;"undefined"!=typeof window?b=window:"undefined"!=typeof global?b=global:"undefined"!=typeof self&&(b=self),b.elementResizeDetectorMaker=a()}}(function(){return function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);var j=new Error("Cannot find module '"+g+"'");throw j.code="MODULE_NOT_FOUND",j}var k=c[g]={exports:{}};b[g][0].call(k.exports,function(a){var c=b[g][1][a];return e(c?c:a)},k,k.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g<d.length;g++)e(d[g]);return e}({1:[function(a,b){"use strict";var c=b.exports={};c.forEach=function(a,b){for(var c=0;c<a.length;c++){var d=b(a[c]);if(d)return d}}},{}],2:[function(a,b){"use strict";var c=a("./collection-utils").forEach,d=a("./element-utils"),e=a("./id-generator"),f=a("./listener-handler");b.exports=function(a){function b(a,b){function e(a){return d.isDetectable(a)&&h.get(a).length}function f(a,b){d.addListener(a,b),h.add(a,b)}void 0===a.length&&(a=[a]),c(a,function(a){if(!d.isDetectable(a)){var c=i.newId();return d.makeDetectable(a,c,function(a){f(a,b)})}if(!e(a)||g)return f(a,b)})}a=a||{};var g=void 0===a.allowMultipleListeners?!0:!1,h=f(),i=e();return{listenTo:b}}},{"./collection-utils":1,"./element-utils":3,"./id-generator":4,"./listener-handler":5}],3:[function(a,b){"use strict";function c(a){return d(a.children,function(a){return a.hasAttribute("elq-object-id")?a:void 0})}var d=a("./collection-utils").forEach,e=b.exports={};e.getId=function(a){return a.getAttribute("elq-target-id")},e.isDetectable=function(a){return c(a)},e.addListener=function(a,b){if(!e.isDetectable(a))throw new Error("Element is not detectable.");var d=c(a);d.contentDocument.defaultView.addEventListener("resize",function(){b(a)})},e.makeDetectable=function(a,b,c){function d(){var b=this.contentDocument,d=b.createElement("style");d.innerHTML="html, body { margin: 0; padding: 0 } div { -webkit-transition: opacity 0.01s; -ms-transition: opacity 0.01s; -o-transition: opacity 0.01s; transition: opacity 0.01s; opacity: 0; }",b.head.appendChild(d),this.style.cssText="display: block; position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: none; padding: 0; margin: 0; opacity: 0; z-index: -1000; pointer-events: none;",c(a)}a.setAttribute("elq-target-id",b),"static"===getComputedStyle(a).position&&(a.style.position="relative");var e=document.createElement("object");e.type="text/html",e.data="about:blank",e.onload=d,e.setAttribute("elq-object-id",b),a.appendChild(e)}},{"./collection-utils":1}],4:[function(a,b){"use strict";b.exports=function(){function a(){return b++}var b=1;return{newId:a}}},{}],5:[function(a,b){"use strict";var c=a("./element-utils");b.exports=function(){function a(a){return d[c.getId(a)]}function b(a,b){var e=c.getId(a);d[e]||(d[e]=[]),d[e].push(b)}var d={};return{get:a,add:b}}},{"./element-utils":3}]},{},[2])(2)}); | ||
!function(a){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=a();else if("function"==typeof define&&define.amd)define([],a);else{var b;b="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,b.elementResizeDetectorMaker=a()}}(function(){return function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);var j=new Error("Cannot find module '"+g+"'");throw j.code="MODULE_NOT_FOUND",j}var k=c[g]={exports:{}};b[g][0].call(k.exports,function(a){var c=b[g][1][a];return e(c?c:a)},k,k.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g<d.length;g++)e(d[g]);return e}({1:[function(a,b){"use strict";var c=b.exports={};c.isIE=function(a){function b(){var a=navigator.userAgent.toLowerCase();return-1!==a.indexOf("msie")||-1!==a.indexOf("trident")}if(!b())return!1;if(!a)return!0;var c=function(){var a,b=3,c=document.createElement("div"),d=c.getElementsByTagName("i");do c.innerHTML="<!--[if gt IE "+ ++b+"]><i></i><![endif]-->";while(d[0]);return b>4?b:a}();return a===c}},{}],2:[function(a,b){"use strict";var c=b.exports={};c.forEach=function(a,b){for(var c=0;c<a.length;c++){var d=b(a[c]);if(d)return d}}},{}],3:[function(a,b){"use strict";function c(a,b,c){var d=a[b];return void 0!==d&&null!==d||void 0===c?d:c}var d=a("./collection-utils").forEach,e=a("./element-utils"),f=a("./listener-handler"),g=a("./id-generator"),h=a("./id-handler"),i=a("./reporter");b.exports=function(a){function b(a,b,e){function f(a){var b=p.get(a);d(b,function(b){b(a)})}function g(a,b,c){p.add(b,c),a&&c(b)}if(e||(e=b,b=a,a={}),!b)throw new Error("At least one element required.");if(!e)throw new Error("Listener required.");void 0===b.length&&(b=[b]);var h=c(a,"callOnAdd",j.callOnAdd);d(b,function(a){var b=a.offsetWidth,c=a.offsetHeight;return q.isDetectable(a)?void g(h,a,e):q.makeDetectable(n,a,function(a){q.addListener(a,f),g(h,a,e);var d=a.offsetWidth,i=a.offsetHeight;h||b===d&&c===i||e(a)})})}a=a||{};var j={};j.callOnAdd=!!c(a,"callOnAdd",!0);var k=a.idHandler;if(!k){var l=g(),m=h(l);k=m}var n=a.reporter;if(!n){var o=n===!1;n=i(o)}var p=f(k),q=e(k);return{listenTo:b}}},{"./collection-utils":2,"./element-utils":4,"./id-generator":5,"./id-handler":6,"./listener-handler":7,"./reporter":8}],4:[function(a,b){"use strict";var c=a("./collection-utils").forEach,d=a("./browser-detector");b.exports=function(a){function b(b){return d.isIE(8)?!!a.get(b):!!g(b)}function e(a,c){function e(){c(a)}if(!b(a))throw new Error("Element is not detectable.");if(d.isIE(8))a.attachEvent("onresize",e);else{var f=g(a);f.contentDocument.defaultView.addEventListener("resize",e)}}function f(b,c,e){function f(a,c,e){function f(){var a=this.contentDocument,b=a.createElement("style");b.innerHTML="html, body { margin: 0; padding: 0 } div { -webkit-transition: opacity 0.01s; -ms-transition: opacity 0.01s; -o-transition: opacity 0.01s; transition: opacity 0.01s; opacity: 0; }",a.head.appendChild(b),e(c)}var g="display: block; position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: none; padding: 0; margin: 0; opacity: 0; z-index: -1000; pointer-events: none;",h=getComputedStyle(c);if("static"===h.position){c.style.position="relative";var i=function(a,b,c,d){function e(a){return a.replace(/[^-\d\.]/g,"")}var f=c[d];"auto"!==f&&"0"!==e(f)&&(a.warn("An element that is positioned static has style."+d+"="+f+" which is ignored due to the static positioning. The element will need to be positioned relateive, so the style."+d+" will be set to 0. Element: ",b),b.style[d]=0)};i(b,c,h,"top"),i(b,c,h,"right"),i(b,c,h,"bottom"),i(b,c,h,"left")}var j=document.createElement("object");j.type="text/html",j.style.cssText=g,j.onload=f,j.setAttribute("erd-object-id",a),d.isIE()||(j.data="about:blank"),c.appendChild(j),d.isIE()&&(j.data="about:blank")}var g=a.set(c);d.isIE(8)?e(c):f(g,c,e)}function g(a){return c(a.children,function(a){return a.hasAttribute("erd-object-id")?a:void 0})}return{isDetectable:b,makeDetectable:f,addListener:e}}},{"./browser-detector":1,"./collection-utils":2}],5:[function(a,b){"use strict";b.exports=function(){function a(){return b++}var b=1;return{generate:a}}},{}],6:[function(a,b){"use strict";b.exports=function(a){function b(a){return a.getAttribute("erd-target-id")}function c(b,c){return c||0===c||(c=a.generate()),b.setAttribute("erd-target-id",c),c}return{get:b,set:c}}},{}],7:[function(a,b){"use strict";b.exports=function(a){function b(b){return d[a.get(b)]}function c(b,c){var e=a.get(b);d[e]||(d[e]=[]),d[e].push(c)}var d={};return{get:b,add:c}}},{}],8:[function(a,b){"use strict";b.exports=function(a){var b=function(){},c={log:b,warn:b,error:b};return!a&&window.console&&(c.log=console.log,c.warn=console.warn,c.error=console.error),c}},{}]},{},[3])(3)}); |
151
Gruntfile.js
@@ -0,3 +1,46 @@ | ||
/* global process:false */ | ||
"use strict"; | ||
var _ = require("lodash"); | ||
var sauceConnectLauncher = require("sauce-connect-launcher"); | ||
function registerSauceBrowsers(config, sauceBrowsers, configFile) { | ||
function capitalize(string) { | ||
if(!string.charAt) { | ||
return string; | ||
} | ||
return string.charAt(0).toUpperCase() + string.slice(1); | ||
} | ||
var karma = config.karma; | ||
var tasks = []; | ||
var formatName = function(result, part) { | ||
return result + capitalize(part); | ||
}; | ||
for(var key in sauceBrowsers) { | ||
if(sauceBrowsers.hasOwnProperty(key)) { | ||
var parts = key.toLowerCase().split("_"); | ||
var name = _.reduce(parts, formatName, "sauce"); | ||
var configObject = { | ||
configFile: configFile, | ||
options: { | ||
browsers: sauceBrowsers[key] | ||
} | ||
}; | ||
karma[name] = configObject; | ||
tasks.push("karma:" + name); | ||
} | ||
} | ||
return tasks; | ||
} | ||
module.exports = function(grunt) { | ||
@@ -62,5 +105,53 @@ require("load-grunt-tasks")(grunt); | ||
} | ||
} | ||
}, | ||
karma: { | ||
local: { | ||
configFile: "karma.conf.js", | ||
options: { | ||
browsers: [ | ||
"Chrome", | ||
"Safari", | ||
"Firefox", | ||
//"IE8 - Win7", | ||
//"IE10 - Win7", | ||
//"IE11 - Win8.1" | ||
], | ||
singleRun: true | ||
} | ||
} | ||
}, | ||
"sauce_connect": { | ||
options: { | ||
username: process.env.SAUCE_USERNAME, | ||
accessKey: process.env.SAUCE_ACCESS_KEY, | ||
verbose: true, | ||
build: process.env.TRAVIS_BUILD_NUMBER || process.env.BUILD_NUMBER, | ||
testName: "element-resize-detector" | ||
}, | ||
tunnel: {} | ||
} | ||
}; | ||
var sauceBrowsers = [ | ||
"SL_CHROME_LATEST_OSX", "SL_CHROME_LATEST_WINDOWS", "SL_CHROME_LATEST_LINUX", | ||
"SL_FIREFOX_LATEST_OSX", "SL_FIREFOX_LATEST_WINDOWS", "SL_FIREFOX_LATEST_LINUX", | ||
"SL_SAFARI_LATEST_OSX", "SL_SAFARI_LATEST_WINDOWS", | ||
"SL_OPERA_LATEST_WINDOWS", "SL_OPERA_LATEST_LINUX", | ||
"SL_IE_LATEST_WINDOWS", "SL_IE_10_WINDOWS", "SL_IE_9_WINDOWS", "SL_IE_8_WINDOWS", | ||
"SL_IOS_LATEST_IPHONE", "SL_IOS_LATEST_IPAD", | ||
"SL_IOS_7_IPHONE", "SL_IOS_7_IPAD" | ||
]; | ||
function batchSauceBrowsers(browsers, batchSize) { | ||
var number = 1; | ||
var batchMap = {}; | ||
_.forEach(_.chunk(browsers, batchSize), function(chunk) { | ||
batchMap["sauceBrowserChunk" + number++] = chunk; | ||
}); | ||
return batchMap; | ||
} | ||
var NUM_PARALLEL_BROWSERS = 3; | ||
var sauceBrowserTasks = registerSauceBrowsers(config, batchSauceBrowsers(sauceBrowsers, NUM_PARALLEL_BROWSERS), "karma.sauce.conf.js"); | ||
grunt.initConfig(config); | ||
@@ -75,5 +166,61 @@ | ||
grunt.registerTask("test:style", ["jshint"]); | ||
grunt.registerTask("test", ["test:style", "build:dev"]); //TODO | ||
grunt.registerTask("test:sauce", ["build"].concat(sauceBrowserTasks)); | ||
grunt.registerTask("test", ["test:style", "build:dev", "karma:local"]); | ||
grunt.registerTask("ci", ["test:style", "sauceConnectTunnel", "test:sauce"]); | ||
grunt.registerTask("default", ["test"]); | ||
var sauceConnectTunnel = {}; | ||
grunt.registerTask("sauceConnectTunnel", "Starts a sauce connect tunnel", function(keepAlive) { | ||
if(!process.env.SAUCE_USERNAME) { | ||
grunt.log.error("env SAUCE_USERNAME needs to be set."); | ||
return false; | ||
} | ||
if(!process.env.SAUCE_ACCESS_KEY) { | ||
grunt.log.error("env SAUCE_ACCESS_KEY needs to be set."); | ||
return false; | ||
} | ||
var done = this.async(); | ||
sauceConnectLauncher({ | ||
username: process.env.SAUCE_USERNAME, | ||
accessKey: process.env.SAUCE_ACCESS_KEY, | ||
logger: grunt.log.writeln, | ||
verbose: true, | ||
logfile: "sauce-connect.log" | ||
}, function (err, sauceConnectProcess) { | ||
function stop() { | ||
grunt.log.writeln("Stopping..."); | ||
sauceConnectTunnel.process.close(function() { | ||
grunt.log.writeln("Closed Sauce Connect process"); | ||
done(); | ||
}); | ||
} | ||
if (err) { | ||
grunt.log.error(err.message); | ||
done(false); | ||
} | ||
sauceConnectTunnel.process = sauceConnectProcess; | ||
grunt.log.success("Sauce Connect ready!"); | ||
if(keepAlive) { | ||
grunt.log.writeln("The tunnel will be kept alive. Stop it by terminating this process with SIGINT (Ctrl-C)."); | ||
process.on("SIGINT", function() { | ||
grunt.log.writeln(); | ||
stop(); | ||
}); | ||
} else { | ||
grunt.log.writeln("Closing tunnel since the :keepAlive argument is not present..."); | ||
done(); | ||
} | ||
}); | ||
}); | ||
}; |
{ | ||
"name": "element-resize-detector", | ||
"version": "0.1.4", | ||
"version": "0.2.2", | ||
"description": "resize event emitter for elements.", | ||
@@ -17,6 +17,20 @@ "homepage": "https://github.com/wnr/element-resize-detector", | ||
"grunt-browserify": "^3.3.0", | ||
"grunt-cli": "^0.1.13", | ||
"grunt-contrib-jshint": "^0.11.0", | ||
"grunt-contrib-uglify": "^0.7.0", | ||
"jquery": "^2.1.3", | ||
"load-grunt-tasks": "^3.0.0" | ||
"grunt-karma": "^0.10.1", | ||
"jasmine-core": "^2.2.0", | ||
"jasmine-expect": "^2.0.0-beta1", | ||
"jasmine-jquery": "^2.0.6", | ||
"jquery": "^1.11.2", | ||
"karma": "^0.12.31", | ||
"karma-chrome-launcher": "^0.1.7", | ||
"karma-firefox-launcher": "^0.1.4", | ||
"karma-ievms": "0.0.4", | ||
"karma-jasmine": "^0.3.5", | ||
"karma-safari-launcher": "^0.1.1", | ||
"karma-sauce-launcher": "^0.2.10", | ||
"load-grunt-tasks": "^3.0.0", | ||
"lodash": "^3.3.1", | ||
"sauce-connect-launcher": "^0.10.1" | ||
}, | ||
@@ -26,4 +40,5 @@ "scripts": { | ||
"dist": "grunt dist", | ||
"test": "grunt test" | ||
"test": "grunt test", | ||
"test-ci": "grunt ci" | ||
} | ||
} |
@@ -28,7 +28,2 @@ # element-resize-detector | ||
var erdDefault = elementResizeDetectorMaker(); | ||
//With custom options. | ||
var erdCustom = elementResizeDetectorMaker({ | ||
allowMultipleListeners: true //Default is false, which only allows one listener function per element. | ||
}); | ||
``` | ||
@@ -35,0 +30,0 @@ |
@@ -6,29 +6,100 @@ //Heavily inspired by http://www.backalleycoder.com/2013/03/18/cross-browser-event-based-element-resize-detection/ | ||
var forEach = require("./collection-utils").forEach; | ||
var elementUtils = require("./element-utils"); | ||
var elementUtilsMaker = require("./element-utils"); | ||
var listenerHandlerMaker = require("./listener-handler"); | ||
var idGeneratorMaker = require("./id-generator"); | ||
var listenerHandlerMaker = require("./listener-handler"); | ||
var idHandlerMaker = require("./id-handler"); | ||
var reporterMaker = require("./reporter"); | ||
/** | ||
* @typedef idHandler | ||
* @type {object} | ||
* @property {function} get Gets the resize detector id of the element. | ||
* @property {function} set Generate and sets the resize detector id of the element. | ||
*/ | ||
/** | ||
* @typedef Options | ||
* @type {object} | ||
* @property {boolean} callOnAdd Determines if listeners should be called when they are getting added. | ||
Default is true. If true, the listener is guaranteed to be called when it has been added. | ||
If false, the listener will not be guarenteed to be called when it has been added (does not prevent it from being called). | ||
* @property {idHandler} idHandler A custom id handler that is responsible for generating, setting and retrieving id's for elements. | ||
If not provided, a default id handler will be used. | ||
* @property {reporter} reporter A custom reporter that handles reporting logs, warnings and errors. | ||
If not provided, a default id handler will be used. | ||
If set to false, then nothing will be reported. | ||
*/ | ||
/** | ||
* Creates an element resize detector instance. | ||
* @public | ||
* @param {Options?} options Optional global options object that will decide how this instance will work. | ||
*/ | ||
module.exports = function(options) { | ||
options = options || {}; | ||
var allowMultipleListeners = options.allowMultipleListeners === undefined ? true : false; | ||
var eventListenerHandler = listenerHandlerMaker(); | ||
var idGenerator = idGeneratorMaker(); | ||
//Options to be used as default for the listenTo function. | ||
var globalOptions = {}; | ||
globalOptions.callOnAdd = !!getOption(options, "callOnAdd", true); | ||
//idHandler is currently not an option to the listenTo function, so it should not be added to globalOptions. | ||
var idHandler = options.idHandler; | ||
if(!idHandler) { | ||
var idGenerator = idGeneratorMaker(); | ||
var defaultIdHandler = idHandlerMaker(idGenerator); | ||
idHandler = defaultIdHandler; | ||
} | ||
//reporter is currently not an option to the listenTo function, so it should not be added to globalOptions. | ||
var reporter = options.reporter; | ||
if(!reporter) { | ||
//If options.reporter is false, then the reporter should be quiet. | ||
var quiet = reporter === false; | ||
reporter = reporterMaker(quiet); | ||
} | ||
var eventListenerHandler = listenerHandlerMaker(idHandler); | ||
var elementUtils = elementUtilsMaker(idHandler); | ||
/** | ||
* Makes the given elements resize-detectable and starts listening to resize events on the elements. Calls the event callback for each event for each element. | ||
* @public | ||
* @param {Options?} options Optional options object. These options will override the global options. Some options may not be overriden, such as idHandler. | ||
* @param {element[]|element} elements The given array of elements to detect resize events of. Single element is also valid. | ||
* @param {function} listener The callback to be executed for each resize event for each element. | ||
*/ | ||
function listenTo(elements, listener) { | ||
function isListenedTo(element) { | ||
return elementUtils.isDetectable(element) && eventListenerHandler.get(element).length; | ||
function listenTo(options, elements, listener) { | ||
function onResizeCallback(element) { | ||
var listeners = eventListenerHandler.get(element); | ||
forEach(listeners, function(listener) { | ||
listener(element); | ||
}); | ||
} | ||
function addListener(element, listener) { | ||
elementUtils.addListener(element, listener); | ||
function onElementReadyToAddListener(callOnAdd, element, listener) { | ||
eventListenerHandler.add(element, listener); | ||
if(callOnAdd) { | ||
listener(element); | ||
} | ||
} | ||
//Options object may be omitted. | ||
if(!listener) { | ||
listener = elements; | ||
elements = options; | ||
options = {}; | ||
} | ||
if(!elements) { | ||
throw new Error("At least one element required."); | ||
} | ||
if(!listener) { | ||
throw new Error("Listener required."); | ||
} | ||
if(elements.length === undefined) { | ||
@@ -38,8 +109,27 @@ elements = [elements]; | ||
var callOnAdd = getOption(options, "callOnAdd", globalOptions.callOnAdd); | ||
forEach(elements, function(element) { | ||
//The element may change size directly after the call to listenTo, which would be unable to detect it because | ||
//the async adding of the object. By checking the size before and after, the size change can still be detected | ||
//and the listener can be called accordingly. | ||
var preWidth = element.offsetWidth; | ||
var preHeight = element.offsetHeight; | ||
if(!elementUtils.isDetectable(element)) { | ||
//The element is not prepared to be detectable, so do prepare it and add a listener to it. | ||
var id = idGenerator.newId(); | ||
return elementUtils.makeDetectable(element, id, function(element) { | ||
addListener(element, listener); | ||
return elementUtils.makeDetectable(reporter, element, function(element) { | ||
elementUtils.addListener(element, onResizeCallback); | ||
onElementReadyToAddListener(callOnAdd, element, listener); | ||
//Only here the uncaught resize may occur (since this code is async). | ||
//Check if the size is the same as when adding the listener. | ||
var postWidth = element.offsetWidth; | ||
var postHeight = element.offsetHeight; | ||
//If callOnAdd is true, then the listener will have been called either way, so no need to call the listener manually then. | ||
if(!callOnAdd && (preWidth !== postWidth || preHeight !== postHeight)) { | ||
//The element was changed while the object was being added. Call the listener. | ||
listener(element); | ||
} | ||
}); | ||
@@ -49,10 +139,3 @@ } | ||
//The element has been prepared to be detectable and is ready to be listened to. | ||
if(isListenedTo(element) && !allowMultipleListeners) { | ||
//Since there is a listener and we disallow multiple listeners no listener should be added. | ||
return; | ||
} | ||
//Since multiple listeners is allowed, another listener is added to the element. | ||
return addListener(element, listener); | ||
onElementReadyToAddListener(callOnAdd, element, listener); | ||
}); | ||
@@ -65,1 +148,11 @@ } | ||
}; | ||
function getOption(options, name, defaultValue) { | ||
var value = options[name]; | ||
if((value === undefined || value === null) && defaultValue !== undefined) { | ||
return defaultValue; | ||
} | ||
return value; | ||
} |
"use strict"; | ||
var forEach = require("./collection-utils").forEach; | ||
var browserDetector = require("./browser-detector"); | ||
var utils = module.exports = {}; | ||
module.exports = function(idHandler) { | ||
/** | ||
* Tells if the element has been made detectable and ready to be listened for resize events. | ||
* @public | ||
* @param {element} The element to check. | ||
* @returns {boolean} True or false depending on if the element is detectable or not. | ||
*/ | ||
function isDetectable(element) { | ||
if(browserDetector.isIE(8)) { | ||
//IE 8 does not use the object method. | ||
//Check only if the element has been given an id. | ||
return !!idHandler.get(element); | ||
} | ||
/** | ||
* Gets the elq id of the element. | ||
* @public | ||
* @param {element} The target element to get the id of. | ||
* @returns {string} The id of the element. | ||
*/ | ||
utils.getId = function(element) { | ||
return element.getAttribute("elq-target-id"); | ||
}; | ||
return !!getObject(element); | ||
} | ||
/** | ||
* Tells if the element has been made detectable and ready to be listened for resize events. | ||
* @public | ||
* @param {element} The element to check. | ||
* @returns {boolean} True or false depending on if the element is detectable or not. | ||
*/ | ||
utils.isDetectable = function(element) { | ||
return getObject(element); | ||
}; | ||
/** | ||
* Adds a resize event listener to the element. | ||
* @public | ||
* @param {element} element The element that should have the listener added. | ||
* @param {function} listener The listener callback to be called for each resize event of the element. The element will be given as a parameter to the listener callback. | ||
*/ | ||
function addListener(element, listener) { | ||
if(!isDetectable(element)) { | ||
throw new Error("Element is not detectable."); | ||
} | ||
/** | ||
* Adds a resize event listener to the element. | ||
* @public | ||
* @param {element} element The element that should have the listener added. | ||
* @param {function} listener The listener callback to be called for each resize event of the element. The element will be given as a parameter to the listener callback. | ||
*/ | ||
utils.addListener = function(element, listener) { | ||
if(!utils.isDetectable(element)) { | ||
throw new Error("Element is not detectable."); | ||
function listenerProxy() { | ||
listener(element); | ||
} | ||
if(browserDetector.isIE(8)) { | ||
//IE 8 does not support object, but supports the resize event directly on elements. | ||
element.attachEvent("onresize", listenerProxy); | ||
} else { | ||
var object = getObject(element); | ||
object.contentDocument.defaultView.addEventListener("resize", listenerProxy); | ||
} | ||
} | ||
var object = getObject(element); | ||
object.contentDocument.defaultView.addEventListener("resize", function() { | ||
listener(element); | ||
}); | ||
}; | ||
/** | ||
* Makes an element detectable and ready to be listened for resize events. Will call the callback when the element is ready to be listened for resize changes. | ||
* @private | ||
* @param {element} element The element to make detectable | ||
* @param {function} callback The callback to be called when the element is ready to be listened for resize changes. Will be called with the element as first parameter. | ||
*/ | ||
function makeDetectable(reporter, element, callback) { | ||
function injectObject(id, element, callback) { | ||
var OBJECT_STYLE = "display: block; position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: none; padding: 0; margin: 0; opacity: 0; z-index: -1000; pointer-events: none;"; | ||
/** | ||
* Makes an element detectable and ready to be listened for resize events. Will call the callback when the element is ready to be listened for resize changes. | ||
* @private | ||
* @param {element} element The element to make detectable | ||
* @param {*} id An unique id in the context of all detectable elements. | ||
* @param {function} callback The callback to be called when the element is ready to be listened for resize changes. Will be called with the element as first parameter. | ||
*/ | ||
utils.makeDetectable = function(element, id, callback) { | ||
function onObjectLoad() { | ||
/*jshint validthis:true */ | ||
function onObjectLoad() { | ||
/*jshint validthis:true */ | ||
//Create the style element to be added to the object. | ||
var objectDocument = this.contentDocument; | ||
var style = objectDocument.createElement("style"); | ||
style.innerHTML = "html, body { margin: 0; padding: 0 } div { -webkit-transition: opacity 0.01s; -ms-transition: opacity 0.01s; -o-transition: opacity 0.01s; transition: opacity 0.01s; opacity: 0; }"; | ||
//Create the style element to be added to the object. | ||
var objectDocument = this.contentDocument; | ||
var style = objectDocument.createElement("style"); | ||
style.innerHTML = "html, body { margin: 0; padding: 0 } div { -webkit-transition: opacity 0.01s; -ms-transition: opacity 0.01s; -o-transition: opacity 0.01s; transition: opacity 0.01s; opacity: 0; }"; | ||
//TODO: Remove any styles that has been set on the object. Only the style above should be styling the object. | ||
//TODO: Remove any styles that has been set on the object. Only the style above should be styling the object. | ||
//Append the style to the object. | ||
objectDocument.head.appendChild(style); | ||
//Append the style to the object. | ||
objectDocument.head.appendChild(style); | ||
this.style.cssText = "display: block; position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: none; padding: 0; margin: 0; opacity: 0; z-index: -1000; pointer-events: none;"; | ||
//TODO: Is this needed here? | ||
//this.style.cssText = OBJECT_STYLE; | ||
//Notify that the element is ready to be listened to. | ||
callback(element); | ||
} | ||
//Notify that the element is ready to be listened to. | ||
callback(element); | ||
} | ||
//Create an unique elq-target-id for the target element, so that event listeners can be identified to this element. | ||
element.setAttribute("elq-target-id", id); | ||
//The target element needs to be positioned (everything except static) so the absolute positioned object will be positioned relative to the target element. | ||
var style = getComputedStyle(element); | ||
if(style.position === "static") { | ||
element.style.position = "relative"; | ||
//The target element needs to be positioned (everything except static) so the absolute positioned object will be positioned relative to the target element. | ||
if(getComputedStyle(element).position === "static") { | ||
element.style.position = "relative"; | ||
var removeRelativeStyles = function(reporter, element, style, property) { | ||
function getNumericalValue(value) { | ||
return value.replace(/[^-\d\.]/g, ""); | ||
} | ||
var value = style[property]; | ||
if(value !== "auto" && getNumericalValue(value) !== "0") { | ||
reporter.warn("An element that is positioned static has style." + property + "=" + value + " which is ignored due to the static positioning. The element will need to be positioned relateive, so the style." + property + " will be set to 0. Element: ", element); | ||
element.style[property] = 0; | ||
} | ||
}; | ||
//Check so that there are no accidental styles that will make the element styled differently now that is is relative. | ||
//If there are any, set them to 0 (this should be okay with the user since the style properties did nothing before [since the element was positioned static] anyway). | ||
removeRelativeStyles(reporter, element, style, "top"); | ||
removeRelativeStyles(reporter, element, style, "right"); | ||
removeRelativeStyles(reporter, element, style, "bottom"); | ||
removeRelativeStyles(reporter, element, style, "left"); | ||
} | ||
//Add an object element as a child to the target element that will be listened to for resize events. | ||
var object = document.createElement("object"); | ||
object.type = "text/html"; | ||
object.style.cssText = OBJECT_STYLE; | ||
object.onload = onObjectLoad; | ||
object.setAttribute("erd-object-id", id); | ||
//Safari: This must occur before adding the object to the DOM. | ||
//IE: Does not like that this happens before, even if it is also added after. | ||
if(!browserDetector.isIE()) { | ||
object.data = "about:blank"; | ||
} | ||
element.appendChild(object); | ||
//IE: This must occur after adding the object to the DOM. | ||
if(browserDetector.isIE()) { | ||
object.data = "about:blank"; | ||
} | ||
} | ||
//Create an unique erd-target-id for the target element, so that event listeners can be identified to this element. | ||
var id = idHandler.set(element); | ||
if(browserDetector.isIE(8)) { | ||
//IE 8 does not support objects properly. Luckily they do support the resize event. | ||
//So do not inject the object and notify that the element is already ready to be listened to. | ||
//The event handler for the resize event is attached in the utils.addListener instead. | ||
callback(element); | ||
} else { | ||
injectObject(id, element, callback); | ||
} | ||
} | ||
//Add an object element as a child to the target element that will be listened to for resize events. | ||
var object = document.createElement("object"); | ||
object.type = "text/html"; | ||
object.data = "about:blank"; | ||
object.onload = onObjectLoad; | ||
object.setAttribute("elq-object-id", id); | ||
element.appendChild(object); | ||
/** | ||
* Returns the child object of the target element. | ||
* @private | ||
* @param {element} element The target element. | ||
* @returns The object element of the target. | ||
*/ | ||
function getObject(element) { | ||
return forEach(element.children, function(child) { | ||
if(child.hasAttribute("erd-object-id")) { | ||
return child; | ||
} | ||
}); | ||
} | ||
return { | ||
isDetectable: isDetectable, | ||
makeDetectable: makeDetectable, | ||
addListener: addListener, | ||
}; | ||
}; | ||
/** | ||
* Returns the child object of the target element. | ||
* @private | ||
* @param {element} element The target element. | ||
* @returns The object element of the target. | ||
*/ | ||
function getObject(element) { | ||
return forEach(element.children, function(child) { | ||
if(child.hasAttribute("elq-object-id")) { | ||
return child; | ||
} | ||
}); | ||
} |
@@ -11,3 +11,3 @@ "use strict"; | ||
*/ | ||
function newId() { | ||
function generate() { | ||
return idCount++; | ||
@@ -17,4 +17,4 @@ } | ||
return { | ||
newId: newId | ||
generate: generate | ||
}; | ||
}; |
"use strict"; | ||
var elementUtils = require("./element-utils"); | ||
module.exports = function() { | ||
module.exports = function(idHandler) { | ||
var eventListeners = {}; | ||
@@ -15,3 +13,3 @@ | ||
function getListeners(element) { | ||
return eventListeners[elementUtils.getId(element)]; | ||
return eventListeners[idHandler.get(element)]; | ||
} | ||
@@ -26,3 +24,3 @@ | ||
function addListener(element, listener) { | ||
var id = elementUtils.getId(element); | ||
var id = idHandler.get(element); | ||
@@ -29,0 +27,0 @@ if(!eventListeners[id]) { |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 4 instances in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
122320
23
1976
21
48
14
2