JAVASCRIPT 29
Alertify.js Guest on 25th April 2021 07:49:08 AM
  1. /**
  2.  * alertifyjs 1.9.0 http://alertifyjs.com
  3.  * AlertifyJS is a javascript framework for developing pretty browser dialogs and notifications.
  4.  * Copyright Mohammad Younes <Mohammad@alertifyjs.com> (http://alertifyjs.com)
  5.  * Licensed under GPL 3 <https://opensource.org/licenses/gpl-3.0>*/
  6. ( function ( window ) {
  7.     'use strict';
  8.    
  9.     /**
  10.      * Keys enum
  11.      * @type {Object}
  12.      */
  13.     var keys = {
  14.         ENTER: 13,
  15.         ESC: 27,
  16.         F1: 112,
  17.         F12: 123,
  18.         LEFT: 37,
  19.         RIGHT: 39
  20.     };
  21.     /**
  22.      * Default options
  23.      * @type {Object}
  24.      */
  25.     var defaults = {
  26.         autoReset:true,
  27.         basic:false,
  28.         closable:true,
  29.         closableByDimmer:true,
  30.         frameless:false,
  31.         maintainFocus:true, //global default not per instance, applies to all dialogs
  32.         maximizable:true,
  33.         modal:true,
  34.         movable:true,
  35.         moveBounded:false,
  36.         overflow:true,
  37.         padding: true,
  38.         pinnable:true,
  39.         pinned:true,
  40.         preventBodyShift:false, //global default not per instance, applies to all dialogs
  41.         resizable:true,
  42.         startMaximized:false,
  43.         transition:'pulse',
  44.         notifier:{
  45.             delay:5,
  46.             position:'bottom-right',
  47.             closeButton:false
  48.         },
  49.         glossary:{
  50.             title:'AlertifyJS',
  51.             ok: 'OK',
  52.             cancel: 'Cancel',
  53.             acccpt: 'Accept',
  54.             deny: 'Deny',
  55.             confirm: 'Confirm',
  56.             decline: 'Decline',
  57.             close: 'Close',
  58.             maximize: 'Maximize',
  59.             restore: 'Restore',
  60.         },
  61.         theme:{
  62.             input:'ajs-input',
  63.             ok:'ajs-ok',
  64.             cancel:'ajs-cancel',
  65.         }
  66.     };
  67.    
  68.     //holds open dialogs instances
  69.     var openDialogs = [];
  70.  
  71.     /**
  72.      * [Helper]  Adds the specified class(es) to the element.
  73.      *
  74.      * @element {node}      The element
  75.      * @className {string}  One or more space-separated classes to be added to the class attribute of the element.
  76.      *
  77.      * @return {undefined}
  78.      */
  79.     function addClass(element,classNames){
  80.         element.className += ' ' + classNames;
  81.     }
  82.    
  83.     /**
  84.      * [Helper]  Removes the specified class(es) from the element.
  85.      *
  86.      * @element {node}      The element
  87.      * @className {string}  One or more space-separated classes to be removed from the class attribute of the element.
  88.      *
  89.      * @return {undefined}
  90.      */
  91.     function removeClass(element, classNames) {
  92.         var original = element.className.split(' ');
  93.         var toBeRemoved = classNames.split(' ');
  94.         for (var x = 0; x < toBeRemoved.length; x += 1) {
  95.             var index = original.indexOf(toBeRemoved[x]);
  96.             if (index > -1){
  97.                 original.splice(index,1);
  98.             }
  99.         }
  100.         element.className = original.join(' ');
  101.     }
  102.  
  103.     /**
  104.      * [Helper]  Checks if the document is RTL
  105.      *
  106.      * @return {Boolean} True if the document is RTL, false otherwise.
  107.      */
  108.     function isRightToLeft(){
  109.         return window.getComputedStyle(document.body).direction === 'rtl';
  110.     }
  111.     /**
  112.      * [Helper]  Get the document current scrollTop
  113.      *
  114.      * @return {Number} current document scrollTop value
  115.      */
  116.     function getScrollTop(){
  117.         return ((document.documentElement && document.documentElement.scrollTop) || document.body.scrollTop);
  118.     }
  119.  
  120.     /**
  121.      * [Helper]  Get the document current scrollLeft
  122.      *
  123.      * @return {Number} current document scrollLeft value
  124.      */
  125.     function getScrollLeft(){
  126.         return ((document.documentElement && document.documentElement.scrollLeft) || document.body.scrollLeft);
  127.     }
  128.  
  129.     /**
  130.     * Helper: clear contents
  131.     *
  132.     */
  133.     function clearContents(element){
  134.         while (element.lastChild) {
  135.             element.removeChild(element.lastChild);
  136.         }
  137.     }
  138.     /**
  139.      * Extends a given prototype by merging properties from base into sub.
  140.      *
  141.      * @sub {Object} sub The prototype being overwritten.
  142.      * @base {Object} base The prototype being written.
  143.      *
  144.      * @return {Object} The extended prototype.
  145.      */
  146.     function copy(src) {
  147.         if(null === src){
  148.             return src;
  149.         }
  150.         var cpy;
  151.         if(Array.isArray(src)){
  152.             cpy = [];
  153.             for(var x=0;x<src.length;x+=1){
  154.                 cpy.push(copy(src[x]));
  155.             }
  156.             return cpy;
  157.         }
  158.      
  159.         if(src instanceof Date){
  160.             return new Date(src.getTime());
  161.         }
  162.      
  163.         if(src instanceof RegExp){
  164.             cpy = new RegExp(src.source);
  165.             cpy.global = src.global;
  166.             cpy.ignoreCase = src.ignoreCase;
  167.             cpy.multiline = src.multiline;
  168.             cpy.lastIndex = src.lastIndex;
  169.             return cpy;
  170.         }
  171.        
  172.         if(typeof src === 'object'){
  173.             cpy = {};
  174.             // copy dialog pototype over definition.
  175.             for (var prop in src) {
  176.                 if (src.hasOwnProperty(prop)) {
  177.                     cpy[prop] = copy(src[prop]);
  178.                 }
  179.             }
  180.             return cpy;
  181.         }
  182.         return src;
  183.     }
  184.     /**
  185.       * Helper: destruct the dialog
  186.       *
  187.       */
  188.     function destruct(instance, initialize){
  189.         //delete the dom and it's references.
  190.         var root = instance.elements.root;
  191.         root.parentNode.removeChild(root);
  192.         delete instance.elements;
  193.         //copy back initial settings.
  194.         instance.settings = copy(instance.__settings);
  195.         //re-reference init function.
  196.         instance.__init = initialize;
  197.         //delete __internal variable to allow re-initialization.
  198.         delete instance.__internal;
  199.     }
  200.  
  201.     /**
  202.      * Use a closure to return proper event listener method. Try to use
  203.      * `addEventListener` by default but fallback to `attachEvent` for
  204.      * unsupported browser. The closure simply ensures that the test doesn't
  205.      * happen every time the method is called.
  206.      *
  207.      * @param    {Node}     el    Node element
  208.      * @param    {String}   event Event type
  209.      * @param    {Function} fn    Callback of event
  210.      * @return   {Function}
  211.      */
  212.     var on = (function () {
  213.         if (document.addEventListener) {
  214.             return function (el, event, fn, useCapture) {
  215.                 el.addEventListener(event, fn, useCapture === true);
  216.             };
  217.         } else if (document.attachEvent) {
  218.             return function (el, event, fn) {
  219.                 el.attachEvent('on' + event, fn);
  220.             };
  221.         }
  222.     }());
  223.  
  224.     /**
  225.      * Use a closure to return proper event listener method. Try to use
  226.      * `removeEventListener` by default but fallback to `detachEvent` for
  227.      * unsupported browser. The closure simply ensures that the test doesn't
  228.      * happen every time the method is called.
  229.      *
  230.      * @param    {Node}     el    Node element
  231.      * @param    {String}   event Event type
  232.      * @param    {Function} fn    Callback of event
  233.      * @return   {Function}
  234.      */
  235.     var off = (function () {
  236.         if (document.removeEventListener) {
  237.             return function (el, event, fn, useCapture) {
  238.                 el.removeEventListener(event, fn, useCapture === true);
  239.             };
  240.         } else if (document.detachEvent) {
  241.             return function (el, event, fn) {
  242.                 el.detachEvent('on' + event, fn);
  243.             };
  244.         }
  245.     }());
  246.  
  247.     /**
  248.      * Prevent default event from firing
  249.      *
  250.      * @param  {Event} event Event object
  251.      * @return {undefined}
  252.  
  253.     function prevent ( event ) {
  254.         if ( event ) {
  255.             if ( event.preventDefault ) {
  256.                 event.preventDefault();
  257.             } else {
  258.                 event.returnValue = false;
  259.             }
  260.         }
  261.     }
  262.     */
  263.     var transition = (function () {
  264.         var t, type;
  265.         var supported = false;
  266.         var transitions = {
  267.             'animation'        : 'animationend',
  268.             'OAnimation'       : 'oAnimationEnd oanimationend',
  269.             'msAnimation'      : 'MSAnimationEnd',
  270.             'MozAnimation'     : 'animationend',
  271.             'WebkitAnimation'  : 'webkitAnimationEnd'
  272.         };
  273.  
  274.         for (t in transitions) {
  275.             if (document.documentElement.style[t] !== undefined) {
  276.                 type = transitions[t];
  277.                 supported = true;
  278.                 break;
  279.             }
  280.         }
  281.  
  282.         return {
  283.             type: type,
  284.             supported: supported
  285.         };
  286.     }());
  287.  
  288.     /**
  289.     * Creates event handler delegate that sends the instance as last argument.
  290.     *
  291.     * @return {Function}    a function wrapper which sends the instance as last argument.
  292.     */
  293.     function delegate(context, method) {
  294.         return function () {
  295.             if (arguments.length > 0) {
  296.                 var args = [];
  297.                 for (var x = 0; x < arguments.length; x += 1) {
  298.                     args.push(arguments[x]);
  299.                 }
  300.                 args.push(context);
  301.                 return method.apply(context, args);
  302.             }
  303.             return method.apply(context, [null, context]);
  304.         };
  305.     }
  306.     /**
  307.     * Helper for creating a dialog close event.
  308.     *
  309.     * @return {object}
  310.     */
  311.     function createCloseEvent(index, button) {
  312.         return {
  313.             index: index,
  314.             button: button,
  315.             cancel: false
  316.         };
  317.     }
  318.     /**
  319.     * Helper for dispatching events.
  320.     *
  321.     * @param  {string} evenType The type of the event to disptach.
  322.     * @param  {object} instance The dialog instance disptaching the event.
  323.     *
  324.     * @return {object}
  325.     */
  326.     function dispatchEvent(eventType, instance) {
  327.         if ( typeof instance.get(eventType) === 'function' ) {
  328.             instance.get(eventType).call(instance);
  329.         }
  330.     }
  331.  
  332.  
  333.     /**
  334.      * Super class for all dialogs
  335.      *
  336.      * @return {Object}       base dialog prototype
  337.      */
  338.     var dialog = (function () {
  339.         var //holds the list of used keys.
  340.             usedKeys = [],
  341.             //dummy variable, used to trigger dom reflow.
  342.             reflow = null,
  343.             //condition for detecting safari
  344.             isSafari = window.navigator.userAgent.indexOf('Safari') > -1 && window.navigator.userAgent.indexOf('Chrome') < 0,
  345.             //dialog building blocks
  346.             templates = {
  347.                 dimmer:'<div class="ajs-dimmer"></div>',
  348.                 /*tab index required to fire click event before body focus*/
  349.                 modal: '<div class="ajs-modal" tabindex="0"></div>',
  350.                 dialog: '<div class="ajs-dialog" tabindex="0"></div>',
  351.                 reset: '<button class="ajs-reset"></button>',
  352.                 commands: '<div class="ajs-commands"><button class="ajs-pin"></button><button class="ajs-maximize"></button><button class="ajs-close"></button></div>',
  353.                 header: '<div class="ajs-header"></div>',
  354.                 body: '<div class="ajs-body"></div>',
  355.                 content: '<div class="ajs-content"></div>',
  356.                 footer: '<div class="ajs-footer"></div>',
  357.                 buttons: { primary: '<div class="ajs-primary ajs-buttons"></div>', auxiliary: '<div class="ajs-auxiliary ajs-buttons"></div>' },
  358.                 button: '<button class="ajs-button"></button>',
  359.                 resizeHandle: '<div class="ajs-handle"></div>',
  360.             },
  361.             //common class names
  362.             classes = {
  363.                 animationIn: 'ajs-in',
  364.                 animationOut: 'ajs-out',
  365.                 base: 'alertify',
  366.                 basic:'ajs-basic',
  367.                 capture: 'ajs-capture',
  368.                 closable:'ajs-closable',
  369.                 fixed: 'ajs-fixed',
  370.                 frameless:'ajs-frameless',
  371.                 hidden: 'ajs-hidden',
  372.                 maximize: 'ajs-maximize',
  373.                 maximized: 'ajs-maximized',
  374.                 maximizable:'ajs-maximizable',
  375.                 modeless: 'ajs-modeless',
  376.                 movable: 'ajs-movable',
  377.                 noSelection: 'ajs-no-selection',
  378.                 noOverflow: 'ajs-no-overflow',
  379.                 noPadding:'ajs-no-padding',
  380.                 pin:'ajs-pin',
  381.                 pinnable:'ajs-pinnable',
  382.                 prefix: 'ajs-',
  383.                 resizable: 'ajs-resizable',
  384.                 restore: 'ajs-restore',
  385.                 shake:'ajs-shake',
  386.                 unpinned:'ajs-unpinned',
  387.             };
  388.  
  389.         /**
  390.          * Helper: initializes the dialog instance
  391.          *
  392.          * @return      {Number}    The total count of currently open modals.
  393.          */
  394.         function initialize(instance){
  395.            
  396.             if(!instance.__internal){
  397.  
  398.                 //no need to expose init after this.
  399.                 delete instance.__init;
  400.              
  401.                 //keep a copy of initial dialog settings
  402.                 if(!instance.__settings){
  403.                     instance.__settings = copy(instance.settings);
  404.                 }
  405.                 //in case the script was included before body.
  406.                 //after first dialog gets initialized, it won't be null anymore!
  407.                 if(null === reflow){
  408.                     // set tabindex attribute on body element this allows script to give it
  409.                     // focus after the dialog is closed
  410.                     document.body.setAttribute( 'tabindex', '0' );
  411.                 }
  412.  
  413.                 //get dialog buttons/focus setup
  414.                 var setup;
  415.                 if(typeof instance.setup === 'function'){
  416.                     setup = instance.setup();
  417.                     setup.options = setup.options  || {};
  418.                     setup.focus = setup.focus  || {};
  419.                 }else{
  420.                     setup = {
  421.                         buttons:[],
  422.                         focus:{
  423.                             element:null,
  424.                             select:false
  425.                         },
  426.                         options:{
  427.                         }
  428.                     };
  429.                 }
  430.                
  431.                 //initialize hooks object.
  432.                 if(typeof instance.hooks !== 'object'){
  433.                     instance.hooks = {};
  434.                 }
  435.  
  436.                 //copy buttons defintion
  437.                 var buttonsDefinition = [];
  438.                 if(Array.isArray(setup.buttons)){
  439.                     for(var b=0;b<setup.buttons.length;b+=1){
  440.                         var ref  = setup.buttons[b],
  441.                             cpy = {};
  442.                         for (var i in ref) {
  443.                             if (ref.hasOwnProperty(i)) {
  444.                                 cpy[i] = ref[i];
  445.                             }
  446.                         }
  447.                         buttonsDefinition.push(cpy);
  448.                     }
  449.                 }
  450.  
  451.                 var internal = instance.__internal = {
  452.                     /**
  453.                      * Flag holding the open state of the dialog
  454.                      *
  455.                      * @type {Boolean}
  456.                      */
  457.                     isOpen:false,
  458.                     /**
  459.                      * Active element is the element that will receive focus after
  460.                      * closing the dialog. It defaults as the body tag, but gets updated
  461.                      * to the last focused element before the dialog was opened.
  462.                      *
  463.                      * @type {Node}
  464.                      */
  465.                     activeElement:document.body,
  466.                     timerIn:undefined,
  467.                     timerOut:undefined,
  468.                     buttons: buttonsDefinition,
  469.                     focus: setup.focus,
  470.                     options: {
  471.                         title: undefined,
  472.                         modal: undefined,
  473.                         basic:undefined,
  474.                         frameless:undefined,
  475.                         pinned: undefined,
  476.                         movable: undefined,
  477.                         moveBounded:undefined,
  478.                         resizable: undefined,
  479.                         autoReset: undefined,
  480.                         closable: undefined,
  481.                         closableByDimmer: undefined,
  482.                         maximizable: undefined,
  483.                         startMaximized: undefined,
  484.                         pinnable: undefined,
  485.                         transition: undefined,
  486.                         padding:undefined,
  487.                         overflow:undefined,
  488.                         onshow:undefined,
  489.                         onclose:undefined,
  490.                         onfocus:undefined,
  491.                         onmove:undefined,
  492.                         onmoved:undefined,
  493.                         onresize:undefined,
  494.                         onresized:undefined,
  495.                         onmaximize:undefined,
  496.                         onmaximized:undefined,
  497.                         onrestore:undefined,
  498.                         onrestored:undefined
  499.                     },
  500.                     resetHandler:undefined,
  501.                     beginMoveHandler:undefined,
  502.                     beginResizeHandler:undefined,
  503.                     bringToFrontHandler:undefined,
  504.                     modalClickHandler:undefined,
  505.                     buttonsClickHandler:undefined,
  506.                     commandsClickHandler:undefined,
  507.                     transitionInHandler:undefined,
  508.                     transitionOutHandler:undefined,
  509.                     destroy:undefined
  510.                 };
  511.  
  512.                 var elements = {};
  513.                 //root node
  514.                 elements.root = document.createElement('div');
  515.                
  516.                 elements.root.className = classes.base + ' ' + classes.hidden + ' ';
  517.  
  518.                 elements.root.innerHTML = templates.dimmer + templates.modal;
  519.                
  520.                 //dimmer
  521.                 elements.dimmer = elements.root.firstChild;
  522.  
  523.                 //dialog
  524.                 elements.modal = elements.root.lastChild;
  525.                 elements.modal.innerHTML = templates.dialog;
  526.                 elements.dialog = elements.modal.firstChild;
  527.                 elements.dialog.innerHTML = templates.reset + templates.commands + templates.header + templates.body + templates.footer + templates.resizeHandle + templates.reset;
  528.  
  529.                 //reset links
  530.                 elements.reset = [];
  531.                 elements.reset.push(elements.dialog.firstChild);
  532.                 elements.reset.push(elements.dialog.lastChild);
  533.                
  534.                 //commands
  535.                 elements.commands = {};
  536.                 elements.commands.container = elements.reset[0].nextSibling;
  537.                 elements.commands.pin = elements.commands.container.firstChild;
  538.                 elements.commands.maximize = elements.commands.pin.nextSibling;
  539.                 elements.commands.close = elements.commands.maximize.nextSibling;
  540.                
  541.                 //header
  542.                 elements.header = elements.commands.container.nextSibling;
  543.  
  544.                 //body
  545.                 elements.body = elements.header.nextSibling;
  546.                 elements.body.innerHTML = templates.content;
  547.                 elements.content = elements.body.firstChild;
  548.  
  549.                 //footer
  550.                 elements.footer = elements.body.nextSibling;
  551.                 elements.footer.innerHTML = templates.buttons.auxiliary + templates.buttons.primary;
  552.                
  553.                 //resize handle
  554.                 elements.resizeHandle = elements.footer.nextSibling;
  555.  
  556.                 //buttons
  557.                 elements.buttons = {};
  558.                 elements.buttons.auxiliary = elements.footer.firstChild;
  559.                 elements.buttons.primary = elements.buttons.auxiliary.nextSibling;
  560.                 elements.buttons.primary.innerHTML = templates.button;
  561.                 elements.buttonTemplate = elements.buttons.primary.firstChild;
  562.                 //remove button template
  563.                 elements.buttons.primary.removeChild(elements.buttonTemplate);
  564.                                
  565.                 for(var x=0; x < instance.__internal.buttons.length; x+=1) {
  566.                     var button = instance.__internal.buttons[x];
  567.                    
  568.                     // add to the list of used keys.
  569.                     if(usedKeys.indexOf(button.key) < 0){
  570.                         usedKeys.push(button.key);
  571.                     }
  572.  
  573.                     button.element = elements.buttonTemplate.cloneNode();
  574.                     button.element.innerHTML = button.text;
  575.                     if(typeof button.className === 'string' &&  button.className !== ''){
  576.                         addClass(button.element, button.className);
  577.                     }
  578.                     for(var key in button.attrs){
  579.                         if(key !== 'className' && button.attrs.hasOwnProperty(key)){
  580.                             button.element.setAttribute(key, button.attrs[key]);
  581.                         }
  582.                     }
  583.                     if(button.scope === 'auxiliary'){
  584.                         elements.buttons.auxiliary.appendChild(button.element);
  585.                     }else{
  586.                         elements.buttons.primary.appendChild(button.element);
  587.                     }
  588.                 }
  589.                 //make elements pubic
  590.                 instance.elements = elements;
  591.                
  592.                 //save event handlers delegates
  593.                 internal.resetHandler = delegate(instance, onReset);
  594.                 internal.beginMoveHandler = delegate(instance, beginMove);
  595.                 internal.beginResizeHandler = delegate(instance, beginResize);
  596.                 internal.bringToFrontHandler = delegate(instance, bringToFront);
  597.                 internal.modalClickHandler = delegate(instance, modalClickHandler);
  598.                 internal.buttonsClickHandler = delegate(instance, buttonsClickHandler);
  599.                 internal.commandsClickHandler = delegate(instance, commandsClickHandler);
  600.                 internal.transitionInHandler = delegate(instance, handleTransitionInEvent);
  601.                 internal.transitionOutHandler = delegate(instance, handleTransitionOutEvent);
  602.  
  603.                 //settings
  604.                 for(var opKey in internal.options){
  605.                     if(setup.options[opKey] !== undefined){
  606.                         // if found in user options
  607.                         instance.set(opKey, setup.options[opKey]);
  608.                     }else if(alertify.defaults.hasOwnProperty(opKey)) {
  609.                         // else if found in defaults options
  610.                         instance.set(opKey, alertify.defaults[opKey]);
  611.                     }else if(opKey === 'title' ) {
  612.                         // else if title key, use alertify.defaults.glossary
  613.                         instance.set(opKey, alertify.defaults.glossary[opKey]);
  614.                     }
  615.                 }
  616.  
  617.                 // allow dom customization
  618.                 if(typeof instance.build === 'function'){
  619.                     instance.build();
  620.                 }
  621.             }
  622.            
  623.             //add to the end of the DOM tree.
  624.             document.body.appendChild(instance.elements.root);
  625.         }
  626.  
  627.         /**
  628.          * Helper: maintains scroll position
  629.          *
  630.          */
  631.         var scrollX, scrollY;
  632.         function saveScrollPosition(){
  633.             scrollX = getScrollLeft();
  634.             scrollY = getScrollTop();
  635.         }
  636.         function restoreScrollPosition(){
  637.             window.scrollTo(scrollX, scrollY);
  638.         }
  639.  
  640.         /**
  641.          * Helper: adds/removes no-overflow class from body
  642.          *
  643.          */
  644.         function ensureNoOverflow(){
  645.             var requiresNoOverflow = 0;
  646.             for(var x=0;x<openDialogs.length;x+=1){
  647.                 var instance = openDialogs[x];
  648.                 if(instance.isModal() || instance.isMaximized()){
  649.                     requiresNoOverflow+=1;
  650.                 }
  651.             }
  652.             if(requiresNoOverflow === 0 && document.body.className.indexOf(classes.noOverflow) >= 0){
  653.                 //last open modal or last maximized one
  654.                 removeClass(document.body, classes.noOverflow);
  655.                 preventBodyShift(false);
  656.             }else if(requiresNoOverflow > 0 && document.body.className.indexOf(classes.noOverflow) < 0){
  657.                 //first open modal or first maximized one
  658.                 preventBodyShift(true);
  659.                 addClass(document.body, classes.noOverflow);
  660.             }
  661.         }
  662.         var top = '', topScroll = 0;
  663.         /**
  664.          * Helper: prevents body shift.
  665.          *
  666.          */
  667.         function preventBodyShift(add){
  668.             if(alertify.defaults.preventBodyShift && document.documentElement.scrollHeight > document.documentElement.clientHeight){
  669.                 if(add ){//&& openDialogs[openDialogs.length-1].elements.dialog.clientHeight <= document.documentElement.clientHeight){
  670.                     topScroll = scrollY;
  671.                     top = window.getComputedStyle(document.body).top;
  672.                     addClass(document.body, classes.fixed);
  673.                     document.body.style.top = -scrollY + 'px';
  674.                 } else {
  675.                     scrollY = topScroll;
  676.                     document.body.style.top = top;
  677.                     removeClass(document.body, classes.fixed);
  678.                     restoreScrollPosition();
  679.                 }
  680.             }
  681.         }
  682.            
  683.         /**
  684.          * Sets the name of the transition used to show/hide the dialog
  685.          *
  686.          * @param {Object} instance The dilog instance.
  687.          *
  688.          */
  689.         function updateTransition(instance, value, oldValue){
  690.             if(typeof oldValue === 'string'){
  691.                 removeClass(instance.elements.root,classes.prefix +  oldValue);
  692.             }
  693.             addClass(instance.elements.root, classes.prefix + value);
  694.             reflow = instance.elements.root.offsetWidth;
  695.         }
  696.            
  697.         /**
  698.          * Toggles the dialog display mode
  699.          *
  700.          * @param {Object} instance The dilog instance.
  701.          *
  702.          * @return {undefined}
  703.          */
  704.         function updateDisplayMode(instance){
  705.             if(instance.get('modal')){
  706.  
  707.                 //make modal
  708.                 removeClass(instance.elements.root, classes.modeless);
  709.  
  710.                 //only if open
  711.                 if(instance.isOpen()){
  712.                     unbindModelessEvents(instance);
  713.  
  714.                     //in case a pinned modless dialog was made modal while open.
  715.                     updateAbsPositionFix(instance);
  716.  
  717.                     ensureNoOverflow();
  718.                 }
  719.             }else{
  720.                 //make modelss
  721.                 addClass(instance.elements.root, classes.modeless);
  722.  
  723.                 //only if open
  724.                 if(instance.isOpen()){
  725.                     bindModelessEvents(instance);
  726.  
  727.                     //in case pin/unpin was called while a modal is open
  728.                     updateAbsPositionFix(instance);
  729.  
  730.                     ensureNoOverflow();
  731.                 }
  732.             }
  733.         }
  734.  
  735.         /**
  736.          * Toggles the dialog basic view mode
  737.          *
  738.          * @param {Object} instance The dilog instance.
  739.          *
  740.          * @return {undefined}
  741.          */
  742.         function updateBasicMode(instance){
  743.             if (instance.get('basic')) {
  744.                 // add class
  745.                 addClass(instance.elements.root, classes.basic);
  746.             } else {
  747.                 // remove class
  748.                 removeClass(instance.elements.root, classes.basic);
  749.             }
  750.         }
  751.  
  752.         /**
  753.          * Toggles the dialog frameless view mode
  754.          *
  755.          * @param {Object} instance The dilog instance.
  756.          *
  757.          * @return {undefined}
  758.          */
  759.         function updateFramelessMode(instance){
  760.             if (instance.get('frameless')) {
  761.                 // add class
  762.                 addClass(instance.elements.root, classes.frameless);
  763.             } else {
  764.                 // remove class
  765.                 removeClass(instance.elements.root, classes.frameless);
  766.             }
  767.         }
  768.            
  769.         /**
  770.          * Helper: Brings the modeless dialog to front, attached to modeless dialogs.
  771.          *
  772.          * @param {Event} event Focus event
  773.          * @param {Object} instance The dilog instance.
  774.          *
  775.          * @return {undefined}
  776.          */
  777.         function bringToFront(event, instance){
  778.            
  779.             // Do not bring to front if preceeded by an open modal
  780.             var index = openDialogs.indexOf(instance);
  781.             for(var x=index+1;x<openDialogs.length;x+=1){
  782.                 if(openDialogs[x].isModal()){
  783.                     return;
  784.                 }
  785.             }
  786.                  
  787.             // Bring to front by making it the last child.
  788.             if(document.body.lastChild !== instance.elements.root){
  789.                 document.body.appendChild(instance.elements.root);
  790.                 //also make sure its at the end of the list
  791.                 openDialogs.splice(openDialogs.indexOf(instance),1);
  792.                 openDialogs.push(instance);
  793.                 setFocus(instance);
  794.             }
  795.                  
  796.             return false;
  797.         }
  798.            
  799.         /**
  800.          * Helper: reflects dialogs options updates
  801.          *
  802.          * @param {Object} instance The dilog instance.
  803.          * @param {String} option The updated option name.
  804.          *
  805.          * @return      {undefined}
  806.          */
  807.         function optionUpdated(instance, option, oldValue, newValue){
  808.             switch(option){
  809.             case 'title':
  810.                 instance.setHeader(newValue);
  811.                 break;
  812.             case 'modal':
  813.                 updateDisplayMode(instance);
  814.                 break;
  815.             case 'basic':
  816.                 updateBasicMode(instance);
  817.                 break;
  818.             case 'frameless':
  819.                 updateFramelessMode(instance);
  820.                 break;
  821.             case 'pinned':
  822.                 updatePinned(instance);
  823.                 break;
  824.             case 'closable':
  825.                 updateClosable(instance);
  826.                 break;
  827.             case 'maximizable':
  828.                 updateMaximizable(instance);
  829.                 break;
  830.             case 'pinnable':
  831.                 updatePinnable(instance);
  832.                 break;
  833.             case 'movable':
  834.                 updateMovable(instance);
  835.                 break;
  836.             case 'resizable':
  837.                 updateResizable(instance);
  838.                 break;
  839.             case 'transition':
  840.                 updateTransition(instance,newValue, oldValue);
  841.                 break;
  842.             case 'padding':
  843.                 if(newValue){
  844.                     removeClass(instance.elements.root, classes.noPadding);
  845.                 }else if(instance.elements.root.className.indexOf(classes.noPadding) < 0){
  846.                     addClass(instance.elements.root, classes.noPadding);
  847.                 }
  848.                 break;
  849.             case 'overflow':
  850.                 if(newValue){
  851.                     removeClass(instance.elements.root, classes.noOverflow);
  852.                 }else if(instance.elements.root.className.indexOf(classes.noOverflow) < 0){
  853.                     addClass(instance.elements.root, classes.noOverflow);
  854.                 }
  855.                 break;
  856.             case 'transition':
  857.                 updateTransition(instance,newValue, oldValue);
  858.                 break;
  859.             }
  860.  
  861.             // internal on option updated event
  862.             if(typeof instance.hooks.onupdate === 'function'){
  863.                 instance.hooks.onupdate.call(instance, option, oldValue, newValue);
  864.             }
  865.         }
  866.            
  867.         /**
  868.          * Helper: reflects dialogs options updates
  869.          *
  870.          * @param {Object} instance The dilog instance.
  871.          * @param {Object} obj The object to set/get a value on/from.
  872.          * @param {Function} callback The callback function to call if the key was found.
  873.          * @param {String|Object} key A string specifying a propery name or a collection of key value pairs.
  874.          * @param {Object} value Optional, the value associated with the key (in case it was a string).
  875.          * @param {String} option The updated option name.
  876.          *
  877.          * @return      {Object} result object
  878.          *  The result objects has an 'op' property, indicating of this is a SET or GET operation.
  879.          *        GET:
  880.          *        - found: a flag indicating if the key was found or not.
  881.          *        - value: the property value.
  882.          *        SET:
  883.          *        - items: a list of key value pairs of the properties being set.
  884.          *                    each contains:
  885.          *                          - found: a flag indicating if the key was found or not.
  886.          *                          - key: the property key.
  887.          *                          - value: the property value.
  888.          */
  889.         function update(instance, obj, callback, key, value){
  890.             var result = {op:undefined, items: [] };
  891.             if(typeof value === 'undefined' && typeof key === 'string') {
  892.                 //get
  893.                 result.op = 'get';
  894.                 if(obj.hasOwnProperty(key)){
  895.                     result.found = true;
  896.                     result.value = obj[key];
  897.                 }else{
  898.                     result.found = false;
  899.                     result.value = undefined;
  900.                 }
  901.             }
  902.             else
  903.             {
  904.                 var old;
  905.                 //set
  906.                 result.op = 'set';
  907.                 if(typeof key === 'object'){
  908.                     //set multiple
  909.                     var args = key;
  910.                     for (var prop in args) {
  911.                         if (obj.hasOwnProperty(prop)) {
  912.                             if(obj[prop] !== args[prop]){
  913.                                 old = obj[prop];
  914.                                 obj[prop] = args[prop];
  915.                                 callback.call(instance,prop, old, args[prop]);
  916.                             }
  917.                             result.items.push({ 'key': prop, 'value': args[prop], 'found':true});
  918.                         }else{
  919.                             result.items.push({ 'key': prop, 'value': args[prop], 'found':false});
  920.                         }
  921.                     }
  922.                 } else if (typeof key === 'string'){
  923.                     //set single
  924.                     if (obj.hasOwnProperty(key)) {
  925.                         if(obj[key] !== value){
  926.                             old  = obj[key];
  927.                             obj[key] = value;
  928.                             callback.call(instance,key, old, value);
  929.                         }
  930.                         result.items.push({'key': key, 'value': value , 'found':true});
  931.  
  932.                     }else{
  933.                         result.items.push({'key': key, 'value': value , 'found':false});
  934.                     }
  935.                 } else {
  936.                     //invalid params
  937.                     throw new Error('args must be a string or object');
  938.                 }
  939.             }
  940.             return result;
  941.         }
  942.  
  943.  
  944.         /**
  945.          * Triggers a close event.
  946.          *
  947.          * @param {Object} instance The dilog instance.
  948.          *
  949.          * @return {undefined}
  950.          */
  951.         function triggerClose(instance) {
  952.             var found;
  953.             triggerCallback(instance, function (button) {
  954.                 return found = (button.invokeOnClose === true);
  955.             });
  956.             //none of the buttons registered as onclose callback
  957.             //close the dialog
  958.             if (!found && instance.isOpen()) {
  959.                 instance.close();
  960.             }
  961.         }
  962.  
  963.         /**
  964.          * Dialogs commands event handler, attached to the dialog commands element.
  965.          *
  966.          * @param {Event} event     DOM event object.
  967.          * @param {Object} instance The dilog instance.
  968.          *
  969.          * @return {undefined}
  970.          */
  971.         function commandsClickHandler(event, instance) {
  972.             var target = event.srcElement || event.target;
  973.             switch (target) {
  974.             case instance.elements.commands.pin:
  975.                 if (!instance.isPinned()) {
  976.                     pin(instance);
  977.                 } else {
  978.                     unpin(instance);
  979.                 }
  980.                 break;
  981.             case instance.elements.commands.maximize:
  982.                 if (!instance.isMaximized()) {
  983.                     maximize(instance);
  984.                 } else {
  985.                     restore(instance);
  986.                 }
  987.                 break;
  988.             case instance.elements.commands.close:
  989.                 triggerClose(instance);
  990.                 break;
  991.             }
  992.             return false;
  993.         }
  994.  
  995.         /**
  996.          * Helper: pins the modeless dialog.
  997.          *
  998.          * @param {Object} instance The dialog instance.
  999.          *
  1000.          * @return {undefined}
  1001.          */
  1002.         function pin(instance) {
  1003.             //pin the dialog
  1004.             instance.set('pinned', true);
  1005.         }
  1006.  
  1007.         /**
  1008.          * Helper: unpins the modeless dialog.
  1009.          *
  1010.          * @param {Object} instance The dilog instance.
  1011.          *
  1012.          * @return {undefined}
  1013.          */
  1014.         function unpin(instance) {
  1015.             //unpin the dialog
  1016.             instance.set('pinned', false);
  1017.         }
  1018.  
  1019.  
  1020.         /**
  1021.          * Helper: enlarges the dialog to fill the entire screen.
  1022.          *
  1023.          * @param {Object} instance The dilog instance.
  1024.          *
  1025.          * @return {undefined}
  1026.          */
  1027.         function maximize(instance) {
  1028.             // allow custom `onmaximize` method
  1029.             dispatchEvent('onmaximize', instance);
  1030.             //maximize the dialog
  1031.             addClass(instance.elements.root, classes.maximized);
  1032.             if (instance.isOpen()) {
  1033.                 ensureNoOverflow();
  1034.             }
  1035.             // allow custom `onmaximized` method
  1036.             dispatchEvent('onmaximized', instance);
  1037.         }
  1038.  
  1039.         /**
  1040.          * Helper: returns the dialog to its former size.
  1041.          *
  1042.          * @param {Object} instance The dilog instance.
  1043.          *
  1044.          * @return {undefined}
  1045.          */
  1046.         function restore(instance) {
  1047.             // allow custom `onrestore` method
  1048.             dispatchEvent('onrestore', instance);
  1049.             //maximize the dialog
  1050.             removeClass(instance.elements.root, classes.maximized);
  1051.             if (instance.isOpen()) {
  1052.                 ensureNoOverflow();
  1053.             }
  1054.             // allow custom `onrestored` method
  1055.             dispatchEvent('onrestored', instance);
  1056.         }
  1057.  
  1058.         /**
  1059.          * Show or hide the maximize box.
  1060.          *
  1061.          * @param {Object} instance The dilog instance.
  1062.          * @param {Boolean} on True to add the behavior, removes it otherwise.
  1063.          *
  1064.          * @return {undefined}
  1065.          */
  1066.         function updatePinnable(instance) {
  1067.             if (instance.get('pinnable')) {
  1068.                 // add class
  1069.                 addClass(instance.elements.root, classes.pinnable);
  1070.             } else {
  1071.                 // remove class
  1072.                 removeClass(instance.elements.root, classes.pinnable);
  1073.             }
  1074.         }
  1075.  
  1076.         /**
  1077.          * Helper: Fixes the absolutly positioned modal div position.
  1078.          *
  1079.          * @param {Object} instance The dialog instance.
  1080.          *
  1081.          * @return {undefined}
  1082.          */
  1083.         function addAbsPositionFix(instance) {
  1084.             var scrollLeft = getScrollLeft();
  1085.             instance.elements.modal.style.marginTop = getScrollTop() + 'px';
  1086.             instance.elements.modal.style.marginLeft = scrollLeft + 'px';
  1087.             instance.elements.modal.style.marginRight = (-scrollLeft) + 'px';
  1088.         }
  1089.  
  1090.         /**
  1091.          * Helper: Removes the absolutly positioned modal div position fix.
  1092.          *
  1093.          * @param {Object} instance The dialog instance.
  1094.          *
  1095.          * @return {undefined}
  1096.          */
  1097.         function removeAbsPositionFix(instance) {
  1098.             var marginTop = parseInt(instance.elements.modal.style.marginTop, 10);
  1099.             var marginLeft = parseInt(instance.elements.modal.style.marginLeft, 10);
  1100.             instance.elements.modal.style.marginTop = '';
  1101.             instance.elements.modal.style.marginLeft = '';
  1102.             instance.elements.modal.style.marginRight = '';
  1103.  
  1104.             if (instance.isOpen()) {
  1105.                 var top = 0,
  1106.                     left = 0
  1107.                 ;
  1108.                 if (instance.elements.dialog.style.top !== '') {
  1109.                     top = parseInt(instance.elements.dialog.style.top, 10);
  1110.                 }
  1111.                 instance.elements.dialog.style.top = (top + (marginTop - getScrollTop())) + 'px';
  1112.  
  1113.                 if (instance.elements.dialog.style.left !== '') {
  1114.                     left = parseInt(instance.elements.dialog.style.left, 10);
  1115.                 }
  1116.                 instance.elements.dialog.style.left = (left + (marginLeft - getScrollLeft())) + 'px';
  1117.             }
  1118.         }
  1119.         /**
  1120.          * Helper: Adds/Removes the absolutly positioned modal div position fix based on its pinned setting.
  1121.          *
  1122.          * @param {Object} instance The dialog instance.
  1123.          *
  1124.          * @return {undefined}
  1125.          */
  1126.         function updateAbsPositionFix(instance) {
  1127.             // if modeless and unpinned add fix
  1128.             if (!instance.get('modal') && !instance.get('pinned')) {
  1129.                 addAbsPositionFix(instance);
  1130.             } else {
  1131.                 removeAbsPositionFix(instance);
  1132.             }
  1133.         }
  1134.         /**
  1135.          * Toggles the dialog position lock | modeless only.
  1136.          *
  1137.          * @param {Object} instance The dilog instance.
  1138.          * @param {Boolean} on True to make it modal, false otherwise.
  1139.          *
  1140.          * @return {undefined}
  1141.          */
  1142.         function updatePinned(instance) {
  1143.             if (instance.get('pinned')) {
  1144.                 removeClass(instance.elements.root, classes.unpinned);
  1145.                 if (instance.isOpen()) {
  1146.                     removeAbsPositionFix(instance);
  1147.                 }
  1148.             } else {
  1149.                 addClass(instance.elements.root, classes.unpinned);
  1150.                 if (instance.isOpen() && !instance.isModal()) {
  1151.                     addAbsPositionFix(instance);
  1152.                 }
  1153.             }
  1154.         }
  1155.  
  1156.         /**
  1157.          * Show or hide the maximize box.
  1158.          *
  1159.          * @param {Object} instance The dilog instance.
  1160.          * @param {Boolean} on True to add the behavior, removes it otherwise.
  1161.          *
  1162.          * @return {undefined}
  1163.          */
  1164.         function updateMaximizable(instance) {
  1165.             if (instance.get('maximizable')) {
  1166.                 // add class
  1167.                 addClass(instance.elements.root, classes.maximizable);
  1168.             } else {
  1169.                 // remove class
  1170.                 removeClass(instance.elements.root, classes.maximizable);
  1171.             }
  1172.         }
  1173.  
  1174.         /**
  1175.          * Show or hide the close box.
  1176.          *
  1177.          * @param {Object} instance The dilog instance.
  1178.          * @param {Boolean} on True to add the behavior, removes it otherwise.
  1179.          *
  1180.          * @return {undefined}
  1181.          */
  1182.         function updateClosable(instance) {
  1183.             if (instance.get('closable')) {
  1184.                 // add class
  1185.                 addClass(instance.elements.root, classes.closable);
  1186.                 bindClosableEvents(instance);
  1187.             } else {
  1188.                 // remove class
  1189.                 removeClass(instance.elements.root, classes.closable);
  1190.                 unbindClosableEvents(instance);
  1191.             }
  1192.         }
  1193.  
  1194.         // flag to cancel click event if already handled by end resize event (the mousedown, mousemove, mouseup sequence fires a click event.).
  1195.         var cancelClick = false;
  1196.  
  1197.         /**
  1198.          * Helper: closes the modal dialog when clicking the modal
  1199.          *
  1200.          * @param {Event} event     DOM event object.
  1201.          * @param {Object} instance The dilog instance.
  1202.          *
  1203.          * @return {undefined}
  1204.          */
  1205.         function modalClickHandler(event, instance) {
  1206.             var target = event.srcElement || event.target;
  1207.             if (!cancelClick && target === instance.elements.modal && instance.get('closableByDimmer') === true) {
  1208.                 triggerClose(instance);
  1209.             }
  1210.             cancelClick = false;
  1211.             return false;
  1212.         }
  1213.  
  1214.         // flag to cancel keyup event if already handled by click event (pressing Enter on a focusted button).
  1215.         var cancelKeyup = false;
  1216.         /**
  1217.          * Helper: triggers a button callback
  1218.          *
  1219.          * @param {Object}          The dilog instance.
  1220.          * @param {Function}  Callback to check which button triggered the event.
  1221.          *
  1222.          * @return {undefined}
  1223.          */
  1224.         function triggerCallback(instance, check) {
  1225.             for (var idx = 0; idx < instance.__internal.buttons.length; idx += 1) {
  1226.                 var button = instance.__internal.buttons[idx];
  1227.                 if (!button.element.disabled && check(button)) {
  1228.                     var closeEvent = createCloseEvent(idx, button);
  1229.                     if (typeof instance.callback === 'function') {
  1230.                         instance.callback.apply(instance, [closeEvent]);
  1231.                     }
  1232.                     //close the dialog only if not canceled.
  1233.                     if (closeEvent.cancel === false) {
  1234.                         instance.close();
  1235.                     }
  1236.                     break;
  1237.                 }
  1238.             }
  1239.         }
  1240.  
  1241.         /**
  1242.          * Clicks event handler, attached to the dialog footer.
  1243.          *
  1244.          * @param {Event}           DOM event object.
  1245.          * @param {Object}          The dilog instance.
  1246.          *
  1247.          * @return {undefined}
  1248.          */
  1249.         function buttonsClickHandler(event, instance) {
  1250.             var target = event.srcElement || event.target;
  1251.             triggerCallback(instance, function (button) {
  1252.                 // if this button caused the click, cancel keyup event
  1253.                 return button.element === target && (cancelKeyup = true);
  1254.             });
  1255.         }
  1256.  
  1257.         /**
  1258.          * Keyup event handler, attached to the document.body
  1259.          *
  1260.          * @param {Event}           DOM event object.
  1261.          * @param {Object}          The dilog instance.
  1262.          *
  1263.          * @return {undefined}
  1264.          */
  1265.         function keyupHandler(event) {
  1266.             //hitting enter while button has focus will trigger keyup too.
  1267.             //ignore if handled by clickHandler
  1268.             if (cancelKeyup) {
  1269.                 cancelKeyup = false;
  1270.                 return;
  1271.             }
  1272.             var instance = openDialogs[openDialogs.length - 1];
  1273.             var keyCode = event.keyCode;
  1274.             if (instance.__internal.buttons.length === 0 && keyCode === keys.ESC && instance.get('closable') === true) {
  1275.                 triggerClose(instance);
  1276.                 return false;
  1277.             }else if (usedKeys.indexOf(keyCode) > -1) {
  1278.                 triggerCallback(instance, function (button) {
  1279.                     return button.key === keyCode;
  1280.                 });
  1281.                 return false;
  1282.             }
  1283.         }
  1284.         /**
  1285.         * Keydown event handler, attached to the document.body
  1286.         *
  1287.         * @param {Event}            DOM event object.
  1288.         * @param {Object}           The dilog instance.
  1289.         *
  1290.         * @return {undefined}
  1291.         */
  1292.         function keydownHandler(event) {
  1293.             var instance = openDialogs[openDialogs.length - 1];
  1294.             var keyCode = event.keyCode;
  1295.             if (keyCode === keys.LEFT || keyCode === keys.RIGHT) {
  1296.                 var buttons = instance.__internal.buttons;
  1297.                 for (var x = 0; x < buttons.length; x += 1) {
  1298.                     if (document.activeElement === buttons[x].element) {
  1299.                         switch (keyCode) {
  1300.                         case keys.LEFT:
  1301.                             buttons[(x || buttons.length) - 1].element.focus();
  1302.                             return;
  1303.                         case keys.RIGHT:
  1304.                             buttons[(x + 1) % buttons.length].element.focus();
  1305.                             return;
  1306.                         }
  1307.                     }
  1308.                 }
  1309.             }else if (keyCode < keys.F12 + 1 && keyCode > keys.F1 - 1 && usedKeys.indexOf(keyCode) > -1) {
  1310.                 event.preventDefault();
  1311.                 event.stopPropagation();
  1312.                 triggerCallback(instance, function (button) {
  1313.                     return button.key === keyCode;
  1314.                 });
  1315.                 return false;
  1316.             }
  1317.         }
  1318.  
  1319.  
  1320.         /**
  1321.          * Sets focus to proper dialog element
  1322.          *
  1323.          * @param {Object} instance The dilog instance.
  1324.          * @param {Node} [resetTarget=undefined] DOM element to reset focus to.
  1325.          *
  1326.          * @return {undefined}
  1327.          */
  1328.         function setFocus(instance, resetTarget) {
  1329.             // reset target has already been determined.
  1330.             if (resetTarget) {
  1331.                 resetTarget.focus();
  1332.             } else {
  1333.                 // current instance focus settings
  1334.                 var focus = instance.__internal.focus;
  1335.                 // the focus element.
  1336.                 var element = focus.element;
  1337.  
  1338.                 switch (typeof focus.element) {
  1339.                 // a number means a button index
  1340.                 case 'number':
  1341.                     if (instance.__internal.buttons.length > focus.element) {
  1342.                         //in basic view, skip focusing the buttons.
  1343.                         if (instance.get('basic') === true) {
  1344.                             element = instance.elements.reset[0];
  1345.                         } else {
  1346.                             element = instance.__internal.buttons[focus.element].element;
  1347.                         }
  1348.                     }
  1349.                     break;
  1350.                 // a string means querySelector to select from dialog body contents.
  1351.                 case 'string':
  1352.                     element = instance.elements.body.querySelector(focus.element);
  1353.                     break;
  1354.                 // a function should return the focus element.
  1355.                 case 'function':
  1356.                     element = focus.element.call(instance);
  1357.                     break;
  1358.                 }
  1359.                
  1360.                 // if no focus element, default to first reset element.
  1361.                 if ((typeof element === 'undefined' || element === null) && instance.__internal.buttons.length === 0) {
  1362.                     element = instance.elements.reset[0];
  1363.                 }
  1364.                 // focus
  1365.                 if (element && element.focus) {
  1366.                     element.focus();
  1367.                     // if selectable
  1368.                     if (focus.select && element.select) {
  1369.                         element.select();
  1370.                     }
  1371.                 }
  1372.             }
  1373.         }
  1374.  
  1375.         /**
  1376.          * Focus event handler, attached to document.body and dialogs own reset links.
  1377.          * handles the focus for modal dialogs only.
  1378.          *
  1379.          * @param {Event} event DOM focus event object.
  1380.          * @param {Object} instance The dilog instance.
  1381.          *
  1382.          * @return {undefined}
  1383.          */
  1384.         function onReset(event, instance) {
  1385.  
  1386.             // should work on last modal if triggered from document.body
  1387.             if (!instance) {
  1388.                 for (var x = openDialogs.length - 1; x > -1; x -= 1) {
  1389.                     if (openDialogs[x].isModal()) {
  1390.                         instance = openDialogs[x];
  1391.                         break;
  1392.                     }
  1393.                 }
  1394.             }
  1395.             // if modal
  1396.             if (instance && instance.isModal()) {
  1397.                 // determine reset target to enable forward/backward tab cycle.
  1398.                 var resetTarget, target = event.srcElement || event.target;
  1399.                 var lastResetElement = target === instance.elements.reset[1] || (instance.__internal.buttons.length === 0 && target === document.body);
  1400.  
  1401.                 // if last reset link, then go to maximize or close
  1402.                 if (lastResetElement) {
  1403.                     if (instance.get('maximizable')) {
  1404.                         resetTarget = instance.elements.commands.maximize;
  1405.                     } else if (instance.get('closable')) {
  1406.                         resetTarget = instance.elements.commands.close;
  1407.                     }
  1408.                 }
  1409.                 // if no reset target found, try finding the best button
  1410.                 if (resetTarget === undefined) {
  1411.                     if (typeof instance.__internal.focus.element === 'number') {
  1412.                         // button focus element, go to first available button
  1413.                         if (target === instance.elements.reset[0]) {
  1414.                             resetTarget = instance.elements.buttons.auxiliary.firstChild || instance.elements.buttons.primary.firstChild;
  1415.                         } else if (lastResetElement) {
  1416.                             //restart the cycle by going to first reset link
  1417.                             resetTarget = instance.elements.reset[0];
  1418.                         }
  1419.                     } else {
  1420.                         // will reach here when tapping backwards, so go to last child
  1421.                         // The focus element SHOULD NOT be a button (logically!).
  1422.                         if (target === instance.elements.reset[0]) {
  1423.                             resetTarget = instance.elements.buttons.primary.lastChild || instance.elements.buttons.auxiliary.lastChild;
  1424.                         }
  1425.                     }
  1426.                 }
  1427.                 // focus
  1428.                 setFocus(instance, resetTarget);
  1429.             }
  1430.         }
  1431.         /**
  1432.          * Transition in transitionend event handler.
  1433.          *
  1434.          * @param {Event}           TransitionEnd event object.
  1435.          * @param {Object}          The dilog instance.
  1436.          *
  1437.          * @return {undefined}
  1438.          */
  1439.         function handleTransitionInEvent(event, instance) {
  1440.             // clear the timer
  1441.             clearTimeout(instance.__internal.timerIn);
  1442.  
  1443.             // once transition is complete, set focus
  1444.             setFocus(instance);
  1445.  
  1446.             //restore scroll to prevent document jump
  1447.             restoreScrollPosition();
  1448.  
  1449.             // allow handling key up after transition ended.
  1450.             cancelKeyup = false;
  1451.  
  1452.             // allow custom `onfocus` method
  1453.             dispatchEvent('onfocus', instance);
  1454.  
  1455.             // unbind the event
  1456.             off(instance.elements.dialog, transition.type, instance.__internal.transitionInHandler);
  1457.  
  1458.             removeClass(instance.elements.root, classes.animationIn);
  1459.         }
  1460.  
  1461.         /**
  1462.          * Transition out transitionend event handler.
  1463.          *
  1464.          * @param {Event}           TransitionEnd event object.
  1465.          * @param {Object}          The dilog instance.
  1466.          *
  1467.          * @return {undefined}
  1468.          */
  1469.         function handleTransitionOutEvent(event, instance) {
  1470.             // clear the timer
  1471.             clearTimeout(instance.__internal.timerOut);
  1472.             // unbind the event
  1473.             off(instance.elements.dialog, transition.type, instance.__internal.transitionOutHandler);
  1474.  
  1475.             // reset move updates
  1476.             resetMove(instance);
  1477.             // reset resize updates
  1478.             resetResize(instance);
  1479.  
  1480.             // restore if maximized
  1481.             if (instance.isMaximized() && !instance.get('startMaximized')) {
  1482.                 restore(instance);
  1483.             }
  1484.  
  1485.             // return focus to the last active element
  1486.             if (alertify.defaults.maintainFocus && instance.__internal.activeElement) {
  1487.                 instance.__internal.activeElement.focus();
  1488.                 instance.__internal.activeElement = null;
  1489.             }
  1490.            
  1491.             //destory the instance
  1492.             if (typeof instance.__internal.destroy === 'function') {
  1493.                 instance.__internal.destroy.apply(instance);
  1494.             }
  1495.         }
  1496.         /* Controls moving a dialog around */
  1497.         //holde the current moving instance
  1498.         var movable = null,
  1499.             //holds the current X offset when move starts
  1500.             offsetX = 0,
  1501.             //holds the current Y offset when move starts
  1502.             offsetY = 0,
  1503.             xProp = 'pageX',
  1504.             yProp = 'pageY',
  1505.             bounds = null,
  1506.             refreshTop = false,
  1507.             moveDelegate = null
  1508.         ;
  1509.  
  1510.         /**
  1511.          * Helper: sets the element top/left coordinates
  1512.          *
  1513.          * @param {Event} event     DOM event object.
  1514.          * @param {Node} element The element being moved.
  1515.          *
  1516.          * @return {undefined}
  1517.          */
  1518.         function moveElement(event, element) {
  1519.             var left = (event[xProp] - offsetX),
  1520.                 top  = (event[yProp] - offsetY);
  1521.  
  1522.             if(refreshTop){
  1523.                 top -= document.body.scrollTop;
  1524.             }
  1525.            
  1526.             element.style.left = left + 'px';
  1527.             element.style.top = top + 'px';
  1528.            
  1529.         }
  1530.         /**
  1531.          * Helper: sets the element top/left coordinates within screen bounds
  1532.          *
  1533.          * @param {Event} event     DOM event object.
  1534.          * @param {Node} element The element being moved.
  1535.          *
  1536.          * @return {undefined}
  1537.          */
  1538.         function moveElementBounded(event, element) {
  1539.             var left = (event[xProp] - offsetX),
  1540.                 top  = (event[yProp] - offsetY);
  1541.  
  1542.             if(refreshTop){
  1543.                 top -= document.body.scrollTop;
  1544.             }
  1545.            
  1546.             element.style.left = Math.min(bounds.maxLeft, Math.max(bounds.minLeft, left)) + 'px';
  1547.             if(refreshTop){
  1548.                 element.style.top = Math.min(bounds.maxTop, Math.max(bounds.minTop, top)) + 'px';
  1549.             }else{
  1550.                 element.style.top = Math.max(bounds.minTop, top) + 'px';
  1551.             }
  1552.         }
  1553.            
  1554.  
  1555.         /**
  1556.          * Triggers the start of a move event, attached to the header element mouse down event.
  1557.          * Adds no-selection class to the body, disabling selection while moving.
  1558.          *
  1559.          * @param {Event} event     DOM event object.
  1560.          * @param {Object} instance The dilog instance.
  1561.          *
  1562.          * @return {Boolean} false
  1563.          */
  1564.         function beginMove(event, instance) {
  1565.             if (resizable === null && !instance.isMaximized() && instance.get('movable')) {
  1566.                 var eventSrc, left=0, top=0;
  1567.                 if (event.type === 'touchstart') {
  1568.                     event.preventDefault();
  1569.                     eventSrc = event.targetTouches[0];
  1570.                     xProp = 'clientX';
  1571.                     yProp = 'clientY';
  1572.                 } else if (event.button === 0) {
  1573.                     eventSrc = event;
  1574.                 }
  1575.  
  1576.                 if (eventSrc) {
  1577.  
  1578.                     var element = instance.elements.dialog;
  1579.                     addClass(element, classes.capture);
  1580.  
  1581.                     if (element.style.left) {
  1582.                         left = parseInt(element.style.left, 10);
  1583.                     }
  1584.  
  1585.                     if (element.style.top) {
  1586.                         top = parseInt(element.style.top, 10);
  1587.                     }
  1588.                    
  1589.                     offsetX = eventSrc[xProp] - left;
  1590.                     offsetY = eventSrc[yProp] - top;
  1591.  
  1592.                     if(instance.isModal()){
  1593.                         offsetY += instance.elements.modal.scrollTop;
  1594.                     }else if(instance.isPinned()){
  1595.                         offsetY -= document.body.scrollTop;
  1596.                     }
  1597.                    
  1598.                     if(instance.get('moveBounded')){
  1599.                         var current = element,
  1600.                             offsetLeft = -left,
  1601.                             offsetTop = -top;
  1602.                        
  1603.                         //calc offset
  1604.                         do {
  1605.                             offsetLeft += current.offsetLeft;
  1606.                             offsetTop += current.offsetTop;
  1607.                         } while (current = current.offsetParent);
  1608.                        
  1609.                         bounds = {
  1610.                             maxLeft : offsetLeft,
  1611.                             minLeft : -offsetLeft,
  1612.                             maxTop  : document.documentElement.clientHeight - element.clientHeight - offsetTop,
  1613.                             minTop  : -offsetTop
  1614.                         };
  1615.                         moveDelegate = moveElementBounded;
  1616.                     }else{
  1617.                         bounds = null;
  1618.                         moveDelegate = moveElement;
  1619.                     }
  1620.                    
  1621.                     // allow custom `onmove` method
  1622.                     dispatchEvent('onmove', instance);
  1623.  
  1624.                     refreshTop = !instance.isModal() && instance.isPinned();
  1625.                     movable = instance;
  1626.                     moveDelegate(eventSrc, element);
  1627.                     addClass(document.body, classes.noSelection);
  1628.                     return false;
  1629.                 }
  1630.             }
  1631.         }
  1632.  
  1633.         /**
  1634.          * The actual move handler,  attached to document.body mousemove event.
  1635.          *
  1636.          * @param {Event} event     DOM event object.
  1637.          *
  1638.          * @return {undefined}
  1639.          */
  1640.         function move(event) {
  1641.             if (movable) {
  1642.                 var eventSrc;
  1643.                 if (event.type === 'touchmove') {
  1644.                     event.preventDefault();
  1645.                     eventSrc = event.targetTouches[0];
  1646.                 } else if (event.button === 0) {
  1647.                     eventSrc = event;
  1648.                 }
  1649.                 if (eventSrc) {
  1650.                     moveDelegate(eventSrc, movable.elements.dialog);
  1651.                 }
  1652.             }
  1653.         }
  1654.  
  1655.         /**
  1656.          * Triggers the end of a move event,  attached to document.body mouseup event.
  1657.          * Removes no-selection class from document.body, allowing selection.
  1658.          *
  1659.          * @return {undefined}
  1660.          */
  1661.         function endMove() {
  1662.             if (movable) {
  1663.                 var instance = movable;
  1664.                 movable = bounds = null;
  1665.                 removeClass(document.body, classes.noSelection);
  1666.                 removeClass(instance.elements.dialog, classes.capture);
  1667.                 // allow custom `onmoved` method
  1668.                 dispatchEvent('onmoved', instance);
  1669.             }
  1670.         }
  1671.  
  1672.         /**
  1673.          * Resets any changes made by moving the element to its original state,
  1674.          *
  1675.          * @param {Object} instance The dilog instance.
  1676.          *
  1677.          * @return {undefined}
  1678.          */
  1679.         function resetMove(instance) {
  1680.             movable = null;
  1681.             var element = instance.elements.dialog;
  1682.             element.style.left = element.style.top = '';
  1683.         }
  1684.  
  1685.         /**
  1686.          * Updates the dialog move behavior.
  1687.          *
  1688.          * @param {Object} instance The dilog instance.
  1689.          * @param {Boolean} on True to add the behavior, removes it otherwise.
  1690.          *
  1691.          * @return {undefined}
  1692.          */
  1693.         function updateMovable(instance) {
  1694.             if (instance.get('movable')) {
  1695.                 // add class
  1696.                 addClass(instance.elements.root, classes.movable);
  1697.                 if (instance.isOpen()) {
  1698.                     bindMovableEvents(instance);
  1699.                 }
  1700.             } else {
  1701.  
  1702.                 //reset
  1703.                 resetMove(instance);
  1704.                 // remove class
  1705.                 removeClass(instance.elements.root, classes.movable);
  1706.                 if (instance.isOpen()) {
  1707.                     unbindMovableEvents(instance);
  1708.                 }
  1709.             }
  1710.         }
  1711.  
  1712.         /* Controls moving a dialog around */
  1713.         //holde the current instance being resized         
  1714.         var resizable = null,
  1715.             //holds the staring left offset when resize starts.
  1716.             startingLeft = Number.Nan,
  1717.             //holds the staring width when resize starts.
  1718.             startingWidth = 0,
  1719.             //holds the initial width when resized for the first time.
  1720.             minWidth = 0,
  1721.             //holds the offset of the resize handle.
  1722.             handleOffset = 0
  1723.         ;
  1724.  
  1725.         /**
  1726.          * Helper: sets the element width/height and updates left coordinate if neccessary.
  1727.          *
  1728.          * @param {Event} event     DOM mousemove event object.
  1729.          * @param {Node} element The element being moved.
  1730.          * @param {Boolean} pinned A flag indicating if the element being resized is pinned to the screen.
  1731.          *
  1732.          * @return {undefined}
  1733.          */
  1734.         function resizeElement(event, element, pageRelative) {
  1735.  
  1736.             //calculate offsets from 0,0
  1737.             var current = element;
  1738.             var offsetLeft = 0;
  1739.             var offsetTop = 0;
  1740.             do {
  1741.                 offsetLeft += current.offsetLeft;
  1742.                 offsetTop += current.offsetTop;
  1743.             } while (current = current.offsetParent);
  1744.  
  1745.             // determine X,Y coordinates.
  1746.             var X, Y;
  1747.             if (pageRelative === true) {
  1748.                 X = event.pageX;
  1749.                 Y = event.pageY;
  1750.             } else {
  1751.                 X = event.clientX;
  1752.                 Y = event.clientY;
  1753.             }
  1754.             // rtl handling
  1755.             var isRTL = isRightToLeft();
  1756.             if (isRTL) {
  1757.                 // reverse X
  1758.                 X = document.body.offsetWidth - X;
  1759.                 // if has a starting left, calculate offsetRight
  1760.                 if (!isNaN(startingLeft)) {
  1761.                     offsetLeft = document.body.offsetWidth - offsetLeft - element.offsetWidth;
  1762.                 }
  1763.             }
  1764.  
  1765.             // set width/height
  1766.             element.style.height = (Y - offsetTop + handleOffset) + 'px';
  1767.             element.style.width = (X - offsetLeft + handleOffset) + 'px';
  1768.  
  1769.             // if the element being resized has a starting left, maintain it.
  1770.             // the dialog is centered, divide by half the offset to maintain the margins.
  1771.             if (!isNaN(startingLeft)) {
  1772.                 var diff = Math.abs(element.offsetWidth - startingWidth) * 0.5;
  1773.                 if (isRTL) {
  1774.                     //negate the diff, why?
  1775.                     //when growing it should decrease left
  1776.                     //when shrinking it should increase left
  1777.                     diff *= -1;
  1778.                 }
  1779.                 if (element.offsetWidth > startingWidth) {
  1780.                     //growing
  1781.                     element.style.left = (startingLeft + diff) + 'px';
  1782.                 } else if (element.offsetWidth >= minWidth) {
  1783.                     //shrinking
  1784.                     element.style.left = (startingLeft - diff) + 'px';
  1785.                 }
  1786.             }
  1787.         }
  1788.  
  1789.         /**
  1790.          * Triggers the start of a resize event, attached to the resize handle element mouse down event.
  1791.          * Adds no-selection class to the body, disabling selection while moving.
  1792.          *
  1793.          * @param {Event} event     DOM event object.
  1794.          * @param {Object} instance The dilog instance.
  1795.          *
  1796.          * @return {Boolean} false
  1797.          */
  1798.         function beginResize(event, instance) {
  1799.             if (!instance.isMaximized()) {
  1800.                 var eventSrc;
  1801.                 if (event.type === 'touchstart') {
  1802.                     event.preventDefault();
  1803.                     eventSrc = event.targetTouches[0];
  1804.                 } else if (event.button === 0) {
  1805.                     eventSrc = event;
  1806.                 }
  1807.                 if (eventSrc) {
  1808.                     // allow custom `onresize` method
  1809.                     dispatchEvent('onresize', instance);
  1810.                    
  1811.                     resizable = instance;
  1812.                     handleOffset = instance.elements.resizeHandle.offsetHeight / 2;
  1813.                     var element = instance.elements.dialog;
  1814.                     addClass(element, classes.capture);
  1815.                     startingLeft = parseInt(element.style.left, 10);
  1816.                     element.style.height = element.offsetHeight + 'px';
  1817.                     element.style.minHeight = instance.elements.header.offsetHeight + instance.elements.footer.offsetHeight + 'px';
  1818.                     element.style.width = (startingWidth = element.offsetWidth) + 'px';
  1819.  
  1820.                     if (element.style.maxWidth !== 'none') {
  1821.                         element.style.minWidth = (minWidth = element.offsetWidth) + 'px';
  1822.                     }
  1823.                     element.style.maxWidth = 'none';
  1824.                     addClass(document.body, classes.noSelection);
  1825.                     return false;
  1826.                 }
  1827.             }
  1828.         }
  1829.  
  1830.         /**
  1831.          * The actual resize handler,  attached to document.body mousemove event.
  1832.          *
  1833.          * @param {Event} event     DOM event object.
  1834.          *
  1835.          * @return {undefined}
  1836.          */
  1837.         function resize(event) {
  1838.             if (resizable) {
  1839.                 var eventSrc;
  1840.                 if (event.type === 'touchmove') {
  1841.                     event.preventDefault();
  1842.                     eventSrc = event.targetTouches[0];
  1843.                 } else if (event.button === 0) {
  1844.                     eventSrc = event;
  1845.                 }
  1846.                 if (eventSrc) {
  1847.                     resizeElement(eventSrc, resizable.elements.dialog, !resizable.get('modal') && !resizable.get('pinned'));
  1848.                 }
  1849.             }
  1850.         }
  1851.  
  1852.         /**
  1853.          * Triggers the end of a resize event,  attached to document.body mouseup event.
  1854.          * Removes no-selection class from document.body, allowing selection.
  1855.          *
  1856.          * @return {undefined}
  1857.          */
  1858.         function endResize() {
  1859.             if (resizable) {
  1860.                 var instance = resizable;
  1861.                 resizable = null;
  1862.                 removeClass(document.body, classes.noSelection);
  1863.                 removeClass(instance.elements.dialog, classes.capture);
  1864.                 cancelClick = true;
  1865.                 // allow custom `onresized` method
  1866.                 dispatchEvent('onresized', instance);
  1867.             }
  1868.         }
  1869.  
  1870.         /**
  1871.          * Resets any changes made by resizing the element to its original state.
  1872.          *
  1873.          * @param {Object} instance The dilog instance.
  1874.          *
  1875.          * @return {undefined}
  1876.          */
  1877.         function resetResize(instance) {
  1878.             resizable = null;
  1879.             var element = instance.elements.dialog;
  1880.             if (element.style.maxWidth === 'none') {
  1881.                 //clear inline styles.
  1882.                 element.style.maxWidth = element.style.minWidth = element.style.width = element.style.height = element.style.minHeight = element.style.left = '';
  1883.                 //reset variables.
  1884.                 startingLeft = Number.Nan;
  1885.                 startingWidth = minWidth = handleOffset = 0;
  1886.             }
  1887.         }
  1888.  
  1889.  
  1890.         /**
  1891.          * Updates the dialog move behavior.
  1892.          *
  1893.          * @param {Object} instance The dilog instance.
  1894.          * @param {Boolean} on True to add the behavior, removes it otherwise.
  1895.          *
  1896.          * @return {undefined}
  1897.          */
  1898.         function updateResizable(instance) {
  1899.             if (instance.get('resizable')) {
  1900.                 // add class
  1901.                 addClass(instance.elements.root, classes.resizable);
  1902.                 if (instance.isOpen()) {
  1903.                     bindResizableEvents(instance);
  1904.                 }
  1905.             } else {
  1906.                 //reset
  1907.                 resetResize(instance);
  1908.                 // remove class
  1909.                 removeClass(instance.elements.root, classes.resizable);
  1910.                 if (instance.isOpen()) {
  1911.                     unbindResizableEvents(instance);
  1912.                 }
  1913.             }
  1914.         }
  1915.  
  1916.         /**
  1917.          * Reset move/resize on window resize.
  1918.          *
  1919.          * @param {Event} event     window resize event object.
  1920.          *
  1921.          * @return {undefined}
  1922.          */
  1923.         function windowResize(/*event*/) {
  1924.             for (var x = 0; x < openDialogs.length; x += 1) {
  1925.                 var instance = openDialogs[x];
  1926.                 if (instance.get('autoReset')) {
  1927.                     resetMove(instance);
  1928.                     resetResize(instance);
  1929.                 }
  1930.             }
  1931.         }
  1932.         /**
  1933.          * Bind dialogs events
  1934.          *
  1935.          * @param {Object} instance The dilog instance.
  1936.          *
  1937.          * @return {undefined}
  1938.          */
  1939.         function bindEvents(instance) {
  1940.             // if first dialog, hook global handlers
  1941.             if (openDialogs.length === 1) {
  1942.                 //global
  1943.                 on(window, 'resize', windowResize);
  1944.                 on(document.body, 'keyup', keyupHandler);
  1945.                 on(document.body, 'keydown', keydownHandler);
  1946.                 on(document.body, 'focus', onReset);
  1947.  
  1948.                 //move
  1949.                 on(document.documentElement, 'mousemove', move);
  1950.                 on(document.documentElement, 'touchmove', move);
  1951.                 on(document.documentElement, 'mouseup', endMove);
  1952.                 on(document.documentElement, 'touchend', endMove);
  1953.                 //resize
  1954.                 on(document.documentElement, 'mousemove', resize);
  1955.                 on(document.documentElement, 'touchmove', resize);
  1956.                 on(document.documentElement, 'mouseup', endResize);
  1957.                 on(document.documentElement, 'touchend', endResize);
  1958.             }
  1959.  
  1960.             // common events
  1961.             on(instance.elements.commands.container, 'click', instance.__internal.commandsClickHandler);
  1962.             on(instance.elements.footer, 'click', instance.__internal.buttonsClickHandler);
  1963.             on(instance.elements.reset[0], 'focus', instance.__internal.resetHandler);
  1964.             on(instance.elements.reset[1], 'focus', instance.__internal.resetHandler);
  1965.  
  1966.             //prevent handling key up when dialog is being opened by a key stroke.
  1967.             cancelKeyup = true;
  1968.             // hook in transition handler
  1969.             on(instance.elements.dialog, transition.type, instance.__internal.transitionInHandler);
  1970.  
  1971.             // modelss only events
  1972.             if (!instance.get('modal')) {
  1973.                 bindModelessEvents(instance);
  1974.             }
  1975.  
  1976.             // resizable
  1977.             if (instance.get('resizable')) {
  1978.                 bindResizableEvents(instance);
  1979.             }
  1980.  
  1981.             // movable
  1982.             if (instance.get('movable')) {
  1983.                 bindMovableEvents(instance);
  1984.             }
  1985.         }
  1986.  
  1987.         /**
  1988.          * Unbind dialogs events
  1989.          *
  1990.          * @param {Object} instance The dilog instance.
  1991.          *
  1992.          * @return {undefined}
  1993.          */
  1994.         function unbindEvents(instance) {
  1995.             // if last dialog, remove global handlers
  1996.             if (openDialogs.length === 1) {
  1997.                 //global
  1998.                 off(window, 'resize', windowResize);
  1999.                 off(document.body, 'keyup', keyupHandler);
  2000.                 off(document.body, 'keydown', keydownHandler);
  2001.                 off(document.body, 'focus', onReset);
  2002.                 //move
  2003.                 off(document.documentElement, 'mousemove', move);
  2004.                 off(document.documentElement, 'mouseup', endMove);
  2005.                 //resize
  2006.                 off(document.documentElement, 'mousemove', resize);
  2007.                 off(document.documentElement, 'mouseup', endResize);
  2008.             }
  2009.  
  2010.             // common events
  2011.             off(instance.elements.commands.container, 'click', instance.__internal.commandsClickHandler);
  2012.             off(instance.elements.footer, 'click', instance.__internal.buttonsClickHandler);
  2013.             off(instance.elements.reset[0], 'focus', instance.__internal.resetHandler);
  2014.             off(instance.elements.reset[1], 'focus', instance.__internal.resetHandler);
  2015.  
  2016.             // hook out transition handler
  2017.             on(instance.elements.dialog, transition.type, instance.__internal.transitionOutHandler);
  2018.  
  2019.             // modelss only events
  2020.             if (!instance.get('modal')) {
  2021.                 unbindModelessEvents(instance);
  2022.             }
  2023.  
  2024.             // movable
  2025.             if (instance.get('movable')) {
  2026.                 unbindMovableEvents(instance);
  2027.             }
  2028.  
  2029.             // resizable
  2030.             if (instance.get('resizable')) {
  2031.                 unbindResizableEvents(instance);
  2032.             }
  2033.  
  2034.         }
  2035.  
  2036.         /**
  2037.          * Bind modeless specific events
  2038.          *
  2039.          * @param {Object} instance The dilog instance.
  2040.          *
  2041.          * @return {undefined}
  2042.          */
  2043.         function bindModelessEvents(instance) {
  2044.             on(instance.elements.dialog, 'focus', instance.__internal.bringToFrontHandler, true);
  2045.         }
  2046.  
  2047.         /**
  2048.          * Unbind modeless specific events
  2049.          *
  2050.          * @param {Object} instance The dilog instance.
  2051.          *
  2052.          * @return {undefined}
  2053.          */
  2054.         function unbindModelessEvents(instance) {
  2055.             off(instance.elements.dialog, 'focus', instance.__internal.bringToFrontHandler, true);
  2056.         }
  2057.  
  2058.  
  2059.  
  2060.         /**
  2061.          * Bind movable specific events
  2062.          *
  2063.          * @param {Object} instance The dilog instance.
  2064.          *
  2065.          * @return {undefined}
  2066.          */
  2067.         function bindMovableEvents(instance) {
  2068.             on(instance.elements.header, 'mousedown', instance.__internal.beginMoveHandler);
  2069.             on(instance.elements.header, 'touchstart', instance.__internal.beginMoveHandler);
  2070.         }
  2071.  
  2072.         /**
  2073.          * Unbind movable specific events
  2074.          *
  2075.          * @param {Object} instance The dilog instance.
  2076.          *
  2077.          * @return {undefined}
  2078.          */
  2079.         function unbindMovableEvents(instance) {
  2080.             off(instance.elements.header, 'mousedown', instance.__internal.beginMoveHandler);
  2081.             off(instance.elements.header, 'touchstart', instance.__internal.beginMoveHandler);
  2082.         }
  2083.  
  2084.  
  2085.  
  2086.         /**
  2087.          * Bind resizable specific events
  2088.          *
  2089.          * @param {Object} instance The dilog instance.
  2090.          *
  2091.          * @return {undefined}
  2092.          */
  2093.         function bindResizableEvents(instance) {
  2094.             on(instance.elements.resizeHandle, 'mousedown', instance.__internal.beginResizeHandler);
  2095.             on(instance.elements.resizeHandle, 'touchstart', instance.__internal.beginResizeHandler);
  2096.         }
  2097.  
  2098.         /**
  2099.          * Unbind resizable specific events
  2100.          *
  2101.          * @param {Object} instance The dilog instance.
  2102.          *
  2103.          * @return {undefined}
  2104.          */
  2105.         function unbindResizableEvents(instance) {
  2106.             off(instance.elements.resizeHandle, 'mousedown', instance.__internal.beginResizeHandler);
  2107.             off(instance.elements.resizeHandle, 'touchstart', instance.__internal.beginResizeHandler);
  2108.         }
  2109.  
  2110.         /**
  2111.          * Bind closable events
  2112.          *
  2113.          * @param {Object} instance The dilog instance.
  2114.          *
  2115.          * @return {undefined}
  2116.          */
  2117.         function bindClosableEvents(instance) {
  2118.             on(instance.elements.modal, 'click', instance.__internal.modalClickHandler);
  2119.         }
  2120.  
  2121.         /**
  2122.          * Unbind closable specific events
  2123.          *
  2124.          * @param {Object} instance The dilog instance.
  2125.          *
  2126.          * @return {undefined}
  2127.          */
  2128.         function unbindClosableEvents(instance) {
  2129.             off(instance.elements.modal, 'click', instance.__internal.modalClickHandler);
  2130.         }
  2131.         // dialog API
  2132.         return {
  2133.             __init:initialize,
  2134.             /**
  2135.              * Check if dialog is currently open
  2136.              *
  2137.              * @return {Boolean}
  2138.              */
  2139.             isOpen: function () {
  2140.                 return this.__internal.isOpen;
  2141.             },
  2142.             isModal: function (){
  2143.                 return this.elements.root.className.indexOf(classes.modeless) < 0;
  2144.             },
  2145.             isMaximized:function(){
  2146.                 return this.elements.root.className.indexOf(classes.maximized) > -1;
  2147.             },
  2148.             isPinned:function(){
  2149.                 return this.elements.root.className.indexOf(classes.unpinned) < 0;
  2150.             },
  2151.             maximize:function(){
  2152.                 if(!this.isMaximized()){
  2153.                     maximize(this);
  2154.                 }
  2155.                 return this;
  2156.             },
  2157.             restore:function(){
  2158.                 if(this.isMaximized()){
  2159.                     restore(this);
  2160.                 }
  2161.                 return this;
  2162.             },
  2163.             pin:function(){
  2164.                 if(!this.isPinned()){
  2165.                     pin(this);
  2166.                 }
  2167.                 return this;
  2168.             },
  2169.             unpin:function(){
  2170.                 if(this.isPinned()){
  2171.                     unpin(this);
  2172.                 }
  2173.                 return this;
  2174.             },
  2175.             bringToFront:function(){
  2176.                 bringToFront(null, this);
  2177.                 return this;
  2178.             },
  2179.             /**
  2180.              * Move the dialog to a specific x/y coordinates
  2181.              *
  2182.              * @param {Number} x    The new dialog x coordinate in pixels.
  2183.              * @param {Number} y    The new dialog y coordinate in pixels.
  2184.              *
  2185.              * @return {Object} The dialog instance.
  2186.              */
  2187.             moveTo:function(x,y){
  2188.                 if(!isNaN(x) && !isNaN(y)){
  2189.                     // allow custom `onmove` method
  2190.                     dispatchEvent('onmove', this);
  2191.                    
  2192.                     var element = this.elements.dialog,
  2193.                         current = element,
  2194.                         offsetLeft = 0,
  2195.                         offsetTop = 0;
  2196.                    
  2197.                     //subtract existing left,top
  2198.                     if (element.style.left) {
  2199.                         offsetLeft -= parseInt(element.style.left, 10);
  2200.                     }
  2201.                     if (element.style.top) {
  2202.                         offsetTop -= parseInt(element.style.top, 10);
  2203.                     }
  2204.                     //calc offset
  2205.                     do {
  2206.                         offsetLeft += current.offsetLeft;
  2207.                         offsetTop += current.offsetTop;
  2208.                     } while (current = current.offsetParent);
  2209.  
  2210.                     //calc left, top
  2211.                     var left = (x - offsetLeft);
  2212.                     var top  = (y - offsetTop);
  2213.  
  2214.                     //// rtl handling
  2215.                     if (isRightToLeft()) {
  2216.                         left *= -1;
  2217.                     }
  2218.  
  2219.                     element.style.left = left + 'px';
  2220.                     element.style.top = top + 'px';
  2221.                    
  2222.                     // allow custom `onmoved` method
  2223.                     dispatchEvent('onmoved', this);
  2224.                 }
  2225.                 return this;
  2226.             },
  2227.             /**
  2228.              * Resize the dialog to a specific width/height (the dialog must be 'resizable').
  2229.              * The dialog can be resized to:
  2230.              *  A minimum width equal to the initial display width
  2231.              *  A minimum height equal to the sum of header/footer heights.
  2232.              *
  2233.              *
  2234.              * @param {Number or String} width    The new dialog width in pixels or in percent.
  2235.              * @param {Number or String} height   The new dialog height in pixels or in percent.
  2236.              *
  2237.              * @return {Object} The dialog instance.
  2238.              */
  2239.             resizeTo:function(width,height){
  2240.                 var w = parseFloat(width),
  2241.                     h = parseFloat(height),
  2242.                     regex = /(\d*\.\d+|\d+)%/
  2243.                 ;
  2244.  
  2245.                 if(!isNaN(w) && !isNaN(h) && this.get('resizable') === true){
  2246.                    
  2247.                     // allow custom `onresize` method
  2248.                     dispatchEvent('onresize', this);
  2249.                    
  2250.                     if(('' + width).match(regex)){
  2251.                         w = w / 100 * document.documentElement.clientWidth ;
  2252.                     }
  2253.  
  2254.                     if(('' + height).match(regex)){
  2255.                         h = h / 100 * document.documentElement.clientHeight;
  2256.                     }
  2257.  
  2258.                     var element = this.elements.dialog;
  2259.                     if (element.style.maxWidth !== 'none') {
  2260.                         element.style.minWidth = (minWidth = element.offsetWidth) + 'px';
  2261.                     }
  2262.                     element.style.maxWidth = 'none';
  2263.                     element.style.minHeight = this.elements.header.offsetHeight + this.elements.footer.offsetHeight + 'px';
  2264.                     element.style.width = w + 'px';
  2265.                     element.style.height = h + 'px';
  2266.                    
  2267.                     // allow custom `onresized` method
  2268.                     dispatchEvent('onresized', this);
  2269.                 }
  2270.                 return this;
  2271.             },
  2272.             /**
  2273.              * Gets or Sets dialog settings/options
  2274.              *
  2275.              * @param {String|Object} key A string specifying a propery name or a collection of key/value pairs.
  2276.              * @param {Object} value Optional, the value associated with the key (in case it was a string).
  2277.              *
  2278.              * @return {undefined}
  2279.              */
  2280.             setting : function (key, value) {
  2281.                 var self = this;
  2282.                 var result = update(this, this.__internal.options, function(k,o,n){ optionUpdated(self,k,o,n); }, key, value);
  2283.                 if(result.op === 'get'){
  2284.                     if(result.found){
  2285.                         return result.value;
  2286.                     }else if(typeof this.settings !== 'undefined'){
  2287.                         return update(this, this.settings, this.settingUpdated || function(){}, key, value).value;
  2288.                     }else{
  2289.                         return undefined;
  2290.                     }
  2291.                 }else if(result.op === 'set'){
  2292.                     if(result.items.length > 0){
  2293.                         var callback = this.settingUpdated || function(){};
  2294.                         for(var x=0;x<result.items.length;x+=1){
  2295.                             var item = result.items[x];
  2296.                             if(!item.found && typeof this.settings !== 'undefined'){
  2297.                                 update(this, this.settings, callback, item.key, item.value);
  2298.                             }
  2299.                         }
  2300.                     }
  2301.                     return this;
  2302.                 }
  2303.             },
  2304.             /**
  2305.              * [Alias] Sets dialog settings/options
  2306.              */
  2307.             set:function(key, value){
  2308.                 this.setting(key,value);
  2309.                 return this;
  2310.             },
  2311.             /**
  2312.              * [Alias] Gets dialog settings/options
  2313.              */
  2314.             get:function(key){
  2315.                 return this.setting(key);
  2316.             },
  2317.             /**
  2318.             * Sets dialog header
  2319.             * @content {string or element}
  2320.             *
  2321.             * @return {undefined}
  2322.             */
  2323.             setHeader:function(content){
  2324.                 if(typeof content === 'string'){
  2325.                     clearContents(this.elements.header);
  2326.                     this.elements.header.innerHTML = content;
  2327.                 }else if (content instanceof window.HTMLElement && this.elements.header.firstChild !== content){
  2328.                     clearContents(this.elements.header);
  2329.                     this.elements.header.appendChild(content);
  2330.                 }
  2331.                 return this;
  2332.             },
  2333.             /**
  2334.             * Sets dialog contents
  2335.             * @content {string or element}
  2336.             *
  2337.             * @return {undefined}
  2338.             */
  2339.             setContent:function(content){
  2340.                 if(typeof content === 'string'){
  2341.                     clearContents(this.elements.content);
  2342.                     this.elements.content.innerHTML = content;
  2343.                 }else if (content instanceof window.HTMLElement && this.elements.content.firstChild !== content){
  2344.                     clearContents(this.elements.content);
  2345.                     this.elements.content.appendChild(content);
  2346.                 }
  2347.                 return this;
  2348.             },
  2349.             /**
  2350.              * Show the dialog as modal
  2351.              *
  2352.              * @return {Object} the dialog instance.
  2353.              */
  2354.             showModal: function(className){
  2355.                 return this.show(true, className);
  2356.             },
  2357.             /**
  2358.              * Show the dialog
  2359.              *
  2360.              * @return {Object} the dialog instance.
  2361.              */
  2362.             show: function (modal, className) {
  2363.                
  2364.                 // ensure initialization
  2365.                 initialize(this);
  2366.  
  2367.                 if ( !this.__internal.isOpen ) {
  2368.  
  2369.                     // add to open dialogs
  2370.                     this.__internal.isOpen = true;
  2371.                     openDialogs.push(this);
  2372.  
  2373.                     // save last focused element
  2374.                     if(alertify.defaults.maintainFocus){
  2375.                         this.__internal.activeElement = document.activeElement;
  2376.                     }
  2377.  
  2378.                     //allow custom dom manipulation updates before showing the dialog.
  2379.                     if(typeof this.prepare === 'function'){
  2380.                         this.prepare();
  2381.                     }
  2382.  
  2383.                     bindEvents(this);
  2384.  
  2385.                     if(modal !== undefined){
  2386.                         this.set('modal', modal);
  2387.                     }
  2388.  
  2389.                     //save scroll to prevent document jump
  2390.                     saveScrollPosition();
  2391.  
  2392.                     ensureNoOverflow();
  2393.  
  2394.                     // allow custom dialog class on show
  2395.                     if(typeof className === 'string' && className !== ''){
  2396.                         this.__internal.className = className;
  2397.                         addClass(this.elements.root, className);
  2398.                     }
  2399.  
  2400.                     // maximize if start maximized
  2401.                     if ( this.get('startMaximized')) {
  2402.                         this.maximize();
  2403.                     }else if(this.isMaximized()){
  2404.                         restore(this);
  2405.                     }
  2406.  
  2407.                     updateAbsPositionFix(this);
  2408.  
  2409.                     removeClass(this.elements.root, classes.animationOut);
  2410.                     addClass(this.elements.root, classes.animationIn);
  2411.  
  2412.                     // set 1s fallback in case transition event doesn't fire
  2413.                     clearTimeout( this.__internal.timerIn);
  2414.                     this.__internal.timerIn = setTimeout( this.__internal.transitionInHandler, transition.supported ? 1000 : 100 );
  2415.  
  2416.                     if(isSafari){
  2417.                         // force desktop safari reflow
  2418.                         var root = this.elements.root;
  2419.                         root.style.display  = 'none';
  2420.                         setTimeout(function(){root.style.display  = 'block';}, 0);
  2421.                     }
  2422.  
  2423.                     //reflow
  2424.                     reflow = this.elements.root.offsetWidth;
  2425.                  
  2426.                     // show dialog
  2427.                     removeClass(this.elements.root, classes.hidden);
  2428.  
  2429.                     // internal on show event
  2430.                     if(typeof this.hooks.onshow === 'function'){
  2431.                         this.hooks.onshow.call(this);
  2432.                     }
  2433.  
  2434.                     // allow custom `onshow` method
  2435.                     dispatchEvent('onshow', this);
  2436.  
  2437.                 }else{
  2438.                     // reset move updates
  2439.                     resetMove(this);
  2440.                     // reset resize updates
  2441.                     resetResize(this);
  2442.                     // shake the dialog to indicate its already open
  2443.                     addClass(this.elements.dialog, classes.shake);
  2444.                     var self = this;
  2445.                     setTimeout(function(){
  2446.                         removeClass(self.elements.dialog, classes.shake);
  2447.                     },200);
  2448.                 }
  2449.                 return this;
  2450.             },
  2451.             /**
  2452.              * Close the dialog
  2453.              *
  2454.              * @return {Object} The dialog instance
  2455.              */
  2456.             close: function () {
  2457.                 if (this.__internal.isOpen ) {
  2458.  
  2459.                     unbindEvents(this);
  2460.  
  2461.                     removeClass(this.elements.root, classes.animationIn);
  2462.                     addClass(this.elements.root, classes.animationOut);
  2463.  
  2464.                     // set 1s fallback in case transition event doesn't fire
  2465.                     clearTimeout( this.__internal.timerOut );
  2466.                     this.__internal.timerOut = setTimeout( this.__internal.transitionOutHandler, transition.supported ? 1000 : 100 );
  2467.                     // hide dialog
  2468.                     addClass(this.elements.root, classes.hidden);
  2469.                     //reflow
  2470.                     reflow = this.elements.modal.offsetWidth;
  2471.  
  2472.                     // remove custom dialog class on hide
  2473.                     if (typeof this.__internal.className !== 'undefined' && this.__internal.className !== '') {
  2474.                         removeClass(this.elements.root, this.__internal.className);
  2475.                     }
  2476.  
  2477.                     // internal on close event
  2478.                     if(typeof this.hooks.onclose === 'function'){
  2479.                         this.hooks.onclose.call(this);
  2480.                     }
  2481.  
  2482.                     // allow custom `onclose` method
  2483.                     dispatchEvent('onclose', this);
  2484.  
  2485.                     //remove from open dialogs
  2486.                     openDialogs.splice(openDialogs.indexOf(this),1);
  2487.                     this.__internal.isOpen = false;
  2488.  
  2489.                     ensureNoOverflow();
  2490.  
  2491.                 }
  2492.                 return this;
  2493.             },
  2494.             /**
  2495.              * Close all open dialogs except this.
  2496.              *
  2497.              * @return {undefined}
  2498.              */
  2499.             closeOthers:function(){
  2500.                 alertify.closeAll(this);
  2501.                 return this;
  2502.             },
  2503.             /**
  2504.              * Destroys this dialog instance
  2505.              *
  2506.              * @return {undefined}
  2507.              */
  2508.             destroy:function(){
  2509.                 if (this.__internal.isOpen ) {
  2510.                     //mark dialog for destruction, this will be called on tranistionOut event.
  2511.                     this.__internal.destroy = function(){
  2512.                         destruct(this, initialize);
  2513.                     };
  2514.                     //close the dialog to unbind all events.
  2515.                     this.close();
  2516.                 }else{
  2517.                     destruct(this, initialize);
  2518.                 }
  2519.                 return this;
  2520.             },
  2521.         };
  2522.       } () );
  2523.     var notifier = (function () {
  2524.         var reflow,
  2525.             element,
  2526.             openInstances = [],
  2527.             classes = {
  2528.                 base: 'alertify-notifier',
  2529.                 message: 'ajs-message',
  2530.                 top: 'ajs-top',
  2531.                 right: 'ajs-right',
  2532.                 bottom: 'ajs-bottom',
  2533.                 left: 'ajs-left',
  2534.                 visible: 'ajs-visible',
  2535.                 hidden: 'ajs-hidden',
  2536.                 close: 'ajs-close'
  2537.             };
  2538.         /**
  2539.          * Helper: initializes the notifier instance
  2540.          *
  2541.          */
  2542.         function initialize(instance) {
  2543.  
  2544.             if (!instance.__internal) {
  2545.                 instance.__internal = {
  2546.                     position: alertify.defaults.notifier.position,
  2547.                     delay: alertify.defaults.notifier.delay,
  2548.                 };
  2549.  
  2550.                 element = document.createElement('DIV');
  2551.  
  2552.                 updatePosition(instance);
  2553.             }
  2554.  
  2555.             //add to DOM tree.
  2556.             if (element.parentNode !== document.body) {
  2557.                 document.body.appendChild(element);
  2558.             }
  2559.         }
  2560.        
  2561.         function pushInstance(instance) {
  2562.             instance.__internal.pushed = true;
  2563.             openInstances.push(instance);
  2564.         }
  2565.         function popInstance(instance) {
  2566.             openInstances.splice(openInstances.indexOf(instance), 1);
  2567.             instance.__internal.pushed = false;
  2568.         }
  2569.         /**
  2570.          * Helper: update the notifier instance position
  2571.          *
  2572.          */
  2573.         function updatePosition(instance) {
  2574.             element.className = classes.base;
  2575.             switch (instance.__internal.position) {
  2576.             case 'top-right':
  2577.                 addClass(element, classes.top + ' ' + classes.right);
  2578.                 break;
  2579.             case 'top-left':
  2580.                 addClass(element, classes.top + ' ' + classes.left);
  2581.                 break;
  2582.             case 'bottom-left':
  2583.                 addClass(element, classes.bottom + ' ' + classes.left);
  2584.                 break;
  2585.  
  2586.             default:
  2587.             case 'bottom-right':
  2588.                 addClass(element, classes.bottom + ' ' + classes.right);
  2589.                 break;
  2590.             }
  2591.         }
  2592.  
  2593.         /**
  2594.         * creates a new notification message
  2595.         *
  2596.         * @param  {DOMElement} message    The notifier message element
  2597.         * @param  {Number} wait   Time (in ms) to wait before the message is dismissed, a value of 0 means keep open till clicked.
  2598.         * @param  {Function} callback A callback function to be invoked when the message is dismissed.
  2599.         *
  2600.         * @return {undefined}
  2601.         */
  2602.         function create(div, callback) {
  2603.  
  2604.             function clickDelegate(event, instance) {
  2605.                 if(!instance.__internal.closeButton || event.target.getAttribute('data-close') === 'true'){
  2606.                     instance.dismiss(true);
  2607.                 }
  2608.             }
  2609.  
  2610.             function transitionDone(event, instance) {
  2611.                 // unbind event
  2612.                 off(instance.element, transition.type, transitionDone);
  2613.                 // remove the message
  2614.                 element.removeChild(instance.element);
  2615.             }
  2616.  
  2617.             function initialize(instance) {
  2618.                 if (!instance.__internal) {
  2619.                     instance.__internal = {
  2620.                         pushed: false,
  2621.                         delay : undefined,
  2622.                         timer: undefined,
  2623.                         clickHandler: undefined,
  2624.                         transitionEndHandler: undefined,
  2625.                         transitionTimeout: undefined
  2626.                     };
  2627.                     instance.__internal.clickHandler = delegate(instance, clickDelegate);
  2628.                     instance.__internal.transitionEndHandler = delegate(instance, transitionDone);
  2629.                 }
  2630.                 return instance;
  2631.             }
  2632.             function clearTimers(instance) {
  2633.                 clearTimeout(instance.__internal.timer);
  2634.                 clearTimeout(instance.__internal.transitionTimeout);
  2635.             }
  2636.             return initialize({
  2637.                 /* notification DOM element*/
  2638.                 element: div,
  2639.                 /*
  2640.                  * Pushes a notification message
  2641.                  * @param {string or DOMElement} content The notification message content
  2642.                  * @param {Number} wait The time (in seconds) to wait before the message is dismissed, a value of 0 means keep open till clicked.
  2643.                  *
  2644.                  */
  2645.                 push: function (_content, _wait) {
  2646.                     if (!this.__internal.pushed) {
  2647.  
  2648.                         pushInstance(this);
  2649.                         clearTimers(this);
  2650.  
  2651.                         var content, wait;
  2652.                         switch (arguments.length) {
  2653.                         case 0:
  2654.                             wait = this.__internal.delay;
  2655.                             break;
  2656.                         case 1:
  2657.                             if (typeof (_content) === 'number') {
  2658.                                 wait = _content;
  2659.                             } else {
  2660.                                 content = _content;
  2661.                                 wait = this.__internal.delay;
  2662.                             }
  2663.                             break;
  2664.                         case 2:
  2665.                             content = _content;
  2666.                             wait = _wait;
  2667.                             break;
  2668.                         }
  2669.                         this.__internal.closeButton = alertify.defaults.notifier.closeButton;
  2670.                         // set contents
  2671.                         if (typeof content !== 'undefined') {
  2672.                             this.setContent(content);
  2673.                         }
  2674.                         // append or insert
  2675.                         if (notifier.__internal.position.indexOf('top') < 0) {
  2676.                             element.appendChild(this.element);
  2677.                         } else {
  2678.                             element.insertBefore(this.element, element.firstChild);
  2679.                         }
  2680.                         reflow = this.element.offsetWidth;
  2681.                         addClass(this.element, classes.visible);
  2682.                         // attach click event
  2683.                         on(this.element, 'click', this.__internal.clickHandler);
  2684.                         return this.delay(wait);
  2685.                     }
  2686.                     return this;
  2687.                 },
  2688.                 /*
  2689.                  * {Function} callback function to be invoked before dismissing the notification message.
  2690.                  * Remarks: A return value === 'false' will cancel the dismissal
  2691.                  *
  2692.                  */
  2693.                 ondismiss: function () { },
  2694.                 /*
  2695.                  * {Function} callback function to be invoked when the message is dismissed.
  2696.                  *
  2697.                  */
  2698.                 callback: callback,
  2699.                 /*
  2700.                  * Dismisses the notification message
  2701.                  * @param {Boolean} clicked A flag indicating if the dismissal was caused by a click.
  2702.                  *
  2703.                  */
  2704.                 dismiss: function (clicked) {
  2705.                     if (this.__internal.pushed) {
  2706.                         clearTimers(this);
  2707.                         if (!(typeof this.ondismiss === 'function' && this.ondismiss.call(this) === false)) {
  2708.                             //detach click event
  2709.                             off(this.element, 'click', this.__internal.clickHandler);
  2710.                             // ensure element exists
  2711.                             if (typeof this.element !== 'undefined' && this.element.parentNode === element) {
  2712.                                 //transition end or fallback
  2713.                                 this.__internal.transitionTimeout = setTimeout(this.__internal.transitionEndHandler, transition.supported ? 1000 : 100);
  2714.                                 removeClass(this.element, classes.visible);
  2715.  
  2716.                                 // custom callback on dismiss
  2717.                                 if (typeof this.callback === 'function') {
  2718.                                     this.callback.call(this, clicked);
  2719.                                 }
  2720.                             }
  2721.                             popInstance(this);
  2722.                         }
  2723.                     }
  2724.                     return this;
  2725.                 },
  2726.                 /*
  2727.                  * Delays the notification message dismissal
  2728.                  * @param {Number} wait The time (in seconds) to wait before the message is dismissed, a value of 0 means keep open till clicked.
  2729.                  *
  2730.                  */
  2731.                 delay: function (wait) {
  2732.                     clearTimers(this);
  2733.                     this.__internal.delay = typeof wait !== 'undefined' && !isNaN(+wait) ? +wait : notifier.__internal.delay;
  2734.                     if (this.__internal.delay > 0) {
  2735.                         var  self = this;
  2736.                         this.__internal.timer = setTimeout(function () { self.dismiss(); }, this.__internal.delay * 1000);
  2737.                     }
  2738.                     return this;
  2739.                 },
  2740.                 /*
  2741.                  * Sets the notification message contents
  2742.                  * @param {string or DOMElement} content The notification message content
  2743.                  *
  2744.                  */
  2745.                 setContent: function (content) {
  2746.                     if (typeof content === 'string') {
  2747.                         clearContents(this.element);
  2748.                         this.element.innerHTML = content;
  2749.                     } else if (content instanceof window.HTMLElement && this.element.firstChild !== content) {
  2750.                         clearContents(this.element);
  2751.                         this.element.appendChild(content);
  2752.                     }
  2753.                     if(this.__internal.closeButton){
  2754.                         var close = document.createElement('span');
  2755.                         addClass(close, classes.close);
  2756.                         close.setAttribute('data-close', true);
  2757.                         this.element.appendChild(close);
  2758.                     }
  2759.                     return this;
  2760.                 },
  2761.                 /*
  2762.                  * Dismisses all open notifications except this.
  2763.                  *
  2764.                  */
  2765.                 dismissOthers: function () {
  2766.                     notifier.dismissAll(this);
  2767.                     return this;
  2768.                 }
  2769.             });
  2770.         }
  2771.  
  2772.         //notifier api
  2773.         return {
  2774.             /**
  2775.              * Gets or Sets notifier settings.
  2776.              *
  2777.              * @param {string} key The setting name
  2778.              * @param {Variant} value The setting value.
  2779.              *
  2780.              * @return {Object}     if the called as a setter, return the notifier instance.
  2781.              */
  2782.             setting: function (key, value) {
  2783.                 //ensure init
  2784.                 initialize(this);
  2785.  
  2786.                 if (typeof value === 'undefined') {
  2787.                     //get
  2788.                     return this.__internal[key];
  2789.                 } else {
  2790.                     //set
  2791.                     switch (key) {
  2792.                     case 'position':
  2793.                         this.__internal.position = value;
  2794.                         updatePosition(this);
  2795.                         break;
  2796.                     case 'delay':
  2797.                         this.__internal.delay = value;
  2798.                         break;
  2799.                     }
  2800.                 }
  2801.                 return this;
  2802.             },
  2803.             /**
  2804.              * [Alias] Sets dialog settings/options
  2805.              */
  2806.             set:function(key,value){
  2807.                 this.setting(key,value);
  2808.                 return this;
  2809.             },
  2810.             /**
  2811.              * [Alias] Gets dialog settings/options
  2812.              */
  2813.             get:function(key){
  2814.                 return this.setting(key);
  2815.             },
  2816.             /**
  2817.              * Creates a new notification message
  2818.              *
  2819.              * @param {string} type The type of notification message (simply a CSS class name 'ajs-{type}' to be added).
  2820.              * @param {Function} callback  A callback function to be invoked when the message is dismissed.
  2821.              *
  2822.              * @return {undefined}
  2823.              */
  2824.             create: function (type, callback) {
  2825.                 //ensure notifier init
  2826.                 initialize(this);
  2827.                 //create new notification message
  2828.                 var div = document.createElement('div');
  2829.                 div.className = classes.message + ((typeof type === 'string' && type !== '') ? ' ajs-' + type : '');
  2830.                 return create(div, callback);
  2831.             },
  2832.             /**
  2833.              * Dismisses all open notifications.
  2834.              *
  2835.              * @param {Object} excpet [optional] The notification object to exclude from dismissal.
  2836.              *
  2837.              */
  2838.             dismissAll: function (except) {
  2839.                 var clone = openInstances.slice(0);
  2840.                 for (var x = 0; x < clone.length; x += 1) {
  2841.                     var  instance = clone[x];
  2842.                     if (except === undefined || except !== instance) {
  2843.                         instance.dismiss();
  2844.                     }
  2845.                 }
  2846.             }
  2847.         };
  2848.     })();
  2849.     /**
  2850.      * Alertify public API
  2851.      * This contains everything that is exposed through the alertify object.
  2852.      *
  2853.      * @return {Object}
  2854.      */
  2855.     function Alertify() {
  2856.  
  2857.         // holds a references of created dialogs
  2858.         var dialogs = {};
  2859.  
  2860.         /**
  2861.          * Extends a given prototype by merging properties from base into sub.
  2862.          *
  2863.          * @sub {Object} sub The prototype being overwritten.
  2864.          * @base {Object} base The prototype being written.
  2865.          *
  2866.          * @return {Object} The extended prototype.
  2867.          */
  2868.         function extend(sub, base) {
  2869.             // copy dialog pototype over definition.
  2870.             for (var prop in base) {
  2871.                 if (base.hasOwnProperty(prop)) {
  2872.                     sub[prop] = base[prop];
  2873.                 }
  2874.             }
  2875.             return sub;
  2876.         }
  2877.  
  2878.  
  2879.         /**
  2880.         * Helper: returns a dialog instance from saved dialogs.
  2881.         * and initializes the dialog if its not already initialized.
  2882.         *
  2883.         * @name {String} name The dialog name.
  2884.         *
  2885.         * @return {Object} The dialog instance.
  2886.         */
  2887.         function get_dialog(name) {
  2888.             var dialog = dialogs[name].dialog;
  2889.             //initialize the dialog if its not already initialized.
  2890.             if (dialog && typeof dialog.__init === 'function') {
  2891.                 dialog.__init(dialog);
  2892.             }
  2893.             return dialog;
  2894.         }
  2895.  
  2896.         /**
  2897.          * Helper:  registers a new dialog definition.
  2898.          *
  2899.          * @name {String} name The dialog name.
  2900.          * @Factory {Function} Factory a function resposible for creating dialog prototype.
  2901.          * @transient {Boolean} transient True to create a new dialog instance each time the dialog is invoked, false otherwise.
  2902.          * @base {String} base the name of another dialog to inherit from.
  2903.          *
  2904.          * @return {Object} The dialog definition.
  2905.          */
  2906.         function register(name, Factory, transient, base) {
  2907.             var definition = {
  2908.                 dialog: null,
  2909.                 factory: Factory
  2910.             };
  2911.  
  2912.             //if this is based on an existing dialog, create a new definition
  2913.             //by applying the new protoype over the existing one.
  2914.             if (base !== undefined) {
  2915.                 definition.factory = function () {
  2916.                     return extend(new dialogs[base].factory(), new Factory());
  2917.                 };
  2918.             }
  2919.  
  2920.             if (!transient) {
  2921.                 //create a new definition based on dialog
  2922.                 definition.dialog = extend(new definition.factory(), dialog);
  2923.             }
  2924.             return dialogs[name] = definition;
  2925.         }
  2926.  
  2927.         return {
  2928.             /**
  2929.              * Alertify defaults
  2930.              *
  2931.              * @type {Object}
  2932.              */
  2933.             defaults: defaults,
  2934.             /**
  2935.              * Dialogs factory
  2936.              *
  2937.              * @param {string}      Dialog name.
  2938.              * @param {Function}    A Dialog factory function.
  2939.              * @param {Boolean}     Indicates whether to create a singleton or transient dialog.
  2940.              * @param {String}      The name of the base type to inherit from.
  2941.              */
  2942.             dialog: function (name, Factory, transient, base) {
  2943.  
  2944.                 // get request, create a new instance and return it.
  2945.                 if (typeof Factory !== 'function') {
  2946.                     return get_dialog(name);
  2947.                 }
  2948.  
  2949.                 if (this.hasOwnProperty(name)) {
  2950.                     throw new Error('alertify.dialog: name already exists');
  2951.                 }
  2952.  
  2953.                 // register the dialog
  2954.                 var definition = register(name, Factory, transient, base);
  2955.  
  2956.                 if (transient) {
  2957.  
  2958.                     // make it public
  2959.                     this[name] = function () {
  2960.                         //if passed with no params, consider it a get request
  2961.                         if (arguments.length === 0) {
  2962.                             return definition.dialog;
  2963.                         } else {
  2964.                             var instance = extend(new definition.factory(), dialog);
  2965.                             //ensure init
  2966.                             if (instance && typeof instance.__init === 'function') {
  2967.                                 instance.__init(instance);
  2968.                             }
  2969.                             instance['main'].apply(instance, arguments);
  2970.                             return instance['show'].apply(instance);
  2971.                         }
  2972.                     };
  2973.                 } else {
  2974.                     // make it public
  2975.                     this[name] = function () {
  2976.                         //ensure init
  2977.                         if (definition.dialog && typeof definition.dialog.__init === 'function') {
  2978.                             definition.dialog.__init(definition.dialog);
  2979.                         }
  2980.                         //if passed with no params, consider it a get request
  2981.                         if (arguments.length === 0) {
  2982.                             return definition.dialog;
  2983.                         } else {
  2984.                             var dialog = definition.dialog;
  2985.                             dialog['main'].apply(definition.dialog, arguments);
  2986.                             return dialog['show'].apply(definition.dialog);
  2987.                         }
  2988.                     };
  2989.                 }
  2990.             },
  2991.             /**
  2992.              * Close all open dialogs.
  2993.              *
  2994.              * @param {Object} excpet [optional] The dialog object to exclude from closing.
  2995.              *
  2996.              * @return {undefined}
  2997.              */
  2998.             closeAll: function (except) {
  2999.                 var clone = openDialogs.slice(0);
  3000.                 for (var x = 0; x < clone.length; x += 1) {
  3001.                     var instance = clone[x];
  3002.                     if (except === undefined || except !== instance) {
  3003.                         instance.close();
  3004.                     }
  3005.                 }
  3006.             },
  3007.             /**
  3008.              * Gets or Sets dialog settings/options. if the dialog is transient, this call does nothing.
  3009.              *
  3010.              * @param {string} name The dialog name.
  3011.              * @param {String|Object} key A string specifying a propery name or a collection of key/value pairs.
  3012.              * @param {Variant} value Optional, the value associated with the key (in case it was a string).
  3013.              *
  3014.              * @return {undefined}
  3015.              */
  3016.             setting: function (name, key, value) {
  3017.  
  3018.                 if (name === 'notifier') {
  3019.                     return notifier.setting(key, value);
  3020.                 }
  3021.  
  3022.                 var dialog = get_dialog(name);
  3023.                 if (dialog) {
  3024.                     return dialog.setting(key, value);
  3025.                 }
  3026.             },
  3027.             /**
  3028.              * [Alias] Sets dialog settings/options
  3029.              */
  3030.             set: function(name,key,value){
  3031.                 return this.setting(name, key,value);
  3032.             },
  3033.             /**
  3034.              * [Alias] Gets dialog settings/options
  3035.              */
  3036.             get: function(name, key){
  3037.                 return this.setting(name, key);
  3038.             },
  3039.             /**
  3040.              * Creates a new notification message.
  3041.              * If a type is passed, a class name "ajs-{type}" will be added.
  3042.              * This allows for custom look and feel for various types of notifications.
  3043.              *
  3044.              * @param  {String | DOMElement}    [message=undefined]           Message text
  3045.              * @param  {String}                 [type='']                     Type of log message
  3046.              * @param  {String}                 [wait='']                     Time (in seconds) to wait before auto-close
  3047.              * @param  {Function}               [callback=undefined]    A callback function to be invoked when the log is closed.
  3048.              *
  3049.              * @return {Object} Notification object.
  3050.              */
  3051.             notify: function (message, type, wait, callback) {
  3052.                 return notifier.create(type, callback).push(message, wait);
  3053.             },
  3054.             /**
  3055.              * Creates a new notification message.
  3056.              *
  3057.              * @param  {String}           [message=undefined]           Message text
  3058.              * @param  {String}     [wait='']                     Time (in seconds) to wait before auto-close
  3059.              * @param  {Function}   [callback=undefined]    A callback function to be invoked when the log is closed.
  3060.              *
  3061.              * @return {Object} Notification object.
  3062.              */
  3063.             message: function (message, wait, callback) {
  3064.                 return notifier.create(null, callback).push(message, wait);
  3065.             },
  3066.             /**
  3067.              * Creates a new notification message of type 'success'.
  3068.              *
  3069.              * @param  {String}           [message=undefined]           Message text
  3070.              * @param  {String}     [wait='']                     Time (in seconds) to wait before auto-close
  3071.              * @param  {Function}   [callback=undefined]    A callback function to be invoked when the log is closed.
  3072.              *
  3073.              * @return {Object} Notification object.
  3074.              */
  3075.             success: function (message, wait, callback) {
  3076.                 return notifier.create('success', callback).push(message, wait);
  3077.             },
  3078.             /**
  3079.              * Creates a new notification message of type 'error'.
  3080.              *
  3081.              * @param  {String}           [message=undefined]           Message text
  3082.              * @param  {String}     [wait='']                     Time (in seconds) to wait before auto-close
  3083.              * @param  {Function}   [callback=undefined]    A callback function to be invoked when the log is closed.
  3084.              *
  3085.              * @return {Object} Notification object.
  3086.              */
  3087.             error: function (message, wait, callback) {
  3088.                 return notifier.create('error', callback).push(message, wait);
  3089.             },
  3090.             /**
  3091.              * Creates a new notification message of type 'warning'.
  3092.              *
  3093.              * @param  {String}           [message=undefined]           Message text
  3094.              * @param  {String}     [wait='']                     Time (in seconds) to wait before auto-close
  3095.              * @param  {Function}   [callback=undefined]    A callback function to be invoked when the log is closed.
  3096.              *
  3097.              * @return {Object} Notification object.
  3098.              */
  3099.             warning: function (message, wait, callback) {
  3100.                 return notifier.create('warning', callback).push(message, wait);
  3101.             },
  3102.             /**
  3103.              * Dismisses all open notifications
  3104.              *
  3105.              * @return {undefined}
  3106.              */
  3107.             dismissAll: function () {
  3108.                 notifier.dismissAll();
  3109.             }
  3110.         };
  3111.     }
  3112.     var alertify = new Alertify();
  3113.  
  3114.     /**
  3115.     * Alert dialog definition
  3116.     *
  3117.     * invoked by:
  3118.     * alertify.alert(message);
  3119.     * alertify.alert(title, message);
  3120.     * alertify.alert(message, onok);
  3121.     * alertify.alert(title, message, onok);
  3122.      */
  3123.     alertify.dialog('alert', function () {
  3124.         return {
  3125.             main: function (_title, _message, _onok) {
  3126.                 var title, message, onok;
  3127.                 switch (arguments.length) {
  3128.                 case 1:
  3129.                     message = _title;
  3130.                     break;
  3131.                 case 2:
  3132.                     if (typeof _message === 'function') {
  3133.                         message = _title;
  3134.                         onok = _message;
  3135.                     } else {
  3136.                         title = _title;
  3137.                         message = _message;
  3138.                     }
  3139.                     break;
  3140.                 case 3:
  3141.                     title = _title;
  3142.                     message = _message;
  3143.                     onok = _onok;
  3144.                     break;
  3145.                 }
  3146.                 this.set('title', title);
  3147.                 this.set('message', message);
  3148.                 this.set('onok', onok);
  3149.                 return this;
  3150.             },
  3151.             setup: function () {
  3152.                 return {
  3153.                     buttons: [
  3154.                         {
  3155.                             text: alertify.defaults.glossary.ok,
  3156.                             key: keys.ESC,
  3157.                             invokeOnClose: true,
  3158.                             className: alertify.defaults.theme.ok,
  3159.                         }
  3160.                     ],
  3161.                     focus: {
  3162.                         element: 0,
  3163.                         select: false
  3164.                     },
  3165.                     options: {
  3166.                         maximizable: false,
  3167.                         resizable: false
  3168.                     }
  3169.                 };
  3170.             },
  3171.             build: function () {
  3172.                 // nothing
  3173.             },
  3174.             prepare: function () {
  3175.                 //nothing
  3176.             },
  3177.             setMessage: function (message) {
  3178.                 this.setContent(message);
  3179.             },
  3180.             settings: {
  3181.                 message: undefined,
  3182.                 onok: undefined,
  3183.                 label: undefined,
  3184.             },
  3185.             settingUpdated: function (key, oldValue, newValue) {
  3186.                 switch (key) {
  3187.                 case 'message':
  3188.                     this.setMessage(newValue);
  3189.                     break;
  3190.                 case 'label':
  3191.                     if (this.__internal.buttons[0].element) {
  3192.                         this.__internal.buttons[0].element.innerHTML = newValue;
  3193.                     }
  3194.                     break;
  3195.                 }
  3196.             },
  3197.             callback: function (closeEvent) {
  3198.                 if (typeof this.get('onok') === 'function') {
  3199.                     var returnValue = this.get('onok').call(this, closeEvent);
  3200.                     if (typeof returnValue !== 'undefined') {
  3201.                         closeEvent.cancel = !returnValue;
  3202.                     }
  3203.                 }
  3204.             }
  3205.         };
  3206.     });
  3207.     /**
  3208.      * Confirm dialog object
  3209.      *
  3210.      *      alertify.confirm(message);
  3211.      *      alertify.confirm(message, onok);
  3212.      *      alertify.confirm(message, onok, oncancel);
  3213.      *      alertify.confirm(title, message, onok, oncancel);
  3214.      */
  3215.     alertify.dialog('confirm', function () {
  3216.  
  3217.         var autoConfirm = {
  3218.             timer: null,
  3219.             index: null,
  3220.             text: null,
  3221.             duration: null,
  3222.             task: function (event, self) {
  3223.                 if (self.isOpen()) {
  3224.                     self.__internal.buttons[autoConfirm.index].element.innerHTML = autoConfirm.text + ' (&#8207;' + autoConfirm.duration + '&#8207;) ';
  3225.                     autoConfirm.duration -= 1;
  3226.                     if (autoConfirm.duration === -1) {
  3227.                         clearAutoConfirm(self);
  3228.                         var button = self.__internal.buttons[autoConfirm.index];
  3229.                         var closeEvent = createCloseEvent(autoConfirm.index, button);
  3230.  
  3231.                         if (typeof self.callback === 'function') {
  3232.                             self.callback.apply(self, [closeEvent]);
  3233.                         }
  3234.                         //close the dialog.
  3235.                         if (closeEvent.close !== false) {
  3236.                             self.close();
  3237.                         }
  3238.                     }
  3239.                 } else {
  3240.                     clearAutoConfirm(self);
  3241.                 }
  3242.             }
  3243.         };
  3244.  
  3245.         function clearAutoConfirm(self) {
  3246.             if (autoConfirm.timer !== null) {
  3247.                 clearInterval(autoConfirm.timer);
  3248.                 autoConfirm.timer = null;
  3249.                 self.__internal.buttons[autoConfirm.index].element.innerHTML = autoConfirm.text;
  3250.             }
  3251.         }
  3252.  
  3253.         function startAutoConfirm(self, index, duration) {
  3254.             clearAutoConfirm(self);
  3255.             autoConfirm.duration = duration;
  3256.             autoConfirm.index = index;
  3257.             autoConfirm.text = self.__internal.buttons[index].element.innerHTML;
  3258.             autoConfirm.timer = setInterval(delegate(self, autoConfirm.task), 1000);
  3259.             autoConfirm.task(null, self);
  3260.         }
  3261.  
  3262.  
  3263.         return {
  3264.             main: function (_title, _message, _onok, _oncancel) {
  3265.                 var title, message, onok, oncancel;
  3266.                 switch (arguments.length) {
  3267.                 case 1:
  3268.                     message = _title;
  3269.                     break;
  3270.                 case 2:
  3271.                     message = _title;
  3272.                     onok = _message;
  3273.                     break;
  3274.                 case 3:
  3275.                     message = _title;
  3276.                     onok = _message;
  3277.                     oncancel = _onok;
  3278.                     break;
  3279.                 case 4:
  3280.                     title = _title;
  3281.                     message = _message;
  3282.                     onok = _onok;
  3283.                     oncancel = _oncancel;
  3284.                     break;
  3285.                 }
  3286.                 this.set('title', title);
  3287.                 this.set('message', message);
  3288.                 this.set('onok', onok);
  3289.                 this.set('oncancel', oncancel);
  3290.                 return this;
  3291.             },
  3292.             setup: function () {
  3293.                 return {
  3294.                     buttons: [
  3295.                         {
  3296.                             text: alertify.defaults.glossary.ok,
  3297.                             key: keys.ENTER,
  3298.                             className: alertify.defaults.theme.ok,
  3299.                         },
  3300.                         {
  3301.                             text: alertify.defaults.glossary.cancel,
  3302.                             key: keys.ESC,
  3303.                             invokeOnClose: true,
  3304.                             className: alertify.defaults.theme.cancel,
  3305.                         }
  3306.                     ],
  3307.                     focus: {
  3308.                         element: 0,
  3309.                         select: false
  3310.                     },
  3311.                     options: {
  3312.                         maximizable: false,
  3313.                         resizable: false
  3314.                     }
  3315.                 };
  3316.             },
  3317.             build: function () {
  3318.                 //nothing
  3319.             },
  3320.             prepare: function () {
  3321.                 //nothing
  3322.             },
  3323.             setMessage: function (message) {
  3324.                 this.setContent(message);
  3325.             },
  3326.             settings: {
  3327.                 message: null,
  3328.                 labels: null,
  3329.                 onok: null,
  3330.                 oncancel: null,
  3331.                 defaultFocus: null,
  3332.                 reverseButtons: null,
  3333.             },
  3334.             settingUpdated: function (key, oldValue, newValue) {
  3335.                 switch (key) {
  3336.                 case 'message':
  3337.                     this.setMessage(newValue);
  3338.                     break;
  3339.                 case 'labels':
  3340.                     if ('ok' in newValue && this.__internal.buttons[0].element) {
  3341.                         this.__internal.buttons[0].text = newValue.ok;
  3342.                         this.__internal.buttons[0].element.innerHTML = newValue.ok;
  3343.                     }
  3344.                     if ('cancel' in newValue && this.__internal.buttons[1].element) {
  3345.                         this.__internal.buttons[1].text = newValue.cancel;
  3346.                         this.__internal.buttons[1].element.innerHTML = newValue.cancel;
  3347.                     }
  3348.                     break;
  3349.                 case 'reverseButtons':
  3350.                     if (newValue === true) {
  3351.                         this.elements.buttons.primary.appendChild(this.__internal.buttons[0].element);
  3352.                     } else {
  3353.                         this.elements.buttons.primary.appendChild(this.__internal.buttons[1].element);
  3354.                     }
  3355.                     break;
  3356.                 case 'defaultFocus':
  3357.                     this.__internal.focus.element = newValue === 'ok' ? 0 : 1;
  3358.                     break;
  3359.                 }
  3360.             },
  3361.             callback: function (closeEvent) {
  3362.                 clearAutoConfirm(this);
  3363.                 var returnValue;
  3364.                 switch (closeEvent.index) {
  3365.                 case 0:
  3366.                     if (typeof this.get('onok') === 'function') {
  3367.                         returnValue = this.get('onok').call(this, closeEvent);
  3368.                         if (typeof returnValue !== 'undefined') {
  3369.                             closeEvent.cancel = !returnValue;
  3370.                         }
  3371.                     }
  3372.                     break;
  3373.                 case 1:
  3374.                     if (typeof this.get('oncancel') === 'function') {
  3375.                         returnValue = this.get('oncancel').call(this, closeEvent);
  3376.                         if (typeof returnValue !== 'undefined') {
  3377.                             closeEvent.cancel = !returnValue;
  3378.                         }
  3379.                     }
  3380.                     break;
  3381.                 }
  3382.             },
  3383.             autoOk: function (duration) {
  3384.                 startAutoConfirm(this, 0, duration);
  3385.                 return this;
  3386.             },
  3387.             autoCancel: function (duration) {
  3388.                 startAutoConfirm(this, 1, duration);
  3389.                 return this;
  3390.             }
  3391.         };
  3392.     });
  3393.     /**
  3394.      * Prompt dialog object
  3395.      *
  3396.      * invoked by:
  3397.      *      alertify.prompt(message);
  3398.      *      alertify.prompt(message, value);
  3399.      *      alertify.prompt(message, value, onok);
  3400.      *      alertify.prompt(message, value, onok, oncancel);
  3401.      *      alertify.prompt(title, message, value, onok, oncancel);
  3402.      */
  3403.     alertify.dialog('prompt', function () {
  3404.         var input = document.createElement('INPUT');
  3405.         var p = document.createElement('P');
  3406.         return {
  3407.             main: function (_title, _message, _value, _onok, _oncancel) {
  3408.                 var title, message, value, onok, oncancel;
  3409.                 switch (arguments.length) {
  3410.                 case 1:
  3411.                     message = _title;
  3412.                     break;
  3413.                 case 2:
  3414.                     message = _title;
  3415.                     value = _message;
  3416.                     break;
  3417.                 case 3:
  3418.                     message = _title;
  3419.                     value = _message;
  3420.                     onok = _value;
  3421.                     break;
  3422.                 case 4:
  3423.                     message = _title;
  3424.                     value = _message;
  3425.                     onok = _value;
  3426.                     oncancel = _onok;
  3427.                     break;
  3428.                 case 5:
  3429.                     title = _title;
  3430.                     message = _message;
  3431.                     value = _value;
  3432.                     onok = _onok;
  3433.                     oncancel = _oncancel;
  3434.                     break;
  3435.                 }
  3436.                 this.set('title', title);
  3437.                 this.set('message', message);
  3438.                 this.set('value', value);
  3439.                 this.set('onok', onok);
  3440.                 this.set('oncancel', oncancel);
  3441.                 return this;
  3442.             },
  3443.             setup: function () {
  3444.                 return {
  3445.                     buttons: [
  3446.                         {
  3447.                             text: alertify.defaults.glossary.ok,
  3448.                             key: keys.ENTER,
  3449.                             className: alertify.defaults.theme.ok,
  3450.                         },
  3451.                         {
  3452.                             text: alertify.defaults.glossary.cancel,
  3453.                             key: keys.ESC,
  3454.                             invokeOnClose: true,
  3455.                             className: alertify.defaults.theme.cancel,
  3456.                         }
  3457.                     ],
  3458.                     focus: {
  3459.                         element: input,
  3460.                         select: true
  3461.                     },
  3462.                     options: {
  3463.                         maximizable: false,
  3464.                         resizable: false
  3465.                     }
  3466.                 };
  3467.             },
  3468.             build: function () {
  3469.                 input.className = alertify.defaults.theme.input;
  3470.                 input.setAttribute('type', 'text');
  3471.                 input.value = this.get('value');
  3472.                 this.elements.content.appendChild(p);
  3473.                 this.elements.content.appendChild(input);
  3474.             },
  3475.             prepare: function () {
  3476.                 //nothing
  3477.             },
  3478.             setMessage: function (message) {
  3479.                 if (typeof message === 'string') {
  3480.                     clearContents(p);
  3481.                     p.innerHTML = message;
  3482.                 } else if (message instanceof window.HTMLElement && p.firstChild !== message) {
  3483.                     clearContents(p);
  3484.                     p.appendChild(message);
  3485.                 }
  3486.             },
  3487.             settings: {
  3488.                 message: undefined,
  3489.                 labels: undefined,
  3490.                 onok: undefined,
  3491.                 oncancel: undefined,
  3492.                 value: '',
  3493.                 type:'text',
  3494.                 reverseButtons: undefined,
  3495.             },
  3496.             settingUpdated: function (key, oldValue, newValue) {
  3497.                 switch (key) {
  3498.                 case 'message':
  3499.                     this.setMessage(newValue);
  3500.                     break;
  3501.                 case 'value':
  3502.                     input.value = newValue;
  3503.                     break;
  3504.                 case 'type':
  3505.                     switch (newValue) {
  3506.                     case 'text':
  3507.                     case 'color':
  3508.                     case 'date':
  3509.                     case 'datetime-local':
  3510.                     case 'email':
  3511.                     case 'month':
  3512.                     case 'number':
  3513.                     case 'password':
  3514.                     case 'search':
  3515.                     case 'tel':
  3516.                     case 'time':
  3517.                     case 'week':
  3518.                         input.type = newValue;
  3519.                         break;
  3520.                     default:
  3521.                         input.type = 'text';
  3522.                         break;
  3523.                     }
  3524.                     break;
  3525.                 case 'labels':
  3526.                     if (newValue.ok && this.__internal.buttons[0].element) {
  3527.                         this.__internal.buttons[0].element.innerHTML = newValue.ok;
  3528.                     }
  3529.                     if (newValue.cancel && this.__internal.buttons[1].element) {
  3530.                         this.__internal.buttons[1].element.innerHTML = newValue.cancel;
  3531.                     }
  3532.                     break;
  3533.                 case 'reverseButtons':
  3534.                     if (newValue === true) {
  3535.                         this.elements.buttons.primary.appendChild(this.__internal.buttons[0].element);
  3536.                     } else {
  3537.                         this.elements.buttons.primary.appendChild(this.__internal.buttons[1].element);
  3538.                     }
  3539.                     break;
  3540.                 }
  3541.             },
  3542.             callback: function (closeEvent) {
  3543.                 var returnValue;
  3544.                 switch (closeEvent.index) {
  3545.                 case 0:
  3546.                     this.settings.value = input.value;
  3547.                     if (typeof this.get('onok') === 'function') {
  3548.                         returnValue = this.get('onok').call(this, closeEvent, this.settings.value);
  3549.                         if (typeof returnValue !== 'undefined') {
  3550.                             closeEvent.cancel = !returnValue;
  3551.                         }
  3552.                     }
  3553.                     break;
  3554.                 case 1:
  3555.                     if (typeof this.get('oncancel') === 'function') {
  3556.                         returnValue = this.get('oncancel').call(this, closeEvent);
  3557.                         if (typeof returnValue !== 'undefined') {
  3558.                             closeEvent.cancel = !returnValue;
  3559.                         }
  3560.                     }
  3561.                     if(!closeEvent.cancel){
  3562.                         input.value = this.settings.value;
  3563.                     }
  3564.                     break;
  3565.                 }
  3566.             }
  3567.         };
  3568.     });
  3569.  
  3570.     // CommonJS
  3571.     if ( typeof module === 'object' && typeof module.exports === 'object' ) {
  3572.         module.exports = alertify;
  3573.     // AMD
  3574.     } else if ( typeof define === 'function' && define.amd) {
  3575.         define( [], function () {
  3576.             return alertify;
  3577.         } );
  3578.     // window
  3579.     } else if ( !window.alertify ) {
  3580.         window.alertify = alertify;
  3581.     }
  3582.  
  3583. } ( typeof window !== 'undefined' ? window : this ) );

Paste-bin is for source code and general debugging text.

Login or Register to edit, delete and keep track of your pastes and more.

Raw Paste

Login or Register to edit or fork this paste. It's free.