|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 'use strict'; |
|
5 |
|
6 module.metadata = { |
|
7 'stability': 'experimental', |
|
8 'engines': { |
|
9 'Firefox': '> 28' |
|
10 } |
|
11 }; |
|
12 |
|
13 const { Class } = require('../../core/heritage'); |
|
14 const { merge } = require('../../util/object'); |
|
15 const { Disposable } = require('../../core/disposable'); |
|
16 const { on, off, emit, setListeners } = require('../../event/core'); |
|
17 const { EventTarget } = require('../../event/target'); |
|
18 const { getNodeView } = require('../../view/core'); |
|
19 |
|
20 const view = require('./view'); |
|
21 const { toggleButtonContract, toggleStateContract } = require('./contract'); |
|
22 const { properties, render, state, register, unregister, |
|
23 setStateFor, getStateFor, getDerivedStateFor } = require('../state'); |
|
24 const { events: stateEvents } = require('../state/events'); |
|
25 const { events: viewEvents } = require('./view/events'); |
|
26 const events = require('../../event/utils'); |
|
27 |
|
28 const { getActiveTab } = require('../../tabs/utils'); |
|
29 |
|
30 const { id: addonID } = require('../../self'); |
|
31 const { identify } = require('../id'); |
|
32 |
|
33 const buttons = new Map(); |
|
34 |
|
35 const toWidgetId = id => |
|
36 ('toggle-button--' + addonID.toLowerCase()+ '-' + id). |
|
37 replace(/[^a-z0-9_-]/g, ''); |
|
38 |
|
39 const ToggleButton = Class({ |
|
40 extends: EventTarget, |
|
41 implements: [ |
|
42 properties(toggleStateContract), |
|
43 state(toggleStateContract), |
|
44 Disposable |
|
45 ], |
|
46 setup: function setup(options) { |
|
47 let state = merge({ |
|
48 disabled: false, |
|
49 checked: false |
|
50 }, toggleButtonContract(options)); |
|
51 |
|
52 let id = toWidgetId(options.id); |
|
53 |
|
54 register(this, state); |
|
55 |
|
56 // Setup listeners. |
|
57 setListeners(this, options); |
|
58 |
|
59 buttons.set(id, this); |
|
60 |
|
61 view.create(merge({ type: 'checkbox' }, state, { id: id })); |
|
62 }, |
|
63 |
|
64 dispose: function dispose() { |
|
65 let id = toWidgetId(this.id); |
|
66 buttons.delete(id); |
|
67 |
|
68 off(this); |
|
69 |
|
70 view.dispose(id); |
|
71 |
|
72 unregister(this); |
|
73 }, |
|
74 |
|
75 get id() this.state().id, |
|
76 |
|
77 click: function click() view.click(toWidgetId(this.id)) |
|
78 }); |
|
79 exports.ToggleButton = ToggleButton; |
|
80 |
|
81 identify.define(ToggleButton, ({id}) => toWidgetId(id)); |
|
82 |
|
83 getNodeView.define(ToggleButton, button => |
|
84 view.nodeFor(toWidgetId(button.id)) |
|
85 ); |
|
86 |
|
87 let toggleButtonStateEvents = events.filter(stateEvents, |
|
88 e => e.target instanceof ToggleButton); |
|
89 |
|
90 let toggleButtonViewEvents = events.filter(viewEvents, |
|
91 e => buttons.has(e.target)); |
|
92 |
|
93 let clickEvents = events.filter(toggleButtonViewEvents, e => e.type === 'click'); |
|
94 let updateEvents = events.filter(toggleButtonViewEvents, e => e.type === 'update'); |
|
95 |
|
96 on(toggleButtonStateEvents, 'data', ({target, window, state}) => { |
|
97 let id = toWidgetId(target.id); |
|
98 |
|
99 view.setIcon(id, window, state.icon); |
|
100 view.setLabel(id, window, state.label); |
|
101 view.setDisabled(id, window, state.disabled); |
|
102 view.setChecked(id, window, state.checked); |
|
103 }); |
|
104 |
|
105 on(clickEvents, 'data', ({target: id, window, checked }) => { |
|
106 let button = buttons.get(id); |
|
107 let windowState = getStateFor(button, window); |
|
108 |
|
109 let newWindowState = merge({}, windowState, { checked: checked }); |
|
110 |
|
111 setStateFor(button, window, newWindowState); |
|
112 |
|
113 let state = getDerivedStateFor(button, getActiveTab(window)); |
|
114 |
|
115 emit(button, 'click', state); |
|
116 |
|
117 emit(button, 'change', state); |
|
118 }); |
|
119 |
|
120 on(updateEvents, 'data', ({target: id, window}) => { |
|
121 render(buttons.get(id), window); |
|
122 }); |