record_collection 0.3.2
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 +7 -0
- data/.gitignore +23 -0
- data/.travis.yml +3 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +217 -0
- data/Rakefile +16 -0
- data/app/assets/images/record_collection/.keep +0 -0
- data/app/assets/javascripts/record_collection/application.js.coffee +1 -0
- data/app/assets/javascripts/record_collection/multi_select.js.coffee +66 -0
- data/app/assets/javascripts/record_collection/optionals.js.coffee +101 -0
- data/app/assets/stylesheets/record_collection/application.css +15 -0
- data/app/assets/stylesheets/record_collection/multi_select.css.sass +20 -0
- data/app/assets/stylesheets/record_collection/optionals.css.sass +48 -0
- data/app/controllers/record_collection/application_controller.rb +4 -0
- data/app/helpers/record_collection/application_helper.rb +4 -0
- data/app/views/layouts/record_collection/application.html.erb +14 -0
- data/lib/record_collection.rb +12 -0
- data/lib/record_collection/base.rb +98 -0
- data/lib/record_collection/engine.rb +5 -0
- data/lib/record_collection/name.rb +7 -0
- data/lib/record_collection/rails/form_options_helper.rb +48 -0
- data/lib/record_collection/rails/routes.rb +21 -0
- data/lib/record_collection/version.rb +3 -0
- data/record_collection.gemspec +43 -0
- data/spec/dummy/README.rdoc +28 -0
- data/spec/dummy/Rakefile +6 -0
- data/spec/dummy/app/assets/images/.keep +0 -0
- data/spec/dummy/app/assets/javascripts/application.js.coffee +10 -0
- data/spec/dummy/app/assets/stylesheets/application.css.sass +4 -0
- data/spec/dummy/app/assets/stylesheets/components/_forms.css.sass +0 -0
- data/spec/dummy/app/assets/stylesheets/components/_structure.css.sass +0 -0
- data/spec/dummy/app/assets/stylesheets/scaffolds.scss +69 -0
- data/spec/dummy/app/controllers/application_controller.rb +5 -0
- data/spec/dummy/app/controllers/concerns/.keep +0 -0
- data/spec/dummy/app/controllers/employees_controller.rb +75 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/mailers/.keep +0 -0
- data/spec/dummy/app/models/.keep +0 -0
- data/spec/dummy/app/models/concerns/.keep +0 -0
- data/spec/dummy/app/models/employee.rb +2 -0
- data/spec/dummy/app/models/employee/collection.rb +6 -0
- data/spec/dummy/app/models/project.rb +2 -0
- data/spec/dummy/app/views/application/_form_errors.html.slim +8 -0
- data/spec/dummy/app/views/employees/_form.html.erb +25 -0
- data/spec/dummy/app/views/employees/batch_actions.html.slim +13 -0
- data/spec/dummy/app/views/employees/edit.html.erb +6 -0
- data/spec/dummy/app/views/employees/index.html.slim +25 -0
- data/spec/dummy/app/views/employees/new.html.erb +5 -0
- data/spec/dummy/app/views/employees/show.html.erb +14 -0
- data/spec/dummy/app/views/layouts/application.html.slim +10 -0
- data/spec/dummy/bin/bundle +3 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/bin/setup +29 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +26 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +41 -0
- data/spec/dummy/config/environments/production.rb +79 -0
- data/spec/dummy/config/environments/test.rb +42 -0
- data/spec/dummy/config/initializers/assets.rb +11 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/mime_types.rb +4 -0
- data/spec/dummy/config/initializers/session_store.rb +3 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +23 -0
- data/spec/dummy/config/locales/models.en.yml +5 -0
- data/spec/dummy/config/routes.rb +3 -0
- data/spec/dummy/config/secrets.yml +22 -0
- data/spec/dummy/db/migrate/20150203124634_create_employees.rb +10 -0
- data/spec/dummy/db/migrate/20150204103712_add_vegan_to_employees.rb +5 -0
- data/spec/dummy/db/migrate/20150204103925_add_admin_to_employees.rb +5 -0
- data/spec/dummy/db/migrate/20150204125014_create_projects.rb +11 -0
- data/spec/dummy/db/schema.rb +33 -0
- data/spec/dummy/lib/assets/.keep +0 -0
- data/spec/dummy/log/.keep +0 -0
- data/spec/dummy/public/404.html +67 -0
- data/spec/dummy/public/422.html +67 -0
- data/spec/dummy/public/500.html +66 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/features/multi_select_spec.rb +23 -0
- data/spec/fixtures/collections.rb +0 -0
- data/spec/record_selection/base_spec.rb +113 -0
- data/spec/spec_helper.rb +26 -0
- data/spec/validations_spec.rb +19 -0
- metadata +482 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 57c83b9fc9b46bcfed66a78f8966f8a71a48cee6
|
4
|
+
data.tar.gz: 0c28f323778b1c26db44f619ebe7814cdc435263
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 0833cd40aa97cf4c08af7be2feff96543b776eb024bb2ccd287b8b081fd3d492eb919e5b97ae7b29669fdced058c1191b49b1eb2f4b97f8da3e4b9b6c9160441
|
7
|
+
data.tar.gz: 9e7768139cba271ec1d58fb48c8e166609547708ee341d41a599d3de05751dfcfd15ae7aa87edc8961b92f17419d744126e55cb0a9ad9ebec11dcf17b9ae6c2c
|
data/.gitignore
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
/.yardoc
|
2
|
+
/Gemfile.lock
|
3
|
+
/_yardoc/
|
4
|
+
/coverage/
|
5
|
+
/doc/
|
6
|
+
/pkg/
|
7
|
+
/spec/reports/
|
8
|
+
/tmp/
|
9
|
+
*.bundle
|
10
|
+
*.so
|
11
|
+
*.o
|
12
|
+
*.a
|
13
|
+
mkmf.log
|
14
|
+
/temt
|
15
|
+
.bundle/
|
16
|
+
log/*.log
|
17
|
+
pkg/
|
18
|
+
spec/dummy/db/*.sqlite3
|
19
|
+
spec/dummy/db/*.sqlite3-journal
|
20
|
+
spec/dummy/log/*.log
|
21
|
+
spec/dummy/tmp/
|
22
|
+
spec/dummy/spec/
|
23
|
+
spec/dummy/.sass-cache
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 Benjamin ter Kuile
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,217 @@
|
|
1
|
+
# RecordCollection
|
2
|
+
[<img src="https://secure.travis-ci.org/bterkuile/record_collection.png?branch=master" alt="Build Status" />](http://travis-ci.org/bterkuile/record_collection)
|
3
|
+
|
4
|
+
record\_collection is a gem that adds functionality to rails to work
|
5
|
+
with collections. This consists of a few components:
|
6
|
+
|
7
|
+
* Collection objects containing some active record models and acting on
|
8
|
+
that collection.
|
9
|
+
* the multi\_select helpers for selecting records from the index page
|
10
|
+
* the optionals helpers for managing attributes on the collection of
|
11
|
+
records you may or may not want to edit in the collection form
|
12
|
+
|
13
|
+
## Installation
|
14
|
+
|
15
|
+
Add this line to your application's Gemfile:
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
gem 'record_collection'
|
19
|
+
```
|
20
|
+
|
21
|
+
And then execute:
|
22
|
+
|
23
|
+
$ bundle
|
24
|
+
|
25
|
+
Or install it yourself as:
|
26
|
+
|
27
|
+
$ gem install record_collection
|
28
|
+
|
29
|
+
## Adding routes
|
30
|
+
Add two collection routes to the normal resources definition.
|
31
|
+
This call behaves exactly as the normal resources :... call,
|
32
|
+
but adds:
|
33
|
+
```ruby
|
34
|
+
collection do
|
35
|
+
get :batch_actions
|
36
|
+
post :process_batch
|
37
|
+
end
|
38
|
+
```
|
39
|
+
So the route definition in `config/routes.rb` defined as:
|
40
|
+
```ruby
|
41
|
+
batch_resources :employees, except: [:new]
|
42
|
+
```
|
43
|
+
is exactly the same as:
|
44
|
+
```ruby
|
45
|
+
resources :employees, except: [:new] do
|
46
|
+
collection do
|
47
|
+
get :batch_actions
|
48
|
+
post :process_batch
|
49
|
+
end
|
50
|
+
end
|
51
|
+
```
|
52
|
+
|
53
|
+
## Defining the collection
|
54
|
+
A good practice is to define your collection as a subclass of your
|
55
|
+
resource class. So an employees collection should be defined like:
|
56
|
+
`app/models/employee.rb`:
|
57
|
+
```ruby
|
58
|
+
class Employee < ActiveRecord::Base
|
59
|
+
# attribute :admin, type: Boolean (defined by database)
|
60
|
+
validates :name, presence: true
|
61
|
+
|
62
|
+
end
|
63
|
+
```
|
64
|
+
`app/models/employee/collection.rb`:
|
65
|
+
```ruby
|
66
|
+
class Employee::Collection < RecordCollection::Base
|
67
|
+
attribute :name
|
68
|
+
validates :section, format: {with: /\A\w{3}\Z/, if: 'section.present?' }
|
69
|
+
attribute :admin, type: Boolean
|
70
|
+
attribute :vegan, type: Boolean
|
71
|
+
end
|
72
|
+
```
|
73
|
+
See the [active_attr](https://github.com/cgriego/active_attr) gem for
|
74
|
+
attribute definitions.
|
75
|
+
|
76
|
+
## Defining your controllers
|
77
|
+
If you already used the specification `batch_resources :employees` in
|
78
|
+
your [config/routes.rb](spec/dummy/config/routes.rb) file you can add
|
79
|
+
the actions in your controller typically looking like:
|
80
|
+
```ruby
|
81
|
+
class EmployeesController < ApplicationController
|
82
|
+
# your standard actions here
|
83
|
+
|
84
|
+
# GET /employees/batch_actions?ids[]=1&ids[]=3&...
|
85
|
+
def batch_actions
|
86
|
+
@employees = Employee.find(Array.wrap(params[:ids]))
|
87
|
+
@collection = Employee::Collection.new(@employees)
|
88
|
+
redirect_to employees_path, alert: 'No employees selected' if @collection.empty?
|
89
|
+
end
|
90
|
+
|
91
|
+
# POST /employees/process_batch
|
92
|
+
def process_batch
|
93
|
+
@employees = Employee.find(Array.wrap(params[:ids]))
|
94
|
+
@collection = Employee::Collection.new(@employees, params[:collection])
|
95
|
+
if @collection.save
|
96
|
+
redirect_to employees_path, notice: 'Collection is updated'
|
97
|
+
else
|
98
|
+
render 'batch_actions'
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
```
|
103
|
+
For more advanced use of the collection the pattern above can of course
|
104
|
+
be different eg: different collection objects for the same active record
|
105
|
+
model types.
|
106
|
+
|
107
|
+
## Creating your views
|
108
|
+
The
|
109
|
+
[app/views/employess/batch_actions.html.slim](spec/dummy/app/views/employees/batch_actions.html.slim) view is a tricky one.
|
110
|
+
Since we are working on a collection of record, and want to edit those
|
111
|
+
attributes we just want a normal form for editing the attributes,
|
112
|
+
treating the collection as the record itself. The problem however is
|
113
|
+
that some attributes can be in a mixed state, say two employees, one
|
114
|
+
having `admin => true`, the other one `admin => false`. If I only want
|
115
|
+
to update the section they are both in, I want to leave the admin
|
116
|
+
attribute allone. To accomplish this, this gem provides the `optional`
|
117
|
+
helpers. These helpers make it easy to manage a form of attributes where
|
118
|
+
you can determine which attributes you want to manage for this
|
119
|
+
particular collection of records. This gem also support [simple_form](https://github.com/plataformatec/simple_form)
|
120
|
+
gem where you can replace `f.input :attribute, ...etc` with
|
121
|
+
`f.optional_input :attribute, ...etc`. Our current example works with
|
122
|
+
the standard [form_helpers](http://guides.rubyonrails.org/form_helpers.html)<br>
|
123
|
+
### currently supported helpers:
|
124
|
+
* `optional_boolean`
|
125
|
+
* `optional_text_field`
|
126
|
+
* `optional_input` ([simple_form](https://github.com/plataformatec/simple_form))
|
127
|
+
|
128
|
+
The form you create typically looks like:
|
129
|
+
```slim
|
130
|
+
h1 Edit multiple employees
|
131
|
+
= form_for @collection, url: [:process_batch, @collection.record_class] do |f|
|
132
|
+
= f.collection_ids
|
133
|
+
.form-inputs= f.optional_text_field :section
|
134
|
+
.form-inputs= f.optional_boolean :admin
|
135
|
+
.form-inputs= f.optional_boolean :vegan
|
136
|
+
.form-actions= f.submit
|
137
|
+
.page-actions
|
138
|
+
= link_to 'Back', employees_path
|
139
|
+
```
|
140
|
+
|
141
|
+
That is the view part. Be sure to read the optionals section for a
|
142
|
+
better understanding of how the optional fields work.
|
143
|
+
|
144
|
+
## Selecting records from the index using checkboxes (multi_select)
|
145
|
+
The idea behind working with collections is that you end up as a `GET` request at:
|
146
|
+
`+controller+/batch_actions?ids[]=2&ids[]=3` etc. How you achieve this
|
147
|
+
is totally up to yourself, but this gem provides you with a nice
|
148
|
+
standard way of selecting records from the index page. To filter records
|
149
|
+
to a specific subset the [ransack](https://github.com/activerecord-hackery/ransack)
|
150
|
+
gem also provides a nice way to add filtering to the index page. To add
|
151
|
+
checkbox selecting to your page this gem assumes the following
|
152
|
+
structure using the [Slim lang](http://slim-lang.com/):
|
153
|
+
```slim
|
154
|
+
table.with-selection
|
155
|
+
thead
|
156
|
+
tr
|
157
|
+
th Name
|
158
|
+
th Section
|
159
|
+
tbody
|
160
|
+
- @employees.each do |employee|
|
161
|
+
tr data-record=employee.attributes.to_json
|
162
|
+
```
|
163
|
+
Note that each row needs a json version of the record at least
|
164
|
+
containing its id.<br>
|
165
|
+
Implement the multiselect dependencies in your manifest files, typically
|
166
|
+
being `app/assets/javascripts/application.js`:
|
167
|
+
```javascript
|
168
|
+
//= require record_collection/multi_select
|
169
|
+
```
|
170
|
+
And for the styling provided by this gem ([app/assets/stylesheets/application.css](spec/dummy/app/assets/stylesheets/application.css.sass)):
|
171
|
+
```css
|
172
|
+
/*
|
173
|
+
*= require record_collection/multi_select
|
174
|
+
*/
|
175
|
+
```
|
176
|
+
The styling uses the [font-awesome-rails](http://fortawesome.github.io/Font-Awesome/) gem, so this gem should be
|
177
|
+
present in your `Gemfile`:
|
178
|
+
```ruby
|
179
|
+
gem 'font-awesome-rails'
|
180
|
+
```
|
181
|
+
Of course you are welcome to create your own awesome styling and send it
|
182
|
+
to me so I can add it as a theme :smile:.
|
183
|
+
|
184
|
+
## Optionals
|
185
|
+
Optionals is the name for the feature in this gem that activates
|
186
|
+
collection attributes to be sumitted in the form or not. Since for a
|
187
|
+
mixed collection on an attribute you might not want to edit, but another
|
188
|
+
attribute you do want to edit you add the optionals functionality to
|
189
|
+
your manifests. This is similar to the `multi_select` feature:
|
190
|
+
```javascript
|
191
|
+
//= require record_collection/optionals
|
192
|
+
```
|
193
|
+
And for the styling provided by this gem ([app/assets/stylesheets/application.css](spec/dummy/app/assets/stylesheets/application.css.sass)):
|
194
|
+
```css
|
195
|
+
/*
|
196
|
+
*= require record_collection/optionals
|
197
|
+
*/
|
198
|
+
```
|
199
|
+
|
200
|
+
**TODO: more explanation about optionals**
|
201
|
+
|
202
|
+
## Special thanks
|
203
|
+
|
204
|
+
Special thanks for this project goes to:<br>
|
205
|
+
<a href="http://companytools.nl/" target="_blank"><img src="http://companytools.nl/assets/logo2-f5f9a19c745e753a4d52b5c0a1a7c6d7.png" alt="Companytools"></a>
|
206
|
+
|
207
|
+
<a href="http://fourstack.nl" target="_blank"><img src="http://fourstack.nl/logo1.png" alt="FourStack"></a>
|
208
|
+
|
209
|
+
<a href="http://www.kpn.com" target="_blank"><img src="http://www.kpn.com/ss/Satellite/yavUnLl8hN7yMh6Gh2IPWqYD60HbUkXsNK4iD8PcUpR0bnBXyZZtwQUuCgSUG72CJE/MungoBlobs/kpn_logo.png"></a>
|
210
|
+
|
211
|
+
## Contributing
|
212
|
+
|
213
|
+
1. Fork it ( https://github.com/bterkuile/record_collection/fork )
|
214
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
215
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
216
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
217
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
require "bundler/gem_tasks"
|
7
|
+
|
8
|
+
require 'rspec/core'
|
9
|
+
require 'rspec/core/rake_task'
|
10
|
+
|
11
|
+
desc "Run all specs in spec directory (excluding plugin specs)"
|
12
|
+
#RSpec::Core::RakeTask.new(spec: 'app:db:test:prepare')
|
13
|
+
RSpec::Core::RakeTask.new(:spec)
|
14
|
+
|
15
|
+
task default: :spec
|
16
|
+
|
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
#= require_tree .
|
@@ -0,0 +1,66 @@
|
|
1
|
+
class MultiSelect
|
2
|
+
setup: (table) ->
|
3
|
+
return unless table and table.length
|
4
|
+
table.data 'multi_select', @
|
5
|
+
@set 'table', table
|
6
|
+
|
7
|
+
@set 'resource', table.data('resource')
|
8
|
+
# Add an extra th to all header rows
|
9
|
+
table.find('thead tr').each -> $(this).prepend("<th></th>")
|
10
|
+
|
11
|
+
# Create a toggle for selecting an deselecting all records
|
12
|
+
# and add it to the last header row
|
13
|
+
#toggle_all = $("<input type='checkbox'></input>").addClass('selection-toggle-all').click ->
|
14
|
+
#checked = $(this).is(':checked')
|
15
|
+
#table.find('td.selection input').prop 'checked', checked
|
16
|
+
toggle_all = $("<span></span>").addClass('selection-toggle-all unchecked').click ->
|
17
|
+
if $(this).hasClass('checked')
|
18
|
+
table.find('td.selection .checker').removeClass('checked').addClass('unchecked')
|
19
|
+
$(this).removeClass('checked').addClass('unchecked')
|
20
|
+
else
|
21
|
+
table.find('td.selection .checker').removeClass('unchecked').addClass('checked')
|
22
|
+
$(this).removeClass('unchecked').addClass('checked')
|
23
|
+
table.find('thead tr:last th:first').append toggle_all
|
24
|
+
|
25
|
+
# Create a toggle/checkbox for all records and add it to the row
|
26
|
+
#record_toggle = $("<input type='checkbox'></input>")
|
27
|
+
record_toggle = $("<span></span>").addClass('checker unchecked').click ->
|
28
|
+
if $(this).hasClass('checked')
|
29
|
+
$(this).removeClass('checked').addClass('unchecked')
|
30
|
+
else
|
31
|
+
$(this).removeClass('unchecked').addClass('checked')
|
32
|
+
record_td = $('<td></td>').addClass('selection').append(record_toggle)
|
33
|
+
table.find('tbody tr').prepend record_td
|
34
|
+
|
35
|
+
@setup_selection_actions()
|
36
|
+
|
37
|
+
toggle_all.click() if table.data('preselected')
|
38
|
+
|
39
|
+
# Find all buttons in the table footer and attach the action given their action data attribute
|
40
|
+
setup_selection_actions: ->
|
41
|
+
selector = this
|
42
|
+
@table.find('tfoot button').click ->
|
43
|
+
$.post Routes["actions_#{selector.get('resource')}_path"](),
|
44
|
+
ids: selector.selected_ids().toArray()
|
45
|
+
selection_action: $(this).data('action')
|
46
|
+
|
47
|
+
# use set and get as a good reactive pattern
|
48
|
+
# implement the raw version, can become more complex int the future
|
49
|
+
set: (path, value) -> @[path] = value
|
50
|
+
get: (path) -> @[path]
|
51
|
+
|
52
|
+
#selected_records: -> @table.find("td.selection input:checked").map( -> $(this).parents('tr').data('record') )
|
53
|
+
selected_records: -> @table.find("td.selection .checked").map( -> $(this).parents('tr').data('record') )
|
54
|
+
selected_ids: -> @selected_records().map( -> this.id ).toArray()
|
55
|
+
root = @
|
56
|
+
root.MultiSelect = new MultiSelect()
|
57
|
+
$.fn.multi_select = ->
|
58
|
+
if @.hasClass('with-selection') or @.prop('tagName') is 'TABLE'
|
59
|
+
select = new MultiSelect()
|
60
|
+
root.MultiSelect = select
|
61
|
+
select.setup @
|
62
|
+
else
|
63
|
+
@.find('table.with-selection').each (i, el)->
|
64
|
+
select = new MultiSelect()
|
65
|
+
root.MultiSelect = select
|
66
|
+
select.setup $(el)
|
@@ -0,0 +1,101 @@
|
|
1
|
+
class Optionals
|
2
|
+
setup: (target)->
|
3
|
+
@setup_inputs(target)
|
4
|
+
|
5
|
+
setup_inputs: (target)->
|
6
|
+
target.find('.optional-attribute-container').each (i, el)=>
|
7
|
+
container = $(el)
|
8
|
+
if container.hasClass('optional-boolean')
|
9
|
+
@optionalBoolean container
|
10
|
+
else
|
11
|
+
@prependActivator(container)
|
12
|
+
|
13
|
+
# Replace the <input type="checkbox"> for a <input type="hidden" # value="0|1"> fields
|
14
|
+
# managed by the javascript
|
15
|
+
optionalBoolean: (container)->
|
16
|
+
check_box = container.find('input')
|
17
|
+
initially_checked = check_box.is(':checked')
|
18
|
+
field_name = check_box.attr('name')
|
19
|
+
|
20
|
+
label_text = container.find('label').text()
|
21
|
+
|
22
|
+
value_field = $('<input>').attr('type', 'hidden').val(0)
|
23
|
+
# Set name based on activated state
|
24
|
+
if container.hasClass('active')
|
25
|
+
value_field.attr 'name', field_name
|
26
|
+
else
|
27
|
+
value_field.attr 'name', "disabled_#{field_name}"
|
28
|
+
|
29
|
+
# Clear the container and initialize to inactive
|
30
|
+
container.html('')
|
31
|
+
|
32
|
+
label = $('<span></span>').addClass('optional-boolean-label').text label_text
|
33
|
+
|
34
|
+
activator_toggle = $('<span></span>').addClass('optional-boolean-activator-toggle').click ->
|
35
|
+
container.toggleClass('active').toggleClass('inactive')
|
36
|
+
if container.hasClass('active')
|
37
|
+
value_field.attr 'name', value_field.attr('name').replace(/^disabled_/, '')
|
38
|
+
else
|
39
|
+
value_field.attr 'name', "disabled_#{value_field.attr('name')}"
|
40
|
+
|
41
|
+
value_toggle = $('<span></span>').addClass('optional-boolean-toggle').click ->
|
42
|
+
return if container.hasClass('inactive')
|
43
|
+
if $(@).hasClass('active')
|
44
|
+
value_field.val(0)
|
45
|
+
$(@).removeClass('active').addClass('inactive')
|
46
|
+
else
|
47
|
+
value_field.val(1)
|
48
|
+
$(@).addClass('active').removeClass('inactive')
|
49
|
+
|
50
|
+
if initially_checked
|
51
|
+
value_toggle.addClass('active')
|
52
|
+
value_field.val(1)
|
53
|
+
else
|
54
|
+
value_toggle.addClass('inactive')
|
55
|
+
|
56
|
+
container.append activator_toggle
|
57
|
+
container.append label
|
58
|
+
container.append value_toggle
|
59
|
+
container.append value_field
|
60
|
+
|
61
|
+
prependActivator: (container)->
|
62
|
+
value_field = container.find('select,input')
|
63
|
+
# INITIAL STATE IS DISABLED, Activation by triggering click if needed
|
64
|
+
value_field.attr 'name', "disabled_#{value_field.attr('name')}"
|
65
|
+
|
66
|
+
label_text = container.find('label').text()
|
67
|
+
|
68
|
+
# Activator container
|
69
|
+
activator_container = $('<div></div>').addClass('optional-input-activator-container inactive')
|
70
|
+
activator_container.addClass container.data('attribute')
|
71
|
+
activator_container.addClass('error') if container.hasClass('error')
|
72
|
+
activator_toggle = $('<span></span>').addClass('optional-input-activator-toggle').click ->
|
73
|
+
activator_container.toggleClass('active').toggleClass('inactive')
|
74
|
+
#label.toggleClass('inactive')
|
75
|
+
if activator_container.hasClass('active')
|
76
|
+
value_field.attr 'name', value_field.attr('name').replace(/^disabled_/, '')
|
77
|
+
#value_toggle.show()
|
78
|
+
container.removeClass('inactive')
|
79
|
+
else
|
80
|
+
value_field.attr 'name', "disabled_#{value_field.attr('name')}"
|
81
|
+
#value_toggle.hide()
|
82
|
+
container.addClass('inactive')
|
83
|
+
activator_label = $('<span></span>').addClass('optional-input-activator-label').text label_text
|
84
|
+
activator_container.append activator_toggle
|
85
|
+
activator_container.append activator_label
|
86
|
+
|
87
|
+
container.before(activator_container)
|
88
|
+
|
89
|
+
container.find('label').remove()
|
90
|
+
|
91
|
+
activator_toggle.click() if container.hasClass('active')
|
92
|
+
|
93
|
+
root = @
|
94
|
+
root.Optionals = new Optionals()
|
95
|
+
$.fn.optionals = (action_or_options = {})->
|
96
|
+
if typeof action_or_options is 'string'
|
97
|
+
#nothing
|
98
|
+
else
|
99
|
+
optionals = new Optionals(action_or_options)
|
100
|
+
optionals.setup(@)
|
101
|
+
root.Optionals = optionals
|