diff options
author | Andrew Dolgov <[email protected]> | 2012-08-14 18:59:10 +0400 |
---|---|---|
committer | Andrew Dolgov <[email protected]> | 2012-08-14 18:59:18 +0400 |
commit | 1354d17270961fff662d40f90521223f8fd0d73b (patch) | |
tree | e9266be71587e47c800303446e968a6d3565e2cf /lib/dijit/_editor/RichText.js | |
parent | d04f8c826f5283765f52cf6b98b42a1ed8f2d6bc (diff) |
update dojo to 1.7.3
Diffstat (limited to 'lib/dijit/_editor/RichText.js')
-rw-r--r-- | lib/dijit/_editor/RichText.js | 2098 |
1 files changed, 2 insertions, 2096 deletions
diff --git a/lib/dijit/_editor/RichText.js b/lib/dijit/_editor/RichText.js index 978371557..afa4a944d 100644 --- a/lib/dijit/_editor/RichText.js +++ b/lib/dijit/_editor/RichText.js @@ -1,2096 +1,2 @@ -/* - Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved. - Available via Academic Free License >= 2.1 OR the modified BSD license. - see: http://dojotoolkit.org/license for details -*/ - - -if(!dojo._hasResource["dijit._editor.RichText"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. -dojo._hasResource["dijit._editor.RichText"] = true; -dojo.provide("dijit._editor.RichText"); -dojo.require("dijit._Widget"); -dojo.require("dijit._CssStateMixin"); -dojo.require("dijit._editor.selection"); -dojo.require("dijit._editor.range"); -dojo.require("dijit._editor.html"); - - -// used to restore content when user leaves this page then comes back -// but do not try doing dojo.doc.write if we are using xd loading. -// dojo.doc.write will only work if RichText.js is included in the dojo.js -// file. If it is included in dojo.js and you want to allow rich text saving -// for back/forward actions, then set dojo.config.allowXdRichTextSave = true. -if(!dojo.config["useXDomain"] || dojo.config["allowXdRichTextSave"]){ - if(dojo._postLoad){ - (function(){ - var savetextarea = dojo.doc.createElement('textarea'); - savetextarea.id = dijit._scopeName + "._editor.RichText.value"; - dojo.style(savetextarea, { - display:'none', - position:'absolute', - top:"-100px", - height:"3px", - width:"3px" - }); - dojo.body().appendChild(savetextarea); - })(); - }else{ - //dojo.body() is not available before onLoad is fired - try{ - dojo.doc.write('<textarea id="' + dijit._scopeName + '._editor.RichText.value" ' + - 'style="display:none;position:absolute;top:-100px;left:-100px;height:3px;width:3px;overflow:hidden;"></textarea>'); - }catch(e){ } - } -} - -dojo.declare("dijit._editor.RichText", [dijit._Widget, dijit._CssStateMixin], { - constructor: function(params){ - // summary: - // dijit._editor.RichText is the core of dijit.Editor, which provides basic - // WYSIWYG editing features. - // - // description: - // dijit._editor.RichText is the core of dijit.Editor, which provides basic - // WYSIWYG editing features. It also encapsulates the differences - // of different js engines for various browsers. Do not use this widget - // with an HTML <TEXTAREA> tag, since the browser unescapes XML escape characters, - // like <. This can have unexpected behavior and lead to security issues - // such as scripting attacks. - // - // tags: - // private - - // contentPreFilters: Function(String)[] - // Pre content filter function register array. - // these filters will be executed before the actual - // editing area gets the html content. - this.contentPreFilters = []; - - // contentPostFilters: Function(String)[] - // post content filter function register array. - // These will be used on the resulting html - // from contentDomPostFilters. The resulting - // content is the final html (returned by getValue()). - this.contentPostFilters = []; - - // contentDomPreFilters: Function(DomNode)[] - // Pre content dom filter function register array. - // These filters are applied after the result from - // contentPreFilters are set to the editing area. - this.contentDomPreFilters = []; - - // contentDomPostFilters: Function(DomNode)[] - // Post content dom filter function register array. - // These filters are executed on the editing area dom. - // The result from these will be passed to contentPostFilters. - this.contentDomPostFilters = []; - - // editingAreaStyleSheets: dojo._URL[] - // array to store all the stylesheets applied to the editing area - this.editingAreaStyleSheets = []; - - // Make a copy of this.events before we start writing into it, otherwise we - // will modify the prototype which leads to bad things on pages w/multiple editors - this.events = [].concat(this.events); - - this._keyHandlers = {}; - - if(params && dojo.isString(params.value)){ - this.value = params.value; - } - - this.onLoadDeferred = new dojo.Deferred(); - }, - - baseClass: "dijitEditor", - - // inheritWidth: Boolean - // whether to inherit the parent's width or simply use 100% - inheritWidth: false, - - // focusOnLoad: [deprecated] Boolean - // Focus into this widget when the page is loaded - focusOnLoad: false, - - // name: String? - // Specifies the name of a (hidden) <textarea> node on the page that's used to save - // the editor content on page leave. Used to restore editor contents after navigating - // to a new page and then hitting the back button. - name: "", - - // styleSheets: [const] String - // semicolon (";") separated list of css files for the editing area - styleSheets: "", - - // height: String - // Set height to fix the editor at a specific height, with scrolling. - // By default, this is 300px. If you want to have the editor always - // resizes to accommodate the content, use AlwaysShowToolbar plugin - // and set height="". If this editor is used within a layout widget, - // set height="100%". - height: "300px", - - // minHeight: String - // The minimum height that the editor should have. - minHeight: "1em", - - // isClosed: [private] Boolean - isClosed: true, - - // isLoaded: [private] Boolean - isLoaded: false, - - // _SEPARATOR: [private] String - // Used to concat contents from multiple editors into a single string, - // so they can be saved into a single <textarea> node. See "name" attribute. - _SEPARATOR: "@@**%%__RICHTEXTBOUNDRY__%%**@@", - - // _NAME_CONTENT_SEP: [private] String - // USed to separate name from content. Just a colon isn't safe. - _NAME_CONTENT_SEP: "@@**%%:%%**@@", - - // onLoadDeferred: [readonly] dojo.Deferred - // Deferred which is fired when the editor finishes loading. - // Call myEditor.onLoadDeferred.then(callback) it to be informed - // when the rich-text area initialization is finalized. - onLoadDeferred: null, - - // isTabIndent: Boolean - // Make tab key and shift-tab indent and outdent rather than navigating. - // Caution: sing this makes web pages inaccessible to users unable to use a mouse. - isTabIndent: false, - - // disableSpellCheck: [const] Boolean - // When true, disables the browser's native spell checking, if supported. - // Works only in Firefox. - disableSpellCheck: false, - - postCreate: function(){ - if("textarea" == this.domNode.tagName.toLowerCase()){ - console.warn("RichText should not be used with the TEXTAREA tag. See dijit._editor.RichText docs."); - } - - // Push in the builtin filters now, making them the first executed, but not over-riding anything - // users passed in. See: #6062 - this.contentPreFilters = [dojo.hitch(this, "_preFixUrlAttributes")].concat(this.contentPreFilters); - if(dojo.isMoz){ - this.contentPreFilters = [this._normalizeFontStyle].concat(this.contentPreFilters); - this.contentPostFilters = [this._removeMozBogus].concat(this.contentPostFilters); - } - if(dojo.isWebKit){ - // Try to clean up WebKit bogus artifacts. The inserted classes - // made by WebKit sometimes messes things up. - this.contentPreFilters = [this._removeWebkitBogus].concat(this.contentPreFilters); - this.contentPostFilters = [this._removeWebkitBogus].concat(this.contentPostFilters); - } - if(dojo.isIE){ - // IE generates <strong> and <em> but we want to normalize to <b> and <i> - this.contentPostFilters = [this._normalizeFontStyle].concat(this.contentPostFilters); - } - this.inherited(arguments); - - dojo.publish(dijit._scopeName + "._editor.RichText::init", [this]); - this.open(); - this.setupDefaultShortcuts(); - }, - - setupDefaultShortcuts: function(){ - // summary: - // Add some default key handlers - // description: - // Overwrite this to setup your own handlers. The default - // implementation does not use Editor commands, but directly - // executes the builtin commands within the underlying browser - // support. - // tags: - // protected - var exec = dojo.hitch(this, function(cmd, arg){ - return function(){ - return !this.execCommand(cmd,arg); - }; - }); - - var ctrlKeyHandlers = { - b: exec("bold"), - i: exec("italic"), - u: exec("underline"), - a: exec("selectall"), - s: function(){ this.save(true); }, - m: function(){ this.isTabIndent = !this.isTabIndent; }, - - "1": exec("formatblock", "h1"), - "2": exec("formatblock", "h2"), - "3": exec("formatblock", "h3"), - "4": exec("formatblock", "h4"), - - "\\": exec("insertunorderedlist") - }; - - if(!dojo.isIE){ - ctrlKeyHandlers.Z = exec("redo"); //FIXME: undo? - } - - for(var key in ctrlKeyHandlers){ - this.addKeyHandler(key, true, false, ctrlKeyHandlers[key]); - } - }, - - // events: [private] String[] - // events which should be connected to the underlying editing area - events: ["onKeyPress", "onKeyDown", "onKeyUp"], // onClick handled specially - - // captureEvents: [deprecated] String[] - // Events which should be connected to the underlying editing - // area, events in this array will be addListener with - // capture=true. - // TODO: looking at the code I don't see any distinction between events and captureEvents, - // so get rid of this for 2.0 if not sooner - captureEvents: [], - - _editorCommandsLocalized: false, - _localizeEditorCommands: function(){ - // summary: - // When IE is running in a non-English locale, the API actually changes, - // so that we have to say (for example) danraku instead of p (for paragraph). - // Handle that here. - // tags: - // private - if(dijit._editor._editorCommandsLocalized){ - // Use the already generate cache of mappings. - this._local2NativeFormatNames = dijit._editor._local2NativeFormatNames; - this._native2LocalFormatNames = dijit._editor._native2LocalFormatNames; - return; - } - dijit._editor._editorCommandsLocalized = true; - dijit._editor._local2NativeFormatNames = {}; - dijit._editor._native2LocalFormatNames = {}; - this._local2NativeFormatNames = dijit._editor._local2NativeFormatNames; - this._native2LocalFormatNames = dijit._editor._native2LocalFormatNames; - //in IE, names for blockformat is locale dependent, so we cache the values here - - //put p after div, so if IE returns Normal, we show it as paragraph - //We can distinguish p and div if IE returns Normal, however, in order to detect that, - //we have to call this.document.selection.createRange().parentElement() or such, which - //could slow things down. Leave it as it is for now - var formats = ['div', 'p', 'pre', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'ol', 'ul', 'address']; - var localhtml = "", format, i=0; - while((format=formats[i++])){ - //append a <br> after each element to separate the elements more reliably - if(format.charAt(1) !== 'l'){ - localhtml += "<"+format+"><span>content</span></"+format+"><br/>"; - }else{ - localhtml += "<"+format+"><li>content</li></"+format+"><br/>"; - } - } - // queryCommandValue returns empty if we hide editNode, so move it out of screen temporary - // Also, IE9 does weird stuff unless we do it inside the editor iframe. - var style = { position: "absolute", top: "0px", zIndex: 10, opacity: 0.01 }; - var div = dojo.create('div', {style: style, innerHTML: localhtml}); - dojo.body().appendChild(div); - - // IE9 has a timing issue with doing this right after setting - // the inner HTML, so put a delay in. - var inject = dojo.hitch(this, function(){ - var node = div.firstChild; - while(node){ - try{ - dijit._editor.selection.selectElement(node.firstChild); - var nativename = node.tagName.toLowerCase(); - this._local2NativeFormatNames[nativename] = document.queryCommandValue("formatblock"); - this._native2LocalFormatNames[this._local2NativeFormatNames[nativename]] = nativename; - node = node.nextSibling.nextSibling; - //console.log("Mapped: ", nativename, " to: ", this._local2NativeFormatNames[nativename]); - }catch(e) { /*Sqelch the occasional IE9 error */ } - } - div.parentNode.removeChild(div); - div.innerHTML = ""; - }); - setTimeout(inject, 0); - }, - - open: function(/*DomNode?*/ element){ - // summary: - // Transforms the node referenced in this.domNode into a rich text editing - // node. - // description: - // Sets up the editing area asynchronously. This will result in - // the creation and replacement with an iframe. - // tags: - // private - - if(!this.onLoadDeferred || this.onLoadDeferred.fired >= 0){ - this.onLoadDeferred = new dojo.Deferred(); - } - - if(!this.isClosed){ this.close(); } - dojo.publish(dijit._scopeName + "._editor.RichText::open", [ this ]); - - if(arguments.length == 1 && element.nodeName){ // else unchanged - this.domNode = element; - } - - var dn = this.domNode; - - // "html" will hold the innerHTML of the srcNodeRef and will be used to - // initialize the editor. - var html; - - if(dojo.isString(this.value)){ - // Allow setting the editor content programmatically instead of - // relying on the initial content being contained within the target - // domNode. - html = this.value; - delete this.value; - dn.innerHTML = ""; - }else if(dn.nodeName && dn.nodeName.toLowerCase() == "textarea"){ - // if we were created from a textarea, then we need to create a - // new editing harness node. - var ta = (this.textarea = dn); - this.name = ta.name; - html = ta.value; - dn = this.domNode = dojo.doc.createElement("div"); - dn.setAttribute('widgetId', this.id); - ta.removeAttribute('widgetId'); - dn.cssText = ta.cssText; - dn.className += " " + ta.className; - dojo.place(dn, ta, "before"); - var tmpFunc = dojo.hitch(this, function(){ - //some browsers refuse to submit display=none textarea, so - //move the textarea off screen instead - dojo.style(ta, { - display: "block", - position: "absolute", - top: "-1000px" - }); - - if(dojo.isIE){ //nasty IE bug: abnormal formatting if overflow is not hidden - var s = ta.style; - this.__overflow = s.overflow; - s.overflow = "hidden"; - } - }); - if(dojo.isIE){ - setTimeout(tmpFunc, 10); - }else{ - tmpFunc(); - } - - if(ta.form){ - var resetValue = ta.value; - this.reset = function(){ - var current = this.getValue(); - if(current != resetValue){ - this.replaceValue(resetValue); - } - }; - dojo.connect(ta.form, "onsubmit", this, function(){ - // Copy value to the <textarea> so it gets submitted along with form. - // FIXME: should we be calling close() here instead? - dojo.attr(ta, 'disabled', this.disabled); // don't submit the value if disabled - ta.value = this.getValue(); - }); - } - }else{ - html = dijit._editor.getChildrenHtml(dn); - dn.innerHTML = ""; - } - - var content = dojo.contentBox(dn); - this._oldHeight = content.h; - this._oldWidth = content.w; - - this.value = html; - - // 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(dn.nodeName && dn.nodeName == "LI"){ - dn.innerHTML = " <br>"; - } - - // Construct the editor div structure. - this.header = dn.ownerDocument.createElement("div"); - dn.appendChild(this.header); - this.editingArea = dn.ownerDocument.createElement("div"); - dn.appendChild(this.editingArea); - this.footer = dn.ownerDocument.createElement("div"); - dn.appendChild(this.footer); - - if(!this.name){ - this.name = this.id + "_AUTOGEN"; - } - - // User has pressed back/forward button so we lost the text in the editor, but it's saved - // in a hidden <textarea> (which contains the data for all the editors on this page), - // so get editor value from there - if(this.name !== "" && (!dojo.config["useXDomain"] || dojo.config["allowXdRichTextSave"])){ - var saveTextarea = dojo.byId(dijit._scopeName + "._editor.RichText.value"); - if(saveTextarea && saveTextarea.value !== ""){ - var datas = saveTextarea.value.split(this._SEPARATOR), i=0, dat; - while((dat=datas[i++])){ - var data = dat.split(this._NAME_CONTENT_SEP); - if(data[0] == this.name){ - html = data[1]; - datas = datas.splice(i, 1); - saveTextarea.value = datas.join(this._SEPARATOR); - break; - } - } - } - - if(!dijit._editor._globalSaveHandler){ - dijit._editor._globalSaveHandler = {}; - dojo.addOnUnload(function() { - var id; - for(id in dijit._editor._globalSaveHandler){ - var f = dijit._editor._globalSaveHandler[id]; - if(dojo.isFunction(f)){ - f(); - } - } - }); - } - dijit._editor._globalSaveHandler[this.id] = dojo.hitch(this, "_saveContent"); - } - - this.isClosed = false; - - var ifr = (this.editorObject = this.iframe = dojo.doc.createElement('iframe')); - ifr.id = this.id+"_iframe"; - this._iframeSrc = this._getIframeDocTxt(); - ifr.style.border = "none"; - ifr.style.width = "100%"; - if(this._layoutMode){ - // iframe should be 100% height, thus getting it's height from surrounding - // <div> (which has the correct height set by Editor) - ifr.style.height = "100%"; - }else{ - if(dojo.isIE >= 7){ - if(this.height){ - ifr.style.height = this.height; - } - if(this.minHeight){ - ifr.style.minHeight = this.minHeight; - } - }else{ - ifr.style.height = this.height ? this.height : this.minHeight; - } - } - ifr.frameBorder = 0; - ifr._loadFunc = dojo.hitch( this, function(win){ - this.window = win; - this.document = this.window.document; - - if(dojo.isIE){ - this._localizeEditorCommands(); - } - - // Do final setup and set initial contents of editor - this.onLoad(html); - }); - - // Set the iframe's initial (blank) content. - var s = 'javascript:parent.' + dijit._scopeName + '.byId("'+this.id+'")._iframeSrc'; - ifr.setAttribute('src', s); - this.editingArea.appendChild(ifr); - - if(dojo.isSafari <= 4){ - var src = ifr.getAttribute("src"); - if(!src || src.indexOf("javascript") == -1){ - // Safari 4 and earlier sometimes act oddly - // So we have to set it again. - setTimeout(function(){ifr.setAttribute('src', s);},0); - } - } - - // TODO: this is a guess at the default line-height, kinda works - if(dn.nodeName == "LI"){ - dn.lastChild.style.marginTop = "-1.2em"; - } - - dojo.addClass(this.domNode, this.baseClass); - }, - - //static cache variables shared among all instance of this class - _local2NativeFormatNames: {}, - _native2LocalFormatNames: {}, - - _getIframeDocTxt: function(){ - // summary: - // Generates the boilerplate text of the document inside the iframe (ie, <html><head>...</head><body/></html>). - // Editor content (if not blank) should be added afterwards. - // tags: - // private - var _cs = dojo.getComputedStyle(this.domNode); - - // The contents inside of <body>. The real contents are set later via a call to setValue(). - var html = ""; - var setBodyId = true; - if(dojo.isIE || dojo.isWebKit || (!this.height && !dojo.isMoz)){ - // In auto-expand mode, need a wrapper div for AlwaysShowToolbar plugin to correctly - // expand/contract the editor as the content changes. - html = "<div id='dijitEditorBody'></div>"; - setBodyId = false; - }else if(dojo.isMoz){ - // workaround bug where can't select then delete text (until user types something - // into the editor)... and/or issue where typing doesn't erase selected text - this._cursorToStart = true; - html = " "; - } - - var font = [ _cs.fontWeight, _cs.fontSize, _cs.fontFamily ].join(" "); - - // 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 = _cs.lineHeight; - if(lineHeight.indexOf("px") >= 0){ - lineHeight = parseFloat(lineHeight)/parseFloat(_cs.fontSize); - // console.debug(lineHeight); - }else if(lineHeight.indexOf("em")>=0){ - lineHeight = parseFloat(lineHeight); - }else{ - // If we can't get a non-units value, just default - // it to the CSS spec default of 'normal'. Seems to - // work better, esp on IE, than '1.0' - lineHeight = "normal"; - } - var userStyle = ""; - var self = this; - this.style.replace(/(^|;)\s*(line-|font-?)[^;]+/ig, function(match){ - match = match.replace(/^;/ig,"") + ';'; - var s = match.split(":")[0]; - if(s){ - s = dojo.trim(s); - s = s.toLowerCase(); - var i; - var sC = ""; - for(i = 0; i < s.length; i++){ - var c = s.charAt(i); - switch(c){ - case "-": - i++; - c = s.charAt(i).toUpperCase(); - default: - sC += c; - } - } - dojo.style(self.domNode, sC, ""); - } - userStyle += match + ';'; - }); - - - // need to find any associated label element and update iframe document title - var label=dojo.query('label[for="'+this.id+'"]'); - - return [ - this.isLeftToRight() ? "<html>\n<head>\n" : "<html dir='rtl'>\n<head>\n", - (dojo.isMoz && label.length ? "<title>" + label[0].innerHTML + "</title>\n" : ""), - "<meta http-equiv='Content-Type' content='text/html'>\n", - "<style>\n", - "\tbody,html {\n", - "\t\tbackground:transparent;\n", - "\t\tpadding: 1px 0 0 0;\n", - "\t\tmargin: -1px 0 0 0;\n", // remove extraneous vertical scrollbar on safari and firefox - - // Set the html/body sizing. Webkit always needs this, other browsers - // only set it when height is defined (not auto-expanding), otherwise - // scrollers do not appear. - ((dojo.isWebKit)?"\t\twidth: 100%;\n":""), - ((dojo.isWebKit)?"\t\theight: 100%;\n":""), - "\t}\n", - - // TODO: left positioning will cause contents to disappear out of view - // if it gets too wide for the visible area - "\tbody{\n", - "\t\ttop:0px;\n", - "\t\tleft:0px;\n", - "\t\tright:0px;\n", - "\t\tfont:", font, ";\n", - ((this.height||dojo.isOpera) ? "" : "\t\tposition: fixed;\n"), - // FIXME: IE 6 won't understand min-height? - "\t\tmin-height:", this.minHeight, ";\n", - "\t\tline-height:", lineHeight,";\n", - "\t}\n", - "\tp{ margin: 1em 0; }\n", - - // Determine how scrollers should be applied. In autoexpand mode (height = "") no scrollers on y at all. - // But in fixed height mode we want both x/y scrollers. Also, if it's using wrapping div and in auto-expand - // (Mainly IE) we need to kill the y scroller on body and html. - (!setBodyId && !this.height ? "\tbody,html {overflow-y: hidden;}\n" : ""), - "\t#dijitEditorBody{overflow-x: auto; overflow-y:" + (this.height ? "auto;" : "hidden;") + " outline: 0px;}\n", - "\tli > ul:-moz-first-node, li > ol:-moz-first-node{ padding-top: 1.2em; }\n", - // Can't set min-height in IE9, it puts layout on li, which puts move/resize handles. - (!dojo.isIE ? "\tli{ min-height:1.2em; }\n" : ""), - "</style>\n", - this._applyEditingAreaStyleSheets(),"\n", - "</head>\n<body ", - (setBodyId?"id='dijitEditorBody' ":""), - "onload='frameElement._loadFunc(window,document)' style='"+userStyle+"'>", html, "</body>\n</html>" - ].join(""); // String - }, - - _applyEditingAreaStyleSheets: function(){ - // summary: - // apply the specified css files in styleSheets - // tags: - // private - var files = []; - if(this.styleSheets){ - files = this.styleSheets.split(';'); - this.styleSheets = ''; - } - - //empty this.editingAreaStyleSheets here, as it will be filled in addStyleSheet - files = files.concat(this.editingAreaStyleSheets); - this.editingAreaStyleSheets = []; - - var text='', i=0, url; - while((url=files[i++])){ - var abstring = (new dojo._Url(dojo.global.location, url)).toString(); - this.editingAreaStyleSheets.push(abstring); - text += '<link rel="stylesheet" type="text/css" href="'+abstring+'"/>'; - } - return text; - }, - - addStyleSheet: function(/*dojo._Url*/ 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 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._Url(dojo.global.location, url)).toString(); - } - - if(dojo.indexOf(this.editingAreaStyleSheets, url) > -1){ -// console.debug("dijit._editor.RichText.addStyleSheet: Style sheet "+url+" is already applied"); - return; - } - - this.editingAreaStyleSheets.push(url); - this.onLoadDeferred.addCallback(dojo.hitch(this, function(){ - 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"); - stylesheet.rel="stylesheet"; - stylesheet.type="text/css"; - stylesheet.href=url; - head.appendChild(stylesheet); - } - })); - }, - - removeStyleSheet: function(/*dojo._Url*/ uri){ - // summary: - // remove an external stylesheet for the editing area - var url=uri.toString(); - //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._Url(dojo.global.location, url)).toString(); - } - var index = dojo.indexOf(this.editingAreaStyleSheets, url); - if(index == -1){ -// console.debug("dijit._editor.RichText.removeStyleSheet: Style sheet "+url+" has not been applied"); - return; - } - delete this.editingAreaStyleSheets[index]; - dojo.withGlobal(this.window,'query', dojo, ['link:[href="'+url+'"]']).orphan(); - }, - - // disabled: Boolean - // The editor is disabled; the text cannot be changed. - disabled: false, - - _mozSettingProps: {'styleWithCSS':false}, - _setDisabledAttr: function(/*Boolean*/ value){ - value = !!value; - this._set("disabled", value); - if(!this.isLoaded){ return; } // this method requires init to be complete - if(dojo.isIE || dojo.isWebKit || dojo.isOpera){ - var preventIEfocus = dojo.isIE && (this.isLoaded || !this.focusOnLoad); - if(preventIEfocus){ this.editNode.unselectable = "on"; } - this.editNode.contentEditable = !value; - if(preventIEfocus){ - var _this = this; - setTimeout(function(){ _this.editNode.unselectable = "off"; }, 0); - } - }else{ //moz - try{ - this.document.designMode=(value?'off':'on'); - }catch(e){ return; } // ! _disabledOK - if(!value && this._mozSettingProps){ - var ps = this._mozSettingProps; - for(var n in ps){ - if(ps.hasOwnProperty(n)){ - try{ - this.document.execCommand(n,false,ps[n]); - }catch(e2){} - } - } - } -// this.document.execCommand('contentReadOnly', false, value); -// if(value){ -// this.blur(); //to remove the blinking caret -// } - } - this._disabledOK = true; - }, - -/* Event handlers - *****************/ - - onLoad: function(/*String*/ html){ - // summary: - // Handler after the iframe finishes loading. - // html: String - // Editor contents should be set to this value - // tags: - // protected - - // TODO: rename this to _onLoad, make empty public onLoad() method, deprecate/make protected onLoadDeferred handler? - - if(!this.window.__registeredWindow){ - this.window.__registeredWindow = true; - this._iframeRegHandle = dijit.registerIframe(this.iframe); - } - if(!dojo.isIE && !dojo.isWebKit && (this.height || dojo.isMoz)){ - this.editNode=this.document.body; - }else{ - // there's a wrapper div around the content, see _getIframeDocTxt(). - this.editNode=this.document.body.firstChild; - var _this = this; - if(dojo.isIE){ // #4996 IE wants to focus the BODY tag - this.tabStop = dojo.create('div', { tabIndex: -1 }, this.editingArea); - this.iframe.onfocus = function(){ _this.editNode.setActive(); }; - } - } - this.focusNode = this.editNode; // for InlineEditBox - - - var events = this.events.concat(this.captureEvents); - var ap = this.iframe ? this.document : this.editNode; - dojo.forEach(events, function(item){ - this.connect(ap, item.toLowerCase(), item); - }, this); - - this.connect(ap, "onmouseup", "onClick"); // mouseup in the margin does not generate an onclick event - - if(dojo.isIE){ // IE contentEditable - this.connect(this.document, "onmousedown", "_onIEMouseDown"); // #4996 fix focus - - // give the node Layout on IE - // TODO: this may no longer be needed, since we've reverted IE to using an iframe, - // not contentEditable. Removing it would also probably remove the need for creating - // the extra <div> in _getIframeDocTxt() - this.editNode.style.zoom = 1.0; - }else{ - this.connect(this.document, "onmousedown", function(){ - // Clear the moveToStart focus, as mouse - // down will set cursor point. Required to properly - // work with selection/position driven plugins and clicks in - // the window. refs: #10678 - delete this._cursorToStart; - }); - } - - if(dojo.isWebKit){ - //WebKit sometimes doesn't fire right on selections, so the toolbar - //doesn't update right. Therefore, help it out a bit with an additional - //listener. A mouse up will typically indicate a display change, so fire this - //and get the toolbar to adapt. Reference: #9532 - this._webkitListener = this.connect(this.document, "onmouseup", "onDisplayChanged"); - this.connect(this.document, "onmousedown", function(e){ - var t = e.target; - if(t && (t === this.document.body || t === this.document)){ - // Since WebKit uses the inner DIV, we need to check and set position. - // See: #12024 as to why the change was made. - setTimeout(dojo.hitch(this, "placeCursorAtEnd"), 0); - } - }); - } - - if(dojo.isIE){ - // Try to make sure 'hidden' elements aren't visible in edit mode (like browsers other than IE - // do). See #9103 - try{ - this.document.execCommand('RespectVisibilityInDesign', true, null); - }catch(e){/* squelch */} - } - - this.isLoaded = true; - - this.set('disabled', this.disabled); // initialize content to editable (or not) - - // Note that setValue() call will only work after isLoaded is set to true (above) - - // Set up a function to allow delaying the setValue until a callback is fired - // This ensures extensions like dijit.Editor have a way to hold the value set - // until plugins load (and do things like register filters). - var setContent = dojo.hitch(this, function(){ - this.setValue(html); - if(this.onLoadDeferred){ - this.onLoadDeferred.callback(true); - } - this.onDisplayChanged(); - if(this.focusOnLoad){ - // after the document loads, then set focus after updateInterval expires so that - // onNormalizedDisplayChanged has run to avoid input caret issues - dojo.addOnLoad(dojo.hitch(this, function(){ setTimeout(dojo.hitch(this, "focus"), this.updateInterval); })); - } - // Save off the initial content now - this.value = this.getValue(true); - }); - if(this.setValueDeferred){ - this.setValueDeferred.addCallback(setContent); - }else{ - setContent(); - } - }, - - onKeyDown: function(/* Event */ e){ - // summary: - // Handler for onkeydown event - // tags: - // protected - - // 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(e.keyCode === dojo.keys.TAB && this.isTabIndent ){ - dojo.stopEvent(e); //prevent tab from moving focus out of editor - - // FIXME: this is a poor-man's indent/outdent. It would be - // better if it added 4 " " chars in an undoable way. - // Unfortunately pasteHTML does not prove to be undoable - if(this.queryCommandEnabled((e.shiftKey ? "outdent" : "indent"))){ - this.execCommand((e.shiftKey ? "outdent" : "indent")); - } - } - if(dojo.isIE){ - if(e.keyCode == dojo.keys.TAB && !this.isTabIndent){ - if(e.shiftKey && !e.ctrlKey && !e.altKey){ - // focus the BODY so the browser will tab away from it instead - this.iframe.focus(); - }else if(!e.shiftKey && !e.ctrlKey && !e.altKey){ - // focus the BODY so the browser will tab away from it instead - this.tabStop.focus(); - } - }else if(e.keyCode === dojo.keys.BACKSPACE && this.document.selection.type === "Control"){ - // IE has a bug where if a non-text object is selected in the editor, - // hitting backspace would act as if the browser's back button was - // clicked instead of deleting the object. see #1069 - dojo.stopEvent(e); - this.execCommand("delete"); - }else if((65 <= e.keyCode && e.keyCode <= 90) || - (e.keyCode>=37 && e.keyCode<=40) // FIXME: get this from connect() instead! - ){ //arrow keys - e.charCode = e.keyCode; - this.onKeyPress(e); - } - } - return true; - }, - - onKeyUp: function(e){ - // summary: - // Handler for onkeyup event - // tags: - // callback - return; - }, - - setDisabled: function(/*Boolean*/ disabled){ - // summary: - // Deprecated, use set('disabled', ...) instead. - // tags: - // deprecated - dojo.deprecated('dijit.Editor::setDisabled is deprecated','use dijit.Editor::attr("disabled",boolean) instead', 2.0); - this.set('disabled',disabled); - }, - _setValueAttr: function(/*String*/ value){ - // summary: - // Registers that attr("value", foo) should call setValue(foo) - this.setValue(value); - }, - _setDisableSpellCheckAttr: function(/*Boolean*/ disabled){ - if(this.document){ - dojo.attr(this.document.body, "spellcheck", !disabled); - }else{ - // try again after the editor is finished loading - this.onLoadDeferred.addCallback(dojo.hitch(this, function(){ - dojo.attr(this.document.body, "spellcheck", !disabled); - })); - } - this._set("disableSpellCheck", disabled); - }, - - onKeyPress: function(e){ - // summary: - // Handle the various key events - // tags: - // protected - - var c = (e.keyChar && e.keyChar.toLowerCase()) || e.keyCode, - handlers = this._keyHandlers[c], - args = arguments; - - if(handlers && !e.altKey){ - dojo.some(handlers, function(h){ - // treat meta- same as ctrl-, for benefit of mac users - if(!(h.shift ^ e.shiftKey) && !(h.ctrl ^ (e.ctrlKey||e.metaKey))){ - if(!h.handler.apply(this, args)){ - e.preventDefault(); - } - return true; - } - }, this); - } - - // function call after the character has been inserted - if(!this._onKeyHitch){ - this._onKeyHitch = dojo.hitch(this, "onKeyPressed"); - } - setTimeout(this._onKeyHitch, 1); - return true; - }, - - addKeyHandler: function(/*String*/ key, /*Boolean*/ ctrl, /*Boolean*/ shift, /*Function*/ handler){ - // summary: - // Add a handler for a keyboard shortcut - // description: - // The key argument should be in lowercase if it is a letter character - // tags: - // protected - if(!dojo.isArray(this._keyHandlers[key])){ - this._keyHandlers[key] = []; - } - //TODO: would be nice to make this a hash instead of an array for quick lookups - this._keyHandlers[key].push({ - shift: shift || false, - ctrl: ctrl || false, - handler: handler - }); - }, - - onKeyPressed: function(){ - // summary: - // Handler for after the user has pressed a key, and the display has been updated. - // (Runs on a timer so that it runs after the display is updated) - // tags: - // private - this.onDisplayChanged(/*e*/); // can't pass in e - }, - - onClick: function(/*Event*/ e){ - // summary: - // Handler for when the user clicks. - // tags: - // private - - // console.info('onClick',this._tryDesignModeOn); - this.onDisplayChanged(e); - }, - - _onIEMouseDown: function(/*Event*/ e){ - // summary: - // IE only to prevent 2 clicks to focus - // tags: - // protected - - if(!this._focused && !this.disabled){ - this.focus(); - } - }, - - _onBlur: function(e){ - // summary: - // Called from focus manager when focus has moved away from this editor - // tags: - // protected - - // console.info('_onBlur') - - this.inherited(arguments); - - var newValue = this.getValue(true); - if(newValue != this.value){ - this.onChange(newValue); - } - this._set("value", newValue); - }, - - _onFocus: function(/*Event*/ e){ - // summary: - // Called from focus manager when focus has moved into this editor - // tags: - // protected - - // console.info('_onFocus') - if(!this.disabled){ - if(!this._disabledOK){ - this.set('disabled', false); - } - this.inherited(arguments); - } - }, - - // TODO: remove in 2.0 - blur: function(){ - // summary: - // Remove focus from this instance. - // tags: - // deprecated - if(!dojo.isIE && this.window.document.documentElement && this.window.document.documentElement.focus){ - this.window.document.documentElement.focus(); - }else if(dojo.doc.body.focus){ - dojo.doc.body.focus(); - } - }, - - focus: function(){ - // summary: - // Move focus to this editor - if(!this.isLoaded){ - this.focusOnLoad = true; - return; - } - if(this._cursorToStart){ - delete this._cursorToStart; - if(this.editNode.childNodes){ - this.placeCursorAtStart(); // this calls focus() so return - return; - } - } - if(!dojo.isIE){ - dijit.focus(this.iframe); - }else if(this.editNode && this.editNode.focus){ - // editNode may be hidden in display:none div, lets just punt in this case - //this.editNode.focus(); -> causes IE to scroll always (strict and quirks mode) to the top the Iframe - // if we fire the event manually and let the browser handle the focusing, the latest - // cursor position is focused like in FF - this.iframe.fireEvent('onfocus', document.createEventObject()); // createEventObject only in IE - // }else{ - // TODO: should we throw here? - // console.debug("Have no idea how to focus into the editor!"); - } - }, - - // _lastUpdate: 0, - updateInterval: 200, - _updateTimer: null, - onDisplayChanged: function(/*Event*/ e){ - // summary: - // This event will be fired everytime the display context - // changes and the result needs to be reflected in the UI. - // description: - // If you don't want to have update too often, - // onNormalizedDisplayChanged should be used instead - // tags: - // private - - // var _t=new Date(); - if(this._updateTimer){ - clearTimeout(this._updateTimer); - } - if(!this._updateHandler){ - this._updateHandler = dojo.hitch(this,"onNormalizedDisplayChanged"); - } - this._updateTimer = setTimeout(this._updateHandler, this.updateInterval); - - // Technically this should trigger a call to watch("value", ...) registered handlers, - // but getValue() is too slow to call on every keystroke so we don't. - }, - onNormalizedDisplayChanged: function(){ - // summary: - // This event is fired every updateInterval ms or more - // description: - // If something needs to happen immediately after a - // user change, please use onDisplayChanged instead. - // tags: - // private - delete this._updateTimer; - }, - onChange: function(newContent){ - // summary: - // This is fired if and only if the editor loses focus and - // the content is changed. - }, - _normalizeCommand: function(/*String*/ cmd, /*Anything?*/argument){ - // summary: - // Used as the advice function by dojo.connect to map our - // normalized set of commands to those supported by the target - // browser. - // tags: - // private - - var command = cmd.toLowerCase(); - if(command == "formatblock"){ - if(dojo.isSafari && argument === undefined){ command = "heading"; } - }else if(command == "hilitecolor" && !dojo.isMoz){ - command = "backcolor"; - } - - return command; - }, - - _qcaCache: {}, - queryCommandAvailable: function(/*String*/ command){ - // summary: - // Tests whether a command is supported by the host. Clients - // SHOULD check whether a command is supported before attempting - // to use it, behaviour for unsupported commands is undefined. - // command: - // The command to test for - // tags: - // private - - // memoizing version. See _queryCommandAvailable for computing version - var ca = this._qcaCache[command]; - if(ca !== undefined){ return ca; } - return (this._qcaCache[command] = this._queryCommandAvailable(command)); - }, - - _queryCommandAvailable: function(/*String*/ command){ - // summary: - // See queryCommandAvailable(). - // tags: - // private - - var ie = 1; - var mozilla = 1 << 1; - var webkit = 1 << 2; - var opera = 1 << 3; - - function isSupportedBy(browsers){ - return { - ie: Boolean(browsers & ie), - mozilla: Boolean(browsers & mozilla), - webkit: Boolean(browsers & webkit), - opera: Boolean(browsers & opera) - }; - } - - var supportedBy = null; - - switch(command.toLowerCase()){ - case "bold": case "italic": case "underline": - case "subscript": case "superscript": - case "fontname": case "fontsize": - case "forecolor": case "hilitecolor": - case "justifycenter": case "justifyfull": case "justifyleft": - case "justifyright": case "delete": case "selectall": case "toggledir": - supportedBy = isSupportedBy(mozilla | ie | webkit | opera); - break; - - case "createlink": case "unlink": case "removeformat": - case "inserthorizontalrule": case "insertimage": - case "insertorderedlist": case "insertunorderedlist": - case "indent": case "outdent": case "formatblock": - case "inserthtml": case "undo": case "redo": case "strikethrough": case "tabindent": - supportedBy = isSupportedBy(mozilla | ie | opera | webkit); - break; - - case "blockdirltr": case "blockdirrtl": - case "dirltr": case "dirrtl": - case "inlinedirltr": case "inlinedirrtl": - supportedBy = isSupportedBy(ie); - break; - case "cut": case "copy": case "paste": - supportedBy = isSupportedBy( ie | mozilla | webkit); - break; - - case "inserttable": - supportedBy = isSupportedBy(mozilla | ie); - break; - - case "insertcell": case "insertcol": case "insertrow": - case "deletecells": case "deletecols": case "deleterows": - case "mergecells": case "splitcell": - supportedBy = isSupportedBy(ie | mozilla); - break; - - default: return false; - } - - return (dojo.isIE && supportedBy.ie) || - (dojo.isMoz && supportedBy.mozilla) || - (dojo.isWebKit && supportedBy.webkit) || - (dojo.isOpera && supportedBy.opera); // Boolean return true if the command is supported, false otherwise - }, - - execCommand: function(/*String*/ command, argument){ - // summary: - // Executes a command in the Rich Text area - // command: - // The command to execute - // argument: - // An optional argument to the command - // tags: - // protected - var returnValue; - - //focus() is required for IE to work - //In addition, focus() makes sure after the execution of - //the command, the editor receives the focus as expected - this.focus(); - - command = this._normalizeCommand(command, argument); - - if(argument !== undefined){ - if(command == "heading"){ - throw new Error("unimplemented"); - }else if((command == "formatblock") && dojo.isIE){ - argument = '<'+argument+'>'; - } - } - - //Check to see if we have any over-rides for commands, they will be functions on this - //widget of the form _commandImpl. If we don't, fall through to the basic native - //exec command of the browser. - var implFunc = "_" + command + "Impl"; - if(this[implFunc]){ - returnValue = this[implFunc](argument); - }else{ - argument = arguments.length > 1 ? argument : null; - if(argument || command!="createlink"){ - returnValue = this.document.execCommand(command, false, argument); - } - } - - this.onDisplayChanged(); - return returnValue; - }, - - queryCommandEnabled: function(/*String*/ command){ - // summary: - // Check whether a command is enabled or not. - // tags: - // protected - if(this.disabled || !this._disabledOK){ return false; } - command = this._normalizeCommand(command); - if(dojo.isMoz || dojo.isWebKit){ - if(command == "unlink"){ // mozilla returns true always - // console.debug(this._sCall("hasAncestorElement", ['a'])); - return this._sCall("hasAncestorElement", ["a"]); - }else if(command == "inserttable"){ - return true; - } - } - //see #4109 - if(dojo.isWebKit){ - if(command == "cut" || command == "copy") { - // WebKit deems clipboard activity as a security threat and natively would return false - var sel = this.window.getSelection(); - if(sel){ sel = sel.toString(); } - return !!sel; - }else if(command == "paste"){ - return true; - } - } - - var elem = dojo.isIE ? this.document.selection.createRange() : this.document; - try{ - return elem.queryCommandEnabled(command); - }catch(e){ - //Squelch, occurs if editor is hidden on FF 3 (and maybe others.) - return false; - } - - }, - - queryCommandState: function(command){ - // summary: - // Check the state of a given command and returns true or false. - // tags: - // protected - - if(this.disabled || !this._disabledOK){ return false; } - command = this._normalizeCommand(command); - try{ - return this.document.queryCommandState(command); - }catch(e){ - //Squelch, occurs if editor is hidden on FF 3 (and maybe others.) - return false; - } - }, - - queryCommandValue: function(command){ - // summary: - // Check the value of a given command. This matters most for - // custom selections and complex values like font value setting. - // tags: - // protected - - if(this.disabled || !this._disabledOK){ return false; } - var r; - command = this._normalizeCommand(command); - if(dojo.isIE && command == "formatblock"){ - r = this._native2LocalFormatNames[this.document.queryCommandValue(command)]; - }else if(dojo.isMoz && command === "hilitecolor"){ - var oldValue; - try{ - oldValue = this.document.queryCommandValue("styleWithCSS"); - }catch(e){ - oldValue = false; - } - this.document.execCommand("styleWithCSS", false, true); - r = this.document.queryCommandValue(command); - this.document.execCommand("styleWithCSS", false, oldValue); - }else{ - r = this.document.queryCommandValue(command); - } - return r; - }, - - // Misc. - - _sCall: function(name, args){ - // summary: - // Run the named method of dijit._editor.selection over the - // current editor instance's window, with the passed args. - // tags: - // private - return dojo.withGlobal(this.window, name, dijit._editor.selection, args); - }, - - // FIXME: this is a TON of code duplication. Why? - - placeCursorAtStart: function(){ - // summary: - // Place the cursor at the start of the editing area. - // tags: - // private - - this.focus(); - - //see comments in placeCursorAtEnd - var isvalid=false; - if(dojo.isMoz){ - // TODO: Is this branch even necessary? - var first=this.editNode.firstChild; - while(first){ - if(first.nodeType == 3){ - if(first.nodeValue.replace(/^\s+|\s+$/g, "").length>0){ - isvalid=true; - this._sCall("selectElement", [ first ]); - break; - } - }else if(first.nodeType == 1){ - isvalid=true; - var tg = first.tagName ? first.tagName.toLowerCase() : ""; - // Collapse before childless tags. - if(/br|input|img|base|meta|area|basefont|hr|link/.test(tg)){ - this._sCall("selectElement", [ first ]); - }else{ - // Collapse inside tags with children. - this._sCall("selectElementChildren", [ first ]); - } - break; - } - first = first.nextSibling; - } - }else{ - isvalid=true; - this._sCall("selectElementChildren", [ this.editNode ]); - } - if(isvalid){ - this._sCall("collapse", [ true ]); - } - }, - - placeCursorAtEnd: function(){ - // summary: - // Place the cursor at the end of the editing area. - // tags: - // private - - this.focus(); - - //In mozilla, if last child is not a text node, we have to use - // selectElementChildren on this.editNode.lastChild otherwise the - // cursor would be placed at the end of the closing tag of - //this.editNode.lastChild - var isvalid=false; - if(dojo.isMoz){ - var last=this.editNode.lastChild; - while(last){ - if(last.nodeType == 3){ - if(last.nodeValue.replace(/^\s+|\s+$/g, "").length>0){ - isvalid=true; - this._sCall("selectElement", [ last ]); - break; - } - }else if(last.nodeType == 1){ - isvalid=true; - if(last.lastChild){ - this._sCall("selectElement", [ last.lastChild ]); - }else{ - this._sCall("selectElement", [ last ]); - } - break; - } - last = last.previousSibling; - } - }else{ - isvalid=true; - this._sCall("selectElementChildren", [ this.editNode ]); - } - if(isvalid){ - this._sCall("collapse", [ false ]); - } - }, - - getValue: function(/*Boolean?*/ nonDestructive){ - // summary: - // Return the current content of the editing area (post filters - // are applied). Users should call get('value') instead. - // nonDestructive: - // defaults to false. Should the post-filtering be run over a copy - // of the live DOM? Most users should pass "true" here unless they - // *really* know that none of the installed filters are going to - // mess up the editing session. - // tags: - // private - if(this.textarea){ - if(this.isClosed || !this.isLoaded){ - return this.textarea.value; - } - } - - return this._postFilterContent(null, nonDestructive); - }, - _getValueAttr: function(){ - // summary: - // Hook to make attr("value") work - return this.getValue(true); - }, - - setValue: function(/*String*/ html){ - // summary: - // This function sets the content. No undo history is preserved. - // Users should use set('value', ...) instead. - // tags: - // deprecated - - // TODO: remove this and getValue() for 2.0, and move code to _setValueAttr() - - if(!this.isLoaded){ - // try again after the editor is finished loading - this.onLoadDeferred.addCallback(dojo.hitch(this, function(){ - this.setValue(html); - })); - return; - } - this._cursorToStart = true; - if(this.textarea && (this.isClosed || !this.isLoaded)){ - this.textarea.value=html; - }else{ - html = this._preFilterContent(html); - var node = this.isClosed ? this.domNode : this.editNode; - if(html && dojo.isMoz && html.toLowerCase() == "<p></p>"){ - html = "<p> </p>"; - } - - // Use to avoid webkit problems where editor is disabled until the user clicks it - if(!html && dojo.isWebKit){ - html = " "; - } - node.innerHTML = html; - this._preDomFilterContent(node); - } - - this.onDisplayChanged(); - this._set("value", this.getValue(true)); - }, - - replaceValue: function(/*String*/ html){ - // summary: - // This function set the content while trying to maintain the undo stack - // (now only works fine with Moz, this is identical to setValue in all - // other browsers) - // tags: - // protected - - if(this.isClosed){ - this.setValue(html); - }else if(this.window && this.window.getSelection && !dojo.isMoz){ // Safari - // look ma! it's a totally f'd browser! - this.setValue(html); - }else if(this.window && this.window.getSelection){ // Moz - html = this._preFilterContent(html); - this.execCommand("selectall"); - if(!html){ - this._cursorToStart = true; - html = " "; - } - this.execCommand("inserthtml", html); - this._preDomFilterContent(this.editNode); - }else if(this.document && this.document.selection){//IE - //In IE, when the first element is not a text node, say - //an <a> tag, when replacing the content of the editing - //area, the <a> tag will be around all the content - //so for now, use setValue for IE too - this.setValue(html); - } - - this._set("value", this.getValue(true)); - }, - - _preFilterContent: function(/*String*/ html){ - // summary: - // Filter the input before setting the content of the editing - // area. DOM pre-filtering may happen after this - // string-based filtering takes place but as of 1.2, this is not - // guaranteed for operations such as the inserthtml command. - // tags: - // private - - var ec = html; - dojo.forEach(this.contentPreFilters, function(ef){ if(ef){ ec = ef(ec); } }); - return ec; - }, - _preDomFilterContent: function(/*DomNode*/ dom){ - // summary: - // filter the input's live DOM. All filter operations should be - // considered to be "live" and operating on the DOM that the user - // will be interacting with in their editing session. - // tags: - // private - dom = dom || this.editNode; - dojo.forEach(this.contentDomPreFilters, function(ef){ - if(ef && dojo.isFunction(ef)){ - ef(dom); - } - }, this); - }, - - _postFilterContent: function( - /*DomNode|DomNode[]|String?*/ dom, - /*Boolean?*/ nonDestructive){ - // summary: - // filter the output after getting the content of the editing area - // - // description: - // post-filtering allows plug-ins and users to specify any number - // of transforms over the editor's content, enabling many common - // use-cases such as transforming absolute to relative URLs (and - // vice-versa), ensuring conformance with a particular DTD, etc. - // The filters are registered in the contentDomPostFilters and - // contentPostFilters arrays. Each item in the - // contentDomPostFilters array is a function which takes a DOM - // Node or array of nodes as its only argument and returns the - // same. It is then passed down the chain for further filtering. - // The contentPostFilters array behaves the same way, except each - // member operates on strings. Together, the DOM and string-based - // filtering allow the full range of post-processing that should - // be necessaray to enable even the most agressive of post-editing - // conversions to take place. - // - // If nonDestructive is set to "true", the nodes are cloned before - // filtering proceeds to avoid potentially destructive transforms - // to the content which may still needed to be edited further. - // Once DOM filtering has taken place, the serialized version of - // the DOM which is passed is run through each of the - // contentPostFilters functions. - // - // dom: - // a node, set of nodes, which to filter using each of the current - // members of the contentDomPostFilters and contentPostFilters arrays. - // - // nonDestructive: - // defaults to "false". If true, ensures that filtering happens on - // a clone of the passed-in content and not the actual node - // itself. - // - // tags: - // private - - var ec; - if(!dojo.isString(dom)){ - dom = dom || this.editNode; - if(this.contentDomPostFilters.length){ - if(nonDestructive){ - dom = dojo.clone(dom); - } - dojo.forEach(this.contentDomPostFilters, function(ef){ - dom = ef(dom); - }); - } - ec = dijit._editor.getChildrenHtml(dom); - }else{ - ec = dom; - } - - if(!dojo.trim(ec.replace(/^\xA0\xA0*/, '').replace(/\xA0\xA0*$/, '')).length){ - ec = ""; - } - - // if(dojo.isIE){ - // //removing appended <P> </P> for IE - // ec = ec.replace(/(?:<p> </p>[\n\r]*)+$/i,""); - // } - dojo.forEach(this.contentPostFilters, function(ef){ - ec = ef(ec); - }); - - return ec; - }, - - _saveContent: function(/*Event*/ e){ - // summary: - // Saves the content in an onunload event if the editor has not been closed - // tags: - // private - - var saveTextarea = dojo.byId(dijit._scopeName + "._editor.RichText.value"); - if(saveTextarea.value){ - saveTextarea.value += this._SEPARATOR; - } - saveTextarea.value += this.name + this._NAME_CONTENT_SEP + this.getValue(true); - }, - - - escapeXml: function(/*String*/ str, /*Boolean*/ noSingleQuotes){ - // summary: - // Adds escape sequences for special characters in XML. - // Optionally skips escapes for single quotes - // tags: - // private - - str = str.replace(/&/gm, "&").replace(/</gm, "<").replace(/>/gm, ">").replace(/"/gm, """); - if(!noSingleQuotes){ - str = str.replace(/'/gm, "'"); - } - return str; // string - }, - - getNodeHtml: function(/* DomNode */ node){ - // summary: - // Deprecated. Use dijit._editor._getNodeHtml() instead. - // tags: - // deprecated - dojo.deprecated('dijit.Editor::getNodeHtml is deprecated','use dijit._editor.getNodeHtml instead', 2); - return dijit._editor.getNodeHtml(node); // String - }, - - getNodeChildrenHtml: function(/* DomNode */ dom){ - // summary: - // Deprecated. Use dijit._editor.getChildrenHtml() instead. - // tags: - // deprecated - dojo.deprecated('dijit.Editor::getNodeChildrenHtml is deprecated','use dijit._editor.getChildrenHtml instead', 2); - return dijit._editor.getChildrenHtml(dom); - }, - - close: function(/*Boolean?*/ save){ - // summary: - // Kills the editor and optionally writes back the modified contents to the - // element from which it originated. - // save: - // Whether or not to save the changes. If false, the changes are discarded. - // tags: - // private - - if(this.isClosed){ return; } - - if(!arguments.length){ save = true; } - if(save){ - this._set("value", this.getValue(true)); - } - - // line height is squashed for iframes - // FIXME: why was this here? if (this.iframe){ this.domNode.style.lineHeight = null; } - - if(this.interval){ clearInterval(this.interval); } - - if(this._webkitListener){ - //Cleaup of WebKit fix: #9532 - this.disconnect(this._webkitListener); - delete this._webkitListener; - } - - // Guard against memory leaks on IE (see #9268) - if(dojo.isIE){ - this.iframe.onfocus = null; - } - this.iframe._loadFunc = null; - - if(this._iframeRegHandle){ - dijit.unregisterIframe(this._iframeRegHandle); - delete this._iframeRegHandle; - } - - if(this.textarea){ - var s = this.textarea.style; - s.position = ""; - s.left = s.top = ""; - if(dojo.isIE){ - s.overflow = this.__overflow; - this.__overflow = null; - } - this.textarea.value = this.value; - dojo.destroy(this.domNode); - this.domNode = this.textarea; - }else{ - // Note that this destroys the iframe - this.domNode.innerHTML = this.value; - } - delete this.iframe; - - dojo.removeClass(this.domNode, this.baseClass); - this.isClosed = true; - this.isLoaded = false; - - delete this.editNode; - delete this.focusNode; - - if(this.window && this.window._frameElement){ - this.window._frameElement = null; - } - - this.window = null; - this.document = null; - this.editingArea = null; - this.editorObject = null; - }, - - destroy: function(){ - if(!this.isClosed){ this.close(false); } - this.inherited(arguments); - if(dijit._editor._globalSaveHandler){ - delete dijit._editor._globalSaveHandler[this.id]; - } - }, - - _removeMozBogus: function(/* String */ html){ - // summary: - // Post filter to remove unwanted HTML attributes generated by mozilla - // tags: - // private - return html.replace(/\stype="_moz"/gi, '').replace(/\s_moz_dirty=""/gi, '').replace(/_moz_resizing="(true|false)"/gi,''); // String - }, - _removeWebkitBogus: function(/* String */ html){ - // summary: - // Post filter to remove unwanted HTML attributes generated by webkit - // tags: - // private - html = html.replace(/\sclass="webkit-block-placeholder"/gi, ''); - html = html.replace(/\sclass="apple-style-span"/gi, ''); - // For some reason copy/paste sometime adds extra meta tags for charset on - // webkit (chrome) on mac.They need to be removed. See: #12007" - html = html.replace(/<meta charset=\"utf-8\" \/>/gi, ''); - return html; // String - }, - _normalizeFontStyle: function(/* String */ html){ - // summary: - // Convert 'strong' and 'em' to 'b' and 'i'. - // description: - // Moz can not handle strong/em tags correctly, so to help - // mozilla and also to normalize output, convert them to 'b' and 'i'. - // - // Note the IE generates 'strong' and 'em' rather than 'b' and 'i' - // tags: - // private - return html.replace(/<(\/)?strong([ \>])/gi, '<$1b$2') - .replace(/<(\/)?em([ \>])/gi, '<$1i$2' ); // String - }, - - _preFixUrlAttributes: function(/* String */ html){ - // summary: - // Pre-filter to do fixing to href attributes on <a> and <img> tags - // tags: - // private - return html.replace(/(?:(<a(?=\s).*?\shref=)("|')(.*?)\2)|(?:(<a\s.*?href=)([^"'][^ >]+))/gi, - '$1$4$2$3$5$2 _djrealurl=$2$3$5$2') - .replace(/(?:(<img(?=\s).*?\ssrc=)("|')(.*?)\2)|(?:(<img\s.*?src=)([^"'][^ >]+))/gi, - '$1$4$2$3$5$2 _djrealurl=$2$3$5$2'); // String - }, - - /***************************************************************************** - The following functions implement HTML manipulation commands for various - browser/contentEditable implementations. The goal of them is to enforce - standard behaviors of them. - ******************************************************************************/ - - _inserthorizontalruleImpl: function(argument){ - // summary: - // This function implements the insertion of HTML 'HR' tags. - // into a point on the page. IE doesn't to it right, so - // we have to use an alternate form - // argument: - // arguments to the exec command, if any. - // tags: - // protected - if(dojo.isIE){ - return this._inserthtmlImpl("<hr>"); - } - return this.document.execCommand("inserthorizontalrule", false, argument); - }, - - _unlinkImpl: function(argument){ - // summary: - // This function implements the unlink of an 'a' tag. - // argument: - // arguments to the exec command, if any. - // tags: - // protected - if((this.queryCommandEnabled("unlink")) && (dojo.isMoz || dojo.isWebKit)){ - var a = this._sCall("getAncestorElement", [ "a" ]); - this._sCall("selectElement", [ a ]); - return this.document.execCommand("unlink", false, null); - } - return this.document.execCommand("unlink", false, argument); - }, - - _hilitecolorImpl: function(argument){ - // summary: - // This function implements the hilitecolor command - // argument: - // arguments to the exec command, if any. - // tags: - // protected - var returnValue; - if(dojo.isMoz){ - // mozilla doesn't support hilitecolor properly when useCSS is - // set to false (bugzilla #279330) - this.document.execCommand("styleWithCSS", false, true); - returnValue = this.document.execCommand("hilitecolor", false, argument); - this.document.execCommand("styleWithCSS", false, false); - }else{ - returnValue = this.document.execCommand("hilitecolor", false, argument); - } - return returnValue; - }, - - _backcolorImpl: function(argument){ - // summary: - // This function implements the backcolor command - // argument: - // arguments to the exec command, if any. - // tags: - // protected - if(dojo.isIE){ - // Tested under IE 6 XP2, no problem here, comment out - // IE weirdly collapses ranges when we exec these commands, so prevent it - // var tr = this.document.selection.createRange(); - argument = argument ? argument : null; - } - return this.document.execCommand("backcolor", false, argument); - }, - - _forecolorImpl: function(argument){ - // summary: - // This function implements the forecolor command - // argument: - // arguments to the exec command, if any. - // tags: - // protected - if(dojo.isIE){ - // Tested under IE 6 XP2, no problem here, comment out - // IE weirdly collapses ranges when we exec these commands, so prevent it - // var tr = this.document.selection.createRange(); - argument = argument? argument : null; - } - return this.document.execCommand("forecolor", false, argument); - }, - - _inserthtmlImpl: function(argument){ - // summary: - // This function implements the insertion of HTML content into - // a point on the page. - // argument: - // The content to insert, if any. - // tags: - // protected - argument = this._preFilterContent(argument); - var rv = true; - if(dojo.isIE){ - var insertRange = this.document.selection.createRange(); - if(this.document.selection.type.toUpperCase() == 'CONTROL'){ - var n=insertRange.item(0); - while(insertRange.length){ - insertRange.remove(insertRange.item(0)); - } - n.outerHTML=argument; - }else{ - insertRange.pasteHTML(argument); - } - insertRange.select(); - //insertRange.collapse(true); - }else if(dojo.isMoz && !argument.length){ - //mozilla can not inserthtml an empty html to delete current selection - //so we delete the selection instead in this case - this._sCall("remove"); // FIXME - }else{ - rv = this.document.execCommand("inserthtml", false, argument); - } - return rv; - }, - - _boldImpl: function(argument){ - // summary: - // This function implements an over-ride of the bold command. - // argument: - // Not used, operates by selection. - // tags: - // protected - if(dojo.isIE){ - this._adaptIESelection() - } - return this.document.execCommand("bold", false, argument); - }, - - _italicImpl: function(argument){ - // summary: - // This function implements an over-ride of the italic command. - // argument: - // Not used, operates by selection. - // tags: - // protected - if(dojo.isIE){ - this._adaptIESelection() - } - return this.document.execCommand("italic", false, argument); - }, - - _underlineImpl: function(argument){ - // summary: - // This function implements an over-ride of the underline command. - // argument: - // Not used, operates by selection. - // tags: - // protected - if(dojo.isIE){ - this._adaptIESelection() - } - return this.document.execCommand("underline", false, argument); - }, - - _strikethroughImpl: function(argument){ - // summary: - // This function implements an over-ride of the strikethrough command. - // argument: - // Not used, operates by selection. - // tags: - // protected - if(dojo.isIE){ - this._adaptIESelection() - } - return this.document.execCommand("strikethrough", false, argument); - }, - - getHeaderHeight: function(){ - // summary: - // A function for obtaining the height of the header node - return this._getNodeChildrenHeight(this.header); // Number - }, - - getFooterHeight: function(){ - // summary: - // A function for obtaining the height of the footer node - return this._getNodeChildrenHeight(this.footer); // Number - }, - - _getNodeChildrenHeight: function(node){ - // summary: - // An internal function for computing the cumulative height of all child nodes of 'node' - // node: - // The node to process the children of; - var h = 0; - if(node && node.childNodes){ - // IE didn't compute it right when position was obtained on the node directly is some cases, - // so we have to walk over all the children manually. - var i; - for(i = 0; i < node.childNodes.length; i++){ - var size = dojo.position(node.childNodes[i]); - h += size.h; - } - } - return h; // Number - }, - - _isNodeEmpty: function(node, startOffset){ - // summary: - // Function to test if a node is devoid of real content. - // node: - // The node to check. - // tags: - // private. - if(node.nodeType == 1/*element*/){ - if(node.childNodes.length > 0){ - return this._isNodeEmpty(node.childNodes[0], startOffset); - } - return true; - }else if(node.nodeType == 3/*text*/){ - return (node.nodeValue.substring(startOffset) == ""); - } - return false; - }, - - _removeStartingRangeFromRange: function(node, range){ - // summary: - // Function to adjust selection range by removing the current - // start node. - // node: - // The node to remove from the starting range. - // range: - // The range to adapt. - // tags: - // private - if(node.nextSibling){ - range.setStart(node.nextSibling,0); - }else{ - var parent = node.parentNode; - while(parent && parent.nextSibling == null){ - //move up the tree until we find a parent that has another node, that node will be the next node - parent = parent.parentNode; - } - if(parent){ - range.setStart(parent.nextSibling,0); - } - } - return range; - }, - - _adaptIESelection: function(){ - // summary: - // Function to adapt the IE range by removing leading 'newlines' - // Needed to fix issue with bold/italics/underline not working if - // range included leading 'newlines'. - // In IE, if a user starts a selection at the very end of a line, - // then the native browser commands will fail to execute correctly. - // To work around the issue, we can remove all empty nodes from - // the start of the range selection. - var selection = dijit.range.getSelection(this.window); - if(selection && selection.rangeCount && !selection.isCollapsed){ - var range = selection.getRangeAt(0); - var firstNode = range.startContainer; - var startOffset = range.startOffset; - - while(firstNode.nodeType == 3/*text*/ && startOffset >= firstNode.length && firstNode.nextSibling){ - //traverse the text nodes until we get to the one that is actually highlighted - startOffset = startOffset - firstNode.length; - firstNode = firstNode.nextSibling; - } - - //Remove the starting ranges until the range does not start with an empty node. - var lastNode=null; - while(this._isNodeEmpty(firstNode, startOffset) && firstNode != lastNode){ - lastNode =firstNode; //this will break the loop in case we can't find the next sibling - range = this._removeStartingRangeFromRange(firstNode, range); //move the start container to the next node in the range - firstNode = range.startContainer; - startOffset = 0; //start at the beginning of the new starting range - } - selection.removeAllRanges();// this will work as long as users cannot select multiple ranges. I have not been able to do that in the editor. - selection.addRange(range); - } - } -}); - -} +//>>built +define("dijit/_editor/RichText",["dojo/_base/array","dojo/_base/config","dojo/_base/declare","dojo/_base/Deferred","dojo/dom","dojo/dom-attr","dojo/dom-class","dojo/dom-construct","dojo/dom-geometry","dojo/dom-style","dojo/_base/event","dojo/_base/kernel","dojo/keys","dojo/_base/lang","dojo/on","dojo/query","dojo/ready","dojo/_base/sniff","dojo/topic","dojo/_base/unload","dojo/_base/url","dojo/_base/window","../_Widget","../_CssStateMixin","./selection","./range","./html","../focus",".."],function(_1,_2,_3,_4,_5,_6,_7,_8,_9,_a,_b,_c,_d,_e,on,_f,_10,has,_11,_12,_13,win,_14,_15,_16,_17,_18,_19,_1a){var _1b=_3("dijit._editor.RichText",[_14,_15],{constructor:function(_1c){this.contentPreFilters=[];this.contentPostFilters=[];this.contentDomPreFilters=[];this.contentDomPostFilters=[];this.editingAreaStyleSheets=[];this.events=[].concat(this.events);this._keyHandlers={};if(_1c&&_e.isString(_1c.value)){this.value=_1c.value;}this.onLoadDeferred=new _4();},baseClass:"dijitEditor",inheritWidth:false,focusOnLoad:false,name:"",styleSheets:"",height:"300px",minHeight:"1em",isClosed:true,isLoaded:false,_SEPARATOR:"@@**%%__RICHTEXTBOUNDRY__%%**@@",_NAME_CONTENT_SEP:"@@**%%:%%**@@",onLoadDeferred:null,isTabIndent:false,disableSpellCheck:false,postCreate:function(){if("textarea"===this.domNode.tagName.toLowerCase()){console.warn("RichText should not be used with the TEXTAREA tag. See dijit._editor.RichText docs.");}this.contentPreFilters=[_e.hitch(this,"_preFixUrlAttributes")].concat(this.contentPreFilters);if(has("mozilla")){this.contentPreFilters=[this._normalizeFontStyle].concat(this.contentPreFilters);this.contentPostFilters=[this._removeMozBogus].concat(this.contentPostFilters);}if(has("webkit")){this.contentPreFilters=[this._removeWebkitBogus].concat(this.contentPreFilters);this.contentPostFilters=[this._removeWebkitBogus].concat(this.contentPostFilters);}if(has("ie")){this.contentPostFilters=[this._normalizeFontStyle].concat(this.contentPostFilters);this.contentDomPostFilters=[_e.hitch(this,this._stripBreakerNodes)].concat(this.contentDomPostFilters);}this.inherited(arguments);_11.publish(_1a._scopeName+"._editor.RichText::init",this);this.open();this.setupDefaultShortcuts();},setupDefaultShortcuts:function(){var _1d=_e.hitch(this,function(cmd,arg){return function(){return !this.execCommand(cmd,arg);};});var _1e={b:_1d("bold"),i:_1d("italic"),u:_1d("underline"),a:_1d("selectall"),s:function(){this.save(true);},m:function(){this.isTabIndent=!this.isTabIndent;},"1":_1d("formatblock","h1"),"2":_1d("formatblock","h2"),"3":_1d("formatblock","h3"),"4":_1d("formatblock","h4"),"\\":_1d("insertunorderedlist")};if(!has("ie")){_1e.Z=_1d("redo");}var key;for(key in _1e){this.addKeyHandler(key,true,false,_1e[key]);}},events:["onKeyPress","onKeyDown","onKeyUp"],captureEvents:[],_editorCommandsLocalized:false,_localizeEditorCommands:function(){if(_1b._editorCommandsLocalized){this._local2NativeFormatNames=_1b._local2NativeFormatNames;this._native2LocalFormatNames=_1b._native2LocalFormatNames;return;}_1b._editorCommandsLocalized=true;_1b._local2NativeFormatNames={};_1b._native2LocalFormatNames={};this._local2NativeFormatNames=_1b._local2NativeFormatNames;this._native2LocalFormatNames=_1b._native2LocalFormatNames;var _1f=["div","p","pre","h1","h2","h3","h4","h5","h6","ol","ul","address"];var _20="",_21,i=0;while((_21=_1f[i++])){if(_21.charAt(1)!=="l"){_20+="<"+_21+"><span>content</span></"+_21+"><br/>";}else{_20+="<"+_21+"><li>content</li></"+_21+"><br/>";}}var _22={position:"absolute",top:"0px",zIndex:10,opacity:0.01};var div=_8.create("div",{style:_22,innerHTML:_20});win.body().appendChild(div);var _23=_e.hitch(this,function(){var _24=div.firstChild;while(_24){try{_16.selectElement(_24.firstChild);var _25=_24.tagName.toLowerCase();this._local2NativeFormatNames[_25]=document.queryCommandValue("formatblock");this._native2LocalFormatNames[this._local2NativeFormatNames[_25]]=_25;_24=_24.nextSibling.nextSibling;}catch(e){}}div.parentNode.removeChild(div);div.innerHTML="";});setTimeout(_23,0);},open:function(_26){if(!this.onLoadDeferred||this.onLoadDeferred.fired>=0){this.onLoadDeferred=new _4();}if(!this.isClosed){this.close();}_11.publish(_1a._scopeName+"._editor.RichText::open",this);if(arguments.length===1&&_26.nodeName){this.domNode=_26;}var dn=this.domNode;var _27;if(_e.isString(this.value)){_27=this.value;delete this.value;dn.innerHTML="";}else{if(dn.nodeName&&dn.nodeName.toLowerCase()=="textarea"){var ta=(this.textarea=dn);this.name=ta.name;_27=ta.value;dn=this.domNode=win.doc.createElement("div");dn.setAttribute("widgetId",this.id);ta.removeAttribute("widgetId");dn.cssText=ta.cssText;dn.className+=" "+ta.className;_8.place(dn,ta,"before");var _28=_e.hitch(this,function(){_a.set(ta,{display:"block",position:"absolute",top:"-1000px"});if(has("ie")){var s=ta.style;this.__overflow=s.overflow;s.overflow="hidden";}});if(has("ie")){setTimeout(_28,10);}else{_28();}if(ta.form){var _29=ta.value;this.reset=function(){var _2a=this.getValue();if(_2a!==_29){this.replaceValue(_29);}};on(ta.form,"submit",_e.hitch(this,function(){_6.set(ta,"disabled",this.disabled);ta.value=this.getValue();}));}}else{_27=_18.getChildrenHtml(dn);dn.innerHTML="";}}this.value=_27;if(dn.nodeName&&dn.nodeName==="LI"){dn.innerHTML=" <br>";}this.header=dn.ownerDocument.createElement("div");dn.appendChild(this.header);this.editingArea=dn.ownerDocument.createElement("div");dn.appendChild(this.editingArea);this.footer=dn.ownerDocument.createElement("div");dn.appendChild(this.footer);if(!this.name){this.name=this.id+"_AUTOGEN";}if(this.name!==""&&(!_2["useXDomain"]||_2["allowXdRichTextSave"])){var _2b=_5.byId(_1a._scopeName+"._editor.RichText.value");if(_2b&&_2b.value!==""){var _2c=_2b.value.split(this._SEPARATOR),i=0,dat;while((dat=_2c[i++])){var _2d=dat.split(this._NAME_CONTENT_SEP);if(_2d[0]===this.name){_27=_2d[1];_2c=_2c.splice(i,1);_2b.value=_2c.join(this._SEPARATOR);break;}}}if(!_1b._globalSaveHandler){_1b._globalSaveHandler={};_12.addOnUnload(function(){var id;for(id in _1b._globalSaveHandler){var f=_1b._globalSaveHandler[id];if(_e.isFunction(f)){f();}}});}_1b._globalSaveHandler[this.id]=_e.hitch(this,"_saveContent");}this.isClosed=false;var ifr=(this.editorObject=this.iframe=win.doc.createElement("iframe"));ifr.id=this.id+"_iframe";this._iframeSrc=this._getIframeDocTxt();ifr.style.border="none";ifr.style.width="100%";if(this._layoutMode){ifr.style.height="100%";}else{if(has("ie")>=7){if(this.height){ifr.style.height=this.height;}if(this.minHeight){ifr.style.minHeight=this.minHeight;}}else{ifr.style.height=this.height?this.height:this.minHeight;}}ifr.frameBorder=0;ifr._loadFunc=_e.hitch(this,function(w){this.window=w;this.document=this.window.document;if(has("ie")){this._localizeEditorCommands();}this.onLoad(_27);});var _2e="parent."+_1a._scopeName+".byId(\""+this.id+"\")._iframeSrc";var s="javascript:(function(){try{return "+_2e+"}catch(e){document.open();document.domain=\""+document.domain+"\";document.write("+_2e+");document.close();}})()";ifr.setAttribute("src",s);this.editingArea.appendChild(ifr);if(has("safari")<=4){var src=ifr.getAttribute("src");if(!src||src.indexOf("javascript")===-1){setTimeout(function(){ifr.setAttribute("src",s);},0);}}if(dn.nodeName==="LI"){dn.lastChild.style.marginTop="-1.2em";}_7.add(this.domNode,this.baseClass);},_local2NativeFormatNames:{},_native2LocalFormatNames:{},_getIframeDocTxt:function(){var _2f=_a.getComputedStyle(this.domNode);var _30="";var _31=true;if(has("ie")||has("webkit")||(!this.height&&!has("mozilla"))){_30="<div id='dijitEditorBody'></div>";_31=false;}else{if(has("mozilla")){this._cursorToStart=true;_30=" ";}}var _32=[_2f.fontWeight,_2f.fontSize,_2f.fontFamily].join(" ");var _33=_2f.lineHeight;if(_33.indexOf("px")>=0){_33=parseFloat(_33)/parseFloat(_2f.fontSize);}else{if(_33.indexOf("em")>=0){_33=parseFloat(_33);}else{_33="normal";}}var _34="";var _35=this;this.style.replace(/(^|;)\s*(line-|font-?)[^;]+/ig,function(_36){_36=_36.replace(/^;/ig,"")+";";var s=_36.split(":")[0];if(s){s=_e.trim(s);s=s.toLowerCase();var i;var sC="";for(i=0;i<s.length;i++){var c=s.charAt(i);switch(c){case "-":i++;c=s.charAt(i).toUpperCase();default:sC+=c;}}_a.set(_35.domNode,sC,"");}_34+=_36+";";});var _37=_f("label[for=\""+this.id+"\"]");return [this.isLeftToRight()?"<html>\n<head>\n":"<html dir='rtl'>\n<head>\n",(has("mozilla")&&_37.length?"<title>"+_37[0].innerHTML+"</title>\n":""),"<meta http-equiv='Content-Type' content='text/html'>\n","<style>\n","\tbody,html {\n","\t\tbackground:transparent;\n","\t\tpadding: 1px 0 0 0;\n","\t\tmargin: -1px 0 0 0;\n",((has("webkit"))?"\t\twidth: 100%;\n":""),((has("webkit"))?"\t\theight: 100%;\n":""),"\t}\n","\tbody{\n","\t\ttop:0px;\n","\t\tleft:0px;\n","\t\tright:0px;\n","\t\tfont:",_32,";\n",((this.height||has("opera"))?"":"\t\tposition: fixed;\n"),"\t\tmin-height:",this.minHeight,";\n","\t\tline-height:",_33,";\n","\t}\n","\tp{ margin: 1em 0; }\n",(!_31&&!this.height?"\tbody,html {overflow-y: hidden;}\n":""),"\t#dijitEditorBody{overflow-x: auto; overflow-y:"+(this.height?"auto;":"hidden;")+" outline: 0px;}\n","\tli > ul:-moz-first-node, li > ol:-moz-first-node{ padding-top: 1.2em; }\n",(!has("ie")?"\tli{ min-height:1.2em; }\n":""),"</style>\n",this._applyEditingAreaStyleSheets(),"\n","</head>\n<body ",(_31?"id='dijitEditorBody' ":""),"onload='frameElement._loadFunc(window,document)' style='"+_34+"'>",_30,"</body>\n</html>"].join("");},_applyEditingAreaStyleSheets:function(){var _38=[];if(this.styleSheets){_38=this.styleSheets.split(";");this.styleSheets="";}_38=_38.concat(this.editingAreaStyleSheets);this.editingAreaStyleSheets=[];var _39="",i=0,url;while((url=_38[i++])){var _3a=(new _13(win.global.location,url)).toString();this.editingAreaStyleSheets.push(_3a);_39+="<link rel=\"stylesheet\" type=\"text/css\" href=\""+_3a+"\"/>";}return _39;},addStyleSheet:function(uri){var url=uri.toString();if(url.charAt(0)==="."||(url.charAt(0)!=="/"&&!uri.host)){url=(new _13(win.global.location,url)).toString();}if(_1.indexOf(this.editingAreaStyleSheets,url)>-1){return;}this.editingAreaStyleSheets.push(url);this.onLoadDeferred.addCallback(_e.hitch(this,function(){if(this.document.createStyleSheet){this.document.createStyleSheet(url);}else{var _3b=this.document.getElementsByTagName("head")[0];var _3c=this.document.createElement("link");_3c.rel="stylesheet";_3c.type="text/css";_3c.href=url;_3b.appendChild(_3c);}}));},removeStyleSheet:function(uri){var url=uri.toString();if(url.charAt(0)==="."||(url.charAt(0)!=="/"&&!uri.host)){url=(new _13(win.global.location,url)).toString();}var _3d=_1.indexOf(this.editingAreaStyleSheets,url);if(_3d===-1){return;}delete this.editingAreaStyleSheets[_3d];win.withGlobal(this.window,"query",dojo,["link:[href=\""+url+"\"]"]).orphan();},disabled:false,_mozSettingProps:{"styleWithCSS":false},_setDisabledAttr:function(_3e){_3e=!!_3e;this._set("disabled",_3e);if(!this.isLoaded){return;}if(has("ie")||has("webkit")||has("opera")){var _3f=has("ie")&&(this.isLoaded||!this.focusOnLoad);if(_3f){this.editNode.unselectable="on";}this.editNode.contentEditable=!_3e;if(_3f){var _40=this;setTimeout(function(){if(_40.editNode){_40.editNode.unselectable="off";}},0);}}else{try{this.document.designMode=(_3e?"off":"on");}catch(e){return;}if(!_3e&&this._mozSettingProps){var ps=this._mozSettingProps;var n;for(n in ps){if(ps.hasOwnProperty(n)){try{this.document.execCommand(n,false,ps[n]);}catch(e2){}}}}}this._disabledOK=true;},onLoad:function(_41){if(!this.window.__registeredWindow){this.window.__registeredWindow=true;this._iframeRegHandle=_19.registerIframe(this.iframe);}if(!has("ie")&&!has("webkit")&&(this.height||has("mozilla"))){this.editNode=this.document.body;}else{this.editNode=this.document.body.firstChild;var _42=this;if(has("ie")){this.tabStop=_8.create("div",{tabIndex:-1},this.editingArea);this.iframe.onfocus=function(){_42.editNode.setActive();};}}this.focusNode=this.editNode;var _43=this.events.concat(this.captureEvents);var ap=this.iframe?this.document:this.editNode;_1.forEach(_43,function(_44){this.connect(ap,_44.toLowerCase(),_44);},this);this.connect(ap,"onmouseup","onClick");if(has("ie")){this.connect(this.document,"onmousedown","_onIEMouseDown");this.editNode.style.zoom=1;}else{this.connect(this.document,"onmousedown",function(){delete this._cursorToStart;});}if(has("webkit")){this._webkitListener=this.connect(this.document,"onmouseup","onDisplayChanged");this.connect(this.document,"onmousedown",function(e){var t=e.target;if(t&&(t===this.document.body||t===this.document)){setTimeout(_e.hitch(this,"placeCursorAtEnd"),0);}});}if(has("ie")){try{this.document.execCommand("RespectVisibilityInDesign",true,null);}catch(e){}}this.isLoaded=true;this.set("disabled",this.disabled);var _45=_e.hitch(this,function(){this.setValue(_41);if(this.onLoadDeferred){this.onLoadDeferred.callback(true);}this.onDisplayChanged();if(this.focusOnLoad){_10(_e.hitch(this,function(){setTimeout(_e.hitch(this,"focus"),this.updateInterval);}));}this.value=this.getValue(true);});if(this.setValueDeferred){this.setValueDeferred.addCallback(_45);}else{_45();}},onKeyDown:function(e){if(e.keyCode===_d.TAB&&this.isTabIndent){_b.stop(e);if(this.queryCommandEnabled((e.shiftKey?"outdent":"indent"))){this.execCommand((e.shiftKey?"outdent":"indent"));}}if(has("ie")){if(e.keyCode==_d.TAB&&!this.isTabIndent){if(e.shiftKey&&!e.ctrlKey&&!e.altKey){this.iframe.focus();}else{if(!e.shiftKey&&!e.ctrlKey&&!e.altKey){this.tabStop.focus();}}}else{if(e.keyCode===_d.BACKSPACE&&this.document.selection.type==="Control"){_b.stop(e);this.execCommand("delete");}else{if((65<=e.keyCode&&e.keyCode<=90)||(e.keyCode>=37&&e.keyCode<=40)){e.charCode=e.keyCode;this.onKeyPress(e);}}}}if(has("ff")){if(e.keyCode===_d.PAGE_UP||e.keyCode===_d.PAGE_DOWN){if(this.editNode.clientHeight>=this.editNode.scrollHeight){e.preventDefault();}}}return true;},onKeyUp:function(){},setDisabled:function(_46){_c.deprecated("dijit.Editor::setDisabled is deprecated","use dijit.Editor::attr(\"disabled\",boolean) instead",2);this.set("disabled",_46);},_setValueAttr:function(_47){this.setValue(_47);},_setDisableSpellCheckAttr:function(_48){if(this.document){_6.set(this.document.body,"spellcheck",!_48);}else{this.onLoadDeferred.addCallback(_e.hitch(this,function(){_6.set(this.document.body,"spellcheck",!_48);}));}this._set("disableSpellCheck",_48);},onKeyPress:function(e){var c=(e.keyChar&&e.keyChar.toLowerCase())||e.keyCode,_49=this._keyHandlers[c],_4a=arguments;if(_49&&!e.altKey){_1.some(_49,function(h){if(!(h.shift^e.shiftKey)&&!(h.ctrl^(e.ctrlKey||e.metaKey))){if(!h.handler.apply(this,_4a)){e.preventDefault();}return true;}},this);}if(!this._onKeyHitch){this._onKeyHitch=_e.hitch(this,"onKeyPressed");}setTimeout(this._onKeyHitch,1);return true;},addKeyHandler:function(key,_4b,_4c,_4d){if(!_e.isArray(this._keyHandlers[key])){this._keyHandlers[key]=[];}this._keyHandlers[key].push({shift:_4c||false,ctrl:_4b||false,handler:_4d});},onKeyPressed:function(){this.onDisplayChanged();},onClick:function(e){this.onDisplayChanged(e);},_onIEMouseDown:function(){if(!this.focused&&!this.disabled){this.focus();}},_onBlur:function(e){this.inherited(arguments);var _4e=this.getValue(true);if(_4e!==this.value){this.onChange(_4e);}this._set("value",_4e);},_onFocus:function(e){if(!this.disabled){if(!this._disabledOK){this.set("disabled",false);}this.inherited(arguments);}},blur:function(){if(!has("ie")&&this.window.document.documentElement&&this.window.document.documentElement.focus){this.window.document.documentElement.focus();}else{if(win.doc.body.focus){win.doc.body.focus();}}},focus:function(){if(!this.isLoaded){this.focusOnLoad=true;return;}if(this._cursorToStart){delete this._cursorToStart;if(this.editNode.childNodes){this.placeCursorAtStart();return;}}if(!has("ie")){_19.focus(this.iframe);}else{if(this.editNode&&this.editNode.focus){this.iframe.fireEvent("onfocus",document.createEventObject());}}},updateInterval:200,_updateTimer:null,onDisplayChanged:function(){if(this._updateTimer){clearTimeout(this._updateTimer);}if(!this._updateHandler){this._updateHandler=_e.hitch(this,"onNormalizedDisplayChanged");}this._updateTimer=setTimeout(this._updateHandler,this.updateInterval);},onNormalizedDisplayChanged:function(){delete this._updateTimer;},onChange:function(){},_normalizeCommand:function(cmd,_4f){var _50=cmd.toLowerCase();if(_50==="formatblock"){if(has("safari")&&_4f===undefined){_50="heading";}}else{if(_50==="hilitecolor"&&!has("mozilla")){_50="backcolor";}}return _50;},_qcaCache:{},queryCommandAvailable:function(_51){var ca=this._qcaCache[_51];if(ca!==undefined){return ca;}return (this._qcaCache[_51]=this._queryCommandAvailable(_51));},_queryCommandAvailable:function(_52){var ie=1;var _53=1<<1;var _54=1<<2;var _55=1<<3;function _56(_57){return {ie:Boolean(_57&ie),mozilla:Boolean(_57&_53),webkit:Boolean(_57&_54),opera:Boolean(_57&_55)};};var _58=null;switch(_52.toLowerCase()){case "bold":case "italic":case "underline":case "subscript":case "superscript":case "fontname":case "fontsize":case "forecolor":case "hilitecolor":case "justifycenter":case "justifyfull":case "justifyleft":case "justifyright":case "delete":case "selectall":case "toggledir":_58=_56(_53|ie|_54|_55);break;case "createlink":case "unlink":case "removeformat":case "inserthorizontalrule":case "insertimage":case "insertorderedlist":case "insertunorderedlist":case "indent":case "outdent":case "formatblock":case "inserthtml":case "undo":case "redo":case "strikethrough":case "tabindent":_58=_56(_53|ie|_55|_54);break;case "blockdirltr":case "blockdirrtl":case "dirltr":case "dirrtl":case "inlinedirltr":case "inlinedirrtl":_58=_56(ie);break;case "cut":case "copy":case "paste":_58=_56(ie|_53|_54);break;case "inserttable":_58=_56(_53|ie);break;case "insertcell":case "insertcol":case "insertrow":case "deletecells":case "deletecols":case "deleterows":case "mergecells":case "splitcell":_58=_56(ie|_53);break;default:return false;}return (has("ie")&&_58.ie)||(has("mozilla")&&_58.mozilla)||(has("webkit")&&_58.webkit)||(has("opera")&&_58.opera);},execCommand:function(_59,_5a){var _5b;this.focus();_59=this._normalizeCommand(_59,_5a);if(_5a!==undefined){if(_59==="heading"){throw new Error("unimplemented");}else{if((_59==="formatblock")&&has("ie")){_5a="<"+_5a+">";}}}var _5c="_"+_59+"Impl";if(this[_5c]){_5b=this[_5c](_5a);}else{_5a=arguments.length>1?_5a:null;if(_5a||_59!=="createlink"){_5b=this.document.execCommand(_59,false,_5a);}}this.onDisplayChanged();return _5b;},queryCommandEnabled:function(_5d){if(this.disabled||!this._disabledOK){return false;}_5d=this._normalizeCommand(_5d);var _5e="_"+_5d+"EnabledImpl";if(this[_5e]){return this[_5e](_5d);}else{return this._browserQueryCommandEnabled(_5d);}},queryCommandState:function(_5f){if(this.disabled||!this._disabledOK){return false;}_5f=this._normalizeCommand(_5f);try{return this.document.queryCommandState(_5f);}catch(e){return false;}},queryCommandValue:function(_60){if(this.disabled||!this._disabledOK){return false;}var r;_60=this._normalizeCommand(_60);if(has("ie")&&_60==="formatblock"){r=this._native2LocalFormatNames[this.document.queryCommandValue(_60)];}else{if(has("mozilla")&&_60==="hilitecolor"){var _61;try{_61=this.document.queryCommandValue("styleWithCSS");}catch(e){_61=false;}this.document.execCommand("styleWithCSS",false,true);r=this.document.queryCommandValue(_60);this.document.execCommand("styleWithCSS",false,_61);}else{r=this.document.queryCommandValue(_60);}}return r;},_sCall:function(_62,_63){return win.withGlobal(this.window,_62,_16,_63);},placeCursorAtStart:function(){this.focus();var _64=false;if(has("mozilla")){var _65=this.editNode.firstChild;while(_65){if(_65.nodeType===3){if(_65.nodeValue.replace(/^\s+|\s+$/g,"").length>0){_64=true;this._sCall("selectElement",[_65]);break;}}else{if(_65.nodeType===1){_64=true;var tg=_65.tagName?_65.tagName.toLowerCase():"";if(/br|input|img|base|meta|area|basefont|hr|link/.test(tg)){this._sCall("selectElement",[_65]);}else{this._sCall("selectElementChildren",[_65]);}break;}}_65=_65.nextSibling;}}else{_64=true;this._sCall("selectElementChildren",[this.editNode]);}if(_64){this._sCall("collapse",[true]);}},placeCursorAtEnd:function(){this.focus();var _66=false;if(has("mozilla")){var _67=this.editNode.lastChild;while(_67){if(_67.nodeType===3){if(_67.nodeValue.replace(/^\s+|\s+$/g,"").length>0){_66=true;this._sCall("selectElement",[_67]);break;}}else{if(_67.nodeType===1){_66=true;if(_67.lastChild){this._sCall("selectElement",[_67.lastChild]);}else{this._sCall("selectElement",[_67]);}break;}}_67=_67.previousSibling;}}else{_66=true;this._sCall("selectElementChildren",[this.editNode]);}if(_66){this._sCall("collapse",[false]);}},getValue:function(_68){if(this.textarea){if(this.isClosed||!this.isLoaded){return this.textarea.value;}}return this._postFilterContent(null,_68);},_getValueAttr:function(){return this.getValue(true);},setValue:function(_69){if(!this.isLoaded){this.onLoadDeferred.addCallback(_e.hitch(this,function(){this.setValue(_69);}));return;}this._cursorToStart=true;if(this.textarea&&(this.isClosed||!this.isLoaded)){this.textarea.value=_69;}else{_69=this._preFilterContent(_69);var _6a=this.isClosed?this.domNode:this.editNode;if(_69&&has("mozilla")&&_69.toLowerCase()==="<p></p>"){_69="<p> </p>";}if(!_69&&has("webkit")){_69=" ";}_6a.innerHTML=_69;this._preDomFilterContent(_6a);}this.onDisplayChanged();this._set("value",this.getValue(true));},replaceValue:function(_6b){if(this.isClosed){this.setValue(_6b);}else{if(this.window&&this.window.getSelection&&!has("mozilla")){this.setValue(_6b);}else{if(this.window&&this.window.getSelection){_6b=this._preFilterContent(_6b);this.execCommand("selectall");if(!_6b){this._cursorToStart=true;_6b=" ";}this.execCommand("inserthtml",_6b);this._preDomFilterContent(this.editNode);}else{if(this.document&&this.document.selection){this.setValue(_6b);}}}}this._set("value",this.getValue(true));},_preFilterContent:function(_6c){var ec=_6c;_1.forEach(this.contentPreFilters,function(ef){if(ef){ec=ef(ec);}});return ec;},_preDomFilterContent:function(dom){dom=dom||this.editNode;_1.forEach(this.contentDomPreFilters,function(ef){if(ef&&_e.isFunction(ef)){ef(dom);}},this);},_postFilterContent:function(dom,_6d){var ec;if(!_e.isString(dom)){dom=dom||this.editNode;if(this.contentDomPostFilters.length){if(_6d){dom=_e.clone(dom);}_1.forEach(this.contentDomPostFilters,function(ef){dom=ef(dom);});}ec=_18.getChildrenHtml(dom);}else{ec=dom;}if(!_e.trim(ec.replace(/^\xA0\xA0*/,"").replace(/\xA0\xA0*$/,"")).length){ec="";}_1.forEach(this.contentPostFilters,function(ef){ec=ef(ec);});return ec;},_saveContent:function(){var _6e=_5.byId(_1a._scopeName+"._editor.RichText.value");if(_6e){if(_6e.value){_6e.value+=this._SEPARATOR;}_6e.value+=this.name+this._NAME_CONTENT_SEP+this.getValue(true);}},escapeXml:function(str,_6f){str=str.replace(/&/gm,"&").replace(/</gm,"<").replace(/>/gm,">").replace(/"/gm,""");if(!_6f){str=str.replace(/'/gm,"'");}return str;},getNodeHtml:function(_70){_c.deprecated("dijit.Editor::getNodeHtml is deprecated","use dijit/_editor/html::getNodeHtml instead",2);return _18.getNodeHtml(_70);},getNodeChildrenHtml:function(dom){_c.deprecated("dijit.Editor::getNodeChildrenHtml is deprecated","use dijit/_editor/html::getChildrenHtml instead",2);return _18.getChildrenHtml(dom);},close:function(_71){if(this.isClosed){return;}if(!arguments.length){_71=true;}if(_71){this._set("value",this.getValue(true));}if(this.interval){clearInterval(this.interval);}if(this._webkitListener){this.disconnect(this._webkitListener);delete this._webkitListener;}if(has("ie")){this.iframe.onfocus=null;}this.iframe._loadFunc=null;if(this._iframeRegHandle){this._iframeRegHandle.remove();delete this._iframeRegHandle;}if(this.textarea){var s=this.textarea.style;s.position="";s.left=s.top="";if(has("ie")){s.overflow=this.__overflow;this.__overflow=null;}this.textarea.value=this.value;_8.destroy(this.domNode);this.domNode=this.textarea;}else{this.domNode.innerHTML=this.value;}delete this.iframe;_7.remove(this.domNode,this.baseClass);this.isClosed=true;this.isLoaded=false;delete this.editNode;delete this.focusNode;if(this.window&&this.window._frameElement){this.window._frameElement=null;}this.window=null;this.document=null;this.editingArea=null;this.editorObject=null;},destroy:function(){if(!this.isClosed){this.close(false);}if(this._updateTimer){clearTimeout(this._updateTimer);}this.inherited(arguments);if(_1b._globalSaveHandler){delete _1b._globalSaveHandler[this.id];}},_removeMozBogus:function(_72){return _72.replace(/\stype="_moz"/gi,"").replace(/\s_moz_dirty=""/gi,"").replace(/_moz_resizing="(true|false)"/gi,"");},_removeWebkitBogus:function(_73){_73=_73.replace(/\sclass="webkit-block-placeholder"/gi,"");_73=_73.replace(/\sclass="apple-style-span"/gi,"");_73=_73.replace(/<meta charset=\"utf-8\" \/>/gi,"");return _73;},_normalizeFontStyle:function(_74){return _74.replace(/<(\/)?strong([ \>])/gi,"<$1b$2").replace(/<(\/)?em([ \>])/gi,"<$1i$2");},_preFixUrlAttributes:function(_75){return _75.replace(/(?:(<a(?=\s).*?\shref=)("|')(.*?)\2)|(?:(<a\s.*?href=)([^"'][^ >]+))/gi,"$1$4$2$3$5$2 _djrealurl=$2$3$5$2").replace(/(?:(<img(?=\s).*?\ssrc=)("|')(.*?)\2)|(?:(<img\s.*?src=)([^"'][^ >]+))/gi,"$1$4$2$3$5$2 _djrealurl=$2$3$5$2");},_browserQueryCommandEnabled:function(_76){if(!_76){return false;}var _77=has("ie")?this.document.selection.createRange():this.document;try{return _77.queryCommandEnabled(_76);}catch(e){return false;}},_createlinkEnabledImpl:function(){var _78=true;if(has("opera")){var sel=this.window.getSelection();if(sel.isCollapsed){_78=true;}else{_78=this.document.queryCommandEnabled("createlink");}}else{_78=this._browserQueryCommandEnabled("createlink");}return _78;},_unlinkEnabledImpl:function(){var _79=true;if(has("mozilla")||has("webkit")){_79=this._sCall("hasAncestorElement",["a"]);}else{_79=this._browserQueryCommandEnabled("unlink");}return _79;},_inserttableEnabledImpl:function(){var _7a=true;if(has("mozilla")||has("webkit")){_7a=true;}else{_7a=this._browserQueryCommandEnabled("inserttable");}return _7a;},_cutEnabledImpl:function(){var _7b=true;if(has("webkit")){var sel=this.window.getSelection();if(sel){sel=sel.toString();}_7b=!!sel;}else{_7b=this._browserQueryCommandEnabled("cut");}return _7b;},_copyEnabledImpl:function(){var _7c=true;if(has("webkit")){var sel=this.window.getSelection();if(sel){sel=sel.toString();}_7c=!!sel;}else{_7c=this._browserQueryCommandEnabled("copy");}return _7c;},_pasteEnabledImpl:function(){var _7d=true;if(has("webkit")){return true;}else{_7d=this._browserQueryCommandEnabled("paste");}return _7d;},_inserthorizontalruleImpl:function(_7e){if(has("ie")){return this._inserthtmlImpl("<hr>");}return this.document.execCommand("inserthorizontalrule",false,_7e);},_unlinkImpl:function(_7f){if((this.queryCommandEnabled("unlink"))&&(has("mozilla")||has("webkit"))){var a=this._sCall("getAncestorElement",["a"]);this._sCall("selectElement",[a]);return this.document.execCommand("unlink",false,null);}return this.document.execCommand("unlink",false,_7f);},_hilitecolorImpl:function(_80){var _81;var _82=this._handleTextColorOrProperties("hilitecolor",_80);if(!_82){if(has("mozilla")){this.document.execCommand("styleWithCSS",false,true);_81=this.document.execCommand("hilitecolor",false,_80);this.document.execCommand("styleWithCSS",false,false);}else{_81=this.document.execCommand("hilitecolor",false,_80);}}return _81;},_backcolorImpl:function(_83){if(has("ie")){_83=_83?_83:null;}var _84=this._handleTextColorOrProperties("backcolor",_83);if(!_84){_84=this.document.execCommand("backcolor",false,_83);}return _84;},_forecolorImpl:function(_85){if(has("ie")){_85=_85?_85:null;}var _86=false;_86=this._handleTextColorOrProperties("forecolor",_85);if(!_86){_86=this.document.execCommand("forecolor",false,_85);}return _86;},_inserthtmlImpl:function(_87){_87=this._preFilterContent(_87);var rv=true;if(has("ie")){var _88=this.document.selection.createRange();if(this.document.selection.type.toUpperCase()==="CONTROL"){var n=_88.item(0);while(_88.length){_88.remove(_88.item(0));}n.outerHTML=_87;}else{_88.pasteHTML(_87);}_88.select();}else{if(has("mozilla")&&!_87.length){this._sCall("remove");}else{rv=this.document.execCommand("inserthtml",false,_87);}}return rv;},_boldImpl:function(_89){var _8a=false;if(has("ie")){this._adaptIESelection();_8a=this._adaptIEFormatAreaAndExec("bold");}if(!_8a){_8a=this.document.execCommand("bold",false,_89);}return _8a;},_italicImpl:function(_8b){var _8c=false;if(has("ie")){this._adaptIESelection();_8c=this._adaptIEFormatAreaAndExec("italic");}if(!_8c){_8c=this.document.execCommand("italic",false,_8b);}return _8c;},_underlineImpl:function(_8d){var _8e=false;if(has("ie")){this._adaptIESelection();_8e=this._adaptIEFormatAreaAndExec("underline");}if(!_8e){_8e=this.document.execCommand("underline",false,_8d);}return _8e;},_strikethroughImpl:function(_8f){var _90=false;if(has("ie")){this._adaptIESelection();_90=this._adaptIEFormatAreaAndExec("strikethrough");}if(!_90){_90=this.document.execCommand("strikethrough",false,_8f);}return _90;},_superscriptImpl:function(_91){var _92=false;if(has("ie")){this._adaptIESelection();_92=this._adaptIEFormatAreaAndExec("superscript");}if(!_92){_92=this.document.execCommand("superscript",false,_91);}return _92;},_subscriptImpl:function(_93){var _94=false;if(has("ie")){this._adaptIESelection();_94=this._adaptIEFormatAreaAndExec("subscript");}if(!_94){_94=this.document.execCommand("subscript",false,_93);}return _94;},_fontnameImpl:function(_95){var _96;if(has("ie")){_96=this._handleTextColorOrProperties("fontname",_95);}if(!_96){_96=this.document.execCommand("fontname",false,_95);}return _96;},_fontsizeImpl:function(_97){var _98;if(has("ie")){_98=this._handleTextColorOrProperties("fontsize",_97);}if(!_98){_98=this.document.execCommand("fontsize",false,_97);}return _98;},_insertorderedlistImpl:function(_99){var _9a=false;if(has("ie")){_9a=this._adaptIEList("insertorderedlist",_99);}if(!_9a){_9a=this.document.execCommand("insertorderedlist",false,_99);}return _9a;},_insertunorderedlistImpl:function(_9b){var _9c=false;if(has("ie")){_9c=this._adaptIEList("insertunorderedlist",_9b);}if(!_9c){_9c=this.document.execCommand("insertunorderedlist",false,_9b);}return _9c;},getHeaderHeight:function(){return this._getNodeChildrenHeight(this.header);},getFooterHeight:function(){return this._getNodeChildrenHeight(this.footer);},_getNodeChildrenHeight:function(_9d){var h=0;if(_9d&&_9d.childNodes){var i;for(i=0;i<_9d.childNodes.length;i++){var _9e=_9.position(_9d.childNodes[i]);h+=_9e.h;}}return h;},_isNodeEmpty:function(_9f,_a0){if(_9f.nodeType===1){if(_9f.childNodes.length>0){return this._isNodeEmpty(_9f.childNodes[0],_a0);}return true;}else{if(_9f.nodeType===3){return (_9f.nodeValue.substring(_a0)==="");}}return false;},_removeStartingRangeFromRange:function(_a1,_a2){if(_a1.nextSibling){_a2.setStart(_a1.nextSibling,0);}else{var _a3=_a1.parentNode;while(_a3&&_a3.nextSibling==null){_a3=_a3.parentNode;}if(_a3){_a2.setStart(_a3.nextSibling,0);}}return _a2;},_adaptIESelection:function(){var _a4=_17.getSelection(this.window);if(_a4&&_a4.rangeCount&&!_a4.isCollapsed){var _a5=_a4.getRangeAt(0);var _a6=_a5.startContainer;var _a7=_a5.startOffset;while(_a6.nodeType===3&&_a7>=_a6.length&&_a6.nextSibling){_a7=_a7-_a6.length;_a6=_a6.nextSibling;}var _a8=null;while(this._isNodeEmpty(_a6,_a7)&&_a6!==_a8){_a8=_a6;_a5=this._removeStartingRangeFromRange(_a6,_a5);_a6=_a5.startContainer;_a7=0;}_a4.removeAllRanges();_a4.addRange(_a5);}},_adaptIEFormatAreaAndExec:function(_a9){var _aa=_17.getSelection(this.window);var doc=this.document;var rs,ret,_ab,txt,_ac,_ad,_ae,_af;if(_a9&&_aa&&_aa.isCollapsed){var _b0=this.queryCommandValue(_a9);if(_b0){var _b1=this._tagNamesForCommand(_a9);_ab=_aa.getRangeAt(0);var fs=_ab.startContainer;if(fs.nodeType===3){var _b2=_ab.endOffset;if(fs.length<_b2){ret=this._adjustNodeAndOffset(rs,_b2);fs=ret.node;_b2=ret.offset;}}var _b3;while(fs&&fs!==this.editNode){var _b4=fs.tagName?fs.tagName.toLowerCase():"";if(_1.indexOf(_b1,_b4)>-1){_b3=fs;break;}fs=fs.parentNode;}if(_b3){rs=_ab.startContainer;var _b5=doc.createElement(_b3.tagName);_8.place(_b5,_b3,"after");if(rs&&rs.nodeType===3){var _b6,_b7;var _b8=_ab.endOffset;if(rs.length<_b8){ret=this._adjustNodeAndOffset(rs,_b8);rs=ret.node;_b8=ret.offset;}txt=rs.nodeValue;_ac=doc.createTextNode(txt.substring(0,_b8));var _b9=txt.substring(_b8,txt.length);if(_b9){_ad=doc.createTextNode(_b9);}_8.place(_ac,rs,"before");if(_ad){_ae=doc.createElement("span");_ae.className="ieFormatBreakerSpan";_8.place(_ae,rs,"after");_8.place(_ad,_ae,"after");_ad=_ae;}_8.destroy(rs);var _ba=_ac.parentNode;var _bb=[];var _bc;while(_ba!==_b3){var tg=_ba.tagName;_bc={tagName:tg};_bb.push(_bc);var _bd=doc.createElement(tg);if(_ba.style){if(_bd.style){if(_ba.style.cssText){_bd.style.cssText=_ba.style.cssText;_bc.cssText=_ba.style.cssText;}}}if(_ba.tagName==="FONT"){if(_ba.color){_bd.color=_ba.color;_bc.color=_ba.color;}if(_ba.face){_bd.face=_ba.face;_bc.face=_ba.face;}if(_ba.size){_bd.size=_ba.size;_bc.size=_ba.size;}}if(_ba.className){_bd.className=_ba.className;_bc.className=_ba.className;}if(_ad){_b6=_ad;while(_b6){_b7=_b6.nextSibling;_bd.appendChild(_b6);_b6=_b7;}}if(_bd.tagName==_ba.tagName){_ae=doc.createElement("span");_ae.className="ieFormatBreakerSpan";_8.place(_ae,_ba,"after");_8.place(_bd,_ae,"after");}else{_8.place(_bd,_ba,"after");}_ac=_ba;_ad=_bd;_ba=_ba.parentNode;}if(_ad){_b6=_ad;if(_b6.nodeType===1||(_b6.nodeType===3&&_b6.nodeValue)){_b5.innerHTML="";}while(_b6){_b7=_b6.nextSibling;_b5.appendChild(_b6);_b6=_b7;}}if(_bb.length){_bc=_bb.pop();var _be=doc.createElement(_bc.tagName);if(_bc.cssText&&_be.style){_be.style.cssText=_bc.cssText;}if(_bc.className){_be.className=_bc.className;}if(_bc.tagName==="FONT"){if(_bc.color){_be.color=_bc.color;}if(_bc.face){_be.face=_bc.face;}if(_bc.size){_be.size=_bc.size;}}_8.place(_be,_b5,"before");while(_bb.length){_bc=_bb.pop();var _bf=doc.createElement(_bc.tagName);if(_bc.cssText&&_bf.style){_bf.style.cssText=_bc.cssText;}if(_bc.className){_bf.className=_bc.className;}if(_bc.tagName==="FONT"){if(_bc.color){_bf.color=_bc.color;}if(_bc.face){_bf.face=_bc.face;}if(_bc.size){_bf.size=_bc.size;}}_be.appendChild(_bf);_be=_bf;}_af=doc.createTextNode(".");_ae.appendChild(_af);_be.appendChild(_af);win.withGlobal(this.window,_e.hitch(this,function(){var _c0=_17.create();_c0.setStart(_af,0);_c0.setEnd(_af,_af.length);_aa.removeAllRanges();_aa.addRange(_c0);_16.collapse(false);_af.parentNode.innerHTML="";}));}else{_ae=doc.createElement("span");_ae.className="ieFormatBreakerSpan";_af=doc.createTextNode(".");_ae.appendChild(_af);_8.place(_ae,_b5,"before");win.withGlobal(this.window,_e.hitch(this,function(){var _c1=_17.create();_c1.setStart(_af,0);_c1.setEnd(_af,_af.length);_aa.removeAllRanges();_aa.addRange(_c1);_16.collapse(false);_af.parentNode.innerHTML="";}));}if(!_b5.firstChild){_8.destroy(_b5);}return true;}}return false;}else{_ab=_aa.getRangeAt(0);rs=_ab.startContainer;if(rs&&rs.nodeType===3){win.withGlobal(this.window,_e.hitch(this,function(){var _c2=_ab.startOffset;if(rs.length<_c2){ret=this._adjustNodeAndOffset(rs,_c2);rs=ret.node;_c2=ret.offset;}txt=rs.nodeValue;_ac=doc.createTextNode(txt.substring(0,_c2));var _c3=txt.substring(_c2);if(_c3!==""){_ad=doc.createTextNode(txt.substring(_c2));}_ae=doc.createElement("span");_af=doc.createTextNode(".");_ae.appendChild(_af);if(_ac.length){_8.place(_ac,rs,"after");}else{_ac=rs;}_8.place(_ae,_ac,"after");if(_ad){_8.place(_ad,_ae,"after");}_8.destroy(rs);var _c4=_17.create();_c4.setStart(_af,0);_c4.setEnd(_af,_af.length);_aa.removeAllRanges();_aa.addRange(_c4);doc.execCommand(_a9);_8.place(_ae.firstChild,_ae,"before");_8.destroy(_ae);_c4.setStart(_af,0);_c4.setEnd(_af,_af.length);_aa.removeAllRanges();_aa.addRange(_c4);_16.collapse(false);_af.parentNode.innerHTML="";}));return true;}}}else{return false;}},_adaptIEList:function(_c5){var _c6=_17.getSelection(this.window);if(_c6.isCollapsed){if(_c6.rangeCount&&!this.queryCommandValue(_c5)){var _c7=_c6.getRangeAt(0);var sc=_c7.startContainer;if(sc&&sc.nodeType==3){if(!_c7.startOffset){win.withGlobal(this.window,_e.hitch(this,function(){var _c8="ul";if(_c5==="insertorderedlist"){_c8="ol";}var _c9=_8.create(_c8);var li=_8.create("li",null,_c9);_8.place(_c9,sc,"before");li.appendChild(sc);_8.create("br",null,_c9,"after");var _ca=_17.create();_ca.setStart(sc,0);_ca.setEnd(sc,sc.length);_c6.removeAllRanges();_c6.addRange(_ca);_16.collapse(true);}));return true;}}}}return false;},_handleTextColorOrProperties:function(_cb,_cc){var _cd=_17.getSelection(this.window);var doc=this.document;var rs,ret,_ce,txt,_cf,_d0,_d1,_d2;_cc=_cc||null;if(_cb&&_cd&&_cd.isCollapsed){if(_cd.rangeCount){_ce=_cd.getRangeAt(0);rs=_ce.startContainer;if(rs&&rs.nodeType===3){win.withGlobal(this.window,_e.hitch(this,function(){var _d3=_ce.startOffset;if(rs.length<_d3){ret=this._adjustNodeAndOffset(rs,_d3);rs=ret.node;_d3=ret.offset;}txt=rs.nodeValue;_cf=doc.createTextNode(txt.substring(0,_d3));var _d4=txt.substring(_d3);if(_d4!==""){_d0=doc.createTextNode(txt.substring(_d3));}_d1=_8.create("span");_d2=doc.createTextNode(".");_d1.appendChild(_d2);var _d5=_8.create("span");_d1.appendChild(_d5);if(_cf.length){_8.place(_cf,rs,"after");}else{_cf=rs;}_8.place(_d1,_cf,"after");if(_d0){_8.place(_d0,_d1,"after");}_8.destroy(rs);var _d6=_17.create();_d6.setStart(_d2,0);_d6.setEnd(_d2,_d2.length);_cd.removeAllRanges();_cd.addRange(_d6);if(has("webkit")){var _d7="color";if(_cb==="hilitecolor"||_cb==="backcolor"){_d7="backgroundColor";}_a.set(_d1,_d7,_cc);_16.remove();_8.destroy(_d5);_d1.innerHTML=" ";_16.selectElement(_d1);this.focus();}else{this.execCommand(_cb,_cc);_8.place(_d1.firstChild,_d1,"before");_8.destroy(_d1);_d6.setStart(_d2,0);_d6.setEnd(_d2,_d2.length);_cd.removeAllRanges();_cd.addRange(_d6);_16.collapse(false);_d2.parentNode.removeChild(_d2);}}));return true;}}}return false;},_adjustNodeAndOffset:function(_d8,_d9){while(_d8.length<_d9&&_d8.nextSibling&&_d8.nextSibling.nodeType===3){_d9=_d9-_d8.length;_d8=_d8.nextSibling;}return {"node":_d8,"offset":_d9};},_tagNamesForCommand:function(_da){if(_da==="bold"){return ["b","strong"];}else{if(_da==="italic"){return ["i","em"];}else{if(_da==="strikethrough"){return ["s","strike"];}else{if(_da==="superscript"){return ["sup"];}else{if(_da==="subscript"){return ["sub"];}else{if(_da==="underline"){return ["u"];}}}}}}return [];},_stripBreakerNodes:function(_db){win.withGlobal(this.window,_e.hitch(this,function(){var _dc=_f(".ieFormatBreakerSpan",_db);var i;for(i=0;i<_dc.length;i++){var b=_dc[i];while(b.firstChild){_8.place(b.firstChild,b,"before");}_8.destroy(b);}}));return _db;}});return _1b;});
\ No newline at end of file |