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();