htmlarea.js
来自「Hippo CMS是一个以信息为中心的开源内容管理系统。Hippo CMS目标是」· JavaScript 代码 · 共 2,000 行 · 第 1/5 页
JS
2,000 行
}
}
break;
case "htmlmode": btn.state("active", text); break;
case "lefttoright":
case "righttoleft":
var el = this.getParentElement();
while (el && !HTMLArea.isBlockElement(el))
el = el.parentNode;
if (el)
btn.state("active", (el.style.direction == ((cmd == "righttoleft") ? "rtl" : "ltr")));
break;
default:
try {
btn.state("active", (!text && doc.queryCommandState(cmd)));
} catch (e) {}
}
}
// take undo snapshots
if (this._customUndo && !this._timerUndo) {
this._undoTakeSnapshot();
var editor = this;
this._timerUndo = setTimeout(function() {
editor._timerUndo = null;
}, this.config.undoTimeout);
}
// check if any plugins have registered refresh handlers
for (var i in this.plugins) {
var plugin = this.plugins[i].instance;
if (typeof plugin.onUpdateToolbar == "function")
plugin.onUpdateToolbar();
}
};
/** Returns a node after which we can insert other nodes, in the current
* selection. The selection is removed. It splits a text node, if needed.
*/
HTMLArea.prototype.insertNodeAtSelection = function(toBeInserted) {
if (!HTMLArea.is_ie) {
var sel = this._getSelection();
var range = this._createRange(sel);
// remove the current selection
sel.removeAllRanges();
range.deleteContents();
var node = range.startContainer;
var pos = range.startOffset;
switch (node.nodeType) {
case 3: // Node.TEXT_NODE
// we have to split it at the caret position.
if (toBeInserted.nodeType == 3) {
// do optimized insertion
node.insertData(pos, toBeInserted.data);
range = this._createRange();
range.setEnd(node, pos + toBeInserted.length);
range.setStart(node, pos + toBeInserted.length);
sel.addRange(range);
} else {
node = node.splitText(pos);
var selnode = toBeInserted;
if (toBeInserted.nodeType == 11 /* Node.DOCUMENT_FRAGMENT_NODE */) {
selnode = selnode.firstChild;
}
node.parentNode.insertBefore(toBeInserted, node);
this.selectNodeContents(selnode);
this.updateToolbar();
}
break;
case 1: // Node.ELEMENT_NODE
var selnode = toBeInserted;
if (toBeInserted.nodeType == 11 /* Node.DOCUMENT_FRAGMENT_NODE */) {
selnode = selnode.firstChild;
}
node.insertBefore(toBeInserted, node.childNodes[pos]);
this.selectNodeContents(selnode);
this.updateToolbar();
break;
}
} else {
return null; // this function not yet used for IE <FIXME>
}
};
// Returns the deepest node that contains both endpoints of the selection.
HTMLArea.prototype.getParentElement = function() {
var sel = this._getSelection();
var range = this._createRange(sel);
if (HTMLArea.is_ie) {
switch (sel.type) {
case "Text":
case "None":
// It seems that even for selection of type "None",
// there _is_ a parent element and it's value is not
// only correct, but very important to us. MSIE is
// certainly the buggiest browser in the world and I
// wonder, God, how can Earth stand it?
return range.parentElement();
case "Control":
return range.item(0);
default:
return this._doc.body;
}
} else try {
var p = range.commonAncestorContainer;
if (!range.collapsed && range.startContainer == range.endContainer &&
range.startOffset - range.endOffset <= 1 && range.startContainer.hasChildNodes())
p = range.startContainer.childNodes[range.startOffset];
/*
alert(range.startContainer + ":" + range.startOffset + "\n" +
range.endContainer + ":" + range.endOffset);
*/
while (p.nodeType == 3) {
p = p.parentNode;
}
return p;
} catch (e) {
return null;
}
};
// Returns an array with all the ancestor nodes of the selection.
HTMLArea.prototype.getAllAncestors = function() {
var p = this.getParentElement();
var a = [];
while (p && (p.nodeType == 1) && (p.tagName.toLowerCase() != 'body')) {
a.push(p);
p = p.parentNode;
}
a.push(this._doc.body);
return a;
};
// Selects the contents inside the given node
HTMLArea.prototype.selectNodeContents = function(node, pos) {
this.focusEditor();
this.forceRedraw();
var range;
var collapsed = (typeof pos != "undefined");
if (HTMLArea.is_ie) {
range = this._doc.body.createTextRange();
range.moveToElementText(node);
(collapsed) && range.collapse(pos);
range.select();
} else {
var sel = this._getSelection();
range = this._doc.createRange();
range.selectNodeContents(node);
(collapsed) && range.collapse(pos);
sel.removeAllRanges();
sel.addRange(range);
}
};
/** Call this function to insert HTML code at the current position. It deletes
* the selection, if any.
*/
HTMLArea.prototype.insertHTML = function(html) {
var sel = this._getSelection();
var range = this._createRange(sel);
if (HTMLArea.is_ie) {
range.pasteHTML(html);
} else {
// construct a new document fragment with the given HTML
var fragment = this._doc.createDocumentFragment();
var div = this._doc.createElement("div");
div.innerHTML = html;
while (div.firstChild) {
// the following call also removes the node from div
fragment.appendChild(div.firstChild);
}
// this also removes the selection
var node = this.insertNodeAtSelection(fragment);
}
};
/**
* Call this function to surround the existing HTML code in the selection with
* your tags. FIXME: buggy! This function will be deprecated "soon".
*/
HTMLArea.prototype.surroundHTML = function(startTag, endTag) {
var html = this.getSelectedHTML();
// the following also deletes the selection
this.insertHTML(startTag + html + endTag);
};
/// Retrieve the selected block
HTMLArea.prototype.getSelectedHTML = function() {
var sel = this._getSelection();
var range = this._createRange(sel);
var existing = null;
if (HTMLArea.is_ie) {
existing = range.htmlText;
} else {
existing = HTMLArea.getHTML(range.cloneContents(), false, this);
}
return existing;
};
/// Return true if we have some selection
HTMLArea.prototype.hasSelectedText = function() {
// FIXME: come _on_ mishoo, you can do better than this ;-)
return this.getSelectedHTML() != '';
};
//// Added by JR for special paste without style.
HTMLArea.prototype._pastespecial = function() {
if(window.clipboardData.getData('Text')!=null)
{
var cbText=window.clipboardData.getData('Text');
//alert(cbText);
var cbText2 = cbText.toString();
cbText2 = cbText2.replace(/&/ig, "&");
cbText2 = cbText2.replace(/</ig, "<");
cbText2 = cbText2.replace(/>/ig, ">");
cbText2 = cbText2.replace(/\x22/ig, """);
cbText2 = cbText2.replace(/\n/g,'<BR />');
//alert(cbText2);
this.insertHTML(cbText2);
}
else
{
//alert('empty');
}
}
HTMLArea.prototype._createLink = function(link) {
var editor = this;
var outparam = null;
if (typeof link == "undefined") {
link = this.getParentElement();
if (link && !/^a$/i.test(link.tagName))
link = null;
}
if (link) outparam = {
f_href : HTMLArea.is_ie ? editor.stripBaseURL(link.href) : link.getAttribute("href"),
f_title : link.title,
f_target : link.target,
f_link_lookup : this.config.lookup_link
}; else
outparam = {
f_href : '',
f_title : '',
f_target:'',
f_link_lookup : this.config.lookup_link
};
this._popupDialog("link.html", function(param) {
if (!param)
return false;
var a = link;
if (!a) {
editor._doc.execCommand("createlink", false, param.f_href);
a = editor.getParentElement();
var sel = editor._getSelection();
var range = editor._createRange(sel);
if (!HTMLArea.is_ie) {
a = range.startContainer;
if (!/^a$/i.test(a.tagName))
a = a.nextSibling;
}
} else a.href = param.f_href.trim();
if (!/^a$/i.test(a.tagName))
return false;
a.target = param.f_target.trim();
a.title = param.f_title.trim();
editor.selectNodeContents(a);
editor.updateToolbar();
}, outparam);
};
HTMLArea.prototype._createdocLink = function(link) {
var editor = this;
var outparam = null;
if (typeof link == "undefined") {
link = this.getParentElement();
if (link && !/^a$/i.test(link.tagName))
link = null;
}
if (link) outparam = {
f_href : HTMLArea.is_ie ? editor.stripBaseURL(link.href) : link.getAttribute("href"),
f_title : link.title,
f_target : link.target
};
this._popupDialog("doclink.html", function(param) {
if (!param)
return false;
var a = link;
if (!a) {
editor._doc.execCommand("createlink", false, param.f_href);
a = editor.getParentElement();
var sel = editor._getSelection();
var range = editor._createRange(sel);
if (!HTMLArea.is_ie) {
a = range.startContainer;
if (!/^a$/i.test(a.tagName))
a = a.nextSibling;
}
} else a.href = param.f_href.trim();
if (!/^a$/i.test(a.tagName))
return false;
a.target = param.f_target.trim();
a.title = param.f_title.trim();
editor.selectNodeContents(a);
editor.updateToolbar();
}, outparam);
};
// Called when the user clicks on "InsertImage" button. If an image is already
// there, it will just modify it's properties.
HTMLArea.prototype._insertImage = function(image) {
var editor = this; // for nested functions
var outparam = null;
if (typeof image == "undefined") {
image = this.getParentElement();
if (image && !/^img$/i.test(image.tagName))
image = null;
}
if (image) outparam = {
f_url : HTMLArea.is_ie ? editor.stripBaseURL(image.src) : image.getAttribute("src"),
f_alt : image.alt,
f_border : image.border,
f_align : image.align,
f_vert : image.vspace,
f_horiz : image.hspace
};
this._popupDialog("insert_image.html", function(param) {
if (!param) { // user must have pressed Cancel
return false;
}
var img = image;
if (!img) {
var sel = editor._getSelection();
var range = editor._createRange(sel);
editor._doc.execCommand("insertimage", false, param.f_url);
if (HTMLArea.is_ie) {
img = range.parentElement();
// wonder if this works...
if (img.tagName.toLowerCase() != "img") {
img = img.previousSibling;
}
} else {
img = range.startContainer.previousSibling;
}
} else {
img.src = param.f_url;
}
for (field in param) {
var value = param[field];
switch (field) {
case "f_alt" : img.alt = value; break;
case "f_border" : img.border = parseInt(value || "0"); break;
case "f_align" : img.align = value; break;
case "f_vert" : img.vspace = parseInt(value || "0"); break;
case "f_horiz" : img.hspace = parseInt(value || "0"); break;
}
}
}, outparam);
};
// Called when the user clicks the Insert Table button
HTMLArea.prototype._insertTable = function() {
var sel = this._getSelection();
var range = this._createRange(sel);
var editor = this; // for nested functions
this._popupDialog("insert_table.html", function(param) {
if (!param) { // user must have pressed Cancel
return false;
}
var doc = editor._doc;
// create the table element
var table = doc.createElement("table");
// assign the given arguments
for (var field in param) {
var value = param[field];
if (!value) {
continue;
}
switch (field) {
case "f_width" : table.style.width = value + param["f_unit"]; break;
case "f_align" : table.align = value; break;
case "f_border" : table.border = parseInt(value); break;
case "f_spacing" : table.cellspacing = parseInt(value); break;
case "f_padding" : table.cellpadding = parseInt(value); break;
}
}
var tbody = doc.createElement("tbody");
table.appendChild(tbody);
for (var i = 0; i < param["f_rows"]; ++i) {
var tr = doc.createElement("tr");
tbody.appendChild(tr);
for (var j = 0; j < param["f_cols"]; ++j) {
var td = doc.createElement("td");
tr.appendChild(td);
// Mozilla likes to see something inside the cell.
(HTMLArea.is_gecko) && td.appendChild(doc.createElement("br"));
}
}
if (HTMLArea.is_ie) {
range.pasteHTML(table.outerHTML);
} else {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?