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

Side by Side Diff: chrome/browser/resources/new_tab.html

Issue 17226: Add hover cards to the recently closed windows on the new tab page. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 11 months 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 <!DOCTYPE HTML> 1 <!DOCTYPE HTML>
2 <html id="t" jsvalues="dir:textdirection;firstview:firstview"> 2 <html id="t" jsvalues="dir:textdirection;firstview:firstview">
3 <!-- 3 <!--
4 This page is optimized for perceived performance. Our enemies are the time 4 This page is optimized for perceived performance. Our enemies are the time
5 taken for the backend to generate our data, and the time taken to parse 5 taken for the backend to generate our data, and the time taken to parse
6 and render the starting HTML/CSS content of the page. This page is 6 and render the starting HTML/CSS content of the page. This page is
7 designed to let Chrome do both of those things in parallel. 7 designed to let Chrome do both of those things in parallel.
8 8
9 1. Defines temporary content callback functions 9 1. Defines temporary content callback functions
10 2. Fires off requests for content (these can come back 20-150ms later) 10 2. Fires off requests for content (these can come back 20-150ms later)
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after
276 margin:3px 0px 3px 0px; 276 margin:3px 0px 3px 0px;
277 min-height:16pt; 277 min-height:16pt;
278 line-height:16px; 278 line-height:16px;
279 overflow: hidden; 279 overflow: hidden;
280 text-overflow: ellipsis; 280 text-overflow: ellipsis;
281 text-decoration:underline; 281 text-decoration:underline;
282 } 282 }
283 .recent-window-container { 283 .recent-window-container {
284 line-height:16px; 284 line-height:16px;
285 display:block; 285 display:block;
286 margin:3px 0px 3px 22px; 286 margin:3px 0px 3px 0px;
287 } 287 }
288 .recent-window-container img { 288 .recent-window-container img {
289 margin:0 3px -2px 3px; 289 margin:0 3px -2px 3px;
290 } 290 }
291 .recent-window-hover-container {
292 position:absolute;
293 border:1px solid #999;
294 -webkit-box-shadow: 5px 5px 10px #ccc;
295 background-color:white;
296 width: 157px;
297 left: 20px;
298 white-space:nowrap;
299 opacity:.9;
300 }
301 .recent-window-hover-container .recent-bookmark {
302 text-decoration:none;
303 text-overflow:ellipsis;
304 overflow:hidden;
305 margin: 3px 0 0 5px;
306 }
307 .recently-closed-window-link {
308 'text-decoration:none';
309 }
310 .recently-close-window-text {
311 text-decoration:underline;
312 }
313
291 html[dir='rtl'] .recent-bookmark { 314 html[dir='rtl'] .recent-bookmark {
292 background-position:right; 315 background-position:right;
293 padding-left:0px; 316 padding-left:0px;
294 padding-right:22px; 317 padding-right:22px;
295 } 318 }
296 a { 319 a {
297 color:#0000cc; 320 color:#0000cc;
298 text-decoration:underline; 321 text-decoration:underline;
299 white-space: nowrap; 322 white-space: nowrap;
300 } 323 }
(...skipping 12 matching lines...) Expand all
313 padding:3px 10px 3px 9px; 336 padding:3px 10px 3px 9px;
314 -webkit-border-radius:5px 5px; 337 -webkit-border-radius:5px 5px;
315 margin-bottom:10px; 338 margin-bottom:10px;
316 } 339 }
317 #searches { 340 #searches {
318 background-color:#e1ecfe; 341 background-color:#e1ecfe;
319 } 342 }
320 #recentlyBookmarked { 343 #recentlyBookmarked {
321 background-color:#e1ecfe; 344 background-color:#e1ecfe;
322 } 345 }
346 #recentlyClosedContainer {
347 position:relative;
Jo 2009/01/07 04:48:55 Will it be a good idea to add back a background co
348 }
323 #searches input { 349 #searches input {
324 border:1px solid #7f9db9; 350 border:1px solid #7f9db9;
325 background-repeat: no-repeat; 351 background-repeat: no-repeat;
326 background-position:4px center; 352 background-position:4px center;
327 padding-left: 23px; 353 padding-left: 23px;
328 min-height:24px; 354 min-height:24px;
329 width:182px; 355 width:182px;
330 margin-bottom:8px; 356 margin-bottom:8px;
331 display:block; 357 display:block;
332 } 358 }
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
441 467
442 /* Return a DOM element with tag name |elem| and attributes |attrs|. */ 468 /* Return a DOM element with tag name |elem| and attributes |attrs|. */
443 function DOM(elem, attrs) { 469 function DOM(elem, attrs) {
444 var elem = document.createElement(elem); 470 var elem = document.createElement(elem);
445 for (var attr in attrs) { 471 for (var attr in attrs) {
446 elem[attr] = attrs[attr]; 472 elem[attr] = attrs[attr];
447 } 473 }
448 return elem; 474 return elem;
449 } 475 }
450 476
477 /**
478 * Partially applies this function to a particular 'this object' and zero or
479 * more arguments. The result is a new function with some arguments of the first
480 * function pre-filled and the value of |this| 'pre-specified'.<br><br>
481 *
482 * Remaining arguments specified at call-time are appended to the pre-
483 * specified ones.<br><br>
484 *
485 * @param {Function} fn A function to partially apply.
486 * @param {Object} selfObj Specifies the object which |this| should point to
487 * when the function is run.
488 * @param {Object} var_args Additional arguments that are partially
489 * applied to the function.
490 *
491 * @return {!Function} A partially-applied form of the function bind() was
492 * invoked as a method of.
493 */
494 function bind(fn, selfObj, var_args) {
495 var boundArgs = Array.prototype.slice.call(arguments, 2);
496 return function() {
497 var args = Array.prototype.slice.call(arguments);
498 args.unshift.apply(args, boundArgs);
499 return fn.apply(selfObj, args);
500 }
501 }
502
451 /* Return the DOM element for a "most visited" entry. 503 /* Return the DOM element for a "most visited" entry.
452 |page| should be an object with "title" and "url" fields. */ 504 |page| should be an object with "title" and "url" fields. */
453 function makeMostVisitedDOM(page, number) { 505 function makeMostVisitedDOM(page, number) {
454 /* The HTML we want looks like this: 506 /* The HTML we want looks like this:
455 <a class="most-visited-item" href="URL" title="gmail.com"> 507 <a class="most-visited-item" href="URL" title="gmail.com">
456 <div class="thumbnail-title" style="background-image:url(faviconurl);">gma il.com</div> 508 <div class="thumbnail-title" style="background-image:url(faviconurl);">gma il.com</div>
457 <img class="thumbnail" style="background-image:url(thumbnailurl);" /> 509 <img class="thumbnail" style="background-image:url(thumbnailurl);" />
458 </a> 510 </a>
459 */ 511 */
460 var root; 512 var root;
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
634 container.innerHTML = ''; 686 container.innerHTML = '';
635 687
636 if (entries.length > 0) { 688 if (entries.length > 0) {
637 section.style.display = 'block'; 689 section.style.display = 'block';
638 690
639 for (var i = 0; entry = entries[i]; ++i) { 691 for (var i = 0; entry = entries[i]; ++i) {
640 var link; 692 var link;
641 693
642 if (entry.type == "tab") { 694 if (entry.type == "tab") {
643 // Closed tab. 695 // Closed tab.
644 link = DOM('a', {href:entry.url, className:'recent-bookmark', title:entr y.title}); 696 link = createRecentBookmark('a', entry);
645 link.style.backgroundImage = 'url("chrome://favicon/' + entry.url + '")' ;
646 link.appendChild(document.createTextNode(entry.title));
647 container.appendChild(link); 697 container.appendChild(link);
648 } else { 698 } else {
649 // Closed window. 699 // Closed window.
650 var linkSpanContainer = DOM('div', { className: 'recent-window-container '}); 700 var linkSpanContainer = DOM('div', { className: 'recent-window-container '});
701
651 var linkSpan = DOM('span'); 702 var linkSpan = DOM('span');
652 link = DOM('a', { href: "window",
653 title: localStrings.getString('closedWindow') } );
654 link.appendChild(
655 document.createTextNode(localStrings.getString('closedwindow')));
656 linkSpan.appendChild(link);
657 linkSpan.appendChild(document.createTextNode(" (")); 703 linkSpan.appendChild(document.createTextNode(" ("));
658 for (var windowIndex = 0; windowIndex < entry.tabs.length; windowIndex++ ) { 704 for (var windowIndex = 0; windowIndex < entry.tabs.length; windowIndex++ ) {
659 var tab = entry.tabs[windowIndex]; 705 var tab = entry.tabs[windowIndex];
660 var tabImg = DOM('img', {src:'url("chrome://favicon/' + tab.url + '")' , width:16, height:16, }); 706 var tabImg = DOM('img', {src:'url("chrome://favicon/' + tab.url + '")' , width:16, height:16, });
661 linkSpan.appendChild(tabImg); 707 linkSpan.appendChild(tabImg);
662 } 708 }
663 linkSpan.appendChild(document.createTextNode(")")); 709 linkSpan.appendChild(document.createTextNode(")"));
664 linkSpanContainer.appendChild(linkSpan); 710
711 link = DOM('a', { href: 'window',
712 className: 'recently-closed-window-link',
713 title: localStrings.getString('closedWindow') } );
714 windowSpan = DOM('span', {className: 'recently-close-window-text'});
715 windowSpan.appendChild(
716 document.createTextNode(localStrings.getString('closedwindow')));
717 link.appendChild(windowSpan);
718 link.appendChild(linkSpan);
719 linkSpanContainer.appendChild(link);
665 container.appendChild(linkSpanContainer); 720 container.appendChild(linkSpanContainer);
721
722 // The card takes care of appending itself to the DOM, so no need to
723 // keep a reference to it.
724 new RecentlyClosedHoverCard(linkSpanContainer, entry);
666 } 725 }
667 726
668 link.onclick = function(sessionId) { 727 link.onclick = function(sessionId) {
669 return function() { 728 return function() {
670 chrome.send("metrics", ["NTP_TabRestored" + i]); 729 chrome.send("metrics", ["NTP_TabRestored" + i]);
671 /* This is a hack because chrome.send is hardcoded to only 730 /* This is a hack because chrome.send is hardcoded to only
672 accept arrays of strings. */ 731 accept arrays of strings. */
673 chrome.send('reopenTab', [sessionId.toString()]); 732 chrome.send('reopenTab', [sessionId.toString()]);
674 return false; 733 return false;
675 } 734 }
676 }(entry.sessionId); 735 }(entry.sessionId);
677 } 736 }
678 } 737 }
679 738
680 logEvent('renderRecentlyClosedTabs done'); 739 logEvent('renderRecentlyClosedTabs done');
681 } 740 }
682 741
742 /**
743 * Creates an item to go in the recent bookmarks or recently closed lists.
744 *
745 * @param {String} tagName Tagname for the DOM element to create.
746 * @param {Object} data Object with title and url to popuplate the element.
747 *
748 * @return {Node} The element containing the bookmark.
749 */
750 function createRecentBookmark(tagName, data) {
751 var link = DOM(tagName, {className:'recent-bookmark', title:data.title});
752 if (tagName == 'a')
753 link.href = data.url;
754 link.style.backgroundImage = 'url("chrome://favicon/' + data.url + '")';
755 link.appendChild(document.createTextNode(data.title));
756 return link;
757 }
758
759 /**
760 * A hover card for windows in the recently closed list to show more details.
761 *
762 * @param {Node} target The element the hover card is for.
763 * @param {Object} data Object containing all the data for the card.
764 */
765 function RecentlyClosedHoverCard(target, data) {
766 this.target_ = target;
767 this.data_ = data;
768 this.target_.onmouseover = bind(this.setShowTimeout_, this);
769 this.target_.onmouseout = bind(this.setHideTimeout_, this);
770 }
771
772 /** Timeout set when closing the card. */
773 RecentlyClosedHoverCard.closeTimeout_;
774
775 /** Timeout set when opening the card. */
776 RecentlyClosedHoverCard.openTimeout_;
777
778 /**
779 * Clears the timer for hiding the card.
780 */
781 RecentlyClosedHoverCard.clearHideTimeout_ = function() {
782 clearTimeout(RecentlyClosedHoverCard.closeTimeout_);
783 };
784
785 /**
786 * Clears the timer for opening the card.
787 */
788 RecentlyClosedHoverCard.clearOpenTimeout_ = function() {
789 clearTimeout(RecentlyClosedHoverCard.openTimeout_);
790 };
791
792 /**
793 * Creates and shows the card.
794 */
795 RecentlyClosedHoverCard.prototype.show_ = function() {
796 if (!this.container_) {
797 this.container_ = DOM('div', {className: 'recent-window-hover-container'});
798 for (var i = 0; i < this.data_.tabs.length; i++) {
799 var tab = this.data_.tabs[i];
800 var item = createRecentBookmark('span', tab);
801 this.container_.appendChild(item);
802 }
803 this.target_.parentNode.insertBefore(this.container_,
804 this.target_.nextSibling);
805 this.container_.onmouseover = RecentlyClosedHoverCard.clearHideTimeout_;
806 this.container_.onmouseout = bind(this.setHideTimeout_, this);
807 }
808 this.container_.style.display = '';
809 };
810
811 /**
812 * Hides teh card.
Glen Murphy 2009/01/12 23:01:07 spelling
813 */
814 RecentlyClosedHoverCard.prototype.hide_ = function() {
815 this.container_.style.display = 'none';
816 };
817
818 /**
819 * Clears any open timers and sets the open timer.
820 * If the card is already showing then we only need to clear
821 * the hide timer.
822 */
823 RecentlyClosedHoverCard.prototype.setShowTimeout_ = function() {
824 if (this.container && this.container_.style.display != 'none') {
825 // If we're already showing the hovercard, make sure we don't hide it again
826 // onmouseover.
827 RecentlyClosedHoverCard.clearHideTimeout_();
828 return;
829 }
830
831 RecentlyClosedHoverCard.clearOpenTimeout_();
832 RecentlyClosedHoverCard.openTimeout_ =
833 setTimeout(bind(this.show_, this), 200);
834 };
835
836 /**
837 * Clears the open timer and sets the close one.
838 */
839 RecentlyClosedHoverCard.prototype.setHideTimeout_ = function() {
840 RecentlyClosedHoverCard.clearOpenTimeout_();
841 RecentlyClosedHoverCard.closeTimeout_ =
842 setTimeout(bind(this.hide_, this), 200);
843 };
844
683 function viewLog() { 845 function viewLog() {
684 var lines = []; 846 var lines = [];
685 var start = log[0][1]; 847 var start = log[0][1];
686 848
687 for (var i = 0; i < log.length; i++) { 849 for (var i = 0; i < log.length; i++) {
688 lines.push((log[i][1] - start) + ': ' + log[i][0]); 850 lines.push((log[i][1] - start) + ': ' + log[i][0]);
689 } 851 }
690 852
691 var lognode = document.createElement('pre'); 853 var lognode = document.createElement('pre');
692 lognode.appendChild(document.createTextNode(lines.join("\n"))); 854 lognode.appendChild(document.createTextNode(lines.join("\n")));
693 document.body.appendChild(lognode); 855 document.body.appendChild(lognode);
694 } 856 }
695 857
696 logEvent('end of second script block'); 858 logEvent('end of second script block');
697 859
698 localStrings = new LocalStrings($('l10n')); 860 localStrings = new LocalStrings($('l10n'));
699 861
700 // We've got all the JS we need, render any unprocessed data. 862 // We've got all the JS we need, render any unprocessed data.
701 renderFunctionsDefined = true; 863 renderFunctionsDefined = true;
702 processData(); 864 processData();
703 865
704 // In case renderMostVisitedItems doesn't come back quickly enough, begin 866 // In case renderMostVisitedItems doesn't come back quickly enough, begin
705 // the first-run fade-in. If it has started or if this is not a first 867 // the first-run fade-in. If it has started or if this is not a first
706 // run new tab, this will be a no-op. 868 // run new tab, this will be a no-op.
707 setTimeout(function(){document.getElementById('main').className = 'visible'}, 869 setTimeout(function(){document.getElementById('main').className = 'visible'},
708 1000); 870 1000);
709 </script> 871 </script>
710 </body> 872 </body>
711 </html> 873 </html>
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698