// DialogTriggerJS
// Copyright (c) 2016-2017 Shahzad Malik
// MIT License
//
// Triggers a callback to pop up a dialog (or do anything else) with the specified trigger options.
//
// "trigger" can be one of the following:
// 'exitIntent': Call 'callback' when a user intends to exit (such as moving cursor off page or coming back to the top)
// 'target': Call 'callback' when a user reaches a particular target element (set 'target' to the name of the element, such as '#mytarget')
// 'scrollDown': Call 'callback' when a user scrolls down by a certain percent from when the object is instantiated (set 'percentDown' to the percentage 0-100)
// 'scrollUp': Call 'callback' when a user scrolls up by a certain percent from when the object is instantiated (set 'percentUp' to the percentage 0-100)
// 'timeout': Call 'callback' after a certain number of milliseconds have elapsed (set 'timeout' to the desired milliseconds)
//
// Examples:
// Setting up individual triggers:
// var dt = new DialogTrigger(triggerNagPopup, { trigger: 'timeout', timeout: 5000 });
// var dt = new DialogTrigger(triggerNagPopup, { trigger: 'target', target: '#all' });
// var dt = new DialogTrigger(triggerNagPopup, { trigger: 'scrollDown', percentDown: 50 });
// var dt = new DialogTrigger(triggerNagPopup, { trigger: 'exitIntent' });
//
// Triggers can also be chained for a sequence of behaviors (such as scroll down by 50%, then exit):
// var dtPercent = new DialogTrigger(function() {
// var dtExit = new DialogTrigger(triggerNagPopup, { trigger: 'exitIntent' });
// }, { trigger: 'scrollDown', percentDown: 50 });
function DialogTrigger(callback, options) {
// Becomes this.options
var defaults = {
trigger : 'timeout',
target : '',
timeout : 0,
percentDown : 50, // Used for 'percent' to define a down scroll threshold of significance (based on page height)
percentUp : 10, // Used for 'percent' to define a threshold of upward scroll after down threshold is reached
scrollInterval: 1000 // Frequency (in ms) to check for scroll changes (to avoid bogging the UI)
}
this.complete = false; // Let's us know if the popup has been triggered
this.callback = callback;
this.timer = null;
this.interval = null;
this.options = jQuery.extend(defaults, options);
this.init = function() {
if(this.options.trigger == 'exitIntent' || this.options.trigger == 'exit_intent') {
var parentThis = this;
jQuery(document).on('mouseleave', function(e) {
//console.log(e.clientX + ',' + e.clientY); // IE returns negative values on all sides
if(!parentThis.complete && e.clientY < 0) { // Check if the cursor went above the top of the browser window
parentThis.callback();
parentThis.complete = true;
jQuery(document).off('mouseleave');
}
});
} else if(this.options.trigger == 'target') {
if(this.options.target !== '') {
// Make sure the target exists
if(jQuery(this.options.target).length == 0) {
this.complete = true;
} else {
var targetScroll = jQuery(this.options.target).offset().top;
var parentThis = this;
// Only check the scroll position every few seconds, to avoid bogging the UI
this.interval = setInterval(function() {
if(jQuery(window).scrollTop() >= targetScroll) {
clearInterval(parentThis.interval);
parentThis.interval = null;
if(!parentThis.complete) {
parentThis.callback();
parentThis.complete = true;
}
}
}, this.options.scrollInterval);
}
}
} else if(this.options.trigger == 'scrollDown') {
// Let the user scroll down by some significant amount
var scrollStart = jQuery(window).scrollTop();
var pageHeight = jQuery(document).height();
var parentThis = this;
if(pageHeight > 0) {
// Only check the scroll position every few seconds, to avoid bogging the UI
this.interval = setInterval(function() {
var scrollAmount = jQuery(window).scrollTop() - scrollStart;
if(scrollAmount < 0) {
scrollAmount = 0;
scrollStart = jQuery(window).scrollTop();
}
var downScrollPercent = parseFloat(scrollAmount) / parseFloat(pageHeight);
if(downScrollPercent > parseFloat(parentThis.options.percentDown) / 100) {
clearInterval(parentThis.interval);
parentThis.interval = null;
if(!parentThis.complete) {
parentThis.callback();
parentThis.complete = true;
}
}
}, this.options.scrollInterval);
}
} else if(this.options.trigger == 'scrollUp') {
// Let the user scroll down by some significant amount
var scrollStart = jQuery(window).scrollTop();
var pageHeight = jQuery(document).height();
var parentThis = this;
if(pageHeight > 0) {
// Only check the scroll position every few seconds, to avoid bogging the UI
this.interval = setInterval(function() {
var scrollAmount = scrollStart - jQuery(window).scrollTop();
if(scrollAmount < 0) {
scrollAmount = 0;
scrollStart = jQuery(window).scrollTop();
}
var upScrollPercent = parseFloat(scrollAmount) / parseFloat(pageHeight);
if(upScrollPercent > parseFloat(parentThis.options.percentUp) / 100) {
clearInterval(parentThis.interval);
parentThis.interval = null;
if(!parentThis.complete) {
parentThis.callback();
parentThis.complete = true;
}
}
}, this.options.scrollInterval);
}
} else if(this.options.trigger == 'timeout') {
this.timer = setTimeout(this.callback, this.options.timeout);
}
};
this.cancel = function() {
if(this.timer !== null) {
clearTimeout(this.timer);
this.timer = null;
}
if(this.interval !== null) {
clearInterval(this.interval);
this.interval = null;
}
this.complete = true;
}
this.init();
}