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.
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.
13 cr.define('suggestionsInternals', function() {
17 * Register our event handlers.
19 function initialize() {
20 $('suggestions-form').addEventListener('submit', onRefreshClicked);
21 $('show-discarded').addEventListener('change', refresh);
26 * Called when the 'Refresh' button is clicked. Reloads the suggestions data.
28 function onRefreshClicked(event) {
30 event.preventDefault();
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.
39 chrome.send('getSuggestions');
43 * A list of columns that we do not want to display.
44 * @type {Array.<string>}
47 var IGNORED_COLUMNS = [
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
55 * @type {Array.<string>}
58 var PREFERRED_COLUMN_ORDER = [
64 function setBooleanColumn(column, value) {
66 column.innerText = 'Y';
67 column.classList.add('boolean-property-true');
69 column.innerText = 'N';
70 column.classList.add('boolean-property-false');
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.
79 function setSuggestions(list) {
80 // Build a list of all the columns that will be displayed.
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)
91 } else if (columns.indexOf(column) < 0) {
97 // Remove columns that we don't want to display.
98 columns = columns.filter(function(column) {
99 return IGNORED_COLUMNS.indexOf(column) < 0;
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]);
106 columns.unshift(columns.splice(index, 1)[0]);
110 columns.unshift('favicon');
111 columns.unshift('screenshot');
112 columns.unshift('rank');
114 // Erase whatever is currently being displayed.
115 var output = $('suggestions-debug-text');
116 output.innerHTML = '';
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);
127 table.appendChild(header);
129 // Add all the suggestions to the table.
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('.');
138 for (var i = 0; i < path.length; ++i) {
139 if (data && data.hasOwnProperty(path[i]))
140 data = data[path[i]];
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');
153 anchor.innerText = data;
154 column.appendChild(anchor);
156 column.innerText = data;
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';
172 row.appendChild(column);
174 table.appendChild(row);
177 output.appendChild(table);
181 initialize: initialize,
182 setSuggestions: setSuggestions
186 document.addEventListener('DOMContentLoaded', suggestionsInternals.initialize);