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
|
-
|
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.
|
55
|
-
else this.element.
|
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.
|
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.
|
182
|
+
if (this.element.text() === "")
|
176
183
|
{
|
177
184
|
this.isNil = true;
|
178
|
-
this.element.
|
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.
|
224
|
-
this.original_content = this.element.
|
225
|
-
this.element.
|
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.
|
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[
|
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)')
|
data/lib/best_in_place/helper.rb
CHANGED
@@ -15,12 +15,13 @@ module BestInPlace
|
|
15
15
|
opts[:collection] ||= []
|
16
16
|
field = field.to_s
|
17
17
|
|
18
|
-
|
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
|
-
|
23
|
-
|
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
|
-
|
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 <<
|
69
|
+
out << display_value.to_s
|
66
70
|
else
|
67
|
-
out << ">#{
|
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
|
@@ -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"]]
|
data/spec/integration/js_spec.rb
CHANGED
@@ -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
|
-
|
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:
|
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:
|
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:
|
242
|
+
hash: -891902797
|
243
243
|
requirements: []
|
244
244
|
rubyforge_project: best_in_place
|
245
245
|
rubygems_version: 1.8.24
|