ultimate-base 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. data/.gitignore +5 -0
  2. data/.rvmrc +2 -0
  3. data/.rvmrc.example +2 -0
  4. data/Gemfile +4 -0
  5. data/Gemfile.lock +14 -0
  6. data/LICENSE +5 -0
  7. data/README.md +1 -0
  8. data/Rakefile +1 -0
  9. data/app/assets/javascripts/backbone/backbone.js +1452 -0
  10. data/app/assets/javascripts/backbone/ultimate/app.js.coffee +25 -0
  11. data/app/assets/javascripts/backbone/ultimate/collection.js.coffee +12 -0
  12. data/app/assets/javascripts/backbone/ultimate/model.js.coffee +12 -0
  13. data/app/assets/javascripts/backbone/ultimate/router.js.coffee +13 -0
  14. data/app/assets/javascripts/backbone/ultimate/view.js.coffee +96 -0
  15. data/app/assets/javascripts/ultimate/base.js.coffee +103 -0
  16. data/app/assets/javascripts/ultimate/bus.js.coffee +57 -0
  17. data/app/assets/javascripts/ultimate/devise.js.coffee +18 -0
  18. data/app/assets/javascripts/ultimate/experimental/_inflections/dzone.inflections.js +154 -0
  19. data/app/assets/javascripts/ultimate/experimental/_inflections/inflections.js.coffee +2 -0
  20. data/app/assets/javascripts/ultimate/experimental/_inflections/plur.js +29 -0
  21. data/app/assets/javascripts/ultimate/experimental/_inflections/underscore.inflection.js +175 -0
  22. data/app/assets/javascripts/ultimate/experimental/fuzzy-json-generator.js.coffee +48 -0
  23. data/app/assets/javascripts/ultimate/helpers/array.js.coffee +63 -0
  24. data/app/assets/javascripts/ultimate/helpers/asset_tag.js.coffee +63 -0
  25. data/app/assets/javascripts/ultimate/helpers/decor.js.coffee +14 -0
  26. data/app/assets/javascripts/ultimate/helpers/forms.js.coffee +0 -0
  27. data/app/assets/javascripts/ultimate/helpers/tags.js.coffee +70 -0
  28. data/app/assets/javascripts/ultimate/helpers.js.coffee +149 -0
  29. data/app/assets/javascripts/ultimate/improves/datepicker.js.coffee +34 -0
  30. data/app/assets/javascripts/ultimate/improves/form-errors.js.coffee +146 -0
  31. data/app/assets/javascripts/ultimate/improves/form.js.coffee +155 -0
  32. data/app/assets/javascripts/ultimate/improves/magic-radios.js.coffee +41 -0
  33. data/app/assets/javascripts/ultimate/improves/tablesorter.js +59 -0
  34. data/app/assets/javascripts/ultimate/improves/typed-field.js.coffee +98 -0
  35. data/app/assets/javascripts/ultimate/underscore/underscore.js +1059 -0
  36. data/app/assets/javascripts/ultimate/underscore/underscore.string.js +480 -0
  37. data/app/assets/javascripts/ultimate/widgets/dock.js.coffee +70 -0
  38. data/app/assets/javascripts/ultimate/widgets/gear.js.coffee +84 -0
  39. data/app/assets/javascripts/ultimate/widgets/jquery-ext.js.coffee +104 -0
  40. data/app/assets/javascripts/ultimate/widgets/jquery.adapter.js.coffee +62 -0
  41. data/app/assets/javascripts/ultimate/widgets/widget.js.coffee +115 -0
  42. data/app/assets/stylesheets/polyfills/PIE.htc +96 -0
  43. data/app/assets/stylesheets/polyfills/boxsizing.htc +300 -0
  44. data/app/assets/stylesheets/ultimate/mixins/_routines.css.scss +95 -0
  45. data/app/assets/stylesheets/ultimate/mixins/_vendors.css.scss +34 -0
  46. data/app/assets/stylesheets/ultimate/mixins/css3/_text-shadow.scss +37 -0
  47. data/app/assets/stylesheets/ultimate/mixins/css3.css.scss +328 -0
  48. data/app/assets/stylesheets/ultimate/mixins/decor.css.scss +86 -0
  49. data/app/assets/stylesheets/ultimate/mixins/fonts.css.scss +100 -0
  50. data/app/assets/stylesheets/ultimate/mixins/microstructures.css.scss +188 -0
  51. data/app/assets/stylesheets/ultimate/structures/slider.css.scss +53 -0
  52. data/lib/ultimate-base/engine.rb +6 -0
  53. data/lib/ultimate-base/extensions/directive_processor.rb +64 -0
  54. data/lib/ultimate-base/extensions/sass_script_functions.rb +39 -0
  55. data/lib/ultimate-base/version.rb +5 -0
  56. data/lib/ultimate-base.rb +10 -0
  57. data/ultimate-base.gemspec +25 -0
  58. metadata +102 -0
