📄 richtext.js
字号:
siblingMarginProp, false); break; } sibling = sibling[siblingAttr]; } if (!sibling) { // no sibling, look at parent's margin instead contextMargin = dojo.html.getPixelValue(element.parentNode, marginProp, false); } if (childMargin > elementMargin) { return parseInt(Math.max((childMargin-elementMargin)-contextMargin, 0)); } else { return 0; } }, _drawIframe: function (/*String*/html){ // summary: // Draws an iFrame using the existing one if one exists. // Used by Mozilla, Safari, and Opera // 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(dojo.doc().location)).host; this.iframe = dojo.doc().createElement("iframe"); // dojo.body().appendChild(this.iframe); with(this.iframe){ style.border = "none"; style.lineHeight = "0"; // squash line height style.verticalAlign = "bottom"; scrolling = this.height ? "auto" : "no"; } } // opera likes this to be outside the with block this.iframe.src = dojo.uri.dojoUri("src/widget/templates/richtextframe.html") + ((dojo.doc().domain != currentDomain) ? ("#"+dojo.doc().domain) : ""); this.iframe.width = this.inheritWidth ? this._oldWidth : "100%"; if(this.height){ this.iframe.style.height = this.height; }else{ var height = this._oldHeight; if(this._hasCollapseableMargin(this.domNode, 'top')){ height += this._firstChildContributingMargin; } if(this._hasCollapseableMargin(this.domNode, 'bottom')){ height += this._lastChildContributingMargin; } this.iframe.height = height; } var tmpContent = dojo.doc().createElement('div'); tmpContent.innerHTML = html; // make relative image urls absolute if(this.relativeImageUrls){ var imgs = tmpContent.getElementsByTagName('img'); for(var i=0; i<imgs.length; i++){ imgs[i].src = (new dojo.uri.Uri(dojo.global().location, imgs[i].src)).toString(); } html = tmpContent.innerHTML; } // fix margins on tmpContent var firstChild = dojo.html.firstElement(tmpContent); var lastChild = dojo.html.lastElement(tmpContent); if(firstChild){ firstChild.style.marginTop = this._firstChildContributingMargin+"px"; } if(lastChild){ lastChild.style.marginBottom = this._lastChildContributingMargin+"px"; } // show existing content behind iframe for now tmpContent.style.position = "absolute"; this.editingArea.appendChild(tmpContent); this.editingArea.appendChild(this.iframe); if(dojo.render.html.safari){ this.iframe.src = this.iframe.src; } var _iframeInitialized = false; // now we wait for onload. Janky hack! var ifrFunc = dojo.lang.hitch(this, function(){ if(!_iframeInitialized){ _iframeInitialized = true; }else{ return; } if(!this.editNode){ if(this.iframe.contentWindow){ this.window = this.iframe.contentWindow; this.document = this.iframe.contentWindow.document }else if(this.iframe.contentDocument){ // for opera this.window = this.iframe.contentDocument.window; this.document = this.iframe.contentDocument; } // curry the getStyle function var getStyle = (function (domNode) { return function (style) { return dojo.html.getStyle(domNode, style); }; })(this.domNode); var font = getStyle('font-weight') + " " + getStyle('font-size') + " " + getStyle('font-family'); // line height is tricky - applying a units value will mess things up. // if we can't get a non-units value, bail out. var lineHeight = "1.0"; var lineHeightStyle = dojo.html.getUnitValue(this.domNode, 'line-height'); if (lineHeightStyle.value && lineHeightStyle.units=="") { lineHeight = lineHeightStyle.value; } dojo.html.insertCssText( ' body,html { background: transparent; padding: 0; margin: 0; }\n' + // TODO: left positioning will case contents to disappear out of view // if it gets too wide for the visible area ' body { top: 0; left: 0; right: 0;' + (((this.height)||(dojo.render.html.opera)) ? '' : ' position: fixed; ') + ' font: ' + font + ';\n' + ' min-height: ' + this.minHeight + '; \n' + ' line-height: ' + lineHeight + '} \n' + ' p { margin: 1em 0 !important; }\n' + ' body > *:first-child { padding-top: 0 !important; margin-top: ' + this._firstChildContributingMargin + 'px !important; }\n' + // FIXME: test firstChild nodeType ' body > *:last-child { padding-bottom: 0 !important; margin-bottom: ' + this._lastChildContributingMargin + 'px !important; }\n' + ' li > ul:-moz-first-node, li > ol:-moz-first-node { padding-top: 1.2em; }\n' + ' li { min-height: 1.2em; }\n' + //' p,ul,li { padding-top: 0; padding-bottom: 0; margin-top:0; margin-bottom: 0; }\n' + '', this.document); tmpContent.parentNode.removeChild(tmpContent); this.document.body.innerHTML = html; if(oldMoz||dojo.render.html.safari){ this.document.designMode = "on"; } this.onLoad(); }else{ tmpContent.parentNode.removeChild(tmpContent); this.editNode.innerHTML = html; this.onDisplayChanged(); } }); if(this.editNode){ ifrFunc(); // iframe already exists, just set content }else if(dojo.render.html.moz){ // FIXME: if we put this on a delay, we get a height of 20px. // Otherwise we get the correctly specified minHeight value. this.iframe.onload = function(){ setTimeout(ifrFunc, 250); } }else{ // new mozillas, opera, safari this.iframe.onload = ifrFunc; } }, _applyEditingAreaStyleSheets: function(){ // summary: // apply the specified css files in styleSheets var files = []; if(this.styleSheets){ files = this.styleSheets.split(';'); } //empty this.editingAreaStyleSheets here, as it will be filled in addStyleSheet files = files.concat(this.editingAreaStyleSheets); this.editingAreaStyleSheets = []; if(files.length>0){ for(var i=0;i<files.length;i++){ var url = files[i]; if(url){ this.addStyleSheet(new dojo.uri.Uri(url)); } } } }, addStyleSheet: function(/*dojo.uri.Uri*/uri) { // summary: // add an external stylesheet for the editing area // uri: a dojo.uri.Uri pointing to the url of the external css file var url=uri.toString(); if(dojo.lang.find(this.editingAreaStyleSheets, url) > -1){ dojo.debug("dojo.widget.RichText.addStyleSheet: Style sheet "+url+" is already applied to the editing area!"); return; } //if uri is relative, then convert it to absolute so that it can be resolved correctly in iframe if(url.charAt(0) == '.' || (url.charAt(0) != '/' && !uri.host)){ url = (new dojo.uri.Uri(dojo.global().location, url)).toString(); } this.editingAreaStyleSheets.push(url); if(this.document.createStyleSheet){ //IE this.document.createStyleSheet(url); }else{ //other browser var head = this.document.getElementsByTagName("head")[0]; var stylesheet = this.document.createElement("link"); with(stylesheet){ rel="stylesheet"; type="text/css"; href=url; } head.appendChild(stylesheet); } }, removeStyleSheet: function (/*dojo.uri.Uri*/uri) { // summary: // remove an external stylesheet for the editing area var url=uri.toString(); var index = dojo.lang.find(this.editingAreaStyleSheets, url); if(index == -1){ dojo.debug("dojo.widget.RichText.removeStyleSheet: Style sheet "+url+" is not applied to the editing area so it can not be removed!"); return; } delete this.editingAreaStyleSheets[index]; var links = this.document.getElementsByTagName("link"); for(var i=0;i<links.length;i++){ if(links[i].href == url){ if(dojo.render.html.ie){//we need to empty the href first, to get IE to remove the rendered styles links[i].href=""; } dojo.html.removeNode(links[i]); break; } } }, _drawObject: function (/*String*/html) { // summary: // Draws an active x object, used by IE this.object = dojo.html.createExternalElement(dojo.doc(), "object"); with (this.object) { classid = "clsid:2D360201-FFF5-11D1-8D03-00A0C959BC0A"; width = this.inheritWidth ? this._oldWidth : "100%"; style.height = this.height ? this.height : (this._oldHeight+"px"); Scrollbars = this.height ? true : false; Appearance = this._activeX.appearance.flat; } this.editorObject = this.object; this.editingArea.appendChild(this.object); this.object.attachEvent("DocumentComplete", dojo.lang.hitch(this, "onLoad")); //DisplayChanged is fired too often even no change is made, so we ignore it //and call onDisplayChanged manually in execCommand instead// this.object.attachEvent("DisplayChanged", dojo.lang.hitch(this, "onDisplayChanged")); dojo.lang.forEach(this.events, function(e){ this.object.attachEvent(e.toLowerCase(), dojo.lang.hitch(this, e)); }, this); this.object.DocumentHTML = '<!doctype HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">' + '<html><title></title>' + '<style type="text/css">' + ' body,html { padding: 0; margin: 0; }' + //font: ' + font + '; }' + (this.height ? '' : ' body, { overflow: hidden; }') + '</style>' + //'<base href="' + dojo.global().location + '">' + '<body><div>' + html + '<div></body></html>'; this._cacheLocalBlockFormatNames(); }, //static cache variables shared among all instance of this class _local2NativeFormatNames: {}, _native2LocalFormatNames: {}, //in IE, names for blockformat is locale dependent, so we cache the values here //we use activeX to obtain the list, if success or the names are already cached, //return true _cacheLocalBlockFormatNames: function(){ // summary: // in IE, names for blockformat is locale dependent, so we cache the values here // we use activeX to obtain the list, if success or the names are already cached, // return true if(!this._native2LocalFormatNames['p']){ var obj = this.object; if(!obj){ //create obj temporarily try{ obj = dojo.html.createExternalElement(dojo.doc(), "object"); obj.classid = "clsid:2D360201-FFF5-11D1-8D03-00A0C959BC0A"; dojo.body().appendChild(obj); obj.DocumentHTML = "<html><head></head><body></body></html>"; }catch(e){ return false; } } var oNamesParm = new ActiveXObject("DEGetBlockFmtNamesParam.DEGetBlockFmtNamesParam"); obj.ExecCommand(this._activeX.command['getblockformatnames'], 0, oNamesParm); var vbNamesArray = new VBArray(oNamesParm.Names); var localFormats = vbNamesArray.toArray(); var nativeFormats = ['p', 'pre', 'address', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'ol', 'ul', '', '', '','','div']; for(var i=0;i<nativeFormats.length;++i){ if(nativeFormats[i].length>0){ this._local2NativeFormatNames[localFormats[i]] = nativeFormats[i]; this._native2LocalFormatNames[nativeFormats[i]] = localFormats[i]; } } if(!this.object){ //delete the temporary obj dojo.body().removeChild(obj); } } return true; }, /* Event handlers *****************/ _isResized: function(){ return false; }, onLoad: function(e){ // summary: handler after the content of the document finishes loading this.isLoaded = true; if (this.object){ this.document = this.object.DOM; this.window = this.document.parentWindow; this.editNode = this.document.body.firstChild; this.editingArea.style.height = this.height ? this.height : this.minHeight; this.connect(this, "onDisplayChanged", "_updateHeight"); //pretend the object as an iframe, so that the context menu for the //editor can be placed correctly when shown this.window._frameElement = this.object; }else if (this.iframe && !dojo.render.html.ie){ this.editNode = this.document.body; this.connect(this, "onDisplayChanged", "_updateHeight"); try { // sanity check for Mozilla this.document.execCommand("useCSS", false, true); // old moz call this.document.execCommand("styleWithCSS", false, false); // new moz call //this.document.execCommand("insertBrOnReturn", false, false); // new moz call }catch(e2){ } if (dojo.render.html.safari) { /* this.iframe.style.visiblity = "visible"; this.iframe.style.border = "1px solid black"; this.editNode.style.visiblity = "visible"; this.editNode.style.border = "1px solid black"; */ // this.onDisplayChanged(); this.connect(this.editNode, "onblur", "onBlur"); this.connect(this.editNode, "onfocus", "onFocus"); this.connect(this.editNode, "onclick", "onFocus"); this.interval = setInterval(dojo.lang.hitch(this, "onDisplayChanged"), 750); // dojo.raise("onload"); // dojo.debug(this.editNode.parentNode.parentNode.parentNode.nodeName); } else if (dojo.render.html.mozilla || dojo.render.html.opera) { var doc = this.document; var addListener = dojo.event.browser.addListener; var self = this; dojo.lang.forEach(this.events, function(e){ var l = addListener(self.document, e.substr(2).toLowerCase(), dojo.lang.hitch(self, e)); if(e=="onBlur"){ // We need to unhook the blur event listener on close as we // can encounter a garunteed crash in FF if another event is // also fired var unBlur = { unBlur: function(e){ dojo.event.browser.removeListener(doc, "blur", l); } }; dojo.event.connect("before", self, "close", unBlur, "unBlur"); } }); } // FIXME: when scrollbars appear/disappear this needs to be fired }else if(dojo.render.html.ie){ // IE contentEditable this.connect(this, "onDisplayChanged", "_updateHeight"); this.editNode.style.zoom = 1.0; } this._applyEditingAreaStyleSheets(); if(this.focusOnLoad){ this.focus(); } this.onDisplayChanged(e); }, onKeyDown: function(e){ // summary: Fired on keydown if((!e)&&(this.object)){ e = dojo.event.browser.fixEvent(this.window.event); } // dojo.debug("onkeydown:", e.keyCode); // we need this event at the moment to get the events from control keys // such as the backspace. It might be possible to add this to Dojo, so that // keyPress events can be emulated by the keyDown and keyUp detection. if((dojo.render.html.ie)&&(e.keyCode == e.KEY_TAB)){ e.preventDefault(); e.stopPropagation(); // FIXME: this is a poor-man's indent/outdent. It would be // better if it added 4 " " chars in an undoable way. // Unfortuantly pasteHTML does not prove to be undoable this.execCommand((e.shiftKey ? "outdent" : "indent")); }else if(dojo.render.html.ie){ if((65 <= e.keyCode)&&(e.keyCode <= 90)){ e.charCode = e.keyCode; this.onKeyPress(e); } // dojo.debug(e.ctrlKey); // dojo.debug(e.keyCode); // dojo.debug(e.charCode); // this.onKeyPress(e); } }, onKeyUp: function(e){ // summary: Fired on keyup return; }, KEY_CTRL: 1,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -