dynamic_scope 0.5.4

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 0d425d85513eb249492e79b15ce14e476caa492b4cd7405b225815a4ab4db4cb
4
+ data.tar.gz: f9170279fd99494cc09101f27eed85bb820c03b26659afeee6d130e235a9a0bf
5
+ SHA512:
6
+ metadata.gz: 67556f423e7f2508c59a56de695a862c22a0f6e7300afed4ab5b2cf2b027cff9375cc3686d0d8fb045adece488a46012243024ab6e9acc16eadafd857b708871
7
+ data.tar.gz: 46d4aa58d0d0c5e30cafa0eaa11b3dfee3e12ff7efaa19e2dc45b355dc290e9c268f96f92c22d767a594948500a0dd82853c5e9d4b7cc74a59ad03eef49d8d01
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ /coverage
2
+ /spec/reports
3
+ /.idea
4
+ /Gemfile.lock
5
+ .DS_Store
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in railsto-datepicker.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,3 @@
1
+ # dynamic_scope
2
+
3
+ Helpers and angular module to make fancy dynamic scopes with arel.
data/Rakefile ADDED
@@ -0,0 +1,4 @@
1
+ require 'bundler/gem_tasks'
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new
@@ -0,0 +1,201 @@
1
+ #= require i18n
2
+ #= require i18n/translations
3
+
4
+ dynamicScope = angular.module('dynamicScope', [])
5
+
6
+ dynamicScope.directive 'dynamicScope', ['$parse', ($parse) ->
7
+ OPERATORS = {
8
+ integer: ['eq', 'not_eq', 'gteq', 'lteq'],
9
+ string: ['matches', 'does_not_match', 'begins_with', 'ends_with', 'eq', 'not_eq'],
10
+ enum: ['eq', 'not_eq', 'in', 'not_in'],
11
+ year: ['eq', 'gteq', 'lteq'],
12
+ month: ['eq', 'gteq', 'lteq'],
13
+ date: ['eq', 'gteq', 'lteq'],
14
+ datetime: ['eq', 'gteq', 'lteq'],
15
+ boolean: ['eq', 'not_eq']
16
+ }
17
+
18
+ IN_OPERATORS = ['in', 'not_in']
19
+
20
+ DEFAULT_VALUES = {
21
+ boolean: true
22
+ enum: undefined
23
+ }
24
+
25
+ defaultQuery = (config) ->
26
+ inputKey = Object.keys(config)[0]
27
+ inputOptions = config[inputKey]
28
+ [
29
+ {
30
+ key: inputKey
31
+ operator: (inputOptions.operators || OPERATORS[inputOptions.type])[0]
32
+ value: ''
33
+ }
34
+ ]
35
+
36
+ objectQueryToArray = (objectQuery = {}) ->
37
+ arrayQuery = []
38
+ Object.keys(objectQuery).forEach (key) ->
39
+ arrayQuery[key] = objectQuery[key]
40
+ arrayQuery
41
+
42
+ arrayQueryToObject = (arrayQuery = []) ->
43
+ objectQuery = {}
44
+ arrayQuery.forEach (queryPart, index) ->
45
+ objectQuery[index] = queryPart
46
+ objectQuery
47
+
48
+ translateKey = (key) ->
49
+ I18n.t("dynamic_scope.key.#{key}")
50
+
51
+ translateAndSortKeys = (keys) ->
52
+ _.chain(keys)
53
+ .inject((memo, key) ->
54
+ memo.push([key, translateKey(key)])
55
+ memo
56
+ , [])
57
+ .sortBy((keyAndName) ->
58
+ keyAndName[1]
59
+ ).value()
60
+
61
+ {
62
+ controllerAs: 'dynamicScope'
63
+ controller: ['$scope', '$element', '$attrs', '$transclude', ($scope, $element, $attrs, $transclude) ->
64
+ optionsAccessor = $parse($attrs.dynamicScope)
65
+ ctrl = this
66
+
67
+ @options = optionsAccessor($scope) || {}
68
+ @config = @options.config
69
+
70
+ if queryVarName = @options.query
71
+ $scope.$watch queryVarName, (newQuery) ->
72
+ ctrl.query = objectQueryToArray(newQuery)
73
+
74
+ @query ||= defaultQuery(@config)
75
+
76
+ @keysForNgOptions = translateAndSortKeys(_.keys(@config))
77
+
78
+ $scope.minDate = new Date()
79
+
80
+ @typeFor = (key) ->
81
+ ctrl.config[key].type
82
+
83
+ @operatorsFor = (key) ->
84
+ ctrl.config[key].operators || OPERATORS[ctrl.typeFor(key)]
85
+
86
+ @valuesFor = (key) ->
87
+ ctrl.config[key].values
88
+
89
+ @translateOperator = (operator) ->
90
+ I18n.t("dynamic_scope.operator.#{operator}")
91
+
92
+ @translateValue = (key, value, returnError) ->
93
+ return value if (returnError == false && I18n.t("dynamic_scope.values.#{key}.#{value}").includes("[missing", "translation]"))
94
+ I18n.t("dynamic_scope.values.#{key}.#{value}")
95
+
96
+ @addInput = ->
97
+ ctrl.query.push defaultQuery(ctrl.config)[0]
98
+
99
+ @removeInput = (input) ->
100
+ ctrl.query.splice(ctrl.query.indexOf(input), 1)
101
+
102
+ @submit = ->
103
+ ctrl.options.submit(arrayQueryToObject(ctrl.query))
104
+
105
+ @clearQuery = ->
106
+ ctrl.query = defaultQuery(ctrl.config)
107
+
108
+ @setInputDefaults = (queryPart) ->
109
+ if (defaultValue = DEFAULT_VALUES[ctrl.typeFor(queryPart.key)])?
110
+ queryPart.value = defaultValue
111
+
112
+ inputOperators = ctrl.operatorsFor(queryPart.key)
113
+ if inputOperators.indexOf(queryPart.operator) == -1
114
+ queryPart.operator = inputOperators[0]
115
+
116
+ @inputChanged = (type, value, queryPart) ->
117
+ console.log(value)
118
+ console.log(queryPart._value)
119
+ switch type
120
+ when 'month'
121
+ queryPart.value = "#{queryPart._value[0]}-#{queryPart._value[1]}"
122
+
123
+ @useMultiselect = (queryPart) ->
124
+ IN_OPERATORS.indexOf(queryPart.operator) >= 0
125
+
126
+ @operatorChanged = (queryPart) ->
127
+ type = ctrl.typeFor(queryPart.key)
128
+ switch type
129
+ when 'enum'
130
+ if IN_OPERATORS.indexOf(queryPart.operator) >= 0
131
+ queryPart.value = [queryPart.value] if typeof queryPart.value == 'string'
132
+ else if typeof queryPart.value == 'object'
133
+ queryPart.value = queryPart.value[0]
134
+
135
+ @keyChanged = (queryPart) ->
136
+ type = ctrl.typeFor(queryPart.key)
137
+ switch type
138
+ when 'enum'
139
+ queryPart.value = undefined
140
+ ctrl.setInputDefaults(queryPart)
141
+
142
+ return this
143
+ ]
144
+
145
+ link: ($scope, $elem, $attrs) ->
146
+ }
147
+ ]
148
+
149
+ dynamicScope.directive 'dynamicScopeFieldset', ->
150
+ keySelectTemplate = '<select class="key form-control" ng-model="queryPart.key" ng-options="keyAndName[0] as keyAndName[1] for keyAndName in dynamicScope.keysForNgOptions" ng-change="dynamicScope.keyChanged(queryPart)"></select>'
151
+ operatorSelectTemplate = '<select class="operator form-control" ng-model="queryPart.operator" ng-options="operator as dynamicScope.translateOperator(operator) for operator in dynamicScope.operatorsFor(queryPart.key)" ng-change="dynamicScope.operatorChanged(queryPart)"></select>'
152
+ stringInputTemplate = '<input class="value form-control type-string" type="text" ng-model="queryPart.value" ng-switch-when="string"></input>'
153
+ integerInputTemplate = '<input class="value form-control type-integer" type="text" ng-model="queryPart.value" ng-switch-when="integer"></input>'
154
+ enumSelectTemplate =
155
+ '<div class="value type-enum" ng-switch-when="enum">' +
156
+ '<ui-select multiple ng-if="dynamicScope.useMultiselect(queryPart)" ng-model="queryPart.value">' +
157
+ '<ui-select-match>{{$item ? dynamicScope.translateValue(queryPart.key, $item, false) : $item}}</ui-select-match>' +
158
+ '<ui-select-choices repeat="value in dynamicScope.valuesFor(queryPart.key)">{{dynamicScope.translateValue(queryPart.key, value, false)}}</ui-select-choices>' +
159
+ '</ui-select>' +
160
+ '<select class="form-control" ng-if="!dynamicScope.useMultiselect(queryPart)" ng-model="queryPart.value" ng-options="value as dynamicScope.translateValue(queryPart.key, value, false) for value in dynamicScope.valuesFor(queryPart.key)"></select>' +
161
+ '</div>'
162
+ yearInputTemplate = '<input type="year" class="value form-control type-year" ng-model="queryPart.value" ng-switch-when="year" placeholder="YYYY"></input>'
163
+ monthInputTemplate =
164
+ '<div class="value type-month" ng-switch-when="month">' +
165
+ '<input class="year form-control" type="number" min="0" max="9999" ng-model="queryPart._value[0]" placeholder="YYYY" ng-change="dynamicScope.inputChanged(\'month\', _value, queryPart)"></input>' +
166
+ '<select class="month form-control" ng-model="queryPart._value[1]" ng-change="dynamicScope.inputChanged(\'month\', _value, queryPart)">' +
167
+ '<option value="1">' + I18n.t('date.month_names.1') + '</value>' +
168
+ '<option value="2">' + I18n.t('date.month_names.2') + '</value>' +
169
+ '<option value="3">' + I18n.t('date.month_names.3') + '</value>' +
170
+ '<option value="4">' + I18n.t('date.month_names.4') + '</value>' +
171
+ '<option value="5">' + I18n.t('date.month_names.5') + '</value>' +
172
+ '<option value="6">' + I18n.t('date.month_names.6') + '</value>' +
173
+ '<option value="7">' + I18n.t('date.month_names.7') + '</value>' +
174
+ '<option value="8">' + I18n.t('date.month_names.8') + '</value>' +
175
+ '<option value="9">' + I18n.t('date.month_names.9') + '</value>' +
176
+ '<option value="10">' + I18n.t('date.month_names.10') + '</value>' +
177
+ '<option value="11">' + I18n.t('date.month_names.11') + '</value>' +
178
+ '<option value="12">' + I18n.t('date.month_names.12') + '</value>' +
179
+ '</select>' +
180
+ '</div>'
181
+ dateFutureInputTemplate = '<div class="value type-date-future" ng-switch-when="date_future"><date-input min="{{minDate | date:\'yyyy-MM-dd\'}}" ng-model="queryPart.value"></date-input></div>'
182
+ dateInputTemplate = '<div class="value type-date" ng-switch-when="date"><date-input ng-model="queryPart.value"></date-input></div>'
183
+ datetimeInputTemplate = '<div class="value type-datetime" ng-switch-when="datetime"><datetime-input ng-model="queryPart.value"></datetime-input></div>'
184
+ booleanSelectTemplate = '<select class="value form-control type-boolean" ng-model="queryPart.value" ng-switch-when="boolean" ng-options="value as dynamicScope.translateValue(queryPart.key, value) for value in [true, false]"></select>'
185
+ fieldsetRemoveTemplate = '<a class="fieldset-remove" href="javascript:;" ng-click="dynamicScope.removeInput(queryPart)" ng-show="dynamicScope.query.length > 1">' + I18n.t('dynamic_scope.remove_fieldset') + '</a>'
186
+ {
187
+ template: '<fieldset ng-repeat="queryPart in dynamicScope.query" ng-switch="dynamicScope.typeFor(queryPart.key)" class="ng-scope">' +
188
+ keySelectTemplate +
189
+ operatorSelectTemplate +
190
+ stringInputTemplate +
191
+ integerInputTemplate +
192
+ enumSelectTemplate +
193
+ yearInputTemplate +
194
+ monthInputTemplate +
195
+ dateFutureInputTemplate +
196
+ dateInputTemplate +
197
+ datetimeInputTemplate +
198
+ #booleanSelectTemplate +
199
+ fieldsetRemoveTemplate +
200
+ '</fieldset>'
201
+ }
@@ -0,0 +1,249 @@
1
+ #= require i18n
2
+ #= require i18n/translations
3
+
4
+ multipleDynamicScope = angular.module('multipleDynamicScope', [])
5
+
6
+ multipleDynamicScope.directive 'multipleDynamicScope', ['$parse', ($parse) ->
7
+ OPERATORS = {
8
+ integer: ['eq', 'not_eq', 'gteq', 'lteq'],
9
+ string: ['matches', 'does_not_match', 'begins_with', 'ends_with', 'eq', 'not_eq'],
10
+ enum: ['eq', 'not_eq', 'in', 'not_in'],
11
+ year: ['eq', 'gteq', 'lteq'],
12
+ month: ['eq', 'gteq', 'lteq'],
13
+ date: ['eq', 'gteq', 'lteq'],
14
+ datetime: ['eq', 'gteq', 'lteq'],
15
+ boolean: ['eq', 'not_eq']
16
+ }
17
+
18
+ IN_OPERATORS = ['in', 'not_in']
19
+
20
+ DEFAULT_VALUES = {
21
+ boolean: true
22
+ enum: undefined
23
+ }
24
+
25
+ sectionDefaultQuery = (section, sections) ->
26
+ inputKey = Object.keys(sections[section])[0]
27
+ inputOptions = sections[section][inputKey]
28
+ [
29
+ {
30
+ key: inputKey
31
+ operator: (inputOptions.operators || OPERATORS[inputOptions.type])[0]
32
+ value: ''
33
+ }
34
+ ]
35
+
36
+ defaultQuery = (sections) ->
37
+ query = {}
38
+ Object.keys(sections).forEach (section) ->
39
+ query[section] = sectionDefaultQuery(section, sections)
40
+ query
41
+
42
+ objectQueryToQuerySections = (config, default_section, objectQuery = {}) ->
43
+ querySections = {}
44
+ angular.forEach objectQuery, (value, key) ->
45
+ section = if config[value.key].section == undefined then default_section else config[objectQuery[key].key].section
46
+ querySections[section] ||= []
47
+ querySections[section].push(objectQuery[key])
48
+ querySections
49
+
50
+ querySectionsToObject = (querySections = []) ->
51
+ objectQuery = {}
52
+ index = 0
53
+ Object.keys(querySections).forEach (key) ->
54
+ querySections[key].forEach (queryPart) ->
55
+ objectQuery[index++] = queryPart
56
+ objectQuery
57
+
58
+ translateKey = (key) ->
59
+ I18n.t("dynamic_scope.key.#{key}")
60
+
61
+ translateAndSortKeys = (sections) ->
62
+ translations = {}
63
+ Object.keys(sections).forEach (section_name) ->
64
+ translations[section_name] =
65
+ _.chain(_.keys(sections[section_name]))
66
+ .inject((memo, key) ->
67
+ memo.push([key, translateKey(key)])
68
+ memo
69
+ , [])
70
+ .sortBy((keyAndName) ->
71
+ keyAndName[1]
72
+ ).value()
73
+ translations
74
+
75
+ makeSections = (config, default_section) ->
76
+ sections = {}
77
+ if config
78
+ Object.keys(config).forEach (key) ->
79
+ section = config[key].section || default_section
80
+ sections[section] ||= {}
81
+ sections[section][key] = config[key]
82
+ sections
83
+
84
+ makeMapping = (sections) ->
85
+ mapping = {}
86
+ Object.keys(sections).forEach (section) ->
87
+ mapping[section] = Object.keys(sections[section])
88
+ mapping
89
+
90
+ {
91
+ controllerAs: 'multipleDynamicScope'
92
+ controller: ['$rootScope', '$scope', '$element', '$attrs', '$transclude', ($rootScope, $scope, $element, $attrs, $transclude) ->
93
+ optionsAccessor = $parse($attrs.multipleDynamicScope)
94
+ ctrl = this
95
+
96
+ @options = optionsAccessor($scope) || {}
97
+ @config = @options.config
98
+ @default_section = @options.default_section
99
+ @sections = makeSections(@config, @default_section)
100
+ @section_fields = makeMapping(@sections)
101
+
102
+ if queryVarName = @options.query
103
+ $scope.$watch queryVarName, (newQuery) ->
104
+ ctrl.query = objectQueryToQuerySections(ctrl.config, ctrl.default_section, newQuery)
105
+
106
+ @query ||= defaultQuery(@sections)
107
+
108
+ @keysForNgOptions = translateAndSortKeys(@sections)
109
+
110
+ $scope.minDate = new Date()
111
+
112
+ @queryFor = (section) ->
113
+ section_query = []
114
+ ctrl.query.forEach (row) ->
115
+ if ctrl.section_fields[section].includes(row.key)
116
+ section_query.push(row)
117
+ section_query
118
+
119
+ @typeFor = (key) ->
120
+ ctrl.config[key].type
121
+
122
+ @operatorsFor = (key) ->
123
+ ctrl.config[key].operators || OPERATORS[ctrl.typeFor(key)]
124
+
125
+ @valuesFor = (key) ->
126
+ ctrl.config[key].values
127
+
128
+ @translateOperator = (operator) ->
129
+ I18n.t("dynamic_scope.operator.#{operator}")
130
+
131
+ @translateValue = (key, value, returnError) ->
132
+ return value if (returnError == false && I18n.t("dynamic_scope.values.#{key}.#{value}").includes("[missing", "translation]"))
133
+ I18n.t("dynamic_scope.values.#{key}.#{value}")
134
+
135
+ @addInput = (section) ->
136
+ ctrl.query[section].push sectionDefaultQuery(section, ctrl.sections)[0]
137
+
138
+ @removeInput = (input, section) ->
139
+ if ctrl.query[section].length > 1
140
+ ctrl.query[section].splice(ctrl.query[section].indexOf(input), 1)
141
+ else
142
+ $rootScope.$broadcast('removeLastFieldset', section)
143
+
144
+ @submit = ->
145
+ ctrl.options.submit(querySectionsToObject(ctrl.query))
146
+
147
+ @clearQuery = ->
148
+ ctrl.query = defaultQuery(ctrl.sections)
149
+
150
+ @setInputDefaults = (queryPart) ->
151
+ if (defaultValue = DEFAULT_VALUES[ctrl.typeFor(queryPart.key)])?
152
+ queryPart.value = defaultValue
153
+
154
+ inputOperators = ctrl.operatorsFor(queryPart.key)
155
+ if inputOperators.indexOf(queryPart.operator) == -1
156
+ queryPart.operator = inputOperators[0]
157
+
158
+ @inputChanged = (type, value, queryPart) ->
159
+ switch type
160
+ when 'month'
161
+ queryPart.value = "#{queryPart._value[0]}-#{queryPart._value[1]}"
162
+
163
+ @useMultiselect = (queryPart) ->
164
+ IN_OPERATORS.indexOf(queryPart.operator) >= 0
165
+
166
+ @operatorChanged = (queryPart) ->
167
+ type = ctrl.typeFor(queryPart.key)
168
+ switch type
169
+ when 'enum'
170
+ if IN_OPERATORS.indexOf(queryPart.operator) >= 0
171
+ queryPart.value = [queryPart.value] if typeof queryPart.value == 'string'
172
+ else if typeof queryPart.value == 'object'
173
+ queryPart.value = queryPart.value[0]
174
+
175
+ @keyChanged = (queryPart) ->
176
+ type = ctrl.typeFor(queryPart.key)
177
+ switch type
178
+ when 'enum'
179
+ queryPart.value = undefined
180
+ ctrl.setInputDefaults(queryPart)
181
+
182
+ return this
183
+ ]
184
+
185
+ link: ($scope, $elem, $attrs) ->
186
+ }
187
+ ]
188
+
189
+ multipleDynamicScope.directive 'multipleDynamicScopeFieldset', ['$parse', ($parse) ->
190
+ keySelectTemplate = '<select class="key form-control" ng-model="queryPart.key" ng-options="keyAndName[0] as keyAndName[1] for keyAndName in multipleDynamicScope.keysForNgOptions[section]" ng-change="multipleDynamicScope.keyChanged(queryPart)"></select>'
191
+ operatorSelectTemplate = '<select class="operator form-control" ng-model="queryPart.operator" ng-options="operator as multipleDynamicScope.translateOperator(operator) for operator in multipleDynamicScope.operatorsFor(queryPart.key)" ng-change="multipleDynamicScope.operatorChanged(queryPart)"></select>'
192
+ stringInputTemplate = '<input class="value form-control type-string" type="text" ng-model="queryPart.value" ng-switch-when="string"></input>'
193
+ integerInputTemplate = '<input class="value form-control type-integer" type="text" ng-model="queryPart.value" ng-switch-when="integer"></input>'
194
+ enumSelectTemplate =
195
+ '<div class="value type-enum" ng-switch-when="enum">' +
196
+ '<ui-select multiple ng-if="multipleDynamicScope.useMultiselect(queryPart)" ng-model="queryPart.value">' +
197
+ '<ui-select-match>{{$item ? multipleDynamicScope.translateValue(queryPart.key, $item, false) : $item}}</ui-select-match>' +
198
+ '<ui-select-choices repeat="value in multipleDynamicScope.valuesFor(queryPart.key)">{{multipleDynamicScope.translateValue(queryPart.key, value, false)}}</ui-select-choices>' +
199
+ '</ui-select>' +
200
+ '<select class="form-control" ng-if="!multipleDynamicScope.useMultiselect(queryPart)" ng-model="queryPart.value" ng-options="value as multipleDynamicScope.translateValue(queryPart.key, value, false) for value in multipleDynamicScope.valuesFor(queryPart.key)"></select>' +
201
+ '</div>'
202
+ yearInputTemplate = '<input type="year" class="value form-control type-year" ng-model="queryPart.value" ng-switch-when="year" placeholder="YYYY"></input>'
203
+ monthInputTemplate =
204
+ '<div class="value type-month" ng-switch-when="month">' +
205
+ '<input class="year form-control" type="number" min="0" max="9999" ng-model="queryPart._value[0]" placeholder="YYYY" ng-change="multipleDynamicScope.inputChanged(\'month\', _value, queryPart)"></input>' +
206
+ '<select class="month form-control" ng-model="queryPart._value[1]" ng-change="multipleDynamicScope.inputChanged(\'month\', _value, queryPart)">' +
207
+ '<option value="1">' + I18n.t('date.month_names.1') + '</value>' +
208
+ '<option value="2">' + I18n.t('date.month_names.2') + '</value>' +
209
+ '<option value="3">' + I18n.t('date.month_names.3') + '</value>' +
210
+ '<option value="4">' + I18n.t('date.month_names.4') + '</value>' +
211
+ '<option value="5">' + I18n.t('date.month_names.5') + '</value>' +
212
+ '<option value="6">' + I18n.t('date.month_names.6') + '</value>' +
213
+ '<option value="7">' + I18n.t('date.month_names.7') + '</value>' +
214
+ '<option value="8">' + I18n.t('date.month_names.8') + '</value>' +
215
+ '<option value="9">' + I18n.t('date.month_names.9') + '</value>' +
216
+ '<option value="10">' + I18n.t('date.month_names.10') + '</value>' +
217
+ '<option value="11">' + I18n.t('date.month_names.11') + '</value>' +
218
+ '<option value="12">' + I18n.t('date.month_names.12') + '</value>' +
219
+ '</select>' +
220
+ '</div>'
221
+ dateFutureInputTemplate = '<div class="value type-date-future" ng-switch-when="date_future"><date-input min="{{minDate | date:\'yyyy-MM-dd\'}}" ng-model="queryPart.value"></date-input></div>'
222
+ dateInputTemplate = '<div class="value type-date" ng-switch-when="date"><date-input ng-model="queryPart.value"></date-input></div>'
223
+ datetimeInputTemplate = '<div class="value type-datetime" ng-switch-when="datetime"><datetime-input ng-model="queryPart.value"></datetime-input></div>'
224
+ booleanSelectTemplate = '<select class="value form-control type-boolean" ng-model="queryPart.value" ng-switch-when="boolean" ng-options="value as multipleDynamicScope.translateValue(queryPart.key, value) for value in [true, false]"></select>'
225
+ fieldsetRemoveTemplate = '<a class="fieldset-remove" href="javascript:;" ng-click="multipleDynamicScope.removeInput(queryPart, section)" ng-show="multipleDynamicScope.query[section].length > removeLength">' + I18n.t('dynamic_scope.remove_fieldset') + '</a>'
226
+ {
227
+ template: '<legend ng-hide="hideTitle">{{ title }}</legend>' +
228
+ '<fieldset ng-repeat="queryPart in multipleDynamicScope.query[section]" ng-switch="multipleDynamicScope.typeFor(queryPart.key)" class="ng-scope">' +
229
+ keySelectTemplate +
230
+ operatorSelectTemplate +
231
+ stringInputTemplate +
232
+ integerInputTemplate +
233
+ enumSelectTemplate +
234
+ yearInputTemplate +
235
+ monthInputTemplate +
236
+ dateFutureInputTemplate +
237
+ dateInputTemplate +
238
+ datetimeInputTemplate +
239
+ #booleanSelectTemplate +
240
+ fieldsetRemoveTemplate +
241
+ '</fieldset>'
242
+ scope: true
243
+ link: ($scope, $elem, $attrs) ->
244
+ $scope.section = $attrs.section
245
+ $scope.hideTitle = $attrs.hideTitle
246
+ $scope.title = I18n.t("dynamic_scope.section_title.#{$scope.section}")
247
+ $scope.removeLength = if $attrs.removeAllFieldsets then 0 else 1
248
+ }
249
+ ]
@@ -0,0 +1,110 @@
1
+ $(() ->
2
+ $.widget('custom.dynamicScope', {
3
+ options: {}
4
+
5
+ _create: () ->
6
+ this.counter = this.element.find('.dynamic_scope_active').size()
7
+ if this.element.is('form')
8
+ this.form = this.element
9
+ else
10
+ this.form = this.element.find('form')
11
+
12
+ this.templates = this.form.prevAll('.templates:first').find('fieldset')
13
+ if this.counter > 1
14
+ this.element.find('.dynamic_scope_remove').attr('style', null)
15
+
16
+ that = this
17
+
18
+ this.fieldsets().each( ->
19
+ that.addTriggers($(this))
20
+ )
21
+
22
+ this.element.on('click', '.dynamic_scope_add', (event) ->
23
+ event.preventDefault
24
+ newFieldset = that.addFieldset()
25
+ that.addTriggers(newFieldset)
26
+ return false
27
+ )
28
+
29
+ this.element.on('click', '.dynamic_scope_clear', (event) ->
30
+ event.preventDefault
31
+ that.clear()
32
+ return false
33
+ )
34
+
35
+ fieldsets: () ->
36
+ this.form.find('fieldset')
37
+
38
+ columnChange: (select) ->
39
+ this.counter = this.counter + 1
40
+ new_value = select.find('option:selected').attr('value')
41
+ template = this.templates.filter('#dynamic_scope_template_' + new_value)
42
+ fieldset = select.closest('fieldset')
43
+ input = fieldset.find('input[type=text]')
44
+
45
+ fieldset.html(template.html().replace(/INDEX/g, this.counter))
46
+ fieldset.attr('id', "dynamic_scope_#{this.counter}")
47
+ fieldset.find('.date').datepicker()
48
+ fieldset.find('[class="' + input.attr('class') + '"]').val(input.val())
49
+
50
+ if this.fieldsets().length > 1
51
+ this.fieldsets().find('.dynamic_scope_remove').attr('style', null)
52
+
53
+ this.element.trigger('dynamicScope:change')
54
+
55
+ return fieldset
56
+
57
+ addFieldset: () ->
58
+ this.counter = this.counter + 1
59
+ newFieldset = this.templates.filter('#dynamic_scope_template_any_field').clone()
60
+ if newFieldset.length == 0
61
+ newFieldset = this.templates.filter('.dynamic_scope_template:first').clone()
62
+
63
+ newFieldset.attr('style', null)
64
+ newFieldset.removeClass('dynamic_scope_template')
65
+ newFieldset.addClass('dynamic_scope_active')
66
+ newFieldset.html(newFieldset.html().replace(/INDEX/g, this.counter))
67
+ newFieldset.attr('id', 'dynamic_scope_' + this.counter)
68
+
69
+ lastActive = this.element.find('.dynamic_scope_active:last')
70
+ if lastActive.length > 0
71
+ lastActive.after(newFieldset)
72
+ else
73
+ this.element.find('.dynamic_scope_fieldsets').prepend(newFieldset)
74
+
75
+ this.fieldsets().find('.dynamic_scope_remove').attr('style', null)
76
+ this.element.trigger('dynamicScope:add', { fieldset: newFieldset })
77
+
78
+ return newFieldset
79
+
80
+ remove: (fieldset) ->
81
+ fieldset.remove()
82
+ if this.fieldsets().length == 1
83
+ this.fieldsets().find('.dynamic_scope_remove').css('display', 'none')
84
+
85
+ this.element.trigger('dynamicScope:remove', { fieldset: fieldset })
86
+
87
+ clear: () ->
88
+ this.form.find('input[type=text]').each( ->
89
+ $(this).val('')
90
+ )
91
+ this.form.submit()
92
+
93
+ addTriggers: (fieldset) ->
94
+ that = this
95
+ fieldset.on('change', '.dynamic_scope_column', (event) ->
96
+ that.columnChange($(this))
97
+ )
98
+ fieldset.on('click', '.dynamic_scope_remove', (event) ->
99
+ that.remove(fieldset)
100
+ event.preventDefault()
101
+ return false
102
+ )
103
+ }
104
+ )
105
+
106
+ )
107
+
108
+ $(->
109
+ $('.dynamic_scope').dynamicScope()
110
+ )