PluginProbe
Boxzilla – WordPress Popup Builder / 3.1.9
Boxzilla – WordPress Popup Builder v3.1.9
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 +385 -251 3.1.13.1.9 View file →
@@ -1,90 +1,136 @@
1 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){
2 2 'use strict';
3 3
4 -var Boxzilla = require('boxzilla');
5 -var options = window.boxzilla_options;
6 -var isLoggedIn = document.body.className.indexOf('logged-in') > -1;
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; };
7 5
8 -// print message when test mode is enabled
9 -if( isLoggedIn && options.testMode ) {
10 - console.log( 'Boxzilla: Test mode is enabled. Please disable test mode if you\'re done testing.' );
11 -}
6 +(function () {
7 + 'use strict';
12 8
13 -// init boxzilla
14 -Boxzilla.init();
9 + var Boxzilla = require('boxzilla');
10 + var options = window.boxzilla_options;
15 11
16 -// create boxes from options
17 -for( var i=0; i < options.boxes.length; i++ ) {
18 - // get opts
19 - var boxOpts = options.boxes[i];
20 - boxOpts.testMode = isLoggedIn && options.testMode;
12 + // expose Boxzilla object to window
13 + window.Boxzilla = Boxzilla;
21 14
22 - // fix http:// links in box content....
23 - if( window.location.origin.substring(0, 5) === "https" ) {
24 - boxOpts.content = boxOpts.content.replace(window.location.origin.replace("https", "http"), window.location.origin);
15 + function ready(fn) {
16 + if (document.readyState != 'loading') {
17 + fn();
18 + } else {
19 + document.addEventListener('DOMContentLoaded', fn);
20 + }
25 21 }
26 22
27 - // create box
28 - var box = Boxzilla.create( boxOpts.id, boxOpts);
29 -
30 - // add custom css to box
31 - css(box.element, boxOpts.css);
32 -}
23 + // helper function for setting CSS styles
24 + function css(element, styles) {
25 + if (styles.background_color) {
26 + element.style.background = styles.background_color;
27 + }
33 28
34 -// helper function for setting CSS styles
35 -function css(element, styles) {
36 - if( styles.background_color ) {
37 - element.style.background = styles.background_color;
29 + if (styles.color) {
30 + element.style.color = styles.color;
31 + }
32 +
33 + if (styles.border_color) {
34 + element.style.borderColor = styles.border_color;
35 + }
36 +
37 + if (styles.border_width) {
38 + element.style.borderWidth = parseInt(styles.border_width) + "px";
39 + }
40 +
41 + if (styles.border_style) {
42 + element.style.borderStyle = styles.border_style;
43 + }
44 +
45 + if (styles.width) {
46 + element.style.maxWidth = parseInt(styles.width) + "px";
47 + }
38 48 }
39 49
40 - if( styles.color ) {
41 - element.style.color = styles.color;
42 - }
50 + function createBoxesFromConfig() {
51 + var isLoggedIn = document.body.className.indexOf('logged-in') > -1;
43 52
44 - if( styles.border_color ) {
45 - element.style.borderColor = styles.border_color;
46 - }
53 + // failsafe against including script twice.
54 + if (options.inited) {
55 + return;
56 + }
47 57
48 - if( styles.border_width ) {
49 - element.style.borderWidth = parseInt(styles.border_width) + "px";
50 - }
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 + }
51 62
52 - if( styles.border_style ) {
53 - element.style.borderStyle = styles.border_style;
54 - }
63 + // init boxzilla
64 + Boxzilla.init();
55 65
56 - if( styles.width ) {
57 - element.style.maxWidth = parseInt(styles.width) + "px";
66 + // create boxes from options
67 + for (var i = 0; i < options.boxes.length; i++) {
68 + // get opts
69 + var boxOpts = options.boxes[i];
70 + boxOpts.testMode = isLoggedIn && options.testMode;
71 +
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);
77 + }
78 +
79 + // create box
80 + var box = Boxzilla.create(boxOpts.id, boxOpts);
81 +
82 + // add box slug to box element as classname
83 + box.element.className = box.element.className + ' boxzilla-' + boxOpts.post.slug;
84 +
85 + // add custom css to box
86 + css(box.element, boxOpts.css);
87 +
88 + box.element.firstChild.firstChild.className += " first-child";
89 + box.element.firstChild.lastChild.className += " last-child";
90 + }
91 +
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 +
99 + options.inited = true;
100 +
101 + // trigger "done" event.
102 + Boxzilla.trigger('done');
58 103 }
59 -}
60 104
61 -/**
62 - * If a MailChimp for WordPress form was submitted, open the box containing that form (if any)
63 - *
64 - * TODO: Just set location hash from MailChimp for WP?
65 - */
66 -window.addEventListener('load', function() {
67 - if( typeof(window.mc4wp_forms_config) === "object" && window.mc4wp_forms_config.submitted_form ) {
68 - var selector = '#' + window.mc4wp_forms_config.submitted_form.element_id;
69 - var boxes = Boxzilla.boxes;
70 - for( var boxId in boxes ) {
71 - if(!boxes.hasOwnProperty(boxId)) { continue; }
72 - var box = boxes[boxId];
73 - if( box.element.querySelector(selector)) {
74 - box.show();
75 - return;
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;
112 + }
113 + var box = boxes[boxId];
114 + if (box.element.querySelector(selector)) {
115 + box.show();
116 + return;
117 + }
76 118 }
77 119 }
78 120 }
79 -});
80 121
81 -window.Boxzilla = Boxzilla;
122 + // create boxes as soon as document.ready fires
123 + ready(createBoxesFromConfig);
124 +})();
125 +
82 126 },{"boxzilla":4}],2:[function(require,module,exports){
127 +'use strict';
128 +
83 129 var duration = 320;
84 130
85 131 function css(element, styles) {
86 - for(var property in styles) {
132 + for (var property in styles) {
87 133 element.style[property] = styles[property];
88 134 }
89 135 }
90 136
@@ -89,9 +135,9 @@
89 135 }
90 136
91 137 function initObjectProperties(properties, value) {
92 138 var newObject = {};
93 - for(var i=0; i<properties.length; i++) {
139 + for (var i = 0; i < properties.length; i++) {
94 140 newObject[properties[i]] = value;
95 141 }
96 142 return newObject;
97 143 }
@@ -96,10 +142,10 @@
96 142 return newObject;
97 143 }
98 144
99 145 function copyObjectProperties(properties, object) {
100 - var newObject = {}
101 - for(var i=0; i<properties.length; i++) {
146 + var newObject = {};
147 + for (var i = 0; i < properties.length; i++) {
102 148 newObject[properties[i]] = object[properties[i]];
103 149 }
104 150 return newObject;
105 151 }
@@ -110,9 +156,9 @@
110 156 * @param element
111 157 * @returns {boolean}
112 158 */
113 159 function animated(element) {
114 - return !! element.getAttribute('data-animated');
160 + return !!element.getAttribute('data-animated');
115 161 }
116 162
117 163 /**
118 164 * Toggles the element using the given animation.
@@ -124,9 +170,9 @@
124 170 var nowVisible = element.style.display != 'none' || element.offsetLeft > 0;
125 171
126 172 // create clone for reference
127 173 var clone = element.cloneNode(true);
128 - var cleanup = function() {
174 + var cleanup = function cleanup() {
129 175 element.removeAttribute('data-animated');
130 176 element.setAttribute('style', clone.getAttribute('style'));
131 177 element.style.display = nowVisible ? 'none' : '';
132 178 };
@@ -134,9 +180,9 @@
134 180 // store attribute so everyone knows we're animating this element
135 181 element.setAttribute('data-animated', "true");
136 182
137 183 // toggle element visiblity right away if we're making something visible
138 - if( ! nowVisible ) {
184 + if (!nowVisible) {
139 185 element.style.display = '';
140 186 }
141 187
142 188 var hiddenStyles, visibleStyles;
@@ -141,13 +187,13 @@
141 187
142 188 var hiddenStyles, visibleStyles;
143 189
144 190 // animate properties
145 - if( animation === 'slide' ) {
191 + if (animation === 'slide') {
146 192 hiddenStyles = initObjectProperties(["height", "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom"], 0);
147 193 visibleStyles = {};
148 194
149 - if( ! nowVisible ) {
195 + if (!nowVisible) {
150 196 var computedStyles = window.getComputedStyle(element);
151 197 visibleStyles = copyObjectProperties(["height", "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom"], computedStyles);
152 198 css(element, hiddenStyles);
153 199 }
@@ -157,9 +203,9 @@
157 203 animate(element, nowVisible ? hiddenStyles : visibleStyles, cleanup);
158 204 } else {
159 205 hiddenStyles = { opacity: 0 };
160 206 visibleStyles = { opacity: 1 };
161 - if( ! nowVisible ) {
207 + if (!nowVisible) {
162 208 css(element, hiddenStyles);
163 209 }
164 210
165 211 animate(element, nowVisible ? hiddenStyles : visibleStyles, cleanup);
@@ -171,9 +217,9 @@
171 217 var initialStyles = window.getComputedStyle(element);
172 218 var currentStyles = {};
173 219 var propSteps = {};
174 220
175 - for(var property in targetStyles) {
221 + for (var property in targetStyles) {
176 222 // make sure we have an object filled with floats
177 223 targetStyles[property] = parseFloat(targetStyles[property]);
178 224
179 225 // calculate step size & current value
@@ -180,30 +226,30 @@
180 226 var to = targetStyles[property];
181 227 var current = parseFloat(initialStyles[property]);
182 228
183 229 // is there something to do?
184 - if( current == to ) {
230 + if (current == to) {
185 231 delete targetStyles[property];
186 232 continue;
187 233 }
188 234
189 - propSteps[property] = ( to - current ) / duration; // points per second
235 + propSteps[property] = (to - current) / duration; // points per second
190 236 currentStyles[property] = current;
191 237 }
192 238
193 - var tick = function() {
239 + var tick = function tick() {
194 240 var now = +new Date();
195 241 var timeSinceLastTick = now - last;
196 242 var done = true;
197 243
198 244 var step, to, increment, newValue;
199 - for(var property in targetStyles ) {
245 + for (var property in targetStyles) {
200 246 step = propSteps[property];
201 247 to = targetStyles[property];
202 - increment = step * timeSinceLastTick;
248 + increment = step * timeSinceLastTick;
203 249 newValue = currentStyles[property] + increment;
204 250
205 - if( step > 0 && newValue >= to || step < 0 && newValue <= to ) {
251 + if (step > 0 && newValue >= to || step < 0 && newValue <= to) {
206 252 newValue = to;
207 253 } else {
208 254 done = false;
209 255 }
@@ -217,10 +263,10 @@
217 263
218 264 last = +new Date();
219 265
220 266 // keep going until we're done for all props
221 - if(!done) {
222 - (window.requestAnimationFrame && requestAnimationFrame(tick)) || setTimeout(tick, 32);
267 + if (!done) {
268 + window.requestAnimationFrame && requestAnimationFrame(tick) || setTimeout(tick, 32);
223 269 } else {
224 270 // call callback
225 271 fn && fn();
226 272 }
@@ -228,29 +274,29 @@
228 274
229 275 tick();
230 276 }
231 277
232 -
233 278 module.exports = {
234 279 'toggle': toggle,
235 280 'animate': animate,
236 281 'animated': animated
237 282 };
283 +
238 284 },{}],3:[function(require,module,exports){
239 285 'use strict';
240 286
241 287 var defaults = {
242 - 'animation': 'fade',
243 - 'rehide': false,
244 - 'content': '',
245 - 'cookie': null,
246 - 'icon': '&times',
247 - 'minimumScreenWidth': 0,
248 - 'position': 'center',
249 - 'testMode': false,
250 - 'trigger': false,
251 - 'closable': true
252 - },
288 + 'animation': 'fade',
289 + 'rehide': false,
290 + 'content': '',
291 + 'cookie': null,
292 + 'icon': '&times',
293 + 'minimumScreenWidth': 0,
294 + 'position': 'center',
295 + 'testMode': false,
296 + 'trigger': false,
297 + 'closable': true
298 +},
253 299 Boxzilla,
254 300 Animator = require('./animator.js');
255 301
256 302 /**
@@ -259,12 +305,16 @@
259 305 * @param obj1
260 306 * @param obj2
261 307 * @returns {*}
262 308 */
263 -function merge( obj1, obj2 ) {
309 +function merge(obj1, obj2) {
264 310 var obj3 = {};
265 - for (var attrname in obj1) { obj3[attrname] = obj1[attrname]; }
266 - for (var attrname in obj2) { obj3[attrname] = obj2[attrname]; }
311 + for (var attrname in obj1) {
312 + obj3[attrname] = obj1[attrname];
313 + }
314 + for (var attrname in obj2) {
315 + obj3[attrname] = obj2[attrname];
316 + }
267 317 return obj3;
268 318 }
269 319
270 320 /**
@@ -274,17 +324,16 @@
274 324 function getDocumentHeight() {
275 325 var body = document.body,
276 326 html = document.documentElement;
277 327
278 - var height = Math.max( body.scrollHeight, body.offsetHeight,
279 - html.clientHeight, html.scrollHeight, html.offsetHeight );
328 + var height = Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight);
280 329
281 330 return height;
282 331 }
283 332
284 333 // Box Object
285 -var Box = function( id, config ) {
286 - this.id = id;
334 +var Box = function Box(id, config) {
335 + this.id = id;
287 336
288 337 // store config values
289 338 this.config = merge(defaults, config);
290 339
@@ -291,11 +340,11 @@
291 340 // store ref to overlay
292 341 this.overlay = document.getElementById('boxzilla-overlay');
293 342
294 343 // state
295 - this.visible = false;
296 - this.dismissed = false;
297 - this.triggered = false;
344 + this.visible = false;
345 + this.dismissed = false;
346 + this.triggered = false;
298 347 this.triggerHeight = 0;
299 348 this.cookieSet = false;
300 349 this.element = null;
301 350 this.closeIcon = null;
@@ -300,10 +349,10 @@
300 349 this.element = null;
301 350 this.closeIcon = null;
302 351
303 352 // if a trigger was given, calculate values once and store
304 - if( this.config.trigger ) {
305 - if( this.config.trigger.method === 'percentage' || this.config.trigger.method === 'element' ) {
353 + if (this.config.trigger) {
354 + if (this.config.trigger.method === 'percentage' || this.config.trigger.method === 'element') {
306 355 this.triggerHeight = this.calculateTriggerHeight();
307 356 }
308 357
309 358 this.cookieSet = this.isCookieSet();
@@ -316,41 +365,35 @@
316 365 this.events();
317 366 };
318 367
319 368 // initialise the box
320 -Box.prototype.events = function() {
369 +Box.prototype.events = function () {
321 370 var box = this;
322 371
323 372 // attach event to "close" icon inside box
324 - this.closeIcon && this.closeIcon.addEventListener('click', box.dismiss.bind(this));
373 + if (this.closeIcon) {
374 + this.closeIcon.addEventListener('click', this.dismiss.bind(this));
375 + }
325 376
326 - this.element.addEventListener('click', function(e) {
327 - if( e.target.tagName === 'A' ) {
328 - Boxzilla.trigger('box.interactions.link', [ box, e.target ] );
377 + this.element.addEventListener('click', function (e) {
378 + if (e.target.tagName === 'A') {
379 + Boxzilla.trigger('box.interactions.link', [box, e.target]);
329 380 }
330 381 }, false);
331 382
332 - this.element.addEventListener('submit', function(e) {
383 + this.element.addEventListener('submit', function (e) {
333 384 box.setCookie();
334 - Boxzilla.trigger('box.interactions.form', [ box, e.target ]);
385 + Boxzilla.trigger('box.interactions.form', [box, e.target]);
335 386 }, false);
336 -
337 - window.addEventListener("hashchange", function() {
338 - var needle = "#boxzilla-" + box.id;
339 - if( location.hash === needle ) {
340 - box.toggle();
341 - }
342 - });
343 387
344 388 // maybe show box right away
345 - if( this.fits() && this.locationHashRefersBox() ) {
389 + if (this.fits() && this.locationHashRefersBox()) {
346 390 window.addEventListener('load', this.show.bind(this));
347 391 }
348 -
349 392 };
350 393
351 394 // generate dom elements for this box
352 -Box.prototype.dom = function() {
395 +Box.prototype.dom = function () {
353 396 var wrapper = document.createElement('div');
354 397 wrapper.className = 'boxzilla-container boxzilla-' + this.config.position + '-container';
355 398
356 399 var box = document.createElement('div');
@@ -365,18 +408,18 @@
365 408 box.appendChild(content);
366 409
367 410 // remove <script> from box content and append them to the document body
368 411 var scripts = content.querySelectorAll('script');
369 - if(scripts.length) {
412 + if (scripts.length) {
370 413 var script = document.createElement('script');
371 - for( var i=0; i<scripts.length; i++ ) {
414 + for (var i = 0; i < scripts.length; i++) {
372 415 script.appendChild(document.createTextNode(scripts[i].text));
373 416 scripts[i].parentNode.removeChild(scripts[i]);
374 417 }
375 418 document.body.appendChild(script);
376 419 }
377 -
378 - if( this.config.closable && this.config.icon ) {
420 +
421 + if (this.config.closable && this.config.icon) {
379 422 var closeIcon = document.createElement('span');
380 423 closeIcon.className = "boxzilla-close-icon";
381 424 closeIcon.innerHTML = this.config.icon;
382 425 box.appendChild(closeIcon);
@@ -387,9 +430,9 @@
387 430 this.element = box;
388 431 };
389 432
390 433 // set (calculate) custom box styling depending on box options
391 -Box.prototype.setCustomBoxStyling = function() {
434 +Box.prototype.setCustomBoxStyling = function () {
392 435
393 436 // reset element to its initial state
394 437 var origDisplay = this.element.style.display;
395 438 this.element.style.display = '';
@@ -400,16 +443,16 @@
400 443 var windowHeight = window.innerHeight;
401 444 var boxHeight = this.element.clientHeight;
402 445
403 446 // add scrollbar to box and limit height
404 - if( boxHeight > windowHeight ) {
447 + if (boxHeight > windowHeight) {
405 448 this.element.style.maxHeight = windowHeight + "px";
406 449 this.element.style.overflowY = 'scroll';
407 450 }
408 451
409 452 // set new top margin for boxes which are centered
410 - if( this.config.position === 'center' ) {
411 - var newTopMargin = ( ( windowHeight - boxHeight ) / 2 );
453 + if (this.config.position === 'center') {
454 + var newTopMargin = (windowHeight - boxHeight) / 2;
412 455 newTopMargin = newTopMargin >= 0 ? newTopMargin : 0;
413 456 this.element.style.marginTop = newTopMargin + "px";
414 457 }
415 458
@@ -416,27 +459,27 @@
416 459 this.element.style.display = origDisplay;
417 460 };
418 461
419 462 // toggle visibility of the box
420 -Box.prototype.toggle = function(show) {
463 +Box.prototype.toggle = function (show) {
421 464
422 465 // revert visibility if no explicit argument is given
423 - if( typeof( show ) === "undefined" ) {
424 - show = ! this.visible;
466 + if (typeof show === "undefined") {
467 + show = !this.visible;
425 468 }
426 469
427 470 // is box already at desired visibility?
428 - if( show === this.visible ) {
471 + if (show === this.visible) {
429 472 return false;
430 473 }
431 474
432 475 // is box being animated?
433 - if( Animator.animated(this.element) ) {
476 + if (Animator.animated(this.element)) {
434 477 return false;
435 478 }
436 479
437 480 // if box should be hidden but is not closable, bail.
438 - if( ! show && ! this.config.closable ) {
481 + if (!show && !this.config.closable) {
439 482 return false;
440 483 }
441 484
442 485 // set new visibility status
@@ -445,48 +488,43 @@
445 488 // calculate new styling rules
446 489 this.setCustomBoxStyling();
447 490
448 491 // trigger event
449 - Boxzilla.trigger('box.' + ( show ? 'show' : 'hide' ), [ this ] );
492 + Boxzilla.trigger('box.' + (show ? 'show' : 'hide'), [this]);
450 493
451 494 // show or hide box using selected animation
452 - if( this.config.position === 'center' ) {
495 + if (this.config.position === 'center') {
496 + this.overlay.classList.toggle('boxzilla-' + this.id + '-overlay');
453 497 Animator.toggle(this.overlay, "fade");
454 498 }
455 499
456 500 Animator.toggle(this.element, this.config.animation);
457 501
458 - // focus on first input field in box
459 - var firstInput = this.element.querySelector('input, textarea');
460 - if(firstInput) {
461 - firstInput.focus();
462 - }
463 -
464 502 return true;
465 503 };
466 504
467 505 // show the box
468 -Box.prototype.show = function() {
506 +Box.prototype.show = function () {
469 507 return this.toggle(true);
470 508 };
471 509
472 510 // hide the box
473 -Box.prototype.hide = function() {
511 +Box.prototype.hide = function () {
474 512 return this.toggle(false);
475 513 };
476 514
477 515 // calculate trigger height
478 -Box.prototype.calculateTriggerHeight = function() {
516 +Box.prototype.calculateTriggerHeight = function () {
479 517 var triggerHeight = 0;
480 518
481 - if( this.config.trigger.method === 'element' ) {
519 + if (this.config.trigger.method === 'element') {
482 520 var triggerElement = document.body.querySelector(this.config.trigger.value);
483 - if( triggerElement ) {
521 + if (triggerElement) {
484 522 var offset = triggerElement.getBoundingClientRect();
485 523 triggerHeight = offset.top;
486 524 }
487 - } else if( this.config.trigger.method === 'percentage' ) {
488 - triggerHeight = ( this.config.trigger.value / 100 * getDocumentHeight() );
525 + } else if (this.config.trigger.method === 'percentage') {
526 + triggerHeight = this.config.trigger.value / 100 * getDocumentHeight();
489 527 }
490 528
491 529 return triggerHeight;
492 530 };
@@ -491,18 +529,18 @@
491 529 return triggerHeight;
492 530 };
493 531
494 532 // checks whether window.location.hash equals the box element ID or that of any element inside the box
495 -Box.prototype.locationHashRefersBox = function() {
533 +Box.prototype.locationHashRefersBox = function () {
496 534
497 - if( ! window.location.hash || 0 === window.location.hash.length ) {
535 + if (!window.location.hash || 0 === window.location.hash.length) {
498 536 return false;
499 537 }
500 538
501 539 var elementId = window.location.hash.substring(1);
502 - if( elementId === this.element.id ) {
540 + if (elementId === this.element.id) {
503 541 return true;
504 - } else if( this.element.querySelector('#' + elementId) ) {
542 + } else if (this.element.querySelector('#' + elementId)) {
505 543 return true;
506 544 }
507 545
508 546 return false;
@@ -507,49 +545,49 @@
507 545
508 546 return false;
509 547 };
510 548
511 -Box.prototype.fits = function() {
512 - if( this.config.minimumScreenWidth <= 0 ) {
549 +Box.prototype.fits = function () {
550 + if (this.config.minimumScreenWidth <= 0) {
513 551 return true;
514 552 }
515 553
516 - return window.innerWidth > this.config.minimumScreenWidth
554 + return window.innerWidth > this.config.minimumScreenWidth;
517 555 };
518 556
519 557 // is this box enabled?
520 -Box.prototype.mayAutoShow = function() {
558 +Box.prototype.mayAutoShow = function () {
521 559
522 - if( this.dismissed ) {
560 + if (this.dismissed) {
523 561 return false;
524 562 }
525 563
526 564 // check if box fits on given minimum screen width
527 - if( ! this.fits() ) {
565 + if (!this.fits()) {
528 566 return false;
529 567 }
530 568
531 569 // if trigger empty or error in calculating triggerHeight, return false
532 - if( ! this.config.trigger ) {
570 + if (!this.config.trigger) {
533 571 return false;
534 572 }
535 573
536 574 // rely on cookie value (show if not set, don't show if set)
537 - return ! this.cookieSet;
575 + return !this.cookieSet;
538 576 };
539 577
540 -Box.prototype.mayRehide = function() {
578 +Box.prototype.mayRehide = function () {
541 579 return this.config.rehide && this.triggered;
542 580 };
543 581
544 -Box.prototype.isCookieSet = function() {
582 +Box.prototype.isCookieSet = function () {
545 583 // always show on test mode
546 - if(this.config.testMode) {
584 + if (this.config.testMode) {
547 585 return false;
548 586 }
549 587
550 588 // if either cookie is null or trigger & dismiss are both falsey, don't bother checking.
551 - if(!this.config.cookie || ( ! this.config.cookie.triggered && ! this.config.cookie.dismissed ) ) {
589 + if (!this.config.cookie || !this.config.cookie.triggered && !this.config.cookie.dismissed) {
552 590 return false;
553 591 }
554 592
555 593 var cookieSet = document.cookie.replace(new RegExp("(?:(?:^|.*;)\\s*" + 'boxzilla_box_' + this.id + "\\s*\\=\\s*([^;]*).*$)|^.*$"), "$1") === "true";
@@ -556,68 +594,84 @@
556 594 return cookieSet;
557 595 };
558 596
559 597 // set cookie that disables automatically showing the box
560 -Box.prototype.setCookie = function(hours) {
598 +Box.prototype.setCookie = function (hours) {
561 599 var expiryDate = new Date();
562 - expiryDate.setHours( expiryDate.getHours() + hours);
563 - document.cookie = 'boxzilla_box_'+ this.id + '=true; expires='+ expiryDate.toUTCString() +'; path=/';
600 + expiryDate.setHours(expiryDate.getHours() + hours);
601 + document.cookie = 'boxzilla_box_' + this.id + '=true; expires=' + expiryDate.toUTCString() + '; path=/';
564 602 };
565 603
566 -Box.prototype.trigger = function() {
604 +Box.prototype.trigger = function () {
567 605 var shown = this.show();
568 - if( ! shown ) {
606 + if (!shown) {
569 607 return;
570 608 }
571 609
572 610 this.triggered = true;
573 - if(this.config.cookie && this.config.cookie.triggered) {
611 + if (this.config.cookie && this.config.cookie.triggered) {
574 612 this.setCookie(this.config.cookie.triggered);
575 613 }
576 614 };
577 615
578 -Box.prototype.dismiss = function() {
616 +/**
617 + * Dismisses the box and optionally sets a cookie.
618 + *
619 + * @param e The event that triggered this dismissal.
620 + * @returns {boolean}
621 + */
622 +Box.prototype.dismiss = function (e) {
623 + // prevent default action
624 + e && e.preventDefault();
625 +
626 + // only dismiss box if it's currently open.
627 + if (!this.visible) {
628 + return false;
629 + }
630 +
631 + // hide box element
579 632 this.hide();
580 633
581 - if(this.config.cookie && this.config.cookie.dismissed) {
634 + // set cookie
635 + if (this.config.cookie && this.config.cookie.dismissed) {
582 636 this.setCookie(this.config.cookie.dismissed);
583 637 }
584 638
585 639 this.dismissed = true;
586 - Boxzilla.trigger('box.dismiss', [ this ]);
640 + Boxzilla.trigger('box.dismiss', [this]);
641 + return true;
587 642 };
588 643
589 -module.exports = function(_Boxzilla) {
644 +module.exports = function (_Boxzilla) {
590 645 Boxzilla = _Boxzilla;
591 646 return Box;
592 647 };
648 +
593 649 },{"./animator.js":2}],4:[function(require,module,exports){
594 650 'use strict';
595 651
652 +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; };
653 +
596 654 var EventEmitter = require('wolfy87-eventemitter'),
597 655 Boxzilla = Object.create(EventEmitter.prototype),
598 656 Box = require('./box.js')(Boxzilla),
599 657 Timer = require('./timer.js'),
600 - boxes = {},
658 + boxes = [],
601 659 overlay,
602 - exitIntentDelayTimer, exitIntentTriggered,
603 - siteTimer, pageTimer, pageViews;
660 + scrollElement = window,
661 + exitIntentDelayTimer,
662 + exitIntentTriggered,
663 + siteTimer,
664 + pageTimer,
665 + pageViews;
604 666
605 -function each( obj, callback ) {
606 - for( var key in obj ) {
607 - if(! obj.hasOwnProperty(key)) continue;
608 - callback(obj[key]);
609 - }
610 -}
611 -
612 667 function throttle(fn, threshhold, scope) {
613 668 threshhold || (threshhold = 250);
614 - var last,
615 - deferTimer;
669 + var last, deferTimer;
616 670 return function () {
617 671 var context = scope || this;
618 672
619 - var now = +new Date,
673 + var now = +new Date(),
620 674 args = arguments;
621 675 if (last && now < last + threshhold) {
622 676 // hold on to it
623 677 clearTimeout(deferTimer);
@@ -640,14 +694,20 @@
640 694 }
641 695
642 696 // check "pageviews" criteria for each box
643 697 function checkPageViewsCriteria() {
644 - each(boxes, function(box) {
645 - if( ! box.mayAutoShow() ) {
698 +
699 + // don't bother if another box is currently open
700 + if (isAnyBoxVisible()) {
701 + return;
702 + }
703 +
704 + boxes.forEach(function (box) {
705 + if (!box.mayAutoShow()) {
646 706 return;
647 707 }
648 708
649 - if( box.config.trigger.method === 'pageviews' && pageViews >= box.config.trigger.value ) {
709 + if (box.config.trigger.method === 'pageviews' && pageViews >= box.config.trigger.value) {
650 710 box.trigger();
651 711 }
652 712 });
653 713 }
@@ -653,10 +713,15 @@
653 713 }
654 714
655 715 // check time trigger criteria for each box
656 716 function checkTimeCriteria() {
657 - each(boxes, function(box) {
658 - if( ! box.mayAutoShow() ) {
717 + // don't bother if another box is currently open
718 + if (isAnyBoxVisible()) {
719 + return;
720 + }
721 +
722 + boxes.forEach(function (box) {
723 + if (!box.mayAutoShow()) {
659 724 return;
660 725 }
661 726
662 727 // check "time on site" trigger
@@ -672,19 +737,27 @@
672 737 }
673 738
674 739 // check triggerHeight criteria for all boxes
675 740 function checkHeightCriteria() {
676 - var scrollY = ( window.scrollY || window.pageYOffset ) + window.innerHeight * 0.75;
677 741
678 - each(boxes, function(box) {
742 + var scrollY = scrollElement.hasOwnProperty('scrollY') ? scrollElement.scrollY : scrollElement.scrollTop;
743 + scrollY = scrollY + window.innerHeight * 0.75;
744 + console.log(scrollY);
679 745
680 - if( ! box.mayAutoShow() || box.triggerHeight <= 0 ) {
746 + boxes.forEach(function (box) {
747 + if (!box.mayAutoShow() || box.triggerHeight <= 0) {
681 748 return;
682 749 }
683 750
684 - if( scrollY > box.triggerHeight ) {
751 + if (scrollY > box.triggerHeight) {
752 + // don't bother if another box is currently open
753 + if (isAnyBoxVisible()) {
754 + return;
755 + }
756 +
757 + // trigger box
685 758 box.trigger();
686 - } else if( box.mayRehide() ) {
759 + } else if (box.mayRehide()) {
687 760 box.hide();
688 761 }
689 762 });
690 763 }
@@ -690,9 +763,9 @@
690 763 }
691 764
692 765 // recalculate heights and variables based on height
693 766 function recalculateHeights() {
694 - each(boxes, function(box) {
767 + boxes.forEach(function (box) {
695 768 box.setCustomBoxStyling();
696 769 });
697 770 }
698 771
@@ -700,14 +773,14 @@
700 773 var x = e.offsetX;
701 774 var y = e.offsetY;
702 775
703 776 // calculate if click was near a box to avoid closing it (click error margin)
704 - each(boxes, function(box) {
777 + boxes.forEach(function (box) {
705 778 var rect = box.element.getBoundingClientRect();
706 - var margin = 100 + ( window.innerWidth * 0.05 );
779 + var margin = 100 + window.innerWidth * 0.05;
707 780
708 781 // if click was not anywhere near box, dismiss it.
709 - if( x < ( rect.left - margin ) || x > ( rect.right + margin ) || y < ( rect.top - margin ) || y > ( rect.bottom + margin ) ) {
782 + if (x < rect.left - margin || x > rect.right + margin || y < rect.top - margin || y > rect.bottom + margin) {
710 783 box.dismiss();
711 784 }
712 785 });
713 786 }
@@ -712,12 +785,15 @@
712 785 });
713 786 }
714 787
715 788 function triggerExitIntent() {
716 - if(exitIntentTriggered) return;
789 + // do nothing if already triggered OR another box is visible.
790 + if (exitIntentTriggered || isAnyBoxVisible()) {
791 + return;
792 + }
717 793
718 - each(boxes, function(box) {
719 - if(box.mayAutoShow() && box.config.trigger.method === 'exit_intent' ) {
794 + boxes.forEach(function (box) {
795 + if (box.mayAutoShow() && box.config.trigger.method === 'exit_intent') {
720 796 box.trigger();
721 797 }
722 798 });
723 799
@@ -727,28 +803,51 @@
727 803 function onMouseLeave(e) {
728 804 var delay = 400;
729 805
730 806 // did mouse leave at top of window?
731 - if( e.clientY <= 0 ) {
807 + if (e.clientY <= 0) {
732 808 exitIntentDelayTimer = window.setTimeout(triggerExitIntent, delay);
733 809 }
734 810 }
735 811
812 +function isAnyBoxVisible() {
813 +
814 + for (var i = 0; i < boxes.length; i++) {
815 + var box = boxes[i];
816 +
817 + if (box.visible) {
818 + return true;
819 + }
820 + }
821 +
822 + return false;
823 +}
824 +
736 825 function onMouseEnter() {
737 - if( exitIntentDelayTimer ) {
826 + if (exitIntentDelayTimer) {
738 827 window.clearInterval(exitIntentDelayTimer);
739 828 exitIntentDelayTimer = null;
740 829 }
741 830 }
742 831
832 +function onElementClick(e) {
833 + var el = e.target || e.srcElement;
834 + if (el && el.tagName === 'A' && el.getAttribute('href').indexOf('#boxzilla-') === 0) {
835 + var boxId = e.target.getAttribute('href').substring("#boxzilla-".length);
836 + Boxzilla.toggle(boxId);
837 + }
838 +}
839 +
743 840 var timers = {
744 - start: function() {
745 - var sessionTime = sessionStorage.getItem('boxzilla_timer');
746 - if( sessionTime ) siteTimer.time = sessionTime;
841 + start: function start() {
842 + try {
843 + var sessionTime = sessionStorage.getItem('boxzilla_timer');
844 + if (sessionTime) siteTimer.time = sessionTime;
845 + } catch (e) {}
747 846 siteTimer.start();
748 847 pageTimer.start();
749 848 },
750 - stop: function() {
849 + stop: function stop() {
751 850 sessionStorage.setItem('boxzilla_timer', siteTimer.time);
752 851 siteTimer.stop();
753 852 pageTimer.stop();
754 853 }
@@ -754,12 +853,19 @@
754 853 }
755 854 };
756 855
757 856 // initialise & add event listeners
758 -Boxzilla.init = function() {
759 - siteTimer = new Timer(sessionStorage.getItem('boxzilla_timer') || 0);
857 +Boxzilla.init = function () {
858 + document.body.addEventListener('click', onElementClick, false);
859 +
860 + try {
861 + pageViews = sessionStorage.getItem('boxzilla_pageviews') || 0;
862 + } catch (e) {
863 + pageViews = 0;
864 + }
865 +
866 + siteTimer = new Timer(0);
760 867 pageTimer = new Timer(0);
761 - pageViews = sessionStorage.getItem('boxzilla_pageviews') || 0;
762 868
763 869 // insert styles into DOM
764 870 var styles = require('./styles.js');
765 871 var styleElement = document.createElement('style');
@@ -773,21 +879,22 @@
773 879 overlay.id = 'boxzilla-overlay';
774 880 document.body.appendChild(overlay);
775 881
776 882 // event binds
777 - window.addEventListener('scroll', throttle(checkHeightCriteria));
883 + scrollElement.addEventListener('touchstart', throttle(checkHeightCriteria), true);
884 + scrollElement.addEventListener('scroll', throttle(checkHeightCriteria), true);
778 885 window.addEventListener('resize', throttle(recalculateHeights));
779 - window.addEventListener('load', recalculateHeights );
886 + window.addEventListener('load', recalculateHeights);
780 887 overlay.addEventListener('click', onOverlayClick);
781 888 window.setInterval(checkTimeCriteria, 1000);
782 - window.setTimeout(checkPageViewsCriteria, 1000 );
783 - document.addEventListener('mouseleave', onMouseLeave);
784 - document.addEventListener('mouseenter', onMouseEnter);
889 + window.setTimeout(checkPageViewsCriteria, 1000);
890 + document.documentElement.addEventListener('mouseleave', onMouseLeave);
891 + document.documentElement.addEventListener('mouseenter', onMouseEnter);
785 892 document.addEventListener('keyup', onKeyUp);
786 893
787 894 timers.start();
788 895 window.addEventListener('focus', timers.start);
789 - window.addEventListener('beforeunload', function() {
896 + window.addEventListener('beforeunload', function () {
790 897 timers.stop();
791 898 sessionStorage.setItem('boxzilla_pageviews', ++pageViews);
792 899 });
793 900 window.addEventListener('blur', timers.stop);
@@ -802,44 +909,64 @@
802 909 * @param object opts
803 910 *
804 911 * @returns Box
805 912 */
806 -Boxzilla.create = function(id, opts) {
807 - boxes[id] = new Box(id, opts);
808 - return boxes[id];
913 +Boxzilla.create = function (id, opts) {
914 + var box = new Box(id, opts);
915 + boxes.push(box);
916 + return box;
809 917 };
810 918
919 +Boxzilla.get = function (id) {
920 + for (var i = 0; i < boxes.length; i++) {
921 + var box = boxes[i];
922 + if (box.id == id) {
923 + return box;
924 + }
925 + }
926 +
927 + throw new Error("No box exists with ID " + id);
928 +};
929 +
811 930 // dismiss a single box (or all by omitting id param)
812 -Boxzilla.dismiss = function(id) {
931 +Boxzilla.dismiss = function (id) {
813 932 // if no id given, dismiss all current open boxes
814 - if( typeof(id) === "undefined" ) {
815 - each(boxes, function(box) { box.dismiss(); });
816 - } else if( typeof( boxes[id] ) === "object" ) {
817 - boxes[id].dismiss();
933 + if (typeof id === "undefined") {
934 + boxes.forEach(function (box) {
935 + box.dismiss();
936 + });
937 + } else if (_typeof(boxes[id]) === "object") {
938 + Boxzilla.get(id).dismiss();
818 939 }
819 940 };
820 941
821 -Boxzilla.hide = function(id) {
822 - if( typeof(id) === "undefined" ) {
823 - each(boxes, function(box) { box.hide(); });
824 - } else if( typeof( boxes[id] ) === "object" ) {
825 - boxes[id].hide();
942 +Boxzilla.hide = function (id) {
943 + if (typeof id === "undefined") {
944 + boxes.forEach(function (box) {
945 + box.hide();
946 + });
947 + } else {
948 + Boxzilla.get(id).hide();
826 949 }
827 950 };
828 951
829 -Boxzilla.show = function(id) {
830 - if( typeof(id) === "undefined" ) {
831 - each(boxes, function(box) { box.show(); });
832 - } else if( typeof( boxes[id] ) === "object" ) {
833 - boxes[id].show();
952 +Boxzilla.show = function (id) {
953 + if (typeof id === "undefined") {
954 + boxes.forEach(function (box) {
955 + box.show();
956 + });
957 + } else {
958 + Boxzilla.get(id).show();
834 959 }
835 960 };
836 961
837 -Boxzilla.toggle = function(id) {
838 - if( typeof(id) === "undefined" ) {
839 - each(boxes, function(box) { box.toggle(); });
840 - } else if( typeof( boxes[id] ) === "object" ) {
841 - boxes[id].toggle();
962 +Boxzilla.toggle = function (id) {
963 + if (typeof id === "undefined") {
964 + boxes.forEach(function (box) {
965 + box.toggle();
966 + });
967 + } else {
968 + Boxzilla.get(id).toggle();
842 969 }
843 970 };
844 971
845 972 // expose each individual box.
@@ -846,38 +973,45 @@
846 973 Boxzilla.boxes = boxes;
847 974
848 975 window.Boxzilla = Boxzilla;
849 976
850 -if ( typeof module !== 'undefined' && module.exports ) {
977 +if (typeof module !== 'undefined' && module.exports) {
851 978 module.exports = Boxzilla;
852 979 }
980 +
853 981 },{"./box.js":3,"./styles.js":5,"./timer.js":6,"wolfy87-eventemitter":7}],5:[function(require,module,exports){
854 -const 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}`;
982 +"use strict";
983 +
984 +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}";
855 985 module.exports = styles;
986 +
856 987 },{}],6:[function(require,module,exports){
857 988 'use strict';
858 989
859 -var Timer = function(start) {
990 +var Timer = function Timer(start) {
860 991 this.time = start;
861 992 this.interval = 0;
862 993 };
863 994
864 -Timer.prototype.tick = function() {
995 +Timer.prototype.tick = function () {
865 996 this.time++;
866 997 };
867 998
868 -Timer.prototype.start = function() {
869 - if( ! this.interval ) {
999 +Timer.prototype.start = function () {
1000 + if (!this.interval) {
870 1001 this.interval = window.setInterval(this.tick.bind(this), 1000);
871 1002 }
872 1003 };
873 1004
874 -Timer.prototype.stop = function() {
875 - window.clearInterval(this.interval);
876 - this.interval = 0;
1005 +Timer.prototype.stop = function () {
1006 + if (this.interval) {
1007 + window.clearInterval(this.interval);
1008 + this.interval = 0;
1009 + }
877 1010 };
878 1011
879 1012 module.exports = Timer;
1013 +
880 1014 },{}],7:[function(require,module,exports){
881 1015 /*!
882 1016 * EventEmitter v4.2.11 - git.io/ee
883 1017 * Unlicense - http://unlicense.org/