home *** CD-ROM | disk | FTP | other *** search
/ Freelog 115 / FreelogNo115-MaiJuin2013.iso / Internet / AvantBrowser / asetup.exe / _data / webkit / chrome.dll / 0 / BINDATA / 599 < prev    next >
Encoding:
Text File  |  2013-04-03  |  13.2 KB  |  475 lines

  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4.  
  5. cr.define('ntp', function() {
  6.   'use strict';
  7.  
  8.   var TilePage = ntp.TilePage;
  9.  
  10.   /**
  11.    * A counter for generating unique tile IDs.
  12.    */
  13.   var tileID = 0;
  14.  
  15.   /**
  16.    * Creates a new Suggestions page object for tiling.
  17.    * @constructor
  18.    * @extends {HTMLAnchorElement}
  19.    */
  20.   function Suggestion() {
  21.     var el = cr.doc.createElement('a');
  22.     el.__proto__ = Suggestion.prototype;
  23.     el.initialize();
  24.  
  25.     return el;
  26.   }
  27.  
  28.   Suggestion.prototype = {
  29.     __proto__: HTMLAnchorElement.prototype,
  30.  
  31.     initialize: function() {
  32.       this.reset();
  33.  
  34.       this.addEventListener('click', this.handleClick_);
  35.       this.addEventListener('keydown', this.handleKeyDown_);
  36.     },
  37.  
  38.     get index() {
  39.       assert(this.tile);
  40.       return this.tile.index;
  41.     },
  42.  
  43.     get data() {
  44.       return this.data_;
  45.     },
  46.  
  47.     /**
  48.      * Clears the DOM hierarchy for this node, setting it back to the default
  49.      * for a blank thumbnail. TODO(georgey) make it a template.
  50.      */
  51.     reset: function() {
  52.       this.className = 'suggestions filler real';
  53.       this.innerHTML =
  54.           '<span class="thumbnail-wrapper fills-parent">' +
  55.             '<div class="close-button"></div>' +
  56.             '<span class="thumbnail fills-parent">' +
  57.               // thumbnail-shield provides a gradient fade effect.
  58.               '<div class="thumbnail-shield fills-parent"></div>' +
  59.             '</span>' +
  60.             '<span class="favicon"></span>' +
  61.           '</span>' +
  62.           '<div class="color-stripe"></div>' +
  63.           '<span class="title"></span>' +
  64.           '<span class="score"></span>';
  65.  
  66.       this.querySelector('.close-button').title =
  67.           loadTimeData.getString('removethumbnailtooltip');
  68.  
  69.       this.tabIndex = -1;
  70.       this.data_ = null;
  71.       this.removeAttribute('id');
  72.       this.title = '';
  73.     },
  74.  
  75.     /**
  76.      * Update the appearance of this tile according to |data|.
  77.      * @param {Object} data A dictionary of relevant data for the page.
  78.      */
  79.     updateForData: function(data) {
  80.       if (this.classList.contains('blacklisted') && data) {
  81.         // Animate appearance of new tile.
  82.         this.classList.add('new-tile-contents');
  83.       }
  84.       this.classList.remove('blacklisted');
  85.  
  86.       if (!data || data.filler) {
  87.         if (this.data_)
  88.           this.reset();
  89.         return;
  90.       }
  91.  
  92.       var id = tileID++;
  93.       this.id = 'suggestions-tile-' + id;
  94.       this.data_ = data;
  95.       this.classList.add('focusable');
  96.  
  97.       var faviconDiv = this.querySelector('.favicon');
  98.       var faviconUrl = 'chrome://favicon/size/16/' + data.url;
  99.       faviconDiv.style.backgroundImage = url(faviconUrl);
  100.       chrome.send('getFaviconDominantColor', [faviconUrl, this.id]);
  101.  
  102.       var title = this.querySelector('.title');
  103.       title.textContent = data.title;
  104.       title.dir = data.direction;
  105.  
  106.       var score = this.querySelector('.score');
  107.       score.textContent = data.score;
  108.  
  109.       // Sets the tooltip.
  110.       this.title = data.title;
  111.  
  112.       var thumbnailUrl;
  113.       thumbnailUrl = data.urlImage ? data.urlImage :
  114.         'chrome://thumb/' + data.url;
  115.  
  116.       this.querySelector('.thumbnail').style.backgroundImage =
  117.           url(thumbnailUrl);
  118.  
  119.       this.href = data.url;
  120.  
  121.       this.classList.remove('filler');
  122.     },
  123.  
  124.     /**
  125.      * Sets the color of the favicon dominant color bar.
  126.      * @param {string} color The css-parsable value for the color.
  127.      */
  128.     set stripeColor(color) {
  129.       this.querySelector('.color-stripe').style.backgroundColor = color;
  130.     },
  131.  
  132.     /**
  133.      * Handles a click on the tile.
  134.      * @param {Event} e The click event.
  135.      */
  136.     handleClick_: function(e) {
  137.       if (e.target.classList.contains('close-button')) {
  138.         this.blacklist_();
  139.         e.preventDefault();
  140.       } else {
  141.         // Records the index of this tile.
  142.         chrome.send('metricsHandler:recordInHistogram',
  143.                     ['NewTabPage.SuggestedSite', this.index, 8]);
  144.         chrome.send('suggestedSitesAction',
  145.                     [ntp.NtpFollowAction.CLICKED_TILE]);
  146.       }
  147.     },
  148.  
  149.     /**
  150.      * Allow blacklisting suggestions site using the keyboard.
  151.      * @param {Event} e The keydown event.
  152.      */
  153.     handleKeyDown_: function(e) {
  154.       if (!cr.isMac && e.keyCode == 46 || // Del
  155.           cr.isMac && e.metaKey && e.keyCode == 8) { // Cmd + Backspace
  156.         this.blacklist_();
  157.       }
  158.     },
  159.  
  160.     /**
  161.      * Permanently removes a page from Suggestions.
  162.      */
  163.     blacklist_: function() {
  164.       this.showUndoNotification_();
  165.       chrome.send('blacklistURLFromSuggestions', [this.data_.url]);
  166.       this.reset();
  167.       chrome.send('getSuggestions');
  168.       this.classList.add('blacklisted');
  169.     },
  170.  
  171.     /**
  172.      * Shows notification that you can undo blacklisting.
  173.      */
  174.     showUndoNotification_: function() {
  175.       var data = this.data_;
  176.       var self = this;
  177.       var doUndo = function() {
  178.         chrome.send('removeURLsFromSuggestionsBlacklist', [data.url]);
  179.         self.updateForData(data);
  180.       };
  181.  
  182.       var undo = {
  183.         action: doUndo,
  184.         text: loadTimeData.getString('undothumbnailremove'),
  185.       };
  186.  
  187.       var undoAll = {
  188.         action: function() {
  189.           chrome.send('clearSuggestionsURLsBlacklist');
  190.         },
  191.         text: loadTimeData.getString('restoreThumbnailsShort'),
  192.       };
  193.  
  194.       ntp.showNotification(
  195.           loadTimeData.getString('thumbnailremovednotification'),
  196.           [undo, undoAll]);
  197.     },
  198.  
  199.     /**
  200.      * Set the size and position of the suggestions tile.
  201.      * @param {number} size The total size of |this|.
  202.      * @param {number} x The x-position.
  203.      * @param {number} y The y-position.
  204.      */
  205.     setBounds: function(size, x, y) {
  206.       this.style.width = size + 'px';
  207.       this.style.height = heightForWidth(size) + 'px';
  208.  
  209.       this.style.left = x + 'px';
  210.       this.style.right = x + 'px';
  211.       this.style.top = y + 'px';
  212.     },
  213.  
  214.     /**
  215.      * Returns whether this element can be 'removed' from chrome (i.e. whether
  216.      * the user can drag it onto the trash and expect something to happen).
  217.      * @return {boolean} True, since suggestions pages can always be
  218.      *     blacklisted.
  219.      */
  220.     canBeRemoved: function() {
  221.       return true;
  222.     },
  223.  
  224.     /**
  225.      * Removes this element from chrome, i.e. blacklists it.
  226.      */
  227.     removeFromChrome: function() {
  228.       this.blacklist_();
  229.       this.parentNode.classList.add('finishing-drag');
  230.     },
  231.  
  232.     /**
  233.      * Called when a drag of this tile has ended (after all animations have
  234.      * finished).
  235.      */
  236.     finalizeDrag: function() {
  237.       this.parentNode.classList.remove('finishing-drag');
  238.     },
  239.  
  240.     /**
  241.      * Called when a drag is starting on the tile. Updates dataTransfer with
  242.      * data for this tile (for dragging outside of the NTP).
  243.      * @param {Event.DataTransfer} dataTransfer The drag event data store.
  244.      */
  245.     setDragData: function(dataTransfer) {
  246.       dataTransfer.setData('Text', this.data_.title);
  247.       dataTransfer.setData('URL', this.data_.url);
  248.     },
  249.   };
  250.  
  251.   var suggestionsPageGridValues = {
  252.     // The fewest tiles we will show in a row.
  253.     minColCount: 2,
  254.     // The suggestions we will show in a row.
  255.     maxColCount: 4,
  256.  
  257.     // The smallest a tile can be.
  258.     minTileWidth: 122,
  259.     // The biggest a tile can be. 212 (max thumbnail width) + 2.
  260.     maxTileWidth: 214,
  261.  
  262.     // The padding between tiles, as a fraction of the tile width.
  263.     tileSpacingFraction: 1 / 8,
  264.   };
  265.   TilePage.initGridValues(suggestionsPageGridValues);
  266.  
  267.   /**
  268.    * Calculates the height for a Suggestion tile for a given width. The size
  269.    * is based on the thumbnail, which should have a 212:132 ratio.
  270.    * @return {number} The height.
  271.    */
  272.   function heightForWidth(width) {
  273.     // The 2s are for borders, the 36 is for the title and score.
  274.     return (width - 2) * 132 / 212 + 2 + 36;
  275.   }
  276.  
  277.   var THUMBNAIL_COUNT = 8;
  278.  
  279.   /**
  280.    * Creates a new SuggestionsPage object.
  281.    * @constructor
  282.    * @extends {TilePage}
  283.    */
  284.   function SuggestionsPage() {
  285.     var el = new TilePage(suggestionsPageGridValues);
  286.     el.__proto__ = SuggestionsPage.prototype;
  287.     el.initialize();
  288.  
  289.     return el;
  290.   }
  291.  
  292.   SuggestionsPage.prototype = {
  293.     __proto__: TilePage.prototype,
  294.  
  295.     initialize: function() {
  296.       this.classList.add('suggestions-page');
  297.       this.data_ = null;
  298.       this.suggestionsTiles_ = this.getElementsByClassName('suggestions real');
  299.  
  300.       this.addEventListener('carddeselected', this.handleCardDeselected_);
  301.       this.addEventListener('cardselected', this.handleCardSelected_);
  302.     },
  303.  
  304.     /**
  305.      * Create blank (filler) tiles.
  306.      * @private
  307.      */
  308.     createTiles_: function() {
  309.       for (var i = 0; i < THUMBNAIL_COUNT; i++) {
  310.         this.appendTile(new Suggestion());
  311.       }
  312.     },
  313.  
  314.     /**
  315.      * Update the tiles after a change to |this.data_|.
  316.      */
  317.     updateTiles_: function() {
  318.       for (var i = 0; i < THUMBNAIL_COUNT; i++) {
  319.         var page = this.data_[i];
  320.         var tile = this.suggestionsTiles_[i];
  321.  
  322.         if (i >= this.data_.length)
  323.           tile.reset();
  324.         else
  325.           tile.updateForData(page);
  326.       }
  327.     },
  328.  
  329.     /**
  330.      * Handles the 'card deselected' event (i.e. the user clicked to another
  331.      * pane).
  332.      * @param {Event} e The CardChanged event.
  333.      */
  334.     handleCardDeselected_: function(e) {
  335.       if (!document.documentElement.classList.contains('starting-up')) {
  336.         chrome.send('suggestedSitesAction',
  337.                     [ntp.NtpFollowAction.CLICKED_OTHER_NTP_PANE]);
  338.       }
  339.     },
  340.  
  341.     /**
  342.      * Handles the 'card selected' event (i.e. the user clicked to select the
  343.      * Suggested pane).
  344.      * @param {Event} e The CardChanged event.
  345.      */
  346.     handleCardSelected_: function(e) {
  347.       if (!document.documentElement.classList.contains('starting-up'))
  348.         chrome.send('suggestedSitesSelected');
  349.     },
  350.  
  351.     /**
  352.      * Array of suggestions data objects.
  353.      * @type {Array}
  354.      */
  355.     get data() {
  356.       return this.data_;
  357.     },
  358.     set data(data) {
  359.       var startTime = Date.now();
  360.  
  361.       // The first time data is set, create the tiles.
  362.       if (!this.data_) {
  363.         this.createTiles_();
  364.         this.data_ = data.slice(0, THUMBNAIL_COUNT);
  365.       } else {
  366.         this.data_ = refreshData(this.data_, data);
  367.       }
  368.  
  369.       this.updateTiles_();
  370.       logEvent('suggestions.layout: ' + (Date.now() - startTime));
  371.     },
  372.  
  373.     /** @override */
  374.     shouldAcceptDrag: function(e) {
  375.       return false;
  376.     },
  377.  
  378.     /** @override */
  379.     heightForWidth: heightForWidth,
  380.   };
  381.  
  382.   /**
  383.    * Executed once the NTP has loaded. Checks if the Suggested pane is
  384.    * shown or not. If it is shown, the 'suggestedSitesSelected' message is sent
  385.    * to the C++ code, to record the fact that the user has seen this pane.
  386.    */
  387.   SuggestionsPage.onLoaded = function() {
  388.     if (ntp.getCardSlider() &&
  389.         ntp.getCardSlider().currentCardValue &&
  390.         ntp.getCardSlider().currentCardValue.classList
  391.         .contains('suggestions-page')) {
  392.       chrome.send('suggestedSitesSelected');
  393.     }
  394.   }
  395.  
  396.   /**
  397.    * We've gotten additional data for Suggestions page. Update our old data with
  398.    * the new data. The ordering of the new data is not important, except when a
  399.    * page is pinned. Thus we try to minimize re-ordering.
  400.    * @param {Array} oldData The current Suggestions page list.
  401.    * @param {Array} newData The new Suggestions page list.
  402.    * @return {Array} The merged page list that should replace the current page
  403.    * list.
  404.    */
  405.   function refreshData(oldData, newData) {
  406.     oldData = oldData.slice(0, THUMBNAIL_COUNT);
  407.     newData = newData.slice(0, THUMBNAIL_COUNT);
  408.  
  409.     // Copy over pinned sites directly.
  410.     for (var i = 0; i < newData.length; i++) {
  411.       if (newData[i].pinned) {
  412.         oldData[i] = newData[i];
  413.         // Mark the entry as 'updated' so we don't try to update again.
  414.         oldData[i].updated = true;
  415.         // Mark the newData page as 'used' so we don't try to re-use it.
  416.         newData[i].used = true;
  417.       }
  418.     }
  419.  
  420.     // Look through old pages; if they exist in the newData list, keep them
  421.     // where they are.
  422.     for (var i = 0; i < oldData.length; i++) {
  423.       if (!oldData[i] || oldData[i].updated)
  424.         continue;
  425.  
  426.       for (var j = 0; j < newData.length; j++) {
  427.         if (newData[j].used)
  428.           continue;
  429.  
  430.         if (newData[j].url == oldData[i].url) {
  431.           // The background image and other data may have changed.
  432.           oldData[i] = newData[j];
  433.           oldData[i].updated = true;
  434.           newData[j].used = true;
  435.           break;
  436.         }
  437.       }
  438.     }
  439.  
  440.     // Look through old pages that haven't been updated yet; replace them.
  441.     for (var i = 0; i < oldData.length; i++) {
  442.       if (oldData[i] && oldData[i].updated)
  443.         continue;
  444.  
  445.       for (var j = 0; j < newData.length; j++) {
  446.         if (newData[j].used)
  447.           continue;
  448.  
  449.         oldData[i] = newData[j];
  450.         oldData[i].updated = true;
  451.         newData[j].used = true;
  452.         break;
  453.       }
  454.  
  455.       if (oldData[i] && !oldData[i].updated)
  456.         oldData[i] = null;
  457.     }
  458.  
  459.     // Clear 'updated' flags so this function will work next time it's called.
  460.     for (var i = 0; i < THUMBNAIL_COUNT; i++) {
  461.       if (oldData[i])
  462.         oldData[i].updated = false;
  463.     }
  464.  
  465.     return oldData;
  466.   }
  467.  
  468.   return {
  469.     SuggestionsPage: SuggestionsPage,
  470.     refreshData: refreshData,
  471.   };
  472. });
  473.  
  474. document.addEventListener('ntpLoaded', ntp.SuggestionsPage.onLoaded);
  475.