best_in_place 0.1.4 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- 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
|