best_in_place 2.0.3 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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: []
|