best_in_place 2.0.3 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +0 -1
- data/README.md +3 -1
- data/lib/assets/javascripts/best_in_place.js +54 -36
- data/lib/assets/javascripts/jquery.purr.js +20 -46
- data/lib/best_in_place/controller_extensions.rb +1 -1
- data/lib/best_in_place/helper.rb +8 -4
- data/lib/best_in_place/test_helpers.rb +1 -0
- data/lib/best_in_place/version.rb +1 -1
- data/spec/helpers/best_in_place_spec.rb +22 -0
- data/spec/integration/js_spec.rb +74 -5
- data/test_app/app/assets/stylesheets/style.css.erb +8 -0
- data/test_app/app/views/users/show.html.erb +9 -3
- data/test_app/db/migrate/20130213224102_add_favorite_locale_to_users.rb +5 -0
- data/test_app/db/schema.rb +6 -5
- metadata +25 -37
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -53,7 +53,9 @@ Options:
|
|
53
53
|
If not defined it will show *"-"*.
|
54
54
|
- **:activator**: Is the DOM object that can activate the field. If not defined the user will making editable by clicking on it.
|
55
55
|
- **:ok_button**: (Inputs and textareas only) If set to a string, then an OK button will be shown with the string as its label, replacing save on blur.
|
56
|
+
- **:ok_button_class**: (Inputs and textareas only) Specifies any extra classes to set on the OK button.
|
56
57
|
- **:cancel_button**: (Inputs and textareas only) If set to a string, then a Cancel button will be shown with the string as its label.
|
58
|
+
- **:cancel_button_class**: (Inputs and textareas only) Specifies any extra classes to set on the Cancel button.
|
57
59
|
- **:sanitize**: True by default. If set to false the input/textarea will accept html tags.
|
58
60
|
- **:html_attrs**: Hash of html arguments, such as maxlength, default-value etc.
|
59
61
|
- **:inner_class**: Class that is set to the rendered form.
|
@@ -188,7 +190,7 @@ You can also pass in a proc or lambda like this:
|
|
188
190
|
|
189
191
|
The 'ajax:success' event is triggered upon success. Use bind:
|
190
192
|
|
191
|
-
$('.best_in_place').bind("ajax:success", function(){$(this).closest('tr').effect('highlight')
|
193
|
+
$('.best_in_place').bind("ajax:success", function () {$(this).closest('tr').effect('highlight'); });
|
192
194
|
|
193
195
|
To bind a callback that is specific to a particular field, use the 'classes' option in the helper method and
|
194
196
|
then bind to that class.
|
@@ -32,7 +32,7 @@ BestInPlaceEditor.prototype = {
|
|
32
32
|
|
33
33
|
activate : function() {
|
34
34
|
var to_display = "";
|
35
|
-
if (this.isNil) {
|
35
|
+
if (this.isNil()) {
|
36
36
|
to_display = "";
|
37
37
|
}
|
38
38
|
else if (this.original_content) {
|
@@ -46,8 +46,7 @@ BestInPlaceEditor.prototype = {
|
|
46
46
|
}
|
47
47
|
}
|
48
48
|
|
49
|
-
|
50
|
-
this.oldValue = elem;
|
49
|
+
this.oldValue = this.isNil() ? "" : this.element.html();
|
51
50
|
this.display_value = to_display;
|
52
51
|
jQuery(this.activator).unbind("click", this.clickHandler);
|
53
52
|
this.activateForm();
|
@@ -55,8 +54,7 @@ BestInPlaceEditor.prototype = {
|
|
55
54
|
},
|
56
55
|
|
57
56
|
abort : function() {
|
58
|
-
|
59
|
-
else this.element.html(this.oldValue);
|
57
|
+
this.activateText(this.oldValue);
|
60
58
|
jQuery(this.activator).bind('click', {editor: this}, this.clickHandler);
|
61
59
|
this.element.trigger(jQuery.Event("best_in_place:abort"));
|
62
60
|
this.element.trigger(jQuery.Event("best_in_place:deactivate"));
|
@@ -80,7 +78,6 @@ BestInPlaceEditor.prototype = {
|
|
80
78
|
this.abort();
|
81
79
|
return true;
|
82
80
|
}
|
83
|
-
this.isNil = false;
|
84
81
|
editor.ajax({
|
85
82
|
"type" : "post",
|
86
83
|
"dataType" : "text",
|
@@ -114,6 +111,11 @@ BestInPlaceEditor.prototype = {
|
|
114
111
|
alert("The form was not properly initialized. activateForm is unbound");
|
115
112
|
},
|
116
113
|
|
114
|
+
activateText : function(value){
|
115
|
+
this.element.html(value);
|
116
|
+
if(this.isNil()) this.element.html(this.nil);
|
117
|
+
},
|
118
|
+
|
117
119
|
// Helper Functions ////////////////////////////////////////////////////////
|
118
120
|
|
119
121
|
initOptions : function() {
|
@@ -121,19 +123,21 @@ BestInPlaceEditor.prototype = {
|
|
121
123
|
var self = this;
|
122
124
|
self.element.parents().each(function(){
|
123
125
|
$parent = jQuery(this);
|
124
|
-
self.url
|
125
|
-
self.collection
|
126
|
-
self.formType
|
127
|
-
self.objectName
|
128
|
-
self.attributeName
|
129
|
-
self.activator
|
130
|
-
self.okButton
|
131
|
-
self.
|
132
|
-
self.
|
133
|
-
self.
|
134
|
-
self.
|
135
|
-
self.
|
136
|
-
self.
|
126
|
+
self.url = self.url || $parent.attr("data-url");
|
127
|
+
self.collection = self.collection || $parent.attr("data-collection");
|
128
|
+
self.formType = self.formType || $parent.attr("data-type");
|
129
|
+
self.objectName = self.objectName || $parent.attr("data-object");
|
130
|
+
self.attributeName = self.attributeName || $parent.attr("data-attribute");
|
131
|
+
self.activator = self.activator || $parent.attr("data-activator");
|
132
|
+
self.okButton = self.okButton || $parent.attr("data-ok-button");
|
133
|
+
self.okButtonClass = self.okButtonClass || $parent.attr("data-ok-button-class");
|
134
|
+
self.cancelButton = self.cancelButton || $parent.attr("data-cancel-button");
|
135
|
+
self.cancelButtonClass = self.cancelButtonClass || $parent.attr("data-cancel-button-class");
|
136
|
+
self.nil = self.nil || $parent.attr("data-nil");
|
137
|
+
self.inner_class = self.inner_class || $parent.attr("data-inner-class");
|
138
|
+
self.html_attrs = self.html_attrs || $parent.attr("data-html-attrs");
|
139
|
+
self.original_content = self.original_content || $parent.attr("data-original-content");
|
140
|
+
self.collectionValue = self.collectionValue || $parent.attr("data-value");
|
137
141
|
});
|
138
142
|
|
139
143
|
// Try Rails-id based if parents did not explicitly supply something
|
@@ -145,19 +149,21 @@ BestInPlaceEditor.prototype = {
|
|
145
149
|
});
|
146
150
|
|
147
151
|
// Load own attributes (overrides all others)
|
148
|
-
self.url
|
149
|
-
self.collection
|
150
|
-
self.formType
|
151
|
-
self.objectName
|
152
|
-
self.attributeName
|
153
|
-
self.activator
|
154
|
-
self.okButton
|
155
|
-
self.
|
156
|
-
self.
|
157
|
-
self.
|
158
|
-
self.
|
159
|
-
self.
|
160
|
-
self.
|
152
|
+
self.url = self.element.attr("data-url") || self.url || document.location.pathname;
|
153
|
+
self.collection = self.element.attr("data-collection") || self.collection;
|
154
|
+
self.formType = self.element.attr("data-type") || self.formtype || "input";
|
155
|
+
self.objectName = self.element.attr("data-object") || self.objectName;
|
156
|
+
self.attributeName = self.element.attr("data-attribute") || self.attributeName;
|
157
|
+
self.activator = self.element.attr("data-activator") || self.element;
|
158
|
+
self.okButton = self.element.attr("data-ok-button") || self.okButton;
|
159
|
+
self.okButtonClass = self.element.attr("data-ok-button-class") || self.okButtonClass || "";
|
160
|
+
self.cancelButton = self.element.attr("data-cancel-button") || self.cancelButton;
|
161
|
+
self.cancelButtonClass = self.element.attr("data-cancel-button-class") || self.cancelButtonClass || "";
|
162
|
+
self.nil = self.element.attr("data-nil") || self.nil || "—";
|
163
|
+
self.inner_class = self.element.attr("data-inner-class") || self.inner_class || null;
|
164
|
+
self.html_attrs = self.element.attr("data-html-attrs") || self.html_attrs;
|
165
|
+
self.original_content = self.element.attr("data-original-content") || self.original_content;
|
166
|
+
self.collectionValue = self.element.attr("data-value") || self.collectionValue;
|
161
167
|
|
162
168
|
if (!self.element.attr("data-sanitize")) {
|
163
169
|
self.sanitize = true;
|
@@ -187,11 +193,16 @@ BestInPlaceEditor.prototype = {
|
|
187
193
|
initNil: function() {
|
188
194
|
if (this.element.html() === "")
|
189
195
|
{
|
190
|
-
this.isNil = true;
|
191
196
|
this.element.html(this.nil);
|
192
197
|
}
|
193
198
|
},
|
194
199
|
|
200
|
+
isNil: function() {
|
201
|
+
// TODO: It only work when form is deactivated.
|
202
|
+
// Condition will fail when form is activated
|
203
|
+
return this.element.html() === "" || this.element.html() === this.nil;
|
204
|
+
},
|
205
|
+
|
195
206
|
getValue : function() {
|
196
207
|
alert("The form was not properly initialized. getValue is unbound");
|
197
208
|
},
|
@@ -225,7 +236,7 @@ BestInPlaceEditor.prototype = {
|
|
225
236
|
// Handlers ////////////////////////////////////////////////////////////////
|
226
237
|
|
227
238
|
loadSuccessCallback : function(data) {
|
228
|
-
data =
|
239
|
+
data = jQuery.trim(data);
|
229
240
|
|
230
241
|
if(data && data!=""){
|
231
242
|
var response = jQuery.parseJSON(jQuery.trim(data));
|
@@ -234,8 +245,12 @@ BestInPlaceEditor.prototype = {
|
|
234
245
|
this.original_content = this.element.text();
|
235
246
|
this.element.html(response["display_as"]);
|
236
247
|
}
|
248
|
+
|
237
249
|
this.element.trigger(jQuery.Event("best_in_place:success"), data);
|
238
250
|
this.element.trigger(jQuery.Event("ajax:success"), data);
|
251
|
+
} else {
|
252
|
+
this.element.trigger(jQuery.Event("best_in_place:success"));
|
253
|
+
this.element.trigger(jQuery.Event("ajax:success"));
|
239
254
|
}
|
240
255
|
|
241
256
|
// Binding back after being clicked
|
@@ -249,7 +264,7 @@ BestInPlaceEditor.prototype = {
|
|
249
264
|
},
|
250
265
|
|
251
266
|
loadErrorCallback : function(request, error) {
|
252
|
-
this.
|
267
|
+
this.activateText(this.oldValue);
|
253
268
|
|
254
269
|
this.element.trigger(jQuery.Event("best_in_place:error"), [request, error]);
|
255
270
|
this.element.trigger(jQuery.Event("ajax:error"), request, error);
|
@@ -301,6 +316,7 @@ BestInPlaceEditor.forms = {
|
|
301
316
|
output.append(
|
302
317
|
jQuery(document.createElement('input'))
|
303
318
|
.attr('type', 'submit')
|
319
|
+
.attr('class', this.okButtonClass)
|
304
320
|
.attr('value', this.okButton)
|
305
321
|
)
|
306
322
|
}
|
@@ -308,6 +324,7 @@ BestInPlaceEditor.forms = {
|
|
308
324
|
output.append(
|
309
325
|
jQuery(document.createElement('input'))
|
310
326
|
.attr('type', 'button')
|
327
|
+
.attr('class', this.cancelButtonClass)
|
311
328
|
.attr('value', this.cancelButton)
|
312
329
|
)
|
313
330
|
}
|
@@ -423,7 +440,8 @@ BestInPlaceEditor.forms = {
|
|
423
440
|
.attr('style', 'display:inline');
|
424
441
|
selected = '',
|
425
442
|
oldValue = this.oldValue,
|
426
|
-
select_elt = jQuery(document.createElement('select'))
|
443
|
+
select_elt = jQuery(document.createElement('select'))
|
444
|
+
.attr('class', this.inned_class !== null ? this.inner_class : '' ),
|
427
445
|
currentCollectionValue = this.collectionValue;
|
428
446
|
|
429
447
|
jQuery.each(this.values, function (index, value) {
|
@@ -62,7 +62,7 @@
|
|
62
62
|
|
63
63
|
// If ESC is pressed remove notice
|
64
64
|
jQuery(document).keyup(function(e) {
|
65
|
-
if (e.keyCode
|
65
|
+
if (e.keyCode === 27) {
|
66
66
|
removeNotice();
|
67
67
|
}
|
68
68
|
});
|
@@ -70,24 +70,15 @@
|
|
70
70
|
// Add the notice to the page and keep it hidden initially
|
71
71
|
notice.appendTo(cont).hide();
|
72
72
|
|
73
|
-
|
74
|
-
|
75
|
-
// IE7 and earlier can't handle the combination of opacity and transparent pngs, so if we're using transparent pngs in our
|
76
|
-
// notice style, we'll just skip the fading in.
|
77
|
-
notice.show();
|
78
|
-
}
|
79
|
-
else
|
80
|
-
{
|
81
|
-
//Fade in the notice we just added
|
82
|
-
notice.fadeIn(options.fadeInSpeed);
|
83
|
-
}
|
73
|
+
//Fade in the notice we just added
|
74
|
+
notice.fadeIn(options.fadeInSpeed);
|
84
75
|
|
85
76
|
// Set up the removal interval for the added notice if that notice is not a sticky
|
86
77
|
if (!options.isSticky)
|
87
78
|
{
|
88
79
|
var topSpotInt = setInterval(function() {
|
89
80
|
// Check to see if our notice is the first non-sticky notice in the list
|
90
|
-
if (notice.prevAll('.purr').length
|
81
|
+
if (notice.prevAll('.purr').length === 0)
|
91
82
|
{
|
92
83
|
// Stop checking once the condition is met
|
93
84
|
clearInterval(topSpotInt);
|
@@ -103,41 +94,24 @@
|
|
103
94
|
|
104
95
|
function removeNotice()
|
105
96
|
{
|
106
|
-
//
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
97
|
+
// Fade the object out before reducing its height to produce the sliding effect
|
98
|
+
notice.animate({ opacity: '0' },
|
99
|
+
{
|
100
|
+
duration: options.fadeOutSpeed,
|
101
|
+
complete: function ()
|
111
102
|
{
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
103
|
+
notice.animate({ height: '0px' },
|
104
|
+
{
|
105
|
+
duration: options.fadeOutSpeed,
|
106
|
+
complete: function()
|
107
|
+
{
|
108
|
+
notice.remove();
|
109
|
+
}
|
110
|
+
}
|
111
|
+
);
|
117
112
|
}
|
118
|
-
|
119
|
-
|
120
|
-
else
|
121
|
-
{
|
122
|
-
// Fade the object out before reducing its height to produce the sliding effect
|
123
|
-
notice.animate({ opacity: '0' },
|
124
|
-
{
|
125
|
-
duration: options.fadeOutSpeed,
|
126
|
-
complete: function ()
|
127
|
-
{
|
128
|
-
notice.animate({ height: '0px' },
|
129
|
-
{
|
130
|
-
duration: options.fadeOutSpeed,
|
131
|
-
complete: function()
|
132
|
-
{
|
133
|
-
notice.remove();
|
134
|
-
}
|
135
|
-
}
|
136
|
-
);
|
137
|
-
}
|
138
|
-
}
|
139
|
-
);
|
140
|
-
}
|
113
|
+
}
|
114
|
+
);
|
141
115
|
};
|
142
116
|
};
|
143
117
|
|
data/lib/best_in_place/helper.rb
CHANGED
@@ -47,7 +47,9 @@ module BestInPlace
|
|
47
47
|
out << " data-attribute='#{field}'"
|
48
48
|
out << " data-activator='#{opts[:activator]}'" unless opts[:activator].blank?
|
49
49
|
out << " data-ok-button='#{opts[:ok_button]}'" unless opts[:ok_button].blank?
|
50
|
+
out << " data-ok-button-class='#{opts[:ok_button_class]}'" unless opts[:ok_button_class].blank?
|
50
51
|
out << " data-cancel-button='#{opts[:cancel_button]}'" unless opts[:cancel_button].blank?
|
52
|
+
out << " data-cancel-button-class='#{opts[:cancel_button_class]}'" unless opts[:cancel_button_class].blank?
|
51
53
|
out << " data-nil='#{attribute_escape(opts[:nil])}'" unless opts[:nil].blank?
|
52
54
|
out << " data-use-confirm='#{opts[:use_confirm]}'" unless opts[:use_confirm].nil?
|
53
55
|
out << " data-type='#{opts[:type]}'"
|
@@ -86,11 +88,12 @@ module BestInPlace
|
|
86
88
|
def build_value_for(object, field, opts)
|
87
89
|
return "" if object.send(field).blank?
|
88
90
|
|
89
|
-
if
|
90
|
-
|
91
|
+
klass = if object.respond_to?(:id)
|
92
|
+
"#{object.class}_#{object.id}"
|
91
93
|
else
|
92
|
-
|
94
|
+
object.class.to_s
|
93
95
|
end
|
96
|
+
|
94
97
|
if opts[:display_as]
|
95
98
|
BestInPlace::DisplayMethods.add_model_method(klass, field, opts[:display_as])
|
96
99
|
object.send(opts[:display_as]).to_s
|
@@ -98,6 +101,7 @@ module BestInPlace
|
|
98
101
|
elsif opts[:display_with].try(:is_a?, Proc)
|
99
102
|
BestInPlace::DisplayMethods.add_helper_proc(klass, field, opts[:display_with])
|
100
103
|
opts[:display_with].call(object.send(field))
|
104
|
+
|
101
105
|
elsif opts[:display_with]
|
102
106
|
BestInPlace::DisplayMethods.add_helper_method(klass, field, opts[:display_with], opts[:helper_options])
|
103
107
|
if opts[:helper_options]
|
@@ -107,7 +111,7 @@ module BestInPlace
|
|
107
111
|
end
|
108
112
|
|
109
113
|
else
|
110
|
-
object.send(field).to_s
|
114
|
+
object.send(field).to_s
|
111
115
|
end
|
112
116
|
end
|
113
117
|
|
@@ -75,10 +75,18 @@ describe BestInPlace::BestInPlaceHelpers do
|
|
75
75
|
@span.attribute("data-ok-button").should be_nil
|
76
76
|
end
|
77
77
|
|
78
|
+
it "should have no OK button class by default" do
|
79
|
+
@span.attribute("data-ok-button-class").should be_nil
|
80
|
+
end
|
81
|
+
|
78
82
|
it "should have no Cancel button text by default" do
|
79
83
|
@span.attribute("data-cancel-button").should be_nil
|
80
84
|
end
|
81
85
|
|
86
|
+
it "should have no Cancel button class by default" do
|
87
|
+
@span.attribute("data-cancel-button-class").should be_nil
|
88
|
+
end
|
89
|
+
|
82
90
|
it "should have no Use-Confirmation dialog option by default" do
|
83
91
|
@span.attribute("data-use-confirm").should be_nil
|
84
92
|
end
|
@@ -158,6 +166,13 @@ describe BestInPlace::BestInPlaceHelpers do
|
|
158
166
|
span.attribute("data-ok-button").value.should == "okay"
|
159
167
|
end
|
160
168
|
|
169
|
+
it "should have the given OK button class" do
|
170
|
+
out = helper.best_in_place @user, :name, :ok_button => "okay", :ok_button_class => "okay-class"
|
171
|
+
nk = Nokogiri::HTML.parse(out)
|
172
|
+
span = nk.css("span")
|
173
|
+
span.attribute("data-ok-button-class").value.should == "okay-class"
|
174
|
+
end
|
175
|
+
|
161
176
|
it "should have the given Cancel button text" do
|
162
177
|
out = helper.best_in_place @user, :name, :cancel_button => "nasty"
|
163
178
|
nk = Nokogiri::HTML.parse(out)
|
@@ -165,6 +180,13 @@ describe BestInPlace::BestInPlaceHelpers do
|
|
165
180
|
span.attribute("data-cancel-button").value.should == "nasty"
|
166
181
|
end
|
167
182
|
|
183
|
+
it "should have the given Cancel button class" do
|
184
|
+
out = helper.best_in_place @user, :name, :cancel_button => "nasty", :cancel_button_class => "nasty-class"
|
185
|
+
nk = Nokogiri::HTML.parse(out)
|
186
|
+
span = nk.css("span")
|
187
|
+
span.attribute("data-cancel-button-class").value.should == "nasty-class"
|
188
|
+
end
|
189
|
+
|
168
190
|
it "should have the given Use-Confirmation dialog option" do
|
169
191
|
out = helper.best_in_place @user, :name, :use_confirm => "false"
|
170
192
|
nk = Nokogiri::HTML.parse(out)
|
data/spec/integration/js_spec.rb
CHANGED
@@ -34,17 +34,17 @@ describe "JS behaviour", :js => true do
|
|
34
34
|
end
|
35
35
|
|
36
36
|
describe "nil option" do
|
37
|
-
it "should render
|
37
|
+
it "should render an em-dash when the field is empty" do
|
38
38
|
@user.name = ""
|
39
39
|
@user.save :validate => false
|
40
40
|
visit user_path(@user)
|
41
41
|
|
42
42
|
within("#name") do
|
43
|
-
page.should have_content("
|
43
|
+
page.should have_content("\u2014")
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
47
|
-
it "should render the default
|
47
|
+
it "should render the default em-dash string when there is an error and if the intial string is em-dash" do
|
48
48
|
@user.money = nil
|
49
49
|
@user.save!
|
50
50
|
visit user_path(@user)
|
@@ -52,7 +52,7 @@ describe "JS behaviour", :js => true do
|
|
52
52
|
bip_text @user, :money, "abcd"
|
53
53
|
|
54
54
|
within("#money") do
|
55
|
-
page.should have_content("
|
55
|
+
page.should have_content("\u2014")
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
@@ -87,6 +87,36 @@ describe "JS behaviour", :js => true do
|
|
87
87
|
end
|
88
88
|
end
|
89
89
|
|
90
|
+
it "should display an empty input field the second time I open it" do
|
91
|
+
@user.favorite_locale = nil
|
92
|
+
@user.save!
|
93
|
+
visit user_path(@user)
|
94
|
+
|
95
|
+
within("#favorite_locale") do
|
96
|
+
page.should have_content("N/A")
|
97
|
+
end
|
98
|
+
|
99
|
+
id = BestInPlace::Utils.build_best_in_place_id @user, :favorite_locale
|
100
|
+
page.execute_script <<-JS
|
101
|
+
$("##{id}").click();
|
102
|
+
JS
|
103
|
+
|
104
|
+
text = page.find("##{id} input").value
|
105
|
+
text.should == ""
|
106
|
+
|
107
|
+
page.execute_script <<-JS
|
108
|
+
$("##{id} input[name='favorite_locale']").blur();
|
109
|
+
$("##{id} input[name='favorite_locale']").blur();
|
110
|
+
JS
|
111
|
+
sleep 1
|
112
|
+
|
113
|
+
page.execute_script <<-JS
|
114
|
+
$("##{id}").click();
|
115
|
+
JS
|
116
|
+
|
117
|
+
text = page.find("##{id} input").value
|
118
|
+
text.should == ""
|
119
|
+
end
|
90
120
|
end
|
91
121
|
|
92
122
|
it "should be able to update last but one item in list" do
|
@@ -196,6 +226,14 @@ describe "JS behaviour", :js => true do
|
|
196
226
|
end
|
197
227
|
end
|
198
228
|
|
229
|
+
it "should apply the inner_class option to a select field" do
|
230
|
+
@user.save!
|
231
|
+
visit user_path(@user)
|
232
|
+
|
233
|
+
find('#country span').click
|
234
|
+
find('#country').should have_css('select.some_class')
|
235
|
+
end
|
236
|
+
|
199
237
|
it "should be able to use bip_text to change a date field" do
|
200
238
|
@user.save!
|
201
239
|
today = Time.now.utc.to_date
|
@@ -295,6 +333,12 @@ describe "JS behaviour", :js => true do
|
|
295
333
|
page.execute_script <<-JS
|
296
334
|
$("##{id}").click();
|
297
335
|
$("##{id} input[name='favorite_color']").val('Blue');
|
336
|
+
JS
|
337
|
+
|
338
|
+
page.find("##{id} input[type='submit']").value.should == 'Do it!'
|
339
|
+
page.should have_css("##{id} input[type='submit'].custom-submit.other-custom-submit")
|
340
|
+
|
341
|
+
page.execute_script <<-JS
|
298
342
|
$("##{id} input[type='submit']").click();
|
299
343
|
JS
|
300
344
|
|
@@ -316,6 +360,12 @@ describe "JS behaviour", :js => true do
|
|
316
360
|
page.execute_script <<-JS
|
317
361
|
$("##{id}").click();
|
318
362
|
$("##{id} input[name='favorite_color']").val('Blue');
|
363
|
+
JS
|
364
|
+
|
365
|
+
page.find("##{id} input[type='button']").value.should == 'Nope'
|
366
|
+
page.should have_css("##{id} input[type='button'].custom-cancel.other-custom-cancel")
|
367
|
+
|
368
|
+
page.execute_script <<-JS
|
319
369
|
$("##{id} input[type='button']").click();
|
320
370
|
JS
|
321
371
|
|
@@ -378,6 +428,7 @@ describe "JS behaviour", :js => true do
|
|
378
428
|
page.execute_script <<-JS
|
379
429
|
$("##{id} input[name='favorite_color']").val('Blue');
|
380
430
|
$("##{id} input[name='favorite_color']").blur();
|
431
|
+
$("##{id} input[name='favorite_color']").blur();
|
381
432
|
JS
|
382
433
|
sleep 1 # Increase if browser is slow
|
383
434
|
|
@@ -443,6 +494,7 @@ describe "JS behaviour", :js => true do
|
|
443
494
|
$("##{id}").click();
|
444
495
|
$("##{id} textarea").val('1Q84');
|
445
496
|
$("##{id} textarea").blur();
|
497
|
+
$("##{id} textarea").blur();
|
446
498
|
JS
|
447
499
|
sleep 1 # Increase if browser is slow
|
448
500
|
page.driver.browser.switch_to.alert.accept
|
@@ -467,6 +519,7 @@ describe "JS behaviour", :js => true do
|
|
467
519
|
page.execute_script <<-JS
|
468
520
|
$("##{id} textarea").val('1Q84');
|
469
521
|
$("##{id} textarea").blur();
|
522
|
+
$("##{id} textarea").blur();
|
470
523
|
JS
|
471
524
|
sleep 1 # Increase if browser is slow
|
472
525
|
|
@@ -501,6 +554,20 @@ describe "JS behaviour", :js => true do
|
|
501
554
|
page.should have_content('Last name was updated!')
|
502
555
|
end
|
503
556
|
|
557
|
+
it "should fire off a callback when retrieve success with empty data" do
|
558
|
+
@user.save!
|
559
|
+
visit user_path(@user)
|
560
|
+
|
561
|
+
id = BestInPlace::Utils.build_best_in_place_id @user, :last_name
|
562
|
+
page.execute_script <<-JS
|
563
|
+
$("##{id}").bind('best_in_place:success', function() { $('body').append('Updated successfully!') });
|
564
|
+
JS
|
565
|
+
|
566
|
+
page.should have_no_content('Updated successfully!')
|
567
|
+
bip_text @user, :last_name, 'Empty'
|
568
|
+
page.should have_content('Updated successfully!')
|
569
|
+
end
|
570
|
+
|
504
571
|
describe "display_as" do
|
505
572
|
it "should render the address with a custom format" do
|
506
573
|
@user.save!
|
@@ -590,7 +657,7 @@ describe "JS behaviour", :js => true do
|
|
590
657
|
|
591
658
|
visit user_path(@user)
|
592
659
|
|
593
|
-
within("#dw_description") { page.should have_content("
|
660
|
+
within("#dw_description") { page.should have_content("\u2014") }
|
594
661
|
end
|
595
662
|
|
596
663
|
it "should render the money using number_to_currency" do
|
@@ -716,6 +783,7 @@ describe "JS behaviour", :js => true do
|
|
716
783
|
page.execute_script <<-JS
|
717
784
|
jQuery("#edit_#{@user.id}").click();
|
718
785
|
jQuery("##{id} input[name='name']").blur();
|
786
|
+
jQuery("##{id} input[name='name']").blur();
|
719
787
|
JS
|
720
788
|
within("tr#user_#{@user.id} > .name > span") do
|
721
789
|
page.should have_content("Lucia")
|
@@ -867,6 +935,7 @@ describe "JS behaviour", :js => true do
|
|
867
935
|
$("##{id}").click();
|
868
936
|
$("##{id} select").val("5' 7\\\"");
|
869
937
|
$("##{id} select").blur();
|
938
|
+
$("##{id} select").blur();
|
870
939
|
JS
|
871
940
|
|
872
941
|
sleep 1
|
@@ -23,6 +23,14 @@ input[type=submit], input[type=button] {
|
|
23
23
|
input[type=checkbox] {
|
24
24
|
width: 1em;
|
25
25
|
}
|
26
|
+
.custom-submit {
|
27
|
+
color: white;
|
28
|
+
background-color: black;
|
29
|
+
}
|
30
|
+
.custom-cancel {
|
31
|
+
border: 2px solid red;
|
32
|
+
font-style: italic;
|
33
|
+
}
|
26
34
|
textarea {
|
27
35
|
max-height:15em;
|
28
36
|
min-width: 40em;
|
@@ -49,7 +49,7 @@
|
|
49
49
|
<tr>
|
50
50
|
<td>Country</td>
|
51
51
|
<td id="country">
|
52
|
-
<%= best_in_place @user, :country, :type => :select, :collection => @countries %>
|
52
|
+
<%= best_in_place @user, :country, :type => :select, :collection => @countries, :inner_class => :some_class %>
|
53
53
|
</td>
|
54
54
|
</tr>
|
55
55
|
<tr>
|
@@ -67,12 +67,18 @@
|
|
67
67
|
<tr>
|
68
68
|
<td>Favorite color</td>
|
69
69
|
<td id="favorite_color">
|
70
|
-
<%- opts = { :ok_button => 'Do it!', :cancel_button => 'Nope' } %>
|
70
|
+
<%- opts = { :ok_button => 'Do it!', :cancel_button => 'Nope', :ok_button_class => 'custom-submit other-custom-submit', :cancel_button_class => 'custom-cancel other-custom-cancel' } %>
|
71
71
|
<%- opts.delete(:ok_button) if params[:suppress_ok_button] %>
|
72
72
|
<%- opts[:nil] = "<span class='nil'>Click to add your favorite color</span>" %>
|
73
73
|
<%= best_in_place @user, :favorite_color, opts %>
|
74
74
|
</td>
|
75
75
|
</tr>
|
76
|
+
<tr>
|
77
|
+
<td>Favorite locale</td>
|
78
|
+
<td id="favorite_locale">
|
79
|
+
<%= best_in_place @user, :favorite_locale, :nil => "N/A" %>
|
80
|
+
</td>
|
81
|
+
</tr>
|
76
82
|
<tr>
|
77
83
|
<td>Favorite books</td>
|
78
84
|
<td id="favorite_books">
|
@@ -102,7 +108,7 @@
|
|
102
108
|
<tr>
|
103
109
|
<td>Money with proc</td>
|
104
110
|
<td id="money_proc">
|
105
|
-
<%= best_in_place @user, :money_proc, :display_with => lambda{ |v| number_to_currency(v) } %>
|
111
|
+
<%= best_in_place @user, :money_proc, :display_with => lambda{ |v| v.blank? ? "No money" : number_to_currency(v) } %>
|
106
112
|
</td>
|
107
113
|
</tr>
|
108
114
|
<tr>
|
data/test_app/db/schema.rb
CHANGED
@@ -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 =>
|
14
|
+
ActiveRecord::Schema.define(:version => 20130213224102) do
|
15
15
|
|
16
16
|
create_table "cars", :force => true do |t|
|
17
17
|
t.string "model"
|
@@ -21,20 +21,21 @@ ActiveRecord::Schema.define(:version => 20120620165212) do
|
|
21
21
|
t.string "name"
|
22
22
|
t.string "last_name"
|
23
23
|
t.string "address"
|
24
|
-
t.string "email",
|
24
|
+
t.string "email", :null => false
|
25
25
|
t.string "zip"
|
26
26
|
t.string "country"
|
27
|
-
t.datetime "created_at",
|
28
|
-
t.datetime "updated_at",
|
27
|
+
t.datetime "created_at", :null => false
|
28
|
+
t.datetime "updated_at", :null => false
|
29
29
|
t.boolean "receive_email"
|
30
30
|
t.text "description"
|
31
31
|
t.string "favorite_color"
|
32
32
|
t.text "favorite_books"
|
33
33
|
t.datetime "birth_date"
|
34
34
|
t.float "money"
|
35
|
+
t.string "favorite_movie"
|
35
36
|
t.float "money_proc"
|
36
37
|
t.string "height"
|
37
|
-
t.string "
|
38
|
+
t.string "favorite_locale"
|
38
39
|
end
|
39
40
|
|
40
41
|
end
|
metadata
CHANGED
@@ -1,91 +1,91 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: best_in_place
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.3
|
5
4
|
prerelease:
|
5
|
+
version: 2.1.0
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Bernat Farrero
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-02-19 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
|
+
prerelease: false
|
16
|
+
type: :runtime
|
15
17
|
name: rails
|
16
|
-
|
18
|
+
version_requirements: !ruby/object:Gem::Requirement
|
17
19
|
none: false
|
18
20
|
requirements:
|
19
21
|
- - ~>
|
20
22
|
- !ruby/object:Gem::Version
|
21
23
|
version: '3.1'
|
22
|
-
|
23
|
-
prerelease: false
|
24
|
-
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirement: !ruby/object:Gem::Requirement
|
25
25
|
none: false
|
26
26
|
requirements:
|
27
27
|
- - ~>
|
28
28
|
- !ruby/object:Gem::Version
|
29
29
|
version: '3.1'
|
30
30
|
- !ruby/object:Gem::Dependency
|
31
|
+
prerelease: false
|
32
|
+
type: :runtime
|
31
33
|
name: jquery-rails
|
32
|
-
|
34
|
+
version_requirements: !ruby/object:Gem::Requirement
|
33
35
|
none: false
|
34
36
|
requirements:
|
35
37
|
- - ! '>='
|
36
38
|
- !ruby/object:Gem::Version
|
37
39
|
version: '0'
|
38
|
-
|
39
|
-
prerelease: false
|
40
|
-
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirement: !ruby/object:Gem::Requirement
|
41
41
|
none: false
|
42
42
|
requirements:
|
43
43
|
- - ! '>='
|
44
44
|
- !ruby/object:Gem::Version
|
45
45
|
version: '0'
|
46
46
|
- !ruby/object:Gem::Dependency
|
47
|
+
prerelease: false
|
48
|
+
type: :development
|
47
49
|
name: rspec-rails
|
48
|
-
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
49
51
|
none: false
|
50
52
|
requirements:
|
51
53
|
- - ~>
|
52
54
|
- !ruby/object:Gem::Version
|
53
55
|
version: 2.8.0
|
54
|
-
|
55
|
-
prerelease: false
|
56
|
-
version_requirements: !ruby/object:Gem::Requirement
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
57
57
|
none: false
|
58
58
|
requirements:
|
59
59
|
- - ~>
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: 2.8.0
|
62
62
|
- !ruby/object:Gem::Dependency
|
63
|
+
prerelease: false
|
64
|
+
type: :development
|
63
65
|
name: nokogiri
|
64
|
-
|
66
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
67
|
none: false
|
66
68
|
requirements:
|
67
69
|
- - ! '>='
|
68
70
|
- !ruby/object:Gem::Version
|
69
71
|
version: '0'
|
70
|
-
|
71
|
-
prerelease: false
|
72
|
-
version_requirements: !ruby/object:Gem::Requirement
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
73
|
none: false
|
74
74
|
requirements:
|
75
75
|
- - ! '>='
|
76
76
|
- !ruby/object:Gem::Version
|
77
77
|
version: '0'
|
78
78
|
- !ruby/object:Gem::Dependency
|
79
|
+
prerelease: false
|
80
|
+
type: :development
|
79
81
|
name: capybara
|
80
|
-
|
82
|
+
version_requirements: !ruby/object:Gem::Requirement
|
81
83
|
none: false
|
82
84
|
requirements:
|
83
85
|
- - ~>
|
84
86
|
- !ruby/object:Gem::Version
|
85
87
|
version: 1.1.2
|
86
|
-
|
87
|
-
prerelease: false
|
88
|
-
version_requirements: !ruby/object:Gem::Requirement
|
88
|
+
requirement: !ruby/object:Gem::Requirement
|
89
89
|
none: false
|
90
90
|
requirements:
|
91
91
|
- - ~>
|
@@ -200,6 +200,7 @@ files:
|
|
200
200
|
- test_app/db/migrate/20120607172609_add_favorite_movie_to_users.rb
|
201
201
|
- test_app/db/migrate/20120616170454_add_money_proc_to_users.rb
|
202
202
|
- test_app/db/migrate/20120620165212_add_height_to_user.rb
|
203
|
+
- test_app/db/migrate/20130213224102_add_favorite_locale_to_users.rb
|
203
204
|
- test_app/db/schema.rb
|
204
205
|
- test_app/db/seeds.rb
|
205
206
|
- test_app/doc/README_FOR_APP
|
@@ -230,30 +231,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
230
231
|
- - ! '>='
|
231
232
|
- !ruby/object:Gem::Version
|
232
233
|
version: '0'
|
233
|
-
segments:
|
234
|
-
- 0
|
235
|
-
hash: -1762438104594404996
|
236
234
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
237
235
|
none: false
|
238
236
|
requirements:
|
239
237
|
- - ! '>='
|
240
238
|
- !ruby/object:Gem::Version
|
241
239
|
version: '0'
|
242
|
-
segments:
|
243
|
-
- 0
|
244
|
-
hash: -1762438104594404996
|
245
240
|
requirements: []
|
246
241
|
rubyforge_project: best_in_place
|
247
|
-
rubygems_version: 1.8.
|
242
|
+
rubygems_version: 1.8.25
|
248
243
|
signing_key:
|
249
244
|
specification_version: 3
|
250
245
|
summary: It makes any field in place editable by clicking on it, it works for inputs,
|
251
246
|
textareas, select dropdowns and checkboxes
|
252
|
-
test_files:
|
253
|
-
- spec/helpers/best_in_place_spec.rb
|
254
|
-
- spec/integration/double_init_spec.rb
|
255
|
-
- spec/integration/js_spec.rb
|
256
|
-
- spec/integration/live_spec.rb
|
257
|
-
- spec/integration/text_area_spec.rb
|
258
|
-
- spec/spec_helper.rb
|
259
|
-
- spec/support/retry_on_timeout.rb
|
247
|
+
test_files: []
|