addon-sdk/source/lib/sdk/ui/button/toggle.js

branch
TOR_BUG_3246
changeset 7
129ffea94266
equal deleted inserted replaced
-1:000000000000 0:751b8ac0ba3b
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 });

mercurial