/*
*
*
jAlert v.3
Made with love by Versatility Werks (http://flwebsites.biz)
MIT Licensed
*
*
*/
;(function($) {
var $jAlertSelectedOpts = {};
if(!Date.now)
Date.now = function(){
return +new Date();
};
$.fn.jAlert = function(options) {
var themes = ['default', 'green', 'red', 'black', 'blue','yellow'],
sizes = ['xsm', 'sm', 'md', 'lg', 'xlg', 'full'],
backgroundColors = ['white', 'black'],
styles = [], //array of styles that gets joined together with a space between in a style tag on the jalert div
classes = ['animated'], //array of classes that get joined together with a space between on the jalert div
backgroundClasses = []; //array of classes that get joined together with a space between on the jalert background div
/* Block Multiple Instances by running jAlert for each one */
if (this.length > 1){
this.each(function() {
$(this).jAlert(options);
});
return this;
}
/* Combine user options with default */
options = $.extend({}, $.fn.jAlert.defaults, options);
/* If they didn't set an id, just create a random one */
if( !options.id )
{
var unique = Date.now().toString() + Math.floor(Math.random() * 100000);
var alert_id = 'ja_' + unique;
}
else
{
var alert_id = options.id;
}
$jAlertSelectedOpts[alert_id] = {};
thisAlert = $jAlertSelectedOpts[alert_id];
thisAlert.options = options;
thisAlert.options.id = alert_id;
thisAlert.instance = false;
if( thisAlert.options.type == 'confirm' )
{
if( !thisAlert.options.content )
{
thisAlert.options.content = thisAlert.options.confirmQuestion;
}
thisAlert.options.btns = [
{ 'text': thisAlert.options.confirmBtnText, 'theme': 'green', 'class': 'confirmBtn', 'closeAlert': true, 'onClick': thisAlert.options.onConfirm },
{ 'text': thisAlert.options.denyBtnText, 'theme': 'red', 'class': 'denyBtn', 'closeAlert': true, 'onClick': thisAlert.options.onDeny }
];
thisAlert.options.autofocus = thisAlert.options.confirmAutofocus;
}
/* Add theme class */
if( $.inArray(thisAlert.options.theme, themes) == -1 )
{
console.log('jAlert Config Error: Invalid theme selection.');
return false;
}
classes.push('ja_'+thisAlert.options.theme);
/* If they set custom classes */
if( thisAlert.options['class'] )
{
classes.push(thisAlert.options['class']);
}
if( thisAlert.options.classes )
{
classes.push(thisAlert.options.classes);
}
/* If no title, add class */
if( !thisAlert.options.title )
{
classes.push( 'ja_noTitle' );
}
/* if it's set and it's not in the array of sizes OR it's an object and it's missing width/height */
if( thisAlert.options.size && ((typeof thisAlert.options.size == 'string' && $.inArray(thisAlert.options.size, sizes) == -1) || (typeof thisAlert.options.size == 'object' && (typeof thisAlert.options.size.width == 'undefined' || typeof thisAlert.options.size.height == 'undefined'))) )
{
console.log('jAlert Config Error: Invalid size selection (try a preset or make sure you\'re including height and width in your size object).');
return false;
}
/* If it's not set, set to md */
else if( !thisAlert.options.size )
{
classes.push('ja_sm');
}
/* If it's set and it's an object */
else if( typeof thisAlert.options.size == 'object' )
{
styles.push('width: '+thisAlert.options.size.width+';');
styles.push('height: '+thisAlert.options.size.height+';');
}
/* If it's set and it's not an object */
else
{
classes.push('ja_'+thisAlert.options.size);
}
/* Add background color class */
if( $.inArray(thisAlert.options.backgroundColor, backgroundColors) == -1 )
{
console.log('jAlert Config Error: Invalid background color selection.');
return false;
}
backgroundClasses.push('ja_wrap_'+thisAlert.options.backgroundColor);
/* If there are button(s), then you obviously don't want to hide the div when you alert anywhere or they'll be useless...SAME with autofocus */
if( (typeof thisAlert.options.btns == 'object' || typeof thisAlert.options.btns == 'array') || thisAlert.options.autofocus ){
thisAlert.options.closeOnClick = false;
}
thisAlert.options.onOpen = [ thisAlert.options.onOpen ];
var onload = "onload='$.fn.jAlert.mediaLoaded($(this))'",
loader = "
Loading...
";
/* Creates content */
if( thisAlert.options.image )
{
thisAlert.options.content = "";
}
else if( thisAlert.options.video )
{
thisAlert.options.content = "";
/* Add to the onOpen callbacks array to append the iframe and attach the onload callback in a crossbrowser compatible way (IE is a bizitch). */
thisAlert.options.onOpen.unshift( function(alert){
var iframe = document.createElement("iframe");
iframe.src = thisAlert.options.video;
if(iframe.addEventListener)
{
iframe.addEventListener('load', function(){
$.fn.jAlert.mediaLoaded($(this));
}, true)
}
else if (iframe.attachEvent){
iframe.attachEvent("onload", function(){
$.fn.jAlert.mediaLoaded($(this));
});
} else {
iframe.onload = function(){
$.fn.jAlert.mediaLoaded($(this));
};
}
alert.find('.ja_video').append(iframe);
});
}
else if( thisAlert.options.iframe )
{
if( !thisAlert.options.iframeHeight )
{
thisAlert.options.iframeHeight = $(window).height() * 0.9+'px';
}
thisAlert.options.content = ""+
loader+
"
";
/* Add to the onOpen callbacks array to append the iframe and attach the onload callback in a crossbrowser compatible way (IE is a bizitch). */
thisAlert.options.onOpen.unshift( function(alert){
var iframe = document.createElement("iframe");
iframe.src = thisAlert.options.iframe;
iframe.height = thisAlert.options.iframeHeight;
iframe.className = 'ja_iframe';
if(iframe.addEventListener)
{
iframe.addEventListener('load', function(){
$.fn.jAlert.mediaLoaded($(this));
}, true)
}
else if (iframe.attachEvent){
iframe.attachEvent("onload", function(){
$.fn.jAlert.mediaLoaded($(this));
});
} else {
iframe.onload = function(){
$.fn.jAlert.mediaLoaded($(this));
};
}
alert.find('.ja_media_wrap').append(iframe);
});
}
else if( thisAlert.options.ajax )
{
thisAlert.options.content = ""+
loader+
"
";
/* Store as another var */
onAjaxCallbacks = thisAlert.options.onOpen;
/* Overwrite the onOpen to be the ajax call */
thisAlert.options.onOpen = [function(alert){
$.ajax(thisAlert.options.ajax, {
async: true,
complete: function(jqXHR, textStatus)
{
alert.find('.ja_media_wrap').replaceWith(jqXHR.responseText);
/* Run onOpen callbacks here */
$.each(onAjaxCallbacks, function(index, onAjax){
onAjax(alert);
});
},
error: function(jqXHR, textStatus, errorThrown)
{
thisAlert.options.onAjaxFail(alert, 'Error getting content: Code: '+jqXHR.status+ ' : Msg: '+jqXHR.statusText);
}
});
}];
}
this.centerAlert = function()
{
var viewportHeight = $(window).height(),
alertHeight = thisAlert.instance.height(),
diff = viewportHeight - alertHeight;
var top = diff / 2;
if( top > 200 )
{
top = top - 100;
}
if( top <= 0 )
{
top = 0;
}
thisAlert.instance.css('margin-top', top+'px');
$('body').css('overflow', 'hidden');
if( diff > 5 )
{
thisAlert.instance.parents('.ja_wrap').css('position', 'fixed');
}
else
{
thisAlert.instance.parents('.ja_wrap').css('position', 'absolute');
/* Scroll to alert */
$('html, body').animate({
scrollTop: top - 50
}, 200);
}
}
var animateAlert = function(which, thisAlert){
if( which == 'hide' )
{
thisAlert.removeClass($jAlertSelectedOpts[thisAlert.attr('id')].options.showAnimation).addClass($jAlertSelectedOpts[thisAlert.attr('id')].options.hideAnimation);
}
else
{
thisAlert.centerAlert();
thisAlert.addClass($jAlertSelectedOpts[thisAlert.attr('id')].options.showAnimation).removeClass($jAlertSelectedOpts[thisAlert.attr('id')].options.hideAnimation).show();
}
}
var getBtnHTML = function(btn){
if(typeof btn.href == 'undefined'){ btn.href = ''; }
if(typeof btn['class'] == 'undefined'){ btn['class'] = ''; }
if(typeof btn.theme == 'undefined'){ btn['class'] += ' ja_btn_default'; }else{ btn['class'] += ' ja_btn_'+btn.theme; }
if(typeof btn.text == 'undefined'){ btn.text = ''; }
if(typeof btn.id == 'undefined'){ var unique = Date.now().toString() + Math.floor(Math.random() * 100000); btn.id = 'ja_btn_' + unique; }
if(typeof btn.target == 'undefined'){ btn.target = '_self'; }
if(typeof btn.closeAlert == 'undefined'){ btn.closeAlert = true; }
/* Attach on click handler */
$('body').on('click', '#'+btn.id, function(e){
var button = $(this);
if( btn.closeAlert )
{
button.parents('.jAlert').closeAlert();
}
var callbackResponse = true;
if( typeof btn.onClick == 'function' )
{
callbackResponse = btn.onClick(e, button);
}
if( !callbackResponse || btn.closeAlert )
{
e.preventDefault();
return false;
}
return callbackResponse;
});
return ""+btn.text+" ";
}
/* Hides an alert and optionally removes it */
this.closeAlert = function(remove, onClose){
var alertInstance = $(this);
if( remove != false )
{
remove = true;
}
if(alertInstance.length)
{
alertInstance.unbind('DOMSubtreeModified');
animateAlert('hide', alertInstance);
window.setTimeout(function()
{
var alertWrap = alertInstance.parents('.ja_wrap');
if( remove )
{
alertWrap.remove();
}
else
{
alertWrap.hide();
}
if(typeof onClose == 'function')
{
onClose(alertInstance);
}
else if(typeof $jAlertSelectedOpts[alertInstance.attr('id')].options.onClose == 'function')
{
$jAlertSelectedOpts[alertInstance.attr('id')].options.onClose(alertInstance);
}
if( $('.jAlert').length > 0 )
{
$('.jAlert:last').centerAlert();
}
else
{
$('body').css('overflow', 'auto');
}
}, $jAlertSelectedOpts[alertInstance.attr('id')].options.animationTimeout);
}
return this;
}
/* Shows an alert that already exists */
this.showAlert = function(replaceOthers, removeOthers, onOpen, onClose){
var alertInstance = $(this);
if( replaceOthers != false )
{
replaceOthers = true;
}
if( removeOthers !== false )
{
removeOthers = true;
}
if( replaceOthers )
{
$('.jAlert:visible').closeAlert(removeOthers);
}
/* Put this one above the last one by moving to end of dom */
var wrap = alertInstance.parents('.ja_wrap');
$('body').append(wrap);
animateAlert('show', alertInstance);
if( typeof onClose == 'function' )
{
$jAlertSelectedOpts[alertInstance.attr('id')].options.onClose = onClose;
}
window.setTimeout(function(){
if(typeof onOpen == 'function')
{
onOpen(alertInstance);
}
}, $jAlertSelectedOpts[alertInstance.attr('id')].options.animationTimeout);
}
/* Adds a new alert to the dom */
var addAlert = function(content){
var html = '';
html += ''+
'
'+
'
';
if( thisAlert.options.closeBtn )
{
html += "
X
"; //closejAlert has a close handler attached, ja_close is for styling
}
if( thisAlert.options.title )
{
html += "
"+thisAlert.options.title+"
";
}
html += '
'+content;
if( thisAlert.options.btns )
{
html += '
';
}
if( typeof thisAlert.options.btns[0] == 'object' )
{
$.each(thisAlert.options.btns, function(index, btn){
if( typeof btn == 'object' )
{
html += getBtnHTML(btn);
}
});
}
else if( typeof thisAlert.options.btns == 'object' )
{
html += getBtnHTML(thisAlert.options.btns);
}
else if( thisAlert.options.btns )
{
console.log('jAlert Config Error: Incorrect value for btns (must be object or array of objects): '+thisAlert.options.btns);
}
if( thisAlert.options.btns )
{
html += '
';
}
html += '
'+
'
'+
'
'+
'
';
var alertHTML = $(html);
if( thisAlert.options.replaceOtherAlerts )
{
$('.jAlert:visible').closeAlert();
}
$('body').append(alertHTML);
thisAlert.instance = $('#'+thisAlert.options.id);
animateAlert('show', thisAlert.instance);
if( thisAlert.options.closeBtn ){
thisAlert.instance.on('click', '.closejAlert', function(e){
e.preventDefault();
$(this).parents('.jAlert').closeAlert();
return false;
});
}
/* Bind mouseup handler to document if this alert has closeOnClick enabled */
if( thisAlert.options.closeOnClick ){
/* Unbind if already exists */
$(document).off('mouseup', $.fn.jAlert.onMouseUp);
/* Bind mouseup */
$(document).on('mouseup', $.fn.jAlert.onMouseUp);
}
/* Bind on keydown handler to document and if esc was pressed, find all visible jAlerts with that close option enabled and close them */
if( thisAlert.options.closeOnEsc ){
/* Unbind if already exists */
$(document).off('keydown', $.fn.jAlert.onEscKeyDown);
/* Bind keydown */
$(document).on('keydown', $.fn.jAlert.onEscKeyDown);
}
/* If there are onOpen callbacks, run them. */
if( thisAlert.options.onOpen )
{
$.each(thisAlert.options.onOpen, function(index, onOpen){
onOpen(thisAlert.instance);
});
}
/* If the alert has an element that should be focused by default */
if( thisAlert.options.autofocus )
{
thisAlert.instance.find(thisAlert.options.autofocus).focus();
}
else
{
thisAlert.instance.focus();
}
thisAlert.instance.bind("DOMSubtreeModified", function(){
thisAlert.instance.centerAlert();
});
return thisAlert.instance;
};
/* Shows an alert based on content type */
this.initialize = function(){
if( !thisAlert.options.content && !thisAlert.options.image && !thisAlert.options.video && !thisAlert.options.iframe && !thisAlert.options.ajax )
{
console.log('jAlert potential error: No content defined');
return addAlert('');
}
else
{
if( !thisAlert.options.content )
{
thisAlert.options.content = '';
}
return addAlert(thisAlert.options.content);
}
}
this.initialize();
return this;
/* END OF PLUGIN */
};
/* Default thisAlert.options */
$.fn.jAlert.defaults = {
'title': false, //title for the popup (false = don't show)
'content': false, //html for the popup (replaced if you use image, ajax, or iframe)
'image': false, //adds a centered img tag
'imageWidth': 'auto', //defaults to max-width: 100%; width: auto;
'video': false, //adds a responsive iframe video - value is the "src" of the iframe
'ajax': false, //uses ajax call to get contents
'onAjaxFail': function(alert, errorThrown){ //callback for when ajax fails
thisAlert.closeAlert();
errorAlert(errorThrown);
},
'iframe': false, //uses iframe as content
'iframeHeight': false, //string. height of the iframe within the popup (false = 90% of viewport height)
'class': '', //adds a class to the jAlert (add as many as you want space delimited)
'classes': '', //add classes to the jAlert (space delimited)
'id': false, //adds an ID to the jAlert
'showAnimation': 'fadeInUp',
'hideAnimation': 'fadeOutDown',
'animationTimeout': 600, //approx duration of animation to wait until onClose
'theme': 'default', // red, green, blue, black, default
'backgroundColor': 'black', //white, black
'size': false, //false = css default, xsm, sm, md, lg, xlg, full, { height: 200, width: 200 }
'replaceOtherAlerts': false, //if there's already an open jAlert, remove it first
'closeOnClick': false, //close the alert when you click anywhere
'closeOnEsc': true, //close the alert when you click the escape key
'closeBtn': true, //adds a button to the top right of the alert that allows you to close it
'closeBtnAlt': false, //alternative close button
'btns': false, //adds buttons to the popup at the bottom. Pass an object for a single button, or an object of objects for many
/*
Variety of buttons you could create (also, an example of how to pass the object
'btns': [
{'text':'Open in new window', 'closeAlert':false, 'href': 'http://google.com', 'target':'_new'},
{'text':'Cool, close this alert', 'theme': 'blue', 'closeAlert':true},
{'text':'Buy Now', 'closeAlert':true, 'theme': 'green', 'onClick': function(){ console.log('You bought it!'); } },
{'text':'I do not want it', 'closeAlert': true, 'theme': 'red', 'onClick': function(){ console.log('Did not want it'); } },
{'text':'DOA', 'closeAlert': true, 'theme': 'black', 'onClick': function(){ console.log('Dead on arrival'); } }
]
*/
'btnBackground': true, //adds optional background to btns
'autofocus': false, //pass a selector to autofocus on it
'onOpen': function(alert){ //on open call back. Fires just after the alert has finished rendering
return false;
},
'onClose': function(alert){ //fires when you close the alert
return false;
},
'type': 'modal', //modal, confirm, tooltip
/* The following only applies when type == 'confirm' */
'confirmQuestion': 'Esta seguro?',
'confirmBtnText': 'Si',
'denyBtnText': 'No',
'confirmAutofocus': '.confirmBtn', //confirmBtn or denyBtn
'onConfirm': function(e, btn){
e.preventDefault();
console.log('confirmed');
return false;
},
'onDeny': function(e, btn){
e.preventDefault();
//console.log('denied');
return false;
}
}
/* Mouseup on document */
$.fn.jAlert.onMouseUp = function(e){
/* Find top visible jAlert and see if it has closeOnClick enabled */
var lastVisibleAlert = $('.jAlert:visible:last');
if( $jAlertSelectedOpts[lastVisibleAlert.attr('id')].options.closeOnClick )
{
lastVisibleAlert.closeAlert();
}
};
/* Keydown on document (escape key) */
$.fn.jAlert.onEscKeyDown = function(e){
/* Escape = 27 */
if(e.keyCode === 27){
/* Find top visible jAlert and see if it has closeOnClick enabled */
var lastVisibleAlert = $('.jAlert:visible:last');
if( $jAlertSelectedOpts[lastVisibleAlert.attr('id')].options.closeOnEsc )
{
lastVisibleAlert.closeAlert();
}
}
};
/* If you're not using the DOM (aka, you're not hiding or showing a specific alert, you can just use $.jAlert */
$.jAlert = function(options){
return $.fn.jAlert(options);
}
/* Alert on click function - attach to existing dom */
$.fn.alertOnClick = function(options)
{
$(this).on('click', function(e){
e.preventDefault();
$.jAlert(options);
return false;
});
}
/* Alert on click function - global, works for changing dom */
$.alertOnClick = function(selector, options)
{
$('body').on('click', selector, function(e){
e.preventDefault();
$.jAlert(options);
return false;
});
}
/* Slowed window resize function */
var $jAlertResizeTimeout;
$(window).resize(function () {
window.clearTimeout($jAlertResizeTimeout);
$jAlertResizeTimeout = window.setTimeout(function(){
$('.jAlert:visible').each(function(){
$(this).centerAlert();
});
}, 200);
});
/* Onload callback for iframe, img, etc */
$.fn.jAlert.mediaLoaded = function(elem){
var wrap = elem.parents('.ja_media_wrap'),
vid_wrap = wrap.find('.ja_video');
wrap.find('.ja_loader').remove();
if( vid_wrap.length > 0 )
{
vid_wrap.fadeIn('fast');
}
else
{
elem.fadeIn('fast');
}
elem.parents('.jAlert').centerAlert();
}
/* END OF ON JQUERY LOAD */
})(jQuery);