best_in_place 0.1.7 → 0.1.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- best_in_place (0.1.5)
4
+ best_in_place (0.1.7)
5
5
  rails (~> 3.0.0)
6
6
 
7
7
  GEM
@@ -20,250 +20,268 @@
20
20
  */
21
21
 
22
22
  function BestInPlaceEditor(e) {
23
- this.element = jQuery(e)
24
- this.initOptions()
25
- this.bindForm()
26
- $(this.activator).bind('click', {editor: this}, this.clickHandler)
23
+ this.element = jQuery(e);
24
+ this.initOptions();
25
+ this.bindForm();
26
+ $(this.activator).bind('click', {editor: this}, this.clickHandler);
27
27
  }
28
28
 
29
29
  BestInPlaceEditor.prototype = {
30
30
  // Public Interface Functions //////////////////////////////////////////////
31
31
 
32
32
  activate : function() {
33
- var elem = this.element.html()
34
- this.oldValue = elem
35
- $(this.activator).unbind("click", this.clickHandler)
36
- this.activateForm()
33
+ var elem = this.element.html();
34
+ this.oldValue = elem;
35
+ $(this.activator).unbind("click", this.clickHandler);
36
+ this.activateForm();
37
37
  },
38
38
 
39
39
  abort : function() {
40
- this.element.html(this.oldValue)
41
- $(this.activator).bind('click', {editor: this}, this.clickHandler)
40
+ this.element.html(this.oldValue);
41
+ $(this.activator).bind('click', {editor: this}, this.clickHandler);
42
42
  },
43
43
 
44
44
  update : function() {
45
- var editor = this
45
+ var editor = this;
46
46
  if (this.formType in {"input":1, "textarea":1} && this.getValue() == this.oldValue)
47
47
  { // Avoid request if no change is made
48
- editor.element.html(this.getValue())
49
- $(this.activator).bind('click', {editor: this}, this.clickHandler)
50
- return true
48
+ editor.element.html(this.getValue());
49
+ $(this.activator).bind('click', {editor: this}, this.clickHandler);
50
+ return true;
51
51
  }
52
52
  editor.ajax({
53
53
  "type" : "post",
54
54
  "dataType" : "text",
55
55
  "data" : editor.requestData(),
56
- "success" : function(data){ editor.loadSuccessCallback(data) },
57
- "error" : function(request, error){ editor.loadErrorCallback(request, error) }
58
- })
56
+ "success" : function(data){ editor.loadSuccessCallback(data); },
57
+ "error" : function(request, error){ editor.loadErrorCallback(request, error); }
58
+ });
59
59
  if (this.formType == "select") {
60
- var value = this.getValue()
61
- $.each(this.values, function(i, v) { if (value == v[0]) editor.element.html(v[1])} )
60
+ var value = this.getValue();
61
+ $.each(this.values, function(i, v) {
62
+ if (value == v[0]) {
63
+ editor.element.html(v[1]);
64
+ }
65
+ }
66
+ );
62
67
  } else if (this.formType == "checkbox") {
63
- editor.element.html(this.getValue() ? this.values[1] : this.values[0])
64
- } else editor.element.html(this.getValue())
68
+ editor.element.html(this.getValue() ? this.values[1] : this.values[0]);
69
+ } else {
70
+ editor.element.html(this.getValue());
71
+ }
65
72
  },
66
73
 
67
74
  activateForm : function() {
68
- alert("The form was not properly initialized. activateForm is unbound")
75
+ alert("The form was not properly initialized. activateForm is unbound");
69
76
  },
70
77
 
71
78
  // Helper Functions ////////////////////////////////////////////////////////
72
79
 
