Changeset 90460 in webkit


Ignore:
Timestamp:
Jul 6, 2011 8:25:40 AM (13 years ago)
Author:
pfeldman@chromium.org
Message:

2011-07-06 Pavel Feldman <pfeldman@google.com>

Web Inspector: implement drag'n'drop in the elements panel for reordering nodes.
https://bugs.webkit.org/show_bug.cgi?id=63990

Reviewed by Yury Semikhatsky.

  • inspector/Inspector.json:
  • inspector/InspectorDOMAgent.cpp: (WebCore::InspectorDOMAgent::moveTo):
  • inspector/InspectorDOMAgent.h:
  • inspector/front-end/DOMAgent.js: (WebInspector.DOMNode.prototype._removeChild): (WebInspector.DOMNode.prototype.ownerDocumentElement): (WebInspector.DOMNode.prototype.moveTo): (WebInspector.DOMAgent.prototype._childNodeRemoved):
  • inspector/front-end/ElementsTreeOutline.js: (WebInspector.ElementsTreeOutline): (WebInspector.ElementsTreeOutline.prototype._ondragstart): (WebInspector.ElementsTreeOutline.prototype._ondragover): (WebInspector.ElementsTreeOutline.prototype._ondragleave): (WebInspector.ElementsTreeOutline.prototype._isValidDragSourceOrTarget): (WebInspector.ElementsTreeOutline.prototype._ondragend.callback): (WebInspector.ElementsTreeOutline.prototype._ondragend): (WebInspector.ElementsTreeOutline.prototype._clearDragOverTreeElementMarker): (WebInspector.ElementsTreeOutline.prototype.populateContextMenu.focusElement): (WebInspector.ElementsTreeOutline.prototype.populateContextMenu): (WebInspector.ElementsTreeElement.prototype.onattach):
  • inspector/front-end/inspector.css: (.outline-disclosure li.elements-drag-over .selection):
  • inspector/front-end/treeoutline.js: (TreeOutline.prototype.treeElementFromEvent):
