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