summaryrefslogtreecommitdiffstats
path: root/chrome/browser/resources
diff options
context:
space:
mode:
authorglen@chromium.org <glen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-03-03 01:47:22 +0000
committerglen@chromium.org <glen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-03-03 01:47:22 +0000
commit13dc779186dedb868df4373ba694c9f5d7cdf419 (patch)
treebf33dcecff152df552c29ab696677165baf04a94 /chrome/browser/resources
parent08ca70052ad87e2fe620313585074b7ae453e64b (diff)
downloadchromium_src-13dc779186dedb868df4373ba694c9f5d7cdf419.zip
chromium_src-13dc779186dedb868df4373ba694c9f5d7cdf419.tar.gz
chromium_src-13dc779186dedb868df4373ba694c9f5d7cdf419.tar.bz2
Resolve crash when deleting history by preventing the deleter from being called multiple times. We need to add UI to make what's happening clearer to the user, but this gets us over the hump for now. Also change the history page to queue deletions.Allow history search from the new tab page.Make history title inclusion safer (createTextNode changes).Show starred status on history page.BUG=8214,8163,8271,8284
Review URL: http://codereview.chromium.org/28308 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@10773 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/resources')
-rw-r--r--chrome/browser/resources/history.html202
1 files changed, 137 insertions, 65 deletions
diff --git a/chrome/browser/resources/history.html b/chrome/browser/resources/history.html
index 4324d2c..0b1e9b6 100644
--- a/chrome/browser/resources/history.html
+++ b/chrome/browser/resources/history.html
@@ -15,12 +15,20 @@ var BROWSING_GAP_TIME = 15 * 60 * 1000;
function $(o) {return document.getElementById(o);}
+function createElementWithClassName(type, className) {
+ var elm = document.createElement(type);
+ elm.className = className;
+ return elm;
+}
+
// TODO(glen): Get rid of these global references, replace with a controller
// or just make the classes own more of the page.
var historyModel;
var historyView;
var localStrings;
var pageState;
+var deleteQueue = [];
+var deleteInFlight = false;
///////////////////////////////////////////////////////////////////////////////
// localStrings:
@@ -74,6 +82,7 @@ function Page(result, continued, model) {
this.model_ = model;
this.title_ = result.title;
this.url_ = result.url;
+ this.starred_ = result.starred;
this.snippet_ = result.snippet || "";
this.changed = false;
@@ -96,65 +105,69 @@ function Page(result, continued, model) {
// Page, Public: --------------------------------------------------------------
/**
- * @return {string} Gets the HTML representation of the page
+ * @return {DOMObject} Gets the DOM representation of the page
* for use in browse results.
*/
-Page.prototype.getBrowseResultHTML = function() {
- return '<div class="entry">' +
- '<div class="time">' +
- this.dateTimeOfDay +
- '</div>' +
- this.getTitleHTML_() +
- '</div>';
+Page.prototype.getBrowseResultDOM = function() {
+ var node = createElementWithClassName('div', 'entry');
+ var time = createElementWithClassName('div', 'time');
+ time.appendChild(document.createTextNode(this.dateTimeOfDay));
+ node.appendChild(time);
+ node.appendChild(this.getTitleDOM_());
+ return node;
}
/**
- * @return {string} Gets the HTML representation of the page for
+ * @return {DOMObject} Gets the DOM representation of the page for
* use in search results.
*/
-Page.prototype.getSearchResultHTML = function() {
- return '<tr class="entry"><td valign="top">' +
- '<div class="time">' +
- this.dateShort +
- '</div>' +
- '</td><td valign="top">' +
- this.getTitleHTML_() +
- '<div class="snippet">' +
- this.getHighlightedSnippet_() +
- '</div>' +
- '</td></tr>';
+Page.prototype.getSearchResultDOM = function() {
+ var row = createElementWithClassName('tr', 'entry');
+ var datecell = createElementWithClassName('td', 'time');
+ datecell.appendChild(document.createTextNode(this.dateShort));
+ row.appendChild(datecell);
+
+ var titleCell = document.createElement('td');
+ titleCell.valign = 'top';
+ titleCell.appendChild(this.getTitleDOM_());
+ var snippet = createElementWithClassName('div', 'snippet');
+ snippet.appendChild(document.createTextNode(this.snippet_));
+ this.highlightNodeContent_(snippet);
+ titleCell.appendChild(snippet);
+ row.appendChild(titleCell);
+
+ return row;
}
// Page, private: -------------------------------------------------------------
/**
- * @return {string} The page's snippet highlighted with the model's
- * current search term.
+ * Highlights the content of a node with the current search text.
+ * @param {DOMObject} node to highlight
*/
-Page.prototype.getHighlightedSnippet_ = function() {
- return Page.getHighlightedText_(this.snippet_, this.model_.getSearchText());
+Page.prototype.highlightNodeContent_ = function(node) {
+ node.innerHTML = Page.getHighlightedText_(node.innerHTML,
+ this.model_.getSearchText());
}
/**
- * @return {string} Gets the page's title highlighted with the
- * model's current search term.
+ * @return {DOMObject} DOM representation for the title block.
*/
-Page.prototype.getHighlightedTitle_ = function() {
- return Page.getHighlightedText_(this.title_, this.model_.getSearchText());
-}
+Page.prototype.getTitleDOM_ = function() {
+ var node = document.createElement('div');
+ node.className = 'title';
+ var link = document.createElement('a');
+ link.href = this.url_;
+ link.style.backgroundImage = 'url(chrome-ui://favicon/' + this.url_ + ')';
+ link.appendChild(document.createTextNode(this.title_));
+ this.highlightNodeContent_(link);
-/**
- * @return {string} HTML for the title block.
- */
-Page.prototype.getTitleHTML_ = function() {
- return '<div class="title">' +
- '<a ' +
- 'href="' + this.url_ + '" ' +
- 'style="background-image:url(chrome-ui://favicon/' +
- this.url_ + ')" ' +
- '>' +
- this.getHighlightedTitle_() +
- '</a>' +
- '</div>';
+ node.appendChild(link);
+
+ if (this.starred_) {
+ node.appendChild(createElementWithClassName('div', 'starred'));
+ }
+
+ return node;
}
// Page, private, static: -----------------------------------------------------
@@ -245,6 +258,7 @@ HistoryModel.prototype.getSearchText = function() {
*/
HistoryModel.prototype.requestPage = function(page) {
this.requestedPage_ = page;
+ this.changed = true;
this.updateSearch_();
}
@@ -476,18 +490,22 @@ HistoryView.prototype.onModelReady = function() {
* Update the page with results.
*/
HistoryView.prototype.displayResults_ = function() {
- var output = [];
+ this.resultDiv_.innerHTML = '';
+
var results = this.model_.getNumberedRange(
this.pageIndex_ * RESULTS_PER_PAGE,
this.pageIndex_ * RESULTS_PER_PAGE + RESULTS_PER_PAGE);
if (this.model_.getSearchText()) {
- output.push('<table class="results" cellspacing="0" ',
- 'cellpadding="0" border="0">');
+ var resultTable = createElementWithClassName('table', 'results');
+ resultTable.cellSpacing = 0;
+ resultTable.cellPadding = 0;
+ resultTable.border = 0;
+
for (var i = 0, page; page = results[i]; i++) {
- output.push(page.getSearchResultHTML());
+ resultTable.appendChild(page.getSearchResultDOM());
}
- output.push('</table>');
+ this.resultDiv_.appendChild(resultTable);
} else {
var lastTime = Math.infinity;
for (var i = 0, page; page = results[i]; i++) {
@@ -495,26 +513,33 @@ HistoryView.prototype.displayResults_ = function() {
var thisTime = page.time.getTime();
if ((i == 0 && page.continued) || !page.continued) {
- output.push('<div class="day">' + page.dateRelativeDay);
-
- if (i == 0 && page.continued)
- output.push(' ' + localStrings.getString('cont'));
-
- output.push('<a href="#" class="delete-day" ' +
- 'onclick="return deleteDay(\'' +
- page.time.toString() + '\');">' +
- localStrings.getString("deleteday") + '</a>');
- output.push('</div>');
+ var day = createElementWithClassName('div', 'day');
+ day.appendChild(document.createTextNode(page.dateRelativeDay));
+
+ if (i == 0 && page.continued) {
+ day.appendChild(document.createTextNode(' ' +
+ localStrings.getString('cont')));
+ }
+
+ var link = createElementWithClassName('a', 'delete-day');
+ link.href = '#';
+ link.time = page.time.toString();
+ link.onclick = deleteDay;
+ link.appendChild(
+ document.createTextNode(localStrings.getString("deleteday")));
+
+ day.appendChild(link);
+ this.resultDiv_.appendChild(day);
} else if (lastTime - thisTime > BROWSING_GAP_TIME) {
- output.push('<div class="gap"></div>');
+ this.resultDiv_.appendChild(createElementWithClassName('div', 'gap'));
}
lastTime = thisTime;
- // Draw entry.
- output.push(page.getBrowseResultHTML());
+ // Add entry.
+ this.resultDiv_.appendChild(page.getBrowseResultDOM());
}
}
- this.resultDiv_.innerHTML = output.join("");
+
this.displaySummaryBar_();
this.displayNavBar_();
}
@@ -664,7 +689,9 @@ PageState.getHashString = function(term, page) {
/**
* Window onload handler, sets up the page.
*/
- function load() {
+function load() {
+ $('term').focus();
+
localStrings = new LocalStrings($('l10n'));
historyModel = new HistoryModel();
historyView = new HistoryView(historyModel);
@@ -699,14 +726,36 @@ function setPage(page) {
/**
* Delete a day from history.
+ * TODO: Add UI to indicate that something is happening.
* @param {number} time A time from the day we wish to delete.
*/
-function deleteDay(time) {
- if (confirm(localStrings.getString("deletedaywarning")))
- chrome.send("deleteDay", [time.toString()]);
+function deleteDay() {
+ var time = this.time;
+
+ // Check to see if item is already being deleted.
+ for (var i = 0, deleting; deleting = deleteQueue[i]; i++) {
+ if (deleting == time)
+ return false;
+ }
+
+ if (confirm(localStrings.getString("deletedaywarning"))) {
+ deleteQueue.push(time);
+ deleteNextInQueue();
+ }
+
return false;
}
+/**
+ * Delete the next item in our deletion queue.
+ */
+function deleteNextInQueue() {
+ if (!deleteInFlight && deleteQueue.length) {
+ deleteInFlight = true;
+ chrome.send("deleteDay", [deleteQueue[0]]);
+ }
+}
+
///////////////////////////////////////////////////////////////////////////////
// Chrome callbacks:
/**
@@ -721,6 +770,21 @@ function historyResult(term, results) {
*/
function deleteComplete() {
historyView.reload();
+ deleteInFlight = false;
+ if (deleteQueue.length > 1) {
+ deleteQueue = deleteQueue.slice(1, deleteQueue.length);
+ deleteNextInQueue();
+ }
+}
+
+/**
+ * Our history system calls this function if a delete is not ready (e.g.
+ * another delete is in-progress).
+ */
+function deleteFailed() {
+ // The deletion failed - try again later.
+ deleteInFlight = false;
+ setTimeout(deleteNextInQueue, 500);
}
</script>
<style type="text/css">
@@ -793,6 +857,14 @@ table.results {
.results .time, .results .title {
margin-top:18px;
}
+.starred {
+ background:url('../../app/theme/star_small.png');
+ background-repeat:no-repeat;
+ display:inline-block;
+ margin-left:12px;
+ width:11px;
+ height:11px;
+}
.entry .title a {
background-repeat:no-repeat;
background-size:16px;