73
80
  initOptions : function() {
74
81
  // Try parent supplied info
75
- var self = this
82
+ var self = this;
76
83
  self.element.parents().each(function(){
77
- self.url = self.url || jQuery(this).attr("data-url")
78
- self.collection = self.collection || jQuery(this).attr("data-collection")
79
- self.formType = self.formType || jQuery(this).attr("data-type")
80
- self.objectName = self.objectName || jQuery(this).attr("data-object")
81
- self.attributeName = self.attributeName || jQuery(this).attr("data-attribute")
82
- })
84
+ self.url = self.url || jQuery(this).attr("data-url");
85
+ self.collection = self.collection || jQuery(this).attr("data-collection");
86
+ self.formType = self.formType || jQuery(this).attr("data-type");
87
+ self.objectName = self.objectName || jQuery(this).attr("data-object");
88
+ self.attributeName = self.attributeName || jQuery(this).attr("data-attribute");
89
+ });
83
90
 
84
91
  // Try Rails-id based if parents did not explicitly supply something
85
92
  self.element.parents().each(function(){
86
- var res
87
- if (res = this.id.match(/^(\w+)_(\d+)$/i)) {
88
- self.objectName = self.objectName || res[1]
93
+ var res = this.id.match(/^(\w+)_(\d+)$/i);
94
+ if (res) {
95
+ self.objectName = self.objectName || res[1];
89
96
  }
90
- })
97
+ });
91
98
 
92
99
  // Load own attributes (overrides all others)
93
- self.url = self.element.attr("data-url") || self.url || document.location.pathname
94
- self.collection = self.element.attr("data-collection") || self.collection
95
- self.formType = self.element.attr("data-type") || self.formtype || "input"
96
- self.objectName = self.element.attr("data-object") || self.objectName
97
- self.attributeName = self.element.attr("data-attribute") || self.attributeName
98
- self.activator = self.element.attr("data-activator") || self.element
99
-
100
- if (!self.element.attr("data-sanitize")) self.sanitize = true
101
- else self.sanitize = (self.element.attr("data-sanitize") == "true")
102
-
100
+ self.url = self.element.attr("data-url") || self.url || document.location.pathname;
101
+ self.collection = self.element.attr("data-collection") || self.collection;
102
+ self.formType = self.element.attr("data-type") || self.formtype || "input";
103
+ self.objectName = self.element.attr("data-object") || self.objectName;
104
+ self.attributeName = self.element.attr("data-attribute") || self.attributeName;
105
+ self.activator = self.element.attr("data-activator") || self.element;
106
+
107
+ if (!self.element.attr("data-sanitize")) {
108
+ self.sanitize = true;
109
+ }
110
+ else {
111
+ self.sanitize = (self.element.attr("data-sanitize") == "true");
112
+ }
103
113
 
104
- if ((self.formType == "select" || self.formType == "checkbox") && self.collection != null)
114
+ if ((self.formType == "select" || self.formType == "checkbox") && self.collection !== null)
105
115
  {
106
- self.values = jQuery.parseJSON(self.collection)
116
+ self.values = jQuery.parseJSON(self.collection);
107
117
  }
108
118
  },
109
119
 
110
120
  bindForm : function() {
111
- this.activateForm = BestInPlaceEditor.forms[this.formType].activateForm
112
- this.getValue = BestInPlaceEditor.forms[this.formType].getValue
121
+ this.activateForm = BestInPlaceEditor.forms[this.formType].activateForm;
122
+ this.getValue = BestInPlaceEditor.forms[this.formType].getValue;
113
123
  },
114
124
 
115
125
  getValue : function() {
116
- alert("The form was not properly initialized. getValue is unbound")
126
+ alert("The form was not properly initialized. getValue is unbound");
117
127
  },
118
128
 
119
129
  // Trim and Strips HTML from text
120
130
  sanitizeValue : function(s) {
121
131
  if (this.sanitize)
122
132
  {
123
- var tmp = document.createElement("DIV")
124
- tmp.innerHTML = s
125
- s = tmp.textContent || tmp.innerText
133
+ var tmp = document.createElement("DIV");
134
+ tmp.innerHTML = s;
135
+ s = tmp.textContent || tmp.innerText;
126
136
  }
127
- return jQuery.trim(s)
137
+ return jQuery.trim(s);
128
138
  },
129
139
 
130
140
  /* Generate the data sent in the POST request */
131
141
  requestData : function() {
132
- //jq14: data as JS object, not string.
133
- var data = "_method=put"
134
- data += "&"+this.objectName+'['+this.attributeName+']='+encodeURIComponent(this.getValue())
135
- if (window.rails_authenticity_token) {
136
- data += "&authenticity_token="+encodeURIComponent(window.rails_authenticity_token)
137
- }
138
- return data
142
+ // To prevent xss attacks, a csrf token must be defined as a meta attribute
143
+ csrf_token = $('meta[name=csrf-token]').attr('content');
144
+ csrf_param = $('meta[name=csrf-param]').attr('content');
145
+
146
+ var data = "_method=put";
147
+ data += "&" + this.objectName + '[' + this.attributeName + ']=' + encodeURIComponent(this.getValue());
148
+
149
+ if (csrf_param !== undefined && csrf_token !== undefined) {
150
+ data += "&" + csrf_param + "=" + encodeURIComponent(csrf_token);
151
+ }
152
+ return data;
139
153
  },
140
154
 
141
155
  ajax : function(options) {
142
- options.url = this.url
143
- options.beforeSend = function(xhr){ xhr.setRequestHeader("Accept", "application/json") }
144
- return jQuery.ajax(options)
156
+ options.url = this.url;
157
+ options.beforeSend = function(xhr){ xhr.setRequestHeader("Accept", "application/json"); };
158
+ return jQuery.ajax(options);
145
159
  },
146
160
 
147
161
  // Handlers ////////////////////////////////////////////////////////////////
148
162
 
149
163
  loadSuccessCallback : function(data) {
150
- //jq14: data as JS object, not string.
151
- if (jQuery.fn.jquery < "1.4") data = eval('(' + data + ')' )
152
- this.element.html(data[this.objectName])
153
-
164
+ this.element.html(data[this.objectName]);
154
165
  // Binding back after being clicked
155
- $(this.activator).bind('click', {editor: this}, this.clickHandler)
166
+ $(this.activator).bind('click', {editor: this}, this.clickHandler);
156
167
  },
157
168
 
158
169
  loadErrorCallback : function(request, error) {
159
- this.element.html(this.oldValue)
170
+ this.element.html(this.oldValue);
160
171
 
161
172
  // Display all error messages from server side validation
162
173
  $.each(jQuery.parseJSON(request.responseText), function(index, value) {
163
- var container = $("<span class='flash-error'></span>").html(value)
164
- container.purr()
165
- })
174
+ var container = $("<span class='flash-error'></span>").html(value);
175
+ container.purr();
176
+ });
166
177
 
167
178
  // Binding back after being clicked
168
- $(this.activator).bind('click', {editor: this}, this.clickHandler)
179
+ $(this.activator).bind('click', {editor: this}, this.clickHandler);
169
180
  },
170
181
 
171
182
  clickHandler : function(event) {
172
- event.data.editor.activate()
183
+ event.data.editor.activate();
173
184
  }
174
- }
185
+ };
175
186
 
176
187
 
177
188
  BestInPlaceEditor.forms = {
178
189
  "input" : {
179
190
  activateForm : function() {
180
- var form = '<form class="form_in_place" action="javascript:void(0)" style="display:inline;"><input type="text" value="' + this.sanitizeValue(this.oldValue) + '"></form>'
181
- this.element.html(form)
182
- this.element.find('input')[0].select()
183
- this.element.find("form").bind('submit', {editor: this}, BestInPlaceEditor.forms.input.submitHandler)
184
- this.element.find("input").bind('blur', {editor: this}, BestInPlaceEditor.forms.input.inputBlurHandler)
185
- this.element.find("input").bind('keyup', {editor: this}, BestInPlaceEditor.forms.input.keyupHandler)
191
+ var output = '<form class="form_in_place" action="javascript:void(0)" style="display:inline;">';
192
+ output += '<input type="text" value="' + this.sanitizeValue(this.oldValue) + '"></form>';
193
+ this.element.html(output);
194
+ this.element.find('input')[0].select();
195
+ this.element.find("form").bind('submit', {editor: this}, BestInPlaceEditor.forms.input.submitHandler);
196
+ this.element.find("input").bind('blur', {editor: this}, BestInPlaceEditor.forms.input.inputBlurHandler);
197
+ this.element.find("input").bind('keyup', {editor: this}, BestInPlaceEditor.forms.input.keyupHandler);
186
198
  },
187
199
 
188
200
  getValue : function() {
189
- return this.sanitizeValue(this.element.find("input").val())
201
+ return this.sanitizeValue(this.element.find("input").val());
190
202
  },
191
203
 
192
204
  inputBlurHandler : function(event) {
193
- event.data.editor.update()
205
+ event.data.editor.update();
194
206
  },
195
207
 
196
208
  submitHandler : function(event) {
197
- event.data.editor.update()
209
+ event.data.editor.update();
198
210
  },
199
211
 
200
212
  keyupHandler : function(event) {
201
- if (event.keyCode == 27) event.data.editor.abort()
213
+ if (event.keyCode == 27) {
214
+ event.data.editor.abort();
215
+ }
202
216
  }
203
217
  },
204
218
 
205
219
  "select" : {
206
220
  activateForm : function() {
207
- var output = "<form action='javascript:void(0)' style='display:inline;'><select>"
208
- var selected = ""
209
- var oldValue = this.oldValue
221
+ var output = "<form action='javascript:void(0)' style='display:inline;'><select>";
222
+ var selected = "";
223
+ var oldValue = this.oldValue;
210
224
  $.each(this.values, function(index, value) {
211
- selected = (value[1] == oldValue ? "selected='selected'" : "")
212
- output += "<option value='" + value[0] + "' " + selected + ">" + value[1] + "</option>"
213
- })
214
- output += "</select></form>"
215
- this.element.html(output)
216
- this.element.find("select").bind('change', {editor: this}, BestInPlaceEditor.forms.select.blurHandler)
225
+ selected = (value[1] == oldValue ? "selected='selected'" : "");
226
+ output += "<option value='" + value[0] + "' " + selected + ">" + value[1] + "</option>";
227
+ });
228
+ output += "</select></form>";
229
+ this.element.html(output);
230
+ this.element.find("select").bind('change', {editor: this}, BestInPlaceEditor.forms.select.blurHandler);
217
231
  },
218
232
 
219
233
  getValue : function() {
220
- return this.sanitizeValue(this.element.find("select").val())
234
+ return this.sanitizeValue(this.element.find("select").val());
221
235
  },
222
236
 
223
237
  blurHandler : function(event) {
224
- event.data.editor.update()
225
- },
238
+ event.data.editor.update();
239
+ }
226
240
  },
227
241
 
228
242
  "checkbox" : {
229
243
  activateForm : function() {
230
- var newValue = Boolean(this.oldValue != this.values[1])
231
- var output = newValue ? this.values[1] : this.values[0]
232
- this.element.html(output)
233
- this.update()
244
+ var newValue = Boolean(this.oldValue != this.values[1]);
245
+ var output = newValue ? this.values[1] : this.values[0];
246
+ this.element.html(output);
247
+ this.update();
234
248
  },
235
249
 
236
250
  getValue : function() {
237
- return Boolean(this.element.html() == this.values[1])
251
+ return Boolean(this.element.html() == this.values[1]);
238
252
  }
239
253
  },
240
254
 
241
255
  "textarea" : {
242
256
  activateForm : function() {
243
- this.element.html('<form action="javascript:void(0)" style="display:inline;"><textarea>' + this.sanitizeValue(this.oldValue) + '</textarea></form>')
244
- this.element.find('textarea')[0].select()
245
- this.element.find("textarea").bind('blur', {editor: this}, BestInPlaceEditor.forms.textarea.blurHandler)
246
- this.element.find("textarea").bind('keyup', {editor: this}, BestInPlaceEditor.forms.textarea.keyupHandler)
257
+ var output = '<form action="javascript:void(0)" style="display:inline;"><textarea>';
258
+ output += this.sanitizeValue(this.oldValue);
259
+ output += '</textarea></form>';
260
+ this.element.html(output);
261
+ this.element.find('textarea')[0].select();
262
+ this.element.find("textarea").bind('blur', {editor: this}, BestInPlaceEditor.forms.textarea.blurHandler);
263
+ this.element.find("textarea").bind('keyup', {editor: this}, BestInPlaceEditor.forms.textarea.keyupHandler);
247
264
  },
248
265
 
249
266
  getValue : function() {
250
- return this.sanitizeValue(this.element.find("textarea").val())
267
+ return this.sanitizeValue(this.element.find("textarea").val());
251
268
  },
252
269
 
253
270
  blurHandler : function(event) {
254
- event.data.editor.update()
271
+ event.data.editor.update();
255
272
  },
256
273
 
257
274
  keyupHandler : function(event) {
258
- if (event.keyCode == 27) event.data.editor.abort()
275
+ if (event.keyCode == 27) {
276
+ event.data.editor.abort();
277
+ }
259
278
  }
260
-
261
279
  }
262
- }
280
+ };
263
281
 
