2 * Copyright (C) 2010 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
26 WebInspector.ApplicationCacheItemsView = function(treeElement, appcacheDomain)
28 WebInspector.View.call(this);
30 this.element.addStyleClass("storage-view");
31 this.element.addStyleClass("table");
33 // FIXME: Delete Button semantics are not yet defined.
34 // FIXME: Needs better tooltip. (Localized)
35 this.deleteButton = new WebInspector.StatusBarButton(WebInspector.UIString("Delete"), "delete-storage-status-bar-item");
36 this.deleteButton.visible = false;
37 this.deleteButton.addEventListener("click", this._deleteButtonClicked.bind(this), false);
39 // FIXME: Refresh Button semantics are not yet defined.
40 // FIXME: Needs better tooltip. (Localized)
41 this.refreshButton = new WebInspector.StatusBarButton(WebInspector.UIString("Refresh"), "refresh-storage-status-bar-item");
42 this.refreshButton.addEventListener("click", this._refreshButtonClicked.bind(this), false);
44 if (Preferences.onlineDetectionEnabled) {
45 this.connectivityIcon = document.createElement("img");
46 this.connectivityIcon.className = "storage-application-cache-connectivity-icon";
47 this.connectivityIcon.src = "";
48 this.connectivityMessage = document.createElement("span");
49 this.connectivityMessage.className = "storage-application-cache-connectivity";
50 this.connectivityMessage.textContent = "";
53 this.divider = document.createElement("span");
54 this.divider.className = "status-bar-item status-bar-divider";
56 this.statusIcon = document.createElement("img");
57 this.statusIcon.className = "storage-application-cache-status-icon";
58 this.statusIcon.src = "";
59 this.statusMessage = document.createElement("span");
60 this.statusMessage.className = "storage-application-cache-status";
61 this.statusMessage.textContent = "";
63 this._treeElement = treeElement;
64 this._appcacheDomain = appcacheDomain;
66 this._emptyMsgElement = document.createElement("div");
67 this._emptyMsgElement.className = "storage-empty-view";
68 this._emptyMsgElement.textContent = WebInspector.UIString("No Application Cache information available.");
69 this.element.appendChild(this._emptyMsgElement);
71 this.updateStatus(applicationCache.UNCACHED);
74 WebInspector.ApplicationCacheItemsView.prototype = {
77 if (Preferences.onlineDetectionEnabled) {
79 this.refreshButton.element, this.deleteButton.element,
80 this.connectivityIcon, this.connectivityMessage, this.divider,
81 this.statusIcon, this.statusMessage
85 this.refreshButton.element, this.deleteButton.element, this.divider,
86 this.statusIcon, this.statusMessage
91 show: function(parentElement)
93 WebInspector.View.prototype.show.call(this, parentElement);
94 this.updateNetworkState(navigator.onLine);
100 WebInspector.View.prototype.hide.call(this);
101 this.deleteButton.visible = false;
104 updateStatus: function(status)
106 var statusInformation = {};
107 statusInformation[applicationCache.UNCACHED] = { src: "Images/warningOrangeDot.png", text: "UNCACHED" };
108 statusInformation[applicationCache.IDLE] = { src: "Images/warningOrangeDot.png", text: "IDLE" };
109 statusInformation[applicationCache.CHECKING] = { src: "Images/successGreenDot.png", text: "CHECKING" };
110 statusInformation[applicationCache.DOWNLOADING] = { src: "Images/successGreenDot.png", text: "DOWNLOADING" };
111 statusInformation[applicationCache.UPDATEREADY] = { src: "Images/successGreenDot.png", text: "UPDATEREADY" };
112 statusInformation[applicationCache.OBSOLETE] = { src: "Images/errorRedDot.png", text: "OBSOLETE" };
114 var info = statusInformation[status];
116 console.error("Unknown Application Cache Status was Not Handled: %d", status);
120 this.statusIcon.src = info.src;
121 this.statusMessage.textContent = info.text;
124 updateNetworkState: function(isNowOnline)
126 if (Preferences.onlineDetectionEnabled) {
128 this.connectivityIcon.src = "Images/successGreenDot.png";
129 this.connectivityMessage.textContent = WebInspector.UIString("Online");
131 this.connectivityIcon.src = "Images/errorRedDot.png";
132 this.connectivityMessage.textContent = WebInspector.UIString("Offline");
139 WebInspector.ApplicationCache.getApplicationCachesAsync(this._updateCallback.bind(this));
142 _updateCallback: function(applicationCaches)
144 // FIXME: applicationCaches is just one cache.
145 // FIXME: are these variables needed anywhere else?
146 this._manifest = applicationCaches.manifest;
147 this._creationTime = applicationCaches.creationTime;
148 this._updateTime = applicationCaches.updateTime;
149 this._size = applicationCaches.size;
150 this._resources = applicationCaches.resources;
151 var lastPathComponent = applicationCaches.lastPathComponent;
153 if (!this._manifest) {
154 this._emptyMsgElement.removeStyleClass("hidden");
155 this.deleteButton.visible = false;
157 this._dataGrid.element.addStyleClass("hidden");
162 this._createDataGrid();
164 this._populateDataGrid();
165 this._dataGrid.autoSizeColumns(20, 80);
166 this._dataGrid.element.removeStyleClass("hidden");
167 this._emptyMsgElement.addStyleClass("hidden");
168 this.deleteButton.visible = true;
170 var totalSizeString = Number.bytesToString(this._size);
171 this._treeElement.subtitle = WebInspector.UIString("%s (%s)", lastPathComponent, totalSizeString);
173 // FIXME: For Chrome, put creationTime and updateTime somewhere.
174 // NOTE: localizedString has not yet been added.
175 // WebInspector.UIString("(%s) Created: %s Updated: %s", this._size, this._creationTime, this._updateTime);
178 _createDataGrid: function()
180 var columns = { 0: {}, 1: {}, 2: {} };
181 columns[0].title = WebInspector.UIString("Resource");
182 columns[0].sort = "ascending";
183 columns[0].sortable = true;
184 columns[1].title = WebInspector.UIString("Type");
185 columns[1].sortable = true;
186 columns[2].title = WebInspector.UIString("Size");
187 columns[2].aligned = "right";
188 columns[2].sortable = true;
189 this._dataGrid = new WebInspector.DataGrid(columns);
190 this.element.appendChild(this._dataGrid.element);
191 this._dataGrid.addEventListener("sorting changed", this._populateDataGrid, this);
192 this._dataGrid.updateWidths();
195 _populateDataGrid: function()
197 var selectedResource = this._dataGrid.selectedNode ? this._dataGrid.selectedNode.resource : null;
198 var sortDirection = this._dataGrid.sortOrder === "ascending" ? 1 : -1;
200 function numberCompare(field, resource1, resource2)
202 return sortDirection * (resource1[field] - resource2[field]);
204 function localeCompare(field, resource1, resource2)
206 return sortDirection * (resource1[field] + "").localeCompare(resource2[field] + "")
210 switch (parseInt(this._dataGrid.sortColumnIdentifier)) {
211 case 0: comparator = localeCompare.bind(this, "name"); break;
212 case 1: comparator = localeCompare.bind(this, "type"); break;
213 case 2: comparator = numberCompare.bind(this, "size"); break;
214 default: localeCompare.bind(this, "resource"); // FIXME: comparator = ?
217 this._resources.sort(comparator);
218 this._dataGrid.removeChildren();
221 for (var i = 0; i < this._resources.length; ++i) {
223 var resource = this._resources[i];
224 data[0] = resource.name;
225 data[1] = resource.type;
226 data[2] = Number.bytesToString(resource.size);
227 var node = new WebInspector.DataGridNode(data);
228 node.resource = resource;
229 node.selectable = true;
230 this._dataGrid.appendChild(node);
231 if (resource === selectedResource) {
233 nodeToSelect.selected = true;
238 this._dataGrid.children[0].selected = true;
244 this._dataGrid.updateWidths();
247 _deleteButtonClicked: function(event)
249 if (!this._dataGrid || !this._dataGrid.selectedNode)
252 // FIXME: Delete Button semantics are not yet defined. (Delete a single, or all?)
253 this._deleteCallback(this._dataGrid.selectedNode);
256 _deleteCallback: function(node)
258 // FIXME: Should we delete a single (selected) resource or all resources?
259 // InspectorBackend.deleteCachedResource(...)
263 _refreshButtonClicked: function(event)
265 // FIXME: Is this a refresh button or a re-fetch manifest button?
270 WebInspector.ApplicationCacheItemsView.prototype.__proto__ = WebInspector.View.prototype;