ultimate-helpers 0.1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +8 -0
- data/.rvmrc +1 -0
- data/.rvmrc.example +1 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +126 -0
- data/LICENSE +19 -0
- data/README.md +25 -0
- data/Rakefile +1 -0
- data/app/assets/javascripts/ultimate/base.js.coffee +11 -0
- data/app/assets/javascripts/ultimate/helpers/asset_tag.js.coffee +82 -0
- data/app/assets/javascripts/ultimate/helpers/base.js.coffee +3 -0
- data/app/assets/javascripts/ultimate/helpers/decor.js.coffee +19 -0
- data/app/assets/javascripts/ultimate/helpers/form_options.js.coffee +106 -0
- data/app/assets/javascripts/ultimate/helpers/form_tag.js.coffee +175 -0
- data/app/assets/javascripts/ultimate/helpers/javascript.js.coffee +31 -0
- data/app/assets/javascripts/ultimate/helpers/number.js.coffee +600 -0
- data/app/assets/javascripts/ultimate/helpers/record_tag.js.coffee +81 -0
- data/app/assets/javascripts/ultimate/helpers/tag.js.coffee +91 -0
- data/app/assets/javascripts/ultimate/helpers/url.js.coffee +152 -0
- data/app/assets/javascripts/ultimate/helpers.js.coffee +122 -0
- data/app/assets/javascripts/ultimate/jquery.base.js.coffee +85 -0
- data/app/assets/javascripts/ultimate/underscore/underscore.inflection.js +176 -0
- data/app/assets/javascripts/ultimate/underscore/underscore.js +1204 -0
- data/app/assets/javascripts/ultimate/underscore/underscore.outcasts.js.coffee +158 -0
- data/app/assets/javascripts/ultimate/underscore/underscore.string.js +600 -0
- data/config/routes.rb +2 -0
- data/lib/ultimate/helpers/engine.rb +7 -0
- data/lib/ultimate/helpers/version.rb +5 -0
- data/lib/ultimate/helpers.rb +8 -0
- data/scripts/rails +8 -0
- data/test/dummy/Rakefile +7 -0
- data/test/dummy/_emfile +18 -0
- data/test/dummy/app/assets/images/.gitkeep +0 -0
- data/test/dummy/app/assets/javascripts/application.js +3 -0
- data/test/dummy/app/assets/stylesheets/application.css +13 -0
- data/test/dummy/app/assets/stylesheets/global/forms.css.scss +65 -0
- data/test/dummy/app/assets/stylesheets/global/layout/footer.scss +18 -0
- data/test/dummy/app/assets/stylesheets/global/layout/header.scss +13 -0
- data/test/dummy/app/assets/stylesheets/global/layout/main-menu.scss +68 -0
- data/test/dummy/app/assets/stylesheets/global/layout.css.scss +46 -0
- data/test/dummy/app/assets/stylesheets/global/reserved.css.scss +79 -0
- data/test/dummy/app/assets/stylesheets/global/reset.css.scss +85 -0
- data/test/dummy/app/assets/stylesheets/global/structures.css.scss +9 -0
- data/test/dummy/app/assets/stylesheets/import/base.scss +36 -0
- data/test/dummy/app/assets/stylesheets/plugins/qunit.css.scss +3 -0
- data/test/dummy/app/controllers/application_controller.rb +4 -0
- data/test/dummy/app/controllers/main_controller.rb +8 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/mailers/.gitkeep +0 -0
- data/test/dummy/app/models/.gitkeep +0 -0
- data/test/dummy/app/views/application/_footer.html.haml +3 -0
- data/test/dummy/app/views/application/_header.html.haml +4 -0
- data/test/dummy/app/views/application/_main_menu.html.haml +11 -0
- data/test/dummy/app/views/layouts/application.html.haml +24 -0
- data/test/dummy/app/views/main/index.html.haml +13 -0
- data/test/dummy/app/views/main/qunit.html.haml +7 -0
- data/test/dummy/config/application.rb +58 -0
- data/test/dummy/config/boot.rb +10 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +40 -0
- data/test/dummy/config/environments/production.rb +67 -0
- data/test/dummy/config/environments/test.rb +37 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/inflections.rb +15 -0
- data/test/dummy/config/initializers/mime_types.rb +5 -0
- data/test/dummy/config/initializers/qunit-rails.rb +1 -0
- data/test/dummy/config/initializers/secret_token.rb +7 -0
- data/test/dummy/config/initializers/session_store.rb +8 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +5 -0
- data/test/dummy/config/routes.rb +63 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/log/.gitkeep +0 -0
- data/test/dummy/public/404.html +26 -0
- data/test/dummy/public/422.html +26 -0
- data/test/dummy/public/500.html +25 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/script/rails +6 -0
- data/test/javascripts/all_tests.js.coffee +12 -0
- data/test/javascripts/test_helper.js.coffee +3 -0
- data/test/javascripts/tests/helpers/asset_tag_test.js.coffee +51 -0
- data/test/javascripts/tests/helpers/form_options_test.js.coffee +170 -0
- data/test/javascripts/tests/helpers/form_tag_test.js.coffee +226 -0
- data/test/javascripts/tests/helpers/javascript_test.js.coffee +25 -0
- data/test/javascripts/tests/helpers/number_test.js.coffee +250 -0
- data/test/javascripts/tests/helpers/record_tag_test.js.coffee +60 -0
- data/test/javascripts/tests/helpers/tag_test.js.coffee +58 -0
- data/test/javascripts/tests/helpers/url_test.js.coffee +76 -0
- data/test/javascripts/tests/underscore/underscore.outcasts.test.js.coffee +47 -0
- data/test/javascripts/vendors/backbone.js +1533 -0
- data/test/javascripts/vendors/i18n-lite.js.coffee +20 -0
- data/test/stylesheets/test_helper.css +4 -0
- data/test/stylesheets/vendors/ultimate/mixins/_routines.scss +120 -0
- data/test/stylesheets/vendors/ultimate/mixins/_vendors.scss +44 -0
- data/test/stylesheets/vendors/ultimate/mixins/css3/_text-shadow.scss +40 -0
- data/test/stylesheets/vendors/ultimate/mixins/css3.scss +350 -0
- data/test/stylesheets/vendors/ultimate/mixins/fonts.scss +100 -0
- data/test/stylesheets/vendors/ultimate/mixins/microstructures.scss +239 -0
- data/ultimate-helpers.gemspec +25 -0
- metadata +193 -0
data/.gitignore
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm 1.9.3@ultimate
|
data/.rvmrc.example
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm 1.9.3@ultimate
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,126 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
ultimate-helpers (0.1.0.0)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: http://rubygems.org/
|
8
|
+
specs:
|
9
|
+
actionmailer (3.2.8)
|
10
|
+
actionpack (= 3.2.8)
|
11
|
+
mail (~> 2.4.4)
|
12
|
+
actionpack (3.2.8)
|
13
|
+
activemodel (= 3.2.8)
|
14
|
+
activesupport (= 3.2.8)
|
15
|
+
builder (~> 3.0.0)
|
16
|
+
erubis (~> 2.7.0)
|
17
|
+
journey (~> 1.0.4)
|
18
|
+
rack (~> 1.4.0)
|
19
|
+
rack-cache (~> 1.2)
|
20
|
+
rack-test (~> 0.6.1)
|
21
|
+
sprockets (~> 2.1.3)
|
22
|
+
activemodel (3.2.8)
|
23
|
+
activesupport (= 3.2.8)
|
24
|
+
builder (~> 3.0.0)
|
25
|
+
activerecord (3.2.8)
|
26
|
+
activemodel (= 3.2.8)
|
27
|
+
activesupport (= 3.2.8)
|
28
|
+
arel (~> 3.0.2)
|
29
|
+
tzinfo (~> 0.3.29)
|
30
|
+
activeresource (3.2.8)
|
31
|
+
activemodel (= 3.2.8)
|
32
|
+
activesupport (= 3.2.8)
|
33
|
+
activesupport (3.2.8)
|
34
|
+
i18n (~> 0.6)
|
35
|
+
multi_json (~> 1.0)
|
36
|
+
arel (3.0.2)
|
37
|
+
builder (3.0.3)
|
38
|
+
coffee-rails (3.2.2)
|
39
|
+
coffee-script (>= 2.2.0)
|
40
|
+
railties (~> 3.2.0)
|
41
|
+
coffee-script (2.2.0)
|
42
|
+
coffee-script-source
|
43
|
+
execjs
|
44
|
+
coffee-script-source (1.3.3)
|
45
|
+
erubis (2.7.0)
|
46
|
+
execjs (1.4.0)
|
47
|
+
multi_json (~> 1.0)
|
48
|
+
haml (3.1.7)
|
49
|
+
haml-rails (0.3.5)
|
50
|
+
actionpack (>= 3.1, < 4.1)
|
51
|
+
activesupport (>= 3.1, < 4.1)
|
52
|
+
haml (~> 3.1)
|
53
|
+
railties (>= 3.1, < 4.1)
|
54
|
+
hike (1.2.1)
|
55
|
+
i18n (0.6.1)
|
56
|
+
journey (1.0.4)
|
57
|
+
jquery-rails (2.1.3)
|
58
|
+
railties (>= 3.1.0, < 5.0)
|
59
|
+
thor (~> 0.14)
|
60
|
+
json (1.7.5)
|
61
|
+
mail (2.4.4)
|
62
|
+
i18n (>= 0.4.0)
|
63
|
+
mime-types (~> 1.16)
|
64
|
+
treetop (~> 1.4.8)
|
65
|
+
mime-types (1.19)
|
66
|
+
multi_json (1.3.6)
|
67
|
+
polyglot (0.3.3)
|
68
|
+
quiet_assets (1.0.1)
|
69
|
+
railties (~> 3.1)
|
70
|
+
qunit-rails (0.0.2)
|
71
|
+
railties (~> 3.2.3)
|
72
|
+
rack (1.4.1)
|
73
|
+
rack-cache (1.2)
|
74
|
+
rack (>= 0.4)
|
75
|
+
rack-ssl (1.3.2)
|
76
|
+
rack
|
77
|
+
rack-test (0.6.2)
|
78
|
+
rack (>= 1.0)
|
79
|
+
rails (3.2.8)
|
80
|
+
actionmailer (= 3.2.8)
|
81
|
+
actionpack (= 3.2.8)
|
82
|
+
activerecord (= 3.2.8)
|
83
|
+
activeresource (= 3.2.8)
|
84
|
+
activesupport (= 3.2.8)
|
85
|
+
bundler (~> 1.0)
|
86
|
+
railties (= 3.2.8)
|
87
|
+
railties (3.2.8)
|
88
|
+
actionpack (= 3.2.8)
|
89
|
+
activesupport (= 3.2.8)
|
90
|
+
rack-ssl (~> 1.3.2)
|
91
|
+
rake (>= 0.8.7)
|
92
|
+
rdoc (~> 3.4)
|
93
|
+
thor (>= 0.14.6, < 2.0)
|
94
|
+
rake (0.9.2.2)
|
95
|
+
rdoc (3.12)
|
96
|
+
json (~> 1.4)
|
97
|
+
sass (3.2.1)
|
98
|
+
sass-rails (3.2.5)
|
99
|
+
railties (~> 3.2.0)
|
100
|
+
sass (>= 3.1.10)
|
101
|
+
tilt (~> 1.3)
|
102
|
+
sprockets (2.1.3)
|
103
|
+
hike (~> 1.2)
|
104
|
+
rack (~> 1.0)
|
105
|
+
tilt (~> 1.1, != 1.3.0)
|
106
|
+
sqlite3 (1.3.6)
|
107
|
+
thor (0.16.0)
|
108
|
+
tilt (1.3.3)
|
109
|
+
treetop (1.4.10)
|
110
|
+
polyglot
|
111
|
+
polyglot (>= 0.3.1)
|
112
|
+
tzinfo (0.3.33)
|
113
|
+
|
114
|
+
PLATFORMS
|
115
|
+
ruby
|
116
|
+
|
117
|
+
DEPENDENCIES
|
118
|
+
coffee-rails (~> 3.2.1)
|
119
|
+
haml-rails
|
120
|
+
jquery-rails
|
121
|
+
quiet_assets
|
122
|
+
qunit-rails
|
123
|
+
rails (~> 3.2.8)
|
124
|
+
sass-rails (~> 3.2.3)
|
125
|
+
sqlite3
|
126
|
+
ultimate-helpers!
|
data/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2011-2013 Dmitry Karpunin (aka KODer) koderfunk@gmail.com
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
Ultimate Helpers, Rails ActionView helpers ported to CoffeeScript
|
2
|
+
|
3
|
+
## Licence ##
|
4
|
+
|
5
|
+
The MIT License
|
6
|
+
|
7
|
+
Copyright (c) 2010-2013 Dmitry Karpunin (aka KODer) koderfunk@gmail.com
|
8
|
+
|
9
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
10
|
+
of this software and associated documentation files (the "Software"), to deal
|
11
|
+
in the Software without restriction, including without limitation the rights
|
12
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
13
|
+
copies of the Software, and to permit persons to whom the Software is
|
14
|
+
furnished to do so, subject to the following conditions:
|
15
|
+
|
16
|
+
The above copyright notice and this permission notice shall be included in
|
17
|
+
all copies or substantial portions of the Software.
|
18
|
+
|
19
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
20
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
21
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
22
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
23
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
24
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
25
|
+
THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,82 @@
|
|
1
|
+
#= require ./base
|
2
|
+
#= require ./tag
|
3
|
+
|
4
|
+
@Ultimate.Helpers.AssetTag =
|
5
|
+
|
6
|
+
favicon_link_tag: (source = 'favicon.ico', options = {}) ->
|
7
|
+
tag 'link', _.extend
|
8
|
+
rel: 'shortcut icon'
|
9
|
+
type: 'image/vnd.microsoft.icon'
|
10
|
+
href: @path_to_image(source)
|
11
|
+
, options
|
12
|
+
|
13
|
+
image_path: (source) ->
|
14
|
+
if source then @compute_public_path(source, 'images') else ''
|
15
|
+
|
16
|
+
path_to_image: -> @image_path arguments... # aliased to avoid conflicts with an image_path named route
|
17
|
+
|
18
|
+
image_tag: (source, options = {}) ->
|
19
|
+
src = options['src'] = @path_to_image(source)
|
20
|
+
if _.isUndefined(options['alt']) and src and not /^(?:cid|data):/.test(src)
|
21
|
+
options['alt'] = @image_alt(src)
|
22
|
+
if size = _.outcasts.delete(options, 'size')
|
23
|
+
if matches = size.match(/^(\d+)x(\d+)$/)
|
24
|
+
options['width'] = matches[1]
|
25
|
+
options['height'] = matches[2]
|
26
|
+
else if /^(\d+)$/.test(size)
|
27
|
+
options['width'] = options['height'] = size
|
28
|
+
Ultimate.Helpers.Tag.tag('img', options)
|
29
|
+
|
30
|
+
image_alt: (src) ->
|
31
|
+
_.string.capitalize @_without_extension(@_basename(src)).replace(/-[A-Fa-f0-9]{32}/, '')
|
32
|
+
|
33
|
+
|
34
|
+
|
35
|
+
# ===================== AssetPaths =====================
|
36
|
+
|
37
|
+
URI_REGEXP: /^[-a-z]+:\/\/|^(?:cid|data):|^\/\//
|
38
|
+
|
39
|
+
is_uri: (path) ->
|
40
|
+
@URI_REGEXP.test(path)
|
41
|
+
|
42
|
+
RELATIVE_URL_ROOT: ''
|
43
|
+
|
44
|
+
compute_public_path: (source, dir, options = {}) ->
|
45
|
+
return source if @is_uri(source)
|
46
|
+
source = @_rewrite_extension(source, options['ext']) if options['ext']
|
47
|
+
source = @_rewrite_asset_path(source, dir)
|
48
|
+
source = @_rewrite_relative_url_root(source, @RELATIVE_URL_ROOT)
|
49
|
+
source
|
50
|
+
|
51
|
+
_rewrite_extension: (source, ext) ->
|
52
|
+
"#{@_without_extension(source)}.#{ext}"
|
53
|
+
|
54
|
+
_without_extension: (source) ->
|
55
|
+
source.replace(/^(.+)(\.\w+)$/, '$1')
|
56
|
+
|
57
|
+
_ASSET_ID: ''
|
58
|
+
_asset_ids_cache: {}
|
59
|
+
# Use the ASSET_ID inscope variable or the random hash as its cache-busting asset id.
|
60
|
+
_asset_id: (source) ->
|
61
|
+
if _.isString(@_ASSET_ID)
|
62
|
+
@_ASSET_ID
|
63
|
+
else
|
64
|
+
@_asset_ids_cache[source] or (@_asset_ids_cache[source] = 10000000 + Math.floor(Math.random() * 90000000))
|
65
|
+
|
66
|
+
# Break out the asset path rewrite in case plugins wish to put the asset id
|
67
|
+
# someplace other than the query string.
|
68
|
+
_rewrite_asset_path: (source, dir) ->
|
69
|
+
source = "/#{dir}/#{source}" unless source[0] is '/'
|
70
|
+
if id = @_asset_id(source)
|
71
|
+
"#{source}?#{id}"
|
72
|
+
else
|
73
|
+
source
|
74
|
+
|
75
|
+
_rewrite_relative_url_root: (source, relative_url_root) ->
|
76
|
+
if relative_url_root and not _.startsWith(source, "#{relative_url_root}/")
|
77
|
+
"#{relative_url_root}#{source}"
|
78
|
+
else
|
79
|
+
source
|
80
|
+
|
81
|
+
_basename: (source) ->
|
82
|
+
source = matches[2] if matches = source.match(/^(.*\/)?(.+)?$/)
|
@@ -0,0 +1,19 @@
|
|
1
|
+
#= require ./base
|
2
|
+
#= require ./tag
|
3
|
+
|
4
|
+
@Ultimate.Helpers.Decor =
|
5
|
+
|
6
|
+
g_decor_body: (tag, inner) ->
|
7
|
+
content_tag(tag, '', class: 'left') +
|
8
|
+
content_tag(tag, '', class: 'right') +
|
9
|
+
content_tag(tag, inner, class: 'fill')
|
10
|
+
|
11
|
+
g_star_decor_body: (tag, inner) ->
|
12
|
+
content_tag(tag, inner, class: 'wrapper') +
|
13
|
+
content_tag(tag, '', class: 'corner left top') +
|
14
|
+
content_tag(tag, '', class: 'corner right top') +
|
15
|
+
content_tag(tag, '', class: 'corner left bottom') +
|
16
|
+
content_tag(tag, '', class: 'corner right bottom')
|
17
|
+
|
18
|
+
g_wrapper_decor_body: (tag, inner) ->
|
19
|
+
content_tag tag, inner, class: 'wrapper'
|
@@ -0,0 +1,106 @@
|
|
1
|
+
#= require ./base
|
2
|
+
#= require ./tag
|
3
|
+
|
4
|
+
@Ultimate.Helpers.FormOptions =
|
5
|
+
|
6
|
+
options_for_select: (container, selected = null) ->
|
7
|
+
return container if _.isString(container)
|
8
|
+
[selected, disabled] = _.map @_extract_selected_and_disabled(selected), (r) ->
|
9
|
+
_.map _.outcasts.arrayWrap(r), (item) -> item.toString()
|
10
|
+
container = _.pairs(container) if $.isPlainObject(container)
|
11
|
+
_.map(container, (element) ->
|
12
|
+
html_attributes = @_option_html_attributes(element)
|
13
|
+
[text, value] = _.map @_option_text_and_value(element), (item) -> if item? then item.toString() else ''
|
14
|
+
html_attributes['value'] = value
|
15
|
+
html_attributes['selected'] = 'selected' if @_option_value_selected(value, selected)
|
16
|
+
html_attributes['disabled'] = 'disabled' if disabled and @_option_value_selected(value, disabled)
|
17
|
+
Ultimate.Helpers.Tag.content_tag_string 'option', text, html_attributes
|
18
|
+
).join("\n")
|
19
|
+
|
20
|
+
options_from_collection_for_select: (collection, value_method, text_method, selected = null) ->
|
21
|
+
options = @__mapCollection collection, (element) ->
|
22
|
+
[@_value_for_collection(element, text_method), @_value_for_collection(element, value_method)]
|
23
|
+
[selected, disabled] = @_extract_selected_and_disabled(selected)
|
24
|
+
select_deselect =
|
25
|
+
selected: @_extract_values_from_collection(collection, value_method, selected)
|
26
|
+
disabled: @_extract_values_from_collection(collection, value_method, disabled)
|
27
|
+
@options_for_select(options, select_deselect)
|
28
|
+
|
29
|
+
option_groups_from_collection_for_select: (collection, group_method, group_label_method, option_key_method, option_value_method, selected_key = null) ->
|
30
|
+
@__mapCollection(collection, (group) ->
|
31
|
+
option_tags = @options_from_collection_for_select(_.result(group, group_method), option_key_method, option_value_method, selected_key)
|
32
|
+
Ultimate.Helpers.Tag.content_tag_string 'optgroup', option_tags, label: _.result(group, group_label_method), true, false
|
33
|
+
).join('')
|
34
|
+
|
35
|
+
grouped_options_for_select: (grouped_options, selected_key = null, options = {}) ->
|
36
|
+
prompt = options['prompt']
|
37
|
+
divider = options['divider']
|
38
|
+
body = ""
|
39
|
+
if prompt
|
40
|
+
body += Ultimate.Helpers.Tag.content_tag_string('option', @_prompt_text(prompt), value: '')
|
41
|
+
grouped_options = _.outcasts.sortHash(grouped_options) if $.isPlainObject(grouped_options)
|
42
|
+
_.each grouped_options, (container) ->
|
43
|
+
if divider
|
44
|
+
label = divider
|
45
|
+
else
|
46
|
+
[label, container] = container
|
47
|
+
body += Ultimate.Helpers.Tag.content_tag_string('optgroup', @options_for_select(container, selected_key), label: label, true, false)
|
48
|
+
body
|
49
|
+
|
50
|
+
|
51
|
+
|
52
|
+
_option_html_attributes: (element) ->
|
53
|
+
result = {}
|
54
|
+
if _.isArray(element)
|
55
|
+
_.extend(result, e) for e in element when $.isPlainObject(e)
|
56
|
+
result
|
57
|
+
|
58
|
+
_option_text_and_value: (option) ->
|
59
|
+
# Options are [text, value] pairs or strings used for both.
|
60
|
+
if _.isArray(option)
|
61
|
+
option = _.reject(option, (e) -> $.isPlainObject(e))
|
62
|
+
[_.first(option), _.last(option)]
|
63
|
+
else
|
64
|
+
[option, option]
|
65
|
+
|
66
|
+
_option_value_selected: (value, selected) ->
|
67
|
+
value in selected
|
68
|
+
|
69
|
+
_extract_selected_and_disabled: (selected) ->
|
70
|
+
if _.isFunction(selected)
|
71
|
+
[selected, null]
|
72
|
+
else
|
73
|
+
selected = _.outcasts.arrayWrap(selected)
|
74
|
+
options = if $.isPlainObject(_.last(selected)) then selected.pop() else {}
|
75
|
+
selected_items = options['selected'] ? selected
|
76
|
+
[selected_items, options['disabled']]
|
77
|
+
|
78
|
+
_extract_values_from_collection: (collection, value_method, selected) ->
|
79
|
+
if _.isFunction(selected)
|
80
|
+
_.compact @__mapCollection collection, (element) ->
|
81
|
+
@__getValueFromElement(element, value_method) if selected(element)
|
82
|
+
else
|
83
|
+
selected
|
84
|
+
|
85
|
+
_value_for_collection: (item, value) ->
|
86
|
+
if _.isFunction(value)
|
87
|
+
value(item)
|
88
|
+
else
|
89
|
+
@__getValueFromElement(item, value)
|
90
|
+
|
91
|
+
_prompt_text: (prompt) ->
|
92
|
+
prompt = if _.isString(prompt) then prompt else I18n?.translate('helpers.select.prompt', default: 'Please select') ? 'Please select'
|
93
|
+
|
94
|
+
|
95
|
+
|
96
|
+
__getValueFromElement: (element, property) ->
|
97
|
+
if _.isFunction(element.get)
|
98
|
+
element.get(property)
|
99
|
+
else
|
100
|
+
_.result(element, property)
|
101
|
+
|
102
|
+
__mapCollection: (collection, iterator) ->
|
103
|
+
if _.isFunction(collection.map)
|
104
|
+
collection.map(iterator)
|
105
|
+
else
|
106
|
+
_.map(collection, iterator)
|
@@ -0,0 +1,175 @@
|
|
1
|
+
#= require ./base
|
2
|
+
#= require ./tag
|
3
|
+
#= require ./url
|
4
|
+
#= require ./asset_tag
|
5
|
+
|
6
|
+
@Ultimate.Helpers.FormTag =
|
7
|
+
|
8
|
+
embed_authenticity_token_in_remote_forms: false
|
9
|
+
|
10
|
+
form_tag: (url_for_options = {}, options = {}, block = null) ->
|
11
|
+
html_options = @_html_options_for_form(url_for_options, options)
|
12
|
+
if block = _.outcasts.blockGiven(arguments)
|
13
|
+
@_form_tag_in_block(html_options, block)
|
14
|
+
else
|
15
|
+
@_form_tag_html(html_options)
|
16
|
+
|
17
|
+
select_tag: (name, option_tags = '', options = {}) ->
|
18
|
+
html_name = if options.multiple is true and not _.string.endsWith(name, '[]') then "#{name}[]" else name
|
19
|
+
if _.outcasts.delete(options, 'include_blank')
|
20
|
+
option_tags = Ultimate.Helpers.Tag.content_tag('option', '', value: '') + option_tags
|
21
|
+
if prompt = _.outcasts.delete(options, 'prompt')
|
22
|
+
option_tags = Ultimate.Helpers.Tag.content_tag('option', prompt, value: '') + option_tags
|
23
|
+
Ultimate.Helpers.Tag.content_tag 'select', option_tags, _.extend({name: html_name, id: @_sanitize_to_id(name)}, options), false
|
24
|
+
|
25
|
+
text_field_tag: (name, value = null, options = {}) ->
|
26
|
+
Ultimate.Helpers.Tag.tag 'input', _.extend({type: 'text', name: name, id: @_sanitize_to_id(name), value: value}, options)
|
27
|
+
|
28
|
+
label_tag: (name = null, content_or_options = null, options = null, block = null) ->
|
29
|
+
if block = _.outcasts.blockGiven(arguments)
|
30
|
+
[options, content_or_options] = [content_or_options, block()]
|
31
|
+
options ||= {}
|
32
|
+
if _.isString(name) and not _.string.isBlank(name)
|
33
|
+
unless _.has(options, 'for')
|
34
|
+
options = _.clone(options)
|
35
|
+
options['for'] = @_sanitize_to_id(name)
|
36
|
+
content_or_options ||= _.string.humanize(name)
|
37
|
+
Ultimate.Helpers.Tag.content_tag_string 'label', content_or_options, options, true, false
|
38
|
+
|
39
|
+
hidden_field_tag: (name, value = null, options = {}) ->
|
40
|
+
@text_field_tag name, value, _.extend(options, type: 'hidden')
|
41
|
+
|
42
|
+
file_field_tag: (name, options = {}) ->
|
43
|
+
@text_field_tag name, null, _.extend(options, type: 'file')
|
44
|
+
|
45
|
+
password_field_tag: (name = 'password', value = null, options = {}) ->
|
46
|
+
@text_field_tag name, value, _.extend(options, type: 'password')
|
47
|
+
|
48
|
+
text_area_tag: (name, content = null, options = {}) ->
|
49
|
+
if size = _.outcasts.delete(options, 'size')
|
50
|
+
[options['cols'], options['rows']] = size.split("x") if _.isFunction(size.split)
|
51
|
+
escape = _.outcasts.delete(options, 'escape') ? true
|
52
|
+
Ultimate.Helpers.Tag.content_tag 'textarea', content, _.extend({name: name, id: @_sanitize_to_id(name)}, options), escape
|
53
|
+
|
54
|
+
check_box_tag: (name, value = '1', checked = false, options = {}) ->
|
55
|
+
html_options = _.extend({type: 'checkbox', name: name, id: @_sanitize_to_id(name), value: value}, options)
|
56
|
+
html_options['checked'] = 'checked' if checked
|
57
|
+
Ultimate.Helpers.Tag.tag 'input', html_options
|
58
|
+
|
59
|
+
radio_button_tag: (name, value, checked = false, options = {}) ->
|
60
|
+
html_options = _.extend({type: 'radio', name: name, id: "#{@_sanitize_to_id(name)}_#{@_sanitize_to_id(value)}", value: value}, options)
|
61
|
+
html_options['checked'] = 'checked' if checked
|
62
|
+
Ultimate.Helpers.Tag.tag 'input', html_options
|
63
|
+
|
64
|
+
submit_tag: (value = 'Save changes', options = {}) ->
|
65
|
+
Ultimate.Helpers.Tag.tag 'input', _.extend({type: 'submit', name: 'commit', value: value}, options)
|
66
|
+
|
67
|
+
button_tag: (content_or_options = null, options = null, block = null) ->
|
68
|
+
options = content_or_options if (block = _.outcasts.blockGiven(arguments)) and $.isPlainObject(content_or_options)
|
69
|
+
options ||= {}
|
70
|
+
options = _.extend({name: 'button', type: 'submit'}, options)
|
71
|
+
content_or_options = options if block
|
72
|
+
Ultimate.Helpers.Tag.content_tag 'button', content_or_options ? 'Button', options, not block, block
|
73
|
+
|
74
|
+
image_submit_tag: (source, options = {}) ->
|
75
|
+
Ultimate.Helpers.Tag.tag 'input', _.extend({type: 'image', src: Ultimate.Helpers.AssetTag.path_to_image(source)}, options)
|
76
|
+
|
77
|
+
field_set_tag: (legend = null, options = null, block) ->
|
78
|
+
output = Ultimate.Helpers.Tag.tag('fieldset', options, true)
|
79
|
+
output += Ultimate.Helpers.Tag.content_tag('legend', legend) if _.isString(legend) and not _.string.isBlank(legend)
|
80
|
+
output += block() if block = _.outcasts.blockGiven(arguments)
|
81
|
+
output += '</fieldset>'
|
82
|
+
output
|
83
|
+
|
84
|
+
color_field_tag: (name, value = null, options = {}) ->
|
85
|
+
@text_field_tag name, value, _.extend(options, type: 'color')
|
86
|
+
|
87
|
+
search_field_tag: (name, value = null, options = {}) ->
|
88
|
+
@text_field_tag name, value, _.extend(options, type: 'search')
|
89
|
+
|
90
|
+
telephone_field_tag: (name, value = null, options = {}) ->
|
91
|
+
@text_field_tag name, value, _.extend(options, type: 'tel')
|
92
|
+
|
93
|
+
phone_field_tag: ->
|
94
|
+
@telephone_field_tag arguments...
|
95
|
+
|
96
|
+
date_field_tag: (name, value = null, options = {}) ->
|
97
|
+
@text_field_tag name, value, _.extend(options, type: 'date')
|
98
|
+
|
99
|
+
time_field_tag: (name, value = null, options = {}) ->
|
100
|
+
@text_field_tag name, value, _.extend(options, type: 'time')
|
101
|
+
|
102
|
+
datetime_field_tag: (name, value = null, options = {}) ->
|
103
|
+
@text_field_tag name, value, _.extend(options, type: 'datetime')
|
104
|
+
|
105
|
+
datetime_local_field_tag: (name, value = null, options = {}) ->
|
106
|
+
@text_field_tag name, value, _.extend(options, type: 'datetime-local')
|
107
|
+
|
108
|
+
month_field_tag: (name, value = null, options = {}) ->
|
109
|
+
@text_field_tag name, value, _.extend(options, type: 'month')
|
110
|
+
|
111
|
+
week_field_tag: (name, value = null, options = {}) ->
|
112
|
+
@text_field_tag name, value, _.extend(options, type: 'week')
|
113
|
+
|
114
|
+
url_field_tag: (name, value = null, options = {}) ->
|
115
|
+
@text_field_tag name, value, _.extend(options, type: 'url')
|
116
|
+
|
117
|
+
email_field_tag: (name, value = null, options = {}) ->
|
118
|
+
@text_field_tag name, value, _.extend(options, type: 'email')
|
119
|
+
|
120
|
+
number_field_tag: (name, value = null, options = {}) ->
|
121
|
+
options['type'] ||= 'number'
|
122
|
+
if range = _.outcasts.delete(options, 'in') or _.outcasts.delete(options, 'within')
|
123
|
+
_.extend options, min: range.min, max: range.max
|
124
|
+
@text_field_tag name, value, options
|
125
|
+
|
126
|
+
range_field_tag: (name, value = null, options = {}) ->
|
127
|
+
@number_field_tag name, value, _.extend(options, type: 'range')
|
128
|
+
|
129
|
+
utf8_enforcer_tag: ->
|
130
|
+
Ultimate.Helpers.Tag.tag 'input', type: 'hidden', name: 'utf8', value: '✓', false, false
|
131
|
+
|
132
|
+
_html_options_for_form: (url_for_options, options) ->
|
133
|
+
html_options = options
|
134
|
+
html_options['enctype'] = 'multipart/form-data' if _.outcasts.delete(html_options, 'multipart')
|
135
|
+
# The following URL is unescaped, this is just a hash of options, and it is the
|
136
|
+
# responsibility of the caller to escape all the values.
|
137
|
+
html_options['action'] = Ultimate.Helpers.Url.url_for(url_for_options)
|
138
|
+
html_options['accept-charset'] = 'UTF-8'
|
139
|
+
html_options['data-remote'] = true if _.outcasts.delete(html_options, 'remote')
|
140
|
+
if html_options['data-remote'] and
|
141
|
+
not @embed_authenticity_token_in_remote_forms and
|
142
|
+
_.string.isBlank(html_options['authenticity_token'])
|
143
|
+
# The authenticity token is taken from the meta tag in this case
|
144
|
+
html_options['authenticity_token'] = false
|
145
|
+
else if html_options['authenticity_token'] is true
|
146
|
+
# Include the default authenticity_token, which is only generated when its set to nil,
|
147
|
+
# but we needed the true value to override the default of no authenticity_token on data-remote.
|
148
|
+
html_options['authenticity_token'] = null
|
149
|
+
html_options
|
150
|
+
|
151
|
+
_extra_tags_for_form: (html_options) ->
|
152
|
+
authenticity_token = _.outcasts.delete(html_options, 'authenticity_token')
|
153
|
+
method = _.outcasts.delete(html_options, 'method')
|
154
|
+
method_tag =
|
155
|
+
if /^get$/i.test(method) # must be case-insensitive, but can't use downcase as might be nil
|
156
|
+
html_options['method'] = 'get'
|
157
|
+
''
|
158
|
+
else if _.string.isBlank(method) or /^post$/i.test(method)
|
159
|
+
html_options['method'] = 'post'
|
160
|
+
Ultimate.Helpers.Url._token_tag(authenticity_token)
|
161
|
+
else
|
162
|
+
html_options['method'] = 'post'
|
163
|
+
Ultimate.Helpers.Url._method_tag(method) + Ultimate.Helpers.Url._token_tag(authenticity_token)
|
164
|
+
tags = @utf8_enforcer_tag() + method_tag
|
165
|
+
Ultimate.Helpers.Tag.content_tag('div', tags, style: 'margin:0;padding:0;display:inline', false)
|
166
|
+
|
167
|
+
_form_tag_html: (html_options) ->
|
168
|
+
extra_tags = @_extra_tags_for_form(html_options)
|
169
|
+
Ultimate.Helpers.Tag.tag('form', html_options, true) + extra_tags
|
170
|
+
|
171
|
+
_form_tag_in_block: (html_options, block) ->
|
172
|
+
"#{@_form_tag_html(html_options)}#{block()}</form>"
|
173
|
+
|
174
|
+
_sanitize_to_id: (name) ->
|
175
|
+
if name? then name.toString().replace(/\]/g, '').replace(/[^-a-zA-Z0-9:.]/g, '_') else ''
|
@@ -0,0 +1,31 @@
|
|
1
|
+
#= require ./base
|
2
|
+
#= require ./tag
|
3
|
+
|
4
|
+
JS_ESCAPE_MAP =
|
5
|
+
'\\' : '\\\\'
|
6
|
+
'</' : '<\\/'
|
7
|
+
"\r\n" : '\\n'
|
8
|
+
"\n" : '\\n'
|
9
|
+
"\r" : '\\n'
|
10
|
+
'"' : '\\"'
|
11
|
+
"'" : "\\'"
|
12
|
+
|
13
|
+
@Ultimate.Helpers.Javascript =
|
14
|
+
|
15
|
+
escape_javascript: (javascript) ->
|
16
|
+
return '' unless _.isString(javascript)
|
17
|
+
javascript.replace( /(\\|<\/|\r\n|[\n\r"'])/g, (match) -> JS_ESCAPE_MAP[match] )
|
18
|
+
|
19
|
+
j: -> @escape_javascript arguments...
|
20
|
+
|
21
|
+
javascript_tag: (content_or_options_with_block = null, html_options = {}, block = null) ->
|
22
|
+
content =
|
23
|
+
if block = _.outcasts.blockGiven(arguments)
|
24
|
+
html_options = content_or_options_with_block if $.isPlainObject(content_or_options_with_block)
|
25
|
+
block()
|
26
|
+
else
|
27
|
+
content_or_options_with_block
|
28
|
+
Ultimate.Helpers.Tag.content_tag 'script', @javascript_cdata_section(content), html_options, false
|
29
|
+
|
30
|
+
javascript_cdata_section: (content) ->
|
31
|
+
"\n//#{Ultimate.Helpers.Tag.cdata_section("\n#{content}\n//")}\n"
|