1/* 2 * Copyright (C) 2008 Nokia Inc. All rights reserved. 3 * Copyright (C) 2013 Samsung Electronics. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27/** 28 * @constructor 29 * @extends {WebInspector.View} 30 */ 31WebInspector.DOMStorageItemsView = function(domStorage) 32{ 33 WebInspector.View.call(this); 34 35 this.domStorage = domStorage; 36 37 this.element.classList.add("storage-view"); 38 this.element.classList.add("table"); 39 40 this.deleteButton = new WebInspector.StatusBarButton(WebInspector.UIString("Delete"), "delete-storage-status-bar-item"); 41 this.deleteButton.visible = false; 42 this.deleteButton.addEventListener("click", this._deleteButtonClicked, this); 43 44 this.refreshButton = new WebInspector.StatusBarButton(WebInspector.UIString("Refresh"), "refresh-storage-status-bar-item"); 45 this.refreshButton.addEventListener("click", this._refreshButtonClicked, this); 46 47 this.domStorage.addEventListener(WebInspector.DOMStorage.Events.DOMStorageItemsCleared, this._domStorageItemsCleared, this); 48 this.domStorage.addEventListener(WebInspector.DOMStorage.Events.DOMStorageItemRemoved, this._domStorageItemRemoved, this); 49 this.domStorage.addEventListener(WebInspector.DOMStorage.Events.DOMStorageItemAdded, this._domStorageItemAdded, this); 50 this.domStorage.addEventListener(WebInspector.DOMStorage.Events.DOMStorageItemUpdated, this._domStorageItemUpdated, this); 51} 52 53WebInspector.DOMStorageItemsView.prototype = { 54 get statusBarItems() 55 { 56 return [this.refreshButton.element, this.deleteButton.element]; 57 }, 58 59 wasShown: function() 60 { 61 this._update(); 62 }, 63 64 willHide: function() 65 { 66 this.deleteButton.visible = false; 67 }, 68 69 /** 70 * @param {!WebInspector.Event} event 71 */ 72 _domStorageItemsCleared: function(event) 73 { 74 if (!this.isShowing() || !this._dataGrid) 75 return; 76 77 this._dataGrid.rootNode().removeChildren(); 78 this._dataGrid.addCreationNode(false); 79 this.deleteButton.visible = false; 80 event.consume(true); 81 }, 82 83 /** 84 * @param {!WebInspector.Event} event 85 */ 86 _domStorageItemRemoved: function(event) 87 { 88 if (!this.isShowing() || !this._dataGrid) 89 return; 90 91 var storageData = event.data; 92 var rootNode = this._dataGrid.rootNode(); 93 var children = rootNode.children; 94 95 event.consume(true); 96 97 for (var i = 0; i < children.length; ++i) { 98 var childNode = children[i]; 99 if (childNode.data.key === storageData.key) { 100 rootNode.removeChild(childNode); 101 this.deleteButton.visible = (children.length > 1); 102 return; 103 } 104 } 105 }, 106 107 /** 108 * @param {!WebInspector.Event} event 109 */ 110 _domStorageItemAdded: function(event) 111 { 112 if (!this.isShowing() || !this._dataGrid) 113 return; 114 115 var storageData = event.data; 116 var rootNode = this._dataGrid.rootNode(); 117 var children = rootNode.children; 118 119 event.consume(true); 120 this.deleteButton.visible = true; 121 122 for (var i = 0; i < children.length; ++i) 123 if (children[i].data.key === storageData.key) 124 return; 125 126 var childNode = new WebInspector.DataGridNode({key: storageData.key, value: storageData.value}, false); 127 rootNode.insertChild(childNode, children.length - 1); 128 }, 129 130 /** 131 * @param {!WebInspector.Event} event 132 */ 133 _domStorageItemUpdated: function(event) 134 { 135 if (!this.isShowing() || !this._dataGrid) 136 return; 137 138 var storageData = event.data; 139 var rootNode = this._dataGrid.rootNode(); 140 var children = rootNode.children; 141 142 event.consume(true); 143 144 var keyFound = false; 145 for (var i = 0; i < children.length; ++i) { 146 var childNode = children[i]; 147 if (childNode.data.key === storageData.key) { 148 if (keyFound) { 149 rootNode.removeChild(childNode); 150 return; 151 } 152 keyFound = true; 153 if (childNode.data.value !== storageData.value) { 154 childNode.data.value = storageData.value; 155 childNode.refresh(); 156 childNode.select(); 157 childNode.reveal(); 158 } 159 this.deleteButton.visible = true; 160 } 161 } 162 }, 163 164 _update: function() 165 { 166 this.detachChildViews(); 167 this.domStorage.getItems(this._showDOMStorageItems.bind(this)); 168 }, 169 170 _showDOMStorageItems: function(error, items) 171 { 172 if (error) 173 return; 174 175 this._dataGrid = this._dataGridForDOMStorageItems(items); 176 this._dataGrid.show(this.element); 177 this.deleteButton.visible = (this._dataGrid.rootNode().children.length > 1); 178 }, 179 180 _dataGridForDOMStorageItems: function(items) 181 { 182 var columns = [ 183 {id: "key", title: WebInspector.UIString("Key"), editable: true, weight: 50}, 184 {id: "value", title: WebInspector.UIString("Value"), editable: true, weight: 50} 185 ]; 186 187 var nodes = []; 188 189 var keys = []; 190 var length = items.length; 191 for (var i = 0; i < items.length; i++) { 192 var key = items[i][0]; 193 var value = items[i][1]; 194 var node = new WebInspector.DataGridNode({key: key, value: value}, false); 195 node.selectable = true; 196 nodes.push(node); 197 keys.push(key); 198 } 199 200 var dataGrid = new WebInspector.DataGrid(columns, this._editingCallback.bind(this), this._deleteCallback.bind(this)); 201 dataGrid.setName("DOMStorageItemsView"); 202 length = nodes.length; 203 for (var i = 0; i < length; ++i) 204 dataGrid.rootNode().appendChild(nodes[i]); 205 dataGrid.addCreationNode(false); 206 if (length > 0) 207 nodes[0].selected = true; 208 return dataGrid; 209 }, 210 211 _deleteButtonClicked: function(event) 212 { 213 if (!this._dataGrid || !this._dataGrid.selectedNode) 214 return; 215 216 this._deleteCallback(this._dataGrid.selectedNode); 217 this._dataGrid.changeNodeAfterDeletion(); 218 }, 219 220 _refreshButtonClicked: function(event) 221 { 222 this._update(); 223 }, 224 225 _editingCallback: function(editingNode, columnIdentifier, oldText, newText) 226 { 227 var domStorage = this.domStorage; 228 if ("key" === columnIdentifier) { 229 if (typeof oldText === "string") 230 domStorage.removeItem(oldText); 231 domStorage.setItem(newText, editingNode.data.value || ''); 232 this._removeDupes(editingNode); 233 } else 234 domStorage.setItem(editingNode.data.key || '', newText); 235 }, 236 237 /** 238 * @param {!WebInspector.DataGridNode} masterNode 239 */ 240 _removeDupes: function(masterNode) 241 { 242 var rootNode = this._dataGrid.rootNode(); 243 var children = rootNode.children; 244 for (var i = children.length - 1; i >= 0; --i) { 245 var childNode = children[i]; 246 if ((childNode.data.key === masterNode.data.key) && (masterNode !== childNode)) 247 rootNode.removeChild(childNode); 248 } 249 }, 250 251 _deleteCallback: function(node) 252 { 253 if (!node || node.isCreationNode) 254 return; 255 256 if (this.domStorage) 257 this.domStorage.removeItem(node.data.key); 258 }, 259 260 __proto__: WebInspector.View.prototype 261} 262