Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(907)

Side by Side Diff: chrome/browser/resources/md_downloads/crisper.js

Issue 1492273002: MD Downloads: limit the amount of downloads we send (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@new-dl-data
Patch Set: asdf Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 if (typeof Polymer == 'undefined') 5 if (typeof Polymer == 'undefined')
6 Polymer = {dom: 'shadow'}; 6 Polymer = {dom: 'shadow'};
7 else 7 else
8 console.error('Polymer is already defined.'); 8 console.error('Polymer is already defined.');
9 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 9 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
10 // Use of this source code is governed by a BSD-style license that can be 10 // Use of this source code is governed by a BSD-style license that can be
(...skipping 1535 matching lines...) Expand 10 before | Expand all | Expand 10 after
1546 /** 1546 /**
1547 * @param {string} searchText Input typed by the user into a search box. 1547 * @param {string} searchText Input typed by the user into a search box.
1548 * @return {Array<string>} A list of terms extracted from |searchText|. 1548 * @return {Array<string>} A list of terms extracted from |searchText|.
1549 */ 1549 */
1550 ActionService.splitTerms = function(searchText) { 1550 ActionService.splitTerms = function(searchText) {
1551 // Split quoted terms (e.g., 'The "lazy" dog' => ['The', 'lazy', 'dog']). 1551 // Split quoted terms (e.g., 'The "lazy" dog' => ['The', 'lazy', 'dog']).
1552 return searchText.split(/"([^"]*)"/).map(trim).filter(truthy); 1552 return searchText.split(/"([^"]*)"/).map(trim).filter(truthy);
1553 }; 1553 };
1554 1554
1555 ActionService.prototype = { 1555 ActionService.prototype = {
1556 /** @private {Array<string>} */
1557 searchTerms_: [],
1558
1556 /** @param {string} id ID of the download to cancel. */ 1559 /** @param {string} id ID of the download to cancel. */
1557 cancel: chromeSendWithId('cancel'), 1560 cancel: chromeSendWithId('cancel'),
1558 1561
1559 /** Instructs the browser to clear all finished downloads. */ 1562 /** Instructs the browser to clear all finished downloads. */
1560 clearAll: function() { 1563 clearAll: function() {
1561 if (loadTimeData.getBoolean('allowDeletingHistory')) { 1564 if (loadTimeData.getBoolean('allowDeletingHistory')) {
1562 chrome.send('clearAll'); 1565 chrome.send('clearAll');
1563 this.search(''); 1566 this.search('');
1564 } 1567 }
1565 }, 1568 },
1566 1569
1567 /** @param {string} id ID of the dangerous download to discard. */ 1570 /** @param {string} id ID of the dangerous download to discard. */
1568 discardDangerous: chromeSendWithId('discardDangerous'), 1571 discardDangerous: chromeSendWithId('discardDangerous'),
1569 1572
1570 /** @param {string} url URL of a file to download. */ 1573 /** @param {string} url URL of a file to download. */
1571 download: function(url) { 1574 download: function(url) {
1572 var a = document.createElement('a'); 1575 var a = document.createElement('a');
1573 a.href = url; 1576 a.href = url;
1574 a.setAttribute('download', ''); 1577 a.setAttribute('download', '');
1575 a.click(); 1578 a.click();
1576 }, 1579 },
1577 1580
1578 /** @param {string} id ID of the download that the user started dragging. */ 1581 /** @param {string} id ID of the download that the user started dragging. */
1579 drag: chromeSendWithId('drag'), 1582 drag: chromeSendWithId('drag'),
1580 1583
1581 /** @private {boolean} */ 1584 /** Loads more downloads with the current search terms. */
1582 isSearching_: false, 1585 loadMore: function() {
1586 chrome.send('getDownloads', this.searchTerms_);
1587 },
1583 1588
1584 /** 1589 /**
1585 * @return {boolean} Whether the user is currently searching for downloads 1590 * @return {boolean} Whether the user is currently searching for downloads
1586 * (i.e. has a non-empty search term). 1591 * (i.e. has a non-empty search term).
1587 */ 1592 */
1588 isSearching: function() { 1593 isSearching: function() {
1589 return this.isSearching_; 1594 return this.searchTerms_.length > 0;
1590 }, 1595 },
1591 1596
1592 /** Opens the current local destination for downloads. */ 1597 /** Opens the current local destination for downloads. */
1593 openDownloadsFolder: chrome.send.bind(chrome, 'openDownloadsFolder'), 1598 openDownloadsFolder: chrome.send.bind(chrome, 'openDownloadsFolder'),
1594 1599
1595 /** 1600 /**
1596 * @param {string} id ID of the download to run locally on the user's box. 1601 * @param {string} id ID of the download to run locally on the user's box.
1597 */ 1602 */
1598 openFile: chromeSendWithId('openFile'), 1603 openFile: chromeSendWithId('openFile'),
1599 1604
1600 /** @param {string} id ID the of the progressing download to pause. */ 1605 /** @param {string} id ID the of the progressing download to pause. */
1601 pause: chromeSendWithId('pause'), 1606 pause: chromeSendWithId('pause'),
1602 1607
1603 /** @param {string} id ID of the finished download to remove. */ 1608 /** @param {string} id ID of the finished download to remove. */
1604 remove: chromeSendWithId('remove'), 1609 remove: chromeSendWithId('remove'),
1605 1610
1606 /** @param {string} id ID of the paused download to resume. */ 1611 /** @param {string} id ID of the paused download to resume. */
1607 resume: chromeSendWithId('resume'), 1612 resume: chromeSendWithId('resume'),
1608 1613
1609 /** 1614 /**
1610 * @param {string} id ID of the dangerous download to save despite 1615 * @param {string} id ID of the dangerous download to save despite
1611 * warnings. 1616 * warnings.
1612 */ 1617 */
1613 saveDangerous: chromeSendWithId('saveDangerous'), 1618 saveDangerous: chromeSendWithId('saveDangerous'),
1614 1619
1615 /** @param {string} searchText What to search for. */ 1620 /** @param {string} searchText What to search for. */
1616 search: function(searchText) { 1621 search: function(searchText) {
1617 if (this.searchText_ == searchText) 1622 var searchTerms = ActionService.splitTerms(searchText);
1623 var sameTerms = searchTerms.length == this.searchTerms_.length;
1624
1625 for (var i = 0; sameTerms && i < searchTerms.length; ++i) {
1626 if (searchTerms[i] != this.searchTerms_[i])
1627 sameTerms = false;
1628 }
1629
1630 if (sameTerms)
1618 return; 1631 return;
1619 1632
1620 this.searchText_ = searchText; 1633 this.searchTerms_ = searchTerms;
1621 1634 this.loadMore();
1622 var terms = ActionService.splitTerms(searchText);
1623 this.isSearching_ = terms.length > 0;
1624
1625 chrome.send('getDownloads', terms);
1626 }, 1635 },
1627 1636
1628 /** 1637 /**
1629 * Shows the local folder a finished download resides in. 1638 * Shows the local folder a finished download resides in.
1630 * @param {string} id ID of the download to show. 1639 * @param {string} id ID of the download to show.
1631 */ 1640 */
1632 show: chromeSendWithId('show'), 1641 show: chromeSendWithId('show'),
1633 1642
1634 /** Undo download removal. */ 1643 /** Undo download removal. */
1635 undo: chrome.send.bind(chrome, 'undo'), 1644 undo: chrome.send.bind(chrome, 'undo'),
(...skipping 9331 matching lines...) Expand 10 before | Expand all | Expand 10 after
10967 (function() { 10976 (function() {
10968 'use strict'; 10977 'use strict';
10969 10978
10970 /** 10979 /**
10971 * Chrome uses an older version of DOM Level 3 Keyboard Events 10980 * Chrome uses an older version of DOM Level 3 Keyboard Events
10972 * 10981 *
10973 * Most keys are labeled as text, but some are Unicode codepoints. 10982 * Most keys are labeled as text, but some are Unicode codepoints.
10974 * Values taken from: http://www.w3.org/TR/2007/WD-DOM-Level-3-Events-200712 21/keyset.html#KeySet-Set 10983 * Values taken from: http://www.w3.org/TR/2007/WD-DOM-Level-3-Events-200712 21/keyset.html#KeySet-Set
10975 */ 10984 */
10976 var KEY_IDENTIFIER = { 10985 var KEY_IDENTIFIER = {
10986 'U+0008': 'backspace',
10977 'U+0009': 'tab', 10987 'U+0009': 'tab',
10978 'U+001B': 'esc', 10988 'U+001B': 'esc',
10979 'U+0020': 'space', 10989 'U+0020': 'space',
10980 'U+002A': '*',
10981 'U+0030': '0',
10982 'U+0031': '1',
10983 'U+0032': '2',
10984 'U+0033': '3',
10985 'U+0034': '4',
10986 'U+0035': '5',
10987 'U+0036': '6',
10988 'U+0037': '7',
10989 'U+0038': '8',
10990 'U+0039': '9',
10991 'U+0041': 'a',
10992 'U+0042': 'b',
10993 'U+0043': 'c',
10994 'U+0044': 'd',
10995 'U+0045': 'e',
10996 'U+0046': 'f',
10997 'U+0047': 'g',
10998 'U+0048': 'h',
10999 'U+0049': 'i',
11000 'U+004A': 'j',
11001 'U+004B': 'k',
11002 'U+004C': 'l',
11003 'U+004D': 'm',
11004 'U+004E': 'n',
11005 'U+004F': 'o',
11006 'U+0050': 'p',
11007 'U+0051': 'q',
11008 'U+0052': 'r',
11009 'U+0053': 's',
11010 'U+0054': 't',
11011 'U+0055': 'u',
11012 'U+0056': 'v',
11013 'U+0057': 'w',
11014 'U+0058': 'x',
11015 'U+0059': 'y',
11016 'U+005A': 'z',
11017 'U+007F': 'del' 10990 'U+007F': 'del'
11018 }; 10991 };
11019 10992
11020 /** 10993 /**
11021 * Special table for KeyboardEvent.keyCode. 10994 * Special table for KeyboardEvent.keyCode.
11022 * KeyboardEvent.keyIdentifier is better, and KeyBoardEvent.key is even bett er 10995 * KeyboardEvent.keyIdentifier is better, and KeyBoardEvent.key is even bett er
11023 * than that. 10996 * than that.
11024 * 10997 *
11025 * Values from: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEve nt.keyCode#Value_of_keyCode 10998 * Values from: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEve nt.keyCode#Value_of_keyCode
11026 */ 10999 */
11027 var KEY_CODE = { 11000 var KEY_CODE = {
11001 8: 'backspace',
11028 9: 'tab', 11002 9: 'tab',
11029 13: 'enter', 11003 13: 'enter',
11030 27: 'esc', 11004 27: 'esc',
11031 33: 'pageup', 11005 33: 'pageup',
11032 34: 'pagedown', 11006 34: 'pagedown',
11033 35: 'end', 11007 35: 'end',
11034 36: 'home', 11008 36: 'home',
11035 32: 'space', 11009 32: 'space',
11036 37: 'left', 11010 37: 'left',
11037 38: 'up', 11011 38: 'up',
11038 39: 'right', 11012 39: 'right',
11039 40: 'down', 11013 40: 'down',
11040 46: 'del', 11014 46: 'del',
11041 106: '*' 11015 106: '*'
11042 }; 11016 };
11043 11017
11044 /** 11018 /**
11045 * MODIFIER_KEYS maps the short name for modifier keys used in a key 11019 * MODIFIER_KEYS maps the short name for modifier keys used in a key
11046 * combo string to the property name that references those same keys 11020 * combo string to the property name that references those same keys
11047 * in a KeyboardEvent instance. 11021 * in a KeyboardEvent instance.
11048 */ 11022 */
11049 var MODIFIER_KEYS = { 11023 var MODIFIER_KEYS = {
11050 'shift': 'shiftKey', 11024 'shift': 'shiftKey',
11051 'ctrl': 'ctrlKey', 11025 'ctrl': 'ctrlKey',
11052 'alt': 'altKey', 11026 'alt': 'altKey',
11053 'meta': 'metaKey' 11027 'meta': 'metaKey'
11054 }; 11028 };
11055 11029
11056 /** 11030 /**
11057 * KeyboardEvent.key is mostly represented by printable character made by
11058 * the keyboard, with unprintable keys labeled nicely.
11059 *
11060 * However, on OS X, Alt+char can make a Unicode character that follows an
11061 * Apple-specific mapping. In this case, we
11062 * fall back to .keyCode.
11063 */
11064 var KEY_CHAR = /[a-z0-9*]/;
11065
11066 /**
11067 * Matches a keyIdentifier string. 11031 * Matches a keyIdentifier string.
11068 */ 11032 */
11069 var IDENT_CHAR = /U\+/; 11033 var IDENT_CHAR = /U\+/;
11070 11034
11071 /** 11035 /**
11072 * Matches arrow keys in Gecko 27.0+ 11036 * Matches arrow keys in Gecko 27.0+
11073 */ 11037 */
11074 var ARROW_KEY = /^arrow/; 11038 var ARROW_KEY = /^arrow/;
11075 11039
11076 /** 11040 /**
11077 * Matches space keys everywhere (notably including IE10's exceptional name 11041 * Matches space keys everywhere (notably including IE10's exceptional name
11078 * `spacebar`). 11042 * `spacebar`).
11079 */ 11043 */
11080 var SPACE_KEY = /^space(bar)?/; 11044 var SPACE_KEY = /^space(bar)?/;
11081 11045
11082 function transformKey(key) { 11046 function transformKey(key) {
11083 var validKey = ''; 11047 var validKey = '';
11084 if (key) { 11048 if (key) {
11085 var lKey = key.toLowerCase(); 11049 var lKey = key.toLowerCase();
11086 if (lKey.length == 1) { 11050 if (lKey === ' ' || SPACE_KEY.test(lKey)) {
11087 if (KEY_CHAR.test(lKey)) { 11051 validKey = 'space';
11088 validKey = lKey; 11052 } else if (lKey.length == 1) {
11089 } 11053 validKey = lKey;
11090 } else if (ARROW_KEY.test(lKey)) { 11054 } else if (ARROW_KEY.test(lKey)) {
11091 validKey = lKey.replace('arrow', ''); 11055 validKey = lKey.replace('arrow', '');
11092 } else if (SPACE_KEY.test(lKey)) {
11093 validKey = 'space';
11094 } else if (lKey == 'multiply') { 11056 } else if (lKey == 'multiply') {
11095 // numpad '*' can map to Multiply on IE/Windows 11057 // numpad '*' can map to Multiply on IE/Windows
11096 validKey = '*'; 11058 validKey = '*';
11097 } else { 11059 } else {
11098 validKey = lKey; 11060 validKey = lKey;
11099 } 11061 }
11100 } 11062 }
11101 return validKey; 11063 return validKey;
11102 } 11064 }
11103 11065
11104 function transformKeyIdentifier(keyIdent) { 11066 function transformKeyIdentifier(keyIdent) {
11105 var validKey = ''; 11067 var validKey = '';
11106 if (keyIdent) { 11068 if (keyIdent) {
11107 if (IDENT_CHAR.test(keyIdent)) { 11069 if (keyIdent in KEY_IDENTIFIER) {
11108 validKey = KEY_IDENTIFIER[keyIdent]; 11070 validKey = KEY_IDENTIFIER[keyIdent];
11071 } else if (IDENT_CHAR.test(keyIdent)) {
11072 keyIdent = parseInt(keyIdent.replace('U+', '0x'), 16);
11073 validKey = String.fromCharCode(keyIdent).toLowerCase();
11109 } else { 11074 } else {
11110 validKey = keyIdent.toLowerCase(); 11075 validKey = keyIdent.toLowerCase();
11111 } 11076 }
11112 } 11077 }
11113 return validKey; 11078 return validKey;
11114 } 11079 }
11115 11080
11116 function transformKeyCode(keyCode) { 11081 function transformKeyCode(keyCode) {
11117 var validKey = ''; 11082 var validKey = '';
11118 if (Number(keyCode)) { 11083 if (Number(keyCode)) {
(...skipping 19 matching lines...) Expand all
11138 11103
11139 function normalizedKeyForEvent(keyEvent) { 11104 function normalizedKeyForEvent(keyEvent) {
11140 // fall back from .key, to .keyIdentifier, to .keyCode, and then to 11105 // fall back from .key, to .keyIdentifier, to .keyCode, and then to
11141 // .detail.key to support artificial keyboard events 11106 // .detail.key to support artificial keyboard events
11142 return transformKey(keyEvent.key) || 11107 return transformKey(keyEvent.key) ||
11143 transformKeyIdentifier(keyEvent.keyIdentifier) || 11108 transformKeyIdentifier(keyEvent.keyIdentifier) ||
11144 transformKeyCode(keyEvent.keyCode) || 11109 transformKeyCode(keyEvent.keyCode) ||
11145 transformKey(keyEvent.detail.key) || ''; 11110 transformKey(keyEvent.detail.key) || '';
11146 } 11111 }
11147 11112
11148 function keyComboMatchesEvent(keyCombo, keyEvent) { 11113 function keyComboMatchesEvent(keyCombo, event, eventKey) {
11149 return normalizedKeyForEvent(keyEvent) === keyCombo.key && 11114 return eventKey === keyCombo.key &&
11150 !!keyEvent.shiftKey === !!keyCombo.shiftKey && 11115 (!keyCombo.hasModifiers || (
11151 !!keyEvent.ctrlKey === !!keyCombo.ctrlKey && 11116 !!event.shiftKey === !!keyCombo.shiftKey &&
11152 !!keyEvent.altKey === !!keyCombo.altKey && 11117 !!event.ctrlKey === !!keyCombo.ctrlKey &&
11153 !!keyEvent.metaKey === !!keyCombo.metaKey; 11118 !!event.altKey === !!keyCombo.altKey &&
11119 !!event.metaKey === !!keyCombo.metaKey)
11120 );
11154 } 11121 }
11155 11122
11156 function parseKeyComboString(keyComboString) { 11123 function parseKeyComboString(keyComboString) {
11124 if (keyComboString.length === 1) {
11125 return {
11126 combo: keyComboString,
11127 key: keyComboString,
11128 event: 'keydown'
11129 };
11130 }
11157 return keyComboString.split('+').reduce(function(parsedKeyCombo, keyComboP art) { 11131 return keyComboString.split('+').reduce(function(parsedKeyCombo, keyComboP art) {
11158 var eventParts = keyComboPart.split(':'); 11132 var eventParts = keyComboPart.split(':');
11159 var keyName = eventParts[0]; 11133 var keyName = eventParts[0];
11160 var event = eventParts[1]; 11134 var event = eventParts[1];
11161 11135
11162 if (keyName in MODIFIER_KEYS) { 11136 if (keyName in MODIFIER_KEYS) {
11163 parsedKeyCombo[MODIFIER_KEYS[keyName]] = true; 11137 parsedKeyCombo[MODIFIER_KEYS[keyName]] = true;
11138 parsedKeyCombo.hasModifiers = true;
11164 } else { 11139 } else {
11165 parsedKeyCombo.key = keyName; 11140 parsedKeyCombo.key = keyName;
11166 parsedKeyCombo.event = event || 'keydown'; 11141 parsedKeyCombo.event = event || 'keydown';
11167 } 11142 }
11168 11143
11169 return parsedKeyCombo; 11144 return parsedKeyCombo;
11170 }, { 11145 }, {
11171 combo: keyComboString.split(':').shift() 11146 combo: keyComboString.split(':').shift()
11172 }); 11147 });
11173 } 11148 }
11174 11149
11175 function parseEventString(eventString) { 11150 function parseEventString(eventString) {
11176 return eventString.split(' ').map(function(keyComboString) { 11151 return eventString.trim().split(' ').map(function(keyComboString) {
11177 return parseKeyComboString(keyComboString); 11152 return parseKeyComboString(keyComboString);
11178 }); 11153 });
11179 } 11154 }
11180 11155
11181
11182 /** 11156 /**
11183 * `Polymer.IronA11yKeysBehavior` provides a normalized interface for proces sing 11157 * `Polymer.IronA11yKeysBehavior` provides a normalized interface for proces sing
11184 * keyboard commands that pertain to [WAI-ARIA best practices](http://www.w3 .org/TR/wai-aria-practices/#kbd_general_binding). 11158 * keyboard commands that pertain to [WAI-ARIA best practices](http://www.w3 .org/TR/wai-aria-practices/#kbd_general_binding).
11185 * The element takes care of browser differences with respect to Keyboard ev ents 11159 * The element takes care of browser differences with respect to Keyboard ev ents
11186 * and uses an expressive syntax to filter key presses. 11160 * and uses an expressive syntax to filter key presses.
11187 * 11161 *
11188 * Use the `keyBindings` prototype property to express what combination of k eys 11162 * Use the `keyBindings` prototype property to express what combination of k eys
11189 * will trigger the event to fire. 11163 * will trigger the event to fire.
11190 * 11164 *
11191 * Use the `key-event-target` attribute to set up event handlers on a specif ic 11165 * Use the `key-event-target` attribute to set up event handlers on a specif ic
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
11267 * When called, will remove all imperatively-added key bindings. 11241 * When called, will remove all imperatively-added key bindings.
11268 */ 11242 */
11269 removeOwnKeyBindings: function() { 11243 removeOwnKeyBindings: function() {
11270 this._imperativeKeyBindings = {}; 11244 this._imperativeKeyBindings = {};
11271 this._prepKeyBindings(); 11245 this._prepKeyBindings();
11272 this._resetKeyEventListeners(); 11246 this._resetKeyEventListeners();
11273 }, 11247 },
11274 11248
11275 keyboardEventMatchesKeys: function(event, eventString) { 11249 keyboardEventMatchesKeys: function(event, eventString) {
11276 var keyCombos = parseEventString(eventString); 11250 var keyCombos = parseEventString(eventString);
11277 var index; 11251 var eventKey = normalizedKeyForEvent(event);
11278 11252 for (var i = 0; i < keyCombos.length; ++i) {
11279 for (index = 0; index < keyCombos.length; ++index) { 11253 if (keyComboMatchesEvent(keyCombos[i], event, eventKey)) {
11280 if (keyComboMatchesEvent(keyCombos[index], event)) {
11281 return true; 11254 return true;
11282 } 11255 }
11283 } 11256 }
11284
11285 return false; 11257 return false;
11286 }, 11258 },
11287 11259
11288 _collectKeyBindings: function() { 11260 _collectKeyBindings: function() {
11289 var keyBindings = this.behaviors.map(function(behavior) { 11261 var keyBindings = this.behaviors.map(function(behavior) {
11290 return behavior.keyBindings; 11262 return behavior.keyBindings;
11291 }); 11263 });
11292 11264
11293 if (keyBindings.indexOf(this.keyBindings) === -1) { 11265 if (keyBindings.indexOf(this.keyBindings) === -1) {
11294 keyBindings.push(this.keyBindings); 11266 keyBindings.push(this.keyBindings);
11295 } 11267 }
11296 11268
11297 return keyBindings; 11269 return keyBindings;
11298 }, 11270 },
11299 11271
11300 _prepKeyBindings: function() { 11272 _prepKeyBindings: function() {
11301 this._keyBindings = {}; 11273 this._keyBindings = {};
11302 11274
11303 this._collectKeyBindings().forEach(function(keyBindings) { 11275 this._collectKeyBindings().forEach(function(keyBindings) {
11304 for (var eventString in keyBindings) { 11276 for (var eventString in keyBindings) {
11305 this._addKeyBinding(eventString, keyBindings[eventString]); 11277 this._addKeyBinding(eventString, keyBindings[eventString]);
11306 } 11278 }
11307 }, this); 11279 }, this);
11308 11280
11309 for (var eventString in this._imperativeKeyBindings) { 11281 for (var eventString in this._imperativeKeyBindings) {
11310 this._addKeyBinding(eventString, this._imperativeKeyBindings[eventStri ng]); 11282 this._addKeyBinding(eventString, this._imperativeKeyBindings[eventStri ng]);
11311 } 11283 }
11284
11285 // Give precedence to combos with modifiers to be checked first.
11286 for (var eventName in this._keyBindings) {
11287 this._keyBindings[eventName].sort(function (kb1, kb2) {
11288 var b1 = kb1[0].hasModifiers;
11289 var b2 = kb2[0].hasModifiers;
11290 return (b1 === b2) ? 0 : b1 ? -1 : 1;
11291 })
11292 }
11312 }, 11293 },
11313 11294
11314 _addKeyBinding: function(eventString, handlerName) { 11295 _addKeyBinding: function(eventString, handlerName) {
11315 parseEventString(eventString).forEach(function(keyCombo) { 11296 parseEventString(eventString).forEach(function(keyCombo) {
11316 this._keyBindings[keyCombo.event] = 11297 this._keyBindings[keyCombo.event] =
11317 this._keyBindings[keyCombo.event] || []; 11298 this._keyBindings[keyCombo.event] || [];
11318 11299
11319 this._keyBindings[keyCombo.event].push([ 11300 this._keyBindings[keyCombo.event].push([
11320 keyCombo, 11301 keyCombo,
11321 handlerName 11302 handlerName
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
11357 11338
11358 keyEventTarget.removeEventListener(eventName, boundKeyHandler); 11339 keyEventTarget.removeEventListener(eventName, boundKeyHandler);
11359 } 11340 }
11360 }, 11341 },
11361 11342
11362 _onKeyBindingEvent: function(keyBindings, event) { 11343 _onKeyBindingEvent: function(keyBindings, event) {
11363 if (this.stopKeyboardEventPropagation) { 11344 if (this.stopKeyboardEventPropagation) {
11364 event.stopPropagation(); 11345 event.stopPropagation();
11365 } 11346 }
11366 11347
11367 keyBindings.forEach(function(keyBinding) { 11348 // if event has been already prevented, don't do anything
11368 var keyCombo = keyBinding[0]; 11349 if (event.defaultPrevented) {
11369 var handlerName = keyBinding[1]; 11350 return;
11351 }
11370 11352
11371 if (!event.defaultPrevented && keyComboMatchesEvent(keyCombo, event)) { 11353 var eventKey = normalizedKeyForEvent(event);
11354 for (var i = 0; i < keyBindings.length; i++) {
11355 var keyCombo = keyBindings[i][0];
11356 var handlerName = keyBindings[i][1];
11357 if (keyComboMatchesEvent(keyCombo, event, eventKey)) {
11372 this._triggerKeyHandler(keyCombo, handlerName, event); 11358 this._triggerKeyHandler(keyCombo, handlerName, event);
11359 // exit the loop if eventDefault was prevented
11360 if (event.defaultPrevented) {
11361 return;
11362 }
11373 } 11363 }
11374 }, this); 11364 }
11375 }, 11365 },
11376 11366
11377 _triggerKeyHandler: function(keyCombo, handlerName, keyboardEvent) { 11367 _triggerKeyHandler: function(keyCombo, handlerName, keyboardEvent) {
11378 var detail = Object.create(keyCombo); 11368 var detail = Object.create(keyCombo);
11379 detail.keyboardEvent = keyboardEvent; 11369 detail.keyboardEvent = keyboardEvent;
11380 var event = new CustomEvent(keyCombo.event, { 11370 var event = new CustomEvent(keyCombo.event, {
11381 detail: detail, 11371 detail: detail,
11382 cancelable: true 11372 cancelable: true
11383 }); 11373 });
11384 this[handlerName].call(this, event); 11374 this[handlerName].call(this, event);
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after
11602 11592
11603 /** 11593 /**
11604 * @param {!KeyboardEvent} event . 11594 * @param {!KeyboardEvent} event .
11605 */ 11595 */
11606 _spaceKeyDownHandler: function(event) { 11596 _spaceKeyDownHandler: function(event) {
11607 var keyboardEvent = event.detail.keyboardEvent; 11597 var keyboardEvent = event.detail.keyboardEvent;
11608 var target = Polymer.dom(keyboardEvent).localTarget; 11598 var target = Polymer.dom(keyboardEvent).localTarget;
11609 11599
11610 // Ignore the event if this is coming from a focused light child, since th at 11600 // Ignore the event if this is coming from a focused light child, since th at
11611 // element will deal with it. 11601 // element will deal with it.
11612 if (this.isLightDescendant(target)) 11602 if (this.isLightDescendant(/** @type {Node} */(target)))
11613 return; 11603 return;
11614 11604
11615 keyboardEvent.preventDefault(); 11605 keyboardEvent.preventDefault();
11616 keyboardEvent.stopImmediatePropagation(); 11606 keyboardEvent.stopImmediatePropagation();
11617 this._setPressed(true); 11607 this._setPressed(true);
11618 }, 11608 },
11619 11609
11620 /** 11610 /**
11621 * @param {!KeyboardEvent} event . 11611 * @param {!KeyboardEvent} event .
11622 */ 11612 */
11623 _spaceKeyUpHandler: function(event) { 11613 _spaceKeyUpHandler: function(event) {
11624 var keyboardEvent = event.detail.keyboardEvent; 11614 var keyboardEvent = event.detail.keyboardEvent;
11625 var target = Polymer.dom(keyboardEvent).localTarget; 11615 var target = Polymer.dom(keyboardEvent).localTarget;
11626 11616
11627 // Ignore the event if this is coming from a focused light child, since th at 11617 // Ignore the event if this is coming from a focused light child, since th at
11628 // element will deal with it. 11618 // element will deal with it.
11629 if (this.isLightDescendant(target)) 11619 if (this.isLightDescendant(/** @type {Node} */(target)))
11630 return; 11620 return;
11631 11621
11632 if (this.pressed) { 11622 if (this.pressed) {
11633 this._asyncClick(); 11623 this._asyncClick();
11634 } 11624 }
11635 this._setPressed(false); 11625 this._setPressed(false);
11636 }, 11626 },
11637 11627
11638 // trigger click asynchronously, the asynchrony is useful to allow one 11628 // trigger click asynchronously, the asynchrony is useful to allow one
11639 // event handler to unwind before triggering another event 11629 // event handler to unwind before triggering another event
(...skipping 932 matching lines...) Expand 10 before | Expand all | Expand 10 after
12572 } 12562 }
12573 }, 12563 },
12574 12564
12575 _calculateElevation: function() { 12565 _calculateElevation: function() {
12576 if (!this.raised) { 12566 if (!this.raised) {
12577 this.elevation = 0; 12567 this.elevation = 0;
12578 } else { 12568 } else {
12579 Polymer.PaperButtonBehaviorImpl._calculateElevation.apply(this); 12569 Polymer.PaperButtonBehaviorImpl._calculateElevation.apply(this);
12580 } 12570 }
12581 } 12571 }
12572 /**
12573
12574 Fired when the animation finishes.
12575 This is useful if you want to wait until
12576 the ripple animation finishes to perform some action.
12577
12578 @event transitionend
12579 @param {{node: Object}} detail Contains the animated node.
12580 */
12582 }); 12581 });
12583 /** 12582 /**
12584 * `iron-range-behavior` provides the behavior for something with a minimum to m aximum range. 12583 * `iron-range-behavior` provides the behavior for something with a minimum to m aximum range.
12585 * 12584 *
12586 * @demo demo/index.html 12585 * @demo demo/index.html
12587 * @polymerBehavior 12586 * @polymerBehavior
12588 */ 12587 */
12589 Polymer.IronRangeBehavior = { 12588 Polymer.IronRangeBehavior = {
12590 12589
12591 properties: { 12590 properties: {
(...skipping 1163 matching lines...) Expand 10 before | Expand all | Expand 10 after
13755 /** 13754 /**
13756 * Given a KeyboardEvent, this method will focus the appropriate item in the 13755 * Given a KeyboardEvent, this method will focus the appropriate item in the
13757 * menu (if there is a relevant item, and it is possible to focus it). 13756 * menu (if there is a relevant item, and it is possible to focus it).
13758 * 13757 *
13759 * @param {KeyboardEvent} event A KeyboardEvent. 13758 * @param {KeyboardEvent} event A KeyboardEvent.
13760 */ 13759 */
13761 _focusWithKeyboardEvent: function(event) { 13760 _focusWithKeyboardEvent: function(event) {
13762 for (var i = 0, item; item = this.items[i]; i++) { 13761 for (var i = 0, item; item = this.items[i]; i++) {
13763 var attr = this.attrForItemTitle || 'textContent'; 13762 var attr = this.attrForItemTitle || 'textContent';
13764 var title = item[attr] || item.getAttribute(attr); 13763 var title = item[attr] || item.getAttribute(attr);
13764
13765 if (title && title.trim().charAt(0).toLowerCase() === String.fromCharCod e(event.keyCode).toLowerCase()) { 13765 if (title && title.trim().charAt(0).toLowerCase() === String.fromCharCod e(event.keyCode).toLowerCase()) {
13766 this._setFocusedItem(item); 13766 this._setFocusedItem(item);
13767 break; 13767 break;
13768 } 13768 }
13769 } 13769 }
13770 }, 13770 },
13771 13771
13772 /** 13772 /**
13773 * Focuses the previous item (relative to the currently focused item) in the 13773 * Focuses the previous item (relative to the currently focused item) in the
13774 * menu. 13774 * menu.
(...skipping 20 matching lines...) Expand all
13795 * @param {Element} item An item in the menu. 13795 * @param {Element} item An item in the menu.
13796 * @param {boolean} isSelected True if the item should be shown in a 13796 * @param {boolean} isSelected True if the item should be shown in a
13797 * selected state, otherwise false. 13797 * selected state, otherwise false.
13798 */ 13798 */
13799 _applySelection: function(item, isSelected) { 13799 _applySelection: function(item, isSelected) {
13800 if (isSelected) { 13800 if (isSelected) {
13801 item.setAttribute('aria-selected', 'true'); 13801 item.setAttribute('aria-selected', 'true');
13802 } else { 13802 } else {
13803 item.removeAttribute('aria-selected'); 13803 item.removeAttribute('aria-selected');
13804 } 13804 }
13805
13806 Polymer.IronSelectableBehavior._applySelection.apply(this, arguments); 13805 Polymer.IronSelectableBehavior._applySelection.apply(this, arguments);
13807 }, 13806 },
13808 13807
13809 /** 13808 /**
13810 * Discretely updates tabindex values among menu items as the focused item 13809 * Discretely updates tabindex values among menu items as the focused item
13811 * changes. 13810 * changes.
13812 * 13811 *
13813 * @param {Element} focusedItem The element that is currently focused. 13812 * @param {Element} focusedItem The element that is currently focused.
13814 * @param {?Element} old The last element that was considered focused, if 13813 * @param {?Element} old The last element that was considered focused, if
13815 * applicable. 13814 * applicable.
(...skipping 27 matching lines...) Expand all
13843 } 13842 }
13844 } 13843 }
13845 }, 13844 },
13846 13845
13847 /** 13846 /**
13848 * Handler that is called when a shift+tab keypress is detected by the menu. 13847 * Handler that is called when a shift+tab keypress is detected by the menu.
13849 * 13848 *
13850 * @param {CustomEvent} event A key combination event. 13849 * @param {CustomEvent} event A key combination event.
13851 */ 13850 */
13852 _onShiftTabDown: function(event) { 13851 _onShiftTabDown: function(event) {
13853 var oldTabIndex; 13852 var oldTabIndex = this.getAttribute('tabindex');
13854 13853
13855 Polymer.IronMenuBehaviorImpl._shiftTabPressed = true; 13854 Polymer.IronMenuBehaviorImpl._shiftTabPressed = true;
13856 13855
13857 oldTabIndex = this.getAttribute('tabindex'); 13856 this._setFocusedItem(null);
13858 13857
13859 this.setAttribute('tabindex', '-1'); 13858 this.setAttribute('tabindex', '-1');
13860 13859
13861 this.async(function() { 13860 this.async(function() {
13862 this.setAttribute('tabindex', oldTabIndex); 13861 this.setAttribute('tabindex', oldTabIndex);
13863 Polymer.IronMenuBehaviorImpl._shiftTabPressed = false; 13862 Polymer.IronMenuBehaviorImpl._shiftTabPressed = false;
13864 // NOTE(cdata): polymer/polymer#1305 13863 // NOTE(cdata): polymer/polymer#1305
13865 }, 1); 13864 }, 1);
13866 }, 13865 },
13867 13866
13868 /** 13867 /**
13869 * Handler that is called when the menu receives focus. 13868 * Handler that is called when the menu receives focus.
13870 * 13869 *
13871 * @param {FocusEvent} event A focus event. 13870 * @param {FocusEvent} event A focus event.
13872 */ 13871 */
13873 _onFocus: function(event) { 13872 _onFocus: function(event) {
13874 if (Polymer.IronMenuBehaviorImpl._shiftTabPressed) { 13873 if (Polymer.IronMenuBehaviorImpl._shiftTabPressed) {
13874 // do not focus the menu itself
13875 return; 13875 return;
13876 } 13876 }
13877 // do not focus the menu itself 13877
13878 this.blur(); 13878 this.blur();
13879
13879 // clear the cached focus item 13880 // clear the cached focus item
13880 this._setFocusedItem(null);
13881 this._defaultFocusAsync = this.async(function() { 13881 this._defaultFocusAsync = this.async(function() {
13882 // focus the selected item when the menu receives focus, or the first it em 13882 // focus the selected item when the menu receives focus, or the first it em
13883 // if no item is selected 13883 // if no item is selected
13884 var selectedItem = this.multi ? (this.selectedItems && this.selectedItem s[0]) : this.selectedItem; 13884 var selectedItem = this.multi ? (this.selectedItems && this.selectedItem s[0]) : this.selectedItem;
13885
13886 this._setFocusedItem(null);
13887
13885 if (selectedItem) { 13888 if (selectedItem) {
13886 this._setFocusedItem(selectedItem); 13889 this._setFocusedItem(selectedItem);
13887 } else { 13890 } else {
13888 this._setFocusedItem(this.items[0]); 13891 this._setFocusedItem(this.items[0]);
13889 } 13892 }
13890 // async 100ms to wait for `select` to get called from `_itemActivate` 13893 // async 1ms to wait for `select` to get called from `_itemActivate`
13891 }, 100); 13894 }, 1);
13892 }, 13895 },
13893 13896
13894 /** 13897 /**
13895 * Handler that is called when the up key is pressed. 13898 * Handler that is called when the up key is pressed.
13896 * 13899 *
13897 * @param {CustomEvent} event A key combination event. 13900 * @param {CustomEvent} event A key combination event.
13898 */ 13901 */
13899 _onUpKey: function(event) { 13902 _onUpKey: function(event) {
13900 // up and down arrows moves the focus 13903 // up and down arrows moves the focus
13901 this._focusPrevious(); 13904 this._focusPrevious();
(...skipping 17 matching lines...) Expand all
13919 // esc blurs the control 13922 // esc blurs the control
13920 this.focusedItem.blur(); 13923 this.focusedItem.blur();
13921 }, 13924 },
13922 13925
13923 /** 13926 /**
13924 * Handler that is called when a keydown event is detected. 13927 * Handler that is called when a keydown event is detected.
13925 * 13928 *
13926 * @param {KeyboardEvent} event A keyboard event. 13929 * @param {KeyboardEvent} event A keyboard event.
13927 */ 13930 */
13928 _onKeydown: function(event) { 13931 _onKeydown: function(event) {
13929 if (this.keyboardEventMatchesKeys(event, 'up down esc')) { 13932 if (!this.keyboardEventMatchesKeys(event, 'up down esc')) {
13930 return; 13933 // all other keys focus the menu item starting with that character
13934 this._focusWithKeyboardEvent(event);
13931 } 13935 }
13936 event.stopPropagation();
13937 },
13932 13938
13933 // all other keys focus the menu item starting with that character 13939 // override _activateHandler
13934 this._focusWithKeyboardEvent(event); 13940 _activateHandler: function(event) {
13941 Polymer.IronSelectableBehavior._activateHandler.call(this, event);
13942 event.stopPropagation();
13935 } 13943 }
13936 }; 13944 };
13937 13945
13938 Polymer.IronMenuBehaviorImpl._shiftTabPressed = false; 13946 Polymer.IronMenuBehaviorImpl._shiftTabPressed = false;
13939 13947
13940 /** @polymerBehavior Polymer.IronMenuBehavior */ 13948 /** @polymerBehavior Polymer.IronMenuBehavior */
13941 Polymer.IronMenuBehavior = [ 13949 Polymer.IronMenuBehavior = [
13942 Polymer.IronMultiSelectableBehavior, 13950 Polymer.IronMultiSelectableBehavior,
13943 Polymer.IronA11yKeysBehavior, 13951 Polymer.IronA11yKeysBehavior,
13944 Polymer.IronMenuBehaviorImpl 13952 Polymer.IronMenuBehaviorImpl
(...skipping 3024 matching lines...) Expand 10 before | Expand all | Expand 10 after
16969 items_: { 16977 items_: {
16970 type: Array, 16978 type: Array,
16971 value: function() { return []; }, 16979 value: function() { return []; },
16972 }, 16980 },
16973 }, 16981 },
16974 16982
16975 hostAttributes: { 16983 hostAttributes: {
16976 loading: true, 16984 loading: true,
16977 }, 16985 },
16978 16986
16987 listeners: {
16988 'downloads-list.scroll': 'onListScroll_',
16989 },
16990
16979 observers: [ 16991 observers: [
16980 'itemsChanged_(items_.*)', 16992 'itemsChanged_(items_.*)',
16981 ], 16993 ],
16982 16994
16983 /** @private */ 16995 /** @private */
16984 clearAll_: function() { 16996 clearAll_: function() {
16985 this.set('items_', []); 16997 this.set('items_', []);
16986 }, 16998 },
16987 16999
16988 /** @private */ 17000 /** @private */
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
17036 * @param {Event} e 17048 * @param {Event} e
17037 * @private 17049 * @private
17038 */ 17050 */
17039 onCommand_: function(e) { 17051 onCommand_: function(e) {
17040 if (e.command.id == 'clear-all-command') 17052 if (e.command.id == 'clear-all-command')
17041 downloads.ActionService.getInstance().clearAll(); 17053 downloads.ActionService.getInstance().clearAll();
17042 else if (e.command.id == 'undo-command') 17054 else if (e.command.id == 'undo-command')
17043 downloads.ActionService.getInstance().undo(); 17055 downloads.ActionService.getInstance().undo();
17044 }, 17056 },
17045 17057
17058 /**
17059 * @param {Event} e
17060 * @private
17061 */
17062 onListScroll_: function(e) {
17063 var list = this.$['downloads-list'];
17064 if (list.scrollHeight - list.scrollTop - list.offsetHeight <= 100) {
17065 // Approaching the end of the scrollback. Attempt to load more items.
17066 downloads.ActionService.getInstance().loadMore();
17067 }
17068 },
17069
17046 /** @private */ 17070 /** @private */
17047 onLoad_: function() { 17071 onLoad_: function() {
17048 cr.ui.decorate('command', cr.ui.Command); 17072 cr.ui.decorate('command', cr.ui.Command);
17049 document.addEventListener('canExecute', this.onCanExecute_.bind(this)); 17073 document.addEventListener('canExecute', this.onCanExecute_.bind(this));
17050 document.addEventListener('command', this.onCommand_.bind(this)); 17074 document.addEventListener('command', this.onCommand_.bind(this));
17051 17075
17052 // Shows all downloads. 17076 downloads.ActionService.getInstance().loadMore();
17053 downloads.ActionService.getInstance().search('');
17054 }, 17077 },
17055 17078
17056 /** 17079 /**
17057 * @param {number} index 17080 * @param {number} index
17058 * @private 17081 * @private
17059 */ 17082 */
17060 removeItem_: function(index) { 17083 removeItem_: function(index) {
17061 this.splice('items_', index, 1); 17084 this.splice('items_', index, 1);
17062 this.updateHideDates_(index, index); 17085 this.updateHideDates_(index, index);
17086 this.onListScroll_();
17063 }, 17087 },
17064 17088
17065 /** 17089 /**
17066 * @param {number} start 17090 * @param {number} start
17067 * @param {number} end 17091 * @param {number} end
17068 * @private 17092 * @private
17069 */ 17093 */
17070 updateHideDates_: function(start, end) { 17094 updateHideDates_: function(start, end) {
17071 for (var i = start; i <= end; ++i) { 17095 for (var i = start; i <= end; ++i) {
17072 var current = this.items_[i]; 17096 var current = this.items_[i];
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
17115 Manager.get().updateItem_(index, data); 17139 Manager.get().updateItem_(index, data);
17116 }; 17140 };
17117 17141
17118 return {Manager: Manager}; 17142 return {Manager: Manager};
17119 }); 17143 });
17120 // Copyright 2015 The Chromium Authors. All rights reserved. 17144 // Copyright 2015 The Chromium Authors. All rights reserved.
17121 // Use of this source code is governed by a BSD-style license that can be 17145 // Use of this source code is governed by a BSD-style license that can be
17122 // found in the LICENSE file. 17146 // found in the LICENSE file.
17123 17147
17124 window.addEventListener('load', downloads.Manager.onLoad); 17148 window.addEventListener('load', downloads.Manager.onLoad);
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698