Commit c31d03b7cdb5d0bbed979c2424621b9980b0782f

Authored by Nathan B
2 parents 258cf879 96361be2
Exists in master and in 1 other branch production

Merge pull request #115 from akzhan/async-confirm

Async confirm
@@ -11,3 +11,4 @@ config/newrelic.yml @@ -11,3 +11,4 @@ config/newrelic.yml
11 .rvmrc 11 .rvmrc
12 *~ 12 *~
13 *.rbc 13 *.rbc
  14 +.DS_Store
app/views/layouts/application.html.haml
@@ -8,7 +8,7 @@ @@ -8,7 +8,7 @@
8 = favicon_link_tag 8 = favicon_link_tag
9 = csrf_meta_tag 9 = csrf_meta_tag
10 = javascript_include_tag :defaults 10 = javascript_include_tag :defaults
11 - = stylesheet_link_tag 'reset', 'application' 11 + = stylesheet_link_tag 'reset', 'application', 'jquery.alerts'
12 :css 12 :css
13 #{render :partial => "issue_trackers/icons.css"} 13 #{render :partial => "issue_trackers/icons.css"}
14 14
config/application.rb
@@ -38,7 +38,7 @@ module Errbit @@ -38,7 +38,7 @@ module Errbit
38 # config.i18n.default_locale = :de 38 # config.i18n.default_locale = :de
39 39
40 # JavaScript files you want as :defaults (application.js is always included). 40 # JavaScript files you want as :defaults (application.js is always included).
41 - config.action_view.javascript_expansions[:defaults] = %w(jquery underscore-1.1.6 rails form jquery.pjax) 41 + config.action_view.javascript_expansions[:defaults] = %w(jquery underscore-1.1.6 rails form jquery.pjax jquery.alerts rails.alerts)
42 42
43 # > rails generate - config 43 # > rails generate - config
44 config.generators do |g| 44 config.generators do |g|
public/images/alerts/help.gif 0 → 100755

1.54 KB

public/images/alerts/important.gif 0 → 100755

1.46 KB

public/images/alerts/info.gif 0 → 100755

1.45 KB

public/images/alerts/title.gif 0 → 100755

317 Bytes

