| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702 |
- /**
- * alertifyjs 1.13.1 http://alertifyjs.com
- * AlertifyJS is a javascript framework for developing pretty browser dialogs and notifications.
- * Copyright 2019 Mohammad Younes <Mohammad@alertifyjs.com> (http://alertifyjs.com)
- * Licensed under GPL 3 <https://opensource.org/licenses/gpl-3.0>*/
- (function (window) {
- 'use strict';
- var NOT_DISABLED_NOT_RESET = ':not(:disabled):not(.ajs-reset)';
- /**
- * Keys enum
- * @type {Object}
- */
- var keys = {
- ENTER: 13,
- ESC: 27,
- F1: 112,
- F12: 123,
- LEFT: 37,
- RIGHT: 39,
- TAB: 9
- };
- /**
- * Default options
- * @type {Object}
- */
- var defaults = {
- autoReset: true,
- basic: false,
- closable: true,
- closableByDimmer: true,
- invokeOnCloseOff: false,
- frameless: false,
- defaultFocusOff: false,
- maintainFocus: true, //global default not per instance, applies to all dialogs
- maximizable: true,
- modal: true,
- movable: true,
- moveBounded: false,
- overflow: true,
- padding: true,
- pinnable: true,
- pinned: true,
- preventBodyShift: false, //global default not per instance, applies to all dialogs
- resizable: true,
- startMaximized: false,
- transition: 'pulse',
- transitionOff: false,
- tabbable: ['button', '[href]', 'input', 'select', 'textarea', '[tabindex]:not([tabindex^="-"])' + NOT_DISABLED_NOT_RESET].join(NOT_DISABLED_NOT_RESET + ','),//global
- notifier: {
- delay: 5,
- position: 'bottom-right',
- closeButton: false,
- classes: {
- base: 'alertify-notifier',
- prefix: 'ajs-',
- message: 'ajs-message',
- top: 'ajs-top',
- right: 'ajs-right',
- bottom: 'ajs-bottom',
- left: 'ajs-left',
- center: 'ajs-center',
- visible: 'ajs-visible',
- hidden: 'ajs-hidden',
- close: 'ajs-close'
- }
- },
- glossary: {
- title: 'AlertifyJS',
- ok: 'OK',
- cancel: 'Cancel',
- acccpt: 'Accept',
- deny: 'Deny',
- confirm: 'Confirm',
- decline: 'Decline',
- close: 'Close',
- maximize: 'Maximize',
- restore: 'Restore',
- },
- theme: {
- input: 'ajs-input',
- ok: 'ajs-ok',
- cancel: 'ajs-cancel',
- },
- hooks: {
- preinit: function () {
- },
- postinit: function () {
- }
- }
- };
-
- //holds open dialogs instances
- var openDialogs = [];
-
- /**
- * [Helper] Adds the specified class(es) to the element.
- *
- * @element {node} The element
- * @className {string} One or more space-separated classes to be added to the class attribute of the element.
- *
- * @return {undefined}
- */
- function addClass(element, classNames) {
- element.className += ' ' + classNames;
- }
-
- /**
- * [Helper] Removes the specified class(es) from the element.
- *
- * @element {node} The element
- * @className {string} One or more space-separated classes to be removed from the class attribute of the element.
- *
- * @return {undefined}
- */
- function removeClass(element, classNames) {
- var original = element.className.split(' ');
- var toBeRemoved = classNames.split(' ');
- for (var x = 0; x < toBeRemoved.length; x += 1) {
- var index = original.indexOf(toBeRemoved[x]);
- if (index > -1) {
- original.splice(index, 1);
- }
- }
- element.className = original.join(' ');
- }
-
- /**
- * [Helper] Checks if the document is RTL
- *
- * @return {Boolean} True if the document is RTL, false otherwise.
- */
- function isRightToLeft() {
- return window.getComputedStyle(document.body).direction === 'rtl';
- }
-
- /**
- * [Helper] Get the document current scrollTop
- *
- * @return {Number} current document scrollTop value
- */
- function getScrollTop() {
- return ((document.documentElement && document.documentElement.scrollTop) || document.body.scrollTop);
- }
-
- /**
- * [Helper] Get the document current scrollLeft
- *
- * @return {Number} current document scrollLeft value
- */
- function getScrollLeft() {
- return ((document.documentElement && document.documentElement.scrollLeft) || document.body.scrollLeft);
- }
-
- /**
- * Helper: clear contents
- *
- */
- function clearContents(element) {
- while (element.lastChild) {
- element.removeChild(element.lastChild);
- }
- }
-
- /**
- * Extends a given prototype by merging properties from base into sub.
- *
- * @sub {Object} sub The prototype being overwritten.
- * @base {Object} base The prototype being written.
- *
- * @return {Object} The extended prototype.
- */
- function copy(src) {
- if (null === src) {
- return src;
- }
- var cpy;
- if (Array.isArray(src)) {
- cpy = [];
- for (var x = 0; x < src.length; x += 1) {
- cpy.push(copy(src[x]));
- }
- return cpy;
- }
-
- if (src instanceof Date) {
- return new Date(src.getTime());
- }
-
- if (src instanceof RegExp) {
- cpy = new RegExp(src.source);
- cpy.global = src.global;
- cpy.ignoreCase = src.ignoreCase;
- cpy.multiline = src.multiline;
- cpy.lastIndex = src.lastIndex;
- return cpy;
- }
-
- if (typeof src === 'object') {
- cpy = {};
- // copy dialog pototype over definition.
- for (var prop in src) {
- if (src.hasOwnProperty(prop)) {
- cpy[prop] = copy(src[prop]);
- }
- }
- return cpy;
- }
- return src;
- }
-
- /**
- * Helper: destruct the dialog
- *
- */
- function destruct(instance, initialize) {
- if (instance.elements) {
- //delete the dom and it's references.
- var root = instance.elements.root;
- root.parentNode.removeChild(root);
- delete instance.elements;
- //copy back initial settings.
- instance.settings = copy(instance.__settings);
- //re-reference init function.
- instance.__init = initialize;
- //delete __internal variable to allow re-initialization.
- delete instance.__internal;
- }
- }
-
- /**
- * Test to check if passive event listeners are supported.
- */
- var IsPassiveSupported = false;
- try {
- var options = Object.defineProperty({}, 'passive', {
- get: function () {
- IsPassiveSupported = true;
- }
- });
- window.addEventListener('test', options, options);
- window.removeEventListener('test', options, options);
- } catch (e) {
- }
-
- /**
- * Removes an event listener
- *
- * @param {HTMLElement} el The EventTarget to register the listenr on.
- * @param {string} event The event type to listen for.
- * @param {Function} handler The function to handle the event.
- * @param {boolean} useCapture Specifices if the event to be dispatched to the registered listener before being dispatched to any EventTarget beneath it in the DOM tree.
- * @param {boolean} passive A Boolean which, if true, indicates that the function specified by listener will never call preventDefault().
- */
- var on = function (el, event, fn, useCapture, passive) {
- el.addEventListener(event, fn, IsPassiveSupported ? {
- capture: useCapture,
- passive: passive
- } : useCapture === true);
- };
-
- /**
- * Removes an event listener
- *
- * @param {HTMLElement} el The EventTarget to unregister the listenr from.
- * @param {string} event The event type to remove.
- * @param {Function} fn The event handler to remove.
- * @param {boolean} useCapture Specifices if the event to be dispatched to the registered listener before being dispatched to any EventTarget beneath it in the DOM tree.
- * @param {boolean} passive A Boolean which, if true, indicates that the function specified by listener will never call preventDefault().
- */
- var off = function (el, event, fn, useCapture, passive) {
- el.removeEventListener(event, fn, IsPassiveSupported ? {
- capture: useCapture,
- passive: passive
- } : useCapture === true);
- };
-
- /**
- * Prevent default event from firing
- *
- * @param {Event} event Event object
- * @return {undefined}
-
- function prevent ( event ) {
- if ( event ) {
- if ( event.preventDefault ) {
- event.preventDefault();
- } else {
- event.returnValue = false;
- }
- }
- }
- */
- var transition = (function () {
- var t, type;
- var supported = false;
- var transitions = {
- 'animation': 'animationend',
- 'OAnimation': 'oAnimationEnd oanimationend',
- 'msAnimation': 'MSAnimationEnd',
- 'MozAnimation': 'animationend',
- 'WebkitAnimation': 'webkitAnimationEnd'
- };
-
- for (t in transitions) {
- if (document.documentElement.style[t] !== undefined) {
- type = transitions[t];
- supported = true;
- break;
- }
- }
-
- return {
- type: type,
- supported: supported
- };
- }());
-
- /**
- * Creates event handler delegate that sends the instance as last argument.
- *
- * @return {Function} a function wrapper which sends the instance as last argument.
- */
- function delegate(context, method) {
- return function () {
- if (arguments.length > 0) {
- var args = [];
- for (var x = 0; x < arguments.length; x += 1) {
- args.push(arguments[x]);
- }
- args.push(context);
- return method.apply(context, args);
- }
- return method.apply(context, [null, context]);
- };
- }
-
- /**
- * Helper for creating a dialog close event.
- *
- * @return {object}
- */
- function createCloseEvent(index, button) {
- return {
- index: index,
- button: button,
- cancel: false
- };
- }
-
- /**
- * Helper for dispatching events.
- *
- * @param {string} evenType The type of the event to disptach.
- * @param {object} instance The dialog instance disptaching the event.
- *
- * @return {any} The result of the invoked function.
- */
- function dispatchEvent(eventType, instance) {
- if (typeof instance.get(eventType) === 'function') {
- return instance.get(eventType).call(instance);
- }
- }
-
-
- /**
- * Super class for all dialogs
- *
- * @return {Object} base dialog prototype
- */
- var dialog = (function () {
- var //holds the list of used keys.
- usedKeys = [],
- //dummy variable, used to trigger dom reflow.
- reflow = null,
- //holds body tab index in case it has any.
- tabindex = false,
- //condition for detecting safari
- isSafari = window.navigator.userAgent.indexOf('Safari') > -1 && window.navigator.userAgent.indexOf('Chrome') < 0,
- //dialog building blocks
- templates = {
- dimmer: '<div class="ajs-dimmer"></div>',
- /*tab index required to fire click event before body focus*/
- modal: '<div class="ajs-modal" tabindex="0"></div>',
- dialog: '<div class="ajs-dialog" tabindex="0"></div>',
- reset: '<button class="ajs-reset"></button>',
- commands: '<div class="ajs-commands"><button class="ajs-pin"></button><button class="ajs-maximize"></button><button class="ajs-close"></button></div>',
- header: '<div class="ajs-header"></div>',
- body: '<div class="ajs-body"></div>',
- content: '<div class="ajs-content"></div>',
- footer: '<div class="ajs-footer"></div>',
- buttons: {
- primary: '<div class="ajs-primary ajs-buttons"></div>',
- auxiliary: '<div class="ajs-auxiliary ajs-buttons"></div>'
- },
- button: '<button class="ajs-button"></button>',
- resizeHandle: '<div class="ajs-handle"></div>',
- },
- //common class names
- classes = {
- animationIn: 'ajs-in',
- animationOut: 'ajs-out',
- base: 'alertify',
- basic: 'ajs-basic',
- capture: 'ajs-capture',
- closable: 'ajs-closable',
- fixed: 'ajs-fixed',
- frameless: 'ajs-frameless',
- hidden: 'ajs-hidden',
- maximize: 'ajs-maximize',
- maximized: 'ajs-maximized',
- maximizable: 'ajs-maximizable',
- modeless: 'ajs-modeless',
- movable: 'ajs-movable',
- noSelection: 'ajs-no-selection',
- noOverflow: 'ajs-no-overflow',
- noPadding: 'ajs-no-padding',
- pin: 'ajs-pin',
- pinnable: 'ajs-pinnable',
- prefix: 'ajs-',
- resizable: 'ajs-resizable',
- restore: 'ajs-restore',
- shake: 'ajs-shake',
- unpinned: 'ajs-unpinned',
- noTransition: 'ajs-no-transition'
- };
-
- /**
- * Helper: initializes the dialog instance
- *
- * @return {Number} The total count of currently open modals.
- */
- function initialize(instance) {
-
- if (!instance.__internal) {
- //invoke preinit global hook
- alertify.defaults.hooks.preinit(instance);
- //no need to expose init after this.
- delete instance.__init;
-
- //keep a copy of initial dialog settings
- if (!instance.__settings) {
- instance.__settings = copy(instance.settings);
- }
-
- //get dialog buttons/focus setup
- var setup;
- if (typeof instance.setup === 'function') {
- setup = instance.setup();
- setup.options = setup.options || {};
- setup.focus = setup.focus || {};
- } else {
- setup = {
- buttons: [],
- focus: {
- element: null,
- select: false
- },
- options: {}
- };
- }
-
- //initialize hooks object.
- if (typeof instance.hooks !== 'object') {
- instance.hooks = {};
- }
-
- //copy buttons defintion
- var buttonsDefinition = [];
- if (Array.isArray(setup.buttons)) {
- for (var b = 0; b < setup.buttons.length; b += 1) {
- var ref = setup.buttons[b],
- cpy = {};
- for (var i in ref) {
- if (ref.hasOwnProperty(i)) {
- cpy[i] = ref[i];
- }
- }
- buttonsDefinition.push(cpy);
- }
- }
-
- var internal = instance.__internal = {
- /**
- * Flag holding the open state of the dialog
- *
- * @type {Boolean}
- */
- isOpen: false,
- /**
- * Active element is the element that will receive focus after
- * closing the dialog. It defaults as the body tag, but gets updated
- * to the last focused element before the dialog was opened.
- *
- * @type {Node}
- */
- activeElement: document.body,
- timerIn: undefined,
- timerOut: undefined,
- buttons: buttonsDefinition,
- focus: setup.focus,
- options: {
- title: undefined,
- modal: undefined,
- basic: undefined,
- frameless: undefined,
- defaultFocusOff: undefined,
- pinned: undefined,
- movable: undefined,
- moveBounded: undefined,
- resizable: undefined,
- autoReset: undefined,
- closable: undefined,
- closableByDimmer: undefined,
- invokeOnCloseOff: undefined,
- maximizable: undefined,
- startMaximized: undefined,
- pinnable: undefined,
- transition: undefined,
- transitionOff: undefined,
- padding: undefined,
- overflow: undefined,
- onshow: undefined,
- onclosing: undefined,
- onclose: undefined,
- onfocus: undefined,
- onmove: undefined,
- onmoved: undefined,
- onresize: undefined,
- onresized: undefined,
- onmaximize: undefined,
- onmaximized: undefined,
- onrestore: undefined,
- onrestored: undefined
- },
- resetHandler: undefined,
- beginMoveHandler: undefined,
- beginResizeHandler: undefined,
- bringToFrontHandler: undefined,
- modalClickHandler: undefined,
- buttonsClickHandler: undefined,
- commandsClickHandler: undefined,
- transitionInHandler: undefined,
- transitionOutHandler: undefined,
- destroy: undefined
- };
-
- var elements = {};
- //root node
- elements.root = document.createElement('div');
- //prevent FOUC in case of async styles loading.
- elements.root.style.display = 'none';
- elements.root.className = classes.base + ' ' + classes.hidden + ' ';
-
- elements.root.innerHTML = templates.dimmer + templates.modal;
-
- //dimmer
- elements.dimmer = elements.root.firstChild;
-
- //dialog
- elements.modal = elements.root.lastChild;
- elements.modal.innerHTML = templates.dialog;
- elements.dialog = elements.modal.firstChild;
- elements.dialog.innerHTML = templates.reset + templates.commands + templates.header + templates.body + templates.footer + templates.resizeHandle + templates.reset;
-
- //reset links
- elements.reset = [];
- elements.reset.push(elements.dialog.firstChild);
- elements.reset.push(elements.dialog.lastChild);
-
- //commands
- elements.commands = {};
- elements.commands.container = elements.reset[0].nextSibling;
- elements.commands.pin = elements.commands.container.firstChild;
- elements.commands.maximize = elements.commands.pin.nextSibling;
- elements.commands.close = elements.commands.maximize.nextSibling;
-
- //header
- elements.header = elements.commands.container.nextSibling;
-
- //body
- elements.body = elements.header.nextSibling;
- elements.body.innerHTML = templates.content;
- elements.content = elements.body.firstChild;
-
- //footer
- elements.footer = elements.body.nextSibling;
- elements.footer.innerHTML = templates.buttons.auxiliary + templates.buttons.primary;
-
- //resize handle
- elements.resizeHandle = elements.footer.nextSibling;
-
- //buttons
- elements.buttons = {};
- elements.buttons.auxiliary = elements.footer.firstChild;
- elements.buttons.primary = elements.buttons.auxiliary.nextSibling;
- elements.buttons.primary.innerHTML = templates.button;
- elements.buttonTemplate = elements.buttons.primary.firstChild;
- //remove button template
- elements.buttons.primary.removeChild(elements.buttonTemplate);
-
- for (var x = 0; x < instance.__internal.buttons.length; x += 1) {
- var button = instance.__internal.buttons[x];
-
- // add to the list of used keys.
- if (usedKeys.indexOf(button.key) < 0) {
- usedKeys.push(button.key);
- }
-
- button.element = elements.buttonTemplate.cloneNode();
- button.element.innerHTML = button.text;
- if (typeof button.className === 'string' && button.className !== '') {
- addClass(button.element, button.className);
- }
- for (var key in button.attrs) {
- if (key !== 'className' && button.attrs.hasOwnProperty(key)) {
- button.element.setAttribute(key, button.attrs[key]);
- }
- }
- if (button.scope === 'auxiliary') {
- elements.buttons.auxiliary.appendChild(button.element);
- } else {
- elements.buttons.primary.appendChild(button.element);
- }
- }
- //make elements pubic
- instance.elements = elements;
-
- //save event handlers delegates
- internal.resetHandler = delegate(instance, onReset);
- internal.beginMoveHandler = delegate(instance, beginMove);
- internal.beginResizeHandler = delegate(instance, beginResize);
- internal.bringToFrontHandler = delegate(instance, bringToFront);
- internal.modalClickHandler = delegate(instance, modalClickHandler);
- internal.buttonsClickHandler = delegate(instance, buttonsClickHandler);
- internal.commandsClickHandler = delegate(instance, commandsClickHandler);
- internal.transitionInHandler = delegate(instance, handleTransitionInEvent);
- internal.transitionOutHandler = delegate(instance, handleTransitionOutEvent);
-
- //settings
- for (var opKey in internal.options) {
- if (setup.options[opKey] !== undefined) {
- // if found in user options
- instance.set(opKey, setup.options[opKey]);
- } else if (alertify.defaults.hasOwnProperty(opKey)) {
- // else if found in defaults options
- instance.set(opKey, alertify.defaults[opKey]);
- } else if (opKey === 'title') {
- // else if title key, use alertify.defaults.glossary
- instance.set(opKey, alertify.defaults.glossary[opKey]);
- }
- }
-
- // allow dom customization
- if (typeof instance.build === 'function') {
- instance.build();
- }
-
- //invoke postinit global hook
- alertify.defaults.hooks.postinit(instance);
- }
-
- //add to the end of the DOM tree.
- document.body.appendChild(instance.elements.root);
- }
-
- /**
- * Helper: maintains scroll position
- *
- */
- var scrollX, scrollY;
-
- function saveScrollPosition() {
- scrollX = getScrollLeft();
- scrollY = getScrollTop();
- }
-
- function restoreScrollPosition() {
- window.scrollTo(scrollX, scrollY);
- }
-
- /**
- * Helper: adds/removes no-overflow class from body
- *
- */
- function ensureNoOverflow() {
- var requiresNoOverflow = 0;
- for (var x = 0; x < openDialogs.length; x += 1) {
- var instance = openDialogs[x];
- if (instance.isModal() || instance.isMaximized()) {
- requiresNoOverflow += 1;
- }
- }
- if (requiresNoOverflow === 0 && document.body.className.indexOf(classes.noOverflow) >= 0) {
- //last open modal or last maximized one
- removeClass(document.body, classes.noOverflow);
- preventBodyShift(false);
- } else if (requiresNoOverflow > 0 && document.body.className.indexOf(classes.noOverflow) < 0) {
- //first open modal or first maximized one
- preventBodyShift(true);
- addClass(document.body, classes.noOverflow);
- }
- }
-
- var top = '', topScroll = 0;
-
- /**
- * Helper: prevents body shift.
- *
- */
- function preventBodyShift(add) {
- if (alertify.defaults.preventBodyShift) {
- if (add && document.documentElement.scrollHeight > document.documentElement.clientHeight) {//&& openDialogs[openDialogs.length-1].elements.dialog.clientHeight <= document.documentElement.clientHeight){
- topScroll = scrollY;
- top = window.getComputedStyle(document.body).top;
- addClass(document.body, classes.fixed);
- document.body.style.top = -scrollY + 'px';
- } else if (!add) {
- scrollY = topScroll;
- document.body.style.top = top;
- removeClass(document.body, classes.fixed);
- restoreScrollPosition();
- }
- }
- }
-
- /**
- * Sets the name of the transition used to show/hide the dialog
- *
- * @param {Object} instance The dilog instance.
- *
- */
- function updateTransition(instance, value, oldValue) {
- if (typeof oldValue === 'string') {
- removeClass(instance.elements.root, classes.prefix + oldValue);
- }
- addClass(instance.elements.root, classes.prefix + value);
- reflow = instance.elements.root.offsetWidth;
- }
-
- /**
- * Toggles the dialog no transition
- *
- * @param {Object} instance The dilog instance.
- *
- * @return {undefined}
- */
- function updateTransitionOff(instance) {
- if (instance.get('transitionOff')) {
- // add class
- addClass(instance.elements.root, classes.noTransition);
- } else {
- // remove class
- removeClass(instance.elements.root, classes.noTransition);
- }
- }
-
- /**
- * Toggles the dialog display mode
- *
- * @param {Object} instance The dilog instance.
- *
- * @return {undefined}
- */
- function updateDisplayMode(instance) {
- if (instance.get('modal')) {
-
- //make modal
- removeClass(instance.elements.root, classes.modeless);
-
- //only if open
- if (instance.isOpen()) {
- unbindModelessEvents(instance);
-
- //in case a pinned modless dialog was made modal while open.
- updateAbsPositionFix(instance);
-
- ensureNoOverflow();
- }
- } else {
- //make modelss
- addClass(instance.elements.root, classes.modeless);
-
- //only if open
- if (instance.isOpen()) {
- bindModelessEvents(instance);
-
- //in case pin/unpin was called while a modal is open
- updateAbsPositionFix(instance);
-
- ensureNoOverflow();
- }
- }
- }
-
- /**
- * Toggles the dialog basic view mode
- *
- * @param {Object} instance The dilog instance.
- *
- * @return {undefined}
- */
- function updateBasicMode(instance) {
- if (instance.get('basic')) {
- // add class
- addClass(instance.elements.root, classes.basic);
- } else {
- // remove class
- removeClass(instance.elements.root, classes.basic);
- }
- }
-
- /**
- * Toggles the dialog frameless view mode
- *
- * @param {Object} instance The dilog instance.
- *
- * @return {undefined}
- */
- function updateFramelessMode(instance) {
- if (instance.get('frameless')) {
- // add class
- addClass(instance.elements.root, classes.frameless);
- } else {
- // remove class
- removeClass(instance.elements.root, classes.frameless);
- }
- }
-
- /**
- * Helper: Brings the modeless dialog to front, attached to modeless dialogs.
- *
- * @param {Event} event Focus event
- * @param {Object} instance The dilog instance.
- *
- * @return {undefined}
- */
- function bringToFront(event, instance) {
-
- // Do not bring to front if preceeded by an open modal
- var index = openDialogs.indexOf(instance);
- for (var x = index + 1; x < openDialogs.length; x += 1) {
- if (openDialogs[x].isModal()) {
- return;
- }
- }
-
- // Bring to front by making it the last child.
- if (document.body.lastChild !== instance.elements.root) {
- document.body.appendChild(instance.elements.root);
- //also make sure its at the end of the list
- openDialogs.splice(openDialogs.indexOf(instance), 1);
- openDialogs.push(instance);
- setFocus(instance);
- }
-
- return false;
- }
-
- /**
- * Helper: reflects dialogs options updates
- *
- * @param {Object} instance The dilog instance.
- * @param {String} option The updated option name.
- *
- * @return {undefined}
- */
- function optionUpdated(instance, option, oldValue, newValue) {
- switch (option) {
- case 'title':
- instance.setHeader(newValue);
- break;
- case 'modal':
- updateDisplayMode(instance);
- break;
- case 'basic':
- updateBasicMode(instance);
- break;
- case 'frameless':
- updateFramelessMode(instance);
- break;
- case 'pinned':
- updatePinned(instance);
- break;
- case 'closable':
- updateClosable(instance);
- break;
- case 'maximizable':
- updateMaximizable(instance);
- break;
- case 'pinnable':
- updatePinnable(instance);
- break;
- case 'movable':
- updateMovable(instance);
- break;
- case 'resizable':
- updateResizable(instance);
- break;
- case 'padding':
- if (newValue) {
- removeClass(instance.elements.root, classes.noPadding);
- } else if (instance.elements.root.className.indexOf(classes.noPadding) < 0) {
- addClass(instance.elements.root, classes.noPadding);
- }
- break;
- case 'overflow':
- if (newValue) {
- removeClass(instance.elements.root, classes.noOverflow);
- } else if (instance.elements.root.className.indexOf(classes.noOverflow) < 0) {
- addClass(instance.elements.root, classes.noOverflow);
- }
- break;
- case 'transition':
- updateTransition(instance, newValue, oldValue);
- break;
- case 'transitionOff':
- updateTransitionOff(instance);
- break;
- }
-
- // internal on option updated event
- if (typeof instance.hooks.onupdate === 'function') {
- instance.hooks.onupdate.call(instance, option, oldValue, newValue);
- }
- }
-
- /**
- * Helper: reflects dialogs options updates
- *
- * @param {Object} instance The dilog instance.
- * @param {Object} obj The object to set/get a value on/from.
- * @param {Function} callback The callback function to call if the key was found.
- * @param {String|Object} key A string specifying a propery name or a collection of key value pairs.
- * @param {Object} value Optional, the value associated with the key (in case it was a string).
- * @param {String} option The updated option name.
- *
- * @return {Object} result object
- * The result objects has an 'op' property, indicating of this is a SET or GET operation.
- * GET:
- * - found: a flag indicating if the key was found or not.
- * - value: the property value.
- * SET:
- * - items: a list of key value pairs of the properties being set.
- * each contains:
- * - found: a flag indicating if the key was found or not.
- * - key: the property key.
- * - value: the property value.
- */
- function update(instance, obj, callback, key, value) {
- var result = {op: undefined, items: []};
- if (typeof value === 'undefined' && typeof key === 'string') {
- //get
- result.op = 'get';
- if (obj.hasOwnProperty(key)) {
- result.found = true;
- result.value = obj[key];
- } else {
- result.found = false;
- result.value = undefined;
- }
- } else {
- var old;
- //set
- result.op = 'set';
- if (typeof key === 'object') {
- //set multiple
- var args = key;
- for (var prop in args) {
- if (obj.hasOwnProperty(prop)) {
- if (obj[prop] !== args[prop]) {
- old = obj[prop];
- obj[prop] = args[prop];
- callback.call(instance, prop, old, args[prop]);
- }
- result.items.push({'key': prop, 'value': args[prop], 'found': true});
- } else {
- result.items.push({'key': prop, 'value': args[prop], 'found': false});
- }
- }
- } else if (typeof key === 'string') {
- //set single
- if (obj.hasOwnProperty(key)) {
- if (obj[key] !== value) {
- old = obj[key];
- obj[key] = value;
- callback.call(instance, key, old, value);
- }
- result.items.push({'key': key, 'value': value, 'found': true});
-
- } else {
- result.items.push({'key': key, 'value': value, 'found': false});
- }
- } else {
- //invalid params
- throw new Error('args must be a string or object');
- }
- }
- return result;
- }
-
-
- /**
- * Triggers a close event.
- *
- * @param {Object} instance The dilog instance.
- *
- * @return {undefined}
- */
- function triggerClose(instance) {
- var found;
- triggerCallback(instance, function (button) {
- return found = instance.get('invokeOnCloseOff') !== true && (button.invokeOnClose === true);
- });
- //none of the buttons registered as onclose callback
- //close the dialog
- if (!found && instance.isOpen()) {
- instance.close();
- }
- }
-
- /**
- * Dialogs commands event handler, attached to the dialog commands element.
- *
- * @param {Event} event DOM event object.
- * @param {Object} instance The dilog instance.
- *
- * @return {undefined}
- */
- function commandsClickHandler(event, instance) {
- var target = event.srcElement || event.target;
- switch (target) {
- case instance.elements.commands.pin:
- if (!instance.isPinned()) {
- pin(instance);
- } else {
- unpin(instance);
- }
- break;
- case instance.elements.commands.maximize:
- if (!instance.isMaximized()) {
- maximize(instance);
- } else {
- restore(instance);
- }
- break;
- case instance.elements.commands.close:
- triggerClose(instance);
- break;
- }
- return false;
- }
-
- /**
- * Helper: pins the modeless dialog.
- *
- * @param {Object} instance The dialog instance.
- *
- * @return {undefined}
- */
- function pin(instance) {
- //pin the dialog
- instance.set('pinned', true);
- }
-
- /**
- * Helper: unpins the modeless dialog.
- *
- * @param {Object} instance The dilog instance.
- *
- * @return {undefined}
- */
- function unpin(instance) {
- //unpin the dialog
- instance.set('pinned', false);
- }
-
-
- /**
- * Helper: enlarges the dialog to fill the entire screen.
- *
- * @param {Object} instance The dilog instance.
- *
- * @return {undefined}
- */
- function maximize(instance) {
- // allow custom `onmaximize` method
- dispatchEvent('onmaximize', instance);
- //maximize the dialog
- addClass(instance.elements.root, classes.maximized);
- if (instance.isOpen()) {
- ensureNoOverflow();
- }
- // allow custom `onmaximized` method
- dispatchEvent('onmaximized', instance);
- }
-
- /**
- * Helper: returns the dialog to its former size.
- *
- * @param {Object} instance The dilog instance.
- *
- * @return {undefined}
- */
- function restore(instance) {
- // allow custom `onrestore` method
- dispatchEvent('onrestore', instance);
- //maximize the dialog
- removeClass(instance.elements.root, classes.maximized);
- if (instance.isOpen()) {
- ensureNoOverflow();
- }
- // allow custom `onrestored` method
- dispatchEvent('onrestored', instance);
- }
-
- /**
- * Show or hide the maximize box.
- *
- * @param {Object} instance The dilog instance.
- * @param {Boolean} on True to add the behavior, removes it otherwise.
- *
- * @return {undefined}
- */
- function updatePinnable(instance) {
- if (instance.get('pinnable')) {
- // add class
- addClass(instance.elements.root, classes.pinnable);
- } else {
- // remove class
- removeClass(instance.elements.root, classes.pinnable);
- }
- }
-
- /**
- * Helper: Fixes the absolutly positioned modal div position.
- *
- * @param {Object} instance The dialog instance.
- *
- * @return {undefined}
- */
- function addAbsPositionFix(instance) {
- var scrollLeft = getScrollLeft();
- instance.elements.modal.style.marginTop = getScrollTop() + 'px';
- instance.elements.modal.style.marginLeft = scrollLeft + 'px';
- instance.elements.modal.style.marginRight = (-scrollLeft) + 'px';
- }
-
- /**
- * Helper: Removes the absolutly positioned modal div position fix.
- *
- * @param {Object} instance The dialog instance.
- *
- * @return {undefined}
- */
- function removeAbsPositionFix(instance) {
- var marginTop = parseInt(instance.elements.modal.style.marginTop, 10);
- var marginLeft = parseInt(instance.elements.modal.style.marginLeft, 10);
- instance.elements.modal.style.marginTop = '';
- instance.elements.modal.style.marginLeft = '';
- instance.elements.modal.style.marginRight = '';
-
- if (instance.isOpen()) {
- var top = 0,
- left = 0
- ;
- if (instance.elements.dialog.style.top !== '') {
- top = parseInt(instance.elements.dialog.style.top, 10);
- }
- instance.elements.dialog.style.top = (top + (marginTop - getScrollTop())) + 'px';
-
- if (instance.elements.dialog.style.left !== '') {
- left = parseInt(instance.elements.dialog.style.left, 10);
- }
- instance.elements.dialog.style.left = (left + (marginLeft - getScrollLeft())) + 'px';
- }
- }
-
- /**
- * Helper: Adds/Removes the absolutly positioned modal div position fix based on its pinned setting.
- *
- * @param {Object} instance The dialog instance.
- *
- * @return {undefined}
- */
- function updateAbsPositionFix(instance) {
- // if modeless and unpinned add fix
- if (!instance.get('modal') && !instance.get('pinned')) {
- addAbsPositionFix(instance);
- } else {
- removeAbsPositionFix(instance);
- }
- }
-
- /**
- * Toggles the dialog position lock | modeless only.
- *
- * @param {Object} instance The dilog instance.
- * @param {Boolean} on True to make it modal, false otherwise.
- *
- * @return {undefined}
- */
- function updatePinned(instance) {
- if (instance.get('pinned')) {
- removeClass(instance.elements.root, classes.unpinned);
- if (instance.isOpen()) {
- removeAbsPositionFix(instance);
- }
- } else {
- addClass(instance.elements.root, classes.unpinned);
- if (instance.isOpen() && !instance.isModal()) {
- addAbsPositionFix(instance);
- }
- }
- }
-
- /**
- * Show or hide the maximize box.
- *
- * @param {Object} instance The dilog instance.
- * @param {Boolean} on True to add the behavior, removes it otherwise.
- *
- * @return {undefined}
- */
- function updateMaximizable(instance) {
- if (instance.get('maximizable')) {
- // add class
- addClass(instance.elements.root, classes.maximizable);
- } else {
- // remove class
- removeClass(instance.elements.root, classes.maximizable);
- }
- }
-
- /**
- * Show or hide the close box.
- *
- * @param {Object} instance The dilog instance.
- * @param {Boolean} on True to add the behavior, removes it otherwise.
- *
- * @return {undefined}
- */
- function updateClosable(instance) {
- if (instance.get('closable')) {
- // add class
- addClass(instance.elements.root, classes.closable);
- bindClosableEvents(instance);
- } else {
- // remove class
- removeClass(instance.elements.root, classes.closable);
- unbindClosableEvents(instance);
- }
- }
-
-
- var cancelClick = false,// flag to cancel click event if already handled by end resize event (the mousedown, mousemove, mouseup sequence fires a click event.).
- modalClickHandlerTS = 0 // stores last click timestamp to prevent executing the handler twice on double click.
- ;
-
- /**
- * Helper: closes the modal dialog when clicking the modal
- *
- * @param {Event} event DOM event object.
- * @param {Object} instance The dilog instance.
- *
- * @return {undefined}
- */
- function modalClickHandler(event, instance) {
- if (event.timeStamp - modalClickHandlerTS > 200 && (modalClickHandlerTS = event.timeStamp) && !cancelClick) {
- var target = event.srcElement || event.target;
- if (instance.get('closableByDimmer') === true && target === instance.elements.modal) {
- triggerClose(instance);
- }
- }
- cancelClick = false;
- }
-
- // stores last call timestamp to prevent triggering the callback twice.
- var callbackTS = 0;
- // flag to cancel keyup event if already handled by click event (pressing Enter on a focusted button).
- var cancelKeyup = false;
-
- /**
- * Helper: triggers a button callback
- *
- * @param {Object} The dilog instance.
- * @param {Function} Callback to check which button triggered the event.
- *
- * @return {undefined}
- */
- function triggerCallback(instance, check) {
- if (Date.now() - callbackTS > 200 && (callbackTS = Date.now())) {
- for (var idx = 0; idx < instance.__internal.buttons.length; idx += 1) {
- var button = instance.__internal.buttons[idx];
- if (!button.element.disabled && check(button)) {
- var closeEvent = createCloseEvent(idx, button);
- if (typeof instance.callback === 'function') {
- instance.callback.apply(instance, [closeEvent]);
- }
- //close the dialog only if not canceled.
- if (closeEvent.cancel === false) {
- instance.close();
- }
- break;
- }
- }
- }
- }
-
- /**
- * Clicks event handler, attached to the dialog footer.
- *
- * @param {Event} DOM event object.
- * @param {Object} The dilog instance.
- *
- * @return {undefined}
- */
- function buttonsClickHandler(event, instance) {
- var target = event.srcElement || event.target;
- triggerCallback(instance, function (button) {
- // if this button caused the click, cancel keyup event
- return button.element === target && (cancelKeyup = true);
- });
- }
-
- /**
- * Keyup event handler, attached to the document.body
- *
- * @param {Event} DOM event object.
- * @param {Object} The dilog instance.
- *
- * @return {undefined}
- */
- function keyupHandler(event) {
- //hitting enter while button has focus will trigger keyup too.
- //ignore if handled by clickHandler
- if (cancelKeyup) {
- cancelKeyup = false;
- return;
- }
- var instance = openDialogs[openDialogs.length - 1];
- var keyCode = event.keyCode;
- if (instance.__internal.buttons.length === 0 && keyCode === keys.ESC && instance.get('closable') === true) {
- triggerClose(instance);
- return false;
- } else if (usedKeys.indexOf(keyCode) > -1) {
- triggerCallback(instance, function (button) {
- return button.key === keyCode;
- });
- return false;
- }
- }
-
- /**
- * Keydown event handler, attached to the document.body
- *
- * @param {Event} DOM event object.
- * @param {Object} The dilog instance.
- *
- * @return {undefined}
- */
- function keydownHandler(event) {
- var instance = openDialogs[openDialogs.length - 1];
- var keyCode = event.keyCode;
- if (keyCode === keys.LEFT || keyCode === keys.RIGHT) {
- var buttons = instance.__internal.buttons;
- for (var x = 0; x < buttons.length; x += 1) {
- if (document.activeElement === buttons[x].element) {
- switch (keyCode) {
- case keys.LEFT:
- buttons[(x || buttons.length) - 1].element.focus();
- return;
- case keys.RIGHT:
- buttons[(x + 1) % buttons.length].element.focus();
- return;
- }
- }
- }
- } else if (keyCode < keys.F12 + 1 && keyCode > keys.F1 - 1 && usedKeys.indexOf(keyCode) > -1) {
- event.preventDefault();
- event.stopPropagation();
- triggerCallback(instance, function (button) {
- return button.key === keyCode;
- });
- return false;
- }
- }
-
-
- /**
- * Sets focus to proper dialog element
- *
- * @param {Object} instance The dilog instance.
- * @param {Node} [resetTarget=undefined] DOM element to reset focus to.
- *
- * @return {undefined}
- */
- function setFocus(instance, resetTarget) {
- // reset target has already been determined.
- if (resetTarget) {
- resetTarget.focus();
- } else {
- // current instance focus settings
- var focus = instance.__internal.focus;
- // the focus element.
- var element = focus.element;
-
- switch (typeof focus.element) {
- // a number means a button index
- case 'number':
- if (instance.__internal.buttons.length > focus.element) {
- //in basic view, skip focusing the buttons.
- if (instance.get('basic') === true) {
- element = instance.elements.reset[0];
- } else {
- element = instance.__internal.buttons[focus.element].element;
- }
- }
- break;
- // a string means querySelector to select from dialog body contents.
- case 'string':
- element = instance.elements.body.querySelector(focus.element);
- break;
- // a function should return the focus element.
- case 'function':
- element = focus.element.call(instance);
- break;
- }
-
- // if no focus element, default to first reset element.
- if (instance.get('defaultFocusOff') === true || ((typeof element === 'undefined' || element === null) && instance.__internal.buttons.length === 0)) {
- element = instance.elements.reset[0];
- }
- // focus
- if (element && element.focus) {
- element.focus();
- // if selectable
- if (focus.select && element.select) {
- element.select();
- }
- }
- }
- }
-
- /**
- * Focus event handler, attached to document.body and dialogs own reset links.
- * handles the focus for modal dialogs only.
- *
- * @param {Event} event DOM focus event object.
- * @param {Object} instance The dilog instance.
- *
- * @return {undefined}
- */
- function onReset(event, instance) {
-
- // should work on last modal if triggered from document.body
- if (!instance) {
- for (var x = openDialogs.length - 1; x > -1; x -= 1) {
- if (openDialogs[x].isModal()) {
- instance = openDialogs[x];
- break;
- }
- }
- }
-
- if (instance) {
- // if modal
- if (instance.isModal()) {
- // determine reset target to enable forward/backward tab cycle.
- var firstReset = instance.elements.reset[0],
- lastReset = instance.elements.reset[1],
- lastFocusedElement = event.relatedTarget,
- within = instance.elements.root.contains(lastFocusedElement),
- target = event.srcElement || event.target,
- resetTarget;
-
- //if the previous focused element element was outside the modal do nthing
- if ( /*first show */
- (target === firstReset && !within) ||
- /*focus cycle */
- (target === lastReset && lastFocusedElement === firstReset)) {
- return;
- } else if (target === lastReset || target === document.body) {
- resetTarget = firstReset;
- } else if (target === firstReset && lastFocusedElement === lastReset) {
- resetTarget = findTabbable(instance);
- } else if (target === firstReset && within) {
- resetTarget = findTabbable(instance, true);
- }
- // focus
- setFocus(instance, resetTarget);
- }
- }
- }
-
- function findTabbable(instance, last) {
- var tabbables = [].slice.call(instance.elements.dialog.querySelectorAll(defaults.tabbable));
- if (last) {
- tabbables.reverse();
- }
- for (var x = 0; x < tabbables.length; x += 1) {
- var tabbable = tabbables[x];
- //check if visible
- if (!!(tabbable.offsetParent || tabbable.offsetWidth || tabbable.offsetHeight || tabbable.getClientRects().length)) {
- return tabbable;
- }
- }
- }
-
- function recycleTab(event) {
- var instance = openDialogs[openDialogs.length - 1];
- if (instance && event.shiftKey && event.keyCode === keys.TAB) {
- instance.elements.reset[1].focus();
- }
- }
-
- /**
- * Transition in transitionend event handler.
- *
- * @param {Event} TransitionEnd event object.
- * @param {Object} The dilog instance.
- *
- * @return {undefined}
- */
- function handleTransitionInEvent(event, instance) {
- // clear the timer
- clearTimeout(instance.__internal.timerIn);
-
- // once transition is complete, set focus
- setFocus(instance);
-
- // allow handling key up after transition ended.
- cancelKeyup = false;
-
- // allow custom `onfocus` method
- dispatchEvent('onfocus', instance);
-
- // unbind the event
- off(instance.elements.dialog, transition.type, instance.__internal.transitionInHandler);
-
- removeClass(instance.elements.root, classes.animationIn);
- }
-
- /**
- * Transition out transitionend event handler.
- *
- * @param {Event} TransitionEnd event object.
- * @param {Object} The dilog instance.
- *
- * @return {undefined}
- */
- function handleTransitionOutEvent(event, instance) {
- // clear the timer
- clearTimeout(instance.__internal.timerOut);
- // unbind the event
- off(instance.elements.dialog, transition.type, instance.__internal.transitionOutHandler);
-
- // reset move updates
- resetMove(instance);
- // reset resize updates
- resetResize(instance);
-
- // restore if maximized
- if (instance.isMaximized() && !instance.get('startMaximized')) {
- restore(instance);
- }
-
- //destory the instance
- if (typeof instance.__internal.destroy === 'function') {
- instance.__internal.destroy.apply(instance);
- }
- }
-
- /* Controls moving a dialog around */
- //holde the current moving instance
- var movable = null,
- //holds the current X offset when move starts
- offsetX = 0,
- //holds the current Y offset when move starts
- offsetY = 0,
- xProp = 'pageX',
- yProp = 'pageY',
- bounds = null,
- refreshTop = false,
- moveDelegate = null
- ;
-
- /**
- * Helper: sets the element top/left coordinates
- *
- * @param {Event} event DOM event object.
- * @param {Node} element The element being moved.
- *
- * @return {undefined}
- */
- function moveElement(event, element) {
- var left = (event[xProp] - offsetX),
- top = (event[yProp] - offsetY);
-
- if (refreshTop) {
- top -= document.body.scrollTop;
- }
-
- element.style.left = left + 'px';
- element.style.top = top + 'px';
-
- }
-
- /**
- * Helper: sets the element top/left coordinates within screen bounds
- *
- * @param {Event} event DOM event object.
- * @param {Node} element The element being moved.
- *
- * @return {undefined}
- */
- function moveElementBounded(event, element) {
- var left = (event[xProp] - offsetX),
- top = (event[yProp] - offsetY);
-
- if (refreshTop) {
- top -= document.body.scrollTop;
- }
-
- element.style.left = Math.min(bounds.maxLeft, Math.max(bounds.minLeft, left)) + 'px';
- if (refreshTop) {
- element.style.top = Math.min(bounds.maxTop, Math.max(bounds.minTop, top)) + 'px';
- } else {
- element.style.top = Math.max(bounds.minTop, top) + 'px';
- }
- }
-
-
- /**
- * Triggers the start of a move event, attached to the header element mouse down event.
- * Adds no-selection class to the body, disabling selection while moving.
- *
- * @param {Event} event DOM event object.
- * @param {Object} instance The dilog instance.
- *
- * @return {Boolean} false
- */
- function beginMove(event, instance) {
- if (resizable === null && !instance.isMaximized() && instance.get('movable')) {
- var eventSrc, left = 0, top = 0;
- if (event.type === 'touchstart') {
- event.preventDefault();
- eventSrc = event.targetTouches[0];
- xProp = 'clientX';
- yProp = 'clientY';
- } else if (event.button === 0) {
- eventSrc = event;
- }
-
- if (eventSrc) {
-
- var element = instance.elements.dialog;
- addClass(element, classes.capture);
-
- if (element.style.left) {
- left = parseInt(element.style.left, 10);
- }
-
- if (element.style.top) {
- top = parseInt(element.style.top, 10);
- }
-
- offsetX = eventSrc[xProp] - left;
- offsetY = eventSrc[yProp] - top;
-
- if (instance.isModal()) {
- offsetY += instance.elements.modal.scrollTop;
- } else if (instance.isPinned()) {
- offsetY -= document.body.scrollTop;
- }
-
- if (instance.get('moveBounded')) {
- var current = element,
- offsetLeft = -left,
- offsetTop = -top;
-
- //calc offset
- do {
- offsetLeft += current.offsetLeft;
- offsetTop += current.offsetTop;
- } while (current = current.offsetParent);
-
- bounds = {
- maxLeft: offsetLeft,
- minLeft: -offsetLeft,
- maxTop: document.documentElement.clientHeight - element.clientHeight - offsetTop,
- minTop: -offsetTop
- };
- moveDelegate = moveElementBounded;
- } else {
- bounds = null;
- moveDelegate = moveElement;
- }
-
- // allow custom `onmove` method
- dispatchEvent('onmove', instance);
-
- refreshTop = !instance.isModal() && instance.isPinned();
- movable = instance;
- moveDelegate(eventSrc, element);
- addClass(document.body, classes.noSelection);
- return false;
- }
- }
- }
-
- /**
- * The actual move handler, attached to document.body mousemove event.
- *
- * @param {Event} event DOM event object.
- *
- * @return {undefined}
- */
- function move(event) {
- if (movable) {
- var eventSrc;
- if (event.type === 'touchmove') {
- event.preventDefault();
- eventSrc = event.targetTouches[0];
- } else if (event.button === 0) {
- eventSrc = event;
- }
- if (eventSrc) {
- moveDelegate(eventSrc, movable.elements.dialog);
- }
- }
- }
-
- /**
- * Triggers the end of a move event, attached to document.body mouseup event.
- * Removes no-selection class from document.body, allowing selection.
- *
- * @return {undefined}
- */
- function endMove() {
- if (movable) {
- var instance = movable;
- movable = bounds = null;
- removeClass(document.body, classes.noSelection);
- removeClass(instance.elements.dialog, classes.capture);
- // allow custom `onmoved` method
- dispatchEvent('onmoved', instance);
- }
- }
-
- /**
- * Resets any changes made by moving the element to its original state,
- *
- * @param {Object} instance The dilog instance.
- *
- * @return {undefined}
- */
- function resetMove(instance) {
- movable = null;
- var element = instance.elements.dialog;
- element.style.left = element.style.top = '';
- }
-
- /**
- * Updates the dialog move behavior.
- *
- * @param {Object} instance The dilog instance.
- * @param {Boolean} on True to add the behavior, removes it otherwise.
- *
- * @return {undefined}
- */
- function updateMovable(instance) {
- if (instance.get('movable')) {
- // add class
- addClass(instance.elements.root, classes.movable);
- if (instance.isOpen()) {
- bindMovableEvents(instance);
- }
- } else {
-
- //reset
- resetMove(instance);
- // remove class
- removeClass(instance.elements.root, classes.movable);
- if (instance.isOpen()) {
- unbindMovableEvents(instance);
- }
- }
- }
-
- /* Controls moving a dialog around */
- //holde the current instance being resized
- var resizable = null,
- //holds the staring left offset when resize starts.
- startingLeft = Number.Nan,
- //holds the staring width when resize starts.
- startingWidth = 0,
- //holds the initial width when resized for the first time.
- minWidth = 0,
- //holds the offset of the resize handle.
- handleOffset = 0
- ;
-
- /**
- * Helper: sets the element width/height and updates left coordinate if neccessary.
- *
- * @param {Event} event DOM mousemove event object.
- * @param {Node} element The element being moved.
- * @param {Boolean} pinned A flag indicating if the element being resized is pinned to the screen.
- *
- * @return {undefined}
- */
- function resizeElement(event, element, pageRelative) {
-
- //calculate offsets from 0,0
- var current = element;
- var offsetLeft = 0;
- var offsetTop = 0;
- do {
- offsetLeft += current.offsetLeft;
- offsetTop += current.offsetTop;
- } while (current = current.offsetParent);
-
- // determine X,Y coordinates.
- var X, Y;
- if (pageRelative === true) {
- X = event.pageX;
- Y = event.pageY;
- } else {
- X = event.clientX;
- Y = event.clientY;
- }
- // rtl handling
- var isRTL = isRightToLeft();
- if (isRTL) {
- // reverse X
- X = document.body.offsetWidth - X;
- // if has a starting left, calculate offsetRight
- if (!isNaN(startingLeft)) {
- offsetLeft = document.body.offsetWidth - offsetLeft - element.offsetWidth;
- }
- }
-
- // set width/height
- element.style.height = (Y - offsetTop + handleOffset) + 'px';
- element.style.width = (X - offsetLeft + handleOffset) + 'px';
-
- // if the element being resized has a starting left, maintain it.
- // the dialog is centered, divide by half the offset to maintain the margins.
- if (!isNaN(startingLeft)) {
- var diff = Math.abs(element.offsetWidth - startingWidth) * 0.5;
- if (isRTL) {
- //negate the diff, why?
- //when growing it should decrease left
- //when shrinking it should increase left
- diff *= -1;
- }
- if (element.offsetWidth > startingWidth) {
- //growing
- element.style.left = (startingLeft + diff) + 'px';
- } else if (element.offsetWidth >= minWidth) {
- //shrinking
- element.style.left = (startingLeft - diff) + 'px';
- }
- }
- }
-
- /**
- * Triggers the start of a resize event, attached to the resize handle element mouse down event.
- * Adds no-selection class to the body, disabling selection while moving.
- *
- * @param {Event} event DOM event object.
- * @param {Object} instance The dilog instance.
- *
- * @return {Boolean} false
- */
- function beginResize(event, instance) {
- if (!instance.isMaximized()) {
- var eventSrc;
- if (event.type === 'touchstart') {
- event.preventDefault();
- eventSrc = event.targetTouches[0];
- } else if (event.button === 0) {
- eventSrc = event;
- }
- if (eventSrc) {
- // allow custom `onresize` method
- dispatchEvent('onresize', instance);
-
- resizable = instance;
- handleOffset = instance.elements.resizeHandle.offsetHeight / 2;
- var element = instance.elements.dialog;
- addClass(element, classes.capture);
- startingLeft = parseInt(element.style.left, 10);
- element.style.height = element.offsetHeight + 'px';
- element.style.minHeight = instance.elements.header.offsetHeight + instance.elements.footer.offsetHeight + 'px';
- element.style.width = (startingWidth = element.offsetWidth) + 'px';
-
- if (element.style.maxWidth !== 'none') {
- element.style.minWidth = (minWidth = element.offsetWidth) + 'px';
- }
- element.style.maxWidth = 'none';
- addClass(document.body, classes.noSelection);
- return false;
- }
- }
- }
-
- /**
- * The actual resize handler, attached to document.body mousemove event.
- *
- * @param {Event} event DOM event object.
- *
- * @return {undefined}
- */
- function resize(event) {
- if (resizable) {
- var eventSrc;
- if (event.type === 'touchmove') {
- event.preventDefault();
- eventSrc = event.targetTouches[0];
- } else if (event.button === 0) {
- eventSrc = event;
- }
- if (eventSrc) {
- resizeElement(eventSrc, resizable.elements.dialog, !resizable.get('modal') && !resizable.get('pinned'));
- }
- }
- }
-
- /**
- * Triggers the end of a resize event, attached to document.body mouseup event.
- * Removes no-selection class from document.body, allowing selection.
- *
- * @return {undefined}
- */
- function endResize() {
- if (resizable) {
- var instance = resizable;
- resizable = null;
- removeClass(document.body, classes.noSelection);
- removeClass(instance.elements.dialog, classes.capture);
- cancelClick = true;
- // allow custom `onresized` method
- dispatchEvent('onresized', instance);
- }
- }
-
- /**
- * Resets any changes made by resizing the element to its original state.
- *
- * @param {Object} instance The dilog instance.
- *
- * @return {undefined}
- */
- function resetResize(instance) {
- resizable = null;
- var element = instance.elements.dialog;
- if (element.style.maxWidth === 'none') {
- //clear inline styles.
- element.style.maxWidth = element.style.minWidth = element.style.width = element.style.height = element.style.minHeight = element.style.left = '';
- //reset variables.
- startingLeft = Number.Nan;
- startingWidth = minWidth = handleOffset = 0;
- }
- }
-
-
- /**
- * Updates the dialog move behavior.
- *
- * @param {Object} instance The dilog instance.
- * @param {Boolean} on True to add the behavior, removes it otherwise.
- *
- * @return {undefined}
- */
- function updateResizable(instance) {
- if (instance.get('resizable')) {
- // add class
- addClass(instance.elements.root, classes.resizable);
- if (instance.isOpen()) {
- bindResizableEvents(instance);
- }
- } else {
- //reset
- resetResize(instance);
- // remove class
- removeClass(instance.elements.root, classes.resizable);
- if (instance.isOpen()) {
- unbindResizableEvents(instance);
- }
- }
- }
-
- /**
- * Reset move/resize on window resize.
- *
- * @param {Event} event window resize event object.
- *
- * @return {undefined}
- */
- function windowResize(/*event*/) {
- for (var x = 0; x < openDialogs.length; x += 1) {
- var instance = openDialogs[x];
- if (instance.get('autoReset')) {
- resetMove(instance);
- resetResize(instance);
- }
- }
- }
-
- /**
- * Bind dialogs events
- *
- * @param {Object} instance The dilog instance.
- *
- * @return {undefined}
- */
- function bindEvents(instance) {
- // if first dialog, hook global handlers
- if (openDialogs.length === 1) {
- //global
- on(window, 'resize', windowResize);
- on(document.body, 'keyup', keyupHandler);
- on(document.body, 'keydown', keydownHandler);
- on(document.body, 'focus', onReset);
-
- //move
- on(document.documentElement, 'mousemove', move);
- on(document.documentElement, 'touchmove', move, false, false);
- on(document.documentElement, 'mouseup', endMove);
- on(document.documentElement, 'touchend', endMove);
- //resize
- on(document.documentElement, 'mousemove', resize);
- on(document.documentElement, 'touchmove', resize, false, false);
- on(document.documentElement, 'mouseup', endResize);
- on(document.documentElement, 'touchend', endResize);
- }
-
- // common events
- on(instance.elements.commands.container, 'click', instance.__internal.commandsClickHandler);
- on(instance.elements.footer, 'click', instance.__internal.buttonsClickHandler);
- on(instance.elements.reset[0], 'focusin', instance.__internal.resetHandler);
- on(instance.elements.reset[0], 'keydown', recycleTab);
- on(instance.elements.reset[1], 'focusin', instance.__internal.resetHandler);
-
- //prevent handling key up when dialog is being opened by a key stroke.
- cancelKeyup = true;
- // hook in transition handler
- on(instance.elements.dialog, transition.type, instance.__internal.transitionInHandler);
-
- // modelss only events
- if (!instance.get('modal')) {
- bindModelessEvents(instance);
- }
-
- // resizable
- if (instance.get('resizable')) {
- bindResizableEvents(instance);
- }
-
- // movable
- if (instance.get('movable')) {
- bindMovableEvents(instance);
- }
- }
-
- /**
- * Unbind dialogs events
- *
- * @param {Object} instance The dilog instance.
- *
- * @return {undefined}
- */
- function unbindEvents(instance) {
- // if last dialog, remove global handlers
- if (openDialogs.length === 1) {
- //global
- off(window, 'resize', windowResize);
- off(document.body, 'keyup', keyupHandler);
- off(document.body, 'keydown', keydownHandler);
- off(document.body, 'focus', onReset);
- //move
- off(document.documentElement, 'mousemove', move);
- off(document.documentElement, 'mouseup', endMove);
- //resize
- off(document.documentElement, 'mousemove', resize);
- off(document.documentElement, 'mouseup', endResize);
- }
-
- // common events
- off(instance.elements.commands.container, 'click', instance.__internal.commandsClickHandler);
- off(instance.elements.footer, 'click', instance.__internal.buttonsClickHandler);
- off(instance.elements.reset[0], 'focusin', instance.__internal.resetHandler);
- off(instance.elements.reset[0], 'keydown', recycleTab);
- off(instance.elements.reset[1], 'focusin', instance.__internal.resetHandler);
-
- // hook out transition handler
- on(instance.elements.dialog, transition.type, instance.__internal.transitionOutHandler);
-
- // modelss only events
- if (!instance.get('modal')) {
- unbindModelessEvents(instance);
- }
-
- // movable
- if (instance.get('movable')) {
- unbindMovableEvents(instance);
- }
-
- // resizable
- if (instance.get('resizable')) {
- unbindResizableEvents(instance);
- }
-
- }
-
- /**
- * Bind modeless specific events
- *
- * @param {Object} instance The dilog instance.
- *
- * @return {undefined}
- */
- function bindModelessEvents(instance) {
- on(instance.elements.dialog, 'focus', instance.__internal.bringToFrontHandler, true);
- }
-
- /**
- * Unbind modeless specific events
- *
- * @param {Object} instance The dilog instance.
- *
- * @return {undefined}
- */
- function unbindModelessEvents(instance) {
- off(instance.elements.dialog, 'focus', instance.__internal.bringToFrontHandler, true);
- }
-
-
- /**
- * Bind movable specific events
- *
- * @param {Object} instance The dilog instance.
- *
- * @return {undefined}
- */
- function bindMovableEvents(instance) {
- on(instance.elements.header, 'mousedown', instance.__internal.beginMoveHandler);
- on(instance.elements.header, 'touchstart', instance.__internal.beginMoveHandler, false, false);
- }
-
- /**
- * Unbind movable specific events
- *
- * @param {Object} instance The dilog instance.
- *
- * @return {undefined}
- */
- function unbindMovableEvents(instance) {
- off(instance.elements.header, 'mousedown', instance.__internal.beginMoveHandler);
- off(instance.elements.header, 'touchstart', instance.__internal.beginMoveHandler, false, false);
- }
-
-
- /**
- * Bind resizable specific events
- *
- * @param {Object} instance The dilog instance.
- *
- * @return {undefined}
- */
- function bindResizableEvents(instance) {
- on(instance.elements.resizeHandle, 'mousedown', instance.__internal.beginResizeHandler);
- on(instance.elements.resizeHandle, 'touchstart', instance.__internal.beginResizeHandler, false, false);
- }
-
- /**
- * Unbind resizable specific events
- *
- * @param {Object} instance The dilog instance.
- *
- * @return {undefined}
- */
- function unbindResizableEvents(instance) {
- off(instance.elements.resizeHandle, 'mousedown', instance.__internal.beginResizeHandler);
- off(instance.elements.resizeHandle, 'touchstart', instance.__internal.beginResizeHandler, false, false);
- }
-
- /**
- * Bind closable events
- *
- * @param {Object} instance The dilog instance.
- *
- * @return {undefined}
- */
- function bindClosableEvents(instance) {
- on(instance.elements.modal, 'click', instance.__internal.modalClickHandler);
- }
-
- /**
- * Unbind closable specific events
- *
- * @param {Object} instance The dilog instance.
- *
- * @return {undefined}
- */
- function unbindClosableEvents(instance) {
- off(instance.elements.modal, 'click', instance.__internal.modalClickHandler);
- }
-
- // dialog API
- return {
- __init: initialize,
- /**
- * Check if dialog is currently open
- *
- * @return {Boolean}
- */
- isOpen: function () {
- return this.__internal.isOpen;
- },
- isModal: function () {
- return this.elements.root.className.indexOf(classes.modeless) < 0;
- },
- isMaximized: function () {
- return this.elements.root.className.indexOf(classes.maximized) > -1;
- },
- isPinned: function () {
- return this.elements.root.className.indexOf(classes.unpinned) < 0;
- },
- maximize: function () {
- if (!this.isMaximized()) {
- maximize(this);
- }
- return this;
- },
- restore: function () {
- if (this.isMaximized()) {
- restore(this);
- }
- return this;
- },
- pin: function () {
- if (!this.isPinned()) {
- pin(this);
- }
- return this;
- },
- unpin: function () {
- if (this.isPinned()) {
- unpin(this);
- }
- return this;
- },
- bringToFront: function () {
- bringToFront(null, this);
- return this;
- },
- /**
- * Move the dialog to a specific x/y coordinates
- *
- * @param {Number} x The new dialog x coordinate in pixels.
- * @param {Number} y The new dialog y coordinate in pixels.
- *
- * @return {Object} The dialog instance.
- */
- moveTo: function (x, y) {
- if (!isNaN(x) && !isNaN(y)) {
- // allow custom `onmove` method
- dispatchEvent('onmove', this);
-
- var element = this.elements.dialog,
- current = element,
- offsetLeft = 0,
- offsetTop = 0;
-
- //subtract existing left,top
- if (element.style.left) {
- offsetLeft -= parseInt(element.style.left, 10);
- }
- if (element.style.top) {
- offsetTop -= parseInt(element.style.top, 10);
- }
- //calc offset
- do {
- offsetLeft += current.offsetLeft;
- offsetTop += current.offsetTop;
- } while (current = current.offsetParent);
-
- //calc left, top
- var left = (x - offsetLeft);
- var top = (y - offsetTop);
-
- //// rtl handling
- if (isRightToLeft()) {
- left *= -1;
- }
-
- element.style.left = left + 'px';
- element.style.top = top + 'px';
-
- // allow custom `onmoved` method
- dispatchEvent('onmoved', this);
- }
- return this;
- },
- /**
- * Resize the dialog to a specific width/height (the dialog must be 'resizable').
- * The dialog can be resized to:
- * A minimum width equal to the initial display width
- * A minimum height equal to the sum of header/footer heights.
- *
- *
- * @param {Number or String} width The new dialog width in pixels or in percent.
- * @param {Number or String} height The new dialog height in pixels or in percent.
- *
- * @return {Object} The dialog instance.
- */
- resizeTo: function (width, height) {
- var w = parseFloat(width),
- h = parseFloat(height),
- regex = /(\d*\.\d+|\d+)%/
- ;
-
- if (!isNaN(w) && !isNaN(h) && this.get('resizable') === true) {
-
- // allow custom `onresize` method
- dispatchEvent('onresize', this);
-
- if (('' + width).match(regex)) {
- w = w / 100 * document.documentElement.clientWidth;
- }
-
- if (('' + height).match(regex)) {
- h = h / 100 * document.documentElement.clientHeight;
- }
-
- var element = this.elements.dialog;
- if (element.style.maxWidth !== 'none') {
- element.style.minWidth = (minWidth = element.offsetWidth) + 'px';
- }
- element.style.maxWidth = 'none';
- element.style.minHeight = this.elements.header.offsetHeight + this.elements.footer.offsetHeight + 'px';
- element.style.width = w + 'px';
- element.style.height = h + 'px';
-
- // allow custom `onresized` method
- dispatchEvent('onresized', this);
- }
- return this;
- },
- /**
- * Gets or Sets dialog settings/options
- *
- * @param {String|Object} key A string specifying a propery name or a collection of key/value pairs.
- * @param {Object} value Optional, the value associated with the key (in case it was a string).
- *
- * @return {undefined}
- */
- setting: function (key, value) {
- var self = this;
- var result = update(this, this.__internal.options, function (k, o, n) {
- optionUpdated(self, k, o, n);
- }, key, value);
- if (result.op === 'get') {
- if (result.found) {
- return result.value;
- } else if (typeof this.settings !== 'undefined') {
- return update(this, this.settings, this.settingUpdated || function () {
- }, key, value).value;
- } else {
- return undefined;
- }
- } else if (result.op === 'set') {
- if (result.items.length > 0) {
- var callback = this.settingUpdated || function () {
- };
- for (var x = 0; x < result.items.length; x += 1) {
- var item = result.items[x];
- if (!item.found && typeof this.settings !== 'undefined') {
- update(this, this.settings, callback, item.key, item.value);
- }
- }
- }
- return this;
- }
- },
- /**
- * [Alias] Sets dialog settings/options
- */
- set: function (key, value) {
- this.setting(key, value);
- return this;
- },
- /**
- * [Alias] Gets dialog settings/options
- */
- get: function (key) {
- return this.setting(key);
- },
- /**
- * Sets dialog header
- * @content {string or element}
- *
- * @return {undefined}
- */
- setHeader: function (content) {
- if (typeof content === 'string') {
- clearContents(this.elements.header);
- this.elements.header.innerHTML = content;
- } else if (content instanceof window.HTMLElement && this.elements.header.firstChild !== content) {
- clearContents(this.elements.header);
- this.elements.header.appendChild(content);
- }
- return this;
- },
- /**
- * Sets dialog contents
- * @content {string or element}
- *
- * @return {undefined}
- */
- setContent: function (content) {
- if (typeof content === 'string') {
- clearContents(this.elements.content);
- this.elements.content.innerHTML = content;
- } else if (content instanceof window.HTMLElement && this.elements.content.firstChild !== content) {
- clearContents(this.elements.content);
- this.elements.content.appendChild(content);
- }
- return this;
- },
- /**
- * Show the dialog as modal
- *
- * @return {Object} the dialog instance.
- */
- showModal: function (className) {
- return this.show(true, className);
- },
- /**
- * Show the dialog
- *
- * @return {Object} the dialog instance.
- */
- show: function (modal, className) {
-
- // ensure initialization
- initialize(this);
-
- if (!this.__internal.isOpen) {
-
- // add to open dialogs
- this.__internal.isOpen = true;
- openDialogs.push(this);
-
- // save last focused element
- if (alertify.defaults.maintainFocus) {
- this.__internal.activeElement = document.activeElement;
- }
-
- // set tabindex attribute on body element this allows script to give it focusable
- if (!document.body.hasAttribute('tabindex')) {
- document.body.setAttribute('tabindex', tabindex = '0');
- }
-
- //allow custom dom manipulation updates before showing the dialog.
- if (typeof this.prepare === 'function') {
- this.prepare();
- }
-
- bindEvents(this);
-
- if (modal !== undefined) {
- this.set('modal', modal);
- }
-
- //save scroll to prevent document jump
- saveScrollPosition();
-
- ensureNoOverflow();
-
- // allow custom dialog class on show
- if (typeof className === 'string' && className !== '') {
- this.__internal.className = className;
- addClass(this.elements.root, className);
- }
-
- // maximize if start maximized
- if (this.get('startMaximized')) {
- this.maximize();
- } else if (this.isMaximized()) {
- restore(this);
- }
-
- updateAbsPositionFix(this);
- this.elements.root.removeAttribute('style');
- removeClass(this.elements.root, classes.animationOut);
- addClass(this.elements.root, classes.animationIn);
-
- // set 1s fallback in case transition event doesn't fire
- clearTimeout(this.__internal.timerIn);
- this.__internal.timerIn = setTimeout(this.__internal.transitionInHandler, transition.supported ? 1000 : 100);
-
- if (isSafari) {
- // force desktop safari reflow
- var root = this.elements.root;
- root.style.display = 'none';
- setTimeout(function () {
- root.style.display = 'block';
- }, 0);
- }
-
- //reflow
- reflow = this.elements.root.offsetWidth;
-
- // show dialog
- removeClass(this.elements.root, classes.hidden);
-
- //restore scroll to prevent document jump
- restoreScrollPosition();
-
- // internal on show event
- if (typeof this.hooks.onshow === 'function') {
- this.hooks.onshow.call(this);
- }
-
- // allow custom `onshow` method
- dispatchEvent('onshow', this);
-
- } else {
- // reset move updates
- resetMove(this);
- // reset resize updates
- resetResize(this);
- // shake the dialog to indicate its already open
- addClass(this.elements.dialog, classes.shake);
- var self = this;
- setTimeout(function () {
- removeClass(self.elements.dialog, classes.shake);
- }, 200);
- }
- return this;
- },
- /**
- * Close the dialog
- *
- * @return {Object} The dialog instance
- */
- close: function () {
- if (this.__internal.isOpen) {
- // custom `onclosing` event
- if (dispatchEvent('onclosing', this) !== false) {
-
- unbindEvents(this);
-
- removeClass(this.elements.root, classes.animationIn);
- addClass(this.elements.root, classes.animationOut);
-
- // set 1s fallback in case transition event doesn't fire
- clearTimeout(this.__internal.timerOut);
- this.__internal.timerOut = setTimeout(this.__internal.transitionOutHandler, transition.supported ? 1000 : 100);
- // hide dialog
- addClass(this.elements.root, classes.hidden);
- //reflow
- reflow = this.elements.modal.offsetWidth;
-
- // return focus to the last active element
- if (alertify.defaults.maintainFocus && this.__internal.activeElement) {
- this.__internal.activeElement.focus();
- this.__internal.activeElement = null;
- }
-
- // remove custom dialog class on hide
- if (typeof this.__internal.className !== 'undefined' && this.__internal.className !== '') {
- removeClass(this.elements.root, this.__internal.className);
- }
-
- // internal on close event
- if (typeof this.hooks.onclose === 'function') {
- this.hooks.onclose.call(this);
- }
-
- // allow custom `onclose` method
- dispatchEvent('onclose', this);
-
- //remove from open dialogs
- openDialogs.splice(openDialogs.indexOf(this), 1);
- this.__internal.isOpen = false;
-
- ensureNoOverflow();
- }
-
- }
- // last dialog and tab index was set by us, remove it.
- if (!openDialogs.length && tabindex === '0') {
- document.body.removeAttribute('tabindex');
- }
- return this;
- },
- /**
- * Close all open dialogs except this.
- *
- * @return {undefined}
- */
- closeOthers: function () {
- alertify.closeAll(this);
- return this;
- },
- /**
- * Destroys this dialog instance
- *
- * @return {undefined}
- */
- destroy: function () {
- if (this.__internal) {
- if (this.__internal.isOpen) {
- //mark dialog for destruction, this will be called on tranistionOut event.
- this.__internal.destroy = function () {
- destruct(this, initialize);
- };
- //close the dialog to unbind all events.
- this.close();
- } else if (!this.__internal.destroy) {
- destruct(this, initialize);
- }
- }
- return this;
- },
- };
- }());
- var notifier = (function () {
- var reflow,
- element,
- openInstances = [],
- classes = defaults.notifier.classes,
- baseClass = classes.base;
-
- /**
- * Helper: initializes the notifier instance
- *
- */
- function initialize(instance) {
-
- if (!instance.__internal) {
- instance.__internal = {
- position: alertify.defaults.notifier.position,
- delay: alertify.defaults.notifier.delay,
- };
-
- element = document.createElement('DIV');
- var transitionOff = 'transitionOff' in defaults.notifier ? defaults.notifier.transitionOff : defaults.transitionOff;
- if (transitionOff) {
- baseClass = classes.base + ' ajs-no-transition';
- }
- updatePosition(instance);
- }
-
- //add to DOM tree.
- if (element.parentNode !== document.body) {
- document.body.appendChild(element);
- }
- }
-
- function pushInstance(instance) {
- instance.__internal.pushed = true;
- openInstances.push(instance);
- }
-
- function popInstance(instance) {
- openInstances.splice(openInstances.indexOf(instance), 1);
- instance.__internal.pushed = false;
- }
-
- /**
- * Helper: update the notifier instance position
- *
- */
- function updatePosition(instance) {
- element.className = baseClass;
- switch (instance.__internal.position) {
- case 'top-right':
- addClass(element, classes.top + ' ' + classes.right);
- break;
- case 'top-left':
- addClass(element, classes.top + ' ' + classes.left);
- break;
- case 'top-center':
- addClass(element, classes.top + ' ' + classes.center);
- break;
- case 'bottom-left':
- addClass(element, classes.bottom + ' ' + classes.left);
- break;
- case 'bottom-center':
- addClass(element, classes.bottom + ' ' + classes.center);
- break;
-
- default:
- case 'bottom-right':
- addClass(element, classes.bottom + ' ' + classes.right);
- break;
- }
- }
-
- /**
- * creates a new notification message
- *
- * @param {DOMElement} message The notifier message element
- * @param {Number} wait Time (in ms) to wait before the message is dismissed, a value of 0 means keep open till clicked.
- * @param {Function} callback A callback function to be invoked when the message is dismissed.
- *
- * @return {undefined}
- */
- function create(div, callback) {
-
- function clickDelegate(event, instance) {
- if (!instance.__internal.closeButton || event.target.getAttribute('data-close') === 'true') {
- instance.dismiss(true);
- }
- }
-
- function transitionDone(event, instance) {
- // unbind event
- off(instance.element, transition.type, transitionDone);
- // remove the message
- element.removeChild(instance.element);
- }
-
- function initialize(instance) {
- if (!instance.__internal) {
- instance.__internal = {
- pushed: false,
- delay: undefined,
- timer: undefined,
- clickHandler: undefined,
- transitionEndHandler: undefined,
- transitionTimeout: undefined
- };
- instance.__internal.clickHandler = delegate(instance, clickDelegate);
- instance.__internal.transitionEndHandler = delegate(instance, transitionDone);
- }
- return instance;
- }
-
- function clearTimers(instance) {
- clearTimeout(instance.__internal.timer);
- clearTimeout(instance.__internal.transitionTimeout);
- }
-
- return initialize({
- /* notification DOM element*/
- element: div,
- /*
- * Pushes a notification message
- * @param {string or DOMElement} content The notification message content
- * @param {Number} wait The time (in seconds) to wait before the message is dismissed, a value of 0 means keep open till clicked.
- *
- */
- push: function (_content, _wait) {
- if (!this.__internal.pushed) {
-
- pushInstance(this);
- clearTimers(this);
-
- var content, wait;
- switch (arguments.length) {
- case 0:
- wait = this.__internal.delay;
- break;
- case 1:
- if (typeof (_content) === 'number') {
- wait = _content;
- } else {
- content = _content;
- wait = this.__internal.delay;
- }
- break;
- case 2:
- content = _content;
- wait = _wait;
- break;
- }
- this.__internal.closeButton = alertify.defaults.notifier.closeButton;
- // set contents
- if (typeof content !== 'undefined') {
- this.setContent(content);
- }
- // append or insert
- if (notifier.__internal.position.indexOf('top') < 0) {
- element.appendChild(this.element);
- } else {
- element.insertBefore(this.element, element.firstChild);
- }
- reflow = this.element.offsetWidth;
- addClass(this.element, classes.visible);
- // attach click event
- on(this.element, 'click', this.__internal.clickHandler);
- return this.delay(wait);
- }
- return this;
- },
- /*
- * {Function} callback function to be invoked before dismissing the notification message.
- * Remarks: A return value === 'false' will cancel the dismissal
- *
- */
- ondismiss: function () {
- },
- /*
- * {Function} callback function to be invoked when the message is dismissed.
- *
- */
- callback: callback,
- /*
- * Dismisses the notification message
- * @param {Boolean} clicked A flag indicating if the dismissal was caused by a click.
- *
- */
- dismiss: function (clicked) {
- if (this.__internal.pushed) {
- clearTimers(this);
- if (!(typeof this.ondismiss === 'function' && this.ondismiss.call(this) === false)) {
- //detach click event
- off(this.element, 'click', this.__internal.clickHandler);
- // ensure element exists
- if (typeof this.element !== 'undefined' && this.element.parentNode === element) {
- //transition end or fallback
- this.__internal.transitionTimeout = setTimeout(this.__internal.transitionEndHandler, transition.supported ? 1000 : 100);
- removeClass(this.element, classes.visible);
-
- // custom callback on dismiss
- if (typeof this.callback === 'function') {
- this.callback.call(this, clicked);
- }
- }
- popInstance(this);
- }
- }
- return this;
- },
- /*
- * Delays the notification message dismissal
- * @param {Number} wait The time (in seconds) to wait before the message is dismissed, a value of 0 means keep open till clicked.
- *
- */
- delay: function (wait) {
- clearTimers(this);
- this.__internal.delay = typeof wait !== 'undefined' && !isNaN(+wait) ? +wait : notifier.__internal.delay;
- if (this.__internal.delay > 0) {
- var self = this;
- this.__internal.timer = setTimeout(function () {
- self.dismiss();
- }, this.__internal.delay * 1000);
- }
- return this;
- },
- /*
- * Sets the notification message contents
- * @param {string or DOMElement} content The notification message content
- *
- */
- setContent: function (content) {
- if (typeof content === 'string') {
- clearContents(this.element);
- this.element.innerHTML = content;
- } else if (content instanceof window.HTMLElement && this.element.firstChild !== content) {
- clearContents(this.element);
- this.element.appendChild(content);
- }
- if (this.__internal.closeButton) {
- var close = document.createElement('span');
- addClass(close, classes.close);
- close.setAttribute('data-close', true);
- this.element.appendChild(close);
- }
- return this;
- },
- /*
- * Dismisses all open notifications except this.
- *
- */
- dismissOthers: function () {
- notifier.dismissAll(this);
- return this;
- }
- });
- }
-
- //notifier api
- return {
- /**
- * Gets or Sets notifier settings.
- *
- * @param {string} key The setting name
- * @param {Variant} value The setting value.
- *
- * @return {Object} if the called as a setter, return the notifier instance.
- */
- setting: function (key, value) {
- //ensure init
- initialize(this);
-
- if (typeof value === 'undefined') {
- //get
- return this.__internal[key];
- } else {
- //set
- switch (key) {
- case 'position':
- this.__internal.position = value;
- updatePosition(this);
- break;
- case 'delay':
- this.__internal.delay = value;
- break;
- }
- }
- return this;
- },
- /**
- * [Alias] Sets dialog settings/options
- */
- set: function (key, value) {
- this.setting(key, value);
- return this;
- },
- /**
- * [Alias] Gets dialog settings/options
- */
- get: function (key) {
- return this.setting(key);
- },
- /**
- * Creates a new notification message
- *
- * @param {string} type The type of notification message (simply a CSS class name 'ajs-{type}' to be added).
- * @param {Function} callback A callback function to be invoked when the message is dismissed.
- *
- * @return {undefined}
- */
- create: function (type, callback) {
- //ensure notifier init
- initialize(this);
- //create new notification message
- var div = document.createElement('div');
- div.className = classes.message + ((typeof type === 'string' && type !== '') ? ' ' + classes.prefix + type : '');
- return create(div, callback);
- },
- /**
- * Dismisses all open notifications.
- *
- * @param {Object} excpet [optional] The notification object to exclude from dismissal.
- *
- */
- dismissAll: function (except) {
- var clone = openInstances.slice(0);
- for (var x = 0; x < clone.length; x += 1) {
- var instance = clone[x];
- if (except === undefined || except !== instance) {
- instance.dismiss();
- }
- }
- }
- };
- })();
-
- /**
- * Alertify public API
- * This contains everything that is exposed through the alertify object.
- *
- * @return {Object}
- */
- function Alertify() {
-
- // holds a references of created dialogs
- var dialogs = {};
-
- /**
- * Extends a given prototype by merging properties from base into sub.
- *
- * @sub {Object} sub The prototype being overwritten.
- * @base {Object} base The prototype being written.
- *
- * @return {Object} The extended prototype.
- */
- function extend(sub, base) {
- // copy dialog pototype over definition.
- for (var prop in base) {
- if (base.hasOwnProperty(prop)) {
- sub[prop] = base[prop];
- }
- }
- return sub;
- }
-
-
- /**
- * Helper: returns a dialog instance from saved dialogs.
- * and initializes the dialog if its not already initialized.
- *
- * @name {String} name The dialog name.
- *
- * @return {Object} The dialog instance.
- */
- function get_dialog(name) {
- var dialog = dialogs[name].dialog;
- //initialize the dialog if its not already initialized.
- if (dialog && typeof dialog.__init === 'function') {
- dialog.__init(dialog);
- }
- return dialog;
- }
-
- /**
- * Helper: registers a new dialog definition.
- *
- * @name {String} name The dialog name.
- * @Factory {Function} Factory a function resposible for creating dialog prototype.
- * @transient {Boolean} transient True to create a new dialog instance each time the dialog is invoked, false otherwise.
- * @base {String} base the name of another dialog to inherit from.
- *
- * @return {Object} The dialog definition.
- */
- function register(name, Factory, transient, base) {
- var definition = {
- dialog: null,
- factory: Factory
- };
-
- //if this is based on an existing dialog, create a new definition
- //by applying the new protoype over the existing one.
- if (base !== undefined) {
- definition.factory = function () {
- return extend(new dialogs[base].factory(), new Factory());
- };
- }
-
- if (!transient) {
- //create a new definition based on dialog
- definition.dialog = extend(new definition.factory(), dialog);
- }
- return dialogs[name] = definition;
- }
-
- return {
- /**
- * Alertify defaults
- *
- * @type {Object}
- */
- defaults: defaults,
- /**
- * Dialogs factory
- *
- * @param {string} Dialog name.
- * @param {Function} A Dialog factory function.
- * @param {Boolean} Indicates whether to create a singleton or transient dialog.
- * @param {String} The name of the base type to inherit from.
- */
- dialog: function (name, Factory, transient, base) {
-
- // get request, create a new instance and return it.
- if (typeof Factory !== 'function') {
- return get_dialog(name);
- }
-
- if (this.hasOwnProperty(name)) {
- throw new Error('alertify.dialog: name already exists');
- }
-
- // register the dialog
- var definition = register(name, Factory, transient, base);
-
- if (transient) {
-
- // make it public
- this[name] = function () {
- //if passed with no params, consider it a get request
- if (arguments.length === 0) {
- return definition.dialog;
- } else {
- var instance = extend(new definition.factory(), dialog);
- //ensure init
- if (instance && typeof instance.__init === 'function') {
- instance.__init(instance);
- }
- instance['main'].apply(instance, arguments);
- return instance['show'].apply(instance);
- }
- };
- } else {
- // make it public
- this[name] = function () {
- //ensure init
- if (definition.dialog && typeof definition.dialog.__init === 'function') {
- definition.dialog.__init(definition.dialog);
- }
- //if passed with no params, consider it a get request
- if (arguments.length === 0) {
- return definition.dialog;
- } else {
- var dialog = definition.dialog;
- dialog['main'].apply(definition.dialog, arguments);
- return dialog['show'].apply(definition.dialog);
- }
- };
- }
- },
- /**
- * Close all open dialogs.
- *
- * @param {Object} excpet [optional] The dialog object to exclude from closing.
- *
- * @return {undefined}
- */
- closeAll: function (except) {
- var clone = openDialogs.slice(0);
- for (var x = 0; x < clone.length; x += 1) {
- var instance = clone[x];
- if (except === undefined || except !== instance) {
- instance.close();
- }
- }
- },
- /**
- * Gets or Sets dialog settings/options. if the dialog is transient, this call does nothing.
- *
- * @param {string} name The dialog name.
- * @param {String|Object} key A string specifying a propery name or a collection of key/value pairs.
- * @param {Variant} value Optional, the value associated with the key (in case it was a string).
- *
- * @return {undefined}
- */
- setting: function (name, key, value) {
-
- if (name === 'notifier') {
- return notifier.setting(key, value);
- }
-
- var dialog = get_dialog(name);
- if (dialog) {
- return dialog.setting(key, value);
- }
- },
- /**
- * [Alias] Sets dialog settings/options
- */
- set: function (name, key, value) {
- return this.setting(name, key, value);
- },
- /**
- * [Alias] Gets dialog settings/options
- */
- get: function (name, key) {
- return this.setting(name, key);
- },
- /**
- * Creates a new notification message.
- * If a type is passed, a class name "ajs-{type}" will be added.
- * This allows for custom look and feel for various types of notifications.
- *
- * @param {String | DOMElement} [message=undefined] Message text
- * @param {String} [type=''] Type of log message
- * @param {String} [wait=''] Time (in seconds) to wait before auto-close
- * @param {Function} [callback=undefined] A callback function to be invoked when the log is closed.
- *
- * @return {Object} Notification object.
- */
- notify: function (message, type, wait, callback) {
- return notifier.create(type, callback).push(message, wait);
- },
- /**
- * Creates a new notification message.
- *
- * @param {String} [message=undefined] Message text
- * @param {String} [wait=''] Time (in seconds) to wait before auto-close
- * @param {Function} [callback=undefined] A callback function to be invoked when the log is closed.
- *
- * @return {Object} Notification object.
- */
- message: function (message, wait, callback) {
- return notifier.create(null, callback).push(message, wait);
- },
- /**
- * Creates a new notification message of type 'success'.
- *
- * @param {String} [message=undefined] Message text
- * @param {String} [wait=''] Time (in seconds) to wait before auto-close
- * @param {Function} [callback=undefined] A callback function to be invoked when the log is closed.
- *
- * @return {Object} Notification object.
- */
- success: function (message, wait, callback) {
- return notifier.create('success', callback).push(message, wait);
- },
- /**
- * Creates a new notification message of type 'error'.
- *
- * @param {String} [message=undefined] Message text
- * @param {String} [wait=''] Time (in seconds) to wait before auto-close
- * @param {Function} [callback=undefined] A callback function to be invoked when the log is closed.
- *
- * @return {Object} Notification object.
- */
- error: function (message, wait, callback) {
- return notifier.create('error', callback).push(message, wait);
- },
- /**
- * Creates a new notification message of type 'warning'.
- *
- * @param {String} [message=undefined] Message text
- * @param {String} [wait=''] Time (in seconds) to wait before auto-close
- * @param {Function} [callback=undefined] A callback function to be invoked when the log is closed.
- *
- * @return {Object} Notification object.
- */
- warning: function (message, wait, callback) {
- return notifier.create('warning', callback).push(message, wait);
- },
- /**
- * Dismisses all open notifications
- *
- * @return {undefined}
- */
- dismissAll: function () {
- notifier.dismissAll();
- }
- };
- }
-
- var alertify = new Alertify();
-
- /**
- * Alert dialog definition
- *
- * invoked by:
- * alertify.alert(message);
- * alertify.alert(title, message);
- * alertify.alert(message, onok);
- * alertify.alert(title, message, onok);
- */
- alertify.dialog('alert', function () {
- return {
- main: function (_title, _message, _onok) {
- var title, message, onok;
- switch (arguments.length) {
- case 1:
- message = _title;
- break;
- case 2:
- if (typeof _message === 'function') {
- message = _title;
- onok = _message;
- } else {
- title = _title;
- message = _message;
- }
- break;
- case 3:
- title = _title;
- message = _message;
- onok = _onok;
- break;
- }
- this.set('title', title);
- this.set('message', message);
- this.set('onok', onok);
- return this;
- },
- setup: function () {
- return {
- buttons: [
- {
- text: alertify.defaults.glossary.ok,
- key: keys.ESC,
- invokeOnClose: true,
- className: alertify.defaults.theme.ok,
- }
- ],
- focus: {
- element: 0,
- select: false
- },
- options: {
- maximizable: false,
- resizable: false
- }
- };
- },
- build: function () {
- // nothing
- },
- prepare: function () {
- //nothing
- },
- setMessage: function (message) {
- this.setContent(message);
- },
- settings: {
- message: undefined,
- onok: undefined,
- label: undefined,
- },
- settingUpdated: function (key, oldValue, newValue) {
- switch (key) {
- case 'message':
- this.setMessage(newValue);
- break;
- case 'label':
- if (this.__internal.buttons[0].element) {
- this.__internal.buttons[0].element.innerHTML = newValue;
- }
- break;
- }
- },
- callback: function (closeEvent) {
- if (typeof this.get('onok') === 'function') {
- var returnValue = this.get('onok').call(this, closeEvent);
- if (typeof returnValue !== 'undefined') {
- closeEvent.cancel = !returnValue;
- }
- }
- }
- };
- });
- /**
- * Confirm dialog object
- *
- * alertify.confirm(message);
- * alertify.confirm(message, onok);
- * alertify.confirm(message, onok, oncancel);
- * alertify.confirm(title, message, onok, oncancel);
- */
- alertify.dialog('confirm', function () {
-
- var autoConfirm = {
- timer: null,
- index: null,
- text: null,
- duration: null,
- task: function (event, self) {
- if (self.isOpen()) {
- self.__internal.buttons[autoConfirm.index].element.innerHTML = autoConfirm.text + ' (‏' + autoConfirm.duration + '‏) ';
- autoConfirm.duration -= 1;
- if (autoConfirm.duration === -1) {
- clearAutoConfirm(self);
- var button = self.__internal.buttons[autoConfirm.index];
- var closeEvent = createCloseEvent(autoConfirm.index, button);
-
- if (typeof self.callback === 'function') {
- self.callback.apply(self, [closeEvent]);
- }
- //close the dialog.
- if (closeEvent.close !== false) {
- self.close();
- }
- }
- } else {
- clearAutoConfirm(self);
- }
- }
- };
-
- function clearAutoConfirm(self) {
- if (autoConfirm.timer !== null) {
- clearInterval(autoConfirm.timer);
- autoConfirm.timer = null;
- self.__internal.buttons[autoConfirm.index].element.innerHTML = autoConfirm.text;
- }
- }
-
- function startAutoConfirm(self, index, duration) {
- clearAutoConfirm(self);
- autoConfirm.duration = duration;
- autoConfirm.index = index;
- autoConfirm.text = self.__internal.buttons[index].element.innerHTML;
- autoConfirm.timer = setInterval(delegate(self, autoConfirm.task), 1000);
- autoConfirm.task(null, self);
- }
-
-
- return {
- main: function (_title, _message, _onok, _oncancel) {
- var title, message, onok, oncancel;
- switch (arguments.length) {
- case 1:
- message = _title;
- break;
- case 2:
- message = _title;
- onok = _message;
- break;
- case 3:
- message = _title;
- onok = _message;
- oncancel = _onok;
- break;
- case 4:
- title = _title;
- message = _message;
- onok = _onok;
- oncancel = _oncancel;
- break;
- }
- this.set('title', title);
- this.set('message', message);
- this.set('onok', onok);
- this.set('oncancel', oncancel);
- return this;
- },
- setup: function () {
- return {
- buttons: [
- {
- text: alertify.defaults.glossary.ok,
- key: keys.ENTER,
- className: alertify.defaults.theme.ok,
- },
- {
- text: alertify.defaults.glossary.cancel,
- key: keys.ESC,
- invokeOnClose: true,
- className: alertify.defaults.theme.cancel,
- }
- ],
- focus: {
- element: 0,
- select: false
- },
- options: {
- maximizable: false,
- resizable: false
- }
- };
- },
- build: function () {
- //nothing
- },
- prepare: function () {
- //nothing
- },
- setMessage: function (message) {
- this.setContent(message);
- },
- settings: {
- message: null,
- labels: null,
- onok: null,
- oncancel: null,
- defaultFocus: null,
- reverseButtons: null,
- },
- settingUpdated: function (key, oldValue, newValue) {
- switch (key) {
- case 'message':
- this.setMessage(newValue);
- break;
- case 'labels':
- if ('ok' in newValue && this.__internal.buttons[0].element) {
- this.__internal.buttons[0].text = newValue.ok;
- this.__internal.buttons[0].element.innerHTML = newValue.ok;
- }
- if ('cancel' in newValue && this.__internal.buttons[1].element) {
- this.__internal.buttons[1].text = newValue.cancel;
- this.__internal.buttons[1].element.innerHTML = newValue.cancel;
- }
- break;
- case 'reverseButtons':
- if (newValue === true) {
- this.elements.buttons.primary.appendChild(this.__internal.buttons[0].element);
- } else {
- this.elements.buttons.primary.appendChild(this.__internal.buttons[1].element);
- }
- break;
- case 'defaultFocus':
- this.__internal.focus.element = newValue === 'ok' ? 0 : 1;
- break;
- }
- },
- callback: function (closeEvent) {
- clearAutoConfirm(this);
- var returnValue;
- switch (closeEvent.index) {
- case 0:
- if (typeof this.get('onok') === 'function') {
- returnValue = this.get('onok').call(this, closeEvent);
- if (typeof returnValue !== 'undefined') {
- closeEvent.cancel = !returnValue;
- }
- }
- break;
- case 1:
- if (typeof this.get('oncancel') === 'function') {
- returnValue = this.get('oncancel').call(this, closeEvent);
- if (typeof returnValue !== 'undefined') {
- closeEvent.cancel = !returnValue;
- }
- }
- break;
- }
- },
- autoOk: function (duration) {
- startAutoConfirm(this, 0, duration);
- return this;
- },
- autoCancel: function (duration) {
- startAutoConfirm(this, 1, duration);
- return this;
- }
- };
- });
- /**
- * Prompt dialog object
- *
- * invoked by:
- * alertify.prompt(message);
- * alertify.prompt(message, value);
- * alertify.prompt(message, value, onok);
- * alertify.prompt(message, value, onok, oncancel);
- * alertify.prompt(title, message, value, onok, oncancel);
- */
- alertify.dialog('prompt', function () {
- var input = document.createElement('INPUT');
- var p = document.createElement('P');
- return {
- main: function (_title, _message, _value, _onok, _oncancel) {
- var title, message, value, onok, oncancel;
- switch (arguments.length) {
- case 1:
- message = _title;
- break;
- case 2:
- message = _title;
- value = _message;
- break;
- case 3:
- message = _title;
- value = _message;
- onok = _value;
- break;
- case 4:
- message = _title;
- value = _message;
- onok = _value;
- oncancel = _onok;
- break;
- case 5:
- title = _title;
- message = _message;
- value = _value;
- onok = _onok;
- oncancel = _oncancel;
- break;
- }
- this.set('title', title);
- this.set('message', message);
- this.set('value', value);
- this.set('onok', onok);
- this.set('oncancel', oncancel);
- return this;
- },
- setup: function () {
- return {
- buttons: [
- {
- text: alertify.defaults.glossary.ok,
- key: keys.ENTER,
- className: alertify.defaults.theme.ok,
- },
- {
- text: alertify.defaults.glossary.cancel,
- key: keys.ESC,
- invokeOnClose: true,
- className: alertify.defaults.theme.cancel,
- }
- ],
- focus: {
- element: input,
- select: true
- },
- options: {
- maximizable: false,
- resizable: false
- }
- };
- },
- build: function () {
- input.className = alertify.defaults.theme.input;
- input.setAttribute('type', 'text');
- input.value = this.get('value');
- this.elements.content.appendChild(p);
- this.elements.content.appendChild(input);
- },
- prepare: function () {
- //nothing
- },
- setMessage: function (message) {
- if (typeof message === 'string') {
- clearContents(p);
- p.innerHTML = message;
- } else if (message instanceof window.HTMLElement && p.firstChild !== message) {
- clearContents(p);
- p.appendChild(message);
- }
- },
- settings: {
- message: undefined,
- labels: undefined,
- onok: undefined,
- oncancel: undefined,
- value: '',
- type: 'text',
- reverseButtons: undefined,
- },
- settingUpdated: function (key, oldValue, newValue) {
- switch (key) {
- case 'message':
- this.setMessage(newValue);
- break;
- case 'value':
- input.value = newValue;
- break;
- case 'type':
- switch (newValue) {
- case 'text':
- case 'color':
- case 'date':
- case 'datetime-local':
- case 'email':
- case 'month':
- case 'number':
- case 'password':
- case 'search':
- case 'tel':
- case 'time':
- case 'week':
- input.type = newValue;
- break;
- default:
- input.type = 'text';
- break;
- }
- break;
- case 'labels':
- if (newValue.ok && this.__internal.buttons[0].element) {
- this.__internal.buttons[0].element.innerHTML = newValue.ok;
- }
- if (newValue.cancel && this.__internal.buttons[1].element) {
- this.__internal.buttons[1].element.innerHTML = newValue.cancel;
- }
- break;
- case 'reverseButtons':
- if (newValue === true) {
- this.elements.buttons.primary.appendChild(this.__internal.buttons[0].element);
- } else {
- this.elements.buttons.primary.appendChild(this.__internal.buttons[1].element);
- }
- break;
- }
- },
- callback: function (closeEvent) {
- var returnValue;
- switch (closeEvent.index) {
- case 0:
- this.settings.value = input.value;
- if (typeof this.get('onok') === 'function') {
- returnValue = this.get('onok').call(this, closeEvent, this.settings.value);
- if (typeof returnValue !== 'undefined') {
- closeEvent.cancel = !returnValue;
- }
- }
- break;
- case 1:
- if (typeof this.get('oncancel') === 'function') {
- returnValue = this.get('oncancel').call(this, closeEvent);
- if (typeof returnValue !== 'undefined') {
- closeEvent.cancel = !returnValue;
- }
- }
- if (!closeEvent.cancel) {
- input.value = this.settings.value;
- }
- break;
- }
- }
- };
- });
-
- // CommonJS
- if (typeof module === 'object' && typeof module.exports === 'object') {
- module.exports = alertify;
- // AMD
- } else if (typeof define === 'function' && define.amd) {
- define([], function () {
- return alertify;
- });
- // window
- } else if (!window.alertify) {
- window.alertify = alertify;
- }
-
- }(typeof window !== 'undefined' ? window : this));
|