@@ -0,0 +1,175 @@
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
+ /**
10
+ * Inflector
11
+ */
12
+ var inflector = {
13
+
14
+ plurals : [ ],
15
+
16
+ singulars : [ ],
17
+
18
+ uncountables : [ ],
19
+
20
+ gsub : function( word, rule, replacement )
21
+ {
22
+ var pattern = new RegExp( rule.source || rule, 'gi' );
23
+
24
+ return pattern.test( word ) ? word.replace( pattern, replacement ) : null;
25
+ },
26
+
27
+ plural : function( rule, replacement )
28
+ {
29
+ this.plurals.unshift( [ rule, replacement ] );
30
+ },
31
+
32
+ pluralize : function( word, count, includeNumber )
33
+ {
34
+ var result;
35
+
36
+ if( count !== undefined )
37
+ {
38
+ result = ( count === 1 ) ? this.singularize( word ) : this.pluralize( word );
39
+ result = ( includeNumber ) ? [ count, result ].join( ' ' ) : result;
40
+ }
41
+ else
42
+ {
43
+ if( _( this.uncountables ).include( word ) )
44
+ {
45
+ return word;
46
+ }
47
+
48
+ result = word;
49
+
50
+ _( this.plurals ).detect( function( rule )
51
+ {
52
+ var gsub = this.gsub( word, rule[ 0 ], rule[ 1 ] );
53
+
54
+ return gsub ? ( result = gsub ) : false;
55
+ },
56
+ this );
57
+ }
58
+
59
+ return result;
60
+ },
61
+
62
+ singular : function( rule, replacement )
63
+ {
64
+ this.singulars.unshift( [ rule, replacement ] );
65
+ },
66
+
67
+ singularize : function( word )
68
+ {
69
+ if( _( this.uncountables ).include( word ) )
70
+ {
71
+ return word;
72
+ }
73
+
74
+ var result = word;
75
+
76
+ _( this.singulars ).detect( function( rule )
77
+ {
78
+ var gsub = this.gsub( word, rule[ 0 ], rule[ 1 ] );
79
+
80
+ return gsub ? ( result = gsub ) : false;
81
+ },
82
+ this );
83
+
84
+ return result;
85
+ },
86
+
87
+ irregular : function( singular, plural )
88
+ {
89
+ this.plural( singular, plural );
90
+ this.singular( plural, singular );
91
+ },
92
+
93
+ uncountable : function( word )
94
+ {
95
+ this.uncountables.unshift( word );
96
+ },
97
+
98
+ resetInflections : function( )
99
+ {
100
+ this.plurals = [ ];
101
+ this.singulars = [ ];
102
+ this.uncountables = [ ];
103
+
104
+ this.plural( /$/, 's' );
105
+ this.plural( /s$/, 's' );
106
+ this.plural( /(ax|test)is$/, '$1es' );
107
+ this.plural( /(octop|vir)us$/, '$1i' );
108
+ this.plural( /(octop|vir)i$/, '$1i' );
109
+ this.plural( /(alias|status)$/, '$1es' );
110
+ this.plural( /(bu)s$/, '$1ses' );
111
+ this.plural( /(buffal|tomat)o$/, '$1oes' );
112
+ this.plural( /([ti])um$/, '$1a' );
113
+ this.plural( /([ti])a$/, '$1a' );
114
+ this.plural( /sis$/, 'ses' );
115
+ this.plural( /(?:([^f])fe|([lr])f)$/, '$1$2ves' );
116
+ this.plural( /(hive)$/, '$1s' );
117
+ this.plural( /([^aeiouy]|qu)y$/, '$1ies' );
118
+ this.plural( /(x|ch|ss|sh)$/, '$1es' );
119
+ this.plural( /(matr|vert|ind)(?:ix|ex)$/, '$1ices' );
120
+ this.plural( /([m|l])ouse$/, '$1ice' );
121
+ this.plural( /([m|l])ice$/, '$1ice' );
122
+ this.plural( /^(ox)$/, '$1en' );
123
+ this.plural( /^(oxen)$/, '$1' );
124
+ this.plural( /(quiz)$/, '$1zes' );
125
+
126
+ this.singular( /s$/, '' );
127
+ this.singular( /(n)ews$/, '$1ews' );
128
+ this.singular( /([ti])a$/, '$1um' );
129
+ this.singular( /((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/, '$1$2sis' );
130
+ this.singular( /(^analy)ses$/, '$1sis' );
131
+ this.singular( /([^f])ves$/, '$1fe' );
132
+ this.singular( /(hive)s$/, '$1' );
133
+ this.singular( /(tive)s$/, '$1' );
134
+ this.singular( /([lr])ves$/, '$1f' );
135
+ this.singular( /([^aeiouy]|qu)ies$/, '$1y' );
136
+ this.singular( /(s)eries$/, '$1eries' );
137
+ this.singular( /(m)ovies$/, '$1ovie' );
138
+ this.singular( /(x|ch|ss|sh)es$/, '$1' );
139
+ this.singular( /([m|l])ice$/, '$1ouse' );
140
+ this.singular( /(bus)es$/, '$1' );
141
+ this.singular( /(o)es$/, '$1' );
142
+ this.singular( /(shoe)s$/, '$1' );
143
+ this.singular( /(cris|ax|test)es$/, '$1is' );
144
+ this.singular( /(octop|vir)i$/, '$1us' );
145
+ this.singular( /(alias|status)es$/, '$1' );
146
+ this.singular( /^(ox)en/, '$1' );
147
+ this.singular( /(vert|ind)ices$/, '$1ex' );
148
+ this.singular( /(matr)ices$/, '$1ix' );
149
+ this.singular( /(quiz)zes$/, '$1' );
150
+ this.singular( /(database)s$/, '$1' );
151
+
152
+ this.irregular( 'person', 'people' );
153
+ this.irregular( 'man', 'men' );
154
+ this.irregular( 'child', 'children' );
155
+ this.irregular( 'sex', 'sexes' );
156
+ this.irregular( 'move', 'moves' );
157
+ this.irregular( 'cow', 'kine' );
158
+
159
+ _( 'equipment information rice money species series fish sheep jeans'.split( /\s+/ ) ).each( function( word )
160
+ {
161
+ this.uncountable( word );
162
+ },
163
+ this );
164
+
165
+ return this;
166
+ }
167
+
168
+ };
169
+
170
+ /**
171
+ * Underscore integration
172
+ */
173
+ _.mixin( inflector.resetInflections( ) );
174
+
175
+ } )( _ );
@@ -0,0 +1,48 @@
1
+ class FuzzyJsonGenerator
2
+
3
+ @idCounter: 0
4
+
5
+ constructor: ->
6
+ # nop
7
+
8
+ nextId: ->
9
+ @constructor.idCounter++
10
+
11
+ # overload this method
12
+ generateOne: ->
13
+ id: @nextId()
14
+
15
+ generateMany: (count, base = 0) ->
16
+ count = @getRandom(count, base) if base > 0
17
+ @generateOne() for i in [0..count]
18
+
19
+ getRandom: (arrayOrCount, base = 0) ->
20
+ rand = Math.random()
21
+ if _.isArray arrayOrCount
22
+ arrayOrCount[Math.floor rand * arrayOrCount.length]
23
+ else if _.isNumber arrayOrCount
24
+ base + Math.floor rand * arrayOrCount
25
+ else
26
+ rand
27
+
28
+
29
+
30
+ @Generators ||= {}
31
+
32
+ class Generators.Offers extends FuzzyJsonGenerator
33
+
34
+ citiesFrom: ['Москва', 'Воронеж', 'Санкт-Петербург']
35
+ citiesTo: ['Хошимин', 'Брюссель', 'Лондон', 'Нью-Йорк', 'Париж', 'Мадрид', 'Берлин']
36
+
37
+ generateOne: ->
38
+ fromDate = new Date
39
+ fromDate.setTime(fromDate.getTime() + 1000 * 60 * 60 * 24 * @getRandom(30))
40
+ toDate = new Date
41
+ toDate.setTime(fromDate.getTime() + 1000 * 60 * 60 * 24 * @getRandom(30))
42
+ id: @nextId()
43
+ city_from : @getRandom(@citiesFrom)
44
+ city_to : @getRandom(@citiesTo)
45
+ date_from : Globalize.format(fromDate, "yyyy-MM-dd")
46
+ date_to : Globalize.format(toDate, "yyyy-MM-dd")
47
+ price : @getRandom(20000, 5000)
48
+ hot : @getRandom(2) is 1
@@ -0,0 +1,63 @@
1
+ @compact = (arr) ->
2
+ @deprecate 'compact(arr)', '_.compact arr'
3
+ r = []
4
+ for e in arr
5
+ r.push e if e?
6
+ r
7
+
8
+ @reverse = (arr) =>
9
+ @deprecate 'reverse(arr)', 'arr.reverse()'
10
+ _isString = _.isString arr
11
+ return arr unless _isString or $.isArray arr
12
+ if _isString then @warning 'reverse(someString)', 'STOP USE IT!' else arr.reverse()
13
+
14
+ ###
15
+ Split array into slices of <number> elements.
16
+ Map result by iterator if last given.
17
+
18
+ >>> eachSlice [1..10], 3, (a) -> cout a
19
+ [1, 2, 3]
20
+ [4, 5, 6]
21
+ [7, 8, 9]
22
+ [10]
23
+ ###
24
+ @eachSlice = (array, number, iterator = null) =>
25
+ size = array.length
26
+ index = 0
27
+ slices = []
28
+ while index < size
29
+ nextIndex = index + number
30
+ slices.push array.slice(index, nextIndex)
31
+ index = nextIndex
32
+ if _.isFunction iterator then _.map slices, iterator else slices
33
+
34
+ ###
35
+ Splits or iterates over the array in groups of size +number+,
36
+ padding any remaining slots with +fill_with+ unless it is +false+.
37
+
38
+ >>> inGroupsOf [1..7], 3, (group) -> cout group
39
+ [1, 2, 3]
40
+ [4, 5, 6]
41
+ [7, null, null]
42
+
43
+ >>> inGroupsOf [1..3], 2, '&nbsp;', (group) -> cout group
44
+ [1, 2]
45
+ [3, "&nbsp;"]
46
+
47
+ >>> inGroupsOf [1..3], 2, false, (group) -> cout group
48
+ [1, 2]
49
+ [3]
50
+ ###
51
+ @inGroupsOf = (array, number, fillWith = null) =>
52
+ return array if number < 1
53
+ iterator = @blockGiven arguments
54
+ unless fillWith is false
55
+ # size % number gives how many extra we have;
56
+ # subtracting from number gives how many to add;
57
+ # modulo number ensures we don't add group of just fill.
58
+ padding = (number - array.length % number) % number
59
+ if padding
60
+ fillWith = null if _.isFunction fillWith
61
+ array = array.slice()
62
+ array.push fillWith while padding-- > 0
63
+ @eachSlice array, number, iterator
@@ -0,0 +1,63 @@
1
+
2
+ @is_uri = (path) ->
3
+ /^[-a-z]+:\/\/|^cid:|^\/\//.test path
4
+
5
+ @without_extension = (source) ->
6
+ source.replace /^(.+)(\.\w+)$/, '$1'
7
+
8
+ @rewrite_extension = (source, ext) =>
9
+ "#{@without_extension source}.#{ext}"
10
+
11
+ @ASSET_ID = ''
12
+ @asset_ids_cache = {}
13
+ # Use the ASSET_ID inscope variable or the random hash as its cache-busting asset id.
14
+ @asset_id = (source) =>
15
+ if _.isString @ASSET_ID
16
+ @ASSET_ID
17
+ else
18
+ @asset_ids_cache[source] or (@asset_ids_cache[source] = 10000000 + Math.floor(Math.random() * 90000000))
19
+
20
+ # Break out the asset path rewrite in case plugins wish to put the asset id
21
+ # someplace other than the query string.
22
+ @rewrite_asset_path = (source, dir) =>
23
+ source = "/#{dir}/#{source}" unless source[0] is '/'
24
+ if id = @asset_id(source)
25
+ "#{source}?#{id}"
26
+ else
27
+ source
28
+
29
+ @rewrite_relative_url_root = (source, relative_url_root) ->
30
+ if relative_url_root and not _.startsWith(source, "#{relative_url_root}/")
31
+ "#{relative_url_root}#{source}"
32
+ else
33
+ source
34
+
35
+ @RELATIVE_URL_ROOT = ''
36
+
37
+ @compute_public_path = (source, dir, options = {}) =>
38
+ return source if is_uri(source)
39
+ source = @rewrite_extension(source, options['ext']) if options['ext']
40
+ source = @rewrite_asset_path(source, dir)
41
+ source = @rewrite_relative_url_root(source, @RELATIVE_URL_ROOT)
42
+ source
43
+
44
+ @image_path = (source) =>
45
+ @compute_public_path(source, 'images')
46
+
47
+ @path_to_image = @image_path # aliased to avoid conflicts with an image_path named route
48
+
49
+ @basename = (source) =>
50
+ source = matches[2] if matches = source.match /^(.*\/)?(.+)?$/
51
+
52
+ @image_alt = (src) =>
53
+ _.capitalize @without_extension(@basename(src))
54
+
55
+ @image_tag = (source, options = {}) =>
56
+ src = options['src'] = @path_to_image source
57
+ unless options['alt'] or /^cid:/.test src
58
+ options['alt'] = @image_alt(src)
59
+ if size = _delete(options, 'size')
60
+ if matches = size.match /^(\d+)x(\d+)$/
61
+ options['width'] = matches[1]
62
+ options['height'] = matches[2]
63
+ tag 'img', options
@@ -0,0 +1,14 @@
1
+ @g_decor_body = (tag, inner) =>
2
+ @content_tag(tag, '', class: 'left') +
3
+ @content_tag(tag, '', class: 'right') +
4
+ @content_tag(tag, inner, class: 'fill')
5
+
6
+ @g_star_decor_body = (tag, inner) =>
7
+ @content_tag(tag, inner, class: 'wrapper') +
8
+ @content_tag(tag, '', class: 'corner left top') +
9
+ @content_tag(tag, '', class: 'corner right top') +
10
+ @content_tag(tag, '', class: 'corner left bottom') +
11
+ @content_tag(tag, '', class: 'corner right bottom')
12
+
13
+ @g_wrapper_decor_body = (tag, inner) =>
14
+ @content_tag tag, inner, class: 'wrapper'
@@ -0,0 +1,70 @@
1
+ # The DOM class convention is to use the singular form of an object or class. Examples:
2
+ #
3
+ # dom_class(post) # => "post"
4
+ # dom_class(Person) # => "person"
5
+ #
6
+ # If you need to address multiple instances of the same class in the same view, you can prefix the dom_class:
7
+ #
8
+ # dom_class(post, :edit) # => "edit_post"
9
+ # dom_class(Person, :edit) # => "edit_person"
10
+ @dom_class = (record_or_class, prefix = "") ->
11
+ singular = _.singular(record_or_class)
12
+ if prefix then "#{prefix}_#{singular}" else singular
13
+
14
+ # The DOM id convention is to use the singular form of an object or class with the id following an underscore.
15
+ # If no id is found, prefix with "new_" instead. Examples:
16
+ #
17
+ # dom_id(Post.find(45)) # => "post_45"
18
+ # dom_id(Post.new) # => "new_post"
19
+ #
20
+ # If you need to address multiple instances of the same class in the same view, you can prefix the dom_id:
21
+ #
22
+ # dom_id(Post.find(45), :edit) # => "edit_post_45"
23
+ # TODO sync with rorId and ror_id
24
+ @dom_id = (record, prefix = "") =>
25
+ if record_id = @record_key_for_dom_id(record)
26
+ "#{@dom_class(record, prefix)}_#{record_id}"
27
+ else
28
+ @dom_class(record, prefix or "new")
29
+
30
+ @record_key_for_dom_id = (record) ->
31
+ record = record.to_model() if _.isFunction(record.to_model)
32
+ key = record.to_key()
33
+ if key then key.join("_") else key
34
+
35
+ # TODO more zen features: +, *x, {content}
36
+ # TODO cache
37
+ @selectorToHtml = (selector) =>
38
+ if matches = selector.match(/^[\s>]*([\w\.]+)(.*)$/)
39
+ selector = matches[1]
40
+ continuation = matches[2]
41
+ classes = selector.split(".")
42
+ tag_name = classes.shift() or "div"
43
+ html_options = {}
44
+ html_options["class"] = classes.join(" ") if classes.length
45
+ if continuation
46
+ @content_tag(tag_name, @selectorToHtml(continuation), html_options)
47
+ else
48
+ @tag(tag_name, html_options)
49
+ else
50
+ ""
51
+
52
+ @concat_class = =>
53
+ @warning "concat_class()", "refactoring with underscore"
54
+ @uniq(@compact(arguments).join(" ").split(/\s+/)).join(" ")
55
+
56
+ @html_options_to_s = (html_options) =>
57
+ if $.isPlainObject(html_options)
58
+ (" #{key}=\"#{value}\"" for key, value of html_options when typeof value isnt "undefined").join("")
59
+ else
60
+ ""
61
+
62
+ @tag = (tag_name, html_options = {}) =>
63
+ "<#{tag_name}#{@html_options_to_s html_options} />"
64
+
65
+ @content_tag = (tag_name, content, html_options) =>
66
+ "<#{tag_name}#{@html_options_to_s html_options}>#{content}</#{tag_name}>"
67
+
68
+ @link_to = (body, url, html_options = {}) =>
69
+ html_options["href"] = url
70
+ @content_tag("a", body, html_options)
@@ -0,0 +1,149 @@
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
+ @WARNINGS ?= true
11
+
12
+ @cout = =>
13
+ args = @args 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 'warn', "\"#{subject}\" DEPRECATED!" + if instead then " Use instead: \"#{instead}\"" else ''
29
+ return
30
+
31
+ @warning = (subject, instead = null) =>
32
+ if @WARNINGS
33
+ @cout 'warn', "\"#{subject}\" WARNING!" + if instead then " Use instead: \"#{instead}\"" else ''
34
+ return
35
+
36
+ @args = (a) ->
37
+ r = []
38
+ Array::push.apply r, a if a.length > 0
39
+ r
40
+
41
+ @blockGiven = (args) =>
42
+ l = args.length
43
+ if l
44
+ l = args[l - 1]
45
+ if _.isFunction l then l else false
46
+ else
47
+ false
48
+
49
+ @_delete = (object, key) ->
50
+ value = object[key]
51
+ delete object[key]
52
+ value
53
+
54
+ # Helper function to get a value from a object as a property or as a function.
55
+ @getValue = (object, prop) ->
56
+ return null unless object and object[prop]
57
+ return if _.isFunction(object[prop]) then object[prop]() else object[prop]
58
+
59
+ @isset = (obj) =>
60
+ @deprecate 'isset(obj)', 'obj isnt undefined" OR "obj?'
61
+ obj isnt undefined
62
+
63
+ @isString = (v) =>
64
+ @deprecate 'isString(v)', '_.isString v'
65
+ _.isString v
66
+
67
+ @isNumber = (v) =>
68
+ @deprecate 'isNumber(v)', '_.isNumber v'
69
+ not isNaN parseInt v
70
+
71
+ @isJQ = (obj) ->
72
+ @deprecate 'isJQ(obj)', 'obj instanceof jQuery'
73
+ _.isObject(obj) and _.isString obj.jquery
74
+
75
+ @uniq = (arrOrString) ->
76
+ @deprecate 'uniq(a)', '_.uniq a'
77
+ isStr = _.isString arrOrString
78
+ return arrOrString unless isStr or _.isArray arrOrString
79
+ r = []
80
+ r.push e for e in arrOrString when not _.include r, e
81
+ if isStr then r.join '' else r
82
+
83
+ @logicalXOR = (a, b) ->
84
+ ( a and not b ) or ( not a and b )
85
+
86
+ @bound = (number, min, max) ->
87
+ Math.max min, Math.min number, max
88
+
89
+ @roundWithPrecision = (number, precision = 2) ->
90
+ precision = Math.pow 10, precision
91
+ Math.round(number * precision) / precision
92
+
93
+ @regexpSpace = new RegExp '^\\s*$'
94
+ @regexpTrim = new RegExp '^\\s*(.*?)\\s*$'
95
+
96
+ @strTrim = (s) =>
97
+ @deprecate "strTrim(s)", "$.trim(s)"
98
+ s.match(@regexpTrim)[1]
99
+
100
+ # !!!!!!!!!!! tags !!!!!!!!!!!!
101
+
102
+ @number_to_currency = (number, units) ->
103
+ precision = 2
104
+ s = parseFloat(number).toFixed precision
105
+ b = s.length - 1 - precision
106
+ r = s.substring b
107
+ while b > 0
108
+ a = b - 3
109
+ r = ' ' + s.substring(a, b) + r
110
+ b = a
111
+ "#{r.substring(1)} #{units}"
112
+
113
+
114
+
115
+ @getParams = ->
116
+ q = location.search.substring(1).split '&'
117
+ r = {}
118
+ for e in q
119
+ t = e.split '='
120
+ r[t[0]] = t[1]
121
+ r
122
+
123
+ @respondFormat = (url, format = null) ->
124
+ aq = url.split '?'
125
+ ah = aq[0].split '#'
126
+ ad = ah[0].split '.'
127
+ currentFormat = if ad.length > 1 and not /\//.test(ad[ad.length - 1]) then ad.pop() else ''
128
+ return currentFormat unless format?
129
+ return url if format is currentFormat
130
+ ad.push format if format
131
+ ah[0] = ad.join '.'
132
+ aq[0] = ah.join '#'
133
+ aq.join '?'
134
+
135
+
136
+
137
+ @rails_data = {}
138
+
139
+ @rails_scope = (controller_name, action_name, scopedCloasure = null, scopedCloasureArguments...) =>
140
+ return false if _.isString(controller_name) and controller_name isnt @rails_data['controller_name']
141
+ return false if _.isString(action_name) and action_name isnt @rails_data['action_name']
142
+ if _.isFunction scopedCloasure
143
+ arguments[2] scopedCloasureArguments...
144
+ true
145
+
146
+
147
+
148
+ $ =>
149
+ @rails_data = $('body').data()
@@ -0,0 +1,34 @@
1
+
2
+ @unlazy_datepickers = (jRoot) ->
3
+ jRoot.find('input.datepicker.lazy').removeClass('lazy').length
4
+
5
+ @bind_datepickers = (jRoot) ->
6
+ jRoot.find('input.datepicker:not(.lazy, .hasDatepicker)').each( ->
7
+ jThis = $ @
8
+ opts =
9
+ 'showAnim' : ''
10
+ 'showOn' : 'both'
11
+ 'buttonImage' : '/images/forms/datepicker__icon.png' # TODO forwarding assets path
12
+ 'buttonImageOnly': true
13
+ 'changeMonth' : true
14
+ 'changeYear' : true
15
+ 'onClose' : (dateText, inst) -> $(inst.input).change().focusout()
16
+ opts[_.camelize(k)] = d for k, d of jThis.data()
17
+ jThis.datepicker opts
18
+ ).length
19
+
20
+ $.fn.orig_datepicker = $.fn.datepicker
21
+
22
+ $.fn.datepicker = ->
23
+ return @ unless @length
24
+ @data('changed', true) if arguments.length and arguments[0] is 'setDate'
25
+ $.fn.orig_datepicker.apply @, arguments
26
+
27
+
28
+
29
+ $ ->
30
+
31
+ $('body').on 'keyup keydown', 'input.datepicker.hasDatepicker', ->
32
+ $(@).datepicker 'hide'
33
+
34
+ bind_datepickers $('body')