public/javascripts/jquery.alerts.js 0 → 100644
@@ -0,0 +1,230 @@ @@ -0,0 +1,230 @@
  1 +// jQuery Alert Dialogs Plugin
  2 +//
  3 +// Version 1.2
  4 +//
  5 +// Cory S.N. LaViska
  6 +// A Beautiful Site (http://abeautifulsite.net/)
  7 +// 14 May 2009
  8 +//
  9 +// Visit http://abeautifulsite.net/notebook/87 for more information
  10 +//
  11 +// Usage:
  12 +// $.jAlert( message, [title, callback] )
  13 +// $.jConfirm( message, [title, callback] )
  14 +// $.jPrompt( message, [value, title, callback] )
  15 +//
  16 +// History:
  17 +//
  18 +// 1.00 - Released (29 December 2008)
  19 +//
  20 +// 1.01 - Fixed bug where unbinding would destroy all resize events
  21 +//
  22 +// 1.2 - global methods removed.
  23 +//
  24 +// License:
  25 +//
  26 +// This plugin is dual-licensed under the GNU General Public License and the MIT License and
  27 +// is copyright 2008 A Beautiful Site, LLC.
  28 +//
  29 +(function($) {
  30 +
  31 + $.alerts = {
  32 +
  33 + // These properties can be read/written by accessing $.alerts.propertyName from your scripts at any time
  34 +
  35 + verticalOffset: -75, // vertical offset of the dialog from center screen, in pixels
  36 + horizontalOffset: 0, // horizontal offset of the dialog from center screen, in pixels/
  37 + repositionOnResize: true, // re-centers the dialog on window resize
  38 + overlayOpacity: 0.01, // transparency level of overlay
  39 + overlayColor: '#FFF', // base color of overlay
  40 + draggable: true, // make the dialogs draggable (requires UI Draggables plugin)
  41 + okButton: ' OK ', // text for the OK button
  42 + cancelButton: ' Cancel ', // text for the Cancel button
  43 + dialogClass: null, // if specified, this class will be applied to all dialogs
  44 + titles: {
  45 + alert: 'Alert',
  46 + confirm: 'Confirm',
  47 + prompt: 'Prompt'
  48 + },
  49 +
  50 + // Public methods
  51 +
  52 + alert: function(message, title, callback) {
  53 + if (! title) title = $.alerts.titles.alert;
  54 + $.alerts._show(title, message, null, 'alert', function(result) {
  55 + if (callback) callback(result);
  56 + });
  57 + },
  58 +
  59 + confirm: function(message, title, callback) {
  60 + if (! title) title = $.alerts.titles.confirm;
  61 + $.alerts._show(title, message, null, 'confirm', function(result) {
  62 + if (callback) callback(result);
  63 + });
  64 + },
  65 +
  66 + prompt: function(message, value, title, callback) {
  67 + if (! title) title = $.alerts.titles.prompt;
  68 + $.alerts._show(title, message, value, 'prompt', function(result) {
  69 + if(callback) callback(result);
  70 + });
  71 + },
  72 +
  73 + // Private methods
  74 +
  75 + _show: function(title, msg, value, type, callback) {
  76 +
  77 + $.alerts._hide();
  78 + $.alerts._overlay('show');
  79 +
  80 + $("BODY").append(
  81 + '<div id="popup_container">' +
  82 + '<h1 id="popup_title"></h1>' +
  83 + '<div id="popup_content">' +
  84 + '<div id="popup_message"></div>' +
  85 + '</div>' +
  86 + '</div>');
  87 +
  88 + if( $.alerts.dialogClass ) $("#popup_container").addClass($.alerts.dialogClass);
  89 +
  90 + // IE6 Fix
  91 + var pos = ($.browser.msie && parseInt($.browser.version, 10) <= 6 ) ? 'absolute' : 'fixed';
  92 +
  93 + $("#popup_container").css({
  94 + position: pos,
  95 + zIndex: 99999,
  96 + padding: 0,
  97 + margin: 0
  98 + });
  99 +
  100 + $("#popup_title").text(title);
  101 + $("#popup_content").addClass(type);
  102 + $("#popup_message").text(msg);
  103 + $("#popup_message").html( $("#popup_message").text().replace(/\n/g, '<br />') );
  104 +
  105 + $("#popup_container").css({
  106 + minWidth: $("#popup_container").outerWidth(),
  107 + maxWidth: $("#popup_container").outerWidth()
  108 + });
  109 +
  110 + $.alerts._reposition();
  111 + $.alerts._maintainPosition(true);
  112 +
  113 + switch( type ) {
  114 + case 'alert':
  115 + $("#popup_message").after('<div id="popup_panel"><input type="button" value="' + $.alerts.okButton + '" id="popup_ok" /></div>');
  116 + $("#popup_ok").click( function() {
  117 + $.alerts._hide();
  118 + callback(true);
  119 + });
  120 + $("#popup_ok").focus().keypress( function(e) {
  121 + if( e.keyCode == 13 || e.keyCode == 27 ) $("#popup_ok").trigger('click');
  122 + });
  123 + break;
  124 + case 'confirm':
  125 + $("#popup_message").after('<div id="popup_panel"><input type="button" value="' + $.alerts.okButton + '" id="popup_ok" /> <input type="button" value="' + $.alerts.cancelButton + '" id="popup_cancel" /></div>');
  126 + $("#popup_ok").click( function() {
  127 + $.alerts._hide();
  128 + if( callback ) callback(true);
  129 + });
  130 + $("#popup_cancel").click( function() {
  131 + $.alerts._hide();
  132 + if( callback ) callback(false);
  133 + });
  134 + $("#popup_ok").focus();
  135 + $("#popup_ok, #popup_cancel").keypress( function(e) {
  136 + if( e.keyCode == 13 ) $("#popup_ok").trigger('click');
  137 + if( e.keyCode == 27 ) $("#popup_cancel").trigger('click');
  138 + });
  139 + break;
  140 + case 'prompt':
  141 + $("#popup_message").append('<br /><input type="text" size="30" id="popup_prompt" />').after('<div id="popup_panel"><input type="button" value="' + $.alerts.okButton + '" id="popup_ok" /> <input type="button" value="' + $.alerts.cancelButton + '" id="popup_cancel" /></div>');
  142 + $("#popup_prompt").width( $("#popup_message").width() );
  143 + $("#popup_ok").click( function() {
  144 + var val = $("#popup_prompt").val();
  145 + $.alerts._hide();
  146 + if( callback ) callback( val );
  147 + });
  148 + $("#popup_cancel").click( function() {
  149 + $.alerts._hide();
  150 + if( callback ) callback( null );
  151 + });
  152 + $("#popup_prompt, #popup_ok, #popup_cancel").keypress( function(e) {
  153 + if( e.keyCode == 13 ) $("#popup_ok").trigger('click');
  154 + if( e.keyCode == 27 ) $("#popup_cancel").trigger('click');
  155 + });
  156 + if( value ) $("#popup_prompt").val(value);
  157 + $("#popup_prompt").focus().select();
  158 + break;
  159 + default: break;
  160 + }
  161 +
  162 + // Make draggable
  163 + if ($.alerts.draggable && $.fn.draggable) {
  164 + $("#popup_container").draggable({ handle: $("#popup_title") });
  165 + $("#popup_title").css({ cursor: 'move' });
  166 + }
  167 + },
  168 +
  169 + _hide: function() {
  170 + $("#popup_container").remove();
  171 + $.alerts._overlay('hide');
  172 + $.alerts._maintainPosition(false);
  173 + },
  174 +
  175 + _overlay: function(status) {
  176 + switch( status ) {
  177 + case 'show':
  178 + $.alerts._overlay('hide');
  179 + $("BODY").append('<div id="popup_overlay"></div>');
  180 + $("#popup_overlay").css({
  181 + position: 'absolute',
  182 + zIndex: 99998,
  183 + top: '0px',
  184 + left: '0px',
  185 + width: '100%',
  186 + height: $(document).height(),
  187 + background: $.alerts.overlayColor,
  188 + opacity: $.alerts.overlayOpacity
  189 + });
  190 + break;
  191 + case 'hide':
  192 + $("#popup_overlay").remove();
  193 + break;
  194 + default: break;
  195 + }
  196 + },
  197 +
  198 + _reposition: function() {
  199 + var top = (($(window).height() / 2) - ($("#popup_container").outerHeight() / 2)) + $.alerts.verticalOffset;
  200 + var left = (($(window).width() / 2) - ($("#popup_container").outerWidth() / 2)) + $.alerts.horizontalOffset;
  201 + if( top < 0 ) top = 0;
  202 + if( left < 0 ) left = 0;
  203 +
  204 + // IE6 fix
  205 + if( $.browser.msie && parseInt($.browser.version, 10) <= 6 ) top = top + $(window).scrollTop();
  206 +
  207 + $("#popup_container").css({
  208 + top: top + 'px',
  209 + left: left + 'px'
  210 + });
  211 + $("#popup_overlay").height( $(document).height() );
  212 + },
  213 +
  214 + _maintainPosition: function(status) {
  215 + if( $.alerts.repositionOnResize ) {
  216 + switch(status) {
  217 + case true:
  218 + $(window).bind('resize', $.alerts._reposition);
  219 + break;
  220 + case false:
  221 + $(window).unbind('resize', $.alerts._reposition);
  222 + break;
  223 + default: break;
  224 + }
  225 + }
  226 + }
  227 +
  228 + };
  229 +
  230 +})(jQuery);
