material_raingular 0.0.3 → 0.0.3.1

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 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