我正在编写一个GUI扩展,它基本上将选定的文本包装在特定的DIV中。我的文本被封装了DIV,但是有点块...
当用户没有选择特定文本时,我假设其意图是包装最近的HTML元素
htmlSelectedNode = target.editor.getSelectedHTMLElement()
这一切似乎都运行正常,我将HTML元素传递给我的扩展程序。经过一些操作后,我然后应用HTML,但是它在前一个元素中注入了新的HTML - 而不是替换它......
是否有可能“选择”HTML元素 - 我可以看到.focus()
和.setCapture()
但这些似乎没有做到这一点 - 我想理想的是使用与从功能区栏上的“当前元素”下拉列表中选择元素时应用的功能相同,但我没有成功找到与此下拉列表关联的onclick / select方法。
只是为了澄清......举个例子......
如果文字是
<div class="notrelevant"><p>test1</p><p>this is an example</p></div>
并且用户将光标插入'和'中的i和s之间我希望GUI预先选择最近的HTML元素 - 在这种情况下,最终结果将是......
<div class="notrelevant"><p>test1</p><div class="INJECTED_CORRECTLY"><p>this is an example</p></div></div>
修改 的 为了完整性,我已经包含了我用来(重新)将HTML注入RTF的提交事件(虽然我认为在这一点上操纵选择并且更愿意'选择'文本是没有意义的以上使用更“标准”的现有Tridion功能......)
$evt.addEventHandler(popup, "submit",
function DateHighlighter$execute$onPopupSubmitted(event) {
var el = event.data.html;
if (el) {
if (htmlSelectedNode != null) {
var lDocument = htmlSelectedNode.ownerDocument;
var lTempContainer = lDocument.createElement("span");
try {
lTempContainer.innerHTML = el || "";
}
catch (err) {
//assigning a value to innerHTML can be sensitive to browser but the error is fine to be ignored
}
var parentNode = htmlSelectedNode.parentNode;
parentNode.replaceChild(lTempContainer, htmlSelectedNode);
//Move to the new element
var lTextRange = $dom.createTextRange(lTempContainer);
$dom.moveRangeToElement(lTextRange, lTempContainer);
//Select and remove the temporary element
$dom.selectRange(lTextRange, $dom.getSelection(lDocument));
$dom.removeNode(lTempContainer, false);
}
else {
// Insert new created element (DIV)
target.editor.applyHTML(el);
}
}
else {
//TODO: test this - it's likely not required
if (htmlSelectedNode.attributes["class"] != null)
htmlSelectedNode.removeAttribute("class");
//TODO: test this - it's likely not required
if (htmlSelectedNode.attributes["ondblclick"] != null)
htmlSelectedNode.removeAttribute("ondblclick");
//TODO: the node isn't removed - leaves the empty <div>...
// - delete the node and then apply the node2.outerHTML? - or follow parentnode pattern above!
var htmlSelectedNode2 = htmlSelectedNode.innerHTML;
htmlSelectedNode = htmlSelectedNode2;
}
//Refreshes the Design view
target.editor.setCurrentView("Source");
target.editor.setCurrentView("RichText");
target.item.closeActivePopup();
});
$evt.addEventHandler(popup, "unload", DateHighlighter$execute$onPopupCanceled);
答案 0 :(得分:7)
所以我找到了CurrentElement
选项,看到了明显的setSelectedHTMLElement
。不确定我是如何错过它但是这里的唉是......正如评论所述 - 确保方法可用(如果用户选择的文本字符串不等同于HTMLElement setSelectedHTMLElement
方法将失败并删除我们用户选择(因此意味着GUI扩展.aspx不能(重新)注入新的HTML ...
//if there's no tagname then the setSelected will fail and remove the (non-element based) select the user has done
if (htmlSelectedNode.nodeName && htmlSelectedNode.nodeName != '#text') {
//unlikely to get #text here as it's the htmlSelectedNode.commonAncestorContainer.nodeName
$log.message(logt + 'selecting the htmlSelectedNode.nodeName:' + htmlSelectedNode.nodeName);
target.editor.setSelectedHTMLElement(htmlSelectedNode);
}
else {
$log.message(logt + 'no htmlSelectedNode.nodeName - user probably selected incomplete element:');
}
答案 1 :(得分:2)
这是一个棘手的问题。您将需要检查所有可能的方案。回到一年前,我们必须实现自定义“超链接”功能作为GUI扩展。问题是一样的:“我怎么知道选择了什么?”,“如果用户选择文本和一半的html节点怎么办?” “如果选择只是文字怎么办?”基本上你面临同样的问题。
如果我理解正确,你想用给定的(自定义)div包装所选文本,对吧?你需要考虑的事情(如果你还没有)是:“如果用户选择已经用自定义div包装的文本会发生什么?”,“如果他选择包含自定义div的文本,该怎么办?之后或之前的一大块文字?“
好吧,正如我前面提到的那样并不容易,或者至少不是直截了当。以下是我们所做的一些提示,在我们的例子中,我们必须使用Hyperlink标签而不是div来包装文本,但是从“获取/设置选择的html”的角度来看,它应该有所帮助:
1st:初始化一个元素节点并获取所选的html:
var element = null;
var htmlSelectedNode = target.editor.getSelectedHTMLElement() || {};
第二:检查那里到底是什么:
if (htmlSelectedNode != null && htmlSelectedNode.tagName != null && htmlSelectedNode.tagName == "A") { //In your case you might wanna check if it is a div, instead
...
...
}
注意:在我们的例子中,我们还必须检查图像和span标签,因为anchor元素会有所不同,因为我们需要从那些信息中获取一些信息。
3rd:如果所选文本是元素(未选择额外文本),则设置元素var
element = htmlSelectedNode;
var selectedText = "";
// Chrome & Firefox
if (htmlSelectedNode != null && htmlSelectedNode.startContainer != null && htmlSelectedNode.startOffset != null) {
selectedText = htmlSelectedNode.toString();
}
// IE Range
else if (htmlSelectedNode != null && htmlSelectedNode.htmlText != null && htmlSelectedNode.text != null) {
selectedText = htmlSelectedNode.text;
}
// IE DIV
else if (htmlSelectedNode != null && (htmlSelectedNode.tagName == "DIV" || htmlSelectedNode.tagName == "P") && htmlSelectedNode.innerText != null) {
selectedText = htmlSelectedNode.innerText;
}
4rd:如果htmlSelectedNode在之前或之后包含节点加原始文本,我们使用范围(进一步阅读),考虑到不同的浏览器行为:
嗯,这里的示例并没有真正解决您的问题,但我希望他们能给您一些关于如何检查xhtml内容的提示。基本上你需要注意使选择成为有效的xhtml元素。
这里有更多关于当元素已经包含链接标记时我们如何处理xhtml的例子:
// If there is a link, delete it
if (htmlSelectedNode != null) {
var lDocument = htmlSelectedNode.ownerDocument;
var lTempContainer = lDocument.createElement("span");
try {
lTempContainer.innerHTML = el || "";
}
catch (err) {
//assigning a value to innerHTML might fail -> ignore it then
}
var parentNode = htmlSelectedNode.parentNode;
parentNode.replaceChild(lTempContainer, htmlSelectedNode);
//move to new element
var lTextRange = $dom.createTextRange(lTempContainer);
$dom.moveRangeToElement(lTextRange, lTempContainer);
//select and remove temp element
$dom.selectRange(lTextRange, $dom.getSelection(lDocument));
$dom.removeNode(lTempContainer, false);
}
如何将HTML设置回RTF并刷新源/设计选项卡:
// Insert new created link
target.editor.applyHTML(el); //el == element
//Refreshes the Design view
target.editor.setCurrentView("Source");
target.editor.setCurrentView("RichText");
同样,我知道这不是解决您问题的方法,但我认为您可以使用一些示例来尝试新方法。如果你需要进一步的帮助,请分享整个JS文件,或者至少是_execute()方法(我假设你有代码,对吗?)
此致