2 * Copyright (C) 2012 Google 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 are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 * @extends {WebInspector.VBox}
34 * @param {!WebInspector.IndexedDBModel.Database} database
36 WebInspector.IDBDatabaseView = function(database)
38 WebInspector.VBox.call(this);
39 this.registerRequiredCSS("indexedDBViews.css");
41 this.element.classList.add("indexed-db-database-view");
43 this._headersListElement = this.element.createChild("ol", "outline-disclosure");
44 this._headersTreeOutline = new TreeOutline(this._headersListElement);
45 this._headersTreeOutline.expandTreeElementsWhenArrowing = true;
47 this._securityOriginTreeElement = new TreeElement("", null, false);
48 this._securityOriginTreeElement.selectable = false;
49 this._headersTreeOutline.appendChild(this._securityOriginTreeElement);
51 this._nameTreeElement = new TreeElement("", null, false);
52 this._nameTreeElement.selectable = false;
53 this._headersTreeOutline.appendChild(this._nameTreeElement);
55 this._intVersionTreeElement = new TreeElement("", null, false);
56 this._intVersionTreeElement.selectable = false;
57 this._headersTreeOutline.appendChild(this._intVersionTreeElement);
59 this._stringVersionTreeElement = new TreeElement("", null, false);
60 this._stringVersionTreeElement.selectable = false;
61 this._headersTreeOutline.appendChild(this._stringVersionTreeElement);
63 this.update(database);
66 WebInspector.IDBDatabaseView.prototype = {
68 * @param {string} name
69 * @param {string} value
71 _formatHeader: function(name, value)
73 var fragment = document.createDocumentFragment();
74 fragment.createChild("div", "attribute-name").textContent = name + ":";
75 fragment.createChild("div", "attribute-value source-code").textContent = value;
80 _refreshDatabase: function()
82 this._securityOriginTreeElement.title = this._formatHeader(WebInspector.UIString("Security origin"), this._database.databaseId.securityOrigin);
83 this._nameTreeElement.title = this._formatHeader(WebInspector.UIString("Name"), this._database.databaseId.name);
84 this._stringVersionTreeElement.title = this._formatHeader(WebInspector.UIString("String Version"), this._database.version);
85 this._intVersionTreeElement.title = this._formatHeader(WebInspector.UIString("Integer Version"), this._database.intVersion);
89 * @param {!WebInspector.IndexedDBModel.Database} database
91 update: function(database)
93 this._database = database;
94 this._refreshDatabase();
97 __proto__: WebInspector.VBox.prototype
103 * @extends {WebInspector.VBox}
104 * @param {!WebInspector.IndexedDBModel} model
105 * @param {!WebInspector.IndexedDBModel.DatabaseId} databaseId
106 * @param {!WebInspector.IndexedDBModel.ObjectStore} objectStore
107 * @param {?WebInspector.IndexedDBModel.Index} index
109 WebInspector.IDBDataView = function(model, databaseId, objectStore, index)
111 WebInspector.VBox.call(this);
112 this.registerRequiredCSS("indexedDBViews.css");
115 this._databaseId = databaseId;
116 this._isIndex = !!index;
118 this.element.classList.add("indexed-db-data-view");
120 var editorToolbar = this._createEditorToolbar();
121 this.element.appendChild(editorToolbar);
123 this._dataGridContainer = this.element.createChild("div", "fill");
124 this._dataGridContainer.classList.add("data-grid-container");
126 this._refreshButton = new WebInspector.StatusBarButton(WebInspector.UIString("Refresh"), "refresh-storage-status-bar-item");
127 this._refreshButton.addEventListener("click", this._refreshButtonClicked, this);
129 this._clearButton = new WebInspector.StatusBarButton(WebInspector.UIString("Clear object store"), "clear-storage-status-bar-item");
130 this._clearButton.addEventListener("click", this._clearButtonClicked, this);
135 this.update(objectStore, index);
139 WebInspector.IDBDataView.prototype = {
141 * @return {!WebInspector.DataGrid}
143 _createDataGrid: function()
145 var keyPath = this._isIndex ? this._index.keyPath : this._objectStore.keyPath;
148 columns.push({id: "number", title: WebInspector.UIString("#"), width: "50px"});
149 columns.push({id: "key", titleDOMFragment: this._keyColumnHeaderFragment(WebInspector.UIString("Key"), keyPath)});
151 columns.push({id: "primaryKey", titleDOMFragment: this._keyColumnHeaderFragment(WebInspector.UIString("Primary key"), this._objectStore.keyPath)});
152 columns.push({id: "value", title: WebInspector.UIString("Value")});
154 var dataGrid = new WebInspector.DataGrid(columns);
159 * @param {string} prefix
161 * @return {!DocumentFragment}
163 _keyColumnHeaderFragment: function(prefix, keyPath)
165 var keyColumnHeaderFragment = document.createDocumentFragment();
166 keyColumnHeaderFragment.appendChild(document.createTextNode(prefix));
167 if (keyPath === null)
168 return keyColumnHeaderFragment;
170 keyColumnHeaderFragment.appendChild(document.createTextNode(" (" + WebInspector.UIString("Key path: ")));
171 if (keyPath instanceof Array) {
172 keyColumnHeaderFragment.appendChild(document.createTextNode("["));
173 for (var i = 0; i < keyPath.length; ++i) {
175 keyColumnHeaderFragment.appendChild(document.createTextNode(", "));
176 keyColumnHeaderFragment.appendChild(this._keyPathStringFragment(keyPath[i]));
178 keyColumnHeaderFragment.appendChild(document.createTextNode("]"));
180 var keyPathString = /** @type {string} */ (keyPath);
181 keyColumnHeaderFragment.appendChild(this._keyPathStringFragment(keyPathString));
183 keyColumnHeaderFragment.appendChild(document.createTextNode(")"));
184 return keyColumnHeaderFragment;
188 * @param {string} keyPathString
189 * @return {!DocumentFragment}
191 _keyPathStringFragment: function(keyPathString)
193 var keyPathStringFragment = document.createDocumentFragment();
194 keyPathStringFragment.appendChild(document.createTextNode("\""));
195 var keyPathSpan = keyPathStringFragment.createChild("span", "source-code console-formatted-string");
196 keyPathSpan.textContent = keyPathString;
197 keyPathStringFragment.appendChild(document.createTextNode("\""));
198 return keyPathStringFragment;
204 _createEditorToolbar: function()
206 var editorToolbar = document.createElement("div");
207 editorToolbar.classList.add("status-bar");
208 editorToolbar.classList.add("data-view-toolbar");
210 this._pageBackButton = editorToolbar.createChild("button", "back-button");
211 this._pageBackButton.classList.add("status-bar-item");
212 this._pageBackButton.title = WebInspector.UIString("Show previous page.");
213 this._pageBackButton.disabled = true;
214 this._pageBackButton.appendChild(document.createElement("img"));
215 this._pageBackButton.addEventListener("click", this._pageBackButtonClicked.bind(this), false);
216 editorToolbar.appendChild(this._pageBackButton);
218 this._pageForwardButton = editorToolbar.createChild("button", "forward-button");
219 this._pageForwardButton.classList.add("status-bar-item");
220 this._pageForwardButton.title = WebInspector.UIString("Show next page.");
221 this._pageForwardButton.disabled = true;
222 this._pageForwardButton.appendChild(document.createElement("img"));
223 this._pageForwardButton.addEventListener("click", this._pageForwardButtonClicked.bind(this), false);
224 editorToolbar.appendChild(this._pageForwardButton);
226 this._keyInputElement = editorToolbar.createChild("input", "key-input");
227 this._keyInputElement.placeholder = WebInspector.UIString("Start from key");
228 this._keyInputElement.addEventListener("paste", this._keyInputChanged.bind(this));
229 this._keyInputElement.addEventListener("cut", this._keyInputChanged.bind(this));
230 this._keyInputElement.addEventListener("keypress", this._keyInputChanged.bind(this));
231 this._keyInputElement.addEventListener("keydown", this._keyInputChanged.bind(this));
233 return editorToolbar;
236 _pageBackButtonClicked: function()
238 this._skipCount = Math.max(0, this._skipCount - this._pageSize);
239 this._updateData(false);
242 _pageForwardButtonClicked: function()
244 this._skipCount = this._skipCount + this._pageSize;
245 this._updateData(false);
248 _keyInputChanged: function()
250 window.setTimeout(this._updateData.bind(this, false), 0);
254 * @param {!WebInspector.IndexedDBModel.ObjectStore} objectStore
255 * @param {?WebInspector.IndexedDBModel.Index} index
257 update: function(objectStore, index)
259 this._objectStore = objectStore;
263 this._dataGrid.detach();
264 this._dataGrid = this._createDataGrid();
265 this._dataGrid.show(this._dataGridContainer);
268 this._updateData(true);
272 * @param {string} keyString
274 _parseKey: function(keyString)
278 result = JSON.parse(keyString);
286 * @param {boolean} force
288 _updateData: function(force)
290 var key = this._parseKey(this._keyInputElement.value);
291 var pageSize = this._pageSize;
292 var skipCount = this._skipCount;
293 this._refreshButton.setEnabled(false);
294 this._clearButton.setEnabled(!this._isIndex);
296 if (!force && this._lastKey === key && this._lastPageSize === pageSize && this._lastSkipCount === skipCount)
299 if (this._lastKey !== key || this._lastPageSize !== pageSize) {
304 this._lastPageSize = pageSize;
305 this._lastSkipCount = skipCount;
308 * @param {!Array.<!WebInspector.IndexedDBModel.Entry>} entries
309 * @param {boolean} hasMore
310 * @this {WebInspector.IDBDataView}
312 function callback(entries, hasMore)
314 this._refreshButton.setEnabled(true);
316 this._entries = entries;
317 for (var i = 0; i < entries.length; ++i) {
319 data["number"] = i + skipCount;
320 data["key"] = entries[i].key;
321 data["primaryKey"] = entries[i].primaryKey;
322 data["value"] = entries[i].value;
324 var primaryKey = JSON.stringify(this._isIndex ? entries[i].primaryKey : entries[i].key);
325 var node = new WebInspector.IDBDataGridNode(data);
326 this._dataGrid.rootNode().appendChild(node);
329 this._pageBackButton.disabled = skipCount === 0;
330 this._pageForwardButton.disabled = !hasMore;
333 var idbKeyRange = key ? window.webkitIDBKeyRange.lowerBound(key) : null;
335 this._model.loadIndexData(this._databaseId, this._objectStore.name, this._index.name, idbKeyRange, skipCount, pageSize, callback.bind(this));
337 this._model.loadObjectStoreData(this._databaseId, this._objectStore.name, idbKeyRange, skipCount, pageSize, callback.bind(this));
340 _refreshButtonClicked: function(event)
342 this._updateData(true);
345 _clearButtonClicked: function(event)
348 * @this {WebInspector.IDBDataView}
351 this._clearButton.setEnabled(true);
352 this._updateData(true);
354 this._clearButton.setEnabled(false);
355 this._model.clearObjectStore(this._databaseId, this._objectStore.name, cleared.bind(this));
360 return [this._refreshButton.element, this._clearButton.element];
365 this._dataGrid.rootNode().removeChildren();
366 for (var i = 0; i < this._entries.length; ++i) {
367 this._entries[i].key.release();
368 this._entries[i].primaryKey.release();
369 this._entries[i].value.release();
374 __proto__: WebInspector.VBox.prototype
379 * @extends {WebInspector.DataGridNode}
380 * @param {!Object.<string, *>} data
382 WebInspector.IDBDataGridNode = function(data)
384 WebInspector.DataGridNode.call(this, data, false);
385 this.selectable = false;
388 WebInspector.IDBDataGridNode.prototype = {
392 createCell: function(columnIdentifier)
394 var cell = WebInspector.DataGridNode.prototype.createCell.call(this, columnIdentifier);
395 var value = this.data[columnIdentifier];
397 switch (columnIdentifier) {
401 cell.removeChildren();
402 this._formatValue(cell, value);
410 _formatValue: function(cell, value)
412 var type = value.subtype || value.type;
413 var contents = cell.createChild("div", "source-code console-formatted-" + type);
418 var section = new WebInspector.ObjectPropertiesSection(value, value.description)
419 section.editable = false;
420 section.skipProto = true;
421 contents.appendChild(section.element);
424 contents.classList.add("primitive-value");
425 contents.appendChild(document.createTextNode("\"" + value.description + "\""));
428 contents.classList.add("primitive-value");
429 contents.appendChild(document.createTextNode(value.description));
433 __proto__: WebInspector.DataGridNode.prototype