summaryrefslogtreecommitdiff
path: root/includes/js/dijit/_editor
diff options
context:
space:
mode:
Diffstat (limited to 'includes/js/dijit/_editor')
-rw-r--r--includes/js/dijit/_editor/RichText.js1449
-rw-r--r--includes/js/dijit/_editor/_Plugin.js101
-rw-r--r--includes/js/dijit/_editor/html.js106
-rw-r--r--includes/js/dijit/_editor/nls/FontChoice.js1
-rw-r--r--includes/js/dijit/_editor/nls/LinkDialog.js1
-rw-r--r--includes/js/dijit/_editor/nls/ar/FontChoice.js1
-rw-r--r--includes/js/dijit/_editor/nls/ar/LinkDialog.js1
-rw-r--r--includes/js/dijit/_editor/nls/ar/commands.js1
-rw-r--r--includes/js/dijit/_editor/nls/commands.js1
-rw-r--r--includes/js/dijit/_editor/nls/cs/FontChoice.js1
-rw-r--r--includes/js/dijit/_editor/nls/cs/LinkDialog.js1
-rw-r--r--includes/js/dijit/_editor/nls/cs/commands.js1
-rw-r--r--includes/js/dijit/_editor/nls/da/FontChoice.js1
-rw-r--r--includes/js/dijit/_editor/nls/da/LinkDialog.js1
-rw-r--r--includes/js/dijit/_editor/nls/da/commands.js1
-rw-r--r--includes/js/dijit/_editor/nls/de/FontChoice.js1
-rw-r--r--includes/js/dijit/_editor/nls/de/LinkDialog.js1
-rw-r--r--includes/js/dijit/_editor/nls/de/commands.js1
-rw-r--r--includes/js/dijit/_editor/nls/el/FontChoice.js1
-rw-r--r--includes/js/dijit/_editor/nls/el/LinkDialog.js1
-rw-r--r--includes/js/dijit/_editor/nls/el/commands.js1
-rw-r--r--includes/js/dijit/_editor/nls/es/FontChoice.js1
-rw-r--r--includes/js/dijit/_editor/nls/es/LinkDialog.js1
-rw-r--r--includes/js/dijit/_editor/nls/es/commands.js1
-rw-r--r--includes/js/dijit/_editor/nls/fi/FontChoice.js1
-rw-r--r--includes/js/dijit/_editor/nls/fi/LinkDialog.js1
-rw-r--r--includes/js/dijit/_editor/nls/fi/commands.js1
-rw-r--r--includes/js/dijit/_editor/nls/fr/FontChoice.js1
-rw-r--r--includes/js/dijit/_editor/nls/fr/LinkDialog.js1
-rw-r--r--includes/js/dijit/_editor/nls/fr/commands.js1
-rw-r--r--includes/js/dijit/_editor/nls/he/FontChoice.js1
-rw-r--r--includes/js/dijit/_editor/nls/he/LinkDialog.js1
-rw-r--r--includes/js/dijit/_editor/nls/he/commands.js1
-rw-r--r--includes/js/dijit/_editor/nls/hu/FontChoice.js1
-rw-r--r--includes/js/dijit/_editor/nls/hu/LinkDialog.js1
-rw-r--r--includes/js/dijit/_editor/nls/hu/commands.js1
-rw-r--r--includes/js/dijit/_editor/nls/it/FontChoice.js1
-rw-r--r--includes/js/dijit/_editor/nls/it/LinkDialog.js1
-rw-r--r--includes/js/dijit/_editor/nls/it/commands.js1
-rw-r--r--includes/js/dijit/_editor/nls/ja/FontChoice.js1
-rw-r--r--includes/js/dijit/_editor/nls/ja/LinkDialog.js1
-rw-r--r--includes/js/dijit/_editor/nls/ja/commands.js1
-rw-r--r--includes/js/dijit/_editor/nls/ko/FontChoice.js1
-rw-r--r--includes/js/dijit/_editor/nls/ko/LinkDialog.js1
-rw-r--r--includes/js/dijit/_editor/nls/ko/commands.js1
-rw-r--r--includes/js/dijit/_editor/nls/nb/FontChoice.js1
-rw-r--r--includes/js/dijit/_editor/nls/nb/LinkDialog.js1
-rw-r--r--includes/js/dijit/_editor/nls/nb/commands.js1
-rw-r--r--includes/js/dijit/_editor/nls/nl/FontChoice.js1
-rw-r--r--includes/js/dijit/_editor/nls/nl/LinkDialog.js1
-rw-r--r--includes/js/dijit/_editor/nls/nl/commands.js1
-rw-r--r--includes/js/dijit/_editor/nls/pl/FontChoice.js1
-rw-r--r--includes/js/dijit/_editor/nls/pl/LinkDialog.js1
-rw-r--r--includes/js/dijit/_editor/nls/pl/commands.js1
-rw-r--r--includes/js/dijit/_editor/nls/pt-pt/FontChoice.js1
-rw-r--r--includes/js/dijit/_editor/nls/pt-pt/LinkDialog.js1
-rw-r--r--includes/js/dijit/_editor/nls/pt-pt/commands.js1
-rw-r--r--includes/js/dijit/_editor/nls/pt/FontChoice.js1
-rw-r--r--includes/js/dijit/_editor/nls/pt/LinkDialog.js1
-rw-r--r--includes/js/dijit/_editor/nls/pt/commands.js1
-rw-r--r--includes/js/dijit/_editor/nls/ru/FontChoice.js1
-rw-r--r--includes/js/dijit/_editor/nls/ru/LinkDialog.js1
-rw-r--r--includes/js/dijit/_editor/nls/ru/commands.js1
-rw-r--r--includes/js/dijit/_editor/nls/sv/FontChoice.js1
-rw-r--r--includes/js/dijit/_editor/nls/sv/LinkDialog.js1
-rw-r--r--includes/js/dijit/_editor/nls/sv/commands.js1
-rw-r--r--includes/js/dijit/_editor/nls/tr/FontChoice.js1
-rw-r--r--includes/js/dijit/_editor/nls/tr/LinkDialog.js1
-rw-r--r--includes/js/dijit/_editor/nls/tr/commands.js1
-rw-r--r--includes/js/dijit/_editor/nls/zh-tw/FontChoice.js1
-rw-r--r--includes/js/dijit/_editor/nls/zh-tw/LinkDialog.js1
-rw-r--r--includes/js/dijit/_editor/nls/zh-tw/commands.js1
-rw-r--r--includes/js/dijit/_editor/nls/zh/FontChoice.js1
-rw-r--r--includes/js/dijit/_editor/nls/zh/LinkDialog.js1
-rw-r--r--includes/js/dijit/_editor/nls/zh/commands.js1
-rw-r--r--includes/js/dijit/_editor/plugins/AlwaysShowToolbar.js140
-rw-r--r--includes/js/dijit/_editor/plugins/EnterKeyHandling.js416
-rw-r--r--includes/js/dijit/_editor/plugins/FontChoice.js167
-rw-r--r--includes/js/dijit/_editor/plugins/LinkDialog.js147
-rw-r--r--includes/js/dijit/_editor/plugins/TextColor.js40
-rw-r--r--includes/js/dijit/_editor/plugins/ToggleDir.js40
-rw-r--r--includes/js/dijit/_editor/range.js570
-rw-r--r--includes/js/dijit/_editor/selection.js246
83 files changed, 3494 insertions, 0 deletions
diff --git a/includes/js/dijit/_editor/RichText.js b/includes/js/dijit/_editor/RichText.js
new file mode 100644
index 0000000..9ece365
--- /dev/null
+++ b/includes/js/dijit/_editor/RichText.js
@@ -0,0 +1,1449 @@
+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("dijit._editor.html");
+dojo.require("dojo.i18n");
+dojo.requireLocalization("dijit.form", "Textarea", null, "zh,pt,da,tr,ru,de,ROOT,sv,ja,he,fi,nb,el,ar,pt-pt,cs,fr,es,ko,nl,zh-tw,pl,it,hu");
+
+// 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.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._scopeName + '._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.contentPostFilters.push(this._removeMozBogus);
+ }else if(dojo.isSafari){
+ this.contentPostFilters.push(this._removeSafariBogus);
+ }
+ //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._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.
+ var exec = function(cmd, arg){
+ return arguments.length == 1 ? function(){ this.execCommand(cmd); } :
+ function(){ this.execCommand(cmd, arg); };
+ };
+
+ var ctrlKeyHandlers = { b: exec("bold"),
+ i: exec("italic"),
+ u: exec("underline"),
+ a: exec("selectall"),
+ s: function(){ this.save(true); },
+
+ "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, this.KEY_CTRL, ctrlKeyHandlers[key]);
+ }
+ },
+
+ // 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=dojo.doc.createElement('div');
+ div.style.position = "absolute";
+ div.style.left = "-2000px";
+ div.style.top = "-2000px";
+ dojo.doc.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] = dojo.doc.queryCommandValue("formatblock");//this.queryCommandValue("formatblock");
+ this._native2LocalFormatNames[this._local2NativeFormatNames[nativename]] = nativename;
+ node = node.nextSibling;
+ }
+ dojo.doc.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._scopeName + "._editor.RichText::open", [ this ]);
+
+ this._content = "";
+ if((arguments.length == 1)&&(element["nodeName"])){ this.domNode = element; } // else unchanged
+
+ var html;
+ 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;
+ 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
+ dojo.attr(this.textarea, 'tabIndex', '-1');
+ 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{
+ html = this._preFilterContent(dijit._editor.getChildrenHtml(this.domNode));
+ this.domNode.innerHTML = '';
+ }
+ if(html == ""){ html = "&nbsp;"; }
+
+ var content = dojo.contentBox(this.domNode);
+ // var content = dojo.contentBox(this.srcNodeRef);
+ this._oldHeight = content.h;
+ this._oldWidth = content.w;
+
+ // 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 != "" && (!dojo.config["useXDomain"] || dojo.config["allowXdRichTextSave"])){
+ var saveTextarea = dojo.byId(dijit._scopeName + "._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
+ this.connect(window, "onbeforeunload", "_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 dojo.doc.body.contentEditable != "undefined"){
+ if(dojo.isIE || dojo.isSafari || dojo.isOpera){ // contentEditable, easy
+
+ if(dojo.config["useXDomain"] && !dojo.config["dojoBlankHtmlUrl"]){
+ console.debug("dijit._editor.RichText: When using cross-domain Dojo builds,"
+ + " please save dojo/resources/blank.html to your domain and set djConfig.dojoBlankHtmlUrl"
+ + " to the path on your domain to blank.html");
+ }
+
+ var burl = dojo.config["dojoBlankHtmlUrl"] || (dojo.moduleUrl("dojo", "resources/blank.html")+"");
+ var ifr = this.editorObject = this.iframe = dojo.doc.createElement('iframe');
+ ifr.id = this.id+"_iframe";
+ ifr.src = burl;
+ ifr.style.border = "none";
+ ifr.style.width = "100%";
+ ifr.frameBorder = 0;
+ // ifr.style.scrolling = this.height ? "auto" : "vertical";
+ this.editingArea.appendChild(ifr);
+ var h = null; // set later in non-ie6 branch
+ var loadFunc = dojo.hitch( this, function(){
+ if(h){ dojo.disconnect(h); h = null; }
+ this.window = ifr.contentWindow;
+ var d = this.document = this.window.document;
+ d.open();
+ d.write(this._getIframeDocTxt(html));
+ d.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();
+ this.savedContent = this.getValue(true);
+ });
+ if(dojo.isIE && dojo.isIE < 7){ // IE 6 is a steaming pile...
+ var t = setInterval(function(){
+ if(ifr.contentWindow.isLoaded){
+ clearInterval(t);
+ loadFunc();
+ }
+ }, 100);
+ }else{ // blissful sanity!
+ h = dojo.connect(
+ ((dojo.isIE) ? ifr.contentWindow : ifr), "onload", loadFunc
+ );
+ }
+ }else{ // designMode in iframe
+ this._drawIframe(html);
+ this.savedContent = this.getValue(true);
+ }
+
+ // 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(dojo.isIE || (!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;",
+ " font:", font, ";",
+ " padding: 1em 0 0 0;",
+ " margin: -1em 0 0 0;", // remove extraneous vertical scrollbar on safari and firefox
+ " height: 100%;",
+ "}",
+ // 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;"),
+ // FIXME: IE 6 won't understand min-height?
+ " min-height:", this.minHeight, ";",
+ " line-height:", lineHeight,
+ "}",
+ "p{ margin: 1em 0 !important; }",
+ (this.height ? // height:auto undoes the height:100%
+ "" : "body,html{height:auto;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");
+ ifr.id=this.id;
+ // this.iframe.src = "about:blank";
+ // dojo.doc.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.form", "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;
+ }
+
+ var tmpContent;
+ if(this.textarea){
+ tmpContent = this.srcNodeRef;
+ }else{
+ 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();
+ if(dojo.isAIR){
+ contentDoc.body.innerHTML = html;
+ }else{
+ 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.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");
+ 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+" has not been applied");
+ return;
+ }
+ delete this.editingAreaStyleSheets[index];
+ dojo.withGlobal(this.window,'query', dojo, ['link:[href="'+url+'"]']).orphan()
+ },
+
+ disabled: true,
+ _mozSettingProps: ['styleWithCSS','insertBrOnReturn'],
+ setDisabled: function(/*Boolean*/ disabled){
+ if(dojo.isIE || dojo.isSafari || dojo.isOpera){
+ if(dojo.isIE){ this.editNode.unselectable = "on"; } // prevent IE from setting focus
+ this.editNode.contentEditable = !disabled;
+ if(dojo.isIE){
+ var _this = this;
+ setTimeout(function(){ _this.editNode.unselectable = "off"; }, 0);
+ }
+ }else{ //moz
+ if(disabled){
+ //AP: why isn't this set in the constructor, or put in mozSettingProps as a hash?
+ this._mozSettings=[false,this.blockNodeForEnter==='BR'];
+ }
+ this.document.designMode=(disabled?'off':'on');
+ if(!disabled && this._mozSettings){
+ 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.window.__registeredWindow){
+ this.window.__registeredWindow=true;
+ dijit.registerWin(this.window);
+ }
+ if(!dojo.isIE && (this.height || dojo.isMoz)){
+ this.editNode=this.document.body;
+ }else{
+ this.editNode=this.document.body.firstChild;
+ var _this = this;
+ if(dojo.isIE){ // #4996 IE wants to focus the BODY tag
+ var tabStop = this.tabStop = dojo.doc.createElement('<div tabIndex=-1>');
+ this.editingArea.appendChild(tabStop);
+ this.iframe.onfocus = function(){ _this.editNode.setActive(); }
+ }
+ }
+
+ try{
+ this.setDisabled(false);
+ }catch(e){
+ // Firefox throws an exception if the editor is initially hidden
+ // so, if this fails, try again onClick by adding "once" advice
+ var handle = dojo.connect(this, "onClick", this, function(){
+ this.setDisabled(false);
+ dojo.disconnect(handle);
+ });
+ }
+
+ 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
+ //AP: what's the point of this?
+// 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.connect(this.document, "onmousedown", "_onMouseDown"); // #4996 fix focus
+ this.editNode.style.zoom = 1.0;
+ }
+
+ if(this.focusOnLoad){
+ setTimeout(dojo.hitch(this, "focus"), 0); // have to wait for IE to set unselectable=off
+ }
+
+ this.onDisplayChanged(e);
+ if(this.onLoadDeferred){
+ this.onLoadDeferred.callback(true);
+ }
+ },
+
+ onKeyDown: function(/* Event */ e){
+ // summary: Fired on keydown
+
+ // 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.TAB && e.shiftKey && !e.ctrlKey && !e.altKey){
+ // focus the BODY so the browser will tab away from it instead
+ this.iframe.focus();
+ }else if(e.keyCode == dojo.keys.TAB && !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);
+ }
+ }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
+
+ // handle the various key events
+ var modifiers = (e.ctrlKey && !e.altKey) ? 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.info('onClick',this._tryDesignModeOn);
+ this.onDisplayChanged(e);
+ },
+
+ _onMouseDown: function(/*Event*/e){ // IE only to prevent 2 clicks to focus
+ if(!this._focused && !this.disabled){
+ this.focus();
+ }
+ },
+
+ _onBlur: function(e){
+ this.inherited(arguments);
+ 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;
+ }
+ },
+ _initialFocus: true,
+ _onFocus: function(/*Event*/e){
+ // summary: Fired on focus
+ this.inherited(arguments);
+ if(dojo.isMoz && this._initialFocus){
+ this._initialFocus = false;
+ if(this.editNode.innerHTML.replace(/^\s+|\s+$/g, "") == "&nbsp;"){
+ this.placeCursorAtStart();
+// this.execCommand("selectall");
+// this.window.getSelection().collapseToStart();
+ }
+ }
+ },
+
+ // TODO: why is this needed - should we deprecate this ?
+ blur: function(){
+ // summary: remove focus from this instance
+ 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 instance
+ 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
+
+// var _t=new Date();
+ 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 == "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": case "toggledir":
+ 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"){
+ argument=this._preFilterContent(argument);
+ 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);
+ 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);
+ 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
+
+ if(this.disabled){ return false; }
+ 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
+
+ if(this.disabled){ return false; }
+ command = this._normalizeCommand(command);
+ return this.document.queryCommandState(command);
+ },
+
+ queryCommandValue: function(command){
+ // summary: check the value of a given command
+
+ if(this.disabled){ return false; }
+ 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.isLoaded){
+ // try again after the editor is finished loading
+ this.onLoadDeferred.addCallback(dojo.hitch(this, function(){
+ this.setValue(html);
+ }));
+ return;
+ }
+
+ if(this.textarea && (this.isClosed || !this.isLoaded)){
+ this.textarea.value=html;
+ }else{
+ html = this._preFilterContent(html);
+ var node = this.isClosed ? this.domNode : this.editNode;
+ node.innerHTML = html;
+ this._preDomFilterContent(node);
+ }
+
+ this.onDisplayChanged();
+ },
+
+ 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 = "&nbsp;" }
+ 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[]|String?*/dom,/*Boolean?*/nonDestructive){
+ // summary:
+ // filter the output after getting the content of the editing area
+ var ec;
+ if(!dojo.isString(dom)){
+ 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);
+ });
+ }
+ ec = dijit._editor.getChildrenHtml(dom);
+ }else{
+ ec = dom;
+ }
+
+ if(!ec.replace(/^(?:\s|\xA0)+/g, "").replace(/(?:\s|\xA0)+$/g,"").length){ ec = ""; }
+
+ // if(dojo.isIE){
+ // //removing appended <P>&nbsp;</P> for IE
+ // ec = ec.replace(/(?:<p>&nbsp;</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._scopeName + "._editor.RichText.savedContent");
+ saveTextarea.value += this._SEPARATOR + this.name + ":" + this.getValue();
+ },
+
+ escapeXml: function(/*String*/str, /*Boolean*/noSingleQuotes){
+ dojo.deprecated('dijit.Editor::escapeXml is deprecated','use dijit._editor.escapeXml instead', 2);
+ return dijit._editor.escapeXml(str,noSingleQuotes);
+ },
+
+ getNodeHtml: function(/* DomNode */node){
+ dojo.deprecated('dijit.Editor::getNodeHtml is deprecated','use dijit._editor.getNodeHtml instead', 2);
+ return dijit._editor.getNodeHtml(node);
+ },
+
+ getNodeChildrenHtml: function(/* DomNode */dom){
+ dojo.deprecated('dijit.Editor::getNodeChildrenHtml is deprecated','use dijit._editor.getChildrenHtml instead', 2);
+ return dijit._editor.getChildrenHtml(dom);
+ },
+
+ 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;
+ }
+ }
+ this.textarea.value = save ? this._content : 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 = save ? this._content : 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);
+ },
+
+ _removeMozBogus: function(/* String */ html){
+ return html.replace(/\stype="_moz"/gi, '').replace(/\s_moz_dirty=""/gi, ''); // String
+ },
+ _removeSafariBogus: function(/* String */ html){
+ return html.replace(/\sclass="webkit-block-placeholder"/gi, ''); // String
+ },
+ _fixContentForMoz: function(/* String */ html){
+ // summary:
+ // Moz can not handle strong/em tags correctly, convert them to b/i
+ return html.replace(/<(\/)?strong([ \>])/gi, '<$1b$2')
+ .replace(/<(\/)?em([ \>])/gi, '<$1i$2' ); // String
+ },
+
+ _srcInImgRegex : /(?:(<img(?=\s).*?\ssrc=)("|')(.*?)\2)|(?:(<img\s.*?src=)([^"'][^ >]+))/gi ,
+ _hrefInARegex : /(?:(<a(?=\s).*?\shref=)("|')(.*?)\2)|(?:(<a\s.*?href=)([^"'][^ >]+))/gi ,
+
+ _preFixUrlAttributes: function(/* String */ html){
+ return html.replace(this._hrefInARegex, '$1$4$2$3$5$2 _djrealurl=$2$3$5$2')
+ .replace(this._srcInImgRegex, '$1$4$2$3$5$2 _djrealurl=$2$3$5$2'); // String
+ }
+});
+
+}
diff --git a/includes/js/dijit/_editor/_Plugin.js b/includes/js/dijit/_editor/_Plugin.js
new file mode 100644
index 0000000..32fde3b
--- /dev/null
+++ b/includes/js/dijit/_editor/_Plugin.js
@@ -0,0 +1,101 @@
+if(!dojo._hasResource["dijit._editor._Plugin"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit._editor._Plugin"] = true;
+dojo.provide("dijit._editor._Plugin");
+dojo.require("dijit._Widget");
+dojo.require("dijit.Editor");
+dojo.require("dijit.form.Button");
+
+dojo.declare("dijit._editor._Plugin", null, {
+ // summary
+ // This represents a "plugin" to the editor, which is basically
+ // a single button on the Toolbar and some associated code
+ constructor: function(/*Object?*/args, /*DomNode?*/node){
+ if(args){
+ dojo.mixin(this, args);
+ }
+ this._connects=[];
+ },
+
+ editor: null,
+ iconClassPrefix: "dijitEditorIcon",
+ button: null,
+ queryCommand: null,
+ command: "",
+ commandArg: null,
+ useDefaultCommand: true,
+ buttonClass: dijit.form.Button,
+ getLabel: function(key){
+ return this.editor.commands[key];
+ },
+ _initButton: function(props){
+ if(this.command.length){
+ var label = this.getLabel(this.command);
+ var className = this.iconClassPrefix+" "+this.iconClassPrefix + this.command.charAt(0).toUpperCase() + this.command.substr(1);
+ if(!this.button){
+ props = dojo.mixin({
+ label: label,
+ showLabel: false,
+ iconClass: className,
+ dropDown: this.dropDown,
+ tabIndex: "-1"
+ }, props || {});
+ this.button = new this.buttonClass(props);
+ }
+ }
+ },
+ destroy: function(f){
+ dojo.forEach(this._connects, dojo.disconnect);
+ },
+ connect: function(o, f, tf){
+ this._connects.push(dojo.connect(o, f, this, tf));
+ },
+ updateState: function(){
+ var _e = this.editor;
+ var _c = this.command;
+ if(!_e){ return; }
+ if(!_e.isLoaded){ return; }
+ if(!_c.length){ return; }
+ if(this.button){
+ try{
+ var enabled = _e.queryCommandEnabled(_c);
+ this.button.setAttribute('disabled', !enabled);
+ if(typeof this.button.checked == 'boolean'){
+ this.button.setAttribute('checked', _e.queryCommandState(_c));
+ }
+ }catch(e){
+ console.debug(e);
+ }
+ }
+ },
+ setEditor: function(/*Widget*/editor){
+ // FIXME: detatch from previous editor!!
+ this.editor = editor;
+
+ // FIXME: prevent creating this if we don't need to (i.e., editor can't handle our command)
+ this._initButton();
+
+ // FIXME: wire up editor to button here!
+ if(this.command.length &&
+ !this.editor.queryCommandAvailable(this.command)
+ ){
+ // console.debug("hiding:", this.command);
+ if(this.button){
+ this.button.domNode.style.display = "none";
+ }
+ }
+ if(this.button && this.useDefaultCommand){
+ this.connect(this.button, "onClick",
+ dojo.hitch(this.editor, "execCommand", this.command, this.commandArg)
+ );
+ }
+ this.connect(this.editor, "onNormalizedDisplayChanged", "updateState");
+ },
+ setToolbar: function(/*Widget*/toolbar){
+ if(this.button){
+ toolbar.addChild(this.button);
+ }
+ // console.debug("adding", this.button, "to:", toolbar);
+ }
+});
+
+}
diff --git a/includes/js/dijit/_editor/html.js b/includes/js/dijit/_editor/html.js
new file mode 100644
index 0000000..8b20592
--- /dev/null
+++ b/includes/js/dijit/_editor/html.js
@@ -0,0 +1,106 @@
+if(!dojo._hasResource["dijit._editor.html"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit._editor.html"] = true;
+dojo.provide("dijit._editor.html");
+
+dijit._editor.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, "&amp;").replace(/</gm, "&lt;").replace(/>/gm, "&gt;").replace(/"/gm, "&quot;");
+ if(!noSingleQuotes){
+ str = str.replace(/'/gm, "&#39;");
+ }
+ return str; // string
+};
+
+dijit._editor.getNodeHtml=function(/* DomNode */node){
+ var output;
+ switch(node.nodeType){
+ case 1: //element node
+ output = '<'+node.nodeName.toLowerCase();
+
+ //store the list of attributes and sort it to have the
+ //attributes appear in the dictionary order
+ var attrarray = [];
+ if(dojo.isIE && node.outerHTML){
+ 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))){
+ 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=='style'){
+ attrarray.push([key, node.style.cssText.toLowerCase()]);
+ }else{
+ attrarray.push([key, key=='class'?node.className: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
+ var n=attr.name;
+ if(n.substr(0,3) != '_dj' /*&&
+ (attr.specified == undefined || attr.specified)*/){
+ var v = attr.value;
+ if(n == 'src' || n == 'href'){
+ if(node.getAttribute('_djrealurl')){
+ v = node.getAttribute('_djrealurl');
+ }
+ }
+ attrarray.push([n,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]+'="'+
+ (dojo.isString(attr[1]) ? dijit._editor.escapeXml(attr[1],true) : attr[1])+'"';
+ }
+ if(node.childNodes.length){
+ output += '>' + dijit._editor.getChildrenHtml(node)+'</'+node.nodeName.toLowerCase()+'>';
+ }else{
+ output += ' />';
+ }
+ break;
+ case 3: //text
+ // FIXME:
+ output = dijit._editor.escapeXml(node.nodeValue,true);
+ break;
+ case 8: //comment
+ // FIXME:
+ output = '<!--'+dijit._editor.escapeXml(node.nodeValue,true)+'-->';
+ break;
+ default:
+ output = "Element not recognized - Type: " + node.nodeType + " Name: " + node.nodeName;
+ }
+ return output;
+};
+
+dijit._editor.getChildrenHtml = 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 += dijit._editor.getNodeHtml(node);
+ }
+ return out; // String
+}
+
+}
diff --git a/includes/js/dijit/_editor/nls/FontChoice.js b/includes/js/dijit/_editor/nls/FontChoice.js
new file mode 100644
index 0000000..71da48d
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/FontChoice.js
@@ -0,0 +1 @@
+({"1":"xx-small","2":"x-small","formatBlock":"Format","3":"small","4":"medium","5":"large","6":"x-large","7":"xx-large","fantasy":"fantasy","serif":"serif","p":"Paragraph","pre":"Pre-formatted","sans-serif":"sans-serif","fontName":"Font","h1":"Heading","h2":"Subheading","h3":"Sub-subheading","monospace":"monospace","fontSize":"Size","cursive":"cursive"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/LinkDialog.js b/includes/js/dijit/_editor/nls/LinkDialog.js
new file mode 100644
index 0000000..3e1b917
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/LinkDialog.js
@@ -0,0 +1 @@
+({"set":"Set","text":"Description:","insertImageTitle":"Image Properties","url":"URL:","createLinkTitle":"Link Properties"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/ar/FontChoice.js b/includes/js/dijit/_editor/nls/ar/FontChoice.js
new file mode 100644
index 0000000..72381b6
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/ar/FontChoice.js
@@ -0,0 +1 @@
+({"1":"صغير جدا جدا ","2":"صغير جدا ","formatBlock":"النسق","monospaced":"خط أحادي المسافة ","3":"صغير ","4":"متوسط ","5":"كبير ","6":"كبير جدا ","7":"كبير جدا جدا ","fantasy":"خيالي ","serif":"serif","p":"فقرة ","pre":"منسق بصفة مسبقة ","sans-serif":"sans-serif","fontName":"طاقم طباعة","h1":"عنوان","h2":"عنوان فرعي ","h3":"فرعي-عنوان فرعي ","fontSize":"الحجم","cursive":"كتابة بحروف متصلة ","monospace":"monospace"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/ar/LinkDialog.js b/includes/js/dijit/_editor/nls/ar/LinkDialog.js
new file mode 100644
index 0000000..ca46031
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/ar/LinkDialog.js
@@ -0,0 +1 @@
+({"set":"تحديد","text":"الوصف: ","insertImageTitle":"خصائص الصورة ","url":"عنوان URL:","createLinkTitle":"خصائص الوصلة "}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/ar/commands.js b/includes/js/dijit/_editor/nls/ar/commands.js
new file mode 100644
index 0000000..79ce209
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/ar/commands.js
@@ -0,0 +1 @@
+({"removeFormat":"ازالة النسق","copy":"نسخ","paste":"لصق","selectAll":"اختيار كل","insertOrderedList":"كشف مرقم","insertTable":"ادراج/تحرير جدول ","underline":"تسطير","foreColor":"لون الواجهة الأمامية","htmlToggle":"مصدر HTML","formatBlock":"نمط الفقرة","insertHorizontalRule":"مسطرة أفقية","delete":"حذف","insertUnorderedList":"كشف نقطي","tableProp":"خصائص الجدول ","insertImage":"ادراج صورة","superscript":"رمز علوي","subscript":"رمز سفلي","createLink":"تكوين وصلة","undo":"تراجع","italic":"مائل","fontName":"اسم طاقم الطباعة","justifyLeft":"محاذاة الى اليسار","unlink":"ازالة وصلة","toggleTableBorder":"تبديل حدود الجدول ","fontSize":"حجم طاقم الطباعة","indent":"ازاحة للداخل","redo":"اعادة","strikethrough":"تشطيب","justifyFull":"ضبط","justifyCenter":"محاذاة في الوسط","hiliteColor":"لون الخلفية","deleteTable":"حذف جدول ","outdent":"ازاحة للخارج","cut":"قص","plainFormatBlock":"نمط الفقرة","toggleDir":"تبديل الاتجاه ","bold":"عريض","systemShortcutFF":"يكون التصرف \"${0}\" متاحا فقط في برنامج Mozilla Firefox باستخدام اختصارات لوحة المفاتيح. استخدم ${1}.","justifyRight":"محاذاة الى اليمين","appleKey":"⌘${0}","ctrlKey":"ctrl+${0}"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/commands.js b/includes/js/dijit/_editor/nls/commands.js
new file mode 100644
index 0000000..d58b0c8
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/commands.js
@@ -0,0 +1 @@
+({"removeFormat":"Remove Format","copy":"Copy","paste":"Paste","selectAll":"Select All","insertOrderedList":"Numbered List","insertTable":"Insert/Edit Table","underline":"Underline","foreColor":"Foreground Color","htmlToggle":"HTML Source","formatBlock":"Paragraph Style","insertHorizontalRule":"Horizontal Rule","delete":"Delete","appleKey":"⌘${0}","insertUnorderedList":"Bullet List","tableProp":"Table Property","insertImage":"Insert Image","superscript":"Superscript","subscript":"Subscript","createLink":"Create Link","undo":"Undo","italic":"Italic","fontName":"Font Name","justifyLeft":"Align Left","unlink":"Remove Link","toggleTableBorder":"Toggle Table Border","ctrlKey":"ctrl+${0}","fontSize":"Font Size","indent":"Indent","redo":"Redo","strikethrough":"Strikethrough","justifyFull":"Justify","justifyCenter":"Align Center","hiliteColor":"Background Color","deleteTable":"Delete Table","outdent":"Outdent","cut":"Cut","plainFormatBlock":"Paragraph Style","toggleDir":"Toggle Direction","bold":"Bold","systemShortcutFF":"The \"${0}\" action is only available in Mozilla Firefox using a keyboard shortcut. Use ${1}.","justifyRight":"Align Right"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/cs/FontChoice.js b/includes/js/dijit/_editor/nls/cs/FontChoice.js
new file mode 100644
index 0000000..2a12e61
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/cs/FontChoice.js
@@ -0,0 +1 @@
+({"1":"extra malé","2":"velmi malé","formatBlock":"Formát","monospaced":"monospaced","3":"malé","4":"střední","5":"velké","6":"velmi velké","7":"extra velké","fantasy":"fantasy","serif":"serif","p":"Odstavec","pre":"Předformátované","sans-serif":"sans-serif","fontName":"Písmo","h1":"Nadpis","h2":"Podnadpis","h3":"Podnadpis 2","fontSize":"Velikost","cursive":"cursive","monospace":"monospace"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/cs/LinkDialog.js b/includes/js/dijit/_editor/nls/cs/LinkDialog.js
new file mode 100644
index 0000000..cf124d5
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/cs/LinkDialog.js
@@ -0,0 +1 @@
+({"set":"Nastavit","text":"Popis:","insertImageTitle":"Vlastnosti obrázku","url":"Adresa URL:","createLinkTitle":"Vlastnosti odkazu"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/cs/commands.js b/includes/js/dijit/_editor/nls/cs/commands.js
new file mode 100644
index 0000000..2d19f8f
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/cs/commands.js
@@ -0,0 +1 @@
+({"removeFormat":"Odebrat formát","copy":"Kopírovat","paste":"Vložit","selectAll":"Vybrat vše","insertOrderedList":"Číslovaný seznam","insertTable":"Vložit/upravit tabulku","underline":"Podtržení","foreColor":"Barva popředí","htmlToggle":"Zdroj HTML","formatBlock":"Styl odstavce","insertHorizontalRule":"Vodorovné pravítko","delete":"Odstranit","insertUnorderedList":"Seznam s odrážkami","tableProp":"Vlastnost tabulky","insertImage":"Vložit obraz","superscript":"Horní index","subscript":"Dolní index","createLink":"Vytvořit odkaz","undo":"Zpět","italic":"Kurzíva","fontName":"Název písma","justifyLeft":"Zarovnat vlevo","unlink":"Odebrat odkaz","toggleTableBorder":"Přepnout ohraničení tabulky","ctrlKey":"Ctrl+${0}","fontSize":"Velikost písma","indent":"Odsadit","redo":"Opakovat","strikethrough":"Přeškrtnutí","justifyFull":"Do bloku","justifyCenter":"Zarovnat na střed","hiliteColor":"Barva pozadí","deleteTable":"Odstranit tabulku","outdent":"Předsadit","cut":"Vyjmout","plainFormatBlock":"Styl odstavce","toggleDir":"Přepnout směr","bold":"Tučné","systemShortcutFF":"Akce \"${0}\" je v prohlížeči Mozilla Firefox dostupná pouze prostřednictvím klávesové zkratky. Použijte klávesy ${1}.","justifyRight":"Zarovnat vpravo","appleKey":"⌘${0}"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/da/FontChoice.js b/includes/js/dijit/_editor/nls/da/FontChoice.js
new file mode 100644
index 0000000..aae3c40
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/da/FontChoice.js
@@ -0,0 +1 @@
+({"1":"xx-small","2":"x-small","formatBlock":"Format","monospaced":"monospaced","3":"small","4":"medium","5":"large","6":"x-large","7":"xx-large","fantasy":"fantasy","serif":"serif","p":"Afsnit","pre":"Forudformateret","sans-serif":"sans-serif","fontName":"Skrifttype","h1":"Overskrift","h2":"Underoverskrift","h3":"Underunderoverskrift","fontSize":"Størrelse","cursive":"kursiv","monospace":"monospace"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/da/LinkDialog.js b/includes/js/dijit/_editor/nls/da/LinkDialog.js
new file mode 100644
index 0000000..87fd8a9
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/da/LinkDialog.js
@@ -0,0 +1 @@
+({"set":"Definér","text":"Beskrivelse:","insertImageTitle":"Billedegenskaber","url":"URL:","createLinkTitle":"Linkegenskaber"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/da/commands.js b/includes/js/dijit/_editor/nls/da/commands.js
new file mode 100644
index 0000000..04e6262
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/da/commands.js
@@ -0,0 +1 @@
+({"removeFormat":"Fjern format","copy":"Kopiér","paste":"Sæt ind","selectAll":"Markér alle","insertOrderedList":"Nummereret liste","insertTable":"Indsæt/redigér tabel","underline":"Understreget","foreColor":"Forgrundsfarve","htmlToggle":"HTML-kilde","formatBlock":"Afsnitstypografi","insertHorizontalRule":"Vandret linje","delete":"Slet","insertUnorderedList":"Punktliste","tableProp":"Tabelegenskab","insertImage":"Indsæt billede","superscript":"Hævet skrift","subscript":"Sænket skrift","createLink":"Opret link","undo":"Fortryd","italic":"Kursiv","fontName":"Skriftnavn","justifyLeft":"Venstrejusteret","unlink":"Fjern link","toggleTableBorder":"Skift tabelramme","fontSize":"Skriftstørrelse","indent":"Indrykning","redo":"Annullér Fortryd","strikethrough":"Gennemstreget","justifyFull":"Lige margener","justifyCenter":"Centreret","hiliteColor":"Baggrundsfarve","deleteTable":"Slet tabel","outdent":"Udrykning","cut":"Klip","plainFormatBlock":"Afsnitstypografi","toggleDir":"Skift retning","bold":"Fed","systemShortcutFF":"Funktionen \"${0}\" kan kun bruges i Mozilla Firefox med en tastaturgenvej. Brug ${1}.","justifyRight":"Højrejusteret","appleKey":"⌘${0}","ctrlKey":"ctrl+${0}"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/de/FontChoice.js b/includes/js/dijit/_editor/nls/de/FontChoice.js
new file mode 100644
index 0000000..d23c16d
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/de/FontChoice.js
@@ -0,0 +1 @@
+({"1":"XXS","2":"XS","formatBlock":"Format","monospaced":"Monospace","3":"S","4":"M","5":"L","6":"XL","7":"XXL","fantasy":"Fantasie","serif":"Serife","p":"Absatz","pre":"Vorformatiert","sans-serif":"Serifenlos","fontName":"Schriftart","h1":"Überschrift","h2":"Unterüberschrift","h3":"Unterunterüberschrift","fontSize":"Größe","cursive":"Kursiv","monospace":"monospace"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/de/LinkDialog.js b/includes/js/dijit/_editor/nls/de/LinkDialog.js
new file mode 100644
index 0000000..0bc01cb
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/de/LinkDialog.js
@@ -0,0 +1 @@
+({"set":"Festlegen","text":"Beschreibung:","insertImageTitle":"Grafikeigenschaften","url":"URL:","createLinkTitle":"Linkeigenschaften"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/de/commands.js b/includes/js/dijit/_editor/nls/de/commands.js
new file mode 100644
index 0000000..d597b0e
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/de/commands.js
@@ -0,0 +1 @@
+({"removeFormat":"Formatierung entfernen","copy":"Kopieren","paste":"Einfügen","selectAll":"Alles auswählen","insertOrderedList":"Nummerierung","insertTable":"Tabelle einfügen/bearbeiten","underline":"Unterstrichen","foreColor":"Vordergrundfarbe","htmlToggle":"HTML-Quelltext","formatBlock":"Absatzstil","insertHorizontalRule":"Horizontaler Strich","delete":"Löschen","insertUnorderedList":"Aufzählungszeichen","tableProp":"Tabelleneigenschaft","insertImage":"Grafik einfügen","superscript":"Hochgestellt","subscript":"Tiefgestellt","createLink":"Link erstellen","undo":"Rückgängig","italic":"Kursiv","fontName":"Schriftartname","justifyLeft":"Linksbündig","unlink":"Link entfernen","toggleTableBorder":"Tabellenumrandung ein-/ausschalten","ctrlKey":"Strg+${0}","fontSize":"Schriftgröße","indent":"Einrücken","redo":"Wiederherstellen","strikethrough":"Durchgestrichen","justifyFull":"Blocksatz","justifyCenter":"Zentriert","hiliteColor":"Hintergrundfarbe","deleteTable":"Tabelle löschen","outdent":"Ausrücken","cut":"Ausschneiden","plainFormatBlock":"Absatzstil","toggleDir":"Richtung wechseln","bold":"Fett","systemShortcutFF":"Die Aktion \"${0}\" ist in Mozilla Firefox nur über einen Tastaturkurzbefehl verfügbar. Verwenden Sie ${1}.","justifyRight":"Rechtsbündig","appleKey":"⌘${0}"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/el/FontChoice.js b/includes/js/dijit/_editor/nls/el/FontChoice.js
new file mode 100644
index 0000000..ac1d1fd
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/el/FontChoice.js
@@ -0,0 +1 @@
+({"1":"xx-μικρά","2":"x-μικρά","formatBlock":"Μορφή","monospaced":"σταθερού πλάτους","3":"μικρά","4":"μεσαία","5":"μεγάλα","6":"x-μεγάλα","7":"xx-μεγάλα","fantasy":"φαντασίας","serif":"με πατούρες (serif)","p":"Παράγραφος","pre":"Προ-μορφοποιημένο","sans-serif":"χωρίς πατούρες (sans-serif)","fontName":"Γραμματοσειρά","h1":"Επικεφαλίδα","h2":"Δευτερεύουσα επικεφαλίδα","h3":"Δευτερεύουσα επικεφαλίδα τρίτου επιπέδου","fontSize":"Μέγεθος","cursive":"πλάγιοι","monospace":"monospace"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/el/LinkDialog.js b/includes/js/dijit/_editor/nls/el/LinkDialog.js
new file mode 100644
index 0000000..a615aeb
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/el/LinkDialog.js
@@ -0,0 +1 @@
+({"set":"Ορισμός","text":"Περιγραφή:","insertImageTitle":"Ιδιότητες εικόνας","url":"Διεύθυνση URL:","createLinkTitle":"Ιδιότητες διασύνδεσης"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/el/commands.js b/includes/js/dijit/_editor/nls/el/commands.js
new file mode 100644
index 0000000..4954c9c
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/el/commands.js
@@ -0,0 +1 @@
+({"removeFormat":"Αφαίρεση μορφοποίησης","copy":"Αντιγραφή","paste":"Επικόλληση","selectAll":"Επιλογή όλων","insertOrderedList":"Αριθμημένη λίστα","insertTable":"Εισαγωγή/Τροποποίηση πίνακα","underline":"Υπογράμμιση","foreColor":"Χρώμα προσκηνίου","htmlToggle":"Πρωτογενής κώδικας HTML","formatBlock":"Στυλ παραγράφου","insertHorizontalRule":"Οριζόντια γραμμή","delete":"Διαγραφή","insertUnorderedList":"Λίστα με κουκίδες","tableProp":"Ιδιότητα πίνακα","insertImage":"Εισαγωγή εικόνας","superscript":"Εκθέτης","subscript":"Δείκτης","createLink":"Δημιουργία διασύνδεσης","undo":"Αναίρεση","italic":"Πλάγια","fontName":"Όνομα γραμματοσειράς","justifyLeft":"Στοίχιση αριστερά","unlink":"Αφαίρεση διασύνδεσης","toggleTableBorder":"Εναλλαγή εμφάνισης περιγράμματος πίνακα","fontSize":"Μέγεθος γραμματοσειράς","indent":"Εσοχή","redo":"Επανάληψη","strikethrough":"Διαγράμμιση","justifyFull":"Πλήρης στοίχιση","justifyCenter":"Στοίχιση στο κέντρο","hiliteColor":"Χρώμα φόντου","deleteTable":"Διαγραφή πίνακα","outdent":"Μείωση περιθωρίου","cut":"Αποκοπή","plainFormatBlock":"Στυλ παραγράφου","toggleDir":"Εναλλαγή κατεύθυνσης","bold":"Έντονα","systemShortcutFF":"Η ενέργεια \"${0}\" είναι διαθέσιμη μόνο στο Mozilla Firefox με τη χρήση συντόμευσης πληκτρολογίου. Χρησιμοποιήστε το ${1}.","justifyRight":"Στοίχιση δεξιά","appleKey":"⌘${0}","ctrlKey":"ctrl+${0}"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/es/FontChoice.js b/includes/js/dijit/_editor/nls/es/FontChoice.js
new file mode 100644
index 0000000..b0f4d90
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/es/FontChoice.js
@@ -0,0 +1 @@
+({"1":"xx-pequeño","2":"x-pequeño","formatBlock":"Formato","monospaced":"monoespacio","3":"pequeño","4":"medio","5":"grande","6":"x-grande","7":"xx-grande","fantasy":"fantasía","serif":"serif","p":"Párrafo","pre":"Preformateado","sans-serif":"sans-serif","fontName":"Font","h1":"Cabecera","h2":"Subcabecera","h3":"Sub-subcabecera","fontSize":"Tamaño","cursive":"cursiva","monospace":"monospace"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/es/LinkDialog.js b/includes/js/dijit/_editor/nls/es/LinkDialog.js
new file mode 100644
index 0000000..8dfe95f
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/es/LinkDialog.js
@@ -0,0 +1 @@
+({"set":"Establecer","text":"Descripción:","insertImageTitle":"Propiedades de la imagen","url":"URL:","createLinkTitle":"Propiedades del enlace"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/es/commands.js b/includes/js/dijit/_editor/nls/es/commands.js
new file mode 100644
index 0000000..54605ed
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/es/commands.js
@@ -0,0 +1 @@
+({"removeFormat":"Eliminar formato","copy":"Copiar","paste":"Pegar","selectAll":"Seleccionar todo","insertOrderedList":"Lista numerada","insertTable":"Insertar/Editar tabla","underline":"Subrayado","foreColor":"Color de primer plano","htmlToggle":"Fuente HTML","formatBlock":"Estilo de párrafo","insertHorizontalRule":"Regla horizontal","delete":"Suprimir","insertUnorderedList":"Lista con viñetas","tableProp":"Propiedad de tabla","insertImage":"Insertar imagen","superscript":"Superíndice","subscript":"Subíndice","createLink":"Crear enlace","undo":"Deshacer","italic":"Cursiva","fontName":"Nombre de font","justifyLeft":"Alinear izquierda","unlink":"Eliminar enlace","toggleTableBorder":"Conmutar borde de tabla","ctrlKey":"Control+${0}","fontSize":"Tamaño de font","indent":"Sangría","redo":"Rehacer","strikethrough":"Tachado","justifyFull":"Justificar","justifyCenter":"Alinear centro","hiliteColor":"Color de segundo plano","deleteTable":"Suprimir tabla","outdent":"Anular sangría","cut":"Cortar","plainFormatBlock":"Estilo de párrafo","toggleDir":"Conmutar dirección","bold":"Negrita","systemShortcutFF":"La acción \"${0}\" sólo está disponible en Mozilla Firefox mediante un atajo de teclado. Utilice ${1}.","justifyRight":"Alinear derecha","appleKey":"⌘${0}"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/fi/FontChoice.js b/includes/js/dijit/_editor/nls/fi/FontChoice.js
new file mode 100644
index 0000000..b5975ef
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/fi/FontChoice.js
@@ -0,0 +1 @@
+({"1":"xx-small","2":"x-small","formatBlock":"Muoto","monospaced":"monospaced","3":"small","4":"medium","5":"large","6":"x-large","7":"xx-large","fantasy":"fantasy","serif":"serif","p":"Kappale","pre":"Esimuotoiltu","sans-serif":"sans-serif","fontName":"Fontti","h1":"Otsikko","h2":"Alatason otsikko","h3":"Alimman tason otsikko","fontSize":"Koko","cursive":"cursive","monospace":"monospace"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/fi/LinkDialog.js b/includes/js/dijit/_editor/nls/fi/LinkDialog.js
new file mode 100644
index 0000000..dba80b6
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/fi/LinkDialog.js
@@ -0,0 +1 @@
+({"set":"Aseta","text":"Kuvaus:","insertImageTitle":"Kuvan ominaisuudet","url":"URL-osoite:","createLinkTitle":"Linkin ominaisuudet"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/fi/commands.js b/includes/js/dijit/_editor/nls/fi/commands.js
new file mode 100644
index 0000000..2d2cfc7
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/fi/commands.js
@@ -0,0 +1 @@
+({"removeFormat":"Poista muotoilu","copy":"Kopioi","paste":"Liitä","selectAll":"Valitse kaikki","insertOrderedList":"Numeroitu luettelo","insertTable":"Lisää taulukko/muokkaa taulukkoa","underline":"Alleviivaus","foreColor":"Edustaväri","htmlToggle":"HTML-lähde","formatBlock":"Kappaletyyli","insertHorizontalRule":"Vaakasuuntainen viiva","delete":"Poista","insertUnorderedList":"Numeroimaton luettelo","tableProp":"Taulukon ominaisuudet","insertImage":"Lisää kuva","superscript":"Yläindeksi","subscript":"Alaindeksi","createLink":"Luo linkki","undo":"Kumoa","italic":"Kursivointi","fontName":"Fontin nimi","justifyLeft":"Tasaus vasemmalle","unlink":"Poista linkki","toggleTableBorder":"Ota taulukon kehys käyttöön/poista kehys käytöstä","fontSize":"Fontin koko","indent":"Sisennä","redo":"Tee uudelleen","strikethrough":"Yliviivaus","justifyFull":"Tasaus","justifyCenter":"Tasaus keskelle","hiliteColor":"Taustaväri","deleteTable":"Poista taulukko","outdent":"Ulonna","cut":"Leikkaa","plainFormatBlock":"Kappaletyyli","toggleDir":"Vaihda suuntaa","bold":"Lihavointi","systemShortcutFF":"Toiminto \"${0}\" on käytettävissä vain Mozilla Firefox -ohjelmassa, kun käytetään pikanäppäimiä. Käytä kohdetta ${1}.","justifyRight":"Tasaus oikealle","appleKey":"⌘${0}","ctrlKey":"ctrl+${0}"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/fr/FontChoice.js b/includes/js/dijit/_editor/nls/fr/FontChoice.js
new file mode 100644
index 0000000..749ed85
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/fr/FontChoice.js
@@ -0,0 +1 @@
+({"1":"xxs","2":"xs","formatBlock":"Mise en forme","monospaced":"espacement constant","3":"s","4":"m","5":"l","6":"xl","7":"xxl","fantasy":"fantaisie","serif":"serif","p":"Paragraphe","pre":"Pré-mise en forme","sans-serif":"sans serif","fontName":"Police","h1":"En-tête","h2":"Sous-en-tête","h3":"Sous-sous-en-tête","fontSize":"Taille","cursive":"cursive","monospace":"monospace"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/fr/LinkDialog.js b/includes/js/dijit/_editor/nls/fr/LinkDialog.js
new file mode 100644
index 0000000..d3d8728
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/fr/LinkDialog.js
@@ -0,0 +1 @@
+({"set":"Définir","text":"Description :","insertImageTitle":"Propriétés de l'image","url":"URL :","createLinkTitle":"Propriétés du lien"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/fr/commands.js b/includes/js/dijit/_editor/nls/fr/commands.js
new file mode 100644
index 0000000..34eb40c
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/fr/commands.js
@@ -0,0 +1 @@
+({"removeFormat":"Supprimer la mise en forme","copy":"Copier","paste":"Coller","selectAll":"Sélectionner tout","insertOrderedList":"Liste numérotée","insertTable":"Insérer/Modifier un tableau","underline":"Souligner","foreColor":"Couleur d'avant-plan","htmlToggle":"Source HTML","formatBlock":"Style de paragraphe","insertHorizontalRule":"Règle horizontale","delete":"Supprimer","insertUnorderedList":"Liste à puces","tableProp":"Propriété du tableau","insertImage":"Insérer une image","superscript":"Exposant","subscript":"Indice","createLink":"Créer un lien","undo":"Annuler","italic":"Italique","fontName":"Nom de police","justifyLeft":"Aligner à gauche","unlink":"Supprimer le lien","toggleTableBorder":"Afficher/Masquer la bordure du tableau","fontSize":"Taille de police","indent":"Retrait","redo":"Rétablir","strikethrough":"Barrer","justifyFull":"Justifier","justifyCenter":"Aligner au centre","hiliteColor":"Couleur d'arrière-plan","deleteTable":"Supprimer le tableau","outdent":"Retrait négatif","cut":"Couper","plainFormatBlock":"Style de paragraphe","toggleDir":"Afficher/Masquer la direction","bold":"Gras","systemShortcutFF":"L'action \"${0}\" est disponible dans Mozilla Firefox uniquement, par le biais d'un raccourci-clavier. Utilisez ${1}.","justifyRight":"Aligner à droite","appleKey":"⌘${0}","ctrlKey":"ctrl+${0}"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/he/FontChoice.js b/includes/js/dijit/_editor/nls/he/FontChoice.js
new file mode 100644
index 0000000..13b2126
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/he/FontChoice.js
@@ -0,0 +1 @@
+({"1":"קטן ביות","2":"קטן מאוד","formatBlock":"עיצוב","monospaced":"monospaced","3":"קטן ","4":"בינוני","5":"גדול","6":"גדול מאוד","7":"גדול ביותר","fantasy":"fantasy","serif":"serif","p":"פיסקה","pre":"מעוצב מראש","sans-serif":"sans-serif","fontName":"גופן","h1":"כותרת","h2":"תת-כותרת","h3":"תת-תת-כותרת","fontSize":"גודל","cursive":"cursive","monospace":"monospace"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/he/LinkDialog.js b/includes/js/dijit/_editor/nls/he/LinkDialog.js
new file mode 100644
index 0000000..c99735b
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/he/LinkDialog.js
@@ -0,0 +1 @@
+({"set":"הגדרה","text":"תיאור:","insertImageTitle":"תכונות תמונה","url":"URL:","createLinkTitle":"תכונות קישור"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/he/commands.js b/includes/js/dijit/_editor/nls/he/commands.js
new file mode 100644
index 0000000..6488ff8
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/he/commands.js
@@ -0,0 +1 @@
+({"removeFormat":"סילוק עיצוב","copy":"העתקה","paste":"הדבקה","selectAll":"בחירת הכל","insertOrderedList":"רשימה ממוספרת","insertTable":"הוספת/עריכת טבלה","underline":"קו תחתי","foreColor":"צבע חזית ","htmlToggle":"מקור HTML","formatBlock":"סגנון פיסקה","insertHorizontalRule":"קו אופקי","delete":"מחיקה","insertUnorderedList":"רשימה עם תבליטים","tableProp":"תכונת טבלה","insertImage":"הוספת תמונה","superscript":"כתב עילי","subscript":"כתב תחתי","createLink":"יצירת קישור","undo":"ביטול פעולה","italic":"נטוי","fontName":"שם גופן","justifyLeft":"יישור לשמאל","unlink":"סילוק הקישור","toggleTableBorder":"מיתוג גבול טבלה","fontSize":"גופן יחסי","indent":"הגדלת כניסה","redo":"שחזור פעולה","strikethrough":"קו חוצה","justifyFull":"יישור דו-צדדי","justifyCenter":"יישור למרכז","hiliteColor":"צבע רקע","deleteTable":"מחיקת טבלה","outdent":"הקטנת כניסה","cut":"גזירה","plainFormatBlock":"סגנון פיסקה","toggleDir":"מיתוג כיוון ","bold":"מודגש","systemShortcutFF":"הפעולה \"${0}\" זמינה בדפדפן Mozilla Firefox רק באמצעות קיצור דרך במקלדת. נא להשתמש ב-${1}.","justifyRight":"יישור לימין","appleKey":"⌘${0}","ctrlKey":"ctrl+${0}"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/hu/FontChoice.js b/includes/js/dijit/_editor/nls/hu/FontChoice.js
new file mode 100644
index 0000000..0a6ca9f
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/hu/FontChoice.js
@@ -0,0 +1 @@
+({"1":"xx-kicsi","2":"x-kicsi","formatBlock":"Formátum","monospaced":"egyenközű","3":"kicsi","4":"közepes","5":"nagy","6":"x-nagy","7":"xx-nagy","fantasy":"fantázia","serif":"talpas","p":"Bekezdés","pre":"Előformázott","sans-serif":"talpatlan","fontName":"Betűtípus","h1":"Címsor","h2":"Alcím","h3":"Al-alcím","fontSize":"Méret","cursive":"kurzív","monospace":"monospace"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/hu/LinkDialog.js b/includes/js/dijit/_editor/nls/hu/LinkDialog.js
new file mode 100644
index 0000000..8662cf2
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/hu/LinkDialog.js
@@ -0,0 +1 @@
+({"set":"Beállítás","text":"Leírás:","insertImageTitle":"Kép tulajdonságai","url":"URL:","createLinkTitle":"Hivatkozás tulajdonságai"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/hu/commands.js b/includes/js/dijit/_editor/nls/hu/commands.js
new file mode 100644
index 0000000..3cd13e3
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/hu/commands.js
@@ -0,0 +1 @@
+({"removeFormat":"Formázás eltávolítása","copy":"Másolás","paste":"Beillesztés","selectAll":"Összes kijelölése","insertOrderedList":"Számozott lista","insertTable":"Táblázat beszúrása/szerkesztése","underline":"Aláhúzott","foreColor":"Előtérszín","htmlToggle":"HTML forrás","formatBlock":"Bekezdés stílusa","insertHorizontalRule":"Vízszintes vonalzó","delete":"Törlés","insertUnorderedList":"Felsorolásjeles lista","tableProp":"Táblázat tulajdonságai","insertImage":"Kép beszúrása","superscript":"Felső index","subscript":"Alsó index","createLink":"Hivatkozás létrehozása","undo":"Visszavonás","italic":"Dőlt","fontName":"Betűtípus","justifyLeft":"Balra igazítás","unlink":"Hivatkozás eltávolítása","toggleTableBorder":"Táblázatszegély ki-/bekapcsolása","fontSize":"Betűméret","indent":"Behúzás","redo":"Újra","strikethrough":"Áthúzott","justifyFull":"Sorkizárás","justifyCenter":"Középre igazítás","hiliteColor":"Háttérszín","deleteTable":"Táblázat törlése","outdent":"Negatív behúzás","cut":"Kivágás","plainFormatBlock":"Bekezdés stílusa","toggleDir":"Irányváltás","bold":"Félkövér","systemShortcutFF":"A(z) \"${0}\" művelet csak Mozilla Firefox böngészőben érhető el billentyűparancs használatával. Használja a következőt: ${1}.","justifyRight":"Jobbra igazítás","appleKey":"⌘${0}","ctrlKey":"ctrl+${0}"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/it/FontChoice.js b/includes/js/dijit/_editor/nls/it/FontChoice.js
new file mode 100644
index 0000000..d2ad29d
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/it/FontChoice.js
@@ -0,0 +1 @@
+({"1":"xx-small","2":"x-small","formatBlock":"Formato","monospaced":"monospaced","3":"small","4":"medium","5":"large","6":"x-large","7":"xx-large","fantasy":"fantasy","serif":"serif","p":"Paragrafo","pre":"Preformattato","sans-serif":"sans-serif","fontName":"Carattere","h1":"Intestazione","h2":"Sottointestazione","h3":"Sottointestazione secondaria","fontSize":"Dimensione","cursive":"cursive","monospace":"monospace"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/it/LinkDialog.js b/includes/js/dijit/_editor/nls/it/LinkDialog.js
new file mode 100644
index 0000000..72f76e4
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/it/LinkDialog.js
@@ -0,0 +1 @@
+({"set":"Imposta","text":"Descrizione:","insertImageTitle":"Proprietà immagine","url":"URL:","createLinkTitle":"Proprietà collegamento"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/it/commands.js b/includes/js/dijit/_editor/nls/it/commands.js
new file mode 100644
index 0000000..6e22372
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/it/commands.js
@@ -0,0 +1 @@
+({"removeFormat":"Rimuovi formato","copy":"Copia","paste":"Incolla","selectAll":"Seleziona tutto","insertOrderedList":"Elenco numerato","insertTable":"Inserisci/Modifica tabella","underline":"Sottolineato","foreColor":"Colore primo piano","htmlToggle":"Origine HTML","formatBlock":"Stile paragrafo","insertHorizontalRule":"Righello orizzontale","delete":"Elimina","insertUnorderedList":"Elenco puntato","tableProp":"Proprietà tabella","insertImage":"Inserisci immagine","superscript":"Apice","subscript":"Pedice","createLink":"Crea collegamento","undo":"Annulla","italic":"Corsivo","fontName":"Nome carattere","justifyLeft":"Allinea a sinistra","unlink":"Rimuovi collegamento","toggleTableBorder":"Mostra/Nascondi margine tabella","fontSize":"Dimensione carattere","indent":"Rientra","redo":"Ripristina","strikethrough":"Barrato","justifyFull":"Giustifica","justifyCenter":"Allinea al centro","hiliteColor":"Colore sfondo","deleteTable":"Elimina tabella","outdent":"Rimuovi rientro","cut":"Taglia","plainFormatBlock":"Stile paragrafo","toggleDir":"Inverti direzione","bold":"Grassetto","systemShortcutFF":"L'azione \"${0}\" è disponibile solo in Mozilla Firefox tramite tasti di scelta rapida. Utilizzare ${1}.","justifyRight":"Allinea a destra","appleKey":"⌘${0}","ctrlKey":"ctrl+${0}"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/ja/FontChoice.js b/includes/js/dijit/_editor/nls/ja/FontChoice.js
new file mode 100644
index 0000000..633fc9a
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/ja/FontChoice.js
@@ -0,0 +1 @@
+({"1":"超極小","2":"極小","formatBlock":"フォーマット","monospaced":"monospace","3":"小","4":"標準","5":"大","6":"特大","7":"超特大","fantasy":"fantasy","serif":"serif","p":"段落","pre":"事前フォーマット済み","sans-serif":"sans-serif","fontName":"フォント","h1":"見出し","h2":"副見出し","h3":"副見出しの副見出し","fontSize":"サイズ","cursive":"cursive","monospace":"monospace"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/ja/LinkDialog.js b/includes/js/dijit/_editor/nls/ja/LinkDialog.js
new file mode 100644
index 0000000..2fc7a63
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/ja/LinkDialog.js
@@ -0,0 +1 @@
+({"set":"設定","text":"説明:","insertImageTitle":"イメージ・プロパティー","url":"URL:","createLinkTitle":"リンク・プロパティー"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/ja/commands.js b/includes/js/dijit/_editor/nls/ja/commands.js
new file mode 100644
index 0000000..c33fdca
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/ja/commands.js
@@ -0,0 +1 @@
+({"removeFormat":"形式の除去","copy":"コピー","paste":"貼り付け","selectAll":"すべて選択","insertOrderedList":"番号付きリスト","insertTable":"テーブルの挿入/編集","underline":"下線","foreColor":"前景色","htmlToggle":"HTML ソース","formatBlock":"段落スタイル","insertHorizontalRule":"水平罫線","delete":"削除","insertUnorderedList":"黒丸付きリスト","tableProp":"テーブル・プロパティー","insertImage":"イメージの挿入","superscript":"上付き文字","subscript":"下付き文字","createLink":"リンクの作成","undo":"元に戻す","italic":"イタリック","fontName":"フォント名","justifyLeft":"左揃え","unlink":"リンクの除去","toggleTableBorder":"テーブル・ボーダーの切り替え","fontSize":"フォント・サイズ","indent":"インデント","redo":"やり直し","strikethrough":"取り消し線","justifyFull":"両端揃え","justifyCenter":"中央揃え","hiliteColor":"背景色","deleteTable":"テーブルの削除","outdent":"アウトデント","cut":"切り取り","plainFormatBlock":"段落スタイル","toggleDir":"方向の切り替え","bold":"太字","systemShortcutFF":"\"${0}\" アクションは、キーボード・ショートカットを使用して Mozilla Firefox でのみ使用できます。${1} を使用してください。","justifyRight":"右揃え","appleKey":"⌘${0}","ctrlKey":"ctrl+${0}"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/ko/FontChoice.js b/includes/js/dijit/_editor/nls/ko/FontChoice.js
new file mode 100644
index 0000000..cd5268a
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/ko/FontChoice.js
@@ -0,0 +1 @@
+({"1":"가장 작게","2":"조금 작게","formatBlock":"서식","monospaced":"monospaced","3":"작게","4":"중간","5":"크게","6":"조금 크게","7":"가장 크게","fantasy":"fantasy","serif":"serif","p":"단락","pre":"서식이 지정됨","sans-serif":"sans-serif","fontName":"글꼴","h1":"제목","h2":"부제목","h3":"하위 부제목","fontSize":"크기","cursive":"cursive","monospace":"monospace"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/ko/LinkDialog.js b/includes/js/dijit/_editor/nls/ko/LinkDialog.js
new file mode 100644
index 0000000..c8d10c3
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/ko/LinkDialog.js
@@ -0,0 +1 @@
+({"set":"설정","text":"설명:","insertImageTitle":"이미지 등록 정보","url":"URL:","createLinkTitle":"링크 등록 정보"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/ko/commands.js b/includes/js/dijit/_editor/nls/ko/commands.js
new file mode 100644
index 0000000..8327472
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/ko/commands.js
@@ -0,0 +1 @@
+({"removeFormat":"형식 제거","copy":"복사","paste":"붙여넣기","selectAll":"모두 선택","insertOrderedList":"번호 목록","insertTable":"테이블 삽입/편집","underline":"밑줄","foreColor":"전경색","htmlToggle":"HTML 소스","formatBlock":"단락 양식","insertHorizontalRule":"수평 자","delete":"삭제","insertUnorderedList":"글머리표 목록","tableProp":"테이블 특성","insertImage":"이미지 삽입","superscript":"위첨자","subscript":"아래첨자","createLink":"링크 작성","undo":"실행 취소","italic":"이탤릭체","fontName":"글꼴 이름","justifyLeft":"왼쪽 맞춤","unlink":"링크 제거","toggleTableBorder":"토글 테이블 경계","fontSize":"글꼴 크기","indent":"들여쓰기","redo":"다시 실행","strikethrough":"취소선","justifyFull":"양쪽 맞춤","justifyCenter":"가운데 맞춤","hiliteColor":"배경색","deleteTable":"테이블 삭제","outdent":"내어쓰기","cut":"잘라내기","plainFormatBlock":"단락 양식","toggleDir":"토글 방향","bold":"굵은체","systemShortcutFF":"\"${0}\" 조치는 키보드 바로 가기를 사용하는 Mozilla Firefox에서만 사용 가능합니다. ${1} 사용.","justifyRight":"오른쪽 맞춤","appleKey":"⌘${0}","ctrlKey":"ctrl+${0}"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/nb/FontChoice.js b/includes/js/dijit/_editor/nls/nb/FontChoice.js
new file mode 100644
index 0000000..440c44b
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/nb/FontChoice.js
@@ -0,0 +1 @@
+({"1":"xx-liten","2":"x-liten","formatBlock":"Format","monospaced":"ikke-proporsjonal","3":"liten","4":"middels","5":"stor","6":"x-stor","7":"xx-stor","fantasy":"fantasi","serif":"serif","p":"Avsnitt","pre":"Forhåndsformatert","sans-serif":"sans-serif","fontName":"Skrift","h1":"Overskrift","h2":"Undertittel","h3":"Under-undertittel","fontSize":"Størrelse","cursive":"kursiv","monospace":"monospace"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/nb/LinkDialog.js b/includes/js/dijit/_editor/nls/nb/LinkDialog.js
new file mode 100644
index 0000000..1f26a40
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/nb/LinkDialog.js
@@ -0,0 +1 @@
+({"set":"Definer","text":"Beskrivelse:","insertImageTitle":"Bildeegenskaper","url":"URL:","createLinkTitle":"Koblingsegenskaper"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/nb/commands.js b/includes/js/dijit/_editor/nls/nb/commands.js
new file mode 100644
index 0000000..039c1b3
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/nb/commands.js
@@ -0,0 +1 @@
+({"removeFormat":"Fjern format","copy":"Kopier","paste":"Lim inn","selectAll":"Velg alle","insertOrderedList":"Nummerert liste","insertTable":"Sett inn/rediger tabell","underline":"Understreking","foreColor":"Forgrunnsfarge","htmlToggle":"HTML-kilde","formatBlock":"Avsnittsstil","insertHorizontalRule":"Vannrett strek","delete":"Slett","insertUnorderedList":"Punktliste","tableProp":"Tabellegenskap","insertImage":"Sett inn bilde","superscript":"Hevet skrift","subscript":"Senket skrift","createLink":"Opprett kobling","undo":"Angre","italic":"Kursiv","fontName":"Skriftnavn","justifyLeft":"Venstrejuster","unlink":"Fjern kobling","toggleTableBorder":"Bytt tabellkant","fontSize":"Skriftstørrelse","indent":"Innrykk","redo":"Gjør om","strikethrough":"Gjennomstreking","justifyFull":"Juster","justifyCenter":"Midtstill","hiliteColor":"Bakgrunnsfarge","deleteTable":"Slett tabell","outdent":"Fjern innrykk","cut":"Klipp ut","plainFormatBlock":"Avsnittsstil","toggleDir":"Bytt retning","bold":"Fet","systemShortcutFF":"Handlingen \"${0}\" er bare tilgjengelig i Mozilla Firefox ved hjelp av en tastatursnarvei. Bruk ${1}.","justifyRight":"Høyrejuster","appleKey":"⌘${0}","ctrlKey":"ctrl+${0}"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/nl/FontChoice.js b/includes/js/dijit/_editor/nls/nl/FontChoice.js
new file mode 100644
index 0000000..7af12bf
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/nl/FontChoice.js
@@ -0,0 +1 @@
+({"1":"xx-klein","2":"x-klein","formatBlock":"Opmaak","monospaced":"monospaced","3":"klein","4":"gemiddeld","5":"groot","6":"x-groot","7":"xx-groot","fantasy":"fantasy","serif":"serif","p":"Alinea","pre":"Vooraf opgemaakt","sans-serif":"sans-serif","fontName":"Lettertype","h1":"Kop","h2":"Subkop","h3":"Sub-subkop","fontSize":"Grootte","cursive":"cursief","monospace":"monospace"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/nl/LinkDialog.js b/includes/js/dijit/_editor/nls/nl/LinkDialog.js
new file mode 100644
index 0000000..5f89113
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/nl/LinkDialog.js
@@ -0,0 +1 @@
+({"set":"Instellen","text":"Beschrijving:","insertImageTitle":"Afbeeldingseigenschappen","url":"URL:","createLinkTitle":"Linkeigenschappen"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/nl/commands.js b/includes/js/dijit/_editor/nls/nl/commands.js
new file mode 100644
index 0000000..3a259c3
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/nl/commands.js
@@ -0,0 +1 @@
+({"removeFormat":"Opmaak verwijderen","copy":"Kopiëren","paste":"Plakken","selectAll":"Alles selecteren","insertOrderedList":"Genummerde lijst","insertTable":"Tabel invoegen/bewerken","underline":"Onderstrepen","foreColor":"Voorgrondkleur","htmlToggle":"HTML-bron","formatBlock":"Alineastijl","insertHorizontalRule":"Horizontale liniaal","delete":"Wissen","insertUnorderedList":"Lijst met opsommingstekens","tableProp":"Tabeleigenschap","insertImage":"Afbeelding invoegen","superscript":"Superscript","subscript":"Subscript","createLink":"Link maken","undo":"Ongedaan maken","italic":"Cursief","fontName":"Lettertype","justifyLeft":"Links uitlijnen","unlink":"Link verwijderen","toggleTableBorder":"Tabelkader wijzigen","ctrlKey":"Ctrl+${0}","fontSize":"Lettergrootte","indent":"Inspringen","redo":"Opnieuw","strikethrough":"Doorhalen","justifyFull":"Uitvullen","justifyCenter":"Centreren","hiliteColor":"Achtergrondkleur","deleteTable":"Tabel wissen","outdent":"Uitspringen","cut":"Knippen","plainFormatBlock":"Alineastijl","toggleDir":"Schrijfrichting wijzigen","bold":"Vet","systemShortcutFF":"De actie \"${0}\" is alleen beschikbaar in Mozilla Firefox via een sneltoestcombinatie. Gebruik ${1}.","justifyRight":"Rechts uitlijnen","appleKey":"⌘${0}"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/pl/FontChoice.js b/includes/js/dijit/_editor/nls/pl/FontChoice.js
new file mode 100644
index 0000000..8c9bbd8
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/pl/FontChoice.js
@@ -0,0 +1 @@
+({"1":"najmniejsza","2":"mniejsza","formatBlock":"Format","monospaced":"stałej szerokości","3":"mała","4":"średnia","5":"duża","6":"większa","7":"największa","fantasy":"fantazyjna","serif":"szeryfowa","p":"Akapit","pre":"Wstępnie sformatowane","sans-serif":"bezszeryfowa","fontName":"Czcionka","h1":"Nagłówek","h2":"Nagłówek 2-go poziomu","h3":"Nagłówek 3-go poziomu","fontSize":"Wielkość","cursive":"kursywa","monospace":"monospace"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/pl/LinkDialog.js b/includes/js/dijit/_editor/nls/pl/LinkDialog.js
new file mode 100644
index 0000000..9d6c182
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/pl/LinkDialog.js
@@ -0,0 +1 @@
+({"set":"Ustaw","text":"Opis:","insertImageTitle":"Właściwości obrazu","url":"Adres URL:","createLinkTitle":"Właściwości odsyłacza"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/pl/commands.js b/includes/js/dijit/_editor/nls/pl/commands.js
new file mode 100644
index 0000000..49f8021
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/pl/commands.js
@@ -0,0 +1 @@
+({"removeFormat":"Usuń formatowanie","copy":"Kopiuj","paste":"Wklej","selectAll":"Wybierz wszystko","insertOrderedList":"Lista numerowana","insertTable":"Wstaw/edytuj tabelę","underline":"Podkreślenie","foreColor":"Kolor pierwszego planu","htmlToggle":"Źródło HTML","formatBlock":"Styl akapitu","insertHorizontalRule":"Linia pozioma","delete":"Usuń","insertUnorderedList":"Lista wypunktowana","tableProp":"Właściwość tabeli","insertImage":"Wstaw obraz","superscript":"Indeks górny","subscript":"Indeks dolny","createLink":"Utwórz odsyłacz","undo":"Cofnij","italic":"Kursywa","fontName":"Nazwa czcionki","justifyLeft":"Wyrównaj do lewej","unlink":"Usuń odsyłacz","toggleTableBorder":"Przełącz ramkę tabeli","fontSize":"Wielkość czcionki","indent":"Wcięcie","redo":"Przywróć","strikethrough":"Przekreślenie","justifyFull":"Wyrównaj do lewej i prawej","justifyCenter":"Wyrównaj do środka","hiliteColor":"Kolor tła","deleteTable":"Usuń tabelę","outdent":"Usuń wcięcie","cut":"Wytnij","plainFormatBlock":"Styl akapitu","toggleDir":"Przełącz kierunek","bold":"Pogrubienie","systemShortcutFF":"Działanie ${0} jest dostępne w przeglądarce Mozilla Firefox wyłącznie za pomocą skrótu klawiaturowego. Użyj ${1}.","justifyRight":"Wyrównaj do prawej","appleKey":"⌘${0}","ctrlKey":"ctrl+${0}"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/pt-pt/FontChoice.js b/includes/js/dijit/_editor/nls/pt-pt/FontChoice.js
new file mode 100644
index 0000000..f697a6f
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/pt-pt/FontChoice.js
@@ -0,0 +1 @@
+({"1":"xxs","2":"xs","formatBlock":"Formato","monospaced":"monospaced","3":"small","4":"medium","5":"large","6":"xl","7":"xxl","fantasy":"fantasy","serif":"serif","p":"Parágrafo","pre":"Pré-formatado","sans-serif":"sans-serif","fontName":"Tipo de letra","h1":"Título","h2":"Sub-título","h3":"Sub-subtítulo","fontSize":"Tamanho","cursive":"cursive","monospace":"monospace"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/pt-pt/LinkDialog.js b/includes/js/dijit/_editor/nls/pt-pt/LinkDialog.js
new file mode 100644
index 0000000..3478d41
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/pt-pt/LinkDialog.js
@@ -0,0 +1 @@
+({"set":"Definir","text":"Descrição:","insertImageTitle":"Propriedades da imagem","url":"URL:","createLinkTitle":"Propriedade da ligação"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/pt-pt/commands.js b/includes/js/dijit/_editor/nls/pt-pt/commands.js
new file mode 100644
index 0000000..0a93447
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/pt-pt/commands.js
@@ -0,0 +1 @@
+({"removeFormat":"Remover formato","copy":"Copiar","paste":"Colar","selectAll":"Seleccionar tudo","insertOrderedList":"Lista numerada","insertTable":"Inserir/Editar tabela","underline":"Sublinhado","foreColor":"Cor de primeiro plano","htmlToggle":"Origem HTML","formatBlock":"Estilo de parágrafo","insertHorizontalRule":"Régua horizontal","delete":"Eliminar","insertUnorderedList":"Lista marcada","tableProp":"Propriedades da tabela","insertImage":"Inserir imagem","superscript":"Superior à linha","subscript":"Inferior à linha","createLink":"Criar ligação","undo":"Anular","italic":"Itálico","fontName":"Nome do tipo de letra","justifyLeft":"Alinhar à esquerda","unlink":"Remover ligação","toggleTableBorder":"Alternar limite da tabela","fontSize":"Tamanho do tipo de letra","indent":"Indentar","redo":"Repetir","strikethrough":"Rasurado","justifyFull":"Justificar","justifyCenter":"Alinhar ao centro","hiliteColor":"Cor de segundo plano","deleteTable":"Eliminar tabela","outdent":"Recuar","cut":"Cortar","plainFormatBlock":"Estilo de parágrafo","toggleDir":"Alternar direcção","bold":"Negrito","systemShortcutFF":"A acção \"${0}\" apenas está disponível no Mozilla Firefox utilizando um atalho de teclado. Utilize ${1}.","justifyRight":"Alinhar à direita","appleKey":"⌘${0}","ctrlKey":"ctrl+${0}"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/pt/FontChoice.js b/includes/js/dijit/_editor/nls/pt/FontChoice.js
new file mode 100644
index 0000000..e2ee4e7
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/pt/FontChoice.js
@@ -0,0 +1 @@
+({"1":"xx-small","2":"x-small","formatBlock":"Formato","monospaced":"monospaced","3":"small","4":"medium","5":"large","6":"x-large","7":"xx-large","fantasy":"fantasy","serif":"serif","p":"Parágrafo","pre":"Pré-formatado","sans-serif":"sans-serif","fontName":"Fonte","h1":"Título","h2":"Subtítulo","h3":"Sub-subtítulo","fontSize":"Tamanho","cursive":"cursive","monospace":"monospace"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/pt/LinkDialog.js b/includes/js/dijit/_editor/nls/pt/LinkDialog.js
new file mode 100644
index 0000000..e74d4fd
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/pt/LinkDialog.js
@@ -0,0 +1 @@
+({"set":"Definir","text":"Descrição:","insertImageTitle":"Propriedades de Imagem","url":"URL:","createLinkTitle":"Propriedades de Link"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/pt/commands.js b/includes/js/dijit/_editor/nls/pt/commands.js
new file mode 100644
index 0000000..e7aabc5
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/pt/commands.js
@@ -0,0 +1 @@
+({"removeFormat":"Remover Formato","copy":"Copiar","paste":"Colar","selectAll":"Selecionar Todos","insertOrderedList":"Lista Numerada","insertTable":"Inserir/Editar Tabela","underline":"Sublinhado","foreColor":"Cor do Primeiro Plano","htmlToggle":"Origem HTML","formatBlock":"Estilo de Parágrafo","insertHorizontalRule":"Régua Horizontal","delete":"Excluir ","insertUnorderedList":"Lista com Marcadores","tableProp":"Propriedade da Tabela","insertImage":"Inserir Imagem","superscript":"Sobrescrito","subscript":"Subscrito","createLink":"Criar Link","undo":"Desfazer","italic":"Itálico","fontName":"Nome da Fonte","justifyLeft":"Alinhar pela Esquerda","unlink":"Remover Link","toggleTableBorder":"Alternar Moldura da Tabela","fontSize":"Tamanho da Fonte","indent":"Recuar","redo":"Refazer","strikethrough":"Tachado","justifyFull":"Justificar","justifyCenter":"Alinhar pelo Centro","hiliteColor":"Cor de segundo plano","deleteTable":"Excluir Tabela","outdent":"Não-chanfrado","cut":"Recortar","plainFormatBlock":"Estilo de Parágrafo","toggleDir":"Alternar Direção","bold":"Negrito","systemShortcutFF":"A ação \"${0}\" está disponível apenas no Mozilla Firefox utilizando um atalho do teclado. Utilize ${1}.","justifyRight":"Alinhar pela Direita","appleKey":"⌘${0}","ctrlKey":"ctrl+${0}"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/ru/FontChoice.js b/includes/js/dijit/_editor/nls/ru/FontChoice.js
new file mode 100644
index 0000000..b1fde8d
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/ru/FontChoice.js
@@ -0,0 +1 @@
+({"1":"самый маленький","2":"очень маленький","formatBlock":"Формат","monospaced":"непропорциональный","3":"маленький","4":"средний","5":"большой","6":"очень большой","7":"самый большой","fantasy":"артистический","serif":"с засечками","p":"Абзац","pre":"Заранее отформатированный","sans-serif":"без засечек","fontName":"Шрифт","h1":"Заголовок","h2":"Подзаголовок","h3":"Вложенный подзаголовок","fontSize":"Размер","cursive":"курсив","monospace":"monospace"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/ru/LinkDialog.js b/includes/js/dijit/_editor/nls/ru/LinkDialog.js
new file mode 100644
index 0000000..42a6826
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/ru/LinkDialog.js
@@ -0,0 +1 @@
+({"set":"Задать","text":"Описание:","insertImageTitle":"Свойства изображения","url":"URL:","createLinkTitle":"Свойства ссылки"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/ru/commands.js b/includes/js/dijit/_editor/nls/ru/commands.js
new file mode 100644
index 0000000..82ed23f
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/ru/commands.js
@@ -0,0 +1 @@
+({"removeFormat":"Удалить формат","copy":"Копировать","paste":"Вставить","selectAll":"Выбрать все","insertOrderedList":"Нумерованный список","insertTable":"Вставить/изменить таблицу","underline":"Подчеркивание","foreColor":"Цвет текста","htmlToggle":"Код HTML","formatBlock":"Стиль абзаца","insertHorizontalRule":"Горизонтальная линейка","delete":"Удалить","insertUnorderedList":"Список с маркерами","tableProp":"Свойства таблицы","insertImage":"Вставить изображение","superscript":"Верхний индекс","subscript":"Нижний индекс","createLink":"Создать ссылку","undo":"Отменить","italic":"Курсив","fontName":"Название шрифта","justifyLeft":"По левому краю","unlink":"Удалить ссылку","toggleTableBorder":"Переключить рамку таблицы","fontSize":"Размер шрифта","indent":"Отступ","redo":"Повторить","strikethrough":"Перечеркивание","justifyFull":"По ширине","justifyCenter":"По центру","hiliteColor":"Цвет фона","deleteTable":"Удалить таблицу","outdent":"Втяжка","cut":"Вырезать","plainFormatBlock":"Стиль абзаца","toggleDir":"Изменить направление","bold":"Полужирный","systemShortcutFF":"Действие \"${0}\" доступно в Mozilla Firefox только через сочетание клавиш. Используйте ${1}.","justifyRight":"По правому краю","appleKey":"⌘${0}","ctrlKey":"ctrl+${0}"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/sv/FontChoice.js b/includes/js/dijit/_editor/nls/sv/FontChoice.js
new file mode 100644
index 0000000..8d9c1b1
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/sv/FontChoice.js
@@ -0,0 +1 @@
+({"1":"mycket, mycket litet","2":"mycket litet","formatBlock":"Format","monospaced":"fast teckenavstånd","3":"litet","4":"medelstort","5":"stort","6":"extra stort","7":"extra extra stort","fantasy":"fantasy","serif":"serif","p":"Stycke","pre":"Förformaterat","sans-serif":"sans-serif","fontName":"Teckensnitt","h1":"Rubrik","h2":"Underrubrik","h3":"Underunderrubrik","fontSize":"Storlek","cursive":"kursivt","monospace":"monospace"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/sv/LinkDialog.js b/includes/js/dijit/_editor/nls/sv/LinkDialog.js
new file mode 100644
index 0000000..64e8cfb
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/sv/LinkDialog.js
@@ -0,0 +1 @@
+({"set":"Ange","text":"Beskrivning:","insertImageTitle":"Bildegenskaper","url":"URL-adress:","createLinkTitle":"Länkegenskaper"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/sv/commands.js b/includes/js/dijit/_editor/nls/sv/commands.js
new file mode 100644
index 0000000..a5082a4
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/sv/commands.js
@@ -0,0 +1 @@
+({"removeFormat":"Ta bort format","copy":"Kopiera","paste":"Klistra in","selectAll":"Markera allt","insertOrderedList":"Numrerad lista","insertTable":"Infoga/redigera tabell","underline":"Understrykning","foreColor":"Förgrundsfärg","htmlToggle":"HTML-källkod","formatBlock":"Styckeformat","insertHorizontalRule":"Horisontell linjal","delete":"Ta bort","insertUnorderedList":"Punktlista","tableProp":"Tabellegenskap","insertImage":"Infoga bild","superscript":"Upphöjt","subscript":"Nedsänkt","createLink":"Skapa länk","undo":"Ångra","italic":"Kursiv","fontName":"Teckensnittsnamn","justifyLeft":"Vänsterjustera","unlink":"Ta bort länk","toggleTableBorder":"Aktivera/avaktivera tabellram","ctrlKey":"Ctrl+${0}","fontSize":"Teckenstorlek","indent":"Indrag","redo":"Gör om","strikethrough":"Genomstruken","justifyFull":"Marginaljustera","justifyCenter":"Centrera","hiliteColor":"Bakgrundsfärg","deleteTable":"Ta bort tabell","outdent":"Utdrag","cut":"Klipp ut","plainFormatBlock":"Styckeformat","toggleDir":"Växla riktning","bold":"Fetstil","systemShortcutFF":"Åtgärden \"${0}\" är endast tillgänglig i Mozilla Firefox med hjälp av ett kortkommando. Använd ${1}.","justifyRight":"Högerjustera","appleKey":"⌘${0}"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/tr/FontChoice.js b/includes/js/dijit/_editor/nls/tr/FontChoice.js
new file mode 100644
index 0000000..3f11939
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/tr/FontChoice.js
@@ -0,0 +1 @@
+({"1":"xx-küçük","2":"x-küçük","formatBlock":"Biçim","monospaced":"eşaralıklı","3":"küçük","4":"orta","5":"büyük","6":"x-büyük","7":"xx-büyük","fantasy":"fantazi","serif":"serif","p":"Paragraf","pre":"Önceden Biçimlendirilmiş","sans-serif":"sans-serif","fontName":"Yazı Tipi","h1":"Başlık","h2":"Alt Başlık","h3":"Alt Alt Başlık","fontSize":"Boyut","cursive":"el yazısı","monospace":"monospace"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/tr/LinkDialog.js b/includes/js/dijit/_editor/nls/tr/LinkDialog.js
new file mode 100644
index 0000000..7f5856d
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/tr/LinkDialog.js
@@ -0,0 +1 @@
+({"set":"Ayarla","text":"Açıklama:","insertImageTitle":"Resim Özellikleri","url":"URL:","createLinkTitle":"Bağlantı Özellikleri"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/tr/commands.js b/includes/js/dijit/_editor/nls/tr/commands.js
new file mode 100644
index 0000000..5731261
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/tr/commands.js
@@ -0,0 +1 @@
+({"removeFormat":"Biçimi Kaldır","copy":"Kopyala","paste":"Yapıştır","selectAll":"Tümünü Seç","insertOrderedList":"Numaralı Liste","insertTable":"Tablo Ekle/Düzenle","underline":"Altı Çizili","foreColor":"Ön Plan Rengi","htmlToggle":"HTML Kaynağı","formatBlock":"Paragraf Stili","insertHorizontalRule":"Yatay Kural","delete":"Sil","insertUnorderedList":"Madde İşaretli Liste","tableProp":"Tablo Özelliği","insertImage":"Resim Ekle","superscript":"Üst Simge","subscript":"Alt Simge","createLink":"Bağlantı Oluştur","undo":"Geri Al","italic":"İtalik","fontName":"Yazı Tipi Adı","justifyLeft":"Sola Hizala","unlink":"Bağlantıyı Kaldır","toggleTableBorder":"Tablo Kenarlığını Göster/Gizle","fontSize":"Yazı Tipi Boyutu","indent":"Girinti","redo":"Yinele","strikethrough":"Üstü Çizili","justifyFull":"Yasla","justifyCenter":"Ortaya Hizala","hiliteColor":"Arka Plan Rengi","deleteTable":"Tabloyu Sil","outdent":"Çıkıntı","cut":"Kes","plainFormatBlock":"Paragraf Stili","toggleDir":"Yönü Değiştir","bold":"Kalın","systemShortcutFF":"\"${0}\" işlemi yalnızca Mozilla Firefox'ta bir klavye kısayoluyla birlikte kullanılabilir. ${1} işlemini kullanın.","justifyRight":"Sağa Hizala","appleKey":"⌘${0}","ctrlKey":"ctrl+${0}"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/zh-tw/FontChoice.js b/includes/js/dijit/_editor/nls/zh-tw/FontChoice.js
new file mode 100644
index 0000000..fa5527c
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/zh-tw/FontChoice.js
@@ -0,0 +1 @@
+({"1":"最小","2":"較小","formatBlock":"格式","monospaced":"單距","3":"小","4":"中","5":"大","6":"較大","7":"最大","fantasy":"Fantasy","serif":"新細明體","p":"段落","pre":"預先格式化","sans-serif":"新細明體","fontName":"字型","h1":"標題","h2":"子標題","h3":"次子標題","fontSize":"大小","cursive":"Cursive","monospace":"monospace"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/zh-tw/LinkDialog.js b/includes/js/dijit/_editor/nls/zh-tw/LinkDialog.js
new file mode 100644
index 0000000..fb74fb6
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/zh-tw/LinkDialog.js
@@ -0,0 +1 @@
+({"set":"設定","text":"說明:","insertImageTitle":"影像檔內容","url":"URL:","createLinkTitle":"鏈結內容"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/zh-tw/commands.js b/includes/js/dijit/_editor/nls/zh-tw/commands.js
new file mode 100644
index 0000000..adde3bc
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/zh-tw/commands.js
@@ -0,0 +1 @@
+({"removeFormat":"移除格式","copy":"複製","paste":"貼上","selectAll":"全選","insertOrderedList":"編號清單","insertTable":"插入/編輯表格","underline":"底線","foreColor":"前景顏色","htmlToggle":"HTML 原始檔","formatBlock":"段落樣式","insertHorizontalRule":"水平尺規","delete":"刪除","insertUnorderedList":"項目符號清單","tableProp":"表格內容","insertImage":"插入影像","superscript":"上標","subscript":"下標","createLink":"建立鏈結","undo":"復原","italic":"斜體","fontName":"字型名稱","justifyLeft":"靠左對齊","unlink":"移除鏈結","toggleTableBorder":"切換表格邊框","fontSize":"字型大小","indent":"縮排","redo":"重做","strikethrough":"加刪除線","justifyFull":"對齊","justifyCenter":"置中對齊","hiliteColor":"背景顏色","deleteTable":"刪除表格","outdent":"凸排","cut":"剪下","plainFormatBlock":"段落樣式","toggleDir":"切換方向","bold":"粗體","systemShortcutFF":"\"${0}\" 動作在 Mozilla Firefox 中,只能使用鍵盤快速鍵。請使用 ${1}。","justifyRight":"靠右對齊","appleKey":"⌘${0}","ctrlKey":"ctrl+${0}"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/zh/FontChoice.js b/includes/js/dijit/_editor/nls/zh/FontChoice.js
new file mode 100644
index 0000000..ba28c8b
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/zh/FontChoice.js
@@ -0,0 +1 @@
+({"1":"XXS 号","2":"XS 号","formatBlock":"格式","monospaced":"等宽","3":"S 号","4":"M 号","5":"L 号","6":"XL 号","7":"XXL 号","fantasy":"虚线","serif":"有衬线","p":"段落","pre":"预设有格式的","sans-serif":"无衬线","fontName":"字体","h1":"标题","h2":"子标题","h3":"二级子标题","fontSize":"大小","cursive":"草书","monospace":"monospace"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/zh/LinkDialog.js b/includes/js/dijit/_editor/nls/zh/LinkDialog.js
new file mode 100644
index 0000000..73fca59
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/zh/LinkDialog.js
@@ -0,0 +1 @@
+({"set":"集合","text":"描述:","insertImageTitle":"图像属性","url":"URL:","createLinkTitle":"链接属性"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/nls/zh/commands.js b/includes/js/dijit/_editor/nls/zh/commands.js
new file mode 100644
index 0000000..4cb3c96
--- /dev/null
+++ b/includes/js/dijit/_editor/nls/zh/commands.js
@@ -0,0 +1 @@
+({"removeFormat":"除去格式","copy":"复制","paste":"粘贴","selectAll":"全选","insertOrderedList":"编号列表","insertTable":"插入/编辑表","underline":"下划线","foreColor":"前景色","htmlToggle":"HTML 源代码","formatBlock":"段落样式","insertHorizontalRule":"水平线","delete":"删除","insertUnorderedList":"符号列表","tableProp":"表属性","insertImage":"插入图像","superscript":"上标","subscript":"下标","createLink":"创建链接","undo":"撤销","italic":"斜体","fontName":"字体名称","justifyLeft":"左对齐","unlink":"除去链接","toggleTableBorder":"切换表边框","fontSize":"字体大小","indent":"增加缩进","redo":"重做","strikethrough":"删除线","justifyFull":"对齐","justifyCenter":"居中","hiliteColor":"背景色","deleteTable":"删除表","outdent":"减少缩进","cut":"剪切","plainFormatBlock":"段落样式","toggleDir":"固定方向","bold":"粗体","systemShortcutFF":"只能在 Mozilla Firefox 中通过键盘快捷方式执行“${0}”操作。请使用 ${1}。","justifyRight":"右对齐","appleKey":"⌘${0}","ctrlKey":"ctrl+${0}"}) \ No newline at end of file
diff --git a/includes/js/dijit/_editor/plugins/AlwaysShowToolbar.js b/includes/js/dijit/_editor/plugins/AlwaysShowToolbar.js
new file mode 100644
index 0000000..9879e88
--- /dev/null
+++ b/includes/js/dijit/_editor/plugins/AlwaysShowToolbar.js
@@ -0,0 +1,140 @@
+if(!dojo._hasResource["dijit._editor.plugins.AlwaysShowToolbar"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit._editor.plugins.AlwaysShowToolbar"] = true;
+dojo.provide("dijit._editor.plugins.AlwaysShowToolbar");
+
+dojo.declare("dijit._editor.plugins.AlwaysShowToolbar", dijit._editor._Plugin,
+ {
+ _handleScroll: true,
+ setEditor: function(e){
+ this.editor = e;
+// setTimeout(dojo.hitch(this,this.enable), 10000);
+ e.onLoadDeferred.addCallback(dojo.hitch(this, this.enable));
+// this.scrollInterval = setInterval(dojo.hitch(this, "globalOnScrollHandler"), 100);
+ },
+ enable: function(d){
+ this._updateHeight();
+ this.connect(window, 'onscroll', "globalOnScrollHandler");
+ this.connect(this.editor, 'onNormalizedDisplayChanged', "_updateHeight");
+ return d;
+ },
+ _updateHeight: function(){
+ // summary:
+ // Updates the height of the editor area to fit the contents.
+ var e = this.editor;
+ if(!e.isLoaded){ return; }
+ if(e.height){ return; }
+
+ var height = dojo.marginBox(e.editNode).h;
+ if(dojo.isOpera){
+ height = e.editNode.scrollHeight;
+ }
+ // console.debug('height',height);
+ // alert(this.editNode);
+
+ //height maybe zero in some cases even though the content is not empty,
+ //we try the height of body instead
+ if(!height){
+ height = dojo.marginBox(e.document.body).h;
+ }
+
+ if(height == 0){
+ console.debug("Can not figure out the height of the editing area!");
+ return; //prevent setting height to 0
+ }
+ if(height != this._lastHeight){
+ this._lastHeight = height;
+ // this.editorObject.style.height = this._lastHeight + "px";
+ dojo.marginBox(e.iframe, { h: this._lastHeight });
+// this.iframe.height=this._lastHeight+10+'px';
+// this.iframe.style.height=this._lastHeight+'px';
+ }
+ },
+ _lastHeight: 0,
+ globalOnScrollHandler: function(){
+ var isIE = dojo.isIE && dojo.isIE<7;
+ if(!this._handleScroll){ return; }
+ var tdn = this.editor.toolbar.domNode;
+ var db = dojo.body;
+
+ if(!this._scrollSetUp){
+ this._scrollSetUp = true;
+ this._scrollThreshold = dojo._abs(tdn, true).y;
+// console.log("threshold:", this._scrollThreshold);
+ //what's this for?? comment out for now
+// if((isIE)&&(db)&&(dojo.style(db, "backgroundIimage")=="none")){
+// db.style.backgroundImage = "url(" + dojo.uri.moduleUri("dijit", "templates/blank.gif") + ")";
+// db.style.backgroundAttachment = "fixed";
+// }
+ }
+
+ var scrollPos = dojo._docScroll().y;
+ var s = tdn.style;
+
+ if(scrollPos > this._scrollThreshold && scrollPos < this._scrollThreshold+this._lastHeight){
+ // dojo.debug(scrollPos);
+ if(!this._fixEnabled){
+ var tdnbox = dojo.marginBox(tdn);
+ this.editor.iframe.style.marginTop = tdnbox.h+"px";
+
+ if(isIE){
+ s.left = dojo._abs(tdn).x;
+ if(tdn.previousSibling){
+ this._IEOriginalPos = ['after',tdn.previousSibling];
+ }else if(tdn.nextSibling){
+ this._IEOriginalPos = ['before',tdn.nextSibling];
+ }else{
+ this._IEOriginalPos = ['last',tdn.parentNode];
+ }
+ dojo.body().appendChild(tdn);
+ dojo.addClass(tdn,'dijitIEFixedToolbar');
+ }else{
+ s.position = "fixed";
+ s.top = "0px";
+ }
+
+ dojo.marginBox(tdn, { w: tdnbox.w });
+ s.zIndex = 2000;
+ this._fixEnabled = true;
+ }
+ // if we're showing the floating toolbar, make sure that if
+ // we've scrolled past the bottom of the editor that we hide
+ // the toolbar for this instance of the editor.
+
+ // TODO: when we get multiple editor toolbar support working
+ // correctly, ensure that we check this against the scroll
+ // position of the bottom-most editor instance.
+ var eHeight = (this.height) ? parseInt(this.editor.height) : this.editor._lastHeight;
+ s.display = (scrollPos > this._scrollThreshold+eHeight) ? "none" : "";
+ }else if(this._fixEnabled){
+ this.editor.iframe.style.marginTop = '';
+ s.position = "";
+ s.top = "";
+ s.zIndex = "";
+ s.display = "";
+ if(isIE){
+ s.left = "";
+ dojo.removeClass(tdn,'dijitIEFixedToolbar');
+ if(this._IEOriginalPos){
+ dojo.place(tdn, this._IEOriginalPos[1], this._IEOriginalPos[0]);
+ this._IEOriginalPos = null;
+ }else{
+ dojo.place(tdn, this.editor.iframe, 'before');
+ }
+ }
+ s.width = "";
+ this._fixEnabled = false;
+ }
+ },
+ destroy: function(){
+ this._IEOriginalPos = null;
+ this._handleScroll = false;
+ dojo.forEach(this._connects, dojo.disconnect);
+// clearInterval(this.scrollInterval);
+
+ if(dojo.isIE && dojo.isIE<7){
+ dojo.removeClass(this.editor.toolbar.domNode, 'dijitIEFixedToolbar');
+ }
+ }
+});
+
+}
diff --git a/includes/js/dijit/_editor/plugins/EnterKeyHandling.js b/includes/js/dijit/_editor/plugins/EnterKeyHandling.js
new file mode 100644
index 0000000..083743d
--- /dev/null
+++ b/includes/js/dijit/_editor/plugins/EnterKeyHandling.js
@@ -0,0 +1,416 @@
+if(!dojo._hasResource["dijit._editor.plugins.EnterKeyHandling"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit._editor.plugins.EnterKeyHandling"] = true;
+dojo.provide("dijit._editor.plugins.EnterKeyHandling");
+
+dojo.declare("dijit._editor.plugins.EnterKeyHandling", dijit._editor._Plugin, {
+ // summary: this plugin tries to handle enter key events to make all
+ // browsers have identical behaviors.
+
+ // blockNodeForEnter: String
+ // this property decides the behavior of Enter key. It can be either P,
+ // DIV, BR, or empty (which means disable this feature). Anything else
+ // will trigger errors.
+ blockNodeForEnter: 'P',
+ constructor: function(args){
+ if(args){
+ dojo.mixin(this,args);
+ }
+ },
+ setEditor: function(editor){
+ this.editor = editor;
+ if(this.blockNodeForEnter == 'BR'){
+ if(dojo.isIE){
+ editor.contentDomPreFilters.push(dojo.hitch(this, "regularPsToSingleLinePs"));
+ editor.contentDomPostFilters.push(dojo.hitch(this, "singleLinePsToRegularPs"));
+ editor.onLoadDeferred.addCallback(dojo.hitch(this, "_fixNewLineBehaviorForIE"));
+ }else{
+ editor.onLoadDeferred.addCallback(dojo.hitch(this,function(d){
+ try{
+ this.editor.document.execCommand("insertBrOnReturn", false, true);
+ }catch(e){}
+ return d;
+ }));
+ }
+ }else if(this.blockNodeForEnter){
+ //add enter key handler
+ // FIXME: need to port to the new event code!!
+ dojo['require']('dijit._editor.range');
+ var h = dojo.hitch(this,this.handleEnterKey);
+ editor.addKeyHandler(13, 0, h); //enter
+ editor.addKeyHandler(13, 2, h); //shift+enter
+ this.connect(this.editor,'onKeyPressed','onKeyPressed');
+ }
+ },
+ connect: function(o,f,tf){
+ if(!this._connects){
+ this._connects=[];
+ }
+ this._connects.push(dojo.connect(o,f,this,tf));
+ },
+ destroy: function(){
+ dojo.forEach(this._connects,dojo.disconnect);
+ this._connects=[];
+ },
+ onKeyPressed: function(e){
+ if(this._checkListLater){
+ if(dojo.withGlobal(this.editor.window, 'isCollapsed', dijit)){
+ if(!dojo.withGlobal(this.editor.window, 'hasAncestorElement', dijit._editor.selection, ['LI'])){
+ //circulate the undo detection code by calling RichText::execCommand directly
+ dijit._editor.RichText.prototype.execCommand.apply(this.editor, ['formatblock',this.blockNodeForEnter]);
+ //set the innerHTML of the new block node
+ var block = dojo.withGlobal(this.editor.window, 'getAncestorElement', dijit._editor.selection, [this.blockNodeForEnter]);
+ if(block){
+ block.innerHTML=this.bogusHtmlContent;
+ if(dojo.isIE){
+ //the following won't work, it will move the caret to the last list item in the previous list
+// var newrange = dijit.range.create();
+// newrange.setStart(block.firstChild,0);
+// var selection = dijit.range.getSelection(this.editor.window)
+// selection.removeAllRanges();
+// selection.addRange(newrange);
+ //move to the start by move backward one char
+ var r = this.editor.document.selection.createRange();
+ r.move('character',-1);
+ r.select();
+ }
+ }else{
+ alert('onKeyPressed: Can not find the new block node'); //FIXME
+ }
+ }
+ }
+ this._checkListLater = false;
+ }else if(this._pressedEnterInBlock){
+ //the new created is the original current P, so we have previousSibling below
+ this.removeTrailingBr(this._pressedEnterInBlock.previousSibling);
+ delete this._pressedEnterInBlock;
+ }
+ },
+ bogusHtmlContent: '&nbsp;',
+ blockNodes: /^(?:H1|H2|H3|H4|H5|H6|LI)$/,
+ handleEnterKey: function(e){
+ // summary: manually handle enter key event to make the behavior consistant across
+ // all supported browsers. See property blockNodeForEnter for available options
+ if(!this.blockNodeForEnter){ return true; } //let browser handle this
+ var selection, range, newrange;
+ if(e.shiftKey //shift+enter always generates <br>
+ || this.blockNodeForEnter=='BR'){
+ var parent = dojo.withGlobal(this.editor.window, "getParentElement", dijit._editor.selection);
+ var header = dijit.range.getAncestor(parent,this.editor.blockNodes);
+ if(header){
+ if(header.tagName=='LI'){
+ return true; //let brower handle
+ }
+ selection = dijit.range.getSelection(this.editor.window);
+ range = selection.getRangeAt(0);
+ if(!range.collapsed){
+ range.deleteContents();
+ }
+ if(dijit.range.atBeginningOfContainer(header, range.startContainer, range.startOffset)){
+ dojo.place(this.editor.document.createElement('br'), header, "before");
+ }else if(dijit.range.atEndOfContainer(header, range.startContainer, range.startOffset)){
+ dojo.place(this.editor.document.createElement('br'), header, "after");
+ newrange = dijit.range.create();
+ newrange.setStartAfter(header);
+
+ selection.removeAllRanges();
+ selection.addRange(newrange);
+ }else{
+ return true; //let brower handle
+ }
+ }else{
+ //don't change this: do not call this.execCommand, as that may have other logic in subclass
+ // FIXME
+ dijit._editor.RichText.prototype.execCommand.call(this.editor, 'inserthtml', '<br>');
+ }
+ return false;
+ }
+ var _letBrowserHandle = true;
+ //blockNodeForEnter is either P or DIV
+ //first remove selection
+ selection = dijit.range.getSelection(this.editor.window);
+ range = selection.getRangeAt(0);
+ if(!range.collapsed){
+ range.deleteContents();
+ }
+
+ var block = dijit.range.getBlockAncestor(range.endContainer, null, this.editor.editNode);
+
+ if((this._checkListLater = (block.blockNode && block.blockNode.tagName == 'LI'))){
+ return true;
+ }
+
+ //text node directly under body, let's wrap them in a node
+ if(!block.blockNode){
+ this.editor.document.execCommand('formatblock', false, this.blockNodeForEnter);
+ //get the newly created block node
+ // FIXME
+ block = {blockNode:dojo.withGlobal(this.editor.window, "getAncestorElement", dijit._editor.selection, [this.blockNodeForEnter]),
+ blockContainer: this.editor.editNode};
+ if(block.blockNode){
+ if(!(block.blockNode.textContent || block.blockNode.innerHTML).replace(/^\s+|\s+$/g, "").length){
+ this.removeTrailingBr(block.blockNode);
+ return false;
+ }
+ }else{
+ block.blockNode = this.editor.editNode;
+ }
+ selection = dijit.range.getSelection(this.editor.window);
+ range = selection.getRangeAt(0);
+ }
+ var newblock = this.editor.document.createElement(this.blockNodeForEnter);
+ newblock.innerHTML=this.bogusHtmlContent;
+ this.removeTrailingBr(block.blockNode);
+ if(dijit.range.atEndOfContainer(block.blockNode, range.endContainer, range.endOffset)){
+ if(block.blockNode === block.blockContainer){
+ block.blockNode.appendChild(newblock);
+ }else{
+ dojo.place(newblock, block.blockNode, "after");
+ }
+ _letBrowserHandle = false;
+ //lets move caret to the newly created block
+ newrange = dijit.range.create();
+ newrange.setStart(newblock,0);
+ selection.removeAllRanges();
+ selection.addRange(newrange);
+ if(this.editor.height){
+ newblock.scrollIntoView(false);
+ }
+ }else if(dijit.range.atBeginningOfContainer(block.blockNode,
+ range.startContainer, range.startOffset)){
+ dojo.place(newblock, block.blockNode, block.blockNode === block.blockContainer ? "first" : "before");
+ if(newblock.nextSibling && this.editor.height){
+ //browser does not scroll the caret position into view, do it manually
+ newblock.nextSibling.scrollIntoView(false);
+ }
+ _letBrowserHandle = false;
+ }else{ //press enter in the middle of P
+ if(dojo.isMoz){
+ //press enter in middle of P may leave a trailing <br/>, let's remove it later
+ this._pressedEnterInBlock = block.blockNode;
+ }
+ }
+ return _letBrowserHandle;
+ },
+ removeTrailingBr: function(container){
+ var para = /P|DIV|LI/i.test(container.tagName) ?
+ container : dijit._editor.selection.getParentOfType(container,['P','DIV','LI']);
+
+ if(!para){ return; }
+ if(para.lastChild){
+ if((para.childNodes.length > 1 && para.lastChild.nodeType == 3 && /^[\s\xAD]*$/.test(para.lastChild.nodeValue)) ||
+ (para.lastChild && para.lastChild.tagName=='BR')){
+
+ dojo._destroyElement(para.lastChild);
+ }
+ }
+ if(!para.childNodes.length){
+ para.innerHTML=this.bogusHtmlContent;
+ }
+ },
+ _fixNewLineBehaviorForIE: function(d){
+ if(this.editor.document.__INSERTED_EDITIOR_NEWLINE_CSS === undefined){
+ var lineFixingStyles = "p{margin:0 !important;}";
+ var insertCssText = function(
+ /*String*/ cssStr,
+ /*Document*/ doc,
+ /*String*/ URI)
+ {
+ // summary:
+ // Attempt to insert CSS rules into the document through inserting a
+ // style element
+
+ // DomNode Style = insertCssText(String ".dojoMenu {color: green;}"[, DomDoc document, dojo.uri.Uri Url ])
+ if(!cssStr){
+ return null; // HTMLStyleElement
+ }
+ if(!doc){ doc = document; }
+// if(URI){// fix paths in cssStr
+// cssStr = dojo.html.fixPathsInCssText(cssStr, URI);
+// }
+ var style = doc.createElement("style");
+ style.setAttribute("type", "text/css");
+ // IE is b0rken enough to require that we add the element to the doc
+ // before changing it's properties
+ var head = doc.getElementsByTagName("head")[0];
+ if(!head){ // must have a head tag
+ console.debug("No head tag in document, aborting styles");
+ return null; // HTMLStyleElement
+ }else{
+ head.appendChild(style);
+ }
+ if(style.styleSheet){// IE
+ var setFunc = function(){
+ try{
+ style.styleSheet.cssText = cssStr;
+ }catch(e){ console.debug(e); }
+ };
+ if(style.styleSheet.disabled){
+ setTimeout(setFunc, 10);
+ }else{
+ setFunc();
+ }
+ }else{ // w3c
+ var cssText = doc.createTextNode(cssStr);
+ style.appendChild(cssText);
+ }
+ return style; // HTMLStyleElement
+ }
+ insertCssText(lineFixingStyles, this.editor.document);
+ this.editor.document.__INSERTED_EDITIOR_NEWLINE_CSS = true;
+ // this.regularPsToSingleLinePs(this.editNode);
+ return d;
+ }
+ return null;
+ },
+ regularPsToSingleLinePs: function(element, noWhiteSpaceInEmptyP){
+ function wrapLinesInPs(el){
+ // move "lines" of top-level text nodes into ps
+ function wrapNodes(nodes){
+ // nodes are assumed to all be siblings
+ var newP = nodes[0].ownerDocument.createElement('p'); // FIXME: not very idiomatic
+ nodes[0].parentNode.insertBefore(newP, nodes[0]);
+ dojo.forEach(nodes, function(node){
+ newP.appendChild(node);
+ });
+ }
+
+ var currentNodeIndex = 0;
+ var nodesInLine = [];
+ var currentNode;
+ while(currentNodeIndex < el.childNodes.length){
+ currentNode = el.childNodes[currentNodeIndex];
+ if( (currentNode.nodeName!='BR') &&
+ (currentNode.nodeType==1) &&
+ (dojo.style(currentNode, "display")!="block")
+ ){
+ nodesInLine.push(currentNode);
+ }else{
+ // hit line delimiter; process nodesInLine if there are any
+ var nextCurrentNode = currentNode.nextSibling;
+ if(nodesInLine.length){
+ wrapNodes(nodesInLine);
+ currentNodeIndex = (currentNodeIndex+1)-nodesInLine.length;
+ if(currentNode.nodeName=="BR"){
+ dojo._destroyElement(currentNode);
+ }
+ }
+ nodesInLine = [];
+ }
+ currentNodeIndex++;
+ }
+ if(nodesInLine.length){ wrapNodes(nodesInLine); }
+ }
+
+ function splitP(el){
+ // split a paragraph into seperate paragraphs at BRs
+ var currentNode = null;
+ var trailingNodes = [];
+ var lastNodeIndex = el.childNodes.length-1;
+ for(var i=lastNodeIndex; i>=0; i--){
+ currentNode = el.childNodes[i];
+ if(currentNode.nodeName=="BR"){
+ var newP = currentNode.ownerDocument.createElement('p');
+ dojo.place(newP, el, "after");
+ if (trailingNodes.length==0 && i != lastNodeIndex) {
+ newP.innerHTML = "&nbsp;"
+ }
+ dojo.forEach(trailingNodes, function(node){
+ newP.appendChild(node);
+ });
+ dojo._destroyElement(currentNode);
+ trailingNodes = [];
+ }else{
+ trailingNodes.unshift(currentNode);
+ }
+ }
+ }
+
+ var pList = [];
+ var ps = element.getElementsByTagName('p');
+ dojo.forEach(ps, function(p){ pList.push(p); });
+ dojo.forEach(pList, function(p){
+ if( (p.previousSibling) &&
+ (p.previousSibling.nodeName == 'P' || dojo.style(p.previousSibling, 'display') != 'block')
+ ){
+ var newP = p.parentNode.insertBefore(this.document.createElement('p'), p);
+ // this is essential to prevent IE from losing the P.
+ // if it's going to be innerHTML'd later we need
+ // to add the &nbsp; to _really_ force the issue
+ newP.innerHTML = noWhiteSpaceInEmptyP ? "" : "&nbsp;";
+ }
+ splitP(p);
+ },this.editor);
+ wrapLinesInPs(element);
+ return element;
+ },
+
+ singleLinePsToRegularPs: function(element){
+ function getParagraphParents(node){
+ var ps = node.getElementsByTagName('p');
+ var parents = [];
+ for(var i=0; i<ps.length; i++){
+ var p = ps[i];
+ var knownParent = false;
+ for(var k=0; k < parents.length; k++){
+ if(parents[k] === p.parentNode){
+ knownParent = true;
+ break;
+ }
+ }
+ if(!knownParent){
+ parents.push(p.parentNode);
+ }
+ }
+ return parents;
+ }
+
+ function isParagraphDelimiter(node){
+ if(node.nodeType != 1 || node.tagName != 'P'){
+ return dojo.style(node, 'display') == 'block';
+ }else{
+ if(!node.childNodes.length || node.innerHTML=="&nbsp;"){ return true; }
+ //return node.innerHTML.match(/^(<br\ ?\/?>| |\&nbsp\;)$/i);
+ }
+ return false;
+ }
+
+ var paragraphContainers = getParagraphParents(element);
+ for(var i=0; i<paragraphContainers.length; i++){
+ var container = paragraphContainers[i];
+ var firstPInBlock = null;
+ var node = container.firstChild;
+ var deleteNode = null;
+ while(node){
+ if(node.nodeType != "1" || node.tagName != 'P'){
+ firstPInBlock = null;
+ }else if (isParagraphDelimiter(node)){
+ deleteNode = node;
+ firstPInBlock = null;
+ }else{
+ if(firstPInBlock == null){
+ firstPInBlock = node;
+ }else{
+ if( (!firstPInBlock.lastChild || firstPInBlock.lastChild.nodeName != 'BR') &&
+ (node.firstChild) &&
+ (node.firstChild.nodeName != 'BR')
+ ){
+ firstPInBlock.appendChild(this.editor.document.createElement('br'));
+ }
+ while(node.firstChild){
+ firstPInBlock.appendChild(node.firstChild);
+ }
+ deleteNode = node;
+ }
+ }
+ node = node.nextSibling;
+ if(deleteNode){
+ dojo._destroyElement(deleteNode);
+ deleteNode = null;
+ }
+ }
+ }
+ return element;
+ }
+});
+
+}
diff --git a/includes/js/dijit/_editor/plugins/FontChoice.js b/includes/js/dijit/_editor/plugins/FontChoice.js
new file mode 100644
index 0000000..642237b
--- /dev/null
+++ b/includes/js/dijit/_editor/plugins/FontChoice.js
@@ -0,0 +1,167 @@
+if(!dojo._hasResource["dijit._editor.plugins.FontChoice"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit._editor.plugins.FontChoice"] = true;
+dojo.provide("dijit._editor.plugins.FontChoice");
+
+dojo.require("dijit._editor._Plugin");
+dojo.require("dijit.form.FilteringSelect");
+dojo.require("dojo.data.ItemFileReadStore");
+dojo.require("dojo.i18n");
+
+dojo.requireLocalization("dijit._editor", "FontChoice", null, "zh,pt,da,tr,ru,de,sv,ja,he,ROOT,fi,nb,el,ar,pt-pt,cs,fr,es,ko,nl,zh-tw,pl,it,hu");
+
+dojo.declare("dijit._editor.plugins.FontChoice",
+ dijit._editor._Plugin,
+ {
+ // summary:
+ // This plugin provides three dropdowns for setting font information in the editor
+ //
+ // description:
+ // The commands provided by this plugin are:
+ //
+ // * fontName
+ // | Provides a dropdown to select from a list of generic font names
+ // * fontSize
+ // | Provides a dropdown to select from a list of pre-defined font sizes
+ // * formatBlock
+ // | Provides a dropdown to select from a list of styles
+ // |
+ //
+ // which can easily be added to an editor by including one or more of the above commands
+ // in the `plugins` attribute as follows:
+ //
+ // | plugins="['fontName','fontSize',...]"
+ //
+ // It is possible to override the default dropdown list by providing an Array for the `custom` property when
+ // instantiating this plugin, e.g.
+ //
+ // | plugins="[{name:'dijit._editor.plugins.FontChoice', command:'fontName', custom:['Verdana','Myriad','Garamond']},...]"
+ //
+ // Alternatively, for `fontName` only, `generic:true` may be specified to provide a dropdown with
+ // [CSS generic font families](http://www.w3.org/TR/REC-CSS2/fonts.html#generic-font-families)
+ //
+ // Note that the editor is often unable to properly handle font styling information defined outside
+ // the context of the current editor instance, such as pre-populated HTML.
+
+ _uniqueId: 0,
+
+ buttonClass: dijit.form.FilteringSelect,
+
+ _initButton: function(){
+ //TODO: would be nice to be able to handle comma-separated font lists and search within them
+ var cmd = this.command;
+ var names = this.custom ||
+ {
+ fontName: this.generic ? ["serif", "sans-serif", "monospace", "cursive", "fantasy"] : // CSS font-family generics
+ ["Arial", "Times New Roman", "Comic Sans MS", "Courier New"],
+ fontSize: [1,2,3,4,5,6,7], // sizes according to the old HTML FONT SIZE
+ formatBlock: ["p", "h1", "h2", "h3", "pre"]
+ }[cmd];
+ var strings = dojo.i18n.getLocalization("dijit._editor", "FontChoice");
+ var items = dojo.map(names, function(value){
+ var name = strings[value] || value;
+ var label = name;
+ switch(cmd){
+ case "fontName":
+ label = "<div style='font-family: "+value+"'>" + name + "</div>";
+ break;
+ case "fontSize":
+ // we're stuck using the deprecated FONT tag to correspond with the size measurements used by the editor
+ label = "<font size="+value+"'>"+name+"</font>";
+ break;
+ case "formatBlock":
+ label = "<" + value + ">" + name + "</" + value + ">";
+ }
+ return { label: label, name: name, value: value };
+ });
+ items.push({label: "", name:"", value:""}); // FilteringSelect doesn't like unmatched blank strings
+
+ dijit._editor.plugins.FontChoice.superclass._initButton.apply(this,
+ [{ labelType: "html", labelAttr: "label", searchAttr: "name", store: new dojo.data.ItemFileReadStore(
+ { data: { identifier: "value", items: items } })}]);
+
+ this.button.setValue("");
+
+ this.connect(this.button, "onChange", function(choice){
+ if(this.updating){ return; }
+ // FIXME: IE is really messed up here!!
+ if(dojo.isIE && "_savedSelection" in this){
+ var b = this._savedSelection;
+ delete this._savedSelection;
+ this.editor.focus();
+ this.editor._moveToBookmark(b);
+ }else{
+// this.editor.focus();
+ dijit.focus(this._focusHandle);
+ }
+ if(this.command == "fontName" && choice.indexOf(" ") != -1){ choice = "'" + choice + "'"; }
+ this.editor.execCommand(this.editor._normalizeCommand(this.command), choice);
+ });
+ },
+
+ updateState: function(){
+ this.inherited(arguments);
+ var _e = this.editor;
+ var _c = this.command;
+ if(!_e || !_e.isLoaded || !_c.length){ return; }
+ if(this.button){
+ var value = _e.queryCommandValue(this.editor._normalizeCommand(_c)) || "";
+ // strip off single quotes, if any
+ var quoted = dojo.isString(value) && value.match(/'([^']*)'/);
+ if(quoted){ value = quoted[1]; }
+//console.log("selected " + value);
+ if(this.generic && _c == "fontName"){
+ var map = {
+ "Arial": "sans-serif",
+ "Helvetica": "sans-serif",
+ "Myriad": "sans-serif",
+ "Times": "serif",
+ "Times New Roman": "serif",
+ "Comic Sans MS": "cursive",
+ "Apple Chancery": "cursive",
+ "Courier": "monospace",
+ "Courier New": "monospace",
+ "Papyrus": "fantasy"
+// ,"????": "fantasy" TODO: IE doesn't map fantasy font-family?
+ };
+//console.log("mapped to " + map[value]);
+ value = map[value] || value;
+ }else if(_c == "fontSize" && value.indexOf && value.indexOf("px") != -1){
+ var pixels = parseInt(value);
+ value = {10:1, 13:2, 16:3, 18:4, 24:5, 32:6, 48:7}[pixels] || value;
+ }
+ this.updating = true;
+ this.button.setValue(value);
+ delete this.updating;
+ }
+
+ // FIXME: IE is *really* b0rken
+ if(dojo.isIE){
+ this._savedSelection = this.editor._getBookmark();
+ }
+ this._focusHandle = dijit.getFocus(this.editor.iframe);
+ },
+
+ setToolbar: function(){
+ this.inherited(arguments);
+
+ var forRef = this.button;
+ if(!forRef.id){ forRef.id = dijit._scopeName+"EditorButton-"+this.command+(this._uniqueId++); } //TODO: is this necessary? FilteringSelects always seem to have an id?
+ var label = dojo.doc.createElement("label");
+ dojo.addClass(label, "dijit dijitReset dijitLeft dijitInline");
+ label.setAttribute("for", forRef.id);
+ var strings = dojo.i18n.getLocalization("dijit._editor", "FontChoice");
+ label.appendChild(dojo.doc.createTextNode(strings[this.command]));
+ dojo.place(label, this.button.domNode, "before");
+ }
+ }
+);
+
+dojo.subscribe(dijit._scopeName + ".Editor.getPlugin",null,function(o){
+ if(o.plugin){ return; }
+ switch(o.args.name){
+ case "fontName": case "fontSize": case "formatBlock":
+ o.plugin = new dijit._editor.plugins.FontChoice({command: o.args.name});
+ }
+});
+
+}
diff --git a/includes/js/dijit/_editor/plugins/LinkDialog.js b/includes/js/dijit/_editor/plugins/LinkDialog.js
new file mode 100644
index 0000000..9015058
--- /dev/null
+++ b/includes/js/dijit/_editor/plugins/LinkDialog.js
@@ -0,0 +1,147 @@
+if(!dojo._hasResource["dijit._editor.plugins.LinkDialog"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit._editor.plugins.LinkDialog"] = true;
+dojo.provide("dijit._editor.plugins.LinkDialog");
+
+dojo.require("dijit._Widget");
+dojo.require("dijit._Templated");
+dojo.require("dijit._editor._Plugin");
+dojo.require("dijit.Dialog");
+dojo.require("dijit.form.Button");
+dojo.require("dijit.form.ValidationTextBox");
+dojo.require("dojo.i18n");
+dojo.require("dojo.string");
+dojo.requireLocalization("dijit._editor", "LinkDialog", null, "zh,pt,da,tr,ru,de,ROOT,sv,ja,he,fi,nb,el,ar,pt-pt,cs,fr,es,ko,nl,zh-tw,pl,it,hu");
+
+dojo.declare("dijit._editor.plugins.LinkDialog",
+ dijit._editor._Plugin,
+ {
+ // summary:
+ // This plugin provides dialogs for inserting links and images into the editor
+ //
+ // description:
+ // The commands provided by this plugin are:
+ // * createLink
+ // * insertImage
+
+ buttonClass: dijit.form.DropDownButton,
+ useDefaultCommand: false,
+ urlRegExp: "((https?|ftps?)\\://|)(([0-9a-zA-Z]([-0-9a-zA-Z]{0,61}[0-9a-zA-Z])?\\.)+(arpa|aero|biz|com|coop|edu|gov|info|int|mil|museum|name|net|org|pro|travel|xxx|jobs|mobi|post|ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cu|cv|cx|cy|cz|de|dj|dk|dm|do|dz|ec|ee|eg|er|eu|es|et|fi|fj|fk|fm|fo|fr|ga|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sk|sl|sm|sn|sr|st|su|sv|sy|sz|tc|td|tf|tg|th|tj|tk|tm|tn|to|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|yu|za|zm|zw)|(((\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])|(0[xX]0*[\\da-fA-F]?[\\da-fA-F]\\.){3}0[xX]0*[\\da-fA-F]?[\\da-fA-F]|(0+[0-3][0-7][0-7]\\.){3}0+[0-3][0-7][0-7]|(0|[1-9]\\d{0,8}|[1-3]\\d{9}|4[01]\\d{8}|42[0-8]\\d{7}|429[0-3]\\d{6}|4294[0-8]\\d{5}|42949[0-5]\\d{4}|429496[0-6]\\d{3}|4294967[01]\\d{2}|42949672[0-8]\\d|429496729[0-5])|0[xX]0*[\\da-fA-F]{1,8}|([\\da-fA-F]{1,4}\\:){7}[\\da-fA-F]{1,4}|([\\da-fA-F]{1,4}\\:){6}((\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])))(\\:(0|[1-9]\\d*))?(/([^?#\\s/]+/)*)?([^?#\\s/]+(\\?[^?#\\s/]*)?(#[A-Za-z][\\w.:-]*)?)?",
+ linkDialogTemplate: [
+ "<table><tr><td>",
+ "<label for='${id}_urlInput'>${url}</label>",
+ "</td><td>",
+ "<input dojoType='dijit.form.ValidationTextBox' regExp='${urlRegExp}' required='true' id='${id}_urlInput' name='urlInput'>",
+ "</td></tr><tr><td>",
+ "<label for='${id}_textInput'>${text}</label>",
+ "</td><td>",
+ "<input dojoType='dijit.form.ValidationTextBox' required='true' id='${id}_textInput' name='textInput'>",
+ "</td></tr><tr><td colspan='2'>",
+ "<button dojoType='dijit.form.Button' type='submit'>${set}</button>",
+ "</td></tr></table>"
+ ].join(""),
+
+ _initButton: function(){
+ var _this = this;
+ this.tag = this.command == 'insertImage' ? 'img' : 'a';
+ var messages = dojo.i18n.getLocalization("dijit._editor", "LinkDialog", this.lang);
+ var dropDown = (this.dropDown = new dijit.TooltipDialog({
+ title: messages[this.command + "Title"],
+ execute: dojo.hitch(this, "setValue"),
+ onOpen: function(){
+ _this._onOpenDialog();
+ dijit.TooltipDialog.prototype.onOpen.apply(this, arguments);
+ },
+ onCancel: function(){
+ setTimeout(dojo.hitch(_this, "_onCloseDialog"),0);
+ },
+ onClose: dojo.hitch(this, "_onCloseDialog")
+ }));
+ messages.urlRegExp = this.urlRegExp;
+ messages.id = dijit.getUniqueId(this.editor.id);
+ this._setContent(dropDown.title + "<div style='border-bottom: 1px black solid;padding-bottom:2pt;margin-bottom:4pt'></div>" + dojo.string.substitute(this.linkDialogTemplate, messages));
+ dropDown.startup();
+
+ this.inherited(arguments);
+ },
+
+ _setContent: function(staticPanel){
+ this.dropDown.setContent(staticPanel);
+ },
+
+ setValue: function(args){
+ // summary: callback from the dialog when user hits "set" button
+ //TODO: prevent closing popup if the text is empty
+ this._onCloseDialog();
+ if(dojo.isIE){ //see #4151
+ var a = dojo.withGlobal(this.editor.window, "getAncestorElement", dijit._editor.selection, [this.tag]);
+ if(a){
+ dojo.withGlobal(this.editor.window, "selectElement", dijit._editor.selection, [a]);
+ }
+ }
+ args.tag = this.tag;
+ args.refAttr = this.tag == 'img' ? 'src' : 'href';
+ //TODO: textInput should be formatted by escapeXml
+ var template = "<${tag} ${refAttr}='${urlInput}' _djrealurl='${urlInput}'" +
+ (args.tag == 'img' ? " alt='${textInput}'>" : ">${textInput}") +
+ "</${tag}>";
+ this.editor.execCommand('inserthtml', dojo.string.substitute(template, args));
+ },
+
+ _onCloseDialog: function(){
+ // FIXME: IE is really messed up here!!
+ if(dojo.isIE){
+ if("_savedSelection" in this){
+ var b = this._savedSelection;
+ delete this._savedSelection;
+ this.editor.focus();
+ this.editor._moveToBookmark(b);
+ }
+ }else{
+ this.editor.focus();
+ }
+ },
+
+ _onOpenDialog: function(){
+ var a = dojo.withGlobal(this.editor.window, "getAncestorElement", dijit._editor.selection, [this.tag]);
+ var url, text;
+ if(a){
+ url = a.getAttribute('_djrealurl');
+ text = this.tag == 'img' ? a.getAttribute('alt') : a.textContent || a.innerText;
+ dojo.withGlobal(this.editor.window, "selectElement", dijit._editor.selection, [a, true]);
+ }else{
+ text = dojo.withGlobal(this.editor.window, dijit._editor.selection.getSelectedText);
+ }
+ // FIXME: IE is *really* b0rken
+ if(dojo.isIE){
+ this._savedSelection = this.editor._getBookmark();
+ }
+ this.dropDown.reset();
+ this.dropDown.setValues({urlInput: url || '', textInput: text || ''});
+ //dijit.focus(this.urlInput);
+ }/*,
+
+//TODO we don't show this state anymore
+ updateState: function(){
+ // summary: change shading on button if we are over a link (or not)
+
+ var _e = this.editor;
+ if(!_e || !_e.isLoaded){ return; }
+ if(this.button){
+ // display button differently if there is an existing link associated with the current selection
+ var hasA = dojo.withGlobal(this.editor.window, "hasAncestorElement", dijit._editor.selection, [this.tag]);
+ this.button.setAttribute('checked', hasA);
+ }
+ }
+*/
+ }
+);
+
+dojo.subscribe(dijit._scopeName + ".Editor.getPlugin",null,function(o){
+ if(o.plugin){ return; }
+ switch(o.args.name){
+ case "createLink": case "insertImage":
+ o.plugin = new dijit._editor.plugins.LinkDialog({command: o.args.name});
+ }
+});
+
+}
diff --git a/includes/js/dijit/_editor/plugins/TextColor.js b/includes/js/dijit/_editor/plugins/TextColor.js
new file mode 100644
index 0000000..fef3911
--- /dev/null
+++ b/includes/js/dijit/_editor/plugins/TextColor.js
@@ -0,0 +1,40 @@
+if(!dojo._hasResource["dijit._editor.plugins.TextColor"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit._editor.plugins.TextColor"] = true;
+dojo.provide("dijit._editor.plugins.TextColor");
+
+dojo.require("dijit._editor._Plugin");
+dojo.require("dijit.ColorPalette");
+
+dojo.declare("dijit._editor.plugins.TextColor",
+ dijit._editor._Plugin,
+ {
+ // summary:
+ // This plugin provides dropdown color pickers for setting text color and background color
+ //
+ // description:
+ // The commands provided by this plugin are:
+ // * foreColor - sets the text color
+ // * hiliteColor - sets the background color
+
+ buttonClass: dijit.form.DropDownButton,
+
+//TODO: set initial focus/selection state?
+
+ constructor: function(){
+ this.dropDown = new dijit.ColorPalette();
+ this.connect(this.dropDown, "onChange", function(color){
+ this.editor.execCommand(this.command, color);
+ });
+ }
+ }
+);
+
+dojo.subscribe(dijit._scopeName + ".Editor.getPlugin",null,function(o){
+ if(o.plugin){ return; }
+ switch(o.args.name){
+ case "foreColor": case "hiliteColor":
+ o.plugin = new dijit._editor.plugins.TextColor({command: o.args.name});
+ }
+});
+
+}
diff --git a/includes/js/dijit/_editor/plugins/ToggleDir.js b/includes/js/dijit/_editor/plugins/ToggleDir.js
new file mode 100644
index 0000000..7aaae70
--- /dev/null
+++ b/includes/js/dijit/_editor/plugins/ToggleDir.js
@@ -0,0 +1,40 @@
+if(!dojo._hasResource["dijit._editor.plugins.ToggleDir"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit._editor.plugins.ToggleDir"] = true;
+dojo.provide("dijit._editor.plugins.ToggleDir");
+dojo.experimental("dijit._editor.plugins.ToggleDir");
+
+dojo.require("dijit._editor._Plugin");
+
+dojo.declare("dijit._editor.plugins.ToggleDir",
+ dijit._editor._Plugin,
+ {
+ //summary: This plugin is used to toggle direction of the edited document only,
+ // no matter what direction the whole page is.
+
+ useDefaultCommand: false,
+ command: "toggleDir",
+
+ _initButton: function(){
+ this.inherited("_initButton", arguments);
+ this.connect(this.button, "onClick", this._toggleDir);
+ },
+
+ updateState: function(){},//overwrite
+
+ _toggleDir: function(){
+ var editDoc = this.editor.editorObject.contentWindow.document.documentElement;
+ var isLtr = dojo.getComputedStyle(editDoc).direction == "ltr";
+ editDoc.dir/*html node*/ = isLtr ? "rtl" : "ltr";
+ }
+ }
+);
+
+dojo.subscribe(dijit._scopeName + ".Editor.getPlugin",null,function(o){
+ if(o.plugin){ return; }
+ switch(o.args.name){
+ case "toggleDir":
+ o.plugin = new dijit._editor.plugins.ToggleDir({command: o.args.name});
+ }
+});
+
+}
diff --git a/includes/js/dijit/_editor/range.js b/includes/js/dijit/_editor/range.js
new file mode 100644
index 0000000..cd84b60
--- /dev/null
+++ b/includes/js/dijit/_editor/range.js
@@ -0,0 +1,570 @@
+if(!dojo._hasResource["dijit._editor.range"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit._editor.range"] = true;
+dojo.provide("dijit._editor.range");
+
+dijit.range={};
+
+dijit.range.getIndex=function(/*DomNode*/node, /*DomNode*/parent){
+// dojo.profile.start("dijit.range.getIndex");
+ var ret=[], retR=[];
+ var stop = parent;
+ var onode = node;
+
+ var pnode, n;
+ while(node != stop){
+ var i = 0;
+ pnode = node.parentNode;
+ while((n=pnode.childNodes[i++])){
+ if(n===node){
+ --i;
+ break;
+ }
+ }
+ if(i>=pnode.childNodes.length){
+ dojo.debug("Error finding index of a node in dijit.range.getIndex");
+ }
+ ret.unshift(i);
+ retR.unshift(i-pnode.childNodes.length);
+ node = pnode;
+ }
+
+ //normalized() can not be called so often to prevent
+ //invalidating selection/range, so we have to detect
+ //here that any text nodes in a row
+ if(ret.length>0 && onode.nodeType==3){
+ n = onode.previousSibling;
+ while(n && n.nodeType==3){
+ ret[ret.length-1]--;
+ n = n.previousSibling;
+ }
+ n = onode.nextSibling;
+ while(n && n.nodeType==3){
+ retR[retR.length-1]++;
+ n = n.nextSibling;
+ }
+ }
+// dojo.profile.end("dijit.range.getIndex");
+ return {o: ret, r:retR};
+}
+
+dijit.range.getNode = function(/*Array*/index, /*DomNode*/parent){
+ if(!dojo.isArray(index) || index.length==0){
+ return parent;
+ }
+ var node = parent;
+// if(!node)debugger
+ dojo.every(index, function(i){
+ if(i>=0&&i< node.childNodes.length){
+ node = node.childNodes[i];
+ }else{
+ node = null;
+ console.debug('Error: can not find node with index',index,'under parent node',parent );
+ return false; //terminate dojo.every
+ }
+ return true; //carry on the every loop
+ });
+
+ return node;
+}
+
+dijit.range.getCommonAncestor = function(n1,n2,root){
+ var getAncestors = function(n,root){
+ var as=[];
+ while(n){
+ as.unshift(n);
+ if(n!=root && n.tagName!='BODY'){
+ n = n.parentNode;
+ }else{
+ break;
+ }
+ }
+ return as;
+ };
+ var n1as = getAncestors(n1,root);
+ var n2as = getAncestors(n2,root);
+
+ var m = Math.min(n1as.length,n2as.length);
+ var com = n1as[0]; //at least, one element should be in the array: the root (BODY by default)
+ for(var i=1;i<m;i++){
+ if(n1as[i]===n2as[i]){
+ com = n1as[i]
+ }else{
+ break;
+ }
+ }
+ return com;
+}
+
+dijit.range.getAncestor = function(/*DomNode*/node, /*RegEx?*/regex, /*DomNode?*/root){
+ root = root || node.ownerDocument.body;
+ while(node && node !== root){
+ var name = node.nodeName.toUpperCase() ;
+ if(regex.test(name)){
+ return node;
+ }
+
+ node = node.parentNode;
+ }
+ return null;
+}
+
+dijit.range.BlockTagNames = /^(?:P|DIV|H1|H2|H3|H4|H5|H6|ADDRESS|PRE|OL|UL|LI|DT|DE)$/;
+dijit.range.getBlockAncestor = function(/*DomNode*/node, /*RegEx?*/regex, /*DomNode?*/root){
+ root = root || node.ownerDocument.body;
+ regex = regex || dijit.range.BlockTagNames;
+ var block=null, blockContainer;
+ while(node && node !== root){
+ var name = node.nodeName.toUpperCase() ;
+ if(!block && regex.test(name)){
+ block = node;
+ }
+ if(!blockContainer && (/^(?:BODY|TD|TH|CAPTION)$/).test(name)){
+ blockContainer = node;
+ }
+
+ node = node.parentNode;
+ }
+ return {blockNode:block, blockContainer:blockContainer || node.ownerDocument.body};
+}
+
+dijit.range.atBeginningOfContainer = function(/*DomNode*/container, /*DomNode*/node, /*Int*/offset){
+ var atBeginning = false;
+ var offsetAtBeginning = (offset == 0);
+ if(!offsetAtBeginning && node.nodeType==3){ //if this is a text node, check whether the left part is all space
+ if(dojo.trim(node.nodeValue.substr(0,offset))==0){
+ offsetAtBeginning = true;
+ }
+ }
+ if(offsetAtBeginning){
+ var cnode = node;
+ atBeginning = true;
+ while(cnode && cnode !== container){
+ if(cnode.previousSibling){
+ atBeginning = false;
+ break;
+ }
+ cnode = cnode.parentNode;
+ }
+ }
+ return atBeginning;
+}
+
+dijit.range.atEndOfContainer = function(/*DomNode*/container, /*DomNode*/node, /*Int*/offset){
+ var atEnd = false;
+ var offsetAtEnd = (offset == (node.length || node.childNodes.length));
+ if(!offsetAtEnd && node.nodeType==3){ //if this is a text node, check whether the right part is all space
+ if(dojo.trim(node.nodeValue.substr(offset))==0){
+ offsetAtEnd = true;
+ }
+ }
+ if(offsetAtEnd){
+ var cnode = node;
+ atEnd = true;
+ while(cnode && cnode !== container){
+ if(cnode.nextSibling){
+ atEnd = false;
+ break;
+ }
+ cnode = cnode.parentNode;
+ }
+ }
+ return atEnd;
+}
+
+dijit.range.adjacentNoneTextNode=function(startnode, next){
+ var node = startnode;
+ var len = (0-startnode.length) || 0;
+ var prop = next?'nextSibling':'previousSibling';
+ while(node){
+ if(node.nodeType!=3){
+ break;
+ }
+ len += node.length
+ node = node[prop];
+ }
+ return [node,len];
+}
+
+dijit.range._w3c = Boolean(window['getSelection']);
+dijit.range.create = function(){
+ if(dijit.range._w3c){
+ return dojo.doc.createRange();
+ }else{//IE
+ return new dijit.range.W3CRange;
+ }
+}
+
+dijit.range.getSelection = function(win, /*Boolean?*/ignoreUpdate){
+ if(dijit.range._w3c){
+ return win.getSelection();
+ }else{//IE
+ var id=win.__W3CRange,s;
+ if(!id || !dijit.range.ie.cachedSelection[id]){
+ s = new dijit.range.ie.selection(win);
+ //use win as the key in an object is not reliable, which
+ //can leads to quite odd behaviors. thus we generate a
+ //string and use it as a key in the cache
+ id=(new Date).getTime();
+ while(id in dijit.range.ie.cachedSelection){
+ id=id+1;
+ }
+ id=String(id);
+ dijit.range.ie.cachedSelection[id] = s;
+ }else{
+ s = dijit.range.ie.cachedSelection[id];
+ }
+ if(!ignoreUpdate){
+ s._getCurrentSelection();
+ }
+ return s;
+ }
+}
+
+if(!dijit.range._w3c){
+ dijit.range.ie={
+ cachedSelection: {},
+ selection: function(win){
+ this._ranges = [];
+ this.addRange = function(r, /*boolean*/internal){
+ this._ranges.push(r);
+ if(!internal){
+ r._select();
+ }
+ this.rangeCount = this._ranges.length;
+ };
+ this.removeAllRanges = function(){
+ //don't detach, the range may be used later
+// for(var i=0;i<this._ranges.length;i++){
+// this._ranges[i].detach();
+// }
+ this._ranges = [];
+ this.rangeCount = 0;
+ };
+ var _initCurrentRange = function(){
+ var r = win.document.selection.createRange();
+ var type=win.document.selection.type.toUpperCase();
+ if(type == "CONTROL"){
+ //TODO: multiple range selection(?)
+ return new dijit.range.W3CRange(dijit.range.ie.decomposeControlRange(r));
+ }else{
+ return new dijit.range.W3CRange(dijit.range.ie.decomposeTextRange(r));
+ }
+ };
+ this.getRangeAt = function(i){
+ return this._ranges[i];
+ };
+ this._getCurrentSelection = function(){
+ this.removeAllRanges();
+ var r=_initCurrentRange();
+ if(r){
+ this.addRange(r, true);
+ }
+ };
+ },
+ decomposeControlRange: function(range){
+ var firstnode = range.item(0), lastnode = range.item(range.length-1)
+ var startContainer = firstnode.parentNode, endContainer = lastnode.parentNode;
+ var startOffset = dijit.range.getIndex(firstnode, startContainer).o;
+ var endOffset = dijit.range.getIndex(lastnode, endContainer).o+1;
+ return [[startContainer, startOffset],[endContainer, endOffset]];
+ },
+ getEndPoint: function(range, end){
+ var atmrange = range.duplicate();
+ atmrange.collapse(!end);
+ var cmpstr = 'EndTo' + (end?'End':'Start');
+ var parentNode = atmrange.parentElement();
+
+ var startnode, startOffset, lastNode;
+ if(parentNode.childNodes.length>0){
+ dojo.every(parentNode.childNodes, function(node,i){
+ var calOffset;
+ if(node.nodeType != 3){
+ atmrange.moveToElementText(node);
+
+ if(atmrange.compareEndPoints(cmpstr,range) > 0){
+ startnode = node.previousSibling;
+ if(lastNode && lastNode.nodeType == 3){
+ //where share we put the start? in the text node or after?
+ startnode = lastNode;
+ calOffset = true;
+ }else{
+ startnode = parentNode;
+ startOffset = i;
+ return false;
+ }
+ }else{
+ if(i==parentNode.childNodes.length-1){
+ startnode = parentNode;
+ startOffset = parentNode.childNodes.length;
+ return false;
+ }
+ }
+ }else{
+ if(i==parentNode.childNodes.length-1){//at the end of this node
+ startnode = node;
+ calOffset = true;
+ }
+ }
+ // try{
+ if(calOffset && startnode){
+ var prevnode = dijit.range.adjacentNoneTextNode(startnode)[0];
+ if(prevnode){
+ startnode = prevnode.nextSibling;
+ }else{
+ startnode = parentNode.firstChild; //firstChild must be a text node
+ }
+ var prevnodeobj = dijit.range.adjacentNoneTextNode(startnode);
+ prevnode = prevnodeobj[0];
+ var lenoffset = prevnodeobj[1];
+ if(prevnode){
+ atmrange.moveToElementText(prevnode);
+ atmrange.collapse(false);
+ }else{
+ atmrange.moveToElementText(parentNode);
+ }
+ atmrange.setEndPoint(cmpstr, range);
+ startOffset = atmrange.text.length-lenoffset;
+
+ return false;
+ }
+ // }catch(e){ debugger }
+ lastNode = node;
+ return true;
+ });
+ }else{
+ startnode = parentNode;
+ startOffset = 0;
+ }
+
+ //if at the end of startnode and we are dealing with start container, then
+ //move the startnode to nextSibling if it is a text node
+ //TODO: do this for end container?
+ if(!end && startnode.nodeType!=3 && startOffset == startnode.childNodes.length){
+ if(startnode.nextSibling && startnode.nextSibling.nodeType==3){
+ startnode = startnode.nextSibling;
+ startOffset = 0;
+ }
+ }
+ return [startnode, startOffset];
+ },
+ setEndPoint: function(range, container, offset){
+ //text node
+ var atmrange = range.duplicate(), node, len;
+ if(container.nodeType!=3){ //normal node
+ atmrange.moveToElementText(container);
+ atmrange.collapse(true);
+ if(offset == container.childNodes.length){
+ if(offset > 0){
+ //a simple atmrange.collapse(false); won't work here:
+ //although moveToElementText(node) is supposed to encompass the content of the node,
+ //but when collapse to end, it is in fact after the ending tag of node (collapse to start
+ //is after the begining tag of node as expected)
+ node = container.lastChild;
+ len = 0;
+ while(node && node.nodeType == 3){
+ len += node.length;
+ container = node; //pass through
+ node = node.previousSibling;
+ }
+ if(node){
+ atmrange.moveToElementText(node);
+ }
+ atmrange.collapse(false);
+ offset = len; //pass through
+ }else{ //no childNodes
+ atmrange.moveToElementText(container);
+ atmrange.collapse(true);
+ }
+ }else{
+ if(offset > 0){
+ node = container.childNodes[offset-1];
+ if(node.nodeType==3){
+ container = node;
+ offset = node.length;
+ //pass through
+ }else{
+ atmrange.moveToElementText(node);
+ atmrange.collapse(false);
+ }
+ }
+ }
+ }
+ if(container.nodeType==3){
+ var prevnodeobj = dijit.range.adjacentNoneTextNode(container);
+ var prevnode = prevnodeobj[0];
+ len = prevnodeobj[1];
+ if(prevnode){
+ atmrange.moveToElementText(prevnode);
+ atmrange.collapse(false);
+ //if contentEditable is not inherit, the above collapse won't make the end point
+ //in the correctly position: it always has a -1 offset, so compensate it
+ if(prevnode.contentEditable!='inherit'){
+ len++;
+ }
+ }else{
+ atmrange.moveToElementText(container.parentNode);
+ atmrange.collapse(true);
+ }
+
+ offset += len;
+ if(offset>0){
+ if(atmrange.moveEnd('character',offset) != offset){
+ alert('Error when moving!');
+ }
+ atmrange.collapse(false);
+ }
+ }
+
+ return atmrange;
+ },
+ decomposeTextRange: function(range){
+ var tmpary = dijit.range.ie.getEndPoint(range);
+ var startContainter = tmpary[0], startOffset = tmpary[1];
+ var endContainter = tmpary[0], endOffset = tmpary[1];
+
+ if(range.htmlText.length){
+ if(range.htmlText == range.text){ //in the same text node
+ endOffset = startOffset+range.text.length;
+ }else{
+ tmpary = dijit.range.ie.getEndPoint(range,true);
+ endContainter = tmpary[0], endOffset = tmpary[1];
+ }
+ }
+ return [[startContainter, startOffset],[endContainter, endOffset], range.parentElement()];
+ },
+ setRange: function(range, startContainter,
+ startOffset, endContainter, endOffset, check){
+ var startrange = dijit.range.ie.setEndPoint(range, startContainter, startOffset);
+ range.setEndPoint('StartToStart', startrange);
+ if(!this.collapsed){
+ var endrange = dijit.range.ie.setEndPoint(range, endContainter, endOffset);
+ range.setEndPoint('EndToEnd', endrange);
+ }
+
+ return range;
+ }
+ }
+
+dojo.declare("dijit.range.W3CRange",null, {
+ constructor: function(){
+ if(arguments.length>0){
+ this.setStart(arguments[0][0][0],arguments[0][0][1]);
+ this.setEnd(arguments[0][1][0],arguments[0][1][1],arguments[0][2]);
+ }else{
+ this.commonAncestorContainer = null;
+ this.startContainer = null;
+ this.startOffset = 0;
+ this.endContainer = null;
+ this.endOffset = 0;
+ this.collapsed = true;
+ }
+ },
+ _simpleSetEndPoint: function(node, range, end){
+ var r = (this._body||node.ownerDocument.body).createTextRange();
+ if(node.nodeType!=1){
+ r.moveToElementText(node.parentNode);
+ }else{
+ r.moveToElementText(node);
+ }
+ r.collapse(true);
+ range.setEndPoint(end?'EndToEnd':'StartToStart',r);
+ },
+ _updateInternal: function(__internal_common){
+ if(this.startContainer !== this.endContainer){
+ if(!__internal_common){
+ var r = (this._body||this.startContainer.ownerDocument.body).createTextRange();
+ this._simpleSetEndPoint(this.startContainer,r);
+ this._simpleSetEndPoint(this.endContainer,r,true);
+ __internal_common = r.parentElement();
+ }
+ this.commonAncestorContainer = dijit.range.getCommonAncestor(this.startContainer, this.endContainer, __internal_common);
+ }else{
+ this.commonAncestorContainer = this.startContainer;
+ }
+ this.collapsed = (this.startContainer === this.endContainer) && (this.startOffset == this.endOffset);
+ },
+ setStart: function(node, offset, __internal_common){
+ offset=parseInt(offset);
+ if(this.startContainer === node && this.startOffset == offset){
+ return;
+ }
+ delete this._cachedBookmark;
+
+ this.startContainer = node;
+ this.startOffset = offset;
+ if(!this.endContainer){
+ this.setEnd(node, offset, __internal_common);
+ }else{
+ this._updateInternal(__internal_common);
+ }
+ },
+ setEnd: function(node, offset, __internal_common){
+ offset=parseInt(offset);
+ if(this.endContainer === node && this.endOffset == offset){
+ return;
+ }
+ delete this._cachedBookmark;
+
+ this.endContainer = node;
+ this.endOffset = offset;
+ if(!this.startContainer){
+ this.setStart(node, offset, __internal_common);
+ }else{
+ this._updateInternal(__internal_common);
+ }
+ },
+ setStartAfter: function(node, offset){
+ this._setPoint('setStart', node, offset, 1);
+ },
+ setStartBefore: function(node, offset){
+ this._setPoint('setStart', node, offset, 0);
+ },
+ setEndAfter: function(node, offset){
+ this._setPoint('setEnd', node, offset, 1);
+ },
+ setEndBefore: function(node, offset){
+ this._setPoint('setEnd', node, offset, 0);
+ },
+ _setPoint: function(what, node, offset, ext){
+ var index = dijit.range.getIndex(node, node.parentNode).o;
+ this[what](node.parentNode, index.pop()+ext);
+ },
+ _getIERange: function(){
+ var r=(this._body||this.endContainer.ownerDocument.body).createTextRange();
+ dijit.range.ie.setRange(r, this.startContainer, this.startOffset, this.endContainer, this.endOffset);
+ return r;
+ },
+ getBookmark: function(body){
+ this._getIERange();
+ return this._cachedBookmark;
+ },
+ _select: function(){
+ var r = this._getIERange();
+ r.select();
+ },
+ deleteContents: function(){
+ var r = this._getIERange();
+ r.pasteHTML('');
+ this.endContainer = this.startContainer;
+ this.endOffset = this.startOffset;
+ this.collapsed = true;
+ },
+ cloneRange: function(){
+ var r = new dijit.range.W3CRange([[this.startContainer,this.startOffset],
+ [this.endContainer,this.endOffset]]);
+ r._body = this._body;
+ return r;
+ },
+ detach: function(){
+ this._body = null;
+ this.commonAncestorContainer = null;
+ this.startContainer = null;
+ this.startOffset = 0;
+ this.endContainer = null;
+ this.endOffset = 0;
+ this.collapsed = true;
+}
+});
+} //if(!dijit.range._w3c)
+
+}
diff --git a/includes/js/dijit/_editor/selection.js b/includes/js/dijit/_editor/selection.js
new file mode 100644
index 0000000..9b403aa
--- /dev/null
+++ b/includes/js/dijit/_editor/selection.js
@@ -0,0 +1,246 @@
+if(!dojo._hasResource["dijit._editor.selection"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit._editor.selection"] = true;
+dojo.provide("dijit._editor.selection");
+
+// FIXME:
+// all of these methods branch internally for IE. This is probably
+// sub-optimal in terms of runtime performance. We should investigate the
+// size difference for differentiating at definition time.
+
+dojo.mixin(dijit._editor.selection, {
+ getType: function(){
+ // summary: Get the selection type (like dojo.doc.select.type in IE).
+ if(dojo.doc.selection){ //IE
+ return dojo.doc.selection.type.toLowerCase();
+ }else{
+ var stype = "text";
+
+ // Check if the actual selection is a CONTROL (IMG, TABLE, HR, etc...).
+ var oSel;
+ try{
+ oSel = dojo.global.getSelection();
+ }catch(e){ /*squelch*/ }
+
+ if(oSel && oSel.rangeCount==1){
+ var oRange = oSel.getRangeAt(0);
+ if( (oRange.startContainer == oRange.endContainer) &&
+ ((oRange.endOffset - oRange.startOffset) == 1) &&
+ (oRange.startContainer.nodeType != 3 /* text node*/)
+ ){
+ stype = "control";
+ }
+ }
+ return stype;
+ }
+ },
+
+ getSelectedText: function(){
+ // summary:
+ // Return the text (no html tags) included in the current selection or null if no text is selected
+ if(dojo.doc.selection){ //IE
+ if(dijit._editor.selection.getType() == 'control'){
+ return null;
+ }
+ return dojo.doc.selection.createRange().text;
+ }else{
+ var selection = dojo.global.getSelection();
+ if(selection){
+ return selection.toString();
+ }
+ }
+ return ''
+ },
+
+ getSelectedHtml: function(){
+ // summary:
+ // Return the html of the current selection or null if unavailable
+ if(dojo.doc.selection){ //IE
+ if(dijit._editor.selection.getType() == 'control'){
+ return null;
+ }
+ return dojo.doc.selection.createRange().htmlText;
+ }else{
+ var selection = dojo.global.getSelection();
+ if(selection && selection.rangeCount){
+ var frag = selection.getRangeAt(0).cloneContents();
+ var div = dojo.doc.createElement("div");
+ div.appendChild(frag);
+ return div.innerHTML;
+ }
+ return null;
+ }
+ },
+
+ getSelectedElement: function(){
+ // summary:
+ // Retrieves the selected element (if any), just in the case that
+ // a single element (object like and image or a table) is
+ // selected.
+ if(this.getType() == "control"){
+ if(dojo.doc.selection){ //IE
+ var range = dojo.doc.selection.createRange();
+ if(range && range.item){
+ return dojo.doc.selection.createRange().item(0);
+ }
+ }else{
+ var selection = dojo.global.getSelection();
+ return selection.anchorNode.childNodes[ selection.anchorOffset ];
+ }
+ }
+ return null;
+ },
+
+ getParentElement: function(){
+ // summary:
+ // Get the parent element of the current selection
+ if(this.getType() == "control"){
+ var p = this.getSelectedElement();
+ if(p){ return p.parentNode; }
+ }else{
+ if(dojo.doc.selection){ //IE
+ return dojo.doc.selection.createRange().parentElement();
+ }else{
+ var selection = dojo.global.getSelection();
+ if(selection){
+ var node = selection.anchorNode;
+
+ while(node && (node.nodeType != 1)){ // not an element
+ node = node.parentNode;
+ }
+
+ return node;
+ }
+ }
+ }
+ return null;
+ },
+
+ hasAncestorElement: function(/*String*/tagName /* ... */){
+ // summary:
+ // Check whether current selection has a parent element which is
+ // of type tagName (or one of the other specified tagName)
+ return this.getAncestorElement.apply(this, arguments) != null;
+ },
+
+ getAncestorElement: function(/*String*/tagName /* ... */){
+ // summary:
+ // Return the parent element of the current selection which is of
+ // type tagName (or one of the other specified tagName)
+
+ var node = this.getSelectedElement() || this.getParentElement();
+ return this.getParentOfType(node, arguments);
+ },
+
+ isTag: function(/*DomNode*/node, /*Array*/tags){
+ if(node && node.tagName){
+ var _nlc = node.tagName.toLowerCase();
+ for(var i=0; i<tags.length; i++){
+ var _tlc = String(tags[i]).toLowerCase();
+ if(_nlc == _tlc){
+ return _tlc;
+ }
+ }
+ }
+ return "";
+ },
+
+ getParentOfType: function(/*DomNode*/node, /*Array*/tags){
+ while(node){
+ if(this.isTag(node, tags).length){
+ return node;
+ }
+ node = node.parentNode;
+ }
+ return null;
+ },
+
+ collapse: function(/*Boolean*/beginning) {
+ // summary: clear current selection
+ if(window['getSelection']){
+ var selection = dojo.global.getSelection();
+ if(selection.removeAllRanges){ // Mozilla
+ if(beginning){
+ selection.collapseToStart();
+ }else{
+ selection.collapseToEnd();
+ }
+ }else{ // Safari
+ // pulled from WebCore/ecma/kjs_window.cpp, line 2536
+ selection.collapse(beginning);
+ }
+ }else if(dojo.doc.selection){ // IE
+ var range = dojo.doc.selection.createRange();
+ range.collapse(beginning);
+ range.select();
+ }
+ },
+
+ remove: function(){
+ // summary: delete current selection
+ var _s = dojo.doc.selection;
+ if(_s){ //IE
+ if(_s.type.toLowerCase() != "none"){
+ _s.clear();
+ }
+ return _s;
+ }else{
+ _s = dojo.global.getSelection();
+ _s.deleteFromDocument();
+ return _s;
+ }
+ },
+
+ selectElementChildren: function(/*DomNode*/element,/*Boolean?*/nochangefocus){
+ // summary:
+ // clear previous selection and select the content of the node
+ // (excluding the node itself)
+ var _window = dojo.global;
+ var _document = dojo.doc;
+ element = dojo.byId(element);
+ if(_document.selection && dojo.body().createTextRange){ // IE
+ var range = element.ownerDocument.body.createTextRange();
+ range.moveToElementText(element);
+ if(!nochangefocus){
+ try{
+ range.select(); // IE throws an exception here if the widget is hidden. See #5439
+ }catch(e){ /* squelch */}
+ }
+ }else if(_window.getSelection){
+ var selection = _window.getSelection();
+ if(selection.setBaseAndExtent){ // Safari
+ selection.setBaseAndExtent(element, 0, element, element.innerText.length - 1);
+ }else if(selection.selectAllChildren){ // Mozilla
+ selection.selectAllChildren(element);
+ }
+ }
+ },
+
+ selectElement: function(/*DomNode*/element,/*Boolean?*/nochangefocus){
+ // summary:
+ // clear previous selection and select element (including all its children)
+ var range, _document = dojo.doc;
+ element = dojo.byId(element);
+ if(_document.selection && dojo.body().createTextRange){ // IE
+ try{
+ range = dojo.body().createControlRange();
+ range.addElement(element);
+ if(!nochangefocus){
+ range.select();
+ }
+ }catch(e){
+ this.selectElementChildren(element,nochangefocus);
+ }
+ }else if(dojo.global.getSelection){
+ var selection = dojo.global.getSelection();
+ // FIXME: does this work on Safari?
+ if(selection.removeAllRanges){ // Mozilla
+ range = _document.createRange();
+ range.selectNode(element);
+ selection.removeAllRanges();
+ selection.addRange(range);
+ }
+ }
+ }
+});
+
+}