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