made with requirebin
Created
May 22, 2017 10:03
-
-
Save kasperlewau/34ce6887aca4662a8000c7a214b7380b to your computer and use it in GitHub Desktop.
requirebin sketch
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Welcome! require() some modules from npm (like you were using browserify) | |
// and then hit Run Code to run your code on the right side. | |
// Modules get downloaded from browserify-cdn and bundled in your browser. | |
const HyperList = require('hyperlist') | |
const root = document.createElement('div') | |
const data = ['a', 'b', 'c', 'd'] | |
const conf = { | |
height: 160, | |
itemHeight: 10, | |
total: 80, | |
generate: function (idx) { | |
const el = document.createElement('span') | |
el.innerHTML = `${data[idx] ? data[idx] : 'placeholder'}` | |
if (data[idx] && idx > 3) { | |
el.style.color = 'red' | |
} | |
return el | |
} | |
}; | |
const list = new HyperList(root, conf); | |
document.body.appendChild(root) | |
setTimeout(function () { | |
data.push(...['e', 'f', 'g', 'h']) | |
list.refresh(root, conf) | |
const notice = document.createElement('span') | |
notice.innerHTML = 'Scroll down & then up please' | |
document.body.appendChild(notice) | |
}, 2500) | |
// scroll manually -> see the list |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
setTimeout(function(){ | |
;require=(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})({"hyperlist":[function(require,module,exports){ | |
(function (global){ | |
(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.HyperList = 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(_dereq_,module,exports){ | |
'use strict'; | |
// Default configuration. | |
Object.defineProperty(exports, "__esModule", { | |
value: true | |
}); | |
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); | |
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | |
var defaultConfig = { | |
width: '100%', | |
height: '100%' | |
}; | |
// Check for valid number. | |
var isNumber = function isNumber(input) { | |
return Number(input) === Number(input); | |
}; | |
/** | |
* Creates a HyperList instance that virtually scrolls very large amounts of | |
* data effortlessly. | |
*/ | |
var HyperList = function () { | |
_createClass(HyperList, null, [{ | |
key: 'create', | |
value: function create(element, userProvidedConfig) { | |
return new HyperList(element, userProvidedConfig); | |
} | |
/** | |
* Merge given css style on an element | |
* @param {DOMElement} element | |
* @param {Object} style | |
*/ | |
}, { | |
key: 'mergeStyle', | |
value: function mergeStyle(element, style) { | |
for (var i in style) { | |
if (element.style[i] !== style[i]) { | |
element.style[i] = style[i]; | |
} | |
} | |
} | |
}, { | |
key: 'getMaxBrowserHeight', | |
value: function getMaxBrowserHeight() { | |
// Create two elements, the wrapper is `1px` tall and is transparent and | |
// positioned at the top of the page. Inside that is an element that gets | |
// set to 1 billion pixels. Then reads the max height the browser can | |
// calculate. | |
var wrapper = document.createElement('div'); | |
var fixture = document.createElement('div'); | |
// As said above, these values get set to put the fixture elements into the | |
// right visual state. | |
HyperList.mergeStyle(wrapper, { position: 'absolute', height: '1px', opacity: 0 }); | |
HyperList.mergeStyle(fixture, { height: '1e7px' }); | |
// Add the fixture into the wrapper element. | |
wrapper.appendChild(fixture); | |
// Apply to the page, the values won't kick in unless this is attached. | |
document.body.appendChild(wrapper); | |
// Get the maximum element height in pixels. | |
var maxElementHeight = fixture.offsetHeight; | |
// Remove the element immediately after reading the value. | |
document.body.removeChild(wrapper); | |
return maxElementHeight; | |
} | |
}]); | |
function HyperList(element, userProvidedConfig) { | |
var _this = this; | |
_classCallCheck(this, HyperList); | |
this._config = {}; | |
this._lastRepaint = null; | |
this._maxElementHeight = HyperList.getMaxBrowserHeight(); | |
this.refresh(element, userProvidedConfig); | |
var config = this._config; | |
// Create internal render loop. | |
var render = function render() { | |
var scrollTop = _this._getScrollPosition(); | |
var lastRepaint = _this._lastRepaint; | |
_this._renderAnimationFrame = window.requestAnimationFrame(render); | |
if (scrollTop === lastRepaint) { | |
return; | |
} | |
if (!lastRepaint || Math.abs(scrollTop - lastRepaint) > _this._averageHeight) { | |
var rendered = _this._renderChunk(); | |
_this._lastRepaint = scrollTop; | |
if (rendered !== false && typeof config.afterRender === 'function') { | |
config.afterRender(); | |
} | |
} | |
}; | |
render(); | |
} | |
_createClass(HyperList, [{ | |
key: 'destroy', | |
value: function destroy() { | |
window.cancelAnimationFrame(this._renderAnimationFrame); | |
} | |
}, { | |
key: 'refresh', | |
value: function refresh(element, userProvidedConfig) { | |
var _this2 = this; | |
Object.assign(this._config, defaultConfig, userProvidedConfig); | |
if (!element || element.nodeType !== 1) { | |
throw new Error('HyperList requires a valid DOM Node container'); | |
} | |
this._element = element; | |
var config = this._config; | |
var scroller = this._scroller || config.scroller || document.createElement(config.scrollerTagName || 'tr'); | |
// Default configuration option `useFragment` to `true`. | |
if (typeof config.useFragment !== 'boolean') { | |
this._config.useFragment = true; | |
} | |
if (!config.generate) { | |
throw new Error('Missing required `generate` function'); | |
} | |
if (!isNumber(config.total)) { | |
throw new Error('Invalid required `total` value, expected number'); | |
} | |
if (!Array.isArray(config.itemHeight) && !isNumber(config.itemHeight)) { | |
throw new Error('\n Invalid required `itemHeight` value, expected number or array\n '.trim()); | |
} else if (isNumber(config.itemHeight)) { | |
this._itemHeights = Array(config.total).fill(config.itemHeight); | |
} else { | |
this._itemHeights = config.itemHeight; | |
} | |
// Width and height should be coerced to string representations. Either in | |
// `%` or `px`. | |
Object.keys(defaultConfig).filter(function (prop) { | |
return prop in config; | |
}).forEach(function (prop) { | |
var value = config[prop]; | |
var isValueNumber = isNumber(value); | |
var isValuePercent = isValueNumber ? false : value.slice(-1) === '%'; | |
if (value && typeof value !== 'string' && typeof value !== 'number') { | |
var msg = 'Invalid optional `' + prop + '`, expected string or number'; | |
throw new Error(msg); | |
} else if (isValueNumber) { | |
config[prop] = value + 'px'; | |
} | |
if (prop !== 'height') { | |
return; | |
} | |
// Compute the containerHeight as number | |
var numberValue = isValueNumber ? value : parseInt(value.replace(/px|%/, ''), 10); | |
if (isValuePercent) { | |
_this2._containerHeight = window.innerHeight * numberValue / 100; | |
} else { | |
_this2._containerHeight = isNumber(value) ? value : numberValue; | |
} | |
}); | |
// Decorate the container element with styles that will match | |
// the user supplied configuration. | |
var elementStyle = { | |
width: '' + config.width, | |
height: '' + config.height, | |
overflow: 'auto', | |
position: 'relative' | |
}; | |
HyperList.mergeStyle(element, elementStyle); | |
var scrollerHeight = config.itemHeight * config.total; | |
var maxElementHeight = this._maxElementHeight; | |
if (scrollerHeight > maxElementHeight) { | |
console.warn(['HyperList: The maximum element height', maxElementHeight + 'px has', 'been exceeded; please reduce your item height.'].join(' ')); | |
} | |
var scrollerStyle = { | |
opacity: '0', | |
position: 'absolute', | |
width: '1px', | |
height: scrollerHeight + 'px' | |
}; | |
HyperList.mergeStyle(scroller, scrollerStyle); | |
// Only append the scroller element once. | |
if (!this._scroller) { | |
element.appendChild(scroller); | |
} | |
// Set the scroller instance. | |
this._scroller = scroller; | |
this._scrollHeight = this._computeScrollHeight(); | |
// Reuse the item positions if refreshed, otherwise set to empty array. | |
this._itemPositions = this._itemPositions || Array(config.total).fill(0); | |
// Each index in the array should represent the position in the DOM. | |
this._computePositions(0); | |
// Render after refreshing. | |
this._renderChunk(); | |
if (typeof config.afterRender === 'function') { | |
config.afterRender(); | |
} | |
} | |
}, { | |
key: '_getRow', | |
value: function _getRow(i) { | |
var config = this._config; | |
var item = config.generate(i); | |
var height = item.height; | |
if (height !== undefined && isNumber(height)) { | |
item = item.element; | |
// The height isn't the same as predicted, compute positions again | |
if (height !== this._itemHeights) { | |
this._itemHeights[i] = height; | |
this._computePositions(i); | |
this._scrollHeight = this._computeScrollHeight(i); | |
} | |
} else { | |
height = this._itemHeights[i]; | |
} | |
if (!item || item.nodeType !== 1) { | |
throw new Error('Generator did not return a DOM Node for index: ' + i); | |
} | |
var oldClass = item.getAttribute('class') || ''; | |
item.setAttribute('class', oldClass + ' ' + (config.rowClassName || 'vrow')); | |
var top = this._itemPositions[i]; | |
HyperList.mergeStyle(item, { | |
position: 'absolute', | |
top: top + 'px' | |
}); | |
return item; | |
} | |
}, { | |
key: '_getScrollPosition', | |
value: function _getScrollPosition() { | |
var config = this._config; | |
if (typeof config.overrideScrollPosition === 'function') { | |
return config.overrideScrollPosition(); | |
} | |
return this._element.scrollTop; | |
} | |
}, { | |
key: '_renderChunk', | |
value: function _renderChunk() { | |
var config = this._config; | |
var element = this._element; | |
var scrollTop = this._getScrollPosition(); | |
var total = config.total; | |
var from = config.reverse ? this._getReverseFrom(scrollTop) : this._getFrom(scrollTop) - 1; | |
from = from < 0 ? 0 : from; | |
if (this._lastFrom === from) { | |
return false; | |
} | |
this._lastFrom = from; | |
var to = from + this._cachedItemsLen; | |
to = to > total ? total : to; | |
// Append all the new rows in a document fragment that we will later append | |
// to the parent node | |
var fragment = config.useFragment ? document.createDocumentFragment() : [] | |
// Sometimes you'll pass fake elements to this tool and Fragments require | |
// real elements. | |
// The element that forces the container to scroll. | |
;var scroller = this._scroller; | |
// Keep the scroller in the list of children. | |
fragment[config.useFragment ? 'appendChild' : 'push'](scroller); | |
for (var i = from; i < to; i++) { | |
var row = this._getRow(i); | |
fragment[config.useFragment ? 'appendChild' : 'push'](row); | |
} | |
if (config.applyPatch) { | |
return config.applyPatch(element, fragment); | |
} | |
element.innerHTML = ''; | |
element.appendChild(fragment); | |
} | |
}, { | |
key: '_computePositions', | |
value: function _computePositions() { | |
var from = arguments.length <= 0 || arguments[0] === undefined ? 1 : arguments[0]; | |
var config = this._config; | |
var total = config.total; | |
var reverse = config.reverse; | |
if (from < 1 && !reverse) { | |
from = 1; | |
} | |
for (var i = from; i < total; i++) { | |
if (reverse) { | |
if (i === 0) { | |
this._itemPositions[0] = this._scrollHeight - this._itemHeights[0]; | |
} else { | |
this._itemPositions[i] = this._itemPositions[i - 1] - this._itemHeights[i]; | |
} | |
} else { | |
this._itemPositions[i] = this._itemHeights[i - 1] + this._itemPositions[i - 1]; | |
} | |
} | |
} | |
}, { | |
key: '_computeScrollHeight', | |
value: function _computeScrollHeight() { | |
var _this3 = this; | |
var config = this._config; | |
var total = config.total; | |
var scrollHeight = this._itemHeights.reduce(function (a, b) { | |
return a + b; | |
}, 0); | |
HyperList.mergeStyle(this._scroller, { | |
opacity: 0, | |
position: 'absolute', | |
width: '1px', | |
height: scrollHeight + 'px' | |
}); | |
var averageHeight = scrollHeight / total; | |
var containerHeight = this._element.innerHeight ? this._element.innerHeight : this._containerHeight; | |
this._screenItemsLen = Math.ceil(containerHeight / averageHeight); | |
this._containerHeight = containerHeight; | |
// Cache 3 times the number of items that fit in the container viewport. | |
this._cachedItemsLen = this._screenItemsLen * 3; | |
this._averageHeight = averageHeight; | |
if (config.reverse) { | |
window.requestAnimationFrame(function () { | |
_this3._element.scrollTop = scrollHeight; | |
}); | |
} | |
return scrollHeight; | |
} | |
}, { | |
key: '_getFrom', | |
value: function _getFrom(scrollTop) { | |
var i = 0; | |
while (this._itemPositions[i] < scrollTop) { | |
i++; | |
} | |
return i; | |
} | |
}, { | |
key: '_getReverseFrom', | |
value: function _getReverseFrom(scrollTop) { | |
var i = this._config.total - 1; | |
while (i > 0 && this._itemPositions[i] < scrollTop + this._containerHeight) { | |
i--; | |
} | |
return i; | |
} | |
}]); | |
return HyperList; | |
}(); | |
exports.default = HyperList; | |
module.exports = exports['default']; | |
},{}]},{},[1])(1) | |
}); | |
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) | |
},{}]},{},[]) | |
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2hvbWUvYWRtaW4vYnJvd3NlcmlmeS1jZG4vbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2Jyb3dzZXItcGFjay9fcHJlbHVkZS5qcyIsImRpc3QvaHlwZXJsaXN0LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsImZpbGUiOiJnZW5lcmF0ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uIGUodCxuLHIpe2Z1bmN0aW9uIHMobyx1KXtpZighbltvXSl7aWYoIXRbb10pe3ZhciBhPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7aWYoIXUmJmEpcmV0dXJuIGEobywhMCk7aWYoaSlyZXR1cm4gaShvLCEwKTt2YXIgZj1uZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK28rXCInXCIpO3Rocm93IGYuY29kZT1cIk1PRFVMRV9OT1RfRk9VTkRcIixmfXZhciBsPW5bb109e2V4cG9ydHM6e319O3Rbb11bMF0uY2FsbChsLmV4cG9ydHMsZnVuY3Rpb24oZSl7dmFyIG49dFtvXVsxXVtlXTtyZXR1cm4gcyhuP246ZSl9LGwsbC5leHBvcnRzLGUsdCxuLHIpfXJldHVybiBuW29dLmV4cG9ydHN9dmFyIGk9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtmb3IodmFyIG89MDtvPHIubGVuZ3RoO28rKylzKHJbb10pO3JldHVybiBzfSkiLCIoZnVuY3Rpb24oZil7aWYodHlwZW9mIGV4cG9ydHM9PT1cIm9iamVjdFwiJiZ0eXBlb2YgbW9kdWxlIT09XCJ1bmRlZmluZWRcIil7bW9kdWxlLmV4cG9ydHM9ZigpfWVsc2UgaWYodHlwZW9mIGRlZmluZT09PVwiZnVuY3Rpb25cIiYmZGVmaW5lLmFtZCl7ZGVmaW5lKFtdLGYpfWVsc2V7dmFyIGc7aWYodHlwZW9mIHdpbmRvdyE9PVwidW5kZWZpbmVkXCIpe2c9d2luZG93fWVsc2UgaWYodHlwZW9mIGdsb2JhbCE9PVwidW5kZWZpbmVkXCIpe2c9Z2xvYmFsfWVsc2UgaWYodHlwZW9mIHNlbGYhPT1cInVuZGVmaW5lZFwiKXtnPXNlbGZ9ZWxzZXtnPXRoaXN9Zy5IeXBlckxpc3QgPSBmKCl9fSkoZnVuY3Rpb24oKXt2YXIgZGVmaW5lLG1vZHVsZSxleHBvcnRzO3JldHVybiAoZnVuY3Rpb24gZSh0LG4scil7ZnVuY3Rpb24gcyhvLHUpe2lmKCFuW29dKXtpZighdFtvXSl7dmFyIGE9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtpZighdSYmYSlyZXR1cm4gYShvLCEwKTtpZihpKXJldHVybiBpKG8sITApO3ZhciBmPW5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIrbytcIidcIik7dGhyb3cgZi5jb2RlPVwiTU9EVUxFX05PVF9GT1VORFwiLGZ9dmFyIGw9bltvXT17ZXhwb3J0czp7fX07dFtvXVswXS5jYWxsKGwuZXhwb3J0cyxmdW5jdGlvbihlKXt2YXIgbj10W29dWzFdW2VdO3JldHVybiBzKG4/bjplKX0sbCxsLmV4cG9ydHMsZSx0LG4scil9cmV0dXJuIG5bb10uZXhwb3J0c312YXIgaT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2Zvcih2YXIgbz0wO288ci5sZW5ndGg7bysrKXMocltvXSk7cmV0dXJuIHN9KSh7MTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCc7XG5cbi8vIERlZmF1bHQgY29uZmlndXJhdGlvbi5cblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcblxudmFyIF9jcmVhdGVDbGFzcyA9IGZ1bmN0aW9uICgpIHsgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmIChcInZhbHVlXCIgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9IHJldHVybiBmdW5jdGlvbiAoQ29uc3RydWN0b3IsIHByb3RvUHJvcHMsIHN0YXRpY1Byb3BzKSB7IGlmIChwcm90b1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7IGlmIChzdGF0aWNQcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvciwgc3RhdGljUHJvcHMpOyByZXR1cm4gQ29uc3RydWN0b3I7IH07IH0oKTtcblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uXCIpOyB9IH1cblxudmFyIGRlZmF1bHRDb25maWcgPSB7XG4gIHdpZHRoOiAnMTAwJScsXG4gIGhlaWdodDogJzEwMCUnXG59O1xuXG4vLyBDaGVjayBmb3IgdmFsaWQgbnVtYmVyLlxudmFyIGlzTnVtYmVyID0gZnVuY3Rpb24gaXNOdW1iZXIoaW5wdXQpIHtcbiAgcmV0dXJuIE51bWJlcihpbnB1dCkgPT09IE51bWJlcihpbnB1dCk7XG59O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBIeXBlckxpc3QgaW5zdGFuY2UgdGhhdCB2aXJ0dWFsbHkgc2Nyb2xscyB2ZXJ5IGxhcmdlIGFtb3VudHMgb2ZcbiAqIGRhdGEgZWZmb3J0bGVzc2x5LlxuICovXG5cbnZhciBIeXBlckxpc3QgPSBmdW5jdGlvbiAoKSB7XG4gIF9jcmVhdGVDbGFzcyhIeXBlckxpc3QsIG51bGwsIFt7XG4gICAga2V5OiAnY3JlYXRlJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gY3JlYXRlKGVsZW1lbnQsIHVzZXJQcm92aWRlZENvbmZpZykge1xuICAgICAgcmV0dXJuIG5ldyBIeXBlckxpc3QoZWxlbWVudCwgdXNlclByb3ZpZGVkQ29uZmlnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNZXJnZSBnaXZlbiBjc3Mgc3R5bGUgb24gYW4gZWxlbWVudFxuICAgICAqIEBwYXJhbSB7RE9NRWxlbWVudH0gZWxlbWVudFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBzdHlsZVxuICAgICAqL1xuXG4gIH0sIHtcbiAgICBrZXk6ICdtZXJnZVN0eWxlJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gbWVyZ2VTdHlsZShlbGVtZW50LCBzdHlsZSkge1xuICAgICAgZm9yICh2YXIgaSBpbiBzdHlsZSkge1xuICAgICAgICBpZiAoZWxlbWVudC5zdHlsZVtpXSAhPT0gc3R5bGVbaV0pIHtcbiAgICAgICAgICBlbGVtZW50LnN0eWxlW2ldID0gc3R5bGVbaV07XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdnZXRNYXhCcm93c2VySGVpZ2h0JyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gZ2V0TWF4QnJvd3NlckhlaWdodCgpIHtcbiAgICAgIC8vIENyZWF0ZSB0d28gZWxlbWVudHMsIHRoZSB3cmFwcGVyIGlzIGAxcHhgIHRhbGwgYW5kIGlzIHRyYW5zcGFyZW50IGFuZFxuICAgICAgLy8gcG9zaXRpb25lZCBhdCB0aGUgdG9wIG9mIHRoZSBwYWdlLiBJbnNpZGUgdGhhdCBpcyBhbiBlbGVtZW50IHRoYXQgZ2V0c1xuICAgICAgLy8gc2V0IHRvIDEgYmlsbGlvbiBwaXhlbHMuIFRoZW4gcmVhZHMgdGhlIG1heCBoZWlnaHQgdGhlIGJyb3dzZXIgY2FuXG4gICAgICAvLyBjYWxjdWxhdGUuXG4gICAgICB2YXIgd3JhcHBlciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgICAgdmFyIGZpeHR1cmUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcblxuICAgICAgLy8gQXMgc2FpZCBhYm92ZSwgdGhlc2UgdmFsdWVzIGdldCBzZXQgdG8gcHV0IHRoZSBmaXh0dXJlIGVsZW1lbnRzIGludG8gdGhlXG4gICAgICAvLyByaWdodCB2aXN1YWwgc3RhdGUuXG4gICAgICBIeXBlckxpc3QubWVyZ2VTdHlsZSh3cmFwcGVyLCB7IHBvc2l0aW9uOiAnYWJzb2x1dGUnLCBoZWlnaHQ6ICcxcHgnLCBvcGFjaXR5OiAwIH0pO1xuICAgICAgSHlwZXJMaXN0Lm1lcmdlU3R5bGUoZml4dHVyZSwgeyBoZWlnaHQ6ICcxZTdweCcgfSk7XG5cbiAgICAgIC8vIEFkZCB0aGUgZml4dHVyZSBpbnRvIHRoZSB3cmFwcGVyIGVsZW1lbnQuXG4gICAgICB3cmFwcGVyLmFwcGVuZENoaWxkKGZpeHR1cmUpO1xuXG4gICAgICAvLyBBcHBseSB0byB0aGUgcGFnZSwgdGhlIHZhbHVlcyB3b24ndCBraWNrIGluIHVubGVzcyB0aGlzIGlzIGF0dGFjaGVkLlxuICAgICAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZCh3cmFwcGVyKTtcblxuICAgICAgLy8gR2V0IHRoZSBtYXhpbXVtIGVsZW1lbnQgaGVpZ2h0IGluIHBpeGVscy5cbiAgICAgIHZhciBtYXhFbGVtZW50SGVpZ2h0ID0gZml4dHVyZS5vZmZzZXRIZWlnaHQ7XG5cbiAgICAgIC8vIFJlbW92ZSB0aGUgZWxlbWVudCBpbW1lZGlhdGVseSBhZnRlciByZWFkaW5nIHRoZSB2YWx1ZS5cbiAgICAgIGRvY3VtZW50LmJvZHkucmVtb3ZlQ2hpbGQod3JhcHBlcik7XG5cbiAgICAgIHJldHVybiBtYXhFbGVtZW50SGVpZ2h0O1xuICAgIH1cbiAgfV0pO1xuXG4gIGZ1bmN0aW9uIEh5cGVyTGlzdChlbGVtZW50LCB1c2VyUHJvdmlkZWRDb25maWcpIHtcbiAgICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIEh5cGVyTGlzdCk7XG5cbiAgICB0aGlzLl9jb25maWcgPSB7fTtcbiAgICB0aGlzLl9sYXN0UmVwYWludCA9IG51bGw7XG4gICAgdGhpcy5fbWF4RWxlbWVudEhlaWdodCA9IEh5cGVyTGlzdC5nZXRNYXhCcm93c2VySGVpZ2h0KCk7XG5cbiAgICB0aGlzLnJlZnJlc2goZWxlbWVudCwgdXNlclByb3ZpZGVkQ29uZmlnKTtcblxuICAgIHZhciBjb25maWcgPSB0aGlzLl9jb25maWc7XG5cbiAgICAvLyBDcmVhdGUgaW50ZXJuYWwgcmVuZGVyIGxvb3AuXG4gICAgdmFyIHJlbmRlciA9IGZ1bmN0aW9uIHJlbmRlcigpIHtcbiAgICAgIHZhciBzY3JvbGxUb3AgPSBfdGhpcy5fZ2V0U2Nyb2xsUG9zaXRpb24oKTtcbiAgICAgIHZhciBsYXN0UmVwYWludCA9IF90aGlzLl9sYXN0UmVwYWludDtcblxuICAgICAgX3RoaXMuX3JlbmRlckFuaW1hdGlvbkZyYW1lID0gd2luZG93LnJlcXVlc3RBbmltYXRpb25GcmFtZShyZW5kZXIpO1xuXG4gICAgICBpZiAoc2Nyb2xsVG9wID09PSBsYXN0UmVwYWludCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGlmICghbGFzdFJlcGFpbnQgfHwgTWF0aC5hYnMoc2Nyb2xsVG9wIC0gbGFzdFJlcGFpbnQpID4gX3RoaXMuX2F2ZXJhZ2VIZWlnaHQpIHtcbiAgICAgICAgdmFyIHJlbmRlcmVkID0gX3RoaXMuX3JlbmRlckNodW5rKCk7XG5cbiAgICAgICAgX3RoaXMuX2xhc3RSZXBhaW50ID0gc2Nyb2xsVG9wO1xuXG4gICAgICAgIGlmIChyZW5kZXJlZCAhPT0gZmFsc2UgJiYgdHlwZW9mIGNvbmZpZy5hZnRlclJlbmRlciA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgIGNvbmZpZy5hZnRlclJlbmRlcigpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfTtcblxuICAgIHJlbmRlcigpO1xuICB9XG5cbiAgX2NyZWF0ZUNsYXNzKEh5cGVyTGlzdCwgW3tcbiAgICBrZXk6ICdkZXN0cm95JyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gZGVzdHJveSgpIHtcbiAgICAgIHdpbmRvdy5jYW5jZWxBbmltYXRpb25GcmFtZSh0aGlzLl9yZW5kZXJBbmltYXRpb25GcmFtZSk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAncmVmcmVzaCcsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHJlZnJlc2goZWxlbWVudCwgdXNlclByb3ZpZGVkQ29uZmlnKSB7XG4gICAgICB2YXIgX3RoaXMyID0gdGhpcztcblxuICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLl9jb25maWcsIGRlZmF1bHRDb25maWcsIHVzZXJQcm92aWRlZENvbmZpZyk7XG5cbiAgICAgIGlmICghZWxlbWVudCB8fCBlbGVtZW50Lm5vZGVUeXBlICE9PSAxKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignSHlwZXJMaXN0IHJlcXVpcmVzIGEgdmFsaWQgRE9NIE5vZGUgY29udGFpbmVyJyk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX2VsZW1lbnQgPSBlbGVtZW50O1xuXG4gICAgICB2YXIgY29uZmlnID0gdGhpcy5fY29uZmlnO1xuXG4gICAgICB2YXIgc2Nyb2xsZXIgPSB0aGlzLl9zY3JvbGxlciB8fCBjb25maWcuc2Nyb2xsZXIgfHwgZG9jdW1lbnQuY3JlYXRlRWxlbWVudChjb25maWcuc2Nyb2xsZXJUYWdOYW1lIHx8ICd0cicpO1xuXG4gICAgICAvLyBEZWZhdWx0IGNvbmZpZ3VyYXRpb24gb3B0aW9uIGB1c2VGcmFnbWVudGAgdG8gYHRydWVgLlxuICAgICAgaWYgKHR5cGVvZiBjb25maWcudXNlRnJhZ21lbnQgIT09ICdib29sZWFuJykge1xuICAgICAgICB0aGlzLl9jb25maWcudXNlRnJhZ21lbnQgPSB0cnVlO1xuICAgICAgfVxuXG4gICAgICBpZiAoIWNvbmZpZy5nZW5lcmF0ZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ01pc3NpbmcgcmVxdWlyZWQgYGdlbmVyYXRlYCBmdW5jdGlvbicpO1xuICAgICAgfVxuXG4gICAgICBpZiAoIWlzTnVtYmVyKGNvbmZpZy50b3RhbCkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIHJlcXVpcmVkIGB0b3RhbGAgdmFsdWUsIGV4cGVjdGVkIG51bWJlcicpO1xuICAgICAgfVxuXG4gICAgICBpZiAoIUFycmF5LmlzQXJyYXkoY29uZmlnLml0ZW1IZWlnaHQpICYmICFpc051bWJlcihjb25maWcuaXRlbUhlaWdodCkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdcXG4gICAgICAgIEludmFsaWQgcmVxdWlyZWQgYGl0ZW1IZWlnaHRgIHZhbHVlLCBleHBlY3RlZCBudW1iZXIgb3IgYXJyYXlcXG4gICAgICAnLnRyaW0oKSk7XG4gICAgICB9IGVsc2UgaWYgKGlzTnVtYmVyKGNvbmZpZy5pdGVtSGVpZ2h0KSkge1xuICAgICAgICB0aGlzLl9pdGVtSGVpZ2h0cyA9IEFycmF5KGNvbmZpZy50b3RhbCkuZmlsbChjb25maWcuaXRlbUhlaWdodCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLl9pdGVtSGVpZ2h0cyA9IGNvbmZpZy5pdGVtSGVpZ2h0O1xuICAgICAgfVxuXG4gICAgICAvLyBXaWR0aCBhbmQgaGVpZ2h0IHNob3VsZCBiZSBjb2VyY2VkIHRvIHN0cmluZyByZXByZXNlbnRhdGlvbnMuIEVpdGhlciBpblxuICAgICAgLy8gYCVgIG9yIGBweGAuXG4gICAgICBPYmplY3Qua2V5cyhkZWZhdWx0Q29uZmlnKS5maWx0ZXIoZnVuY3Rpb24gKHByb3ApIHtcbiAgICAgICAgcmV0dXJuIHByb3AgaW4gY29uZmlnO1xuICAgICAgfSkuZm9yRWFjaChmdW5jdGlvbiAocHJvcCkge1xuICAgICAgICB2YXIgdmFsdWUgPSBjb25maWdbcHJvcF07XG4gICAgICAgIHZhciBpc1ZhbHVlTnVtYmVyID0gaXNOdW1iZXIodmFsdWUpO1xuICAgICAgICB2YXIgaXNWYWx1ZVBlcmNlbnQgPSBpc1ZhbHVlTnVtYmVyID8gZmFsc2UgOiB2YWx1ZS5zbGljZSgtMSkgPT09ICclJztcblxuICAgICAgICBpZiAodmFsdWUgJiYgdHlwZW9mIHZhbHVlICE9PSAnc3RyaW5nJyAmJiB0eXBlb2YgdmFsdWUgIT09ICdudW1iZXInKSB7XG4gICAgICAgICAgdmFyIG1zZyA9ICdJbnZhbGlkIG9wdGlvbmFsIGAnICsgcHJvcCArICdgLCBleHBlY3RlZCBzdHJpbmcgb3IgbnVtYmVyJztcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IobXNnKTtcbiAgICAgICAgfSBlbHNlIGlmIChpc1ZhbHVlTnVtYmVyKSB7XG4gICAgICAgICAgY29uZmlnW3Byb3BdID0gdmFsdWUgKyAncHgnO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHByb3AgIT09ICdoZWlnaHQnKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ29tcHV0ZSB0aGUgY29udGFpbmVySGVpZ2h0IGFzIG51bWJlclxuICAgICAgICB2YXIgbnVtYmVyVmFsdWUgPSBpc1ZhbHVlTnVtYmVyID8gdmFsdWUgOiBwYXJzZUludCh2YWx1ZS5yZXBsYWNlKC9weHwlLywgJycpLCAxMCk7XG5cbiAgICAgICAgaWYgKGlzVmFsdWVQZXJjZW50KSB7XG4gICAgICAgICAgX3RoaXMyLl9jb250YWluZXJIZWlnaHQgPSB3aW5kb3cuaW5uZXJIZWlnaHQgKiBudW1iZXJWYWx1ZSAvIDEwMDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBfdGhpczIuX2NvbnRhaW5lckhlaWdodCA9IGlzTnVtYmVyKHZhbHVlKSA/IHZhbHVlIDogbnVtYmVyVmFsdWU7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICAvLyBEZWNvcmF0ZSB0aGUgY29udGFpbmVyIGVsZW1lbnQgd2l0aCBzdHlsZXMgdGhhdCB3aWxsIG1hdGNoXG4gICAgICAvLyB0aGUgdXNlciBzdXBwbGllZCBjb25maWd1cmF0aW9uLlxuICAgICAgdmFyIGVsZW1lbnRTdHlsZSA9IHtcbiAgICAgICAgd2lkdGg6ICcnICsgY29uZmlnLndpZHRoLFxuICAgICAgICBoZWlnaHQ6ICcnICsgY29uZmlnLmhlaWdodCxcbiAgICAgICAgb3ZlcmZsb3c6ICdhdXRvJyxcbiAgICAgICAgcG9zaXRpb246ICdyZWxhdGl2ZSdcbiAgICAgIH07XG5cbiAgICAgIEh5cGVyTGlzdC5tZXJnZVN0eWxlKGVsZW1lbnQsIGVsZW1lbnRTdHlsZSk7XG5cbiAgICAgIHZhciBzY3JvbGxlckhlaWdodCA9IGNvbmZpZy5pdGVtSGVpZ2h0ICogY29uZmlnLnRvdGFsO1xuICAgICAgdmFyIG1heEVsZW1lbnRIZWlnaHQgPSB0aGlzLl9tYXhFbGVtZW50SGVpZ2h0O1xuXG4gICAgICBpZiAoc2Nyb2xsZXJIZWlnaHQgPiBtYXhFbGVtZW50SGVpZ2h0KSB7XG4gICAgICAgIGNvbnNvbGUud2FybihbJ0h5cGVyTGlzdDogVGhlIG1heGltdW0gZWxlbWVudCBoZWlnaHQnLCBtYXhFbGVtZW50SGVpZ2h0ICsgJ3B4IGhhcycsICdiZWVuIGV4Y2VlZGVkOyBwbGVhc2UgcmVkdWNlIHlvdXIgaXRlbSBoZWlnaHQuJ10uam9pbignICcpKTtcbiAgICAgIH1cblxuICAgICAgdmFyIHNjcm9sbGVyU3R5bGUgPSB7XG4gICAgICAgIG9wYWNpdHk6ICcwJyxcbiAgICAgICAgcG9zaXRpb246ICdhYnNvbHV0ZScsXG4gICAgICAgIHdpZHRoOiAnMXB4JyxcbiAgICAgICAgaGVpZ2h0OiBzY3JvbGxlckhlaWdodCArICdweCdcbiAgICAgIH07XG5cbiAgICAgIEh5cGVyTGlzdC5tZXJnZVN0eWxlKHNjcm9sbGVyLCBzY3JvbGxlclN0eWxlKTtcblxuICAgICAgLy8gT25seSBhcHBlbmQgdGhlIHNjcm9sbGVyIGVsZW1lbnQgb25jZS5cbiAgICAgIGlmICghdGhpcy5fc2Nyb2xsZXIpIHtcbiAgICAgICAgZWxlbWVudC5hcHBlbmRDaGlsZChzY3JvbGxlcik7XG4gICAgICB9XG5cbiAgICAgIC8vIFNldCB0aGUgc2Nyb2xsZXIgaW5zdGFuY2UuXG4gICAgICB0aGlzLl9zY3JvbGxlciA9IHNjcm9sbGVyO1xuICAgICAgdGhpcy5fc2Nyb2xsSGVpZ2h0ID0gdGhpcy5fY29tcHV0ZVNjcm9sbEhlaWdodCgpO1xuXG4gICAgICAvLyBSZXVzZSB0aGUgaXRlbSBwb3NpdGlvbnMgaWYgcmVmcmVzaGVkLCBvdGhlcndpc2Ugc2V0IHRvIGVtcHR5IGFycmF5LlxuICAgICAgdGhpcy5faXRlbVBvc2l0aW9ucyA9IHRoaXMuX2l0ZW1Qb3NpdGlvbnMgfHwgQXJyYXkoY29uZmlnLnRvdGFsKS5maWxsKDApO1xuXG4gICAgICAvLyBFYWNoIGluZGV4IGluIHRoZSBhcnJheSBzaG91bGQgcmVwcmVzZW50IHRoZSBwb3NpdGlvbiBpbiB0aGUgRE9NLlxuICAgICAgdGhpcy5fY29tcHV0ZVBvc2l0aW9ucygwKTtcblxuICAgICAgLy8gUmVuZGVyIGFmdGVyIHJlZnJlc2hpbmcuXG4gICAgICB0aGlzLl9yZW5kZXJDaHVuaygpO1xuXG4gICAgICBpZiAodHlwZW9mIGNvbmZpZy5hZnRlclJlbmRlciA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBjb25maWcuYWZ0ZXJSZW5kZXIoKTtcbiAgICAgIH1cbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfZ2V0Um93JyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gX2dldFJvdyhpKSB7XG4gICAgICB2YXIgY29uZmlnID0gdGhpcy5fY29uZmlnO1xuICAgICAgdmFyIGl0ZW0gPSBjb25maWcuZ2VuZXJhdGUoaSk7XG4gICAgICB2YXIgaGVpZ2h0ID0gaXRlbS5oZWlnaHQ7XG5cbiAgICAgIGlmIChoZWlnaHQgIT09IHVuZGVmaW5lZCAmJiBpc051bWJlcihoZWlnaHQpKSB7XG4gICAgICAgIGl0ZW0gPSBpdGVtLmVsZW1lbnQ7XG5cbiAgICAgICAgLy8gVGhlIGhlaWdodCBpc24ndCB0aGUgc2FtZSBhcyBwcmVkaWN0ZWQsIGNvbXB1dGUgcG9zaXRpb25zIGFnYWluXG4gICAgICAgIGlmIChoZWlnaHQgIT09IHRoaXMuX2l0ZW1IZWlnaHRzKSB7XG4gICAgICAgICAgdGhpcy5faXRlbUhlaWdodHNbaV0gPSBoZWlnaHQ7XG4gICAgICAgICAgdGhpcy5fY29tcHV0ZVBvc2l0aW9ucyhpKTtcbiAgICAgICAgICB0aGlzLl9zY3JvbGxIZWlnaHQgPSB0aGlzLl9jb21wdXRlU2Nyb2xsSGVpZ2h0KGkpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBoZWlnaHQgPSB0aGlzLl9pdGVtSGVpZ2h0c1tpXTtcbiAgICAgIH1cblxuICAgICAgaWYgKCFpdGVtIHx8IGl0ZW0ubm9kZVR5cGUgIT09IDEpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdHZW5lcmF0b3IgZGlkIG5vdCByZXR1cm4gYSBET00gTm9kZSBmb3IgaW5kZXg6ICcgKyBpKTtcbiAgICAgIH1cblxuICAgICAgdmFyIG9sZENsYXNzID0gaXRlbS5nZXRBdHRyaWJ1dGUoJ2NsYXNzJykgfHwgJyc7XG4gICAgICBpdGVtLnNldEF0dHJpYnV0ZSgnY2xhc3MnLCBvbGRDbGFzcyArICcgJyArIChjb25maWcucm93Q2xhc3NOYW1lIHx8ICd2cm93JykpO1xuXG4gICAgICB2YXIgdG9wID0gdGhpcy5faXRlbVBvc2l0aW9uc1tpXTtcblxuICAgICAgSHlwZXJMaXN0Lm1lcmdlU3R5bGUoaXRlbSwge1xuICAgICAgICBwb3NpdGlvbjogJ2Fic29sdXRlJyxcbiAgICAgICAgdG9wOiB0b3AgKyAncHgnXG4gICAgICB9KTtcblxuICAgICAgcmV0dXJuIGl0ZW07XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX2dldFNjcm9sbFBvc2l0aW9uJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gX2dldFNjcm9sbFBvc2l0aW9uKCkge1xuICAgICAgdmFyIGNvbmZpZyA9IHRoaXMuX2NvbmZpZztcblxuICAgICAgaWYgKHR5cGVvZiBjb25maWcub3ZlcnJpZGVTY3JvbGxQb3NpdGlvbiA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICByZXR1cm4gY29uZmlnLm92ZXJyaWRlU2Nyb2xsUG9zaXRpb24oKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMuX2VsZW1lbnQuc2Nyb2xsVG9wO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19yZW5kZXJDaHVuaycsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9yZW5kZXJDaHVuaygpIHtcbiAgICAgIHZhciBjb25maWcgPSB0aGlzLl9jb25maWc7XG4gICAgICB2YXIgZWxlbWVudCA9IHRoaXMuX2VsZW1lbnQ7XG4gICAgICB2YXIgc2Nyb2xsVG9wID0gdGhpcy5fZ2V0U2Nyb2xsUG9zaXRpb24oKTtcbiAgICAgIHZhciB0b3RhbCA9IGNvbmZpZy50b3RhbDtcblxuICAgICAgdmFyIGZyb20gPSBjb25maWcucmV2ZXJzZSA/IHRoaXMuX2dldFJldmVyc2VGcm9tKHNjcm9sbFRvcCkgOiB0aGlzLl9nZXRGcm9tKHNjcm9sbFRvcCkgLSAxO1xuICAgICAgZnJvbSA9IGZyb20gPCAwID8gMCA6IGZyb207XG5cbiAgICAgIGlmICh0aGlzLl9sYXN0RnJvbSA9PT0gZnJvbSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX2xhc3RGcm9tID0gZnJvbTtcblxuICAgICAgdmFyIHRvID0gZnJvbSArIHRoaXMuX2NhY2hlZEl0ZW1zTGVuO1xuICAgICAgdG8gPSB0byA+IHRvdGFsID8gdG90YWwgOiB0bztcblxuICAgICAgLy8gQXBwZW5kIGFsbCB0aGUgbmV3IHJvd3MgaW4gYSBkb2N1bWVudCBmcmFnbWVudCB0aGF0IHdlIHdpbGwgbGF0ZXIgYXBwZW5kXG4gICAgICAvLyB0byB0aGUgcGFyZW50IG5vZGVcbiAgICAgIHZhciBmcmFnbWVudCA9IGNvbmZpZy51c2VGcmFnbWVudCA/IGRvY3VtZW50LmNyZWF0ZURvY3VtZW50RnJhZ21lbnQoKSA6IFtdXG4gICAgICAvLyBTb21ldGltZXMgeW91J2xsIHBhc3MgZmFrZSBlbGVtZW50cyB0byB0aGlzIHRvb2wgYW5kIEZyYWdtZW50cyByZXF1aXJlXG4gICAgICAvLyByZWFsIGVsZW1lbnRzLlxuXG5cbiAgICAgIC8vIFRoZSBlbGVtZW50IHRoYXQgZm9yY2VzIHRoZSBjb250YWluZXIgdG8gc2Nyb2xsLlxuICAgICAgO3ZhciBzY3JvbGxlciA9IHRoaXMuX3Njcm9sbGVyO1xuXG4gICAgICAvLyBLZWVwIHRoZSBzY3JvbGxlciBpbiB0aGUgbGlzdCBvZiBjaGlsZHJlbi5cbiAgICAgIGZyYWdtZW50W2NvbmZpZy51c2VGcmFnbWVudCA/ICdhcHBlbmRDaGlsZCcgOiAncHVzaCddKHNjcm9sbGVyKTtcblxuICAgICAgZm9yICh2YXIgaSA9IGZyb207IGkgPCB0bzsgaSsrKSB7XG4gICAgICAgIHZhciByb3cgPSB0aGlzLl9nZXRSb3coaSk7XG5cbiAgICAgICAgZnJhZ21lbnRbY29uZmlnLnVzZUZyYWdtZW50ID8gJ2FwcGVuZENoaWxkJyA6ICdwdXNoJ10ocm93KTtcbiAgICAgIH1cblxuICAgICAgaWYgKGNvbmZpZy5hcHBseVBhdGNoKSB7XG4gICAgICAgIHJldHVybiBjb25maWcuYXBwbHlQYXRjaChlbGVtZW50LCBmcmFnbWVudCk7XG4gICAgICB9XG5cbiAgICAgIGVsZW1lbnQuaW5uZXJIVE1MID0gJyc7XG4gICAgICBlbGVtZW50LmFwcGVuZENoaWxkKGZyYWdtZW50KTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfY29tcHV0ZVBvc2l0aW9ucycsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9jb21wdXRlUG9zaXRpb25zKCkge1xuICAgICAgdmFyIGZyb20gPSBhcmd1bWVudHMubGVuZ3RoIDw9IDAgfHwgYXJndW1lbnRzWzBdID09PSB1bmRlZmluZWQgPyAxIDogYXJndW1lbnRzWzBdO1xuXG4gICAgICB2YXIgY29uZmlnID0gdGhpcy5fY29uZmlnO1xuICAgICAgdmFyIHRvdGFsID0gY29uZmlnLnRvdGFsO1xuICAgICAgdmFyIHJldmVyc2UgPSBjb25maWcucmV2ZXJzZTtcblxuICAgICAgaWYgKGZyb20gPCAxICYmICFyZXZlcnNlKSB7XG4gICAgICAgIGZyb20gPSAxO1xuICAgICAgfVxuXG4gICAgICBmb3IgKHZhciBpID0gZnJvbTsgaSA8IHRvdGFsOyBpKyspIHtcbiAgICAgICAgaWYgKHJldmVyc2UpIHtcbiAgICAgICAgICBpZiAoaSA9PT0gMCkge1xuICAgICAgICAgICAgdGhpcy5faXRlbVBvc2l0aW9uc1swXSA9IHRoaXMuX3Njcm9sbEhlaWdodCAtIHRoaXMuX2l0ZW1IZWlnaHRzWzBdO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLl9pdGVtUG9zaXRpb25zW2ldID0gdGhpcy5faXRlbVBvc2l0aW9uc1tpIC0gMV0gLSB0aGlzLl9pdGVtSGVpZ2h0c1tpXTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy5faXRlbVBvc2l0aW9uc1tpXSA9IHRoaXMuX2l0ZW1IZWlnaHRzW2kgLSAxXSArIHRoaXMuX2l0ZW1Qb3NpdGlvbnNbaSAtIDFdO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnX2NvbXB1dGVTY3JvbGxIZWlnaHQnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBfY29tcHV0ZVNjcm9sbEhlaWdodCgpIHtcbiAgICAgIHZhciBfdGhpczMgPSB0aGlzO1xuXG4gICAgICB2YXIgY29uZmlnID0gdGhpcy5fY29uZmlnO1xuICAgICAgdmFyIHRvdGFsID0gY29uZmlnLnRvdGFsO1xuICAgICAgdmFyIHNjcm9sbEhlaWdodCA9IHRoaXMuX2l0ZW1IZWlnaHRzLnJlZHVjZShmdW5jdGlvbiAoYSwgYikge1xuICAgICAgICByZXR1cm4gYSArIGI7XG4gICAgICB9LCAwKTtcblxuICAgICAgSHlwZXJMaXN0Lm1lcmdlU3R5bGUodGhpcy5fc2Nyb2xsZXIsIHtcbiAgICAgICAgb3BhY2l0eTogMCxcbiAgICAgICAgcG9zaXRpb246ICdhYnNvbHV0ZScsXG4gICAgICAgIHdpZHRoOiAnMXB4JyxcbiAgICAgICAgaGVpZ2h0OiBzY3JvbGxIZWlnaHQgKyAncHgnXG4gICAgICB9KTtcblxuICAgICAgdmFyIGF2ZXJhZ2VIZWlnaHQgPSBzY3JvbGxIZWlnaHQgLyB0b3RhbDtcbiAgICAgIHZhciBjb250YWluZXJIZWlnaHQgPSB0aGlzLl9lbGVtZW50LmlubmVySGVpZ2h0ID8gdGhpcy5fZWxlbWVudC5pbm5lckhlaWdodCA6IHRoaXMuX2NvbnRhaW5lckhlaWdodDtcbiAgICAgIHRoaXMuX3NjcmVlbkl0ZW1zTGVuID0gTWF0aC5jZWlsKGNvbnRhaW5lckhlaWdodCAvIGF2ZXJhZ2VIZWlnaHQpO1xuICAgICAgdGhpcy5fY29udGFpbmVySGVpZ2h0ID0gY29udGFpbmVySGVpZ2h0O1xuXG4gICAgICAvLyBDYWNoZSAzIHRpbWVzIHRoZSBudW1iZXIgb2YgaXRlbXMgdGhhdCBmaXQgaW4gdGhlIGNvbnRhaW5lciB2aWV3cG9ydC5cbiAgICAgIHRoaXMuX2NhY2hlZEl0ZW1zTGVuID0gdGhpcy5fc2NyZWVuSXRlbXNMZW4gKiAzO1xuICAgICAgdGhpcy5fYXZlcmFnZUhlaWdodCA9IGF2ZXJhZ2VIZWlnaHQ7XG5cbiAgICAgIGlmIChjb25maWcucmV2ZXJzZSkge1xuICAgICAgICB3aW5kb3cucmVxdWVzdEFuaW1hdGlvbkZyYW1lKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBfdGhpczMuX2VsZW1lbnQuc2Nyb2xsVG9wID0gc2Nyb2xsSGVpZ2h0O1xuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHNjcm9sbEhlaWdodDtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdfZ2V0RnJvbScsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9nZXRGcm9tKHNjcm9sbFRvcCkge1xuICAgICAgdmFyIGkgPSAwO1xuXG4gICAgICB3aGlsZSAodGhpcy5faXRlbVBvc2l0aW9uc1tpXSA8IHNjcm9sbFRvcCkge1xuICAgICAgICBpKys7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ19nZXRSZXZlcnNlRnJvbScsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIF9nZXRSZXZlcnNlRnJvbShzY3JvbGxUb3ApIHtcbiAgICAgIHZhciBpID0gdGhpcy5fY29uZmlnLnRvdGFsIC0gMTtcblxuICAgICAgd2hpbGUgKGkgPiAwICYmIHRoaXMuX2l0ZW1Qb3NpdGlvbnNbaV0gPCBzY3JvbGxUb3AgKyB0aGlzLl9jb250YWluZXJIZWlnaHQpIHtcbiAgICAgICAgaS0tO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gaTtcbiAgICB9XG4gIH1dKTtcblxuICByZXR1cm4gSHlwZXJMaXN0O1xufSgpO1xuXG5leHBvcnRzLmRlZmF1bHQgPSBIeXBlckxpc3Q7XG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHNbJ2RlZmF1bHQnXTtcblxufSx7fV19LHt9LFsxXSkoMSlcbn0pOyJdfQ== | |
// Welcome! require() some modules from npm (like you were using browserify) | |
// and then hit Run Code to run your code on the right side. | |
// Modules get downloaded from browserify-cdn and bundled in your browser. | |
const HyperList = require('hyperlist') | |
const root = document.createElement('div') | |
const data = ['a', 'b', 'c', 'd'] | |
const conf = { | |
height: 160, | |
itemHeight: 10, | |
total: 80, | |
generate: function (idx) { | |
const el = document.createElement('span') | |
el.innerHTML = `${data[idx] ? data[idx] : 'placeholder'}` | |
if (data[idx] && idx > 3) { | |
el.style.color = 'red' | |
} | |
return el | |
} | |
}; | |
const list = new HyperList(root, conf); | |
document.body.appendChild(root) | |
setTimeout(function () { | |
data.push(...['e', 'f', 'g', 'h']) | |
list.refresh(root, conf) | |
const notice = document.createElement('span') | |
notice.innerHTML = 'Scroll down & then up please' | |
document.body.appendChild(notice) | |
}, 2500) | |
// scroll manually -> see the list | |
;}, 0) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "requirebin-sketch", | |
"version": "1.0.0", | |
"dependencies": { | |
"hyperlist": "1.0.0-alpha-7" | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- contents of this file will be placed inside the <body> --> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- contents of this file will be placed inside the <head> --> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment