PageSourceSearch

https://sifhn.com:10101/alertifyjs/alertify.js

js sifhn.com collected 2026-10-02 01:43:52 UTC 139,423 bytes, 3,589 lines download raw bytes

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

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.