PluginProbe
Boxzilla – WordPress Popup Builder / 3.2
Boxzilla – WordPress Popup Builder v3.2
3.4.11 3.4.10 3.4.9 3.4.3 3.4.4 3.4.5 3.4.6 3.4.7 3.4.8 trunk 3.0 3.0.1 3.0.2 3.0.3 3.1 3.1.1 3.1.10 3.1.11 3.1.12 3.1.13 3.1.14 3.1.15 3.1.16 3.1.17 3.1.18 All 72 releases
← All changes | assets/js/script.js +777 -784 3.1.14 → 3.2 View file →
@@ -1,5 +1,5 @@
1 -(function () { var require = undefined; var module = undefined; var exports = undefined; var define = undefined; (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){
1 +(function () { var require = undefined; var module = undefined; var exports = undefined; var define = undefined; (function(){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}return e})()({1:[function(require,module,exports){
2 2 'use strict';
3 3
4 4 var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
5 5
@@ -39,9 +39,8 @@
39 39 }
40 40 }
41 41
42 42 function createBoxesFromConfig() {
43 - var isLoggedIn = document.body.className.indexOf('logged-in') > -1;
44 43
45 44 // failsafe against including script twice.
46 45 if (options.inited) {
47 46 return;
@@ -46,16 +45,8 @@
46 45 if (options.inited) {
47 46 return;
48 47 }
49 48
50 - // print message when test mode is enabled
51 - if (isLoggedIn && options.testMode) {
52 - console.log('Boxzilla: Test mode is enabled. Please disable test mode if you\'re done testing.');
53 - }
54 -
55 - // init boxzilla
56 - Boxzilla.init();
57 -
58 49 // create boxes from options
59 50 for (var i = 0; i < options.boxes.length; i++) {
60 51 // get opts
61 52 var boxOpts = options.boxes[i];
@@ -60,14 +51,10 @@
60 51 // get opts
61 52 var boxOpts = options.boxes[i];
62 53 boxOpts.testMode = isLoggedIn && options.testMode;
63 54
64 - // fix http:// links in box content....
65 - if (window.location.protocol === "https:" && window.location.host) {
66 - var o = "http://" + window.location.host;
67 - var n = o.replace('http://', 'https://');
68 - boxOpts.content = boxOpts.content.replace(o, n);
69 - }
55 + // set box content element
56 + boxOpts.content = document.getElementById('boxzilla-box-' + boxOpts.id + '-content');
70 57
71 58 // create box
72 59 var box = Boxzilla.create(boxOpts.id, boxOpts);
73 60
@@ -78,8 +65,13 @@
78 65 css(box.element, boxOpts.css);
79 66
80 67 box.element.firstChild.firstChild.className += " first-child";
81 68 box.element.firstChild.lastChild.className += " last-child";
69 +
70 + // maybe show box right away
71 + if (box.fits() && locationHashRefersBox(box)) {
72 + box.show();
73 + }
82 74 }
83 75
84 76 // set flag to prevent initialising twice
85 77 options.inited = true;
@@ -85,32 +77,544 @@
85 77 options.inited = true;
86 78
87 79 // trigger "done" event.
88 80 Boxzilla.trigger('done');
81 +
82 + // maybe open box with MC4WP form in it
83 + maybeOpenMailChimpForWordPressBox();
89 84 }
90 85
91 - function openMailChimpForWordPressBox() {
92 - if (_typeof(window.mc4wp_forms_config) === "object" && window.mc4wp_forms_config.submitted_form) {
93 - var selector = '#' + window.mc4wp_forms_config.submitted_form.element_id;
94 - var boxes = Boxzilla.boxes;
95 - for (var boxId in boxes) {
96 - if (!boxes.hasOwnProperty(boxId)) {
97 - continue;
86 + function locationHashRefersBox(box) {
87 + if (!window.location.hash || 0 === window.location.hash.length) {
88 + return false;
89 + }
90 +
91 + var elementId = window.location.hash.substring(1);
92 +
93 + // only attempt on strings looking like an ID
94 + var regex = /^[a-zA-Z\-\_0-9]+$/;
95 + if (!regex.test(elementId)) {
96 + return false;
97 + }
98 +
99 + if (elementId === box.element.id) {
100 + return true;
101 + } else if (box.element.querySelector('#' + elementId)) {
102 + return true;
103 + }
104 +
105 + return false;
106 + }
107 +
108 + function maybeOpenMailChimpForWordPressBox() {
109 + if (_typeof(window.mc4wp_forms_config) !== "object" || !window.mc4wp_forms_config.submitted_form) {
110 + return;
111 + }
112 +
113 + var selector = '#' + window.mc4wp_forms_config.submitted_form.element_id;
114 + var boxes = Boxzilla.boxes;
115 + for (var boxId in boxes) {
116 + if (!boxes.hasOwnProperty(boxId)) {
117 + continue;
118 + }
119 + var box = boxes[boxId];
120 + if (box.element.querySelector(selector)) {
121 + box.show();
122 + return;
123 + }
124 + }
125 + }
126 +
127 + // print message when test mode is enabled
128 + var isLoggedIn = document.body.className.indexOf('logged-in') > -1;
129 + if (isLoggedIn && options.testMode) {
130 + console.log('Boxzilla: Test mode is enabled. Please disable test mode if you\'re done testing.');
131 + }
132 +
133 + // init boxzilla
134 + Boxzilla.init();
135 +
136 + // on window.load, create DOM elements for boxes
137 + window.addEventListener('load', createBoxesFromConfig);
138 +})();
139 +
140 +},{"boxzilla":5}],2:[function(require,module,exports){
141 +/*!
142 + * EventEmitter v4.2.11 - git.io/ee
143 + * Unlicense - http://unlicense.org/
144 + * Oliver Caldwell - http://oli.me.uk/
145 + * @preserve
146 + */
147 +
148 +;(function () {
149 + 'use strict';
150 +
151 + /**
152 + * Class for managing events.
153 + * Can be extended to provide event functionality in other classes.
154 + *
155 + * @class EventEmitter Manages event registering and emitting.
156 + */
157 + function EventEmitter() {}
158 +
159 + // Shortcuts to improve speed and size
160 + var proto = EventEmitter.prototype;
161 + var exports = this;
162 + var originalGlobalValue = exports.EventEmitter;
163 +
164 + /**
165 + * Finds the index of the listener for the event in its storage array.
166 + *
167 + * @param {Function[]} listeners Array of listeners to search through.
168 + * @param {Function} listener Method to look for.
169 + * @return {Number} Index of the specified listener, -1 if not found
170 + * @api private
171 + */
172 + function indexOfListener(listeners, listener) {
173 + var i = listeners.length;
174 + while (i--) {
175 + if (listeners[i].listener === listener) {
176 + return i;
177 + }
178 + }
179 +
180 + return -1;
181 + }
182 +
183 + /**
184 + * Alias a method while keeping the context correct, to allow for overwriting of target method.
185 + *
186 + * @param {String} name The name of the target method.
187 + * @return {Function} The aliased method
188 + * @api private
189 + */
190 + function alias(name) {
191 + return function aliasClosure() {
192 + return this[name].apply(this, arguments);
193 + };
194 + }
195 +
196 + /**
197 + * Returns the listener array for the specified event.
198 + * Will initialise the event object and listener arrays if required.
199 + * Will return an object if you use a regex search. The object contains keys for each matched event. So /ba[rz]/ might return an object containing bar and baz. But only if you have either defined them with defineEvent or added some listeners to them.
200 + * Each property in the object response is an array of listener functions.
201 + *
202 + * @param {String|RegExp} evt Name of the event to return the listeners from.
203 + * @return {Function[]|Object} All listener functions for the event.
204 + */
205 + proto.getListeners = function getListeners(evt) {
206 + var events = this._getEvents();
207 + var response;
208 + var key;
209 +
210 + // Return a concatenated array of all matching events if
211 + // the selector is a regular expression.
212 + if (evt instanceof RegExp) {
213 + response = {};
214 + for (key in events) {
215 + if (events.hasOwnProperty(key) && evt.test(key)) {
216 + response[key] = events[key];
98 217 }
99 - var box = boxes[boxId];
100 - if (box.element.querySelector(selector)) {
101 - box.show();
102 - return;
218 + }
219 + }
220 + else {
221 + response = events[evt] || (events[evt] = []);
222 + }
223 +
224 + return response;
225 + };
226 +
227 + /**
228 + * Takes a list of listener objects and flattens it into a list of listener functions.
229 + *
230 + * @param {Object[]} listeners Raw listener objects.
231 + * @return {Function[]} Just the listener functions.
232 + */
233 + proto.flattenListeners = function flattenListeners(listeners) {
234 + var flatListeners = [];
235 + var i;
236 +
237 + for (i = 0; i < listeners.length; i += 1) {
238 + flatListeners.push(listeners[i].listener);
239 + }
240 +
241 + return flatListeners;
242 + };
243 +
244 + /**
245 + * Fetches the requested listeners via getListeners but will always return the results inside an object. This is mainly for internal use but others may find it useful.
246 + *
247 + * @param {String|RegExp} evt Name of the event to return the listeners from.
248 + * @return {Object} All listener functions for an event in an object.
249 + */
250 + proto.getListenersAsObject = function getListenersAsObject(evt) {
251 + var listeners = this.getListeners(evt);
252 + var response;
253 +
254 + if (listeners instanceof Array) {
255 + response = {};
256 + response[evt] = listeners;
257 + }
258 +
259 + return response || listeners;
260 + };
261 +
262 + /**
263 + * Adds a listener function to the specified event.
264 + * The listener will not be added if it is a duplicate.
265 + * If the listener returns true then it will be removed after it is called.
266 + * If you pass a regular expression as the event name then the listener will be added to all events that match it.
267 + *
268 + * @param {String|RegExp} evt Name of the event to attach the listener to.
269 + * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.
270 + * @return {Object} Current instance of EventEmitter for chaining.
271 + */
272 + proto.addListener = function addListener(evt, listener) {
273 + var listeners = this.getListenersAsObject(evt);
274 + var listenerIsWrapped = typeof listener === 'object';
275 + var key;
276 +
277 + for (key in listeners) {
278 + if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) {
279 + listeners[key].push(listenerIsWrapped ? listener : {
280 + listener: listener,
281 + once: false
282 + });
283 + }
284 + }
285 +
286 + return this;
287 + };
288 +
289 + /**
290 + * Alias of addListener
291 + */
292 + proto.on = alias('addListener');
293 +
294 + /**
295 + * Semi-alias of addListener. It will add a listener that will be
296 + * automatically removed after its first execution.
297 + *
298 + * @param {String|RegExp} evt Name of the event to attach the listener to.
299 + * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.
300 + * @return {Object} Current instance of EventEmitter for chaining.
301 + */
302 + proto.addOnceListener = function addOnceListener(evt, listener) {
303 + return this.addListener(evt, {
304 + listener: listener,
305 + once: true
306 + });
307 + };
308 +
309 + /**
310 + * Alias of addOnceListener.
311 + */
312 + proto.once = alias('addOnceListener');
313 +
314 + /**
315 + * Defines an event name. This is required if you want to use a regex to add a listener to multiple events at once. If you don't do this then how do you expect it to know what event to add to? Should it just add to every possible match for a regex? No. That is scary and bad.
316 + * You need to tell it what event names should be matched by a regex.
317 + *
318 + * @param {String} evt Name of the event to create.
319 + * @return {Object} Current instance of EventEmitter for chaining.
320 + */
321 + proto.defineEvent = function defineEvent(evt) {
322 + this.getListeners(evt);
323 + return this;
324 + };
325 +
326 + /**
327 + * Uses defineEvent to define multiple events.
328 + *
329 + * @param {String[]} evts An array of event names to define.
330 + * @return {Object} Current instance of EventEmitter for chaining.
331 + */
332 + proto.defineEvents = function defineEvents(evts) {
333 + for (var i = 0; i < evts.length; i += 1) {
334 + this.defineEvent(evts[i]);
335 + }
336 + return this;
337 + };
338 +
339 + /**
340 + * Removes a listener function from the specified event.
341 + * When passed a regular expression as the event name, it will remove the listener from all events that match it.
342 + *
343 + * @param {String|RegExp} evt Name of the event to remove the listener from.
344 + * @param {Function} listener Method to remove from the event.
345 + * @return {Object} Current instance of EventEmitter for chaining.
346 + */
347 + proto.removeListener = function removeListener(evt, listener) {
348 + var listeners = this.getListenersAsObject(evt);
349 + var index;
350 + var key;
351 +
352 + for (key in listeners) {
353 + if (listeners.hasOwnProperty(key)) {
354 + index = indexOfListener(listeners[key], listener);
355 +
356 + if (index !== -1) {
357 + listeners[key].splice(index, 1);
103 358 }
104 359 }
105 360 }
361 +
362 + return this;
363 + };
364 +
365 + /**
366 + * Alias of removeListener
367 + */
368 + proto.off = alias('removeListener');
369 +
370 + /**
371 + * Adds listeners in bulk using the manipulateListeners method.
372 + * If you pass an object as the second argument you can add to multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. You can also pass it an event name and an array of listeners to be added.
373 + * You can also pass it a regular expression to add the array of listeners to all events that match it.
374 + * Yeah, this function does quite a bit. That's probably a bad thing.
375 + *
376 + * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add to multiple events at once.
377 + * @param {Function[]} [listeners] An optional array of listener functions to add.
378 + * @return {Object} Current instance of EventEmitter for chaining.
379 + */
380 + proto.addListeners = function addListeners(evt, listeners) {
381 + // Pass through to manipulateListeners
382 + return this.manipulateListeners(false, evt, listeners);
383 + };
384 +
385 + /**
386 + * Removes listeners in bulk using the manipulateListeners method.
387 + * If you pass an object as the second argument you can remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.
388 + * You can also pass it an event name and an array of listeners to be removed.
389 + * You can also pass it a regular expression to remove the listeners from all events that match it.
390 + *
391 + * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to remove from multiple events at once.
392 + * @param {Function[]} [listeners] An optional array of listener functions to remove.
393 + * @return {Object} Current instance of EventEmitter for chaining.
394 + */
395 + proto.removeListeners = function removeListeners(evt, listeners) {
396 + // Pass through to manipulateListeners
397 + return this.manipulateListeners(true, evt, listeners);
398 + };
399 +
400 + /**
401 + * Edits listeners in bulk. The addListeners and removeListeners methods both use this to do their job. You should really use those instead, this is a little lower level.
402 + * The first argument will determine if the listeners are removed (true) or added (false).
403 + * If you pass an object as the second argument you can add/remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.
404 + * You can also pass it an event name and an array of listeners to be added/removed.
405 + * You can also pass it a regular expression to manipulate the listeners of all events that match it.
406 + *
407 + * @param {Boolean} remove True if you want to remove listeners, false if you want to add.
408 + * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add/remove from multiple events at once.
409 + * @param {Function[]} [listeners] An optional array of listener functions to add/remove.
410 + * @return {Object} Current instance of EventEmitter for chaining.
411 + */
412 + proto.manipulateListeners = function manipulateListeners(remove, evt, listeners) {
413 + var i;
414 + var value;
415 + var single = remove ? this.removeListener : this.addListener;
416 + var multiple = remove ? this.removeListeners : this.addListeners;
417 +
418 + // If evt is an object then pass each of its properties to this method
419 + if (typeof evt === 'object' && !(evt instanceof RegExp)) {
420 + for (i in evt) {
421 + if (evt.hasOwnProperty(i) && (value = evt[i])) {
422 + // Pass the single listener straight through to the singular method
423 + if (typeof value === 'function') {
424 + single.call(this, i, value);
425 + }
426 + else {
427 + // Otherwise pass back to the multiple function
428 + multiple.call(this, i, value);
429 + }
430 + }
431 + }
432 + }
433 + else {
434 + // So evt must be a string
435 + // And listeners must be an array of listeners
436 + // Loop over it and pass each one to the multiple method
437 + i = listeners.length;
438 + while (i--) {
439 + single.call(this, evt, listeners[i]);
440 + }
441 + }
442 +
443 + return this;
444 + };
445 +
446 + /**
447 + * Removes all listeners from a specified event.
448 + * If you do not specify an event then all listeners will be removed.
449 + * That means every event will be emptied.
450 + * You can also pass a regex to remove all events that match it.
451 + *
452 + * @param {String|RegExp} [evt] Optional name of the event to remove all listeners for. Will remove from every event if not passed.
453 + * @return {Object} Current instance of EventEmitter for chaining.
454 + */
455 + proto.removeEvent = function removeEvent(evt) {
456 + var type = typeof evt;
457 + var events = this._getEvents();
458 + var key;
459 +
460 + // Remove different things depending on the state of evt
461 + if (type === 'string') {
462 + // Remove all listeners for the specified event
463 + delete events[evt];
464 + }
465 + else if (evt instanceof RegExp) {
466 + // Remove all events matching the regex.
467 + for (key in events) {
468 + if (events.hasOwnProperty(key) && evt.test(key)) {
469 + delete events[key];
470 + }
471 + }
472 + }
473 + else {
474 + // Remove all listeners in all events
475 + delete this._events;
476 + }
477 +
478 + return this;
479 + };
480 +
481 + /**
482 + * Alias of removeEvent.
483 + *
484 + * Added to mirror the node API.
485 + */
486 + proto.removeAllListeners = alias('removeEvent');
487 +
488 + /**
489 + * Emits an event of your choice.
490 + * When emitted, every listener attached to that event will be executed.
491 + * If you pass the optional argument array then those arguments will be passed to every listener upon execution.
492 + * Because it uses `apply`, your array of arguments will be passed as if you wrote them out separately.
493 + * So they will not arrive within the array on the other side, they will be separate.
494 + * You can also pass a regular expression to emit to all events that match it.
495 + *
496 + * @param {String|RegExp} evt Name of the event to emit and execute listeners for.
497 + * @param {Array} [args] Optional array of arguments to be passed to each listener.
498 + * @return {Object} Current instance of EventEmitter for chaining.
499 + */
500 + proto.emitEvent = function emitEvent(evt, args) {
501 + var listenersMap = this.getListenersAsObject(evt);
502 + var listeners;
503 + var listener;
504 + var i;
505 + var key;
506 + var response;
507 +
508 + for (key in listenersMap) {
509 + if (listenersMap.hasOwnProperty(key)) {
510 + listeners = listenersMap[key].slice(0);
511 + i = listeners.length;
512 +
513 + while (i--) {
514 + // If the listener returns true then it shall be removed from the event
515 + // The function is executed either with a basic call or an apply if there is an args array
516 + listener = listeners[i];
517 +
518 + if (listener.once === true) {
519 + this.removeListener(evt, listener.listener);
520 + }
521 +
522 + response = listener.listener.apply(this, args || []);
523 +
524 + if (response === this._getOnceReturnValue()) {
525 + this.removeListener(evt, listener.listener);
526 + }
527 + }
528 + }
529 + }
530 +
531 + return this;
532 + };
533 +
534 + /**
535 + * Alias of emitEvent
536 + */
537 + proto.trigger = alias('emitEvent');
538 +
539 + /**
540 + * Subtly different from emitEvent in that it will pass its arguments on to the listeners, as opposed to taking a single array of arguments to pass on.
541 + * As with emitEvent, you can pass a regex in place of the event name to emit to all events that match it.
542 + *
543 + * @param {String|RegExp} evt Name of the event to emit and execute listeners for.
544 + * @param {...*} Optional additional arguments to be passed to each listener.
545 + * @return {Object} Current instance of EventEmitter for chaining.
546 + */
547 + proto.emit = function emit(evt) {
548 + var args = Array.prototype.slice.call(arguments, 1);
549 + return this.emitEvent(evt, args);
550 + };
551 +
552 + /**
553 + * Sets the current value to check against when executing listeners. If a
554 + * listeners return value matches the one set here then it will be removed
555 + * after execution. This value defaults to true.
556 + *
557 + * @param {*} value The new value to check for when executing listeners.
558 + * @return {Object} Current instance of EventEmitter for chaining.
559 + */
560 + proto.setOnceReturnValue = function setOnceReturnValue(value) {
561 + this._onceReturnValue = value;
562 + return this;
563 + };
564 +
565 + /**
566 + * Fetches the current value to check against when executing listeners. If
567 + * the listeners return value matches this one then it should be removed
568 + * automatically. It will return true by default.
569 + *
570 + * @return {*|Boolean} The current value to check for or the default, true.
571 + * @api private
572 + */
573 + proto._getOnceReturnValue = function _getOnceReturnValue() {
574 + if (this.hasOwnProperty('_onceReturnValue')) {
575 + return this._onceReturnValue;
576 + }
577 + else {
578 + return true;
579 + }
580 + };
581 +
582 + /**
583 + * Fetches the events object and creates one if required.
584 + *
585 + * @return {Object} The events storage object.
586 + * @api private
587 + */
588 + proto._getEvents = function _getEvents() {
589 + return this._events || (this._events = {});
590 + };
591 +
592 + /**
593 + * Reverts the global {@link EventEmitter} to its previous value and returns a reference to this version.
594 + *
595 + * @return {Function} Non conflicting EventEmitter class.
596 + */
597 + EventEmitter.noConflict = function noConflict() {
598 + exports.EventEmitter = originalGlobalValue;
599 + return EventEmitter;
600 + };
601 +
602 + // Expose the class either via AMD, CommonJS or the global object
603 + if (typeof define === 'function' && define.amd) {
604 + define(function () {
605 + return EventEmitter;
606 + });
106 607 }
608 + else if (typeof module === 'object' && module.exports){
609 + module.exports = EventEmitter;
610 + }
611 + else {
612 + exports.EventEmitter = EventEmitter;
613 + }
614 +}.call(this));
107 615
108 - window.addEventListener('load', openMailChimpForWordPressBox);
109 - createBoxesFromConfig();
110 -})();
111 -
112 -},{"boxzilla":4}],2:[function(require,module,exports){
616 +},{}],3:[function(require,module,exports){
113 617 'use strict';
114 618
115 619 var duration = 320;
116 620
@@ -275,403 +779,364 @@
275 779 'animate': animate,
276 780 'animated': animated
277 781 };
278 782
279 -},{}],3:[function(require,module,exports){
783 +},{}],4:[function(require,module,exports){
280 784 'use strict';
281 785
282 786 var defaults = {
283 - 'animation': 'fade',
284 - 'rehide': false,
285 - 'content': '',
286 - 'cookie': null,
287 - 'icon': '&times',
288 - 'screenWidthCondition': null,
289 - 'position': 'center',
290 - 'testMode': false,
291 - 'trigger': false,
292 - 'closable': true
787 + 'animation': 'fade',
788 + 'rehide': false,
789 + 'content': '',
790 + 'cookie': null,
791 + 'icon': '&times',
792 + 'screenWidthCondition': null,
793 + 'position': 'center',
794 + 'testMode': false,
795 + 'trigger': false,
796 + 'closable': true
293 797 },
294 798 Boxzilla,
295 799 Animator = require('./animator.js');
296 800
297 801 /**
298 - * Merge 2 objects, values of the latter overwriting the former.
299 - *
300 - * @param obj1
301 - * @param obj2
302 - * @returns {*}
303 - */
802 +* Merge 2 objects, values of the latter overwriting the former.
803 +*
804 +* @param obj1
805 +* @param obj2
806 +* @returns {*}
807 +*/
304 808 function merge(obj1, obj2) {
305 - var obj3 = {};
306 - for (var attrname in obj1) {
307 - obj3[attrname] = obj1[attrname];
308 - }
309 - for (var attrname in obj2) {
310 - obj3[attrname] = obj2[attrname];
311 - }
312 - return obj3;
809 + var obj3 = {};
810 + for (var attrname in obj1) {
811 + obj3[attrname] = obj1[attrname];
812 + }
813 + for (var attrname in obj2) {
814 + obj3[attrname] = obj2[attrname];
815 + }
816 + return obj3;
313 817 }
314 818
315 819 /**
316 - * Get the real height of entire document.
317 - * @returns {number}
318 - */
820 +* Get the real height of entire document.
821 +* @returns {number}
822 +*/
319 823 function getDocumentHeight() {
320 - var body = document.body,
321 - html = document.documentElement;
824 + var body = document.body,
825 + html = document.documentElement;
322 826
323 - var height = Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight);
827 + var height = Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight);
324 828
325 - return height;
829 + return height;
326 830 }
327 831
328 832 // Box Object
329 833 var Box = function Box(id, config) {
330 - this.id = id;
834 + this.id = id;
331 835
332 - // store config values
333 - this.config = merge(defaults, config);
836 + // store config values
837 + this.config = merge(defaults, config);
334 838
335 - // store ref to overlay
336 - this.overlay = document.getElementById('boxzilla-overlay');
839 + // store ref to overlay
840 + this.overlay = document.getElementById('boxzilla-overlay');
337 841
338 - // state
339 - this.visible = false;
340 - this.dismissed = false;
341 - this.triggered = false;
342 - this.triggerHeight = 0;
343 - this.cookieSet = false;
344 - this.element = null;
345 - this.contentElement = null;
346 - this.closeIcon = null;
842 + // state
843 + this.visible = false;
844 + this.dismissed = false;
845 + this.triggered = false;
846 + this.triggerHeight = this.calculateTriggerHeight();
847 + this.cookieSet = this.isCookieSet();
848 + this.element = null;
849 + this.contentElement = null;
850 + this.closeIcon = null;
347 851
348 - // if a trigger was given, calculate values once and store
349 - if (this.config.trigger) {
350 - if (this.config.trigger.method === 'percentage' || this.config.trigger.method === 'element') {
351 - this.triggerHeight = this.calculateTriggerHeight();
352 - }
852 + // create dom elements for this box
853 + this.dom();
353 854
354 - this.cookieSet = this.isCookieSet();
355 - }
356 -
357 - // create dom elements for this box
358 - this.dom();
359 -
360 - // further initialise the box
361 - this.events();
855 + // further initialise the box
856 + this.events();
362 857 };
363 858
364 859 // initialise the box
365 860 Box.prototype.events = function () {
366 - var box = this;
861 + var box = this;
367 862
368 - // attach event to "close" icon inside box
369 - if (this.closeIcon) {
370 - this.closeIcon.addEventListener('click', this.dismiss.bind(this));
863 + // attach event to "close" icon inside box
864 + if (this.closeIcon) {
865 + this.closeIcon.addEventListener('click', this.dismiss.bind(this));
866 + }
867 +
868 + this.element.addEventListener('click', function (e) {
869 + if (e.target.tagName === 'A') {
870 + Boxzilla.trigger('box.interactions.link', [box, e.target]);
371 871 }
872 + }, false);
372 873
373 - this.element.addEventListener('click', function (e) {
374 - if (e.target.tagName === 'A') {
375 - Boxzilla.trigger('box.interactions.link', [box, e.target]);
376 - }
377 - }, false);
378 -
379 - this.element.addEventListener('submit', function (e) {
380 - box.setCookie();
381 - Boxzilla.trigger('box.interactions.form', [box, e.target]);
382 - }, false);
383 -
384 - // maybe show box right away
385 - if (this.fits() && this.locationHashRefersBox()) {
386 - window.addEventListener('load', this.show.bind(this));
387 - }
874 + this.element.addEventListener('submit', function (e) {
875 + box.setCookie();
876 + Boxzilla.trigger('box.interactions.form', [box, e.target]);
877 + }, false);
388 878 };
389 879
390 880 // generate dom elements for this box
391 881 Box.prototype.dom = function () {
392 - var wrapper = document.createElement('div');
393 - wrapper.className = 'boxzilla-container boxzilla-' + this.config.position + '-container';
882 + var wrapper = document.createElement('div');
883 + wrapper.className = 'boxzilla-container boxzilla-' + this.config.position + '-container';
394 884
395 - var box = document.createElement('div');
396 - box.setAttribute('id', 'boxzilla-' + this.id);
397 - box.className = 'boxzilla boxzilla-' + this.id + ' boxzilla-' + this.config.position;
398 - box.style.display = 'none';
399 - wrapper.appendChild(box);
885 + var box = document.createElement('div');
886 + box.setAttribute('id', 'boxzilla-' + this.id);
887 + box.className = 'boxzilla boxzilla-' + this.id + ' boxzilla-' + this.config.position;
888 + box.style.display = 'none';
889 + wrapper.appendChild(box);
400 890
401 - var content = document.createElement('div');
402 - content.className = 'boxzilla-content';
891 + var content;
892 + if (typeof this.config.content === "string") {
893 + content = document.createElement('div');
403 894 content.innerHTML = this.config.content;
404 - box.appendChild(content);
895 + } else {
896 + content = this.config.content;
405 897
406 - // remove <script> from box content and append them to the document body
407 - var scripts = content.querySelectorAll('script');
408 - if (scripts.length) {
409 - for (var i = 0; i < scripts.length; i++) {
410 - var script = document.createElement('script');
411 - if (scripts[i].src) {
412 - script.src = scripts[i].src;
413 - }
414 - script.appendChild(document.createTextNode(scripts[i].text));
415 - scripts[i].parentNode.removeChild(scripts[i]);
416 - document.body.appendChild(script);
417 - }
418 - }
898 + // make sure element is visible
899 + content.style.display = '';
900 + }
901 + content.className = 'boxzilla-content';
902 + box.appendChild(content);
419 903
420 - if (this.config.closable && this.config.icon) {
421 - var closeIcon = document.createElement('span');
422 - closeIcon.className = "boxzilla-close-icon";
423 - closeIcon.innerHTML = this.config.icon;
424 - box.appendChild(closeIcon);
425 - this.closeIcon = closeIcon;
426 - }
904 + if (this.config.closable && this.config.icon) {
905 + var closeIcon = document.createElement('span');
906 + closeIcon.className = "boxzilla-close-icon";
907 + closeIcon.innerHTML = this.config.icon;
908 + box.appendChild(closeIcon);
909 + this.closeIcon = closeIcon;
910 + }
427 911
428 - document.body.appendChild(wrapper);
429 - this.contentElement = content;
430 - this.element = box;
912 + document.body.appendChild(wrapper);
913 + this.contentElement = content;
914 + this.element = box;
431 915 };
432 916
433 917 // set (calculate) custom box styling depending on box options
434 918 Box.prototype.setCustomBoxStyling = function () {
435 919
436 - // reset element to its initial state
437 - var origDisplay = this.element.style.display;
438 - this.element.style.display = '';
439 - this.element.style.overflowY = 'auto';
440 - this.element.style.maxHeight = 'none';
920 + // reset element to its initial state
921 + var origDisplay = this.element.style.display;
922 + this.element.style.display = '';
923 + this.element.style.overflowY = 'auto';
924 + this.element.style.maxHeight = 'none';
441 925
442 - // get new dimensions
443 - var windowHeight = window.innerHeight;
444 - var boxHeight = this.element.clientHeight;
926 + // get new dimensions
927 + var windowHeight = window.innerHeight;
928 + var boxHeight = this.element.clientHeight;
445 929
446 - // add scrollbar to box and limit height
447 - if (boxHeight > windowHeight) {
448 - this.element.style.maxHeight = windowHeight + "px";
449 - this.element.style.overflowY = 'scroll';
450 - }
930 + // add scrollbar to box and limit height
931 + if (boxHeight > windowHeight) {
932 + this.element.style.maxHeight = windowHeight + "px";
933 + this.element.style.overflowY = 'scroll';
934 + }
451 935
452 - // set new top margin for boxes which are centered
453 - if (this.config.position === 'center') {
454 - var newTopMargin = (windowHeight - boxHeight) / 2;
455 - newTopMargin = newTopMargin >= 0 ? newTopMargin : 0;
456 - this.element.style.marginTop = newTopMargin + "px";
457 - }
936 + // set new top margin for boxes which are centered
937 + if (this.config.position === 'center') {
938 + var newTopMargin = (windowHeight - boxHeight) / 2;
939 + newTopMargin = newTopMargin >= 0 ? newTopMargin : 0;
940 + this.element.style.marginTop = newTopMargin + "px";
941 + }
458 942
459 - this.element.style.display = origDisplay;
943 + this.element.style.display = origDisplay;
460 944 };
461 945
462 946 // toggle visibility of the box
463 947 Box.prototype.toggle = function (show) {
464 948
465 - // revert visibility if no explicit argument is given
466 - if (typeof show === "undefined") {
467 - show = !this.visible;
468 - }
949 + // revert visibility if no explicit argument is given
950 + if (typeof show === "undefined") {
951 + show = !this.visible;
952 + }
469 953
470 - // is box already at desired visibility?
471 - if (show === this.visible) {
472 - return false;
473 - }
954 + // is box already at desired visibility?
955 + if (show === this.visible) {
956 + return false;
957 + }
474 958
475 - // is box being animated?
476 - if (Animator.animated(this.element)) {
477 - return false;
478 - }
959 + // is box being animated?
960 + if (Animator.animated(this.element)) {
961 + return false;
962 + }
479 963
480 - // if box should be hidden but is not closable, bail.
481 - if (!show && !this.config.closable) {
482 - return false;
483 - }
964 + // if box should be hidden but is not closable, bail.
965 + if (!show && !this.config.closable) {
966 + return false;
967 + }
484 968
485 - // set new visibility status
486 - this.visible = show;
969 + // set new visibility status
970 + this.visible = show;
487 971
488 - // calculate new styling rules
489 - this.setCustomBoxStyling();
972 + // calculate new styling rules
973 + this.setCustomBoxStyling();
490 974
491 - // trigger event
492 - Boxzilla.trigger('box.' + (show ? 'show' : 'hide'), [this]);
975 + // trigger event
976 + Boxzilla.trigger('box.' + (show ? 'show' : 'hide'), [this]);
493 977
494 - // show or hide box using selected animation
495 - if (this.config.position === 'center') {
496 - this.overlay.classList.toggle('boxzilla-' + this.id + '-overlay');
497 - Animator.toggle(this.overlay, "fade");
978 + // show or hide box using selected animation
979 + if (this.config.position === 'center') {
980 + this.overlay.classList.toggle('boxzilla-' + this.id + '-overlay');
981 + Animator.toggle(this.overlay, "fade");
982 + }
983 +
984 + Animator.toggle(this.element, this.config.animation, function () {
985 + if (this.visible) {
986 + return;
498 987 }
988 + this.contentElement.innerHTML = this.contentElement.innerHTML;
989 + }.bind(this));
499 990
500 - Animator.toggle(this.element, this.config.animation, function () {
501 - if (this.visible) {
502 - return;
503 - }
504 - this.contentElement.innerHTML = this.contentElement.innerHTML;
505 - }.bind(this));
506 -
507 - return true;
991 + return true;
508 992 };
509 993
510 994 // show the box
511 995 Box.prototype.show = function () {
512 - return this.toggle(true);
996 + return this.toggle(true);
513 997 };
514 998
515 999 // hide the box
516 1000 Box.prototype.hide = function () {
517 - return this.toggle(false);
1001 + return this.toggle(false);
518 1002 };
519 1003
520 1004 // calculate trigger height
521 1005 Box.prototype.calculateTriggerHeight = function () {
522 - var triggerHeight = 0;
1006 + var triggerHeight = 0;
523 1007
1008 + if (this.config.trigger) {
524 1009 if (this.config.trigger.method === 'element') {
525 - var triggerElement = document.body.querySelector(this.config.trigger.value);
526 - if (triggerElement) {
527 - var offset = triggerElement.getBoundingClientRect();
528 - triggerHeight = offset.top;
529 - }
1010 + var triggerElement = document.body.querySelector(this.config.trigger.value);
1011 + if (triggerElement) {
1012 + var offset = triggerElement.getBoundingClientRect();
1013 + triggerHeight = offset.top;
1014 + }
530 1015 } else if (this.config.trigger.method === 'percentage') {
531 - triggerHeight = this.config.trigger.value / 100 * getDocumentHeight();
1016 + triggerHeight = this.config.trigger.value / 100 * getDocumentHeight();
532 1017 }
1018 + }
533 1019
534 - return triggerHeight;
1020 + return triggerHeight;
535 1021 };
536 1022
537 -// checks whether window.location.hash equals the box element ID or that of any element inside the box
538 -Box.prototype.locationHashRefersBox = function () {
1023 +Box.prototype.fits = function () {
1024 + if (!this.config.screenWidthCondition || !this.config.screenWidthCondition.value) {
1025 + return true;
1026 + }
539 1027
540 - if (!window.location.hash || 0 === window.location.hash.length) {
541 - return false;
542 - }
1028 + switch (this.config.screenWidthCondition.condition) {
1029 + case "larger":
1030 + return window.innerWidth > this.config.screenWidthCondition.value;
1031 + case "smaller":
1032 + return window.innerWidth < this.config.screenWidthCondition.value;
1033 + }
543 1034
544 - var elementId = window.location.hash.substring(1);
545 -
546 - // only attempt on strings looking like an ID or classname
547 - var regex = /^[a-zA-Z\-\_0-9]{1,}$/;
548 - if (regex.test(elementId)) {
549 - return false;
550 - }
551 -
552 - if (elementId === this.element.id) {
553 - return true;
554 - } else if (this.element.querySelector('#' + elementId)) {
555 - return true;
556 - }
557 -
558 - return false;
1035 + // meh.. condition should be "smaller" or "larger", just return true.
1036 + return true;
559 1037 };
560 1038
561 -Box.prototype.fits = function () {
562 - if (!this.config.screenWidthCondition || !this.config.screenWidthCondition.value) {
563 - return true;
564 - }
565 -
566 - switch (this.config.screenWidthCondition.condition) {
567 - case "larger":
568 - return window.innerWidth > this.config.screenWidthCondition.value;
569 - case "smaller":
570 - return window.innerWidth < this.config.screenWidthCondition.value;
571 - }
572 -
573 - // meh.. condition should be "smaller" or "larger", just return true.
574 - return true;
1039 +Box.prototype.onResize = function () {
1040 + this.triggerHeight = this.calculateTriggerHeight();
1041 + this.setCustomBoxStyling();
575 1042 };
576 1043
577 1044 // is this box enabled?
578 1045 Box.prototype.mayAutoShow = function () {
579 1046
580 - if (this.dismissed) {
581 - return false;
582 - }
1047 + if (this.dismissed) {
1048 + return false;
1049 + }
583 1050
584 - // check if box fits on given minimum screen width
585 - if (!this.fits()) {
586 - return false;
587 - }
1051 + // check if box fits on given minimum screen width
1052 + if (!this.fits()) {
1053 + return false;
1054 + }
588 1055
589 - // if trigger empty or error in calculating triggerHeight, return false
590 - if (!this.config.trigger) {
591 - return false;
592 - }
1056 + // if trigger empty or error in calculating triggerHeight, return false
1057 + if (!this.config.trigger) {
1058 + return false;
1059 + }
593 1060
594 - // rely on cookie value (show if not set, don't show if set)
595 - return !this.cookieSet;
1061 + // rely on cookie value (show if not set, don't show if set)
1062 + return !this.cookieSet;
596 1063 };
597 1064
598 1065 Box.prototype.mayRehide = function () {
599 - return this.config.rehide && this.triggered;
1066 + return this.config.rehide && this.triggered;
600 1067 };
601 1068
602 1069 Box.prototype.isCookieSet = function () {
603 - // always show on test mode
604 - if (this.config.testMode) {
605 - return false;
606 - }
1070 + // always show on test mode or when no auto-trigger is configured
1071 + if (this.config.testMode || !this.config.trigger) {
1072 + return false;
1073 + }
607 1074
608 - // if either cookie is null or trigger & dismiss are both falsey, don't bother checking.
609 - if (!this.config.cookie || !this.config.cookie.triggered && !this.config.cookie.dismissed) {
610 - return false;
611 - }
1075 + // if either cookie is null or trigger & dismiss are both falsey, don't bother checking.
1076 + if (!this.config.cookie || !this.config.cookie.triggered && !this.config.cookie.dismissed) {
1077 + return false;
1078 + }
612 1079
613 - var cookieSet = document.cookie.replace(new RegExp("(?:(?:^|.*;)\\s*" + 'boxzilla_box_' + this.id + "\\s*\\=\\s*([^;]*).*$)|^.*$"), "$1") === "true";
614 - return cookieSet;
1080 + var cookieSet = document.cookie.replace(new RegExp("(?:(?:^|.*;)\\s*" + 'boxzilla_box_' + this.id + "\\s*\\=\\s*([^;]*).*$)|^.*$"), "$1") === "true";
1081 + return cookieSet;
615 1082 };
616 1083
617 1084 // set cookie that disables automatically showing the box
618 1085 Box.prototype.setCookie = function (hours) {
619 - var expiryDate = new Date();
620 - expiryDate.setHours(expiryDate.getHours() + hours);
621 - document.cookie = 'boxzilla_box_' + this.id + '=true; expires=' + expiryDate.toUTCString() + '; path=/';
1086 + var expiryDate = new Date();
1087 + expiryDate.setHours(expiryDate.getHours() + hours);
1088 + document.cookie = 'boxzilla_box_' + this.id + '=true; expires=' + expiryDate.toUTCString() + '; path=/';
622 1089 };
623 1090
624 1091 Box.prototype.trigger = function () {
625 - var shown = this.show();
626 - if (!shown) {
627 - return;
628 - }
1092 + var shown = this.show();
1093 + if (!shown) {
1094 + return;
1095 + }
629 1096
630 - this.triggered = true;
631 - if (this.config.cookie && this.config.cookie.triggered) {
632 - this.setCookie(this.config.cookie.triggered);
633 - }
1097 + this.triggered = true;
1098 + if (this.config.cookie && this.config.cookie.triggered) {
1099 + this.setCookie(this.config.cookie.triggered);
1100 + }
634 1101 };
635 1102
636 1103 /**
637 - * Dismisses the box and optionally sets a cookie.
638 - *
639 - * @param e The event that triggered this dismissal.
640 - * @returns {boolean}
641 - */
1104 +* Dismisses the box and optionally sets a cookie.
1105 +*
1106 +* @param e The event that triggered this dismissal.
1107 +* @returns {boolean}
1108 +*/
642 1109 Box.prototype.dismiss = function (e) {
643 - // prevent default action
644 - e && e.preventDefault();
1110 + // prevent default action
1111 + e && e.preventDefault();
645 1112
646 - // only dismiss box if it's currently open.
647 - if (!this.visible) {
648 - return false;
649 - }
1113 + // only dismiss box if it's currently open.
1114 + if (!this.visible) {
1115 + return false;
1116 + }
650 1117
651 - // hide box element
652 - this.hide();
1118 + // hide box element
1119 + this.hide();
653 1120
654 - // set cookie
655 - if (this.config.cookie && this.config.cookie.dismissed) {
656 - this.setCookie(this.config.cookie.dismissed);
657 - }
1121 + // set cookie
1122 + if (this.config.cookie && this.config.cookie.dismissed) {
1123 + this.setCookie(this.config.cookie.dismissed);
1124 + }
658 1125
659 - this.dismissed = true;
660 - Boxzilla.trigger('box.dismiss', [this]);
661 - return true;
1126 + this.dismissed = true;
1127 + Boxzilla.trigger('box.dismiss', [this]);
1128 + return true;
662 1129 };
663 1130
664 1131 module.exports = function (_Boxzilla) {
665 - Boxzilla = _Boxzilla;
666 - return Box;
1132 + Boxzilla = _Boxzilla;
1133 + return Box;
667 1134 };
668 1135
669 -},{"./animator.js":2}],4:[function(require,module,exports){
1136 +},{"./animator.js":3}],5:[function(require,module,exports){
670 1137 'use strict';
671 1138
672 -var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
673 -
674 1139 var EventEmitter = require('wolfy87-eventemitter'),
675 1140 Boxzilla = Object.create(EventEmitter.prototype),
676 1141 Box = require('./box.js')(Boxzilla),
677 1142 Timer = require('./timer.js'),
@@ -758,9 +1223,9 @@
758 1223
759 1224 // check triggerHeight criteria for all boxes
760 1225 function checkHeightCriteria() {
761 1226
762 - var scrollY = scrollElement.hasOwnProperty('scrollY') ? scrollElement.scrollY : scrollElement.scrollTop;
1227 + var scrollY = scrollElement.hasOwnProperty('pageYOffset') ? scrollElement.pageYOffset : scrollElement.scrollTop;
763 1228 scrollY = scrollY + window.innerHeight * 0.9;
764 1229
765 1230 boxes.forEach(function (box) {
766 1231 if (!box.mayAutoShow() || box.triggerHeight <= 0) {
@@ -783,9 +1248,9 @@
783 1248
784 1249 // recalculate heights and variables based on height
785 1250 function recalculateHeights() {
786 1251 boxes.forEach(function (box) {
787 - box.setCustomBoxStyling();
1252 + box.onResize();
788 1253 });
789 1254 }
790 1255
791 1256 function onOverlayClick(e) {
@@ -859,9 +1324,13 @@
859 1324
860 1325 el = el.parentElement;
861 1326 }
862 1327
863 - if (el && el.tagName === 'A' && el.getAttribute('href').toLowerCase().indexOf('#boxzilla-') === 0) {
1328 + if (!el || el.tagName !== 'A' || !el.getAttribute('href')) {
1329 + return;
1330 + }
1331 +
1332 + if (el.getAttribute('href').toLowerCase().indexOf('#boxzilla-') === 0) {
864 1333 var boxId = el.getAttribute('href').toLowerCase().substring("#boxzilla-".length);
865 1334 Boxzilla.toggle(boxId);
866 1335 }
867 1336 }
@@ -883,9 +1352,9 @@
883 1352 };
884 1353
885 1354 // initialise & add event listeners
886 1355 Boxzilla.init = function () {
887 - document.body.addEventListener('click', onElementClick, false);
1356 + document.body.addEventListener('click', onElementClick, true);
888 1357
889 1358 try {
890 1359 pageViews = sessionStorage.getItem('boxzilla_pageviews') || 0;
891 1360 } catch (e) {
@@ -971,9 +1440,9 @@
971 1440 if (typeof id === "undefined") {
972 1441 boxes.forEach(function (box) {
973 1442 box.dismiss();
974 1443 });
975 - } else if (_typeof(boxes[id]) === "object") {
1444 + } else {
976 1445 Boxzilla.get(id).dismiss();
977 1446 }
978 1447 };
979 1448
@@ -1016,15 +1485,15 @@
1016 1485 if (typeof module !== 'undefined' && module.exports) {
1017 1486 module.exports = Boxzilla;
1018 1487 }
1019 1488
1020 -},{"./box.js":3,"./styles.js":5,"./timer.js":6,"wolfy87-eventemitter":7}],5:[function(require,module,exports){
1489 +},{"./box.js":4,"./styles.js":6,"./timer.js":7,"wolfy87-eventemitter":2}],6:[function(require,module,exports){
1021 1490 "use strict";
1022 1491
1023 1492 var styles = "#boxzilla-overlay{position:fixed;background:rgba(0,0,0,.65);width:100%;height:100%;left:0;top:0;z-index:99999}.boxzilla-center-container{position:fixed;top:0;left:0;right:0;height:0;text-align:center;z-index:999999;line-height:0}.boxzilla-center-container .boxzilla{display:inline-block;text-align:left;position:relative;line-height:normal}.boxzilla{position:fixed;z-index:999999;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;background:#fff;padding:25px}.boxzilla.boxzilla-top-left{top:0;left:0}.boxzilla.boxzilla-top-right{top:0;right:0}.boxzilla.boxzilla-bottom-left{bottom:0;left:0}.boxzilla.boxzilla-bottom-right{bottom:0;right:0}.boxzilla-content>:first-child{margin-top:0;padding-top:0}.boxzilla-content>:last-child{margin-bottom:0;padding-bottom:0}.boxzilla-close-icon{position:absolute;right:0;top:0;text-align:center;padding:6px;cursor:pointer;-webkit-appearance:none;font-size:28px;font-weight:700;line-height:20px;color:#000;opacity:.5}.boxzilla-close-icon:focus,.boxzilla-close-icon:hover{opacity:.8}";
1024 1493 module.exports = styles;
1025 1494
1026 -},{}],6:[function(require,module,exports){
1495 +},{}],7:[function(require,module,exports){
1027 1496 'use strict';
1028 1497
1029 1498 var Timer = function Timer(start) {
1030 1499 this.time = start;
@@ -1048,483 +1517,7 @@
1048 1517 }
1049 1518 };
1050 1519
1051 1520 module.exports = Timer;
1052 -
1053 -},{}],7:[function(require,module,exports){
1054 -/*!
1055 - * EventEmitter v4.2.11 - git.io/ee
1056 - * Unlicense - http://unlicense.org/
1057 - * Oliver Caldwell - http://oli.me.uk/
1058 - * @preserve
1059 - */
1060 -
1061 -;(function () {
1062 - 'use strict';
1063 -
1064 - /**
1065 - * Class for managing events.
1066 - * Can be extended to provide event functionality in other classes.
1067 - *
1068 - * @class EventEmitter Manages event registering and emitting.
1069 - */
1070 - function EventEmitter() {}
1071 -
1072 - // Shortcuts to improve speed and size
1073 - var proto = EventEmitter.prototype;
1074 - var exports = this;
1075 - var originalGlobalValue = exports.EventEmitter;
1076 -
1077 - /**
1078 - * Finds the index of the listener for the event in its storage array.
1079 - *
1080 - * @param {Function[]} listeners Array of listeners to search through.
1081 - * @param {Function} listener Method to look for.
1082 - * @return {Number} Index of the specified listener, -1 if not found
1083 - * @api private
1084 - */
1085 - function indexOfListener(listeners, listener) {
1086 - var i = listeners.length;
1087 - while (i--) {
1088 - if (listeners[i].listener === listener) {
1089 - return i;
1090 - }
1091 - }
1092 -
1093 - return -1;
1094 - }
1095 -
1096 - /**
1097 - * Alias a method while keeping the context correct, to allow for overwriting of target method.
1098 - *
1099 - * @param {String} name The name of the target method.
1100 - * @return {Function} The aliased method
1101 - * @api private
1102 - */
1103 - function alias(name) {
1104 - return function aliasClosure() {
1105 - return this[name].apply(this, arguments);
1106 - };
1107 - }
1108 -
1109 - /**
1110 - * Returns the listener array for the specified event.
1111 - * Will initialise the event object and listener arrays if required.
1112 - * Will return an object if you use a regex search. The object contains keys for each matched event. So /ba[rz]/ might return an object containing bar and baz. But only if you have either defined them with defineEvent or added some listeners to them.
1113 - * Each property in the object response is an array of listener functions.
1114 - *
1115 - * @param {String|RegExp} evt Name of the event to return the listeners from.
1116 - * @return {Function[]|Object} All listener functions for the event.
1117 - */
1118 - proto.getListeners = function getListeners(evt) {
1119 - var events = this._getEvents();
1120 - var response;
1121 - var key;
1122 -
1123 - // Return a concatenated array of all matching events if
1124 - // the selector is a regular expression.
1125 - if (evt instanceof RegExp) {
1126 - response = {};
1127 - for (key in events) {
1128 - if (events.hasOwnProperty(key) && evt.test(key)) {
1129 - response[key] = events[key];
1130 - }
1131 - }
1132 - }
1133 - else {
1134 - response = events[evt] || (events[evt] = []);
1135 - }
1136 -
1137 - return response;
1138 - };
1139 -
1140 - /**
1141 - * Takes a list of listener objects and flattens it into a list of listener functions.
1142 - *
1143 - * @param {Object[]} listeners Raw listener objects.
1144 - * @return {Function[]} Just the listener functions.
1145 - */
1146 - proto.flattenListeners = function flattenListeners(listeners) {
1147 - var flatListeners = [];
1148 - var i;
1149 -
1150 - for (i = 0; i < listeners.length; i += 1) {
1151 - flatListeners.push(listeners[i].listener);
1152 - }
1153 -
1154 - return flatListeners;
1155 - };
1156 -
1157 - /**
1158 - * Fetches the requested listeners via getListeners but will always return the results inside an object. This is mainly for internal use but others may find it useful.
1159 - *
1160 - * @param {String|RegExp} evt Name of the event to return the listeners from.
1161 - * @return {Object} All listener functions for an event in an object.
1162 - */
1163 - proto.getListenersAsObject = function getListenersAsObject(evt) {
1164 - var listeners = this.getListeners(evt);
1165 - var response;
1166 -
1167 - if (listeners instanceof Array) {
1168 - response = {};
1169 - response[evt] = listeners;
1170 - }
1171 -
1172 - return response || listeners;
1173 - };
1174 -
1175 - /**
1176 - * Adds a listener function to the specified event.
1177 - * The listener will not be added if it is a duplicate.
1178 - * If the listener returns true then it will be removed after it is called.
1179 - * If you pass a regular expression as the event name then the listener will be added to all events that match it.
1180 - *
1181 - * @param {String|RegExp} evt Name of the event to attach the listener to.
1182 - * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.
1183 - * @return {Object} Current instance of EventEmitter for chaining.
1184 - */
1185 - proto.addListener = function addListener(evt, listener) {
1186 - var listeners = this.getListenersAsObject(evt);
1187 - var listenerIsWrapped = typeof listener === 'object';
1188 - var key;
1189 -
1190 - for (key in listeners) {
1191 - if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) {
1192 - listeners[key].push(listenerIsWrapped ? listener : {
1193 - listener: listener,
1194 - once: false
1195 - });
1196 - }
1197 - }
1198 -
1199 - return this;
1200 - };
1201 -
1202 - /**
1203 - * Alias of addListener
1204 - */
1205 - proto.on = alias('addListener');
1206 -
1207 - /**
1208 - * Semi-alias of addListener. It will add a listener that will be
1209 - * automatically removed after its first execution.
1210 - *
1211 - * @param {String|RegExp} evt Name of the event to attach the listener to.
1212 - * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.
1213 - * @return {Object} Current instance of EventEmitter for chaining.
1214 - */
1215 - proto.addOnceListener = function addOnceListener(evt, listener) {
1216 - return this.addListener(evt, {
1217 - listener: listener,
1218 - once: true
1219 - });
1220 - };
1221 -
1222 - /**
1223 - * Alias of addOnceListener.
1224 - */
1225 - proto.once = alias('addOnceListener');
1226 -
1227 - /**
1228 - * Defines an event name. This is required if you want to use a regex to add a listener to multiple events at once. If you don't do this then how do you expect it to know what event to add to? Should it just add to every possible match for a regex? No. That is scary and bad.
1229 - * You need to tell it what event names should be matched by a regex.
1230 - *
1231 - * @param {String} evt Name of the event to create.
1232 - * @return {Object} Current instance of EventEmitter for chaining.
1233 - */
1234 - proto.defineEvent = function defineEvent(evt) {
1235 - this.getListeners(evt);
1236 - return this;
1237 - };
1238 -
1239 - /**
1240 - * Uses defineEvent to define multiple events.
1241 - *
1242 - * @param {String[]} evts An array of event names to define.
1243 - * @return {Object} Current instance of EventEmitter for chaining.
1244 - */
1245 - proto.defineEvents = function defineEvents(evts) {
1246 - for (var i = 0; i < evts.length; i += 1) {
1247 - this.defineEvent(evts[i]);
1248 - }
1249 - return this;
1250 - };
1251 -
1252 - /**
1253 - * Removes a listener function from the specified event.
1254 - * When passed a regular expression as the event name, it will remove the listener from all events that match it.
1255 - *
1256 - * @param {String|RegExp} evt Name of the event to remove the listener from.
1257 - * @param {Function} listener Method to remove from the event.
1258 - * @return {Object} Current instance of EventEmitter for chaining.
1259 - */
1260 - proto.removeListener = function removeListener(evt, listener) {
1261 - var listeners = this.getListenersAsObject(evt);
1262 - var index;
1263 - var key;
1264 -
1265 - for (key in listeners) {
1266 - if (listeners.hasOwnProperty(key)) {
1267 - index = indexOfListener(listeners[key], listener);
1268 -
1269 - if (index !== -1) {
1270 - listeners[key].splice(index, 1);
1271 - }
1272 - }
1273 - }
1274 -
1275 - return this;
1276 - };
1277 -
1278 - /**
1279 - * Alias of removeListener
1280 - */
1281 - proto.off = alias('removeListener');
1282 -
1283 - /**
1284 - * Adds listeners in bulk using the manipulateListeners method.
1285 - * If you pass an object as the second argument you can add to multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. You can also pass it an event name and an array of listeners to be added.
1286 - * You can also pass it a regular expression to add the array of listeners to all events that match it.
1287 - * Yeah, this function does quite a bit. That's probably a bad thing.
1288 - *
1289 - * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add to multiple events at once.
1290 - * @param {Function[]} [listeners] An optional array of listener functions to add.
1291 - * @return {Object} Current instance of EventEmitter for chaining.
1292 - */
1293 - proto.addListeners = function addListeners(evt, listeners) {
1294 - // Pass through to manipulateListeners
1295 - return this.manipulateListeners(false, evt, listeners);
1296 - };
1297 -
1298 - /**
1299 - * Removes listeners in bulk using the manipulateListeners method.
1300 - * If you pass an object as the second argument you can remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.
1301 - * You can also pass it an event name and an array of listeners to be removed.
1302 - * You can also pass it a regular expression to remove the listeners from all events that match it.
1303 - *
1304 - * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to remove from multiple events at once.
1305 - * @param {Function[]} [listeners] An optional array of listener functions to remove.
1306 - * @return {Object} Current instance of EventEmitter for chaining.
1307 - */
1308 - proto.removeListeners = function removeListeners(evt, listeners) {
1309 - // Pass through to manipulateListeners
1310 - return this.manipulateListeners(true, evt, listeners);
1311 - };
1312 -
1313 - /**
1314 - * Edits listeners in bulk. The addListeners and removeListeners methods both use this to do their job. You should really use those instead, this is a little lower level.
1315 - * The first argument will determine if the listeners are removed (true) or added (false).
1316 - * If you pass an object as the second argument you can add/remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.
1317 - * You can also pass it an event name and an array of listeners to be added/removed.
1318 - * You can also pass it a regular expression to manipulate the listeners of all events that match it.
1319 - *
1320 - * @param {Boolean} remove True if you want to remove listeners, false if you want to add.
1321 - * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add/remove from multiple events at once.
1322 - * @param {Function[]} [listeners] An optional array of listener functions to add/remove.
1323 - * @return {Object} Current instance of EventEmitter for chaining.
1324 - */
1325 - proto.manipulateListeners = function manipulateListeners(remove, evt, listeners) {
1326 - var i;
1327 - var value;
1328 - var single = remove ? this.removeListener : this.addListener;
1329 - var multiple = remove ? this.removeListeners : this.addListeners;
1330 -
1331 - // If evt is an object then pass each of its properties to this method
1332 - if (typeof evt === 'object' && !(evt instanceof RegExp)) {
1333 - for (i in evt) {
1334 - if (evt.hasOwnProperty(i) && (value = evt[i])) {
1335 - // Pass the single listener straight through to the singular method
1336 - if (typeof value === 'function') {
1337 - single.call(this, i, value);
1338 - }
1339 - else {
1340 - // Otherwise pass back to the multiple function
1341 - multiple.call(this, i, value);
1342 - }
1343 - }
1344 - }
1345 - }
1346 - else {
1347 - // So evt must be a string
1348 - // And listeners must be an array of listeners
1349 - // Loop over it and pass each one to the multiple method
1350 - i = listeners.length;
1351 - while (i--) {
1352 - single.call(this, evt, listeners[i]);
1353 - }
1354 - }
1355 -
1356 - return this;
1357 - };
1358 -
1359 - /**
1360 - * Removes all listeners from a specified event.
1361 - * If you do not specify an event then all listeners will be removed.
1362 - * That means every event will be emptied.
1363 - * You can also pass a regex to remove all events that match it.
1364 - *
1365 - * @param {String|RegExp} [evt] Optional name of the event to remove all listeners for. Will remove from every event if not passed.
1366 - * @return {Object} Current instance of EventEmitter for chaining.
1367 - */
1368 - proto.removeEvent = function removeEvent(evt) {
1369 - var type = typeof evt;
1370 - var events = this._getEvents();
1371 - var key;
1372 -
1373 - // Remove different things depending on the state of evt
1374 - if (type === 'string') {
1375 - // Remove all listeners for the specified event
1376 - delete events[evt];
1377 - }
1378 - else if (evt instanceof RegExp) {
1379 - // Remove all events matching the regex.
1380 - for (key in events) {
1381 - if (events.hasOwnProperty(key) && evt.test(key)) {
1382 - delete events[key];
1383 - }
1384 - }
1385 - }
1386 - else {
1387 - // Remove all listeners in all events
1388 - delete this._events;
1389 - }
1390 -
1391 - return this;
1392 - };
1393 -
1394 - /**
1395 - * Alias of removeEvent.
1396 - *
1397 - * Added to mirror the node API.
1398 - */
1399 - proto.removeAllListeners = alias('removeEvent');
1400 -
1401 - /**
1402 - * Emits an event of your choice.
1403 - * When emitted, every listener attached to that event will be executed.
1404 - * If you pass the optional argument array then those arguments will be passed to every listener upon execution.
1405 - * Because it uses `apply`, your array of arguments will be passed as if you wrote them out separately.
1406 - * So they will not arrive within the array on the other side, they will be separate.
1407 - * You can also pass a regular expression to emit to all events that match it.
1408 - *
1409 - * @param {String|RegExp} evt Name of the event to emit and execute listeners for.
1410 - * @param {Array} [args] Optional array of arguments to be passed to each listener.
1411 - * @return {Object} Current instance of EventEmitter for chaining.
1412 - */
1413 - proto.emitEvent = function emitEvent(evt, args) {
1414 - var listenersMap = this.getListenersAsObject(evt);
1415 - var listeners;
1416 - var listener;
1417 - var i;
1418 - var key;
1419 - var response;
1420 -
1421 - for (key in listenersMap) {
1422 - if (listenersMap.hasOwnProperty(key)) {
1423 - listeners = listenersMap[key].slice(0);
1424 - i = listeners.length;
1425 -
1426 - while (i--) {
1427 - // If the listener returns true then it shall be removed from the event
1428 - // The function is executed either with a basic call or an apply if there is an args array
1429 - listener = listeners[i];
1430 -
1431 - if (listener.once === true) {
1432 - this.removeListener(evt, listener.listener);
1433 - }
1434 -
1435 - response = listener.listener.apply(this, args || []);
1436 -
1437 - if (response === this._getOnceReturnValue()) {
1438 - this.removeListener(evt, listener.listener);
1439 - }
1440 - }
1441 - }
1442 - }
1443 -
1444 - return this;
1445 - };
1446 -
1447 - /**
1448 - * Alias of emitEvent
1449 - */
1450 - proto.trigger = alias('emitEvent');
1451 -
1452 - /**
1453 - * Subtly different from emitEvent in that it will pass its arguments on to the listeners, as opposed to taking a single array of arguments to pass on.
1454 - * As with emitEvent, you can pass a regex in place of the event name to emit to all events that match it.
1455 - *
1456 - * @param {String|RegExp} evt Name of the event to emit and execute listeners for.
1457 - * @param {...*} Optional additional arguments to be passed to each listener.
1458 - * @return {Object} Current instance of EventEmitter for chaining.
1459 - */
1460 - proto.emit = function emit(evt) {
1461 - var args = Array.prototype.slice.call(arguments, 1);
1462 - return this.emitEvent(evt, args);
1463 - };
1464 -
1465 - /**
1466 - * Sets the current value to check against when executing listeners. If a
1467 - * listeners return value matches the one set here then it will be removed
1468 - * after execution. This value defaults to true.
1469 - *
1470 - * @param {*} value The new value to check for when executing listeners.
1471 - * @return {Object} Current instance of EventEmitter for chaining.
1472 - */
1473 - proto.setOnceReturnValue = function setOnceReturnValue(value) {
1474 - this._onceReturnValue = value;
1475 - return this;
1476 - };
1477 -
1478 - /**
1479 - * Fetches the current value to check against when executing listeners. If
1480 - * the listeners return value matches this one then it should be removed
1481 - * automatically. It will return true by default.
1482 - *
1483 - * @return {*|Boolean} The current value to check for or the default, true.
1484 - * @api private
1485 - */
1486 - proto._getOnceReturnValue = function _getOnceReturnValue() {
1487 - if (this.hasOwnProperty('_onceReturnValue')) {
1488 - return this._onceReturnValue;
1489 - }
1490 - else {
1491 - return true;
1492 - }
1493 - };
1494 -
1495 - /**
1496 - * Fetches the events object and creates one if required.
1497 - *
1498 - * @return {Object} The events storage object.
1499 - * @api private
1500 - */
1501 - proto._getEvents = function _getEvents() {
1502 - return this._events || (this._events = {});
1503 - };
1504 -
1505 - /**
1506 - * Reverts the global {@link EventEmitter} to its previous value and returns a reference to this version.
1507 - *
1508 - * @return {Function} Non conflicting EventEmitter class.
1509 - */
1510 - EventEmitter.noConflict = function noConflict() {
1511 - exports.EventEmitter = originalGlobalValue;
1512 - return EventEmitter;
1513 - };
1514 -
1515 - // Expose the class either via AMD, CommonJS or the global object
1516 - if (typeof define === 'function' && define.amd) {
1517 - define(function () {
1518 - return EventEmitter;
1519 - });
1520 - }
1521 - else if (typeof module === 'object' && module.exports){
1522 - module.exports = EventEmitter;
1523 - }
1524 - else {
1525 - exports.EventEmitter = EventEmitter;
1526 - }
1527 -}.call(this));
1528 1521
1529 1522 },{}]},{},[1]);
1530 1523 ; })();