📄 htmlarea.js
字号:
if (height < 0) {
height = 0;
}
iframe.style.height = height + "px";
// the editor including the toolbar now have the same size as the
// original textarea.. which means that we need to reduce that a bit.
textarea.style.width = iframe.style.width;
textarea.style.height = iframe.style.height;
// IMPORTANT: we have to allow Mozilla a short time to recognize the
// new frame. Otherwise we get a stupid exception.
function initIframe() {
var doc = editor._iframe.contentWindow.document;
if (!doc) {
// Try again..
// FIXME: don't know what else to do here. Normally
// we'll never reach this point.
if (HTMLArea.is_gecko) {
setTimeout(initIframe, 100);
return false;
} else {
alert("ERROR: IFRAME can't be initialized.");
}
}
if (HTMLArea.is_gecko) {
// enable editable mode for Mozilla
doc.designMode = "on";
}
editor._doc = doc;
if (!editor.config.fullPage) {
doc.open();
var html = '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 3.2//EN">\n';
html += "<html>\n";
html += "<head>\n";
if (editor.config.baseURL)
html += '<base href="' + editor.config.baseURL + '" />';
html += "<style type=\"text/css\">" + editor.config.pageStyle +
" html,body { border: 0px; }</style>\n";
html += "<title> </title>\n";
html += "</head>\n";
html += "<body>\n";
html += editor._textArea.value;
html += "</body>\n";
html += "</html>";
doc.write(html);
doc.close();
} else {
var html = editor._textArea.value;
if (html.match(HTMLArea.RE_doctype)) {
editor.setDoctype(RegExp.$1);
html = html.replace(HTMLArea.RE_doctype, "");
}
doc.open();
doc.write(html);
doc.close();
}
if (HTMLArea.is_ie) {
// enable editable mode for IE. For some reason this
// doesn't work if done in the same place as for Gecko
// (above).
doc.body.contentEditable = true;
}
editor.focusEditor();
// intercept some events; for updating the toolbar & keyboard handlers
HTMLArea._addEvents
(doc, ["keydown", "keypress", "mousedown", "mouseup", "drag"],
function (event) {
return editor._editorEvent(HTMLArea.is_ie ? editor._iframe.contentWindow.event : event);
});
// check if any plugins have registered refresh handlers
for (var i in editor.plugins) {
var plugin = editor.plugins[i].instance;
if (typeof plugin.onGenerate == "function")
plugin.onGenerate();
if (typeof plugin.onGenerateOnce == "function") {
plugin.onGenerateOnce();
plugin.onGenerateOnce = null;
}
}
setTimeout(function() {
editor.updateToolbar();
}, 250);
if (typeof editor.onGenerate == "function")
editor.onGenerate();
};
setTimeout(initIframe, 100);
};
// Switches editor mode; parameter can be "textmode" or "wysiwyg". If no
// parameter was passed this function toggles between modes.
HTMLArea.prototype.setMode = function(mode) {
if (typeof mode == "undefined") {
mode = ((this._editMode == "textmode") ? "wysiwyg" : "textmode");
}
switch (mode) {
case "textmode":
this._textArea.value = this.getHTML();
this._iframe.style.display = "none";
this._textArea.style.display = "block";
if (this.config.statusBar) {
this._statusBar.innerHTML = HTMLArea.I18N.msg["TEXT_MODE"];
}
break;
case "wysiwyg":
if (HTMLArea.is_gecko) {
// disable design mode before changing innerHTML
try {
this._doc.designMode = "off";
} catch(e) {};
}
if (!this.config.fullPage)
this._doc.body.innerHTML = this.getHTML();
else
this.setFullHTML(this.getHTML());
this._iframe.style.display = "block";
this._textArea.style.display = "none";
if (HTMLArea.is_gecko) {
// we need to refresh that info for Moz-1.3a
try {
this._doc.designMode = "on";
} catch(e) {};
}
if (this.config.statusBar) {
this._statusBar.innerHTML = '';
// this._statusBar.appendChild(document.createTextNode(HTMLArea.I18N.msg["Path"] + ": "));
this._statusBar.appendChild(this._statusBarTree);
}
break;
default:
alert("Mode <" + mode + "> not defined!");
return false;
}
this._editMode = mode;
this.focusEditor();
for (var i in this.plugins) {
var plugin = this.plugins[i].instance;
if (typeof plugin.onMode == "function") plugin.onMode(mode);
}
};
HTMLArea.prototype.setFullHTML = function(html) {
var save_multiline = RegExp.multiline;
RegExp.multiline = true;
if (html.match(HTMLArea.RE_doctype)) {
this.setDoctype(RegExp.$1);
html = html.replace(HTMLArea.RE_doctype, "");
}
RegExp.multiline = save_multiline;
if (!HTMLArea.is_ie) {
if (html.match(HTMLArea.RE_head))
this._doc.getElementsByTagName("head")[0].innerHTML = RegExp.$1;
if (html.match(HTMLArea.RE_body))
this._doc.getElementsByTagName("body")[0].innerHTML = RegExp.$1;
} else {
var html_re = /<html>((.|\n)*?)<\/html>/i;
html = html.replace(html_re, "$1");
this._doc.open();
this._doc.write(html);
this._doc.close();
this._doc.body.contentEditable = true;
return true;
}
};
/***************************************************
* Category: PLUGINS
***************************************************/
// Create the specified plugin and register it with this HTMLArea
HTMLArea.prototype.registerPlugin = function() {
var plugin = arguments[0];
var args = [];
for (var i = 1; i < arguments.length; ++i)
args.push(arguments[i]);
this.registerPlugin2(plugin, args);
};
// this is the variant of the function above where the plugin arguments are
// already packed in an array. Externally, it should be only used in the
// full-screen editor code, in order to initialize plugins with the same
// parameters as in the opener window.
HTMLArea.prototype.registerPlugin2 = function(plugin, args) {
if (typeof plugin == "string")
plugin = eval(plugin);
if (typeof plugin == "undefined") {
/* FIXME: This should never happen. But why does it do? */
return false;
}
var obj = new plugin(this, args);
if (obj) {
var clone = {};
var info = plugin._pluginInfo;
for (var i in info)
clone[i] = info[i];
clone.instance = obj;
clone.args = args;
this.plugins[plugin._pluginInfo.name] = clone;
} else
alert("Can't register plugin " + plugin.toString() + ".");
};
// static function that loads the required plugin and lang file, based on the
// language loaded already for HTMLArea. You better make sure that the plugin
// _has_ that language, otherwise shit might happen ;-)
HTMLArea.getPluginDir = function(pluginName) {
return _editor_url + "plugins/" + pluginName;
};
HTMLArea.loadPlugin = function(pluginName) {
var dir = this.getPluginDir(pluginName);
var plugin = pluginName.replace(/([a-z])([A-Z])([a-z])/g,
function (str, l1, l2, l3) {
return l1 + "-" + l2.toLowerCase() + l3;
}).toLowerCase() + ".js";
var plugin_file = dir + "/" + plugin;
var plugin_lang = dir + "/lang/" + _editor_lang + ".js";
//document.write("<script type='text/javascript' src='" + plugin_file + "'></script>");
//document.write("<script type='text/javascript' src='" + plugin_lang + "'></script>");
this.loadScript(plugin_file);
this.loadScript(plugin_lang);
};
HTMLArea.loadStyle = function(style, plugin) {
var url = _editor_url || '';
if (typeof plugin != "undefined") {
url += "plugins/" + plugin + "/";
}
url += style;
if (/^\//.test(style))
url = style;
var head = document.getElementsByTagName("head")[0];
var link = document.createElement("link");
link.rel = "stylesheet";
link.href = url;
head.appendChild(link);
//document.write("<style type='text/css'>@import url(" + url + ");</style>");
};
HTMLArea.loadStyle(typeof _editor_css == "string" ? _editor_css : "htmlarea.css");
/***************************************************
* Category: EDITOR UTILITIES
***************************************************/
HTMLArea.prototype.debugTree = function() {
var ta = document.createElement("textarea");
ta.style.width = "100%";
ta.style.height = "20em";
ta.value = "";
function debug(indent, str) {
for (; --indent >= 0;)
ta.value += " ";
ta.value += str + "\n";
};
function _dt(root, level) {
var tag = root.tagName.toLowerCase(), i;
var ns = HTMLArea.is_ie ? root.scopeName : root.prefix;
debug(level, "- " + tag + " [" + ns + "]");
for (i = root.firstChild; i; i = i.nextSibling)
if (i.nodeType == 1)
_dt(i, level + 2);
};
_dt(this._doc.body, 0);
document.body.appendChild(ta);
};
HTMLArea.getInnerText = function(el) {
var txt = '', i;
for (i = el.firstChild; i; i = i.nextSibling) {
if (i.nodeType == 3)
txt += i.data;
else if (i.nodeType == 1)
txt += HTMLArea.getInnerText(i);
}
return txt;
};
HTMLArea.prototype._wordClean = function() {
var
editor = this,
stats = {
empty_tags : 0,
mso_class : 0,
mso_style : 0,
mso_xmlel : 0,
orig_len : this._doc.body.innerHTML.length,
T : (new Date()).getTime()
},
stats_txt = {
empty_tags : "Empty tags removed: ",
mso_class : "MSO class names removed: ",
mso_style : "MSO inline style removed: ",
mso_xmlel : "MSO XML elements stripped: "
};
function showStats() {
var txt = "HTMLArea word cleaner stats: \n\n";
for (var i in stats)
if (stats_txt[i])
txt += stats_txt[i] + stats[i] + "\n";
txt += "\nInitial document length: " + stats.orig_len + "\n";
txt += "Final document length: " + editor._doc.body.innerHTML.length + "\n";
txt += "Clean-up took " + (((new Date()).getTime() - stats.T) / 1000) + " seconds";
alert(txt);
};
function clearClass(node) {
var newc = node.className.replace(/(^|\s)mso.*?(\s|$)/ig, ' ');
if (newc != node.className) {
node.className = newc;
if (!/\S/.test(node.className)) {
node.removeAttribute("className");
++stats.mso_class;
}
}
};
function clearStyle(node) {
var declarations = node.style.cssText.split(/\s*;\s*/);
for (var i = declarations.length; --i >= 0;)
if (/^mso|^tab-stops/i.test(declarations[i]) ||
/^margin\s*:\s*0..\s+0..\s+0../i.test(declarations[i])) {
++stats.mso_style;
declarations.splice(i, 1);
}
node.style.cssText = declarations.join("; ");
};
function stripTag(el) {
if (HTMLArea.is_ie)
el.outerHTML = HTMLArea.htmlEncode(el.innerText);
else {
var txt = document.createTextNode(HTMLArea.getInnerText(el));
el.parentNode.insertBefore(txt, el);
el.parentNode.removeChild(el);
}
++stats.mso_xmlel;
};
function checkEmpty(el) {
if (/^(a|span|b|strong|i|em|font)$/i.test(el.tagName) &&
!el.firstChild) {
el.parentNode.removeChild(el);
++stats.empty_tags;
}
};
function parseTree(root) {
var tag = root.tagName.toLowerCase(), i, next;
if ((HTMLArea.is_ie && root.scopeName != 'HTML') || (!HTMLArea.is_ie && /:/.test(tag))) {
stripTag(root);
return false;
} else {
clearClass(root);
clearStyle(root);
for (i = root.firstChild; i; i = next) {
next = i.nextSibling;
if (i.nodeType == 1 && parseTree(i))
checkEmpty(i);
}
}
return true;
};
parseTree(this._doc.body);
// showStats();
// this.debugTree();
// this.setHTML(this.getHTML());
// this.setHTML(this.getInnerHTML());
// this.forceRedraw();
this.updateToolbar();
};
HTMLArea.prototype.forceRedraw = function() {
this._doc.body.style.visibility = "hidden";
this._doc.body.style.visibility = "visible";
// this._doc.body.innerHTML = this.getInnerHTML();
};
// focuses the iframe window. returns a reference to the editor document.
HTMLArea.prototype.focusEditor = function() {
switch (this._editMode) {
// notice the try { ... } catch block to avoid some rare exceptions in FireFox
// (perhaps also in other Gecko browsers). Manual focus by user is required in
// case of an error. Somebody has an idea?
case "wysiwyg" : try { this._iframe.contentWindow.focus() } catch (e) {} break;
case "textmode": try { this._textArea.focus() } catch (e) {} break;
default : alert("ERROR: mode " + this._editMode + " is not defined");
}
return this._doc;
};
// takes a snapshot of the current text (for undo)
HTMLArea.prototype._undoTakeSnapshot = function() {
++this._undoPos;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -