best_in_place 1.1.2 → 1.1.3

Sign up to get free protection for your applications and to get access to all the features.
data/.travis.yml CHANGED
@@ -1,5 +1,4 @@
1
1
  rvm:
2
- - 1.8.7
3
2
  - 1.9.2
4
3
  - 1.9.3
5
4
 
data/README.md CHANGED
@@ -61,6 +61,7 @@ Options:
61
61
  this field.
62
62
  - **:object_name**: Used for overriding the default params key used for the object (the data-object attribute). Useful for e.g. STI scenarios where best_in_place should post to a common controller for different models.
63
63
  - **:data**: Hash of custom data attributes to be added to span. Can be used to provide data to the ajax:success callback.
64
+ - **:classes**: Additional classes to apply to the best_in_place span. Accepts either a string or Array of strings
64
65
 
65
66
  ###best_in_place_if
66
67
  **best_in_place_if condition, object, field, OPTIONS**
@@ -189,6 +190,15 @@ The 'ajax:success' event is triggered upon success. Use bind:
189
190
 
190
191
  $('.best_in_place').bind("ajax:success", function(){$(this).closest('tr').effect('highlight'));});
191
192
 
193
+ To bind a callback that is specific to a particular field, use the 'classes' option in the helper method and
194
+ then bind to that class.
195
+
196
+ <%= best_in_place @user, :name, :classes => 'highlight_on_success' %>
197
+ <%= best_in_place @user, :mail, :classes => 'bounce_on_success' %>
198
+
199
+ $('.highlight_on_success').bind("ajax:success", function(){$(this).closest('tr').effect('highlight'));});
200
+ $('.bounce_on_success').bind("ajax:success", function(){$(this).closest('tr').effect('bounce'));});
201
+
192
202
  ### Providing data to the callback
193
203
 
194
204
  Use the :data option to add HTML5 data attributes to the best_in_place span. For example, in your view:
@@ -303,13 +313,12 @@ thanks to Rails 3.1. Just begin including the gem in your Gemfile:
303
313
 
304
314
  gem "best_in_place"
305
315
 
306
- After that, specify the use of the jquery, jquery.purr and best in place
316
+ After that, specify the use of the jquery and best in place
307
317
  javascripts in your application.js, and optionally specify jquery-ui if
308
318
  you want to use jQuery UI datepickers:
309
319
 
310
320
  //= require jquery
311
321
  //= require jquery-ui
312
- //= require jquery.purr
313
322
  //= require best_in_place
314
323
 
315
324
  If you want to use jQuery UI datepickers, you should also install and
@@ -340,7 +349,6 @@ After that, install and load all the javascripts from the folder
340
349
  **/public/javascripts** in your layouts. They have to be in the order:
341
350
 
342
351
  * jquery
343
- * jquery.purr
344
352
  * **best_in_place**
345
353
 
346
354
  You can automatize this installation by doing
@@ -360,6 +368,27 @@ Finally, as for Rails 3.1, just add a binding to prepare all best in place field
360
368
 
361
369
  ---
362
370
 
371
+ ## Notification
372
+
373
+ Sometimes your in-place updates will fail due to validation or for some other reason. In such case, you'll want to notify the user somehow. **Best in Place** supports doing so through the best_in_place:error event, and has built-in support for notification via jquery.purr, right out of the box.
374
+
375
+ To opt into the jquery.purr error notification, just add best_in_place.purr to your javascripts, as described below. If you'd like to develop your own custom form of error notification, you can use best_in_place.purr as an example to guide you.
376
+
377
+ ###Rails 3.1 and higher
378
+
379
+ It's as simple as adding:
380
+
381
+ //= require best_in_place.purr
382
+
383
+ ###Rails 3.0 and lower
384
+
385
+ You'll have to load the following additional javascripts, in this order, after loading jquery and **best_in_place**:
386
+
387
+ * jquery.purr
388
+ * **best_in_place.purr**
389
+
390
+ ---
391
+
363
392
  ## Security
364
393
 
365
394
  If the script is used with the Rails Gem no html tags will be allowed unless the sanitize option is set to true, in that case only the tags [*b i u s a strong em p h1 h2 h3 h4 h5 ul li ol hr pre span img*] will be allowed. If the script is used without the gem and with frameworks other than Rails, then you should make sure you are providing the csrf authenticity params as meta tags and you should always escape undesired html tags such as script, object and so forth.
@@ -23,6 +23,6 @@ Gem::Specification.new do |s|
23
23
  s.add_dependency "jquery-rails"
24
24
 
25
25
  s.add_development_dependency "rspec-rails", "~> 2.8.0"
26
- s.add_development_dependency "nokogiri", ">= 1.5.0"
27
- s.add_development_dependency "capybara", ">= 1.0.1"
26
+ s.add_development_dependency "nokogiri"
27
+ s.add_development_dependency "capybara", "~> 1.1.2"
28
28
  end
@@ -59,6 +59,11 @@ BestInPlaceEditor.prototype = {
59
59
  },
60
60
 
61
61
  abortIfConfirm : function () {
62
+ if (!this.useConfirm) {
63
+ this.abort();
64
+ return;
65
+ }
66
+
62
67
  if (confirm("Are you sure you want to discard your changes?")) {
63
68
  this.abort();
64
69
  }
@@ -90,7 +95,7 @@ BestInPlaceEditor.prototype = {
90
95
  } else if (this.formType == "checkbox") {
91
96
  editor.element.html(this.getValue() ? this.values[1] : this.values[0]);
92
97
  } else {
93
- editor.element.html(this.getValue() != "" ? this.getValue() : this.nil);
98
+ editor.element.html(this.getValue() !== "" ? this.getValue() : this.nil);
94
99
  }
95
100
  editor.element.trigger(jQuery.Event("best_in_place:update"));
96
101
  },
