OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 /** | 5 /** |
6 * @fileoverview The ChromeVox panel and menus. | 6 * @fileoverview The ChromeVox panel and menus. |
7 */ | 7 */ |
8 | 8 |
9 goog.provide('Panel'); | 9 goog.provide('Panel'); |
10 | 10 |
11 goog.require('BrailleCommandHandler'); | 11 goog.require('BrailleCommandHandler'); |
12 goog.require('ISearchUI'); | 12 goog.require('ISearchUI'); |
13 goog.require('Msgs'); | 13 goog.require('Msgs'); |
14 goog.require('PanelCommand'); | 14 goog.require('PanelCommand'); |
15 goog.require('PanelMenu'); | 15 goog.require('PanelMenu'); |
16 goog.require('PanelMenuItem'); | 16 goog.require('PanelMenuItem'); |
17 goog.require('Tutorial'); | 17 goog.require('Tutorial'); |
18 goog.require('cvox.ChromeVoxKbHandler'); | 18 goog.require('cvox.ChromeVoxKbHandler'); |
19 goog.require('cvox.CommandStore'); | 19 goog.require('cvox.CommandStore'); |
20 | 20 |
21 /** | 21 /** |
22 * Class to manage the panel. | 22 * Class to manage the panel. |
23 * @constructor | 23 * @constructor |
24 */ | 24 */ |
25 Panel = function() { | 25 Panel = function() {}; |
26 }; | |
27 | 26 |
28 /** | 27 /** |
29 * @enum {string} | 28 * @enum {string} |
30 */ | 29 */ |
31 Panel.Mode = { | 30 Panel.Mode = { |
32 COLLAPSED: 'collapsed', | 31 COLLAPSED: 'collapsed', |
33 FOCUSED: 'focused', | 32 FOCUSED: 'focused', |
34 FULLSCREEN_MENUS: 'menus', | 33 FULLSCREEN_MENUS: 'menus', |
35 FULLSCREEN_TUTORIAL: 'tutorial', | 34 FULLSCREEN_TUTORIAL: 'tutorial', |
36 SEARCH: 'search' | 35 SEARCH: 'search' |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
77 /** @type {Element} @private */ | 76 /** @type {Element} @private */ |
78 this.searchInput_ = $('search'); | 77 this.searchInput_ = $('search'); |
79 | 78 |
80 /** @type {Element} @private */ | 79 /** @type {Element} @private */ |
81 this.brailleTableElement_ = $('braille-table'); | 80 this.brailleTableElement_ = $('braille-table'); |
82 this.brailleTableElement2_ = $('braille-table2'); | 81 this.brailleTableElement2_ = $('braille-table2'); |
83 | 82 |
84 /** @type {Panel.Mode} @private */ | 83 /** @type {Panel.Mode} @private */ |
85 this.mode_ = Panel.Mode.COLLAPSED; | 84 this.mode_ = Panel.Mode.COLLAPSED; |
86 | 85 |
87 var blockedSessionQuery = location.search.match( | 86 var blockedSessionQuery = |
88 /[?&]?blockedUserSession=(true|false)/); | 87 location.search.match(/[?&]?blockedUserSession=(true|false)/); |
89 /** | 88 /** |
90 * Whether the panel is loaded for blocked user session - e.g. on sign-in or | 89 * Whether the panel is loaded for blocked user session - e.g. on sign-in or |
91 * lock screen. | 90 * lock screen. |
92 * @type {boolean} | 91 * @type {boolean} |
93 * @private @const | 92 * @private @const |
94 */ | 93 */ |
95 this.isUserSessionBlocked_ = | 94 this.isUserSessionBlocked_ = |
96 !!blockedSessionQuery && blockedSessionQuery[1] == 'true'; | 95 !!blockedSessionQuery && blockedSessionQuery[1] == 'true'; |
97 | 96 |
98 /** | 97 /** |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
130 Msgs.addTranslatedMessagesToDom(document); | 129 Msgs.addTranslatedMessagesToDom(document); |
131 | 130 |
132 window.addEventListener('storage', function(event) { | 131 window.addEventListener('storage', function(event) { |
133 if (event.key == 'brailleCaptions') { | 132 if (event.key == 'brailleCaptions') { |
134 Panel.updateFromPrefs(); | 133 Panel.updateFromPrefs(); |
135 } | 134 } |
136 }, false); | 135 }, false); |
137 | 136 |
138 window.addEventListener('message', function(message) { | 137 window.addEventListener('message', function(message) { |
139 var command = JSON.parse(message.data); | 138 var command = JSON.parse(message.data); |
140 Panel.exec(/** @type {PanelCommand} */(command)); | 139 Panel.exec(/** @type {PanelCommand} */ (command)); |
141 }, false); | 140 }, false); |
142 | 141 |
143 if (this.isUserSessionBlocked_) { | 142 if (this.isUserSessionBlocked_) { |
144 $('menus_button').disabled = true; | 143 $('menus_button').disabled = true; |
145 $('triangle').hidden = true; | 144 $('triangle').hidden = true; |
146 | 145 |
147 $('options').disabled = true; | 146 $('options').disabled = true; |
148 } else { | 147 } else { |
149 $('menus_button').addEventListener('mousedown', Panel.onOpenMenus, false); | 148 $('menus_button').addEventListener('mousedown', Panel.onOpenMenus, false); |
150 $('options').addEventListener('click', Panel.onOptions, false); | 149 $('options').addEventListener('click', Panel.onOptions, false); |
151 } | 150 } |
152 | 151 |
153 $('close').addEventListener('click', Panel.onClose, false); | 152 $('close').addEventListener('click', Panel.onClose, false); |
154 | 153 |
155 $('tutorial_next').addEventListener('click', Panel.onTutorialNext, false); | 154 $('tutorial_next').addEventListener('click', Panel.onTutorialNext, false); |
156 $('tutorial_previous').addEventListener( | 155 $('tutorial_previous') |
157 'click', Panel.onTutorialPrevious, false); | 156 .addEventListener('click', Panel.onTutorialPrevious, false); |
158 $('close_tutorial').addEventListener('click', Panel.onCloseTutorial, false); | 157 $('close_tutorial').addEventListener('click', Panel.onCloseTutorial, false); |
159 | 158 |
160 document.addEventListener('keydown', Panel.onKeyDown, false); | 159 document.addEventListener('keydown', Panel.onKeyDown, false); |
161 document.addEventListener('mouseup', Panel.onMouseUp, false); | 160 document.addEventListener('mouseup', Panel.onMouseUp, false); |
162 window.addEventListener('blur', function(evt) { | 161 window.addEventListener('blur', function(evt) { |
163 if (evt.target != window || document.activeElement == document.body) | 162 if (evt.target != window || document.activeElement == document.body) |
164 return; | 163 return; |
165 | 164 |
166 Panel.closeMenusAndRestoreFocus(); | 165 Panel.closeMenusAndRestoreFocus(); |
167 }, false); | 166 }, false); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
216 } | 215 } |
217 | 216 |
218 switch (command.type) { | 217 switch (command.type) { |
219 case PanelCommandType.CLEAR_SPEECH: | 218 case PanelCommandType.CLEAR_SPEECH: |
220 this.speechElement_.innerHTML = ''; | 219 this.speechElement_.innerHTML = ''; |
221 break; | 220 break; |
222 case PanelCommandType.ADD_NORMAL_SPEECH: | 221 case PanelCommandType.ADD_NORMAL_SPEECH: |
223 if (this.speechElement_.innerHTML != '') { | 222 if (this.speechElement_.innerHTML != '') { |
224 this.speechElement_.innerHTML += ' '; | 223 this.speechElement_.innerHTML += ' '; |
225 } | 224 } |
226 this.speechElement_.innerHTML += '<span class="usertext">' + | 225 this.speechElement_.innerHTML += |
227 escapeForHtml(command.data) + | 226 '<span class="usertext">' + escapeForHtml(command.data) + '</span>'; |
228 '</span>'; | |
229 break; | 227 break; |
230 case PanelCommandType.ADD_ANNOTATION_SPEECH: | 228 case PanelCommandType.ADD_ANNOTATION_SPEECH: |
231 if (this.speechElement_.innerHTML != '') { | 229 if (this.speechElement_.innerHTML != '') { |
232 this.speechElement_.innerHTML += ' '; | 230 this.speechElement_.innerHTML += ' '; |
233 } | 231 } |
234 this.speechElement_.innerHTML += escapeForHtml(command.data); | 232 this.speechElement_.innerHTML += escapeForHtml(command.data); |
235 break; | 233 break; |
236 case PanelCommandType.UPDATE_BRAILLE: | 234 case PanelCommandType.UPDATE_BRAILLE: |
237 Panel.onUpdateBraille(command.data); | 235 Panel.onUpdateBraille(command.data); |
238 break; | 236 break; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
281 | 279 |
282 /** | 280 /** |
283 * Sets the mode, which determines the size of the panel and what objects | 281 * Sets the mode, which determines the size of the panel and what objects |
284 * are shown or hidden. | 282 * are shown or hidden. |
285 * @param {Panel.Mode} mode The new mode. | 283 * @param {Panel.Mode} mode The new mode. |
286 */ | 284 */ |
287 Panel.setMode = function(mode) { | 285 Panel.setMode = function(mode) { |
288 if (this.mode_ == mode) | 286 if (this.mode_ == mode) |
289 return; | 287 return; |
290 | 288 |
291 if (this.isUserSessionBlocked_ && | 289 if (this.isUserSessionBlocked_ && mode != Panel.Mode.COLLAPSED && |
292 mode != Panel.Mode.COLLAPSED && mode != Panel.Mode.FOCUSED) | 290 mode != Panel.Mode.FOCUSED) |
293 return; | 291 return; |
294 this.mode_ = mode; | 292 this.mode_ = mode; |
295 | 293 |
296 document.title = Msgs.getMsg(Panel.ModeInfo[this.mode_].title); | 294 document.title = Msgs.getMsg(Panel.ModeInfo[this.mode_].title); |
297 | 295 |
298 // Fully qualify the path here because this function might be called with a | 296 // Fully qualify the path here because this function might be called with a |
299 // window object belonging to the background page. | 297 // window object belonging to the background page. |
300 Panel.ownerWindow.location = | 298 Panel.ownerWindow.location = |
301 chrome.extension.getURL('cvox2/background/panel.html') + | 299 chrome.extension.getURL('cvox2/background/panel.html') + |
302 Panel.ModeInfo[this.mode_].location; | 300 Panel.ModeInfo[this.mode_].location; |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
342 'navigation': jumpMenu, | 340 'navigation': jumpMenu, |
343 'jump_commands': jumpMenu, | 341 'jump_commands': jumpMenu, |
344 'overview': jumpMenu, | 342 'overview': jumpMenu, |
345 'tables': jumpMenu, | 343 'tables': jumpMenu, |
346 'controlling_speech': speechMenu, | 344 'controlling_speech': speechMenu, |
347 'information': speechMenu, | 345 'information': speechMenu, |
348 'modifier_keys': chromevoxMenu, | 346 'modifier_keys': chromevoxMenu, |
349 'help_commands': chromevoxMenu, | 347 'help_commands': chromevoxMenu, |
350 | 348 |
351 'braille': null, | 349 'braille': null, |
352 'developer': null}; | 350 'developer': null |
| 351 }; |
353 | 352 |
354 // Get the key map from the background page. | 353 // Get the key map from the background page. |
355 var bkgnd = chrome.extension.getBackgroundPage(); | 354 var bkgnd = chrome.extension.getBackgroundPage(); |
356 var keymap = bkgnd['cvox']['KeyMap']['fromCurrentKeyMap'](); | 355 var keymap = bkgnd['cvox']['KeyMap']['fromCurrentKeyMap'](); |
357 | 356 |
358 // Make a copy of the key bindings, get the localized title of each | 357 // Make a copy of the key bindings, get the localized title of each |
359 // command, and then sort them. | 358 // command, and then sort them. |
360 var sortedBindings = keymap.bindings().slice(); | 359 var sortedBindings = keymap.bindings().slice(); |
361 sortedBindings.forEach(goog.bind(function(binding) { | 360 sortedBindings.forEach(goog.bind(function(binding) { |
362 var command = binding.command; | 361 var command = binding.command; |
(...skipping 20 matching lines...) Expand all Loading... |
383 var sawBindingSet = {}; | 382 var sawBindingSet = {}; |
384 sortedBindings.forEach(goog.bind(function(binding) { | 383 sortedBindings.forEach(goog.bind(function(binding) { |
385 var command = binding.command; | 384 var command = binding.command; |
386 if (sawBindingSet[command]) | 385 if (sawBindingSet[command]) |
387 return; | 386 return; |
388 sawBindingSet[command] = true; | 387 sawBindingSet[command] = true; |
389 var category = cvox.CommandStore.categoryForCommand(binding.command); | 388 var category = cvox.CommandStore.categoryForCommand(binding.command); |
390 var menu = category ? categoryToMenu[category] : null; | 389 var menu = category ? categoryToMenu[category] : null; |
391 if (binding.title && menu) { | 390 if (binding.title && menu) { |
392 menu.addMenuItem( | 391 menu.addMenuItem( |
393 binding.title, | 392 binding.title, binding.keySeq, |
394 binding.keySeq, | |
395 BrailleCommandHandler.getDotShortcut(binding.command, true), | 393 BrailleCommandHandler.getDotShortcut(binding.command, true), |
396 function() { | 394 function() { |
397 var CommandHandler = | 395 var CommandHandler = |
398 chrome.extension.getBackgroundPage()['CommandHandler']; | 396 chrome.extension.getBackgroundPage()['CommandHandler']; |
399 CommandHandler['onCommand'](binding.command); | 397 CommandHandler['onCommand'](binding.command); |
400 }); | 398 }); |
401 } | 399 } |
402 }, this)); | 400 }, this)); |
403 | 401 |
404 // Add all open tabs to the Tabs menu. | 402 // Add all open tabs to the Tabs menu. |
405 bkgnd.chrome.windows.getLastFocused(function(lastFocusedWindow) { | 403 bkgnd.chrome.windows.getLastFocused(function(lastFocusedWindow) { |
406 bkgnd.chrome.windows.getAll({'populate': true}, function(windows) { | 404 bkgnd.chrome.windows.getAll({'populate': true}, function(windows) { |
407 for (var i = 0; i < windows.length; i++) { | 405 for (var i = 0; i < windows.length; i++) { |
408 var tabs = windows[i].tabs; | 406 var tabs = windows[i].tabs; |
409 for (var j = 0; j < tabs.length; j++) { | 407 for (var j = 0; j < tabs.length; j++) { |
410 var title = tabs[j].title; | 408 var title = tabs[j].title; |
411 if (tabs[j].active && windows[i].id == lastFocusedWindow.id) | 409 if (tabs[j].active && windows[i].id == lastFocusedWindow.id) |
412 title += ' ' + Msgs.getMsg('active_tab'); | 410 title += ' ' + Msgs.getMsg('active_tab'); |
413 tabsMenu.addMenuItem(title, '', '', (function(win, tab) { | 411 tabsMenu.addMenuItem( |
414 bkgnd.chrome.windows.update(win.id, {focused: true}, function() { | 412 title, '', '', (function(win, tab) { |
415 bkgnd.chrome.tabs.update(tab.id, {active: true}); | 413 bkgnd.chrome.windows.update( |
416 }); | 414 win.id, {focused: true}, function() { |
417 }).bind(this, windows[i], tabs[j])); | 415 bkgnd.chrome.tabs.update( |
| 416 tab.id, {active: true}); |
| 417 }); |
| 418 }).bind(this, windows[i], tabs[j])); |
418 } | 419 } |
419 } | 420 } |
420 }); | 421 }); |
421 }); | 422 }); |
422 | 423 |
423 // Add a menu item that disables / closes ChromeVox. | 424 // Add a menu item that disables / closes ChromeVox. |
424 chromevoxMenu.addMenuItem( | 425 chromevoxMenu.addMenuItem( |
425 Msgs.getMsg('disable_chromevox'), 'Ctrl+Alt+Z', '', function() { | 426 Msgs.getMsg('disable_chromevox'), 'Ctrl+Alt+Z', '', function() { |
426 Panel.onClose(); | 427 Panel.onClose(); |
427 }); | 428 }); |
428 | 429 |
429 var roleListMenuMapping = [ | 430 var roleListMenuMapping = [ |
430 { menuTitle: 'role_heading', predicate: AutomationPredicate.heading }, | 431 {menuTitle: 'role_heading', predicate: AutomationPredicate.heading}, |
431 { menuTitle: 'role_landmark', predicate: AutomationPredicate.landmark }, | 432 {menuTitle: 'role_landmark', predicate: AutomationPredicate.landmark}, |
432 { menuTitle: 'role_link', predicate: AutomationPredicate.link }, | 433 {menuTitle: 'role_link', predicate: AutomationPredicate.link}, |
433 { menuTitle: 'role_form', predicate: AutomationPredicate.formField }, | 434 {menuTitle: 'role_form', predicate: AutomationPredicate.formField}, |
434 { menuTitle: 'role_table', predicate: AutomationPredicate.table }]; | 435 {menuTitle: 'role_table', predicate: AutomationPredicate.table} |
| 436 ]; |
435 | 437 |
436 var node = bkgnd.ChromeVoxState.instance.getCurrentRange().start.node; | 438 var node = bkgnd.ChromeVoxState.instance.getCurrentRange().start.node; |
437 for (var i = 0; i < roleListMenuMapping.length; ++i) { | 439 for (var i = 0; i < roleListMenuMapping.length; ++i) { |
438 var menuTitle = roleListMenuMapping[i].menuTitle; | 440 var menuTitle = roleListMenuMapping[i].menuTitle; |
439 var predicate = roleListMenuMapping[i].predicate; | 441 var predicate = roleListMenuMapping[i].predicate; |
440 // Create node menus asynchronously (because it may require searching a | 442 // Create node menus asynchronously (because it may require searching a |
441 // long document) unless that's the specific menu the | 443 // long document) unless that's the specific menu the |
442 // user requested. | 444 // user requested. |
443 var async = (menuTitle != opt_activateMenuTitle); | 445 var async = (menuTitle != opt_activateMenuTitle); |
444 Panel.addNodeMenu(menuTitle, node, predicate, async); | 446 Panel.addNodeMenu(menuTitle, node, predicate, async); |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
586 row1 = this.brailleTableElement_.insertRow(-1); | 588 row1 = this.brailleTableElement_.insertRow(-1); |
587 if (sideBySide) { | 589 if (sideBySide) { |
588 // Side by side. | 590 // Side by side. |
589 row2 = this.brailleTableElement2_.insertRow(-1); | 591 row2 = this.brailleTableElement2_.insertRow(-1); |
590 } else { | 592 } else { |
591 // Interleaved. | 593 // Interleaved. |
592 row2 = this.brailleTableElement_.insertRow(-1); | 594 row2 = this.brailleTableElement_.insertRow(-1); |
593 } | 595 } |
594 var bottomCell2 = row2.insertCell(-1); | 596 var bottomCell2 = row2.insertCell(-1); |
595 bottomCell2.id = i + '-brailleCell2'; | 597 bottomCell2.id = i + '-brailleCell2'; |
596 bottomCell2.setAttribute('data-companionIDs', | 598 bottomCell2.setAttribute( |
597 i + '-textCell ' + i + '-brailleCell'); | 599 'data-companionIDs', i + '-textCell ' + i + '-brailleCell'); |
598 bottomCell.setAttribute('data-companionIDs', | 600 bottomCell.setAttribute( |
599 bottomCell.getAttribute('data-companionIDs') + | 601 'data-companionIDs', |
600 ' ' + i + '-brailleCell2'); | 602 bottomCell.getAttribute('data-companionIDs') + ' ' + i + |
601 topCell.setAttribute('data-companionID2', | 603 '-brailleCell2'); |
602 bottomCell.getAttribute('data-companionIDs') + | 604 topCell.setAttribute( |
603 ' ' + i + '-brailleCell2'); | 605 'data-companionID2', |
| 606 bottomCell.getAttribute('data-companionIDs') + ' ' + i + |
| 607 '-brailleCell2'); |
604 | 608 |
605 bottomCell2.className = 'unhighlighted-cell'; | 609 bottomCell2.className = 'unhighlighted-cell'; |
606 bottomCell = bottomCell2; | 610 bottomCell = bottomCell2; |
607 cellCount = 0; | 611 cellCount = 0; |
608 } | 612 } |
609 // Fill the rest. | 613 // Fill the rest. |
610 bottomCell.innerHTML = brailleText; | 614 bottomCell.innerHTML = brailleText; |
611 cellCount = brailleText.length; | 615 cellCount = brailleText.length; |
612 } else { | 616 } else { |
613 bottomCell.innerHTML = groups[i][1]; | 617 bottomCell.innerHTML = groups[i][1]; |
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
839 // Clear it before calling it, in case the callback itself triggers | 843 // Clear it before calling it, in case the callback itself triggers |
840 // another pending callback. | 844 // another pending callback. |
841 var pendingCallback = Panel.pendingCallback_; | 845 var pendingCallback = Panel.pendingCallback_; |
842 Panel.pendingCallback_ = null; | 846 Panel.pendingCallback_ = null; |
843 pendingCallback(); | 847 pendingCallback(); |
844 } | 848 } |
845 }.bind(this); | 849 }.bind(this); |
846 | 850 |
847 var bkgnd = chrome.extension.getBackgroundPage(); | 851 var bkgnd = chrome.extension.getBackgroundPage(); |
848 bkgnd.chrome.automation.getDesktop(function(desktop) { | 852 bkgnd.chrome.automation.getDesktop(function(desktop) { |
849 onFocus = /** @type {function(chrome.automation.AutomationEvent)} */( | 853 onFocus = /** @type {function(chrome.automation.AutomationEvent)} */ ( |
850 onFocus.bind(this, desktop)); | 854 onFocus.bind(this, desktop)); |
851 desktop.addEventListener(chrome.automation.EventType.FOCUS, | 855 desktop.addEventListener(chrome.automation.EventType.FOCUS, onFocus, true); |
852 onFocus, | |
853 true); | |
854 | 856 |
855 // Make sure all menus are cleared to avoid bogous output when we re-open. | 857 // Make sure all menus are cleared to avoid bogous output when we re-open. |
856 Panel.clearMenus(); | 858 Panel.clearMenus(); |
857 | 859 |
858 // Make sure we're not in full-screen mode. | 860 // Make sure we're not in full-screen mode. |
859 Panel.setMode(Panel.Mode.COLLAPSED); | 861 Panel.setMode(Panel.Mode.COLLAPSED); |
860 | 862 |
861 this.activeMenu_ = null; | 863 this.activeMenu_ = null; |
862 }); | 864 }); |
863 }; | 865 }; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
911 }, false); | 913 }, false); |
912 | 914 |
913 window.addEventListener('hashchange', function() { | 915 window.addEventListener('hashchange', function() { |
914 if (location.hash == '#fullscreen' || location.hash == '#focus') { | 916 if (location.hash == '#fullscreen' || location.hash == '#focus') { |
915 this.originalStickyState_ = cvox.ChromeVox.isStickyPrefOn; | 917 this.originalStickyState_ = cvox.ChromeVox.isStickyPrefOn; |
916 cvox.ChromeVox.isStickyPrefOn = false; | 918 cvox.ChromeVox.isStickyPrefOn = false; |
917 } else { | 919 } else { |
918 cvox.ChromeVox.isStickyPrefOn = this.originalStickyState_; | 920 cvox.ChromeVox.isStickyPrefOn = this.originalStickyState_; |
919 } | 921 } |
920 }, false); | 922 }, false); |
OLD | NEW |