Location:
trunk/Source/WebCore
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r90456 r90460  
     12011-07-06  Pavel Feldman  <pfeldman@google.com>
     2
     3        Web Inspector: implement drag'n'drop in the elements panel for reordering nodes.
     4        https://bugs.webkit.org/show_bug.cgi?id=63990
     5
     6        Reviewed by Yury Semikhatsky.
     7
     8        * inspector/Inspector.json:
     9        * inspector/InspectorDOMAgent.cpp:
     10        (WebCore::InspectorDOMAgent::moveTo):
     11        * inspector/InspectorDOMAgent.h:
     12        * inspector/front-end/DOMAgent.js:
     13        (WebInspector.DOMNode.prototype._removeChild):
     14        (WebInspector.DOMNode.prototype.ownerDocumentElement):
     15        (WebInspector.DOMNode.prototype.moveTo):
     16        (WebInspector.DOMAgent.prototype._childNodeRemoved):
     17        * inspector/front-end/ElementsTreeOutline.js:
     18        (WebInspector.ElementsTreeOutline):
     19        (WebInspector.ElementsTreeOutline.prototype._ondragstart):
     20        (WebInspector.ElementsTreeOutline.prototype._ondragover):
     21        (WebInspector.ElementsTreeOutline.prototype._ondragleave):
     22        (WebInspector.ElementsTreeOutline.prototype._isValidDragSourceOrTarget):
     23        (WebInspector.ElementsTreeOutline.prototype._ondragend.callback):
     24        (WebInspector.ElementsTreeOutline.prototype._ondragend):
     25        (WebInspector.ElementsTreeOutline.prototype._clearDragOverTreeElementMarker):
     26        (WebInspector.ElementsTreeOutline.prototype.populateContextMenu.focusElement):
     27        (WebInspector.ElementsTreeOutline.prototype.populateContextMenu):
     28        (WebInspector.ElementsTreeElement.prototype.onattach):
     29        * inspector/front-end/inspector.css:
     30        (.outline-disclosure li.elements-drag-over .selection):
     31        * inspector/front-end/treeoutline.js:
     32        (TreeOutline.prototype.treeElementFromEvent):
     33
    1342011-07-06  Andras Becsi  <abecsi@webkit.org>
    235
  • trunk/Source/WebCore/inspector/Inspector.json

    r90364 r90460  
    10161016                ],
    10171017                "description": "Returns attributes for the specified nodes."
     1018            },
     1019            {
     1020                "name": "moveTo",
     1021                "parameters": [
     1022                    { "name": "nodeId", "type": "integer", "description": "Id of the node to drop." },
     1023                    { "name": "targetNodeId", "type": "integer", "description": "Id of the node to drop into." },
     1024                    { "name": "anchorNodeId", "type": "integer", "optional": true, "description": "Drop node before given one." }
     1025                ],
     1026                "returns": [
     1027                    { "name": "nodeId", "type": "integer", "description": "New id of the moved node." }
     1028                ],
     1029                "description": "Moves node into the new container, places it before the given anchor."
    10181030            }
    10191031        ],
  • trunk/Source/WebCore/inspector/InspectorDOMAgent.cpp

    r90013 r90460  
    10331033}
    10341034
     1035void InspectorDOMAgent::moveTo(ErrorString* error, int nodeId, int targetNodeId, const int* const anchorNodeId, int* newNodeId)
     1036{
     1037    Element* element = assertElement(error, nodeId);
     1038    if (!element)
     1039        return;
     1040
     1041    Element* targetElement = assertElement(error, targetNodeId);
     1042    if (!targetElement)
     1043        return;
     1044
     1045    Element* anchorElement = 0;
     1046    if (anchorNodeId && *anchorNodeId) {
     1047        anchorElement = assertElement(error, *anchorNodeId);
     1048        if (!anchorElement)
     1049            return;
     1050        if (anchorElement->parentNode() != targetElement) {
     1051            *error = "Anchor node must be child of the target node.";
     1052            return;
     1053        }
     1054    }
     1055
     1056    ExceptionCode ec = 0;
     1057    bool success = targetElement->insertBefore(element, anchorElement, ec);
     1058    if (ec || !success) {
     1059        *error = "Could not drop node.";
     1060        return;
     1061    }
     1062    *newNodeId = pushNodePathToFrontend(element);
     1063}
     1064
    10351065void InspectorDOMAgent::resolveNode(ErrorString* error, int nodeId, const String* const objectGroup, RefPtr<InspectorObject>* result)
    10361066{
  • trunk/Source/WebCore/inspector/InspectorDOMAgent.h

    r89439 r90460  
    137137    void highlightFrame(ErrorString*, const String& frameId);
    138138    void hideFrameHighlight(ErrorString* error) { hideHighlight(error); }
     139    void moveTo(ErrorString*, int nodeId, int targetNodeId, const int* const anchorNodeId, int* newNodeId);
     140
    139141    Node* highlightedNode() const { return m_highlightedNode.get(); }
    140142
  • trunk/Source/WebCore/inspector/front-end/DOMAgent.js

    r89439 r90460  
    260260    },
    261261
    262     removeChild_: function(node)
     262    _removeChild: function(node)
    263263    {
    264264        this.children.splice(this.children.indexOf(node), 1);
     
    316316            node = node.parentNode;
    317317        return node;
     318    },
     319
     320    moveTo: function(targetNode, anchorNode, callback)
     321    {
     322        DOMAgent.moveTo(this.id, targetNode.id, anchorNode ? anchorNode.id : undefined, callback);
    318323    }
    319324}
     
    536541        var parent = this._idToDOMNode[parentId];
    537542        var node = this._idToDOMNode[nodeId];
    538         parent.removeChild_(node);
     543        parent._removeChild(node);
    539544        this.dispatchEventToListeners(WebInspector.DOMAgent.Events.NodeRemoved, {node:node, parent:parent});
    540545        delete this._idToDOMNode[nodeId];
  • trunk/Source/WebCore/inspector/front-end/ElementsTreeOutline.js

    r90013 r90460  
    3434    this.element.addEventListener("mousemove", this._onmousemove.bind(this), false);
    3535    this.element.addEventListener("mouseout", this._onmouseout.bind(this), false);
     36    this.element.addEventListener("dragstart", this._ondragstart.bind(this), false);
     37    this.element.addEventListener("dragover", this._ondragover.bind(this), false);
     38    this.element.addEventListener("dragleave", this._ondragleave.bind(this), false);
     39    this.element.addEventListener("dragend", this._ondragend.bind(this), false);
    3640
    3741    TreeOutline.call(this, this.element);
     
    259263    },
    260264
     265    _ondragstart: function(event)
     266    {
     267        var treeElement = this._treeElementFromEvent(event);
     268        if (!treeElement)
     269            return false;
     270
     271        if (!this._isValidDragSourceOrTarget(treeElement))
     272            return false;
     273
     274        if (treeElement.representedObject.nodeName() === "BODY" || treeElement.representedObject.nodeName() === "HEAD")
     275            return false;
     276
     277        event.dataTransfer.setData("text/plain", treeElement.listItemElement.textContent);
     278        event.dataTransfer.effectAllowed = "copy";
     279        this._nodeBeingDragged = treeElement.representedObject;
     280
     281        WebInspector.highlightDOMNode(0);
     282
     283        return true;
     284    },
     285
     286    _ondragover: function(event)
     287    {
     288        this._clearDragOverTreeElementMarker();
     289
     290        if (!this._nodeBeingDragged)
     291            return;
     292       
     293        var treeElement = this._treeElementFromEvent(event);
     294        if (!this._isValidDragSourceOrTarget(treeElement))
     295            return;
     296
     297        var node = treeElement.representedObject;
     298        while (node) {
     299            if (node === this._nodeBeingDragged)
     300                return;
     301            node = node.parentNode;
     302        }
     303
     304        treeElement.updateSelection();
     305        treeElement.listItemElement.addStyleClass("elements-drag-over");
     306        this._dragOverTreeElement = treeElement;
     307    },
     308
     309    _ondragleave: function(event)
     310    {
     311        this._clearDragOverTreeElementMarker();
     312
     313        if (!this._nodeBeingDragged)
     314            return;
     315       
     316        var treeElement = this._treeElementFromEvent(event);
     317        if (!this._isValidDragSourceOrTarget(treeElement))
     318            return false;
     319
     320        var node = treeElement.representedObject;
     321        while (node) {
     322            if (node === this._nodeBeingDragged)
     323                return;
     324            node = node.parentNode;
     325        }
     326
     327        treeElement.updateSelection();
     328        treeElement.listItemElement.addStyleClass("elements-drag-over");
     329        this._dragOverTreeElement = treeElement;
     330    },
     331
     332    _isValidDragSourceOrTarget: function(treeElement)
     333    {
     334        if (!treeElement)
     335            return false;
     336
     337        var node = treeElement.representedObject;
     338        if (!(node instanceof WebInspector.DOMNode))
     339            return false;
     340
     341        if (node.nodeType() !== Node.ELEMENT_NODE)
     342            return false;
     343
     344        if (!node.parentNode || node.parentNode.nodeType() !== Node.ELEMENT_NODE)
     345            return false;
     346
     347        return true;
     348    },
     349
     350    _ondragend: function(event)
     351    {
     352        if (this._nodeBeingDragged && this._dragOverTreeElement) {
     353            var parentNode;
     354            var anchorNode;
     355
     356            if (this._dragOverTreeElement._elementCloseTag) {
     357                // Drop onto closing tag -> insert as last child.
     358                parentNode = this._dragOverTreeElement.representedObject;
     359            } else {
     360                var dragTargetNode = this._dragOverTreeElement.representedObject;
     361                parentNode = dragTargetNode.parentNode;
     362                anchorNode = dragTargetNode;
     363            }
     364
     365            function callback(error, newNodeId)
     366            {
     367                if (error)
     368                    return;
     369
     370                WebInspector.panels.elements.updateModifiedNodes();
     371                var newNode = WebInspector.domAgent.nodeForId(newNodeId);
     372                if (newNode)
     373                    this.focusedDOMNode = newNode;
     374            }
     375            this._nodeBeingDragged.moveTo(parentNode, anchorNode, callback.bind(this));
     376        }
     377       
     378        this._clearDragOverTreeElementMarker();
     379        delete this._nodeBeingDragged;
     380    },
     381
     382    _clearDragOverTreeElementMarker: function()
     383    {
     384        if (this._dragOverTreeElement) {
     385            this._dragOverTreeElement.updateSelection();
     386            this._dragOverTreeElement.listItemElement.removeStyleClass("elements-drag-over");
     387            delete this._dragOverTreeElement;
     388        }
     389    },
     390
    261391    populateContextMenu: function(contextMenu, event)
    262392    {
    263         var listItem = event.target.enclosingNodeOrSelfWithNodeName("LI");
    264         if (!listItem || !listItem.treeElement)
     393        var treeElement = this._treeElementFromEvent(event);
     394        if (!treeElement)
    265395            return false;
    266396
     
    269399            function focusElement()
    270400            {
    271                 WebInspector.panels.elements.switchToAndFocus(listItem.treeElement.representedObject);
     401                WebInspector.panels.elements.switchToAndFocus(treeElement.representedObject);
    272402            }
    273403            contextMenu.appendItem(WebInspector.UIString("Reveal in Elements Panel"), focusElement.bind(this));
     
    279409            if (href)
    280410                populated = WebInspector.panels.elements.populateHrefContextMenu(contextMenu, event, href);
    281             if (tag && listItem.treeElement._populateTagContextMenu) {
     411            if (tag && treeElement._populateTagContextMenu) {
    282412                if (populated)
    283413                    contextMenu.appendSeparator();
    284                 listItem.treeElement._populateTagContextMenu(contextMenu, event);
     414                treeElement._populateTagContextMenu(contextMenu, event);
    285415                populated = true;
    286             } else if (textNode && listItem.treeElement._populateTextContextMenu) {
     416            } else if (textNode && treeElement._populateTextContextMenu) {
    287417                if (populated)
    288418                    contextMenu.appendSeparator();
    289                 listItem.treeElement._populateTextContextMenu(contextMenu, textNode);
     419                treeElement._populateTextContextMenu(contextMenu, textNode);
    290420                populated = true;
    291421            }
     
    509639
    510640        this.updateTitle();
    511 
    512641        this._preventFollowingLinksOnDoubleClick();
     642        this.listItemElement.draggable = true;
    513643    },
    514644
  • trunk/Source/WebCore/inspector/front-end/inspector.css

    r90397 r90460  
    12221222}
    12231223
     1224.outline-disclosure li.elements-drag-over .selection {
     1225    display: block;
     1226    margin-top: -2px;
     1227    border-top: 2px solid rgb(56, 121, 217);
     1228}
     1229
    12241230.outline-disclosure ol:focus li.selected .selection {
    12251231    background-color: rgb(56, 121, 217);
Note: See TracChangeset for help on using the changeset viewer.