OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2012 Google Inc. All rights reserved. | 2 * Copyright (C) 2012 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
11 * copyright notice, this list of conditions and the following disclaimer | 11 * copyright notice, this list of conditions and the following disclaimer |
12 * in the documentation and/or other materials provided with the | 12 * in the documentation and/or other materials provided with the |
13 * distribution. | 13 * distribution. |
14 * * Neither the name of Google Inc. nor the names of its | 14 * * Neither the name of Google Inc. nor the names of its |
15 * contributors may be used to endorse or promote products derived from | 15 * contributors may be used to endorse or promote products derived from |
16 * this software without specific prior written permission. | 16 * this software without specific prior written permission. |
17 * | 17 * |
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
29 */ | 29 */ |
30 | |
31 /** | 30 /** |
32 * @constructor | 31 * @unrestricted |
33 * @extends {WebInspector.VBox} | |
34 * @param {!WebInspector.IndexedDBModel.Database} database | |
35 */ | 32 */ |
36 WebInspector.IDBDatabaseView = function(database) | 33 WebInspector.IDBDatabaseView = class extends WebInspector.VBox { |
37 { | 34 /** |
38 WebInspector.VBox.call(this); | 35 * @param {!WebInspector.IndexedDBModel.Database} database |
39 this.registerRequiredCSS("resources/indexedDBViews.css"); | 36 */ |
40 | 37 constructor(database) { |
41 this.element.classList.add("indexed-db-database-view"); | 38 super(); |
42 this.element.classList.add("storage-view"); | 39 this.registerRequiredCSS('resources/indexedDBViews.css'); |
43 | 40 |
44 this._securityOriginElement = this.element.createChild("div", "header-row"); | 41 this.element.classList.add('indexed-db-database-view'); |
45 this._nameElement = this.element.createChild("div", "header-row"); | 42 this.element.classList.add('storage-view'); |
46 this._versionElement = this.element.createChild("div", "header-row"); | 43 |
| 44 this._securityOriginElement = this.element.createChild('div', 'header-row'); |
| 45 this._nameElement = this.element.createChild('div', 'header-row'); |
| 46 this._versionElement = this.element.createChild('div', 'header-row'); |
47 | 47 |
48 this.update(database); | 48 this.update(database); |
| 49 } |
| 50 |
| 51 /** |
| 52 * @param {!Element} element |
| 53 * @param {string} name |
| 54 * @param {string} value |
| 55 */ |
| 56 _formatHeader(element, name, value) { |
| 57 element.removeChildren(); |
| 58 element.createChild('div', 'attribute-name').textContent = name + ':'; |
| 59 element.createChild('div', 'attribute-value source-code').textContent = valu
e; |
| 60 } |
| 61 |
| 62 _refreshDatabase() { |
| 63 this._formatHeader( |
| 64 this._securityOriginElement, WebInspector.UIString('Security origin'), |
| 65 this._database.databaseId.securityOrigin); |
| 66 this._formatHeader(this._nameElement, WebInspector.UIString('Name'), this._d
atabase.databaseId.name); |
| 67 this._formatHeader(this._versionElement, WebInspector.UIString('Version'), t
his._database.version); |
| 68 } |
| 69 |
| 70 /** |
| 71 * @param {!WebInspector.IndexedDBModel.Database} database |
| 72 */ |
| 73 update(database) { |
| 74 this._database = database; |
| 75 this._refreshDatabase(); |
| 76 } |
49 }; | 77 }; |
50 | 78 |
51 WebInspector.IDBDatabaseView.prototype = { | |
52 /** | |
53 * @param {!Element} element | |
54 * @param {string} name | |
55 * @param {string} value | |
56 */ | |
57 _formatHeader: function(element, name, value) | |
58 { | |
59 element.removeChildren(); | |
60 element.createChild("div", "attribute-name").textContent = name + ":"; | |
61 element.createChild("div", "attribute-value source-code").textContent =
value; | |
62 }, | |
63 | |
64 _refreshDatabase: function() | |
65 { | |
66 this._formatHeader(this._securityOriginElement, WebInspector.UIString("S
ecurity origin"), this._database.databaseId.securityOrigin); | |
67 this._formatHeader(this._nameElement, WebInspector.UIString("Name"), thi
s._database.databaseId.name); | |
68 this._formatHeader(this._versionElement, WebInspector.UIString("Version"
), this._database.version); | |
69 }, | |
70 | |
71 /** | |
72 * @param {!WebInspector.IndexedDBModel.Database} database | |
73 */ | |
74 update: function(database) | |
75 { | |
76 this._database = database; | |
77 this._refreshDatabase(); | |
78 }, | |
79 | |
80 __proto__: WebInspector.VBox.prototype | |
81 }; | |
82 | |
83 | |
84 /** | 79 /** |
85 * @constructor | 80 * @unrestricted |
86 * @extends {WebInspector.SimpleView} | |
87 * @param {!WebInspector.IndexedDBModel} model | |
88 * @param {!WebInspector.IndexedDBModel.DatabaseId} databaseId | |
89 * @param {!WebInspector.IndexedDBModel.ObjectStore} objectStore | |
90 * @param {?WebInspector.IndexedDBModel.Index} index | |
91 */ | 81 */ |
92 WebInspector.IDBDataView = function(model, databaseId, objectStore, index) | 82 WebInspector.IDBDataView = class extends WebInspector.SimpleView { |
93 { | 83 /** |
94 WebInspector.SimpleView.call(this, WebInspector.UIString("IDB")); | 84 * @param {!WebInspector.IndexedDBModel} model |
95 this.registerRequiredCSS("resources/indexedDBViews.css"); | 85 * @param {!WebInspector.IndexedDBModel.DatabaseId} databaseId |
| 86 * @param {!WebInspector.IndexedDBModel.ObjectStore} objectStore |
| 87 * @param {?WebInspector.IndexedDBModel.Index} index |
| 88 */ |
| 89 constructor(model, databaseId, objectStore, index) { |
| 90 super(WebInspector.UIString('IDB')); |
| 91 this.registerRequiredCSS('resources/indexedDBViews.css'); |
96 | 92 |
97 this._model = model; | 93 this._model = model; |
98 this._databaseId = databaseId; | 94 this._databaseId = databaseId; |
99 this._isIndex = !!index; | 95 this._isIndex = !!index; |
100 | 96 |
101 this.element.classList.add("indexed-db-data-view"); | 97 this.element.classList.add('indexed-db-data-view'); |
102 | 98 |
103 this._createEditorToolbar(); | 99 this._createEditorToolbar(); |
104 | 100 |
105 this._refreshButton = new WebInspector.ToolbarButton(WebInspector.UIString("
Refresh"), "refresh-toolbar-item"); | 101 this._refreshButton = new WebInspector.ToolbarButton(WebInspector.UIString('
Refresh'), 'refresh-toolbar-item'); |
106 this._refreshButton.addEventListener("click", this._refreshButtonClicked, th
is); | 102 this._refreshButton.addEventListener('click', this._refreshButtonClicked, th
is); |
107 | 103 |
108 this._clearButton = new WebInspector.ToolbarButton(WebInspector.UIString("Cl
ear object store"), "clear-toolbar-item"); | 104 this._clearButton = |
109 this._clearButton.addEventListener("click", this._clearButtonClicked, this); | 105 new WebInspector.ToolbarButton(WebInspector.UIString('Clear object store
'), 'clear-toolbar-item'); |
| 106 this._clearButton.addEventListener('click', this._clearButtonClicked, this); |
110 | 107 |
111 this._pageSize = 50; | 108 this._pageSize = 50; |
112 this._skipCount = 0; | 109 this._skipCount = 0; |
113 | 110 |
114 this.update(objectStore, index); | 111 this.update(objectStore, index); |
115 this._entries = []; | 112 this._entries = []; |
| 113 } |
| 114 |
| 115 /** |
| 116 * @return {!WebInspector.DataGrid} |
| 117 */ |
| 118 _createDataGrid() { |
| 119 var keyPath = this._isIndex ? this._index.keyPath : this._objectStore.keyPat
h; |
| 120 |
| 121 var columns = /** @type {!Array<!WebInspector.DataGrid.ColumnDescriptor>} */
([]); |
| 122 columns.push({id: 'number', title: WebInspector.UIString('#'), sortable: fal
se, width: '50px'}); |
| 123 columns.push({ |
| 124 id: 'key', |
| 125 titleDOMFragment: this._keyColumnHeaderFragment(WebInspector.UIString('Key
'), keyPath), |
| 126 sortable: false |
| 127 }); |
| 128 if (this._isIndex) |
| 129 columns.push({ |
| 130 id: 'primaryKey', |
| 131 titleDOMFragment: |
| 132 this._keyColumnHeaderFragment(WebInspector.UIString('Primary key'),
this._objectStore.keyPath), |
| 133 sortable: false |
| 134 }); |
| 135 columns.push({id: 'value', title: WebInspector.UIString('Value'), sortable:
false}); |
| 136 |
| 137 var dataGrid = new WebInspector.DataGrid(columns); |
| 138 return dataGrid; |
| 139 } |
| 140 |
| 141 /** |
| 142 * @param {string} prefix |
| 143 * @param {*} keyPath |
| 144 * @return {!DocumentFragment} |
| 145 */ |
| 146 _keyColumnHeaderFragment(prefix, keyPath) { |
| 147 var keyColumnHeaderFragment = createDocumentFragment(); |
| 148 keyColumnHeaderFragment.createTextChild(prefix); |
| 149 if (keyPath === null) |
| 150 return keyColumnHeaderFragment; |
| 151 |
| 152 keyColumnHeaderFragment.createTextChild(' (' + WebInspector.UIString('Key pa
th: ')); |
| 153 if (Array.isArray(keyPath)) { |
| 154 keyColumnHeaderFragment.createTextChild('['); |
| 155 for (var i = 0; i < keyPath.length; ++i) { |
| 156 if (i !== 0) |
| 157 keyColumnHeaderFragment.createTextChild(', '); |
| 158 keyColumnHeaderFragment.appendChild(this._keyPathStringFragment(keyPath[
i])); |
| 159 } |
| 160 keyColumnHeaderFragment.createTextChild(']'); |
| 161 } else { |
| 162 var keyPathString = /** @type {string} */ (keyPath); |
| 163 keyColumnHeaderFragment.appendChild(this._keyPathStringFragment(keyPathStr
ing)); |
| 164 } |
| 165 keyColumnHeaderFragment.createTextChild(')'); |
| 166 return keyColumnHeaderFragment; |
| 167 } |
| 168 |
| 169 /** |
| 170 * @param {string} keyPathString |
| 171 * @return {!DocumentFragment} |
| 172 */ |
| 173 _keyPathStringFragment(keyPathString) { |
| 174 var keyPathStringFragment = createDocumentFragment(); |
| 175 keyPathStringFragment.createTextChild('"'); |
| 176 var keyPathSpan = keyPathStringFragment.createChild('span', 'source-code ind
exed-db-key-path'); |
| 177 keyPathSpan.textContent = keyPathString; |
| 178 keyPathStringFragment.createTextChild('"'); |
| 179 return keyPathStringFragment; |
| 180 } |
| 181 |
| 182 _createEditorToolbar() { |
| 183 var editorToolbar = new WebInspector.Toolbar('data-view-toolbar', this.eleme
nt); |
| 184 |
| 185 this._pageBackButton = |
| 186 new WebInspector.ToolbarButton(WebInspector.UIString('Show previous page
'), 'play-backwards-toolbar-item'); |
| 187 this._pageBackButton.addEventListener('click', this._pageBackButtonClicked,
this); |
| 188 editorToolbar.appendToolbarItem(this._pageBackButton); |
| 189 |
| 190 this._pageForwardButton = |
| 191 new WebInspector.ToolbarButton(WebInspector.UIString('Show next page'),
'play-toolbar-item'); |
| 192 this._pageForwardButton.setEnabled(false); |
| 193 this._pageForwardButton.addEventListener('click', this._pageForwardButtonCli
cked, this); |
| 194 editorToolbar.appendToolbarItem(this._pageForwardButton); |
| 195 |
| 196 this._keyInputElement = editorToolbar.element.createChild('input', 'key-inpu
t'); |
| 197 this._keyInputElement.placeholder = WebInspector.UIString('Start from key'); |
| 198 this._keyInputElement.addEventListener('paste', this._keyInputChanged.bind(t
his), false); |
| 199 this._keyInputElement.addEventListener('cut', this._keyInputChanged.bind(thi
s), false); |
| 200 this._keyInputElement.addEventListener('keypress', this._keyInputChanged.bin
d(this), false); |
| 201 this._keyInputElement.addEventListener('keydown', this._keyInputChanged.bind
(this), false); |
| 202 } |
| 203 |
| 204 _pageBackButtonClicked() { |
| 205 this._skipCount = Math.max(0, this._skipCount - this._pageSize); |
| 206 this._updateData(false); |
| 207 } |
| 208 |
| 209 _pageForwardButtonClicked() { |
| 210 this._skipCount = this._skipCount + this._pageSize; |
| 211 this._updateData(false); |
| 212 } |
| 213 |
| 214 _keyInputChanged() { |
| 215 window.setTimeout(this._updateData.bind(this, false), 0); |
| 216 } |
| 217 |
| 218 /** |
| 219 * @param {!WebInspector.IndexedDBModel.ObjectStore} objectStore |
| 220 * @param {?WebInspector.IndexedDBModel.Index} index |
| 221 */ |
| 222 update(objectStore, index) { |
| 223 this._objectStore = objectStore; |
| 224 this._index = index; |
| 225 |
| 226 if (this._dataGrid) |
| 227 this._dataGrid.asWidget().detach(); |
| 228 this._dataGrid = this._createDataGrid(); |
| 229 this._dataGrid.asWidget().show(this.element); |
| 230 |
| 231 this._skipCount = 0; |
| 232 this._updateData(true); |
| 233 } |
| 234 |
| 235 /** |
| 236 * @param {string} keyString |
| 237 */ |
| 238 _parseKey(keyString) { |
| 239 var result; |
| 240 try { |
| 241 result = JSON.parse(keyString); |
| 242 } catch (e) { |
| 243 result = keyString; |
| 244 } |
| 245 return result; |
| 246 } |
| 247 |
| 248 /** |
| 249 * @param {boolean} force |
| 250 */ |
| 251 _updateData(force) { |
| 252 var key = this._parseKey(this._keyInputElement.value); |
| 253 var pageSize = this._pageSize; |
| 254 var skipCount = this._skipCount; |
| 255 this._refreshButton.setEnabled(false); |
| 256 this._clearButton.setEnabled(!this._isIndex); |
| 257 |
| 258 if (!force && this._lastKey === key && this._lastPageSize === pageSize && th
is._lastSkipCount === skipCount) |
| 259 return; |
| 260 |
| 261 if (this._lastKey !== key || this._lastPageSize !== pageSize) { |
| 262 skipCount = 0; |
| 263 this._skipCount = 0; |
| 264 } |
| 265 this._lastKey = key; |
| 266 this._lastPageSize = pageSize; |
| 267 this._lastSkipCount = skipCount; |
| 268 |
| 269 /** |
| 270 * @param {!Array.<!WebInspector.IndexedDBModel.Entry>} entries |
| 271 * @param {boolean} hasMore |
| 272 * @this {WebInspector.IDBDataView} |
| 273 */ |
| 274 function callback(entries, hasMore) { |
| 275 this._refreshButton.setEnabled(true); |
| 276 this.clear(); |
| 277 this._entries = entries; |
| 278 for (var i = 0; i < entries.length; ++i) { |
| 279 var data = {}; |
| 280 data['number'] = i + skipCount; |
| 281 data['key'] = entries[i].key; |
| 282 data['primaryKey'] = entries[i].primaryKey; |
| 283 data['value'] = entries[i].value; |
| 284 |
| 285 var node = new WebInspector.IDBDataGridNode(data); |
| 286 this._dataGrid.rootNode().appendChild(node); |
| 287 } |
| 288 |
| 289 this._pageBackButton.setEnabled(!!skipCount); |
| 290 this._pageForwardButton.setEnabled(hasMore); |
| 291 } |
| 292 |
| 293 var idbKeyRange = key ? window.IDBKeyRange.lowerBound(key) : null; |
| 294 if (this._isIndex) |
| 295 this._model.loadIndexData( |
| 296 this._databaseId, this._objectStore.name, this._index.name, idbKeyRang
e, skipCount, pageSize, |
| 297 callback.bind(this)); |
| 298 else |
| 299 this._model.loadObjectStoreData( |
| 300 this._databaseId, this._objectStore.name, idbKeyRange, skipCount, page
Size, callback.bind(this)); |
| 301 } |
| 302 |
| 303 _refreshButtonClicked(event) { |
| 304 this._updateData(true); |
| 305 } |
| 306 |
| 307 _clearButtonClicked(event) { |
| 308 /** |
| 309 * @this {WebInspector.IDBDataView} |
| 310 */ |
| 311 function cleared() { |
| 312 this._clearButton.setEnabled(true); |
| 313 this._updateData(true); |
| 314 } |
| 315 this._clearButton.setEnabled(false); |
| 316 this._model.clearObjectStore(this._databaseId, this._objectStore.name, clear
ed.bind(this)); |
| 317 } |
| 318 |
| 319 /** |
| 320 * @override |
| 321 * @return {!Array.<!WebInspector.ToolbarItem>} |
| 322 */ |
| 323 syncToolbarItems() { |
| 324 return [this._refreshButton, this._clearButton]; |
| 325 } |
| 326 |
| 327 clear() { |
| 328 this._dataGrid.rootNode().removeChildren(); |
| 329 this._entries = []; |
| 330 } |
116 }; | 331 }; |
117 | 332 |
118 WebInspector.IDBDataView.prototype = { | 333 /** |
119 /** | 334 * @unrestricted |
120 * @return {!WebInspector.DataGrid} | 335 */ |
121 */ | 336 WebInspector.IDBDataGridNode = class extends WebInspector.DataGridNode { |
122 _createDataGrid: function() | 337 /** |
123 { | 338 * @param {!Object.<string, *>} data |
124 var keyPath = this._isIndex ? this._index.keyPath : this._objectStore.ke
yPath; | 339 */ |
125 | 340 constructor(data) { |
126 var columns = /** @type {!Array<!WebInspector.DataGrid.ColumnDescriptor>
} */ ([]); | 341 super(data, false); |
127 columns.push({id: "number", title: WebInspector.UIString("#"), sortable:
false, width: "50px"}); | 342 this.selectable = false; |
128 columns.push({id: "key", titleDOMFragment: this._keyColumnHeaderFragment
(WebInspector.UIString("Key"), keyPath), sortable: false}); | 343 } |
129 if (this._isIndex) | 344 |
130 columns.push({id: "primaryKey", titleDOMFragment: this._keyColumnHea
derFragment(WebInspector.UIString("Primary key"), this._objectStore.keyPath), so
rtable: false}); | 345 /** |
131 columns.push({id: "value", title: WebInspector.UIString("Value"), sortab
le: false}); | 346 * @override |
132 | 347 * @return {!Element} |
133 var dataGrid = new WebInspector.DataGrid(columns); | 348 */ |
134 return dataGrid; | 349 createCell(columnIdentifier) { |
135 }, | 350 var cell = super.createCell(columnIdentifier); |
136 | 351 var value = /** @type {!WebInspector.RemoteObject} */ (this.data[columnIdent
ifier]); |
137 /** | 352 |
138 * @param {string} prefix | 353 switch (columnIdentifier) { |
139 * @param {*} keyPath | 354 case 'value': |
140 * @return {!DocumentFragment} | 355 case 'key': |
141 */ | 356 case 'primaryKey': |
142 _keyColumnHeaderFragment: function(prefix, keyPath) | 357 cell.removeChildren(); |
143 { | 358 var objectElement = WebInspector.ObjectPropertiesSection.defaultObjectPr
esentation(value, undefined, true); |
144 var keyColumnHeaderFragment = createDocumentFragment(); | 359 cell.appendChild(objectElement); |
145 keyColumnHeaderFragment.createTextChild(prefix); | 360 break; |
146 if (keyPath === null) | 361 default: |
147 return keyColumnHeaderFragment; | 362 } |
148 | 363 |
149 keyColumnHeaderFragment.createTextChild(" (" + WebInspector.UIString("Ke
y path: ")); | 364 return cell; |
150 if (Array.isArray(keyPath)) { | 365 } |
151 keyColumnHeaderFragment.createTextChild("["); | |
152 for (var i = 0; i < keyPath.length; ++i) { | |
153 if (i !== 0) | |
154 keyColumnHeaderFragment.createTextChild(", "); | |
155 keyColumnHeaderFragment.appendChild(this._keyPathStringFragment(
keyPath[i])); | |
156 } | |
157 keyColumnHeaderFragment.createTextChild("]"); | |
158 } else { | |
159 var keyPathString = /** @type {string} */ (keyPath); | |
160 keyColumnHeaderFragment.appendChild(this._keyPathStringFragment(keyP
athString)); | |
161 } | |
162 keyColumnHeaderFragment.createTextChild(")"); | |
163 return keyColumnHeaderFragment; | |
164 }, | |
165 | |
166 /** | |
167 * @param {string} keyPathString | |
168 * @return {!DocumentFragment} | |
169 */ | |
170 _keyPathStringFragment: function(keyPathString) | |
171 { | |
172 var keyPathStringFragment = createDocumentFragment(); | |
173 keyPathStringFragment.createTextChild("\""); | |
174 var keyPathSpan = keyPathStringFragment.createChild("span", "source-code
indexed-db-key-path"); | |
175 keyPathSpan.textContent = keyPathString; | |
176 keyPathStringFragment.createTextChild("\""); | |
177 return keyPathStringFragment; | |
178 }, | |
179 | |
180 _createEditorToolbar: function() | |
181 { | |
182 var editorToolbar = new WebInspector.Toolbar("data-view-toolbar", this.e
lement); | |
183 | |
184 this._pageBackButton = new WebInspector.ToolbarButton(WebInspector.UIStr
ing("Show previous page"), "play-backwards-toolbar-item"); | |
185 this._pageBackButton.addEventListener("click", this._pageBackButtonClick
ed, this); | |
186 editorToolbar.appendToolbarItem(this._pageBackButton); | |
187 | |
188 this._pageForwardButton = new WebInspector.ToolbarButton(WebInspector.UI
String("Show next page"), "play-toolbar-item"); | |
189 this._pageForwardButton.setEnabled(false); | |
190 this._pageForwardButton.addEventListener("click", this._pageForwardButto
nClicked, this); | |
191 editorToolbar.appendToolbarItem(this._pageForwardButton); | |
192 | |
193 this._keyInputElement = editorToolbar.element.createChild("input", "key-
input"); | |
194 this._keyInputElement.placeholder = WebInspector.UIString("Start from ke
y"); | |
195 this._keyInputElement.addEventListener("paste", this._keyInputChanged.bi
nd(this), false); | |
196 this._keyInputElement.addEventListener("cut", this._keyInputChanged.bind
(this), false); | |
197 this._keyInputElement.addEventListener("keypress", this._keyInputChanged
.bind(this), false); | |
198 this._keyInputElement.addEventListener("keydown", this._keyInputChanged.
bind(this), false); | |
199 }, | |
200 | |
201 _pageBackButtonClicked: function() | |
202 { | |
203 this._skipCount = Math.max(0, this._skipCount - this._pageSize); | |
204 this._updateData(false); | |
205 }, | |
206 | |
207 _pageForwardButtonClicked: function() | |
208 { | |
209 this._skipCount = this._skipCount + this._pageSize; | |
210 this._updateData(false); | |
211 }, | |
212 | |
213 _keyInputChanged: function() | |
214 { | |
215 window.setTimeout(this._updateData.bind(this, false), 0); | |
216 }, | |
217 | |
218 /** | |
219 * @param {!WebInspector.IndexedDBModel.ObjectStore} objectStore | |
220 * @param {?WebInspector.IndexedDBModel.Index} index | |
221 */ | |
222 update: function(objectStore, index) | |
223 { | |
224 this._objectStore = objectStore; | |
225 this._index = index; | |
226 | |
227 if (this._dataGrid) | |
228 this._dataGrid.asWidget().detach(); | |
229 this._dataGrid = this._createDataGrid(); | |
230 this._dataGrid.asWidget().show(this.element); | |
231 | |
232 this._skipCount = 0; | |
233 this._updateData(true); | |
234 }, | |
235 | |
236 /** | |
237 * @param {string} keyString | |
238 */ | |
239 _parseKey: function(keyString) | |
240 { | |
241 var result; | |
242 try { | |
243 result = JSON.parse(keyString); | |
244 } catch (e) { | |
245 result = keyString; | |
246 } | |
247 return result; | |
248 }, | |
249 | |
250 /** | |
251 * @param {boolean} force | |
252 */ | |
253 _updateData: function(force) | |
254 { | |
255 var key = this._parseKey(this._keyInputElement.value); | |
256 var pageSize = this._pageSize; | |
257 var skipCount = this._skipCount; | |
258 this._refreshButton.setEnabled(false); | |
259 this._clearButton.setEnabled(!this._isIndex); | |
260 | |
261 if (!force && this._lastKey === key && this._lastPageSize === pageSize &
& this._lastSkipCount === skipCount) | |
262 return; | |
263 | |
264 if (this._lastKey !== key || this._lastPageSize !== pageSize) { | |
265 skipCount = 0; | |
266 this._skipCount = 0; | |
267 } | |
268 this._lastKey = key; | |
269 this._lastPageSize = pageSize; | |
270 this._lastSkipCount = skipCount; | |
271 | |
272 /** | |
273 * @param {!Array.<!WebInspector.IndexedDBModel.Entry>} entries | |
274 * @param {boolean} hasMore | |
275 * @this {WebInspector.IDBDataView} | |
276 */ | |
277 function callback(entries, hasMore) | |
278 { | |
279 this._refreshButton.setEnabled(true); | |
280 this.clear(); | |
281 this._entries = entries; | |
282 for (var i = 0; i < entries.length; ++i) { | |
283 var data = {}; | |
284 data["number"] = i + skipCount; | |
285 data["key"] = entries[i].key; | |
286 data["primaryKey"] = entries[i].primaryKey; | |
287 data["value"] = entries[i].value; | |
288 | |
289 var node = new WebInspector.IDBDataGridNode(data); | |
290 this._dataGrid.rootNode().appendChild(node); | |
291 } | |
292 | |
293 this._pageBackButton.setEnabled(!!skipCount); | |
294 this._pageForwardButton.setEnabled(hasMore); | |
295 } | |
296 | |
297 var idbKeyRange = key ? window.IDBKeyRange.lowerBound(key) : null; | |
298 if (this._isIndex) | |
299 this._model.loadIndexData(this._databaseId, this._objectStore.name,
this._index.name, idbKeyRange, skipCount, pageSize, callback.bind(this)); | |
300 else | |
301 this._model.loadObjectStoreData(this._databaseId, this._objectStore.
name, idbKeyRange, skipCount, pageSize, callback.bind(this)); | |
302 }, | |
303 | |
304 _refreshButtonClicked: function(event) | |
305 { | |
306 this._updateData(true); | |
307 }, | |
308 | |
309 _clearButtonClicked: function(event) | |
310 { | |
311 /** | |
312 * @this {WebInspector.IDBDataView} | |
313 */ | |
314 function cleared() { | |
315 this._clearButton.setEnabled(true); | |
316 this._updateData(true); | |
317 } | |
318 this._clearButton.setEnabled(false); | |
319 this._model.clearObjectStore(this._databaseId, this._objectStore.name, c
leared.bind(this)); | |
320 }, | |
321 | |
322 /** | |
323 * @override | |
324 * @return {!Array.<!WebInspector.ToolbarItem>} | |
325 */ | |
326 syncToolbarItems: function() | |
327 { | |
328 return [this._refreshButton, this._clearButton]; | |
329 }, | |
330 | |
331 clear: function() | |
332 { | |
333 this._dataGrid.rootNode().removeChildren(); | |
334 this._entries = []; | |
335 }, | |
336 | |
337 __proto__: WebInspector.SimpleView.prototype | |
338 }; | 366 }; |
339 | |
340 /** | |
341 * @constructor | |
342 * @extends {WebInspector.DataGridNode} | |
343 * @param {!Object.<string, *>} data | |
344 */ | |
345 WebInspector.IDBDataGridNode = function(data) | |
346 { | |
347 WebInspector.DataGridNode.call(this, data, false); | |
348 this.selectable = false; | |
349 }; | |
350 | |
351 WebInspector.IDBDataGridNode.prototype = { | |
352 /** | |
353 * @override | |
354 * @return {!Element} | |
355 */ | |
356 createCell: function(columnIdentifier) | |
357 { | |
358 var cell = WebInspector.DataGridNode.prototype.createCell.call(this, col
umnIdentifier); | |
359 var value = /** @type {!WebInspector.RemoteObject} */ (this.data[columnI
dentifier]); | |
360 | |
361 switch (columnIdentifier) { | |
362 case "value": | |
363 case "key": | |
364 case "primaryKey": | |
365 cell.removeChildren(); | |
366 var objectElement = WebInspector.ObjectPropertiesSection.defaultObje
ctPresentation(value, undefined, true); | |
367 cell.appendChild(objectElement); | |
368 break; | |
369 default: | |
370 } | |
371 | |
372 return cell; | |
373 }, | |
374 | |
375 __proto__: WebInspector.DataGridNode.prototype | |
376 }; | |
OLD | NEW |