materialize-sass 0.100.2 → 0.100.2.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 +5 -5
- data/app/assets/javascripts/materialize/date_picker/picker.date.js +1120 -952
- data/app/assets/javascripts/materialize/date_picker/picker.js +723 -561
- data/app/assets/stylesheets/materialize/components/date_picker/_default.date.scss +43 -30
- data/app/assets/stylesheets/materialize/components/date_picker/_default.scss +7 -3
- data/lib/materialize-sass/version.rb +1 -1
- metadata +3 -4
@@ -1,51 +1,55 @@
|
|
1
1
|
/*!
|
2
|
-
* pickadate.js v3.
|
2
|
+
* pickadate.js v3.6.1, 2019/03/15
|
3
3
|
* By Amsul, http://amsul.ca
|
4
4
|
* Hosted on http://amsul.github.io/pickadate.js
|
5
5
|
* Licensed under MIT
|
6
6
|
*/
|
7
7
|
|
8
|
-
(function (factory) {
|
8
|
+
(function ( factory ) {
|
9
9
|
|
10
|
-
Materialize.Picker = factory(jQuery)
|
11
|
-
})(function
|
10
|
+
Materialize.Picker = factory( jQuery )
|
11
|
+
})(function( $ ) {
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
var $window = $( window )
|
14
|
+
var $document = $( document )
|
15
|
+
var $html = $( document.documentElement )
|
16
|
+
var supportsTransitions = document.documentElement.style.transition != null
|
16
17
|
|
17
|
-
/**
|
18
|
-
* The picker constructor that creates a blank picker.
|
19
|
-
*/
|
20
|
-
function PickerConstructor(ELEMENT, NAME, COMPONENT, OPTIONS) {
|
21
18
|
|
22
|
-
|
23
|
-
|
19
|
+
/**
|
20
|
+
* The picker constructor that creates a blank picker.
|
21
|
+
*/
|
22
|
+
function PickerConstructor( ELEMENT, NAME, COMPONENT, OPTIONS ) {
|
23
|
+
|
24
|
+
// If there’s no element, return the picker constructor.
|
25
|
+
if ( !ELEMENT ) return PickerConstructor
|
26
|
+
|
24
27
|
|
25
|
-
|
28
|
+
var
|
29
|
+
IS_DEFAULT_THEME = false,
|
26
30
|
|
27
31
|
|
28
32
|
// The state of the picker.
|
29
33
|
STATE = {
|
30
|
-
id: ELEMENT.id || 'P' + Math.abs(~~(Math.random() * new Date()))
|
34
|
+
id: ELEMENT.id || 'P' + Math.abs( ~~(Math.random() * new Date()) )
|
31
35
|
},
|
32
36
|
|
33
37
|
|
34
38
|
// Merge the defaults and options passed.
|
35
|
-
SETTINGS = COMPONENT ? $.extend(true, {}, COMPONENT.defaults, OPTIONS) : OPTIONS || {},
|
39
|
+
SETTINGS = COMPONENT ? $.extend( true, {}, COMPONENT.defaults, OPTIONS ) : OPTIONS || {},
|
36
40
|
|
37
41
|
|
38
42
|
// Merge the default classes with the settings classes.
|
39
|
-
CLASSES = $.extend({}, PickerConstructor.klasses(), SETTINGS.klass),
|
43
|
+
CLASSES = $.extend( {}, PickerConstructor.klasses(), SETTINGS.klass ),
|
40
44
|
|
41
45
|
|
42
46
|
// The element node wrapper into a jQuery object.
|
43
|
-
$ELEMENT = $(ELEMENT),
|
47
|
+
$ELEMENT = $( ELEMENT ),
|
44
48
|
|
45
49
|
|
46
50
|
// Pseudo picker constructor.
|
47
|
-
PickerInstance = function
|
48
|
-
return this.start()
|
51
|
+
PickerInstance = function() {
|
52
|
+
return this.start()
|
49
53
|
},
|
50
54
|
|
51
55
|
|
@@ -56,46 +60,66 @@
|
|
56
60
|
|
57
61
|
$node: $ELEMENT,
|
58
62
|
|
63
|
+
|
59
64
|
/**
|
60
65
|
* Initialize everything
|
61
66
|
*/
|
62
|
-
start: function
|
67
|
+
start: function() {
|
63
68
|
|
64
69
|
// If it’s already started, do nothing.
|
65
|
-
if (STATE && STATE.start) return P
|
70
|
+
if ( STATE && STATE.start ) return P
|
71
|
+
|
66
72
|
|
67
73
|
// Update the picker states.
|
68
|
-
STATE.methods = {}
|
69
|
-
STATE.start = true
|
70
|
-
STATE.open = false
|
71
|
-
STATE.type = ELEMENT.type
|
74
|
+
STATE.methods = {}
|
75
|
+
STATE.start = true
|
76
|
+
STATE.open = false
|
77
|
+
STATE.type = ELEMENT.type
|
78
|
+
|
72
79
|
|
73
80
|
// Confirm focus state, convert into text input to remove UA stylings,
|
74
81
|
// and set as readonly to prevent keyboard popup.
|
75
|
-
ELEMENT.autofocus = ELEMENT == getActiveElement()
|
76
|
-
ELEMENT.readOnly = !SETTINGS.editable
|
77
|
-
ELEMENT.id = ELEMENT.id || STATE.id
|
78
|
-
if (ELEMENT.type != 'text') {
|
79
|
-
ELEMENT.type = 'text'
|
82
|
+
ELEMENT.autofocus = ELEMENT == getActiveElement()
|
83
|
+
ELEMENT.readOnly = !SETTINGS.editable
|
84
|
+
ELEMENT.id = ELEMENT.id || STATE.id
|
85
|
+
if ( ELEMENT.type != 'text' ) {
|
86
|
+
ELEMENT.type = 'text'
|
80
87
|
}
|
81
88
|
|
89
|
+
|
82
90
|
// Create a new picker component with the settings.
|
83
|
-
P.component = new COMPONENT(P, SETTINGS)
|
91
|
+
P.component = new COMPONENT(P, SETTINGS)
|
92
|
+
|
93
|
+
|
94
|
+
// Create the picker root and then prepare it.
|
95
|
+
P.$root = $( '<div class="' + CLASSES.picker + '" id="' + ELEMENT.id + '_root" />' )
|
96
|
+
prepareElementRoot()
|
97
|
+
|
98
|
+
|
99
|
+
// Create the picker holder and then prepare it.
|
100
|
+
P.$holder = $( createWrappedComponent() ).appendTo( P.$root )
|
101
|
+
prepareElementHolder()
|
84
102
|
|
85
|
-
// Create the picker root with a holder and then prepare it.
|
86
|
-
P.$root = $(PickerConstructor._.node('div', createWrappedComponent(), CLASSES.picker, 'id="' + ELEMENT.id + '_root" tabindex="0"'));
|
87
|
-
prepareElementRoot();
|
88
103
|
|
89
104
|
// If there’s a format for the hidden input element, create the element.
|
90
|
-
if (SETTINGS.formatSubmit) {
|
91
|
-
prepareElementHidden()
|
105
|
+
if ( SETTINGS.formatSubmit ) {
|
106
|
+
prepareElementHidden()
|
92
107
|
}
|
93
108
|
|
109
|
+
|
94
110
|
// Prepare the input element.
|
95
|
-
prepareElement()
|
111
|
+
prepareElement()
|
112
|
+
|
113
|
+
|
114
|
+
// Insert the hidden input as specified in the settings.
|
115
|
+
if ( SETTINGS.containerHidden ) $( SETTINGS.containerHidden ).append( P._hidden )
|
116
|
+
else $ELEMENT.after( P._hidden )
|
117
|
+
|
96
118
|
|
97
119
|
// Insert the root as specified in the settings.
|
98
|
-
if (SETTINGS.container) $(SETTINGS.container).append(P.$root
|
120
|
+
if ( SETTINGS.container ) $( SETTINGS.container ).append( P.$root )
|
121
|
+
else $ELEMENT.after( P.$root )
|
122
|
+
|
99
123
|
|
100
124
|
// Bind the default component and settings events.
|
101
125
|
P.on({
|
@@ -112,116 +136,126 @@
|
|
112
136
|
open: SETTINGS.onOpen,
|
113
137
|
close: SETTINGS.onClose,
|
114
138
|
set: SETTINGS.onSet
|
115
|
-
})
|
139
|
+
})
|
140
|
+
|
116
141
|
|
117
142
|
// Once we’re all set, check the theme in use.
|
118
|
-
IS_DEFAULT_THEME = isUsingDefaultTheme(P.$
|
143
|
+
IS_DEFAULT_THEME = isUsingDefaultTheme( P.$holder[0] )
|
144
|
+
|
119
145
|
|
120
146
|
// If the element has autofocus, open the picker.
|
121
|
-
if (ELEMENT.autofocus) {
|
122
|
-
P.open()
|
147
|
+
if ( ELEMENT.autofocus ) {
|
148
|
+
P.open()
|
123
149
|
}
|
124
150
|
|
151
|
+
|
125
152
|
// Trigger queued the “start” and “render” events.
|
126
|
-
return P.trigger('start').trigger('render')
|
153
|
+
return P.trigger( 'start' ).trigger( 'render' )
|
127
154
|
}, //start
|
128
155
|
|
129
156
|
|
130
157
|
/**
|
131
158
|
* Render a new picker
|
132
159
|
*/
|
133
|
-
render: function
|
160
|
+
render: function( entireComponent ) {
|
134
161
|
|
135
162
|
// Insert a new component holder in the root or box.
|
136
|
-
if (entireComponent
|
163
|
+
if ( entireComponent ) {
|
164
|
+
P.$holder = $( createWrappedComponent() )
|
165
|
+
prepareElementHolder()
|
166
|
+
P.$root.html( P.$holder )
|
167
|
+
}
|
168
|
+
else P.$root.find( '.' + CLASSES.box ).html( P.component.nodes( STATE.open ) )
|
137
169
|
|
138
170
|
// Trigger the queued “render” events.
|
139
|
-
return P.trigger('render')
|
171
|
+
return P.trigger( 'render' )
|
140
172
|
}, //render
|
141
173
|
|
142
174
|
|
143
175
|
/**
|
144
176
|
* Destroy everything
|
145
177
|
*/
|
146
|
-
stop: function
|
178
|
+
stop: function() {
|
147
179
|
|
148
180
|
// If it’s already stopped, do nothing.
|
149
|
-
if (!STATE.start) return P
|
181
|
+
if ( !STATE.start ) return P
|
150
182
|
|
151
183
|
// Then close the picker.
|
152
|
-
P.close()
|
184
|
+
P.close()
|
153
185
|
|
154
186
|
// Remove the hidden field.
|
155
|
-
if (P._hidden) {
|
156
|
-
P._hidden.parentNode.removeChild(P._hidden)
|
187
|
+
if ( P._hidden ) {
|
188
|
+
P._hidden.parentNode.removeChild( P._hidden )
|
157
189
|
}
|
158
190
|
|
159
191
|
// Remove the root.
|
160
|
-
P.$root.remove()
|
192
|
+
P.$root.remove()
|
161
193
|
|
162
194
|
// Remove the input class, remove the stored data, and unbind
|
163
195
|
// the events (after a tick for IE - see `P.close`).
|
164
|
-
$ELEMENT.removeClass(CLASSES.input).removeData(NAME)
|
165
|
-
setTimeout(function
|
166
|
-
$ELEMENT.off('.' + STATE.id)
|
167
|
-
}, 0)
|
196
|
+
$ELEMENT.removeClass( CLASSES.input ).removeData( NAME )
|
197
|
+
setTimeout( function() {
|
198
|
+
$ELEMENT.off( '.' + STATE.id )
|
199
|
+
}, 0)
|
168
200
|
|
169
201
|
// Restore the element state
|
170
|
-
ELEMENT.type = STATE.type
|
171
|
-
ELEMENT.readOnly = false
|
202
|
+
ELEMENT.type = STATE.type
|
203
|
+
ELEMENT.readOnly = false
|
172
204
|
|
173
205
|
// Trigger the queued “stop” events.
|
174
|
-
P.trigger('stop')
|
206
|
+
P.trigger( 'stop' )
|
175
207
|
|
176
208
|
// Reset the picker states.
|
177
|
-
STATE.methods = {}
|
178
|
-
STATE.start = false
|
209
|
+
STATE.methods = {}
|
210
|
+
STATE.start = false
|
179
211
|
|
180
|
-
return P
|
212
|
+
return P
|
181
213
|
}, //stop
|
182
214
|
|
183
215
|
|
184
216
|
/**
|
185
217
|
* Open up the picker
|
186
218
|
*/
|
187
|
-
open: function
|
219
|
+
open: function( dontGiveFocus ) {
|
188
220
|
|
189
221
|
// If it’s already open, do nothing.
|
190
|
-
if (STATE.open) return P
|
222
|
+
if ( STATE.open ) return P
|
191
223
|
|
192
224
|
// Add the “active” class.
|
193
|
-
$ELEMENT.addClass(CLASSES.active)
|
194
|
-
aria(ELEMENT, 'expanded', true)
|
225
|
+
$ELEMENT.addClass( CLASSES.active )
|
226
|
+
aria( ELEMENT, 'expanded', true )
|
195
227
|
|
196
228
|
// * A Firefox bug, when `html` has `overflow:hidden`, results in
|
197
229
|
// killing transitions :(. So add the “opened” state on the next tick.
|
198
230
|
// Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=625289
|
199
|
-
setTimeout(function
|
231
|
+
setTimeout( function() {
|
200
232
|
|
201
233
|
// Add the “opened” class to the picker root.
|
202
|
-
P.$root.addClass(CLASSES.opened)
|
203
|
-
aria(P.$root[0], 'hidden', false)
|
204
|
-
|
234
|
+
P.$root.addClass( CLASSES.opened )
|
235
|
+
aria( P.$root[0], 'hidden', false )
|
236
|
+
|
237
|
+
}, 0 )
|
205
238
|
|
206
239
|
// If we have to give focus, bind the element and doc events.
|
207
|
-
if (dontGiveFocus !== false) {
|
240
|
+
if ( dontGiveFocus !== false ) {
|
208
241
|
|
209
242
|
// Set it as open.
|
210
|
-
STATE.open = true
|
243
|
+
STATE.open = true
|
211
244
|
|
212
245
|
// Prevent the page from scrolling.
|
213
|
-
if (IS_DEFAULT_THEME) {
|
214
|
-
$
|
246
|
+
if ( IS_DEFAULT_THEME ) {
|
247
|
+
$('body').
|
248
|
+
css( 'overflow', 'hidden' ).
|
249
|
+
css( 'padding-right', '+=' + getScrollbarWidth() )
|
215
250
|
}
|
216
251
|
|
217
252
|
// Pass focus to the root element’s jQuery object.
|
218
|
-
|
219
|
-
P.$root.eq(0).focus();
|
253
|
+
focusPickerOnceOpened()
|
220
254
|
|
221
255
|
// Bind the document events.
|
222
|
-
$document.on('click.' + STATE.id + ' focusin.' + STATE.id, function
|
256
|
+
$document.on( 'click.' + STATE.id + ' focusin.' + STATE.id, function( event ) {
|
223
257
|
|
224
|
-
var target = event
|
258
|
+
var target = getRealEventTarget( event, ELEMENT )
|
225
259
|
|
226
260
|
// If the target of the event is not the element, close the picker picker.
|
227
261
|
// * Don’t worry about clicks or focusins on the root because those don’t bubble up.
|
@@ -230,321 +264,345 @@
|
|
230
264
|
// * In Firefox stopPropagation() doesn’t prevent right-click events from bubbling,
|
231
265
|
// which causes the picker to unexpectedly close when right-clicking it. So make
|
232
266
|
// sure the event wasn’t a right-click.
|
233
|
-
|
267
|
+
// * In Chrome 62 and up, password autofill causes a simulated focusin event which
|
268
|
+
// closes the picker.
|
269
|
+
if ( ! event.isSimulated && target != ELEMENT && target != document && event.which != 3 ) {
|
234
270
|
|
235
271
|
// If the target was the holder that covers the screen,
|
236
272
|
// keep the element focused to maintain tabindex.
|
237
|
-
P.close(target === P.$
|
273
|
+
P.close( target === P.$holder[0] )
|
238
274
|
}
|
239
|
-
}).on('keydown.' + STATE.id, function (event) {
|
240
275
|
|
241
|
-
|
242
|
-
// Get the keycode.
|
243
|
-
keycode = event.keyCode,
|
276
|
+
}).on( 'keydown.' + STATE.id, function( event ) {
|
244
277
|
|
278
|
+
var
|
279
|
+
// Get the keycode.
|
280
|
+
keycode = event.keyCode,
|
245
281
|
|
246
|
-
|
247
|
-
|
282
|
+
// Translate that to a selection change.
|
283
|
+
keycodeToMove = P.component.key[ keycode ],
|
248
284
|
|
285
|
+
// Grab the target.
|
286
|
+
target = getRealEventTarget( event, ELEMENT )
|
249
287
|
|
250
|
-
// Grab the target.
|
251
|
-
target = event.target;
|
252
288
|
|
253
289
|
// On escape, close the picker and give focus.
|
254
|
-
if (keycode == 27) {
|
255
|
-
P.close(true)
|
290
|
+
if ( keycode == 27 ) {
|
291
|
+
P.close( true )
|
256
292
|
}
|
257
293
|
|
258
|
-
// Check if there is a key movement or “enter” keypress on the element.
|
259
|
-
else if (target == P.$root[0] && (keycodeToMove || keycode == 13)) {
|
260
294
|
|
261
|
-
|
262
|
-
|
295
|
+
// Check if there is a key movement or “enter” keypress on the element.
|
296
|
+
else if ( target == P.$holder[0] && ( keycodeToMove || keycode == 13 ) ) {
|
263
297
|
|
264
|
-
|
265
|
-
|
266
|
-
PickerConstructor._.trigger(P.component.key.go, P, [PickerConstructor._.trigger(keycodeToMove)]);
|
267
|
-
}
|
298
|
+
// Prevent the default action to stop page movement.
|
299
|
+
event.preventDefault()
|
268
300
|
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
if (SETTINGS.closeOnSelect) {
|
273
|
-
P.close(true);
|
274
|
-
}
|
275
|
-
}
|
301
|
+
// Trigger the key movement action.
|
302
|
+
if ( keycodeToMove ) {
|
303
|
+
PickerConstructor._.trigger( P.component.key.go, P, [ PickerConstructor._.trigger( keycodeToMove ) ] )
|
276
304
|
}
|
277
305
|
|
278
|
-
//
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
306
|
+
// On “enter”, if the highlighted item isn’t disabled, set the value and close.
|
307
|
+
else if ( !P.$root.find( '.' + CLASSES.highlighted ).hasClass( CLASSES.disabled ) ) {
|
308
|
+
P.set( 'select', P.component.item.highlight )
|
309
|
+
if ( SETTINGS.closeOnSelect ) {
|
310
|
+
P.close( true )
|
283
311
|
}
|
284
|
-
|
312
|
+
}
|
313
|
+
}
|
314
|
+
|
315
|
+
|
316
|
+
// If the target is within the root and “enter” is pressed,
|
317
|
+
// prevent the default action and trigger a click on the target instead.
|
318
|
+
else if ( $.contains( P.$root[0], target ) && keycode == 13 ) {
|
319
|
+
event.preventDefault()
|
320
|
+
target.click()
|
321
|
+
}
|
322
|
+
})
|
285
323
|
}
|
286
324
|
|
287
325
|
// Trigger the queued “open” events.
|
288
|
-
return P.trigger('open')
|
326
|
+
return P.trigger( 'open' )
|
289
327
|
}, //open
|
290
328
|
|
291
329
|
|
292
330
|
/**
|
293
331
|
* Close the picker
|
294
332
|
*/
|
295
|
-
close: function
|
333
|
+
close: function( giveFocus ) {
|
296
334
|
|
297
335
|
// If we need to give focus, do it before changing states.
|
298
|
-
if (giveFocus) {
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
336
|
+
if ( giveFocus ) {
|
337
|
+
if ( SETTINGS.editable ) {
|
338
|
+
ELEMENT.focus()
|
339
|
+
}
|
340
|
+
else {
|
341
|
+
// ....ah yes! It would’ve been incomplete without a crazy workaround for IE :|
|
342
|
+
// The focus is triggered *after* the close has completed - causing it
|
343
|
+
// to open again. So unbind and rebind the event at the next tick.
|
344
|
+
P.$holder.off( 'focus.toOpen' ).focus()
|
345
|
+
setTimeout( function() {
|
346
|
+
P.$holder.on( 'focus.toOpen', handleFocusToOpenEvent )
|
347
|
+
}, 0 )
|
348
|
+
}
|
306
349
|
}
|
307
350
|
|
308
351
|
// Remove the “active” class.
|
309
|
-
$ELEMENT.removeClass(CLASSES.active)
|
310
|
-
aria(ELEMENT, 'expanded', false)
|
352
|
+
$ELEMENT.removeClass( CLASSES.active )
|
353
|
+
aria( ELEMENT, 'expanded', false )
|
311
354
|
|
312
355
|
// * A Firefox bug, when `html` has `overflow:hidden`, results in
|
313
356
|
// killing transitions :(. So remove the “opened” state on the next tick.
|
314
357
|
// Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=625289
|
315
|
-
setTimeout(function
|
358
|
+
setTimeout( function() {
|
316
359
|
|
317
360
|
// Remove the “opened” and “focused” class from the picker root.
|
318
|
-
P.$root.removeClass(CLASSES.opened + ' ' + CLASSES.focused)
|
319
|
-
aria(P.$root[0], 'hidden', true)
|
320
|
-
|
361
|
+
P.$root.removeClass( CLASSES.opened + ' ' + CLASSES.focused )
|
362
|
+
aria( P.$root[0], 'hidden', true )
|
363
|
+
|
364
|
+
}, 0 )
|
321
365
|
|
322
366
|
// If it’s already closed, do nothing more.
|
323
|
-
if (!STATE.open) return P
|
367
|
+
if ( !STATE.open ) return P
|
324
368
|
|
325
369
|
// Set it as closed.
|
326
|
-
STATE.open = false
|
370
|
+
STATE.open = false
|
327
371
|
|
328
372
|
// Allow the page to scroll.
|
329
|
-
if (IS_DEFAULT_THEME) {
|
330
|
-
$
|
373
|
+
if ( IS_DEFAULT_THEME ) {
|
374
|
+
$('body').
|
375
|
+
css( 'overflow', '' ).
|
376
|
+
css( 'padding-right', '-=' + getScrollbarWidth() )
|
331
377
|
}
|
332
378
|
|
333
379
|
// Unbind the document events.
|
334
|
-
$document.off('.' + STATE.id)
|
380
|
+
$document.off( '.' + STATE.id )
|
335
381
|
|
336
382
|
// Trigger the queued “close” events.
|
337
|
-
return P.trigger('close')
|
383
|
+
return P.trigger( 'close' )
|
338
384
|
}, //close
|
339
385
|
|
340
386
|
|
341
387
|
/**
|
342
388
|
* Clear the values
|
343
389
|
*/
|
344
|
-
clear: function
|
345
|
-
return P.set('clear', null, options)
|
390
|
+
clear: function( options ) {
|
391
|
+
return P.set( 'clear', null, options )
|
346
392
|
}, //clear
|
347
393
|
|
348
394
|
|
349
395
|
/**
|
350
396
|
* Set something
|
351
397
|
*/
|
352
|
-
set: function
|
398
|
+
set: function( thing, value, options ) {
|
353
399
|
|
354
|
-
var thingItem,
|
355
|
-
|
356
|
-
|
357
|
-
thingObject = thingIsObject ? thing : {};
|
400
|
+
var thingItem, thingValue,
|
401
|
+
thingIsObject = $.isPlainObject( thing ),
|
402
|
+
thingObject = thingIsObject ? thing : {}
|
358
403
|
|
359
404
|
// Make sure we have usable options.
|
360
|
-
options = thingIsObject && $.isPlainObject(value) ? value : options || {}
|
405
|
+
options = thingIsObject && $.isPlainObject( value ) ? value : options || {}
|
361
406
|
|
362
|
-
if (thing) {
|
407
|
+
if ( thing ) {
|
363
408
|
|
364
409
|
// If the thing isn’t an object, make it one.
|
365
|
-
if (!thingIsObject) {
|
366
|
-
thingObject[thing] = value
|
410
|
+
if ( !thingIsObject ) {
|
411
|
+
thingObject[ thing ] = value
|
367
412
|
}
|
368
413
|
|
369
414
|
// Go through the things of items to set.
|
370
|
-
for (thingItem in thingObject) {
|
415
|
+
for ( thingItem in thingObject ) {
|
371
416
|
|
372
417
|
// Grab the value of the thing.
|
373
|
-
thingValue = thingObject[thingItem]
|
418
|
+
thingValue = thingObject[ thingItem ]
|
374
419
|
|
375
420
|
// First, if the item exists and there’s a value, set it.
|
376
|
-
if (thingItem in P.component.item) {
|
377
|
-
if (thingValue === undefined) thingValue = null
|
378
|
-
P.component.set(thingItem, thingValue, options)
|
421
|
+
if ( thingItem in P.component.item ) {
|
422
|
+
if ( thingValue === undefined ) thingValue = null
|
423
|
+
P.component.set( thingItem, thingValue, options )
|
379
424
|
}
|
380
425
|
|
381
426
|
// Then, check to update the element value and broadcast a change.
|
382
|
-
if (thingItem == 'select' || thingItem == 'clear') {
|
383
|
-
$ELEMENT.
|
427
|
+
if ( ( thingItem == 'select' || thingItem == 'clear' ) && SETTINGS.updateInput ) {
|
428
|
+
$ELEMENT.
|
429
|
+
val( thingItem == 'clear' ? '' : P.get( thingItem, SETTINGS.format ) ).
|
430
|
+
trigger( 'change' )
|
384
431
|
}
|
385
432
|
}
|
386
433
|
|
387
434
|
// Render a new picker.
|
388
|
-
P.render()
|
435
|
+
P.render()
|
389
436
|
}
|
390
437
|
|
391
438
|
// When the method isn’t muted, trigger queued “set” events and pass the `thingObject`.
|
392
|
-
return options.muted ? P : P.trigger('set', thingObject)
|
439
|
+
return options.muted ? P : P.trigger( 'set', thingObject )
|
393
440
|
}, //set
|
394
441
|
|
395
442
|
|
396
443
|
/**
|
397
444
|
* Get something
|
398
445
|
*/
|
399
|
-
get: function
|
446
|
+
get: function( thing, format ) {
|
400
447
|
|
401
448
|
// Make sure there’s something to get.
|
402
|
-
thing = thing || 'value'
|
449
|
+
thing = thing || 'value'
|
403
450
|
|
404
451
|
// If a picker state exists, return that.
|
405
|
-
if (STATE[thing] != null) {
|
406
|
-
return STATE[thing]
|
452
|
+
if ( STATE[ thing ] != null ) {
|
453
|
+
return STATE[ thing ]
|
407
454
|
}
|
408
455
|
|
409
456
|
// Return the submission value, if that.
|
410
|
-
if (thing == 'valueSubmit') {
|
411
|
-
if (P._hidden) {
|
412
|
-
return P._hidden.value
|
457
|
+
if ( thing == 'valueSubmit' ) {
|
458
|
+
if ( P._hidden ) {
|
459
|
+
return P._hidden.value
|
413
460
|
}
|
414
|
-
thing = 'value'
|
461
|
+
thing = 'value'
|
415
462
|
}
|
416
463
|
|
417
464
|
// Return the value, if that.
|
418
|
-
if (thing == 'value') {
|
419
|
-
return ELEMENT.value
|
465
|
+
if ( thing == 'value' ) {
|
466
|
+
return ELEMENT.value
|
420
467
|
}
|
421
468
|
|
422
469
|
// Check if a component item exists, return that.
|
423
|
-
if (thing in P.component.item) {
|
424
|
-
if (typeof format == 'string') {
|
425
|
-
var thingValue = P.component.get(thing)
|
426
|
-
return thingValue ?
|
470
|
+
if ( thing in P.component.item ) {
|
471
|
+
if ( typeof format == 'string' ) {
|
472
|
+
var thingValue = P.component.get( thing )
|
473
|
+
return thingValue ?
|
474
|
+
PickerConstructor._.trigger(
|
475
|
+
P.component.formats.toString,
|
476
|
+
P.component,
|
477
|
+
[ format, thingValue ]
|
478
|
+
) : ''
|
427
479
|
}
|
428
|
-
return P.component.get(thing)
|
480
|
+
return P.component.get( thing )
|
429
481
|
}
|
430
482
|
}, //get
|
431
483
|
|
432
484
|
|
485
|
+
|
433
486
|
/**
|
434
487
|
* Bind events on the things.
|
435
488
|
*/
|
436
|
-
on: function
|
489
|
+
on: function( thing, method, internal ) {
|
437
490
|
|
438
|
-
var thingName,
|
439
|
-
|
440
|
-
|
441
|
-
thingObject = thingIsObject ? thing : {};
|
491
|
+
var thingName, thingMethod,
|
492
|
+
thingIsObject = $.isPlainObject( thing ),
|
493
|
+
thingObject = thingIsObject ? thing : {}
|
442
494
|
|
443
|
-
if (thing) {
|
495
|
+
if ( thing ) {
|
444
496
|
|
445
497
|
// If the thing isn’t an object, make it one.
|
446
|
-
if (!thingIsObject) {
|
447
|
-
thingObject[thing] = method
|
498
|
+
if ( !thingIsObject ) {
|
499
|
+
thingObject[ thing ] = method
|
448
500
|
}
|
449
501
|
|
450
502
|
// Go through the things to bind to.
|
451
|
-
for (thingName in thingObject) {
|
503
|
+
for ( thingName in thingObject ) {
|
452
504
|
|
453
505
|
// Grab the method of the thing.
|
454
|
-
thingMethod = thingObject[thingName]
|
506
|
+
thingMethod = thingObject[ thingName ]
|
455
507
|
|
456
508
|
// If it was an internal binding, prefix it.
|
457
|
-
if (internal) {
|
458
|
-
thingName = '_' + thingName
|
509
|
+
if ( internal ) {
|
510
|
+
thingName = '_' + thingName
|
459
511
|
}
|
460
512
|
|
461
513
|
// Make sure the thing methods collection exists.
|
462
|
-
STATE.methods[thingName] = STATE.methods[thingName] || []
|
514
|
+
STATE.methods[ thingName ] = STATE.methods[ thingName ] || []
|
463
515
|
|
464
516
|
// Add the method to the relative method collection.
|
465
|
-
STATE.methods[thingName].push(thingMethod)
|
517
|
+
STATE.methods[ thingName ].push( thingMethod )
|
466
518
|
}
|
467
519
|
}
|
468
520
|
|
469
|
-
return P
|
521
|
+
return P
|
470
522
|
}, //on
|
471
523
|
|
472
524
|
|
525
|
+
|
473
526
|
/**
|
474
527
|
* Unbind events on the things.
|
475
528
|
*/
|
476
|
-
off: function
|
477
|
-
var i,
|
478
|
-
thingName,
|
529
|
+
off: function() {
|
530
|
+
var i, thingName,
|
479
531
|
names = arguments;
|
480
|
-
for (i = 0, namesCount = names.length; i < namesCount; i += 1) {
|
481
|
-
thingName = names[i]
|
482
|
-
if (thingName in STATE.methods) {
|
483
|
-
delete STATE.methods[thingName]
|
532
|
+
for ( i = 0, namesCount = names.length; i < namesCount; i += 1 ) {
|
533
|
+
thingName = names[i]
|
534
|
+
if ( thingName in STATE.methods ) {
|
535
|
+
delete STATE.methods[thingName]
|
484
536
|
}
|
485
537
|
}
|
486
|
-
return P
|
538
|
+
return P
|
487
539
|
},
|
488
540
|
|
541
|
+
|
489
542
|
/**
|
490
543
|
* Fire off method events.
|
491
544
|
*/
|
492
|
-
trigger: function
|
493
|
-
var _trigger = function
|
494
|
-
var methodList = STATE.methods[name]
|
495
|
-
if (methodList) {
|
496
|
-
methodList.map(function
|
497
|
-
PickerConstructor._.trigger(method, P, [data])
|
498
|
-
})
|
545
|
+
trigger: function( name, data ) {
|
546
|
+
var _trigger = function( name ) {
|
547
|
+
var methodList = STATE.methods[ name ]
|
548
|
+
if ( methodList ) {
|
549
|
+
methodList.map( function( method ) {
|
550
|
+
PickerConstructor._.trigger( method, P, [ data ] )
|
551
|
+
})
|
499
552
|
}
|
500
|
-
}
|
501
|
-
_trigger('_' + name)
|
502
|
-
_trigger(name)
|
503
|
-
return P
|
553
|
+
}
|
554
|
+
_trigger( '_' + name )
|
555
|
+
_trigger( name )
|
556
|
+
return P
|
504
557
|
} //trigger
|
505
|
-
|
558
|
+
} //PickerInstance.prototype
|
506
559
|
|
507
560
|
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
561
|
+
/**
|
562
|
+
* Wrap the picker holder components together.
|
563
|
+
*/
|
564
|
+
function createWrappedComponent() {
|
512
565
|
|
513
|
-
|
514
|
-
|
566
|
+
// Create a picker wrapper holder
|
567
|
+
return PickerConstructor._.node( 'div',
|
515
568
|
|
516
569
|
// Create a picker wrapper node
|
517
|
-
PickerConstructor._.node('div',
|
570
|
+
PickerConstructor._.node( 'div',
|
518
571
|
|
519
|
-
|
520
|
-
|
572
|
+
// Create a picker frame
|
573
|
+
PickerConstructor._.node( 'div',
|
521
574
|
|
522
|
-
|
523
|
-
|
575
|
+
// Create a picker box node
|
576
|
+
PickerConstructor._.node( 'div',
|
524
577
|
|
525
|
-
|
526
|
-
|
578
|
+
// Create the components nodes.
|
579
|
+
P.component.nodes( STATE.open ),
|
527
580
|
|
528
|
-
|
529
|
-
|
581
|
+
// The picker box class
|
582
|
+
CLASSES.box
|
583
|
+
),
|
530
584
|
|
531
|
-
|
532
|
-
|
585
|
+
// Picker wrap class
|
586
|
+
CLASSES.wrap
|
587
|
+
),
|
533
588
|
|
534
|
-
|
535
|
-
|
589
|
+
// Picker frame class
|
590
|
+
CLASSES.frame
|
591
|
+
),
|
536
592
|
|
537
593
|
// Picker holder class
|
538
|
-
CLASSES.holder
|
539
|
-
} //createWrappedComponent
|
594
|
+
CLASSES.holder,
|
540
595
|
|
596
|
+
'tabindex="-1"'
|
597
|
+
) //endreturn
|
598
|
+
} //createWrappedComponent
|
541
599
|
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
600
|
+
/**
|
601
|
+
* Prepare the input element with all bindings.
|
602
|
+
*/
|
603
|
+
function prepareElement() {
|
546
604
|
|
547
|
-
|
605
|
+
$ELEMENT.
|
548
606
|
|
549
607
|
// Store the picker data by component name.
|
550
608
|
data(NAME, P).
|
@@ -552,483 +610,587 @@
|
|
552
610
|
// Add the “input” class name.
|
553
611
|
addClass(CLASSES.input).
|
554
612
|
|
555
|
-
// Remove the tabindex.
|
556
|
-
attr('tabindex', -1).
|
557
|
-
|
558
613
|
// If there’s a `data-value`, update the value of the element.
|
559
|
-
val($ELEMENT.data('value') ?
|
614
|
+
val( $ELEMENT.data('value') ?
|
615
|
+
P.get('select', SETTINGS.format) :
|
616
|
+
ELEMENT.value
|
617
|
+
).
|
560
618
|
|
561
|
-
//
|
562
|
-
|
619
|
+
// On focus/click, open the picker.
|
620
|
+
on( 'focus.' + STATE.id + ' click.' + STATE.id,
|
621
|
+
debounce(function(event) {
|
622
|
+
event.preventDefault()
|
623
|
+
P.open()
|
624
|
+
}, 50))
|
563
625
|
|
564
|
-
|
626
|
+
// Only bind keydown events if the element isn’t editable.
|
627
|
+
if ( !SETTINGS.editable ) {
|
565
628
|
|
566
|
-
|
567
|
-
on('focus.' + STATE.id + ' click.' + STATE.id, function (event) {
|
568
|
-
event.preventDefault();
|
569
|
-
P.$root.eq(0).focus();
|
570
|
-
}).
|
629
|
+
$ELEMENT.
|
571
630
|
|
572
631
|
// Handle keyboard event based on the picker being opened or not.
|
573
|
-
on('keydown.' + STATE.id, handleKeydownEvent)
|
574
|
-
}
|
575
|
-
|
576
|
-
// Update the aria attributes.
|
577
|
-
aria(ELEMENT, {
|
578
|
-
haspopup: true,
|
579
|
-
expanded: false,
|
580
|
-
readonly: false,
|
581
|
-
owns: ELEMENT.id + '_root'
|
582
|
-
});
|
632
|
+
on( 'keydown.' + STATE.id, handleKeydownEvent )
|
583
633
|
}
|
584
634
|
|
585
|
-
/**
|
586
|
-
* Prepare the root picker element with all bindings.
|
587
|
-
*/
|
588
|
-
function prepareElementRoot() {
|
589
635
|
|
590
|
-
|
636
|
+
// Update the aria attributes.
|
637
|
+
aria(ELEMENT, {
|
638
|
+
haspopup: true,
|
639
|
+
expanded: false,
|
640
|
+
readonly: false,
|
641
|
+
owns: ELEMENT.id + '_root'
|
642
|
+
})
|
643
|
+
}
|
644
|
+
|
645
|
+
|
646
|
+
/**
|
647
|
+
* Prepare the root picker element with all bindings.
|
648
|
+
*/
|
649
|
+
function prepareElementRoot() {
|
650
|
+
aria( P.$root[0], 'hidden', true )
|
651
|
+
}
|
652
|
+
|
653
|
+
|
654
|
+
/**
|
655
|
+
* Prepare the holder picker element with all bindings.
|
656
|
+
*/
|
657
|
+
function prepareElementHolder() {
|
658
|
+
|
659
|
+
P.$holder.
|
660
|
+
|
661
|
+
on({
|
591
662
|
|
592
663
|
// For iOS8.
|
593
664
|
keydown: handleKeydownEvent,
|
594
665
|
|
595
|
-
|
666
|
+
'focus.toOpen': handleFocusToOpenEvent,
|
667
|
+
|
668
|
+
blur: function() {
|
669
|
+
// Remove the “target” class.
|
670
|
+
$ELEMENT.removeClass( CLASSES.target )
|
671
|
+
},
|
672
|
+
|
673
|
+
// When something within the holder is focused, stop from bubbling
|
596
674
|
// to the doc and remove the “focused” state from the root.
|
597
|
-
focusin: function
|
598
|
-
P.$root.removeClass(CLASSES.focused)
|
599
|
-
event.stopPropagation()
|
675
|
+
focusin: function( event ) {
|
676
|
+
P.$root.removeClass( CLASSES.focused )
|
677
|
+
event.stopPropagation()
|
600
678
|
},
|
601
679
|
|
602
|
-
// When something within the
|
680
|
+
// When something within the holder is clicked, stop it
|
603
681
|
// from bubbling to the doc.
|
604
|
-
'mousedown click': function
|
682
|
+
'mousedown click': function( event ) {
|
605
683
|
|
606
|
-
var target = event
|
684
|
+
var target = getRealEventTarget( event, ELEMENT )
|
607
685
|
|
608
686
|
// Make sure the target isn’t the root holder so it can bubble up.
|
609
|
-
if (target != P.$
|
687
|
+
if ( target != P.$holder[0] ) {
|
610
688
|
|
611
|
-
event.stopPropagation()
|
689
|
+
event.stopPropagation()
|
612
690
|
|
613
691
|
// * For mousedown events, cancel the default action in order to
|
614
692
|
// prevent cases where focus is shifted onto external elements
|
615
693
|
// when using things like jQuery mobile or MagnificPopup (ref: #249 & #120).
|
616
694
|
// Also, for Firefox, don’t prevent action on the `option` element.
|
617
|
-
if (event.type == 'mousedown' && !$(target).is('input, select, textarea, button, option')) {
|
695
|
+
if ( event.type == 'mousedown' && !$( target ).is( 'input, select, textarea, button, option' )) {
|
618
696
|
|
619
|
-
event.preventDefault()
|
697
|
+
event.preventDefault()
|
620
698
|
|
621
|
-
// Re-focus onto the
|
699
|
+
// Re-focus onto the holder so that users can click away
|
622
700
|
// from elements focused within the picker.
|
623
|
-
P.$
|
701
|
+
P.$holder.eq(0).focus()
|
624
702
|
}
|
625
703
|
}
|
626
704
|
}
|
627
|
-
}).
|
628
705
|
|
629
|
-
// Add/remove the “target” class on focus and blur.
|
630
|
-
on({
|
631
|
-
focus: function () {
|
632
|
-
$ELEMENT.addClass(CLASSES.target);
|
633
|
-
},
|
634
|
-
blur: function () {
|
635
|
-
$ELEMENT.removeClass(CLASSES.target);
|
636
|
-
}
|
637
706
|
}).
|
638
707
|
|
639
|
-
// Open the picker and adjust the root “focused” state
|
640
|
-
on('focus.toOpen', handleFocusToOpenEvent).
|
641
|
-
|
642
708
|
// If there’s a click on an actionable element, carry out the actions.
|
643
|
-
on('click', '[data-pick], [data-nav], [data-clear], [data-close]', function
|
709
|
+
on( 'click', '[data-pick], [data-nav], [data-clear], [data-close]', function() {
|
644
710
|
|
645
|
-
var $target = $(this),
|
711
|
+
var $target = $( this ),
|
646
712
|
targetData = $target.data(),
|
647
|
-
targetDisabled = $target.hasClass(CLASSES.navDisabled) || $target.hasClass(CLASSES.disabled),
|
648
|
-
|
713
|
+
targetDisabled = $target.hasClass( CLASSES.navDisabled ) || $target.hasClass( CLASSES.disabled ),
|
649
714
|
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
715
|
+
// * For IE, non-focusable elements can be active elements as well
|
716
|
+
// (http://stackoverflow.com/a/2684561).
|
717
|
+
activeElement = getActiveElement()
|
718
|
+
activeElement = activeElement && ( (activeElement.type || activeElement.href ) ? activeElement : null);
|
654
719
|
|
655
720
|
// If it’s disabled or nothing inside is actively focused, re-focus the element.
|
656
|
-
if (targetDisabled || activeElement && !$.contains(P.$root[0], activeElement)) {
|
657
|
-
P.$
|
721
|
+
if ( targetDisabled || activeElement && !$.contains( P.$root[0], activeElement ) ) {
|
722
|
+
P.$holder.eq(0).focus()
|
658
723
|
}
|
659
724
|
|
660
725
|
// If something is superficially changed, update the `highlight` based on the `nav`.
|
661
|
-
if (!targetDisabled && targetData.nav) {
|
662
|
-
P.set('highlight', P.component.item.highlight, { nav: targetData.nav })
|
726
|
+
if ( !targetDisabled && targetData.nav ) {
|
727
|
+
P.set( 'highlight', P.component.item.highlight, { nav: targetData.nav } )
|
663
728
|
}
|
664
729
|
|
665
730
|
// If something is picked, set `select` then close with focus.
|
666
|
-
else if (!targetDisabled && 'pick' in targetData) {
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
}
|
731
|
+
else if ( !targetDisabled && 'pick' in targetData ) {
|
732
|
+
P.set( 'select', targetData.pick )
|
733
|
+
if ( SETTINGS.closeOnSelect ) {
|
734
|
+
P.close( true )
|
671
735
|
}
|
736
|
+
}
|
672
737
|
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
P.close(true);
|
681
|
-
}
|
682
|
-
}); //P.$root
|
738
|
+
// If a “clear” button is pressed, empty the values and close with focus.
|
739
|
+
else if ( targetData.clear ) {
|
740
|
+
P.clear()
|
741
|
+
if ( SETTINGS.closeOnClear ) {
|
742
|
+
P.close( true )
|
743
|
+
}
|
744
|
+
}
|
683
745
|
|
684
|
-
|
685
|
-
|
746
|
+
else if ( targetData.close ) {
|
747
|
+
P.close( true )
|
748
|
+
}
|
749
|
+
|
750
|
+
}) //P.$holder
|
686
751
|
|
687
|
-
|
688
|
-
* Prepare the hidden input element along with all bindings.
|
689
|
-
*/
|
690
|
-
function prepareElementHidden() {
|
752
|
+
}
|
691
753
|
|
692
|
-
var name;
|
693
754
|
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
name = [typeof SETTINGS.hiddenPrefix == 'string' ? SETTINGS.hiddenPrefix : '', typeof SETTINGS.hiddenSuffix == 'string' ? SETTINGS.hiddenSuffix : '_submit'];
|
699
|
-
name = name[0] + ELEMENT.name + name[1];
|
700
|
-
}
|
755
|
+
/**
|
756
|
+
* Prepare the hidden input element along with all bindings.
|
757
|
+
*/
|
758
|
+
function prepareElementHidden() {
|
701
759
|
|
702
|
-
|
760
|
+
var name
|
761
|
+
|
762
|
+
if ( SETTINGS.hiddenName === true ) {
|
763
|
+
name = ELEMENT.name
|
764
|
+
ELEMENT.name = ''
|
765
|
+
}
|
766
|
+
else {
|
767
|
+
name = [
|
768
|
+
typeof SETTINGS.hiddenPrefix == 'string' ? SETTINGS.hiddenPrefix : '',
|
769
|
+
typeof SETTINGS.hiddenSuffix == 'string' ? SETTINGS.hiddenSuffix : '_submit'
|
770
|
+
]
|
771
|
+
name = name[0] + ELEMENT.name + name[1]
|
772
|
+
}
|
773
|
+
|
774
|
+
P._hidden = $(
|
775
|
+
'<input ' +
|
776
|
+
'type=hidden ' +
|
703
777
|
|
704
778
|
// Create the name using the original input’s with a prefix and suffix.
|
705
|
-
'name="' + name + '"' +
|
779
|
+
'name="' + name + '"' +
|
706
780
|
|
707
781
|
// If the element has a value, set the hidden value as well.
|
708
|
-
|
782
|
+
(
|
783
|
+
$ELEMENT.data('value') || ELEMENT.value ?
|
784
|
+
' value="' + P.get('select', SETTINGS.formatSubmit) + '"' :
|
785
|
+
''
|
786
|
+
) +
|
787
|
+
'>'
|
788
|
+
)[0]
|
709
789
|
|
710
|
-
|
790
|
+
$ELEMENT.
|
711
791
|
|
712
792
|
// If the value changes, update the hidden input with the correct format.
|
713
|
-
on('change.' + STATE.id, function
|
714
|
-
P._hidden.value = ELEMENT.value ?
|
715
|
-
|
793
|
+
on('change.' + STATE.id, function() {
|
794
|
+
P._hidden.value = ELEMENT.value ?
|
795
|
+
P.get('select', SETTINGS.formatSubmit) :
|
796
|
+
''
|
797
|
+
})
|
798
|
+
}
|
799
|
+
|
716
800
|
|
717
|
-
|
718
|
-
|
801
|
+
// Wait for transitions to end before focusing the holder. Otherwise, while
|
802
|
+
// using the `container` option, the view jumps to the container.
|
803
|
+
function focusPickerOnceOpened() {
|
804
|
+
|
805
|
+
if (IS_DEFAULT_THEME && supportsTransitions) {
|
806
|
+
P.$holder.find('.' + CLASSES.frame).one('transitionend', function() {
|
807
|
+
P.$holder.eq(0).focus()
|
808
|
+
})
|
809
|
+
}
|
810
|
+
else {
|
811
|
+
setTimeout(function() {
|
812
|
+
P.$holder.eq(0).focus()
|
813
|
+
}, 0)
|
719
814
|
}
|
815
|
+
}
|
816
|
+
|
817
|
+
|
818
|
+
function handleFocusToOpenEvent(event) {
|
720
819
|
|
721
|
-
//
|
722
|
-
|
820
|
+
// Stop the event from propagating to the doc.
|
821
|
+
event.stopPropagation()
|
723
822
|
|
724
|
-
|
823
|
+
// Add the “target” class.
|
824
|
+
$ELEMENT.addClass( CLASSES.target )
|
725
825
|
|
826
|
+
// Add the “focused” class to the root.
|
827
|
+
P.$root.addClass( CLASSES.focused )
|
828
|
+
|
829
|
+
// And then finally open the picker.
|
830
|
+
P.open()
|
831
|
+
}
|
832
|
+
|
833
|
+
|
834
|
+
// For iOS8.
|
835
|
+
function handleKeydownEvent( event ) {
|
836
|
+
|
837
|
+
var keycode = event.keyCode,
|
726
838
|
|
727
839
|
// Check if one of the delete keys was pressed.
|
728
|
-
isKeycodeDelete = /^(8|46)$/.test(keycode)
|
840
|
+
isKeycodeDelete = /^(8|46)$/.test(keycode)
|
729
841
|
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
842
|
+
// For some reason IE clears the input value on “escape”.
|
843
|
+
if ( keycode == 27 ) {
|
844
|
+
P.close( true )
|
845
|
+
return false
|
846
|
+
}
|
735
847
|
|
736
|
-
|
737
|
-
|
848
|
+
// Check if `space` or `delete` was pressed or the picker is closed with a key movement.
|
849
|
+
if ( keycode == 32 || isKeycodeDelete || !STATE.open && P.component.key[keycode] ) {
|
738
850
|
|
739
|
-
|
740
|
-
|
741
|
-
|
851
|
+
// Prevent it from moving the page and bubbling to doc.
|
852
|
+
event.preventDefault()
|
853
|
+
event.stopPropagation()
|
742
854
|
|
743
|
-
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
} else {
|
748
|
-
P.open();
|
749
|
-
}
|
750
|
-
}
|
855
|
+
// If `delete` was pressed, clear the values and close the picker.
|
856
|
+
// Otherwise open the picker.
|
857
|
+
if ( isKeycodeDelete ) { P.clear().close() }
|
858
|
+
else { P.open() }
|
751
859
|
}
|
860
|
+
}
|
752
861
|
|
753
|
-
// Separated for IE
|
754
|
-
function handleFocusToOpenEvent(event) {
|
755
862
|
|
756
|
-
|
757
|
-
|
863
|
+
// Return a new picker instance.
|
864
|
+
return new PickerInstance()
|
865
|
+
} //PickerConstructor
|
758
866
|
|
759
|
-
// If it’s a focus event, add the “focused” class to the root.
|
760
|
-
if (event.type == 'focus') {
|
761
|
-
P.$root.addClass(CLASSES.focused);
|
762
|
-
}
|
763
867
|
|
764
|
-
// And then finally open the picker.
|
765
|
-
P.open();
|
766
|
-
}
|
767
868
|
|
768
|
-
|
769
|
-
|
770
|
-
|
869
|
+
/**
|
870
|
+
* The default classes and prefix to use for the HTML classes.
|
871
|
+
*/
|
872
|
+
PickerConstructor.klasses = function( prefix ) {
|
873
|
+
prefix = prefix || 'picker'
|
874
|
+
return {
|
771
875
|
|
876
|
+
picker: prefix,
|
877
|
+
opened: prefix + '--opened',
|
878
|
+
focused: prefix + '--focused',
|
772
879
|
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
PickerConstructor.klasses = function (prefix) {
|
777
|
-
prefix = prefix || 'picker';
|
778
|
-
return {
|
880
|
+
input: prefix + '__input',
|
881
|
+
active: prefix + '__input--active',
|
882
|
+
target: prefix + '__input--target',
|
779
883
|
|
780
|
-
|
781
|
-
opened: prefix + '--opened',
|
782
|
-
focused: prefix + '--focused',
|
884
|
+
holder: prefix + '__holder',
|
783
885
|
|
784
|
-
|
785
|
-
|
786
|
-
target: prefix + '__input--target',
|
886
|
+
frame: prefix + '__frame',
|
887
|
+
wrap: prefix + '__wrap',
|
787
888
|
|
788
|
-
|
889
|
+
box: prefix + '__box'
|
890
|
+
}
|
891
|
+
} //PickerConstructor.klasses
|
789
892
|
|
790
|
-
frame: prefix + '__frame',
|
791
|
-
wrap: prefix + '__wrap',
|
792
893
|
|
793
|
-
box: prefix + '__box'
|
794
|
-
};
|
795
|
-
}; //PickerConstructor.klasses
|
796
894
|
|
895
|
+
/**
|
896
|
+
* Check if the default theme is being used.
|
897
|
+
*/
|
898
|
+
function isUsingDefaultTheme( element ) {
|
797
899
|
|
798
|
-
|
799
|
-
|
800
|
-
*/
|
801
|
-
function isUsingDefaultTheme(element) {
|
900
|
+
var theme,
|
901
|
+
prop = 'position'
|
802
902
|
|
803
|
-
|
804
|
-
|
903
|
+
// For IE.
|
904
|
+
if ( element.currentStyle ) {
|
905
|
+
theme = element.currentStyle[prop]
|
906
|
+
}
|
805
907
|
|
806
|
-
|
807
|
-
|
808
|
-
|
809
|
-
|
908
|
+
// For normal browsers.
|
909
|
+
else if ( window.getComputedStyle ) {
|
910
|
+
theme = getComputedStyle( element )[prop]
|
911
|
+
}
|
810
912
|
|
811
|
-
|
812
|
-
|
813
|
-
theme = getComputedStyle(element)[prop];
|
814
|
-
}
|
913
|
+
return theme == 'fixed'
|
914
|
+
}
|
815
915
|
|
816
|
-
|
916
|
+
|
917
|
+
|
918
|
+
/**
|
919
|
+
* Get the width of the browser’s scrollbar.
|
920
|
+
* Taken from: https://github.com/VodkaBears/Remodal/blob/master/src/jquery.remodal.js
|
921
|
+
*/
|
922
|
+
function getScrollbarWidth() {
|
923
|
+
|
924
|
+
if ( $html.height() <= $window.height() ) {
|
925
|
+
return 0
|
817
926
|
}
|
818
927
|
|
819
|
-
|
820
|
-
|
821
|
-
* Taken from: https://github.com/VodkaBears/Remodal/blob/master/src/jquery.remodal.js
|
822
|
-
*/
|
823
|
-
function getScrollbarWidth() {
|
928
|
+
var $outer = $( '<div style="visibility:hidden;width:100px" />' ).
|
929
|
+
appendTo( 'body' )
|
824
930
|
|
825
|
-
|
826
|
-
|
827
|
-
|
931
|
+
// Get the width without scrollbars.
|
932
|
+
var widthWithoutScroll = $outer[0].offsetWidth
|
933
|
+
|
934
|
+
// Force adding scrollbars.
|
935
|
+
$outer.css( 'overflow', 'scroll' )
|
936
|
+
|
937
|
+
// Add the inner div.
|
938
|
+
var $inner = $( '<div style="width:100%" />' ).appendTo( $outer )
|
828
939
|
|
829
|
-
|
940
|
+
// Get the width with scrollbars.
|
941
|
+
var widthWithScroll = $inner[0].offsetWidth
|
830
942
|
|
831
|
-
|
832
|
-
|
943
|
+
// Remove the divs.
|
944
|
+
$outer.remove()
|
833
945
|
|
834
|
-
|
835
|
-
|
946
|
+
// Return the difference between the widths.
|
947
|
+
return widthWithoutScroll - widthWithScroll
|
948
|
+
}
|
836
949
|
|
837
|
-
// Add the inner div.
|
838
|
-
var $inner = $('<div style="width:100%" />').appendTo($outer);
|
839
950
|
|
840
|
-
// Get the width with scrollbars.
|
841
|
-
var widthWithScroll = $inner[0].offsetWidth;
|
842
951
|
|
843
|
-
|
844
|
-
|
952
|
+
/**
|
953
|
+
* Get the target element from the event.
|
954
|
+
* If ELEMENT is supplied and present in the event path (ELEMENT is ancestor of the target),
|
955
|
+
* returns ELEMENT instead
|
956
|
+
*/
|
957
|
+
function getRealEventTarget( event, ELEMENT ) {
|
958
|
+
|
959
|
+
var path = []
|
845
960
|
|
846
|
-
|
847
|
-
|
961
|
+
if ( event.path ) {
|
962
|
+
path = event.path
|
848
963
|
}
|
849
964
|
|
965
|
+
if ( event.originalEvent && event.originalEvent.path ) {
|
966
|
+
path = event.originalEvent.path
|
967
|
+
}
|
968
|
+
|
969
|
+
if ( path && path.length > 0 ) {
|
970
|
+
if ( ELEMENT && path.indexOf( ELEMENT ) >= 0 ) {
|
971
|
+
return ELEMENT
|
972
|
+
} else {
|
973
|
+
return path[0]
|
974
|
+
}
|
975
|
+
}
|
976
|
+
|
977
|
+
return event.target
|
978
|
+
}
|
979
|
+
|
980
|
+
// taken from https://davidwalsh.name/javascript-debounce-function
|
981
|
+
function debounce(func, wait, immediate) {
|
982
|
+
var timeout;
|
983
|
+
return function() {
|
984
|
+
var context = this, args = arguments;
|
985
|
+
var later = function() {
|
986
|
+
timeout = null;
|
987
|
+
if (!immediate) func.apply(context, args);
|
988
|
+
};
|
989
|
+
var callNow = immediate && !timeout;
|
990
|
+
clearTimeout(timeout);
|
991
|
+
timeout = setTimeout(later, wait);
|
992
|
+
if (callNow) func.apply(context, args);
|
993
|
+
};
|
994
|
+
}
|
995
|
+
|
996
|
+
/**
|
997
|
+
* PickerConstructor helper methods.
|
998
|
+
*/
|
999
|
+
PickerConstructor._ = {
|
1000
|
+
|
850
1001
|
/**
|
851
|
-
*
|
1002
|
+
* Create a group of nodes. Expects:
|
1003
|
+
* `
|
1004
|
+
{
|
1005
|
+
min: {Integer},
|
1006
|
+
max: {Integer},
|
1007
|
+
i: {Integer},
|
1008
|
+
node: {String},
|
1009
|
+
item: {Function}
|
1010
|
+
}
|
1011
|
+
* `
|
852
1012
|
*/
|
853
|
-
|
854
|
-
|
855
|
-
/**
|
856
|
-
* Create a group of nodes. Expects:
|
857
|
-
* `
|
858
|
-
{
|
859
|
-
min: {Integer},
|
860
|
-
max: {Integer},
|
861
|
-
i: {Integer},
|
862
|
-
node: {String},
|
863
|
-
item: {Function}
|
864
|
-
}
|
865
|
-
* `
|
866
|
-
*/
|
867
|
-
group: function (groupObject) {
|
1013
|
+
group: function( groupObject ) {
|
868
1014
|
|
869
|
-
|
1015
|
+
var
|
870
1016
|
// Scope for the looped object
|
871
1017
|
loopObjectScope,
|
872
1018
|
|
873
|
-
|
874
1019
|
// Create the nodes list
|
875
1020
|
nodesList = '',
|
876
1021
|
|
877
|
-
|
878
1022
|
// The counter starts from the `min`
|
879
|
-
counter = PickerConstructor._.trigger(groupObject.min, groupObject)
|
1023
|
+
counter = PickerConstructor._.trigger( groupObject.min, groupObject )
|
880
1024
|
|
881
|
-
// Loop from the `min` to `max`, incrementing by `i`
|
882
|
-
for (; counter <= PickerConstructor._.trigger(groupObject.max, groupObject, [counter]); counter += groupObject.i) {
|
883
1025
|
|
884
|
-
|
885
|
-
|
1026
|
+
// Loop from the `min` to `max`, incrementing by `i`
|
1027
|
+
for ( ; counter <= PickerConstructor._.trigger( groupObject.max, groupObject, [ counter ] ); counter += groupObject.i ) {
|
886
1028
|
|
887
|
-
|
888
|
-
|
889
|
-
loopObjectScope[1], // the classes
|
890
|
-
loopObjectScope[2] // the attributes
|
891
|
-
);
|
892
|
-
}
|
1029
|
+
// Trigger the `item` function within scope of the object
|
1030
|
+
loopObjectScope = PickerConstructor._.trigger( groupObject.item, groupObject, [ counter ] )
|
893
1031
|
|
894
|
-
//
|
895
|
-
|
896
|
-
|
1032
|
+
// Splice the subgroup and create nodes out of the sub nodes
|
1033
|
+
nodesList += PickerConstructor._.node(
|
1034
|
+
groupObject.node,
|
1035
|
+
loopObjectScope[ 0 ], // the node
|
1036
|
+
loopObjectScope[ 1 ], // the classes
|
1037
|
+
loopObjectScope[ 2 ] // the attributes
|
1038
|
+
)
|
1039
|
+
}
|
897
1040
|
|
1041
|
+
// Return the list of nodes
|
1042
|
+
return nodesList
|
1043
|
+
}, //group
|
898
1044
|
|
899
|
-
/**
|
900
|
-
* Create a dom node string
|
901
|
-
*/
|
902
|
-
node: function (wrapper, item, klass, attribute) {
|
903
1045
|
|
904
|
-
|
905
|
-
|
1046
|
+
/**
|
1047
|
+
* Create a dom node string
|
1048
|
+
*/
|
1049
|
+
node: function( wrapper, item, klass, attribute ) {
|
906
1050
|
|
907
|
-
|
908
|
-
|
1051
|
+
// If the item is false-y, just return an empty string
|
1052
|
+
if ( !item ) return ''
|
909
1053
|
|
910
|
-
|
911
|
-
|
1054
|
+
// If the item is an array, do a join
|
1055
|
+
item = $.isArray( item ) ? item.join( '' ) : item
|
912
1056
|
|
913
|
-
|
914
|
-
|
1057
|
+
// Check for the class
|
1058
|
+
klass = klass ? ' class="' + klass + '"' : ''
|
915
1059
|
|
916
|
-
|
917
|
-
|
918
|
-
}, //node
|
1060
|
+
// Check for any attributes
|
1061
|
+
attribute = attribute ? ' ' + attribute : ''
|
919
1062
|
|
1063
|
+
// Return the wrapped item
|
1064
|
+
return '<' + wrapper + klass + attribute + '>' + item + '</' + wrapper + '>'
|
1065
|
+
}, //node
|
920
1066
|
|
921
|
-
/**
|
922
|
-
* Lead numbers below 10 with a zero.
|
923
|
-
*/
|
924
|
-
lead: function (number) {
|
925
|
-
return (number < 10 ? '0' : '') + number;
|
926
|
-
},
|
927
1067
|
|
928
|
-
|
929
|
-
|
930
|
-
|
931
|
-
|
932
|
-
|
933
|
-
|
1068
|
+
/**
|
1069
|
+
* Lead numbers below 10 with a zero.
|
1070
|
+
*/
|
1071
|
+
lead: function( number ) {
|
1072
|
+
return ( number < 10 ? '0': '' ) + number
|
1073
|
+
},
|
934
1074
|
|
935
|
-
/**
|
936
|
-
* If the second character is a digit, length is 2 otherwise 1.
|
937
|
-
*/
|
938
|
-
digits: function (string) {
|
939
|
-
return (/\d/.test(string[1]) ? 2 : 1
|
940
|
-
);
|
941
|
-
},
|
942
1075
|
|
943
|
-
|
944
|
-
|
945
|
-
|
946
|
-
|
947
|
-
|
948
|
-
|
1076
|
+
/**
|
1077
|
+
* Trigger a function otherwise return the value.
|
1078
|
+
*/
|
1079
|
+
trigger: function( callback, scope, args ) {
|
1080
|
+
return typeof callback == 'function' ? callback.apply( scope, args || [] ) : callback
|
1081
|
+
},
|
949
1082
|
|
950
|
-
/**
|
951
|
-
* Tell if something is an integer.
|
952
|
-
*/
|
953
|
-
isInteger: function (value) {
|
954
|
-
return {}.toString.call(value).indexOf('Number') > -1 && value % 1 === 0;
|
955
|
-
},
|
956
1083
|
|
957
|
-
|
958
|
-
|
959
|
-
|
960
|
-
|
1084
|
+
/**
|
1085
|
+
* If the second character is a digit, length is 2 otherwise 1.
|
1086
|
+
*/
|
1087
|
+
digits: function( string ) {
|
1088
|
+
return ( /\d/ ).test( string[ 1 ] ) ? 2 : 1
|
1089
|
+
},
|
961
1090
|
|
962
1091
|
|
963
|
-
|
964
|
-
|
965
|
-
|
966
|
-
|
1092
|
+
/**
|
1093
|
+
* Tell if something is a date object.
|
1094
|
+
*/
|
1095
|
+
isDate: function( value ) {
|
1096
|
+
return {}.toString.call( value ).indexOf( 'Date' ) > -1 && this.isInteger( value.getDate() )
|
1097
|
+
},
|
967
1098
|
|
968
|
-
// Extend jQuery.
|
969
|
-
$.fn[name] = function (options, action) {
|
970
1099
|
|
971
|
-
|
972
|
-
|
1100
|
+
/**
|
1101
|
+
* Tell if something is an integer.
|
1102
|
+
*/
|
1103
|
+
isInteger: function( value ) {
|
1104
|
+
return {}.toString.call( value ).indexOf( 'Number' ) > -1 && value % 1 === 0
|
1105
|
+
},
|
973
1106
|
|
974
|
-
// If the picker is requested, return the data object.
|
975
|
-
if (options == 'picker') {
|
976
|
-
return componentData;
|
977
|
-
}
|
978
1107
|
|
979
|
-
|
980
|
-
|
981
|
-
|
982
|
-
|
1108
|
+
/**
|
1109
|
+
* Create ARIA attribute strings.
|
1110
|
+
*/
|
1111
|
+
ariaAttr: ariaAttr
|
1112
|
+
} //PickerConstructor._
|
983
1113
|
|
984
|
-
// Otherwise go through each matched element and if the component
|
985
|
-
// doesn’t exist, create a new picker using `this` element
|
986
|
-
// and merging the defaults and options with a deep copy.
|
987
|
-
return this.each(function () {
|
988
|
-
var $this = $(this);
|
989
|
-
if (!$this.data(name)) {
|
990
|
-
new PickerConstructor(this, name, Component, options);
|
991
|
-
}
|
992
|
-
});
|
993
|
-
};
|
994
1114
|
|
995
|
-
// Set the defaults.
|
996
|
-
$.fn[name].defaults = Component.defaults;
|
997
|
-
}; //PickerConstructor.extend
|
998
1115
|
|
1116
|
+
/**
|
1117
|
+
* Extend the picker with a component and defaults.
|
1118
|
+
*/
|
1119
|
+
PickerConstructor.extend = function( name, Component ) {
|
1120
|
+
|
1121
|
+
// Extend jQuery.
|
1122
|
+
$.fn[ name ] = function( options, action ) {
|
1123
|
+
|
1124
|
+
// Grab the component data.
|
1125
|
+
var componentData = this.data( name )
|
1126
|
+
|
1127
|
+
// If the picker is requested, return the data object.
|
1128
|
+
if ( options == 'picker' ) {
|
1129
|
+
return componentData
|
1130
|
+
}
|
1131
|
+
|
1132
|
+
// If the component data exists and `options` is a string, carry out the action.
|
1133
|
+
if ( componentData && typeof options == 'string' ) {
|
1134
|
+
return PickerConstructor._.trigger( componentData[ options ], componentData, [ action ] )
|
1135
|
+
}
|
999
1136
|
|
1000
|
-
|
1001
|
-
|
1002
|
-
|
1003
|
-
|
1137
|
+
// Otherwise go through each matched element and if the component
|
1138
|
+
// doesn’t exist, create a new picker using `this` element
|
1139
|
+
// and merging the defaults and options with a deep copy.
|
1140
|
+
return this.each( function() {
|
1141
|
+
var $this = $( this )
|
1142
|
+
if ( !$this.data( name ) ) {
|
1143
|
+
new PickerConstructor( this, name, Component, options )
|
1004
1144
|
}
|
1005
|
-
}
|
1006
|
-
|
1145
|
+
})
|
1146
|
+
}
|
1147
|
+
|
1148
|
+
// Set the defaults.
|
1149
|
+
$.fn[ name ].defaults = Component.defaults
|
1150
|
+
} //PickerConstructor.extend
|
1151
|
+
|
1152
|
+
|
1153
|
+
|
1154
|
+
function aria(element, attribute, value) {
|
1155
|
+
if ( $.isPlainObject(attribute) ) {
|
1156
|
+
for ( var key in attribute ) {
|
1157
|
+
ariaSet(element, key, attribute[key])
|
1007
1158
|
}
|
1008
1159
|
}
|
1009
|
-
|
1010
|
-
element
|
1160
|
+
else {
|
1161
|
+
ariaSet(element, attribute, value)
|
1011
1162
|
}
|
1012
|
-
|
1013
|
-
|
1014
|
-
|
1015
|
-
|
1016
|
-
|
1017
|
-
|
1018
|
-
|
1019
|
-
|
1020
|
-
|
1021
|
-
}
|
1022
|
-
return data;
|
1163
|
+
}
|
1164
|
+
function ariaSet(element, attribute, value) {
|
1165
|
+
element.setAttribute(
|
1166
|
+
(attribute == 'role' ? '' : 'aria-') + attribute,
|
1167
|
+
value
|
1168
|
+
)
|
1169
|
+
}
|
1170
|
+
function ariaAttr(attribute, data) {
|
1171
|
+
if ( !$.isPlainObject(attribute) ) {
|
1172
|
+
attribute = { attribute: data }
|
1023
1173
|
}
|
1024
|
-
|
1025
|
-
|
1026
|
-
|
1027
|
-
|
1028
|
-
|
1029
|
-
} catch (err) {}
|
1174
|
+
data = ''
|
1175
|
+
for ( var key in attribute ) {
|
1176
|
+
var attr = (key == 'role' ? '' : 'aria-') + key,
|
1177
|
+
attrVal = attribute[key]
|
1178
|
+
data += attrVal == null ? '' : attr + '="' + attribute[key] + '"'
|
1030
1179
|
}
|
1180
|
+
return data
|
1181
|
+
}
|
1182
|
+
|
1183
|
+
// IE8 bug throws an error for activeElements within iframes.
|
1184
|
+
function getActiveElement() {
|
1185
|
+
try {
|
1186
|
+
return document.activeElement
|
1187
|
+
} catch ( err ) { }
|
1188
|
+
}
|
1189
|
+
|
1190
|
+
|
1191
|
+
|
1192
|
+
// Expose the picker constructor.
|
1193
|
+
return PickerConstructor
|
1194
|
+
|
1031
1195
|
|
1032
|
-
// Expose the picker constructor.
|
1033
|
-
return PickerConstructor;
|
1034
1196
|
});
|