rte.js
上传用户:simon2hong
上传日期:2021-11-18
资源大小:16746k
文件大小:18k
- // Internal (private) properties.
- // RichEditor is the global RichEditor object (function) of which there is only
- // 1 instance.
- RichEditor.txtView = true; // WYSIWYG mode. false == View Source
- // initEditor(): Initialise the editor (called on window load, see below)
- function initEditor()
- {
- // Apply style data if supplied
- if (!public_description.styleData) {
- public_description.put_styleData(null);
- }
- // Apply default editor options
- var strDefaults = 'dragdrop=no;source=yes';
- strDefaults += ';history=' + (document.queryCommandSupported('Undo') ? 'yes' : 'no');
- applyOptions(strDefaults);
- // Prepare the editable region
- loading.style.display = 'none';
- doc.contentEditable = "true";
- editor.style.visibility = 'visible';
- if(parent.document.all("IMG_ATTACHMENT_ID"))
- document.all("IMG_ATTACHMENT_ID").value=parent.document.all("IMG_ATTACHMENT_ID").value;
- if(parent.document.all("IMG_ATTACHMENT_NAME"))
- document.all("IMG_ATTACHMENT_NAME").value=parent.document.all("IMG_ATTACHMENT_NAME").value;
-
- // OZ - 12-06-2002
- // Put focus into the document (required when no HTML is supplied via docHtml property)
- doc.focus();
- }
- // checkRange(): make sure our pretend document (the content editable
- // DIV with id of "doc") has focus and that a text range exists (which
- // is what execCommand() operates on).
- function checkRange()
- {
- RichEditor.selectedImage = null;
- if (!RichEditor.txtView) return; // Disabled in View Source mode
- doc.focus();
- if (document.selection.type == "None") {
- document.selection.createRange();
- }
- var r = document.selection.createRange();
- DBG(1, 'RANGE Bounding('
- + 'top='+r.boundingHeight
- + ', left='+r.boundingHeight
- + ', width='+r.boundingWidth
- + ', height='+r.boundingHeight + ')'
- + ', Offset('
- + 'top='+r.offsetTop
- + ', left='+r.offsetLeft + ')'
- + ', Text=(' + r.text + ')'
- + ', HTML=(' + r.htmlText + ')'
- );
- }
- // post(): Called in response to clicking the post button in the
- // toolbar. It fires an event in the container named post, passing the
- // HTML of our newly edited document as the data argument.
- function post()
- {
- //DBG(1, 'Raise "post" event');
- //window.external.raiseEvent("post", doc.innerHTML);
- //alert(doc.innerHTML);
- return doc.innerHTML;
- }
- // insert(): called in response to clicking the insert table, image,
- // smily icons in the toolbar. Loads up an appropriate dialog to
- // prompt for information, the dialog then returns the HTML code or
- // NULL. We paste the HTML code into the document.
- function insert(what)
- {
- if (!RichEditor.txtView) return; // Disabled in View Source mode
- DBG(1, 'insert' + what + ')');
- // Chose action based on what is being inserted.
- switch(what)
- {
- case "table":
- strPage = "dlg_ins_table.html";
- strAttr = "status:no;dialogWidth:340px;dialogHeight:360px;help:no";
- break;
- case "smile":
- strPage = "dlg_ins_smile.html";
- strAttr = "status:no;dialogWidth:300px;dialogHeight:350px;help:no";
- break;
- case "char":
- strPage = "dlg_ins_char.html";
- strAttr = "status:no;dialogWidth:450px;dialogHeight:290px;help:no";
- break;
- case "image":
- strPage = "dlg_ins_image.html";
- strAttr = "status:no;dialogWidth:400px;dialogHeight:210px;help:no";' '
- break;
- case "about":
- strPage = "dlg_about.html";
- strAttr = "status:no;dialogWidth:250px;dialogHeight:130px;help:no";' '
- break;
- }
- // run the dialog that implements this type of element
- html = showModalDialog(strPage, window, strAttr);
- // and insert any result into the document.
- if (html) {
- insertHtml(html);
- }
- }
- // insertHtml(): Insert the supplied HTML into the current position
- // within the document.
- function insertHtml(html)
- {
- doc.focus();
- var sel = document.selection.createRange();
- // don't try to insert HTML into a control selection (ie. image or table)
- if (document.selection.type == 'Control') {
- return;
- }
-
- sel.pasteHTML(html);
- }
- // doStyle(): called to handle the simple style commands such a bold,
- // italic etc. These require no special handling, just a call to
- // execCommand(). We also call reset so that the toolbar represents
- // the state of the current text.
- //
- // 2002-07-30 Updated based on patch submitted by Michael Keck (mkkeck)
- //
- function doStyle(s){
- if(!RichEditor.txtView) return;
- /* Disabled in View Source mode */
- DBG(1, 'doStyle(' + s + ')');
- checkRange();
- if(s!='InsertHorizontalRule'){
- /* what command string? */
- document.execCommand(s);
- } else if( s=='InsertHorizontalRule') {
- /* if s=='InsertHorizontalRule then use this command */
- document.execCommand(s,false, null);
- /* Note:
- In your source view the <HR> has an ID like this
- <HR id=null>
- */
- }
- reset();
- }
- // link(): called to insert a hyperlink. It will use the selected text
- // if there is some, or the URL entered if not. If clicked when over a
- // link, that link is allowed to be edited.
- function link(on)
- {
- if (!RichEditor.txtView) return; // Disabled in View Source mode
- var strURL = "http://";
- var strText;
- // First, pick up the current selection.
- doc.focus();
- var r = document.selection.createRange();
- var el = r.parentElement();
- // Is this aready a link?
- if (el && el.nodeName == "A") {
- r.moveToElementText(el);
- if (!on) { // If removing the link, then replace all with
- r.pasteHTML(el.innerHTML);
- return;
- }
- strURL = el.href;
- }
- // Get the text associated with this link
- strText = r.text;
- // Prompt for the URL
- strURL = window.prompt("输入地址:", strURL);
- if (strURL) {
- // Default the TEXT to the url if non selected
- if (!strText || !strText.length) {
- strText = strURL;
- }
- // Replace with new URL
- r.pasteHTML('<A href=' + strURL + ' target=_new>' + strText + '</a>');
- }
- reset();
- }
- // sel(); similar to doStyle() but called from the dropdown list boxes
- // for font and style commands.
- function sel(el)
- {
- if (!RichEditor.txtView) return; // Disabled in View Source mode
- checkRange();
- switch(el.id)
- {
- case "ctlFont":
- document.execCommand('FontName', false, el[el.selectedIndex].value);
- break;
- case "ctlSize":
- document.execCommand('FontSize', false, el[el.selectedIndex].value);
- break;
- case "ctlStyle":
- document.execCommand('FormatBlock', false, el[el.selectedIndex].text);
- break;
- }
- doc.focus();
- reset();
- }
- // pickColor(): called when the text or fill color icons are clicked. Displays
- // the color chooser control. The color setting is completed by the event
- // handler of this control (see richedit.html)
- function pickColor(fg)
- {
- if (!RichEditor.txtView) return; // Disabled in View Source mode
- checkRange();
- var el = window.event.srcElement;
- if (el && el.nodeName == "IMG") {
- setState(el, true);
- }
- color.style.top = window.event.clientY + 10;
- color.style.left = window.event.clientX - 100;
- color.style.display = 'block';
- color._fg = fg;
- }
- // setColor(): called from the fore/back color selection dialog event handler
- // to set/reset the fore/background color.
- function setColor(name, data)
- {
- color.style.display = 'none';
- checkRange();
- if (!data) {
- removeFormat(document.selection.createRange(), color._fg);
- } else {
- document.execCommand(color._fg, false, data);
- }
- setState(btnText, false);
- setState(btnFill, false);
- doc.focus();
- }
- // removeFormat(): Called to remove specific formats from the selected text.
- // The 'removeFormat' command removes all formatting. The principle behind
- // this routine is to have a list of the possible formats the selection may
- // have, check the selection for the current formats, ignoreing the one we
- // want to use, then remove all formatting and then re-apply all but the
- // one we wanted to remove.
- function removeFormat(r, name)
- {
- var cmd = [ "Bold", "Italic", "Underline", "Strikethrough", "FontName", "FontSize", "ForeColor", "BackColor" ];
- var on = new Array(cmd.length);
- for (var i = 0; i < cmd.length; i++) {
- on[i] = name == cmd[i] ? null : r.queryCommandValue(cmd[i]);
- }
- r.execCommand('RemoveFormat');
- for (var i = 0; i < cmd.length; i++) {
- if (on[i]) r.execCommand(cmd[i], false, on[i]);
- }
- }
- // setValue(): called from reset() to make a select list show the current font
- // or style attributes
- function selValue(el, str)
- {
- if (!RichEditor.txtView) return; // Disabled in View Source mode
- for (var i = 0; i < el.length; i++) {
- if ((!el[i].value && el[i].text == str) || el[i].value == str) {
- el.selectedIndex = i;
- return;
- }
- }
- el.selectedIndex = 0;
- }
- // setState(): called from reset() to make a button represent the state
- // of the current text. Pressed is on, unpressed is off.
- function setState(el, on)
- {
- if (!RichEditor.txtView) return; // Disabled in View Source mode
- if (!el.disabled) {
- if (on) {
- el.defaultState = el.className = "down";
- } else {
- el.defaultState = el.className = null;
- }
- }
- }
- // getStyle(): called to obtain the class or type of formatting applied to an element,
- // This is used by reset() to set the state of the toolbar to indicate the class of
- // the current element.
- function getStyle() {
- var style = document.queryCommandValue('FormatBlock');
- if (style == "Normal") {
- doc.focus();
- var rng = document.selection.createRange();
- if (typeof(rng.parentElement) != "undefined") {
- var el = rng.parentElement();
- var tag = el.nodeName.toUpperCase();
- var str = el.className.toLowerCase();
- if (!(tag == "DIV" && el.id == "doc" && str == "textedit")) {
- if (tag == "SPAN") {
- style = "." + str;
- } else if (str == "") {
- style = tag;
- } else {
- style = tag + "." + str;
- }
- }
- return style;
- }
- }
- return style;
- }
- // getfontface(): called to obtain the face attribute applied to a font tag,
- // This is used by reset() to set the state of the toolbar to indicate the class of
- // the current element.
- function getfontface()
- {
- var family = document.selection.createRange(); //create text range
- // don't get font face for image or table
- if (document.selection.type == 'Control') {
- return;
- }
- var el = family.parentElement(); //get parent element
- var tag = el.nodeName.toUpperCase(); //convert tag element to upper case
- if (typeof(el.parentElement) != "undefined" && tag == "FONT") { //only do function if tag is font - this is for greater execution speed
- var elface = el.getAttribute('FACE'); //get the font tags FACE attribute
- return elface; //return the value of the face attribute to the reset() function
- }
- }
- // markSelectedElement(): called by onClick and onKeyup events
- // on the contectEditable area
- function markSelectedElement() {
- RichEditor.selectedImage = null;
- var r = document.selection.createRange();
- if (document.selection.type != 'Text') {
- if (r.length == 1) {
- if (r.item(0).tagName == "IMG") {
- RichEditor.selectedImage = r.item(0);
- }
- }
- }
- }
- // reset(): called from all over the place to make the toolbar
- // represent the current text. If el specified, it was called from
- // hover(off)
- function reset(el)
- {
- if (!RichEditor.txtView) return; // Disabled in View Source mode
- if (!el) color.style.display = 'none';
- if (!el || el == ctlStyle) selValue(ctlStyle, getStyle());
- if (!el || el == ctlFont) selValue(ctlFont, getfontface());
- if (!el || el == ctlSize) selValue(ctlSize, document.queryCommandValue('FontSize'));
- if (!el || el == btnBold) setState(btnBold, document.queryCommandValue('Bold'));
- if (!el || el == btnItalic) setState(btnItalic, document.queryCommandValue('Italic'));
- if (!el || el == btnUnderline) setState(btnUnderline, document.queryCommandValue('Underline'));
- if (!el || el == btnStrikethrough) setState(btnStrikethrough, document.queryCommandValue('Strikethrough'));
- if (!el || el == btnLeftJustify) setState(btnLeftJustify, document.queryCommandValue('JustifyLeft'));
- if (!el || el == btnCenter) setState(btnCenter, document.queryCommandValue('JustifyCenter'));
- if (!el || el == btnRightJustify) setState(btnRightJustify, document.queryCommandValue('JustifyRight'));
- if (!el || el == btnFullJustify) setState(btnFullJustify, document.queryCommandValue('JustifyFull'));
- if (!el || el == btnNumList) setState(btnNumList, document.queryCommandValue('InsertOrderedList'));
- if (!el || el == btnBulList) setState(btnBulList, document.queryCommandValue('InsertUnorderedList'));
- }
- // hover(): Handles mouse hovering over toolbar buttons
- function hover(on)
- {
- if (!RichEditor.txtView) return; // Disabled in View Source mode
- var el = window.event.srcElement;
- if (el && !el.disabled && el.nodeName == "IMG" && el.className != "spacer") {
- if (on) {
- el.className = "hover";
- } else {
- el.className = el.defaultState ? el.defaultState : null;
- }
- }
- }
- // hover(): Handles mouse clicks on toolbar buttons
- function press(on)
- {
- if (!RichEditor.txtView) return; // Disabled in View Source mode
- var el = window.event.srcElement;
- if (el && !el.disabled && el.nodeName == "IMG" && el.className != "spacer") {
- if (on) {
- el.className = "down";
- } else {
- el.className = el.className == "down" ? "hover" : el.defaultState ? el.defaultState : null;
- }
- }
- }
- // addTag(): This is the handler for the style dropdown. This takes value
- // selected and interprates it and makes the necessary changes to the HTML to
- // apply this style.
- function addTag(obj) {
- if (!RichEditor.txtView) return; // Disabled in View Source mode
- // Determine the type of element we are dealing with.
- // TYPE 0 IS NORMAL-TAG, 1 IS CLASS, 2 IS SUBCLASS, 3 = Format Block command
- var value = obj[obj.selectedIndex].value;
- if (!value) { // Format Block
- sel(obj);
- return;
- }
- var type = 0; // TAG
- if (value.indexOf(".") == 0) { // .className
- type = 1;
- } else if (value.indexOf(".") != -1) { // TAG.className
- type = 2;
- }
- doc.focus();
- // Pick up the highlighted text
- var r = document.selection.createRange();
- r.select();
- var s = r.htmlText;
- // If we have some selected text, then ignore silly selections
- if (s == " " || s == " ") {
- return;
- }
- // How we apply formatting is based upon the type of formitting being
- // done.
- switch(type)
- {
- case 1:
- // class: Wrap the selected text with a span of the specified
- // class name
- value = value.substring(1,value.length);
- r.pasteHTML("<span class="+value+">" + r.htmlText + "</span>")
- break;
- case 2:
- // subclass: split the value into tag + class
- value = value.split(".");
- r.pasteHTML('<' + value[0] + ' class="' + value[1] +'">'
- + r.htmlText
- + '</' + value[0] + '>'
- );
- break;
- default:
- // TAG: wrap up the highlighted text with the specified tag
- r.pasteHTML("<"+value+">"+r.htmlText+"</"+value+">")
- break;
- }
- }
- // initStyleDropdown(): This takes the passed styleList and generates the style
- // dropdown list box from it.
- function initStyleDropdown(styleList) {
- // Build the option list for the styles dropdown from the passed styles
- for (var i = 0; i < styleList.length; i++) {
- var oOption = document.createElement("OPTION");
- if (styleList[i][0]) oOption.value = styleList[i][0];
- oOption.text = styleList[i][1];
- oOption.style.backgroundColor = 'white';
- document.all.ctlStyle.add(oOption);
- }
- }
- // applyOptions(): This takes the passed options string and actions them.
- // Called during the init process.
- function applyOptions(str)
- {
- var options = str.split(";");
- for (var i = 0; i < options.length; i++) {
- var eq = options[i].indexOf('=');
- var on = eq == -1 ? true : "yes;true;1".indexOf(options[i].substr(eq+1).toLowerCase()) != -1;
- var name = eq == -1 ? options[i] : options[i].substr(0,eq);
- var el = document.all("feature" + name);
- if (el) {
- el.runtimeStyle.display = (on ? 'inline' : 'none');
- } else {
- if (!RichEditor.aOptions) RichEditor.aOptions = new Array;
- RichEditor.aOptions[name] = on;
- }
- }
- }
- // getOption(): Get the value for a previously set option or return undefined if
- // the option is not set.
- function getOption(name)
- {
- if (RichEditor.aOptions) return RichEditor.aOptions[name];
- return; // Undefined
- }
- // Handle drag and drop events into the editor window. Until we
- // work out how to handle these better (which requires co-operation
- // from the code being dragged from as far as I can tell) we simply
- // disable the functionality.
- function handleDrag(n)
- {
- // if drag and drop is disabled, then cancel the dragdrop
- // events
- if (!getOption("dragdrop"))
- {
- switch(n) {
- case 0: // ondragenter
- window.event.dataTransfer.dropEffect = "none";
- break;
- }
- // Cancel the event
- window.event.returnValue = false;
- }
- }