material 0.8.2 → 0.8.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js CHANGED
@@ -30,12 +30,12 @@ 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'
34
33
  import attributes from './src/module/attributes'
35
34
  import build from './src/module/build'
36
35
  import dataset from './src/module/dataset'
36
+ import device from './src/module/device'
37
37
  import display from './src/mixin/display'
38
- import events from './src/module/attach'
38
+ import events from './src/module/events'
39
39
  import emitter from './src/module/emitter'
40
40
  import jsonToHTML from './src/module/jsontohtml'
41
41
  import mediator from './src/module/mediator'
@@ -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, attributes, build, dataset, device, 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.4",
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,403 @@
1
+ // based on the work of
2
+ // https://github.com/matthewhudson/current-device
3
+
4
+ const previousDevice = window.device
5
+
6
+ const device = {}
7
+ const os = ['ios', 'iphone', 'ipad', 'ipod', 'android', 'blackberry', 'macos', 'windows', 'fxos', 'meego', 'television']
8
+ const type = ['mobile', 'tablet', 'desktop']
9
+ const changeOrientationList = []
10
+
11
+ // Add device as a global object.
12
+ window.device = device
13
+
14
+ // The <html> element.
15
+ const documentElement = window.document.documentElement
16
+
17
+ // The client user agent string.
18
+ // Lowercase, so we can use the more efficient indexOf(), instead of Regex
19
+ let userAgent = window.navigator.userAgent.toLowerCase()
20
+
21
+ // Detectable television devices.
22
+ const television = [
23
+ 'googletv',
24
+ 'viera',
25
+ 'smarttv',
26
+ 'internet.tv',
27
+ 'netcast',
28
+ 'nettv',
29
+ 'appletv',
30
+ 'boxee',
31
+ 'kylo',
32
+ 'roku',
33
+ 'dlnadoc',
34
+ 'pov_tv',
35
+ 'hbbtv',
36
+ 'ce-html'
37
+ ]
38
+
39
+ // Main functions
40
+ // --------------
41
+
42
+ device.macos = function () {
43
+ return find('mac')
44
+ }
45
+
46
+ device.ios = function () {
47
+ return device.iphone() || device.ipod() || device.ipad()
48
+ }
49
+
50
+ device.iphone = function () {
51
+ return !device.windows() && find('iphone')
52
+ }
53
+
54
+ device.ipod = function () {
55
+ return find('ipod')
56
+ }
57
+
58
+ device.ipad = function () {
59
+ const iPadOS13Up =
60
+ navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1
61
+ return find('ipad') || iPadOS13Up
62
+ }
63
+
64
+ device.android = function () {
65
+ return !device.windows() && find('android')
66
+ }
67
+
68
+ device.androidPhone = function () {
69
+ return device.android() && find('mobile')
70
+ }
71
+
72
+ device.androidTablet = function () {
73
+ return device.android() && !find('mobile')
74
+ }
75
+
76
+ device.blackberry = function () {
77
+ return find('blackberry') || find('bb10')
78
+ }
79
+
80
+ device.blackberryPhone = function () {
81
+ return device.blackberry() && !find('tablet')
82
+ }
83
+
84
+ device.blackberryTablet = function () {
85
+ return device.blackberry() && find('tablet')
86
+ }
87
+
88
+ device.windows = function () {
89
+ return find('windows')
90
+ }
91
+
92
+ device.windowsPhone = function () {
93
+ return device.windows() && find('phone')
94
+ }
95
+
96
+ device.windowsTablet = function () {
97
+ return device.windows() && (find('touch') && !device.windowsPhone())
98
+ }
99
+
100
+ device.fxos = function () {
101
+ return (find('(mobile') || find('(tablet')) && find(' rv:')
102
+ }
103
+
104
+ device.fxosPhone = function () {
105
+ return device.fxos() && find('mobile')
106
+ }
107
+
108
+ device.fxosTablet = function () {
109
+ return device.fxos() && find('tablet')
110
+ }
111
+
112
+ device.meego = function () {
113
+ return find('meego')
114
+ }
115
+
116
+ device.cordova = function () {
117
+ return window.cordova && location.protocol === 'file:'
118
+ }
119
+
120
+ device.nodeWebkit = function () {
121
+ return typeof window.process === 'object'
122
+ }
123
+
124
+ device.mobile = function () {
125
+ return (
126
+ device.androidPhone() ||
127
+ device.iphone() ||
128
+ device.ipod() ||
129
+ device.windowsPhone() ||
130
+ device.blackberryPhone() ||
131
+ device.fxosPhone() ||
132
+ device.meego()
133
+ )
134
+ }
135
+
136
+ device.tablet = function () {
137
+ return (
138
+ device.ipad() ||
139
+ device.androidTablet() ||
140
+ device.blackberryTablet() ||
141
+ device.windowsTablet() ||
142
+ device.fxosTablet()
143
+ )
144
+ }
145
+
146
+ device.desktop = function () {
147
+ return !device.tablet() && !device.mobile()
148
+ }
149
+
150
+ device.television = function () {
151
+ let i = 0
152
+ while (i < television.length) {
153
+ if (find(television[i])) {
154
+ return true
155
+ }
156
+ i++
157
+ }
158
+ return false
159
+ }
160
+
161
+ device.portrait = function () {
162
+ if (
163
+ screen.orientation &&
164
+ Object.prototype.hasOwnProperty.call(window, 'onorientationchange')
165
+ ) {
166
+ return includes(screen.orientation.type, 'portrait')
167
+ }
168
+ if (
169
+ device.ios() &&
170
+ Object.prototype.hasOwnProperty.call(window, 'orientation')
171
+ ) {
172
+ return Math.abs(window.orientation) !== 90
173
+ }
174
+ return window.innerHeight / window.innerWidth > 1
175
+ }
176
+
177
+ device.landscape = function () {
178
+ if (
179
+ screen.orientation &&
180
+ Object.prototype.hasOwnProperty.call(window, 'onorientationchange')
181
+ ) {
182
+ return includes(screen.orientation.type, 'landscape')
183
+ }
184
+ if (
185
+ device.ios() &&
186
+ Object.prototype.hasOwnProperty.call(window, 'orientation')
187
+ ) {
188
+ return Math.abs(window.orientation) === 90
189
+ }
190
+ return window.innerHeight / window.innerWidth < 1
191
+ }
192
+
193
+ // Public Utility Functions
194
+ // ------------------------
195
+
196
+ // Run device.js in noConflict mode,
197
+ // returning the device variable to its previous owner.
198
+ device.noConflict = function () {
199
+ window.device = previousDevice
200
+ return this
201
+ }
202
+
203
+ // Private Utility Functions
204
+ // -------------------------
205
+
206
+ // Check if element exists
207
+ function includes (haystack, needle) {
208
+ return haystack.indexOf(needle) !== -1
209
+ }
210
+
211
+ // Simple UA string search
212
+ function find (needle) {
213
+ return includes(userAgent, needle)
214
+ }
215
+
216
+ // Check if documentElement already has a given class.
217
+ function hasClass (className) {
218
+ return documentElement.className.match(new RegExp(className, 'i'))
219
+ }
220
+
221
+ // Add one or more CSS classes to the <html> element.
222
+ function addClass (className) {
223
+ let currentClassNames = null
224
+ if (!hasClass(className)) {
225
+ currentClassNames = documentElement.className.replace(/^\s+|\s+$/g, '')
226
+ documentElement.className = `${currentClassNames} ${className}`
227
+ }
228
+ }
229
+
230
+ // Remove single CSS class from the <html> element.
231
+ function removeClass (className) {
232
+ if (hasClass(className)) {
233
+ documentElement.className = documentElement.className.replace(
234
+ ` ${className}`,
235
+ ''
236
+ )
237
+ }
238
+ }
239
+
240
+ function cleanClasses () {
241
+ const classes = [...os, ...type]
242
+ for (let i = 0; i < classes.length; i++) {
243
+ removeClass(classes[i])
244
+ }
245
+ }
246
+
247
+ // HTML Element Handling
248
+ // ---------------------
249
+
250
+ // Insert the appropriate CSS class based on the _user_agent.
251
+ function applyClass () {
252
+ cleanClasses()
253
+
254
+ if (device.ios()) {
255
+ if (device.ipad()) {
256
+ addClass('ios ipad tablet')
257
+ } else if (device.iphone()) {
258
+ addClass('ios iphone mobile')
259
+ } else if (device.ipod()) {
260
+ addClass('ios ipod mobile')
261
+ }
262
+ } else if (device.macos()) {
263
+ addClass('macos desktop')
264
+ } else if (device.android()) {
265
+ if (device.androidTablet()) {
266
+ addClass('android tablet')
267
+ } else {
268
+ addClass('android mobile')
269
+ }
270
+ } else if (device.blackberry()) {
271
+ if (device.blackberryTablet()) {
272
+ addClass('blackberry tablet')
273
+ } else {
274
+ addClass('blackberry mobile')
275
+ }
276
+ } else if (device.windows()) {
277
+ if (device.windowsTablet()) {
278
+ addClass('windows tablet')
279
+ } else if (device.windowsPhone()) {
280
+ addClass('windows mobile')
281
+ } else {
282
+ addClass('windows desktop')
283
+ }
284
+ } else if (device.fxos()) {
285
+ if (device.fxosTablet()) {
286
+ addClass('fxos tablet')
287
+ } else {
288
+ addClass('fxos mobile')
289
+ }
290
+ } else if (device.meego()) {
291
+ addClass('meego mobile')
292
+ } else if (device.nodeWebkit()) {
293
+ addClass('node-webkit')
294
+ } else if (device.television()) {
295
+ addClass('television')
296
+ } else if (device.desktop()) {
297
+ addClass('desktop')
298
+ }
299
+
300
+ if (device.cordova()) {
301
+ addClass('cordova')
302
+ }
303
+ }
304
+
305
+ applyClass()
306
+
307
+ // Orientation Handling
308
+ // --------------------
309
+
310
+ // Handle device orientation changes.
311
+ function handleOrientation () {
312
+ if (device.landscape()) {
313
+ removeClass('portrait')
314
+ addClass('landscape')
315
+ walkOnChangeOrientationList('landscape')
316
+ } else {
317
+ removeClass('landscape')
318
+ addClass('portrait')
319
+ walkOnChangeOrientationList('portrait')
320
+ }
321
+ setOrientationCache()
322
+ }
323
+
324
+ function walkOnChangeOrientationList (newOrientation) {
325
+ for (let index = 0; index < changeOrientationList.length; index++) {
326
+ changeOrientationList[index](newOrientation)
327
+ }
328
+ }
329
+
330
+ device.onChangeOrientation = function (cb) {
331
+ if (typeof cb === 'function') {
332
+ changeOrientationList.push(cb)
333
+ }
334
+ }
335
+
336
+ // Detect whether device supports orientationchange event,
337
+ // otherwise fall back to the resize event.
338
+ let orientationEvent = 'resize'
339
+ if (Object.prototype.hasOwnProperty.call(window, 'onorientationchange')) {
340
+ orientationEvent = 'orientationchange'
341
+ }
342
+
343
+ // Listen for changes in orientation.
344
+ if (window.addEventListener) {
345
+ window.addEventListener(orientationEvent, handleOrientation, false)
346
+ } else if (window.attachEvent) {
347
+ window.attachEvent(orientationEvent, handleOrientation)
348
+ } else {
349
+ window[orientationEvent] = handleOrientation
350
+ }
351
+
352
+ handleOrientation()
353
+
354
+ // Public functions to get the current value of type, os, or orientation
355
+ // ---------------------------------------------------------------------
356
+
357
+ function findMatch (arr) {
358
+ for (let i = 0; i < arr.length; i++) {
359
+ if (device[arr[i]]()) {
360
+ return arr[i]
361
+ }
362
+ }
363
+ return 'unknown'
364
+ }
365
+
366
+ device.type = findMatch(type)
367
+ device.os = findMatch(os)
368
+
369
+ function setOrientationCache () {
370
+ device.orientation = findMatch(['portrait', 'landscape'])
371
+ }
372
+
373
+ setOrientationCache()
374
+
375
+ let previousDeviceType = null
376
+ device.onDeviceChange = null
377
+
378
+ function updateDeviceDetection () {
379
+ userAgent = window.navigator.userAgent.toLowerCase()
380
+ device.type = findMatch(type)
381
+ device.os = findMatch(os)
382
+ setOrientationCache()
383
+ applyClass()
384
+ checkAndHandleDeviceChange()
385
+ }
386
+
387
+ window.addEventListener('resize', updateDeviceDetection)
388
+
389
+ function triggerOnDeviceChange () {
390
+ if (typeof device.onDeviceChange === 'function') {
391
+ device.onDeviceChange(device.type)
392
+ }
393
+ }
394
+
395
+ function checkAndHandleDeviceChange () {
396
+ const currentDeviceType = device.type
397
+ if (previousDeviceType !== currentDeviceType) {
398
+ triggerOnDeviceChange()
399
+ previousDeviceType = currentDeviceType
400
+ }
401
+ }
402
+
403
+ 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
  }