best_in_place 0.1.4 → 0.1.5
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/Gemfile.lock +78 -0
- data/README.md +40 -22
- data/lib/best_in_place.rb +23 -17
- data/lib/best_in_place/version.rb +1 -1
- data/public/javascripts/best_in_place.js +25 -17
- data/test_app/Gemfile +1 -1
- data/test_app/Gemfile.lock +7 -3
- data/test_app/app/views/users/show.html.erb +19 -8
- data/test_app/public/javascripts/best_in_place.js +26 -18
- data/test_app/public/stylesheets/style.css +1 -1
- metadata +5 -4
data/Gemfile.lock
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
best_in_place (0.1.4)
|
5
|
+
rails (~> 3.0.0)
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: http://rubygems.org/
|
9
|
+
specs:
|
10
|
+
abstract (1.0.0)
|
11
|
+
actionmailer (3.0.3)
|
12
|
+
actionpack (= 3.0.3)
|
13
|
+
mail (~> 2.2.9)
|
14
|
+
actionpack (3.0.3)
|
15
|
+
activemodel (= 3.0.3)
|
16
|
+
activesupport (= 3.0.3)
|
17
|
+
builder (~> 2.1.2)
|
18
|
+
erubis (~> 2.6.6)
|
19
|
+
i18n (~> 0.4)
|
20
|
+
rack (~> 1.2.1)
|
21
|
+
rack-mount (~> 0.6.13)
|
22
|
+
rack-test (~> 0.5.6)
|
23
|
+
tzinfo (~> 0.3.23)
|
24
|
+
activemodel (3.0.3)
|
25
|
+
activesupport (= 3.0.3)
|
26
|
+
builder (~> 2.1.2)
|
27
|
+
i18n (~> 0.4)
|
28
|
+
activerecord (3.0.3)
|
29
|
+
activemodel (= 3.0.3)
|
30
|
+
activesupport (= 3.0.3)
|
31
|
+
arel (~> 2.0.2)
|
32
|
+
tzinfo (~> 0.3.23)
|
33
|
+
activeresource (3.0.3)
|
34
|
+
activemodel (= 3.0.3)
|
35
|
+
activesupport (= 3.0.3)
|
36
|
+
activesupport (3.0.3)
|
37
|
+
arel (2.0.7)
|
38
|
+
builder (2.1.2)
|
39
|
+
erubis (2.6.6)
|
40
|
+
abstract (>= 1.0.0)
|
41
|
+
i18n (0.5.0)
|
42
|
+
mail (2.2.14)
|
43
|
+
activesupport (>= 2.3.6)
|
44
|
+
i18n (>= 0.4.0)
|
45
|
+
mime-types (~> 1.16)
|
46
|
+
treetop (~> 1.4.8)
|
47
|
+
mime-types (1.16)
|
48
|
+
polyglot (0.3.1)
|
49
|
+
rack (1.2.1)
|
50
|
+
rack-mount (0.6.13)
|
51
|
+
rack (>= 1.0.0)
|
52
|
+
rack-test (0.5.7)
|
53
|
+
rack (>= 1.0)
|
54
|
+
rails (3.0.3)
|
55
|
+
actionmailer (= 3.0.3)
|
56
|
+
actionpack (= 3.0.3)
|
57
|
+
activerecord (= 3.0.3)
|
58
|
+
activeresource (= 3.0.3)
|
59
|
+
activesupport (= 3.0.3)
|
60
|
+
bundler (~> 1.0)
|
61
|
+
railties (= 3.0.3)
|
62
|
+
railties (3.0.3)
|
63
|
+
actionpack (= 3.0.3)
|
64
|
+
activesupport (= 3.0.3)
|
65
|
+
rake (>= 0.8.7)
|
66
|
+
thor (~> 0.14.4)
|
67
|
+
rake (0.8.7)
|
68
|
+
thor (0.14.6)
|
69
|
+
treetop (1.4.9)
|
70
|
+
polyglot (>= 0.3.1)
|
71
|
+
tzinfo (0.3.24)
|
72
|
+
|
73
|
+
PLATFORMS
|
74
|
+
ruby
|
75
|
+
|
76
|
+
DEPENDENCIES
|
77
|
+
best_in_place!
|
78
|
+
rails (~> 3.0.0)
|
data/README.md
CHANGED
@@ -19,48 +19,60 @@ The editor works by PUTting the updated value to the server and GETting the upda
|
|
19
19
|
- Compatible with text **inputs**
|
20
20
|
- Compatible with **textarea**
|
21
21
|
- Compatible with **select** dropdown with custom collections
|
22
|
-
- Compatible with custom boolean values (
|
22
|
+
- Compatible with custom boolean values (same usage of **checkboxes**)
|
23
23
|
- Sanitize HTML and trim spaces of user's input
|
24
24
|
- Displays server-side **validation** errors
|
25
|
+
- Allows external activator
|
26
|
+
- ESC key destroys changes
|
25
27
|
|
26
28
|
---
|
27
29
|
|
28
30
|
##Usage of Rails 3 Gem
|
29
31
|
|
30
|
-
**best_in_place
|
32
|
+
**best_in_place object, field, OPTIONS**
|
33
|
+
|
34
|
+
Params:
|
35
|
+
|
36
|
+
- **object** (Mandatory): The Object parameter represents the object itself you are about to modify
|
37
|
+
- **field** (Mandatory): The field (passed as symbol) is the attribute of the Object you are going to display/edit.
|
38
|
+
|
39
|
+
Options:
|
40
|
+
|
41
|
+
- **:type** It can be only [:input, :textarea, :select, :checkbox] or if undefined it defaults to :input.
|
42
|
+
- **:collection**: In case you are using the :select type then you must specify the collection of values it takes. In case you are
|
43
|
+
using the :checkbox type you can specify the two values it can take, or otherwise they will default to Yes and No.
|
44
|
+
- **:path**: URL to which the updating action will be sent. If not defined it defaults to the :object path.
|
45
|
+
- **:nil**: The nil param defines the content displayed in case no value is defined for that field. It can be something like "click me to edit".
|
46
|
+
If not defined it will show *"-"*.
|
47
|
+
- **:activator**: Is the DOM object that can activate the field. If not defined the user will making editable by clicking on it.
|
31
48
|
|
32
|
-
The *Object* parameter represents the object itself you are about to modify. The *field* (passed as symbol) is the attribute of the Object
|
33
|
-
you are going to display/edit. You can add the *formType* [:input, :textarea, :select, :checkbox] or it defaults to :input. In case you chose
|
34
|
-
:select, you must specify the collection of values it takes through the *selectValues* param. In case you use :checkbox, you can user the parameter
|
35
|
-
selectValues to specify the two possible boolean values. If the Object url cannot be obtained directly from the Object, you can pass the parameter
|
36
|
-
*urlObject* the same way you pass any url in Rails. The last parameter *nilValue* allows you to customize the null value, in case the user deletes
|
37
|
-
the contents. By default it will display *"-"*.
|
38
49
|
|
39
50
|
I created a [test_app](https://github.com/bernat/best_in_place/tree/master/test_app) and a running demo in heroku to test the features.
|
40
51
|
|
41
|
-
Examples (code
|
52
|
+
Examples (code in the views):
|
42
53
|
|
43
54
|
### Input
|
44
55
|
|
45
|
-
<%= best_in_place @user, :name, :input %>
|
56
|
+
<%= best_in_place @user, :name, :type => :input %>
|
46
57
|
|
47
|
-
<%= best_in_place @user, :name, :input, nil
|
58
|
+
<%= best_in_place @user, :name, :type => :input, :nil => "Click me to add content!" %>
|
48
59
|
|
49
60
|
### Textarea
|
50
61
|
|
51
|
-
<%= best_in_place @user, :description, :textarea %>
|
62
|
+
<%= best_in_place @user, :description, :type => :textarea %>
|
52
63
|
|
53
64
|
### Select
|
54
65
|
|
55
|
-
<%= best_in_place @user, :country, :select, [[1, "Spain"], [2, "Italy"], [3, "Germany"], [4, "France"]] %>
|
66
|
+
<%= best_in_place @user, :country, :type => :select, :collection => [[1, "Spain"], [2, "Italy"], [3, "Germany"], [4, "France"]] %>
|
56
67
|
|
57
|
-
Of course it can take an instance or global variable for the collection, just remember the structure [[key, value], [key, value],...]
|
68
|
+
Of course it can take an instance or global variable for the collection, just remember the structure [[key, value], [key, value],...].
|
69
|
+
The key can be a string or an integer.
|
58
70
|
|
59
71
|
### Checkbox
|
60
72
|
|
61
|
-
<%= best_in_place @user, :receive_emails, :checkbox, ["No, thanks", "Yes, of course!"] %>
|
73
|
+
<%= best_in_place @user, :receive_emails, :type => :checkbox, :collection => ["No, thanks", "Yes, of course!"] %>
|
62
74
|
|
63
|
-
The first value is always the negative boolean value and the second the positive [false, true].
|
75
|
+
The first value is always the negative boolean value and the second the positive. Structure: ["false value", "true value"].
|
64
76
|
If not defined, it will default to *Yes* and *No* options.
|
65
77
|
|
66
78
|
### Display server validation errors
|
@@ -99,7 +111,7 @@ At the same time, you must define the restrictions, validations and error messag
|
|
99
111
|
:format => {:with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i, :message => "has wrong email format"}
|
100
112
|
validates :zip, :numericality => true, :length => { :minimum => 5 }
|
101
113
|
end
|
102
|
-
|
114
|
+
|
103
115
|
When the user tries to introduce invalid data, the error messages defined in the model will be displayed in pop-up windows using the jQuery.purr plugin.
|
104
116
|
|
105
117
|
---
|
@@ -113,7 +125,8 @@ in the following order:
|
|
113
125
|
- jquery.purr.js
|
114
126
|
- **best_in_place.js**
|
115
127
|
|
116
|
-
The last one you can copy it (and keeping up to date to the last version) by running the following generator in your application's root
|
128
|
+
The last one you can copy it (and keeping up to date to the last version) by running the following generator in your application's root.
|
129
|
+
Remember to do it every time you update the gem (or you will see no change).
|
117
130
|
|
118
131
|
rails g best_in_place:setup
|
119
132
|
|
@@ -133,9 +146,8 @@ In order to use the Rails 3 gem, just add the following line to the gemfile:
|
|
133
146
|
##TODO
|
134
147
|
|
135
148
|
- Client Side Validation definitions
|
136
|
-
-
|
137
|
-
-
|
138
|
-
- Specs
|
149
|
+
- Accepting more than one handler to activate best_in_place fields
|
150
|
+
- Specs *(sacrilege!!)*
|
139
151
|
|
140
152
|
---
|
141
153
|
|
@@ -144,7 +156,13 @@ In order to use the Rails 3 gem, just add the following line to the gemfile:
|
|
144
156
|
- v.0.1.0 Initial deploy
|
145
157
|
- v.0.1.2 Fixing errors in collections (taken value[0] instead of index) and fixing test_app controller responses
|
146
158
|
- v.0.1.3 Bug in Rails Helper. Key wrongly considered an Integer.
|
159
|
+
- v.0.1.4 Adding two new parameters for further customization urlObject and nilValue and making input update on blur.
|
160
|
+
- v.0.1.5 **Attention: this release is not backwards compatible**. Changing params from list to option hash, helper's refactoring,
|
161
|
+
fixing bug with objects inside namespaces, adding feature for passing an external activator handler as param. Adding feature
|
162
|
+
of key ESCAPE for destroying changes before they are made permanent (in inputs and textarea).
|
147
163
|
|
148
164
|
##Authors, License and Stuff
|
149
165
|
|
150
|
-
Code by [Bernat Farrero](http://bernatfarrero.com) based on the [original project](http://github.com/janv/rest_in_place/) of Jan Varwig and released under [MIT](http://www.opensource.org/licenses/mit-license.php).
|
166
|
+
Code by [Bernat Farrero](http://bernatfarrero.com) (based on the [original project](http://github.com/janv/rest_in_place/) of Jan Varwig) and released under [MIT](http://www.opensource.org/licenses/mit-license.php).
|
167
|
+
|
168
|
+
Many thanks to the contributors: Specially [Roger Campos](http://github.com/rogercampos)
|
data/lib/best_in_place.rb
CHANGED
@@ -1,27 +1,33 @@
|
|
1
1
|
module BestInPlace
|
2
2
|
module BestInPlaceHelpers
|
3
|
-
def best_in_place(object, field,
|
3
|
+
def best_in_place(object, field, opts = {})
|
4
|
+
opts[:type] ||= :input
|
5
|
+
opts[:collection] ||= []
|
6
|
+
opts[:nil] ||= "-"
|
4
7
|
field = field.to_s
|
5
|
-
value = object.send(field).blank? ?
|
6
|
-
|
7
|
-
|
8
|
-
|
8
|
+
value = object.send(field).blank? ? opts[:nil].to_s : object.send(field)
|
9
|
+
collection = nil
|
10
|
+
if opts[:type] == :select && !opts[:collection].blank?
|
11
|
+
v = object.send(field)
|
12
|
+
value = Hash[opts[:collection]][!!(v =~ /^[0-9]+$/) ? v.to_i : v]
|
13
|
+
collection = opts[:collection].to_json
|
9
14
|
end
|
10
|
-
if
|
15
|
+
if opts[:type] == :checkbox
|
11
16
|
fieldValue = !!object.send(field)
|
12
|
-
if
|
13
|
-
|
17
|
+
if opts[:collection].blank? || opts[:collection].size != 2
|
18
|
+
opts[:collection] = ["No", "Yes"]
|
14
19
|
end
|
15
|
-
value = fieldValue ?
|
16
|
-
|
20
|
+
value = fieldValue ? opts[:collection][1] : opts[:collection][0]
|
21
|
+
collection = opts[:collection].to_json
|
17
22
|
end
|
18
23
|
out = "<span class='best_in_place'"
|
19
|
-
out += " id='best_in_place_" + object.class.to_s.
|
20
|
-
out += " data-url='" + (
|
21
|
-
out += " data-object='" + object.class.to_s.underscore + "'"
|
22
|
-
out += " data-
|
23
|
-
out += " data-attribute='
|
24
|
-
out += " data-
|
24
|
+
out += " id='best_in_place_" + object.class.to_s.gsub("::", "_").underscore + "_#{field}"
|
25
|
+
out += " data-url='" + (opts[:path].blank? ? url_for(object).to_s : url_for(opts[:path])) + "'"
|
26
|
+
out += " data-object='" + object.class.to_s.gsub("::", "_").underscore + "'"
|
27
|
+
out += " data-collection='#{collection}'" unless collection.blank?
|
28
|
+
out += " data-attribute='#{field}'"
|
29
|
+
out += " data-activator='#{opts[:activator].to_s}'" unless opts[:activator].blank?
|
30
|
+
out += " data-type='#{opts[:type].to_s}'>"
|
25
31
|
out += value.to_s
|
26
32
|
out += "</span>"
|
27
33
|
raw(out)
|
@@ -30,4 +36,4 @@ module BestInPlace
|
|
30
36
|
end
|
31
37
|
|
32
38
|
|
33
|
-
ActionView::Base.send(:include, BestInPlace::BestInPlaceHelpers)
|
39
|
+
ActionView::Base.send(:include, BestInPlace::BestInPlaceHelpers)
|
@@ -23,7 +23,7 @@ function BestInPlaceEditor(e) {
|
|
23
23
|
this.element = jQuery(e)
|
24
24
|
this.initOptions()
|
25
25
|
this.bindForm()
|
26
|
-
this.activator.bind('click', {editor: this}, this.clickHandler)
|
26
|
+
$(this.activator).bind('click', {editor: this}, this.clickHandler)
|
27
27
|
}
|
28
28
|
|
29
29
|
BestInPlaceEditor.prototype = {
|
@@ -32,12 +32,13 @@ BestInPlaceEditor.prototype = {
|
|
32
32
|
activate : function() {
|
33
33
|
var elem = this.element.html()
|
34
34
|
this.oldValue = elem
|
35
|
-
this.activator.unbind("click", this.clickHandler)
|
35
|
+
$(this.activator).unbind("click", this.clickHandler)
|
36
36
|
this.activateForm()
|
37
37
|
},
|
38
38
|
|
39
39
|
abort : function() {
|
40
|
-
this.element.html(this.oldValue)
|
40
|
+
this.element.html(this.oldValue)
|
41
|
+
$(this.activator).bind('click', {editor: this}, this.clickHandler)
|
41
42
|
},
|
42
43
|
|
43
44
|
update : function() {
|
@@ -68,8 +69,8 @@ BestInPlaceEditor.prototype = {
|
|
68
69
|
var self = this
|
69
70
|
self.element.parents().each(function(){
|
70
71
|
self.url = self.url || jQuery(this).attr("data-url")
|
71
|
-
self.
|
72
|
-
self.formType = self.formType || jQuery(this).attr("data-
|
72
|
+
self.collection = self.collection || jQuery(this).attr("data-collection")
|
73
|
+
self.formType = self.formType || jQuery(this).attr("data-type")
|
73
74
|
self.objectName = self.objectName || jQuery(this).attr("data-object")
|
74
75
|
self.attributeName = self.attributeName || jQuery(this).attr("data-attribute")
|
75
76
|
})
|
@@ -83,15 +84,15 @@ BestInPlaceEditor.prototype = {
|
|
83
84
|
|
84
85
|
// Load own attributes (overrides all others)
|
85
86
|
self.url = self.element.attr("data-url") || self.url || document.location.pathname
|
86
|
-
self.
|
87
|
-
self.formType = self.element.attr("data-
|
87
|
+
self.collection = self.element.attr("data-collection") || self.collection
|
88
|
+
self.formType = self.element.attr("data-type") || self.formtype || "input"
|
88
89
|
self.objectName = self.element.attr("data-object") || self.objectName
|
89
90
|
self.attributeName = self.element.attr("data-attribute") || self.attributeName
|
90
91
|
self.activator = self.element.attr("data-activator") || self.element
|
91
92
|
|
92
|
-
if ((self.formType == "select" || self.formType == "checkbox") && self.
|
93
|
+
if ((self.formType == "select" || self.formType == "checkbox") && self.collection != null)
|
93
94
|
{
|
94
|
-
self.values = jQuery.parseJSON(self.
|
95
|
+
self.values = jQuery.parseJSON(self.collection)
|
95
96
|
}
|
96
97
|
},
|
97
98
|
|
@@ -136,7 +137,7 @@ BestInPlaceEditor.prototype = {
|
|
136
137
|
this.element.html(data[this.objectName])
|
137
138
|
|
138
139
|
// Binding back after being clicked
|
139
|
-
this.
|
140
|
+
$(this.activator).bind('click', {editor: this}, this.clickHandler)
|
140
141
|
},
|
141
142
|
|
142
143
|
loadErrorCallback : function(request, error) {
|
@@ -149,7 +150,7 @@ BestInPlaceEditor.prototype = {
|
|
149
150
|
})
|
150
151
|
|
151
152
|
// Binding back after being clicked
|
152
|
-
this.
|
153
|
+
$(this.activator).bind('click', {editor: this}, this.clickHandler)
|
153
154
|
},
|
154
155
|
|
155
156
|
clickHandler : function(event) {
|
@@ -164,10 +165,9 @@ BestInPlaceEditor.forms = {
|
|
164
165
|
var form = '<form class="form_in_place" action="javascript:void(0)" style="display:inline;"><input type="text" value="' + this.sanitize(this.oldValue) + '"></form>'
|
165
166
|
this.element.html(form)
|
166
167
|
this.element.find('input')[0].select()
|
167
|
-
this.element.find("form")
|
168
|
-
|
169
|
-
this.element.find("input")
|
170
|
-
.bind('blur', {editor: this}, BestInPlaceEditor.forms.input.inputBlurHandler)
|
168
|
+
this.element.find("form").bind('submit', {editor: this}, BestInPlaceEditor.forms.input.submitHandler)
|
169
|
+
this.element.find("input").bind('blur', {editor: this}, BestInPlaceEditor.forms.input.inputBlurHandler)
|
170
|
+
this.element.find("input").bind('keyup', {editor: this}, BestInPlaceEditor.forms.input.keyupHandler)
|
171
171
|
},
|
172
172
|
|
173
173
|
getValue : function() {
|
@@ -180,7 +180,10 @@ BestInPlaceEditor.forms = {
|
|
180
180
|
|
181
181
|
submitHandler : function(event) {
|
182
182
|
event.data.editor.update()
|
183
|
-
|
183
|
+
},
|
184
|
+
|
185
|
+
keyupHandler : function(event) {
|
186
|
+
if (event.keyCode == 27) event.data.editor.abort()
|
184
187
|
}
|
185
188
|
},
|
186
189
|
|
@@ -204,7 +207,7 @@ BestInPlaceEditor.forms = {
|
|
204
207
|
|
205
208
|
blurHandler : function(event) {
|
206
209
|
event.data.editor.update()
|
207
|
-
}
|
210
|
+
},
|
208
211
|
},
|
209
212
|
|
210
213
|
"checkbox" : {
|
@@ -225,6 +228,7 @@ BestInPlaceEditor.forms = {
|
|
225
228
|
this.element.html('<form action="javascript:void(0)" style="display:inline;"><textarea>' + this.sanitize(this.oldValue) + '</textarea></form>')
|
226
229
|
this.element.find('textarea')[0].select()
|
227
230
|
this.element.find("textarea").bind('blur', {editor: this}, BestInPlaceEditor.forms.textarea.blurHandler)
|
231
|
+
this.element.find("textarea").bind('keyup', {editor: this}, BestInPlaceEditor.forms.textarea.keyupHandler)
|
228
232
|
},
|
229
233
|
|
230
234
|
getValue : function() {
|
@@ -233,6 +237,10 @@ BestInPlaceEditor.forms = {
|
|
233
237
|
|
234
238
|
blurHandler : function(event) {
|
235
239
|
event.data.editor.update()
|
240
|
+
},
|
241
|
+
|
242
|
+
keyupHandler : function(event) {
|
243
|
+
if (event.keyCode == 27) event.data.editor.abort()
|
236
244
|
}
|
237
245
|
|
238
246
|
}
|
data/test_app/Gemfile
CHANGED
data/test_app/Gemfile.lock
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
PATH
|
2
|
+
remote: ..
|
3
|
+
specs:
|
4
|
+
best_in_place (0.1.5)
|
5
|
+
rails (~> 3.0.0)
|
6
|
+
|
1
7
|
GEM
|
2
8
|
remote: http://rubygems.org/
|
3
9
|
specs:
|
@@ -30,8 +36,6 @@ GEM
|
|
30
36
|
activesupport (3.0.0)
|
31
37
|
arel (1.0.1)
|
32
38
|
activesupport (~> 3.0.0)
|
33
|
-
best_in_place (0.1.1)
|
34
|
-
rails (~> 3.0.0)
|
35
39
|
builder (2.1.2)
|
36
40
|
erubis (2.6.6)
|
37
41
|
abstract (>= 1.0.0)
|
@@ -71,6 +75,6 @@ PLATFORMS
|
|
71
75
|
ruby
|
72
76
|
|
73
77
|
DEPENDENCIES
|
74
|
-
best_in_place
|
78
|
+
best_in_place!
|
75
79
|
rails (= 3.0.0)
|
76
80
|
sqlite3-ruby
|
@@ -1,12 +1,13 @@
|
|
1
1
|
<p id="notice"><%= notice %></p>
|
2
2
|
<div id="user_account">
|
3
3
|
<h1>User details</h1>
|
4
|
-
|
4
|
+
<%= link_to "Go back to USERS", users_path %>
|
5
|
+
<p style="margin-left:48em">Click to edit</p>
|
5
6
|
<table>
|
6
7
|
<tr>
|
7
|
-
<td>Name</td>
|
8
|
+
<td>Name <a id="editme" href="#">(edit me)</a></td>
|
8
9
|
<td>
|
9
|
-
<%= best_in_place @user, :name, :input %>
|
10
|
+
<%= best_in_place @user, :name, :type => :input, :activator => "#editme" %>
|
10
11
|
</td>
|
11
12
|
</tr>
|
12
13
|
<tr>
|
@@ -36,22 +37,32 @@
|
|
36
37
|
<tr>
|
37
38
|
<td>Country</td>
|
38
39
|
<td>
|
39
|
-
<%= best_in_place @user, :country, :select, @countries %>
|
40
|
+
<%= best_in_place @user, :country, {:type => :select, :collection => @countries} %>
|
41
|
+
<!-- <%= @countries.inspect %> -->
|
40
42
|
</td>
|
41
43
|
</tr>
|
42
44
|
<tr>
|
43
45
|
<td>Receive newsletter?</td>
|
44
46
|
<td>
|
45
|
-
<%= best_in_place @user, :receive_email, :checkbox, ["No thanks", "Yes of course"] %>
|
47
|
+
<%= best_in_place @user, :receive_email, {:type => :checkbox, :collection => ["No thanks", "Yes of course"]} %>
|
46
48
|
</td>
|
47
49
|
</tr>
|
48
50
|
<tr>
|
49
51
|
<td>User description</td>
|
50
52
|
<td>
|
51
|
-
<%= best_in_place @user, :description, :textarea %>
|
53
|
+
<%= best_in_place @user, :description, :type => :textarea %>
|
52
54
|
</td>
|
53
55
|
</table>
|
54
|
-
|
55
|
-
|
56
|
+
<br />
|
57
|
+
<hr />
|
58
|
+
<p>Try the <b>features of Best In Place</b>:</p>
|
59
|
+
<ul>
|
60
|
+
<li>Try giving wrong email values or too short address, inputs to see server errors.</li>
|
61
|
+
<li>Click on newsletter to change a boolean value</li>
|
62
|
+
<li>Click on country to change the value in a collection of values</li>
|
63
|
+
<li>Use the external handler to change the value of the name</li>
|
64
|
+
<li>Try making changes inside inputs or textareas and then press the ESC key to recover the old value</li>
|
65
|
+
</ul>
|
66
|
+
<p>More information on <a href="http://github.com/bernat/best_in_place">github</a> or <a href="http://blog.bernatfarrero.com/in-place-editing-with-javascript-jquery-and-rails-3/">bernatfarrero.com</a>.</p>
|
56
67
|
|
57
68
|
</div>
|
@@ -23,7 +23,7 @@ function BestInPlaceEditor(e) {
|
|
23
23
|
this.element = jQuery(e)
|
24
24
|
this.initOptions()
|
25
25
|
this.bindForm()
|
26
|
-
this.activator.bind('click', {editor: this}, this.clickHandler)
|
26
|
+
$(this.activator).bind('click', {editor: this}, this.clickHandler)
|
27
27
|
}
|
28
28
|
|
29
29
|
BestInPlaceEditor.prototype = {
|
@@ -32,12 +32,13 @@ BestInPlaceEditor.prototype = {
|
|
32
32
|
activate : function() {
|
33
33
|
var elem = this.element.html()
|
34
34
|
this.oldValue = elem
|
35
|
-
this.activator.unbind("click", this.clickHandler)
|
35
|
+
$(this.activator).unbind("click", this.clickHandler)
|
36
36
|
this.activateForm()
|
37
37
|
},
|
38
38
|
|
39
39
|
abort : function() {
|
40
|
-
this.element.html(this.oldValue)
|
40
|
+
this.element.html(this.oldValue)
|
41
|
+
$(this.activator).bind('click', {editor: this}, this.clickHandler)
|
41
42
|
},
|
42
43
|
|
43
44
|
update : function() {
|
@@ -68,8 +69,8 @@ BestInPlaceEditor.prototype = {
|
|
68
69
|
var self = this
|
69
70
|
self.element.parents().each(function(){
|
70
71
|
self.url = self.url || jQuery(this).attr("data-url")
|
71
|
-
self.
|
72
|
-
self.formType = self.formType || jQuery(this).attr("data-
|
72
|
+
self.collection = self.collection || jQuery(this).attr("data-collection")
|
73
|
+
self.formType = self.formType || jQuery(this).attr("data-type")
|
73
74
|
self.objectName = self.objectName || jQuery(this).attr("data-object")
|
74
75
|
self.attributeName = self.attributeName || jQuery(this).attr("data-attribute")
|
75
76
|
})
|
@@ -83,15 +84,15 @@ BestInPlaceEditor.prototype = {
|
|
83
84
|
|
84
85
|
// Load own attributes (overrides all others)
|
85
86
|
self.url = self.element.attr("data-url") || self.url || document.location.pathname
|
86
|
-
self.
|
87
|
-
self.formType = self.element.attr("data-
|
87
|
+
self.collection = self.element.attr("data-collection") || self.collection
|
88
|
+
self.formType = self.element.attr("data-type") || self.formtype || "input"
|
88
89
|
self.objectName = self.element.attr("data-object") || self.objectName
|
89
90
|
self.attributeName = self.element.attr("data-attribute") || self.attributeName
|
90
91
|
self.activator = self.element.attr("data-activator") || self.element
|
91
92
|
|
92
|
-
if ((self.formType == "select" || self.formType == "checkbox") && self.
|
93
|
+
if ((self.formType == "select" || self.formType == "checkbox") && self.collection != null)
|
93
94
|
{
|
94
|
-
self.values = jQuery.parseJSON(self.
|
95
|
+
self.values = jQuery.parseJSON(self.collection)
|
95
96
|
}
|
96
97
|
},
|
97
98
|
|
@@ -136,7 +137,7 @@ BestInPlaceEditor.prototype = {
|
|
136
137
|
this.element.html(data[this.objectName])
|
137
138
|
|
138
139
|
// Binding back after being clicked
|
139
|
-
this.
|
140
|
+
$(this.activator).bind('click', {editor: this}, this.clickHandler)
|
140
141
|
},
|
141
142
|
|
142
143
|
loadErrorCallback : function(request, error) {
|
@@ -149,7 +150,7 @@ BestInPlaceEditor.prototype = {
|
|
149
150
|
})
|
150
151
|
|
151
152
|
// Binding back after being clicked
|
152
|
-
this.
|
153
|
+
$(this.activator).bind('click', {editor: this}, this.clickHandler)
|
153
154
|
},
|
154
155
|
|
155
156
|
clickHandler : function(event) {
|
@@ -164,10 +165,9 @@ BestInPlaceEditor.forms = {
|
|
164
165
|
var form = '<form class="form_in_place" action="javascript:void(0)" style="display:inline;"><input type="text" value="' + this.sanitize(this.oldValue) + '"></form>'
|
165
166
|
this.element.html(form)
|
166
167
|
this.element.find('input')[0].select()
|
167
|
-
this.element.find("form")
|
168
|
-
|
169
|
-
this.element.find("input")
|
170
|
-
.bind('blur', {editor: this}, BestInPlaceEditor.forms.input.inputBlurHandler)
|
168
|
+
this.element.find("form").bind('submit', {editor: this}, BestInPlaceEditor.forms.input.submitHandler)
|
169
|
+
this.element.find("input").bind('blur', {editor: this}, BestInPlaceEditor.forms.input.inputBlurHandler)
|
170
|
+
this.element.find("input").bind('keyup', {editor: this}, BestInPlaceEditor.forms.input.keyupHandler)
|
171
171
|
},
|
172
172
|
|
173
173
|
getValue : function() {
|
@@ -175,12 +175,15 @@ BestInPlaceEditor.forms = {
|
|
175
175
|
},
|
176
176
|
|
177
177
|
inputBlurHandler : function(event) {
|
178
|
-
event.data.editor.
|
178
|
+
event.data.editor.update()
|
179
179
|
},
|
180
180
|
|
181
181
|
submitHandler : function(event) {
|
182
182
|
event.data.editor.update()
|
183
|
-
|
183
|
+
},
|
184
|
+
|
185
|
+
keyupHandler : function(event) {
|
186
|
+
if (event.keyCode == 27) event.data.editor.abort()
|
184
187
|
}
|
185
188
|
},
|
186
189
|
|
@@ -204,7 +207,7 @@ BestInPlaceEditor.forms = {
|
|
204
207
|
|
205
208
|
blurHandler : function(event) {
|
206
209
|
event.data.editor.update()
|
207
|
-
}
|
210
|
+
},
|
208
211
|
},
|
209
212
|
|
210
213
|
"checkbox" : {
|
@@ -225,6 +228,7 @@ BestInPlaceEditor.forms = {
|
|
225
228
|
this.element.html('<form action="javascript:void(0)" style="display:inline;"><textarea>' + this.sanitize(this.oldValue) + '</textarea></form>')
|
226
229
|
this.element.find('textarea')[0].select()
|
227
230
|
this.element.find("textarea").bind('blur', {editor: this}, BestInPlaceEditor.forms.textarea.blurHandler)
|
231
|
+
this.element.find("textarea").bind('keyup', {editor: this}, BestInPlaceEditor.forms.textarea.keyupHandler)
|
228
232
|
},
|
229
233
|
|
230
234
|
getValue : function() {
|
@@ -233,6 +237,10 @@ BestInPlaceEditor.forms = {
|
|
233
237
|
|
234
238
|
blurHandler : function(event) {
|
235
239
|
event.data.editor.update()
|
240
|
+
},
|
241
|
+
|
242
|
+
keyupHandler : function(event) {
|
243
|
+
if (event.keyCode == 27) event.data.editor.abort()
|
236
244
|
}
|
237
245
|
|
238
246
|
}
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: best_in_place
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 17
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 5
|
10
|
+
version: 0.1.5
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Bernat Farrero
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-01-
|
18
|
+
date: 2011-01-26 00:00:00 +01:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -46,6 +46,7 @@ extra_rdoc_files: []
|
|
46
46
|
files:
|
47
47
|
- .gitignore
|
48
48
|
- Gemfile
|
49
|
+
- Gemfile.lock
|
49
50
|
- README.md
|
50
51
|
- Rakefile
|
51
52
|
- best_in_place.gemspec
|