OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 // Globals: | 6 // Globals: |
7 var RESULTS_PER_PAGE = 150; | 7 var RESULTS_PER_PAGE = 150; |
8 var MAX_SEARCH_DEPTH_MONTHS = 18; | 8 var MAX_SEARCH_DEPTH_MONTHS = 18; |
9 | 9 |
10 // Amount of time between pageviews that we consider a 'break' in browsing, | 10 // Amount of time between pageviews that we consider a 'break' in browsing, |
11 // measured in milliseconds. | 11 // measured in milliseconds. |
12 var BROWSING_GAP_TIME = 15 * 60 * 1000; | 12 var BROWSING_GAP_TIME = 15 * 60 * 1000; |
13 | 13 |
14 function $(o) {return document.getElementById(o);} | 14 function $(o) {return document.getElementById(o);} |
15 | 15 |
16 function createElementWithClassName(type, className) { | 16 function createElementWithClassName(type, className) { |
17 var elm = document.createElement(type); | 17 var elm = document.createElement(type); |
18 elm.className = className; | 18 elm.className = className; |
19 return elm; | 19 return elm; |
20 } | 20 } |
21 | 21 |
22 // Escapes a URI as appropriate for CSS. | 22 // Escapes a URI as appropriate for CSS. |
23 function encodeURIForCSS(uri) { | 23 function encodeURIForCSS(uri) { |
24 // CSS uris need to have '(' and ')' escaped. | 24 // CSS URIs need to have '(' and ')' escaped. |
25 return uri.replace(/\(/g, "\\(").replace(/\)/g, "\\)"); | 25 return uri.replace(/\(/g, "\\(").replace(/\)/g, "\\)"); |
26 } | 26 } |
27 | 27 |
28 // TODO(glen): Get rid of these global references, replace with a controller | 28 // TODO(glen): Get rid of these global references, replace with a controller |
29 // or just make the classes own more of the page. | 29 // or just make the classes own more of the page. |
30 var historyModel; | 30 var historyModel; |
31 var historyView; | 31 var historyView; |
32 var localStrings; | 32 var localStrings; |
33 var pageState; | 33 var pageState; |
34 var deleteQueue = []; | 34 var deleteQueue = []; |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
96 | 96 |
97 // Page, Public: -------------------------------------------------------------- | 97 // Page, Public: -------------------------------------------------------------- |
98 /** | 98 /** |
99 * Returns a dom structure for a browse page result or a search page result. | 99 * Returns a dom structure for a browse page result or a search page result. |
100 * @param {boolean} Flag to indicate if result is a search result. | 100 * @param {boolean} Flag to indicate if result is a search result. |
101 * @return {Element} The dom structure. | 101 * @return {Element} The dom structure. |
102 */ | 102 */ |
103 Page.prototype.getResultDOM = function(searchResultFlag) { | 103 Page.prototype.getResultDOM = function(searchResultFlag) { |
104 var node = createElementWithClassName('li', 'entry'); | 104 var node = createElementWithClassName('li', 'entry'); |
105 var time = createElementWithClassName('div', 'time'); | 105 var time = createElementWithClassName('div', 'time'); |
106 var entryBox = createElementWithClassName('div', 'entry-box'); | 106 var entryBox = createElementWithClassName('label', 'entry-box'); |
107 var domain = createElementWithClassName('div', 'domain'); | 107 var domain = createElementWithClassName('div', 'domain'); |
108 | 108 |
109 var dropDown = createElementWithClassName('button', 'drop-down'); | 109 var dropDown = createElementWithClassName('button', 'drop-down'); |
110 dropDown.value = 'Open action menu'; | 110 dropDown.value = 'Open action menu'; |
111 dropDown.title = localStrings.getString('actionMenuDescription'); | 111 dropDown.title = localStrings.getString('actionMenuDescription'); |
112 dropDown.setAttribute('menu', '#action-menu'); | 112 dropDown.setAttribute('menu', '#action-menu'); |
113 cr.ui.decorate(dropDown, MenuButton); | 113 cr.ui.decorate(dropDown, MenuButton); |
114 | 114 |
115 // Checkbox is always created, but only visible on hover & when checked. | 115 // Checkbox is always created, but only visible on hover & when checked. |
116 var checkbox = document.createElement('input'); | 116 var checkbox = document.createElement('input'); |
117 checkbox.type = 'checkbox'; | 117 checkbox.type = 'checkbox'; |
118 checkbox.id = 'checkbox-' + this.id_; | 118 checkbox.id = 'checkbox-' + this.id_; |
119 checkbox.time = this.time.getTime(); | 119 checkbox.time = this.time.getTime(); |
120 checkbox.addEventListener('click', checkboxClicked); | 120 checkbox.addEventListener('click', checkboxClicked); |
121 time.appendChild(checkbox); | 121 time.appendChild(checkbox); |
122 | 122 |
123 // Keep track of the drop down that triggered the menu, so we know | 123 // Keep track of the drop down that triggered the menu, so we know |
124 // which element to apply the command to. | 124 // which element to apply the command to. |
125 // TODO(dubroy): Ideally we'd use 'activate', but MenuButton swallows it. | 125 // TODO(dubroy): Ideally we'd use 'activate', but MenuButton swallows it. |
126 var self = this; | 126 var self = this; |
127 var setActivePage = function(e) { | 127 var setActivePage = function(e) { |
128 activePage = self; | 128 activePage = self; |
129 }; | 129 }; |
130 dropDown.addEventListener('mousedown', setActivePage); | 130 dropDown.addEventListener('mousedown', setActivePage); |
131 dropDown.addEventListener('focus', setActivePage); | 131 dropDown.addEventListener('focus', setActivePage); |
132 | 132 |
133 domain.style.backgroundImage = | |
134 'url(chrome://favicon/' + encodeURIForCSS(this.url_) + ')'; | |
135 domain.textContent = this.domain_; | 133 domain.textContent = this.domain_; |
136 | 134 |
137 // Clicking anywhere in the entryBox will check/uncheck the checkbox. | 135 // Clicking anywhere in the entryBox will check/uncheck the checkbox. |
136 entryBox.setAttribute('for', checkbox.id); | |
138 entryBox.addEventListener('mousedown', entryBoxMousedown, false); | 137 entryBox.addEventListener('mousedown', entryBoxMousedown, false); |
139 | 138 |
140 // Prevent clicks on the drop down from affecting the checkbox. | 139 // Prevent clicks on the drop down from affecting the checkbox. |
141 dropDown.addEventListener('click', function(e) { e.preventDefault(); }); | 140 dropDown.addEventListener('click', function(e) { e.preventDefault(); }); |
142 | 141 |
143 // A label around the parts that should be clicked to activate the check box. | |
144 var label = document.createElement('label'); | |
145 label.appendChild(time); | |
146 label.appendChild(domain); | |
147 | |
148 // We use a wrapper div so that the entry contents will be shinkwrapped. | 142 // We use a wrapper div so that the entry contents will be shinkwrapped. |
149 entryBox.appendChild(label); | 143 entryBox.appendChild(time); |
150 entryBox.appendChild(this.getTitleDOM_()); | 144 entryBox.appendChild(this.getTitleDOM_()); |
145 entryBox.appendChild(domain); | |
151 entryBox.appendChild(dropDown); | 146 entryBox.appendChild(dropDown); |
152 | 147 |
153 // Let the entryBox be styled appropriately when it contains keyboard focus. | 148 // Let the entryBox be styled appropriately when it contains keyboard focus. |
154 entryBox.addEventListener('focus', function() { | 149 entryBox.addEventListener('focus', function() { |
155 this.classList.add('contains-focus'); | 150 this.classList.add('contains-focus'); |
156 }, true); | 151 }, true); |
157 entryBox.addEventListener('blur', function() { | 152 entryBox.addEventListener('blur', function() { |
158 this.classList.remove('contains-focus'); | 153 this.classList.remove('contains-focus'); |
159 }, true); | 154 }, true); |
160 | 155 |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
219 } | 214 } |
220 if (i < content.length) | 215 if (i < content.length) |
221 node.appendChild(document.createTextNode(content.slice(i))); | 216 node.appendChild(document.createTextNode(content.slice(i))); |
222 }; | 217 }; |
223 | 218 |
224 /** | 219 /** |
225 * @return {DOMObject} DOM representation for the title block. | 220 * @return {DOMObject} DOM representation for the title block. |
226 */ | 221 */ |
227 Page.prototype.getTitleDOM_ = function() { | 222 Page.prototype.getTitleDOM_ = function() { |
228 var node = createElementWithClassName('div', 'title'); | 223 var node = createElementWithClassName('div', 'title'); |
224 node.style['background-image'] = | |
Evan Stade
2011/11/30 04:46:18
node.style.backgroundImage =
Patrick Dubroy
2011/12/01 16:23:47
Done.
| |
225 'url(chrome://favicon/' + encodeURIForCSS(this.url_) + ')'; | |
226 | |
229 var link = document.createElement('a'); | 227 var link = document.createElement('a'); |
230 link.href = this.url_; | 228 link.href = this.url_; |
231 link.id = "id-" + this.id_; | 229 link.id = "id-" + this.id_; |
232 | 230 |
233 // Add a tooltip, since it might be ellipsized. | 231 // Add a tooltip, since it might be ellipsized. |
234 // TODO(dubroy): Find a way to show the tooltip only when necessary. | 232 // TODO(dubroy): Find a way to show the tooltip only when necessary. |
235 link.title = this.title_; | 233 link.title = this.title_; |
236 | 234 |
237 this.addHighlightedText_(link, this.title_, this.model_.getSearchText()); | 235 this.addHighlightedText_(link, this.title_, this.model_.getSearchText()); |
238 node.appendChild(link); | 236 node.appendChild(link); |
239 | 237 |
240 if (this.starred_) { | 238 if (this.starred_) |
241 node.className += ' starred'; | |
242 node.appendChild(createElementWithClassName('div', 'starred')); | 239 node.appendChild(createElementWithClassName('div', 'starred')); |
243 } | |
244 | 240 |
245 return node; | 241 return node; |
246 }; | 242 }; |
247 | 243 |
248 /** | 244 /** |
249 * Launch a search for more history entries from the same domain. | 245 * Launch a search for more history entries from the same domain. |
250 */ | 246 */ |
251 Page.prototype.showMoreFromSite_ = function() { | 247 Page.prototype.showMoreFromSite_ = function() { |
252 setSearch(this.domain_); | 248 setSearch(this.domain_); |
253 }; | 249 }; |
(...skipping 723 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
977 var cbDate = new Date(checkbox.time); | 973 var cbDate = new Date(checkbox.time); |
978 if (date.getFullYear() != cbDate.getFullYear() || | 974 if (date.getFullYear() != cbDate.getFullYear() || |
979 date.getMonth() != cbDate.getMonth() || | 975 date.getMonth() != cbDate.getMonth() || |
980 date.getDate() != cbDate.getDate()) { | 976 date.getDate() != cbDate.getDate()) { |
981 if (urls.length > 0) { | 977 if (urls.length > 0) { |
982 queue.push([date, urls]); | 978 queue.push([date, urls]); |
983 } | 979 } |
984 urls = []; | 980 urls = []; |
985 date = cbDate; | 981 date = cbDate; |
986 } | 982 } |
987 var link = checkbox.parentNode.parentNode.parentNode.querySelector('a'); | 983 var link = checkbox.parentNode.parentNode.querySelector('a'); |
Evan Stade
2011/11/30 04:46:18
this parentnode chain is super unfortunate code
Patrick Dubroy
2011/12/01 16:23:47
Agreed. I did it in a slightly different way in my
| |
988 checkbox.disabled = true; | 984 checkbox.disabled = true; |
989 link.classList.add('to-be-removed'); | 985 link.classList.add('to-be-removed'); |
990 disabledItems.push(checkbox); | 986 disabledItems.push(checkbox); |
991 urls.push(link.href); | 987 urls.push(link.href); |
992 } | 988 } |
993 if (urls.length > 0) { | 989 if (urls.length > 0) { |
994 queue.push([date, urls]); | 990 queue.push([date, urls]); |
995 } | 991 } |
996 if (checked.length > 0 && confirm(localStrings.getString('deletewarning'))) { | 992 if (checked.length > 0 && confirm(localStrings.getString('deletewarning'))) { |
997 for (var i = 0; i < queue.length; i++) { | 993 for (var i = 0; i < queue.length; i++) { |
998 // Reload the page when the final entry has been deleted. | 994 // Reload the page when the final entry has been deleted. |
999 var callback = i == 0 ? reloadHistory : null; | 995 var callback = i == 0 ? reloadHistory : null; |
1000 | 996 |
1001 queueURLsForDeletion(queue[i][0], queue[i][1], callback); | 997 queueURLsForDeletion(queue[i][0], queue[i][1], callback); |
1002 } | 998 } |
1003 deleteNextInQueue(); | 999 deleteNextInQueue(); |
1004 } else { | 1000 } else { |
1005 // If the remove is cancelled, return the checkboxes to their | 1001 // If the remove is cancelled, return the checkboxes to their |
1006 // enabled, non-line-through state. | 1002 // enabled, non-line-through state. |
1007 for (var i = 0; i < disabledItems.length; i++) { | 1003 for (var i = 0; i < disabledItems.length; i++) { |
1008 var checkbox = disabledItems[i]; | 1004 var checkbox = disabledItems[i]; |
1009 var link = checkbox.parentNode.parentNode.parentNode.querySelector('a'); | 1005 var link = checkbox.parentNode.parentNode.querySelector('a'); |
1010 checkbox.disabled = false; | 1006 checkbox.disabled = false; |
1011 link.classList.remove('to-be-removed'); | 1007 link.classList.remove('to-be-removed'); |
1012 } | 1008 } |
1013 } | 1009 } |
1014 return false; | 1010 return false; |
1015 } | 1011 } |
1016 | 1012 |
1017 /** | 1013 /** |
1018 * Toggle state of checkbox and handle Shift modifier. | 1014 * Toggle state of checkbox and handle Shift modifier. |
1019 */ | 1015 */ |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1127 historyView.reload(); | 1123 historyView.reload(); |
1128 } | 1124 } |
1129 | 1125 |
1130 // Add handlers to HTML elements. | 1126 // Add handlers to HTML elements. |
1131 document.addEventListener('DOMContentLoaded', load); | 1127 document.addEventListener('DOMContentLoaded', load); |
1132 | 1128 |
1133 // This event lets us enable and disable menu items before the menu is shown. | 1129 // This event lets us enable and disable menu items before the menu is shown. |
1134 document.addEventListener('canExecute', function(e) { | 1130 document.addEventListener('canExecute', function(e) { |
1135 e.canExecute = true; | 1131 e.canExecute = true; |
1136 }); | 1132 }); |
OLD | NEW |