x-editable-rails 1.5.1 → 1.5.5.1
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.
- checksums.yaml +4 -4
- data/README.md +17 -13
- data/lib/x-editable-rails/version.rb +2 -2
- data/lib/x-editable-rails/view_helpers.rb +66 -41
- data/vendor/assets/javascripts/editable/bootstrap-editable.js +336 -203
- data/vendor/assets/javascripts/editable/bootstrap2-editable.js +308 -202
- data/vendor/assets/javascripts/editable/inputs-ext/wysihtml5-editable.js +9 -1
- data/vendor/assets/javascripts/editable/jquery-editable-poshytip.js +315 -202
- data/vendor/assets/javascripts/editable/jqueryui-editable.js +316 -203
- data/vendor/assets/javascripts/editable/rails/editable_form.js.coffee +14 -18
- data/vendor/assets/javascripts/editable/rails/error_handling.js.coffee +4 -0
- data/vendor/assets/javascripts/editable/rails.js.coffee +2 -1
- data/vendor/assets/stylesheets/editable/bootstrap-editable.scss +25 -25
- data/vendor/assets/stylesheets/editable/bootstrap2-editable.scss +25 -25
- metadata +19 -32
- /data/vendor/assets/stylesheets/editable/inputs-ext/{bootstrap-typehead.css → bootstrap-typeahead.css} +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fee9739c77324495b6e7a6227d85fdb2f77c972b
|
4
|
+
data.tar.gz: fd6565d1908e346778674f1f42f95f235c335f01
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5d3c95a332e7da5252af57f86fb0ae39d171566d7f616b09f9d691073fbd1051e64b53e35ff9f13dbd124f57b55901e2a2cbc3295451749f1a2997627b55ff05
|
7
|
+
data.tar.gz: d43ebe0f3957a31e1c8c6476494f869f37bd456af8878d4993363130de8b41795df1dd9012ed1948e32c1ba74fdad34af06085062a03a4e46368d0b703a6740a
|
data/README.md
CHANGED
@@ -1,7 +1,13 @@
|
|
1
1
|
# X::Editable::Rails
|
2
2
|
|
3
|
+
[](https://travis-ci.org/werein/x-editable-rails) [](https://codeclimate.com/github/werein/x-editable-rails) [](https://codeclimate.com/github/werein/x-editable-rails) [](https://badge.fury.io/rb/x-editable-rails) [](https://gemnasium.com/werein/x-editable-rails)
|
4
|
+
|
3
5
|
X-editable for Rails
|
4
6
|
|
7
|
+
## Live demo
|
8
|
+
|
9
|
+
Checkout live demo [here](https://x-editable-rails.herokuapp.com/?denied=true)
|
10
|
+
|
5
11
|
## Installation
|
6
12
|
|
7
13
|
Add this line to your application's Gemfile:
|
@@ -75,8 +81,8 @@ And related stylesheets:
|
|
75
81
|
|
76
82
|
### Making Things Editable
|
77
83
|
|
78
|
-
`x-editable-rails` provides a helper method in your view to make your model values editable.
|
79
|
-
By default, you need to specify the model and property that should be editable.
|
84
|
+
`x-editable-rails` provides a helper method in your view to make your model values editable.
|
85
|
+
By default, you need to specify the model and property that should be editable.
|
80
86
|
A `span` element is rendered with `data-*` attributes used by `x-editable`.
|
81
87
|
|
82
88
|
```ruby
|
@@ -120,7 +126,7 @@ classes = { "Active" => "label-success", "Disabled" => "label-default" }
|
|
120
126
|
editable @model, :enabled, source: source, classes: classes, class: "label"
|
121
127
|
```
|
122
128
|
|
123
|
-
* **nested** - Name of a nested attributes (such as [
|
129
|
+
* **nested** - Name of a nested attributes (such as [globalize](https://github.com/globalize/globalize)'s `translations`)
|
124
130
|
* **nid** - ID of the nested attribute
|
125
131
|
|
126
132
|
```ruby
|
@@ -135,18 +141,16 @@ editable @model, :enabled, source: source, classes: classes, class: "label"
|
|
135
141
|
Add a helper method to your controllers to indicate if `x-editable` should be enabled.
|
136
142
|
|
137
143
|
```ruby
|
138
|
-
def xeditable?
|
144
|
+
def xeditable? object = nil
|
139
145
|
true # Or something like current_user.xeditable?
|
140
146
|
end
|
141
147
|
```
|
142
148
|
|
143
|
-
|
149
|
+
You can use [CanCan](https://github.com/ryanb/cancan) and checks the `:edit` permission for the model being edited.
|
144
150
|
|
145
151
|
```ruby
|
146
|
-
|
147
|
-
|
148
|
-
else
|
149
|
-
... output uneditable value ...
|
152
|
+
def xeditable? object = nil
|
153
|
+
can?(:edit, object) ? true : false
|
150
154
|
end
|
151
155
|
```
|
152
156
|
|
@@ -154,14 +158,14 @@ end
|
|
154
158
|
|
155
159
|
### "Don't Repeat Yourself" Templates
|
156
160
|
|
157
|
-
To make your views cleaner, you can specify all your options for each class and attribute in a YAML configuration file.
|
161
|
+
To make your views cleaner, you can specify all your options for each class and attribute in a YAML configuration file.
|
158
162
|
Attributes where the `title` or `placeholder` are not different except maybe capitalized can be left out because they are automatically capitalized when rendered (see above).
|
159
163
|
|
160
|
-
This example uses the `MailingList` class and its attributes.
|
161
|
-
The attribute value can be a string, which is used as the `title` and `placeholder`.
|
164
|
+
This example uses the `MailingList` class and its attributes.
|
165
|
+
The attribute value can be a string, which is used as the `title` and `placeholder`.
|
162
166
|
If you want to specify other options, create a hash of options.
|
163
167
|
|
164
|
-
Install configuration file like this: `rails g x_editable_rails:install`, this step is not necessary
|
168
|
+
Install configuration file like this: `rails g x_editable_rails:install`, this step is not necessary
|
165
169
|
|
166
170
|
```yaml
|
167
171
|
class_options:
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'base64'
|
2
|
+
|
1
3
|
module X
|
2
4
|
module Editable
|
3
5
|
module Rails
|
@@ -16,63 +18,86 @@ module X
|
|
16
18
|
# - enumerable shorthand ['Yes', 'No', 'Maybe'] becomes { 'Yes' => 'Yes', 'No' => 'No', 'Maybe' => 'Maybe' }
|
17
19
|
# classes: a Hash of classes to add based on the value (same format and shorthands as source)
|
18
20
|
# value: override the object's value
|
19
|
-
#
|
21
|
+
#
|
20
22
|
def editable(object, method, options = {})
|
21
23
|
options = Configuration.method_options_for(object, method).deep_merge(options).with_indifferent_access
|
22
24
|
# merge data attributes for backwards-compatibility
|
23
25
|
options.merge! options.delete(:data){ Hash.new }
|
24
|
-
|
26
|
+
|
25
27
|
url = options.delete(:url){ polymorphic_path(object) }
|
26
28
|
object = object.last if object.kind_of?(Array)
|
27
29
|
value = options.delete(:value){ object.send(method) }
|
28
30
|
source = options[:source] ? format_source(options.delete(:source), value) : default_source_for(value)
|
29
31
|
classes = format_source(options.delete(:classes), value)
|
30
32
|
error = options.delete(:e)
|
31
|
-
|
32
|
-
|
33
|
-
|
33
|
+
html_options = options.delete(:html){ Hash.new }
|
34
|
+
|
35
|
+
if xeditable?(object)
|
36
|
+
model = object.class.model_name.param_key
|
34
37
|
nid = options.delete(:nid)
|
35
38
|
nested = options.delete(:nested)
|
36
39
|
title = options.delete(:title) do
|
37
|
-
klass = nested ? object.class.const_get(nested.to_s.
|
40
|
+
klass = nested ? object.class.const_get(nested.to_s.classify) : object.class
|
38
41
|
klass.human_attribute_name(method)
|
39
42
|
end
|
40
|
-
|
43
|
+
|
41
44
|
output_value = output_value_for(value)
|
42
|
-
css_list = options.delete(:class).to_s.split(
|
45
|
+
css_list = options.delete(:class).to_s.split(/\s+/).unshift('editable')
|
43
46
|
css_list << classes[output_value] if classes
|
44
|
-
|
47
|
+
type = options.delete(:type){ default_type_for(value) }
|
45
48
|
css = css_list.compact.uniq.join(' ')
|
46
49
|
tag = options.delete(:tag){ 'span' }
|
47
50
|
placeholder = options.delete(:placeholder){ title }
|
48
|
-
|
51
|
+
|
49
52
|
# any remaining options become data attributes
|
50
53
|
data = {
|
51
|
-
type:
|
52
|
-
model: model,
|
53
|
-
name: method,
|
54
|
-
value: output_value,
|
55
|
-
placeholder: placeholder,
|
56
|
-
classes: classes,
|
57
|
-
source: source,
|
58
|
-
url: url,
|
59
|
-
nested: nested,
|
54
|
+
type: type,
|
55
|
+
model: model,
|
56
|
+
name: method,
|
57
|
+
value: ( type == 'wysihtml5' ? Base64.encode64(output_value) : output_value ),
|
58
|
+
placeholder: placeholder,
|
59
|
+
classes: classes,
|
60
|
+
source: source,
|
61
|
+
url: url,
|
62
|
+
nested: nested,
|
60
63
|
nid: nid
|
61
|
-
}.merge(options)
|
62
|
-
|
64
|
+
}.merge(options.symbolize_keys)
|
65
|
+
|
63
66
|
data.reject!{|_, value| value.nil?}
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
+
|
68
|
+
html_options.update({
|
69
|
+
class: css,
|
70
|
+
title: title,
|
71
|
+
data: data
|
72
|
+
})
|
73
|
+
|
74
|
+
content_tag tag, html_options do
|
75
|
+
if %w(select checklist).include?(data[:type].to_s) && !source.is_a?(String)
|
76
|
+
source = normalize_source(source)
|
77
|
+
content = source.detect { |t| output_value == output_value_for(t[0]) }
|
78
|
+
content.present? ? content[1] : ""
|
79
|
+
else
|
80
|
+
safe_join(source_values_for(value, source), tag(:br))
|
81
|
+
end
|
67
82
|
end
|
68
83
|
else
|
69
|
-
|
70
|
-
error || source_values_for(value, source).join('<br/>').html_safe
|
84
|
+
error || safe_join(source_values_for(value, source), tag(:br))
|
71
85
|
end
|
72
86
|
end
|
73
|
-
|
87
|
+
|
74
88
|
private
|
75
|
-
|
89
|
+
|
90
|
+
def normalize_source(source)
|
91
|
+
return [] unless source
|
92
|
+
source.map do |el|
|
93
|
+
if el.is_a? Array
|
94
|
+
el
|
95
|
+
else
|
96
|
+
[el[:value], el[:text]]
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
76
101
|
def output_value_for(value)
|
77
102
|
value = case value
|
78
103
|
when TrueClass
|
@@ -86,22 +111,22 @@ module X
|
|
86
111
|
else
|
87
112
|
value.to_s
|
88
113
|
end
|
89
|
-
|
90
|
-
value
|
114
|
+
|
115
|
+
value
|
91
116
|
end
|
92
|
-
|
117
|
+
|
93
118
|
def source_values_for(value, source = nil)
|
94
119
|
source ||= default_source_for value
|
95
|
-
|
120
|
+
|
96
121
|
values = Array.wrap(value)
|
97
|
-
|
98
|
-
if source
|
122
|
+
|
123
|
+
if source && ( source.first.is_a?(String) || source.kind_of?(Hash) )
|
99
124
|
values.map{|item| source[output_value_for item]}
|
100
125
|
else
|
101
126
|
values
|
102
127
|
end
|
103
128
|
end
|
104
|
-
|
129
|
+
|
105
130
|
def default_type_for(value)
|
106
131
|
case value
|
107
132
|
when TrueClass, FalseClass
|
@@ -112,14 +137,14 @@ module X
|
|
112
137
|
'text'
|
113
138
|
end
|
114
139
|
end
|
115
|
-
|
140
|
+
|
116
141
|
def default_source_for(value)
|
117
142
|
case value
|
118
143
|
when TrueClass, FalseClass
|
119
144
|
{ '1' => 'Yes', '0' => 'No' }
|
120
145
|
end
|
121
146
|
end
|
122
|
-
|
147
|
+
|
123
148
|
# helper method that take some shorthand source definitions and reformats them
|
124
149
|
def format_source(source, value)
|
125
150
|
formatted_source = case value
|
@@ -127,15 +152,15 @@ module X
|
|
127
152
|
if source.is_a?(Array) && source.first.is_a?(String) && source.size == 2
|
128
153
|
{ '1' => source[0], '0' => source[1] }
|
129
154
|
end
|
130
|
-
|
155
|
+
else
|
131
156
|
if source.is_a?(Array) && source.first.is_a?(String)
|
132
|
-
source.
|
157
|
+
source.map { |v| { value: v, text: v } }
|
133
158
|
end
|
134
159
|
end
|
135
|
-
|
160
|
+
|
136
161
|
formatted_source || source
|
137
162
|
end
|
138
|
-
|
163
|
+
|
139
164
|
end
|
140
165
|
end
|
141
166
|
end
|