123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662 |
- 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._editor.selection");
- dojo.require("dojo.i18n");
- dojo.requireLocalization("dijit", "Textarea", null, "ROOT");
- // used to restore content when user leaves this page then comes back
- // but do not try doing document.write if we are using xd loading.
- // document.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 djConfig.allowXdRichTextSave = true.
- if (!djConfig["useXDomain"] || djConfig["allowXdRichTextSave"]) {
- if (dojo._postLoad) {
- (function() {
- var savetextarea = dojo.doc.createElement('textarea');
- savetextarea.id = "dijit._editor.RichText.savedContent";
- var s = savetextarea.style;
- s.display = 'none';
- s.position = 'absolute';
- s.top = "-100px";
- s.left = "-100px"
- s.height = "3px";
- s.width = "3px";
- dojo.body().appendChild(savetextarea);
- })();
- } else {
- // dojo.body() is not available before onLoad is fired
- try {
- dojo.doc
- .write('<textarea id="dijit._editor.RichText.savedContent" '
- + '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], {
- constructor : function() {
- // summary:
- // dijit._editor.RichText is the core of the WYSIWYG editor in dojo,
- // which
- // provides the basic editing features. It also encapsulates the
- // differences
- // of different js engines for various browsers
- //
- // contentPreFilters: Array
- // pre content filter function register array.
- // these filters will be executed before the actual
- // editing area get the html content
- this.contentPreFilters = [];
- // contentPostFilters: Array
- // post content filter function register array.
- // these will be used on the resulting html
- // from contentDomPostFilters. The resuling
- // content is the final html (returned by getValue())
- this.contentPostFilters = [];
- // contentDomPreFilters: Array
- // 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: Array
- // 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: Array
- // array to store all the stylesheets applied to the editing area
- this.editingAreaStyleSheets = [];
- this._keyHandlers = {};
- this.contentPreFilters.push(dojo
- .hitch(this, "_preFixUrlAttributes"));
- if (dojo.isMoz) {
- this.contentPreFilters.push(this._fixContentForMoz);
- }
- // this.contentDomPostFilters.push(this._postDomFixUrlAttributes);
- this.onLoadDeferred = new dojo.Deferred();
- },
- // inheritWidth: Boolean
- // whether to inherit the parent's width or simply use 100%
- inheritWidth : false,
- // focusOnLoad: Boolean
- // whether focusing into this instance of richtext when page onload
- focusOnLoad : false,
- // name: String
- // If a save name is specified the content is saved and restored when
- // the user
- // leave this page can come back, or if the editor is not properly
- // closed after
- // editing has started.
- name : "",
- // styleSheets: String
- // semicolon (";") separated list of css files for the editing area
- styleSheets : "",
- // _content: String
- // temporary content storage
- _content : "",
- // 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=""
- height : "300px",
- // minHeight: String
- // The minimum height that the editor should have
- minHeight : "1em",
- // isClosed: Boolean
- isClosed : true,
- // isLoaded: Boolean
- isLoaded : false,
- // _SEPARATOR: String
- // used to concat contents from multiple textareas into a single string
- _SEPARATOR : "@@**%%__RICHTEXTBOUNDRY__%%**@@",
- // onLoadDeferred: dojo.Deferred
- // deferred which is fired when the editor finishes loading
- onLoadDeferred : null,
- postCreate : function() {
- // summary: init
- dojo.publish("dijit._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.
- var ctrl = this.KEY_CTRL;
- var exec = function(cmd, arg) {
- return arguments.length == 1 ? function() {
- this.execCommand(cmd);
- } : function() {
- this.execCommand(cmd, arg);
- }
- }
- this.addKeyHandler("b", ctrl, exec("bold"));
- this.addKeyHandler("i", ctrl, exec("italic"));
- this.addKeyHandler("u", ctrl, exec("underline"));
- this.addKeyHandler("a", ctrl, exec("selectall"));
- this.addKeyHandler("s", ctrl, function() {
- this.save(true);
- });
- this.addKeyHandler("1", ctrl, exec("formatblock", "h1"));
- this.addKeyHandler("2", ctrl, exec("formatblock", "h2"));
- this.addKeyHandler("3", ctrl, exec("formatblock", "h3"));
- this.addKeyHandler("4", ctrl, exec("formatblock", "h4"));
- this.addKeyHandler("\\", ctrl, exec("insertunorderedlist"));
- if (!dojo.isIE) {
- this.addKeyHandler("Z", ctrl, exec("redo"));
- }
- },
- // events: Array
- // events which should be connected to the underlying editing area
- events : ["onKeyPress", "onKeyDown", "onKeyUp", "onClick"],
- // events: Array
- // events which should be connected to the underlying editing
- // area, events in this array will be addListener with
- // capture=true
- captureEvents : [],
- _editorCommandsLocalized : false,
- _localizeEditorCommands : function() {
- if (this._editorCommandsLocalized) {
- return;
- }
- this._editorCommandsLocalized = true;
- // in IE, names for blockformat is locale dependent, so we cache the
- // values here
- // if the normal way fails, we try the hard way to get the list
- // do not use _cacheLocalBlockFormatNames here, as it will
- // trigger security warning in IE7
- // in the array below, ul can not come directly after ol,
- // otherwise the queryCommandValue returns Normal for it
- var formats = ['p', 'pre', 'address', 'h1', 'h2', 'h3', 'h4', 'h5',
- 'h6', 'ol', 'div', 'ul'];
- var localhtml = "", format, i = 0;
- while ((format = formats[i++])) {
- if (format.charAt(1) != 'l') {
- localhtml += "<" + format + "><span>content</span></"
- + format + ">";
- } else {
- localhtml += "<" + format + "><li>content</li></" + format
- + ">";
- }
- }
- // queryCommandValue returns empty if we hide editNode, so move it
- // out of screen temporary
- var div = document.createElement('div');
- div.style.position = "absolute";
- div.style.left = "-2000px";
- div.style.top = "-2000px";
- document.body.appendChild(div);
- div.innerHTML = localhtml;
- var node = div.firstChild;
- while (node) {
- dijit._editor.selection.selectElement(node.firstChild);
- dojo.withGlobal(this.window, "selectElement",
- dijit._editor.selection, [node.firstChild]);
- var nativename = node.tagName.toLowerCase();
- this._local2NativeFormatNames[nativename] = document
- .queryCommandValue("formatblock");// this.queryCommandValue("formatblock");
- this._native2LocalFormatNames[this._local2NativeFormatNames[nativename]] = nativename;
- node = node.nextSibling;
- }
- document.body.removeChild(div);
- },
- open : function(/* DomNode? */element) {
- // summary:
- // Transforms the node referenced in this.domNode into a rich text
- // editing
- // node. This will result in the creation and replacement with an
- // <iframe>
- // if designMode(FF)/contentEditable(IE) is used.
- if ((!this.onLoadDeferred) || (this.onLoadDeferred.fired >= 0)) {
- this.onLoadDeferred = new dojo.Deferred();
- }
- if (!this.isClosed) {
- this.close();
- }
- dojo.publish("dijit._editor.RichText::open", [this]);
- this._content = "";
- if ((arguments.length == 1) && (element["nodeName"])) {
- this.domNode = element;
- } // else unchanged
- if ((this.domNode["nodeName"])
- && (this.domNode.nodeName.toLowerCase() == "textarea")) {
- // if we were created from a textarea, then we need to create a
- // new editing harness node.
- this.textarea = this.domNode;
- this.name = this.textarea.name;
- var html = this._preFilterContent(this.textarea.value);
- this.domNode = dojo.doc.createElement("div");
- this.domNode.setAttribute('widgetId', this.id);
- this.textarea.removeAttribute('widgetId');
- this.domNode.cssText = this.textarea.cssText;
- this.domNode.className += " " + this.textarea.className;
- dojo.place(this.domNode, this.textarea, "before");
- var tmpFunc = dojo.hitch(this, function() {
- // some browsers refuse to submit display=none
- // textarea, so
- // move the textarea out of screen instead
- with (this.textarea.style) {
- display = "block";
- position = "absolute";
- left = top = "-1000px";
- if (dojo.isIE) { // nasty IE bug: abnormal
- // formatting if overflow is
- // not hidden
- this.__overflow = overflow;
- overflow = "hidden";
- }
- }
- });
- if (dojo.isIE) {
- setTimeout(tmpFunc, 10);
- } else {
- tmpFunc();
- }
- // this.domNode.innerHTML = html;
- // if(this.textarea.form){
- // // FIXME: port: this used to be before advice!!!
- // dojo.connect(this.textarea.form, "onsubmit", this,
- // function(){
- // // FIXME: should we be calling close() here instead?
- // this.textarea.value = this.getValue();
- // });
- // }
- } else {
- var html = this._preFilterContent(this
- .getNodeChildrenHtml(this.domNode));
- this.domNode.innerHTML = '';
- }
- if (html == "") {
- html = " ";
- }
- var content = dojo.contentBox(this.domNode);
- // var content = dojo.contentBox(this.srcNodeRef);
- this._oldHeight = content.h;
- this._oldWidth = content.w;
- this.savedContent = 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 ((this.domNode["nodeName"]) && (this.domNode.nodeName == "LI")) {
- this.domNode.innerHTML = " <br>";
- }
- this.editingArea = dojo.doc.createElement("div");
- this.domNode.appendChild(this.editingArea);
- if (this.name != ""
- && (!djConfig["useXDomain"] || djConfig["allowXdRichTextSave"])) {
- var saveTextarea = dojo
- .byId("dijit._editor.RichText.savedContent");
- if (saveTextarea.value != "") {
- var datas = saveTextarea.value.split(this._SEPARATOR), i = 0, dat;
- while ((dat = datas[i++])) {
- var data = dat.split(":");
- if (data[0] == this.name) {
- html = data[1];
- datas.splice(i, 1);
- break;
- }
- }
- }
- // FIXME: need to do something different for Opera/Safari
- dojo.connect(window, "onbeforeunload", this, "_saveContent");
- // dojo.connect(window, "onunload", this, "_saveContent");
- }
- this.isClosed = false;
- // Safari's selections go all out of whack if we do it inline,
- // so for now IE is our only hero
- // if (typeof document.body.contentEditable != "undefined") {
- if (dojo.isIE || dojo.isSafari || dojo.isOpera) { // contentEditable,
- // easy
- var ifr = this.iframe = dojo.doc.createElement('iframe');
- ifr.src = 'javascript:void(0)';
- this.editorObject = ifr;
- ifr.style.border = "none";
- ifr.style.width = "100%";
- ifr.frameBorder = 0;
- // ifr.style.scrolling = this.height ? "auto" : "vertical";
- this.editingArea.appendChild(ifr);
- this.window = ifr.contentWindow;
- this.document = this.window.document;
- this.document.open();
- this.document.write(this._getIframeDocTxt(html));
- this.document.close();
- 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;
- }
- if (dojo.isIE) {
- this._localizeEditorCommands();
- }
- this.onLoad();
- } else { // designMode in iframe
- this._drawIframe(html);
- }
- // TODO: this is a guess at the default line-height, kinda works
- if (this.domNode.nodeName == "LI") {
- this.domNode.lastChild.style.marginTop = "-1.2em";
- }
- this.domNode.className += " RichTextEditable";
- },
- // static cache variables shared among all instance of this class
- _local2NativeFormatNames : {},
- _native2LocalFormatNames : {},
- _localizedIframeTitles : null,
- _getIframeDocTxt : function(/* String */html) {
- var _cs = dojo.getComputedStyle(this.domNode);
- if (!this.height && !dojo.isMoz) {
- html = "<div>" + html + "</div>";
- }
- 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 {
- lineHeight = "1.0";
- }
- return [
- this.isLeftToRight()
- ? "<html><head>"
- : "<html dir='rtl'><head>",
- (dojo.isMoz ? "<title>"
- + this._localizedIframeTitles.iframeEditTitle
- + "</title>" : ""),
- "<style>",
- "body,html {",
- " background:transparent;",
- " padding: 0;",
- " margin: 0;",
- "}",
- // TODO: left positioning will cause contents to disappear
- // out of view
- // if it gets too wide for the visible area
- "body{",
- " top:0px; left:0px; right:0px;",
- ((this.height || dojo.isOpera) ? "" : "position: fixed;"),
- " font:",
- font,
- ";",
- // FIXME: IE 6 won't understand min-height?
- " min-height:",
- this.minHeight,
- ";",
- " line-height:",
- lineHeight,
- "}",
- "p{ margin: 1em 0 !important; }",
- (this.height
- ? ""
- : "body,html{overflow-y:hidden;/*for IE*/} body > div {overflow-x:auto;/*for FF to show vertical scrollbar*/}"),
- "li > ul:-moz-first-node, li > ol:-moz-first-node{ padding-top: 1.2em; } ",
- "li{ min-height:1.2em; }", "</style>",
- this._applyEditingAreaStyleSheets(),
- "</head><body>" + html + "</body></html>"].join(""); // String
- },
- _drawIframe : function(/* String */html) {
- // summary:
- // Draws an iFrame using the existing one if one exists.
- // Used by Mozilla, Safari, and Opera
- if (!this.iframe) {
- var ifr = this.iframe = dojo.doc.createElement("iframe");
- // this.iframe.src = "about:blank";
- // document.body.appendChild(this.iframe);
- // console.debug(this.iframe.contentDocument.open());
- // dojo.body().appendChild(this.iframe);
- var ifrs = ifr.style;
- // ifrs.border = "1px solid black";
- ifrs.border = "none";
- ifrs.lineHeight = "0"; // squash line height
- ifrs.verticalAlign = "bottom";
- // ifrs.scrolling = this.height ? "auto" : "vertical";
- this.editorObject = this.iframe;
- // get screen reader text for mozilla here, too
- this._localizedIframeTitles = dojo.i18n.getLocalization(
- "dijit", "Textarea");
- // need to find any associated label element and update iframe
- // document title
- var label = dojo.query('label[for="' + this.id + '"]');
- if (label.length) {
- this._localizedIframeTitles.iframeEditTitle = label[0].innerHTML
- + " " + this._localizedIframeTitles.iframeEditTitle;
- }
- }
- // opera likes this to be outside the with block
- // this.iframe.src =
- // "javascript:void(0)";//dojo.uri.dojoUri("src/widget/templates/richtextframe.html")
- // + ((dojo.doc.domain != currentDomain) ? ("#"+dojo.doc.domain) :
- // "");
- this.iframe.style.width = this.inheritWidth
- ? this._oldWidth
- : "100%";
- if (this.height) {
- this.iframe.style.height = this.height;
- } else {
- this.iframe.height = this._oldHeight;
- }
- if (this.textarea) {
- var tmpContent = this.srcNodeRef;
- } else {
- var tmpContent = dojo.doc.createElement('div');
- tmpContent.style.display = "none";
- tmpContent.innerHTML = html;
- // append tmpContent to under the current domNode so that the
- // margin
- // calculation below is correct
- this.editingArea.appendChild(tmpContent);
- }
- this.editingArea.appendChild(this.iframe);
- // do we want to show the content before the editing area finish
- // loading here?
- // if external style sheets are used for the editing area, the
- // appearance now
- // and after loading of the editing area won't be the same (and
- // padding/margin
- // calculation above may not be accurate)
- // tmpContent.style.display = "none";
- // this.editingArea.appendChild(this.iframe);
- var _iframeInitialized = false;
- // console.debug(this.iframe);
- // var contentDoc = this.iframe.contentWindow.document;
- // note that on Safari lower than 420+, we have to get the iframe
- // by ID in order to get something w/ a contentDocument property
- var contentDoc = this.iframe.contentDocument;
- contentDoc.open();
- contentDoc.write(this._getIframeDocTxt(html));
- contentDoc.close();
- // now we wait for onload. Janky hack!
- var ifrFunc = dojo.hitch(this, function() {
- if (!_iframeInitialized) {
- _iframeInitialized = true;
- } else {
- return;
- }
- if (!this.editNode) {
- try {
- if (this.iframe.contentWindow) {
- this.window = this.iframe.contentWindow;
- this.document = this.iframe.contentWindow.document
- } else if (this.iframe.contentDocument) {
- // for opera
- this.window = this.iframe.contentDocument.window;
- this.document = this.iframe.contentDocument;
- }
- if (!this.document.body) {
- throw 'Error';
- }
- } catch (e) {
- setTimeout(ifrFunc, 500);
- _iframeInitialized = false;
- return;
- }
- dojo._destroyElement(tmpContent);
- this.document.designMode = "on";
- // try{
- // this.document.designMode = "on";
- // }catch(e){
- // this._tryDesignModeOnClick=true;
- // }
- this.onLoad();
- } else {
- dojo._destroyElement(tmpContent);
- this.editNode.innerHTML = html;
- this.onDisplayChanged();
- }
- this._preDomFilterContent(this.editNode);
- });
- ifrFunc();
- },
- _applyEditingAreaStyleSheets : function() {
- // summary:
- // apply the specified css files in styleSheets
- 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 to the editing area!");
- return;
- }
- this.editingAreaStyleSheets.push(url);
- if (this.document.createStyleSheet) { // IE
- this.document.createStyleSheet(url);
- } else { // other browser
- var head = this.document.getElementsByTagName("head")[0];
- var stylesheet = this.document.createElement("link");
- with (stylesheet) {
- rel = "stylesheet";
- type = "text/css";
- href = url;
- }
- head.appendChild(stylesheet);
- }
- },
- removeStyleSheet : function(/* dojo._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
- + " is not applied to the editing area so it can not be removed!");
- return;
- }
- delete this.editingAreaStyleSheets[index];
- dojo.withGlobal(this.window, 'query', dojo,
- ['link:[href="' + url + '"]']).orphan()
- },
- disabled : false,
- _mozSettingProps : ['styleWithCSS', 'insertBrOnReturn'],
- setDisabled : function(/* Boolean */disabled) {
- if (dojo.isIE || dojo.isSafari || dojo.isOpera) {
- this.editNode.contentEditable = !disabled;
- } else { // moz
- if (disabled) {
- this._mozSettings = [false, this.blockNodeForEnter === 'BR'];
- }
- this.document.designMode = (disabled ? 'off' : 'on');
- if (!disabled) {
- dojo.forEach(this._mozSettingProps, function(s, i) {
- this.document.execCommand(s, false,
- this._mozSettings[i]);
- }, this);
- }
- // this.document.execCommand('contentReadOnly', false,
- // disabled);
- // if(disabled){
- // this.blur(); //to remove the blinking caret
- // }
- //
- }
- this.disabled = disabled;
- },
- /***********************************************************************
- * Event handlers
- **********************************************************************/
- _isResized : function() {
- return false;
- },
- onLoad : function(/* Event */e) {
- // summary: handler after the content of the document finishes
- // loading
- this.isLoaded = true;
- if (this.height || dojo.isMoz) {
- this.editNode = this.document.body;
- } else {
- this.editNode = this.document.body.firstChild;
- }
- this.editNode.contentEditable = true; // should do no harm in FF
- this._preDomFilterContent(this.editNode);
- var events = this.events.concat(this.captureEvents), i = 0, et;
- while ((et = events[i++])) {
- this.connect(this.document, et.toLowerCase(), et);
- }
- if (!dojo.isIE) {
- try { // sanity check for Mozilla
- // this.document.execCommand("useCSS", false, true); // old moz
- // call
- this.document.execCommand("styleWithCSS", false, false); // new
- // moz
- // call
- // this.document.execCommand("insertBrOnReturn", false,
- // false); // new moz call
- } catch (e2) {
- }
- // FIXME: when scrollbars appear/disappear this needs to be
- // fired
- } else { // IE contentEditable
- // give the node Layout on IE
- this.editNode.style.zoom = 1.0;
- }
- if (this.focusOnLoad) {
- this.focus();
- }
- this.onDisplayChanged(e);
- if (this.onLoadDeferred) {
- this.onLoadDeferred.callback(true);
- }
- },
- onKeyDown : function(/* Event */e) {
- // summary: Fired on keydown
- // console.info("onkeydown:", e.keyCode);
- // we need this event at the moment to get the events from control
- // keys
- // such as the backspace. It might be possible to add this to Dojo,
- // so that
- // keyPress events can be emulated by the keyDown and keyUp
- // detection.
- if (dojo.isIE) {
- 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);
- }
- } else if (dojo.isMoz) {
- if (e.keyCode == dojo.keys.TAB && !e.shiftKey && !e.ctrlKey
- && !e.altKey && this.iframe) {
- // update iframe document title for screen reader
- this.iframe.contentDocument.title = this._localizedIframeTitles.iframeFocusTitle;
- // Place focus on the iframe. A subsequent tab or shift tab
- // will put focus
- // on the correct control.
- this.iframe.focus(); // this.focus(); won't work
- dojo.stopEvent(e);
- } else if (e.keyCode == dojo.keys.TAB && e.shiftKey) {
- // if there is a toolbar, set focus to it, otherwise ignore
- if (this.toolbar) {
- this.toolbar.focus();
- }
- dojo.stopEvent(e);
- }
- }
- },
- onKeyUp : function(e) {
- // summary: Fired on keyup
- return;
- },
- KEY_CTRL : 1,
- KEY_SHIFT : 2,
- onKeyPress : function(e) {
- // summary: Fired on keypress
- // console.info("onkeypress:", e.keyCode);
- // handle the various key events
- var modifiers = e.ctrlKey ? this.KEY_CTRL : 0 | e.shiftKey
- ? this.KEY_SHIFT
- : 0;
- var key = e.keyChar || e.keyCode;
- if (this._keyHandlers[key]) {
- // console.debug("char:", e.key);
- var handlers = this._keyHandlers[key], i = 0, h;
- while ((h = handlers[i++])) {
- if (modifiers == h.modifiers) {
- if (!h.handler.apply(this, arguments)) {
- e.preventDefault();
- }
- break;
- }
- }
- }
- // function call after the character has been inserted
- setTimeout(dojo.hitch(this, function() {
- this.onKeyPressed(e);
- }), 1);
- },
- addKeyHandler : function(/* String */key, /* Int */modifiers, /* Function */
- handler) {
- // summary: add a handler for a keyboard shortcut
- if (!dojo.isArray(this._keyHandlers[key])) {
- this._keyHandlers[key] = [];
- }
- this._keyHandlers[key].push({
- modifiers : modifiers || 0,
- handler : handler
- });
- },
- onKeyPressed : function(/* Event */e) {
- this.onDisplayChanged(/* e */); // can't pass in e
- },
- onClick : function(/* Event */e) {
- // console.debug('onClick',this._tryDesignModeOnClick);
- // if(this._tryDesignModeOnClick){
- // try{
- // this.document.designMode='on';
- // this._tryDesignModeOnClick=false;
- // }catch(e){}
- // }
- this.onDisplayChanged(e);
- },
- _onBlur : function(e) {
- var _c = this.getValue(true);
- if (_c != this.savedContent) {
- this.onChange(_c);
- this.savedContent = _c;
- }
- if (dojo.isMoz && this.iframe) {
- this.iframe.contentDocument.title = this._localizedIframeTitles.iframeEditTitle;
- }
- // console.info('_onBlur')
- },
- _initialFocus : true,
- _onFocus : function(/* Event */e) {
- // console.info('_onFocus')
- // summary: Fired on focus
- if ((dojo.isMoz) && (this._initialFocus)) {
- this._initialFocus = false;
- if (this.editNode.innerHTML.replace(/^\s+|\s+$/g, "") == " ") {
- this.placeCursorAtStart();
- // this.execCommand("selectall");
- // this.window.getSelection().collapseToStart();
- }
- }
- },
- blur : function() {
- // summary: remove focus from this instance
- if (this.iframe) {
- this.window.blur();
- } else if (this.editNode) {
- this.editNode.blur();
- }
- },
- focus : function() {
- // summary: move focus to this instance
- if (this.iframe && !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
- dijit.focus(this.editNode);
- } else {
- 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
- // var _t=allGetServerTime();
- if (!this._updateTimer) {
- // this._lastUpdate=_t;
- if (this._updateTimer) {
- clearTimeout(this._updateTimer);
- }
- this._updateTimer = setTimeout(dojo.hitch(this,
- this.onNormalizedDisplayChanged),
- this.updateInterval);
- }
- },
- onNormalizedDisplayChanged : function() {
- // summary:
- // This event is fired every updateInterval ms or more
- // description:
- // If something needs to happen immidiately after a
- // user change, please use onDisplayChanged instead
- this._updateTimer = null;
- },
- onChange : function(newContent) {
- // summary:
- // this is fired if and only if the editor loses focus and
- // the content is changed
- // console.log('onChange',newContent);
- },
- _normalizeCommand : function(/* String */cmd) {
- // summary:
- // Used as the advice function by dojo.connect to map our
- // normalized set of commands to those supported by the target
- // browser
- var command = cmd.toLowerCase();
- if (command == "formatblock") {
- if (dojo.isSafari) {
- command = "heading";
- }
- } else if (command == "hilitecolor" && !dojo.isMoz) {
- command = "backcolor";
- }
- return command;
- },
- 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
- var ie = 1;
- var mozilla = 1 << 1;
- var safari = 1 << 2;
- var opera = 1 << 3;
- var safari420 = 1 << 4;
- var gt420 = dojo.isSafari;
- function isSupportedBy(browsers) {
- return {
- ie : Boolean(browsers & ie),
- mozilla : Boolean(browsers & mozilla),
- safari : Boolean(browsers & safari),
- safari420 : Boolean(browsers & safari420),
- 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" :
- supportedBy = isSupportedBy(mozilla | ie | safari | 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" :
- supportedBy = isSupportedBy(mozilla | ie | opera
- | safari420);
- 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 | safari420);
- 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.isSafari && supportedBy.safari)
- || (gt420 && supportedBy.safari420)
- || (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
- 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);
- if (argument != undefined) {
- if (command == "heading") {
- throw new Error("unimplemented");
- } else if ((command == "formatblock") && dojo.isIE) {
- argument = '<' + argument + '>';
- }
- }
- if (command == "inserthtml") {
- // TODO: we shall probably call _preDomFilterContent here as
- // well
- argument = this._preFilterContent(argument);
- if (dojo.isIE) {
- var insertRange = this.document.selection.createRange();
- insertRange.pasteHTML(argument);
- insertRange.select();
- // insertRange.collapse(true);
- returnValue = 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
- dojo.withGlobal(this.window, 'remove',
- dijit._editor.selection); // FIXME
- returnValue = true;
- } else {
- returnValue = this.document.execCommand(command, false,
- argument);
- }
- } else if ((command == "unlink")
- && (this.queryCommandEnabled("unlink"))
- && (dojo.isMoz || dojo.isSafari)) {
- // fix up unlink in Mozilla to unlink the link and not just the
- // selection
- // grab selection
- // Mozilla gets upset if we just store the range so we have to
- // get the basic properties and recreate to save the selection
- var selection = this.window.getSelection();
- // var selectionRange = selection.getRangeAt(0);
- // var selectionStartContainer = selectionRange.startContainer;
- // var selectionStartOffset = selectionRange.startOffset;
- // var selectionEndContainer = selectionRange.endContainer;
- // var selectionEndOffset = selectionRange.endOffset;
- // select our link and unlink
- var a = dojo.withGlobal(this.window, "getAncestorElement",
- dijit._editor.selection, ['a']);
- dojo.withGlobal(this.window, "selectElement",
- dijit._editor.selection, [a]);
- returnValue = this.document.execCommand("unlink", false, null);
- } else if ((command == "hilitecolor") && (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(command, false,
- argument);
- this.document.execCommand("styleWithCSS", false, false);
- } else if ((dojo.isIE)
- && ((command == "backcolor") || (command == "forecolor"))) {
- // 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 = arguments.length > 1 ? argument : null;
- returnValue = this.document.execCommand(command, false,
- argument);
- // timeout is workaround for weird IE behavior were the text
- // selection gets correctly re-created, but subsequent input
- // apparently isn't bound to it
- // setTimeout(function(){tr.select();}, 1);
- } else {
- argument = arguments.length > 1 ? argument : null;
- // if(dojo.isMoz){
- // this.document = this.iframe.contentWindow.document
- // }
- 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
- command = this._normalizeCommand(command);
- if (dojo.isMoz || dojo.isSafari) {
- if (command == "unlink") { // mozilla returns true always
- // console.debug(dojo.withGlobal(this.window,
- // "hasAncestorElement",dijit._editor.selection, ['a']));
- return dojo.withGlobal(this.window, "hasAncestorElement",
- dijit._editor.selection, ['a']);
- } else if (command == "inserttable") {
- return true;
- }
- }
- // see #4109
- if (dojo.isSafari)
- if (command == "copy") {
- command = "cut";
- } else if (command == "paste") {
- return true;
- }
- // return this.document.queryCommandEnabled(command);
- var elem = (dojo.isIE)
- ? this.document.selection.createRange()
- : this.document;
- return elem.queryCommandEnabled(command);
- },
- queryCommandState : function(command) {
- // summary: check the state of a given command
- command = this._normalizeCommand(command);
- return this.document.queryCommandState(command);
- },
- queryCommandValue : function(command) {
- // summary: check the value of a given command
- command = this._normalizeCommand(command);
- if (dojo.isIE && command == "formatblock") {
- return this._local2NativeFormatNames[this.document
- .queryCommandValue(command)];
- }
- return this.document.queryCommandValue(command);
- },
- // Misc.
- placeCursorAtStart : function() {
- // summary:
- // place the cursor at the start of the editing area
- this.focus();
- // see comments in placeCursorAtEnd
- var isvalid = false;
- if (dojo.isMoz) {
- var first = this.editNode.firstChild;
- while (first) {
- if (first.nodeType == 3) {
- if (first.nodeValue.replace(/^\s+|\s+$/g, "").length > 0) {
- isvalid = true;
- dojo.withGlobal(this.window, "selectElement",
- dijit._editor.selection, [first]);
- break;
- }
- } else if (first.nodeType == 1) {
- isvalid = true;
- dojo.withGlobal(this.window, "selectElementChildren",
- dijit._editor.selection, [first]);
- break;
- }
- first = first.nextSibling;
- }
- } else {
- isvalid = true;
- dojo.withGlobal(this.window, "selectElementChildren",
- dijit._editor.selection, [this.editNode]);
- }
- if (isvalid) {
- dojo.withGlobal(this.window, "collapse",
- dijit._editor.selection, [true]);
- }
- },
- placeCursorAtEnd : function() {
- // summary:
- // place the cursor at the end of the editing area
- 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;
- dojo.withGlobal(this.window, "selectElement",
- dijit._editor.selection, [last]);
- break;
- }
- } else if (last.nodeType == 1) {
- isvalid = true;
- if (last.lastChild) {
- dojo.withGlobal(this.window, "selectElement",
- dijit._editor.selection, [last.lastChild]);
- } else {
- dojo.withGlobal(this.window, "selectElement",
- dijit._editor.selection, [last]);
- }
- break;
- }
- last = last.previousSibling;
- }
- } else {
- isvalid = true;
- dojo.withGlobal(this.window, "selectElementChildren",
- dijit._editor.selection, [this.editNode]);
- }
- if (isvalid) {
- dojo.withGlobal(this.window, "collapse",
- dijit._editor.selection, [false]);
- }
- },
- getValue : function(/* Boolean? */nonDestructive) {
- // summary:
- // return the current content of the editing area (post filters are
- // applied)
- if (this.textarea) {
- if (this.isClosed || !this.isLoaded) {
- return this.textarea.value;
- }
- }
- return this._postFilterContent(null, nonDestructive);
- },
- setValue : function(/* String */html) {
- // summary:
- // this function set the content. No undo history is preserved
- if (this.textarea && (this.isClosed || !this.isLoaded)) {
- this.textarea.value = html;
- } else {
- html = this._preFilterContent(html);
- if (this.isClosed) {
- this.domNode.innerHTML = html;
- this._preDomFilterContent(this.domNode);
- } else {
- this.editNode.innerHTML = html;
- this._preDomFilterContent(this.editNode);
- }
- }
- },
- 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)
- 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 (dojo.isMoz && !html) {
- 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);
- }
- },
- _preFilterContent : function(/* String */html) {
- // summary:
- // filter the input before setting the content of the editing area
- var ec = html;
- dojo.forEach(this.contentPreFilters, function(ef) {
- if (ef) {
- ec = ef(ec);
- }
- });
- return ec;
- },
- _preDomFilterContent : function(/* DomNode */dom) {
- // summary:
- // filter the input
- dom = dom || this.editNode;
- dojo.forEach(this.contentDomPreFilters, function(ef) {
- if (ef && dojo.isFunction(ef)) {
- ef(dom);
- }
- }, this);
- },
- _postFilterContent : function(/* DomNode|DomNode[]? */dom,/* Boolean? */
- nonDestructive) {
- // summary:
- // filter the output after getting the content of the editing area
- dom = dom || this.editNode;
- if (this.contentDomPostFilters.length) {
- if (nonDestructive && dom['cloneNode']) {
- dom = dom.cloneNode(true);
- }
- dojo.forEach(this.contentDomPostFilters, function(ef) {
- dom = ef(dom);
- });
- }
- var ec = this.getNodeChildrenHtml(dom);
- if (!ec.replace(/^(?:\s|\xA0)+/g, "").replace(/(?:\s|\xA0)+$/g, "").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
- var saveTextarea = dojo.byId("dijit._editor.RichText.savedContent");
- saveTextarea.value += this._SEPARATOR + this.name + ":"
- + this.getValue();
- },
- escapeXml : function(/* String */str, /* Boolean */noSingleQuotes) {
- // summary:
- // Adds escape sequences for special characters in XML: &<>"'
- // Optionally skips escapes for single quotes
- str = str.replace(/&/gm, "&").replace(/</gm, "<").replace(
- />/gm, ">").replace(/"/gm, """);
- if (!noSingleQuotes) {
- str = str.replace(/'/gm, "'");
- }
- return str; // string
- },
- getNodeHtml : function(/* DomNode */node) {
- switch (node.nodeType) {
- case 1 : // element node
- var output = '<' + node.tagName.toLowerCase();
- if (dojo.isMoz) {
- if (node.getAttribute('type') == '_moz') {
- node.removeAttribute('type');
- }
- if (node.getAttribute('_moz_dirty') != undefined) {
- node.removeAttribute('_moz_dirty');
- }
- }
- // store the list of attributes and sort it to have the
- // attributes appear in the dictionary order
- var attrarray = [];
- if (dojo.isIE) {
- var s = node.outerHTML;
- s = s.substr(0, s.indexOf('>'));
- s = s.replace(/(?:['"])[^"']*\1/g, '');// to make the
- // following
- // regexp safe
- var reg = /([^\s=]+)=/g;
- var m, key;
- while ((m = reg.exec(s)) != undefined) {
- key = m[1];
- if (key.substr(0, 3) != '_dj') {
- if (key == 'src' || key == 'href') {
- if (node.getAttribute('_djrealurl')) {
- attrarray
- .push([
- key,
- node
- .getAttribute('_djrealurl')]);
- continue;
- }
- }
- if (key == 'class') {
- attrarray.push([key, node.className]);
- } else {
- attrarray
- .push([key, node.getAttribute(key)]);
- }
- }
- }
- } else {
- var attr, i = 0, attrs = node.attributes;
- while ((attr = attrs[i++])) {
- // ignore all attributes starting with _dj which are
- // internal temporary attributes used by the editor
- if (attr.name.substr(0, 3) != '_dj' /*
- * &&
- * (attr.specified ==
- * undefined ||
- * attr.specified)
- */) {
- var v = attr.value;
- if (attr.name == 'src' || attr.name == 'href') {
- if (node.getAttribute('_djrealurl')) {
- v = node.getAttribute('_djrealurl');
- }
- }
- attrarray.push([attr.name, v]);
- }
- }
- }
- attrarray.sort(function(a, b) {
- return a[0] < b[0]
- ? -1
- : (a[0] == b[0] ? 0 : 1);
- });
- i = 0;
- while ((attr = attrarray[i++])) {
- output += ' ' + attr[0] + '="' + attr[1] + '"';
- }
- if (node.childNodes.length) {
- output += '>' + this.getNodeChildrenHtml(node) + '</'
- + node.tagName.toLowerCase() + '>';
- } else {
- output += ' />';
- }
- break;
- case 3 : // text
- // FIXME:
- var output = this.escapeXml(node.nodeValue, true);
- break;
- case 8 : // comment
- // FIXME:
- var output = '<!--' + this.escapeXml(node.nodeValue, true)
- + '-->';
- break;
- default :
- var output = "Element not recognized - Type: "
- + node.nodeType + " Name: " + node.nodeName;
- }
- return output;
- },
- getNodeChildrenHtml : function(/* DomNode */dom) {
- // summary: Returns the html content of a DomNode and children
- var out = "";
- if (!dom) {
- return out;
- }
- var nodes = dom["childNodes"] || dom;
- var i = 0;
- var node;
- while ((node = nodes[i++])) {
- out += this.getNodeHtml(node);
- }
- return out; // String
- },
- close : function(/* Boolean */save, /* Boolean */force) {
- // 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.
- // force:
- if (this.isClosed) {
- return false;
- }
- if (!arguments.length) {
- save = true;
- }
- this._content = this.getValue();
- var changed = (this.savedContent != this._content);
- // 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.textarea) {
- with (this.textarea.style) {
- position = "";
- left = top = "";
- if (dojo.isIE) {
- overflow = this.__overflow;
- this.__overflow = null;
- }
- }
- if (save) {
- this.textarea.value = this._content;
- } else {
- this.textarea.value = this.savedContent;
- }
- dojo._destroyElement(this.domNode);
- this.domNode = this.textarea;
- } else {
- if (save) {
- // why we treat moz differently? comment out to fix #1061
- // if(dojo.isMoz){
- // var nc = dojo.doc.createElement("span");
- // this.domNode.appendChild(nc);
- // nc.innerHTML = this.editNode.innerHTML;
- // }else{
- // this.domNode.innerHTML = this._content;
- // }
- this.domNode.innerHTML = this._content;
- } else {
- this.domNode.innerHTML = this.savedContent;
- }
- }
- dojo.removeClass(this.domNode, "RichTextEditable");
- this.isClosed = true;
- this.isLoaded = false;
- // FIXME: is this always the right thing to do?
- delete this.editNode;
- if (this.window && this.window._frameElement) {
- this.window._frameElement = null;
- }
- this.window = null;
- this.document = null;
- this.editingArea = null;
- this.editorObject = null;
- return changed; // Boolean: whether the content has been modified
- },
- destroyRendering : function() {
- // summary: stub
- },
- destroy : function() {
- this.destroyRendering();
- if (!this.isClosed) {
- this.close(false);
- }
- this.inherited("destroy", arguments);
- // dijit._editor.RichText.superclass.destroy.call(this);
- },
- _fixContentForMoz : function(/* String */html) {
- // summary:
- // Moz can not handle strong/em tags correctly, convert them to b/i
- html = html.replace(/<(\/)?strong([ \>])/gi, '<$1b$2');
- html = html.replace(/<(\/)?em([ \>])/gi, '<$1i$2');
- return html; // String
- },
- _srcInImgRegex : /(?:(<img(?=\s).*?\ssrc=)("|')(.*?)\2)|(?:(<img\s.*?src=)([^"'][^ >]+))/gi,
- _hrefInARegex : /(?:(<a(?=\s).*?\shref=)("|')(.*?)\2)|(?:(<a\s.*?href=)([^"'][^ >]+))/gi,
- _preFixUrlAttributes : function(/* String */html) {
- html = html.replace(this._hrefInARegex,
- '$1$4$2$3$5$2 _djrealurl=$2$3$5$2');
- html = html.replace(this._srcInImgRegex,
- '$1$4$2$3$5$2 _djrealurl=$2$3$5$2');
- return html; // String
- }
- });
- }
|