Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 <include src="../uber/uber_utils.js"> | 5 <include src="../uber/uber_utils.js"> |
| 6 <include src="history_focus_manager.js"> | 6 <include src="history_focus_manager.js"> |
| 7 | 7 |
| 8 /////////////////////////////////////////////////////////////////////////////// | 8 /////////////////////////////////////////////////////////////////////////////// |
| 9 // Globals: | 9 // Globals: |
| 10 /** @const */ var RESULTS_PER_PAGE = 150; | 10 /** @const */ var RESULTS_PER_PAGE = 150; |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 180 var menu = $('action-menu'); | 180 var menu = $('action-menu'); |
| 181 menu.dataset.devicename = self.deviceName; | 181 menu.dataset.devicename = self.deviceName; |
| 182 menu.dataset.devicetype = self.deviceType; | 182 menu.dataset.devicetype = self.deviceType; |
| 183 }; | 183 }; |
| 184 domain.textContent = this.domain_; | 184 domain.textContent = this.domain_; |
| 185 | 185 |
| 186 entryBox.appendChild(time); | 186 entryBox.appendChild(time); |
| 187 | 187 |
| 188 var bookmarkSection = createElementWithClassName('div', 'bookmark-section'); | 188 var bookmarkSection = createElementWithClassName('div', 'bookmark-section'); |
| 189 if (this.starred_) { | 189 if (this.starred_) { |
| 190 bookmarkSection.title = loadTimeData.getString('removeBookmark'); | |
| 190 bookmarkSection.classList.add('starred'); | 191 bookmarkSection.classList.add('starred'); |
| 191 bookmarkSection.addEventListener('click', function f(e) { | 192 bookmarkSection.addEventListener('click', function f(e) { |
| 192 recordUmaAction('HistoryPage_BookmarkStarClicked'); | 193 recordUmaAction('HistoryPage_BookmarkStarClicked'); |
| 193 bookmarkSection.classList.remove('starred'); | 194 bookmarkSection.classList.remove('starred'); |
| 194 chrome.send('removeBookmark', [self.url_]); | 195 chrome.send('removeBookmark', [self.url_]); |
| 195 bookmarkSection.removeEventListener('click', f); | 196 bookmarkSection.removeEventListener('click', f); |
| 196 e.preventDefault(); | 197 e.preventDefault(); |
| 197 }); | 198 }); |
| 198 } | 199 } |
| 199 entryBox.appendChild(bookmarkSection); | 200 entryBox.appendChild(bookmarkSection); |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 284 }.bind(this)); | 285 }.bind(this)); |
| 285 }; | 286 }; |
| 286 | 287 |
| 287 /** | 288 /** |
| 288 * @param {boolean} isLead Whether this visit is the "lead" visit, i.e. the one | 289 * @param {boolean} isLead Whether this visit is the "lead" visit, i.e. the one |
| 289 * that would be focused if the entry list is tabbed to. | 290 * that would be focused if the entry list is tabbed to. |
| 290 */ | 291 */ |
| 291 Visit.prototype.setIsLead = function(isLead) { | 292 Visit.prototype.setIsLead = function(isLead) { |
| 292 this.domNode_.querySelector('.entry-box').classList.toggle('lead', isLead); | 293 this.domNode_.querySelector('.entry-box').classList.toggle('lead', isLead); |
| 293 if (!isLead) { | 294 if (!isLead) { |
| 294 if (this.checkBox) | 295 this.getFocusableControls_().forEach(function(control) { |
| 295 this.checkBox.tabIndex = -1; | 296 control.tabIndex = -1; |
| 296 | 297 }); |
| 297 this.titleLink.tabIndex = -1; | |
| 298 | |
| 299 if (this.dropDown) | |
| 300 this.dropDown.tabIndex = -1; | |
| 301 } | 298 } |
| 302 }; | 299 }; |
| 303 | 300 |
| 304 /** | 301 /** |
| 305 * @param {Element} control A control element to focus. | 302 * @param {Element} control A control element to focus. |
| 306 */ | 303 */ |
| 307 Visit.prototype.focusControl = function(control) { | 304 Visit.prototype.focusControl = function(control) { |
| 308 var controls = [this.titleLink]; | 305 var controls = this.getFocusableControls_(); |
| 309 | |
| 310 if (this.checkBox) | |
| 311 controls.push(this.checkBox); | |
| 312 | |
| 313 if (this.dropDown) | |
| 314 controls.push(this.dropDown); | |
| 315 | |
| 316 assert(controls.indexOf(control) >= 0); | 306 assert(controls.indexOf(control) >= 0); |
| 317 | 307 |
| 318 for (var i = 0; i < controls.length; ++i) { | 308 for (var i = 0; i < controls.length; ++i) { |
| 319 controls[i].tabIndex = controls[i] == control ? 0 : -1; | 309 controls[i].tabIndex = controls[i] == control ? 0 : -1; |
| 320 } | 310 } |
| 321 | 311 |
| 322 control.focus(); | 312 control.focus(); |
| 323 this.setIsLead(true); | 313 this.setIsLead(true); |
| 324 }; | 314 }; |
| 325 | 315 |
| 326 Object.defineProperty(Visit.prototype, 'checkBox', { | 316 Object.defineProperty(Visit.prototype, 'checkBox', { |
| 327 get: function() { | 317 get: function() { |
| 328 return this.domNode_.querySelector('input[type=checkbox]'); | 318 return this.domNode_.querySelector('input[type=checkbox]'); |
| 329 }, | 319 }, |
| 330 }); | 320 }); |
| 331 | 321 |
| 322 Object.defineProperty(Visit.prototype, 'bookmarkStar', { | |
| 323 get: function() { | |
| 324 return this.domNode_.querySelector('.bookmark-section.starred'); | |
| 325 }, | |
| 326 }); | |
| 327 | |
| 332 Object.defineProperty(Visit.prototype, 'titleLink', { | 328 Object.defineProperty(Visit.prototype, 'titleLink', { |
| 333 get: function() { | 329 get: function() { |
| 334 return this.domNode_.querySelector('.title a'); | 330 return this.domNode_.querySelector('.title a'); |
| 335 }, | 331 }, |
| 336 }); | 332 }); |
| 337 | 333 |
| 338 Object.defineProperty(Visit.prototype, 'dropDown', { | 334 Object.defineProperty(Visit.prototype, 'dropDown', { |
| 339 get: function() { | 335 get: function() { |
| 340 return this.domNode_.querySelector('button.drop-down'); | 336 return this.domNode_.querySelector('button.drop-down'); |
| 341 }, | 337 }, |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 452 * Launch a search for more history entries from the same domain. | 448 * Launch a search for more history entries from the same domain. |
| 453 * @private | 449 * @private |
| 454 */ | 450 */ |
| 455 Visit.prototype.showMoreFromSite_ = function() { | 451 Visit.prototype.showMoreFromSite_ = function() { |
| 456 recordUmaAction('HistoryPage_EntryMenuShowMoreFromSite'); | 452 recordUmaAction('HistoryPage_EntryMenuShowMoreFromSite'); |
| 457 historyView.setSearch(this.domain_); | 453 historyView.setSearch(this.domain_); |
| 458 $('search-field').focus(); | 454 $('search-field').focus(); |
| 459 }; | 455 }; |
| 460 | 456 |
| 461 /** | 457 /** |
| 458 * @return {Array.<Element>} A list of focusable controls. | |
| 459 * @private | |
| 460 */ | |
| 461 Visit.prototype.getFocusableControls_ = function() { | |
| 462 var controls = []; | |
| 463 | |
| 464 if (this.checkBox) | |
| 465 controls.push(this.checkBox); | |
| 466 | |
| 467 if (this.bookmarkStar) | |
| 468 controls.push(this.bookmarkStar); | |
| 469 | |
| 470 controls.push(this.titleLink); | |
| 471 | |
| 472 if (this.dropDown) | |
| 473 controls.push(this.dropDown); | |
| 474 | |
| 475 return controls; | |
| 476 }; | |
| 477 | |
| 478 /** | |
| 462 * @param {Event} e A keydown event to handle. | 479 * @param {Event} e A keydown event to handle. |
| 463 * @private | 480 * @private |
| 464 */ | 481 */ |
| 465 Visit.prototype.handleKeydown_ = function(e) { | 482 Visit.prototype.handleKeydown_ = function(e) { |
| 466 var keyCode = e.keyCode; | 483 var keyCode = e.keyCode; |
| 467 if (keyCode == 8 || keyCode == 46) { // Delete or Backspace. | 484 if (keyCode == 8 || keyCode == 46) { // Delete or Backspace. |
| 468 if (!this.model_.isDeletingVisits()) | 485 if (!this.model_.isDeletingVisits()) |
| 469 this.removeEntryFromHistory_(e); | 486 this.removeEntryFromHistory_(e); |
| 470 return; | 487 return; |
| 471 } | 488 } |
| 472 | 489 |
| 473 var target = e.target; | 490 var target = e.target; |
| 474 if (target != document.activeElement || | 491 if (target != document.activeElement || !(keyCode == 37 || keyCode == 39)) { |
| 475 !(keyCode == 37 || keyCode == 39) || // Left or right. | 492 // Handling key code for inactive element or key wasn't left or right. |
| 476 (keyCode == 37 && target == this.checkBox) || | |
| 477 (keyCode == 39 && target == this.dropDown)) { | |
| 478 return; | 493 return; |
| 479 } | 494 } |
| 480 | 495 |
| 481 var toFocus; | 496 var controls = this.getFocusableControls_(); |
| 482 if (e.keyCode == 37) // Left. | 497 for (var i = 0; i < controls.length; ++i) { |
| 483 toFocus = target == this.dropDown ? this.titleLink : this.checkBox; | 498 if (controls[i].contains(target)) { |
| 484 else // Right. | 499 var toFocus = e.keyCode == 37 ? controls[i - 1] : controls[i + 1]; |
|
dmazzoni
2014/07/22 16:59:16
Add back a comment for 37 == "left" or use a const
Dan Beam
2014/07/22 18:10:06
Done.
| |
| 485 toFocus = target == this.checkBox ? this.titleLink : this.dropDown; | 500 if (toFocus) { |
| 486 | 501 this.focusControl(toFocus); |
| 487 this.focusControl(toFocus); | 502 e.preventDefault(); |
| 488 e.preventDefault(); | 503 } |
| 504 break; | |
| 505 } | |
| 506 } | |
| 489 }; | 507 }; |
| 490 | 508 |
| 491 /** | 509 /** |
| 492 * Removes a history entry on click or keydown and finds a new entry to focus. | 510 * Removes a history entry on click or keydown and finds a new entry to focus. |
| 493 * @param {Event} e A click or keydown event. | 511 * @param {Event} e A click or keydown event. |
| 494 * @private | 512 * @private |
| 495 */ | 513 */ |
| 496 Visit.prototype.removeEntryFromHistory_ = function(e) { | 514 Visit.prototype.removeEntryFromHistory_ = function(e) { |
| 497 this.model_.getView().onBeforeRemove(this); | 515 this.model_.getView().onBeforeRemove(this); |
| 498 this.removeFromHistory(); | 516 this.removeFromHistory(); |
| (...skipping 1121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1620 | 1638 |
| 1621 /** | 1639 /** |
| 1622 * Swaps focus to |toBeFocused|. Assumes the another visit is currently focused. | 1640 * Swaps focus to |toBeFocused|. Assumes the another visit is currently focused. |
| 1623 * @param {Visit} visit A visit to focus. | 1641 * @param {Visit} visit A visit to focus. |
| 1624 * @private | 1642 * @private |
| 1625 */ | 1643 */ |
| 1626 HistoryView.prototype.swapFocusedVisit_ = function(visit) { | 1644 HistoryView.prototype.swapFocusedVisit_ = function(visit) { |
| 1627 if (!visit) | 1645 if (!visit) |
| 1628 return; | 1646 return; |
| 1629 | 1647 |
| 1630 var control; | |
| 1631 var activeVisit = findAncestorByClass(document.activeElement, 'entry').visit; | 1648 var activeVisit = findAncestorByClass(document.activeElement, 'entry').visit; |
| 1632 if (document.activeElement == activeVisit.checkBox) | 1649 var controls = activeVisit.getFocusableControls_(); |
| 1633 control = visit.checkBox; | |
| 1634 else if (document.activeElement == activeVisit.titleLink) | |
| 1635 control = visit.titleLink; | |
| 1636 else if (document.activeElement == activeVisit.dropDown) | |
| 1637 control = visit.dropDown; | |
| 1638 | 1650 |
| 1639 visit.focusControl(control); | 1651 for (var i = 0; i < controls.length; ++i) { |
| 1652 var control = controls[i]; | |
| 1653 if (!control.contains(document.activeElement)) | |
| 1654 continue; | |
| 1655 | |
| 1656 // Try to focus the same type of control if the new visit has it. | |
| 1657 if (control == activeVisit.checkBox && visit.checkBox) { | |
| 1658 visit.focusControl(visit.checkBox); | |
| 1659 } else if (control == activeVisit.bookmarkStar && visit.bookmarkStar) { | |
| 1660 visit.focusControl(visit.bookmarkStar); | |
| 1661 } else if (control == activeVisit.titleLink) { | |
| 1662 visit.focusControl(visit.titleLink); | |
| 1663 } else if (control == activeVisit.dropDown && visit.dropDown) { | |
| 1664 visit.focusControl(visit.dropDown); | |
| 1665 } else { | |
| 1666 // Otherwise, just focus something that might be in a similar column. | |
| 1667 var controlsToFocus = visit.getFocusableControls_(); | |
| 1668 var indexToFocus = Math.min(i, controlsToFocus.length - 1); | |
| 1669 visit.focusControl(controlsToFocus[indexToFocus]); | |
| 1670 } | |
| 1671 break; | |
| 1672 } | |
| 1673 | |
| 1640 activeVisit.setIsLead(false); | 1674 activeVisit.setIsLead(false); |
| 1641 }; | 1675 }; |
| 1642 | 1676 |
| 1643 /** | 1677 /** |
| 1644 * @param {Event} e A keydown event to handle. | 1678 * @param {Event} e A keydown event to handle. |
| 1645 * @private | 1679 * @private |
| 1646 */ | 1680 */ |
| 1647 HistoryView.prototype.handleKeydown_ = function(e) { | 1681 HistoryView.prototype.handleKeydown_ = function(e) { |
| 1648 // Only handle up or down arrows on the focused element. | 1682 // Only handle up or down arrows on the focused element. |
| 1649 var keyCode = e.keyCode, target = e.target; | 1683 var keyCode = e.keyCode, target = e.target; |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 1660 * @param {Event} e A mousedown event to handle. | 1694 * @param {Event} e A mousedown event to handle. |
| 1661 * @private | 1695 * @private |
| 1662 */ | 1696 */ |
| 1663 HistoryView.prototype.handleMousedown_ = function(e) { | 1697 HistoryView.prototype.handleMousedown_ = function(e) { |
| 1664 var target = e.target; | 1698 var target = e.target; |
| 1665 var entry = findAncestorByClass(target, 'entry'); | 1699 var entry = findAncestorByClass(target, 'entry'); |
| 1666 if (!entry || !entry.contains(target)) | 1700 if (!entry || !entry.contains(target)) |
| 1667 return; | 1701 return; |
| 1668 | 1702 |
| 1669 var visit = entry.visit; | 1703 var visit = entry.visit; |
| 1704 if (visit.bookmarkStar && visit.bookmarkStar.contains(target)) | |
| 1705 return; | |
| 1706 | |
| 1670 if (visit.titleLink.contains(target)) | 1707 if (visit.titleLink.contains(target)) |
| 1671 visit.focusControl(visit.titleLink); | 1708 visit.focusControl(visit.titleLink); |
| 1672 else if (visit.dropDown && visit.dropDown.contains(target)) | 1709 else if (visit.dropDown && visit.dropDown.contains(target)) |
| 1673 visit.focusControl(visit.dropDown); | 1710 visit.focusControl(visit.dropDown); |
| 1674 else // Focus the checkbox by default. If no checkbox, focus the title. | 1711 else // Focus the checkbox by default. If no checkbox, focus the title. |
| 1675 visit.focusControl(visit.checkBox || visit.titleLink); | 1712 visit.focusControl(visit.checkBox || visit.titleLink); |
| 1676 | 1713 |
| 1677 e.preventDefault(); | 1714 e.preventDefault(); |
| 1678 }; | 1715 }; |
| 1679 | 1716 |
| (...skipping 610 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2290 historyView.reload(); | 2327 historyView.reload(); |
| 2291 } | 2328 } |
| 2292 | 2329 |
| 2293 // Add handlers to HTML elements. | 2330 // Add handlers to HTML elements. |
| 2294 document.addEventListener('DOMContentLoaded', load); | 2331 document.addEventListener('DOMContentLoaded', load); |
| 2295 | 2332 |
| 2296 // This event lets us enable and disable menu items before the menu is shown. | 2333 // This event lets us enable and disable menu items before the menu is shown. |
| 2297 document.addEventListener('canExecute', function(e) { | 2334 document.addEventListener('canExecute', function(e) { |
| 2298 e.canExecute = true; | 2335 e.canExecute = true; |
| 2299 }); | 2336 }); |
| OLD | NEW |