diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
commit | 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch) | |
tree | 46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebInspectorUI/UserInterface/Views/DOMStorageContentView.js | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/WebInspectorUI/UserInterface/Views/DOMStorageContentView.js')
-rw-r--r-- | Source/WebInspectorUI/UserInterface/Views/DOMStorageContentView.js | 260 |
1 files changed, 260 insertions, 0 deletions
diff --git a/Source/WebInspectorUI/UserInterface/Views/DOMStorageContentView.js b/Source/WebInspectorUI/UserInterface/Views/DOMStorageContentView.js new file mode 100644 index 000000000..8932342ae --- /dev/null +++ b/Source/WebInspectorUI/UserInterface/Views/DOMStorageContentView.js @@ -0,0 +1,260 @@ +/* + * Copyright (C) 2013-2015 Apple Inc. All rights reserved. + * Copyright (C) 2013 Samsung Electronics. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +WebInspector.DOMStorageContentView = class DOMStorageContentView extends WebInspector.ContentView +{ + constructor(representedObject) + { + super(representedObject); + + this.element.classList.add("dom-storage"); + + representedObject.addEventListener(WebInspector.DOMStorageObject.Event.ItemsCleared, this.itemsCleared, this); + representedObject.addEventListener(WebInspector.DOMStorageObject.Event.ItemAdded, this.itemAdded, this); + representedObject.addEventListener(WebInspector.DOMStorageObject.Event.ItemRemoved, this.itemRemoved, this); + representedObject.addEventListener(WebInspector.DOMStorageObject.Event.ItemUpdated, this.itemUpdated, this); + + let columns = {}; + columns.key = {title: WebInspector.UIString("Key"), sortable: true}; + columns.value = {title: WebInspector.UIString("Value"), sortable: true}; + + this._dataGrid = new WebInspector.DataGrid(columns, this._editingCallback.bind(this), this._deleteCallback.bind(this)); + this._dataGrid.sortOrder = WebInspector.DataGrid.SortOrder.Ascending; + this._dataGrid.sortColumnIdentifier = "key"; + this._dataGrid.createSettings("dom-storage-content-view"); + this._dataGrid.addEventListener(WebInspector.DataGrid.Event.SortChanged, this._sortDataGrid, this); + + this.addSubview(this._dataGrid); + + this._populate(); + } + + // Public + + saveToCookie(cookie) + { + cookie.type = WebInspector.ContentViewCookieType.DOMStorage; + cookie.isLocalStorage = this.representedObject.isLocalStorage(); + cookie.host = this.representedObject.host; + } + + get scrollableElements() + { + return [this._dataGrid.scrollContainer]; + } + + itemsCleared(event) + { + this._dataGrid.removeChildren(); + this._dataGrid.addPlaceholderNode(); + } + + itemRemoved(event) + { + for (let node of this._dataGrid.children) { + if (node.data.key === event.data.key) + return this._dataGrid.removeChild(node); + } + + return null; + } + + itemAdded(event) + { + let {key, value} = event.data; + value = this._truncateValue(value); + + // Enforce key uniqueness. + for (let node of this._dataGrid.children) { + if (node.data.key === key) + return; + } + + this._dataGrid.appendChild(new WebInspector.DataGridNode({key, value}, false)); + this._sortDataGrid(); + } + + itemUpdated(event) + { + let {key, value} = event.data; + value = this._truncateValue(value); + + let keyFound = false; + for (let childNode of this._dataGrid.children) { + if (childNode.data.key === key) { + // Remove any rows that are now duplicates. + if (keyFound) { + this._dataGrid.removeChild(childNode); + continue; + } + + keyFound = true; + childNode.data.value = value; + childNode.refresh(); + } + } + this._sortDataGrid(); + } + + // Private + + _truncateValue(value) + { + return value.truncate(200); + } + + _populate() + { + this.representedObject.getEntries(function(error, entries) { + if (error) + return; + + for (let [key, value] of entries) { + if (!key || !value) + continue; + + value = this._truncateValue(value); + let node = new WebInspector.DataGridNode({key, value}, false); + this._dataGrid.appendChild(node); + } + + this._sortDataGrid(); + this._dataGrid.addPlaceholderNode(); + this._dataGrid.updateLayout(); + }.bind(this)); + } + + _sortDataGrid() + { + let sortColumnIdentifier = this._dataGrid.sortColumnIdentifier || "key"; + + function comparator(a, b) + { + return a.data[sortColumnIdentifier].localeCompare(b.data[sortColumnIdentifier]); + } + + this._dataGrid.sortNodesImmediately(comparator); + } + + _deleteCallback(node) + { + if (!node || node.isPlaceholderNode) + return; + + this._dataGrid.removeChild(node); + this.representedObject.removeItem(node.data["key"]); + } + + _editingCallback(editingNode, columnIdentifier, oldText, newText, moveDirection) + { + var key = editingNode.data["key"].trim().removeWordBreakCharacters(); + var value = editingNode.data["value"].trim().removeWordBreakCharacters(); + var previousValue = oldText.trim().removeWordBreakCharacters(); + var enteredValue = newText.trim().removeWordBreakCharacters(); + var hasUncommittedEdits = editingNode.__hasUncommittedEdits; + var hasChange = previousValue !== enteredValue; + var isEditingKey = columnIdentifier === "key"; + var isEditingValue = !isEditingKey; + var domStorage = this.representedObject; + + // Nothing changed, just bail. + if (!hasChange && !hasUncommittedEdits) + return; + + // Something changed, save the original key/value and enter uncommitted state. + if (hasChange && !editingNode.__hasUncommittedEdits) { + editingNode.__hasUncommittedEdits = true; + editingNode.__originalKey = isEditingKey ? previousValue : key; + editingNode.__originalValue = isEditingValue ? previousValue : value; + } + + function cleanup() + { + editingNode.element.classList.remove(WebInspector.DOMStorageContentView.MissingKeyStyleClassName); + editingNode.element.classList.remove(WebInspector.DOMStorageContentView.MissingValueStyleClassName); + editingNode.element.classList.remove(WebInspector.DOMStorageContentView.DuplicateKeyStyleClassName); + editingNode.__hasUncommittedEdits = undefined; + editingNode.__originalKey = undefined; + editingNode.__originalValue = undefined; + } + + // If the key/value field was cleared, add "missing" style. + if (isEditingKey) { + if (key.length) + editingNode.element.classList.remove(WebInspector.DOMStorageContentView.MissingKeyStyleClassName); + else + editingNode.element.classList.add(WebInspector.DOMStorageContentView.MissingKeyStyleClassName); + } else if (isEditingValue) { + if (value.length) + editingNode.element.classList.remove(WebInspector.DOMStorageContentView.MissingValueStyleClassName); + else + editingNode.element.classList.add(WebInspector.DOMStorageContentView.MissingValueStyleClassName); + } + + // Check for key duplicates. If this is a new row, or an existing row that changed key. + var keyChanged = key !== editingNode.__originalKey; + if (keyChanged) { + if (domStorage.entries.has(key)) + editingNode.element.classList.add(WebInspector.DOMStorageContentView.DuplicateKeyStyleClassName); + else + editingNode.element.classList.remove(WebInspector.DOMStorageContentView.DuplicateKeyStyleClassName); + } + + // See if we are done editing this row or not. + var columnIndex = this._dataGrid.orderedColumns.indexOf(columnIdentifier); + var mayMoveToNextRow = moveDirection === "forward" && columnIndex === this._dataGrid.orderedColumns.length - 1; + var mayMoveToPreviousRow = moveDirection === "backward" && columnIndex === 0; + var doneEditing = mayMoveToNextRow || mayMoveToPreviousRow || !moveDirection; + + // Expecting more edits on this row. + if (!doneEditing) + return; + + // Key and value were cleared, remove the row. + if (!key.length && !value.length && !editingNode.isPlaceholderNode) { + this._dataGrid.removeChild(editingNode); + domStorage.removeItem(editingNode.__originalKey); + return; + } + + // Done editing but leaving the row in an invalid state. Leave in uncommitted state. + var isDuplicate = editingNode.element.classList.contains(WebInspector.DOMStorageContentView.DuplicateKeyStyleClassName); + if (!key.length || !value.length || isDuplicate) + return; + + // Commit. + if (keyChanged && !editingNode.isPlaceholderNode) + domStorage.removeItem(editingNode.__originalKey); + if (editingNode.isPlaceholderNode) + this._dataGrid.addPlaceholderNode(); + cleanup(); + domStorage.setItem(key, value); + } +}; + +WebInspector.DOMStorageContentView.DuplicateKeyStyleClassName = "duplicate-key"; +WebInspector.DOMStorageContentView.MissingKeyStyleClassName = "missing-key"; +WebInspector.DOMStorageContentView.MissingValueStyleClassName = "missing-value"; |