ultimate-base 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +5 -0
- data/.rvmrc +2 -0
- data/.rvmrc.example +2 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +14 -0
- data/LICENSE +5 -0
- data/README.md +1 -0
- data/Rakefile +1 -0
- data/app/assets/javascripts/backbone/backbone.js +1452 -0
- data/app/assets/javascripts/backbone/ultimate/app.js.coffee +25 -0
- data/app/assets/javascripts/backbone/ultimate/collection.js.coffee +12 -0
- data/app/assets/javascripts/backbone/ultimate/model.js.coffee +12 -0
- data/app/assets/javascripts/backbone/ultimate/router.js.coffee +13 -0
- data/app/assets/javascripts/backbone/ultimate/view.js.coffee +96 -0
- data/app/assets/javascripts/ultimate/base.js.coffee +103 -0
- data/app/assets/javascripts/ultimate/bus.js.coffee +57 -0
- data/app/assets/javascripts/ultimate/devise.js.coffee +18 -0
- data/app/assets/javascripts/ultimate/experimental/_inflections/dzone.inflections.js +154 -0
- data/app/assets/javascripts/ultimate/experimental/_inflections/inflections.js.coffee +2 -0
- data/app/assets/javascripts/ultimate/experimental/_inflections/plur.js +29 -0
- data/app/assets/javascripts/ultimate/experimental/_inflections/underscore.inflection.js +175 -0
- data/app/assets/javascripts/ultimate/experimental/fuzzy-json-generator.js.coffee +48 -0
- data/app/assets/javascripts/ultimate/helpers/array.js.coffee +63 -0
- data/app/assets/javascripts/ultimate/helpers/asset_tag.js.coffee +63 -0
- data/app/assets/javascripts/ultimate/helpers/decor.js.coffee +14 -0
- data/app/assets/javascripts/ultimate/helpers/forms.js.coffee +0 -0
- data/app/assets/javascripts/ultimate/helpers/tags.js.coffee +70 -0
- data/app/assets/javascripts/ultimate/helpers.js.coffee +149 -0
- data/app/assets/javascripts/ultimate/improves/datepicker.js.coffee +34 -0
- data/app/assets/javascripts/ultimate/improves/form-errors.js.coffee +146 -0
- data/app/assets/javascripts/ultimate/improves/form.js.coffee +155 -0
- data/app/assets/javascripts/ultimate/improves/magic-radios.js.coffee +41 -0
- data/app/assets/javascripts/ultimate/improves/tablesorter.js +59 -0
- data/app/assets/javascripts/ultimate/improves/typed-field.js.coffee +98 -0
- data/app/assets/javascripts/ultimate/underscore/underscore.js +1059 -0
- data/app/assets/javascripts/ultimate/underscore/underscore.string.js +480 -0
- data/app/assets/javascripts/ultimate/widgets/dock.js.coffee +70 -0
- data/app/assets/javascripts/ultimate/widgets/gear.js.coffee +84 -0
- data/app/assets/javascripts/ultimate/widgets/jquery-ext.js.coffee +104 -0
- data/app/assets/javascripts/ultimate/widgets/jquery.adapter.js.coffee +62 -0
- data/app/assets/javascripts/ultimate/widgets/widget.js.coffee +115 -0
- data/app/assets/stylesheets/polyfills/PIE.htc +96 -0
- data/app/assets/stylesheets/polyfills/boxsizing.htc +300 -0
- data/app/assets/stylesheets/ultimate/mixins/_routines.css.scss +95 -0
- data/app/assets/stylesheets/ultimate/mixins/_vendors.css.scss +34 -0
- data/app/assets/stylesheets/ultimate/mixins/css3/_text-shadow.scss +37 -0
- data/app/assets/stylesheets/ultimate/mixins/css3.css.scss +328 -0
- data/app/assets/stylesheets/ultimate/mixins/decor.css.scss +86 -0
- data/app/assets/stylesheets/ultimate/mixins/fonts.css.scss +100 -0
- data/app/assets/stylesheets/ultimate/mixins/microstructures.css.scss +188 -0
- data/app/assets/stylesheets/ultimate/structures/slider.css.scss +53 -0
- data/lib/ultimate-base/engine.rb +6 -0
- data/lib/ultimate-base/extensions/directive_processor.rb +64 -0
- data/lib/ultimate-base/extensions/sass_script_functions.rb +39 -0
- data/lib/ultimate-base/version.rb +5 -0
- data/lib/ultimate-base.rb +10 -0
- data/ultimate-base.gemspec +25 -0
- metadata +102 -0
@@ -0,0 +1,146 @@
|
|
1
|
+
# TODO this is part of custom forms
|
2
|
+
# TODO registrable
|
3
|
+
# TODO may be, replace "clear immune" technique with something more effective, ex. additional class
|
4
|
+
|
5
|
+
( ( $ ) ->
|
6
|
+
|
7
|
+
$.errorableFields = {}
|
8
|
+
$.errorableFieldsSelector = ''
|
9
|
+
|
10
|
+
$.registerErrorableField = (selector, events, errorCleaner) ->
|
11
|
+
$.errorableFields[selector.split(/\s+/)[0]] = arguments
|
12
|
+
$.errorableFieldsSelector = _.keys($.errorableFields).join(', ')
|
13
|
+
true
|
14
|
+
|
15
|
+
$.fieldWithErrorsWrapperClass = 'field_with_errors'
|
16
|
+
$.fieldWithClearImmuneWrapperClass = 'immune'
|
17
|
+
$.labelForFieldWithErrorClass = 'with-error'
|
18
|
+
|
19
|
+
# [ selector: String = '.g-select, .g-text-field, .g-text-area' ]
|
20
|
+
# [ [, ]errors: Array = [] ]
|
21
|
+
# [ [, ]clearImmune: Boolean = false ]
|
22
|
+
$.fn.setFormErrors = ->
|
23
|
+
# dafault parameters
|
24
|
+
selector = $.errorableFieldsSelector # '.g-select, .g-text-field, .g-text-area'
|
25
|
+
errors = []
|
26
|
+
clearImmune = false
|
27
|
+
# parsing arguments
|
28
|
+
# TODO liquid arguments parser ( by arguments info, ex: {selector: String, errors: Array, clearImmune: Boolean} )
|
29
|
+
a = args arguments
|
30
|
+
if a.length
|
31
|
+
first = a.shift()
|
32
|
+
if _.isString first
|
33
|
+
selector = first
|
34
|
+
if a.length
|
35
|
+
first = a.shift()
|
36
|
+
if _.isString first
|
37
|
+
first = [first]
|
38
|
+
if _.isArray first
|
39
|
+
errors = _.uniq first
|
40
|
+
if a.length
|
41
|
+
first = a.shift()
|
42
|
+
if _.isBoolean first
|
43
|
+
clearImmune = first
|
44
|
+
# ui process
|
45
|
+
@clearFormErrors selector, clearImmune
|
46
|
+
wrapperSelector = ".#{$.fieldWithErrorsWrapperClass}"
|
47
|
+
if clearImmune
|
48
|
+
wrapperSelector += ".#{$.fieldWithClearImmuneWrapperClass}"
|
49
|
+
jErrorWrappers = @find(selector).wrap(selectorToHtml wrapperSelector).parent()
|
50
|
+
jErrorWrappers.append (for err in errors then content_tag('div', err, class: 'error')).join("\n")
|
51
|
+
jErrorWrappers.closestLabel().addClass($.labelForFieldWithErrorClass)
|
52
|
+
|
53
|
+
$.fn.setErrors = ->
|
54
|
+
deprecate('jQ.setErrors(...)', 'jQ.setFormErrors(...)')
|
55
|
+
@setFormErrors.apply(@, arguments)
|
56
|
+
|
57
|
+
# [selector]
|
58
|
+
# [clearImmune]
|
59
|
+
$.fn.clearFormErrors = ->
|
60
|
+
selector = $.errorableFieldsSelector # '.g-select, .g-text-field, .g-text-area'
|
61
|
+
clearImmune = false
|
62
|
+
# parsing arguments
|
63
|
+
# TODO liquid arguments parser ( by arguments info, ex: {selector: String, clearImmune: Boolean} )
|
64
|
+
a = args arguments
|
65
|
+
if a.length
|
66
|
+
first = a.shift()
|
67
|
+
if _.isString first
|
68
|
+
selector = first
|
69
|
+
if a.length
|
70
|
+
first = a.shift()
|
71
|
+
if _.isBoolean(first)
|
72
|
+
clearImmune = first
|
73
|
+
wrapperSelector = ".#{$.fieldWithErrorsWrapperClass}"
|
74
|
+
if clearImmune
|
75
|
+
wrapperSelector += ".#{$.fieldWithClearImmuneWrapperClass}"
|
76
|
+
else
|
77
|
+
wrapperSelector += ":not(.#{$.fieldWithClearImmuneWrapperClass})"
|
78
|
+
fullSelector = "#{wrapperSelector}:has(#{selector})"
|
79
|
+
jErrorWrappers = @find fullSelector
|
80
|
+
jErrorWrappers = @closest fullSelector unless jErrorWrappers.length
|
81
|
+
if jErrorWrappers.length
|
82
|
+
jErrorWrappers.closestLabel().removeClass($.labelForFieldWithErrorClass)
|
83
|
+
jErrorWrappers.children('.error').remove()
|
84
|
+
jErrorWrappers.children(selector).unwrap()
|
85
|
+
@
|
86
|
+
|
87
|
+
$.fn.clearFromErrors = ->
|
88
|
+
deprecate('jQ.clearFromErrors(...)', 'jQ.clearFormErrors(...)')
|
89
|
+
@clearFormErrors.apply(@, arguments)
|
90
|
+
|
91
|
+
$.ujsAjaxError = (event, jqXHR) ->
|
92
|
+
jForm = $(@).clearFormErrors()
|
93
|
+
try
|
94
|
+
responseJSON = $.parseJSON jqXHR.responseText
|
95
|
+
errors = responseJSON['errors'] or responseJSON
|
96
|
+
if errors
|
97
|
+
jFields = jForm.find '[name*="["]:input:visible' # TODO research without :visible, because has custom elements
|
98
|
+
if jFields.length
|
99
|
+
for fieldErrors, fieldName of errors
|
100
|
+
jField = jFields.filter "[name$=\"[#{fieldName}]\"]"
|
101
|
+
if jField.length
|
102
|
+
jField.closestEdge().setErrors fieldErrors
|
103
|
+
catch e
|
104
|
+
# nop
|
105
|
+
true
|
106
|
+
|
107
|
+
|
108
|
+
$.fn.customErrorsHandler = (suspend = true, eventName = 'ajax:error', selector = 'form[data-remote="true"]') ->
|
109
|
+
if @length
|
110
|
+
if @is 'form'
|
111
|
+
jForms = @filter selector
|
112
|
+
jForms.off eventName, $.ujsAjaxError
|
113
|
+
jForms.on eventName, $.ujsAjaxError if suspend
|
114
|
+
else
|
115
|
+
@off eventName, selector, $.ujsAjaxError
|
116
|
+
@on eventName, selector, $.ujsAjaxError if suspend
|
117
|
+
@
|
118
|
+
|
119
|
+
|
120
|
+
|
121
|
+
|
122
|
+
$.fn.errorCleaners = (suspend = true) ->
|
123
|
+
if @length
|
124
|
+
jDocks = if @is ':input' then @closestEdge() else @
|
125
|
+
for fieldWrapperSelector, [selector, events, errorCleaner] of $.errorableFields
|
126
|
+
fullSelector = ".#{$.fieldWithErrorsWrapperClass} > #{selector}"
|
127
|
+
jDocks.off events, fullSelector
|
128
|
+
jDocks.on events, fullSelector, errorCleaner if suspend
|
129
|
+
@
|
130
|
+
|
131
|
+
|
132
|
+
|
133
|
+
$.registerErrorableField '.g-text-field input:visible', 'change keyup', ->
|
134
|
+
# text-fields error cleaner
|
135
|
+
jTextField = $ @
|
136
|
+
unless jTextField.val() is '' # TODO may be use isEmptyString()
|
137
|
+
jTextField.clearFormErrors('.g-text-field').clearFormErrors('.g-text-field', true)
|
138
|
+
jTextField.change().focus() # unwraping break change, and there changing continue
|
139
|
+
|
140
|
+
$.registerErrorableField '.g-select select', 'change', ->
|
141
|
+
# selects error cleaner
|
142
|
+
jSelect = $ @
|
143
|
+
unless jSelect.val() is '' # TODO may be use isEmptyString()
|
144
|
+
jSelect.clearFormErrors('.g-select').clearFormErrors('.g-select', true)
|
145
|
+
|
146
|
+
)( jQuery )
|
@@ -0,0 +1,155 @@
|
|
1
|
+
( ( $ ) ->
|
2
|
+
|
3
|
+
# TODO try optimize, excepting Edge and search in siblings for next cycle
|
4
|
+
$.fn.nearestFind = (selector, extremeEdgeSelector = 'form, body') ->
|
5
|
+
jEdge = @
|
6
|
+
jResult = jEdge.find selector
|
7
|
+
until jResult.length or jEdge.is extremeEdgeSelector
|
8
|
+
jEdge = jEdge.parent()
|
9
|
+
jResult = jEdge.find selector
|
10
|
+
jResult
|
11
|
+
|
12
|
+
|
13
|
+
|
14
|
+
$.fn.closestEdge = (edgeSelector = '.input-line, .field, .field-line, tr, li, fieldset, .g-box, form') ->
|
15
|
+
# TODO remove and extract edgeSelector, else undeprecate
|
16
|
+
deprecate 'closestEdge', '$().closest(\'your selector\')'
|
17
|
+
@closest edgeSelector
|
18
|
+
|
19
|
+
|
20
|
+
|
21
|
+
# @param strongById: Boolean = false
|
22
|
+
$.fn.closestLabel = ( strongById = false, passCache = false ) ->
|
23
|
+
(if @is(':input') then @ else @find(':input')).filter(':not(input[type="hidden"])').map ->
|
24
|
+
jInput = $ @
|
25
|
+
jLabel = jInput.data 'closestLabel' unless passCache
|
26
|
+
unless jLabel
|
27
|
+
if jLabel is false
|
28
|
+
return null
|
29
|
+
else
|
30
|
+
jLabel = {length: 0}
|
31
|
+
jEdge = jInput.closestEdge() # TODO may be need params
|
32
|
+
inputId = jInput.attr 'id'
|
33
|
+
if inputId
|
34
|
+
# try search label by id linkage
|
35
|
+
labelSelectorByFor = "label[for=\"#{inputId}\"]"
|
36
|
+
# at first search in the edge area
|
37
|
+
jLabel = jEdge.find labelSelectorByFor
|
38
|
+
unless jLabel.length
|
39
|
+
# try search in the closest form
|
40
|
+
jLabel = jInput.closest('form').find labelSelectorByFor
|
41
|
+
# trust only unique label on the form
|
42
|
+
jLabel = {length: 0} if jLabel.length > 1
|
43
|
+
# try get first labet in the edge area
|
44
|
+
jLabel = jEdge.find('label:first') unless jLabel.length
|
45
|
+
# taken!
|
46
|
+
if jLabel.length
|
47
|
+
# oh, this label already linked
|
48
|
+
if jLabel.data 'closestInput'
|
49
|
+
jLabel = {length: 0}
|
50
|
+
else
|
51
|
+
jLabel.data 'closestInput', jInput
|
52
|
+
jInput.data 'closestLabel', jLabel
|
53
|
+
if jLabel.length
|
54
|
+
if strongById and jLabel.attr('for') isnt jInput.attr('id')
|
55
|
+
null
|
56
|
+
else
|
57
|
+
jLabel[0]
|
58
|
+
else
|
59
|
+
null
|
60
|
+
|
61
|
+
|
62
|
+
|
63
|
+
$.linkedLabelsClick = ->
|
64
|
+
jLabel = $ @
|
65
|
+
jInput = jLabel.data 'closestInput'
|
66
|
+
|
67
|
+
unless jInput
|
68
|
+
attrFor = jLabel.attr 'for'
|
69
|
+
jInput = jLabel.nearestFind ":input##{attrFor}"
|
70
|
+
jInput = jLabel.nearestFind ':input' unless jInput.length is 1
|
71
|
+
jLabel.data 'closestInput', jInput if jInput.length
|
72
|
+
|
73
|
+
if jInput and jInput.length is 1
|
74
|
+
if jInput.is 'input:checkbox, input:radio'
|
75
|
+
jInput.click()
|
76
|
+
else if jInput.is 'select'
|
77
|
+
# TODO try: jInput.click() в любом случае свести к универсальносит
|
78
|
+
jInput.closest('.g-select').click()
|
79
|
+
else
|
80
|
+
jInput.focus()
|
81
|
+
false
|
82
|
+
|
83
|
+
# Cacheble bulletproof labels
|
84
|
+
# example: $('body').linkedLabels();
|
85
|
+
$.fn.linkedLabels = (suspend = true, eventName = 'click.linked-labels') ->
|
86
|
+
if @is 'label'
|
87
|
+
jLabels = @filter 'label'
|
88
|
+
jLabels.off eventName
|
89
|
+
jLabels.on eventName, $.linkedLabelsClick if suspend
|
90
|
+
else
|
91
|
+
@off eventName, 'label'
|
92
|
+
@on eventName, 'label', $.linkedLabelsClick if suspend
|
93
|
+
@
|
94
|
+
|
95
|
+
|
96
|
+
|
97
|
+
# [ additionAttr: String = 'data-nested-addition' ]
|
98
|
+
$.fn.setNestedAdditions = (additionAttr = 'data-nested-addition') ->
|
99
|
+
@find(":input[#{additionAttr}]").each ->
|
100
|
+
jInput = $ @
|
101
|
+
inputId = jInput.attr 'id'
|
102
|
+
if inputId
|
103
|
+
newId = "#{inputId}_#{jInput.attr additionAttr}"
|
104
|
+
jInput.attr 'id', newId
|
105
|
+
jLabel = jInput.closestLabel(true)
|
106
|
+
jLabel.attr 'for', newId if jLabel.length
|
107
|
+
jInput.removeAttr additionAttr
|
108
|
+
@
|
109
|
+
|
110
|
+
|
111
|
+
|
112
|
+
# setNestedIndex(params = {nestedField: index || [index, old_index]})
|
113
|
+
# setNestedIndex(nestedField, index, [old_index])
|
114
|
+
$.fn.setNestedIndex = ->
|
115
|
+
params = {}
|
116
|
+
if arguments.length is 1
|
117
|
+
params = arguments[0]
|
118
|
+
else
|
119
|
+
params[arguments[0]] = (if arguments.length > 2 then [arguments[1], arguments[2]] else arguments[1])
|
120
|
+
replacers =
|
121
|
+
name: []
|
122
|
+
id: []
|
123
|
+
for nestedField, index of params
|
124
|
+
if $.isArray index
|
125
|
+
[index, oldIndex] = index
|
126
|
+
else
|
127
|
+
oldIndex = '\\d*'
|
128
|
+
replacers['id'].push [ (new RegExp "_#{nestedField}_#{oldIndex}"), "_#{nestedField}_#{index}" ]
|
129
|
+
replacers['name'].push [ (new RegExp "\\[#{nestedField}\\]\\[#{oldIndex}\\]"), "[#{nestedField}][#{index}]" ]
|
130
|
+
( if @is(':input') then @filter('[name]') else @find(':input[name]') ).map ->
|
131
|
+
jInput = $ @
|
132
|
+
for replacerAttr, replacerPairs of replacers
|
133
|
+
# if extract attribute
|
134
|
+
if attr = jInput.attr replacerAttr
|
135
|
+
# dup attr
|
136
|
+
newAttr = attr
|
137
|
+
for pair in replacerPairs
|
138
|
+
newAttr = newAttr.replace pair[0], pair[1]
|
139
|
+
if newAttr isnt attr
|
140
|
+
jInput.closestLabel(true).attr('for', newAttr) if replacerAttr is 'id'
|
141
|
+
jInput.attr replacerAttr, newAttr
|
142
|
+
@
|
143
|
+
|
144
|
+
|
145
|
+
|
146
|
+
$.fillTabIndexesCounter = 0
|
147
|
+
|
148
|
+
# TODO this may be .is 'input'
|
149
|
+
$.fn.fillTabIndexes = (onlyVisible = false) ->
|
150
|
+
if @length
|
151
|
+
@find("input:not([readonly])#{if onlyVisible then ':visible' else ''}").each ->
|
152
|
+
$(@).attr 'tabindex', ++$.fillTabIndexesCounter
|
153
|
+
@
|
154
|
+
|
155
|
+
)( jQuery )
|
@@ -0,0 +1,41 @@
|
|
1
|
+
#
|
2
|
+
# Magic Radios
|
3
|
+
#
|
4
|
+
# @example
|
5
|
+
# = f.radio_button :main_addr_same_as_jur, true, data: {disable: ".main-addr"}
|
6
|
+
# = f.radio_button :main_addr_same_as_jur, false, data: {enable: ".main-addr"}
|
7
|
+
# = f.text_field :main_addr, :disabled => @profile.main_addr_same_as_jur, :class => "main-addr"
|
8
|
+
# javascript:
|
9
|
+
# $('.some form').magicRadios();
|
10
|
+
|
11
|
+
( ( $ ) ->
|
12
|
+
|
13
|
+
$.fn.magicRadios = (suspend = true, closestDock = 'fieldset, form, body', eventName = 'change.magic-radios') ->
|
14
|
+
if @length
|
15
|
+
jDocks = if @is 'input:radio' then @closest closestDock else @
|
16
|
+
jDocks.off eventName
|
17
|
+
if suspend
|
18
|
+
jDocks.on eventName, 'input:radio', (event) ->
|
19
|
+
jDock = $ event.delegateTarget
|
20
|
+
rules = [
|
21
|
+
['enable', 'disabled', false, true]
|
22
|
+
['check', 'checked', true]
|
23
|
+
['uncheck', 'checked', false]
|
24
|
+
['disable', 'disabled', true]
|
25
|
+
['writable', 'readonly', false, true]
|
26
|
+
['readonly', 'readonly', true]
|
27
|
+
]
|
28
|
+
for rule in rules
|
29
|
+
[dataParam, propName, propValue, focusFirst] = rule
|
30
|
+
linkedFields = $(@).data dataParam
|
31
|
+
if linkedFields
|
32
|
+
jFounded = jDock.find linkedFields
|
33
|
+
jFields = jFounded.filter ':input'
|
34
|
+
jFields = jFounded.find ':input' unless jFields.length
|
35
|
+
if jFields.length
|
36
|
+
jFields.prop propName, propValue
|
37
|
+
jFields.first().focus() if focusFirst
|
38
|
+
true
|
39
|
+
@
|
40
|
+
|
41
|
+
)( jQuery )
|
@@ -0,0 +1,59 @@
|
|
1
|
+
/**
|
2
|
+
* Декорирование таблиц с данными + добавление сортировки + доп. обработка таблиц с checkable строками
|
3
|
+
*
|
4
|
+
* @param {jQuery} jRoot корневые jQuery объекты, в которых будет осуществляться поиск table.tablesorter:not(.decorated)
|
5
|
+
* @returns {Number} count >= 0 количество продекорированных таблиц
|
6
|
+
*/
|
7
|
+
function decor_tables(jRoot) {
|
8
|
+
var jTables = jRoot.find('table.tablesorter:not(.decorated)'),
|
9
|
+
jTablesHeaders = jTables.find('thead th:not([colspan])'),
|
10
|
+
ts_initData = {};
|
11
|
+
if ( arguments.length > 1 ) ts_initData.sortList = arguments[1];
|
12
|
+
jTablesHeaders.prepend('<div class="bullet-wrapper"><div class="bullet"></div></div>');
|
13
|
+
jTables.find('thead')
|
14
|
+
.find('tr:first th:first').addClass('first-child')
|
15
|
+
.prepend('<div class="corner-wrapper"><div class="corner left"></div></div>')
|
16
|
+
.end().find('tr th:last-child').addClass('last-child').first()
|
17
|
+
.prepend('<div class="corner-wrapper"><div class="corner right"></div></div>');
|
18
|
+
jTables.find('td:last-child').addClass('last-child');
|
19
|
+
jTables.each( function () {
|
20
|
+
var jTable = $(this),
|
21
|
+
jTFoot = jTable.children('tfoot');
|
22
|
+
if ( !jTFoot.length ) jTFoot = $('<tfoot></tfoot>').appendTo(jTable);
|
23
|
+
var jRow = $('<tr></tr>').appendTo(jTFoot);
|
24
|
+
$('<td colspan="' + jTable.find('thead th').length + '" class="border-bottom"></td>').appendTo(jRow)
|
25
|
+
.append('<div class="corner-wrapper"><div class="corner left"></div><div class="corner right"></div></div>');
|
26
|
+
} )
|
27
|
+
.addClass('decorated')
|
28
|
+
.tablesorter(ts_initData);
|
29
|
+
jTables.filter('.checkable').tablesorter({headers: { 0: { sorter: false}}})
|
30
|
+
.find('thead th.first-child').removeClass('header')
|
31
|
+
.find('.bullet-wrapper').remove();
|
32
|
+
return jTables.length;
|
33
|
+
}
|
34
|
+
|
35
|
+
$('table.checkable thead th:first input:checkbox').live('change', function () {
|
36
|
+
var jThis = $(this),
|
37
|
+
jTable = jThis.closest('table.checkable'),
|
38
|
+
jCheckboxes = jTable.find('tbody input:checkbox');
|
39
|
+
jCheckboxes.prop('checked', jThis.prop('checked'));
|
40
|
+
refresh_states(jTable);
|
41
|
+
} );
|
42
|
+
|
43
|
+
$('table.checkable tbody td:first-child input:checkbox').live('change', function () {
|
44
|
+
var jTable = $(this).closest('table.checkable');
|
45
|
+
jTable.find('input:checkbox#select_all').prop('checked', jTable.find('tbody input:checkbox:not(:checked)').length === 0);
|
46
|
+
refresh_states(jTable);
|
47
|
+
} );
|
48
|
+
|
49
|
+
|
50
|
+
|
51
|
+
$( function () {
|
52
|
+
|
53
|
+
if ( $.tablesorter ) {
|
54
|
+
$.tablesorter.defaults.widgets = ['zebra'];
|
55
|
+
}
|
56
|
+
|
57
|
+
//decor_tables($('body'));
|
58
|
+
|
59
|
+
} );
|
@@ -0,0 +1,98 @@
|
|
1
|
+
( ( $ ) ->
|
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
|
+
min = parseFloat jField.data('gte')
|
9
|
+
max = parseFloat jField.data('lte')
|
10
|
+
oldValue = parseFloat realValue
|
11
|
+
v = oldValue
|
12
|
+
v = 0 if isNaN v
|
13
|
+
v = min if not isNaN(min) and v < min
|
14
|
+
v = max if not isNaN(max) and v > max
|
15
|
+
jField.val(v).change() unless v is oldValue
|
16
|
+
|
17
|
+
$.fn.setFieldBounds = (min, max) ->
|
18
|
+
@filter('input:text')
|
19
|
+
.attr
|
20
|
+
'data-gte': min
|
21
|
+
'data-lte': max
|
22
|
+
.data
|
23
|
+
'gte': min
|
24
|
+
'lte': max
|
25
|
+
|
26
|
+
# ========= regexpMask =========
|
27
|
+
|
28
|
+
$.regexp = {} unless $.regexp
|
29
|
+
$.regexp.typedField =
|
30
|
+
'integer' : /^$|^\d+$/
|
31
|
+
'float' : /^$|^\d+(\.\d*)?$/
|
32
|
+
'currency' : /^$|^\d+(\.\d{0,2})?$/
|
33
|
+
'text' : /^.*$/
|
34
|
+
|
35
|
+
$.fn.getRegExpMask = ->
|
36
|
+
mask = @data 'regexpMask'
|
37
|
+
if _.isString(mask)
|
38
|
+
try
|
39
|
+
mask = new RegExp mask
|
40
|
+
@data 'regexpMask', mask
|
41
|
+
catch e
|
42
|
+
# nop
|
43
|
+
else
|
44
|
+
dataType = @data 'dataType'
|
45
|
+
mask = $.regexp.typedField[dataType] if dataType
|
46
|
+
unless mask
|
47
|
+
@val 'unknown dataType'
|
48
|
+
mask = $.regexp.typedField['text']
|
49
|
+
mask
|
50
|
+
|
51
|
+
$.fn.dropRegExpMask = ->
|
52
|
+
@
|
53
|
+
.removeAttr('data-regexp-mask')
|
54
|
+
.removeData('regexpMask')
|
55
|
+
.removeData('value')
|
56
|
+
|
57
|
+
$.fn.setRegExpMask = (mask) ->
|
58
|
+
stringMask = 'true'
|
59
|
+
if _.isString mask
|
60
|
+
stringMask = mask
|
61
|
+
try
|
62
|
+
mask = new RegExp mask
|
63
|
+
catch e
|
64
|
+
# nop
|
65
|
+
if _.isRegExp mask
|
66
|
+
@
|
67
|
+
.dropRegExpMask()
|
68
|
+
.attr('data-regexp-mask', stringMask)
|
69
|
+
.data('regexpMask', mask)
|
70
|
+
.change()
|
71
|
+
@
|
72
|
+
|
73
|
+
$.fn.observeTypedFields = (selector = 'input:text[data-data-type], input:text[data-regexp-mask]') ->
|
74
|
+
return @ unless @length
|
75
|
+
|
76
|
+
@on 'keypress', selector, (event) ->
|
77
|
+
if event.metaKey
|
78
|
+
$(@).trigger 'paste', arguments
|
79
|
+
return true
|
80
|
+
return true unless event.charCode
|
81
|
+
jThis = $ @
|
82
|
+
oldValue = jThis.val()
|
83
|
+
newValue = oldValue.substring(0, @selectionStart) + String.fromCharCode(event.charCode) + oldValue.substring(@selectionEnd)
|
84
|
+
return false unless jThis.getRegExpMask().test(newValue)
|
85
|
+
jThis.data 'value', newValue
|
86
|
+
|
87
|
+
@on 'change', selector, ->
|
88
|
+
jThis = $ @
|
89
|
+
if jThis.getRegExpMask().test(jThis.val())
|
90
|
+
jThis.data 'value', jThis.val()
|
91
|
+
else
|
92
|
+
jThis.val jThis.data('value')
|
93
|
+
|
94
|
+
@on 'paste drop', selector, ->
|
95
|
+
jThis = $ @
|
96
|
+
setTimeout ( -> jThis.trigger 'change', arguments ), 100
|
97
|
+
|
98
|
+
)( jQuery )
|