1(function(root, factory) { 2 if (typeof define === 'function' && define.amd) { 3 define(['jquery'], factory); 4 } else { 5 factory(root.jQuery); 6 } 7}(this, function($) { 8 'use strict'; 9 10 // ######################################################################## 11 // Base object 12 // ######################################################################## 13 14 /** 15 * Imp - Impromptu object - passing no params will not open, only return the instance 16 * @param message String/Object - String of html or Object of states 17 * @param options Object - Options to set the prompt 18 * @return Imp - the instance of this Impromptu object 19 */ 20 var Imp = function(message, options){ 21 var t = this; 22 t.id = Imp.count++; 23 24 Imp.lifo.push(t); 25 26 if(message){ 27 t.open(message, options); 28 } 29 return t; 30 }; 31 32 // ######################################################################## 33 // static properties and methods 34 // ######################################################################## 35 36 /** 37 * defaults - the default options 38 */ 39 Imp.defaults = { 40 prefix:'jqi', 41 classes: { 42 box: '', 43 fade: '', 44 prompt: '', 45 form: '', 46 close: '', 47 title: '', 48 message: '', 49 buttons: '', 50 button: '', 51 defaultButton: '' 52 }, 53 title: '', 54 closeText: '×', 55 buttons: { 56 Ok: true 57 }, 58 buttonTimeout: 1000, 59 loaded: function(e){}, 60 submit: function(e,v,m,f){}, 61 close: function(e,v,m,f){}, 62 statechanging: function(e, from, to){}, 63 statechanged: function(e, to){}, 64 opacity: 0.6, 65 zIndex: 999, 66 overlayspeed: 'slow', 67 promptspeed: 'fast', 68 show: 'fadeIn', 69 hide: 'fadeOut', 70 focus: 0, 71 defaultButton: 0, 72 useiframe: false, 73 top: '15%', 74 position: { 75 container: null, 76 x: null, 77 y: null, 78 arrow: null, 79 width: null 80 }, 81 persistent: true, 82 timeout: 0, 83 states: {}, 84 initialState: 0, 85 state: { 86 name: null, 87 title: '', 88 html: '', 89 buttons: { 90 Ok: true 91 }, 92 focus: 0, 93 defaultButton: 0, 94 position: { 95 container: null, 96 x: null, 97 y: null, 98 arrow: null, 99 width: null 100 }, 101 submit: function(e,v,m,f){ 102 return true; 103 } 104 } 105 }; 106 107 /** 108 * setDefaults - Sets the default options 109 * @param o Object - Options to set as defaults 110 * @return void 111 */ 112 Imp.setDefaults = function(o) { 113 Imp.defaults = $.extend({}, Imp.defaults, o); 114 }; 115 116 /** 117 * setStateDefaults - Sets the default options for a state 118 * @param o Object - Options to set as defaults 119 * @return void 120 */ 121 Imp.setStateDefaults = function(o) { 122 Imp.defaults.state = $.extend({}, Imp.defaults.state, o); 123 }; 124 125 /** 126 * @var Int - A counter used to provide a unique ID for new prompts 127 */ 128 Imp.count = 0; 129 130 /** 131 * @var Array - An array of Impromptu intances in a LIFO queue (last in first out) 132 */ 133 Imp.lifo = []; 134 135 /** 136 * getLast - get the last element from the queue (doesn't pop, just returns) 137 * @return Imp - the instance of this Impromptu object or false if queue is empty 138 */ 139 Imp.getLast = function(){ 140 var l = Imp.lifo.length; 141 return (l > 0)? Imp.lifo[l-1] : false; 142 }; 143 144 /** 145 * removeFromStack - remove an element from the lifo stack by its id 146 * @param id int - id of the instance to remove 147 * @return api - The api of the element removed from the stack or void 148 */ 149 Imp.removeFromStack = function(id){ 150 for(var i=Imp.lifo.length-1; i>=0; i--){ 151 if(Imp.lifo[i].id === id){ 152 return Imp.lifo.splice(i,1)[0]; 153 } 154 } 155 }; 156 157 // ######################################################################## 158 // extend our object instance properties and methods 159 // ######################################################################## 160 Imp.prototype = { 161 162 /** 163 * @var Int - A unique id, simply an autoincremented number 164 */ 165 id: null, 166 167 /** 168 * open - Opens the prompt 169 * @param message String/Object - String of html or Object of states 170 * @param options Object - Options to set the prompt 171 * @return Imp - the instance of this Impromptu object 172 */ 173 open: function(message, options) { 174 var t = this; 175 176 t.options = $.extend({},Imp.defaults,options); 177 178 // Be sure any previous timeouts are destroyed 179 if(t.timeout){ 180 clearTimeout(t.timeout); 181 } 182 t.timeout = false;
183 184 var opts = t.options, 185 $body = $(document.body), 186 $window = $(window); 187 188 //build the box and fade 189 var msgbox = '<div class="'+ opts.prefix +'box '+ opts.classes.box +'">'; 190 if(opts.useiframe && ($('object, applet').length > 0)) { 191 msgbox += '<iframe src="javascript:false;" class="'+ opts.prefix +'fade '+ opts.classes.fade +'"></iframe>'; 192 } else { 193 msgbox += '<div class="'+ opts.prefix +'fade '+ opts.classes.fade +'"></div>'; 194 } 195 msgbox += '<div class="'+ opts.prefix +' '+ opts.classes.prompt +'">'+ 196 '<form action="#" class="'+ opts.prefix +'form '+ opts.classes.form +'">'+ 197 '<div class="'+ opts.prefix +'close '+ opts.classes.close +'">'+ opts.closeText +'</div>'+ 198 '<div class="'+ opts.prefix +'states"></div>'+ 199 '</form>'+ 200 '</div>'+ 201 '</div>'; 202 203 t.jqib = $(msgbox).appendTo($body); 204 t.jqi = t.jqib.children('.'+ opts.prefix); 205 t.jqif = t.jqib.children('.'+ opts.prefix +'fade'); 206 207 //if a string was passed, convert to a single state 208 if(message.constructor === String){ 209 message = { 210 state0: { 211 title: opts.title, 212 html: message, 213 buttons: opts.buttons, 214 position: opts.position, 215 focus: opts.focus, 216 defaultButton: opts.defaultButton, 217 submit: opts.submit 218 } 219 }; 220 } 221 222 //build the states 223 t.options.states = {}; 224 var k,v; 225 for(k in message){ 226 v = $.extend({},Imp.defaults.state,{name:k},message[k]); 227 t.addState(v.name, v); 228 229 if(t.currentStateName === ''){ 230 t.currentStateName = v.name; 231 } 232 } 233 234 //Events 235 t.jqi.on('click', '.'+ opts.prefix +'buttons button', function(e){ 236 var $t = $(this), 237 $state = $t.parents('.'+ opts.prefix +'state'), 238 statename = $state.data('jqi-name'), 239 stateobj = t.options.states[statename], 240 msg = $state.children('.'+ opts.prefix +'message'), 241 clicked = stateobj.buttons[$t.text()] || stateobj.buttons[$t.html()], 242 forminputs = {}; 243 244 // disable for a moment to prevent multiple clicks 245 if(t.options.buttonTimeout > 0){ 246 t.disableStateButtons(statename); 247 setTimeout(function(){ 248 t.enableStateButtons(statename); 249 }, t.options.buttonTimeout); 250 } 251 252 // if for some reason we couldn't get the value 253 if(clicked === undefined){ 254 for(var i in stateobj.buttons){ 255 if(stateobj.buttons[i].title === $t.text() || stateobj.buttons[i].title === $t.html()){ 256 clicked = stateobj.buttons[i].value; 257 } 258 } 259 } 260 261 //collect all form element values from all states. 262 $.each(t.jqi.children('form').serializeArray(),function(i,obj){ 263 if (forminputs[obj.name] === undefined) { 264 forminputs[obj.name] = obj.value; 265 } else if (typeof forminputs[obj.name] === Array || typeof forminputs[obj.name] === 'object') { 266 forminputs[obj.name].push(obj.value); 267 } else { 268 forminputs[obj.name] = [forminputs[obj.name],obj.value]; 269 } 270 }); 271 272 // trigger an event 273 var promptsubmite = new $.Event('impromptu:submit'); 274 promptsubmite.stateName = stateobj.name; 275 promptsubmite.state = $state; 276 $state.trigger(promptsubmite, [clicked, msg, forminputs]); 277 278 if(!promptsubmite.isDefaultPrevented()){ 279 t.close(true, clicked,msg,forminputs); 280 } 281 }); 282 283 // if the fade is clicked blink the prompt 284 var fadeClicked = function(){ 285 if(opts.persistent){ 286 var offset = (opts.top.toString().indexOf('%') >= 0? ($window.height()*(parseInt(opts.top,10)/100)) : parseInt(opts.top,10)), 287 top = parseInt(t.jqi.css('top').replace('px',''),10) - offset; 288 289 //$window.scrollTop(top); 290 $('html,body').animate({ scrollTop: top }, 'fast', function(){ 291 var i = 0; 292 t.jqib.addClass(opts.prefix +'warning'); 293 var intervalid = setInterval(function(){ 294 t.jqib.toggleClass(opts.prefix +'warning'); 295 if(i++ > 1){ 296 clearInterval(intervalid); 297 t.jqib.removeClass(opts.prefix +'warning'); 298 } 299 }, 100); 300 }); 301 } 302 else { 303 t.close(true); 304 } 305 }; 306 307 // listen for esc or tab keys 308 var keyDownEventHandler = function(e){ 309 var key = (window.event) ? event.keyCode : e.keyCode; 310 311 //escape key closes 312 if(key === 27) { 313 fadeClicked(); 314 } 315 316 //enter key pressed trigger the default button if its not on it, ignore if it is a textarea 317 if(key === 13){ 318 var $defBtn = t.getCurrentState().find('.'+ opts.prefix +'defaultbutton'); 319 var $tgt = $(e.target); 320 321 if($tgt.is('textarea,.'+opts.prefix+'button') === false && $defBtn.length > 0){ 322 e.preventDefault(); 323 $defBtn.click(); 324 } 325 } 326 327 //constrain tabs, tabs should iterate through the state and not leave 328 if (key === 9){ 329 var $inputels = $('input,select,textarea,button',t.getCurrentState()); 330 var fwd = !e.shiftKey && e.target === $inputels[$inputels.length-1]; 331 var back = e.shiftKey && e.target === $inputels[0]; 332 if (fwd || back) { 333 setTimeout(function(){ 334 if (!$inputels){ 335 return; 336 } 337 var el = $inputels[back===true ? $inputels.length-1 : 0]; 338 339 if (el){ 340 el.focus(); 341 } 342 },10); 343 return false;
344 } 345 } 346 }; 347 348 t.position(); 349 t.style(); 350 351 // store copy of the window resize function for interal use only 352 t._windowResize = function(e){ 353 t.position(e); 354 }; 355 $window.resize({ animate: false }, t._windowResize); 356 357 t.jqif.click(fadeClicked); 358 t.jqi.find('.'+ opts.prefix +'close').click(function(){ t.close(); }); 359 t.jqi.find('.'+ opts.prefix +'form').submit(function(){ return false; }); 360 t.jqib.on("keydown",keyDownEventHandler) 361 .on('impromptu:loaded', opts.loaded) 362 .on('impromptu:close', opts.close) 363 .on('impromptu:statechanging', opts.statechanging) 364 .on('impromptu:statechanged', opts.statechanged); 365 366 // Show it 367 t.jqif[opts.show](opts.overlayspeed); 368 t.jqi[opts.show](opts.promptspeed, function(){ 369 370 t.goToState( 371 isNaN(opts.initialState) ? opts.initialState : 372 t.jqi.find('.'+ opts.prefix +'states .'+ opts.prefix +'state').eq(opts.initialState).data('jqi-name') 373 ); 374 375 t.jqib.trigger('impromptu:loaded'); 376 }); 377 378 // Timeout 379 if(opts.timeout > 0){ 380 t.timeout = setTimeout(function(){ t.close(true); },opts.timeout); 381 } 382 383 return t; 384 }, 385 386 /** 387 * close - Closes the prompt 388 * @param callback Function - called when the transition is complete 389 * @param clicked String - value of the button clicked (only used internally) 390 * @param msg jQuery - The state message body (only used internally) 391 * @param forvals Object - key/value pairs of all form field names and values (only used internally) 392 * @return Imp - the instance of this Impromptu object 393 */ 394 close: function(callCallback, clicked, msg, formvals){ 395 var t = this; 396 Imp.removeFromStack(t.id); 397 398 if(t.timeout){ 399 clearTimeout(t.timeout); 400 t.timeout = false; 401 } 402 403 if(t.jqib){ 404 t.jqib[t.options.hide]('fast',function(){ 405 406 t.jqib.trigger('impromptu:close', [clicked,msg,formvals]); 407 408 t.jqib.remove(); 409 410 $(window).off('resize', t._windowResize); 411 412 if(typeof callCallback === 'function'){ 413 callCallback(); 414 } 415 }); 416 } 417 t.currentStateName = ""; 418 419 return t; 420 }, 421 422 /** 423 * addState - Injects a state into the prompt 424 * @param statename String - Name of the state 425 * @param stateobj Object - options for the state 426 * @param afterState String - selector of the state to insert after 427 * @return jQuery - the newly created state 428 */ 429 addState: function(statename, stateobj, afterState) { 430 var t = this, 431 state = '', 432 $state = null, 433 arrow = '', 434 title = '', 435 opts = t.options, 436 $jqistates = t.jqi.find('.'+ opts.prefix +'states'), 437 buttons = [], 438 showHtml,defbtn,k,v,l,i=0; 439 440 stateobj = $.extend({},Imp.defaults.state, {name:statename}, stateobj); 441 442 if(stateobj.position.arrow !== null){ 443 arrow = '<div class="'+ opts.prefix + 'arrow '+ opts.prefix + 'arrow'+ stateobj.position.arrow +'"></div>'; 444 } 445 if(stateobj.title && stateobj.title !== ''){ 446 title = '<div class="lead '+ opts.prefix + 'title '+ opts.classes.title +'">'+ stateobj.title +'</div>'; 447 } 448 449 showHtml = stateobj.html; 450 if (typeof stateobj.html === 'function') { 451 showHtml = 'Error: html function must return text'; 452 } 453 454 state += '<div class="'+ opts.prefix + 'state" data-jqi-name="'+ statename +'">'+ 455 arrow + title + 456 '<div class="'+ opts.prefix +'message '+ opts.classes.message +'">' + showHtml +'</div>'+ 457 '<div class="'+ opts.prefix +'buttons'+ ($.isEmptyObject(stateobj.buttons)? 'hide ':' ') + opts.classes.buttons +'">'; 458 459 // state buttons may be in object or array, lets convert objects to arrays 460 if($.isArray(stateobj.buttons)){ 461 buttons = stateobj.buttons; 462 } 463 else if($.isPlainObject(stateobj.buttons)){ 464 for(k in stateobj.buttons){ 465 if(stateobj.buttons.hasOwnProperty(k)){ 466 buttons.push({ title: k, value: stateobj.buttons[k] }); 467 } 468 } 469 } 470 471 // iterate over each button and create them 472 for(i=0, l=buttons.length; i<l; i++){ 473 v = buttons[i], 474 defbtn = stateobj.focus === i || (isNaN(stateobj.focus) && stateobj.defaultButton === i) ? (opts.prefix + 'defaultbutton ' + opts.classes.defaultButton) : ''; 475 476 state += '<button class="'+ opts.classes.button +' '+ opts.prefix + 'button '+ defbtn; 477 478 if(typeof v.classes !== "undefined"){ 479 state += ' '+ ($.isArray(v.classes)? v.classes.join(' ') : v.classes) + ' '; 480 } 481 482 state += '" name="' + opts.prefix + '_' + statename + '_button' + v.title.replace(/[^a-z0-9]+/gi,'') + '" value="' + v.value + '">' + v.title + '</button>'; 483 } 484 485 state += '</div></div>'; 486 487 $state = $(state).css({display:'none'}); 488 489 $state.on('impromptu:submit', stateobj.submit); 490 491 if(afterState !== undefined){ 492 t.getState(afterState).after($state); 493 } 494 else{ 495 $jqistates.append($state); 496 } 497 498 t.options.states[statename] = stateobj; 499 500 return $state; 501 }, 502 503 /** 504 * removeState - Removes a state from the prompt 505 * @param state String - Name of the state 506 * @param newState String - Name of the state to transition to 507 * @return Boolean - returns true on success, false on failure 508 */ 509 removeState: function(state, newState) { 510 var t = this, 511 $state = t.getState(state), 512 rm = function(){ $state.remove(); }; 513 514 if($state.length === 0){ 515 return false;
516 } 517 518 // transition away from it before deleting 519 if($state.css('display') !== 'none'){ 520 if(newState !== undefined && t.getState(newState).length > 0){ 521 t.goToState(newState, false, rm); 522 } 523 else if($state.next().length > 0){ 524 t.nextState(rm); 525 } 526 else if($state.prev().length > 0){ 527 t.prevState(rm); 528 } 529 else{ 530 t.close(); 531 } 532 } 533 else{ 534 $state.slideUp('slow', rm); 535 } 536 537 return true; 538 }, 539 540 /** 541 * getApi - Get the api, so you can extract it from $.prompt stack 542 * @return jQuery - the prompt 543 */ 544 getApi: function() { 545 return this; 546 }, 547 548 /** 549 * getBox - Get the box containing fade and prompt 550 * @return jQuery - the prompt 551 */ 552 getBox: function() { 553 return this.jqib; 554 }, 555 556 /** 557 * getPrompt - Get the prompt 558 * @return jQuery - the prompt 559 */ 560 getPrompt: function() { 561 return this.jqi; 562 }, 563 564 /** 565 * getState - Get the state by its name 566 * @param statename String - Name of the state 567 * @return jQuery - the state 568 */ 569 getState: function(statename) { 570 return this.jqi.find('[data-jqi-name="'+ statename +'"]'); 571 }, 572 573 /** 574 * getCurrentState - Get the current visible state 575 * @return jQuery - the current visible state 576 */ 577 getCurrentState: function() { 578 return this.getState(this.getCurrentStateName()); 579 }, 580 581 /** 582 * getCurrentStateName - Get the name of the current visible state/substate 583 * @return String - the current visible state's name 584 */ 585 getCurrentStateName: function() { 586 return this.currentStateName; 587 }, 588 589 /** 590 * disableStateButtons - Disables the buttons in a state 591 * @param statename String - Name of the state containing buttons 592 * @param buttons Array - Array of button values to disable. By default all are disabled 593 * @param enable Boolean - True to enable the buttons instead of disabling (internally use only) 594 * @return Void 595 */ 596 disableStateButtons: function(statename, buttons, enable) { 597 var t = this; 598 599 if($.isArray(statename)){ 600 buttons = statename; 601 statename = null; 602 } 603 604 t.getState(statename || t.getCurrentStateName()).find('.'+ t.options.prefix + 'button').each(function(i,btn){ 605 if(buttons === undefined || $.inArray(btn.value, buttons) !== -1){ 606 btn.disabled = !enable; 607 } 608 }); 609 }, 610 611 /** 612 * enableStateButtons - Enables the buttons in a state 613 * @param statename String - Name of the state containing buttons. Defaults to current state 614 * @param buttons Array - Array of button values to enable. By default all are enabled 615 * @return Void 616 */ 617 enableStateButtons: function(statename, buttons) { 618 this.disableStateButtons(statename, buttons, true); 619 }, 620 621 /** 622 * position - Repositions the prompt (Used internally) 623 * @return void 624 */ 625 position: function(e){ 626 var t = this, 627 restoreFx = $.fx.off, 628 $state = t.getCurrentState(), 629 stateObj = t.options.states[$state.data('jqi-name')], 630 pos = stateObj? stateObj.position : undefined, 631 $window = $(window), 632 bodyHeight = document.body.scrollHeight, //$(document.body).outerHeight(true), 633 windowHeight = $(window).height(), 634 documentHeight = $(document).height(), 635 height = (bodyHeight > windowHeight) ? bodyHeight : windowHeight, 636 scrollTop = parseInt($window.scrollTop(),10), 637 top = scrollTop + (t.options.top.toString().indexOf('%') >= 0? 638 (windowHeight*(parseInt(t.options.top,10)/100)) : parseInt(t.options.top,10)); 639 640 // when resizing the window turn off animation 641 if(e !== undefined && e.data.animate === false){ 642 $.fx.off = true; 643 } 644 645 t.jqib.css({ 646 position: "absolute", 647 height: height, 648 width: "100%", 649 top: 0, 650 left: 0, 651 right: 0, 652 bottom: 0 653 }); 654 t.jqif.css({ 655 position: "fixed", 656 height: height, 657 width: "100%", 658 top: 0, 659 left: 0, 660 right: 0, 661 bottom: 0 662 }); 663 664 // tour positioning 665 if(pos && pos.container){ 666 var offset = $(pos.container).offset(), 667 hasScrolled = false; 668 669 if($.isPlainObject(offset) && offset.top !== undefined){ 670 top = (offset.top + pos.y) - (t.options.top.toString().indexOf('%') >= 0? (windowHeight*(parseInt(t.options.top,10)/100)) : parseInt(t.options.top,10)); 671 672 t.jqi.css({ 673 position: "absolute" 674 }); 675 t.jqi.animate({ 676 top: offset.top + pos.y, 677 left: offset.left + pos.x, 678 marginLeft: 0, 679 width: (pos.width !== undefined)? pos.width : null 680 }, function(){ 681 // if it didn't scroll before, check that the bottom is within view. Since width 682 // is animated we must use the callback before we know the height 683 if(!hasScrolled && (offset.top + pos.y + t.jqi.outerHeight(true)) > (scrollTop + windowHeight)){ 684 $('html,body').animate({ scrollTop: top }, 'slow', 'swing', function(){}); 685 hasScrolled = true; 686 } 687 }); 688 689 // scroll if the top is out of the viewing area 690 if(top < scrollTop || top > scrollTop + windowHeight){ 691 $('html,body').animate({ scrollTop: top }, 'slow', 'swing', function(){}); 692 hasScrolled = true; 693 } 694 } 695 } 696 // custom state width animation 697 else if(pos && pos.width){ 698 t.jqi.css({ 699 position: "absolute", 700 left: '50%' 701 }); 702 t.jqi.animate({ 703 top: pos.y || top, 704 left: pos.x || '50%', 705 marginLeft: ((pos.width/2)*-1), 706 width: pos.width 707 }); 708 } 709 // standard prompt positioning 710 else{ 711 t.jqi.css({ 712 position: "absolute", 713 top: top, 714 left: '50%',//$window.width()/2, 715 marginLeft: ((t.jqi.outerWidth(false)/2)*-1) 716 }); 717 } 718 719 // restore fx settings 720 if(e !== undefined && e.data.animate === false){ 721 $.fx.off = restoreFx; 722 } 723 }, 724 725 /** 726 * style - Restyles the prompt (Used internally) 727 * @return void 728 */ 729 style: function(){ 730 var t = this; 731 732 t.jqif.css({ 733 zIndex: t.options.zIndex, 734 display: "none", 735 opacity: t.options.opacity 736 }); 737 t.jqi.css({ 738 zIndex: t.options.zIndex+1, 739 display: "none" 740 }); 741 t.jqib.css({ 742 zIndex: t.options.zIndex 743 }); 744 }, 745 746 /** 747 * goToState - Goto the specified state 748 * @param state String - name of the state to transition to 749 * @param subState Boolean - true to be a sub state within the currently open state 750 * @param callback Function - called when the transition is complete 751 * @return jQuery - the newly active state 752 */ 753 goToState: function(state, subState, callback) { 754 var t = this, 755 $jqi = t.jqi, 756 jqiopts = t.options, 757 $state = t.getState(state), 758 stateobj = jqiopts.states[$state.data('jqi-name')], 759 promptstatechanginge = new $.Event('impromptu:statechanging'), 760 opts = t.options; 761 762 if(stateobj !== undefined){ 763 764 765 if (typeof stateobj.html === 'function') { 766 var contentLaterFunc = stateobj.html; 767 $state.find('.' + opts.prefix +'message ').html(contentLaterFunc()); 768 } 769 770 // subState can be ommitted 771 if(typeof subState === 'function'){ 772 callback = subState; 773 subState = false;
774 } 775 776 t.jqib.trigger(promptstatechanginge, [t.getCurrentStateName(), state]); 777 778 if(!promptstatechanginge.isDefaultPrevented() && $state.length > 0){ 779 t.jqi.find('.'+ opts.prefix +'parentstate').removeClass(opts.prefix +'parentstate'); 780 781 if(subState){ // hide any open substates 782 // get rid of any substates 783 t.jqi.find('.'+ opts.prefix +'substate').not($state) 784 .slideUp(jqiopts.promptspeed) 785 .removeClass('.'+ opts.prefix +'substate') 786 .find('.'+ opts.prefix +'arrow').hide(); 787 788 // add parent state class so it can be visible, but blocked 789 t.jqi.find('.'+ opts.prefix +'state:visible').addClass(opts.prefix +'parentstate'); 790 791 // add substate class so we know it will be smaller 792 $state.addClass(opts.prefix +'substate'); 793 } 794 else{ // hide any open states 795 t.jqi.find('.'+ opts.prefix +'state').not($state) 796 .slideUp(jqiopts.promptspeed) 797 .find('.'+ opts.prefix +'arrow').hide(); 798 } 799 t.currentStateName = stateobj.name; 800 801 $state.slideDown(jqiopts.promptspeed,function(){ 802 var $t = $(this); 803 t.enableStateButtons(); 804 805 // if focus is a selector, find it, else its button index 806 if(typeof(stateobj.focus) === 'string'){ 807 $t.find(stateobj.focus).eq(0).focus(); 808 } 809 else{ 810 $t.find('.'+ opts.prefix +'defaultbutton').focus(); 811 } 812 813 $t.find('.'+ opts.prefix +'arrow').show(jqiopts.promptspeed); 814 815 if (typeof callback === 'function'){ 816 t.jqib.on('impromptu:statechanged', callback); 817 } 818 t.jqib.trigger('impromptu:statechanged', [state]); 819 if (typeof callback === 'function'){ 820 t.jqib.off('impromptu:statechanged', callback); 821 } 822 }); 823 if(!subState){ 824 t.position(); 825 } 826 } // end isDefaultPrevented() 827 }// end stateobj !== undefined 828 829 return $state; 830 }, 831 832 /** 833 * nextState - Transition to the next state 834 * @param callback Function - called when the transition is complete 835 * @return jQuery - the newly active state 836 */ 837 nextState: function(callback) { 838 var t = this, 839 $next = t.getCurrentState().next(); 840 if($next.length > 0){ 841 t.goToState( $next.data('jqi-name'), callback ); 842 } 843 return $next; 844 }, 845 846 /** 847 * prevState - Transition to the previous state 848 * @param callback Function - called when the transition is complete 849 * @return jQuery - the newly active state 850 */ 851 prevState: function(callback) { 852 var t = this, 853 $prev = t.getCurrentState().prev(); 854 if($prev.length > 0){ 855 t.goToState( $prev.data('jqi-name'), callback ); 856 } 857 return $prev; 858 } 859 860 }; 861 862 // ######################################################################## 863 // $.prompt will manage a queue of Impromptu instances 864 // ######################################################################## 865 866 /** 867 * $.prompt create a new Impromptu instance and push it on the stack of instances 868 * @param message String/Object - String of html or Object of states 869 * @param options Object - Options to set the prompt 870 * @return jQuery - the jQuery object of the prompt within the modal 871 */ 872 $.prompt = function(message, options){ 873 var api = new Imp(message, options); 874 return api.jqi; 875 }; 876 877 /** 878 * Copy over static methods 879 */ 880 $.each(Imp, function(k,v){ 881 $.prompt[k] = v; 882 }); 883 884 /** 885 * Create a proxy for accessing all instance methods. The close method pops from queue. 886 */ 887 $.each(Imp.prototype, function(k,v){ 888 $.prompt[k] = function(){ 889 var api = Imp.getLast(); // always use the last instance on the stack 890 891 if(api && typeof api[k] === "function"){ 892 return api[k].apply(api, arguments); 893 } 894 }; 895 }); 896 897 // ######################################################################## 898 // jQuery Plugin and public access 899 // ######################################################################## 900 901 /** 902 * Enable using $('.selector').prompt({}); 903 * This will grab the html within the prompt as the prompt message 904 */ 905 $.fn.prompt = function(options){ 906 if(options === undefined){ 907 options = {}; 908 } 909 if(options.withDataAndEvents === undefined){ 910 options.withDataAndEvents = false;
911 } 912 913 $.prompt($(this).clone(options.withDataAndEvents).html(),options); 914 }; 915 916 /** 917 * Export it as Impromptu and $.prompt 918 * Can be used from here forth as new Impromptu(states, opts) 919 */ 920 window.Impromptu = Imp; 921 922}));
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.