material_raingular 0.0.3 → 0.0.3.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cbdd155f510682affee2271e8eb83df2446ad959
4
- data.tar.gz: b1ee0aed082d80b1f9145cd3d00fdacb178bd1a9
3
+ metadata.gz: 7ea94f133f48652bdd35aad89979c597ce1c7893
4
+ data.tar.gz: 203d64c5846c918081873b6441732814db7aa025
5
5
  SHA512:
6
- metadata.gz: ae067161369d177749ee9767d0e490d0522c58c33eff3d94f6eb24bce45bde3ce446649b9155f5846bd852e07375bb4c04ba45452a9fc23728a9520050d80c4f
7
- data.tar.gz: 4a15effbbd28995118f464612fcd0effab1cd5c96d126ef23edf9ec564b8f0544929c0d92bd6955be3a9dc14dcbd2aa11904e251e1ccbcc09201e6baf9d26335
6
+ metadata.gz: d5e66387e6d9135d424b33ba1c9db028124063222aad8771e1ae6da31c53929e45f569fdcc1f2c88e653e208fae99d49344ad47b68f4f83adc41630f87e56b9f
7
+ data.tar.gz: fb439a409e1bfcbe33f3445cf4ef730075f5bd41b2c6d42e8d4e87876909bbbdf123dc917ef3cb0c4c20722f4267e59489c977016ce2e9a30ecd5f9284c22445
@@ -1,4 +1,5 @@
1
- REGEXP = /^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+group\s+by\s+([\s\S]+?))?(?:\s+disable\s+when\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?$/;
1
+ class SelectOptions
2
+ REGEXP: /^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+group\s+by\s+([\s\S]+?))?(?:\s+disable\s+when\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?$/;
2
3
  # 1: Model Value
3
4
  # 2: Display Value
4
5
  # 3: group by expression (groupByFn)
@@ -8,126 +9,261 @@ REGEXP = /^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+group\s+by\s+([\s\S]+?))?(?
8
9
  # 7: object item value variable name
9
10
  # 8: collection
10
11
  # 9: track by expressionj
12
+ constructor: (@unparsed,@html) ->
13
+ @filters = @unparsed.split('|')
14
+ @options = @filters.shift()
15
+ @match = @options.match(@REGEXP)
16
+ @raiseError() if !@match
17
+ raiseError: ->
18
+ throw new Error(
19
+ "Expected expression in form of " +
20
+ "'_select_ (as _label_)? for (_key_,)?_value_ in _collection_'" +
21
+ " but got '" + @unparsed + "'. Element: " + @html)
22
+ class SelectFunctions
23
+ constructor: (match,parse) ->
24
+ @collection = parse(match[8])
25
+ @modelValue = match[1].replace(match[5] + '.','')
26
+ @viewValue = if match[2] then match[2].replace(match[5] + '.','') else @modelValue
27
+ @viewValueFn = parse(@viewValue || @modelValue)
28
+ @modelValueFn = parse(@modelValue || @viewValue)
29
+
30
+ class MobileTemplate
31
+ constructor: (@element,functions) ->
32
+ @template = angular.element("<ul> </ul>")
33
+ @search = angular.element "<input type='search' placeholder='Search'>"
34
+ @tempHolder = angular.element("<div class='filtered-select' ></div>")
35
+ @body = angular.element(document.body)
36
+ @mousedownFunction = functions[0]
37
+ @keydownFunction = functions[1]
38
+ @inputFunction = functions[2]
39
+
40
+ @bind()
41
+ @stylize()
42
+ @attachElements()
43
+ attachElements: ->
44
+ @tempHolder.append @search
45
+ @tempHolder.append @template
46
+ @body.append @tempHolder
47
+ stylize: ->
48
+ ulHeight = =>
49
+ full = window.innerHeight
50
+ full = full/2 if @element.hasClass('bottom')
51
+ full - @search[0].offsetHeight + 'px'
52
+ @tempHolder.addClass('bottom') if @element.hasClass('bottom')
53
+ @template.css('height',ulHeight())
54
+
55
+ bind: ->
56
+ @element.bind 'mousedown', (event) =>
57
+ @mousedownFunction(@tempHolder,@search,event)
58
+ @body.bind 'keydown', (event) =>
59
+ @keydownFunction(@tempHolder,event)
60
+ @search.bind 'input', (event) =>
61
+ @inputFunction(event)
62
+
63
+ class StandardTemplate
64
+ constructor: (@element,attrs,functions,@disabled) ->
65
+ @span = angular.element "<span></span>"
66
+ @search = angular.element "<input style='opacity:0.5'class='autocomplete' type='search' placeholder='" + attrs.placeholder + "'>"
67
+ @tempHolder = angular.element "<div class='autocomplete menu md-whiteframe-z1'>"
68
+ @template = @tempHolder
69
+ @typeAhead = angular.element "<span style='position:absolute;'></span>"
70
+ @inputFunction = functions[0]
71
+ @focusFunction = functions[1]
72
+ @blurFunction = functions[2]
73
+ @keydownFunction = functions[3]
74
+ @attachElements()
75
+ @stylize()
76
+ @bind()
77
+ stylize: ->
78
+ @search.addClass('md-input') if @element.hasClass('md-input')
79
+ @search.css({'width': '100%','color': 'black'})
80
+ searchCss = window.getComputedStyle(@search[0])
81
+ @typeAhead.css('padding-left', parseFloat(searchCss["padding-left"]) + parseFloat(searchCss["margin-left"]) + parseFloat(searchCss["border-left-width"]) + 'px')
82
+ @typeAhead.css('padding-top', parseFloat(searchCss["padding-top"]) + parseFloat(searchCss["margin-top"]) + parseFloat(searchCss["border-top-width"]) + 'px')
83
+
84
+ bind: ->
85
+ @search.bind 'input', (event)=>
86
+ @inputFunction(@search,@typeAhead,event)
87
+ @search.bind 'focus', (event)=>
88
+ @focusFunction(event)
89
+ @search.bind 'blur', (event)=>
90
+ @blurFunction(@search,event)
91
+ @search.bind 'keydown', (event)=>
92
+ @keydownFunction(@search,@typeAhead,@template,event)
93
+ attachElements: ->
94
+ @span.append @typeAhead
95
+ @span.append @search
96
+ @span.append @tempHolder
97
+ @element.append @span
98
+
99
+ class EventFunctions
100
+ constructor: (@functions,@buildTemplate,@updateValue,@filteredList,@filter,@timeout,@parse,@scope,@disabled) ->
101
+
102
+ inputFunction: (search,typeAhead,event) =>
103
+ location = search[0].selectionStart
104
+ if location > 3
105
+ if @functions.viewValueFn(@filteredList()[0])
106
+ search.val(@functions.viewValueFn(@filteredList()[0]))
107
+ else
108
+ search.val(search.val()[0..location - 1])
109
+ search[0].setSelectionRange(location,location)
110
+ else
111
+ search.val(search.val()[0..2])
112
+ typeAhead.html(search.val()[0..location - 1])
113
+ @buildTemplate()
114
+ focusFunction: (event) =>
115
+ @buildTemplate()
116
+ blurFunction: (search,event) =>
117
+ obj={}
118
+ obj[@functions.viewValue] = search.val()
119
+ val = @filter('filter')(@functions.collection(@scope), obj)[0]
120
+ @updateValue @functions.modelValueFn(val)
121
+ search.css
122
+ search.val(@functions.viewValueFn(val))
123
+ keydownFunction: (search,typeAhead,template,input) =>
124
+ keypress = (direction) ->
125
+ index = if direction == 'next' then 0 else template.find('a').length - 1
126
+ selected = angular.element(template[0].getElementsByClassName('active')[0])
127
+ if selected.hasClass('active')
128
+ selected.removeClass('active')
129
+ until complete
130
+ selected = angular.element(selected[0][direction + 'Sibling']) if selected[0]
131
+ complete = !!selected[0]
132
+ complete = selected[0].tagName == 'A' if complete
133
+ complete = true if !selected[0]
134
+ selected = angular.element(template.find('a')[index]) unless selected[0]
135
+ ind = 0
136
+ for el,i in template[0].getElementsByTagName('a')
137
+ ind = i if el == selected[0]
138
+ scroll = selected[0].scrollHeight * ind
139
+ selected[0].parentElement.scrollTop = scroll
140
+ selected.addClass('active')
141
+ location = search[0].selectionStart
142
+ search.val(selected.text())
143
+ search[0].setSelectionRange(location,location)
144
+ typeAhead.html(selected.text()[0..location - 1])
145
+ if input.keyCode == 40
146
+ input.preventDefault()
147
+ keypress('next')
148
+ if input.keyCode == 38
149
+ input.preventDefault()
150
+ keypress('previous')
151
+ mkeydownFunction: (tempHolder,event) =>
152
+ tempHolder.removeClass('active') if event.keyCode == 27
153
+ mousedownFunction: (tempHolder,search,event) =>
154
+ return if tempHolder.hasClass('active')
155
+ return if @disabled
156
+ search.val('')
157
+ @buildTemplate()
158
+ tempHolder.css('top',event.clientY)
159
+ tempHolder.css('transition','none')
160
+ @timeout ->
161
+ tempHolder.css('transition','')
162
+ tempHolder.css('top','')
163
+ tempHolder.addClass('active')
164
+ minputFunction: (event) =>
165
+ @buildTemplate()
166
+
167
+ standard: ->
168
+ [@inputFunction,@focusFunction,@blurFunction,@keydownFunction]
169
+ mobile: ->
170
+ [@mousedownFunction,@mkeydownFunction,@minputFunction]
171
+
11
172
 
12
173
  angular.module('FilteredSelect', [])
13
174
  .directive 'ngFilteredSelect', ($parse,$filter,$timeout)->
14
175
  require: 'ngModel'
15
176
  link: (scope,element,attrs,ngModel) ->
16
- filters = attrs.ngSelectOptions.split('|')
17
- options = filters.shift()
18
- match = options.match(REGEXP);
19
- if !match
20
- throw new Error(
21
- "Expected expression in form of " +
22
- "'_select_ (as _label_)? for (_key_,)?_value_ in _collection_'" +
23
- " but got '" + attrs.ngSelectOptions + "'. Element: " + element[0].outerHTML)
24
- collection = $parse(match[8])
25
- modelValue = match[1].replace(match[5] + '.','')
26
- viewValue = if match[2] then match[2].replace(match[5] + '.','') else modelValue
27
- template = angular.element("<ul> </ul>")
28
- search = angular.element "<input type='search' placeholder='Search'>"
29
- tempHolder = angular.element("<div class='filtered-select' ></div>")
30
- viewValueFn = $parse(viewValue || modelValue)
31
- modelValueFn = $parse(modelValue || viewValue)
32
- tempHolder.addClass('bottom') if element.hasClass('bottom')
33
- template.bind 'mousewheel DOMMouseScroll', (event)->
34
- delta = event.wheelDelta or event.originalEvent and event.originalEvent.wheelDelta or -event.detail
35
- bottomOverflow = template[0].scrollTop + template.outerHeight() - template[0].scrollHeight >= 0
36
- topOverflow = template[0].scrollTop <= 0
37
- if delta < 0 and bottomOverflow or delta > 0 and topOverflow
38
- event.preventDefault()
39
- scrollStart = null
40
- scrollTop = null
41
- template.bind 'touchstart', (event)->
42
- event.stopPropagation()
43
- scrollStart = event.originalEvent.touches[0].clientY
44
- template.bind 'touchmove', (event) ->
45
- event.stopPropagation()
46
- scroll = event.originalEvent.touches[0].clientY
47
- scrollStart = scroll unless scrollStart
48
- if scroll > scrollStart
49
- event.preventDefault() if template.scrollTop() == 0
50
- else if scroll < scrollStart
51
- newScrollTop = template.scrollTop()
52
- event.preventDefault() if scrollTop == newScrollTop
53
- scrollTop = newScrollTop
54
- scrollStart = scroll
55
- return true
56
- template.bind 'touchend', ->
57
- event.stopPropagation()
58
- scrollStart = null
59
- body = angular.element('body')
60
- body.bind 'keydown', (event) ->
61
- tempHolder.removeClass('active') if event.keyCode == 27
62
- tempHolder.append search
63
- tempHolder.append template
64
- body.append tempHolder
65
- ulHeight = ->
66
- full = window.innerHeight
67
- full = full/3 if element.hasClass('bottom')
68
- full - search[0].offsetHeight + 'px'
69
- template.css('height',ulHeight())
70
- scope.$watch collection, (newVal,oldVal) ->
71
- return if newVal == oldVal
72
- setInitialValue()
73
- buildTemplate()
74
- scope.$watch attrs.ngModel, (newVal,oldVal) ->
75
- return if newVal == oldVal
76
- setInitialValue()
77
- search.bind 'input', ->
78
- buildTemplate()
79
- buildTemplate = ->
80
- list= []
177
+ equiv = (left,right) ->
178
+ return true if left == right
179
+ return true if (!!left && !!right) == false
180
+ if !isNaN(left) && !isNaN(right)
181
+ return true if parseFloat(left) == parseFloat(right)
182
+ false
183
+ filteredList = (bool)->
184
+ if bool
185
+ bool = (left,right) ->
186
+ !!left.match(new RegExp("^" + right))
187
+ location = elements.search[0].selectionStart || elements.search.val().length
81
188
  obj={}
82
- obj[viewValue] = search.val() || ''
83
- return unless collection(scope)
84
- filteredList = $filter('orderBy')($filter('filter')(collection(scope), obj), viewValue)
85
- for filter in filters
189
+ obj[functions.viewValue] = elements.search.val()[0..location - 1] || ''
190
+ return unless functions.collection(scope)
191
+ fList = $filter('orderBy')($filter('filter')(functions.collection(scope), obj,bool), functions.viewValue)
192
+ for filter in options.filters
86
193
  [filterType,value] = filter.replace(/\s+/,'').split(':')
87
- filteredList = $filter(filterType)(filteredList, value)
88
- for item in filteredList
89
- li = angular.element '<li ng-model-value="' + modelValueFn(item) + '">' + viewValueFn(item) + '</li>'
194
+ fList = $filter(filterType)(fList, value)
195
+ fList
196
+ buildTemplate = ->
197
+ elements.template.empty()
198
+ return unless filteredList()
199
+ for item in filteredList()
200
+ if isMobile
201
+ li = angular.element '<li>' + functions.viewValueFn(item) + '</li>'
202
+ else
203
+ li = angular.element '<a class="item">' + functions.viewValueFn(item) + '</a>'
204
+ ip = angular.element '<input type="hidden">'
205
+ ip.val(functions.modelValueFn(item))
206
+ li.append(ip)
90
207
  li.bind 'mousedown', ($event)->
91
- updateValue($event.target.attributes['ng-model-value'].value)
92
- list.push li
93
- template.empty()
94
- template.append(list)
208
+ updateValue($event.target.children[0].value)
209
+ elements.template.append(li)
95
210
  setInitialValue = ->
96
- unless model = ngModel.$modelValue
97
- view = attrs.placeholder
98
- element.css('color','rgba(0,0,0,0.4)')
99
- else
100
- element.css('color','')
211
+ unless isMobile
101
212
  obj = {}
102
- obj[modelValue] = model
103
- list = $filter('filter')(collection(scope), obj)
213
+ obj[functions.modelValue] = ngModel.$modelValue
214
+ list = $filter('filter')(functions.collection(scope), obj,equiv)
104
215
  viewScope = list[0] if list
105
- view = if viewScope then viewValueFn(viewScope) else attrs.placeholder
106
- element.html('')
107
- element.html(view)
108
- setInitialValue()
109
- buildTemplate()
216
+ elements.search.val(if viewScope then functions.viewValueFn(viewScope) else '')
217
+ elements.typeAhead.html(elements.search.val())
218
+ else
219
+ unless model = ngModel.$modelValue
220
+ view = attrs.placeholder
221
+ element.css('color','rgba(0,0,0,0.4)')
222
+ else
223
+ element.css('color','')
224
+ obj = {}
225
+ obj[functions.modelValue] = model
226
+ list = $filter('filter')(functions.collection(scope), obj,true)
227
+ viewScope = list[0] if list
228
+ view = if viewScope then functions.viewValueFn(viewScope) else attrs.placeholder
229
+ element.html('')
230
+ element.html(view)
231
+
110
232
  updateValue = (model) ->
111
233
  ngModel.$setViewValue(model)
112
- tempHolder.removeClass('active')
113
- done = false
114
- fieldset = element
115
- until done
116
- fieldset = fieldset.parent()
117
- unless done = typeof fieldset[0] == 'undefined'
118
- done = fieldset[0].tagName == 'FIELDSET'
119
- element.parent('fieldset')
120
- element.bind 'mousedown', (event)->
121
- return if tempHolder.hasClass('active')
122
- return if attrs.disabled || $parse(attrs.ngDisabled)(scope)
123
- if fieldset
234
+ elements.tempHolder.removeClass('active')
235
+ setInitialValue()
236
+ disabled = ->
237
+ unless typeof fieldset != 'undefined'
238
+ done = false
239
+ fieldset = element
240
+ until done
241
+ fieldset = fieldset.parent()
242
+ unless done = typeof fieldset[0] == 'undefined'
243
+ done = fieldset[0].tagName == 'FIELDSET'
244
+ return true if typeof element[0].attributes.disabled != 'undefined' || $parse(attrs.ngDisabled)(scope)
245
+ if fieldset.length > 0
124
246
  ngdis = if fieldset[0].attributes.ngDisabled then fieldset[0].attributes.ngDisabled.value else ''
125
- return if fieldset[0].attributes.disabled || $parse(ngdis)(scope)
126
- search.val('')
247
+ return true if fieldset[0].attributes.disabled || $parse(ngdis)(scope)
248
+ return false
249
+
250
+ options = new SelectOptions(attrs.ngSelectOptions,element[0].outerHTML)
251
+ functions = new SelectFunctions(options.match,$parse)
252
+ eFunctions = new EventFunctions(functions,buildTemplate,updateValue,filteredList,$filter,$timeout,$parse,scope,disabled())
253
+ if isMobile = typeof attrs.ngMobile != 'undefined'
254
+ elements = new MobileTemplate(element,eFunctions.mobile())
255
+ else
256
+ elements = new StandardTemplate(element,attrs,eFunctions.standard(),disabled())
257
+ scope.$watchCollection functions.collection, (newVal,oldVal) ->
258
+ return if newVal == oldVal
259
+ setInitialValue()
127
260
  buildTemplate()
128
- tempHolder.css('top',event.clientY)
129
- tempHolder.css('transition','none')
130
- $timeout ->
131
- tempHolder.css('transition','')
132
- tempHolder.css('top','')
133
- tempHolder.addClass('active')
261
+ scope.$watch attrs.ngModel, (newVal,oldVal) ->
262
+ return if newVal == oldVal
263
+ setInitialValue()
264
+ scope.$watch disabled, (newVal,oldVal) ->
265
+ return if newVal == oldVal
266
+ elements.search[0].disabled = newVal
267
+
268
+ setInitialValue()
269
+ buildTemplate()
@@ -1,3 +1,4 @@
1
+ @import "angular-material.min"
1
2
  div.filtered-select
2
3
  position: fixed
3
4
  z-index: 1001
@@ -33,12 +34,54 @@ div.filtered-select
33
34
  cursor: pointer
34
35
  box-shadow: 0 4px 2px -2px rgba(0,0,0,0.14)
35
36
  &.bottom
36
- top: 67%
37
+ top: 50%
37
38
  z-index: 1000
38
39
  &.active
39
- height: 33%
40
+ height: 50%
40
41
  ng-filtered-select
41
42
  display: block
42
43
  width: 100%
43
44
  overflow: hidden
44
45
  text-overflow: ellipsis
46
+ md-autocomplete
47
+ background: none
48
+ md-autocomplete-wrap.md-whiteframe-z1
49
+ box-shadow: none
50
+ button
51
+ display: none
52
+ .autocomplete.menu
53
+ text-align: left
54
+ &:empty
55
+ display: none
56
+ a
57
+ overflow: hidden
58
+ width: 100%
59
+ text-overflow: ellipsis
60
+ display: block
61
+ line-height: 48px
62
+ height: 48px
63
+ font-size: 14px
64
+ white-space: nowrap
65
+ cursor: pointer
66
+ &.active
67
+ font-weight: bolder
68
+ &:hover
69
+ max-height: 30rem
70
+ padding: 0.5rem
71
+ opacity: 1
72
+ z-index: 10
73
+ max-height: 0
74
+ overflow-y: hidden
75
+ overflow-x: hidden
76
+ position: absolute
77
+ background-color: white
78
+ opacity: 0
79
+ border-radius: 0.25rem
80
+ text-overflow: ellipsis
81
+ transition: all 0.55s cubic-bezier(0.25, 0.8, 0.25, 1)
82
+ padding: 0
83
+
84
+ input.autocomplete:focus + div
85
+ max-height: 30rem
86
+ padding: 0.5rem
87
+ opacity: 1
@@ -1,3 +1,3 @@
1
1
  module MaterialRaingular
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.3.1"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: material_raingular
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Moody
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-10-26 00:00:00.000000000 Z
11
+ date: 2015-10-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler