| OLD | NEW |
| (Empty) |
| 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 /** | |
| 6 * Javascript for suggestions_internals.html, served from | |
| 7 * chrome://suggestions-internals/. This is used to debug suggestions ranking. | |
| 8 * When loaded, the page will show the current set of suggestions, along with a | |
| 9 * large set of information (e.g. all the signals that were taken into | |
| 10 * consideration for deciding which pages were selected to be shown to the user) | |
| 11 * that will aid in debugging and optimizing the algorithms. | |
| 12 */ | |
| 13 cr.define('suggestionsInternals', function() { | |
| 14 'use strict'; | |
| 15 | |
| 16 /** | |
| 17 * Register our event handlers. | |
| 18 */ | |
| 19 function initialize() { | |
| 20 $('suggestions-form').addEventListener('submit', onRefreshClicked); | |
| 21 $('show-discarded').addEventListener('change', refresh); | |
| 22 refresh(); | |
| 23 } | |
| 24 | |
| 25 /** | |
| 26 * Called when the 'Refresh' button is clicked. Reloads the suggestions data. | |
| 27 */ | |
| 28 function onRefreshClicked(event) { | |
| 29 refresh(); | |
| 30 event.preventDefault(); | |
| 31 } | |
| 32 | |
| 33 /** | |
| 34 * Reloads the suggestions data by sending a 'getSuggestions' message to | |
| 35 * Chrome. The C++ code is then expected to call 'setSuggestions' when there | |
| 36 * are suggestions ready. | |
| 37 */ | |
| 38 function refresh() { | |
| 39 chrome.send('getSuggestions'); | |
| 40 } | |
| 41 | |
| 42 /** | |
| 43 * A list of columns that we do not want to display. | |
| 44 * @type {Array<string>} | |
| 45 * @const | |
| 46 */ | |
| 47 var IGNORED_COLUMNS = [ | |
| 48 'direction' | |
| 49 ]; | |
| 50 | |
| 51 /** | |
| 52 * A list specifying the name of the first columns to be displayed. If | |
| 53 * present, they will be displayed in this order, followed by the remaining | |
| 54 * columns. | |
| 55 * @type {Array<string>} | |
| 56 * @const | |
| 57 */ | |
| 58 var PREFERRED_COLUMN_ORDER = [ | |
| 59 'title', | |
| 60 'url', | |
| 61 'score' | |
| 62 ]; | |
| 63 | |
| 64 function setBooleanColumn(column, value) { | |
| 65 if (value) { | |
| 66 column.innerText = 'Y'; | |
| 67 column.classList.add('boolean-property-true'); | |
| 68 } else { | |
| 69 column.innerText = 'N'; | |
| 70 column.classList.add('boolean-property-false'); | |
| 71 } | |
| 72 } | |
| 73 | |
| 74 /** | |
| 75 * Called by Chrome code, with a ranked list of suggestions. The columns | |
| 76 * to be displayed are calculated automatically from the properties of the | |
| 77 * elements in the list, such that all properties have a column. | |
| 78 */ | |
| 79 function setSuggestions(list) { | |
| 80 // Build a list of all the columns that will be displayed. | |
| 81 var columns = []; | |
| 82 list.forEach(function(entry) { | |
| 83 for (var column in entry) { | |
| 84 if (typeof entry[column] == 'object') { | |
| 85 // Expand one level deep | |
| 86 for (var subColumn in entry[column]) { | |
| 87 var path = column + '.' + subColumn; | |
| 88 if (columns.indexOf(path) < 0) | |
| 89 columns.push(path); | |
| 90 } | |
| 91 } else if (columns.indexOf(column) < 0) { | |
| 92 columns.push(column); | |
| 93 } | |
| 94 } | |
| 95 }); | |
| 96 | |
| 97 // Remove columns that we don't want to display. | |
| 98 columns = columns.filter(function(column) { | |
| 99 return IGNORED_COLUMNS.indexOf(column) < 0; | |
| 100 }); | |
| 101 | |
| 102 // Move the preferred columns to the start of the column list. | |
| 103 for (var i = PREFERRED_COLUMN_ORDER.length - 1; i >= 0; i--) { | |
| 104 var index = columns.indexOf(PREFERRED_COLUMN_ORDER[i]); | |
| 105 if (index >= 0) | |
| 106 columns.unshift(columns.splice(index, 1)[0]); | |
| 107 } | |
| 108 | |
| 109 // Special columns. | |
| 110 columns.unshift('favicon'); | |
| 111 columns.unshift('screenshot'); | |
| 112 columns.unshift('rank'); | |
| 113 | |
| 114 // Erase whatever is currently being displayed. | |
| 115 var output = $('suggestions-debug-text'); | |
| 116 output.innerHTML = ''; | |
| 117 | |
| 118 // Create the container table and add the header row. | |
| 119 var table = document.createElement('table'); | |
| 120 table.className = 'suggestions-debug-table'; | |
| 121 var header = document.createElement('tr'); | |
| 122 columns.forEach(function(entry) { | |
| 123 var column = document.createElement('th'); | |
| 124 column.innerText = entry; | |
| 125 header.appendChild(column); | |
| 126 }); | |
| 127 table.appendChild(header); | |
| 128 | |
| 129 // Add all the suggestions to the table. | |
| 130 var rank = 1; | |
| 131 list.forEach(function(entry) { | |
| 132 var row = document.createElement('tr'); | |
| 133 columns.forEach(function(columnName) { | |
| 134 var column = document.createElement('td'); | |
| 135 // Expand the path and find the data if it's there. | |
| 136 var path = columnName.split('.'); | |
| 137 var data = entry; | |
| 138 for (var i = 0; i < path.length; ++i) { | |
| 139 if (data && data.hasOwnProperty(path[i])) | |
| 140 data = data[path[i]]; | |
| 141 else | |
| 142 data = undefined; | |
| 143 } | |
| 144 // Only add the column if the current suggestion has this property | |
| 145 // (otherwise, leave the cell empty). | |
| 146 if (typeof(data) != 'undefined') { | |
| 147 if (typeof(data) == 'boolean') { | |
| 148 setBooleanColumn(column, data); | |
| 149 } else if (/^https?:\/\/.+$/.test(data)) { | |
| 150 // If the text is a URL, make it an anchor element. | |
| 151 var anchor = document.createElement('a'); | |
| 152 anchor.href = data; | |
| 153 anchor.innerText = data; | |
| 154 column.appendChild(anchor); | |
| 155 } else { | |
| 156 column.innerText = data; | |
| 157 } | |
| 158 } else if (columnName == 'rank') { | |
| 159 column.innerText = rank++; | |
| 160 } else if (columnName == 'screenshot') { | |
| 161 var thumbnailUrl = 'chrome://thumb/' + entry.url; | |
| 162 var img = document.createElement('img'); | |
| 163 img.onload = function() { setBooleanColumn(column, true); }; | |
| 164 img.onerror = function() { setBooleanColumn(column, false); }; | |
| 165 img.src = thumbnailUrl; | |
| 166 } else if (columnName == 'favicon') { | |
| 167 var faviconUrl = 'chrome://favicon/size/16@1x/' + entry.url; | |
| 168 column.style.backgroundImage = url(faviconUrl); | |
| 169 column.style.backgroundRepeat = 'no-repeat'; | |
| 170 column.style.backgroundPosition = 'center center'; | |
| 171 } | |
| 172 row.appendChild(column); | |
| 173 }); | |
| 174 table.appendChild(row); | |
| 175 }); | |
| 176 | |
| 177 output.appendChild(table); | |
| 178 } | |
| 179 | |
| 180 return { | |
| 181 initialize: initialize, | |
| 182 setSuggestions: setSuggestions | |
| 183 }; | |
| 184 }); | |
| 185 | |
| 186 document.addEventListener('DOMContentLoaded', suggestionsInternals.initialize); | |
| OLD | NEW |