ultimate-helpers 0.1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. data/.gitignore +8 -0
  2. data/.rvmrc +1 -0
  3. data/.rvmrc.example +1 -0
  4. data/Gemfile +10 -0
  5. data/Gemfile.lock +126 -0
  6. data/LICENSE +19 -0
  7. data/README.md +25 -0
  8. data/Rakefile +1 -0
  9. data/app/assets/javascripts/ultimate/base.js.coffee +11 -0
  10. data/app/assets/javascripts/ultimate/helpers/asset_tag.js.coffee +82 -0
  11. data/app/assets/javascripts/ultimate/helpers/base.js.coffee +3 -0
  12. data/app/assets/javascripts/ultimate/helpers/decor.js.coffee +19 -0
  13. data/app/assets/javascripts/ultimate/helpers/form_options.js.coffee +106 -0
  14. data/app/assets/javascripts/ultimate/helpers/form_tag.js.coffee +175 -0
  15. data/app/assets/javascripts/ultimate/helpers/javascript.js.coffee +31 -0
  16. data/app/assets/javascripts/ultimate/helpers/number.js.coffee +600 -0
  17. data/app/assets/javascripts/ultimate/helpers/record_tag.js.coffee +81 -0
  18. data/app/assets/javascripts/ultimate/helpers/tag.js.coffee +91 -0
  19. data/app/assets/javascripts/ultimate/helpers/url.js.coffee +152 -0
  20. data/app/assets/javascripts/ultimate/helpers.js.coffee +122 -0
  21. data/app/assets/javascripts/ultimate/jquery.base.js.coffee +85 -0
  22. data/app/assets/javascripts/ultimate/underscore/underscore.inflection.js +176 -0
  23. data/app/assets/javascripts/ultimate/underscore/underscore.js +1204 -0
  24. data/app/assets/javascripts/ultimate/underscore/underscore.outcasts.js.coffee +158 -0
  25. data/app/assets/javascripts/ultimate/underscore/underscore.string.js +600 -0
  26. data/config/routes.rb +2 -0
  27. data/lib/ultimate/helpers/engine.rb +7 -0
  28. data/lib/ultimate/helpers/version.rb +5 -0
  29. data/lib/ultimate/helpers.rb +8 -0
  30. data/scripts/rails +8 -0
  31. data/test/dummy/Rakefile +7 -0
  32. data/test/dummy/_emfile +18 -0
  33. data/test/dummy/app/assets/images/.gitkeep +0 -0
  34. data/test/dummy/app/assets/javascripts/application.js +3 -0
  35. data/test/dummy/app/assets/stylesheets/application.css +13 -0
  36. data/test/dummy/app/assets/stylesheets/global/forms.css.scss +65 -0
  37. data/test/dummy/app/assets/stylesheets/global/layout/footer.scss +18 -0
  38. data/test/dummy/app/assets/stylesheets/global/layout/header.scss +13 -0
  39. data/test/dummy/app/assets/stylesheets/global/layout/main-menu.scss +68 -0
  40. data/test/dummy/app/assets/stylesheets/global/layout.css.scss +46 -0
  41. data/test/dummy/app/assets/stylesheets/global/reserved.css.scss +79 -0
  42. data/test/dummy/app/assets/stylesheets/global/reset.css.scss +85 -0
  43. data/test/dummy/app/assets/stylesheets/global/structures.css.scss +9 -0
  44. data/test/dummy/app/assets/stylesheets/import/base.scss +36 -0
  45. data/test/dummy/app/assets/stylesheets/plugins/qunit.css.scss +3 -0
  46. data/test/dummy/app/controllers/application_controller.rb +4 -0
  47. data/test/dummy/app/controllers/main_controller.rb +8 -0
  48. data/test/dummy/app/helpers/application_helper.rb +2 -0
  49. data/test/dummy/app/mailers/.gitkeep +0 -0
  50. data/test/dummy/app/models/.gitkeep +0 -0
  51. data/test/dummy/app/views/application/_footer.html.haml +3 -0
  52. data/test/dummy/app/views/application/_header.html.haml +4 -0
  53. data/test/dummy/app/views/application/_main_menu.html.haml +11 -0
  54. data/test/dummy/app/views/layouts/application.html.haml +24 -0
  55. data/test/dummy/app/views/main/index.html.haml +13 -0
  56. data/test/dummy/app/views/main/qunit.html.haml +7 -0
  57. data/test/dummy/config/application.rb +58 -0
  58. data/test/dummy/config/boot.rb +10 -0
  59. data/test/dummy/config/database.yml +25 -0
  60. data/test/dummy/config/environment.rb +5 -0
  61. data/test/dummy/config/environments/development.rb +40 -0
  62. data/test/dummy/config/environments/production.rb +67 -0
  63. data/test/dummy/config/environments/test.rb +37 -0
  64. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  65. data/test/dummy/config/initializers/inflections.rb +15 -0
  66. data/test/dummy/config/initializers/mime_types.rb +5 -0
  67. data/test/dummy/config/initializers/qunit-rails.rb +1 -0
  68. data/test/dummy/config/initializers/secret_token.rb +7 -0
  69. data/test/dummy/config/initializers/session_store.rb +8 -0
  70. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  71. data/test/dummy/config/locales/en.yml +5 -0
  72. data/test/dummy/config/routes.rb +63 -0
  73. data/test/dummy/config.ru +4 -0
  74. data/test/dummy/log/.gitkeep +0 -0
  75. data/test/dummy/public/404.html +26 -0
  76. data/test/dummy/public/422.html +26 -0
  77. data/test/dummy/public/500.html +25 -0
  78. data/test/dummy/public/favicon.ico +0 -0
  79. data/test/dummy/script/rails +6 -0
  80. data/test/javascripts/all_tests.js.coffee +12 -0
  81. data/test/javascripts/test_helper.js.coffee +3 -0
  82. data/test/javascripts/tests/helpers/asset_tag_test.js.coffee +51 -0
  83. data/test/javascripts/tests/helpers/form_options_test.js.coffee +170 -0
  84. data/test/javascripts/tests/helpers/form_tag_test.js.coffee +226 -0
  85. data/test/javascripts/tests/helpers/javascript_test.js.coffee +25 -0
  86. data/test/javascripts/tests/helpers/number_test.js.coffee +250 -0
  87. data/test/javascripts/tests/helpers/record_tag_test.js.coffee +60 -0
  88. data/test/javascripts/tests/helpers/tag_test.js.coffee +58 -0
  89. data/test/javascripts/tests/helpers/url_test.js.coffee +76 -0
  90. data/test/javascripts/tests/underscore/underscore.outcasts.test.js.coffee +47 -0
  91. data/test/javascripts/vendors/backbone.js +1533 -0
  92. data/test/javascripts/vendors/i18n-lite.js.coffee +20 -0
  93. data/test/stylesheets/test_helper.css +4 -0
  94. data/test/stylesheets/vendors/ultimate/mixins/_routines.scss +120 -0
  95. data/test/stylesheets/vendors/ultimate/mixins/_vendors.scss +44 -0
  96. data/test/stylesheets/vendors/ultimate/mixins/css3/_text-shadow.scss +40 -0
  97. data/test/stylesheets/vendors/ultimate/mixins/css3.scss +350 -0
  98. data/test/stylesheets/vendors/ultimate/mixins/fonts.scss +100 -0
  99. data/test/stylesheets/vendors/ultimate/mixins/microstructures.scss +239 -0
  100. data/ultimate-helpers.gemspec +25 -0
  101. metadata +193 -0
data/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ *.gem
2
+ .bundle
3
+ pkg/*
4
+ .idea/
5
+ test/dummy/db/*.sqlite3
6
+ test/dummy/log/*.log
7
+ test/dummy/tmp/
8
+ test/dummy/.sass-cache
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
@@ -0,0 +1,10 @@
1
+ source 'http://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in ultimate-helpers.gemspec
4
+ gemspec
5
+
6
+ gem 'quiet_assets'
7
+ gem 'haml-rails'
8
+ gem 'sass-rails', '~> 3.2.3'
9
+ gem 'qunit-rails'
10
+ gem 'jquery-rails'
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,11 @@
1
+ #= require ./helpers
2
+
3
+ @Ultimate =
4
+
5
+ debugMode: false
6
+
7
+ debug: ->
8
+ if @debugMode
9
+ a = ["info", "Ultimate"]
10
+ Array::push.apply a, arguments if arguments.length > 0
11
+ cout.apply @, a
@@ -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,3 @@
1
+ #= require ultimate/base
2
+
3
+ @Ultimate.Helpers ||= {}
@@ -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: '&#x2713;', 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"