0 \ No newline at end of file 231 \ No newline at end of file
public/javascripts/rails.alerts.js 0 → 100644
@@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
  1 +/*
  2 + * Replaces default rails.confirm implementation with $.alerts.confirm.
  3 + */
  4 +
  5 +(function($) {
  6 + $.rails.confirm = function(msg) {
  7 + var answer = $.Deferred();
  8 + $.alerts.confirm(msg, 'Confirmation', function(r) {
  9 + $.rails.resolveOrReject(answer, r);
  10 + });
  11 + return answer.promise();
  12 + };
  13 +})(jQuery);
  14 +
public/javascripts/rails.js
@@ -51,8 +51,8 @@ @@ -51,8 +51,8 @@
51 // Link elements bound by jquery-ujs 51 // Link elements bound by jquery-ujs
52 linkClickSelector: 'a[data-confirm], a[data-method], a[data-remote]', 52 linkClickSelector: 'a[data-confirm], a[data-method], a[data-remote]',
53 53
54 - // Select elements bound by jquery-ujs  
55 - selectChangeSelector: 'select[data-remote]', 54 + // Select elements bound by jquery-ujs
  55 + selectChangeSelector: 'select[data-remote]',
56 56
57 // Form elements bound by jquery-ujs 57 // Form elements bound by jquery-ujs
58 formSubmitSelector: 'form', 58 formSubmitSelector: 'form',
@@ -85,9 +85,22 @@ @@ -85,9 +85,22 @@
85 return event.result !== false; 85 return event.result !== false;
86 }, 86 },
87 87
  88 + resolveOrReject: function(deferred, resolved) {
  89 + if (resolved) {
  90 + deferred.resolve();
  91 + } else {
  92 + deferred.reject();
  93 + }
  94 + return deferred;
  95 + },
  96 +
