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
@@ -0,0 +1,91 @@
|
|
1
|
+
#= require ./base
|
2
|
+
|
3
|
+
@Ultimate.Helpers.Tag =
|
4
|
+
|
5
|
+
BOOLEAN_ATTRIBUTES: "disabled readonly multiple checked autobuffer
|
6
|
+
autoplay controls loop selected hidden scoped async
|
7
|
+
defer reversed ismap seemless muted required
|
8
|
+
autofocus novalidate formnovalidate open pubdate itemscope".split(/\s+/)
|
9
|
+
|
10
|
+
PRE_CONTENT_STRINGS:
|
11
|
+
textarea: "\n"
|
12
|
+
|
13
|
+
tag: (tag_name, options = {}, open = false, escape = true) ->
|
14
|
+
"<#{tag_name}#{@tag_options(options, escape)}#{if open then '>' else ' />'}"
|
15
|
+
|
16
|
+
content_tag: (name, content_or_options_with_block = null, options = null, escape = true, block = null) ->
|
17
|
+
if block = _.outcasts.blockGiven(arguments)
|
18
|
+
options = content_or_options_with_block
|
19
|
+
@content_tag_string(name, block(), options, escape)
|
20
|
+
else
|
21
|
+
@content_tag_string(name, content_or_options_with_block, options, escape)
|
22
|
+
|
23
|
+
cdata_section: (content) ->
|
24
|
+
splitted = content.replace(/\]\]>/g, ']]]]><![CDATA[>')
|
25
|
+
"<![CDATA[#{splitted}]]>"
|
26
|
+
|
27
|
+
content_tag_string: (name, content = '', options = {}, escape = true, _escapeContent = escape) ->
|
28
|
+
content = _.string.escapeHTML(content) if _escapeContent
|
29
|
+
"<#{name}#{@tag_options(options, escape)}>#{@PRE_CONTENT_STRINGS[name] ? ''}#{content}</#{name}>"
|
30
|
+
|
31
|
+
html_options_to_s: (html_options, escape = false, prefix = "") ->
|
32
|
+
deprecate 'html_options_to_s()', "tag_options()"
|
33
|
+
@tag_options arguments...
|
34
|
+
|
35
|
+
tag_options: (options, escape = true) ->
|
36
|
+
return "" if _.isEmpty(options)
|
37
|
+
attrs = []
|
38
|
+
for key, value of options
|
39
|
+
if key is "data" and _.isObject(value)
|
40
|
+
for k, v of value
|
41
|
+
attrs.push @data_tag_option(k, v, escape)
|
42
|
+
else if _.include(@BOOLEAN_ATTRIBUTES, key)
|
43
|
+
attrs.push @boolean_tag_option(key) if value
|
44
|
+
else if value?
|
45
|
+
attrs.push @tag_option(key, value, escape)
|
46
|
+
if _.isEmpty(attrs) then "" else " #{attrs.sort().join(' ')}"
|
47
|
+
|
48
|
+
data_tag_option: (key, value, escape) ->
|
49
|
+
key = "data-#{_.string.dasherize(key)}"
|
50
|
+
value = JSON.stringify(value) if JSON? and _.isObject(value)
|
51
|
+
@tag_option(key, value, escape)
|
52
|
+
|
53
|
+
boolean_tag_option: (key) ->
|
54
|
+
"#{key}=\"#{key}\""
|
55
|
+
|
56
|
+
tag_option: (key, value, escape) ->
|
57
|
+
value = value.join(" ") if _.isArray(value)
|
58
|
+
value = _.string.escapeHTML(value) if escape
|
59
|
+
"#{key}=\"#{value}\""
|
60
|
+
|
61
|
+
concat_class: ->
|
62
|
+
flatten_classes = _.filter( _.flatten(arguments), (e) -> _.isString(e) ).join(' ')
|
63
|
+
_.uniq( _.string.words(flatten_classes) ).join(' ')
|
64
|
+
|
65
|
+
|
66
|
+
|
67
|
+
selfClosedTags: _.string.words('area base br col command embed hr img input keygen link meta param source track wbr')
|
68
|
+
|
69
|
+
# Generate html from zen-selector. Ninja tool.
|
70
|
+
# TODO more zen features: +, *x, {content}
|
71
|
+
# TODO cache
|
72
|
+
selectorToHtml: (selector) ->
|
73
|
+
if matches = selector.match(/^[\s>]*([\w\-\.#]+)(.*)$/)
|
74
|
+
selector = matches[1]
|
75
|
+
continuation = matches[2] # in v1 {(if continuation then ">" + content else " />")}
|
76
|
+
tag_name = selector.match(/^\w+/)?[0] or 'div'
|
77
|
+
id = selector.match(/#([\w\-]+)/)?[1]
|
78
|
+
classes = _.map( selector.match(/\.[\w\-]+/g), (c) -> _.string.ltrim(c, '.') )
|
79
|
+
html_options = {}
|
80
|
+
html_options['id'] = id if id
|
81
|
+
html_options['class'] = classes.join(' ') if classes.length
|
82
|
+
if _.contains(@selfClosedTags, tag_name)
|
83
|
+
@tag(tag_name, html_options)
|
84
|
+
else
|
85
|
+
continuation = @selectorToHtml(continuation) if continuation
|
86
|
+
@content_tag(tag_name, continuation, html_options)
|
87
|
+
# else if matches = selector.match(/^\s*\+\s*(.*)$/) # /^\s*\+\s*([\w\.#]+)(.*)$/)
|
88
|
+
# continuation = matches[1]
|
89
|
+
# if continuation then @selectorToHtml(continuation) else continuation
|
90
|
+
else
|
91
|
+
''
|
@@ -0,0 +1,152 @@
|
|
1
|
+
#= require ./base
|
2
|
+
#= require ./tag
|
3
|
+
#= require ./javascript
|
4
|
+
|
5
|
+
__char_encode = (char) -> "%#{char.charCodeAt(0).toString(16)}"
|
6
|
+
__escape_path = (str) -> str.replace(/[^*\-.0-9A-Z_a-z]/g, __char_encode).replace(/\+/g, '%20')
|
7
|
+
__string_encode = (str) -> _.map(str, (char) -> "&##{char.charCodeAt(0)};" ).join('')
|
8
|
+
|
9
|
+
@Ultimate.Helpers.Url =
|
10
|
+
|
11
|
+
url_for: (options = null) ->
|
12
|
+
if _.isString(options)
|
13
|
+
if options is 'back'
|
14
|
+
'javascript:history.back();'
|
15
|
+
else
|
16
|
+
options
|
17
|
+
else unless _.isEmpty(options)
|
18
|
+
url = _.result(options, 'url') ? ''
|
19
|
+
if $.isPlainObject(options)
|
20
|
+
options = _.clone(options)
|
21
|
+
delete options['url']
|
22
|
+
anchor = _.outcasts.delete(options, 'anchor')
|
23
|
+
url += "?#{_.map(options, (value, key) -> "#{key}=#{value}").sort().join('&')}" unless _.isEmpty(options)
|
24
|
+
url += "##{anchor}" if anchor
|
25
|
+
url
|
26
|
+
else
|
27
|
+
'javascript:;'
|
28
|
+
|
29
|
+
link_to: (name = null, options = null, html_options = null, block = null) ->
|
30
|
+
[html_options, options] = [options, name] if block = _.outcasts.blockGiven(arguments)
|
31
|
+
options ||= {}
|
32
|
+
url = @url_for(options)
|
33
|
+
html_options = @_convert_options_to_data_attributes(options, html_options)
|
34
|
+
html_options['href'] ||= url
|
35
|
+
if block
|
36
|
+
Ultimate.Helpers.Tag.content_tag('a', html_options, null, false, block)
|
37
|
+
else
|
38
|
+
Ultimate.Helpers.Tag.content_tag('a', name ? url, html_options, false)
|
39
|
+
|
40
|
+
link_to_js: (name = null, html_options = null, block = null) ->
|
41
|
+
[options, name] = [name, null] if block = _.outcasts.blockGiven(arguments)
|
42
|
+
@link_to [name, options, html_options, block]...
|
43
|
+
|
44
|
+
# TODO tests
|
45
|
+
link_to_unless_current_span: (name, options = null, html_options = null, block = null) ->
|
46
|
+
[html_options, options] = [options, name] if block = _.outcasts.blockGiven(arguments)
|
47
|
+
url = @url_for(options)
|
48
|
+
if @current_page_(url)
|
49
|
+
if block
|
50
|
+
Ultimate.Helpers.Tag.content_tag('span', html_options, null, false, block)
|
51
|
+
else
|
52
|
+
Ultimate.Helpers.Tag.content_tag('span', name ? url, html_options, false)
|
53
|
+
else
|
54
|
+
if block
|
55
|
+
@link_to options, html_options, block
|
56
|
+
else
|
57
|
+
@link_to name, options, html_options
|
58
|
+
|
59
|
+
# TODO tests
|
60
|
+
link_to_unless_current: (name, options = {}, html_options = {}, block = null) ->
|
61
|
+
@link_to_unless @current_page_(options), name, options, html_options, block
|
62
|
+
|
63
|
+
# TODO tests
|
64
|
+
link_to_unless: (condition, name, options = {}, html_options = {}, block = null) ->
|
65
|
+
if condition
|
66
|
+
if block = _.outcasts.blockGiven(arguments)
|
67
|
+
block(name, options, html_options)
|
68
|
+
else
|
69
|
+
name
|
70
|
+
else
|
71
|
+
@link_to name, options, html_options, block
|
72
|
+
|
73
|
+
# TODO tests
|
74
|
+
link_to_if: (condition, name, options = {}, html_options = {}, block = null) ->
|
75
|
+
@link_to_unless not condition, name, options, html_options, block
|
76
|
+
|
77
|
+
mail_to: (email_address, name = null, html_options = {}) ->
|
78
|
+
email_address = _.string.escapeHTML(email_address)
|
79
|
+
encode = _.outcasts.delete(html_options, 'encode')
|
80
|
+
extras = _.compact _.map _.string.words('cc bcc body subject'), (item) ->
|
81
|
+
option = _.outcasts.delete(html_options, item)
|
82
|
+
if option?
|
83
|
+
"#{item}=#{__escape_path(option)}"
|
84
|
+
extras = if _.isEmpty(extras) then '' else '?' + _.string.escapeHTML(extras.join('&'))
|
85
|
+
email_address_obfuscated = email_address
|
86
|
+
email_address_obfuscated = email_address_obfuscated.replace('@', _.outcasts.delete(html_options, 'replace_at')) if 'replace_at' of html_options
|
87
|
+
email_address_obfuscated = email_address_obfuscated.replace('.', _.outcasts.delete(html_options, 'replace_dot')) if 'replace_dot' of html_options
|
88
|
+
switch encode
|
89
|
+
when 'javascript'
|
90
|
+
html = @link_to(name or email_address_obfuscated, "mailto:#{email_address}#{extras}", html_options)
|
91
|
+
html = Ultimate.Helpers.Javascript.escape_javascript(html)
|
92
|
+
string = _.map("document.write('#{html}');", __char_encode).join('')
|
93
|
+
"<script>eval(decodeURIComponent('#{string}'))</script>"
|
94
|
+
when 'hex'
|
95
|
+
email_address_encoded = __string_encode(email_address_obfuscated)
|
96
|
+
string = __string_encode('mailto:') + _.map(email_address, (char) -> if /\w/.test(char) then __char_encode(char) else char).join('')
|
97
|
+
@link_to name or email_address_encoded, "#{string}#{extras}", html_options
|
98
|
+
else
|
99
|
+
@link_to name or email_address_obfuscated, "mailto:#{email_address}#{extras}", html_options
|
100
|
+
|
101
|
+
# TODO tests
|
102
|
+
current_page_: (options) ->
|
103
|
+
url_string = @url_for(options)
|
104
|
+
request_uri = location.pathname
|
105
|
+
if /^\w+:\/\//.test(url_string)
|
106
|
+
url_string == "#{location.protocol}#{location.host}#{request_uri}"
|
107
|
+
else
|
108
|
+
url_string == request_uri
|
109
|
+
|
110
|
+
|
111
|
+
|
112
|
+
_convert_options_to_data_attributes: (options, html_options) ->
|
113
|
+
if html_options
|
114
|
+
html_options['data-remote'] = 'true' if @_link_to_remote_options(options) or @_link_to_remote_options(html_options)
|
115
|
+
method = _.outcasts.delete(html_options, 'method')
|
116
|
+
@_add_method_to_attributes(html_options, method) if method
|
117
|
+
html_options
|
118
|
+
else
|
119
|
+
if @_link_to_remote_options(options) then {'data-remote': 'true'} else {}
|
120
|
+
|
121
|
+
_link_to_remote_options: (options) ->
|
122
|
+
_.isObject(options) and _.outcasts.delete(options, 'remote')
|
123
|
+
|
124
|
+
_add_method_to_attributes: (html_options, method) ->
|
125
|
+
if _.isString(method) and method.toLowerCase() isnt 'get' and not /nofollow/.test(html_options['rel'])
|
126
|
+
html_options['rel'] = Ultimate.Helpers.Tag.concat_class(html_options['rel'], 'nofollow')
|
127
|
+
html_options['data-method'] = method
|
128
|
+
|
129
|
+
_convert_boolean_attributes: (html_options, bool_attrs) ->
|
130
|
+
html_options[x] = x for x in bool_attrs when _.outcasts.delete(html_options, x)
|
131
|
+
html_options
|
132
|
+
|
133
|
+
__protect_against_forgery: false
|
134
|
+
__request_forgery_protection_token: 'form_token'
|
135
|
+
__form_authenticity_token: 'secret'
|
136
|
+
|
137
|
+
__init_request_forgery_protection: ->
|
138
|
+
param = $('head meta[name="csrf-param"]').attr('content')
|
139
|
+
token = $('head meta[name="csrf-token"]').attr('content')
|
140
|
+
if param and token
|
141
|
+
@__protect_against_forgery = true
|
142
|
+
@__request_forgery_protection_token = param
|
143
|
+
@__form_authenticity_token = token
|
144
|
+
|
145
|
+
_token_tag: (token = @__form_authenticity_token) ->
|
146
|
+
if token isnt false and @__protect_against_forgery
|
147
|
+
Ultimate.Helpers.Tag.tag 'input', type: 'hidden', name: @__request_forgery_protection_token, value: token
|
148
|
+
else
|
149
|
+
''
|
150
|
+
|
151
|
+
_method_tag: (method) ->
|
152
|
+
Ultimate.Helpers.Tag.tag 'input', type: 'hidden', name: '_method', value: method
|
@@ -0,0 +1,122 @@
|
|
1
|
+
###
|
2
|
+
* front-end js helpers
|
3
|
+
* 0.3.3.alpha / 2010-2011
|
4
|
+
* Karpunin Dmitry / Evrone.com
|
5
|
+
* koderfunk_at_gmail_dot_com
|
6
|
+
###
|
7
|
+
|
8
|
+
@DEBUG_MODE ?= false
|
9
|
+
@TEST_MODE ?= false
|
10
|
+
@LOG_TODO ?= true
|
11
|
+
|
12
|
+
@cout = =>
|
13
|
+
args = _.toArray(arguments)
|
14
|
+
method = if args[0] in ['log', 'info', 'warn', 'error', 'assert', 'clear'] then args.shift() else 'log'
|
15
|
+
if @DEBUG_MODE and console?
|
16
|
+
method = console[method]
|
17
|
+
if method.apply?
|
18
|
+
method.apply(console, args)
|
19
|
+
else
|
20
|
+
method(args)
|
21
|
+
return args[0]
|
22
|
+
|
23
|
+
@_cout = =>
|
24
|
+
console.log(arguments) if console?
|
25
|
+
arguments[0]
|
26
|
+
|
27
|
+
@deprecate = (subject, instead = null) =>
|
28
|
+
@cout 'error', "`#{subject}` DEPRECATED!#{if instead then " Use instead `#{instead}`" else ''}"
|
29
|
+
|
30
|
+
@todo = (subject, location = null, numberOrString = null) =>
|
31
|
+
if @LOG_TODO
|
32
|
+
@cout 'warn', "TODO: #{subject}#{if location then " ### #{location}" else ''}#{if numberOrString then (if _.isNumber(numberOrString) then ":#{numberOrString}" else " > #{numberOrString}") else ''}"
|
33
|
+
|
34
|
+
@args = (a) ->
|
35
|
+
@deprecate 'arg()', '_.toArray()'
|
36
|
+
r = []
|
37
|
+
Array::push.apply(r, a) if a.length > 0
|
38
|
+
r
|
39
|
+
|
40
|
+
@logicalXOR = (a, b) ->
|
41
|
+
( a and not b ) or ( not a and b )
|
42
|
+
|
43
|
+
@bound = (number, min, max) ->
|
44
|
+
Math.max(min, Math.min(max, number))
|
45
|
+
|
46
|
+
|
47
|
+
|
48
|
+
@getParams = ->
|
49
|
+
q = location.search.substring(1).split('&')
|
50
|
+
r = {}
|
51
|
+
for e in q
|
52
|
+
t = e.split('=')
|
53
|
+
r[t[0]] = t[1]
|
54
|
+
r
|
55
|
+
|
56
|
+
@respondFormat = (url, format = null) ->
|
57
|
+
aq = url.split('?')
|
58
|
+
ah = aq[0].split('#')
|
59
|
+
ad = ah[0].split('.')
|
60
|
+
currentFormat = if ad.length > 1 and not /\//.test(ad[ad.length - 1]) then ad.pop() else ''
|
61
|
+
return currentFormat unless format?
|
62
|
+
return url if format is currentFormat
|
63
|
+
ad.push format if format
|
64
|
+
ah[0] = ad.join('.')
|
65
|
+
aq[0] = ah.join('#')
|
66
|
+
aq.join('?')
|
67
|
+
|
68
|
+
|
69
|
+
|
70
|
+
########### Deprecated ###########
|
71
|
+
|
72
|
+
# Helper function to get a value from a object as a property or as a function.
|
73
|
+
@getValue = (object, prop) ->
|
74
|
+
@deprecate "getValue()", "_.result()"
|
75
|
+
return null unless object and object[prop]
|
76
|
+
return if _.isFunction(object[prop]) then object[prop]() else object[prop]
|
77
|
+
|
78
|
+
@isset = (obj) =>
|
79
|
+
@deprecate 'isset(obj)', '_.isUndefined(obj) OR "obj isnt undefined" OR "obj?'
|
80
|
+
obj isnt undefined
|
81
|
+
|
82
|
+
@isString = (v) =>
|
83
|
+
@deprecate 'isString(v)', '_.isString(v)'
|
84
|
+
_.isString v
|
85
|
+
|
86
|
+
@isNumber = (v) =>
|
87
|
+
@deprecate 'isNumber(v)', '_.isNumber(v)'
|
88
|
+
not isNaN(parseInt(v))
|
89
|
+
|
90
|
+
@isJQ = (obj) ->
|
91
|
+
@deprecate 'isJQ(obj)', 'obj instanceof jQuery'
|
92
|
+
_.isObject(obj) and _.isString(obj.jquery)
|
93
|
+
|
94
|
+
@uniq = (arrOrString) ->
|
95
|
+
@deprecate 'uniq(a)', '_.uniq(a)'
|
96
|
+
isStr = _.isString(arrOrString)
|
97
|
+
return arrOrString unless isStr or _.isArray(arrOrString)
|
98
|
+
r = []
|
99
|
+
r.push(e) for e in arrOrString when not _.include(r, e)
|
100
|
+
if isStr then r.join('') else r
|
101
|
+
|
102
|
+
@regexpSpace = /^\s*$/
|
103
|
+
@regexpTrim = /^\s*(.*?)\s*$/
|
104
|
+
|
105
|
+
@strTrim = (s) =>
|
106
|
+
@deprecate "strTrim(s)", "_.trim(s)"
|
107
|
+
s.match(@regexpTrim)[1]
|
108
|
+
|
109
|
+
|
110
|
+
|
111
|
+
@rails_data = {}
|
112
|
+
|
113
|
+
@rails_scope = (controller_name, action_name, scopedCloasure = null, scopedCloasureArguments...) =>
|
114
|
+
@deprecate 'rails_scope'
|
115
|
+
return false if _.isString(controller_name) and controller_name isnt @rails_data['controller_name']
|
116
|
+
return false if _.isString(action_name) and action_name isnt @rails_data['action_name']
|
117
|
+
if _.isFunction(scopedCloasure)
|
118
|
+
arguments[2] scopedCloasureArguments...
|
119
|
+
true
|
120
|
+
|
121
|
+
$ =>
|
122
|
+
@rails_data = $('body').data()
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# TODO: register components
|
2
|
+
|
3
|
+
do ($ = jQuery) =>
|
4
|
+
|
5
|
+
$.regexp ||= {}
|
6
|
+
|
7
|
+
$.regexp.rorId ||= /(\w+)_(\d+)$/
|
8
|
+
|
9
|
+
@ror_id = (jObjOrString) ->
|
10
|
+
if jObjOrString instanceof jQuery
|
11
|
+
id = jObjOrString.data("rorId") # Maybe use "id"
|
12
|
+
unless id?
|
13
|
+
id = ror_id(jObjOrString.attr("id"))
|
14
|
+
jObjOrString.data("rorId", id) if id?
|
15
|
+
id
|
16
|
+
else if _.isString(jObjOrString)
|
17
|
+
matchResult = jObjOrString.match($.regexp.rorId)
|
18
|
+
if matchResult then matchResult[2] else null
|
19
|
+
else
|
20
|
+
null
|
21
|
+
|
22
|
+
$.fn.rorId = (id = null, prefix = null) ->
|
23
|
+
if arguments.length
|
24
|
+
jThis = @first()
|
25
|
+
thisId = @attr("id")
|
26
|
+
if not prefix? and _.isString(thisId)
|
27
|
+
prefix = matchResult[1] if matchResult = thisId.match($.regexp.rorId)
|
28
|
+
@data("rorId", id)
|
29
|
+
if prefix?
|
30
|
+
jThis.attr "id", "#{prefix}_#{id}"
|
31
|
+
jThis
|
32
|
+
else
|
33
|
+
ror_id @
|
34
|
+
|
35
|
+
$.fn.getClasses = ->
|
36
|
+
_.string.words @attr("class")
|
37
|
+
|
38
|
+
# Get hash of html-dom attributes from first matched element or false, if no elements
|
39
|
+
$.fn.getAttributes = ->
|
40
|
+
attrs = {}
|
41
|
+
if @length
|
42
|
+
attrs[attr.nodeName] = attr.nodeValue for attr in this[0].attributes
|
43
|
+
attrs
|
44
|
+
|
45
|
+
# [showOrHide[, duration[, callback]]]
|
46
|
+
$.fn.slideToggleByState = ->
|
47
|
+
if @length
|
48
|
+
if arguments.length > 0
|
49
|
+
a = _.toArray(arguments)
|
50
|
+
if a.shift()
|
51
|
+
@slideDown.apply @, a
|
52
|
+
else
|
53
|
+
@slideUp.apply @, a
|
54
|
+
else
|
55
|
+
@slideToggle()
|
56
|
+
@
|
57
|
+
|
58
|
+
unless $.isHTML
|
59
|
+
$.regexp.HTML = /^\s*<(\w+)[\S\s]*<\/(\w+)>\s*$/
|
60
|
+
$.isHTML = (content, strong = false) ->
|
61
|
+
return false unless _.isString(content)
|
62
|
+
matches = content.match($.regexp.HTML)
|
63
|
+
return false unless matches?
|
64
|
+
not strong or matches[1] is matches[2]
|
65
|
+
|
66
|
+
# TODO replace usages to underscore methods and using distribution
|
67
|
+
unless $.isRegExp
|
68
|
+
$.isRegExp = (candidate) ->
|
69
|
+
deprecate '$.isRegExp', '_.isRegExp'
|
70
|
+
typeof candidate is "object" and typeof candidate.test is "function"
|
71
|
+
|
72
|
+
unless $.isBoolean
|
73
|
+
$.isBoolean = (v) ->
|
74
|
+
deprecate '$.isBoolean', '_.isBoolean'
|
75
|
+
typeof v is "boolean"
|
76
|
+
|
77
|
+
unless $.isString
|
78
|
+
$.isString = (v) ->
|
79
|
+
deprecate '$.isString', '_.isString'
|
80
|
+
typeof v is "string"
|
81
|
+
|
82
|
+
if typeof $.isEmptyString is "undefined"
|
83
|
+
$.isEmptyString = (v) ->
|
84
|
+
deprecate '$.isEmptyString', '_.isBlank'
|
85
|
+
regexpSpace.test v
|
@@ -0,0 +1,176 @@
|
|
1
|
+
// Underscore.inflection.js
|
2
|
+
// (c) 2011 Jeremy Ruppel
|
3
|
+
// Underscore.inflection is freely distributable under the MIT license.
|
4
|
+
// Portions of Underscore.inflection are inspired or borrowed from ActiveSupport
|
5
|
+
// Version 1.0.0
|
6
|
+
|
7
|
+
( function( _, undefined )
|
8
|
+
{
|
9
|
+
var
|
10
|
+
plurals = [ ],
|
11
|
+
|
12
|
+
singulars = [ ],
|
13
|
+
|
14
|
+
uncountables = [ ];
|
15
|
+
|
16
|
+
/**
|
17
|
+
* Inflector
|
18
|
+
*/
|
19
|
+
var inflector = {
|
20
|
+
|
21
|
+
gsub : function( word, rule, replacement )
|
22
|
+
{
|
23
|
+
var pattern = new RegExp( rule.source || rule, 'gi' );
|
24
|
+
|
25
|
+
return pattern.test( word ) ? word.replace( pattern, replacement ) : null;
|
26
|
+
},
|
27
|
+
|
28
|
+
plural : function( rule, replacement )
|
29
|
+
{
|
30
|
+
plurals.unshift( [ rule, replacement ] );
|
31
|
+
},
|
32
|
+
|
33
|
+
pluralize : function( word, count, includeNumber )
|
34
|
+
{
|
35
|
+
var result;
|
36
|
+
|
37
|
+
if( count !== undefined )
|
38
|
+
{
|
39
|
+
result = ( count === 1 ) ? this.singularize( word ) : this.pluralize( word );
|
40
|
+
result = ( includeNumber ) ? [ count, result ].join( ' ' ) : result;
|
41
|
+
}
|
42
|
+
else
|
43
|
+
{
|
44
|
+
if( _( uncountables ).include( word ) )
|
45
|
+
{
|
46
|
+
return word;
|
47
|
+
}
|
48
|
+
|
49
|
+
result = word;
|
50
|
+
|
51
|
+
_( plurals ).detect( function( rule )
|
52
|
+
{
|
53
|
+
var gsub = this.gsub( word, rule[ 0 ], rule[ 1 ] );
|
54
|
+
|
55
|
+
return gsub ? ( result = gsub ) : false;
|
56
|
+
},
|
57
|
+
this );
|
58
|
+
}
|
59
|
+
|
60
|
+
return result;
|
61
|
+
},
|
62
|
+
|
63
|
+
singular : function( rule, replacement )
|
64
|
+
{
|
65
|
+
singulars.unshift( [ rule, replacement ] );
|
66
|
+
},
|
67
|
+
|
68
|
+
singularize : function( word )
|
69
|
+
{
|
70
|
+
if( _( uncountables ).include( word ) )
|
71
|
+
{
|
72
|
+
return word;
|
73
|
+
}
|
74
|
+
|
75
|
+
var result = word;
|
76
|
+
|
77
|
+
_( singulars ).detect( function( rule )
|
78
|
+
{
|
79
|
+
var gsub = this.gsub( word, rule[ 0 ], rule[ 1 ] );
|
80
|
+
|
81
|
+
return gsub ? ( result = gsub ) : false;
|
82
|
+
},
|
83
|
+
this );
|
84
|
+
|
85
|
+
return result;
|
86
|
+
},
|
87
|
+
|
88
|
+
irregular : function( singular, plural )
|
89
|
+
{
|
90
|
+
this.plural( '\\b' + singular + '\\b', plural );
|
91
|
+
this.singular( '\\b' + plural + '\\b', singular );
|
92
|
+
},
|
93
|
+
|
94
|
+
uncountable : function( word )
|
95
|
+
{
|
96
|
+
uncountables.unshift( word );
|
97
|
+
},
|
98
|
+
|
99
|
+
resetInflections : function( )
|
100
|
+
{
|
101
|
+
plurals = [ ];
|
102
|
+
singulars = [ ];
|
103
|
+
uncountables = [ ];
|
104
|
+
|
105
|
+
this.plural( /$/, 's' );
|
106
|
+
this.plural( /s$/, 's' );
|
107
|
+
this.plural( /(ax|test)is$/, '$1es' );
|
108
|
+
this.plural( /(octop|vir)us$/, '$1i' );
|
109
|
+
this.plural( /(octop|vir)i$/, '$1i' );
|
110
|
+
this.plural( /(alias|status)$/, '$1es' );
|
111
|
+
this.plural( /(bu)s$/, '$1ses' );
|
112
|
+
this.plural( /(buffal|tomat)o$/, '$1oes' );
|
113
|
+
this.plural( /([ti])um$/, '$1a' );
|
114
|
+
this.plural( /([ti])a$/, '$1a' );
|
115
|
+
this.plural( /sis$/, 'ses' );
|
116
|
+
this.plural( /(?:([^f])fe|([lr])f)$/, '$1$2ves' );
|
117
|
+
this.plural( /(hive)$/, '$1s' );
|
118
|
+
this.plural( /([^aeiouy]|qu)y$/, '$1ies' );
|
119
|
+
this.plural( /(x|ch|ss|sh)$/, '$1es' );
|
120
|
+
this.plural( /(matr|vert|ind)(?:ix|ex)$/, '$1ices' );
|
121
|
+
this.plural( /([m|l])ouse$/, '$1ice' );
|
122
|
+
this.plural( /([m|l])ice$/, '$1ice' );
|
123
|
+
this.plural( /^(ox)$/, '$1en' );
|
124
|
+
this.plural( /^(oxen)$/, '$1' );
|
125
|
+
this.plural( /(quiz)$/, '$1zes' );
|
126
|
+
|
127
|
+
this.singular( /s$/, '' );
|
128
|
+
this.singular( /(n)ews$/, '$1ews' );
|
129
|
+
this.singular( /([ti])a$/, '$1um' );
|
130
|
+
this.singular( /((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/, '$1$2sis' );
|
131
|
+
this.singular( /(^analy)ses$/, '$1sis' );
|
132
|
+
this.singular( /([^f])ves$/, '$1fe' );
|
133
|
+
this.singular( /(hive)s$/, '$1' );
|
134
|
+
this.singular( /(tive)s$/, '$1' );
|
135
|
+
this.singular( /([lr])ves$/, '$1f' );
|
136
|
+
this.singular( /([^aeiouy]|qu)ies$/, '$1y' );
|
137
|
+
this.singular( /(s)eries$/, '$1eries' );
|
138
|
+
this.singular( /(m)ovies$/, '$1ovie' );
|
139
|
+
this.singular( /(x|ch|ss|sh)es$/, '$1' );
|
140
|
+
this.singular( /([m|l])ice$/, '$1ouse' );
|
141
|
+
this.singular( /(bus)es$/, '$1' );
|
142
|
+
this.singular( /(o)es$/, '$1' );
|
143
|
+
this.singular( /(shoe)s$/, '$1' );
|
144
|
+
this.singular( /(cris|ax|test)es$/, '$1is' );
|
145
|
+
this.singular( /(octop|vir)i$/, '$1us' );
|
146
|
+
this.singular( /(alias|status)es$/, '$1' );
|
147
|
+
this.singular( /^(ox)en/, '$1' );
|
148
|
+
this.singular( /(vert|ind)ices$/, '$1ex' );
|
149
|
+
this.singular( /(matr)ices$/, '$1ix' );
|
150
|
+
this.singular( /(quiz)zes$/, '$1' );
|
151
|
+
this.singular( /(database)s$/, '$1' );
|
152
|
+
|
153
|
+
this.irregular( 'person', 'people' );
|
154
|
+
this.irregular( 'man', 'men' );
|
155
|
+
this.irregular( 'child', 'children' );
|
156
|
+
this.irregular( 'sex', 'sexes' );
|
157
|
+
this.irregular( 'move', 'moves' );
|
158
|
+
this.irregular( 'cow', 'kine' );
|
159
|
+
|
160
|
+
_( 'equipment information rice money species series fish sheep jeans'.split( /\s+/ ) ).each( function( word )
|
161
|
+
{
|
162
|
+
this.uncountable( word );
|
163
|
+
},
|
164
|
+
this );
|
165
|
+
|
166
|
+
return this;
|
167
|
+
}
|
168
|
+
|
169
|
+
};
|
170
|
+
|
171
|
+
/**
|
172
|
+
* Underscore integration
|
173
|
+
*/
|
174
|
+
_.mixin( inflector.resetInflections( ) );
|
175
|
+
|
176
|
+
} )( _ );
|