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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f211902f307559fafdeb55542265063b6aed1b74
4
- data.tar.gz: b01c23c18a006cd2079bf562621df7774830942c
3
+ metadata.gz: fee9739c77324495b6e7a6227d85fdb2f77c972b
4
+ data.tar.gz: fd6565d1908e346778674f1f42f95f235c335f01
5
5
  SHA512:
6
- metadata.gz: 9fe4a918b0d2e3da58d6105c8646f757780855011bd347c814d3b7b073abb6d6e40b77d52dc7dde206fb7d3d61b1d792b28ddc9521605ceeac297c4e8fd90842
7
- data.tar.gz: da69e8902b82d4f9fe578e02a9bb2f2e8b17598a346168b198cd2dc57f8cac572406bdf90436a6f15290c490bbd9f2b547943fc35000b46f661fa2aa8d4c21fa
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
+ [![Build Status](https://travis-ci.org/werein/x-editable-rails.svg)](https://travis-ci.org/werein/x-editable-rails) [![Code Climate](https://codeclimate.com/github/werein/x-editable-rails/badges/gpa.svg)](https://codeclimate.com/github/werein/x-editable-rails) [![Test coverage](https://codeclimate.com/github/werein/x-editable-rails/badges/coverage.svg)](https://codeclimate.com/github/werein/x-editable-rails) [![Version](https://badge.fury.io/rb/x-editable-rails.svg)](https://badge.fury.io/rb/x-editable-rails) [![Dependencies](https://gemnasium.com/werein/x-editable-rails.svg)](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 [gobalize](https://github.com/globalize/globalize)'s `translations`)
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
- This gem requires [CanCan](https://github.com/ryanb/cancan) and checks the `:edit` permission for the model being edited.
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
- if xeditable? && can?(:edit, model)
147
- ... output x-editable HTML ...
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,7 +1,7 @@
1
1
  module X
2
2
  module Editable
3
3
  module Rails
4
- VERSION = "1.5.1"
4
+ VERSION = "1.5.5.1"
5
5
  end
6
6
  end
7
- end
7
+ end
@@ -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
- if xeditable? and can?(:edit, object)
33
- model = object.class.name.split('::').last.underscore
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.singularize.capitalize) : object.class
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(/s+/).unshift('editable')
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: options.delete(:type){ default_type_for(value) },
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
- content_tag tag, class: css, title: title, data: data do
66
- source_values_for(value, source).join('<br/>').html_safe
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
- # create a friendly value using the source to display a default value (if no error message given)
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.html_safe
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
- when String
155
+ else
131
156
  if source.is_a?(Array) && source.first.is_a?(String)
132
- source.inject({}){|hash, key| hash.merge(key => key)}
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