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
@@ -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
+ } )( _ );