You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
518 lines
35 KiB
518 lines
35 KiB
6 years ago
|
!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.Slideout=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){
|
||
|
'use strict';
|
||
|
|
||
|
/**
|
||
|
* Module dependencies
|
||
|
*/
|
||
|
var decouple = require('decouple');
|
||
|
var Emitter = require('emitter');
|
||
|
|
||
|
/**
|
||
|
* Privates
|
||
|
*/
|
||
|
var scrollTimeout;
|
||
|
var scrolling = false;
|
||
|
var doc = window.document;
|
||
|
var html = doc.documentElement;
|
||
|
var msPointerSupported = window.navigator.msPointerEnabled;
|
||
|
var touch = {
|
||
|
'start': msPointerSupported ? 'MSPointerDown' : 'touchstart',
|
||
|
'move': msPointerSupported ? 'MSPointerMove' : 'touchmove',
|
||
|
'end': msPointerSupported ? 'MSPointerUp' : 'touchend'
|
||
|
};
|
||
|
var prefix = (function prefix() {
|
||
|
var regex = /^(Webkit|Khtml|Moz|ms|O)(?=[A-Z])/;
|
||
|
var styleDeclaration = doc.getElementsByTagName('script')[0].style;
|
||
|
for (var prop in styleDeclaration) {
|
||
|
if (regex.test(prop)) {
|
||
|
return '-' + prop.match(regex)[0].toLowerCase() + '-';
|
||
|
}
|
||
|
}
|
||
|
// Nothing found so far? Webkit does not enumerate over the CSS properties of the style object.
|
||
|
// However (prop in style) returns the correct value, so we'll have to test for
|
||
|
// the precence of a specific property
|
||
|
if ('WebkitOpacity' in styleDeclaration) { return '-webkit-'; }
|
||
|
if ('KhtmlOpacity' in styleDeclaration) { return '-khtml-'; }
|
||
|
return '';
|
||
|
}());
|
||
|
function extend(destination, from) {
|
||
|
for (var prop in from) {
|
||
|
if (from[prop]) {
|
||
|
destination[prop] = from[prop];
|
||
|
}
|
||
|
}
|
||
|
return destination;
|
||
|
}
|
||
|
function inherits(child, uber) {
|
||
|
child.prototype = extend(child.prototype || {}, uber.prototype);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Slideout constructor
|
||
|
*/
|
||
|
function Slideout(options) {
|
||
|
options = options || {};
|
||
|
|
||
|
// Sets default values
|
||
|
this._startOffsetX = 0;
|
||
|
this._currentOffsetX = 0;
|
||
|
this._opening = false;
|
||
|
this._moved = false;
|
||
|
this._opened = false;
|
||
|
this._preventOpen = false;
|
||
|
this._touch = options.touch === undefined ? true : options.touch && true;
|
||
|
|
||
|
// Sets panel
|
||
|
this.panel = options.panel;
|
||
|
this.menu = options.menu;
|
||
|
|
||
|
// Sets classnames
|
||
|
if(this.panel.className.search('slideout-panel') === -1) { this.panel.className += ' slideout-panel'; }
|
||
|
if(this.menu.className.search('slideout-menu') === -1) { this.menu.className += ' slideout-menu'; }
|
||
|
|
||
|
|
||
|
// Sets options
|
||
|
this._fx = options.fx || 'ease';
|
||
|
this._duration = parseInt(options.duration, 10) || 300;
|
||
|
this._tolerance = parseInt(options.tolerance, 10) || 70;
|
||
|
this._padding = this._translateTo = parseInt(options.padding, 10) || 256;
|
||
|
this._orientation = options.side === 'right' ? -1 : 1;
|
||
|
this._translateTo *= this._orientation;
|
||
|
|
||
|
// Init touch events
|
||
|
if (this._touch) {
|
||
|
this._initTouchEvents();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Inherits from Emitter
|
||
|
*/
|
||
|
inherits(Slideout, Emitter);
|
||
|
|
||
|
/**
|
||
|
* Opens the slideout menu.
|
||
|
*/
|
||
|
Slideout.prototype.open = function() {
|
||
|
var self = this;
|
||
|
this.emit('beforeopen');
|
||
|
if (html.className.search('slideout-open') === -1) { html.className += ' slideout-open'; }
|
||
|
this._setTransition();
|
||
|
this._translateXTo(this._translateTo);
|
||
|
this._opened = true;
|
||
|
setTimeout(function() {
|
||
|
self.panel.style.transition = self.panel.style['-webkit-transition'] = '';
|
||
|
self.emit('open');
|
||
|
}, this._duration + 50);
|
||
|
return this;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Closes slideout menu.
|
||
|
*/
|
||
|
Slideout.prototype.close = function() {
|
||
|
var self = this;
|
||
|
if (!this.isOpen() && !this._opening) {
|
||
|
return this;
|
||
|
}
|
||
|
this.emit('beforeclose');
|
||
|
this._setTransition();
|
||
|
this._translateXTo(0);
|
||
|
this._opened = false;
|
||
|
setTimeout(function() {
|
||
|
html.className = html.className.replace(/ slideout-open/, '');
|
||
|
self.panel.style.transition = self.panel.style['-webkit-transition'] = self.panel.style[prefix + 'transform'] = self.panel.style.transform = '';
|
||
|
self.emit('close');
|
||
|
}, this._duration + 50);
|
||
|
return this;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Toggles (open/close) slideout menu.
|
||
|
*/
|
||
|
Slideout.prototype.toggle = function() {
|
||
|
return this.isOpen() ? this.close() : this.open();
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Returns true if the slideout is currently open, and false if it is closed.
|
||
|
*/
|
||
|
Slideout.prototype.isOpen = function() {
|
||
|
return this._opened;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Translates panel and updates currentOffset with a given X point
|
||
|
*/
|
||
|
Slideout.prototype._translateXTo = function(translateX) {
|
||
|
this._currentOffsetX = translateX;
|
||
|
this.panel.style[prefix + 'transform'] = this.panel.style.transform = 'translateX(' + translateX + 'px)';
|
||
|
return this;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Set transition properties
|
||
|
*/
|
||
|
Slideout.prototype._setTransition = function() {
|
||
|
this.panel.style[prefix + 'transition'] = this.panel.style.transition = prefix + 'transform ' + this._duration + 'ms ' + this._fx;
|
||
|
return this;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Initializes touch event
|
||
|
*/
|
||
|
Slideout.prototype._initTouchEvents = function() {
|
||
|
var self = this;
|
||
|
|
||
|
/**
|
||
|
* Decouple scroll event
|
||
|
*/
|
||
|
this._onScrollFn = decouple(doc, 'scroll', function() {
|
||
|
if (!self._moved) {
|
||
|
clearTimeout(scrollTimeout);
|
||
|
scrolling = true;
|
||
|
scrollTimeout = setTimeout(function() {
|
||
|
scrolling = false;
|
||
|
}, 250);
|
||
|
}
|
||
|
});
|
||
|
|
||
|
/**
|
||
|
* Prevents touchmove event if slideout is moving
|
||
|
*/
|
||
|
this._preventMove = function(eve) {
|
||
|
if (self._moved) {
|
||
|
eve.preventDefault();
|
||
|
}
|
||
|
};
|
||
|
|
||
|
doc.addEventListener(touch.move, this._preventMove);
|
||
|
|
||
|
/**
|
||
|
* Resets values on touchstart
|
||
|
*/
|
||
|
this._resetTouchFn = function(eve) {
|
||
|
if (typeof eve.touches === 'undefined') {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
self._moved = false;
|
||
|
self._opening = false;
|
||
|
self._startOffsetX = eve.touches[0].pageX;
|
||
|
self._preventOpen = (!self._touch || (!self.isOpen() && self.menu.clientWidth !== 0));
|
||
|
};
|
||
|
|
||
|
this.panel.addEventListener(touch.start, this._resetTouchFn);
|
||
|
|
||
|
/**
|
||
|
* Resets values on touchcancel
|
||
|
*/
|
||
|
this._onTouchCancelFn = function() {
|
||
|
self._moved = false;
|
||
|
self._opening = false;
|
||
|
};
|
||
|
|
||
|
this.panel.addEventListener('touchcancel', this._onTouchCancelFn);
|
||
|
|
||
|
/**
|
||
|
* Toggles slideout on touchend
|
||
|
*/
|
||
|
this._onTouchEndFn = function() {
|
||
|
if (self._moved) {
|
||
|
(self._opening && Math.abs(self._currentOffsetX) > self._tolerance) ? self.open() : self.close();
|
||
|
}
|
||
|
self._moved = false;
|
||
|
};
|
||
|
|
||
|
this.panel.addEventListener(touch.end, this._onTouchEndFn);
|
||
|
|
||
|
/**
|
||
|
* Translates panel on touchmove
|
||
|
*/
|
||
|
this._onTouchMoveFn = function(eve) {
|
||
|
|
||
|
if (scrolling || self._preventOpen || typeof eve.touches === 'undefined') {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var dif_x = eve.touches[0].clientX - self._startOffsetX;
|
||
|
var translateX = self._currentOffsetX = dif_x;
|
||
|
|
||
|
if (Math.abs(translateX) > self._padding) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (Math.abs(dif_x) > 20) {
|
||
|
|
||
|
self._opening = true;
|
||
|
|
||
|
var oriented_dif_x = dif_x * self._orientation;
|
||
|
|
||
|
if (self._opened && oriented_dif_x > 0 || !self._opened && oriented_dif_x < 0) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (oriented_dif_x <= 0) {
|
||
|
translateX = dif_x + self._padding * self._orientation;
|
||
|
self._opening = false;
|
||
|
}
|
||
|
|
||
|
if (!self._moved && html.className.search('slideout-open') === -1) {
|
||
|
html.className += ' slideout-open';
|
||
|
}
|
||
|
|
||
|
self.panel.style[prefix + 'transform'] = self.panel.style.transform = 'translateX(' + translateX + 'px)';
|
||
|
self.emit('translate', translateX);
|
||
|
self._moved = true;
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
this.panel.addEventListener(touch.move, this._onTouchMoveFn);
|
||
|
|
||
|
return this;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Enable opening the slideout via touch events.
|
||
|
*/
|
||
|
Slideout.prototype.enableTouch = function() {
|
||
|
this._touch = true;
|
||
|
return this;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Disable opening the slideout via touch events.
|
||
|
*/
|
||
|
Slideout.prototype.disableTouch = function() {
|
||
|
this._touch = false;
|
||
|
return this;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Destroy an instance of slideout.
|
||
|
*/
|
||
|
Slideout.prototype.destroy = function() {
|
||
|
// Close before clean
|
||
|
this.close();
|
||
|
|
||
|
// Remove event listeners
|
||
|
doc.removeEventListener(touch.move, this._preventMove);
|
||
|
this.panel.removeEventListener(touch.start, this._resetTouchFn);
|
||
|
this.panel.removeEventListener('touchcancel', this._onTouchCancelFn);
|
||
|
this.panel.removeEventListener(touch.end, this._onTouchEndFn);
|
||
|
this.panel.removeEventListener(touch.move, this._onTouchMoveFn);
|
||
|
doc.removeEventListener('scroll', this._onScrollFn);
|
||
|
|
||
|
// Remove methods
|
||
|
this.open = this.close = function() {};
|
||
|
|
||
|
// Return the instance so it can be easily dereferenced
|
||
|
return this;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Expose Slideout
|
||
|
*/
|
||
|
module.exports = Slideout;
|
||
|
|
||
|
},{"decouple":2,"emitter":3}],2:[function(require,module,exports){
|
||
|
'use strict';
|
||
|
|
||
|
var requestAnimFrame = (function() {
|
||
|
return window.requestAnimationFrame ||
|
||
|
window.webkitRequestAnimationFrame ||
|
||
|
function (callback) {
|
||
|
window.setTimeout(callback, 1000 / 60);
|
||
|
};
|
||
|
}());
|
||
|
|
||
|
function decouple(node, event, fn) {
|
||
|
var eve,
|
||
|
tracking = false;
|
||
|
|
||
|
function captureEvent(e) {
|
||
|
eve = e;
|
||
|
track();
|
||
|
}
|
||
|
|
||
|
function track() {
|
||
|
if (!tracking) {
|
||
|
requestAnimFrame(update);
|
||
|
tracking = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function update() {
|
||
|
fn.call(node, eve);
|
||
|
tracking = false;
|
||
|
}
|
||
|
|
||
|
node.addEventListener(event, captureEvent, false);
|
||
|
|
||
|
return captureEvent;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Expose decouple
|
||
|
*/
|
||
|
module.exports = decouple;
|
||
|
|
||
|
},{}],3:[function(require,module,exports){
|
||
|
"use strict";
|
||
|
|
||
|
var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } };
|
||
|
|
||
|
exports.__esModule = true;
|
||
|
/**
|
||
|
* Creates a new instance of Emitter.
|
||
|
* @class
|
||
|
* @returns {Object} Returns a new instance of Emitter.
|
||
|
* @example
|
||
|
* // Creates a new instance of Emitter.
|
||
|
* var Emitter = require('emitter');
|
||
|
*
|
||
|
* var emitter = new Emitter();
|
||
|
*/
|
||
|
|
||
|
var Emitter = (function () {
|
||
|
function Emitter() {
|
||
|
_classCallCheck(this, Emitter);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Adds a listener to the collection for the specified event.
|
||
|
* @memberof! Emitter.prototype
|
||
|
* @function
|
||
|
* @param {String} event - The event name.
|
||
|
* @param {Function} listener - A listener function to add.
|
||
|
* @returns {Object} Returns an instance of Emitter.
|
||
|
* @example
|
||
|
* // Add an event listener to "foo" event.
|
||
|
* emitter.on('foo', listener);
|
||
|
*/
|
||
|
|
||
|
Emitter.prototype.on = function on(event, listener) {
|
||
|
// Use the current collection or create it.
|
||
|
this._eventCollection = this._eventCollection || {};
|
||
|
|
||
|
// Use the current collection of an event or create it.
|
||
|
this._eventCollection[event] = this._eventCollection[event] || [];
|
||
|
|
||
|
// Appends the listener into the collection of the given event
|
||
|
this._eventCollection[event].push(listener);
|
||
|
|
||
|
return this;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Adds a listener to the collection for the specified event that will be called only once.
|
||
|
* @memberof! Emitter.prototype
|
||
|
* @function
|
||
|
* @param {String} event - The event name.
|
||
|
* @param {Function} listener - A listener function to add.
|
||
|
* @returns {Object} Returns an instance of Emitter.
|
||
|
* @example
|
||
|
* // Will add an event handler to "foo" event once.
|
||
|
* emitter.once('foo', listener);
|
||
|
*/
|
||
|
|
||
|
Emitter.prototype.once = function once(event, listener) {
|
||
|
var self = this;
|
||
|
|
||
|
function fn() {
|
||
|
self.off(event, fn);
|
||
|
listener.apply(this, arguments);
|
||
|
}
|
||
|
|
||
|
fn.listener = listener;
|
||
|
|
||
|
this.on(event, fn);
|
||
|
|
||
|
return this;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Removes a listener from the collection for the specified event.
|
||
|
* @memberof! Emitter.prototype
|
||
|
* @function
|
||
|
* @param {String} event - The event name.
|
||
|
* @param {Function} listener - A listener function to remove.
|
||
|
* @returns {Object} Returns an instance of Emitter.
|
||
|
* @example
|
||
|
* // Remove a given listener.
|
||
|
* emitter.off('foo', listener);
|
||
|
*/
|
||
|
|
||
|
Emitter.prototype.off = function off(event, listener) {
|
||
|
|
||
|
var listeners = undefined;
|
||
|
|
||
|
// Defines listeners value.
|
||
|
if (!this._eventCollection || !(listeners = this._eventCollection[event])) {
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
listeners.forEach(function (fn, i) {
|
||
|
if (fn === listener || fn.listener === listener) {
|
||
|
// Removes the given listener.
|
||
|
listeners.splice(i, 1);
|
||
|
}
|
||
|
});
|
||
|
|
||
|
// Removes an empty event collection.
|
||
|
if (listeners.length === 0) {
|
||
|
delete this._eventCollection[event];
|
||
|
}
|
||
|
|
||
|
return this;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Execute each item in the listener collection in order with the specified data.
|
||
|
* @memberof! Emitter.prototype
|
||
|
* @function
|
||
|
* @param {String} event - The name of the event you want to emit.
|
||
|
* @param {...Object} data - Data to pass to the listeners.
|
||
|
* @returns {Object} Returns an instance of Emitter.
|
||
|
* @example
|
||
|
* // Emits the "foo" event with 'param1' and 'param2' as arguments.
|
||
|
* emitter.emit('foo', 'param1', 'param2');
|
||
|
*/
|
||
|
|
||
|
Emitter.prototype.emit = function emit(event) {
|
||
|
var _this = this;
|
||
|
|
||
|
for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
|
||
|
args[_key - 1] = arguments[_key];
|
||
|
}
|
||
|
|
||
|
var listeners = undefined;
|
||
|
|
||
|
// Defines listeners value.
|
||
|
if (!this._eventCollection || !(listeners = this._eventCollection[event])) {
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
// Clone listeners
|
||
|
listeners = listeners.slice(0);
|
||
|
|
||
|
listeners.forEach(function (fn) {
|
||
|
return fn.apply(_this, args);
|
||
|
});
|
||
|
|
||
|
return this;
|
||
|
};
|
||
|
|
||
|
return Emitter;
|
||
|
})();
|
||
|
|
||
|
/**
|
||
|
* Exports Emitter
|
||
|
*/
|
||
|
exports["default"] = Emitter;
|
||
|
module.exports = exports["default"];
|
||
|
},{}]},{},[1])(1)
|
||
|
});
|
||
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJpbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9kZWNvdXBsZS9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9lbWl0dGVyL2Rpc3QvaW5kZXguanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVUQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbiBlKHQsbixyKXtmdW5jdGlvbiBzKG8sdSl7aWYoIW5bb10pe2lmKCF0W29dKXt2YXIgYT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2lmKCF1JiZhKXJldHVybiBhKG8sITApO2lmKGkpcmV0dXJuIGkobywhMCk7dmFyIGY9bmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIitvK1wiJ1wiKTt0aHJvdyBmLmNvZGU9XCJNT0RVTEVfTk9UX
|