ultimate-base 0.6.0 → 0.6.2
Sign up to get free protection for your applications and to get access to all the features.
- data/app/assets/javascripts/ultimate/backbone/app.js.coffee +31 -12
- data/app/assets/javascripts/ultimate/backbone/view.js.coffee +20 -3
- data/app/assets/javascripts/ultimate/{helpers.js.coffee → helpers.js.coffee.erb} +5 -5
- data/app/assets/javascripts/ultimate/jquery-plugin-class.js.coffee +1 -3
- data/app/assets/javascripts/ultimate/underscore/underscore.outcasts.js.coffee +48 -3
- data/lib/ultimate/base/version.rb +1 -1
- data/test/javascripts/tests/jquery-plugin-class_test.js.coffee +0 -3
- metadata +3 -5
- data/app/assets/javascripts/ultimate/backbone/views/typed-fields.js.coffee +0 -41
- data/app/assets/javascripts/ultimate/improves/typed-fields.js.coffee +0 -72
@@ -4,6 +4,8 @@ class Ultimate.Backbone.App
|
|
4
4
|
@App: null
|
5
5
|
|
6
6
|
name: null
|
7
|
+
warnOnMultibind: true
|
8
|
+
preventMultibind: false
|
7
9
|
|
8
10
|
Models: {}
|
9
11
|
Collections: {}
|
@@ -23,28 +25,48 @@ class Ultimate.Backbone.App
|
|
23
25
|
|
24
26
|
start: ->
|
25
27
|
@bindViews()
|
26
|
-
@bindCustomElements()
|
28
|
+
@bindCustomElements(null, true)
|
27
29
|
|
28
30
|
bindViews: (jRoot = $('html')) ->
|
29
31
|
bindedViews = []
|
30
32
|
for viewName, viewClass of @Views when viewClass::el
|
31
33
|
#cout 'info', "Try bind #{viewName} [#{viewClass::el}]"
|
32
34
|
jRoot.find(viewClass::el).each (index, el) =>
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
35
|
+
if @canBind(el, viewClass)
|
36
|
+
view = new viewClass(el: el)
|
37
|
+
cout 'info', "Binded view #{viewName}:", view
|
38
|
+
@viewInstances.push view
|
39
|
+
bindedViews.push view
|
37
40
|
bindedViews
|
38
41
|
|
42
|
+
canBind: (element, viewClass) ->
|
43
|
+
if @warnOnMultibind or @preventMultibind
|
44
|
+
views = @getViewsOnElement(element)
|
45
|
+
l = views.length
|
46
|
+
if l > 0
|
47
|
+
if @warnOnMultibind
|
48
|
+
cout 'warn', "Element already has binded #{l} view#{if l > 1 then 's' else ''}", element, viewClass, views
|
49
|
+
not @preventMultibind
|
50
|
+
else
|
51
|
+
true
|
52
|
+
else
|
53
|
+
true
|
54
|
+
|
55
|
+
getViewsOnElement: (element) ->
|
56
|
+
element = if element instanceof jQuery then element[0] else element
|
57
|
+
_.where @viewInstances, el: element
|
58
|
+
|
39
59
|
unbindViews: (views) ->
|
40
|
-
|
60
|
+
for view in views
|
61
|
+
view.undelegateEvents()
|
62
|
+
view.leave?()
|
41
63
|
@viewInstances = _.without(@viewInstances, views...)
|
42
64
|
|
43
65
|
getFirstView: (viewClass) ->
|
44
66
|
for view in @viewInstances
|
45
67
|
if view.constructor is viewClass
|
46
68
|
return view
|
47
|
-
|
69
|
+
null
|
48
70
|
|
49
71
|
getAllViews: (viewClass) ->
|
50
72
|
_.filter(@viewInstances, (view) -> view.constructor is viewClass)
|
@@ -56,12 +78,9 @@ class Ultimate.Backbone.App
|
|
56
78
|
registerCustomElementBinder: (binder) ->
|
57
79
|
@customElementBinders.push binder
|
58
80
|
|
59
|
-
bindCustomElements: (jRoot = $('body')) ->
|
81
|
+
bindCustomElements: (jRoot = $('body'), initial = false) ->
|
60
82
|
for binder in @customElementBinders
|
61
|
-
|
62
|
-
binder jRoot
|
63
|
-
else
|
64
|
-
jRoot.find(binder['selector'])[binder['method']] binder['arguments']...
|
83
|
+
binder arguments...
|
65
84
|
|
66
85
|
|
67
86
|
|
@@ -2,12 +2,29 @@
|
|
2
2
|
|
3
3
|
class Ultimate.Backbone.View extends Backbone.View
|
4
4
|
|
5
|
-
|
6
|
-
|
5
|
+
@mixinNames: null
|
6
|
+
|
7
|
+
# Rest mixinNames
|
8
|
+
@mixinable: ->
|
9
|
+
@mixinNames = _.clone(@mixinNames)
|
10
|
+
|
11
|
+
# Mixins support
|
12
|
+
@include: (mixin, name = null) ->
|
13
|
+
@mixinNames ||= []
|
14
|
+
@mixinNames.push(name) if name?
|
7
15
|
unless mixin?
|
8
|
-
throw new Error(
|
16
|
+
throw new Error("Mixin #{name} is undefined")
|
9
17
|
_.extend @::, mixin
|
10
18
|
|
19
|
+
mixinsEvents: (events = {}) ->
|
20
|
+
_.reduce( @constructor.mixinNames, ( (memo, name) -> _.extend(memo, _.result(@, _.string.camelize(name + 'Events'))) ), events, @ )
|
21
|
+
|
22
|
+
mixinsInitialize: ->
|
23
|
+
for name in @constructor.mixinNames
|
24
|
+
@[_.string.camelize(name + 'Initialize')]? arguments...
|
25
|
+
@
|
26
|
+
|
27
|
+
# TODO comment for this trick
|
11
28
|
__super: (methodName, args) ->
|
12
29
|
obj = @
|
13
30
|
calledMethod = @[methodName]
|
@@ -2,9 +2,9 @@
|
|
2
2
|
* global front-end js helpers
|
3
3
|
###
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
window.DEBUG_MODE ?= <%= Rails.env.development? %>
|
6
|
+
window.TEST_MODE ?= <%= Rails.env.test? %>
|
7
|
+
window.LOG_TODO ?= DEBUG_MODE
|
8
8
|
|
9
9
|
@cout = =>
|
10
10
|
args = _.toArray(arguments)
|
@@ -36,8 +36,8 @@
|
|
36
36
|
|
37
37
|
|
38
38
|
|
39
|
-
@getParams = ->
|
40
|
-
q =
|
39
|
+
@getParams = (searchString = location.search) ->
|
40
|
+
q = searchString.replace(/^\?/, '').split('&')
|
41
41
|
r = {}
|
42
42
|
for e in q
|
43
43
|
t = e.split('=')
|
@@ -99,7 +99,5 @@ class Ultimate.Plugin
|
|
99
99
|
_.extend @options, options
|
100
100
|
@_reflectOptions()
|
101
101
|
|
102
|
-
_reflectOptions: (
|
103
|
-
if _.isArray(reflectableOptions)
|
104
|
-
@[attr] = options[attr] for attr in reflectableOptions when not _.isUndefined(options[attr])
|
102
|
+
_reflectOptions: (options = @options) ->
|
105
103
|
@[attr] = value for attr, value of options when not _.isUndefined(@[attr])
|
@@ -1,10 +1,10 @@
|
|
1
1
|
###
|
2
2
|
Underscore.outcasts
|
3
|
-
(c) 2012 Dmitry Karpunin <koderfunk aet gmail dot com>
|
3
|
+
(c) 2012-2013 Dmitry Karpunin <koderfunk aet gmail dot com>
|
4
4
|
Underscore.outcasts is freely distributable under the terms of the MIT license.
|
5
5
|
Documentation: https://github.com/KODerFunk/underscore.outcasts
|
6
6
|
Some code is borrowed from outcasts pull requests to Underscore.
|
7
|
-
Version '0.1.
|
7
|
+
Version '0.1.5'
|
8
8
|
###
|
9
9
|
|
10
10
|
'use strict'
|
@@ -15,7 +15,7 @@
|
|
15
15
|
|
16
16
|
UnderscoreOutcasts =
|
17
17
|
|
18
|
-
VERSION: '0.1.
|
18
|
+
VERSION: '0.1.5'
|
19
19
|
|
20
20
|
delete: (object, key) ->
|
21
21
|
value = object[key]
|
@@ -133,6 +133,51 @@ UnderscoreOutcasts =
|
|
133
133
|
array.push(fillWith) while padding-- > 0
|
134
134
|
@eachSlice array, number, @blockGiven(arguments)
|
135
135
|
|
136
|
+
###
|
137
|
+
Splits or iterates over the array in +number+ of groups, padding any
|
138
|
+
remaining slots with +fill_with+ unless it is +false+.
|
139
|
+
|
140
|
+
%w(1 2 3 4 5 6 7 8 9 10).in_groups(3) {|group| p group}
|
141
|
+
["1", "2", "3", "4"]
|
142
|
+
["5", "6", "7", nil]
|
143
|
+
["8", "9", "10", nil]
|
144
|
+
|
145
|
+
%w(1 2 3 4 5 6 7 8 9 10).in_groups(3, ' ') {|group| p group}
|
146
|
+
["1", "2", "3", "4"]
|
147
|
+
["5", "6", "7", " "]
|
148
|
+
["8", "9", "10", " "]
|
149
|
+
|
150
|
+
%w(1 2 3 4 5 6 7).in_groups(3, false) {|group| p group}
|
151
|
+
["1", "2", "3"]
|
152
|
+
["4", "5"]
|
153
|
+
["6", "7"]
|
154
|
+
###
|
155
|
+
# TODO tests
|
156
|
+
inGroups: (array, number, fillWith = null) ->
|
157
|
+
# size / number gives minor group size;
|
158
|
+
# size % number gives how many objects need extra accommodation;
|
159
|
+
# each group hold either division or division + 1 items.
|
160
|
+
division = Math.floor(array.length / number)
|
161
|
+
modulo = array.length % number
|
162
|
+
|
163
|
+
# create a new array avoiding dup
|
164
|
+
groups = []
|
165
|
+
start = 0
|
166
|
+
|
167
|
+
for index in [0...number]
|
168
|
+
length = division + (if modulo > 0 and modulo > index then 1 else 0)
|
169
|
+
groups.push last_group = array.slice(start, start + length)
|
170
|
+
if fillWith isnt false and modulo > 0 and length is division
|
171
|
+
last_group.push fillWith
|
172
|
+
start += length
|
173
|
+
|
174
|
+
if block = @blockGiven(arguments)
|
175
|
+
_.map groups, block
|
176
|
+
else
|
177
|
+
groups
|
178
|
+
|
179
|
+
|
180
|
+
|
136
181
|
exports: ->
|
137
182
|
result = {}
|
138
183
|
for prop of @
|
@@ -21,7 +21,6 @@ test "EmptyPlugin", ->
|
|
21
21
|
|
22
22
|
class TestPlugin extends Ultimate.Plugin
|
23
23
|
someOption: null
|
24
|
-
reflectableOptions: -> ['thirdOption']
|
25
24
|
@defaultLocales =
|
26
25
|
en:
|
27
26
|
someMessage: 'English message.'
|
@@ -36,12 +35,10 @@ test "TestPlugin", ->
|
|
36
35
|
el: '.test-plugin'
|
37
36
|
someOption: 'bingo!'
|
38
37
|
otherOption: 'ringo!'
|
39
|
-
thirdOption: 'dingo!'
|
40
38
|
locale: 'de'
|
41
39
|
|
42
40
|
equal plugin.someOption, 'bingo!'
|
43
41
|
ok typeof plugin.otherOption is 'undefined'
|
44
|
-
equal plugin.thirdOption, 'dingo!'
|
45
42
|
equal plugin.locale, 'de'
|
46
43
|
deepEqual plugin.translations, {}
|
47
44
|
# equal plugin.t('someMessage'), 'Some message'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ultimate-base
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.6.
|
4
|
+
version: 0.6.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-09-18 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
@@ -81,16 +81,14 @@ files:
|
|
81
81
|
- app/assets/javascripts/ultimate/backbone/view-mixins/nodes.js.coffee
|
82
82
|
- app/assets/javascripts/ultimate/backbone/view.js.coffee
|
83
83
|
- app/assets/javascripts/ultimate/backbone/views/slider.js.coffee
|
84
|
-
- app/assets/javascripts/ultimate/backbone/views/typed-fields.js.coffee
|
85
84
|
- app/assets/javascripts/ultimate/base.js.coffee
|
86
85
|
- app/assets/javascripts/ultimate/experimental/_inflections/inflections.js.coffee
|
87
86
|
- app/assets/javascripts/ultimate/experimental/_inflections/plur.js
|
88
87
|
- app/assets/javascripts/ultimate/experimental/fuzzy-json-generator.js.coffee
|
89
|
-
- app/assets/javascripts/ultimate/helpers.js.coffee
|
88
|
+
- app/assets/javascripts/ultimate/helpers.js.coffee.erb
|
90
89
|
- app/assets/javascripts/ultimate/improves/form.js.coffee
|
91
90
|
- app/assets/javascripts/ultimate/improves/i18n-lite.js.coffee
|
92
91
|
- app/assets/javascripts/ultimate/improves/magic-radios.js.coffee
|
93
|
-
- app/assets/javascripts/ultimate/improves/typed-fields.js.coffee
|
94
92
|
- app/assets/javascripts/ultimate/jquery-plugin-adapter.js.coffee
|
95
93
|
- app/assets/javascripts/ultimate/jquery-plugin-class.js.coffee
|
96
94
|
- app/assets/javascripts/ultimate/jquery.base.js.coffee
|
@@ -1,41 +0,0 @@
|
|
1
|
-
#= require ../view
|
2
|
-
#= require ultimate/improves/typed-fields
|
3
|
-
|
4
|
-
Ultimate.Backbone.Observers ||= {}
|
5
|
-
|
6
|
-
class Ultimate.Backbone.Observers.TypedFields extends Ultimate.Backbone.View
|
7
|
-
|
8
|
-
selector: "input:text[data-data-type], input:text[data-regexp-mask]"
|
9
|
-
|
10
|
-
events: ->
|
11
|
-
"keypress selector": "onKeyPress"
|
12
|
-
"change selector": "onChange"
|
13
|
-
"paste selector": "onPasteOrDrop"
|
14
|
-
"drop selector": "onPasteOrDrop"
|
15
|
-
|
16
|
-
viewOptions: ["selector"]
|
17
|
-
|
18
|
-
onKeyPress: (event) ->
|
19
|
-
if event.metaKey
|
20
|
-
@onPasteOrDrop event
|
21
|
-
return true
|
22
|
-
return true unless event.charCode
|
23
|
-
jField = $(event.currentTarget)
|
24
|
-
oldValue = jField.val()
|
25
|
-
newValue = oldValue.substring(0, @selectionStart) + String.fromCharCode(event.charCode) + oldValue.substring(@selectionEnd)
|
26
|
-
return false unless jField.getRegExpMask().test(newValue)
|
27
|
-
jField.data "value", newValue
|
28
|
-
|
29
|
-
onChange: (event) ->
|
30
|
-
jField = $(event.currentTarget)
|
31
|
-
if jField.getRegExpMask().test(jField.val())
|
32
|
-
jField.data "value", jField.val()
|
33
|
-
else
|
34
|
-
jField.val jField.data("value")
|
35
|
-
|
36
|
-
onPasteOrDrop: (event) ->
|
37
|
-
setTimeout ( -> $(event.currentTarget).trigger "change", arguments ), 100
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
Ultimate.createJQueryPlugin? "typedFields", Ultimate.Backbone.Observers.TypedFields
|
@@ -1,72 +0,0 @@
|
|
1
|
-
do ($ = jQuery) ->
|
2
|
-
|
3
|
-
# ========= max & min =========
|
4
|
-
$('input:text[data-gte], input:text[data-lte]').live 'change focusout blur', ->
|
5
|
-
jField = $(@)
|
6
|
-
realValue = jField.val()
|
7
|
-
if realValue isnt ''
|
8
|
-
# TODO refactor this
|
9
|
-
min = parseFloat(jField.data('gte'))
|
10
|
-
max = parseFloat(jField.data('lte'))
|
11
|
-
oldValue = parseFloat(realValue)
|
12
|
-
v = oldValue
|
13
|
-
v = 0 if isNaN(v)
|
14
|
-
v = min if not isNaN(min) and v < min
|
15
|
-
v = max if not isNaN(max) and v > max
|
16
|
-
jField.val(v).change() unless v is oldValue
|
17
|
-
|
18
|
-
$.fn.setFieldBounds = (min, max) ->
|
19
|
-
@filter('input:text')
|
20
|
-
.attr
|
21
|
-
'data-gte': min
|
22
|
-
'data-lte': max
|
23
|
-
.data
|
24
|
-
'gte': min
|
25
|
-
'lte': max
|
26
|
-
|
27
|
-
# ========= regexpMask =========
|
28
|
-
|
29
|
-
$.regexp = {} unless $.regexp
|
30
|
-
$.regexp.typedField =
|
31
|
-
'integer' : /^$|^\d+$/
|
32
|
-
'float' : /^$|^\d+(\.\d*)?$/
|
33
|
-
'currency' : /^$|^\d+(\.\d{0,2})?$/
|
34
|
-
'text' : /^.*$/
|
35
|
-
|
36
|
-
$.fn.getRegExpMask = ->
|
37
|
-
mask = @data('regexpMask')
|
38
|
-
if _.isString(mask)
|
39
|
-
try
|
40
|
-
mask = new RegExp(mask)
|
41
|
-
@data 'regexpMask', mask
|
42
|
-
catch e
|
43
|
-
# nop
|
44
|
-
else
|
45
|
-
dataType = @data('dataType')
|
46
|
-
mask = $.regexp.typedField[dataType] if dataType
|
47
|
-
unless mask
|
48
|
-
@val 'unknown dataType'
|
49
|
-
mask = $.regexp.typedField['text']
|
50
|
-
mask
|
51
|
-
|
52
|
-
$.fn.dropRegExpMask = ->
|
53
|
-
@
|
54
|
-
.removeAttr('data-regexp-mask')
|
55
|
-
.removeData('regexpMask')
|
56
|
-
.removeData('value')
|
57
|
-
|
58
|
-
$.fn.setRegExpMask = (mask) ->
|
59
|
-
stringMask = 'true'
|
60
|
-
if _.isString(mask)
|
61
|
-
stringMask = mask
|
62
|
-
try
|
63
|
-
mask = new RegExp(mask)
|
64
|
-
catch e
|
65
|
-
# nop
|
66
|
-
if _.isRegExp(mask)
|
67
|
-
@
|
68
|
-
.dropRegExpMask()
|
69
|
-
.attr('data-regexp-mask', stringMask)
|
70
|
-
.data('regexpMask', mask)
|
71
|
-
.change()
|
72
|
-
@
|