/**
* {@link XMLEditor} part used to display the full path of explicitly or
* implicitly selected node.
*/
class NodePath extends HTMLElement {
constructor() {
super();
this._xmlEditor = null;
this._onNodeClicked = this.onNodeClicked.bind(this);
}
// -----------------------------------------------------------------------
// Event handlers
// -----------------------------------------------------------------------
onNodeClicked(event) {
XUI.Util.consumeEvent(event);
if (this._xmlEditor === null || // Should not happen.
(event.type === "click" && event.detail !== 1)) { // Click count.
return;
}
let docView = this._xmlEditor.documentView;
let uid = event.target.getAttribute("data-uid");
if (uid) {
let view = docView.getNodeView(uid, /*reportError*/ false);
if (view !== null) {
let selectItem;
if (!Object.is(docView.selected, view) ||
docView.selected2 !== null) {
selectItem = docView.selectNode(view, /*show*/ true);
} else {
selectItem = Promise.resolve(true);
}
if (event.type === "contextmenu") {
const where = event.target.getBoundingClientRect();
selectItem.then((selected) => {
if (selected) {
let cmd = docView.getCommand("contextualMenu");
if (cmd) {
cmd.showContextualMenu(docView, where.left,
where.bottom);
}
}
});
} else { // It's a click event.
if (event.shiftKey) {
selectItem.then((selected) => {
if (selected) {
docView.executeCommand(EXECUTE_NORMAL,
"selectNode",
"children");
}
});
}
}
}
}
}
// -----------------------------------------------------------------------
// Used by XMLEditor
// -----------------------------------------------------------------------
set xmlEditor(editor) {
this._xmlEditor = editor;
}
nodePathChanged(items) {
XUI.Util.removeAllChildren(this);
if (items === null) {
// No document is being edited.
return;
}
this.appendChild(this.createDocumentSegment(this._xmlEditor));
let seg = null;
const count = items.length;
for (let i = 0; i < count; i += 3) {
let uid = items[i];
let tag = items[i+1];
let info = items[i+2];
this.appendChild(this.createSegmentSeparator());
seg = this.createNodeSegment(uid, tag, info);
this.appendChild(seg);
}
if (seg !== null) {
seg.scrollIntoView({ block: "center", inline: "end" });
}
}
createDocumentSegment(editor) {
let seg = document.createElement("span");
seg.textContent = XUI.StockIcon["doc"];
this.updateDocumentSegment(seg, editor);
return seg;
}
updateDocumentSegment(seg, editor) {
let classNames = "xui-small-icon xxe-ndpth-doc";
let tooltip = "Location:\n" + editor.documentURI;
if (editor.readOnlyDocument) {
classNames += " xxe-ndpth-doc-ro";
tooltip += "\n(read-only)";
} else if (editor.saveNeeded) {
classNames += " xxe-ndpth-doc-mod";
tooltip += "\n(modified)";
}
if (editor.configurationName !== null) {
tooltip += "\nConfiguration: " + editor.configurationName;
}
if (editor.diffSupport >= 1) {
tooltip += "\nComparison of revisions: enabled.";
if (editor.diffSupport >= 2) {
tooltip += " All revisions stored in the document.";
}
}
seg.className = classNames;
seg.setAttribute("title", tooltip);
}
createSegmentSeparator() {
let seg = document.createElement("span");
seg.className = "xui-small-icon xxe-ndpth-separ";
seg.textContent = XUI.StockIcon["right-open"];
return seg;
}
createNodeSegment(uid, tag, info) {
let classNames = "xxe-ndpth-node";
let tooltip = tag;
if (info.length > 0) {
const lines = info.split('\n');
const lineCount = lines.length;
if (lineCount > 0) {
let flags = lines[0];
if (flags.length > 0) {
if (flags.indexOf("sel") >= 0) {
classNames += " xxe-ndpth-node-sel";
}
if (flags.indexOf("ro") >= 0) {
classNames += " xxe-ndpth-node-ro";
}
}
if (lineCount > 1) {
// Element attributes.
for (let i = 1; i < lineCount; i += 2) {
let name = lines[i];
let value = lines[i+1];
tooltip += "\n\u2022 ";
tooltip += name;
tooltip += "=";
let quote = (value.indexOf("\"") >= 0)? "'" : "\"";
tooltip += quote;
tooltip += value;
tooltip += quote;
}
}
}
}
let seg = document.createElement("span");
seg.setAttribute("data-uid", uid);
seg.className = classNames;
tooltip += `\n\n\
-\u00A0Click to select.`;
if (!tag.startsWith("#")) {
tooltip += `\n\
-\u00A0Shift-click to select child nodes.`;
}
tooltip += `\n\
-\u00A0Right-click to display contextual menu.`;
seg.setAttribute("title", tooltip);
if (tag.length > 40) {
tag = tag.substring(0, 39) + "\u2026";
}
seg.textContent = tag;
seg.addEventListener("click", this._onNodeClicked);
seg.addEventListener("contextmenu", this._onNodeClicked);
return seg;
}
documentStateChanged() {
let seg = this.firstElementChild;
if (seg !== null) {
this.updateDocumentSegment(seg, this._xmlEditor);
}
}
}
window.customElements.define("xxe-node-path", NodePath);