?? richtext.js
字號:
/* Copyright (c) 2004-2006, The Dojo Foundation All Rights Reserved. Licensed under the Academic Free License version 2.1 or above OR the modified BSD license. For more information on Dojo licensing, see: http://dojotoolkit.org/community/licensing.shtml*/ /* -*- tab-width: 4 -*- */dojo.provide("dojo.widget.RichText");dojo.provide("dojo.widget.html.RichText");dojo.require("dojo.widget.*");dojo.require("dojo.dom");dojo.require("dojo.html");dojo.require("dojo.event.*");dojo.require("dojo.style");dojo.require("dojo.string");// used to save contenttry { document.write('<textarea id="dojo.widget.RichText.savedContent" ' + 'style="display:none;position:absolute;top:-100px;left:-100px;height:3px;width:3px;overflow:hidden;"></textarea>');}catch(e){ }dojo.widget.defineWidget( "dojo.widget.html.RichText", dojo.widget.HtmlWidget, { /** whether to inherit the parent's width or simply use 100% */ inheritWidth: false, focusOnLoad: true, /** * If a save name is specified the content is saved and restored if the * editor is not properly closed after editing has started. */ saveName: "", _content: "", /* set height to fix the editor at a specific height, with scrolling */ height: null, /** The minimum height that the editor should have */ minHeight: "1em", isClosed: true, isLoaded: false, /** whether to use the active-x object in IE */ useActiveX: false, /* whether to use relative URLs for images - if this is enabled images will be given absolute URLs when inside the editor but will be changed to use relative URLs (to the current page) on save */ relativeImageUrls: false, _SEPARATOR: "@@**%%__RICHTEXTBOUNDRY__%%**@@", // contentFilters: [], /* defaultContentCleaner: function(content){ if(!dojo.render.html.ie){ return content; } content = content.replace(/\x20/g, " "); // alert(content); return content; }, */ /* Init *******/ fillInTemplate: function(){ this.open(); // add the formatting functions var funcs = ["queryCommandEnabled", "queryCommandState", "queryCommandValue", "execCommand"]; for(var i = 0; i < funcs.length; i++){ dojo.event.connect("around", this, funcs[i], this, "_normalizeCommand"); } // backwards compatibility, needs to be removed dojo.event.connect(this, "onKeyPressed", this, "afterKeyPress"); dojo.event.connect(this, "onKeyPress", this, "keyPress"); dojo.event.connect(this, "onKeyDown", this, "keyDown"); dojo.event.connect(this, "onKeyUp", this, "keyUp"); // add default some key handlers var ctrl = this.KEY_CTRL; var exec = function (cmd, arg) { return arguments.length == 1 ? function () { this.execCommand(cmd); } : function () { this.execCommand(cmd, arg); } } this.addKeyHandler("b", ctrl, exec("bold")); this.addKeyHandler("i", ctrl, exec("italic")); this.addKeyHandler("u", ctrl, exec("underline")); this.addKeyHandler("a", ctrl, exec("selectall")); //this.addKeyHandler("k", ctrl, exec("createlink", "")); //this.addKeyHandler("K", ctrl, exec("unlink")); this.addKeyHandler("s", ctrl, function () { this.save(true); }); this.addKeyHandler("1", ctrl, exec("formatblock", "h1")); this.addKeyHandler("2", ctrl, exec("formatblock", "h2")); this.addKeyHandler("3", ctrl, exec("formatblock", "h3")); this.addKeyHandler("4", ctrl, exec("formatblock", "h4")); this.addKeyHandler("\\", ctrl, exec("insertunorderedlist")); if(!dojo.render.html.ie){ this.addKeyHandler("Z", ctrl, exec("redo")); } }, events: ["onBlur", "onFocus", "onKeyPress", "onKeyDown", "onKeyUp", "onClick"], /** * Transforms the node referenced in this.domNode into a rich text editing * node. This can result in the creation and replacement with an <iframe> if * designMode is used, an <object> and active-x component if inside of IE or * a reguler element if contentEditable is available. */ open: function (element) { dojo.event.topic.publish("dojo.widget.RichText::open", this); if (!this.isClosed) { this.close(); } this._content = ""; if((arguments.length == 1)&&(element["nodeName"])){ this.domNode = element; } // else unchanged if( (this.domNode["nodeName"])&& (this.domNode.nodeName.toLowerCase() == "textarea")){ this.textarea = this.domNode; var html = dojo.string.trim(this.textarea.value); if(html == ""){ html = " "; } this.domNode = document.createElement("div"); with(this.textarea.style){ display = "block"; position = "absolute"; width = "1px"; height = "1px"; border = margin = padding = "0px"; visiblity = "hidden"; if(dojo.render.html.ie){ overflow = "hidden"; } } dojo.dom.insertBefore(this.domNode, this.textarea); this.domNode.innerHTML = html; if(this.textarea.form){ dojo.event.connect(this.textarea.form, "onsubmit", // FIXME: should we be calling close() here instead? dojo.lang.hitch(this, function(){ this.textarea.value = this.getEditorContent(); }) ); } // dojo plucks our original domNode from the document so we need // to go back and put ourselves back in var editor = this; dojo.event.connect(this, "postCreate", function (){ dojo.dom.insertAfter(editor.textarea, editor.domNode); }); }else{ var html = dojo.string.trim(this.domNode.innerHTML); if(html == ""){ html = " "; } } this._oldHeight = dojo.style.getContentHeight(this.domNode); this._oldWidth = dojo.style.getContentWidth(this.domNode); this._firstChildContributingMargin = this._getContributingMargin(this.domNode, "top"); this._lastChildContributingMargin = this._getContributingMargin(this.domNode, "bottom"); this.savedContent = document.createElement("div"); while (this.domNode.hasChildNodes()) { this.savedContent.appendChild(this.domNode.firstChild); } // If we're a list item we have to put in a blank line to force the // bullet to nicely align at the top of text if( (this.domNode["nodeName"])&& (this.domNode.nodeName == "LI")){ this.domNode.innerHTML = " <br>"; } if(this.saveName != ""){ var saveTextarea = document.getElementById("dojo.widget.RichText.savedContent"); if (saveTextarea.value != "") { var datas = saveTextarea.value.split(this._SEPARATOR); for (var i = 0; i < datas.length; i++) { var data = datas[i].split(":"); if (data[0] == this.saveName) { html = data[1]; datas.splice(i, 1); break; } } } dojo.event.connect("before", window, "onunload", this, "_saveContent"); // dojo.event.connect(window, "onunload", this, "_saveContent"); } // Safari's selections go all out of whack if we do it inline, // so for now IE is our only hero //if (typeof document.body.contentEditable != "undefined") { if (this.useActiveX && dojo.render.html.ie) { // active-x this._drawObject(html); // dojo.debug(this.object.document); } else if (dojo.render.html.ie) { // contentEditable, easy this.editNode = document.createElement("div"); with (this.editNode) { innerHTML = html; contentEditable = true; style.height = this.height ? this.height : this.minHeight; } if(this.height){ this.editNode.style.overflowY="scroll"; } // FIXME: setting contentEditable on switches this element to // IE's hasLayout mode, triggering weird margin collapsing // behavior. It's particularly bad if the element you're editing // contains childnodes that don't have margin: defined in local // css rules. It would be nice if it was possible to hack around // this. Sadly _firstChildContributingMargin and // _lastChildContributingMargin don't work on IE unless all // elements have margins set in CSS :-( this.domNode.appendChild(this.editNode); dojo.lang.forEach(this.events, function(e){ dojo.event.connect(this.editNode, e.toLowerCase(), this, e); }, this); this.window = window; this.document = document; this.onLoad(); } else { // designMode in iframe this._drawIframe(html); } // TODO: this is a guess at the default line-height, kinda works if (this.domNode.nodeName == "LI") { this.domNode.lastChild.style.marginTop = "-1.2em"; } dojo.html.addClass(this.domNode, "RichTextEditable"); this.isClosed = false; }, _hasCollapseableMargin: function(element, side) { // check if an element has padding or borders on the given side // which would prevent it from collapsing margins if (dojo.style.getPixelValue(element, 'border-'+side+'-width', false)) { return false; } else if (dojo.style.getPixelValue(element, 'padding-'+side, false)) { return false; } else { return true; } }, _getContributingMargin: function(element, topOrBottom) { // calculate how much margin this element and its first or last // child are contributing to the total margin between this element // and the adjacent node. CSS border collapsing makes this // necessary. if (topOrBottom == "top") { var siblingAttr = "previousSibling"; var childSiblingAttr = "nextSibling"; var childAttr = "firstChild"; var marginProp = "margin-top"; var siblingMarginProp = "margin-bottom"; } else { var siblingAttr = "nextSibling"; var childSiblingAttr = "previousSibling"; var childAttr = "lastChild"; var marginProp = "margin-bottom"; var siblingMarginProp = "margin-top"; } var elementMargin = dojo.style.getPixelValue(element, marginProp, false); function isSignificantNode(element) { // see if an node is significant in the current context // for calulating margins return !(element.nodeType==3 && dojo.string.isBlank(element.data)) && dojo.style.getStyle(element, "display") != "none" && !dojo.style.isPositionAbsolute(element); } // walk throuh first/last children to find total collapsed margin size var childMargin = 0; var child = element[childAttr]; while (child) { // skip over insignificant elements (whitespace, etc) while ((!isSignificantNode(child)) && child[childSiblingAttr]) { child = child[childSiblingAttr]; } childMargin = Math.max(childMargin, dojo.style.getPixelValue(child, marginProp, false)); // stop if we hit a bordered/padded element if (!this._hasCollapseableMargin(child, topOrBottom)) break; child = child[childAttr]; } // if this element has a border, return full child margin immediately // as there won't be any margin collapsing if (!this._hasCollapseableMargin(element, topOrBottom)){ return parseInt(childMargin); } // find margin supplied by nearest sibling var contextMargin = 0; var sibling = element[siblingAttr]; while (sibling) { if (isSignificantNode(sibling)) { contextMargin = dojo.style.getPixelValue(sibling, siblingMarginProp, false); break; } sibling = sibling[siblingAttr]; } if (!sibling) { // no sibling, look at parent's margin instead contextMargin = dojo.style.getPixelValue(element.parentNode, marginProp, false); } if (childMargin > elementMargin) { return parseInt(Math.max((childMargin-elementMargin)-contextMargin, 0)); } else { return 0; } }, /** Draws an iFrame using the existing one if one exists. Used by Mozilla, Safari, and Opera */ _drawIframe: function (html) { // detect firefox < 1.5, which has some iframe loading issues var oldMoz = Boolean(dojo.render.html.moz && ( typeof window.XML == 'undefined')) if (!this.iframe) { var currentDomain = (new dojo.uri.Uri(document.location)).host; this.iframe = document.createElement("iframe"); with (this.iframe) { scrolling = this.height ? "auto" : "no"; style.border = "none"; style.lineHeight = "0"; // squash line height style.verticalAlign = "bottom";
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -