|
/* This Source Code Form is subject to the terms of the Mozilla Public |
|
* License, v. 2.0. If a copy of the MPL was not distributed with this |
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
|
|
/***************************************************************************** |
|
* DOMNodeViewer -------------------------------------------------------------- |
|
* The default viewer for DOM Nodes |
|
*****************************************************************************/ |
|
|
|
////////////////////////////////////////////////////////////////////////////// |
|
//// Global Constants |
|
|
|
const Cc = Components.classes, |
|
Ci = Components.interfaces; |
|
|
|
XPCOMUtils.defineLazyModuleGetter(this, "Services", "resource://gre/modules/Services.jsm"); |
|
|
|
////////////////////////////////////////////////////////////////////////////// |
|
//// Global Variables |
|
|
|
var viewer; |
|
var gPromptService; |
|
|
|
////////////////////////////////////////////////////////////////////////////// |
|
|
|
window.addEventListener("load", DOMNodeViewer_initialize, false); |
|
|
|
function DOMNodeViewer_initialize() |
|
{ |
|
viewer = new DOMNodeViewer(); |
|
viewer.initialize(parent.FrameExchange.receiveData(window)); |
|
} |
|
|
|
////////////////////////////////////////////////////////////////////////////// |
|
//// DOMNodeViewer Class |
|
|
|
function DOMNodeViewer() // implements inIViewer |
|
{ |
|
this.mObsMan = new ObserverManager(this); |
|
|
|
this.mURL = window.location; |
|
this.mAttrTree = document.getElementById("olListeners"); |
|
this.mAttrGroupBox = document.getElementById("grpAttr"); |
|
|
|
this.mDOMView = new EventListenerView(); |
|
this.mAttrTree.treeBoxObject.view = this.mDOMView; |
|
} |
|
|
|
DOMNodeViewer.prototype = |
|
{ |
|
//////////////////////////////////////////////////////////////////////////// |
|
//// Initialization |
|
|
|
mDOMView: null, |
|
mSubject: null, |
|
mPanel: null, |
|
|
|
get selectedIndex() |
|
{ |
|
return this.mAttrTree.currentIndex; |
|
}, |
|
|
|
/** |
|
* Returns an array of the selected indices |
|
*/ |
|
get selectedIndices() |
|
{ |
|
var indices = []; |
|
var rangeCount = this.mAttrTree.view.selection.getRangeCount(); |
|
for (var i = 0; i < rangeCount; ++i) { |
|
var start = {}; |
|
var end = {}; |
|
this.mAttrTree.view.selection.getRangeAt(i, start, end); |
|
for (var c = start.value; c <= end.value; ++c) { |
|
indices.push(c); |
|
} |
|
} |
|
return indices; |
|
}, |
|
|
|
/** |
|
* Returns a DOMAttribute from the selected index |
|
*/ |
|
get selectedAttribute() |
|
{ |
|
var index = this.selectedIndex; |
|
return index >= 0 ? |
|
new DOMAttribute(this.mDOMView.getNodeFromRowIndex(index)) : null; |
|
}, |
|
|
|
/** |
|
* Returns an array of DOMAttributes from the selected indices |
|
*/ |
|
get selectedAttributes() |
|
{ |
|
var indices = this.selectedIndices; |
|
var attrs = []; |
|
for (var i = 0; i < indices.length; ++i) { |
|
var idx = this.mDOMView.getNodeFromRowIndex(indices[i]); |
|
attrs.push(new DOMAttribute(idx)); |
|
} |
|
return attrs; |
|
}, |
|
|
|
//////////////////////////////////////////////////////////////////////////// |
|
//// interface inIViewer |
|
|
|
//// attributes |
|
|
|
get uid() |
|
{ |
|
return "eventListeners" |
|
}, |
|
|
|
get pane() |
|
{ |
|
return this.mPanel |
|
}, |
|
|
|
|
|
get selection() |
|
{ |
|
return null |
|
}, |
|
|
|
|
|
get subject() |
|
{ |
|
return this.mSubject |
|
}, |
|
|
|
set subject(aObject) |
|
{ |
|
// the node value's textbox won't fire onchange when we change subjects, so |
|
// let's fire it. this won't do anything if it wasn't actually changed |
|
|
|
this.mSubject = aObject; |
|
|
|
switch (aObject.nodeType) { |
|
// things with useful nodeValues |
|
case Node.TEXT_NODE: |
|
case Node.CDATA_SECTION_NODE: |
|
case Node.COMMENT_NODE: |
|
case Node.PROCESSING_INSTRUCTION_NODE: |
|
this.mDOMView.setTarget(null); |
|
break; |
|
//XXX this view is designed for elements, write a more useful one for |
|
// document nodes, etc. |
|
default: |
|
this.mDOMView.setTarget(aObject); |
|
var bundle = this.pane.panelset.stringBundle; |
|
this.setTextValue("localName", aObject.localName); |
|
this.setTextValue("nodeType", bundle.getString(aObject.nodeType)); |
|
this.setTextValue("namespace", aObject.namespaceURI); |
|
} |
|
|
|
var hideAttributes = aObject.nodeType != Node.ELEMENT_NODE; |
|
this.mAttrGroupBox.hidden = hideAttributes; |
|
if (!hideAttributes && aObject != this.mDOMView.rootNode) { |
|
this.mDOMView.rootNode = aObject; |
|
this.mAttrTree.view.selection.select(-1); |
|
} |
|
|
|
this.mObsMan.dispatchEvent("subjectChange", { subject: aObject }); |
|
}, |
|
|
|
// methods |
|
|
|
initialize: function DNVr_Initialize(aPane) |
|
{ |
|
this.mPanel = aPane; |
|
aPane.notifyViewerReady(this); |
|
}, |
|
|
|
destroy: function DNVr_Destroy() |
|
{ |
|
// the node value's textbox won't fire onchange when we change views, so |
|
// let's fire it. this won't do anything if it wasn't actually changed |
|
}, |
|
|
|
isCommandEnabled: function DNVr_IsCommandEnabled(aCommand) |
|
{ |
|
// NB: This function can be fired before the subject is set. |
|
switch (aCommand) { |
|
case "cmdEditCopy": |
|
return this.selectedAttribute != null; |
|
} |
|
return false; |
|
}, |
|
|
|
getCommand: function DNVr_GetCommand(aCommand) |
|
{ |
|
switch (aCommand) { |
|
case "cmdEditCopy": |
|
return new cmdEditCopy(this.selectedAttributes); |
|
} |
|
return null; |
|
}, |
|
|
|
//////////////////////////////////////////////////////////////////////////// |
|
//// Event Dispatching |
|
|
|
addObserver: function DNVr_AddObserver(aEvent, aObserver) |
|
{ |
|
this.mObsMan.addObserver(aEvent, aObserver); |
|
}, |
|
|
|
removeObserver: function DNVr_RemoveObserver(aEvent, aObserver) |
|
{ |
|
this.mObsMan.removeObserver(aEvent, aObserver); |
|
}, |
|
|
|
//////////////////////////////////////////////////////////////////////////// |
|
//// Uncategorized |
|
|
|
setTextValue: function DNVr_SetTextValue(aName, aText) |
|
{ |
|
var field = document.getElementById("tx_" + aName); |
|
if (field) { |
|
field.value = aText; |
|
} |
|
} |
|
}; |
|
|
|
|
|
function EventListenerView () { |
|
this.rows = []; |
|
this.target = null; |
|
this.treeBox = null; |
|
} |
|
EventListenerView.prototype = { |
|
setTarget: function (aTarget) { |
|
this.target = aTarget; |
|
this.rebuild(); |
|
}, |
|
rebuild: function() { |
|
var oldLength = this.rows.length; |
|
if (!this.target || !this.treeBox) { |
|
if (oldLength > 0 && this.treeBox) { |
|
this.treeBox.rowCountChanged(oldLength, -oldLength); |
|
} |
|
return; |
|
} |
|
|
|
const listenerService = Cc["@mozilla.org/eventlistenerservice;1"].getService(Ci.nsIEventListenerService); |
|
this.rows = [info for ([, info] in Iterator(listenerService.getListenerInfoFor(this.target)))]; |
|
this.treeBox.rowCountChanged(this.rows.length, this.rows.length - oldLength) |
|
this.treeBox.invalidate(); |
|
}, |
|
// implement nsITreeView |
|
setTree: function (treeBox) { |
|
this.treeBox = treeBox; |
|
this.rebuild(); |
|
}, |
|
get rowCount() this.rows.length, |
|
canDrop: function () false, |
|
getLevel: function (aRow) 0, |
|
getCellText: function (aRow, aCol) { |
|
if (!(aRow in this.rows)) |
|
return; |
|
|
|
switch (aCol.element.id) { |
|
case "colType": |
|
return this.rows[aRow].type; |
|
case "colSource": |
|
return this.rows[aRow].toSource(); |
|
case "colCapturing": |
|
return this.rows[aRow].capturing; |
|
} |
|
return ""; |
|
}, |
|
getCellValue: function (aRow, aCol) { |
|
if (!(aRow in this.rows)) |
|
return; |
|
|
|
if (aCol.element.id === "colCapturing") { |
|
return this.rows[aRow].capturing; |
|
} |
|
return ""; |
|
}, |
|
isContainer: function (aRow) false, |
|
isSeparator: function (aRow) false, |
|
isSorted: function (aRow) false, |
|
getImageSrc: function (aRow, aCol) "", |
|
getRowProperties: function (aRow, aProps) {}, |
|
getCellProperties: function (aRow, aCol, aProps) {}, |
|
getColumnProperties: function (aId, aCol, aProps) {}, |
|
}; |