best_in_place 1.1.3 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -39,10 +39,14 @@ BestInPlaceEditor.prototype = {
39
39
  to_display = this.original_content;
40
40
  }
41
41
  else {
42
- to_display = this.element.html();
42
+ if (this.sanitize) {
43
+ to_display = this.element.text();
44
+ } else {
45
+ to_display = this.element.html();
46
+ }
43
47
  }
44
48
 
45
- var elem = this.isNil ? "-" : this.element.html();
49
+ var elem = this.isNil ? "-" : this.sanitize ? this.element.text() : this.element.html();
46
50
  this.oldValue = elem;
47
51
  this.display_value = to_display;
48
52
  jQuery(this.activator).unbind("click", this.clickHandler);
@@ -51,8 +55,8 @@ BestInPlaceEditor.prototype = {
51
55
  },
52
56
 
53
57
  abort : function() {
54
- if (this.isNil) this.element.html(this.nil);
55
- else this.element.html(this.oldValue);
58
+ if (this.isNil) this.element.text(this.nil);
59
+ else this.element.text(this.oldValue);
56
60
  jQuery(this.activator).bind('click', {editor: this}, this.clickHandler);
57
61
  this.element.trigger(jQuery.Event("best_in_place:abort"));
58
62
  this.element.trigger(jQuery.Event("best_in_place:deactivate"));
@@ -95,7 +99,7 @@ BestInPlaceEditor.prototype = {
95
99
  } else if (this.formType == "checkbox") {
96
100
  editor.element.html(this.getValue() ? this.values[1] : this.values[0]);
97
101
  } else {
98
- editor.element.html(this.getValue() !== "" ? this.getValue() : this.nil);
102
+ editor.element.text(this.getValue() !== "" ? this.getValue() : this.nil);
99
103
  }
100
104
  editor.element.trigger(jQuery.Event("best_in_place:update"));
101
105
  },
@@ -123,6 +127,7 @@ BestInPlaceEditor.prototype = {
123
127
  self.inner_class = self.inner_class || $parent.attr("data-inner-class");
124
128
  self.html_attrs = self.html_attrs || $parent.attr("data-html-attrs");
125
129
  self.original_content = self.original_content || $parent.attr("data-original-content");
130
+ self.collectionValue = self.collectionValue || $parent.attr("data-value");
126
131
  });
127
132
 
128
133
  // Try Rails-id based if parents did not explicitly supply something
