1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
6 * Global exports, used locally to separate initialization from declaration.
12 * Toggle between filters 0 and 1 in order to force a repaint.
13 * TODO(kevers): Consolidate with filter in CVD.
16 var activeFilterIndex
= 0;
19 * Save previous state of setup parameters for use in the event of a canceled
21 * @type {{type: string, severity: number} | undefined}
23 var restoreSettings
= undefined;
26 * The strings for CVD Types.
27 * TODO(mustaq): Define an enum in cvd.js instead.
28 * @const {array{string}}
37 * Vertical offset for displaying the row highlight.
40 var HIGHLIGHT_OFFSET
= 7;
42 // ======= Swatch generator =======
45 * Set of colors for test swatches.
46 * Each row of swatches corresponds to a different type of color blindness.
47 * Tests for the 3 different types of dichromatic color vison.
48 * Colors selected based on color confusion lines for dichromats using our
49 * swatch generator tool. See:
50 * http://www.color-blindness.com/2007/01/23/confusion-lines-of-the-cie-1931-color-space/
54 BACKGROUND
: [194,66,96],
55 PROTANOMALY
: [123,73,103],
56 DEUTERANOMALY
: [131,91,97],
57 TRITANOMALY
: [182,57,199]
60 BACKGROUND
: [156,90,94],
61 PROTANOMALY
: [100,96,97],
62 DEUTERANOMALY
: [106,110,95],
63 TRITANOMALY
: [165,100,0]
66 BACKGROUND
: [201,110,50],
67 PROTANOMALY
: [125,120,52],
68 DEUTERANOMALY
: [135,136,51],
69 TRITANOMALY
: [189,99,163]
72 BACKGROUND
: [90,180,60],
73 PROTANOMALY
: [161,171,57],
74 DEUTERANOMALY
: [156,154,59],
75 TRITANOMALY
: [84,151,247]
78 BACKGROUND
: [30,172,150],
79 PROTANOMALY
: [114,163,144],
80 DEUTERANOMALY
: [97,146,148],
81 TRITANOMALY
: [31,154,246]
84 BACKGROUND
: [50,99,144],
85 PROTANOMALY
: [145,90,135],
86 DEUTERANOMALY
: [97,81,142],
87 TRITANOMALY
: [52,112,59]
90 BACKGROUND
: [91,72,147],
91 PROTANOMALY
: [62,74,151],
92 DEUTERANOMALY
: [63,83,148],
93 TRITANOMALY
: [102,88,12]
98 * Creates a radio button for selecting the given type of CVD and a series of
99 * color swatches for testing color vision.
100 * @param {string} cvdType Type of CVD, either "PROTANOMALY" or
101 * "DEUTERANOMALY" or "TRITANOMALY".
102 * @return {!Element} Row of color swatches with a leading radio button.
104 function createTestRow(type
) {
105 var toCssColor = function(rgb
) {
106 return 'rgb(' + rgb
.join(',') + ')';
108 var row
= document
.createElement('label');
109 row
.classList
.add('row');
111 var button
= document
.createElement('input');
112 button
.id
= 'select-' + type
;
113 button
.name
= 'cvdType';
114 button
.setAttribute('type', 'radio');
116 button
.checked
= false;
117 row
.appendChild(button
);
118 button
.addEventListener('change', function() {
119 onTypeChange(this.value
);
121 button
.setAttribute('aria-label', type
);
123 SWATCH_COLORS
.forEach(function(data
) {
124 var swatch
= document
.querySelector('.swatch.template').cloneNode(true);
125 swatch
.style
.background
= toCssColor(data
.BACKGROUND
);
126 swatch
.style
.color
= toCssColor(data
[type
]);
127 swatch
.classList
.remove('template');
128 row
.appendChild(swatch
);
134 // ======= UI hooks =======
137 * Gets the CVD type selected through the radio buttons.
140 function getCvdTypeSelection() {
141 var active
= undefined;
142 CVD_TYPES
.forEach(function(str
) {
143 if ($('select-' + str
).checked
) {
153 * Sets the radio buttons selection to the given CVD type.
154 * @param {string} cvdType Type of CVD, either "PROTANOMALY" or
155 * "DEUTERANOMALY" or "TRITANOMALY".
158 function setCvdTypeSelection(cvdType
) {
159 var highlight
= $('row-highlight');
160 highlight
.hidden
= true;
161 CVD_TYPES
.forEach(function(str
) {
162 var checkbox
= $('select-' + str
);
163 if (cvdType
== str
) {
164 checkbox
.checked
= true;
165 var top
= checkbox
.parentElement
.offsetTop
- HIGHLIGHT_OFFSET
;
166 highlight
.style
.top
= top
+ 'px';
167 highlight
.hidden
= false;
169 checkbox
.checked
= false;
175 * Styles controls based on stage of setup.
177 function updateControls() {
178 if ($('setup-panel').classList
.contains('collapsed')) {
179 // Not performing setup. Ensure main controls are enabled.
180 $('enable').disabled
= false;
181 $('delta').disabled
= false;
182 $('setup').disabled
= false;
184 // Disable main controls during setup phase.
185 $('enable').disabled
= true;
186 $('delta').disabled
= true;
187 $('setup').disabled
= true;
189 if (!getCvdTypeSelection()) {
190 // Have not selected a CVD type. Mark Step 1 as active.
191 $('step-1').classList
.add('active');
192 $('step-2').classList
.remove('active');
193 // Disable "step 2" controls.
194 $('severity').disabled
= true;
195 $('reset').disabled
= true;
197 $('step-1').classList
.remove('active');
198 $('step-2').classList
.add('active');
199 // Enable "step 2" controls.
200 $('severity').disabled
= false;
201 $('reset').disabled
= false;
202 // Force filter update.
203 onSeverityChange(parseFloat($('severity').value
));
209 * Update the popup controls based on settings for this site or the default.
210 * @return {boolean} True if settings are valid and update performed.
213 var type
= getDefaultType();
214 var validType
= false;
215 CVD_TYPES
.forEach(function(cvdType
) {
216 if (cvdType
== type
) {
226 $('delta').value
= getSiteDelta(site
);
228 $('delta').value
= getDefaultDelta();
231 $('severity').value
= getDefaultSeverity();
233 if (!$('setup-panel').classList
.contains('collapsed'))
234 setCvdTypeSelection(getDefaultType());
235 $('enable').checked
= getDefaultEnable();
237 debugPrint('update: ' +
238 ' del=' + $('delta').value
+
239 ' sev=' + $('severity').value
+
240 ' typ=' + getDefaultType() +
241 ' enb=' + $('enable').checked
+
244 chrome
.extension
.getBackgroundPage().updateTabs();
249 * Callback for color rotation slider.
251 * @param {number} value Parsed value of slider element.
253 function onDeltaChange(value
) {
254 debugPrint('onDeltaChange: ' + value
+ ' for ' + site
);
256 setSiteDelta(site
, value
);
258 setDefaultDelta(value
);
263 * Callback for severity slider.
265 * @param {number} value Parsed value of slider element.
267 function onSeverityChange(value
) {
268 debugPrint('onSeverityChange: ' + value
+ ' for ' + site
);
269 setDefaultSeverity(value
);
271 // Apply filter to popup swatches.
272 var filter
= window
.getDefaultCvdCorrectionFilter(
273 getCvdTypeSelection(), value
);
274 injectColorEnhancementFilter(filter
);
276 window
.getComputedStyle(document
.documentElement
, null);
280 * Callback for changing color deficiency type.
282 * @param {string} value Value of dropdown element.
284 function onTypeChange(value
) {
285 debugPrint('onTypeChange: ' + value
+ ' for ' + site
);
286 setDefaultType(value
);
288 // TODO(kevers): reset severity to effectively disable filter.
289 activeFilterType
= value
;
290 $('severity').value
= 0;
295 * Callback for enable/disable setting.
297 * @param {boolean} value Value of checkbox element.
299 function onEnableChange(value
) {
300 debugPrint('onEnableChange: ' + value
+ ' for ' + site
);
301 setDefaultEnable(value
);
303 // Settings are not valid for a reconfiguration.
304 $('setup').onclick();
309 * Callback for resetting stored per-site values.
312 debugPrint('onReset');
318 * Attach event handlers to controls and update the filter config values for
319 * the currently visible tab.
321 function initialize() {
322 var i18nElements
= document
.querySelectorAll('*[i18n-content]');
323 for (var i
= 0; i
< i18nElements
.length
; i
++) {
324 var elem
= i18nElements
[i
];
325 var msg
= elem
.getAttribute('i18n-content');
326 elem
.textContent
= chrome
.i18n
.getMessage(msg
);
329 $('setup').onclick = function() {
330 $('setup-panel').classList
.remove('collapsed');
331 // Store current settings in the event of a canceled setup.
333 type
: getDefaultType(),
334 severity
: getDefaultSeverity()
336 // Initalize controls based on current settings.
337 setCvdTypeSelection(restoreSettings
.type
);
338 $('severity').value
= restoreSettings
.severity
;
342 $('delta').addEventListener('input', function() {
343 onDeltaChange(parseFloat(this.value
));
345 $('severity').addEventListener('input', function() {
346 onSeverityChange(parseFloat(this.value
));
348 $('enable').addEventListener('change', function() {
349 onEnableChange(this.checked
);
352 $('reset').onclick = function() {
353 setDefaultSeverity(0);
355 setDefaultEnable(false);
356 $('severity').value
= 0;
357 $('enable').checked
= false;
358 setCvdTypeSelection('');
360 clearColorEnhancementFilter();
362 $('reset').hidden
= !IS_DEV_MODE
;
364 var closeSetup = function() {
365 $('setup-panel').classList
.add('collapsed');
369 $('ok').onclick = function() {
373 $('cancel').onclick = function() {
375 if (restoreSettings
) {
377 'restore previous settings: ' +
378 'type = ' + restoreSettings
.type
+
379 ', severity = ' + restoreSettings
.severity
);
380 setDefaultType(restoreSettings
.type
);
381 setDefaultSeverity(restoreSettings
.severity
);
385 var swatches
= $('swatches');
386 CVD_TYPES
.forEach(function(cvdType
) {
387 swatches
.appendChild(createTestRow(cvdType
));
390 chrome
.windows
.getLastFocused({'populate': true}, function(window
) {
391 for (var i
= 0; i
< window
.tabs
.length
; i
++) {
392 var tab
= window
.tabs
[i
];
394 site
= siteFromUrl(tab
.url
);
395 debugPrint('init: active tab update for ' + site
);
400 site
= 'unknown site';
406 * Runs initialize once popup loading is complete.
408 exports
.initializeOnLoad = function() {
409 var ready
= new Promise(function readyPromise(resolve
) {
410 if (document
.readyState
=== 'complete') {
413 document
.addEventListener('DOMContentLoaded', resolve
);
415 ready
.then(initialize
);
419 this.initializeOnLoad();