UNPKG

4.84 kBJavaScriptView Raw
1import { select } from "d3-selection";
2import { getDefaultParser, getDefaultFormatter } from "./lib/parse-format";
3import { sortArray } from "./lib/sort";
4import { injectCSS } from "./lib/css";
5import { createDropdown } from "./controls/dropdown.js";
6import { createButtons } from "./controls/buttons.js";
7import { createSlider } from "./controls/slider.js";
8import { getRemToPx } from "./lib/remToPx";
9
10
11var DEFAULTS = Object.freeze({
12 control_type: "dropdown",
13
14 // Dropdown
15 dropdown_width_mode: "auto",
16 dropdown_width_fixed: 20,
17
18 // Buttons
19 button_group: true,
20 button_group_width_mode: "fixed",
21 button_group_width_fixed: 20,
22
23 // Slider
24 slider_width: 15,
25 slider_handle_color: null,
26 slider_font_color: null,
27 slider_background_color: "#dddddd",
28
29 slider_handle_height: 1,
30 slider_track_height: 0.2,
31 slider_margin: 4.5,
32
33 slider_play_button: true,
34 slider_step_time: 2,
35 slider_loop: true,
36 slider_restart_pause: 0,
37
38 // Data typing
39 sort: "unsorted",
40 sort_temporal_format: "%Y",
41
42 _index_: null,
43 _is_playing_: false
44});
45
46
47function init(state, getParser, getFormatter) {
48 var control_obj = {};
49 getParser = getParser || getDefaultParser;
50 getFormatter = getFormatter || getDefaultFormatter;
51 var options = [];
52 var sorted_options = [];
53 var changeHandlers = [];
54 var container = document.createElement("div");
55 container.setAttribute("class", "fl-controls-container");
56 var dropdown_obj = createDropdown(control_obj, state, container);
57 var buttons_obj = createButtons(control_obj, state, container);
58 var slider_obj = createSlider(control_obj, state, container);
59
60 for (var key in DEFAULTS) {
61 if (state[key] === undefined) state[key] = DEFAULTS[key];
62 }
63
64 var current_index = state._index_;
65
66 var checkValidIndex = function(i) {
67 return options.length && i >= 0 && i < options.length;
68 };
69
70 var updateControls = function(sorted_options) {
71 container.style.display = (sorted_options.length > 1) ? null : "none";
72 container.style.width = "";
73 slider_obj.update(sorted_options); // Do slider first in case we're stopping playing
74 dropdown_obj.update(sorted_options);
75 buttons_obj.update(sorted_options);
76 };
77
78 control_obj.appendTo = function(parent_container, bounding_container) {
79 injectCSS();
80 select(parent_container).node().appendChild(container);
81 dropdown_obj.appendedToDOM(bounding_container);
82 return control_obj;
83 };
84
85 var callOnChangeCallbacks = function() {
86 var index = indexFunction();
87 var value = options[index];
88 changeHandlers.forEach(function(func) {
89 func(value, index);
90 });
91 return control_obj;
92 };
93
94 control_obj.remove = function() {
95 if (container.parentElement) container.parentElement.removeChild(container);
96 dropdown_obj.removedFromDOM();
97
98 return control_obj;
99 };
100
101 control_obj.options = function(arr) {
102 if (arr === undefined) return options.slice();
103 if (!Array.isArray(arr)) return control_obj;
104 options = arr.slice();
105 var n = options.length;
106 var i = indexFunction();
107 if (!n) indexFunction(null);
108 else if (i === null || i >= n) indexFunction(0);
109 return control_obj;
110 };
111
112 Object.defineProperty(control_obj, "n_options", { get: function() { return options.length; } });
113
114
115 var indexFunction = function(i) {
116 if (i === undefined) {
117 if (!state._is_playing_) current_index = state._index_;
118 return current_index;
119 }
120 if (i === null || checkValidIndex(i)) {
121 current_index = i;
122 if (!state._is_playing_) state._index_ = current_index;
123 }
124 else console.warn("Invalid index, ignoring update call");
125 return control_obj;
126 };
127 control_obj.index = indexFunction;
128
129 control_obj.getSortedIndex = function() {
130 var options_index = indexFunction();
131 if (state.sort == "unsorted") return options_index;
132 var sorted_index;
133 sorted_options.some(function(d, i) {
134 if (d.options_index === options_index) {
135 sorted_index = i;
136 return true;
137 }
138 });
139 return sorted_index;
140 };
141
142 control_obj.value = function(value) {
143 if (value === undefined) return options[indexFunction()];
144 var index = options.indexOf(value);
145 if (index !== -1) indexFunction(index);
146 return control_obj;
147 };
148
149 control_obj.on = function(event, callback) {
150 if (event === "change") changeHandlers.push(callback.bind(control_obj));
151 return control_obj;
152 };
153
154 control_obj.update = function() {
155 getRemToPx();
156 sorted_options = sortArray(options, state, getParser(), getFormatter());
157 updateControls(sorted_options);
158 return control_obj;
159 };
160
161 control_obj.trigger = function(event) {
162 if (event === "change") callOnChangeCallbacks();
163 return control_obj;
164 };
165
166 var isPlaying = function(is_playing) {
167 if (is_playing === undefined) return state._is_playing_;
168 state._is_playing_ = !!is_playing;
169 if (!is_playing) indexFunction(current_index); // Force _index_ to match current index
170 };
171
172 control_obj._isPlaying_ = isPlaying;
173
174 return control_obj;
175}
176
177
178export default init;