@@ -146,6 +151,7 @@ BestInPlaceEditor.prototype = {
146
151
  self.inner_class = self.element.attr("data-inner-class") || self.inner_class || null;
147
152
  self.html_attrs = self.element.attr("data-html-attrs") || self.html_attrs;
148
153
  self.original_content = self.element.attr("data-original-content") || self.original_content;
154
+ self.collectionValue = self.element.attr("data-value") || self.collectionValue;
149
155
 
150
156
  if (!self.element.attr("data-sanitize")) {
151
157
  self.sanitize = true;
@@ -164,6 +170,7 @@ BestInPlaceEditor.prototype = {
164
170
  {
165
171
  self.values = jQuery.parseJSON(self.collection);
166
172
  }
173
+
167
174
  },
168
175
 
169
176
  bindForm : function() {
@@ -172,10 +179,10 @@ BestInPlaceEditor.prototype = {
172
179
  },
173
180
 
174
181
  initNil: function() {
175
- if (this.element.html() === "")
182
+ if (this.element.text() === "")
176
183
  {
177
184
  this.isNil = true;
178
- this.element.html(this.nil);
185
+ this.element.text(this.nil);
179
186
  }
180
187
  },
181
188
 
@@ -185,12 +192,6 @@ BestInPlaceEditor.prototype = {
185
192
 
186
193
  // Trim and Strips HTML from text
187
194
  sanitizeValue : function(s) {
188
- if (this.sanitize)
189
- {
190
- var tmp = document.createElement("DIV");
191
- tmp.innerHTML = s;
192
- s = jQuery.trim(tmp.textContent || tmp.innerText).replace(/"/g, '"');
193
- }
194
195
  return jQuery.trim(s);
195
196
  },
196
197
 
@@ -220,9 +221,9 @@ BestInPlaceEditor.prototype = {
220
221
  loadSuccessCallback : function(data) {
221
222
  var response = jQuery.parseJSON(jQuery.trim(data));
222
223
  if (response !== null && response.hasOwnProperty("display_as")) {
223
- this.element.attr("data-original-content", this.element.html());
224
- this.original_content = this.element.html();
225
- this.element.html(response["display_as"]);
224
+ this.element.attr("data-original-content", this.element.text());
225
+ this.original_content = this.element.text();
226
+ this.element.text(response["display_as"]);
226
227
  }
227
228
  this.element.trigger(jQuery.Event("ajax:success"), data);
228
229
 
@@ -232,7 +233,7 @@ BestInPlaceEditor.prototype = {
232
233
  },
233
234
 
234
235
  loadErrorCallback : function(request, error) {
235
- this.element.html(this.oldValue);
236
+ this.element.text(this.oldValue);
236
237
 
237
238
  this.element.trigger(jQuery.Event("best_in_place:error"), [request, error])
238
239
  this.element.trigger(jQuery.Event("ajax:error"));
@@ -291,7 +292,7 @@ BestInPlaceEditor.forms = {
291
292
  .attr('value', this.cancelButton)
292
293
  )
293
294
  }
294
-
295
+
295
296
  this.element.html(output);
296
297
  this.setHtmlAttributes();
297
298
  this.element.find("input[type='text']")[0].select();
@@ -365,7 +366,7 @@ BestInPlaceEditor.forms = {
365
366
  input_elt.addClass(this.inner_class);
366
367
  }
367
368
  output.append(input_elt)
368
-
369
+
369
370
  this.element.html(output);
370
371
  this.setHtmlAttributes();
371
372
  this.element.find('input')[0].select();
@@ -403,13 +404,15 @@ BestInPlaceEditor.forms = {
403
404
  .attr('style', 'display:inline');
404
405
  selected = '',
405
406
  oldValue = this.oldValue,
406
- select_elt = $(document.createElement('select'));
407
+ select_elt = $(document.createElement('select')),
408
+ currentCollectionValue = this.collectionValue;
409
+
407
410
  jQuery.each(this.values, function (index, value) {
408
411
  var option_elt = $(document.createElement('option'))
409
412
  // .attr('value', value[0])
410
413
  .val(value[0])
411
414
  .html(value[1]);
412
- if(value[1] == oldValue) {
415
+ if(value[0] == currentCollectionValue) {
413
416
  option_elt.attr('selected', 'selected');
414
417
  }
415
418
  select_elt.append(option_elt);
@@ -457,7 +460,7 @@ BestInPlaceEditor.forms = {
457
460
  // grab width and height of text
458
461
  width = this.element.css('width');
459
462
  height = this.element.css('height');
460
-
463
+
461
464
  // construct form
462
465
  var output = $(document.createElement('form'))
463
466
  .attr('action', 'javascript:void(0)')
@@ -15,12 +15,13 @@ module BestInPlace
15
15
  opts[:collection] ||= []
16
16
  field = field.to_s
17
17
 
18
- value = build_value_for(real_object, field, opts)
18
+ display_value = build_value_for(real_object, field, opts)
19
19
 
20
20
  collection = nil
21
+ value = nil
21
22
  if opts[:type] == :select && !opts[:collection].blank?
22
- v = real_object.send(field)
23
- value = Hash[opts[:collection]].stringify_keys[v.to_s]
23
+ value = real_object.send(field)
24
+ display_value = Hash[opts[:collection]].stringify_keys[value.to_s]
24
25
  collection = opts[:collection].to_json
25
26
  end
26
27
  if opts[:type] == :checkbox
@@ -28,7 +29,7 @@ module BestInPlace
28
29
  if opts[:collection].blank? || opts[:collection].size != 2
29
30
  opts[:collection] = ["No", "Yes"]
30
31
  end
31
- value = fieldValue ? opts[:collection][1] : opts[:collection][0]
32
+ display_value = fieldValue ? opts[:collection][1] : opts[:collection][0]
32
33
  collection = opts[:collection].to_json
33
34
  end
34
35
  classes = ["best_in_place"]
@@ -37,6 +38,7 @@ module BestInPlace
37
38
  classes << opts[:classes]
38
39
  classes.flatten!
39
40
  end
41
+
40
42
  out = "<span class='#{classes.join(" ")}'"
41
43
  out << " id='#{BestInPlace::Utils.build_best_in_place_id(real_object, field)}'"
42
44
  out << " data-url='#{opts[:path].blank? ? url_for(object) : url_for(opts[:path])}'"
@@ -52,6 +54,8 @@ module BestInPlace
52
54
  out << " data-inner-class='#{opts[:inner_class]}'" if opts[:inner_class]
53
55
  out << " data-html-attrs='#{opts[:html_attrs].to_json}'" unless opts[:html_attrs].blank?
54
56
  out << " data-original-content='#{attribute_escape(real_object.send(field))}'" if opts[:display_as] || opts[:display_with]
57
+ out << " data-value='#{attribute_escape(value)}'" if value
58
+
55
59
  if opts[:data] && opts[:data].is_a?(Hash)
56
60
  opts[:data].each do |k, v|
57
61
  if !v.is_a?(String) && !v.is_a?(Symbol)
@@ -62,9 +66,9 @@ module BestInPlace
62
66
  end
63
67
  if !opts[:sanitize].nil? && !opts[:sanitize]
64
68
  out << " data-sanitize='false'>"
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))
69
+ out << display_value.to_s
66
70
  else
67
- out << ">#{sanitize(value.to_s, :tags => nil, :attributes => nil)}"
71
+ out << ">#{h(display_value.to_s)}"
68
72
  end
69
73
  out << "</span>"
70
74
  raw out
@@ -1,11 +1,13 @@
1
1
  module BestInPlace
2
2
  module TestHelpers
3
+
4
+ include ActionView::Helpers::JavaScriptHelper
3
5
 
4
6
  def bip_area(model, attr, new_value)
5
7
  id = BestInPlace::Utils.build_best_in_place_id model, attr
6
8
  page.execute_script <<-JS
7
9
  jQuery("##{id}").click();
8
- jQuery("##{id} form textarea").val('#{new_value}');
10
+ jQuery("##{id} form textarea").val('#{escape_javascript new_value.to_s}');
9
11
  jQuery("##{id} form textarea").blur();
10
12
  JS
11
13
  end
@@ -14,7 +16,7 @@ module BestInPlace
14
16
  id = BestInPlace::Utils.build_best_in_place_id model, attr
15
17
  page.execute_script <<-JS
16
18
  jQuery("##{id}").click();
17
- jQuery("##{id} input[name='#{attr}']").val('#{new_value}');
19
+ jQuery("##{id} input[name='#{attr}']").val('#{escape_javascript new_value.to_s}');
18
20
  jQuery("##{id} form").submit();
19
21
  JS
20
22
  end
@@ -1,3 +1,3 @@
1
1
  module BestInPlace
2
- VERSION = "1.1.3"
2
+ VERSION = "2.0.0"
3
3
  end
@@ -328,6 +328,10 @@ describe BestInPlace::BestInPlaceHelpers do
328
328
  @span.text.should == "Italy"
329
329
  end
330
330
 
331
+ it "should include the proper data-value" do
332
+ @span.attribute("data-value").value.should == "2"
333
+ end
334
+
331
335
  context "with an apostrophe in it" do
332
336
  before do
333
337
  @apostrophe_countries = [[1, "Joe's Country"], [2, "Bob's Country"]]
@@ -86,6 +86,7 @@ describe "JS behaviour", :js => true do
86
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
87
 
88
88
  visit users_path
89
+
89
90
  within("tr#user_#{@user.id} > .name > span") do
90
91
  page.should have_content("Lucia")
91
92
  page.should have_xpath("//a[contains(@href,'#{user_path(@user)}')]")
@@ -97,13 +98,11 @@ describe "JS behaviour", :js => true do
97
98
  $("##{id} input[name='name']").val('Lisa');
98
99
  $("##{id} form").submit();
99
100
  JS
100
- # binding.pry
101
- # visit users_path
101
+
102
102
  within("tr#user_#{@user.id} > .name > span") do
103
103
  page.should have_content('Lisa')
104
- page.should have_xpath("//a[contains(@href,'#{user_path(@user)}')]")
105
104
  end
106
- end
105
+ end
107
106
 
108
107
  it "should be able to use bip_text to update a text field" do
109
108
  @user.save!
@@ -745,6 +744,26 @@ describe "JS behaviour", :js => true do
745
744
  end
746
745
  end
747
746
 
747
+ it "should keep the same value after multipe edits" do
748
+ @user.save!
749
+
750
+ retry_on_timeout do
751
+ visit double_init_user_path(@user)
752
+
753
+ bip_area @user, :description, "A <a href=\"http://google.es\">link in this text</a> not sanitized."
754
+ visit double_init_user_path(@user)
755
+
756
+ page.should have_link("link in this text", :href => "http://google.es")
757
+
758
+ id = BestInPlace::Utils.build_best_in_place_id @user, :description
759
+ page.execute_script <<-JS
760
+ $("##{id}").click();
761
+ JS
762
+
763
+ page.find("##{id} textarea").value.should eq("A <a href=\"http://google.es\">link in this text</a> not sanitized.")
764
+ end
765
+ end
766
+
748
767
  it "should display single- and double-quotes in values appropriately" do
749
768
  @user.height = %{5' 6"}
750
769
  @user.save!
@@ -782,4 +801,66 @@ describe "JS behaviour", :js => true do
782
801
  end
783
802
  end
784
803
 
804
+ it "should escape javascript in test helpers" do
805
+ @user.save!
806
+
807
+ retry_on_timeout do
808
+ visit user_path(@user)
809
+
810
+ bip_text @user, :last_name, "Other '); alert('hi');"
811
+ sleep 1
812
+
813
+ @user.reload
814
+ @user.last_name.should eq("Other '); alert('hi');")
815
+ end
816
+ end
817
+
818
+ it "should save text in database without encoding" do
819
+ @user.save!
820
+
821
+ retry_on_timeout do
822
+ visit user_path(@user)
823
+
824
+ bip_text @user, :last_name, "Other \"thing\""
825
+ sleep 1
826
+
827
+ @user.reload
828
+ @user.last_name.should eq("Other \"thing\"")
829
+ end
830
+ end
831
+
832
+ it "should not strip html tags" do
833
+ @user.save!
834
+
835
+ retry_on_timeout do
836
+ visit user_path(@user)
837
+
838
+ bip_text @user, :last_name, "<script>alert('hi');</script>"
839
+ within("#last_name") { page.should have_content("<script>alert('hi');</script>") }
840
+
841
+ visit user_path(@user)
842
+
843
+ id = BestInPlace::Utils.build_best_in_place_id @user, :last_name
844
+ page.execute_script <<-JS
845
+ $("##{id}").click();
846
+ JS
847
+
848
+ page.find("##{id} input").value.should eq("<script>alert('hi');</script>")
849
+ end
850
+ end
851
+
852
+ it "should generate the select html with the proper current option selected" do
853
+ @user.save!
854
+ visit user_path(@user)
855
+ within("#country") do
856
+ page.should have_content("Italy")
857
+ end
858
+
859
+ id = BestInPlace::Utils.build_best_in_place_id @user, :country
860
+ page.execute_script <<-JS
861
+ $("##{id}").click();
862
+ JS
863
+
864
+ page.should have_css("##{id} select option[value='2'][selected='selected']")
865
+ end
785
866
  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.3
4
+ version: 2.0.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -230,7 +230,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
230
230
  version: '0'
231
231
  segments:
232
232
  - 0
233
- hash: 572357039
233
+ hash: -891902797
234
234
  required_rubygems_version: !ruby/object:Gem::Requirement
235
235
  none: false
236
236
  requirements:
@@ -239,7 +239,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
239
239
  version: '0'
240
240
  segments:
241
241
  - 0
242
- hash: 572357039
242
+ hash: -891902797
243
243
  requirements: []
244
244
  rubyforge_project: best_in_place
245
245
  rubygems_version: 1.8.24