@@ -105,18 +110,19 @@ BestInPlaceEditor.prototype = {
105
110
  // Try parent supplied info
106
111
  var self = this;
107
112
  self.element.parents().each(function(){
108
- self.url = self.url || jQuery(this).attr("data-url");
109
- self.collection = self.collection || jQuery(this).attr("data-collection");
110
- self.formType = self.formType || jQuery(this).attr("data-type");
111
- self.objectName = self.objectName || jQuery(this).attr("data-object");
112
- self.attributeName = self.attributeName || jQuery(this).attr("data-attribute");
113
- self.activator = self.activator || jQuery(this).attr("data-activator");
114
- self.okButton = self.okButton || jQuery(this).attr("data-ok-button");
115
- self.cancelButton = self.cancelButton || jQuery(this).attr("data-cancel-button");
116
- self.nil = self.nil || jQuery(this).attr("data-nil");
117
- self.inner_class = self.inner_class || jQuery(this).attr("data-inner-class");
118
- self.html_attrs = self.html_attrs || jQuery(this).attr("data-html-attrs");
119
- self.original_content = self.original_content || jQuery(this).attr("data-original-content");
113
+ $parent = jQuery(this);
114
+ self.url = self.url || $parent.attr("data-url");
115
+ self.collection = self.collection || $parent.attr("data-collection");
116
+ self.formType = self.formType || $parent.attr("data-type");
117
+ self.objectName = self.objectName || $parent.attr("data-object");
118
+ self.attributeName = self.attributeName || $parent.attr("data-attribute");
119
+ self.activator = self.activator || $parent.attr("data-activator");
120
+ self.okButton = self.okButton || $parent.attr("data-ok-button");
121
+ self.cancelButton = self.cancelButton || $parent.attr("data-cancel-button");
122
+ self.nil = self.nil || $parent.attr("data-nil");
123
+ self.inner_class = self.inner_class || $parent.attr("data-inner-class");
124
+ self.html_attrs = self.html_attrs || $parent.attr("data-html-attrs");
125
+ self.original_content = self.original_content || $parent.attr("data-original-content");
120
126
  });
121
127
 
122
128
  // Try Rails-id based if parents did not explicitly supply something
@@ -148,6 +154,12 @@ BestInPlaceEditor.prototype = {
148
154
  self.sanitize = (self.element.attr("data-sanitize") == "true");
149
155
  }
150
156
 
157
+ if (!self.element.attr("data-use-confirm")) {
158
+ self.useConfirm = true;
159
+ } else {
160
+ self.useConfirm = (self.element.attr("data-use-confirm") != "false");
161
+ }
162
+
151
163
  if ((self.formType == "select" || self.formType == "checkbox") && self.collection !== null)
152
164
  {
153
165
  self.values = jQuery.parseJSON(self.collection);
@@ -160,10 +172,10 @@ BestInPlaceEditor.prototype = {
160
172
  },
161
173
 
162
174
  initNil: function() {
163
- if (this.element.html() == "")
175
+ if (this.element.html() === "")
164
176
  {
165
- this.isNil = true
166
- this.element.html(this.nil)
177
+ this.isNil = true;
178
+ this.element.html(this.nil);
167
179
  }
168
180
  },
169
181
 
@@ -207,7 +219,7 @@ BestInPlaceEditor.prototype = {
207
219
 
208
220
  loadSuccessCallback : function(data) {
209
221
  var response = jQuery.parseJSON(jQuery.trim(data));
210
- if (response != null && response.hasOwnProperty("display_as")) {
222
+ if (response !== null && response.hasOwnProperty("display_as")) {
211
223
  this.element.attr("data-original-content", this.element.html());
212
224
  this.original_content = this.element.html();
213
225
  this.element.html(response["display_as"]);
@@ -222,12 +234,7 @@ BestInPlaceEditor.prototype = {
222
234
  loadErrorCallback : function(request, error) {
223
235
  this.element.html(this.oldValue);
224
236
 
225
- // Display all error messages from server side validation
226
- jQuery.each(jQuery.parseJSON(request.responseText), function(index, value) {
227
- if( typeof(value) == "object") {value = index + " " + value.toString(); }
228
- var container = jQuery("<span class='flash-error'></span>").html(value);
229
- container.purr();
230
- });
237
+ this.element.trigger(jQuery.Event("best_in_place:error"), [request, error])
231
238
  this.element.trigger(jQuery.Event("ajax:error"));
232
239
 
233
240
  // Binding back after being clicked
@@ -258,25 +265,39 @@ BestInPlaceEditor.prototype = {
258
265
  BestInPlaceEditor.forms = {
259
266
  "input" : {
260
267
  activateForm : function() {
261
- var output = '<form class="form_in_place" action="javascript:void(0)" style="display:inline;">';
262
- output += '<input type="text" name="'+ this.attributeName + '" value="' + this.sanitizeValue(this.display_value) + '"';
263
- if (this.inner_class != null) {
264
- output += ' class="' + this.inner_class + '"';
268
+ var output = $(document.createElement('form'))
269
+ .addClass('form_in_place')
270
+ .attr('action', 'javascript:void(0);')
271
+ .attr('style', 'display:inline');
272
+ var input_elt = $(document.createElement('input'))
273
+ .attr('type', 'text')
274
+ .attr('name', this.attributeName)
275
+ .val(this.display_value);
276
+ if(this.inner_class !== null) {
277
+ input_elt.addClass(this.inner_class);
265
278
  }
266
- output += '>';
267
- if (this.okButton) {
268
- output += '<input type="submit" value="' + this.okButton + '" />'
279
+ output.append(input_elt);
280
+ if(this.okButton) {
281
+ output.append(
282
+ $(document.createElement('input'))
283
+ .attr('type', 'submit')
284
+ .attr('value', this.okButton)
285
+ )
269
286
  }
270
- if (this.cancelButton) {
271
- output += '<input type="button" value="' + this.cancelButton + '" />'
287
+ if(this.cancelButton) {
288
+ output.append(
289
+ $(document.createElement('input'))
290
+ .attr('type', 'button')
291
+ .attr('value', this.cancelButton)
292
+ )
272
293
  }
273
- output += '</form>';
294
+
274
295
  this.element.html(output);
275
296
  this.setHtmlAttributes();
276
297
  this.element.find("input[type='text']")[0].select();
277
298
  this.element.find("form").bind('submit', {editor: this}, BestInPlaceEditor.forms.input.submitHandler);
278
299
  if (this.cancelButton) {
279
- this.element.find("input[type='button']").bind('click', {editor: this}, BestInPlaceEditor.forms.input.cancelButtonHandler)
300
+ this.element.find("input[type='button']").bind('click', {editor: this}, BestInPlaceEditor.forms.input.cancelButtonHandler);
280
301
  }
281
302
  this.element.find("input[type='text']").bind('blur', {editor: this}, BestInPlaceEditor.forms.input.inputBlurHandler);
282
303
  this.element.find("input[type='text']").bind('keyup', {editor: this}, BestInPlaceEditor.forms.input.keyupHandler);
@@ -331,13 +352,20 @@ BestInPlaceEditor.forms = {
331
352
 
332
353
  "date" : {
333
354
  activateForm : function() {
334
- var that = this,
335
- output = '<form class="form_in_place" action="javascript:void(0)" style="display:inline;">';
336
- output += '<input type="text" name="'+ this.attributeName + '" value="' + this.sanitizeValue(this.display_value) + '"';
337
- if (this.inner_class != null) {
338
- output += ' class="' + this.inner_class + '"';
355
+ var that = this,
356
+ output = $(document.createElement('form'))
357
+ .addClass('form_in_place')
358
+ .attr('action', 'javascript:void(0);')
359
+ .attr('style', 'display:inline'),
360
+ input_elt = $(document.createElement('input'))
361
+ .attr('type', 'text')
362
+ .attr('name', this.attributeName)
363
+ .attr('value', this.sanitizeValue(this.display_value));
364
+ if(this.inner_class !== null) {
365
+ input_elt.addClass(this.inner_class);
339
366
  }
340
- output += '></form>'
367
+ output.append(input_elt)
368
+
341
369
  this.element.html(output);
342
370
  this.setHtmlAttributes();
343
371
  this.element.find('input')[0].select();
@@ -370,14 +398,24 @@ BestInPlaceEditor.forms = {
370
398
 
371
399
  "select" : {
372
400
  activateForm : function() {
373
- var output = "<form action='javascript:void(0)' style='display:inline;'><select>";
374
- var selected = "";
375
- var oldValue = this.oldValue;
376
- jQuery.each(this.values, function(index, value) {
377
- selected = (value[1] == oldValue ? "selected='selected'" : "");
378
- output += "<option value='" + value[0] + "' " + selected + ">" + value[1] + "</option>";
379
- });
380
- output += "</select></form>";
401
+ var output = $(document.createElement('form'))
402
+ .attr('action', 'javascript:void(0)')
403
+ .attr('style', 'display:inline');
404
+ selected = '',
405
+ oldValue = this.oldValue,
406
+ select_elt = $(document.createElement('select'));
407
+ jQuery.each(this.values, function (index, value) {
408
+ var option_elt = $(document.createElement('option'))
409
+ // .attr('value', value[0])
410
+ .val(value[0])
411
+ .html(value[1]);
412
+ if(value[1] == oldValue) {
413
+ option_elt.attr('selected', 'selected');
414
+ }
415
+ select_elt.append(option_elt);
416
+ });
417
+ output.append(select_elt);
418
+
381
419
  this.element.html(output);
382
420
  this.setHtmlAttributes();
383
421
  this.element.find("select").bind('change', {editor: this}, BestInPlaceEditor.forms.select.blurHandler);
@@ -388,6 +426,7 @@ BestInPlaceEditor.forms = {
388
426
 
389
427
  getValue : function() {
390
428
  return this.sanitizeValue(this.element.find("select").val());
429
+ // return this.element.find("select").val();
391
430
  },
392
431
 
393
432
  blurHandler : function(event) {
@@ -401,7 +440,7 @@ BestInPlaceEditor.forms = {
401
440
 
402
441
  "checkbox" : {
403
442
  activateForm : function() {
404
- var newValue = Boolean(this.oldValue != this.values[1]);
443
+ var newValue = Boolean(this.oldValue.toLowerCase() != this.values[1].toLowerCase());
405
444
  var output = newValue ? this.values[1] : this.values[0];
406
445
  this.element.html(output);
407
446
  this.setHtmlAttributes();
@@ -409,7 +448,7 @@ BestInPlaceEditor.forms = {
409
448
  },
410
449
 
411
450
  getValue : function() {
412
- return Boolean(this.element.html() == this.values[1]);
451
+ return Boolean(this.element.html().toLowerCase() == this.values[1].toLowerCase());
413
452
  }
414
453
  },
415
454
 
@@ -418,18 +457,28 @@ BestInPlaceEditor.forms = {
418
457
  // grab width and height of text
419
458
  width = this.element.css('width');
420
459
  height = this.element.css('height');
421
-
422
- // construct the form
423
- var output = '<form action="javascript:void(0)" style="display:inline;"><textarea>';
424
- output += this.sanitizeValue(this.display_value);
425
- output += '</textarea>';
426
- if (this.okButton) {
427
- output += '<input type="submit" value="' + this.okButton + '" />'
460
+
461
+ // construct form
462
+ var output = $(document.createElement('form'))
463
+ .attr('action', 'javascript:void(0)')
464
+ .attr('style', 'display:inline')
465
+ .append($(document.createElement('textarea'))
466
+ .val(this.sanitizeValue(this.display_value)));
467
+ if(this.okButton) {
468
+ output.append(
469
+ $(document.createElement('input'))
470
+ .attr('type', 'submit')
471
+ .attr('value', this.okButton)
472
+ );
428
473
  }
429
- if (this.cancelButton) {
430
- output += '<input type="button" value="' + this.cancelButton + '" />'
474
+ if(this.cancelButton) {
475
+ output.append(
476
+ $(document.createElement('input'))
477
+ .attr('type', 'button')
478
+ .attr('value', this.cancelButton)
479
+ )
431
480
  }
432
- output += '</form>';
481
+
433
482
  this.element.html(output);
434
483
  this.setHtmlAttributes();
435
484
 
@@ -440,7 +489,7 @@ BestInPlaceEditor.forms = {
440
489
  this.element.find("textarea")[0].focus();
441
490
  this.element.find("form").bind('submit', {editor: this}, BestInPlaceEditor.forms.textarea.submitHandler);
442
491
  if (this.cancelButton) {
443
- this.element.find("input[type='button']").bind('click', {editor: this}, BestInPlaceEditor.forms.textarea.cancelButtonHandler)
492
+ this.element.find("input[type='button']").bind('click', {editor: this}, BestInPlaceEditor.forms.textarea.cancelButtonHandler);
444
493
  }
445
494
  this.element.find("textarea").bind('blur', {editor: this}, BestInPlaceEditor.forms.textarea.blurHandler);
446
495
  this.element.find("textarea").bind('keyup', {editor: this}, BestInPlaceEditor.forms.textarea.keyupHandler);
@@ -570,7 +619,7 @@ jQuery.fn.best_in_place = function() {
570
619
  $twin.appendTo($textarea.parent());
571
620
 
572
621
  // Copy the essential styles (mimics) from the textarea to the twin
573
- var i = mimics.length;
622
+ i = mimics.length;
574
623
  while(i--){
575
624
  $twin.css(mimics[i].toString(),$textarea.css(mimics[i].toString()));
576
625
  }
@@ -0,0 +1,10 @@
1
+ //= require jquery.purr
2
+
3
+ $(document).on('best_in_place:error', function(event, request, error) {
4
+ // Display all error messages from server side validation
5
+ jQuery.each(jQuery.parseJSON(request.responseText), function(index, value) {
6
+ if( typeof(value) == "object") {value = index + " " + value.toString(); }
7
+ var container = jQuery("<span class='flash-error'></span>").html(value);
8
+ container.purr();
9
+ });
10
+ });
@@ -6,7 +6,11 @@ module BestInPlace
6
6
 
7
7
  private
8
8
  def respond_bip_ok(obj)
9
- klass = obj.class.to_s
9
+ if obj.respond_to?(:id)
10
+ klass = "#{obj.class}_#{obj.id}"
11
+ else
12
+ klass = obj.class.to_s
13
+ end
10
14
  param_key = BestInPlace::Utils.object_to_key(obj)
11
15
  updating_attr = params[param_key].keys.first
12
16
 
@@ -14,6 +14,8 @@ module BestInPlace
14
14
  BestInPlace::ViewHelpers.send(opts[:method], object.send(opts[:attr]))
15
15
  end
16
16
  {:display_as => value}.to_json
17
+ when :proc
18
+ {:display_as => opts[:proc].call(object.send(opts[:attr]))}.to_json
17
19
  else
18
20
  {}.to_json
19
21
  end
@@ -34,5 +36,9 @@ module BestInPlace
34
36
  def add_helper_method(klass, attr, helper_method, helper_options = nil)
35
37
  @@table[klass.to_s][attr.to_s] = Renderer.new :method => helper_method.to_sym, :type => :helper, :attr => attr, :helper_options => helper_options
36
38
  end
39
+
40
+ def add_helper_proc(klass, attr, helper_proc)
41
+ @@table[klass.to_s][attr.to_s] = Renderer.new :type => :proc, :attr => attr, :proc => helper_proc
42
+ end
37
43
  end
38
44
  end
@@ -10,7 +10,7 @@ module BestInPlace
10
10
  raise ArgumentError, "Can't find helper #{opts[:display_with]}"
11
11
  end
12
12
 
13
- real_object = (object.is_a?(Array) && object.last.class.respond_to?(:model_name)) ? object.last : object
13
+ real_object = real_object_for object
14
14
  opts[:type] ||= :input
15
15
  opts[:collection] ||= []
16
16
  field = field.to_s
@@ -20,7 +20,7 @@ module BestInPlace
20
20
  collection = nil
21
21
  if opts[:type] == :select && !opts[:collection].blank?
22
22
  v = real_object.send(field)
23
- value = Hash[opts[:collection]][!!(v =~ /^[0-9]+$/) ? v.to_i : v]
23
+ value = Hash[opts[:collection]].stringify_keys[v.to_s]
24
24
  collection = opts[:collection].to_json
25
25
  end
26
26
  if opts[:type] == :checkbox
@@ -31,7 +31,13 @@ module BestInPlace
31
31
  value = fieldValue ? opts[:collection][1] : opts[:collection][0]
32
32
  collection = opts[:collection].to_json
33
33
  end
34
- out = "<span class='best_in_place'"
34
+ classes = ["best_in_place"]
35
+ unless opts[:classes].nil?
36
+ # the next three lines enable this opt to handle both a stings and a arrays
37
+ classes << opts[:classes]
38
+ classes.flatten!
39
+ end
40
+ out = "<span class='#{classes.join(" ")}'"
35
41
  out << " id='#{BestInPlace::Utils.build_best_in_place_id(real_object, field)}'"
36
42
  out << " data-url='#{opts[:path].blank? ? url_for(object) : url_for(opts[:path])}'"
37
43
  out << " data-object='#{opts[:object_name] || BestInPlace::Utils.object_to_key(real_object)}'"
@@ -41,6 +47,7 @@ module BestInPlace
41
47
  out << " data-ok-button='#{opts[:ok_button]}'" unless opts[:ok_button].blank?
42
48
  out << " data-cancel-button='#{opts[:cancel_button]}'" unless opts[:cancel_button].blank?
43
49
  out << " data-nil='#{opts[:nil]}'" unless opts[:nil].blank?
50
+ out << " data-use-confirm='#{opts[:use_confirm]}'" unless opts[:use_confirm].nil?
44
51
  out << " data-type='#{opts[:type]}'"
45
52
  out << " data-inner-class='#{opts[:inner_class]}'" if opts[:inner_class]
46
53
  out << " data-html-attrs='#{opts[:html_attrs].to_json}'" unless opts[:html_attrs].blank?
@@ -55,9 +62,9 @@ module BestInPlace
55
62
  end
56
63
  if !opts[:sanitize].nil? && !opts[:sanitize]
57
64
  out << " data-sanitize='false'>"
58
- out << sanitize(value, :tags => %w(b i u s a strong em p h1 h2 h3 h4 h5 ul li ol hr pre span img br), :attributes => %w(id class href))
65
+ out << sanitize(value.to_s, :tags => %w(b i u s a strong em p h1 h2 h3 h4 h5 ul li ol hr pre span img br), :attributes => %w(id class href))
59
66
  else
60
- out << ">#{sanitize(value, :tags => nil, :attributes => nil)}"
67
+ out << ">#{sanitize(value.to_s, :tags => nil, :attributes => nil)}"
61
68
  end
62
69
  out << "</span>"
63
70
  raw out
@@ -67,7 +74,7 @@ module BestInPlace
67
74
  if condition
68
75
  best_in_place(object, field, opts)
69
76
  else
70
- build_value_for object, field, opts
77
+ build_value_for real_object_for(object), field, opts
71
78
  end
72
79
  end
73
80
 
@@ -75,15 +82,20 @@ module BestInPlace
75
82
  def build_value_for(object, field, opts)
76
83
  return "" if object.send(field).blank?
77
84
 
85
+ if (object.respond_to?(:id))
86
+ klass = "#{object.class}_#{object.id}"
87
+ else
88
+ klass = object.class.to_s
89
+ end
78
90
  if opts[:display_as]
79
- BestInPlace::DisplayMethods.add_model_method(object.class.to_s, field, opts[:display_as])
91
+ BestInPlace::DisplayMethods.add_model_method(klass, field, opts[:display_as])
80
92
  object.send(opts[:display_as]).to_s
81
93
 
82
94
  elsif opts[:display_with].try(:is_a?, Proc)
95
+ BestInPlace::DisplayMethods.add_helper_proc(klass, field, opts[:display_with])
83
96
  opts[:display_with].call(object.send(field))
84
-
85
97
  elsif opts[:display_with]
86
- BestInPlace::DisplayMethods.add_helper_method(object.class.to_s, field, opts[:display_with], opts[:helper_options])
98
+ BestInPlace::DisplayMethods.add_helper_method(klass, field, opts[:display_with], opts[:helper_options])
87
99
  if opts[:helper_options]
88
100
  BestInPlace::ViewHelpers.send(opts[:display_with], object.send(field), opts[:helper_options])
89
101
  else
@@ -101,7 +113,11 @@ module BestInPlace
101
113
  data.to_s.
102
114
  gsub("&", "&amp;").
103
115
  gsub("'", "&apos;").
104
- gsub("\n", "&#10;")
116
+ gsub(/\r?\n/, "&#10;")
117
+ end
118
+
119
+ def real_object_for(object)
120
+ (object.is_a?(Array) && object.last.class.respond_to?(:model_name)) ? object.last : object
105
121
  end
106
122
  end
107
123
  end
@@ -1,3 +1,3 @@
1
1
  module BestInPlace
2
- VERSION = "1.1.2"
2
+ VERSION = "1.1.3"
3
3
  end
@@ -7,6 +7,7 @@ describe BestInPlace::BestInPlaceHelpers do
7
7
  @user = User.new :name => "Lucia",
8
8
  :last_name => "Napoli",
9
9
  :email => "lucianapoli@gmail.com",
10
+ :height => "5' 5\"",
10
11
  :address => "Via Roma 99",
11
12
  :zip => "25123",
12
13
  :country => "2",
@@ -78,6 +79,10 @@ describe BestInPlace::BestInPlaceHelpers do
78
79
  @span.attribute("data-cancel-button").should be_nil
79
80
  end
80
81
 
82
+ it "should have no Use-Confirmation dialog option by default" do
83
+ @span.attribute("data-use-confirm").should be_nil
84
+ end
85
+
81
86
  it "should have no inner_class by default" do
82
87
  @span.attribute("data-inner-class").should be_nil
83
88
  end
@@ -160,6 +165,13 @@ describe BestInPlace::BestInPlaceHelpers do
160
165
  span.attribute("data-cancel-button").value.should == "nasty"
161
166
  end
162
167
 
168
+ it "should have the given Use-Confirmation dialog option" do
169
+ out = helper.best_in_place @user, :name, :use_confirm => "false"
170
+ nk = Nokogiri::HTML.parse(out)
171
+ span = nk.css("span")
172
+ span.attribute("data-use-confirm").value.should == "false"
173
+ end
174
+
163
175
  describe "object_name" do
164
176
  it "should change the data-object value" do
165
177
  out = helper.best_in_place @user, :name, :object_name => "my_user"
@@ -213,6 +225,14 @@ describe BestInPlace::BestInPlaceHelpers do
213
225
  span.text.should == "º150.00"
214
226
  end
215
227
  end
228
+
229
+ describe "array-like objects" do
230
+ it "should work with array-like objects in order to provide support to namespaces" do
231
+ nk = Nokogiri::HTML.parse(helper.best_in_place [:admin, @user], :name)
232
+ span = nk.css("span")
233
+ span.text.should == "Lucia"
234
+ end
235
+ end
216
236
  end
217
237
 
218
238
  context "with a text field attribute" do
@@ -324,34 +344,58 @@ describe BestInPlace::BestInPlaceHelpers do
324
344
 
325
345
  describe "#best_in_place_if" do
326
346
  context "when the parameters are valid" do
327
- before(:each) do
328
- @output = "Some Value"
329
- @field = :somefield
330
- @object = mock("object", @field => @output)
347
+ before do
348
+ @user = User.new :name => "Lucia",
349
+ :last_name => "Napoli",
350
+ :email => "lucianapoli@gmail.com",
351
+ :height => "5' 5\"",
352
+ :address => "Via Roma 99",
353
+ :zip => "25123",
354
+ :country => "2",
355
+ :receive_email => false,
356
+ :birth_date => Time.now.utc.to_date,
357
+ :description => "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus a lectus et lacus ultrices auctor. Morbi aliquet convallis tincidunt. Praesent enim libero, iaculis at commodo nec, fermentum a dolor. Quisque eget eros id felis lacinia faucibus feugiat et ante. Aenean justo nisi, aliquam vel egestas vel, porta in ligula. Etiam molestie, lacus eget tincidunt accumsan, elit justo rhoncus urna, nec pretium neque mi et lorem. Aliquam posuere, dolor quis pulvinar luctus, felis dolor tincidunt leo, eget pretium orci purus ac nibh. Ut enim sem, suscipit ac elementum vitae, sodales vel sem.",
358
+ :money => 150
331
359
  @options = {}
332
360
  end
361
+
333
362
  context "when the condition is true" do
334
363
  before {@condition = true}
364
+
365
+ it "should work with array-like objects in order to provide support to namespaces" do
366
+ nk = Nokogiri::HTML.parse(helper.best_in_place_if @condition, [:admin, @user], :name)
367
+ span = nk.css("span")
368
+ span.text.should == "Lucia"
369
+ end
370
+
335
371
  context "when the options parameter is left off" do
336
372
  it "should call best_in_place with the rest of the parameters and empty options" do
337
- helper.should_receive(:best_in_place).with(@object, @field, {})
338
- helper.best_in_place_if @condition, @object, @field
373
+ helper.should_receive(:best_in_place).with(@user, :name, {})
374
+ helper.best_in_place_if @condition, @user, :name
339
375
  end
340
376
  end
377
+
341
378
  context "when the options parameter is included" do
342
379
  it "should call best_in_place with the rest of the parameters" do
343
- helper.should_receive(:best_in_place).with(@object, @field, @options)
344
- helper.best_in_place_if @condition, @object, @field, @options
380
+ helper.should_receive(:best_in_place).with(@user, :name, @options)
381
+ helper.best_in_place_if @condition, @user, :name, @options
345
382
  end
346
383
  end
347
384
  end
385
+
348
386
  context "when the condition is false" do
349
387
  before {@condition = false}
388
+
389
+ it "should work with array-like objects in order to provide support to namespaces" do
390
+ helper.best_in_place_if(@condition, [:admin, @user], :name).should eq "Lucia"
391
+ end
392
+
350
393
  it "should return the value of the field when the options value is left off" do
351
- helper.best_in_place_if(@condition, @object, @field).should eq @output
394
+ helper.best_in_place_if(@condition, @user, :name).should eq "Lucia"
352
395
  end
396
+
353
397
  it "should return the value of the field when the options value is included" do
354
- helper.best_in_place_if(@condition, @object, @field, @options).should eq @output
398
+ helper.best_in_place_if(@condition, @user, :name, @options).should eq "Lucia"
355
399
  end
356
400
  end
357
401
  end
@@ -6,6 +6,7 @@ describe "Double initialization bug", :js => true do
6
6
  @user = User.new :name => "Lucia",
7
7
  :last_name => "Napoli",
8
8
  :email => "lucianapoli@gmail.com",
9
+ :height => "5' 5\"",
9
10
  :address => "Via Roma 99",
10
11
  :zip => "25123",
11
12
  :country => "2",
@@ -6,6 +6,7 @@ describe "JS behaviour", :js => true do
6
6
  @user = User.new :name => "Lucia",
7
7
  :last_name => "Napoli",
8
8
  :email => "lucianapoli@gmail.com",
9
+ :height => "5' 5\"",
9
10
  :address => "Via Roma 99",
10
11
  :zip => "25123",
11
12
  :country => "2",
@@ -13,9 +14,11 @@ describe "JS behaviour", :js => true do
13
14
  :birth_date => Time.now.utc,
14
15
  :description => "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus a lectus et lacus ultrices auctor. Morbi aliquet convallis tincidunt. Praesent enim libero, iaculis at commodo nec, fermentum a dolor. Quisque eget eros id felis lacinia faucibus feugiat et ante. Aenean justo nisi, aliquam vel egestas vel, porta in ligula. Etiam molestie, lacus eget tincidunt accumsan, elit justo rhoncus urna, nec pretium neque mi et lorem. Aliquam posuere, dolor quis pulvinar luctus, felis dolor tincidunt leo, eget pretium orci purus ac nibh. Ut enim sem, suscipit ac elementum vitae, sodales vel sem.",
15
16
  :money => 100,
17
+ :money_proc => 100,
16
18
  :favorite_color => 'Red',
17
19
  :favorite_books => "The City of Gold and Lead",
18
- :description => "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus a lectus et lacus ultrices auctor. Morbi aliquet convallis tincidunt. Praesent enim libero, iaculis at commodo nec, fermentum a dolor. Quisque eget eros id felis lacinia faucibus feugiat et ante. Aenean justo nisi, aliquam vel egestas vel, porta in ligula. Etiam molestie, lacus eget tincidunt accumsan, elit justo rhoncus urna, nec pretium neque mi et lorem. Aliquam posuere, dolor quis pulvinar luctus, felis dolor tincidunt leo, eget pretium orci purus ac nibh. Ut enim sem, suscipit ac elementum vitae, sodales vel sem."
20
+ :description => "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus a lectus et lacus ultrices auctor. Morbi aliquet convallis tincidunt. Praesent enim libero, iaculis at commodo nec, fermentum a dolor. Quisque eget eros id felis lacinia faucibus feugiat et ante. Aenean justo nisi, aliquam vel egestas vel, porta in ligula. Etiam molestie, lacus eget tincidunt accumsan, elit justo rhoncus urna, nec pretium neque mi et lorem. Aliquam posuere, dolor quis pulvinar luctus, felis dolor tincidunt leo, eget pretium orci purus ac nibh. Ut enim sem, suscipit ac elementum vitae, sodales vel sem.",
21
+ :favorite_movie => "The Hitchhiker's Guide to the Galaxy"
19
22
  end
20
23
 
21
24
  describe "namespaced controllers" do
@@ -64,6 +67,44 @@ describe "JS behaviour", :js => true do
64
67
  end
65
68
  end
66
69
 
70
+ it "should be able to update last but one item in list" do
71
+ @user.save!
72
+ @user2 = User.create :name => "Test",
73
+ :last_name => "User",
74
+ :email => "test@example.com",
75
+ :height => "5' 5\"",
76
+ :address => "Via Roma 99",
77
+ :zip => "25123",
78
+ :country => "2",
79
+ :receive_email => false,
80
+ :birth_date => Time.now.utc,
81
+ :description => "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus a lectus et lacus ultrices auctor. Morbi aliquet convallis tincidunt. Praesent enim libero, iaculis at commodo nec, fermentum a dolor. Quisque eget eros id felis lacinia faucibus feugiat et ante. Aenean justo nisi, aliquam vel egestas vel, porta in ligula. Etiam molestie, lacus eget tincidunt accumsan, elit justo rhoncus urna, nec pretium neque mi et lorem. Aliquam posuere, dolor quis pulvinar luctus, felis dolor tincidunt leo, eget pretium orci purus ac nibh. Ut enim sem, suscipit ac elementum vitae, sodales vel sem.",
82
+ :money => 100,
83
+ :money_proc => 100,
84
+ :favorite_color => 'Red',
85
+ :favorite_books => "The City of Gold and Lead",
86
+ :description => "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus a lectus et lacus ultrices auctor. Morbi aliquet convallis tincidunt. Praesent enim libero, iaculis at commodo nec, fermentum a dolor. Quisque eget eros id felis lacinia faucibus feugiat et ante. Aenean justo nisi, aliquam vel egestas vel, porta in ligula. Etiam molestie, lacus eget tincidunt accumsan, elit justo rhoncus urna, nec pretium neque mi et lorem. Aliquam posuere, dolor quis pulvinar luctus, felis dolor tincidunt leo, eget pretium orci purus ac nibh. Ut enim sem, suscipit ac elementum vitae, sodales vel sem."
87
+
88
+ visit users_path
89
+ within("tr#user_#{@user.id} > .name > span") do
90
+ page.should have_content("Lucia")
91
+ page.should have_xpath("//a[contains(@href,'#{user_path(@user)}')]")
92
+ end
93
+
94
+ id = BestInPlace::Utils.build_best_in_place_id @user, :name
95
+ page.execute_script <<-JS
96
+ $("#edit_#{@user.id}").click();
97
+ $("##{id} input[name='name']").val('Lisa');
98
+ $("##{id} form").submit();
99
+ JS
100
+ # binding.pry
101
+ # visit users_path
102
+ within("tr#user_#{@user.id} > .name > span") do
103
+ page.should have_content('Lisa')
104
+ page.should have_xpath("//a[contains(@href,'#{user_path(@user)}')]")
105
+ end
106
+ end
107
+
67
108
  it "should be able to use bip_text to update a text field" do
68
109
  @user.save!
69
110
  visit user_path(@user)
@@ -247,6 +288,23 @@ describe "JS behaviour", :js => true do
247
288
  end
248
289
  end
249
290
 
291
+ it "should not ask for confirmation on cancel if it is switched off" do
292
+ @user.save!
293
+ visit user_path(@user)
294
+
295
+ id = BestInPlace::Utils.build_best_in_place_id @user, :favorite_movie
296
+ page.execute_script <<-JS
297
+ $("##{id}").click();
298
+ $("##{id} input[name='favorite_movie']").val('No good movie');
299
+ $("##{id} input[type='button']").click();
300
+ JS
301
+
302
+ lambda { page.driver.browser.switch_to.alert }.should raise_exception(Selenium::WebDriver::Error::NoAlertPresentError)
303
+ within("#favorite_movie") do
304
+ page.should have_content("The Hitchhiker's Guide to the Galaxy")
305
+ end
306
+ end
307
+
250
308
  it "should not submit input on blur if there's an OK button present" do
251
309
  @user.save!
252
310
  visit user_path(@user)
@@ -507,6 +565,18 @@ describe "JS behaviour", :js => true do
507
565
  end
508
566
  end
509
567
 
568
+ it "should let me use custom helpers with a lambda" do
569
+ @user.save!
570
+ visit user_path(@user)
571
+
572
+ page.should have_content("100.0 €")
573
+ bip_text @user, :money_custom, "250"
574
+
575
+ within("#money_custom") do
576
+ page.should have_content("250.0 €")
577
+ end
578
+ end
579
+
510
580
  it "should still show the custom format after an error" do
511
581
  @user.save!
512
582
  visit user_path(@user)
@@ -579,6 +649,70 @@ describe "JS behaviour", :js => true do
579
649
  within("#alt_money") { page.should have_content("€58.00") }
580
650
  end
581
651
 
652
+ describe "display_with using a lambda" do
653
+
654
+
655
+ it "should render the money" do
656
+ @user.save!
657
+ visit user_path(@user)
658
+
659
+ within("#money_proc") do
660
+ page.should have_content("$100.00")
661
+ end
662
+ end
663
+
664
+
665
+
666
+ it "should show the new value using the helper after a successful update" do
667
+ @user.save!
668
+ visit user_path(@user)
669
+
670
+ bip_text @user, :money_proc, "240"
671
+
672
+ within("#money_proc") do
673
+ page.should have_content("$240.00")
674
+ end
675
+ end
676
+
677
+ it "should display the original content when editing the form" do
678
+ @user.save!
679
+ retry_on_timeout do
680
+ visit user_path(@user)
681
+
682
+ id = BestInPlace::Utils.build_best_in_place_id @user, :money_proc
683
+ page.execute_script <<-JS
684
+ $("##{id}").click();
685
+ JS
686
+
687
+ text = page.find("##{id} input").value
688
+ text.should == "100.0"
689
+ end
690
+ end
691
+
692
+ it "should display the updated content after editing the field two consecutive times" do
693
+ @user.save!
694
+
695
+ retry_on_timeout do
696
+ visit user_path(@user)
697
+
698
+ bip_text @user, :money_proc, "40"
699
+
700
+ sleep 1
701
+
702
+ id = BestInPlace::Utils.build_best_in_place_id @user, :money_proc
703
+ page.execute_script <<-JS
704
+ $("##{id}").click();
705
+ JS
706
+
707
+ sleep 1
708
+
709
+ text = page.find("##{id} input").value
710
+ text.should == "40"
711
+ end
712
+ end
713
+
714
+ end
715
+
582
716
  end
583
717
 
584
718
  it "should display strings with quotes correctly in fields" do
@@ -610,4 +744,42 @@ describe "JS behaviour", :js => true do
610
744
  page.should have_link("link in this text", :href => "http://google.es")
611
745
  end
612
746
  end
747
+
748
+ it "should display single- and double-quotes in values appropriately" do
749
+ @user.height = %{5' 6"}
750
+ @user.save!
751
+
752
+ retry_on_timeout do
753
+ visit user_path(@user)
754
+
755
+ id = BestInPlace::Utils.build_best_in_place_id @user, :height
756
+ page.execute_script <<-JS
757
+ $("##{id}").click();
758
+ JS
759
+
760
+ page.find("##{id} select").value.should eq(%{5' 6"})
761
+ end
762
+ end
763
+
764
+ it "should save single- and double-quotes in values appropriately" do
765
+ @user.height = %{5' 10"}
766
+ @user.save!
767
+
768
+ retry_on_timeout do
769
+ visit user_path(@user)
770
+
771
+ id = BestInPlace::Utils.build_best_in_place_id @user, :height
772
+ page.execute_script <<-JS
773
+ $("##{id}").click();
774
+ $("##{id} select").val("5' 7\\\"");
775
+ $("##{id} select").blur();
776
+ JS
777
+
778
+ sleep 1
779
+
780
+ @user.reload
781
+ @user.height.should eq(%{5' 7"})
782
+ end
783
+ end
784
+
613
785
  end
@@ -6,6 +6,7 @@ describe "Monitor new fields", :js => true do
6
6
  @user = User.new :name => "Lucia",
7
7
  :last_name => "Napoli",
8
8
  :email => "lucianapoli@gmail.com",
9
+ :height => "5' 5\"",
9
10
  :address => "Via Roma 99",
10
11
  :zip => "25123",
11
12
  :country => "2",
@@ -6,6 +6,7 @@ describe "JS behaviour", :js => true do
6
6
  @user = User.new :name => "Lucia",
7
7
  :last_name => "Napoli",
8
8
  :email => "lucianapoli@gmail.com",
9
+ :height => "5' 5\"",
9
10
  :address => "Via Roma 99",
10
11
  :zip => "25123",
11
12
  :country => "2",
@@ -1,7 +1,7 @@
1
1
  //= require jquery
2
2
  //= require jquery-ui
3
3
  //= require best_in_place
4
- //= require jquery.purr
4
+ //= require best_in_place.purr
5
5
  //= require_self
6
6
 
7
7
  $(document).ready(function() {
@@ -1,2 +1,29 @@
1
+ #encoding: utf-8
1
2
  module UsersHelper
3
+ def height_collection
4
+ [
5
+ %{5' 1"} ,
6
+ %{5' 2"} ,
7
+ %{5' 3"} ,
8
+ %{5' 4"} ,
9
+ %{5' 5"} ,
10
+ %{5' 6"} ,
11
+ %{5' 7"} ,
12
+ %{5' 8"} ,
13
+ %{5' 9"} ,
14
+ %{5' 10"},
15
+ %{5' 11"},
16
+ %{6' 0"} ,
17
+ %{6' 1"} ,
18
+ %{6' 2"} ,
19
+ %{6' 3"} ,
20
+ %{6' 4"} ,
21
+ %{6' 5"} ,
22
+ %{6' 6"}
23
+ ]
24
+ end
25
+
26
+ def bb(value)
27
+ "#{value} €"
28
+ end
2
29
  end
@@ -13,6 +13,9 @@ class User < ActiveRecord::Base
13
13
  :format => {:with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i, :message => "has wrong email format"}
14
14
  validates :zip, :numericality => true, :length => { :minimum => 5 }
15
15
  validates_numericality_of :money, :allow_blank => true
16
+ validates_numericality_of :money_proc, :allow_blank => true
17
+
18
+ alias_attribute :money_custom, :money
16
19
 
17
20
  def address_format
18
21
  "<b>addr => [#{address}]</b>".html_safe
@@ -19,6 +19,10 @@
19
19
  <%= f.label :last_name %><br />
20
20
  <%= f.text_field :last_name %>
21
21
  </div>
22
+ <div class="field">
23
+ <%= f.label :height %><br />
24
+ <%= f.select :height, height_collection %>
25
+ </div>
22
26
  <div class="field">
23
27
  <%= f.label :address %><br />
24
28
  <%= f.text_field :address %>
@@ -2,14 +2,20 @@
2
2
 
3
3
  <table>
4
4
  <tr>
5
- <th>Name</th>
5
+ <th colspan="2">Name</th>
6
6
  <th>Last name</th>
7
7
  <th>Country</th>
8
8
  </tr>
9
9
 
10
10
  <% @users.each do |user| %>
11
- <tr>
12
- <td><%= link_to user.name, user %></td>
11
+ <tr id="user_<%= user.id %>">
12
+ <td class="name">
13
+ <%= best_in_place user, :name,
14
+ activator: "#edit_#{user.id}",
15
+ display_with: :link_to,
16
+ helper_options: user_path(user) %>
17
+ </td>
18
+ <td><small><a href="#" id="edit_<%= user.id %>">edit</a></small></td>
13
19
  <td><%= user.last_name %></td>
14
20
  <td><%= COUNTRIES[user.country.to_i] %></td>
15
21
  </tr>
@@ -16,6 +16,12 @@
16
16
  <%= best_in_place @user, :last_name, :nil => "Nothing to show" %>
17
17
  </td>
18
18
  </tr>
19
+ <tr>
20
+ <td>Height</td>
21
+ <td id="height">
22
+ <%= best_in_place @user, :height, :type => :select, :collection => height_collection.zip(height_collection), :sanitize => false %>
23
+ </td>
24
+ </tr>
19
25
  <tr>
20
26
  <td>Email</td>
21
27
  <td id="email">
@@ -86,6 +92,26 @@
86
92
  <%= best_in_place @user, :money, :display_with => :number_to_currency %>
87
93
  </td>
88
94
  </tr>
95
+ <tr>
96
+ <td>Money with proc</td>
97
+ <td id="money_proc">
98
+ <%= best_in_place @user, :money_proc, :display_with => lambda{ |v| number_to_currency(v) } %>
99
+ </td>
100
+ </tr>
101
+ <tr>
102
+ <td>Money with custom helper</td>
103
+ <td id="money_custom">
104
+ <%= best_in_place @user, :money_custom, :display_with => lambda { |x| bb(x) } %>
105
+ </td>
106
+ </tr>
107
+ <tr>
108
+ <td>Favorite Movie</td>
109
+ <td id="favorite_movie">
110
+ <%- opts = { :ok_button => 'Do it!', :cancel_button => 'Nope', :use_confirm => false } %>
111
+ <%- opts.delete(:ok_button) if params[:suppress_ok_button] %>
112
+ <%= best_in_place @user, :favorite_movie, opts %>
113
+ </td>
114
+ </tr>
89
115
  </table>
90
116
  <br />
91
117
  <hr />
@@ -0,0 +1,5 @@
1
+ class AddFavoriteMovieToUsers < ActiveRecord::Migration
2
+ def change
3
+ add_column :users, :favorite_movie, :string
4
+ end
5
+ end
@@ -0,0 +1,6 @@
1
+ class AddMoneyProcToUsers < ActiveRecord::Migration
2
+ def change
3
+ add_column :users, :money_proc, :float
4
+
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ class AddHeightToUser < ActiveRecord::Migration
2
+ def change
3
+ add_column :users, :height, :string
4
+ end
5
+ end
@@ -11,7 +11,7 @@
11
11
  #
12
12
  # It's strongly recommended to check this file into your version control system.
13
13
 
14
- ActiveRecord::Schema.define(:version => 20120513003308) do
14
+ ActiveRecord::Schema.define(:version => 20120620165212) do
15
15
 
16
16
  create_table "cars", :force => true do |t|
17
17
  t.string "model"
@@ -32,6 +32,9 @@ ActiveRecord::Schema.define(:version => 20120513003308) do
32
32
  t.text "favorite_books"
33
33
  t.datetime "birth_date"
34
34
  t.float "money"
35
+ t.float "money_proc"
36
+ t.string "height"
37
+ t.string "favorite_movie"
35
38
  end
36
39
 
37
40
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: best_in_place
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.2
4
+ version: 1.1.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-05-24 00:00:00.000000000 Z
12
+ date: 2012-11-16 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
16
- requirement: &77694080 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,15 @@ dependencies:
21
21
  version: '3.1'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *77694080
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '3.1'
25
30
  - !ruby/object:Gem::Dependency
26
31
  name: jquery-rails
27
- requirement: &77693870 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
28
33
  none: false
29
34
  requirements:
30
35
  - - ! '>='
@@ -32,10 +37,15 @@ dependencies:
32
37
  version: '0'
33
38
  type: :runtime
34
39
  prerelease: false
35
- version_requirements: *77693870
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
36
46
  - !ruby/object:Gem::Dependency
37
47
  name: rspec-rails
38
- requirement: &77693600 !ruby/object:Gem::Requirement
48
+ requirement: !ruby/object:Gem::Requirement
39
49
  none: false
40
50
  requirements:
41
51
  - - ~>
@@ -43,29 +53,44 @@ dependencies:
43
53
  version: 2.8.0
44
54
  type: :development
45
55
  prerelease: false
46
- version_requirements: *77693600
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 2.8.0
47
62
  - !ruby/object:Gem::Dependency
48
63
  name: nokogiri
49
- requirement: &77693350 !ruby/object:Gem::Requirement
64
+ requirement: !ruby/object:Gem::Requirement
50
65
  none: false
51
66
  requirements:
52
67
  - - ! '>='
53
68
  - !ruby/object:Gem::Version
54
- version: 1.5.0
69
+ version: '0'
55
70
  type: :development
56
71
  prerelease: false
57
- version_requirements: *77693350
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
58
78
  - !ruby/object:Gem::Dependency
59
79
  name: capybara
60
- requirement: &77693120 !ruby/object:Gem::Requirement
80
+ requirement: !ruby/object:Gem::Requirement
61
81
  none: false
62
82
  requirements:
63
- - - ! '>='
83
+ - - ~>
64
84
  - !ruby/object:Gem::Version
65
- version: 1.0.1
85
+ version: 1.1.2
66
86
  type: :development
67
87
  prerelease: false
68
- version_requirements: *77693120
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ~>
92
+ - !ruby/object:Gem::Version
93
+ version: 1.1.2
69
94
  description: BestInPlace is a jQuery script and a Rails 3 helper that provide the
70
95
  method best_in_place to display any object field easily editable for the user by
71
96
  just clicking on it. It supports input data, text data, boolean data and custom
@@ -85,6 +110,7 @@ files:
85
110
  - Rakefile
86
111
  - best_in_place.gemspec
87
112
  - lib/assets/javascripts/best_in_place.js
113
+ - lib/assets/javascripts/best_in_place.purr.js
88
114
  - lib/assets/javascripts/jquery.purr.js
89
115
  - lib/best_in_place.rb
90
116
  - lib/best_in_place/check_version.rb
@@ -169,6 +195,9 @@ files:
169
195
  - test_app/db/migrate/20111217215935_add_birth_date_to_users.rb
170
196
  - test_app/db/migrate/20111224181356_add_money_to_user.rb
171
197
  - test_app/db/migrate/20120513003308_create_cars.rb
198
+ - test_app/db/migrate/20120607172609_add_favorite_movie_to_users.rb
199
+ - test_app/db/migrate/20120616170454_add_money_proc_to_users.rb
200
+ - test_app/db/migrate/20120620165212_add_height_to_user.rb
172
201
  - test_app/db/schema.rb
173
202
  - test_app/db/seeds.rb
174
203
  - test_app/doc/README_FOR_APP
@@ -199,15 +228,21 @@ required_ruby_version: !ruby/object:Gem::Requirement
199
228
  - - ! '>='
200
229
  - !ruby/object:Gem::Version
201
230
  version: '0'
231
+ segments:
232
+ - 0
233
+ hash: 572357039
202
234
  required_rubygems_version: !ruby/object:Gem::Requirement
203
235
  none: false
204
236
  requirements:
205
237
  - - ! '>='
206
238
  - !ruby/object:Gem::Version
207
239
  version: '0'
240
+ segments:
241
+ - 0
242
+ hash: 572357039
208
243
  requirements: []
209
244
  rubyforge_project: best_in_place
210
- rubygems_version: 1.8.15
245
+ rubygems_version: 1.8.24
211
246
  signing_key:
212
247
  specification_version: 3
213
248
  summary: It makes any field in place editable by clicking on it, it works for inputs,