summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrent Richardson <trentdrichardson@gmail.com>2015-03-02 14:19:31 -0500
committerTrent Richardson <trentdrichardson@gmail.com>2015-03-02 14:19:31 -0500
commit76f9f5f046e64196148572a86d23bc4946277f75 (patch)
tree264796c25fd1fd3876d0629b9264c458e3c585fd
parent73ab5f48dbdb7b8bf37c090c85d8014019a84612 (diff)
downloadjQuery-Impromptu-76f9f5f046e64196148572a86d23bc4946277f75.zip
jQuery-Impromptu-76f9f5f046e64196148572a86d23bc4946277f75.tar.gz
jQuery-Impromptu-76f9f5f046e64196148572a86d23bc4946277f75.tar.bz2
Fix #58 - Adds buttonTimeout option, enableStateButtons() api method, and disableStateButtons api method to prevent multiple submit of each state
-rw-r--r--dist/index.html9
-rw-r--r--dist/jquery-impromptu.css7
-rw-r--r--dist/jquery-impromptu.js52
-rw-r--r--dist/jquery-impromptu.min.css2
-rw-r--r--dist/jquery-impromptu.min.js2
-rw-r--r--src/index.html9
-rw-r--r--src/jquery-impromptu.css1
-rw-r--r--src/jquery-impromptu.js48
8 files changed, 119 insertions, 11 deletions
diff --git a/dist/index.html b/dist/index.html
index 0cbd6bf..6fe21c4 100644
--- a/dist/index.html
+++ b/dist/index.html
@@ -188,6 +188,9 @@ var api = new Impromptu( msg , options );</code></pre>
<dt>buttons</dt>
<dd>An object containing the text and values of each button the user may click. <em>Default: { Ok : true }</em></dd>
+ <dt>buttonTimeout</dt>
+ <dd>A time frame in milliseconds to disable buttons after a click to prevent double submitting. -1 will disable this feature. <em>Default: 1000</em></dd>
+
<dt>classes</dt>
<dd>An object of class names for each part of a prompt for greater compatibilty with existing css frameworks. For example if you would like to use twitter bootstrap you would include the base theme (in the themes folder), then pass the following classes:
<pre><code>{
@@ -317,6 +320,12 @@ var api = new Impromptu( msg , options );</code></pre>
<dt>jQuery.prompt.prevState(callback)</dt>
<dd>Transitions to the previous state. Callback represents a statechanged event.</dd>
+ <dt>jQuery.prompt.enableStateButtons(stateName, buttons)</dt>
+ <dd>Enable buttons in a state. stateName defaults to the current state and buttons is an array of button values to enable. Omit the buttons argument to enable all buttons.</dd>
+
+ <dt>jQuery.prompt.disableStateButtons(stateName, buttons)</dt>
+ <dd>disable buttons in a state. stateName defaults to the current state and buttons is an array of button values to disable. Omit the buttons argument to disable all buttons.</dd>
+
<dt>jQuery.prompt.close()</dt>
<dd>Closes the prompt.</dd>
</dl>
diff --git a/dist/jquery-impromptu.css b/dist/jquery-impromptu.css
index 5875413..f4a5b4b 100644
--- a/dist/jquery-impromptu.css
+++ b/dist/jquery-impromptu.css
@@ -5,6 +5,10 @@
position: absolute;
background-color: #777777;
}
+iframe.jqifade{
+ display:block;
+ z-index:-1;
+}
div.jqi{
width: 400px;
max-width:90%;
@@ -44,6 +48,9 @@ div.jqi .jqimessage{
color: #444444;
overflow: auto;
}
+div.jqi .jqibuttonshide{
+ display: none;
+}
div.jqi .jqibuttons{
text-align: right;
margin: 0 -7px -7px -7px;
diff --git a/dist/jquery-impromptu.js b/dist/jquery-impromptu.js
index 233e010..9f10d69 100644
--- a/dist/jquery-impromptu.js
+++ b/dist/jquery-impromptu.js
@@ -58,6 +58,7 @@
buttons: {
Ok: true
},
+ buttonTimeout: 1000,
loaded: function(e){},
submit: function(e,v,m,f){},
close: function(e,v,m,f){},
@@ -189,7 +190,7 @@
//build the box and fade
var msgbox = '<div class="'+ opts.prefix +'box '+ opts.classes.box +'">';
if(opts.useiframe && ($('object, applet').length > 0)) {
- msgbox += '<iframe src="javascript:false;" style="display:block;position:absolute;z-index:-1;" class="'+ opts.prefix +'fade '+ opts.classes.fade +'"></iframe>';
+ msgbox += '<iframe src="javascript:false;" class="'+ opts.prefix +'fade '+ opts.classes.fade +'"></iframe>';
} else {
msgbox += '<div class="'+ opts.prefix +'fade '+ opts.classes.fade +'"></div>';
}
@@ -236,11 +237,20 @@
t.jqi.on('click', '.'+ opts.prefix +'buttons button', function(e){
var $t = $(this),
$state = $t.parents('.'+ opts.prefix +'state'),
- stateobj = t.options.states[$state.data('jqi-name')],
+ statename = $state.data('jqi-name'),
+ stateobj = t.options.states[statename],
msg = $state.children('.'+ opts.prefix +'message'),
clicked = stateobj.buttons[$t.text()] || stateobj.buttons[$t.html()],
forminputs = {};
+ // disable for a moment to prevent multiple clicks
+ if(t.options.buttonTimeout > 0){
+ t.disableStateButtons(statename);
+ setTimeout(function(){
+ t.enableStateButtons(statename);
+ }, t.options.buttonTimeout);
+ }
+
// if for some reason we couldn't get the value
if(clicked === undefined){
for(var i in stateobj.buttons){
@@ -441,10 +451,10 @@
showHtml = 'Error: html function must return text';
}
- state += '<div class="'+ opts.prefix + 'state" data-jqi-name="'+ statename +'" style="display:none;">'+
+ state += '<div class="'+ opts.prefix + 'state" data-jqi-name="'+ statename +'">'+
arrow + title +
'<div class="'+ opts.prefix +'message '+ opts.classes.message +'">' + showHtml +'</div>'+
- '<div class="'+ opts.prefix +'buttons '+ opts.classes.buttons +'"'+ ($.isEmptyObject(stateobj.buttons)? 'style="display:none;"':'') +'>';
+ '<div class="'+ opts.prefix +'buttons'+ ($.isEmptyObject(stateobj.buttons)? 'hide ':' ') + opts.classes.buttons +'">';
// state buttons may be in object or array, lets convert objects to arrays
if($.isArray(stateobj.buttons)){
@@ -474,7 +484,7 @@
state += '</div></div>';
- $state = $(state);
+ $state = $(state).css({display:'none'});
$state.on('impromptu:submit', stateobj.submit);
@@ -577,6 +587,38 @@
},
/**
+ * disableStateButtons - Disables the buttons in a state
+ * @param statename String - Name of the state containing buttons
+ * @param buttons Array - Array of button values to disable. By default all are disabled
+ * @param enable Boolean - True to enable the buttons instead of disabling (internally use only)
+ * @return Void
+ */
+ disableStateButtons: function(statename, buttons, enable) {
+ var t = this;
+
+ if($.isArray(statename)){
+ buttons = statename;
+ statename = null;
+ }
+
+ t.getState(statename || t.getCurrentStateName()).find('.'+ t.options.prefix + 'button').each(function(i,btn){
+ if(buttons === undefined || $.inArray(btn.value, buttons) !== -1){
+ btn.disabled = !enable;
+ }
+ });
+ },
+
+ /**
+ * enableStateButtons - Enables the buttons in a state
+ * @param statename String - Name of the state containing buttons. Defaults to current state
+ * @param buttons Array - Array of button values to enable. By default all are enabled
+ * @return Void
+ */
+ enableStateButtons: function(statename, buttons) {
+ this.disableStateButtons(statename, buttons, true);
+ },
+
+ /**
* position - Repositions the prompt (Used internally)
* @return void
*/
diff --git a/dist/jquery-impromptu.min.css b/dist/jquery-impromptu.min.css
index 6bcf90e..5857f09 100644
--- a/dist/jquery-impromptu.min.css
+++ b/dist/jquery-impromptu.min.css
@@ -1,3 +1,3 @@
/*! jQuery-Impromptu - v6.0.1 - 2014-12-27
* http://trentrichardson.com/Impromptu
-* Copyright (c) 2015 Trent Richardson; Licensed MIT */.jqifade{position:absolute;background-color:#777}div.jqi{width:400px;max-width:90%;font-family:Verdana,Geneva,Arial,Helvetica,sans-serif;position:absolute;background-color:#fff;font-size:11px;text-align:left;border:solid 1px #eee;border-radius:6px;-moz-border-radius:6px;-webkit-border-radius:6px;padding:7px}div.jqi .jqicontainer{}div.jqi .jqiclose{position:absolute;top:4px;right:-2px;width:18px;cursor:default;color:#bbb;font-weight:700}div.jqi .jqistate{background-color:#fff}div.jqi .jqititle{padding:5px 10px;font-size:16px;line-height:20px;border-bottom:solid 1px #eee}div.jqi .jqimessage{padding:10px;line-height:20px;color:#444;overflow:auto}div.jqi .jqibuttons{text-align:right;margin:0 -7px -7px -7px;border-top:solid 1px #e4e4e4;background-color:#f4f4f4;border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;-webkit-border-radius:0 0 6px 6px}div.jqi .jqibuttons button{margin:0;padding:15px 20px;background-color:transparent;font-weight:400;border:0;border-left:solid 1px #e4e4e4;color:#777;font-weight:700;font-size:12px}div.jqi .jqibuttons button.jqidefaultbutton{color:#489afe}div.jqi .jqibuttons button:hover,div.jqi .jqibuttons button:focus{color:#287ade;outline:0}.jqiwarning .jqi .jqibuttons{background-color:#b95656}div.jqi .jqiparentstate::after{background-color:#777;opacity:.6;filter:alpha(opacity=60);content:'';position:absolute;top:0;left:0;bottom:0;right:0;border-radius:6px;-moz-border-radius:6px;-webkit-border-radius:6px}div.jqi .jqisubstate{position:absolute;top:0;left:20%;width:60%;padding:7px;border:solid 1px #eee;border-top:0;border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;-webkit-border-radius:0 0 6px 6px}div.jqi .jqisubstate .jqibuttons button{padding:10px 18px}.jqi .jqiarrow{position:absolute;height:0;width:0;line-height:0;font-size:0;border:solid 10px transparent}.jqi .jqiarrowtl{left:10px;top:-20px;border-bottom-color:#fff}.jqi .jqiarrowtc{left:50%;top:-20px;border-bottom-color:#fff;margin-left:-10px}.jqi .jqiarrowtr{right:10px;top:-20px;border-bottom-color:#fff}.jqi .jqiarrowbl{left:10px;bottom:-20px;border-top-color:#fff}.jqi .jqiarrowbc{left:50%;bottom:-20px;border-top-color:#fff;margin-left:-10px}.jqi .jqiarrowbr{right:10px;bottom:-20px;border-top-color:#fff}.jqi .jqiarrowlt{left:-20px;top:10px;border-right-color:#fff}.jqi .jqiarrowlm{left:-20px;top:50%;border-right-color:#fff;margin-top:-10px}.jqi .jqiarrowlb{left:-20px;bottom:10px;border-right-color:#fff}.jqi .jqiarrowrt{right:-20px;top:10px;border-left-color:#fff}.jqi .jqiarrowrm{right:-20px;top:50%;border-left-color:#fff;margin-top:-10px}.jqi .jqiarrowrb{right:-20px;bottom:10px;border-left-color:#fff} \ No newline at end of file
+* Copyright (c) 2015 Trent Richardson; Licensed MIT */.jqifade{position:absolute;background-color:#777}iframe.jqifade{display:block;z-index:-1}div.jqi{width:400px;max-width:90%;font-family:Verdana,Geneva,Arial,Helvetica,sans-serif;position:absolute;background-color:#fff;font-size:11px;text-align:left;border:solid 1px #eee;border-radius:6px;-moz-border-radius:6px;-webkit-border-radius:6px;padding:7px}div.jqi .jqicontainer{}div.jqi .jqiclose{position:absolute;top:4px;right:-2px;width:18px;cursor:default;color:#bbb;font-weight:700}div.jqi .jqistate{background-color:#fff}div.jqi .jqititle{padding:5px 10px;font-size:16px;line-height:20px;border-bottom:solid 1px #eee}div.jqi .jqimessage{padding:10px;line-height:20px;color:#444;overflow:auto}div.jqi .jqibuttonshide{display:none}div.jqi .jqibuttons{text-align:right;margin:0 -7px -7px -7px;border-top:solid 1px #e4e4e4;background-color:#f4f4f4;border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;-webkit-border-radius:0 0 6px 6px}div.jqi .jqibuttons button{margin:0;padding:15px 20px;background-color:transparent;font-weight:400;border:0;border-left:solid 1px #e4e4e4;color:#777;font-weight:700;font-size:12px}div.jqi .jqibuttons button.jqidefaultbutton{color:#489afe}div.jqi .jqibuttons button:hover,div.jqi .jqibuttons button:focus{color:#287ade;outline:0}.jqiwarning .jqi .jqibuttons{background-color:#b95656}div.jqi .jqiparentstate::after{background-color:#777;opacity:.6;filter:alpha(opacity=60);content:'';position:absolute;top:0;left:0;bottom:0;right:0;border-radius:6px;-moz-border-radius:6px;-webkit-border-radius:6px}div.jqi .jqisubstate{position:absolute;top:0;left:20%;width:60%;padding:7px;border:solid 1px #eee;border-top:0;border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;-webkit-border-radius:0 0 6px 6px}div.jqi .jqisubstate .jqibuttons button{padding:10px 18px}.jqi .jqiarrow{position:absolute;height:0;width:0;line-height:0;font-size:0;border:solid 10px transparent}.jqi .jqiarrowtl{left:10px;top:-20px;border-bottom-color:#fff}.jqi .jqiarrowtc{left:50%;top:-20px;border-bottom-color:#fff;margin-left:-10px}.jqi .jqiarrowtr{right:10px;top:-20px;border-bottom-color:#fff}.jqi .jqiarrowbl{left:10px;bottom:-20px;border-top-color:#fff}.jqi .jqiarrowbc{left:50%;bottom:-20px;border-top-color:#fff;margin-left:-10px}.jqi .jqiarrowbr{right:10px;bottom:-20px;border-top-color:#fff}.jqi .jqiarrowlt{left:-20px;top:10px;border-right-color:#fff}.jqi .jqiarrowlm{left:-20px;top:50%;border-right-color:#fff;margin-top:-10px}.jqi .jqiarrowlb{left:-20px;bottom:10px;border-right-color:#fff}.jqi .jqiarrowrt{right:-20px;top:10px;border-left-color:#fff}.jqi .jqiarrowrm{right:-20px;top:50%;border-left-color:#fff;margin-top:-10px}.jqi .jqiarrowrb{right:-20px;bottom:10px;border-left-color:#fff} \ No newline at end of file
diff --git a/dist/jquery-impromptu.min.js b/dist/jquery-impromptu.min.js
index 1adbdba..b0744eb 100644
--- a/dist/jquery-impromptu.min.js
+++ b/dist/jquery-impromptu.min.js
@@ -1,4 +1,4 @@
/*! jQuery-Impromptu - v6.0.1 - 2014-12-27
* http://trentrichardson.com/Impromptu
* Copyright (c) 2015 Trent Richardson; Licensed MIT */
-(function(t,e){"function"==typeof define&&define.amd?define(["jquery"],e):e(t.jQuery)})(this,function(t){"use strict";var e=function(t,i){var n=this;return n.id=e.count++,e.lifo.push(n),t&&n.open(t,i),n};e.defaults={prefix:"jqi",classes:{box:"",fade:"",prompt:"",form:"",close:"",title:"",message:"",buttons:"",button:"",defaultButton:""},title:"",closeText:"&times;",buttons:{Ok:!0},loaded:function(){},submit:function(){},close:function(){},statechanging:function(){},statechanged:function(){},opacity:.6,zIndex:999,overlayspeed:"slow",promptspeed:"fast",show:"fadeIn",hide:"fadeOut",focus:0,defaultButton:0,useiframe:!1,top:"15%",position:{container:null,x:null,y:null,arrow:null,width:null},persistent:!0,timeout:0,states:{},state:{name:null,title:"",html:"",buttons:{Ok:!0},focus:0,defaultButton:0,position:{container:null,x:null,y:null,arrow:null,width:null},submit:function(){return!0}}},e.setDefaults=function(i){e.defaults=t.extend({},e.defaults,i)},e.setStateDefaults=function(i){e.defaults.state=t.extend({},e.defaults.state,i)},e.count=0,e.lifo=[],e.getLast=function(){var t=e.lifo.length;return t>0?e.lifo[t-1]:!1},e.removeFromStack=function(t){for(var i=e.lifo.length-1;i>=0;i--)if(e.lifo[i].id===t)return e.lifo.splice(i,1)[0]},e.prototype={id:null,open:function(i,n){var o=this;o.options=t.extend({},e.defaults,n),o.timeout&&clearTimeout(o.timeout),o.timeout=!1;var s=o.options,a=t(document.body),r=t(window),f='<div class="'+s.prefix+"box "+s.classes.box+'">';f+=s.useiframe&&t("object, applet").length>0?'<iframe src="javascript:false;" style="display:block;position:absolute;z-index:-1;" class="'+s.prefix+"fade "+s.classes.fade+'"></iframe>':'<div class="'+s.prefix+"fade "+s.classes.fade+'"></div>',f+='<div class="'+s.prefix+" "+s.classes.prompt+'">'+'<form action="#" class="'+s.prefix+"form "+s.classes.form+'">'+'<div class="'+s.prefix+"close "+s.classes.close+'">'+s.closeText+"</div>"+'<div class="'+s.prefix+'states"></div>'+"</form>"+"</div>"+"</div>",o.jqib=t(f).appendTo(a),o.jqi=o.jqib.children("."+s.prefix),o.jqif=o.jqib.children("."+s.prefix+"fade"),i.constructor===String&&(i={state0:{title:s.title,html:i,buttons:s.buttons,position:s.position,focus:s.focus,defaultButton:s.defaultButton,submit:s.submit}}),o.options.states={};var u,l;for(u in i)l=t.extend({},e.defaults.state,{name:u},i[u]),o.addState(l.name,l),""===o.currentStateName&&(o.currentStateName=l.name);o.jqi.on("click","."+s.prefix+"buttons button",function(){var e=t(this),i=e.parents("."+s.prefix+"state"),n=o.options.states[i.data("jqi-name")],a=i.children("."+s.prefix+"message"),r=n.buttons[e.text()]||n.buttons[e.html()],f={};if(void 0===r)for(var u in n.buttons)(n.buttons[u].title===e.text()||n.buttons[u].title===e.html())&&(r=n.buttons[u].value);t.each(o.jqi.children("form").serializeArray(),function(t,e){void 0===f[e.name]?f[e.name]=e.value:typeof f[e.name]===Array||"object"==typeof f[e.name]?f[e.name].push(e.value):f[e.name]=[f[e.name],e.value]});var l=new t.Event("impromptu:submit");l.stateName=n.name,l.state=i,i.trigger(l,[r,a,f]),l.isDefaultPrevented()||o.close(!0,r,a,f)});var p=function(){if(s.persistent){var e=(""+s.top).indexOf("%")>=0?r.height()*(parseInt(s.top,10)/100):parseInt(s.top,10),i=parseInt(o.jqi.css("top").replace("px",""),10)-e;t("html,body").animate({scrollTop:i},"fast",function(){var t=0;o.jqib.addClass(s.prefix+"warning");var e=setInterval(function(){o.jqib.toggleClass(s.prefix+"warning"),t++>1&&(clearInterval(e),o.jqib.removeClass(s.prefix+"warning"))},100)})}else o.close(!0)},d=function(e){var i=window.event?event.keyCode:e.keyCode;if(27===i&&p(),13===i){var n=o.getCurrentState().find("."+s.prefix+"defaultbutton"),a=t(e.target);a.is("textarea,."+s.prefix+"button")===!1&&n.length>0&&(e.preventDefault(),n.click())}if(9===i){var r=t("input,select,textarea,button",o.getCurrentState()),f=!e.shiftKey&&e.target===r[r.length-1],u=e.shiftKey&&e.target===r[0];if(f||u)return setTimeout(function(){if(r){var t=r[u===!0?r.length-1:0];t&&t.focus()}},10),!1}};return o.position(),o.style(),o._windowResize=function(t){o.position(t)},r.resize({animate:!1},o._windowResize),o.jqif.click(p),o.jqi.find("."+s.prefix+"close").click(function(){o.close()}),o.jqi.find("."+s.prefix+"form").submit(function(){return!1}),o.jqib.on("keydown",d).on("impromptu:loaded",s.loaded).on("impromptu:close",s.close).on("impromptu:statechanging",s.statechanging).on("impromptu:statechanged",s.statechanged),o.jqif[s.show](s.overlayspeed),o.jqi[s.show](s.promptspeed,function(){var t=o.jqi.find("."+s.prefix+"states ."+s.prefix+"state").eq(0);o.goToState(t.data("jqi-name")),o.jqib.trigger("impromptu:loaded")}),s.timeout>0&&(o.timeout=setTimeout(function(){o.close(!0)},s.timeout)),o},close:function(i,n,o,s){var a=this;return e.removeFromStack(a.id),a.timeout&&(clearTimeout(a.timeout),a.timeout=!1),a.jqib&&a.jqib[a.options.hide]("fast",function(){a.jqib.trigger("impromptu:close",[n,o,s]),a.jqib.remove(),t(window).off("resize",a._windowResize),"function"==typeof i&&i()}),a.currentStateName="",a},addState:function(i,n,o){var s,a,r,f,u,l=this,p="",d=null,c="",m="",h=l.options,v=t("."+h.prefix+"states"),g=[],x=0;if(n=t.extend({},e.defaults.state,{name:i},n),null!==n.position.arrow&&(c='<div class="'+h.prefix+"arrow "+h.prefix+"arrow"+n.position.arrow+'"></div>'),n.title&&""!==n.title&&(m='<div class="lead '+h.prefix+"title "+h.classes.title+'">'+n.title+"</div>"),s=n.html,"function"==typeof n.html&&(s="Error: html function must return text"),p+='<div class="'+h.prefix+'state" data-jqi-name="'+i+'" style="display:none;">'+c+m+'<div class="'+h.prefix+"message "+h.classes.message+'">'+s+"</div>"+'<div class="'+h.prefix+"buttons "+h.classes.buttons+'"'+(t.isEmptyObject(n.buttons)?'style="display:none;"':"")+">",t.isArray(n.buttons))g=n.buttons;else if(t.isPlainObject(n.buttons))for(r in n.buttons)n.buttons.hasOwnProperty(r)&&g.push({title:r,value:n.buttons[r]});for(x=0,u=g.length;u>x;x++)f=g[x],a=n.focus===x||isNaN(n.focus)&&n.defaultButton===x?h.prefix+"defaultbutton "+h.classes.defaultButton:"",p+='<button class="'+h.classes.button+" "+h.prefix+"button "+a,f.classes!==void 0&&(p+=" "+(t.isArray(f.classes)?f.classes.join(" "):f.classes)+" "),p+='" name="'+h.prefix+"_"+i+"_button"+f.title.replace(/[^a-z0-9]+/gi,"")+'" value="'+f.value+'">'+f.title+"</button>";return p+="</div></div>",d=t(p),d.on("impromptu:submit",n.submit),void 0!==o?v.find('[data-jqi-name="'+o+'"]').after(d):v.append(d),l.options.states[i]=n,d},removeState:function(t,e){var i=this,n=i.getState(t),o=function(){n.remove()};return 0===n.length?!1:("none"!==n.css("display")?void 0!==e&&i.getState(e).length>0?i.goToState(e,!1,o):n.next().length>0?i.nextState(o):n.prev().length>0?i.prevState(o):i.close():n.slideUp("slow",o),!0)},getApi:function(){return this},getBox:function(){return this.jqib},getPrompt:function(){return this.jqi},getState:function(t){return this.jqi.find('[data-jqi-name="'+t+'"]')},getCurrentState:function(){return this.getState(this.getCurrentStateName())},getCurrentStateName:function(){return this.currentStateName},position:function(e){var i=this,n=t.fx.off,o=i.getCurrentState(),s=i.options.states[o.data("jqi-name")],a=s?s.position:void 0,r=t(window),f=document.body.scrollHeight,u=t(window).height(),l=(t(document).height(),f>u?f:u),p=parseInt(r.scrollTop(),10)+((""+i.options.top).indexOf("%")>=0?u*(parseInt(i.options.top,10)/100):parseInt(i.options.top,10));if(void 0!==e&&e.data.animate===!1&&(t.fx.off=!0),i.jqib.css({position:"absolute",height:l,width:"100%",top:0,left:0,right:0,bottom:0}),i.jqif.css({position:"fixed",height:l,width:"100%",top:0,left:0,right:0,bottom:0}),a&&a.container){var d=t(a.container).offset();t.isPlainObject(d)&&void 0!==d.top&&(i.jqi.css({position:"absolute"}),i.jqi.animate({top:d.top+a.y,left:d.left+a.x,marginLeft:0,width:void 0!==a.width?a.width:null}),p=d.top+a.y-((""+i.options.top).indexOf("%")>=0?u*(parseInt(i.options.top,10)/100):parseInt(i.options.top,10)),t("html,body").animate({scrollTop:p},"slow","swing",function(){}))}else a&&a.width?(i.jqi.css({position:"absolute",left:"50%"}),i.jqi.animate({top:a.y||p,left:a.x||"50%",marginLeft:-1*(a.width/2),width:a.width})):i.jqi.css({position:"absolute",top:p,left:"50%",marginLeft:-1*(i.jqi.outerWidth(!1)/2)});void 0!==e&&e.data.animate===!1&&(t.fx.off=n)},style:function(){var t=this;t.jqif.css({zIndex:t.options.zIndex,display:"none",opacity:t.options.opacity}),t.jqi.css({zIndex:t.options.zIndex+1,display:"none"}),t.jqib.css({zIndex:t.options.zIndex})},goToState:function(e,i,n){var o=this,s=(o.jqi,o.options),a=o.getState(e),r=s.states[a.data("jqi-name")],f=new t.Event("impromptu:statechanging"),u=o.options;if(void 0!==r){if("function"==typeof r.html){var l=r.html;a.find("."+u.prefix+"message ").html(l())}"function"==typeof i&&(n=i,i=!1),o.jqib.trigger(f,[o.getCurrentStateName(),e]),!f.isDefaultPrevented()&&a.length>0&&(o.jqi.find("."+u.prefix+"parentstate").removeClass(u.prefix+"parentstate"),i?(o.jqi.find("."+u.prefix+"substate").not(a).slideUp(s.promptspeed).removeClass("."+u.prefix+"substate").find("."+u.prefix+"arrow").hide(),o.jqi.find("."+u.prefix+"state:visible").addClass(u.prefix+"parentstate"),a.addClass(u.prefix+"substate")):o.jqi.find("."+u.prefix+"state").not(a).slideUp(s.promptspeed).find("."+u.prefix+"arrow").hide(),o.currentStateName=r.name,a.slideDown(s.promptspeed,function(){var i=t(this);"string"==typeof r.focus?i.find(r.focus).eq(0).focus():i.find("."+u.prefix+"defaultbutton").focus(),i.find("."+u.prefix+"arrow").show(s.promptspeed),"function"==typeof n&&o.jqib.on("impromptu:statechanged",n),o.jqib.trigger("impromptu:statechanged",[e]),"function"==typeof n&&o.jqib.off("impromptu:statechanged",n)}),i||o.position())}return a},nextState:function(t){var e=this,i=e.getCurrentState().next();return i.length>0&&e.goToState(i.data("jqi-name"),t),i},prevState:function(t){var e=this,i=e.getCurrentState().prev();return i.length>0&&e.goToState(i.data("jqi-name"),t),i}},t.prompt=function(t,i){var n=new e(t,i);return n.jqi},t.each(e,function(e,i){t.prompt[e]=i}),t.each(e.prototype,function(i){t.prompt[i]=function(){var t=e.getLast();return t&&"function"==typeof t[i]?t[i].apply(t,arguments):void 0}}),t.fn.prompt=function(e){void 0===e&&(e={}),void 0===e.withDataAndEvents&&(e.withDataAndEvents=!1),t.prompt(t(this).clone(e.withDataAndEvents).html(),e)},window.Impromptu=e}); \ No newline at end of file
+(function(t,e){"function"==typeof define&&define.amd?define(["jquery"],e):e(t.jQuery)})(this,function(t){"use strict";var e=function(t,i){var n=this;return n.id=e.count++,e.lifo.push(n),t&&n.open(t,i),n};e.defaults={prefix:"jqi",classes:{box:"",fade:"",prompt:"",form:"",close:"",title:"",message:"",buttons:"",button:"",defaultButton:""},title:"",closeText:"&times;",buttons:{Ok:!0},buttonTimeout:1e3,loaded:function(){},submit:function(){},close:function(){},statechanging:function(){},statechanged:function(){},opacity:.6,zIndex:999,overlayspeed:"slow",promptspeed:"fast",show:"fadeIn",hide:"fadeOut",focus:0,defaultButton:0,useiframe:!1,top:"15%",position:{container:null,x:null,y:null,arrow:null,width:null},persistent:!0,timeout:0,states:{},state:{name:null,title:"",html:"",buttons:{Ok:!0},focus:0,defaultButton:0,position:{container:null,x:null,y:null,arrow:null,width:null},submit:function(){return!0}}},e.setDefaults=function(i){e.defaults=t.extend({},e.defaults,i)},e.setStateDefaults=function(i){e.defaults.state=t.extend({},e.defaults.state,i)},e.count=0,e.lifo=[],e.getLast=function(){var t=e.lifo.length;return t>0?e.lifo[t-1]:!1},e.removeFromStack=function(t){for(var i=e.lifo.length-1;i>=0;i--)if(e.lifo[i].id===t)return e.lifo.splice(i,1)[0]},e.prototype={id:null,open:function(i,n){var o=this;o.options=t.extend({},e.defaults,n),o.timeout&&clearTimeout(o.timeout),o.timeout=!1;var s=o.options,a=t(document.body),r=t(window),u='<div class="'+s.prefix+"box "+s.classes.box+'">';u+=s.useiframe&&t("object, applet").length>0?'<iframe src="javascript:false;" class="'+s.prefix+"fade "+s.classes.fade+'"></iframe>':'<div class="'+s.prefix+"fade "+s.classes.fade+'"></div>',u+='<div class="'+s.prefix+" "+s.classes.prompt+'">'+'<form action="#" class="'+s.prefix+"form "+s.classes.form+'">'+'<div class="'+s.prefix+"close "+s.classes.close+'">'+s.closeText+"</div>"+'<div class="'+s.prefix+'states"></div>'+"</form>"+"</div>"+"</div>",o.jqib=t(u).appendTo(a),o.jqi=o.jqib.children("."+s.prefix),o.jqif=o.jqib.children("."+s.prefix+"fade"),i.constructor===String&&(i={state0:{title:s.title,html:i,buttons:s.buttons,position:s.position,focus:s.focus,defaultButton:s.defaultButton,submit:s.submit}}),o.options.states={};var f,l;for(f in i)l=t.extend({},e.defaults.state,{name:f},i[f]),o.addState(l.name,l),""===o.currentStateName&&(o.currentStateName=l.name);o.jqi.on("click","."+s.prefix+"buttons button",function(){var e=t(this),i=e.parents("."+s.prefix+"state"),n=i.data("jqi-name"),a=o.options.states[n],r=i.children("."+s.prefix+"message"),u=a.buttons[e.text()]||a.buttons[e.html()],f={};if(o.options.buttonTimeout>0&&(o.disableStateButtons(n),setTimeout(function(){o.enableStateButtons(n)},o.options.buttonTimeout)),void 0===u)for(var l in a.buttons)(a.buttons[l].title===e.text()||a.buttons[l].title===e.html())&&(u=a.buttons[l].value);t.each(o.jqi.children("form").serializeArray(),function(t,e){void 0===f[e.name]?f[e.name]=e.value:typeof f[e.name]===Array||"object"==typeof f[e.name]?f[e.name].push(e.value):f[e.name]=[f[e.name],e.value]});var p=new t.Event("impromptu:submit");p.stateName=a.name,p.state=i,i.trigger(p,[u,r,f]),p.isDefaultPrevented()||o.close(!0,u,r,f)});var p=function(){if(s.persistent){var e=(""+s.top).indexOf("%")>=0?r.height()*(parseInt(s.top,10)/100):parseInt(s.top,10),i=parseInt(o.jqi.css("top").replace("px",""),10)-e;t("html,body").animate({scrollTop:i},"fast",function(){var t=0;o.jqib.addClass(s.prefix+"warning");var e=setInterval(function(){o.jqib.toggleClass(s.prefix+"warning"),t++>1&&(clearInterval(e),o.jqib.removeClass(s.prefix+"warning"))},100)})}else o.close(!0)},d=function(e){var i=window.event?event.keyCode:e.keyCode;if(27===i&&p(),13===i){var n=o.getCurrentState().find("."+s.prefix+"defaultbutton"),a=t(e.target);a.is("textarea,."+s.prefix+"button")===!1&&n.length>0&&(e.preventDefault(),n.click())}if(9===i){var r=t("input,select,textarea,button",o.getCurrentState()),u=!e.shiftKey&&e.target===r[r.length-1],f=e.shiftKey&&e.target===r[0];if(u||f)return setTimeout(function(){if(r){var t=r[f===!0?r.length-1:0];t&&t.focus()}},10),!1}};return o.position(),o.style(),o._windowResize=function(t){o.position(t)},r.resize({animate:!1},o._windowResize),o.jqif.click(p),o.jqi.find("."+s.prefix+"close").click(function(){o.close()}),o.jqi.find("."+s.prefix+"form").submit(function(){return!1}),o.jqib.on("keydown",d).on("impromptu:loaded",s.loaded).on("impromptu:close",s.close).on("impromptu:statechanging",s.statechanging).on("impromptu:statechanged",s.statechanged),o.jqif[s.show](s.overlayspeed),o.jqi[s.show](s.promptspeed,function(){var t=o.jqi.find("."+s.prefix+"states ."+s.prefix+"state").eq(0);o.goToState(t.data("jqi-name")),o.jqib.trigger("impromptu:loaded")}),s.timeout>0&&(o.timeout=setTimeout(function(){o.close(!0)},s.timeout)),o},close:function(i,n,o,s){var a=this;return e.removeFromStack(a.id),a.timeout&&(clearTimeout(a.timeout),a.timeout=!1),a.jqib&&a.jqib[a.options.hide]("fast",function(){a.jqib.trigger("impromptu:close",[n,o,s]),a.jqib.remove(),t(window).off("resize",a._windowResize),"function"==typeof i&&i()}),a.currentStateName="",a},addState:function(i,n,o){var s,a,r,u,f,l=this,p="",d=null,c="",m="",h=l.options,v=t("."+h.prefix+"states"),g=[],b=0;if(n=t.extend({},e.defaults.state,{name:i},n),null!==n.position.arrow&&(c='<div class="'+h.prefix+"arrow "+h.prefix+"arrow"+n.position.arrow+'"></div>'),n.title&&""!==n.title&&(m='<div class="lead '+h.prefix+"title "+h.classes.title+'">'+n.title+"</div>"),s=n.html,"function"==typeof n.html&&(s="Error: html function must return text"),p+='<div class="'+h.prefix+'state" data-jqi-name="'+i+'">'+c+m+'<div class="'+h.prefix+"message "+h.classes.message+'">'+s+"</div>"+'<div class="'+h.prefix+"buttons"+(t.isEmptyObject(n.buttons)?"hide ":" ")+h.classes.buttons+'">',t.isArray(n.buttons))g=n.buttons;else if(t.isPlainObject(n.buttons))for(r in n.buttons)n.buttons.hasOwnProperty(r)&&g.push({title:r,value:n.buttons[r]});for(b=0,f=g.length;f>b;b++)u=g[b],a=n.focus===b||isNaN(n.focus)&&n.defaultButton===b?h.prefix+"defaultbutton "+h.classes.defaultButton:"",p+='<button class="'+h.classes.button+" "+h.prefix+"button "+a,u.classes!==void 0&&(p+=" "+(t.isArray(u.classes)?u.classes.join(" "):u.classes)+" "),p+='" name="'+h.prefix+"_"+i+"_button"+u.title.replace(/[^a-z0-9]+/gi,"")+'" value="'+u.value+'">'+u.title+"</button>";return p+="</div></div>",d=t(p).css({display:"none"}),d.on("impromptu:submit",n.submit),void 0!==o?v.find('[data-jqi-name="'+o+'"]').after(d):v.append(d),l.options.states[i]=n,d},removeState:function(t,e){var i=this,n=i.getState(t),o=function(){n.remove()};return 0===n.length?!1:("none"!==n.css("display")?void 0!==e&&i.getState(e).length>0?i.goToState(e,!1,o):n.next().length>0?i.nextState(o):n.prev().length>0?i.prevState(o):i.close():n.slideUp("slow",o),!0)},getApi:function(){return this},getBox:function(){return this.jqib},getPrompt:function(){return this.jqi},getState:function(t){return this.jqi.find('[data-jqi-name="'+t+'"]')},getCurrentState:function(){return this.getState(this.getCurrentStateName())},getCurrentStateName:function(){return this.currentStateName},disableStateButtons:function(e,i,n){var o=this;t.isArray(e)&&(i=e,e=null),o.getState(e||o.getCurrentStateName()).find("."+o.options.prefix+"button").each(function(e,o){(void 0===i||-1!==t.inArray(o.value,i))&&(o.disabled=!n)})},enableStateButtons:function(t,e){this.disableStateButtons(t,e,!0)},position:function(e){var i=this,n=t.fx.off,o=i.getCurrentState(),s=i.options.states[o.data("jqi-name")],a=s?s.position:void 0,r=t(window),u=document.body.scrollHeight,f=t(window).height(),l=(t(document).height(),u>f?u:f),p=parseInt(r.scrollTop(),10)+((""+i.options.top).indexOf("%")>=0?f*(parseInt(i.options.top,10)/100):parseInt(i.options.top,10));if(void 0!==e&&e.data.animate===!1&&(t.fx.off=!0),i.jqib.css({position:"absolute",height:l,width:"100%",top:0,left:0,right:0,bottom:0}),i.jqif.css({position:"fixed",height:l,width:"100%",top:0,left:0,right:0,bottom:0}),a&&a.container){var d=t(a.container).offset();t.isPlainObject(d)&&void 0!==d.top&&(i.jqi.css({position:"absolute"}),i.jqi.animate({top:d.top+a.y,left:d.left+a.x,marginLeft:0,width:void 0!==a.width?a.width:null}),p=d.top+a.y-((""+i.options.top).indexOf("%")>=0?f*(parseInt(i.options.top,10)/100):parseInt(i.options.top,10)),t("html,body").animate({scrollTop:p},"slow","swing",function(){}))}else a&&a.width?(i.jqi.css({position:"absolute",left:"50%"}),i.jqi.animate({top:a.y||p,left:a.x||"50%",marginLeft:-1*(a.width/2),width:a.width})):i.jqi.css({position:"absolute",top:p,left:"50%",marginLeft:-1*(i.jqi.outerWidth(!1)/2)});void 0!==e&&e.data.animate===!1&&(t.fx.off=n)},style:function(){var t=this;t.jqif.css({zIndex:t.options.zIndex,display:"none",opacity:t.options.opacity}),t.jqi.css({zIndex:t.options.zIndex+1,display:"none"}),t.jqib.css({zIndex:t.options.zIndex})},goToState:function(e,i,n){var o=this,s=(o.jqi,o.options),a=o.getState(e),r=s.states[a.data("jqi-name")],u=new t.Event("impromptu:statechanging"),f=o.options;if(void 0!==r){if("function"==typeof r.html){var l=r.html;a.find("."+f.prefix+"message ").html(l())}"function"==typeof i&&(n=i,i=!1),o.jqib.trigger(u,[o.getCurrentStateName(),e]),!u.isDefaultPrevented()&&a.length>0&&(o.jqi.find("."+f.prefix+"parentstate").removeClass(f.prefix+"parentstate"),i?(o.jqi.find("."+f.prefix+"substate").not(a).slideUp(s.promptspeed).removeClass("."+f.prefix+"substate").find("."+f.prefix+"arrow").hide(),o.jqi.find("."+f.prefix+"state:visible").addClass(f.prefix+"parentstate"),a.addClass(f.prefix+"substate")):o.jqi.find("."+f.prefix+"state").not(a).slideUp(s.promptspeed).find("."+f.prefix+"arrow").hide(),o.currentStateName=r.name,a.slideDown(s.promptspeed,function(){var i=t(this);"string"==typeof r.focus?i.find(r.focus).eq(0).focus():i.find("."+f.prefix+"defaultbutton").focus(),i.find("."+f.prefix+"arrow").show(s.promptspeed),"function"==typeof n&&o.jqib.on("impromptu:statechanged",n),o.jqib.trigger("impromptu:statechanged",[e]),"function"==typeof n&&o.jqib.off("impromptu:statechanged",n)}),i||o.position())}return a},nextState:function(t){var e=this,i=e.getCurrentState().next();return i.length>0&&e.goToState(i.data("jqi-name"),t),i},prevState:function(t){var e=this,i=e.getCurrentState().prev();return i.length>0&&e.goToState(i.data("jqi-name"),t),i}},t.prompt=function(t,i){var n=new e(t,i);return n.jqi},t.each(e,function(e,i){t.prompt[e]=i}),t.each(e.prototype,function(i){t.prompt[i]=function(){var t=e.getLast();return t&&"function"==typeof t[i]?t[i].apply(t,arguments):void 0}}),t.fn.prompt=function(e){void 0===e&&(e={}),void 0===e.withDataAndEvents&&(e.withDataAndEvents=!1),t.prompt(t(this).clone(e.withDataAndEvents).html(),e)},window.Impromptu=e}); \ No newline at end of file
diff --git a/src/index.html b/src/index.html
index 691c34a..8e6ca75 100644
--- a/src/index.html
+++ b/src/index.html
@@ -188,6 +188,9 @@ var api = new Impromptu( msg , options );</code></pre>
<dt>buttons</dt>
<dd>An object containing the text and values of each button the user may click. <em>Default: { Ok : true }</em></dd>
+ <dt>buttonTimeout</dt>
+ <dd>A time frame in milliseconds to disable buttons after a click to prevent double submitting. -1 will disable this feature. <em>Default: 1000</em></dd>
+
<dt>classes</dt>
<dd>An object of class names for each part of a prompt for greater compatibilty with existing css frameworks. For example if you would like to use twitter bootstrap you would include the base theme (in the themes folder), then pass the following classes:
<pre><code>{
@@ -317,6 +320,12 @@ var api = new Impromptu( msg , options );</code></pre>
<dt>jQuery.prompt.prevState(callback)</dt>
<dd>Transitions to the previous state. Callback represents a statechanged event.</dd>
+ <dt>jQuery.prompt.enableStateButtons(stateName, buttons)</dt>
+ <dd>Enable buttons in a state. stateName defaults to the current state and buttons is an array of button values to enable. Omit the buttons argument to enable all buttons.</dd>
+
+ <dt>jQuery.prompt.disableStateButtons(stateName, buttons)</dt>
+ <dd>disable buttons in a state. stateName defaults to the current state and buttons is an array of button values to disable. Omit the buttons argument to disable all buttons.</dd>
+
<dt>jQuery.prompt.close()</dt>
<dd>Closes the prompt.</dd>
</dl>
diff --git a/src/jquery-impromptu.css b/src/jquery-impromptu.css
index ba16a05..c5cd729 100644
--- a/src/jquery-impromptu.css
+++ b/src/jquery-impromptu.css
@@ -32,7 +32,6 @@ div.jqi .jqiclose{
}
div.jqi .jqistate{
background-color: #fff;
- display: none;
}
div.jqi .jqititle{
padding: 5px 10px;
diff --git a/src/jquery-impromptu.js b/src/jquery-impromptu.js
index 5b97028..73b08b0 100644
--- a/src/jquery-impromptu.js
+++ b/src/jquery-impromptu.js
@@ -55,6 +55,7 @@
buttons: {
Ok: true
},
+ buttonTimeout: 1000,
loaded: function(e){},
submit: function(e,v,m,f){},
close: function(e,v,m,f){},
@@ -233,11 +234,20 @@
t.jqi.on('click', '.'+ opts.prefix +'buttons button', function(e){
var $t = $(this),
$state = $t.parents('.'+ opts.prefix +'state'),
- stateobj = t.options.states[$state.data('jqi-name')],
+ statename = $state.data('jqi-name'),
+ stateobj = t.options.states[statename],
msg = $state.children('.'+ opts.prefix +'message'),
clicked = stateobj.buttons[$t.text()] || stateobj.buttons[$t.html()],
forminputs = {};
+ // disable for a moment to prevent multiple clicks
+ if(t.options.buttonTimeout > 0){
+ t.disableStateButtons(statename);
+ setTimeout(function(){
+ t.enableStateButtons(statename);
+ }, t.options.buttonTimeout);
+ }
+
// if for some reason we couldn't get the value
if(clicked === undefined){
for(var i in stateobj.buttons){
@@ -441,7 +451,7 @@
state += '<div class="'+ opts.prefix + 'state" data-jqi-name="'+ statename +'">'+
arrow + title +
'<div class="'+ opts.prefix +'message '+ opts.classes.message +'">' + showHtml +'</div>'+
- '<div class="'+ opts.prefix +'buttons'+ ($.isEmptyObject(stateobj.buttons)? 'hide ':' ')+ opts.classes.buttons +'">';
+ '<div class="'+ opts.prefix +'buttons'+ ($.isEmptyObject(stateobj.buttons)? 'hide ':' ') + opts.classes.buttons +'">';
// state buttons may be in object or array, lets convert objects to arrays
if($.isArray(stateobj.buttons)){
@@ -471,7 +481,7 @@
state += '</div></div>';
- $state = $(state);
+ $state = $(state).css({display:'none'});
$state.on('impromptu:submit', stateobj.submit);
@@ -574,6 +584,38 @@
},
/**
+ * disableStateButtons - Disables the buttons in a state
+ * @param statename String - Name of the state containing buttons
+ * @param buttons Array - Array of button values to disable. By default all are disabled
+ * @param enable Boolean - True to enable the buttons instead of disabling (internally use only)
+ * @return Void
+ */
+ disableStateButtons: function(statename, buttons, enable) {
+ var t = this;
+
+ if($.isArray(statename)){
+ buttons = statename;
+ statename = null;
+ }
+
+ t.getState(statename || t.getCurrentStateName()).find('.'+ t.options.prefix + 'button').each(function(i,btn){
+ if(buttons === undefined || $.inArray(btn.value, buttons) !== -1){
+ btn.disabled = !enable;
+ }
+ });
+ },
+
+ /**
+ * enableStateButtons - Enables the buttons in a state
+ * @param statename String - Name of the state containing buttons. Defaults to current state
+ * @param buttons Array - Array of button values to enable. By default all are enabled
+ * @return Void
+ */
+ enableStateButtons: function(statename, buttons) {
+ this.disableStateButtons(statename, buttons, true);
+ },
+
+ /**
* position - Repositions the prompt (Used internally)
* @return void
*/