material 0.8.2 → 0.8.3

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.
package/index.js CHANGED
@@ -30,7 +30,7 @@ import Textfield from './src/textfield'
30
30
  import Toolbar from './src/toolbar'
31
31
  import Tooltip from './src/tooltip'
32
32
  import View from './src/view'
33
- import attach from './src/module/attach'
33
+ import events from './src/module/events'
34
34
  import attributes from './src/module/attributes'
35
35
  import build from './src/module/build'
36
36
  import dataset from './src/module/dataset'
@@ -46,6 +46,6 @@ export {
46
46
  AppBar, Button, Card, Checkbox, Component, DateHour, Dialog, Drawer, Element,
47
47
  File, Form, Image, Layout, List, Loading, Menu, Navigation, Progress, Select,
48
48
  Selecter, Slider, Snackbar, Switch, Switcher, Tabs, TabView, Text, Textfield, Toolbar, Tooltip,
49
- View, attach, attributes, build, dataset, display, events, emitter, jsonToHTML, mediator,
49
+ View, events, attributes, build, dataset, display, events, emitter, jsonToHTML, mediator,
50
50
  observer, smoothscroll
51
51
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "material",
3
- "version": "0.8.2",
3
+ "version": "0.8.3",
4
4
  "description": "A lightweight implementation of Material Design Components for the web - ES6",
5
5
  "main": "index.js",
6
6
  "type": "module",
package/src/button.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import EventEmitter from './mixin/emitter'
2
2
  import build from './module/build'
3
3
  import display from './mixin/display'
4
- import bindEvents from './module/events'
4
+ import events from './module/events'
5
5
  import dataset from './module/dataset'
6
6
  import ripple from './module/ripple'
7
7
 
@@ -35,12 +35,11 @@ class Button extends EventEmitter {
35
35
  this.init(options)
36
36
  this.build()
37
37
  this.setup()
38
- this.bindEvents()
39
38
  }
40
39
 
41
40
  init (options) {
42
41
  this.options = { ...Button.defaults, ...options }
43
- Object.assign(this, build, display, bindEvents)
42
+ Object.assign(this, build, display)
44
43
  }
45
44
 
46
45
  setup () {
@@ -50,6 +49,8 @@ class Button extends EventEmitter {
50
49
  if (this.options.text) {
51
50
  this.element.innerHTML = this.element.innerHTML + this.options.text
52
51
  }
52
+
53
+ events.attach(this.options.events, this)
53
54
  }
54
55
 
55
56
  setAttributes () {
package/src/calendar.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import create from './element/create'
2
2
  import insert from './element/insert'
3
3
  import * as css from './module/css'
4
- import attach from './module/attach'
4
+ import events from './module/events'
5
5
  import emitter from './module/emitter'
6
6
 
7
7
  import Button from './button'
@@ -45,7 +45,7 @@ class Calendar {
45
45
 
46
46
  this.init()
47
47
  this.build()
48
- this.attach()
48
+ events.attach(this.options.events, this)
49
49
 
50
50
  return this
51
51
  }
package/src/checkbox.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import EventEmitter from './mixin/events'
2
2
  // import control from './mixin/control'
3
3
  import build from './module/build'
4
- import attach from './module/attach'
4
+ import events from './module/events'
5
5
  import * as css from './module/css'
6
6
 
7
7
  import icon from './skin/material/icon/checkbox.svg'
@@ -12,8 +12,8 @@ class Checkbox {
12
12
  static defaults = {
13
13
  class: 'checkbox',
14
14
  layout: [
15
- [Element, 'input', { type: 'checkbox' } ],
16
- [Element, 'control', { type: 'checkbox' } ],
15
+ [Element, 'input', { type: 'checkbox' }],
16
+ [Element, 'control', { type: 'checkbox' }],
17
17
  [Element, 'label', { tag: 'label' }]
18
18
  ],
19
19
  events: [
@@ -31,7 +31,6 @@ class Checkbox {
31
31
  this.init(options)
32
32
  this.build()
33
33
  this.setup()
34
- this.attach()
35
34
  }
36
35
 
37
36
  init (options) {
@@ -72,6 +71,8 @@ class Checkbox {
72
71
  if (this.options.value) {
73
72
  this.set('value', this.value)
74
73
  }
74
+
75
+ events.attach(this.options.events, this)
75
76
  }
76
77
 
77
78
  set (prop, value) {
@@ -107,7 +108,6 @@ class Checkbox {
107
108
  return this
108
109
  }
109
110
 
110
-
111
111
  click (e) {
112
112
  this.toggle(e)
113
113
  this.ui.input.focus()
package/src/dialog.js CHANGED
@@ -1,6 +1,6 @@
1
1
  // dialog related modules
2
2
  import emitter from './module/emitter'
3
- import attach from './module/attach'
3
+ import events from './module/events'
4
4
  import display from './mixin/display'
5
5
 
6
6
  import Element from './element'
@@ -38,14 +38,14 @@ class Dialog {
38
38
  this.init(options)
39
39
  this.build()
40
40
  this.render()
41
- this.attach()
41
+ this.setup()
42
42
 
43
43
  return this
44
44
  }
45
45
 
46
46
  init (options) {
47
47
  this.options = Object.assign({}, Dialog.defaults, options || {})
48
- Object.assign(this, emitter, attach, display)
48
+ Object.assign(this, emitter, display)
49
49
  }
50
50
 
51
51
  build () {
@@ -100,6 +100,10 @@ class Dialog {
100
100
  }
101
101
  }
102
102
 
103
+ setup () {
104
+ events.attach(this.options.events, this)
105
+ }
106
+
103
107
  setPosition () {
104
108
  const coord = this.options.target.getBoundingClientRect()
105
109
  const surface_coord = this.surface.getBoundingClientRect()
package/src/drawer.js CHANGED
@@ -25,7 +25,6 @@ class Drawer {
25
25
 
26
26
  this.build()
27
27
  this.attach()
28
-
29
28
  this.emit('ready')
30
29
  }
31
30
 
package/src/file.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import EventEmitter from './mixin/emitter'
2
-
2
+ import events from './module/events'
3
3
  import build from './module/build'
4
4
  import dataset from './module/dataset'
5
5
  import attributes from './module/attributes'
@@ -7,14 +7,18 @@ import attributes from './module/attributes'
7
7
  class File {
8
8
  static defaults = {
9
9
  class: 'file',
10
- attributes: ['name', 'accept', 'required', 'disabled', 'multiple']
10
+ attributes: ['name', 'accept', 'required', 'disabled', 'multiple'],
11
+ events: [
12
+ ['input.change', 'change']
13
+
14
+ ]
11
15
  }
12
16
 
13
17
  constructor (options) {
14
18
  this.init(options)
15
19
  this.build()
16
20
  this.buildInput()
17
- this.attach()
21
+ events.attach(this.options.events, this)
18
22
  }
19
23
 
20
24
  init (options) {
@@ -40,10 +44,8 @@ class File {
40
44
  }
41
45
  }
42
46
 
43
- attach () {
44
- this.input.addEventListener('change', (e) => {
45
- this.emit('change', e)
46
- })
47
+ change (e) {
48
+ this.emit('change', e)
47
49
  }
48
50
 
49
51
  image (e) {
package/src/form.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import insert from './element/insert'
2
2
  import * as css from './module/css'
3
3
  import emitter from './module/emitter'
4
- import attach from './module/attach'
4
+ import events from './module/events'
5
5
  import controller from './mixin/controller'
6
6
 
7
7
  // import component
@@ -31,7 +31,7 @@ class Form {
31
31
 
32
32
  this.init()
33
33
  this.build()
34
- this.attach()
34
+ events.attach(this.options.events, this)
35
35
 
36
36
  return this
37
37
  }
package/src/list/init.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export default {
2
2
  init () {
3
3
  this.build()
4
- this.attach()
4
+ events.attach(this.options.events, this)
5
5
  }
6
6
  }
package/src/loader.js CHANGED
@@ -6,7 +6,7 @@ class Loader {
6
6
  constructor (options) {
7
7
  this.options = Object.assign({}, Loader.defaults, options || {})
8
8
 
9
- // Object.assign(this, attach, mediator, build)
9
+ // Object.assign(this, mediator, build)
10
10
 
11
11
  this.build()
12
12
 
package/src/map.js CHANGED
@@ -1,4 +1,3 @@
1
-
2
1
  import mediator from '../module/mediator'
3
2
  import emitter from 'material/src/module/emitter'
4
3
  import attach from 'material/src/module/attach'
@@ -50,7 +49,7 @@ class Map {
50
49
  this.options = Object.assign({}, defaults, options || {})
51
50
 
52
51
  Object.assign(
53
- this, attach, emitter, init, build, viewport, mouse,
52
+ this, emitter, init, build, viewport, mouse,
54
53
  mode, countries,
55
54
  set, display, select, focus
56
55
  )
package/src/menu.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import EventEmitter from './mixin/emitter'
2
2
  // menu related modules
3
3
  import build from './module/build'
4
- import bindEvents from './module/events'
4
+ import events from './module/events'
5
5
  import display from './mixin/display'
6
6
 
7
7
  import Element from './element'
@@ -27,14 +27,18 @@ class Menu extends EventEmitter {
27
27
 
28
28
  this.init(options)
29
29
  this.build(this.constructor)
30
- this.bindEvents()
30
+ this.setup()
31
31
 
32
32
  this.render(this.options.items)
33
33
  }
34
34
 
35
35
  init (options) {
36
36
  this.options = Object.assign({}, Menu.defaults, options || {})
37
- Object.assign(this, build, bindEvents, display)
37
+ Object.assign(this, build, display)
38
+ }
39
+
40
+ setup () {
41
+ events.attach(this.options.events, this)
38
42
  }
39
43
 
40
44
  render (items) {
@@ -2,11 +2,13 @@ import extract from './extract'
2
2
  import last from './last'
3
3
 
4
4
  const attachModule = {
5
+ eventHandlers: [], // Utiliser un tableau pour stocker les événements et les gestionnaires
6
+
5
7
  attach (events) {
6
8
  events = events || this.options.events
7
9
  if (!events) return
8
10
 
9
- events.map(([eventDef, funcDef, option]) => {
11
+ events.forEach(([eventDef, funcDef, option]) => {
10
12
  const e = extract.e(this, eventDef)
11
13
  const isFunction = typeof funcDef === 'function'
12
14
  let f = null
@@ -32,21 +34,35 @@ const attachModule = {
32
34
  }
33
35
 
34
36
  if (handler && e && e.element && e.element.addEventListener) {
35
- if (option) {
36
- e.element.addEventListener(e.name, handler, option)
37
- } else {
38
- e.element.addEventListener(e.name, handler)
39
- }
37
+ e.element.addEventListener(e.name, handler, option)
38
+ this.eventHandlers.push({ eventDef, element: e.element, handler })
40
39
  } else if (e && e.element && e.element.on && handler) {
41
40
  e.element.on(e.name, handler)
41
+ this.eventHandlers.push({ eventDef, element: e.element, handler })
42
42
  } else {
43
43
  // console.error(`Can't attach ${eventDef}`)
44
44
  }
45
45
  })
46
46
 
47
47
  return this
48
- }
48
+ },
49
49
 
50
+ detach (events) {
51
+ (events || []).forEach(([eventDef]) => {
52
+ this.eventHandlers.forEach((handlerObj, index) => {
53
+ if (handlerObj.eventDef === eventDef) {
54
+ const { element, handler } = handlerObj
55
+ if (element.removeEventListener) {
56
+ element.removeEventListener(eventDef, handler)
57
+ } else if (element.off) {
58
+ element.off(eventDef, handler)
59
+ }
60
+ delete this.eventHandlers[index]
61
+ }
62
+ })
63
+ this.eventHandlers = this.eventHandlers.filter(Boolean) // Nettoyer les entrées supprimées
64
+ })
65
+ }
50
66
  }
51
67
 
52
68
  export default attachModule
@@ -0,0 +1,415 @@
1
+ // based on the work of
2
+ // https://github.com/matthewhudson/current-device
3
+
4
+ const previousDevice = window.device
5
+
6
+ const device = {}
7
+
8
+ const changeOrientationList = []
9
+
10
+ // Add device as a global object.
11
+ window.device = device
12
+
13
+ // The <html> element.
14
+ const documentElement = window.document.documentElement
15
+
16
+ // The client user agent string.
17
+ // Lowercase, so we can use the more efficient indexOf(), instead of Regex
18
+ let userAgent = window.navigator.userAgent.toLowerCase()
19
+
20
+ // Detectable television devices.
21
+ const television = [
22
+ 'googletv',
23
+ 'viera',
24
+ 'smarttv',
25
+ 'internet.tv',
26
+ 'netcast',
27
+ 'nettv',
28
+ 'appletv',
29
+ 'boxee',
30
+ 'kylo',
31
+ 'roku',
32
+ 'dlnadoc',
33
+ 'pov_tv',
34
+ 'hbbtv',
35
+ 'ce-html'
36
+ ]
37
+
38
+ // Main functions
39
+ // --------------
40
+
41
+ device.macos = function () {
42
+ return find('mac')
43
+ }
44
+
45
+ device.ios = function () {
46
+ return device.iphone() || device.ipod() || device.ipad()
47
+ }
48
+
49
+ device.iphone = function () {
50
+ return !device.windows() && find('iphone')
51
+ }
52
+
53
+ device.ipod = function () {
54
+ return find('ipod')
55
+ }
56
+
57
+ device.ipad = function () {
58
+ const iPadOS13Up =
59
+ navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1
60
+ return find('ipad') || iPadOS13Up
61
+ }
62
+
63
+ device.android = function () {
64
+ return !device.windows() && find('android')
65
+ }
66
+
67
+ device.androidPhone = function () {
68
+ return device.android() && find('mobile')
69
+ }
70
+
71
+ device.androidTablet = function () {
72
+ return device.android() && !find('mobile')
73
+ }
74
+
75
+ device.blackberry = function () {
76
+ return find('blackberry') || find('bb10')
77
+ }
78
+
79
+ device.blackberryPhone = function () {
80
+ return device.blackberry() && !find('tablet')
81
+ }
82
+
83
+ device.blackberryTablet = function () {
84
+ return device.blackberry() && find('tablet')
85
+ }
86
+
87
+ device.windows = function () {
88
+ return find('windows')
89
+ }
90
+
91
+ device.windowsPhone = function () {
92
+ return device.windows() && find('phone')
93
+ }
94
+
95
+ device.windowsTablet = function () {
96
+ return device.windows() && (find('touch') && !device.windowsPhone())
97
+ }
98
+
99
+ device.fxos = function () {
100
+ return (find('(mobile') || find('(tablet')) && find(' rv:')
101
+ }
102
+
103
+ device.fxosPhone = function () {
104
+ return device.fxos() && find('mobile')
105
+ }
106
+
107
+ device.fxosTablet = function () {
108
+ return device.fxos() && find('tablet')
109
+ }
110
+
111
+ device.meego = function () {
112
+ return find('meego')
113
+ }
114
+
115
+ device.cordova = function () {
116
+ return window.cordova && location.protocol === 'file:'
117
+ }
118
+
119
+ device.nodeWebkit = function () {
120
+ return typeof window.process === 'object'
121
+ }
122
+
123
+ device.mobile = function () {
124
+ return (
125
+ device.androidPhone() ||
126
+ device.iphone() ||
127
+ device.ipod() ||
128
+ device.windowsPhone() ||
129
+ device.blackberryPhone() ||
130
+ device.fxosPhone() ||
131
+ device.meego()
132
+ )
133
+ }
134
+
135
+ device.tablet = function () {
136
+ return (
137
+ device.ipad() ||
138
+ device.androidTablet() ||
139
+ device.blackberryTablet() ||
140
+ device.windowsTablet() ||
141
+ device.fxosTablet()
142
+ )
143
+ }
144
+
145
+ device.desktop = function () {
146
+ return !device.tablet() && !device.mobile()
147
+ }
148
+
149
+ device.television = function () {
150
+ let i = 0
151
+ while (i < television.length) {
152
+ if (find(television[i])) {
153
+ return true
154
+ }
155
+ i++
156
+ }
157
+ return false
158
+ }
159
+
160
+ device.portrait = function () {
161
+ if (
162
+ screen.orientation &&
163
+ Object.prototype.hasOwnProperty.call(window, 'onorientationchange')
164
+ ) {
165
+ return includes(screen.orientation.type, 'portrait')
166
+ }
167
+ if (
168
+ device.ios() &&
169
+ Object.prototype.hasOwnProperty.call(window, 'orientation')
170
+ ) {
171
+ return Math.abs(window.orientation) !== 90
172
+ }
173
+ return window.innerHeight / window.innerWidth > 1
174
+ }
175
+
176
+ device.landscape = function () {
177
+ if (
178
+ screen.orientation &&
179
+ Object.prototype.hasOwnProperty.call(window, 'onorientationchange')
180
+ ) {
181
+ return includes(screen.orientation.type, 'landscape')
182
+ }
183
+ if (
184
+ device.ios() &&
185
+ Object.prototype.hasOwnProperty.call(window, 'orientation')
186
+ ) {
187
+ return Math.abs(window.orientation) === 90
188
+ }
189
+ return window.innerHeight / window.innerWidth < 1
190
+ }
191
+
192
+ // Public Utility Functions
193
+ // ------------------------
194
+
195
+ // Run device.js in noConflict mode,
196
+ // returning the device variable to its previous owner.
197
+ device.noConflict = function () {
198
+ window.device = previousDevice
199
+ return this
200
+ }
201
+
202
+ // Private Utility Functions
203
+ // -------------------------
204
+
205
+ // Check if element exists
206
+ function includes (haystack, needle) {
207
+ return haystack.indexOf(needle) !== -1
208
+ }
209
+
210
+ // Simple UA string search
211
+ function find (needle) {
212
+ return includes(userAgent, needle)
213
+ }
214
+
215
+ // Check if documentElement already has a given class.
216
+ function hasClass (className) {
217
+ return documentElement.className.match(new RegExp(className, 'i'))
218
+ }
219
+
220
+ // Add one or more CSS classes to the <html> element.
221
+ function addClass (className) {
222
+ let currentClassNames = null
223
+ if (!hasClass(className)) {
224
+ currentClassNames = documentElement.className.replace(/^\s+|\s+$/g, '')
225
+ documentElement.className = `${currentClassNames} ${className}`
226
+ }
227
+ }
228
+
229
+ // Remove single CSS class from the <html> element.
230
+ function removeClass (className) {
231
+ if (hasClass(className)) {
232
+ documentElement.className = documentElement.className.replace(
233
+ ` ${className}`,
234
+ ''
235
+ )
236
+ }
237
+ }
238
+
239
+ function cleanClasses () {
240
+ const classes = ['mobile', 'tablet', 'desktop', 'ios', 'iphone', 'ipad', 'ipod', 'android', 'blackberry', 'macos', 'windows', 'fxos', 'meego', 'television']
241
+ for (let i = 0; i < classes.length; i++) {
242
+ removeClass(classes[i])
243
+ }
244
+ }
245
+
246
+ // HTML Element Handling
247
+ // ---------------------
248
+
249
+ // Insert the appropriate CSS class based on the _user_agent.
250
+ function applyClass () {
251
+ cleanClasses()
252
+
253
+ if (device.ios()) {
254
+ if (device.ipad()) {
255
+ addClass('ios ipad tablet')
256
+ } else if (device.iphone()) {
257
+ addClass('ios iphone mobile')
258
+ } else if (device.ipod()) {
259
+ addClass('ios ipod mobile')
260
+ }
261
+ } else if (device.macos()) {
262
+ addClass('macos desktop')
263
+ } else if (device.android()) {
264
+ if (device.androidTablet()) {
265
+ addClass('android tablet')
266
+ } else {
267
+ addClass('android mobile')
268
+ }
269
+ } else if (device.blackberry()) {
270
+ if (device.blackberryTablet()) {
271
+ addClass('blackberry tablet')
272
+ } else {
273
+ addClass('blackberry mobile')
274
+ }
275
+ } else if (device.windows()) {
276
+ if (device.windowsTablet()) {
277
+ addClass('windows tablet')
278
+ } else if (device.windowsPhone()) {
279
+ addClass('windows mobile')
280
+ } else {
281
+ addClass('windows desktop')
282
+ }
283
+ } else if (device.fxos()) {
284
+ if (device.fxosTablet()) {
285
+ addClass('fxos tablet')
286
+ } else {
287
+ addClass('fxos mobile')
288
+ }
289
+ } else if (device.meego()) {
290
+ addClass('meego mobile')
291
+ } else if (device.nodeWebkit()) {
292
+ addClass('node-webkit')
293
+ } else if (device.television()) {
294
+ addClass('television')
295
+ } else if (device.desktop()) {
296
+ addClass('desktop')
297
+ }
298
+
299
+ if (device.cordova()) {
300
+ addClass('cordova')
301
+ }
302
+ }
303
+
304
+ applyClass()
305
+
306
+ // Orientation Handling
307
+ // --------------------
308
+
309
+ // Handle device orientation changes.
310
+ function handleOrientation () {
311
+ if (device.landscape()) {
312
+ removeClass('portrait')
313
+ addClass('landscape')
314
+ walkOnChangeOrientationList('landscape')
315
+ } else {
316
+ removeClass('landscape')
317
+ addClass('portrait')
318
+ walkOnChangeOrientationList('portrait')
319
+ }
320
+ setOrientationCache()
321
+ }
322
+
323
+ function walkOnChangeOrientationList (newOrientation) {
324
+ for (let index = 0; index < changeOrientationList.length; index++) {
325
+ changeOrientationList[index](newOrientation)
326
+ }
327
+ }
328
+
329
+ device.onChangeOrientation = function (cb) {
330
+ if (typeof cb === 'function') {
331
+ changeOrientationList.push(cb)
332
+ }
333
+ }
334
+
335
+ // Detect whether device supports orientationchange event,
336
+ // otherwise fall back to the resize event.
337
+ let orientationEvent = 'resize'
338
+ if (Object.prototype.hasOwnProperty.call(window, 'onorientationchange')) {
339
+ orientationEvent = 'orientationchange'
340
+ }
341
+
342
+ // Listen for changes in orientation.
343
+ if (window.addEventListener) {
344
+ window.addEventListener(orientationEvent, handleOrientation, false)
345
+ } else if (window.attachEvent) {
346
+ window.attachEvent(orientationEvent, handleOrientation)
347
+ } else {
348
+ window[orientationEvent] = handleOrientation
349
+ }
350
+
351
+ handleOrientation()
352
+
353
+ // Public functions to get the current value of type, os, or orientation
354
+ // ---------------------------------------------------------------------
355
+
356
+ function findMatch (arr) {
357
+ for (let i = 0; i < arr.length; i++) {
358
+ if (device[arr[i]]()) {
359
+ return arr[i]
360
+ }
361
+ }
362
+ return 'unknown'
363
+ }
364
+
365
+ device.type = findMatch(['mobile', 'tablet', 'desktop'])
366
+ device.os = findMatch([
367
+ 'ios',
368
+ 'iphone',
369
+ 'ipad',
370
+ 'ipod',
371
+ 'android',
372
+ 'blackberry',
373
+ 'macos',
374
+ 'windows',
375
+ 'fxos',
376
+ 'meego',
377
+ 'television'
378
+ ])
379
+
380
+ function setOrientationCache () {
381
+ device.orientation = findMatch(['portrait', 'landscape'])
382
+ }
383
+
384
+ setOrientationCache()
385
+
386
+ let previousDeviceType = null
387
+ device.onDeviceChange = null
388
+
389
+ function updateDeviceDetection () {
390
+ userAgent = window.navigator.userAgent.toLowerCase()
391
+ console.log('UA', userAgent)
392
+ device.type = findMatch(['mobile', 'tablet', 'desktop'])
393
+ device.os = findMatch(['ios', 'iphone', 'ipad', 'ipod', 'android', 'blackberry', 'macos', 'windows', 'fxos', 'meego', 'television'])
394
+ setOrientationCache()
395
+ applyClass()
396
+ checkAndHandleDeviceChange()
397
+ }
398
+
399
+ window.addEventListener('resize', updateDeviceDetection)
400
+
401
+ function triggerOnDeviceChange () {
402
+ if (typeof device.onDeviceChange === 'function') {
403
+ device.onDeviceChange(device.type)
404
+ }
405
+ }
406
+
407
+ function checkAndHandleDeviceChange () {
408
+ const currentDeviceType = device.type
409
+ if (previousDeviceType !== currentDeviceType) {
410
+ triggerOnDeviceChange()
411
+ previousDeviceType = currentDeviceType
412
+ }
413
+ }
414
+
415
+ export default device
@@ -1,22 +1,30 @@
1
1
  import extract from './extract'
2
+ import last from './last'
2
3
 
3
- const attachModule = {
4
- bindEvents (events) {
5
- events = events || this.options.events
6
- if (!events) return
4
+ const events = {
5
+ eventHandlers: [], // Utiliser un tableau pour stocker les événements et les gestionnaires
7
6
 
8
- events.map(([eventDef, funcDef, option]) => {
9
- const e = extract.e(this, eventDef)
7
+ attach (eventsArray, context) {
8
+ if (!eventsArray) return
9
+
10
+ eventsArray.forEach(([eventDef, funcDef, option]) => {
11
+ const e = extract.e(context, eventDef)
10
12
  const isFunction = typeof funcDef === 'function'
11
- const f = isFunction ? null : extract.f(this, funcDef)
12
- const keys = funcDef.split('.')
13
- keys.pop()
14
- const bound = this.last(keys.join('.'))
13
+ let f = null
14
+ let keys = []
15
+
16
+ if (!isFunction) {
17
+ f = extract.f(context, funcDef)
18
+ keys = funcDef.split('.')
19
+ keys.pop()
20
+ }
21
+
22
+ const bound = last(keys.join('.'), context)
15
23
 
16
24
  let handler = null
17
25
 
18
- if (isFunction && funcDef) {
19
- handler = funcDef.bind(this)
26
+ if (isFunction) {
27
+ handler = funcDef.bind(context)
20
28
  } else if (f && bound) {
21
29
  handler = f.bind(bound)
22
30
  } else {
@@ -25,13 +33,11 @@ const attachModule = {
25
33
  }
26
34
 
27
35
  if (handler && e && e.element && e.element.addEventListener) {
28
- if (option) {
29
- e.element.addEventListener(e.name, handler, option)
30
- } else {
31
- e.element.addEventListener(e.name, handler)
32
- }
36
+ e.element.addEventListener(e.name, handler, option)
37
+ this.eventHandlers.push({ eventDef, element: e.element, handler })
33
38
  } else if (e && e.element && e.element.on && handler) {
34
39
  e.element.on(e.name, handler)
40
+ this.eventHandlers.push({ eventDef, element: e.element, handler })
35
41
  } else {
36
42
  // console.error(`Can't attach ${eventDef}`)
37
43
  }
@@ -40,12 +46,22 @@ const attachModule = {
40
46
  return this
41
47
  },
42
48
 
43
- last (str) {
44
- if (!str) return this
45
- if (!str.includes('.')) return this[str]
46
-
47
- return str.split('.').reduce((acc, key) => acc[key], this)
49
+ detach (eventsArray, context) {
50
+ (eventsArray || []).forEach(([eventDef]) => {
51
+ this.eventHandlers.forEach((handlerObj, index) => {
52
+ if (handlerObj.eventDef === eventDef) {
53
+ const { element, handler } = handlerObj
54
+ if (element.removeEventListener) {
55
+ element.removeEventListener(eventDef, handler)
56
+ } else if (element.off) {
57
+ element.off(eventDef, handler)
58
+ }
59
+ delete this.eventHandlers[index]
60
+ }
61
+ })
62
+ this.eventHandlers = this.eventHandlers.filter(Boolean) // Nettoyer les entrées supprimées
63
+ })
48
64
  }
49
65
  }
50
66
 
51
- export default attachModule
67
+ export default events
package/src/navigation.js CHANGED
@@ -2,7 +2,7 @@ import EventEmitter from './mixin/emitter'
2
2
 
3
3
  import * as css from './module/css'
4
4
  import build from './module/build'
5
- import attach from './module/attach'
5
+ import events from './module/events'
6
6
  import display from './mixin/display'
7
7
  import Element from './element'
8
8
  import Button from './button'
@@ -25,13 +25,13 @@ class Navigation extends EventEmitter {
25
25
 
26
26
  this.init(options)
27
27
  this.build()
28
- this.attach()
28
+ events.attach(this.options.events, this)
29
29
  this.setup()
30
30
  }
31
31
 
32
32
  init (options) {
33
33
  this.options = { ...Navigation.defaults, ...options }
34
- Object.assign(this, build, attach, display)
34
+ Object.assign(this, build, display)
35
35
  this.items = []
36
36
  }
37
37
 
package/src/search.js CHANGED
@@ -2,7 +2,7 @@ import EventEmitter from './mixin/emitter'
2
2
 
3
3
  import build from './module/build'
4
4
  import display from './mixin/display'
5
- import bindEvents from './module/events'
5
+ import events from './module/events'
6
6
 
7
7
  import Element from './element'
8
8
  import Button from './button'
@@ -13,8 +13,8 @@ class Search extends EventEmitter {
13
13
  minChar: 4,
14
14
  timeout: 200,
15
15
  layout: [
16
- [Element, 'input', { tag: 'input', class: 'input'} ],
17
- [Button, 'clear', { class: 'clear'} ]
16
+ [Element, 'input', { tag: 'input', class: 'input' }],
17
+ [Button, 'clear', { class: 'clear' }]
18
18
  ],
19
19
  events: [
20
20
  ['ui.input.input', 'onInput'],
@@ -27,14 +27,17 @@ class Search extends EventEmitter {
27
27
 
28
28
  this.init(options)
29
29
  this.build()
30
- this.bindEvents()
31
-
32
- this.input = this.ui.input
30
+ this.setup()
33
31
  }
34
32
 
35
33
  init (options) {
36
34
  this.options = { ...Search.defaults, ...options }
37
- Object.assign(this, build, display, bindEvents)
35
+ Object.assign(this, build, display)
36
+ }
37
+
38
+ setup () {
39
+ this.input = this.ui.input
40
+ events.attach(this.options.events, this)
38
41
  }
39
42
 
40
43
  set (value) {
package/src/select.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import EventEmitter from './mixin/emitter'
2
2
  // modules
3
3
  import build from './module/build'
4
- import attach from './module/attach'
4
+ import events from './module/events'
5
5
  import attributes from './module/attributes'
6
6
  import dataset from './module/dataset'
7
7
 
@@ -20,12 +20,12 @@ class Select extends EventEmitter {
20
20
  this.build()
21
21
  this.buildLabel()
22
22
  this.buildInput()
23
- this.attach()
23
+ events.attach(this.options.events, this)
24
24
  }
25
25
 
26
26
  init (options) {
27
27
  this.options = Object.assign({}, Select.defaults, options || {})
28
- Object.assign(this, build, attach, dataset)
28
+ Object.assign(this, build, dataset)
29
29
  }
30
30
 
31
31
  buildLabel () {
package/src/selecter.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import EventEmitter from './mixin/emitter'
2
2
  // modules
3
- import attach from './module/attach'
3
+ import events from './module/events'
4
4
  import dataset from './module/dataset'
5
5
  import attributes from './module/attributes'
6
6
  import * as css from './module/css'
@@ -39,12 +39,12 @@ class Selecter extends EventEmitter {
39
39
  this.init(options)
40
40
  this.build()
41
41
  this.setup()
42
- this.attach()
42
+ events.attach(this.options.events, this)
43
43
  }
44
44
 
45
45
  init (options) {
46
46
  this.options = Object.assign({}, Selecter.defaults, options || {})
47
- Object.assign(this, attach, dataset)
47
+ Object.assign(this, dataset)
48
48
  }
49
49
 
50
50
  setup () {
package/src/selector.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import emitter from './module/emitter'
2
- import attach from './module/attach'
2
+ import events from './module/events'
3
3
 
4
4
  const defaults = {
5
5
  class: 'selector',
@@ -41,7 +41,7 @@ class Selector {
41
41
  init () {
42
42
  this.build()
43
43
  this.setup()
44
- this.attach()
44
+ events.attach(this.options.events, this)
45
45
 
46
46
  if (this.options.container) {
47
47
  this.options.container.appendChild(this.element)
package/src/slider.js CHANGED
@@ -7,7 +7,6 @@ import insert from './element/insert'
7
7
  import offset from './element/offset'
8
8
  import classify from './module/classify'
9
9
  // import control from './control';
10
- import attach from './module/attach'
11
10
  import * as css from './module/css'
12
11
  import emitter from './module/emitter'
13
12
 
@@ -23,7 +22,7 @@ const defaults = {
23
22
  value: false,
24
23
  range: [0, 100],
25
24
  step: 5,
26
- modules: [events, control, emitter, attach],
25
+ modules: [control, emitter],
27
26
  mixins: [],
28
27
  build: ['$root.material-slider', {},
29
28
  ['label$label.slider-label', {}],
@@ -60,7 +59,7 @@ class Slider {
60
59
 
61
60
  this.init(this.options)
62
61
  this.build(this.options)
63
- this.attach()
62
+ events.attach(this.options.events, this)
64
63
 
65
64
  return this
66
65
  }
package/src/snackbar.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import EventEmitter from './mixin/emitter'
3
3
  // related modules
4
4
  import build from './module/build'
5
- import bindEvents from './module/events'
5
+ import events from './module/events'
6
6
  import display from './mixin/display'
7
7
  // ui element
8
8
  import Element from './element'
@@ -35,7 +35,7 @@ class Snackbar extends EventEmitter {
35
35
  this.init(options)
36
36
  this.build(this.constructor)
37
37
  this.render()
38
- this.bindEvents()
38
+ events.attach(this.options.events, this)
39
39
  this.show()
40
40
 
41
41
  if (this.options.duration) {
@@ -47,7 +47,7 @@ class Snackbar extends EventEmitter {
47
47
 
48
48
  init (options) {
49
49
  this.options = Object.assign({}, Snackbar.defaults, options || {})
50
- Object.assign(this, build, bindEvents, display)
50
+ Object.assign(this, build, display)
51
51
 
52
52
  this.buildSnackbarContainer(this.options.container)
53
53
  }
package/src/switch.js CHANGED
@@ -3,7 +3,7 @@ import EventEmitter from './mixin/emitter'
3
3
  // module
4
4
  import build from './module/build'
5
5
  import dataset from './module/dataset'
6
- import attach from './module/attach'
6
+ import events from './module/events'
7
7
  import attributes from './module/attributes'
8
8
  // ui
9
9
  import Element from './element'
@@ -37,12 +37,12 @@ class Switch extends EventEmitter {
37
37
  this.init(options)
38
38
  this.build()
39
39
  this.setup()
40
- this.attach()
40
+ events.attach(this.options.events, this)
41
41
  }
42
42
 
43
43
  init (options) {
44
44
  this.options = Object.assign({}, Switch.defaults, options || {})
45
- Object.assign(this, build, attach, dataset)
45
+ Object.assign(this, build, dataset)
46
46
 
47
47
  this.value = this.options.value
48
48
  }
package/src/switcher.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import EventEmitter from './mixin/emitter'
2
+ import events from './module/events'
2
3
 
3
4
  class Switcher extends EventEmitter {
4
5
  static defaults = {
@@ -7,7 +8,10 @@ class Switcher extends EventEmitter {
7
8
  list: [],
8
9
  first: false,
9
10
  mode: 'unique',
10
- allowEmpty: false
11
+ allowEmpty: false,
12
+ events: [
13
+ ['element.click', 'click']
14
+ ]
11
15
  }
12
16
 
13
17
  constructor (options) {
@@ -15,11 +19,7 @@ class Switcher extends EventEmitter {
15
19
 
16
20
  this.init(options)
17
21
  this.build()
18
- this.attach()
19
-
20
- if (this.options.default) {
21
- this.selectByName(this.options.default, true)
22
- }
22
+ this.setup()
23
23
  }
24
24
 
25
25
  init (options) {
@@ -65,11 +65,19 @@ class Switcher extends EventEmitter {
65
65
  this.element.appendChild(this.list)
66
66
  }
67
67
 
68
- attach () {
69
- this.element.addEventListener('click', (event) => {
70
- if (!event.target.dataset.switcher) return
71
- this.select(event.target)
72
- })
68
+ setup () {
69
+ console.log('events.attach', this.options.events)
70
+ events.attach(this.options.events, this)
71
+
72
+ if (this.options.default) {
73
+ this.selectByName(this.options.default, true)
74
+ }
75
+ }
76
+
77
+ click (event) {
78
+ console.log('click', event)
79
+ if (!event.target.dataset.switcher) return
80
+ this.select(event.target)
73
81
  }
74
82
 
75
83
  select (option) {
package/src/tabview.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import EventEmitter from './mixin/emitter'
2
2
  import observer from './element/observer'
3
+ import events from './module/events'
3
4
  import build from './module/build'
4
5
  import display from './view/display'
5
6
 
@@ -7,7 +8,10 @@ class TabView extends EventEmitter {
7
8
  static defaults = {
8
9
  base: 'view',
9
10
  class: 'tabview',
10
- mode: 'style'
11
+ mode: 'style',
12
+ events: [
13
+ ['ui.tabs.click', 'onTabClick']
14
+ ]
11
15
  }
12
16
 
13
17
  constructor (options) {
@@ -22,7 +26,7 @@ class TabView extends EventEmitter {
22
26
  if (!ready) {
23
27
  ready = true
24
28
  this.setup()
25
- this.attach()
29
+ events.attach(this.options.events, this)
26
30
 
27
31
  this.emit('ready')
28
32
  }
@@ -64,15 +68,13 @@ class TabView extends EventEmitter {
64
68
  this.click(this.ui.buttons[0])
65
69
  }
66
70
 
67
- attach () {
68
- this.ui.tabs.addEventListener('click', (e) => {
69
- e.stopPropagation()
70
- if (e.target === e.currentTarget) return
71
+ onTabClick (e) {
72
+ e.stopPropagation()
73
+ if (e.target === e.currentTarget) return
71
74
 
72
- if (e.target.matches('BUTTON')) {
73
- this.click(e.target)
74
- }
75
- })
75
+ if (e.target.matches('BUTTON')) {
76
+ this.click(e.target)
77
+ }
76
78
  }
77
79
 
78
80
  select (view) {
package/src/textfield.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import emitter from './module/emitter'
2
- import attach from './module/attach'
2
+ import events from './module/events'
3
3
  import dataset from './module/dataset'
4
4
  import attributes from './module/attributes'
5
5
 
@@ -22,12 +22,12 @@ class Textfield {
22
22
  constructor (options) {
23
23
  this.init(options)
24
24
  this.build()
25
- this.attach()
25
+ events.attach(this.options.events, this)
26
26
  }
27
27
 
28
28
  init (options) {
29
29
  this.options = Object.assign({}, Textfield.defaults, options || {})
30
- Object.assign(this, emitter, attach, dataset)
30
+ Object.assign(this, emitter, dataset)
31
31
  // console.log('options', options)
32
32
  }
33
33
 
package/src/tooltip.js CHANGED
@@ -32,7 +32,7 @@ class Tooltip {
32
32
  // console.log('element options', options)
33
33
 
34
34
  this.build()
35
- this.attach()
35
+ this.attachEvent()
36
36
 
37
37
  return this
38
38
  }
@@ -55,7 +55,7 @@ class Tooltip {
55
55
  container.appendChild(this.element)
56
56
  }
57
57
 
58
- attach () {
58
+ attachEvent () {
59
59
  // console.log('attach', this.options.targets)
60
60
  const targets = document.querySelectorAll(this.options.targets)
61
61
 
package/src/tree.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import emitter from './module/emitter'
2
2
  import * as css from './module/css'
3
- import attach from './module/attach'
3
+ import events from './module/events'
4
4
  import insert from './mixin/insert'
5
5
 
6
6
  const defaults = {
@@ -19,7 +19,7 @@ class Tree {
19
19
 
20
20
  this.init()
21
21
  this.build()
22
- this.attach()
22
+ events.attach(this.options.events, this)
23
23
 
24
24
  return this
25
25
  }