264
282
  jQuery.fn.best_in_place = function() {
265
283
  this.each(function(){
266
- jQuery(this).data('bestInPlaceEditor', new BestInPlaceEditor(this))
267
- })
268
- return this
269
- }
284
+ jQuery(this).data('bestInPlaceEditor', new BestInPlaceEditor(this));
285
+ });
286
+ return this;
287
+ };
@@ -1,133 +1,148 @@
1
- jQuery(function ($) {
2
- var csrf_token = $('meta[name=csrf-token]').attr('content'),
3
- csrf_param = $('meta[name=csrf-param]').attr('content');
4
-
5
- $.fn.extend({
6
- /**
7
- * Triggers a custom event on an element and returns the event result
8
- * this is used to get around not being able to ensure callbacks are placed
9
- * at the end of the chain.
10
- *
11
- * TODO: deprecate with jQuery 1.4.2 release, in favor of subscribing to our
12
- * own events and placing ourselves at the end of the chain.
13
- */
14
- triggerAndReturn: function (name, data) {
15
- var event = new $.Event(name);
16
- this.trigger(event, data);
17
-
18
- return event.result !== false;
19
- },
20
-
21
- /**
22
- * Handles execution of remote calls firing overridable events along the way
23
- */
24
- callRemote: function () {
25
- var el = this,
26
- method = el.attr('method') || el.attr('data-method') || 'GET',
27
- url = el.attr('action') || el.attr('href'),
28
- dataType = el.attr('data-type') || 'script';
29
-
30
- if (url === undefined) {
31
- throw "No URL specified for remote call (action or href must be present).";
32
- } else {
33
- if (el.triggerAndReturn('ajax:before')) {
34
- var data = el.is('form') ? el.serializeArray() : [];
35
- $.ajax({
36
- url: url,
37
- data: data,
38
- dataType: dataType,
39
- type: method.toUpperCase(),
40
- beforeSend: function (xhr) {
41
- el.trigger('ajax:loading', xhr);
42
- },
43
- success: function (data, status, xhr) {
44
- el.trigger('ajax:success', [data, status, xhr]);
45
- },
46
- complete: function (xhr) {
47
- el.trigger('ajax:complete', xhr);
48
- },
49
- error: function (xhr, status, error) {
50
- el.trigger('ajax:failure', [xhr, status, error]);
51
- }
52
- });
53
- }
54
-
55
- el.trigger('ajax:after');
56
- }
57
- }
58
- });
59
-
60
- /**
61
- * confirmation handler
62
- */
63
- $('a[data-confirm],input[data-confirm]').live('click', function () {
64
- var el = $(this);
65
- if (el.triggerAndReturn('confirm')) {
66
- if (!confirm(el.attr('data-confirm'))) {
67
- return false;
68
- }
69
- }
70
- });
71
-
72
-
73
- /**
74
- * remote handlers
75
- */
76
- $('form[data-remote]').live('submit', function (e) {
77
- $(this).callRemote();
78
- e.preventDefault();
79
- });
80
-
81
- $('a[data-remote],input[data-remote]').live('click', function (e) {
82
- $(this).callRemote();
83
- e.preventDefault();
84
- });
85
-
86
- $('a[data-method]:not([data-remote])').live('click', function (e){
87
- var link = $(this),
88
- href = link.attr('href'),
89
- method = link.attr('data-method'),
90
- form = $('<form method="post" action="'+href+'"></form>'),
91
- metadata_input = '<input name="_method" value="'+method+'" type="hidden" />';
92
-
93
- if (csrf_param != null && csrf_token != null) {
94
- metadata_input += '<input name="'+csrf_param+'" value="'+csrf_token+'" type="hidden" />';
95
- }
96
-
97
- form.hide()
98
- .append(metadata_input)
99
- .appendTo('body');
100
-
101
- e.preventDefault();
102
- form.submit();
103
- });
104
-
105
- /**
106
- * disable-with handlers
107
- */
108
- var disable_with_input_selector = 'input[data-disable-with]';
109
- var disable_with_form_remote_selector = 'form[data-remote]:has(' + disable_with_input_selector + ')';
110
- var disable_with_form_not_remote_selector = 'form:not([data-remote]):has(' + disable_with_input_selector + ')';
111
-
112
- var disable_with_input_function = function () {
113
- $(this).find(disable_with_input_selector).each(function () {
114
- var input = $(this);
115
- input.data('enable-with', input.val())
116
- .attr('value', input.attr('data-disable-with'))
117
- .attr('disabled', 'disabled');
118
- });
119
- };
120
-
121
- $(disable_with_form_remote_selector).live('ajax:before', disable_with_input_function);
122
- $(disable_with_form_not_remote_selector).live('submit', disable_with_input_function);
123
-
124
- $(disable_with_form_remote_selector).live('ajax:complete', function () {
125
- $(this).find(disable_with_input_selector).each(function () {
126
- var input = $(this);
127
- input.removeAttr('disabled')
128
- .val(input.data('enable-with'));
129
- });
130
- });
131
-
132
- });
133
-
1
+ /**
2
+ * Unobtrusive scripting adapter for jQuery
3
+ *
4
+ * Requires jQuery 1.4.3 or later.
5
+ * https://github.com/rails/jquery-ujs
6
+ */
7
+
8
+ (function($) {
9
+ // Triggers an event on an element and returns the event result
10
+ function fire(obj, name, data) {
11
+ var event = new $.Event(name);
12
+ obj.trigger(event, data);
13
+ return event.result !== false;
14
+ }
15
+
16
+ // Submits "remote" forms and links with ajax
17
+ function handleRemote(element) {
18
+ var method, url, data,
19
+ dataType = element.attr('data-type') || ($.ajaxSettings && $.ajaxSettings.dataType);
20
+
21
+ if (element.is('form')) {
22
+ method = element.attr('method');
23
+ url = element.attr('action');
24
+ data = element.serializeArray();
25
+ // memoized value from clicked submit button
26
+ var button = element.data('ujs:submit-button');
27
+ if (button) {
28
+ data.push(button);
29
+ element.data('ujs:submit-button', null);
30
+ }
31
+ } else {
32
+ method = element.attr('data-method');
33
+ url = element.attr('href');
34
+ data = null;
35
+ }
36
+
37
+ $.ajax({
38
+ url: url, type: method || 'GET', data: data, dataType: dataType,
39
+ // stopping the "ajax:beforeSend" event will cancel the ajax request
40
+ beforeSend: function(xhr, settings) {
41
+ if (settings.dataType === undefined) {
42
+ xhr.setRequestHeader('accept', '*/*;q=0.5, ' + settings.accepts.script);
43
+ }
44
+ return fire(element, 'ajax:beforeSend', [xhr, settings]);
45
+ },
46
+ success: function(data, status, xhr) {
47
+ element.trigger('ajax:success', [data, status, xhr]);
48
+ },
49
+ complete: function(xhr, status) {
50
+ element.trigger('ajax:complete', [xhr, status]);
51
+ },
52
+ error: function(xhr, status, error) {
53
+ element.trigger('ajax:error', [xhr, status, error]);
54
+ }
55
+ });
56
+ }
57
+
58
+ // Handles "data-method" on links such as:
59
+ // <a href="/users/5" data-method="delete" rel="nofollow" data-confirm="Are you sure?">Delete</a>
60
+ function handleMethod(link) {
61
+ var href = link.attr('href'),
62
+ method = link.attr('data-method'),
63
+ csrf_token = $('meta[name=csrf-token]').attr('content'),
64
+ csrf_param = $('meta[name=csrf-param]').attr('content'),
65
+ form = $('<form method="post" action="' + href + '"></form>'),
66
+ metadata_input = '<input name="_method" value="' + method + '" type="hidden" />';
67
+
68
+ if (csrf_param !== undefined && csrf_token !== undefined) {
69
+ metadata_input += '<input name="' + csrf_param + '" value="' + csrf_token + '" type="hidden" />';
70
+ }
71
+
72
+ form.hide().append(metadata_input).appendTo('body');
73
+ form.submit();
74
+ }
75
+
76
+ function disableFormElements(form) {
77
+ form.find('input[data-disable-with]').each(function() {
78
+ var input = $(this);
79
+ input.data('ujs:enable-with', input.val())
80
+ .val(input.attr('data-disable-with'))
81
+ .attr('disabled', 'disabled');
82
+ });
83
+ }
84
+
85
+ function enableFormElements(form) {
86
+ form.find('input[data-disable-with]').each(function() {
87
+ var input = $(this);
88
+ input.val(input.data('ujs:enable-with')).removeAttr('disabled');
89
+ });
90
+ }
91
+
92
+ function allowAction(element) {
93
+ var message = element.attr('data-confirm');
94
+ return !message || (fire(element, 'confirm') && confirm(message));
95
+ }
96
+
97
+ function requiredValuesMissing(form) {
98
+ var missing = false;
99
+ form.find('input[name][required]').each(function() {
100
+ if (!$(this).val()) missing = true;
101
+ });
102
+ return missing;
103
+ }
104
+
105
+ $('a[data-confirm], a[data-method], a[data-remote]').live('click.rails', function(e) {
106
+ var link = $(this);
107
+ if (!allowAction(link)) return false;
108
+
109
+ if (link.attr('data-remote') != undefined) {
110
+ handleRemote(link);
111
+ return false;
112
+ } else if (link.attr('data-method')) {
113
+ handleMethod(link);
114
+ return false;
115
+ }
116
+ });
117
+
118
+ $('form').live('submit.rails', function(e) {
119
+ var form = $(this), remote = form.attr('data-remote') != undefined;
120
+ if (!allowAction(form)) return false;
121
+
122
+ // skip other logic when required values are missing
123
+ if (requiredValuesMissing(form)) return !remote;
124
+
125
+ if (remote) {
126
+ handleRemote(form);
127
+ return false;
128
+ } else {
129
+ disableFormElements(form);
130
+ }
131
+ });
132
+
133
+ $('form input[type=submit], form button[type=submit], form button:not([type])').live('click.rails', function() {
134
+ var button = $(this);
135
+ if (!allowAction(button)) return false;
136
+ // register the pressed submit button
137
+ var name = button.attr('name'), data = name ? {name:name, value:button.val()} : null;
138
+ button.closest('form').data('ujs:submit-button', data);
139
+ });
140
+
141
+ $('form').live('ajax:beforeSend.rails', function(event) {
142
+ if (this == event.target) disableFormElements($(this));
143
+ });
144
+
145
+ $('form').live('ajax:complete.rails', function(event) {
146
+ if (this == event.target) enableFormElements($(this));
147
+ });
148
+ })( jQuery );