summaryrefslogtreecommitdiffstats
path: root/chrome/browser/resources/history.html
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/resources/history.html')
-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;