88 // Default confirm dialog, may be overridden with custom confirm dialog in $.rails.confirm 97 // Default confirm dialog, may be overridden with custom confirm dialog in $.rails.confirm
89 confirm: function(message) { 98 confirm: function(message) {
90 - return confirm(message); 99 + var res = confirm(message),
  100 + answer = $.Deferred();
  101 +
  102 + rails.resolveOrReject(answer, res);
  103 + return answer.promise();
91 }, 104 },
92 105
93 // Default ajax function, may be overridden with custom function in $.rails.ajax 106 // Default ajax function, may be overridden with custom function in $.rails.ajax
@@ -97,9 +110,10 @@ @@ -97,9 +110,10 @@
97 110
98 // Submits "remote" forms and links with ajax 111 // Submits "remote" forms and links with ajax
99 handleRemote: function(element) { 112 handleRemote: function(element) {
100 - var method, url, data,  
101 - crossDomain = element.data('cross-domain') || null,  
102 - dataType = element.data('type') || ($.ajaxSettings && $.ajaxSettings.dataType); 113 + var method, url, data, button,
  114 + crossDomain = element.data('cross-domain') || null,
  115 + dataType = element.data('type') || ($.ajaxSettings && $.ajaxSettings.dataType),
  116 + options;
103 117
104 if (rails.fire(element, 'ajax:before')) { 118 if (rails.fire(element, 'ajax:before')) {
105 119
@@ -108,7 +122,7 @@ @@ -108,7 +122,7 @@
108 url = element.attr('action'); 122 url = element.attr('action');
109 data = element.serializeArray(); 123 data = element.serializeArray();
110 // memoized value from clicked submit button 124 // memoized value from clicked submit button
111 - var button = element.data('ujs:submit-button'); 125 + button = element.data('ujs:submit-button');
112 if (button) { 126 if (button) {
113 data.push(button); 127 data.push(button);
114 element.data('ujs:submit-button', null); 128 element.data('ujs:submit-button', null);
@@ -119,9 +133,9 @@ @@ -119,9 +133,9 @@
119 data = element.serialize(); 133 data = element.serialize();
120 if (element.data('params')) data = data + "&" + element.data('params'); 134 if (element.data('params')) data = data + "&" + element.data('params');
121 } else { 135 } else {
122 - method = element.data('method');  
123 - url = element.attr('href');  
124 - data = element.data('params') || null; 136 + method = element.data('method');
  137 + url = element.attr('href');
  138 + data = element.data('params') || null;
125 } 139 }
126 140
127 options = { 141 options = {
@@ -143,8 +157,8 @@ @@ -143,8 +157,8 @@
143 element.trigger('ajax:error', [xhr, status, error]); 157 element.trigger('ajax:error', [xhr, status, error]);
144 } 158 }
145 }; 159 };
146 - // Do not pass url to `ajax` options if blank  
147 - if (url) { $.extend(options, { url: url }); } 160 + // Only pass url to `ajax` options if not blank
  161 + if (url) { options.url = url; }
148 162
149 rails.ajax(options); 163 rails.ajax(options);
150 } 164 }
@@ -154,14 +168,19 @@ @@ -154,14 +168,19 @@
154 // <a href="/users/5" data-method="delete" rel="nofollow" data-confirm="Are you sure?">Delete</a> 168 // <a href="/users/5" data-method="delete" rel="nofollow" data-confirm="Are you sure?">Delete</a>
155 handleMethod: function(link) { 169 handleMethod: function(link) {
156 var href = link.attr('href'), 170 var href = link.attr('href'),
157 - method = link.data('method'),  
158 - csrf_token = $('meta[name=csrf-token]').attr('content'),  
159 - csrf_param = $('meta[name=csrf-param]').attr('content'),  
160 - form = $('<form method="post" action="' + href + '"></form>'),  
161 - metadata_input = '<input name="_method" value="' + method + '" type="hidden" />';  
162 -  
163 - if (csrf_param !== undefined && csrf_token !== undefined) {  
164 - metadata_input += '<input name="' + csrf_param + '" value="' + csrf_token + '" type="hidden" />'; 171 + method = link.data('method') || 'GET',
  172 + csrf_token = $('meta[name=csrf-token]').attr('content'),
  173 + csrf_param = $('meta[name=csrf-param]').attr('content'),
  174 + form = $('<form></form>', { action: href, method: method, 'data-ujs-generated': 'true' }),
  175 + metadata_input = '';
  176 +
  177 + if (method !== 'GET') {
  178 + form.attr('method', 'POST');
  179 + metadata_input += '<input name="_method" value="' + method + '" type="hidden" />';
  180 +
  181 + if (csrf_param !== undefined && csrf_token !== undefined) {
  182 + metadata_input += '<input name="' + csrf_param + '" value="' + csrf_token + '" type="hidden" />';
  183 + }
165 } 184 }
166 185
167 form.hide().append(metadata_input).appendTo('body'); 186 form.hide().append(metadata_input).appendTo('body');
@@ -175,7 +194,9 @@ @@ -175,7 +194,9 @@
175 */ 194 */
176 disableFormElements: function(form) { 195 disableFormElements: function(form) {
177 form.find(rails.disableSelector).each(function() { 196 form.find(rails.disableSelector).each(function() {
178 - var element = $(this), method = element.is('button') ? 'html' : 'val'; 197 + var element = $(this),
  198 + method = element.is('button') ? 'html' : 'val';
  199 +
179 element.data('ujs:enable-with', element[method]()); 200 element.data('ujs:enable-with', element[method]());
180 element[method](element.data('disable-with')); 201 element[method](element.data('disable-with'));
181 element.attr('disabled', 'disabled'); 202 element.attr('disabled', 'disabled');
@@ -188,7 +209,9 @@ @@ -188,7 +209,9 @@
188 */ 209 */
189 enableFormElements: function(form) { 210 enableFormElements: function(form) {
190 form.find(rails.enableSelector).each(function() { 211 form.find(rails.enableSelector).each(function() {
191 - var element = $(this), method = element.is('button') ? 'html' : 'val'; 212 + var element = $(this),
  213 + method = element.is('button') ? 'html' : 'val';
  214 +
192 if (element.data('ujs:enable-with')) element[method](element.data('ujs:enable-with')); 215 if (element.data('ujs:enable-with')) element[method](element.data('ujs:enable-with'));
193 element.removeAttr('disabled'); 216 element.removeAttr('disabled');
194 }); 217 });
@@ -206,20 +229,36 @@ @@ -206,20 +229,36 @@
206 */ 229 */
207 allowAction: function(element) { 230 allowAction: function(element) {
208 var message = element.data('confirm'), 231 var message = element.data('confirm'),
209 - answer = false, callback;  
210 - if (!message) { return true; } 232 + confirmAnswer,
  233 + answer = $.Deferred();
  234 +
  235 + if (!message) { return $.when(true); }
211 236
212 if (rails.fire(element, 'confirm')) { 237 if (rails.fire(element, 'confirm')) {
213 - answer = rails.confirm(message);  
214 - callback = rails.fire(element, 'confirm:complete', [answer]); 238 + confirmAnswer = rails.confirm(message);
  239 + confirmAnswer.then(
  240 + function() {
  241 + var callbackOk = rails.fire(element, 'confirm:complete', [ true ]);
  242 + rails.resolveOrReject(answer, callbackOk);
  243 + },
  244 + function() {
  245 + rails.fire(element, 'confirm:complete', [ false ]);
  246 + answer.reject();
  247 + }
  248 + );
  249 + return answer.promise();
  250 + // If `confirm` event handler returned false...
  251 + } else {
  252 + answer.reject();
  253 + return answer.promise();
215 } 254 }
216 - return answer && callback;  
217 }, 255 },
218 256
219 // Helper function which checks for blank inputs in a form that match the specified CSS selector 257 // Helper function which checks for blank inputs in a form that match the specified CSS selector
220 blankInputs: function(form, specifiedSelector, nonBlank) { 258 blankInputs: function(form, specifiedSelector, nonBlank) {
221 var inputs = $(), input, 259 var inputs = $(), input,
222 - selector = specifiedSelector || 'input,textarea'; 260 + selector = specifiedSelector || 'input,textarea';
  261 +
223 form.find(selector).each(function() { 262 form.find(selector).each(function() {
224 input = $(this); 263 input = $(this);
225 // Collect non-blank inputs if nonBlank option is true, otherwise, collect blank inputs 264 // Collect non-blank inputs if nonBlank option is true, otherwise, collect blank inputs
@@ -246,6 +285,7 @@ @@ -246,6 +285,7 @@
246 // manually invoke them. If anyone returns false then stop the loop 285 // manually invoke them. If anyone returns false then stop the loop
247 callFormSubmitBindings: function(form) { 286 callFormSubmitBindings: function(form) {
248 var events = form.data('events'), continuePropagation = true; 287 var events = form.data('events'), continuePropagation = true;
  288 +
249 if (events !== undefined && events['submit'] !== undefined) { 289 if (events !== undefined && events['submit'] !== undefined) {
250 $.each(events['submit'], function(i, obj){ 290 $.each(events['submit'], function(i, obj){
251 if (typeof obj.handler === 'function') return continuePropagation = obj.handler(obj.data); 291 if (typeof obj.handler === 'function') return continuePropagation = obj.handler(obj.data);
@@ -259,65 +299,99 @@ @@ -259,65 +299,99 @@
259 299
260 $(rails.linkClickSelector).live('click.rails', function(e) { 300 $(rails.linkClickSelector).live('click.rails', function(e) {
261 var link = $(this); 301 var link = $(this);
262 - if (!rails.allowAction(link)) return rails.stopEverything(e);  
263 302
264 - if (link.data('remote') !== undefined) {  
265 - rails.handleRemote(link);  
266 - return false;  
267 - } else if (link.data('method')) {  
268 - rails.handleMethod(link);  
269 - return false;  
270 - } 303 + rails.allowAction(link).then(
  304 + function() {
  305 + if (link.data('remote') !== undefined) {
  306 + rails.handleRemote(link);
  307 + } else {
  308 + rails.handleMethod(link);
  309 + }
  310 + },
  311 + function() {
  312 + rails.stopEverything(e);
  313 + }
  314 + );
  315 +
  316 + e.preventDefault();
271 }); 317 });
272 318
273 - $(rails.selectChangeSelector).live('change.rails', function(e) { 319 + $(rails.selectChangeSelector).live('change.rails', function(e) {
274 var link = $(this); 320 var link = $(this);
275 - if (!rails.allowAction(link)) return rails.stopEverything(e);  
276 321
277 - rails.handleRemote(link);  
278 - return false;  
279 - }); 322 + rails.allowAction(link).then(
  323 + function() {
  324 + rails.handleRemote(link);
  325 + },
  326 + function() {
  327 + rails.stopEverything(e);
  328 + }
  329 + );
  330 +
  331 + e.preventDefault();
  332 + });
280 333
281 $(rails.formSubmitSelector).live('submit.rails', function(e) { 334 $(rails.formSubmitSelector).live('submit.rails', function(e) {
282 var form = $(this), 335 var form = $(this),
283 - remote = form.data('remote') !== undefined,  
284 - blankRequiredInputs = rails.blankInputs(form, rails.requiredInputSelector),  
285 - nonBlankFileInputs = rails.nonBlankInputs(form, rails.fileInputSelector); 336 + remote = (form.data('remote') !== undefined),
  337 + blankRequiredInputs = rails.blankInputs(form, rails.requiredInputSelector),
  338 + nonBlankFileInputs = rails.nonBlankInputs(form, rails.fileInputSelector);
  339 +
  340 + rails.allowAction(form).then(
  341 + function() {
  342 + // skip other logic when required values are missing or file upload is present
  343 + if (blankRequiredInputs && form.attr("novalidate") == undefined && rails.fire(form, 'ajax:aborted:required', [blankRequiredInputs])) {
  344 + return rails.stopEverything(e);
  345 + }
286 346
287 - if (!rails.allowAction(form)) return rails.stopEverything(e); 347 + if (remote) {
  348 + if (nonBlankFileInputs) {
  349 + return rails.fire(form, 'ajax:aborted:file', [nonBlankFileInputs]);
  350 + }
288 351
289 - // skip other logic when required values are missing or file upload is present  
290 - if (blankRequiredInputs && form.attr("novalidate") == undefined && rails.fire(form, 'ajax:aborted:required', [blankRequiredInputs])) {  
291 - return rails.stopEverything(e);  
292 - } 352 + // If browser does not support submit bubbling, then this live-binding will be called before direct
  353 + // bindings. Therefore, we should directly call any direct bindings before remotely submitting form.
  354 + if (!$.support.submitBubbles && rails.callFormSubmitBindings(form) === false) return rails.stopEverything(e);
293 355
294 - if (remote) {  
295 - if (nonBlankFileInputs) {  
296 - return rails.fire(form, 'ajax:aborted:file', [nonBlankFileInputs]); 356 + rails.handleRemote(form);
  357 + } else {
  358 + // slight timeout so that the submit button gets properly serialized
  359 + setTimeout(function() {
  360 + rails.disableFormElements(form);
  361 + // Submit the form from dom-level js (i.e. *not* via jquery),
  362 + // which will skip all submit bindings (including this live-binding),
  363 + // since they have already been called.
  364 + form.get(0).submit();
  365 + }, 13);
  366 + }
  367 + },
  368 + function() {
  369 + rails.stopEverything(e);
297 } 370 }
  371 + );
298 372
299 - // If browser does not support submit bubbling, then this live-binding will be called before direct  
300 - // bindings. Therefore, we should directly call any direct bindings before remotely submitting form.  
301 - if (!$.support.submitBubbles && rails.callFormSubmitBindings(form) === false) return rails.stopEverything(e);  
302 -  
303 - rails.handleRemote(form);  
304 - return false;  
305 - } else {  
306 - // slight timeout so that the submit button gets properly serialized  
307 - setTimeout(function(){ rails.disableFormElements(form); }, 13);  
308 - } 373 + e.preventDefault();
309 }); 374 });
310 375
311 $(rails.formInputClickSelector).live('click.rails', function(event) { 376 $(rails.formInputClickSelector).live('click.rails', function(event) {
312 var button = $(this); 377 var button = $(this);
313 378
314 - if (!rails.allowAction(button)) return rails.stopEverything(event);  
315 -  
316 - // register the pressed submit button  
317 - var name = button.attr('name'),  
318 - data = name ? {name:name, value:button.val()} : null; 379 + rails.allowAction(button).then(
  380 + function() {
  381 + // register the pressed submit button
  382 + var name = button.attr('name'), form,
  383 + data = name ? {name:name, value:button.val()} : null;
  384 +
  385 + form = button.closest('form');
  386 + form.data('ujs:submit-button', data);
  387 + form.submit();
  388 + },
  389 + function() {
  390 + rails.stopEverything(event);
  391 + }
  392 + );
319 393
320 - button.closest('form').data('ujs:submit-button', data); 394 + e.preventDefault();
321 }); 395 });
322 396
323 $(rails.formSubmitSelector).live('ajax:beforeSend.rails', function(event) { 397 $(rails.formSubmitSelector).live('ajax:beforeSend.rails', function(event) {
@@ -329,3 +403,4 @@ @@ -329,3 +403,4 @@
329 }); 403 });
330 404
331 })( jQuery ); 405 })( jQuery );
  406 +
public/stylesheets/jquery.alerts.css 0 → 100644
@@ -0,0 +1,57 @@ @@ -0,0 +1,57 @@
  1 +#popup_container {
  2 + font-family: Arial, sans-serif;
  3 + font-size: 12px;
  4 + min-width: 300px; /* Dialog will be no smaller than this */
  5 + max-width: 600px; /* Dialog will wrap after this width */
  6 + background: #FFF;
  7 + border: solid 5px #999;
  8 + color: #000;
  9 + -moz-border-radius: 5px;
  10 + -webkit-border-radius: 5px;
  11 + border-radius: 5px;
  12 +}
  13 +
  14 +#popup_title {
  15 + font-size: 14px;
  16 + font-weight: bold;
  17 + text-align: center;
  18 + line-height: 1.75em;
  19 + color: #666;
  20 + background: #CCC url(/images/alerts/title.gif) top repeat-x;
  21 + border: solid 1px #FFF;
  22 + border-bottom: solid 1px #999;
  23 + cursor: default;
  24 + padding: 0em;
  25 + margin: 0em;
  26 +}
  27 +
  28 +#popup_content {
  29 + background: 16px 16px no-repeat url(/images/alerts/info.gif);
  30 + padding: 1em 1.75em;
  31 + margin: 0em;
  32 +}
  33 +
  34 +#popup_content.alert {
  35 + background-image: url(/images/alerts/info.gif);
  36 +}
  37 +
  38 +#popup_content.confirm {
  39 + background-image: url(/images/alerts/important.gif);
  40 +}
  41 +
  42 +#popup_content.prompt {
  43 + background-image: url(/images/alerts/help.gif);
  44 +}
  45 +
  46 +#popup_message {
  47 + padding-left: 48px;
  48 +}
  49 +
  50 +#popup_panel {
  51 + text-align: center;
  52 + margin: 1em 0em 0em 1em;
  53 +}
  54 +
  55 +#popup_prompt {
  56 + margin: .5em 0em;
  57 +}
0 \ No newline at end of file 58 \ No newline at end of file