~oif-team/ubuntu/natty/qt4-x11/xi2.1

« back to all changes in this revision

Viewing changes to src/3rdparty/webkit/WebCore/inspector/front-end/ElementsTreeOutline.js

  • Committer: Bazaar Package Importer
  • Author(s): Alessandro Ghersi
  • Date: 2009-11-02 18:30:08 UTC
  • mfrom: (1.2.2 upstream)
  • mto: (15.2.5 experimental)
  • mto: This revision was merged to the branch mainline in revision 88.
  • Revision ID: james.westby@ubuntu.com-20091102183008-b6a4gcs128mvfb3m
Tags: upstream-4.6.0~beta1
ImportĀ upstreamĀ versionĀ 4.6.0~beta1

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 * Copyright (C) 2007, 2008 Apple Inc.  All rights reserved.
3
3
 * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com>
 
4
 * Copyright (C) 2009 Joseph Pecoraro
4
5
 *
5
6
 * Redistribution and use in source and binary forms, with or without
6
7
 * modification, are permitted provided that the following conditions
30
31
WebInspector.ElementsTreeOutline = function() {
31
32
    this.element = document.createElement("ol");
32
33
    this.element.addEventListener("mousedown", this._onmousedown.bind(this), false);
33
 
    this.element.addEventListener("dblclick", this._ondblclick.bind(this), false);
34
34
    this.element.addEventListener("mousemove", this._onmousemove.bind(this), false);
35
35
    this.element.addEventListener("mouseout", this._onmouseout.bind(this), false);
36
36
 
50
50
 
51
51
    set rootDOMNode(x)
52
52
    {
53
 
        if (objectsAreSame(this._rootDOMNode, x))
 
53
        if (this._rootDOMNode === x)
54
54
            return;
55
55
 
56
56
        this._rootDOMNode = x;
65
65
 
66
66
    set focusedDOMNode(x)
67
67
    {
68
 
        if (objectsAreSame(this._focusedDOMNode, x)) {
 
68
        if (this._focusedDOMNode === x) {
69
69
            this.revealAndSelectNode(x);
70
70
            return;
71
71
        }
78
78
        // and the select() call would change the focusedDOMNode and reenter this setter. So to
79
79
        // avoid calling focusedNodeChanged() twice, first check if _focusedDOMNode is the same
80
80
        // node as the one passed in.
81
 
        if (objectsAreSame(this._focusedDOMNode, x)) {
 
81
        if (this._focusedDOMNode === x) {
82
82
            this.focusedNodeChanged();
83
83
 
84
84
            if (x && !this.suppressSelectHighlight) {
85
 
                InspectorController.highlightDOMNode(x);
 
85
                InspectorController.highlightDOMNode(x.id);
86
86
 
87
87
                if ("_restorePreviousHighlightNodeTimeout" in this)
88
88
                    clearTimeout(this._restorePreviousHighlightNodeTimeout);
91
91
                {
92
92
                    var hoveredNode = WebInspector.hoveredDOMNode;
93
93
                    if (hoveredNode)
94
 
                        InspectorController.highlightDOMNode(hoveredNode);
 
94
                        InspectorController.highlightDOMNode(hoveredNode.id);
95
95
                    else
96
96
                        InspectorController.hideDOMNodeHighlight();
97
97
                }
137
137
 
138
138
    focusedNodeChanged: function(forceUpdate) {},
139
139
 
140
 
    findTreeElement: function(node, isAncestor, getParent, equal)
 
140
    findTreeElement: function(node)
141
141
    {
142
 
        if (typeof isAncestor === "undefined")
143
 
            isAncestor = isAncestorIncludingParentFrames;
144
 
        if (typeof getParent === "undefined")
145
 
            getParent = parentNodeOrFrameElement;
146
 
        if (typeof equal === "undefined")
147
 
            equal = objectsAreSame;
148
 
 
149
 
        var treeElement = TreeOutline.prototype.findTreeElement.call(this, node, isAncestor, getParent, equal);
 
142
        var treeElement = TreeOutline.prototype.findTreeElement.call(this, node, isAncestorNode, parentNode);
150
143
        if (!treeElement && node.nodeType === Node.TEXT_NODE) {
151
144
            // The text node might have been inlined if it was short, so try to find the parent element.
152
 
            treeElement = TreeOutline.prototype.findTreeElement.call(this, node.parentNode, isAncestor, getParent, equal);
 
145
            treeElement = TreeOutline.prototype.findTreeElement.call(this, node.parentNode, isAncestorNode, parentNode);
153
146
        }
154
147
 
155
148
        return treeElement;
192
185
        return element;
193
186
    },
194
187
 
195
 
    _ondblclick: function(event)
196
 
    {
197
 
        var element = this._treeElementFromEvent(event);
198
 
 
199
 
        if (!element || !element.ondblclick)
200
 
            return;
201
 
 
202
 
        element.ondblclick(element, event);
203
 
    },
204
 
 
205
188
    _onmousedown: function(event)
206
189
    {
207
190
        var element = this._treeElementFromEvent(event);
231
214
    _onmouseout: function(event)
232
215
    {
233
216
        var nodeUnderMouse = document.elementFromPoint(event.pageX, event.pageY);
234
 
        if (nodeUnderMouse.isDescendant(this.element))
 
217
        if (nodeUnderMouse && nodeUnderMouse.isDescendant(this.element))
235
218
            return;
236
219
 
237
220
        if (this._previousHoveredElement) {
247
230
 
248
231
WebInspector.ElementsTreeElement = function(node)
249
232
{
250
 
    var hasChildren = node.contentDocument || (Preferences.ignoreWhitespace ? (firstChildSkippingWhitespace.call(node) ? true : false) : node.hasChildNodes());
 
233
    var hasChildren = Preferences.ignoreWhitespace ? (firstChildSkippingWhitespace.call(node) ? true : false) : node.hasChildNodes();
251
234
    var titleInfo = nodeTitleInfo.call(node, hasChildren, WebInspector.linkifyURL);
252
235
 
253
236
    if (titleInfo.hasChildren) 
255
238
 
256
239
    // The title will be updated in onattach.
257
240
    TreeElement.call(this, "", node, titleInfo.hasChildren);
 
241
 
 
242
    if (this.representedObject.nodeType == Node.ELEMENT_NODE)
 
243
        this._canAddAttributes = true;
258
244
}
259
245
 
260
246
WebInspector.ElementsTreeElement.prototype = {
296
282
                this.listItemElement.addStyleClass("hovered");
297
283
            } else
298
284
                this.listItemElement.removeStyleClass("hovered");
299
 
        }
300
 
    },
301
 
 
 
285
            if (this._canAddAttributes)
 
286
                this.toggleNewAttributeButton();
 
287
        }
 
288
    },
 
289
 
 
290
    toggleNewAttributeButton: function()
 
291
    {
 
292
        function removeWhenEditing(event)
 
293
        {
 
294
            if (this._addAttributeElement && this._addAttributeElement.parentNode)
 
295
                this._addAttributeElement.parentNode.removeChild(this._addAttributeElement);
 
296
            delete this._addAttributeElement;
 
297
        }
 
298
 
 
299
        if (!this._addAttributeElement && this._hovered && !this._editing) {
 
300
            var span = document.createElement("span");
 
301
            span.className = "add-attribute";
 
302
            span.textContent = "\u2026";
 
303
            span.addEventListener("dblclick", removeWhenEditing.bind(this), false);
 
304
            this._addAttributeElement = span;
 
305
 
 
306
            var tag = this.listItemElement.getElementsByClassName("webkit-html-tag")[0];
 
307
            this._insertInLastAttributePosition(tag, span);
 
308
        } else if (!this._hovered && this._addAttributeElement) {
 
309
            if (this._addAttributeElement.parentNode)
 
310
                this._addAttributeElement.parentNode.removeChild(this._addAttributeElement);
 
311
            delete this._addAttributeElement;
 
312
        }
 
313
    },
 
314
    
302
315
    updateSelection: function()
303
316
    {
304
317
        var listItemElement = this.listItemElement;
356
369
 
357
370
        this.updateChildren();
358
371
    },
359
 
 
 
372
    
360
373
    updateChildren: function(fullRefresh)
361
374
    {
 
375
        WebInspector.domAgent.getChildNodesAsync(this.representedObject, this._updateChildren.bind(this, fullRefresh));
 
376
    },
 
377
 
 
378
    _updateChildren: function(fullRefresh)
 
379
    {
362
380
        if (fullRefresh) {
363
381
            var selectedTreeElement = this.treeOutline.selectedTreeElement;
364
382
            if (selectedTreeElement && selectedTreeElement.hasAncestor(this))
375
393
            var child = (Preferences.ignoreWhitespace ? firstChildSkippingWhitespace.call(node) : node.firstChild);
376
394
            while (child) {
377
395
                var currentTreeElement = treeElement.children[treeChildIndex];
378
 
                if (!currentTreeElement || !objectsAreSame(currentTreeElement.representedObject, child)) {
 
396
                if (!currentTreeElement || currentTreeElement.representedObject !== child) {
379
397
                    // Find any existing element that is later in the children list.
380
398
                    var existingTreeElement = null;
381
399
                    for (var i = (treeChildIndex + 1); i < treeElement.children.length; ++i) {
382
 
                        if (objectsAreSame(treeElement.children[i].representedObject, child)) {
 
400
                        if (treeElement.children[i].representedObject === child) {
383
401
                            existingTreeElement = treeElement.children[i];
384
402
                            break;
385
403
                        }
414
432
            var currentNode = currentChild.representedObject;
415
433
            var currentParentNode = currentNode.parentNode;
416
434
 
417
 
            if (objectsAreSame(currentParentNode, this.representedObject))
418
 
                continue;
419
 
            if (this.representedObject.contentDocument && objectsAreSame(currentParentNode, this.representedObject.contentDocument))
 
435
            if (currentParentNode === this.representedObject)
420
436
                continue;
421
437
 
422
438
            var selectedTreeElement = this.treeOutline.selectedTreeElement;
424
440
                this.select();
425
441
 
426
442
            this.removeChildAtIndex(i);
427
 
 
428
 
            if (this.treeOutline.panel && currentNode.contentDocument)
429
 
                this.treeOutline.panel.unregisterMutationEventListeners(currentNode.contentDocument.defaultView);
430
443
        }
431
444
 
432
 
        if (this.representedObject.contentDocument)
433
 
            updateChildrenOfNode(this.representedObject.contentDocument);
434
445
        updateChildrenOfNode(this.representedObject);
435
446
 
436
447
        var lastChild = this.children[this.children.length - 1];
446
457
    onexpand: function()
447
458
    {
448
459
        this.treeOutline.updateSelection();
449
 
 
450
 
        if (this.treeOutline.panel && this.representedObject.contentDocument)
451
 
            this.treeOutline.panel.registerMutationEventListeners(this.representedObject.contentDocument.defaultView);
452
460
    },
453
461
 
454
462
    oncollapse: function()
483
491
        if (this._editing)
484
492
            return;
485
493
 
486
 
        if (this._startEditing(event))
 
494
        if (this._startEditing(event, treeElement))
487
495
            return;
488
496
 
489
497
        if (this.treeOutline.panel) {
490
 
            this.treeOutline.rootDOMNode = this.parent.representedObject;
 
498
            this.treeOutline.rootDOMNode = this.representedObject.parentNode;
491
499
            this.treeOutline.focusedDOMNode = this.representedObject;
492
500
        }
493
501
 
495
503
            this.expand();
496
504
    },
497
505
 
498
 
    _startEditing: function(event)
 
506
    _insertInLastAttributePosition: function(tag, node)
 
507
    {
 
508
        if (tag.getElementsByClassName("webkit-html-attribute").length > 0)
 
509
            tag.insertBefore(node, tag.lastChild);
 
510
        else {
 
511
            var nodeName = tag.textContent.match(/^<(.*?)>$/)[1];
 
512
            tag.textContent = '';
 
513
            tag.appendChild(document.createTextNode('<'+nodeName));
 
514
            tag.appendChild(node);
 
515
            tag.appendChild(document.createTextNode('>'));
 
516
        }
 
517
    },
 
518
 
 
519
    _startEditing: function(event, treeElement)
499
520
    {
500
521
        if (this.treeOutline.focusedDOMNode != this.representedObject)
501
522
            return;
509
530
 
510
531
        var attribute = event.target.enclosingNodeOrSelfWithClass("webkit-html-attribute");
511
532
        if (attribute)
512
 
            return this._startEditingAttribute(attribute, event);
 
533
            return this._startEditingAttribute(attribute, event.target);
 
534
 
 
535
        var newAttribute = event.target.enclosingNodeOrSelfWithClass("add-attribute");
 
536
        if (newAttribute)
 
537
            return this._addNewAttribute(treeElement.listItemElement);
513
538
 
514
539
        return false;
515
540
    },
516
541
 
517
 
    _startEditingAttribute: function(attribute, event)
 
542
    _addNewAttribute: function(listItemElement)
 
543
    {
 
544
        var attr = document.createElement("span");
 
545
        attr.className = "webkit-html-attribute";
 
546
        attr.style.marginLeft = "2px"; // overrides the .editing margin rule
 
547
        attr.style.marginRight = "2px"; // overrides the .editing margin rule
 
548
        var name = document.createElement("span");
 
549
        name.className = "webkit-html-attribute-name new-attribute";
 
550
        name.textContent = " ";
 
551
        var value = document.createElement("span");
 
552
        value.className = "webkit-html-attribute-value";
 
553
        attr.appendChild(name);
 
554
        attr.appendChild(value);
 
555
 
 
556
        var tag = listItemElement.getElementsByClassName("webkit-html-tag")[0];
 
557
        this._insertInLastAttributePosition(tag, attr);
 
558
        return this._startEditingAttribute(attr, attr);
 
559
    },
 
560
 
 
561
    _triggerEditAttribute: function(attributeName)
 
562
    {
 
563
        var attributeElements = this.listItemElement.getElementsByClassName("webkit-html-attribute-name");
 
564
        for (var i = 0, len = attributeElements.length; i < len; ++i) {
 
565
            if (attributeElements[i].textContent === attributeName) {
 
566
                for (var elem = attributeElements[i].nextSibling; elem; elem = elem.nextSibling) {
 
567
                    if (elem.nodeType !== Node.ELEMENT_NODE)
 
568
                        continue;
 
569
 
 
570
                    if (elem.hasStyleClass("webkit-html-attribute-value"))
 
571
                        return this._startEditingAttribute(attributeElements[i].parentNode, elem);
 
572
                }
 
573
            }
 
574
        }
 
575
    },
 
576
 
 
577
    _startEditingAttribute: function(attribute, elementForSelection)
518
578
    {
519
579
        if (WebInspector.isBeingEdited(attribute))
520
580
            return true;
545
605
        this._editing = true;
546
606
 
547
607
        WebInspector.startEditing(attribute, this._attributeEditingCommitted.bind(this), this._editingCancelled.bind(this), attributeName);
548
 
        window.getSelection().setBaseAndExtent(event.target, 0, event.target, 1);
 
608
        window.getSelection().setBaseAndExtent(elementForSelection, 0, elementForSelection, 1);
549
609
 
550
610
        return true;
551
611
    },
563
623
        return true;
564
624
    },
565
625
 
566
 
    _attributeEditingCommitted: function(element, newText, oldText, attributeName)
 
626
    _attributeEditingCommitted: function(element, newText, oldText, attributeName, moveDirection)
567
627
    {
568
628
        delete this._editing;
569
629
 
 
630
        // Before we do anything, determine where we should move
 
631
        // next based on the current element's settings
 
632
        var moveToAttribute;
 
633
        var newAttribute;
 
634
        if (moveDirection) {
 
635
            var found = false;
 
636
            var attributes = this.representedObject.attributes;
 
637
            for (var i = 0, len = attributes.length; i < len; ++i) {
 
638
                if (attributes[i].name === attributeName) {
 
639
                    found = true;
 
640
                    if (moveDirection === "backward" && i > 0)
 
641
                        moveToAttribute = attributes[i - 1].name;
 
642
                    else if (moveDirection === "forward" && i < attributes.length - 1)
 
643
                        moveToAttribute = attributes[i + 1].name;
 
644
                    else if (moveDirection === "forward" && i === attributes.length - 1)
 
645
                        newAttribute = true;
 
646
                }
 
647
            }
 
648
 
 
649
            if (!found && moveDirection === "backward")
 
650
                moveToAttribute = attributes[attributes.length - 1].name;
 
651
            else if (!found && moveDirection === "forward" && !/^\s*$/.test(newText))
 
652
                newAttribute = true;
 
653
        }
 
654
 
 
655
        function moveToNextAttributeIfNeeded() {
 
656
            if (moveToAttribute)
 
657
                this._triggerEditAttribute(moveToAttribute);
 
658
            else if (newAttribute)
 
659
                this._addNewAttribute(this.listItemElement);
 
660
        }
 
661
 
570
662
        var parseContainerElement = document.createElement("span");
571
663
        parseContainerElement.innerHTML = "<span " + newText + "></span>";
572
664
        var parseElement = parseContainerElement.firstChild;
573
 
        if (!parseElement || !parseElement.hasAttributes()) {
574
 
            editingCancelled(element, context);
 
665
 
 
666
        if (!parseElement) {
 
667
            this._editingCancelled(element, attributeName);
 
668
            moveToNextAttributeIfNeeded.call(this);
 
669
            return;
 
670
        }
 
671
 
 
672
        if (!parseElement.hasAttributes()) {
 
673
            this.representedObject.removeAttribute(attributeName);
 
674
            this._updateTitle();
 
675
            moveToNextAttributeIfNeeded.call(this);
575
676
            return;
576
677
        }
577
678
 
579
680
        for (var i = 0; i < parseElement.attributes.length; ++i) {
580
681
            var attr = parseElement.attributes[i];
581
682
            foundOriginalAttribute = foundOriginalAttribute || attr.name === attributeName;
582
 
            InspectorController.inspectedWindow().Element.prototype.setAttribute.call(this.representedObject, attr.name, attr.value);
 
683
            try {
 
684
                this.representedObject.setAttribute(attr.name, attr.value);
 
685
            } catch(e) {} // ignore invalid attribute (innerHTML doesn't throw errors, but this can)
583
686
        }
584
687
 
585
688
        if (!foundOriginalAttribute)
586
 
            InspectorController.inspectedWindow().Element.prototype.removeAttribute.call(this.representedObject, attributeName);
 
689
            this.representedObject.removeAttribute(attributeName);
587
690
 
588
691
        this._updateTitle();
589
692
 
590
693
        this.treeOutline.focusedNodeChanged(true);
 
694
 
 
695
        moveToNextAttributeIfNeeded.call(this);
591
696
    },
592
697
 
593
698
    _textNodeEditingCommitted: function(element, newText)