diff options
author | Andrew Dolgov <[email protected]> | 2011-11-08 20:40:44 +0400 |
---|---|---|
committer | Andrew Dolgov <[email protected]> | 2011-11-08 20:40:44 +0400 |
commit | 81bea17aefb26859f825b9293c7c99192874806e (patch) | |
tree | fb244408ca271affa2899adb634788802c9a89d8 /lib/dijit/_editor | |
parent | 870a70e109ac9e80a88047044530de53d0404ec7 (diff) |
upgrade Dojo to 1.6.1
Diffstat (limited to 'lib/dijit/_editor')
74 files changed, 6688 insertions, 3664 deletions
diff --git a/lib/dijit/_editor/RichText.js b/lib/dijit/_editor/RichText.js index 696715986..978371557 100644 --- a/lib/dijit/_editor/RichText.js +++ b/lib/dijit/_editor/RichText.js @@ -1,1046 +1,2096 @@ /* - Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved. + Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved. Available via Academic Free License >= 2.1 OR the modified BSD license. see: http://dojotoolkit.org/license for details */ -if(!dojo._hasResource["dijit._editor.RichText"]){ -dojo._hasResource["dijit._editor.RichText"]=true; +if(!dojo._hasResource["dijit._editor.RichText"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dijit._editor.RichText"] = true; dojo.provide("dijit._editor.RichText"); dojo.require("dijit._Widget"); dojo.require("dijit._CssStateMixin"); dojo.require("dijit._editor.selection"); dojo.require("dijit._editor.range"); dojo.require("dijit._editor.html"); -if(!dojo.config["useXDomain"]||dojo.config["allowXdRichTextSave"]){ -if(dojo._postLoad){ -(function(){ -var _1=dojo.doc.createElement("textarea"); -_1.id=dijit._scopeName+"._editor.RichText.savedContent"; -dojo.style(_1,{display:"none",position:"absolute",top:"-100px",height:"3px",width:"3px"}); -dojo.body().appendChild(_1); -})(); -}else{ -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,dijit._CssStateMixin],{constructor:function(_2){ -this.contentPreFilters=[]; -this.contentPostFilters=[]; -this.contentDomPreFilters=[]; -this.contentDomPostFilters=[]; -this.editingAreaStyleSheets=[]; -this.events=[].concat(this.events); -this._keyHandlers={}; -this.contentPreFilters.push(dojo.hitch(this,"_preFixUrlAttributes")); -if(dojo.isMoz){ -this.contentPreFilters.push(this._normalizeFontStyle); -this.contentPostFilters.push(this._removeMozBogus); -} -if(dojo.isWebKit){ -this.contentPreFilters.push(this._removeWebkitBogus); -this.contentPostFilters.push(this._removeWebkitBogus); -} -if(dojo.isIE){ -this.contentPostFilters.push(this._normalizeFontStyle); -} -if(_2&&dojo.isString(_2.value)){ -this.value=_2.value; -} -this.onLoadDeferred=new dojo.Deferred(); -},baseClass:"dijitEditor",inheritWidth:false,focusOnLoad:false,name:"",styleSheets:"",_content:"",height:"300px",minHeight:"1em",isClosed:true,isLoaded:false,_SEPARATOR:"@@**%%__RICHTEXTBOUNDRY__%%**@@",onLoadDeferred:null,isTabIndent:false,disableSpellCheck:false,postCreate:function(){ -if("textarea"==this.domNode.tagName.toLowerCase()){ -console.warn("RichText should not be used with the TEXTAREA tag. See dijit._editor.RichText docs."); -} -this.inherited(arguments); -dojo.publish(dijit._scopeName+"._editor.RichText::init",[this]); -this.open(); -this.setupDefaultShortcuts(); -},setupDefaultShortcuts:function(){ -var _3=dojo.hitch(this,function(_4,_5){ -return function(){ -return !this.execCommand(_4,_5); -}; -}); -var _6={b:_3("bold"),i:_3("italic"),u:_3("underline"),a:_3("selectall"),s:function(){ -this.save(true); -},m:function(){ -this.isTabIndent=!this.isTabIndent; -},"1":_3("formatblock","h1"),"2":_3("formatblock","h2"),"3":_3("formatblock","h3"),"4":_3("formatblock","h4"),"\\":_3("insertunorderedlist")}; -if(!dojo.isIE){ -_6.Z=_3("redo"); -} -for(var _7 in _6){ -this.addKeyHandler(_7,true,false,_6[_7]); -} -},events:["onKeyPress","onKeyDown","onKeyUp","onClick"],captureEvents:[],_editorCommandsLocalized:false,_localizeEditorCommands:function(){ -if(this._editorCommandsLocalized){ -return; -} -this._editorCommandsLocalized=true; -var _8=["div","p","pre","h1","h2","h3","h4","h5","h6","ol","ul","address"]; -var _9="",_a,i=0; -while((_a=_8[i++])){ -if(_a.charAt(1)!="l"){ -_9+="<"+_a+"><span>content</span></"+_a+"><br/>"; -}else{ -_9+="<"+_a+"><li>content</li></"+_a+"><br/>"; -} -} -var _b=dojo.doc.createElement("div"); -dojo.style(_b,{position:"absolute",top:"-2000px"}); -dojo.doc.body.appendChild(_b); -_b.innerHTML=_9; -var _c=_b.firstChild; -while(_c){ -dijit._editor.selection.selectElement(_c.firstChild); -dojo.withGlobal(this.window,"selectElement",dijit._editor.selection,[_c.firstChild]); -var _d=_c.tagName.toLowerCase(); -this._local2NativeFormatNames[_d]=document.queryCommandValue("formatblock"); -this._native2LocalFormatNames[this._local2NativeFormatNames[_d]]=_d; -_c=_c.nextSibling.nextSibling; -} -dojo.body().removeChild(_b); -},open:function(_e){ -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&&_e.nodeName){ -this.domNode=_e; -} -var dn=this.domNode; -var _f; -if(dojo.isString(this.value)){ -_f=this.value; -delete this.value; -dn.innerHTML=""; -}else{ -if(dn.nodeName&&dn.nodeName.toLowerCase()=="textarea"){ -var ta=(this.textarea=dn); -this.name=ta.name; -_f=ta.value; -dn=this.domNode=dojo.doc.createElement("div"); -dn.setAttribute("widgetId",this.id); -ta.removeAttribute("widgetId"); -dn.cssText=ta.cssText; -dn.className+=" "+ta.className; -dojo.place(dn,ta,"before"); -var _10=dojo.hitch(this,function(){ -dojo.style(ta,{display:"block",position:"absolute",top:"-1000px"}); -if(dojo.isIE){ -var s=ta.style; -this.__overflow=s.overflow; -s.overflow="hidden"; -} -}); -if(dojo.isIE){ -setTimeout(_10,10); -}else{ -_10(); -} -if(ta.form){ -dojo.connect(ta.form,"onsubmit",this,function(){ -ta.value=this.getValue(); -}); -} -}else{ -_f=dijit._editor.getChildrenHtml(dn); -dn.innerHTML=""; -} -} -var _11=dojo.contentBox(dn); -this._oldHeight=_11.h; -this._oldWidth=_11.w; -this.savedContent=_f; -if(dn.nodeName&&dn.nodeName=="LI"){ -dn.innerHTML=" <br>"; -} -this.header=dn.ownerDocument.createElement("div"); -dn.appendChild(this.header); -this.editingArea=dn.ownerDocument.createElement("div"); -dn.appendChild(this.editingArea); -this.footer=dn.ownerDocument.createElement("div"); -dn.appendChild(this.footer); -if(this.name!==""&&(!dojo.config["useXDomain"]||dojo.config["allowXdRichTextSave"])){ -var _12=dojo.byId(dijit._scopeName+"._editor.RichText.savedContent"); -if(_12.value!==""){ -var _13=_12.value.split(this._SEPARATOR),i=0,dat; -while((dat=_13[i++])){ -var _14=dat.split(":"); -if(_14[0]==this.name){ -_f=_14[1]; -_13.splice(i,1); -break; -} -} -} -dojo.addOnUnload(dojo.hitch(this,"_saveContent")); -} -this.isClosed=false; -var ifr=(this.editorObject=this.iframe=dojo.doc.createElement("iframe")); -ifr.id=this.id+"_iframe"; -this._iframeSrc=this._getIframeDocTxt(); -ifr.style.border="none"; -ifr.style.width="100%"; -if(this._layoutMode){ -ifr.style.height="100%"; -}else{ -if(dojo.isIE>=7){ -if(this.height){ -ifr.style.height=this.height; -} -if(this.minHeight){ -ifr.style.minHeight=this.minHeight; -} -}else{ -ifr.style.height=this.height?this.height:this.minHeight; -} -} -ifr.frameBorder=0; -ifr._loadFunc=dojo.hitch(this,function(win){ -this.window=win; -this.document=this.window.document; -if(dojo.isIE){ -this._localizeEditorCommands(); -} -this.onLoad(_f); -}); -var s="javascript:parent."+dijit._scopeName+".byId(\""+this.id+"\")._iframeSrc"; -ifr.setAttribute("src",s); -this.editingArea.appendChild(ifr); -if(dn.nodeName=="LI"){ -dn.lastChild.style.marginTop="-1.2em"; -} -dojo.addClass(this.domNode,this.baseClass); -},_local2NativeFormatNames:{},_native2LocalFormatNames:{},_getIframeDocTxt:function(){ -var _15=dojo.getComputedStyle(this.domNode); -var _16=""; -var _17=true; -if(dojo.isIE||(!this.height&&!dojo.isMoz)){ -_16="<div id='dijitEditorBody'></div>"; -_17=false; -}else{ -if(dojo.isMoz){ -this._cursorToStart=true; -_16=" "; -} -} -var _18=[_15.fontWeight,_15.fontSize,_15.fontFamily].join(" "); -var _19=_15.lineHeight; -if(_19.indexOf("px")>=0){ -_19=parseFloat(_19)/parseFloat(_15.fontSize); -}else{ -if(_19.indexOf("em")>=0){ -_19=parseFloat(_19); -}else{ -_19="normal"; -} -} -var _1a=""; -var _1b=this; -this.style.replace(/(^|;)\s*(line-|font-?)[^;]+/ig,function(_1c){ -_1c=_1c.replace(/^;/ig,"")+";"; -var s=_1c.split(":")[0]; -if(s){ -s=dojo.trim(s); -s=s.toLowerCase(); -var i; -var sC=""; -for(i=0;i<s.length;i++){ -var c=s.charAt(i); -switch(c){ -case "-": -i++; -c=s.charAt(i).toUpperCase(); -default: -sC+=c; -} -} -dojo.style(_1b.domNode,sC,""); -} -_1a+=_1c+";"; -}); -var _1d=dojo.query("label[for=\""+this.id+"\"]"); -return [this.isLeftToRight()?"<html>\n<head>\n":"<html dir='rtl'>\n<head>\n",(dojo.isMoz&&_1d.length?"<title>"+_1d[0].innerHTML+"</title>\n":""),"<meta http-equiv='Content-Type' content='text/html'>\n","<style>\n","\tbody,html {\n","\t\tbackground:transparent;\n","\t\tpadding: 1px 0 0 0;\n","\t\tmargin: -1px 0 0 0;\n",((dojo.isWebKit)?"\t\twidth: 100%;\n":""),((dojo.isWebKit)?"\t\theight: 100%;\n":""),"\t}\n","\tbody{\n","\t\ttop:0px;\n","\t\tleft:0px;\n","\t\tright:0px;\n","\t\tfont:",_18,";\n",((this.height||dojo.isOpera)?"":"\t\tposition: fixed;\n"),"\t\tmin-height:",this.minHeight,";\n","\t\tline-height:",_19,";\n","\t}\n","\tp{ margin: 1em 0; }\n",(!_17&&!this.height?"\tbody,html {overflow-y: hidden;}\n":""),"\t#dijitEditorBody{overflow-x: auto; overflow-y:"+(this.height?"auto;":"hidden;")+"}\n","\tli > ul:-moz-first-node, li > ol:-moz-first-node{ padding-top: 1.2em; }\n","\tli{ min-height:1.2em; }\n","</style>\n",this._applyEditingAreaStyleSheets(),"\n","</head>\n<body ",(_17?"id='dijitEditorBody' ":""),"onload='frameElement._loadFunc(window,document)' style='"+_1a+"'>",_16,"</body>\n</html>"].join(""); -},_applyEditingAreaStyleSheets:function(){ -var _1e=[]; -if(this.styleSheets){ -_1e=this.styleSheets.split(";"); -this.styleSheets=""; -} -_1e=_1e.concat(this.editingAreaStyleSheets); -this.editingAreaStyleSheets=[]; -var _1f="",i=0,url; -while((url=_1e[i++])){ -var _20=(new dojo._Url(dojo.global.location,url)).toString(); -this.editingAreaStyleSheets.push(_20); -_1f+="<link rel=\"stylesheet\" type=\"text/css\" href=\""+_20+"\"/>"; -} -return _1f; -},addStyleSheet:function(uri){ -var url=uri.toString(); -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){ -return; -} -this.editingAreaStyleSheets.push(url); -this.onLoadDeferred.addCallback(dojo.hitch(function(){ -if(this.document.createStyleSheet){ -this.document.createStyleSheet(url); -}else{ -var _21=this.document.getElementsByTagName("head")[0]; -var _22=this.document.createElement("link"); -_22.rel="stylesheet"; -_22.type="text/css"; -_22.href=url; -_21.appendChild(_22); -} -})); -},removeStyleSheet:function(uri){ -var url=uri.toString(); -if(url.charAt(0)=="."||(url.charAt(0)!="/"&&!uri.host)){ -url=(new dojo._Url(dojo.global.location,url)).toString(); -} -var _23=dojo.indexOf(this.editingAreaStyleSheets,url); -if(_23==-1){ -return; -} -delete this.editingAreaStyleSheets[_23]; -dojo.withGlobal(this.window,"query",dojo,["link:[href=\""+url+"\"]"]).orphan(); -},disabled:false,_mozSettingProps:{"styleWithCSS":false},_setDisabledAttr:function(_24){ -this.disabled=_24; -if(!this.isLoaded){ -return; -} -_24=!!_24; -if(dojo.isIE||dojo.isWebKit||dojo.isOpera){ -var _25=dojo.isIE&&(this.isLoaded||!this.focusOnLoad); -if(_25){ -this.editNode.unselectable="on"; -} -this.editNode.contentEditable=!_24; -if(_25){ -var _26=this; -setTimeout(function(){ -_26.editNode.unselectable="off"; -},0); -} -}else{ -try{ -this.document.designMode=(_24?"off":"on"); -} -catch(e){ -return; -} -if(!_24&&this._mozSettingProps){ -var ps=this._mozSettingProps; -for(var n in ps){ -if(ps.hasOwnProperty(n)){ -try{ -this.document.execCommand(n,false,ps[n]); -} -catch(e2){ -} -} -} -} -} -this._disabledOK=true; -},onLoad:function(_27){ -if(!this.window.__registeredWindow){ -this.window.__registeredWindow=true; -this._iframeRegHandle=dijit.registerIframe(this.iframe); -} -if(!dojo.isIE&&(this.height||dojo.isMoz)){ -this.editNode=this.document.body; -}else{ -this.editNode=this.document.body.firstChild; -var _28=this; -if(dojo.isIE){ -var _29=(this.tabStop=dojo.doc.createElement("<div tabIndex=-1>")); -this.editingArea.appendChild(_29); -this.iframe.onfocus=function(){ -_28.editNode.setActive(); -}; -} -} -this.focusNode=this.editNode; -var _2a=this.events.concat(this.captureEvents); -var ap=this.iframe?this.document:this.editNode; -dojo.forEach(_2a,function(_2b){ -this.connect(ap,_2b.toLowerCase(),_2b); -},this); -if(dojo.isIE){ -this.connect(this.document,"onmousedown","_onIEMouseDown"); -this.editNode.style.zoom=1; -}else{ -this.connect(this.document,"onmousedown",function(){ -delete this._cursorToStart; -}); -} -if(dojo.isWebKit){ -this._webkitListener=this.connect(this.document,"onmouseup","onDisplayChanged"); -} -if(dojo.isIE){ -try{ -this.document.execCommand("RespectVisibilityInDesign",true,null); -} -catch(e){ -} -} -this.isLoaded=true; -this.set("disabled",this.disabled); -var _2c=dojo.hitch(this,function(){ -this.setValue(_27); -if(this.onLoadDeferred){ -this.onLoadDeferred.callback(true); -} -this.onDisplayChanged(); -if(this.focusOnLoad){ -dojo.addOnLoad(dojo.hitch(this,function(){ -setTimeout(dojo.hitch(this,"focus"),this.updateInterval); -})); -} -this.savedContent=this.getValue(true); -}); -if(this.setValueDeferred){ -this.setValueDeferred.addCallback(_2c); -}else{ -_2c(); -} -},onKeyDown:function(e){ -if(e.keyCode===dojo.keys.TAB&&this.isTabIndent){ -dojo.stopEvent(e); -if(this.queryCommandEnabled((e.shiftKey?"outdent":"indent"))){ -this.execCommand((e.shiftKey?"outdent":"indent")); -} -} -if(dojo.isIE){ -if(e.keyCode==dojo.keys.TAB&&!this.isTabIndent){ -if(e.shiftKey&&!e.ctrlKey&&!e.altKey){ -this.iframe.focus(); -}else{ -if(!e.shiftKey&&!e.ctrlKey&&!e.altKey){ -this.tabStop.focus(); -} -} -}else{ -if(e.keyCode===dojo.keys.BACKSPACE&&this.document.selection.type==="Control"){ -dojo.stopEvent(e); -this.execCommand("delete"); -}else{ -if((65<=e.keyCode&&e.keyCode<=90)||(e.keyCode>=37&&e.keyCode<=40)){ -e.charCode=e.keyCode; -this.onKeyPress(e); -} -} -} -} -return true; -},onKeyUp:function(e){ -return; -},setDisabled:function(_2d){ -dojo.deprecated("dijit.Editor::setDisabled is deprecated","use dijit.Editor::attr(\"disabled\",boolean) instead",2); -this.set("disabled",_2d); -},_setValueAttr:function(_2e){ -this.setValue(_2e); -},_setDisableSpellCheckAttr:function(_2f){ -if(this.document){ -dojo.attr(this.document.body,"spellcheck",!_2f); -}else{ -this.onLoadDeferred.addCallback(dojo.hitch(this,function(){ -dojo.attr(this.document.body,"spellcheck",!_2f); -})); -} -this.disableSpellCheck=_2f; -},onKeyPress:function(e){ -var c=(e.keyChar&&e.keyChar.toLowerCase())||e.keyCode,_30=this._keyHandlers[c],_31=arguments; -if(_30&&!e.altKey){ -dojo.some(_30,function(h){ -if(!(h.shift^e.shiftKey)&&!(h.ctrl^(e.ctrlKey||e.metaKey))){ -if(!h.handler.apply(this,_31)){ -e.preventDefault(); -} -return true; -} -},this); -} -if(!this._onKeyHitch){ -this._onKeyHitch=dojo.hitch(this,"onKeyPressed"); -} -setTimeout(this._onKeyHitch,1); -return true; -},addKeyHandler:function(key,_32,_33,_34){ -if(!dojo.isArray(this._keyHandlers[key])){ -this._keyHandlers[key]=[]; -} -this._keyHandlers[key].push({shift:_33||false,ctrl:_32||false,handler:_34}); -},onKeyPressed:function(){ -this.onDisplayChanged(); -},onClick:function(e){ -this.onDisplayChanged(e); -},_onIEMouseDown:function(e){ -if(!this._focused&&!this.disabled){ -this.focus(); -} -},_onBlur:function(e){ -this.inherited(arguments); -var _35=this.getValue(true); -if(_35!=this.savedContent){ -this.onChange(_35); -this.savedContent=_35; -} -},_onFocus:function(e){ -if(!this.disabled){ -if(!this._disabledOK){ -this.set("disabled",false); -} -this.inherited(arguments); -} -},blur:function(){ -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(){ -if(!this.isLoaded){ -this.focusOnLoad=true; -return; -} -if(this._cursorToStart){ -delete this._cursorToStart; -if(this.editNode.childNodes){ -this.placeCursorAtStart(); -return; -} -} -if(!dojo.isIE){ -dijit.focus(this.iframe); -}else{ -if(this.editNode&&this.editNode.focus){ -this.iframe.fireEvent("onfocus",document.createEventObject()); -} -} -},updateInterval:200,_updateTimer:null,onDisplayChanged:function(e){ -if(this._updateTimer){ -clearTimeout(this._updateTimer); -} -if(!this._updateHandler){ -this._updateHandler=dojo.hitch(this,"onNormalizedDisplayChanged"); -} -this._updateTimer=setTimeout(this._updateHandler,this.updateInterval); -},onNormalizedDisplayChanged:function(){ -delete this._updateTimer; -},onChange:function(_36){ -},_normalizeCommand:function(cmd,_37){ -var _38=cmd.toLowerCase(); -if(_38=="formatblock"){ -if(dojo.isSafari&&_37===undefined){ -_38="heading"; -} -}else{ -if(_38=="hilitecolor"&&!dojo.isMoz){ -_38="backcolor"; -} -} -return _38; -},_qcaCache:{},queryCommandAvailable:function(_39){ -var ca=this._qcaCache[_39]; -if(ca!==undefined){ -return ca; -} -return (this._qcaCache[_39]=this._queryCommandAvailable(_39)); -},_queryCommandAvailable:function(_3a){ -var ie=1; -var _3b=1<<1; -var _3c=1<<2; -var _3d=1<<3; -var _3e=1<<4; -function _3f(_40){ -return {ie:Boolean(_40&ie),mozilla:Boolean(_40&_3b),webkit:Boolean(_40&_3c),webkit420:Boolean(_40&_3e),opera:Boolean(_40&_3d)}; -}; -var _41=null; -switch(_3a.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": -_41=_3f(_3b|ie|_3c|_3d); -break; -case "createlink": -case "unlink": -case "removeformat": -case "inserthorizontalrule": -case "insertimage": -case "insertorderedlist": -case "insertunorderedlist": -case "indent": -case "outdent": -case "formatblock": -case "inserthtml": -case "undo": -case "redo": -case "strikethrough": -case "tabindent": -_41=_3f(_3b|ie|_3d|_3e); -break; -case "blockdirltr": -case "blockdirrtl": -case "dirltr": -case "dirrtl": -case "inlinedirltr": -case "inlinedirrtl": -_41=_3f(ie); -break; -case "cut": -case "copy": -case "paste": -_41=_3f(ie|_3b|_3e); -break; -case "inserttable": -_41=_3f(_3b|ie); -break; -case "insertcell": -case "insertcol": -case "insertrow": -case "deletecells": -case "deletecols": -case "deleterows": -case "mergecells": -case "splitcell": -_41=_3f(ie|_3b); -break; -default: -return false; -} -return (dojo.isIE&&_41.ie)||(dojo.isMoz&&_41.mozilla)||(dojo.isWebKit&&_41.webkit)||(dojo.isWebKit>420&&_41.webkit420)||(dojo.isOpera&&_41.opera); -},execCommand:function(_42,_43){ -var _44; -this.focus(); -_42=this._normalizeCommand(_42,_43); -if(_43!==undefined){ -if(_42=="heading"){ -throw new Error("unimplemented"); -}else{ -if((_42=="formatblock")&&dojo.isIE){ -_43="<"+_43+">"; -} -} -} -var _45="_"+_42+"Impl"; -if(this[_45]){ -_44=this[_45](_43); -}else{ -_43=arguments.length>1?_43:null; -if(_43||_42!="createlink"){ -_44=this.document.execCommand(_42,false,_43); -} -} -this.onDisplayChanged(); -return _44; -},queryCommandEnabled:function(_46){ -if(this.disabled||!this._disabledOK){ -return false; -} -_46=this._normalizeCommand(_46); -if(dojo.isMoz||dojo.isWebKit){ -if(_46=="unlink"){ -return this._sCall("hasAncestorElement",["a"]); -}else{ -if(_46=="inserttable"){ -return true; -} -} -} -if(dojo.isWebKit){ -if(_46=="copy"){ -_46="cut"; -}else{ -if(_46=="paste"){ -return true; -} -} -} -var _47=dojo.isIE?this.document.selection.createRange():this.document; -try{ -return _47.queryCommandEnabled(_46); -} -catch(e){ -return false; -} -},queryCommandState:function(_48){ -if(this.disabled||!this._disabledOK){ -return false; -} -_48=this._normalizeCommand(_48); -try{ -return this.document.queryCommandState(_48); -} -catch(e){ -return false; -} -},queryCommandValue:function(_49){ -if(this.disabled||!this._disabledOK){ -return false; -} -var r; -_49=this._normalizeCommand(_49); -if(dojo.isIE&&_49=="formatblock"){ -r=this._native2LocalFormatNames[this.document.queryCommandValue(_49)]; -}else{ -if(dojo.isMoz&&_49==="hilitecolor"){ -var _4a; -try{ -_4a=this.document.queryCommandValue("styleWithCSS"); -} -catch(e){ -_4a=false; -} -this.document.execCommand("styleWithCSS",false,true); -r=this.document.queryCommandValue(_49); -this.document.execCommand("styleWithCSS",false,_4a); -}else{ -r=this.document.queryCommandValue(_49); -} -} -return r; -},_sCall:function(_4b,_4c){ -return dojo.withGlobal(this.window,_4b,dijit._editor.selection,_4c); -},placeCursorAtStart:function(){ -this.focus(); -var _4d=false; -if(dojo.isMoz){ -var _4e=this.editNode.firstChild; -while(_4e){ -if(_4e.nodeType==3){ -if(_4e.nodeValue.replace(/^\s+|\s+$/g,"").length>0){ -_4d=true; -this._sCall("selectElement",[_4e]); -break; -} -}else{ -if(_4e.nodeType==1){ -_4d=true; -var tg=_4e.tagName?_4e.tagName.toLowerCase():""; -if(/br|input|img|base|meta|area|basefont|hr|link/.test(tg)){ -this._sCall("selectElement",[_4e]); -}else{ -this._sCall("selectElementChildren",[_4e]); -} -break; -} -} -_4e=_4e.nextSibling; -} -}else{ -_4d=true; -this._sCall("selectElementChildren",[this.editNode]); -} -if(_4d){ -this._sCall("collapse",[true]); -} -},placeCursorAtEnd:function(){ -this.focus(); -var _4f=false; -if(dojo.isMoz){ -var _50=this.editNode.lastChild; -while(_50){ -if(_50.nodeType==3){ -if(_50.nodeValue.replace(/^\s+|\s+$/g,"").length>0){ -_4f=true; -this._sCall("selectElement",[_50]); -break; -} -}else{ -if(_50.nodeType==1){ -_4f=true; -if(_50.lastChild){ -this._sCall("selectElement",[_50.lastChild]); -}else{ -this._sCall("selectElement",[_50]); -} -break; -} -} -_50=_50.previousSibling; -} -}else{ -_4f=true; -this._sCall("selectElementChildren",[this.editNode]); -} -if(_4f){ -this._sCall("collapse",[false]); -} -},getValue:function(_51){ -if(this.textarea){ -if(this.isClosed||!this.isLoaded){ -return this.textarea.value; -} -} -return this._postFilterContent(null,_51); -},_getValueAttr:function(){ -return this.getValue(true); -},setValue:function(_52){ -if(!this.isLoaded){ -this.onLoadDeferred.addCallback(dojo.hitch(this,function(){ -this.setValue(_52); -})); -return; -} -this._cursorToStart=true; -if(this.textarea&&(this.isClosed||!this.isLoaded)){ -this.textarea.value=_52; -}else{ -_52=this._preFilterContent(_52); -var _53=this.isClosed?this.domNode:this.editNode; -if(!_52&&dojo.isWebKit){ -_52=" "; -} -_53.innerHTML=_52; -this._preDomFilterContent(_53); -} -this.onDisplayChanged(); -},replaceValue:function(_54){ -if(this.isClosed){ -this.setValue(_54); -}else{ -if(this.window&&this.window.getSelection&&!dojo.isMoz){ -this.setValue(_54); -}else{ -if(this.window&&this.window.getSelection){ -_54=this._preFilterContent(_54); -this.execCommand("selectall"); -if(!_54){ -this._cursorToStart=true; -_54=" "; -} -this.execCommand("inserthtml",_54); -this._preDomFilterContent(this.editNode); -}else{ -if(this.document&&this.document.selection){ -this.setValue(_54); -} -} -} -} -},_preFilterContent:function(_55){ -var ec=_55; -dojo.forEach(this.contentPreFilters,function(ef){ -if(ef){ -ec=ef(ec); -} -}); -return ec; -},_preDomFilterContent:function(dom){ -dom=dom||this.editNode; -dojo.forEach(this.contentDomPreFilters,function(ef){ -if(ef&&dojo.isFunction(ef)){ -ef(dom); -} -},this); -},_postFilterContent:function(dom,_56){ -var ec; -if(!dojo.isString(dom)){ -dom=dom||this.editNode; -if(this.contentDomPostFilters.length){ -if(_56){ -dom=dojo.clone(dom); -} -dojo.forEach(this.contentDomPostFilters,function(ef){ -dom=ef(dom); -}); -} -ec=dijit._editor.getChildrenHtml(dom); -}else{ -ec=dom; -} -if(!dojo.trim(ec.replace(/^\xA0\xA0*/,"").replace(/\xA0\xA0*$/,"")).length){ -ec=""; + + +// used to restore content when user leaves this page then comes back +// but do not try doing dojo.doc.write if we are using xd loading. +// dojo.doc.write will only work if RichText.js is included in the dojo.js +// file. If it is included in dojo.js and you want to allow rich text saving +// for back/forward actions, then set dojo.config.allowXdRichTextSave = true. +if(!dojo.config["useXDomain"] || dojo.config["allowXdRichTextSave"]){ + if(dojo._postLoad){ + (function(){ + var savetextarea = dojo.doc.createElement('textarea'); + savetextarea.id = dijit._scopeName + "._editor.RichText.value"; + dojo.style(savetextarea, { + display:'none', + position:'absolute', + top:"-100px", + height:"3px", + width:"3px" + }); + dojo.body().appendChild(savetextarea); + })(); + }else{ + //dojo.body() is not available before onLoad is fired + try{ + dojo.doc.write('<textarea id="' + dijit._scopeName + '._editor.RichText.value" ' + + 'style="display:none;position:absolute;top:-100px;left:-100px;height:3px;width:3px;overflow:hidden;"></textarea>'); + }catch(e){ } + } } -dojo.forEach(this.contentPostFilters,function(ef){ -ec=ef(ec); + +dojo.declare("dijit._editor.RichText", [dijit._Widget, dijit._CssStateMixin], { + constructor: function(params){ + // summary: + // dijit._editor.RichText is the core of dijit.Editor, which provides basic + // WYSIWYG editing features. + // + // description: + // dijit._editor.RichText is the core of dijit.Editor, which provides basic + // WYSIWYG editing features. It also encapsulates the differences + // of different js engines for various browsers. Do not use this widget + // with an HTML <TEXTAREA> tag, since the browser unescapes XML escape characters, + // like <. This can have unexpected behavior and lead to security issues + // such as scripting attacks. + // + // tags: + // private + + // contentPreFilters: Function(String)[] + // Pre content filter function register array. + // these filters will be executed before the actual + // editing area gets the html content. + this.contentPreFilters = []; + + // contentPostFilters: Function(String)[] + // post content filter function register array. + // These will be used on the resulting html + // from contentDomPostFilters. The resulting + // content is the final html (returned by getValue()). + this.contentPostFilters = []; + + // contentDomPreFilters: Function(DomNode)[] + // Pre content dom filter function register array. + // These filters are applied after the result from + // contentPreFilters are set to the editing area. + this.contentDomPreFilters = []; + + // contentDomPostFilters: Function(DomNode)[] + // Post content dom filter function register array. + // These filters are executed on the editing area dom. + // The result from these will be passed to contentPostFilters. + this.contentDomPostFilters = []; + + // editingAreaStyleSheets: dojo._URL[] + // array to store all the stylesheets applied to the editing area + this.editingAreaStyleSheets = []; + + // Make a copy of this.events before we start writing into it, otherwise we + // will modify the prototype which leads to bad things on pages w/multiple editors + this.events = [].concat(this.events); + + this._keyHandlers = {}; + + if(params && dojo.isString(params.value)){ + this.value = params.value; + } + + this.onLoadDeferred = new dojo.Deferred(); + }, + + baseClass: "dijitEditor", + + // inheritWidth: Boolean + // whether to inherit the parent's width or simply use 100% + inheritWidth: false, + + // focusOnLoad: [deprecated] Boolean + // Focus into this widget when the page is loaded + focusOnLoad: false, + + // name: String? + // Specifies the name of a (hidden) <textarea> node on the page that's used to save + // the editor content on page leave. Used to restore editor contents after navigating + // to a new page and then hitting the back button. + name: "", + + // styleSheets: [const] String + // semicolon (";") separated list of css files for the editing area + styleSheets: "", + + // height: String + // Set height to fix the editor at a specific height, with scrolling. + // By default, this is 300px. If you want to have the editor always + // resizes to accommodate the content, use AlwaysShowToolbar plugin + // and set height="". If this editor is used within a layout widget, + // set height="100%". + height: "300px", + + // minHeight: String + // The minimum height that the editor should have. + minHeight: "1em", + + // isClosed: [private] Boolean + isClosed: true, + + // isLoaded: [private] Boolean + isLoaded: false, + + // _SEPARATOR: [private] String + // Used to concat contents from multiple editors into a single string, + // so they can be saved into a single <textarea> node. See "name" attribute. + _SEPARATOR: "@@**%%__RICHTEXTBOUNDRY__%%**@@", + + // _NAME_CONTENT_SEP: [private] String + // USed to separate name from content. Just a colon isn't safe. + _NAME_CONTENT_SEP: "@@**%%:%%**@@", + + // onLoadDeferred: [readonly] dojo.Deferred + // Deferred which is fired when the editor finishes loading. + // Call myEditor.onLoadDeferred.then(callback) it to be informed + // when the rich-text area initialization is finalized. + onLoadDeferred: null, + + // isTabIndent: Boolean + // Make tab key and shift-tab indent and outdent rather than navigating. + // Caution: sing this makes web pages inaccessible to users unable to use a mouse. + isTabIndent: false, + + // disableSpellCheck: [const] Boolean + // When true, disables the browser's native spell checking, if supported. + // Works only in Firefox. + disableSpellCheck: false, + + postCreate: function(){ + if("textarea" == this.domNode.tagName.toLowerCase()){ + console.warn("RichText should not be used with the TEXTAREA tag. See dijit._editor.RichText docs."); + } + + // Push in the builtin filters now, making them the first executed, but not over-riding anything + // users passed in. See: #6062 + this.contentPreFilters = [dojo.hitch(this, "_preFixUrlAttributes")].concat(this.contentPreFilters); + if(dojo.isMoz){ + this.contentPreFilters = [this._normalizeFontStyle].concat(this.contentPreFilters); + this.contentPostFilters = [this._removeMozBogus].concat(this.contentPostFilters); + } + if(dojo.isWebKit){ + // Try to clean up WebKit bogus artifacts. The inserted classes + // made by WebKit sometimes messes things up. + this.contentPreFilters = [this._removeWebkitBogus].concat(this.contentPreFilters); + this.contentPostFilters = [this._removeWebkitBogus].concat(this.contentPostFilters); + } + if(dojo.isIE){ + // IE generates <strong> and <em> but we want to normalize to <b> and <i> + this.contentPostFilters = [this._normalizeFontStyle].concat(this.contentPostFilters); + } + this.inherited(arguments); + + dojo.publish(dijit._scopeName + "._editor.RichText::init", [this]); + this.open(); + this.setupDefaultShortcuts(); + }, + + setupDefaultShortcuts: function(){ + // summary: + // Add some default key handlers + // description: + // Overwrite this to setup your own handlers. The default + // implementation does not use Editor commands, but directly + // executes the builtin commands within the underlying browser + // support. + // tags: + // protected + var exec = dojo.hitch(this, function(cmd, arg){ + return function(){ + return !this.execCommand(cmd,arg); + }; + }); + + var ctrlKeyHandlers = { + b: exec("bold"), + i: exec("italic"), + u: exec("underline"), + a: exec("selectall"), + s: function(){ this.save(true); }, + m: function(){ this.isTabIndent = !this.isTabIndent; }, + + "1": exec("formatblock", "h1"), + "2": exec("formatblock", "h2"), + "3": exec("formatblock", "h3"), + "4": exec("formatblock", "h4"), + + "\\": exec("insertunorderedlist") + }; + + if(!dojo.isIE){ + ctrlKeyHandlers.Z = exec("redo"); //FIXME: undo? + } + + for(var key in ctrlKeyHandlers){ + this.addKeyHandler(key, true, false, ctrlKeyHandlers[key]); + } + }, + + // events: [private] String[] + // events which should be connected to the underlying editing area + events: ["onKeyPress", "onKeyDown", "onKeyUp"], // onClick handled specially + + // captureEvents: [deprecated] String[] + // Events which should be connected to the underlying editing + // area, events in this array will be addListener with + // capture=true. + // TODO: looking at the code I don't see any distinction between events and captureEvents, + // so get rid of this for 2.0 if not sooner + captureEvents: [], + + _editorCommandsLocalized: false, + _localizeEditorCommands: function(){ + // summary: + // When IE is running in a non-English locale, the API actually changes, + // so that we have to say (for example) danraku instead of p (for paragraph). + // Handle that here. + // tags: + // private + if(dijit._editor._editorCommandsLocalized){ + // Use the already generate cache of mappings. + this._local2NativeFormatNames = dijit._editor._local2NativeFormatNames; + this._native2LocalFormatNames = dijit._editor._native2LocalFormatNames; + return; + } + dijit._editor._editorCommandsLocalized = true; + dijit._editor._local2NativeFormatNames = {}; + dijit._editor._native2LocalFormatNames = {}; + this._local2NativeFormatNames = dijit._editor._local2NativeFormatNames; + this._native2LocalFormatNames = dijit._editor._native2LocalFormatNames; + //in IE, names for blockformat is locale dependent, so we cache the values here + + //put p after div, so if IE returns Normal, we show it as paragraph + //We can distinguish p and div if IE returns Normal, however, in order to detect that, + //we have to call this.document.selection.createRange().parentElement() or such, which + //could slow things down. Leave it as it is for now + var formats = ['div', 'p', 'pre', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'ol', 'ul', 'address']; + var localhtml = "", format, i=0; + while((format=formats[i++])){ + //append a <br> after each element to separate the elements more reliably + if(format.charAt(1) !== 'l'){ + localhtml += "<"+format+"><span>content</span></"+format+"><br/>"; + }else{ + localhtml += "<"+format+"><li>content</li></"+format+"><br/>"; + } + } + // queryCommandValue returns empty if we hide editNode, so move it out of screen temporary + // Also, IE9 does weird stuff unless we do it inside the editor iframe. + var style = { position: "absolute", top: "0px", zIndex: 10, opacity: 0.01 }; + var div = dojo.create('div', {style: style, innerHTML: localhtml}); + dojo.body().appendChild(div); + + // IE9 has a timing issue with doing this right after setting + // the inner HTML, so put a delay in. + var inject = dojo.hitch(this, function(){ + var node = div.firstChild; + while(node){ + try{ + dijit._editor.selection.selectElement(node.firstChild); + var nativename = node.tagName.toLowerCase(); + this._local2NativeFormatNames[nativename] = document.queryCommandValue("formatblock"); + this._native2LocalFormatNames[this._local2NativeFormatNames[nativename]] = nativename; + node = node.nextSibling.nextSibling; + //console.log("Mapped: ", nativename, " to: ", this._local2NativeFormatNames[nativename]); + }catch(e) { /*Sqelch the occasional IE9 error */ } + } + div.parentNode.removeChild(div); + div.innerHTML = ""; + }); + setTimeout(inject, 0); + }, + + open: function(/*DomNode?*/ element){ + // summary: + // Transforms the node referenced in this.domNode into a rich text editing + // node. + // description: + // Sets up the editing area asynchronously. This will result in + // the creation and replacement with an iframe. + // tags: + // private + + if(!this.onLoadDeferred || this.onLoadDeferred.fired >= 0){ + this.onLoadDeferred = new dojo.Deferred(); + } + + if(!this.isClosed){ this.close(); } + dojo.publish(dijit._scopeName + "._editor.RichText::open", [ this ]); + + if(arguments.length == 1 && element.nodeName){ // else unchanged + this.domNode = element; + } + + var dn = this.domNode; + + // "html" will hold the innerHTML of the srcNodeRef and will be used to + // initialize the editor. + var html; + + if(dojo.isString(this.value)){ + // Allow setting the editor content programmatically instead of + // relying on the initial content being contained within the target + // domNode. + html = this.value; + delete this.value; + dn.innerHTML = ""; + }else if(dn.nodeName && dn.nodeName.toLowerCase() == "textarea"){ + // if we were created from a textarea, then we need to create a + // new editing harness node. + var ta = (this.textarea = dn); + this.name = ta.name; + html = ta.value; + dn = this.domNode = dojo.doc.createElement("div"); + dn.setAttribute('widgetId', this.id); + ta.removeAttribute('widgetId'); + dn.cssText = ta.cssText; + dn.className += " " + ta.className; + dojo.place(dn, ta, "before"); + var tmpFunc = dojo.hitch(this, function(){ + //some browsers refuse to submit display=none textarea, so + //move the textarea off screen instead + dojo.style(ta, { + display: "block", + position: "absolute", + top: "-1000px" + }); + + if(dojo.isIE){ //nasty IE bug: abnormal formatting if overflow is not hidden + var s = ta.style; + this.__overflow = s.overflow; + s.overflow = "hidden"; + } + }); + if(dojo.isIE){ + setTimeout(tmpFunc, 10); + }else{ + tmpFunc(); + } + + if(ta.form){ + var resetValue = ta.value; + this.reset = function(){ + var current = this.getValue(); + if(current != resetValue){ + this.replaceValue(resetValue); + } + }; + dojo.connect(ta.form, "onsubmit", this, function(){ + // Copy value to the <textarea> so it gets submitted along with form. + // FIXME: should we be calling close() here instead? + dojo.attr(ta, 'disabled', this.disabled); // don't submit the value if disabled + ta.value = this.getValue(); + }); + } + }else{ + html = dijit._editor.getChildrenHtml(dn); + dn.innerHTML = ""; + } + + var content = dojo.contentBox(dn); + this._oldHeight = content.h; + this._oldWidth = content.w; + + this.value = html; + + // If we're a list item we have to put in a blank line to force the + // bullet to nicely align at the top of text + if(dn.nodeName && dn.nodeName == "LI"){ + dn.innerHTML = " <br>"; + } + + // Construct the editor div structure. + this.header = dn.ownerDocument.createElement("div"); + dn.appendChild(this.header); + this.editingArea = dn.ownerDocument.createElement("div"); + dn.appendChild(this.editingArea); + this.footer = dn.ownerDocument.createElement("div"); + dn.appendChild(this.footer); + + if(!this.name){ + this.name = this.id + "_AUTOGEN"; + } + + // User has pressed back/forward button so we lost the text in the editor, but it's saved + // in a hidden <textarea> (which contains the data for all the editors on this page), + // so get editor value from there + if(this.name !== "" && (!dojo.config["useXDomain"] || dojo.config["allowXdRichTextSave"])){ + var saveTextarea = dojo.byId(dijit._scopeName + "._editor.RichText.value"); + if(saveTextarea && saveTextarea.value !== ""){ + var datas = saveTextarea.value.split(this._SEPARATOR), i=0, dat; + while((dat=datas[i++])){ + var data = dat.split(this._NAME_CONTENT_SEP); + if(data[0] == this.name){ + html = data[1]; + datas = datas.splice(i, 1); + saveTextarea.value = datas.join(this._SEPARATOR); + break; + } + } + } + + if(!dijit._editor._globalSaveHandler){ + dijit._editor._globalSaveHandler = {}; + dojo.addOnUnload(function() { + var id; + for(id in dijit._editor._globalSaveHandler){ + var f = dijit._editor._globalSaveHandler[id]; + if(dojo.isFunction(f)){ + f(); + } + } + }); + } + dijit._editor._globalSaveHandler[this.id] = dojo.hitch(this, "_saveContent"); + } + + this.isClosed = false; + + var ifr = (this.editorObject = this.iframe = dojo.doc.createElement('iframe')); + ifr.id = this.id+"_iframe"; + this._iframeSrc = this._getIframeDocTxt(); + ifr.style.border = "none"; + ifr.style.width = "100%"; + if(this._layoutMode){ + // iframe should be 100% height, thus getting it's height from surrounding + // <div> (which has the correct height set by Editor) + ifr.style.height = "100%"; + }else{ + if(dojo.isIE >= 7){ + if(this.height){ + ifr.style.height = this.height; + } + if(this.minHeight){ + ifr.style.minHeight = this.minHeight; + } + }else{ + ifr.style.height = this.height ? this.height : this.minHeight; + } + } + ifr.frameBorder = 0; + ifr._loadFunc = dojo.hitch( this, function(win){ + this.window = win; + this.document = this.window.document; + + if(dojo.isIE){ + this._localizeEditorCommands(); + } + + // Do final setup and set initial contents of editor + this.onLoad(html); + }); + + // Set the iframe's initial (blank) content. + var s = 'javascript:parent.' + dijit._scopeName + '.byId("'+this.id+'")._iframeSrc'; + ifr.setAttribute('src', s); + this.editingArea.appendChild(ifr); + + if(dojo.isSafari <= 4){ + var src = ifr.getAttribute("src"); + if(!src || src.indexOf("javascript") == -1){ + // Safari 4 and earlier sometimes act oddly + // So we have to set it again. + setTimeout(function(){ifr.setAttribute('src', s);},0); + } + } + + // TODO: this is a guess at the default line-height, kinda works + if(dn.nodeName == "LI"){ + dn.lastChild.style.marginTop = "-1.2em"; + } + + dojo.addClass(this.domNode, this.baseClass); + }, + + //static cache variables shared among all instance of this class + _local2NativeFormatNames: {}, + _native2LocalFormatNames: {}, + + _getIframeDocTxt: function(){ + // summary: + // Generates the boilerplate text of the document inside the iframe (ie, <html><head>...</head><body/></html>). + // Editor content (if not blank) should be added afterwards. + // tags: + // private + var _cs = dojo.getComputedStyle(this.domNode); + + // The contents inside of <body>. The real contents are set later via a call to setValue(). + var html = ""; + var setBodyId = true; + if(dojo.isIE || dojo.isWebKit || (!this.height && !dojo.isMoz)){ + // In auto-expand mode, need a wrapper div for AlwaysShowToolbar plugin to correctly + // expand/contract the editor as the content changes. + html = "<div id='dijitEditorBody'></div>"; + setBodyId = false; + }else if(dojo.isMoz){ + // workaround bug where can't select then delete text (until user types something + // into the editor)... and/or issue where typing doesn't erase selected text + this._cursorToStart = true; + html = " "; + } + + var font = [ _cs.fontWeight, _cs.fontSize, _cs.fontFamily ].join(" "); + + // line height is tricky - applying a units value will mess things up. + // if we can't get a non-units value, bail out. + var lineHeight = _cs.lineHeight; + if(lineHeight.indexOf("px") >= 0){ + lineHeight = parseFloat(lineHeight)/parseFloat(_cs.fontSize); + // console.debug(lineHeight); + }else if(lineHeight.indexOf("em")>=0){ + lineHeight = parseFloat(lineHeight); + }else{ + // If we can't get a non-units value, just default + // it to the CSS spec default of 'normal'. Seems to + // work better, esp on IE, than '1.0' + lineHeight = "normal"; + } + var userStyle = ""; + var self = this; + this.style.replace(/(^|;)\s*(line-|font-?)[^;]+/ig, function(match){ + match = match.replace(/^;/ig,"") + ';'; + var s = match.split(":")[0]; + if(s){ + s = dojo.trim(s); + s = s.toLowerCase(); + var i; + var sC = ""; + for(i = 0; i < s.length; i++){ + var c = s.charAt(i); + switch(c){ + case "-": + i++; + c = s.charAt(i).toUpperCase(); + default: + sC += c; + } + } + dojo.style(self.domNode, sC, ""); + } + userStyle += match + ';'; + }); + + + // need to find any associated label element and update iframe document title + var label=dojo.query('label[for="'+this.id+'"]'); + + return [ + this.isLeftToRight() ? "<html>\n<head>\n" : "<html dir='rtl'>\n<head>\n", + (dojo.isMoz && label.length ? "<title>" + label[0].innerHTML + "</title>\n" : ""), + "<meta http-equiv='Content-Type' content='text/html'>\n", + "<style>\n", + "\tbody,html {\n", + "\t\tbackground:transparent;\n", + "\t\tpadding: 1px 0 0 0;\n", + "\t\tmargin: -1px 0 0 0;\n", // remove extraneous vertical scrollbar on safari and firefox + + // Set the html/body sizing. Webkit always needs this, other browsers + // only set it when height is defined (not auto-expanding), otherwise + // scrollers do not appear. + ((dojo.isWebKit)?"\t\twidth: 100%;\n":""), + ((dojo.isWebKit)?"\t\theight: 100%;\n":""), + "\t}\n", + + // TODO: left positioning will cause contents to disappear out of view + // if it gets too wide for the visible area + "\tbody{\n", + "\t\ttop:0px;\n", + "\t\tleft:0px;\n", + "\t\tright:0px;\n", + "\t\tfont:", font, ";\n", + ((this.height||dojo.isOpera) ? "" : "\t\tposition: fixed;\n"), + // FIXME: IE 6 won't understand min-height? + "\t\tmin-height:", this.minHeight, ";\n", + "\t\tline-height:", lineHeight,";\n", + "\t}\n", + "\tp{ margin: 1em 0; }\n", + + // Determine how scrollers should be applied. In autoexpand mode (height = "") no scrollers on y at all. + // But in fixed height mode we want both x/y scrollers. Also, if it's using wrapping div and in auto-expand + // (Mainly IE) we need to kill the y scroller on body and html. + (!setBodyId && !this.height ? "\tbody,html {overflow-y: hidden;}\n" : ""), + "\t#dijitEditorBody{overflow-x: auto; overflow-y:" + (this.height ? "auto;" : "hidden;") + " outline: 0px;}\n", + "\tli > ul:-moz-first-node, li > ol:-moz-first-node{ padding-top: 1.2em; }\n", + // Can't set min-height in IE9, it puts layout on li, which puts move/resize handles. + (!dojo.isIE ? "\tli{ min-height:1.2em; }\n" : ""), + "</style>\n", + this._applyEditingAreaStyleSheets(),"\n", + "</head>\n<body ", + (setBodyId?"id='dijitEditorBody' ":""), + "onload='frameElement._loadFunc(window,document)' style='"+userStyle+"'>", html, "</body>\n</html>" + ].join(""); // String + }, + + _applyEditingAreaStyleSheets: function(){ + // summary: + // apply the specified css files in styleSheets + // tags: + // private + var files = []; + if(this.styleSheets){ + files = this.styleSheets.split(';'); + this.styleSheets = ''; + } + + //empty this.editingAreaStyleSheets here, as it will be filled in addStyleSheet + files = files.concat(this.editingAreaStyleSheets); + this.editingAreaStyleSheets = []; + + var text='', i=0, url; + while((url=files[i++])){ + var abstring = (new dojo._Url(dojo.global.location, url)).toString(); + this.editingAreaStyleSheets.push(abstring); + text += '<link rel="stylesheet" type="text/css" href="'+abstring+'"/>'; + } + return text; + }, + + addStyleSheet: function(/*dojo._Url*/ uri){ + // summary: + // add an external stylesheet for the editing area + // uri: + // A dojo.uri.Uri pointing to the url of the external css file + var url=uri.toString(); + + //if uri is relative, then convert it to absolute so that it can be resolved correctly in iframe + if(url.charAt(0) == '.' || (url.charAt(0) != '/' && !uri.host)){ + url = (new dojo._Url(dojo.global.location, url)).toString(); + } + + if(dojo.indexOf(this.editingAreaStyleSheets, url) > -1){ +// console.debug("dijit._editor.RichText.addStyleSheet: Style sheet "+url+" is already applied"); + return; + } + + this.editingAreaStyleSheets.push(url); + this.onLoadDeferred.addCallback(dojo.hitch(this, function(){ + if(this.document.createStyleSheet){ //IE + this.document.createStyleSheet(url); + }else{ //other browser + var head = this.document.getElementsByTagName("head")[0]; + var stylesheet = this.document.createElement("link"); + stylesheet.rel="stylesheet"; + stylesheet.type="text/css"; + stylesheet.href=url; + head.appendChild(stylesheet); + } + })); + }, + + removeStyleSheet: function(/*dojo._Url*/ uri){ + // summary: + // remove an external stylesheet for the editing area + var url=uri.toString(); + //if uri is relative, then convert it to absolute so that it can be resolved correctly in iframe + if(url.charAt(0) == '.' || (url.charAt(0) != '/' && !uri.host)){ + url = (new dojo._Url(dojo.global.location, url)).toString(); + } + var index = dojo.indexOf(this.editingAreaStyleSheets, url); + if(index == -1){ +// console.debug("dijit._editor.RichText.removeStyleSheet: Style sheet "+url+" has not been applied"); + return; + } + delete this.editingAreaStyleSheets[index]; + dojo.withGlobal(this.window,'query', dojo, ['link:[href="'+url+'"]']).orphan(); + }, + + // disabled: Boolean + // The editor is disabled; the text cannot be changed. + disabled: false, + + _mozSettingProps: {'styleWithCSS':false}, + _setDisabledAttr: function(/*Boolean*/ value){ + value = !!value; + this._set("disabled", value); + if(!this.isLoaded){ return; } // this method requires init to be complete + if(dojo.isIE || dojo.isWebKit || dojo.isOpera){ + var preventIEfocus = dojo.isIE && (this.isLoaded || !this.focusOnLoad); + if(preventIEfocus){ this.editNode.unselectable = "on"; } + this.editNode.contentEditable = !value; + if(preventIEfocus){ + var _this = this; + setTimeout(function(){ _this.editNode.unselectable = "off"; }, 0); + } + }else{ //moz + try{ + this.document.designMode=(value?'off':'on'); + }catch(e){ return; } // ! _disabledOK + if(!value && this._mozSettingProps){ + var ps = this._mozSettingProps; + for(var n in ps){ + if(ps.hasOwnProperty(n)){ + try{ + this.document.execCommand(n,false,ps[n]); + }catch(e2){} + } + } + } +// this.document.execCommand('contentReadOnly', false, value); +// if(value){ +// this.blur(); //to remove the blinking caret +// } + } + this._disabledOK = true; + }, + +/* Event handlers + *****************/ + + onLoad: function(/*String*/ html){ + // summary: + // Handler after the iframe finishes loading. + // html: String + // Editor contents should be set to this value + // tags: + // protected + + // TODO: rename this to _onLoad, make empty public onLoad() method, deprecate/make protected onLoadDeferred handler? + + if(!this.window.__registeredWindow){ + this.window.__registeredWindow = true; + this._iframeRegHandle = dijit.registerIframe(this.iframe); + } + if(!dojo.isIE && !dojo.isWebKit && (this.height || dojo.isMoz)){ + this.editNode=this.document.body; + }else{ + // there's a wrapper div around the content, see _getIframeDocTxt(). + this.editNode=this.document.body.firstChild; + var _this = this; + if(dojo.isIE){ // #4996 IE wants to focus the BODY tag + this.tabStop = dojo.create('div', { tabIndex: -1 }, this.editingArea); + this.iframe.onfocus = function(){ _this.editNode.setActive(); }; + } + } + this.focusNode = this.editNode; // for InlineEditBox + + + var events = this.events.concat(this.captureEvents); + var ap = this.iframe ? this.document : this.editNode; + dojo.forEach(events, function(item){ + this.connect(ap, item.toLowerCase(), item); + }, this); + + this.connect(ap, "onmouseup", "onClick"); // mouseup in the margin does not generate an onclick event + + if(dojo.isIE){ // IE contentEditable + this.connect(this.document, "onmousedown", "_onIEMouseDown"); // #4996 fix focus + + // give the node Layout on IE + // TODO: this may no longer be needed, since we've reverted IE to using an iframe, + // not contentEditable. Removing it would also probably remove the need for creating + // the extra <div> in _getIframeDocTxt() + this.editNode.style.zoom = 1.0; + }else{ + this.connect(this.document, "onmousedown", function(){ + // Clear the moveToStart focus, as mouse + // down will set cursor point. Required to properly + // work with selection/position driven plugins and clicks in + // the window. refs: #10678 + delete this._cursorToStart; + }); + } + + if(dojo.isWebKit){ + //WebKit sometimes doesn't fire right on selections, so the toolbar + //doesn't update right. Therefore, help it out a bit with an additional + //listener. A mouse up will typically indicate a display change, so fire this + //and get the toolbar to adapt. Reference: #9532 + this._webkitListener = this.connect(this.document, "onmouseup", "onDisplayChanged"); + this.connect(this.document, "onmousedown", function(e){ + var t = e.target; + if(t && (t === this.document.body || t === this.document)){ + // Since WebKit uses the inner DIV, we need to check and set position. + // See: #12024 as to why the change was made. + setTimeout(dojo.hitch(this, "placeCursorAtEnd"), 0); + } + }); + } + + if(dojo.isIE){ + // Try to make sure 'hidden' elements aren't visible in edit mode (like browsers other than IE + // do). See #9103 + try{ + this.document.execCommand('RespectVisibilityInDesign', true, null); + }catch(e){/* squelch */} + } + + this.isLoaded = true; + + this.set('disabled', this.disabled); // initialize content to editable (or not) + + // Note that setValue() call will only work after isLoaded is set to true (above) + + // Set up a function to allow delaying the setValue until a callback is fired + // This ensures extensions like dijit.Editor have a way to hold the value set + // until plugins load (and do things like register filters). + var setContent = dojo.hitch(this, function(){ + this.setValue(html); + if(this.onLoadDeferred){ + this.onLoadDeferred.callback(true); + } + this.onDisplayChanged(); + if(this.focusOnLoad){ + // after the document loads, then set focus after updateInterval expires so that + // onNormalizedDisplayChanged has run to avoid input caret issues + dojo.addOnLoad(dojo.hitch(this, function(){ setTimeout(dojo.hitch(this, "focus"), this.updateInterval); })); + } + // Save off the initial content now + this.value = this.getValue(true); + }); + if(this.setValueDeferred){ + this.setValueDeferred.addCallback(setContent); + }else{ + setContent(); + } + }, + + onKeyDown: function(/* Event */ e){ + // summary: + // Handler for onkeydown event + // tags: + // protected + + // we need this event at the moment to get the events from control keys + // such as the backspace. It might be possible to add this to Dojo, so that + // keyPress events can be emulated by the keyDown and keyUp detection. + + if(e.keyCode === dojo.keys.TAB && this.isTabIndent ){ + dojo.stopEvent(e); //prevent tab from moving focus out of editor + + // FIXME: this is a poor-man's indent/outdent. It would be + // better if it added 4 " " chars in an undoable way. + // Unfortunately pasteHTML does not prove to be undoable + if(this.queryCommandEnabled((e.shiftKey ? "outdent" : "indent"))){ + this.execCommand((e.shiftKey ? "outdent" : "indent")); + } + } + if(dojo.isIE){ + if(e.keyCode == dojo.keys.TAB && !this.isTabIndent){ + if(e.shiftKey && !e.ctrlKey && !e.altKey){ + // focus the BODY so the browser will tab away from it instead + this.iframe.focus(); + }else if(!e.shiftKey && !e.ctrlKey && !e.altKey){ + // focus the BODY so the browser will tab away from it instead + this.tabStop.focus(); + } + }else if(e.keyCode === dojo.keys.BACKSPACE && this.document.selection.type === "Control"){ + // IE has a bug where if a non-text object is selected in the editor, + // hitting backspace would act as if the browser's back button was + // clicked instead of deleting the object. see #1069 + dojo.stopEvent(e); + this.execCommand("delete"); + }else if((65 <= e.keyCode && e.keyCode <= 90) || + (e.keyCode>=37 && e.keyCode<=40) // FIXME: get this from connect() instead! + ){ //arrow keys + e.charCode = e.keyCode; + this.onKeyPress(e); + } + } + return true; + }, + + onKeyUp: function(e){ + // summary: + // Handler for onkeyup event + // tags: + // callback + return; + }, + + setDisabled: function(/*Boolean*/ disabled){ + // summary: + // Deprecated, use set('disabled', ...) instead. + // tags: + // deprecated + dojo.deprecated('dijit.Editor::setDisabled is deprecated','use dijit.Editor::attr("disabled",boolean) instead', 2.0); + this.set('disabled',disabled); + }, + _setValueAttr: function(/*String*/ value){ + // summary: + // Registers that attr("value", foo) should call setValue(foo) + this.setValue(value); + }, + _setDisableSpellCheckAttr: function(/*Boolean*/ disabled){ + if(this.document){ + dojo.attr(this.document.body, "spellcheck", !disabled); + }else{ + // try again after the editor is finished loading + this.onLoadDeferred.addCallback(dojo.hitch(this, function(){ + dojo.attr(this.document.body, "spellcheck", !disabled); + })); + } + this._set("disableSpellCheck", disabled); + }, + + onKeyPress: function(e){ + // summary: + // Handle the various key events + // tags: + // protected + + var c = (e.keyChar && e.keyChar.toLowerCase()) || e.keyCode, + handlers = this._keyHandlers[c], + args = arguments; + + if(handlers && !e.altKey){ + dojo.some(handlers, function(h){ + // treat meta- same as ctrl-, for benefit of mac users + if(!(h.shift ^ e.shiftKey) && !(h.ctrl ^ (e.ctrlKey||e.metaKey))){ + if(!h.handler.apply(this, args)){ + e.preventDefault(); + } + return true; + } + }, this); + } + + // function call after the character has been inserted + if(!this._onKeyHitch){ + this._onKeyHitch = dojo.hitch(this, "onKeyPressed"); + } + setTimeout(this._onKeyHitch, 1); + return true; + }, + + addKeyHandler: function(/*String*/ key, /*Boolean*/ ctrl, /*Boolean*/ shift, /*Function*/ handler){ + // summary: + // Add a handler for a keyboard shortcut + // description: + // The key argument should be in lowercase if it is a letter character + // tags: + // protected + if(!dojo.isArray(this._keyHandlers[key])){ + this._keyHandlers[key] = []; + } + //TODO: would be nice to make this a hash instead of an array for quick lookups + this._keyHandlers[key].push({ + shift: shift || false, + ctrl: ctrl || false, + handler: handler + }); + }, + + onKeyPressed: function(){ + // summary: + // Handler for after the user has pressed a key, and the display has been updated. + // (Runs on a timer so that it runs after the display is updated) + // tags: + // private + this.onDisplayChanged(/*e*/); // can't pass in e + }, + + onClick: function(/*Event*/ e){ + // summary: + // Handler for when the user clicks. + // tags: + // private + + // console.info('onClick',this._tryDesignModeOn); + this.onDisplayChanged(e); + }, + + _onIEMouseDown: function(/*Event*/ e){ + // summary: + // IE only to prevent 2 clicks to focus + // tags: + // protected + + if(!this._focused && !this.disabled){ + this.focus(); + } + }, + + _onBlur: function(e){ + // summary: + // Called from focus manager when focus has moved away from this editor + // tags: + // protected + + // console.info('_onBlur') + + this.inherited(arguments); + + var newValue = this.getValue(true); + if(newValue != this.value){ + this.onChange(newValue); + } + this._set("value", newValue); + }, + + _onFocus: function(/*Event*/ e){ + // summary: + // Called from focus manager when focus has moved into this editor + // tags: + // protected + + // console.info('_onFocus') + if(!this.disabled){ + if(!this._disabledOK){ + this.set('disabled', false); + } + this.inherited(arguments); + } + }, + + // TODO: remove in 2.0 + blur: function(){ + // summary: + // Remove focus from this instance. + // tags: + // deprecated + if(!dojo.isIE && this.window.document.documentElement && this.window.document.documentElement.focus){ + this.window.document.documentElement.focus(); + }else if(dojo.doc.body.focus){ + dojo.doc.body.focus(); + } + }, + + focus: function(){ + // summary: + // Move focus to this editor + if(!this.isLoaded){ + this.focusOnLoad = true; + return; + } + if(this._cursorToStart){ + delete this._cursorToStart; + if(this.editNode.childNodes){ + this.placeCursorAtStart(); // this calls focus() so return + return; + } + } + if(!dojo.isIE){ + dijit.focus(this.iframe); + }else if(this.editNode && this.editNode.focus){ + // editNode may be hidden in display:none div, lets just punt in this case + //this.editNode.focus(); -> causes IE to scroll always (strict and quirks mode) to the top the Iframe + // if we fire the event manually and let the browser handle the focusing, the latest + // cursor position is focused like in FF + this.iframe.fireEvent('onfocus', document.createEventObject()); // createEventObject only in IE + // }else{ + // TODO: should we throw here? + // console.debug("Have no idea how to focus into the editor!"); + } + }, + + // _lastUpdate: 0, + updateInterval: 200, + _updateTimer: null, + onDisplayChanged: function(/*Event*/ e){ + // summary: + // This event will be fired everytime the display context + // changes and the result needs to be reflected in the UI. + // description: + // If you don't want to have update too often, + // onNormalizedDisplayChanged should be used instead + // tags: + // private + + // var _t=new Date(); + if(this._updateTimer){ + clearTimeout(this._updateTimer); + } + if(!this._updateHandler){ + this._updateHandler = dojo.hitch(this,"onNormalizedDisplayChanged"); + } + this._updateTimer = setTimeout(this._updateHandler, this.updateInterval); + + // Technically this should trigger a call to watch("value", ...) registered handlers, + // but getValue() is too slow to call on every keystroke so we don't. + }, + onNormalizedDisplayChanged: function(){ + // summary: + // This event is fired every updateInterval ms or more + // description: + // If something needs to happen immediately after a + // user change, please use onDisplayChanged instead. + // tags: + // private + delete this._updateTimer; + }, + onChange: function(newContent){ + // summary: + // This is fired if and only if the editor loses focus and + // the content is changed. + }, + _normalizeCommand: function(/*String*/ cmd, /*Anything?*/argument){ + // summary: + // Used as the advice function by dojo.connect to map our + // normalized set of commands to those supported by the target + // browser. + // tags: + // private + + var command = cmd.toLowerCase(); + if(command == "formatblock"){ + if(dojo.isSafari && argument === undefined){ command = "heading"; } + }else if(command == "hilitecolor" && !dojo.isMoz){ + command = "backcolor"; + } + + return command; + }, + + _qcaCache: {}, + queryCommandAvailable: function(/*String*/ command){ + // summary: + // Tests whether a command is supported by the host. Clients + // SHOULD check whether a command is supported before attempting + // to use it, behaviour for unsupported commands is undefined. + // command: + // The command to test for + // tags: + // private + + // memoizing version. See _queryCommandAvailable for computing version + var ca = this._qcaCache[command]; + if(ca !== undefined){ return ca; } + return (this._qcaCache[command] = this._queryCommandAvailable(command)); + }, + + _queryCommandAvailable: function(/*String*/ command){ + // summary: + // See queryCommandAvailable(). + // tags: + // private + + var ie = 1; + var mozilla = 1 << 1; + var webkit = 1 << 2; + var opera = 1 << 3; + + function isSupportedBy(browsers){ + return { + ie: Boolean(browsers & ie), + mozilla: Boolean(browsers & mozilla), + webkit: Boolean(browsers & webkit), + opera: Boolean(browsers & opera) + }; + } + + var supportedBy = null; + + switch(command.toLowerCase()){ + case "bold": case "italic": case "underline": + case "subscript": case "superscript": + case "fontname": case "fontsize": + case "forecolor": case "hilitecolor": + case "justifycenter": case "justifyfull": case "justifyleft": + case "justifyright": case "delete": case "selectall": case "toggledir": + supportedBy = isSupportedBy(mozilla | ie | webkit | opera); + break; + + case "createlink": case "unlink": case "removeformat": + case "inserthorizontalrule": case "insertimage": + case "insertorderedlist": case "insertunorderedlist": + case "indent": case "outdent": case "formatblock": + case "inserthtml": case "undo": case "redo": case "strikethrough": case "tabindent": + supportedBy = isSupportedBy(mozilla | ie | opera | webkit); + break; + + case "blockdirltr": case "blockdirrtl": + case "dirltr": case "dirrtl": + case "inlinedirltr": case "inlinedirrtl": + supportedBy = isSupportedBy(ie); + break; + case "cut": case "copy": case "paste": + supportedBy = isSupportedBy( ie | mozilla | webkit); + break; + + case "inserttable": + supportedBy = isSupportedBy(mozilla | ie); + break; + + case "insertcell": case "insertcol": case "insertrow": + case "deletecells": case "deletecols": case "deleterows": + case "mergecells": case "splitcell": + supportedBy = isSupportedBy(ie | mozilla); + break; + + default: return false; + } + + return (dojo.isIE && supportedBy.ie) || + (dojo.isMoz && supportedBy.mozilla) || + (dojo.isWebKit && supportedBy.webkit) || + (dojo.isOpera && supportedBy.opera); // Boolean return true if the command is supported, false otherwise + }, + + execCommand: function(/*String*/ command, argument){ + // summary: + // Executes a command in the Rich Text area + // command: + // The command to execute + // argument: + // An optional argument to the command + // tags: + // protected + var returnValue; + + //focus() is required for IE to work + //In addition, focus() makes sure after the execution of + //the command, the editor receives the focus as expected + this.focus(); + + command = this._normalizeCommand(command, argument); + + if(argument !== undefined){ + if(command == "heading"){ + throw new Error("unimplemented"); + }else if((command == "formatblock") && dojo.isIE){ + argument = '<'+argument+'>'; + } + } + + //Check to see if we have any over-rides for commands, they will be functions on this + //widget of the form _commandImpl. If we don't, fall through to the basic native + //exec command of the browser. + var implFunc = "_" + command + "Impl"; + if(this[implFunc]){ + returnValue = this[implFunc](argument); + }else{ + argument = arguments.length > 1 ? argument : null; + if(argument || command!="createlink"){ + returnValue = this.document.execCommand(command, false, argument); + } + } + + this.onDisplayChanged(); + return returnValue; + }, + + queryCommandEnabled: function(/*String*/ command){ + // summary: + // Check whether a command is enabled or not. + // tags: + // protected + if(this.disabled || !this._disabledOK){ return false; } + command = this._normalizeCommand(command); + if(dojo.isMoz || dojo.isWebKit){ + if(command == "unlink"){ // mozilla returns true always + // console.debug(this._sCall("hasAncestorElement", ['a'])); + return this._sCall("hasAncestorElement", ["a"]); + }else if(command == "inserttable"){ + return true; + } + } + //see #4109 + if(dojo.isWebKit){ + if(command == "cut" || command == "copy") { + // WebKit deems clipboard activity as a security threat and natively would return false + var sel = this.window.getSelection(); + if(sel){ sel = sel.toString(); } + return !!sel; + }else if(command == "paste"){ + return true; + } + } + + var elem = dojo.isIE ? this.document.selection.createRange() : this.document; + try{ + return elem.queryCommandEnabled(command); + }catch(e){ + //Squelch, occurs if editor is hidden on FF 3 (and maybe others.) + return false; + } + + }, + + queryCommandState: function(command){ + // summary: + // Check the state of a given command and returns true or false. + // tags: + // protected + + if(this.disabled || !this._disabledOK){ return false; } + command = this._normalizeCommand(command); + try{ + return this.document.queryCommandState(command); + }catch(e){ + //Squelch, occurs if editor is hidden on FF 3 (and maybe others.) + return false; + } + }, + + queryCommandValue: function(command){ + // summary: + // Check the value of a given command. This matters most for + // custom selections and complex values like font value setting. + // tags: + // protected + + if(this.disabled || !this._disabledOK){ return false; } + var r; + command = this._normalizeCommand(command); + if(dojo.isIE && command == "formatblock"){ + r = this._native2LocalFormatNames[this.document.queryCommandValue(command)]; + }else if(dojo.isMoz && command === "hilitecolor"){ + var oldValue; + try{ + oldValue = this.document.queryCommandValue("styleWithCSS"); + }catch(e){ + oldValue = false; + } + this.document.execCommand("styleWithCSS", false, true); + r = this.document.queryCommandValue(command); + this.document.execCommand("styleWithCSS", false, oldValue); + }else{ + r = this.document.queryCommandValue(command); + } + return r; + }, + + // Misc. + + _sCall: function(name, args){ + // summary: + // Run the named method of dijit._editor.selection over the + // current editor instance's window, with the passed args. + // tags: + // private + return dojo.withGlobal(this.window, name, dijit._editor.selection, args); + }, + + // FIXME: this is a TON of code duplication. Why? + + placeCursorAtStart: function(){ + // summary: + // Place the cursor at the start of the editing area. + // tags: + // private + + this.focus(); + + //see comments in placeCursorAtEnd + var isvalid=false; + if(dojo.isMoz){ + // TODO: Is this branch even necessary? + var first=this.editNode.firstChild; + while(first){ + if(first.nodeType == 3){ + if(first.nodeValue.replace(/^\s+|\s+$/g, "").length>0){ + isvalid=true; + this._sCall("selectElement", [ first ]); + break; + } + }else if(first.nodeType == 1){ + isvalid=true; + var tg = first.tagName ? first.tagName.toLowerCase() : ""; + // Collapse before childless tags. + if(/br|input|img|base|meta|area|basefont|hr|link/.test(tg)){ + this._sCall("selectElement", [ first ]); + }else{ + // Collapse inside tags with children. + this._sCall("selectElementChildren", [ first ]); + } + break; + } + first = first.nextSibling; + } + }else{ + isvalid=true; + this._sCall("selectElementChildren", [ this.editNode ]); + } + if(isvalid){ + this._sCall("collapse", [ true ]); + } + }, + + placeCursorAtEnd: function(){ + // summary: + // Place the cursor at the end of the editing area. + // tags: + // private + + this.focus(); + + //In mozilla, if last child is not a text node, we have to use + // selectElementChildren on this.editNode.lastChild otherwise the + // cursor would be placed at the end of the closing tag of + //this.editNode.lastChild + var isvalid=false; + if(dojo.isMoz){ + var last=this.editNode.lastChild; + while(last){ + if(last.nodeType == 3){ + if(last.nodeValue.replace(/^\s+|\s+$/g, "").length>0){ + isvalid=true; + this._sCall("selectElement", [ last ]); + break; + } + }else if(last.nodeType == 1){ + isvalid=true; + if(last.lastChild){ + this._sCall("selectElement", [ last.lastChild ]); + }else{ + this._sCall("selectElement", [ last ]); + } + break; + } + last = last.previousSibling; + } + }else{ + isvalid=true; + this._sCall("selectElementChildren", [ this.editNode ]); + } + if(isvalid){ + this._sCall("collapse", [ false ]); + } + }, + + getValue: function(/*Boolean?*/ nonDestructive){ + // summary: + // Return the current content of the editing area (post filters + // are applied). Users should call get('value') instead. + // nonDestructive: + // defaults to false. Should the post-filtering be run over a copy + // of the live DOM? Most users should pass "true" here unless they + // *really* know that none of the installed filters are going to + // mess up the editing session. + // tags: + // private + if(this.textarea){ + if(this.isClosed || !this.isLoaded){ + return this.textarea.value; + } + } + + return this._postFilterContent(null, nonDestructive); + }, + _getValueAttr: function(){ + // summary: + // Hook to make attr("value") work + return this.getValue(true); + }, + + setValue: function(/*String*/ html){ + // summary: + // This function sets the content. No undo history is preserved. + // Users should use set('value', ...) instead. + // tags: + // deprecated + + // TODO: remove this and getValue() for 2.0, and move code to _setValueAttr() + + if(!this.isLoaded){ + // try again after the editor is finished loading + this.onLoadDeferred.addCallback(dojo.hitch(this, function(){ + this.setValue(html); + })); + return; + } + this._cursorToStart = true; + if(this.textarea && (this.isClosed || !this.isLoaded)){ + this.textarea.value=html; + }else{ + html = this._preFilterContent(html); + var node = this.isClosed ? this.domNode : this.editNode; + if(html && dojo.isMoz && html.toLowerCase() == "<p></p>"){ + html = "<p> </p>"; + } + + // Use to avoid webkit problems where editor is disabled until the user clicks it + if(!html && dojo.isWebKit){ + html = " "; + } + node.innerHTML = html; + this._preDomFilterContent(node); + } + + this.onDisplayChanged(); + this._set("value", this.getValue(true)); + }, + + replaceValue: function(/*String*/ html){ + // summary: + // This function set the content while trying to maintain the undo stack + // (now only works fine with Moz, this is identical to setValue in all + // other browsers) + // tags: + // protected + + if(this.isClosed){ + this.setValue(html); + }else if(this.window && this.window.getSelection && !dojo.isMoz){ // Safari + // look ma! it's a totally f'd browser! + this.setValue(html); + }else if(this.window && this.window.getSelection){ // Moz + html = this._preFilterContent(html); + this.execCommand("selectall"); + if(!html){ + this._cursorToStart = true; + html = " "; + } + this.execCommand("inserthtml", html); + this._preDomFilterContent(this.editNode); + }else if(this.document && this.document.selection){//IE + //In IE, when the first element is not a text node, say + //an <a> tag, when replacing the content of the editing + //area, the <a> tag will be around all the content + //so for now, use setValue for IE too + this.setValue(html); + } + + this._set("value", this.getValue(true)); + }, + + _preFilterContent: function(/*String*/ html){ + // summary: + // Filter the input before setting the content of the editing + // area. DOM pre-filtering may happen after this + // string-based filtering takes place but as of 1.2, this is not + // guaranteed for operations such as the inserthtml command. + // tags: + // private + + var ec = html; + dojo.forEach(this.contentPreFilters, function(ef){ if(ef){ ec = ef(ec); } }); + return ec; + }, + _preDomFilterContent: function(/*DomNode*/ dom){ + // summary: + // filter the input's live DOM. All filter operations should be + // considered to be "live" and operating on the DOM that the user + // will be interacting with in their editing session. + // tags: + // private + dom = dom || this.editNode; + dojo.forEach(this.contentDomPreFilters, function(ef){ + if(ef && dojo.isFunction(ef)){ + ef(dom); + } + }, this); + }, + + _postFilterContent: function( + /*DomNode|DomNode[]|String?*/ dom, + /*Boolean?*/ nonDestructive){ + // summary: + // filter the output after getting the content of the editing area + // + // description: + // post-filtering allows plug-ins and users to specify any number + // of transforms over the editor's content, enabling many common + // use-cases such as transforming absolute to relative URLs (and + // vice-versa), ensuring conformance with a particular DTD, etc. + // The filters are registered in the contentDomPostFilters and + // contentPostFilters arrays. Each item in the + // contentDomPostFilters array is a function which takes a DOM + // Node or array of nodes as its only argument and returns the + // same. It is then passed down the chain for further filtering. + // The contentPostFilters array behaves the same way, except each + // member operates on strings. Together, the DOM and string-based + // filtering allow the full range of post-processing that should + // be necessaray to enable even the most agressive of post-editing + // conversions to take place. + // + // If nonDestructive is set to "true", the nodes are cloned before + // filtering proceeds to avoid potentially destructive transforms + // to the content which may still needed to be edited further. + // Once DOM filtering has taken place, the serialized version of + // the DOM which is passed is run through each of the + // contentPostFilters functions. + // + // dom: + // a node, set of nodes, which to filter using each of the current + // members of the contentDomPostFilters and contentPostFilters arrays. + // + // nonDestructive: + // defaults to "false". If true, ensures that filtering happens on + // a clone of the passed-in content and not the actual node + // itself. + // + // tags: + // private + + var ec; + if(!dojo.isString(dom)){ + dom = dom || this.editNode; + if(this.contentDomPostFilters.length){ + if(nonDestructive){ + dom = dojo.clone(dom); + } + dojo.forEach(this.contentDomPostFilters, function(ef){ + dom = ef(dom); + }); + } + ec = dijit._editor.getChildrenHtml(dom); + }else{ + ec = dom; + } + + if(!dojo.trim(ec.replace(/^\xA0\xA0*/, '').replace(/\xA0\xA0*$/, '')).length){ + ec = ""; + } + + // if(dojo.isIE){ + // //removing appended <P> </P> for IE + // ec = ec.replace(/(?:<p> </p>[\n\r]*)+$/i,""); + // } + dojo.forEach(this.contentPostFilters, function(ef){ + ec = ef(ec); + }); + + return ec; + }, + + _saveContent: function(/*Event*/ e){ + // summary: + // Saves the content in an onunload event if the editor has not been closed + // tags: + // private + + var saveTextarea = dojo.byId(dijit._scopeName + "._editor.RichText.value"); + if(saveTextarea.value){ + saveTextarea.value += this._SEPARATOR; + } + saveTextarea.value += this.name + this._NAME_CONTENT_SEP + this.getValue(true); + }, + + + escapeXml: function(/*String*/ str, /*Boolean*/ noSingleQuotes){ + // summary: + // Adds escape sequences for special characters in XML. + // Optionally skips escapes for single quotes + // tags: + // private + + str = str.replace(/&/gm, "&").replace(/</gm, "<").replace(/>/gm, ">").replace(/"/gm, """); + if(!noSingleQuotes){ + str = str.replace(/'/gm, "'"); + } + return str; // string + }, + + getNodeHtml: function(/* DomNode */ node){ + // summary: + // Deprecated. Use dijit._editor._getNodeHtml() instead. + // tags: + // deprecated + dojo.deprecated('dijit.Editor::getNodeHtml is deprecated','use dijit._editor.getNodeHtml instead', 2); + return dijit._editor.getNodeHtml(node); // String + }, + + getNodeChildrenHtml: function(/* DomNode */ dom){ + // summary: + // Deprecated. Use dijit._editor.getChildrenHtml() instead. + // tags: + // deprecated + dojo.deprecated('dijit.Editor::getNodeChildrenHtml is deprecated','use dijit._editor.getChildrenHtml instead', 2); + return dijit._editor.getChildrenHtml(dom); + }, + + close: function(/*Boolean?*/ save){ + // summary: + // Kills the editor and optionally writes back the modified contents to the + // element from which it originated. + // save: + // Whether or not to save the changes. If false, the changes are discarded. + // tags: + // private + + if(this.isClosed){ return; } + + if(!arguments.length){ save = true; } + if(save){ + this._set("value", this.getValue(true)); + } + + // line height is squashed for iframes + // FIXME: why was this here? if (this.iframe){ this.domNode.style.lineHeight = null; } + + if(this.interval){ clearInterval(this.interval); } + + if(this._webkitListener){ + //Cleaup of WebKit fix: #9532 + this.disconnect(this._webkitListener); + delete this._webkitListener; + } + + // Guard against memory leaks on IE (see #9268) + if(dojo.isIE){ + this.iframe.onfocus = null; + } + this.iframe._loadFunc = null; + + if(this._iframeRegHandle){ + dijit.unregisterIframe(this._iframeRegHandle); + delete this._iframeRegHandle; + } + + if(this.textarea){ + var s = this.textarea.style; + s.position = ""; + s.left = s.top = ""; + if(dojo.isIE){ + s.overflow = this.__overflow; + this.__overflow = null; + } + this.textarea.value = this.value; + dojo.destroy(this.domNode); + this.domNode = this.textarea; + }else{ + // Note that this destroys the iframe + this.domNode.innerHTML = this.value; + } + delete this.iframe; + + dojo.removeClass(this.domNode, this.baseClass); + this.isClosed = true; + this.isLoaded = false; + + delete this.editNode; + delete this.focusNode; + + if(this.window && this.window._frameElement){ + this.window._frameElement = null; + } + + this.window = null; + this.document = null; + this.editingArea = null; + this.editorObject = null; + }, + + destroy: function(){ + if(!this.isClosed){ this.close(false); } + this.inherited(arguments); + if(dijit._editor._globalSaveHandler){ + delete dijit._editor._globalSaveHandler[this.id]; + } + }, + + _removeMozBogus: function(/* String */ html){ + // summary: + // Post filter to remove unwanted HTML attributes generated by mozilla + // tags: + // private + return html.replace(/\stype="_moz"/gi, '').replace(/\s_moz_dirty=""/gi, '').replace(/_moz_resizing="(true|false)"/gi,''); // String + }, + _removeWebkitBogus: function(/* String */ html){ + // summary: + // Post filter to remove unwanted HTML attributes generated by webkit + // tags: + // private + html = html.replace(/\sclass="webkit-block-placeholder"/gi, ''); + html = html.replace(/\sclass="apple-style-span"/gi, ''); + // For some reason copy/paste sometime adds extra meta tags for charset on + // webkit (chrome) on mac.They need to be removed. See: #12007" + html = html.replace(/<meta charset=\"utf-8\" \/>/gi, ''); + return html; // String + }, + _normalizeFontStyle: function(/* String */ html){ + // summary: + // Convert 'strong' and 'em' to 'b' and 'i'. + // description: + // Moz can not handle strong/em tags correctly, so to help + // mozilla and also to normalize output, convert them to 'b' and 'i'. + // + // Note the IE generates 'strong' and 'em' rather than 'b' and 'i' + // tags: + // private + return html.replace(/<(\/)?strong([ \>])/gi, '<$1b$2') + .replace(/<(\/)?em([ \>])/gi, '<$1i$2' ); // String + }, + + _preFixUrlAttributes: function(/* String */ html){ + // summary: + // Pre-filter to do fixing to href attributes on <a> and <img> tags + // tags: + // private + return html.replace(/(?:(<a(?=\s).*?\shref=)("|')(.*?)\2)|(?:(<a\s.*?href=)([^"'][^ >]+))/gi, + '$1$4$2$3$5$2 _djrealurl=$2$3$5$2') + .replace(/(?:(<img(?=\s).*?\ssrc=)("|')(.*?)\2)|(?:(<img\s.*?src=)([^"'][^ >]+))/gi, + '$1$4$2$3$5$2 _djrealurl=$2$3$5$2'); // String + }, + + /***************************************************************************** + The following functions implement HTML manipulation commands for various + browser/contentEditable implementations. The goal of them is to enforce + standard behaviors of them. + ******************************************************************************/ + + _inserthorizontalruleImpl: function(argument){ + // summary: + // This function implements the insertion of HTML 'HR' tags. + // into a point on the page. IE doesn't to it right, so + // we have to use an alternate form + // argument: + // arguments to the exec command, if any. + // tags: + // protected + if(dojo.isIE){ + return this._inserthtmlImpl("<hr>"); + } + return this.document.execCommand("inserthorizontalrule", false, argument); + }, + + _unlinkImpl: function(argument){ + // summary: + // This function implements the unlink of an 'a' tag. + // argument: + // arguments to the exec command, if any. + // tags: + // protected + if((this.queryCommandEnabled("unlink")) && (dojo.isMoz || dojo.isWebKit)){ + var a = this._sCall("getAncestorElement", [ "a" ]); + this._sCall("selectElement", [ a ]); + return this.document.execCommand("unlink", false, null); + } + return this.document.execCommand("unlink", false, argument); + }, + + _hilitecolorImpl: function(argument){ + // summary: + // This function implements the hilitecolor command + // argument: + // arguments to the exec command, if any. + // tags: + // protected + var returnValue; + if(dojo.isMoz){ + // mozilla doesn't support hilitecolor properly when useCSS is + // set to false (bugzilla #279330) + this.document.execCommand("styleWithCSS", false, true); + returnValue = this.document.execCommand("hilitecolor", false, argument); + this.document.execCommand("styleWithCSS", false, false); + }else{ + returnValue = this.document.execCommand("hilitecolor", false, argument); + } + return returnValue; + }, + + _backcolorImpl: function(argument){ + // summary: + // This function implements the backcolor command + // argument: + // arguments to the exec command, if any. + // tags: + // protected + if(dojo.isIE){ + // Tested under IE 6 XP2, no problem here, comment out + // IE weirdly collapses ranges when we exec these commands, so prevent it + // var tr = this.document.selection.createRange(); + argument = argument ? argument : null; + } + return this.document.execCommand("backcolor", false, argument); + }, + + _forecolorImpl: function(argument){ + // summary: + // This function implements the forecolor command + // argument: + // arguments to the exec command, if any. + // tags: + // protected + if(dojo.isIE){ + // Tested under IE 6 XP2, no problem here, comment out + // IE weirdly collapses ranges when we exec these commands, so prevent it + // var tr = this.document.selection.createRange(); + argument = argument? argument : null; + } + return this.document.execCommand("forecolor", false, argument); + }, + + _inserthtmlImpl: function(argument){ + // summary: + // This function implements the insertion of HTML content into + // a point on the page. + // argument: + // The content to insert, if any. + // tags: + // protected + argument = this._preFilterContent(argument); + var rv = true; + if(dojo.isIE){ + var insertRange = this.document.selection.createRange(); + if(this.document.selection.type.toUpperCase() == 'CONTROL'){ + var n=insertRange.item(0); + while(insertRange.length){ + insertRange.remove(insertRange.item(0)); + } + n.outerHTML=argument; + }else{ + insertRange.pasteHTML(argument); + } + insertRange.select(); + //insertRange.collapse(true); + }else if(dojo.isMoz && !argument.length){ + //mozilla can not inserthtml an empty html to delete current selection + //so we delete the selection instead in this case + this._sCall("remove"); // FIXME + }else{ + rv = this.document.execCommand("inserthtml", false, argument); + } + return rv; + }, + + _boldImpl: function(argument){ + // summary: + // This function implements an over-ride of the bold command. + // argument: + // Not used, operates by selection. + // tags: + // protected + if(dojo.isIE){ + this._adaptIESelection() + } + return this.document.execCommand("bold", false, argument); + }, + + _italicImpl: function(argument){ + // summary: + // This function implements an over-ride of the italic command. + // argument: + // Not used, operates by selection. + // tags: + // protected + if(dojo.isIE){ + this._adaptIESelection() + } + return this.document.execCommand("italic", false, argument); + }, + + _underlineImpl: function(argument){ + // summary: + // This function implements an over-ride of the underline command. + // argument: + // Not used, operates by selection. + // tags: + // protected + if(dojo.isIE){ + this._adaptIESelection() + } + return this.document.execCommand("underline", false, argument); + }, + + _strikethroughImpl: function(argument){ + // summary: + // This function implements an over-ride of the strikethrough command. + // argument: + // Not used, operates by selection. + // tags: + // protected + if(dojo.isIE){ + this._adaptIESelection() + } + return this.document.execCommand("strikethrough", false, argument); + }, + + getHeaderHeight: function(){ + // summary: + // A function for obtaining the height of the header node + return this._getNodeChildrenHeight(this.header); // Number + }, + + getFooterHeight: function(){ + // summary: + // A function for obtaining the height of the footer node + return this._getNodeChildrenHeight(this.footer); // Number + }, + + _getNodeChildrenHeight: function(node){ + // summary: + // An internal function for computing the cumulative height of all child nodes of 'node' + // node: + // The node to process the children of; + var h = 0; + if(node && node.childNodes){ + // IE didn't compute it right when position was obtained on the node directly is some cases, + // so we have to walk over all the children manually. + var i; + for(i = 0; i < node.childNodes.length; i++){ + var size = dojo.position(node.childNodes[i]); + h += size.h; + } + } + return h; // Number + }, + + _isNodeEmpty: function(node, startOffset){ + // summary: + // Function to test if a node is devoid of real content. + // node: + // The node to check. + // tags: + // private. + if(node.nodeType == 1/*element*/){ + if(node.childNodes.length > 0){ + return this._isNodeEmpty(node.childNodes[0], startOffset); + } + return true; + }else if(node.nodeType == 3/*text*/){ + return (node.nodeValue.substring(startOffset) == ""); + } + return false; + }, + + _removeStartingRangeFromRange: function(node, range){ + // summary: + // Function to adjust selection range by removing the current + // start node. + // node: + // The node to remove from the starting range. + // range: + // The range to adapt. + // tags: + // private + if(node.nextSibling){ + range.setStart(node.nextSibling,0); + }else{ + var parent = node.parentNode; + while(parent && parent.nextSibling == null){ + //move up the tree until we find a parent that has another node, that node will be the next node + parent = parent.parentNode; + } + if(parent){ + range.setStart(parent.nextSibling,0); + } + } + return range; + }, + + _adaptIESelection: function(){ + // summary: + // Function to adapt the IE range by removing leading 'newlines' + // Needed to fix issue with bold/italics/underline not working if + // range included leading 'newlines'. + // In IE, if a user starts a selection at the very end of a line, + // then the native browser commands will fail to execute correctly. + // To work around the issue, we can remove all empty nodes from + // the start of the range selection. + var selection = dijit.range.getSelection(this.window); + if(selection && selection.rangeCount && !selection.isCollapsed){ + var range = selection.getRangeAt(0); + var firstNode = range.startContainer; + var startOffset = range.startOffset; + + while(firstNode.nodeType == 3/*text*/ && startOffset >= firstNode.length && firstNode.nextSibling){ + //traverse the text nodes until we get to the one that is actually highlighted + startOffset = startOffset - firstNode.length; + firstNode = firstNode.nextSibling; + } + + //Remove the starting ranges until the range does not start with an empty node. + var lastNode=null; + while(this._isNodeEmpty(firstNode, startOffset) && firstNode != lastNode){ + lastNode =firstNode; //this will break the loop in case we can't find the next sibling + range = this._removeStartingRangeFromRange(firstNode, range); //move the start container to the next node in the range + firstNode = range.startContainer; + startOffset = 0; //start at the beginning of the new starting range + } + selection.removeAllRanges();// this will work as long as users cannot select multiple ranges. I have not been able to do that in the editor. + selection.addRange(range); + } + } }); -return ec; -},_saveContent:function(e){ -var _57=dojo.byId(dijit._scopeName+"._editor.RichText.savedContent"); -if(_57.value){ -_57.value+=this._SEPARATOR; -} -_57.value+=this.name+":"+this.getValue(true); -},escapeXml:function(str,_58){ -str=str.replace(/&/gm,"&").replace(/</gm,"<").replace(/>/gm,">").replace(/"/gm,"""); -if(!_58){ -str=str.replace(/'/gm,"'"); -} -return str; -},getNodeHtml:function(_59){ -dojo.deprecated("dijit.Editor::getNodeHtml is deprecated","use dijit._editor.getNodeHtml instead",2); -return dijit._editor.getNodeHtml(_59); -},getNodeChildrenHtml:function(dom){ -dojo.deprecated("dijit.Editor::getNodeChildrenHtml is deprecated","use dijit._editor.getChildrenHtml instead",2); -return dijit._editor.getChildrenHtml(dom); -},close:function(_5a){ -if(this.isClosed){ -return false; -} -if(!arguments.length){ -_5a=true; -} -this._content=this.getValue(); -var _5b=(this.savedContent!=this._content); -if(this.interval){ -clearInterval(this.interval); -} -if(this._webkitListener){ -this.disconnect(this._webkitListener); -delete this._webkitListener; -} -if(dojo.isIE){ -this.iframe.onfocus=null; -} -this.iframe._loadFunc=null; -if(this._iframeRegHandle){ -dijit.unregisterIframe(this._iframeRegHandle); -delete this._iframeRegHandle; -} -if(this.textarea){ -var s=this.textarea.style; -s.position=""; -s.left=s.top=""; -if(dojo.isIE){ -s.overflow=this.__overflow; -this.__overflow=null; -} -this.textarea.value=_5a?this._content:this.savedContent; -dojo.destroy(this.domNode); -this.domNode=this.textarea; -}else{ -this.domNode.innerHTML=_5a?this._content:this.savedContent; -} -delete this.iframe; -dojo.removeClass(this.domNode,this.baseClass); -this.isClosed=true; -this.isLoaded=false; -delete this.editNode; -delete this.focusNode; -if(this.window&&this.window._frameElement){ -this.window._frameElement=null; -} -this.window=null; -this.document=null; -this.editingArea=null; -this.editorObject=null; -return _5b; -},destroy:function(){ -if(!this.isClosed){ -this.close(false); -} -this.inherited(arguments); -},_removeMozBogus:function(_5c){ -return _5c.replace(/\stype="_moz"/gi,"").replace(/\s_moz_dirty=""/gi,"").replace(/_moz_resizing="(true|false)"/gi,""); -},_removeWebkitBogus:function(_5d){ -_5d=_5d.replace(/\sclass="webkit-block-placeholder"/gi,""); -_5d=_5d.replace(/\sclass="apple-style-span"/gi,""); -return _5d; -},_normalizeFontStyle:function(_5e){ -return _5e.replace(/<(\/)?strong([ \>])/gi,"<$1b$2").replace(/<(\/)?em([ \>])/gi,"<$1i$2"); -},_preFixUrlAttributes:function(_5f){ -return _5f.replace(/(?:(<a(?=\s).*?\shref=)("|')(.*?)\2)|(?:(<a\s.*?href=)([^"'][^ >]+))/gi,"$1$4$2$3$5$2 _djrealurl=$2$3$5$2").replace(/(?:(<img(?=\s).*?\ssrc=)("|')(.*?)\2)|(?:(<img\s.*?src=)([^"'][^ >]+))/gi,"$1$4$2$3$5$2 _djrealurl=$2$3$5$2"); -},_inserthorizontalruleImpl:function(_60){ -if(dojo.isIE){ -return this._inserthtmlImpl("<hr>"); -} -return this.document.execCommand("inserthorizontalrule",false,_60); -},_unlinkImpl:function(_61){ -if((this.queryCommandEnabled("unlink"))&&(dojo.isMoz||dojo.isWebKit)){ -var a=this._sCall("getAncestorElement",["a"]); -this._sCall("selectElement",[a]); -return this.document.execCommand("unlink",false,null); -} -return this.document.execCommand("unlink",false,_61); -},_hilitecolorImpl:function(_62){ -var _63; -if(dojo.isMoz){ -this.document.execCommand("styleWithCSS",false,true); -_63=this.document.execCommand("hilitecolor",false,_62); -this.document.execCommand("styleWithCSS",false,false); -}else{ -_63=this.document.execCommand("hilitecolor",false,_62); -} -return _63; -},_backcolorImpl:function(_64){ -if(dojo.isIE){ -_64=_64?_64:null; -} -return this.document.execCommand("backcolor",false,_64); -},_forecolorImpl:function(_65){ -if(dojo.isIE){ -_65=_65?_65:null; -} -return this.document.execCommand("forecolor",false,_65); -},_inserthtmlImpl:function(_66){ -_66=this._preFilterContent(_66); -var rv=true; -if(dojo.isIE){ -var _67=this.document.selection.createRange(); -if(this.document.selection.type.toUpperCase()=="CONTROL"){ -var n=_67.item(0); -while(_67.length){ -_67.remove(_67.item(0)); -} -n.outerHTML=_66; -}else{ -_67.pasteHTML(_66); -} -_67.select(); -}else{ -if(dojo.isMoz&&!_66.length){ -this._sCall("remove"); -}else{ -rv=this.document.execCommand("inserthtml",false,_66); -} -} -return rv; -},getHeaderHeight:function(){ -return this._getNodeChildrenHeight(this.header); -},getFooterHeight:function(){ -return this._getNodeChildrenHeight(this.footer); -},_getNodeChildrenHeight:function(_68){ -var h=0; -if(_68&&_68.childNodes){ -var i; -for(i=0;i<_68.childNodes.length;i++){ -var _69=dojo.position(_68.childNodes[i]); -h+=_69.h; -} -} -return h; -}}); + } diff --git a/lib/dijit/_editor/_Plugin.js b/lib/dijit/_editor/_Plugin.js index f3c95aae0..2f769960d 100644 --- a/lib/dijit/_editor/_Plugin.js +++ b/lib/dijit/_editor/_Plugin.js @@ -1,73 +1,289 @@ /* - Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved. + Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved. Available via Academic Free License >= 2.1 OR the modified BSD license. see: http://dojotoolkit.org/license for details */ -if(!dojo._hasResource["dijit._editor._Plugin"]){ -dojo._hasResource["dijit._editor._Plugin"]=true; +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.form.Button"); -dojo.declare("dijit._editor._Plugin",null,{constructor:function(_1,_2){ -this.params=_1||{}; -dojo.mixin(this,this.params); -this._connects=[]; -},editor:null,iconClassPrefix:"dijitEditorIcon",button:null,command:"",useDefaultCommand:true,buttonClass:dijit.form.Button,getLabel:function(_3){ -return this.editor.commands[_3]; -},_initButton:function(){ -if(this.command.length){ -var _4=this.getLabel(this.command),_5=this.editor,_6=this.iconClassPrefix+" "+this.iconClassPrefix+this.command.charAt(0).toUpperCase()+this.command.substr(1); -if(!this.button){ -var _7=dojo.mixin({label:_4,dir:_5.dir,lang:_5.lang,showLabel:false,iconClass:_6,dropDown:this.dropDown,tabIndex:"-1"},this.params||{}); -this.button=new this.buttonClass(_7); -} -} -},destroy:function(){ -dojo.forEach(this._connects,dojo.disconnect); -if(this.dropDown){ -this.dropDown.destroyRecursive(); -} -},connect:function(o,f,tf){ -this._connects.push(dojo.connect(o,f,this,tf)); -},updateState:function(){ -var e=this.editor,c=this.command,_8,_9; -if(!e||!e.isLoaded||!c.length){ -return; -} -if(this.button){ -try{ -_9=e.queryCommandEnabled(c); -if(this.enabled!==_9){ -this.enabled=_9; -this.button.set("disabled",!_9); -} -if(typeof this.button.checked=="boolean"){ -_8=e.queryCommandState(c); -if(this.checked!==_8){ -this.checked=_8; -this.button.set("checked",e.queryCommandState(c)); -} -} -} -catch(e){ -} -} -},setEditor:function(_a){ -this.editor=_a; -this._initButton(); -if(this.button&&this.useDefaultCommand){ -if(this.editor.queryCommandAvailable(this.command)){ -this.connect(this.button,"onClick",dojo.hitch(this.editor,"execCommand",this.command,this.commandArg)); -}else{ -this.button.domNode.style.display="none"; -} -} -this.connect(this.editor,"onNormalizedDisplayChanged","updateState"); -},setToolbar:function(_b){ -if(this.button){ -_b.addChild(this.button); -} -}}); + + +dojo.declare("dijit._editor._Plugin", null, { + // summary + // Base class for a "plugin" to the editor, which is usually + // a single button on the Toolbar and some associated code + + constructor: function(/*Object?*/args, /*DomNode?*/node){ + this.params = args || {}; + dojo.mixin(this, this.params); + this._connects=[]; + this._attrPairNames = {}; + }, + + // editor: [const] dijit.Editor + // Points to the parent editor + editor: null, + + // iconClassPrefix: [const] String + // The CSS class name for the button node is formed from `iconClassPrefix` and `command` + iconClassPrefix: "dijitEditorIcon", + + // button: dijit._Widget? + // Pointer to `dijit.form.Button` or other widget (ex: `dijit.form.FilteringSelect`) + // that is added to the toolbar to control this plugin. + // If not specified, will be created on initialization according to `buttonClass` + button: null, + + // command: String + // String like "insertUnorderedList", "outdent", "justifyCenter", etc. that represents an editor command. + // Passed to editor.execCommand() if `useDefaultCommand` is true. + command: "", + + // useDefaultCommand: Boolean + // If true, this plugin executes by calling Editor.execCommand() with the argument specified in `command`. + useDefaultCommand: true, + + // buttonClass: Widget Class + // Class of widget (ex: dijit.form.Button or dijit.form.FilteringSelect) + // that is added to the toolbar to control this plugin. + // This is used to instantiate the button, unless `button` itself is specified directly. + buttonClass: dijit.form.Button, + + // disabled: Boolean + // Flag to indicate if this plugin has been disabled and should do nothing + // helps control button state, among other things. Set via the setter api. + disabled: false, + + getLabel: function(/*String*/key){ + // summary: + // Returns the label to use for the button + // tags: + // private + return this.editor.commands[key]; // String + }, + + _initButton: function(){ + // summary: + // Initialize the button or other widget that will control this plugin. + // This code only works for plugins controlling built-in commands in the editor. + // tags: + // protected extension + if(this.command.length){ + var label = this.getLabel(this.command), + editor = this.editor, + className = this.iconClassPrefix+" "+this.iconClassPrefix + this.command.charAt(0).toUpperCase() + this.command.substr(1); + if(!this.button){ + var props = dojo.mixin({ + label: label, + dir: editor.dir, + lang: editor.lang, + showLabel: false, + iconClass: className, + dropDown: this.dropDown, + tabIndex: "-1" + }, this.params || {}); + this.button = new this.buttonClass(props); + } + } + if(this.get("disabled") && this.button){ + this.button.set("disabled", this.get("disabled")); + } + }, + + destroy: function(){ + // summary: + // Destroy this plugin + + dojo.forEach(this._connects, dojo.disconnect); + if(this.dropDown){ + this.dropDown.destroyRecursive(); + } + }, + + connect: function(o, f, tf){ + // summary: + // Make a dojo.connect() that is automatically disconnected when this plugin is destroyed. + // Similar to `dijit._Widget.connect`. + // tags: + // protected + this._connects.push(dojo.connect(o, f, this, tf)); + }, + + updateState: function(){ + // summary: + // Change state of the plugin to respond to events in the editor. + // description: + // This is called on meaningful events in the editor, such as change of selection + // or caret position (but not simple typing of alphanumeric keys). It gives the + // plugin a chance to update the CSS of its button. + // + // For example, the "bold" plugin will highlight/unhighlight the bold button depending on whether the + // characters next to the caret are bold or not. + // + // Only makes sense when `useDefaultCommand` is true, as it calls Editor.queryCommandEnabled(`command`). + var e = this.editor, + c = this.command, + checked, enabled; + if(!e || !e.isLoaded || !c.length){ return; } + var disabled = this.get("disabled"); + if(this.button){ + try{ + enabled = !disabled && e.queryCommandEnabled(c); + if(this.enabled !== enabled){ + this.enabled = enabled; + this.button.set('disabled', !enabled); + } + if(typeof this.button.checked == 'boolean'){ + checked = e.queryCommandState(c); + if(this.checked !== checked){ + this.checked = checked; + this.button.set('checked', e.queryCommandState(c)); + } + } + }catch(e){ + console.log(e); // FIXME: we shouldn't have debug statements in our code. Log as an error? + } + } + }, + + setEditor: function(/*dijit.Editor*/ editor){ + // summary: + // Tell the plugin which Editor it is associated with. + + // TODO: refactor code to just pass editor to constructor. + + // FIXME: detach 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(); + + // Processing for buttons that execute by calling editor.execCommand() + if(this.button && this.useDefaultCommand){ + if(this.editor.queryCommandAvailable(this.command)){ + this.connect(this.button, "onClick", + dojo.hitch(this.editor, "execCommand", this.command, this.commandArg) + ); + }else{ + // hide button because editor doesn't support command (due to browser limitations) + this.button.domNode.style.display = "none"; + } + } + + this.connect(this.editor, "onNormalizedDisplayChanged", "updateState"); + }, + + setToolbar: function(/*dijit.Toolbar*/ toolbar){ + // summary: + // Tell the plugin to add it's controller widget (often a button) + // to the toolbar. Does nothing if there is no controller widget. + + // TODO: refactor code to just pass toolbar to constructor. + + if(this.button){ + toolbar.addChild(this.button); + } + // console.debug("adding", this.button, "to:", toolbar); + }, + + set: function(/* attribute */ name, /* anything */ value){ + // summary: + // Set a property on a plugin + // name: + // The property to set. + // value: + // The value to set in the property. + // description: + // Sets named properties on a plugin which may potentially be handled by a + // setter in the plugin. + // For example, if the plugin has a properties "foo" + // and "bar" and a method named "_setFooAttr", calling: + // | plugin.set("foo", "Howdy!"); + // would be equivalent to writing: + // | plugin._setFooAttr("Howdy!"); + // and: + // | plugin.set("bar", 3); + // would be equivalent to writing: + // | plugin.bar = 3; + // + // set() may also be called with a hash of name/value pairs, ex: + // | plugin.set({ + // | foo: "Howdy", + // | bar: 3 + // | }) + // This is equivalent to calling set(foo, "Howdy") and set(bar, 3) + if(typeof name === "object"){ + for(var x in name){ + this.set(x, name[x]); + } + return this; + } + var names = this._getAttrNames(name); + if(this[names.s]){ + // use the explicit setter + var result = this[names.s].apply(this, Array.prototype.slice.call(arguments, 1)); + }else{ + this._set(name, value); + } + return result || this; + }, + + get: function(name){ + // summary: + // Get a property from a plugin. + // name: + // The property to get. + // description: + // Get a named property from a plugin. The property may + // potentially be retrieved via a getter method. If no getter is defined, this + // just retrieves the object's property. + // For example, if the plugin has a properties "foo" + // and "bar" and a method named "_getFooAttr", calling: + // | plugin.get("foo"); + // would be equivalent to writing: + // | plugin._getFooAttr(); + // and: + // | plugin.get("bar"); + // would be equivalent to writing: + // | plugin.bar; + var names = this._getAttrNames(name); + return this[names.g] ? this[names.g]() : this[name]; + }, + + _setDisabledAttr: function(disabled){ + // summary: + // Function to set the plugin state and call updateState to make sure the + // button is updated appropriately. + this.disabled = disabled; + this.updateState(); + }, + + _getAttrNames: function(name){ + // summary: + // Helper function for get() and set(). + // Caches attribute name values so we don't do the string ops every time. + // tags: + // private + + var apn = this._attrPairNames; + if(apn[name]){ return apn[name]; } + var uc = name.charAt(0).toUpperCase() + name.substr(1); + return (apn[name] = { + s: "_set"+uc+"Attr", + g: "_get"+uc+"Attr" + }); + }, + + _set: function(/*String*/ name, /*anything*/ value){ + // summary: + // Helper function to set new value for specified attribute + var oldValue = this[name]; + this[name] = value; + } +}); + } diff --git a/lib/dijit/_editor/html.js b/lib/dijit/_editor/html.js index 7db85c7d9..196c8a309 100644 --- a/lib/dijit/_editor/html.js +++ b/lib/dijit/_editor/html.js @@ -1,147 +1,193 @@ /* - Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved. + Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved. Available via Academic Free License >= 2.1 OR the modified BSD license. see: http://dojotoolkit.org/license for details */ -if(!dojo._hasResource["dijit._editor.html"]){ -dojo._hasResource["dijit._editor.html"]=true; +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(_1,_2){ -_1=_1.replace(/&/gm,"&").replace(/</gm,"<").replace(/>/gm,">").replace(/"/gm,"""); -if(!_2){ -_1=_1.replace(/'/gm,"'"); -} -return _1; + +dojo.getObject("_editor", true, dijit); + +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, "&").replace(/</gm, "<").replace(/>/gm, ">").replace(/"/gm, """); + if(!noSingleQuotes){ + str = str.replace(/'/gm, "'"); + } + return str; // string }; -dijit._editor.getNodeHtml=function(_3){ -var _4; -switch(_3.nodeType){ -case 1: -var _5=_3.nodeName.toLowerCase(); -if(!_5||_5.charAt(0)=="/"){ -return ""; -} -_4="<"+_5; -var _6=[]; -var _7; -if(dojo.isIE&&_3.outerHTML){ -var s=_3.outerHTML; -s=s.substr(0,s.indexOf(">")).replace(/(['"])[^"']*\1/g,""); -var _8=/(\b\w+)\s?=/g; -var m,_9; -while((m=_8.exec(s))){ -_9=m[1]; -if(_9.substr(0,3)!="_dj"){ -if(_9=="src"||_9=="href"){ -if(_3.getAttribute("_djrealurl")){ -_6.push([_9,_3.getAttribute("_djrealurl")]); -continue; -} -} -var _a,_b; -switch(_9){ -case "style": -_a=_3.style.cssText.toLowerCase(); -break; -case "class": -_a=_3.className; -break; -case "width": -if(_5==="img"){ -_b=/width=(\S+)/i.exec(s); -if(_b){ -_a=_b[1]; -} -break; -} -case "height": -if(_5==="img"){ -_b=/height=(\S+)/i.exec(s); -if(_b){ -_a=_b[1]; -} -break; -} -default: -_a=_3.getAttribute(_9); -} -if(_a!=null){ -_6.push([_9,_a.toString()]); -} -} -} -}else{ -var i=0; -while((_7=_3.attributes[i++])){ -var n=_7.name; -if(n.substr(0,3)!="_dj"){ -var v=_7.value; -if(n=="src"||n=="href"){ -if(_3.getAttribute("_djrealurl")){ -v=_3.getAttribute("_djrealurl"); -} -} -_6.push([n,v]); -} -} -} -_6.sort(function(a,b){ -return a[0]<b[0]?-1:(a[0]==b[0]?0:1); -}); -var j=0; -while((_7=_6[j++])){ -_4+=" "+_7[0]+"=\""+(dojo.isString(_7[1])?dijit._editor.escapeXml(_7[1],true):_7[1])+"\""; -} -if(_5==="script"){ -_4+=">"+_3.innerHTML+"</"+_5+">"; -}else{ -if(_3.childNodes.length){ -_4+=">"+dijit._editor.getChildrenHtml(_3)+"</"+_5+">"; -}else{ -switch(_5){ -case "br": -case "hr": -case "img": -case "input": -case "base": -case "meta": -case "area": -case "basefont": -_4+=" />"; -break; -default: -_4+="></"+_5+">"; -} -} -} -break; -case 4: -case 3: -_4=dijit._editor.escapeXml(_3.nodeValue,true); -break; -case 8: -_4="<!--"+dijit._editor.escapeXml(_3.nodeValue,true)+"-->"; -break; -default: -_4="<!-- Element not recognized - Type: "+_3.nodeType+" Name: "+_3.nodeName+"-->"; -} -return _4; + +dijit._editor.getNodeHtml=function(/* DomNode */node){ + var output; + switch(node.nodeType){ + case 1: //element node + var lName = node.nodeName.toLowerCase(); + if(!lName || lName.charAt(0) == "/"){ + // IE does some strange things with malformed HTML input, like + // treating a close tag </span> without an open tag <span>, as + // a new tag with tagName of /span. Corrupts output HTML, remove + // them. Other browsers don't prefix tags that way, so will + // never show up. + return ""; + } + output = '<' + lName; + + //store the list of attributes and sort it to have the + //attributes appear in the dictionary order + var attrarray = []; + var attr; + if(dojo.isIE && node.outerHTML){ + var s = node.outerHTML; + s = s.substr(0, s.indexOf('>')) + .replace(/(['"])[^"']*\1/g, ''); //to make the following regexp safe + var reg = /(\b\w+)\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; + } + } + var val, match; + switch(key){ + case 'style': + val = node.style.cssText.toLowerCase(); + break; + case 'class': + val = node.className; + break; + case 'width': + if(lName === "img"){ + // This somehow gets lost on IE for IMG tags and the like + // and we have to find it in outerHTML, known IE oddity. + match=/width=(\S+)/i.exec(s); + if(match){ + val = match[1]; + } + break; + } + case 'height': + if(lName === "img"){ + // This somehow gets lost on IE for IMG tags and the like + // and we have to find it in outerHTML, known IE oddity. + match=/height=(\S+)/i.exec(s); + if(match){ + val = match[1]; + } + break; + } + default: + val = node.getAttribute(key); + } + if(val != null){ + attrarray.push([key, val.toString()]); + } + } + } + }else{ + var i = 0; + while((attr = node.attributes[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); + }); + var j = 0; + while((attr = attrarray[j++])){ + output += ' ' + attr[0] + '="' + + (dojo.isString(attr[1]) ? dijit._editor.escapeXml(attr[1], true) : attr[1]) + '"'; + } + if(lName === "script"){ + // Browsers handle script tags differently in how you get content, + // but innerHTML always seems to work, so insert its content that way + // Yes, it's bad to allow script tags in the editor code, but some people + // seem to want to do it, so we need to at least return them right. + // other plugins/filters can strip them. + output += '>' + node.innerHTML +'</' + lName + '>'; + }else{ + if(node.childNodes.length){ + output += '>' + dijit._editor.getChildrenHtml(node)+'</' + lName +'>'; + }else{ + switch(lName){ + case 'br': + case 'hr': + case 'img': + case 'input': + case 'base': + case 'meta': + case 'area': + case 'basefont': + // These should all be singly closed + output += ' />'; + break; + default: + // Assume XML style separate closure for everything else. + output += '></' + lName + '>'; + } + } + } + break; + case 4: // cdata + 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(_c){ -var _d=""; -if(!_c){ -return _d; -} -var _e=_c["childNodes"]||_c; -var _f=!dojo.isIE||_e!==_c; -var _10,i=0; -while((_10=_e[i++])){ -if(!_f||_10.parentNode==_c){ -_d+=dijit._editor.getNodeHtml(_10); -} -} -return _d; + +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; + + //IE issue. + //If we have an actual node we can check parent relationships on for IE, + //We should check, as IE sometimes builds invalid DOMS. If no parent, we can't check + //And should just process it and hope for the best. + var checkParent = !dojo.isIE || nodes !== dom; + + var node, i = 0; + while((node = nodes[i++])){ + //IE is broken. DOMs are supposed to be a tree. But in the case of malformed HTML, IE generates a graph + //meaning one node ends up with multiple references (multiple parents). This is totally wrong and invalid, but + //such is what it is. We have to keep track and check for this because otherise the source output HTML will have dups. + //No other browser generates a graph. Leave it to IE to break a fundamental DOM rule. So, we check the parent if we can + //If we can't, nothing more we can do other than walk it. + if(!checkParent || node.parentNode == dom){ + out += dijit._editor.getNodeHtml(node); + } + } + return out; // String }; + } diff --git a/lib/dijit/_editor/nls/ar/FontChoice.js b/lib/dijit/_editor/nls/ar/FontChoice.js index 71683c008..dd4f99423 100644 --- a/lib/dijit/_editor/nls/ar/FontChoice.js +++ b/lib/dijit/_editor/nls/ar/FontChoice.js @@ -1 +1 @@ -({"1":"صغير جدا جدا","2":"صغير جدا","formatBlock":"النسق","3":"صغير","4":"متوسط","5":"كبير","6":"كبير جدا","7":"كبير جدا جدا","fantasy":"خيالي","serif":"serif","p":"فقرة","pre":"منسق بصفة مسبقة","sans-serif":"sans-serif","fontName":"طاقم طباعة","h1":"عنوان","h2":"عنوان فرعي","h3":"فرعي-عنوان فرعي","monospace":"أحادي المسافة","fontSize":"الحجم","cursive":"كتابة بحروف متصلة","noFormat":"None"})
\ No newline at end of file +({"noFormat":"لا شيء","1":"صغير جدا جدا","2":"صغير جدا","formatBlock":"النسق","3":"صغير","4":"متوسط","5":"كبير","6":"كبير جدا","7":"كبير جدا جدا","fantasy":"خيالي","serif":"serif","p":"فقرة","pre":"منسق بصفة مسبقة","sans-serif":"sans-serif","fontName":"طاقم طباعة","h1":"عنوان","h2":"عنوان فرعي","h3":"فرعي-عنوان فرعي","monospace":"أحادي المسافة","fontSize":"الحجم","cursive":"كتابة بحروف متصلة"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/ar/LinkDialog.js b/lib/dijit/_editor/nls/ar/LinkDialog.js index 1a1b32e59..e229c6860 100644 --- a/lib/dijit/_editor/nls/ar/LinkDialog.js +++ b/lib/dijit/_editor/nls/ar/LinkDialog.js @@ -1 +1 @@ -({"text":"الوصف:","insertImageTitle":"خصائص الصورة","set":"تحديد","newWindow":"نافذة جديدة","topWindow":"النافذة العلوية","target":"الهدف: ","createLinkTitle":"خصائص الوصلة","parentWindow":"النافذة الرئيسية","currentWindow":"النافذة الحالية","url":"عنوان URL:"})
\ No newline at end of file +({"text":"الوصف:","insertImageTitle":"خصائص الصورة","set":"تحديد","newWindow":"نافذة جديدة","topWindow":"النافذة العلوية","target":"الهدف:","createLinkTitle":"خصائص الوصلة","parentWindow":"النافذة الرئيسية","currentWindow":"النافذة الحالية","url":"عنوان URL:"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/ar/commands.js b/lib/dijit/_editor/nls/ar/commands.js index 3e524ea91..81069e8d2 100644 --- a/lib/dijit/_editor/nls/ar/commands.js +++ b/lib/dijit/_editor/nls/ar/commands.js @@ -1 +1 @@ -({"removeFormat":"ازالة النسق","copy":"نسخ","paste":"لصق","selectAll":"اختيار كل","insertOrderedList":"كشف مرقم","insertTable":"ادراج/تحرير جدول","print":"طباعة","underline":"~تسطير","foreColor":"لون الواجهة الأمامية","htmlToggle":"مصدر HTML","formatBlock":"نمط الفقرة","newPage":"صفحة جديدة","insertHorizontalRule":"مسطرة أفقية","delete":"حذف","insertUnorderedList":"كشف نقطي","tableProp":"خصائص الجدول","insertImage":"ادراج صورة","superscript":"رمز علوي","subscript":"رمز سفلي","createLink":"تكوين وصلة","undo":"تراجع","fullScreen":"تبديل الشاشة الكاملة","italic":"~مائل","fontName":"اسم طاقم الطباعة","justifyLeft":"محاذاة الى اليسار","unlink":"ازالة وصلة","toggleTableBorder":"تبديل حدود الجدول","viewSource":"مشاهدة مصدر HTML","ctrlKey":"ctrl+${0}","fontSize":"حجم طاقم الطباعة","systemShortcut":"التصرف \"${0}\" يكون متاحا فقط في برنامج الاستعراض الخاص بك باستخدام المسار المختصر للوحة المفاتيح. استخدم ${1}.","indent":"ازاحة للداخل","redo":"اعادة","strikethrough":"تشطيب","justifyFull":"ضبط","justifyCenter":"محاذاة في الوسط","hiliteColor":"لون الخلفية","deleteTable":"حذف جدول","outdent":"ازاحة للخارج","cut":"قص","plainFormatBlock":"نمط الفقرة","toggleDir":"تبديل الاتجاه","bold":"عري~ض","tabIndent":"ازاحة للداخل باستخدام Tab","justifyRight":"محاذاة الى اليمين","appleKey":"⌘${0}"})
\ No newline at end of file +({"removeFormat":"ازالة النسق","copy":"نسخ","paste":"لصق","selectAll":"اختيار كل","insertOrderedList":"كشف مرقم","insertTable":"ادراج/تحرير جدول","print":"طباعة","underline":"~تسطير","foreColor":"لون الواجهة الأمامية","htmlToggle":"مصدر HTML","formatBlock":"نمط الفقرة","newPage":"صفحة جديدة","insertHorizontalRule":"مسطرة أفقية","delete":"حذف","appleKey":"⌘${0}","insertUnorderedList":"كشف نقطي","tableProp":"خصائص الجدول","insertImage":"ادراج صورة","superscript":"رمز علوي","subscript":"رمز سفلي","createLink":"تكوين وصلة","undo":"تراجع","fullScreen":"تبديل الشاشة الكاملة","italic":"~مائل","fontName":"اسم طاقم الطباعة","justifyLeft":"محاذاة الى اليسار","unlink":"ازالة وصلة","toggleTableBorder":"تبديل حدود الجدول","viewSource":"مشاهدة مصدر HTML","ctrlKey":"ctrl+${0}","fontSize":"حجم طاقم الطباعة","systemShortcut":"يكون التصرف \"${0}\" متاحا فقط ببرنامج الاستعراض الخاص بك باستخدام المسار المختصر للوحة المفاتيح. استخدم ${1}.","indent":"ازاحة للداخل","redo":"اعادة","strikethrough":"تشطيب","justifyFull":"ضبط","justifyCenter":"محاذاة في الوسط","hiliteColor":"لون الخلفية","deleteTable":"حذف جدول","outdent":"ازاحة للخارج","cut":"قص","plainFormatBlock":"نمط الفقرة","toggleDir":"تبديل الاتجاه","bold":"عري~ض","tabIndent":"ازاحة علامة الجدولة للداخل","justifyRight":"محاذاة الى اليمين"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/ca/FontChoice.js b/lib/dijit/_editor/nls/ca/FontChoice.js index efba7dec4..6a393feaa 100644 --- a/lib/dijit/_editor/nls/ca/FontChoice.js +++ b/lib/dijit/_editor/nls/ca/FontChoice.js @@ -1 +1 @@ -({"1":"xx-petit","2":"x-petit","formatBlock":"Format","3":"petit","4":"mitjà","5":"gran","6":"x-gran","7":"xx-gran","fantasy":"Fantasia","serif":"serif","p":"Paràgraf","pre":"Format previ","sans-serif":"sans-serif","fontName":"Tipus de lletra","h1":"Títol","h2":"Subtítol","h3":"Subsubtítol","monospace":"monoespai","fontSize":"Mida","cursive":"Cursiva","noFormat":"None"})
\ No newline at end of file +({"noFormat":"Cap","1":"xx-petit","2":"x-petit","formatBlock":"Format","3":"petit","4":"mitjà","5":"gran","6":"x-gran","7":"xx-gran","fantasy":"Fantasia","serif":"serif","p":"Paràgraf","pre":"Format previ","sans-serif":"sans-serif","fontName":"Tipus de lletra","h1":"Títol","h2":"Subtítol","h3":"Subsubtítol","monospace":"monoespai","fontSize":"Mida","cursive":"Cursiva"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/ca/LinkDialog.js b/lib/dijit/_editor/nls/ca/LinkDialog.js index b030a2ced..f7dd3af07 100644 --- a/lib/dijit/_editor/nls/ca/LinkDialog.js +++ b/lib/dijit/_editor/nls/ca/LinkDialog.js @@ -1 +1 @@ -({"text":"Descipció:","insertImageTitle":"Propietats de la imatge","set":"Defineix","newWindow":"Finestra nova","topWindow":"Finestra superior","target":"Destinació:","createLinkTitle":"Propietats de l'enllaç","parentWindow":"Finestra pare","currentWindow":"Finestra actual","url":"URL:"})
\ No newline at end of file +({"text":"Descripció:","insertImageTitle":"Propietats de la imatge","set":"Defineix","newWindow":"Finestra nova","topWindow":"Finestra superior","target":"Destinació:","createLinkTitle":"Propietats de l'enllaç","parentWindow":"Finestra pare","currentWindow":"Finestra actual","url":"URL:"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/ca/commands.js b/lib/dijit/_editor/nls/ca/commands.js index f78e71c85..534715e5a 100644 --- a/lib/dijit/_editor/nls/ca/commands.js +++ b/lib/dijit/_editor/nls/ca/commands.js @@ -1 +1 @@ -({"removeFormat":"Elimina el format","copy":"Copia","paste":"Enganxa","selectAll":"Selecciona-ho tot","insertOrderedList":"Llista numerada","insertTable":"Insereix/edita la taula","print":"Imprimeix","underline":"Subratllat","foreColor":"Color de primer pla","htmlToggle":"Font HTML","formatBlock":"Estil de paràgraf","newPage":"Pàgina nova","insertHorizontalRule":"Regle horitzontal","delete":"Suprimeix","insertUnorderedList":"Llista de vinyetes","tableProp":"Propietat de taula","insertImage":"Insereix imatge","superscript":"Superíndex","subscript":"Subíndex","createLink":"Crea un enllaç","undo":"Desfés","fullScreen":"Commuta pantalla completa","italic":"Cursiva","fontName":"Nom del tipus de lletra","justifyLeft":"Alinea a la esquerra","unlink":"Elimina l'enllaç","toggleTableBorder":"Inverteix els contorns de taula","viewSource":"Visualitza font HTML","ctrlKey":"control+${0}","fontSize":"Cos de la lletra","systemShortcut":"L'acció \"${0}\" és l'única disponible al navegador utilitzant una drecera del teclat. Utilitzeu ${1}.","indent":"Sagnat","redo":"Refés","strikethrough":"Ratllat","justifyFull":"Justifica","justifyCenter":"Centra","hiliteColor":"Color de fons","deleteTable":"Suprimeix la taula","outdent":"Sagna a l'esquerra","cut":"Retalla","plainFormatBlock":"Estil de paràgraf","toggleDir":"Inverteix la direcció","bold":"Negreta","tabIndent":"Sagnat","justifyRight":"Alinea a la dreta","appleKey":"⌘${0}"})
\ No newline at end of file +({"removeFormat":"Elimina el format","copy":"Copia","paste":"Enganxa","selectAll":"Selecciona-ho tot","insertOrderedList":"Llista numerada","insertTable":"Insereix/edita la taula","print":"Imprimeix","underline":"Subratllat","foreColor":"Color de primer pla","htmlToggle":"Font HTML","formatBlock":"Estil de paràgraf","newPage":"Pàgina nova","insertHorizontalRule":"Regla horitzontal","delete":"Suprimeix","insertUnorderedList":"Llista de vinyetes","tableProp":"Propietat de taula","insertImage":"Insereix imatge","superscript":"Superíndex","subscript":"Subíndex","createLink":"Crea un enllaç","undo":"Desfés","fullScreen":"Commuta pantalla completa","italic":"Cursiva","fontName":"Nom del tipus de lletra","justifyLeft":"Alinea a l'esquerra","unlink":"Elimina l'enllaç","toggleTableBorder":"Inverteix els contorns de taula","viewSource":"Visualitza font HTML","ctrlKey":"control+${0}","fontSize":"Cos de la lletra","systemShortcut":"L'acció \"${0}\" és l'única disponible al navegador utilitzant una drecera del teclat. Utilitzeu ${1}.","indent":"Sagnat","redo":"Refés","strikethrough":"Ratllat","justifyFull":"Justifica","justifyCenter":"Centra","hiliteColor":"Color de fons","deleteTable":"Suprimeix la taula","outdent":"Sagna a l'esquerra","cut":"Retalla","plainFormatBlock":"Estil de paràgraf","toggleDir":"Inverteix la direcció","bold":"Negreta","tabIndent":"Sagnat","justifyRight":"Alinea a la dreta","appleKey":"⌘${0}"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/cs/FontChoice.js b/lib/dijit/_editor/nls/cs/FontChoice.js index 447fe6685..b60a88027 100644 --- a/lib/dijit/_editor/nls/cs/FontChoice.js +++ b/lib/dijit/_editor/nls/cs/FontChoice.js @@ -1 +1 @@ -({"1":"extra malé","2":"velmi malé","formatBlock":"Formát","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","monospace":"monospace","fontSize":"Velikost","cursive":"cursive","noFormat":"None"})
\ No newline at end of file +({"noFormat":"Žádný","1":"extra malé","2":"velmi malé","formatBlock":"Formát","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","monospace":"monospace","fontSize":"Velikost","cursive":"cursive"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/cs/commands.js b/lib/dijit/_editor/nls/cs/commands.js index ce515587c..c3572d1d2 100644 --- a/lib/dijit/_editor/nls/cs/commands.js +++ b/lib/dijit/_editor/nls/cs/commands.js @@ -1 +1 @@ -({"removeFormat":"Odebrat formát","copy":"Kopírovat","paste":"Vložit","selectAll":"Vybrat vše","insertOrderedList":"Číslovaný seznam","insertTable":"Vložit/upravit tabulku","print":"Tisk","underline":"Podtržení","foreColor":"Barva popředí","htmlToggle":"Zdroj HTML","formatBlock":"Styl odstavce","newPage":"Nová stránka","insertHorizontalRule":"Vodorovná čára","delete":"Odstranit","insertUnorderedList":"Seznam s odrážkami","tableProp":"Vlastnost tabulky","insertImage":"Vložit obrázek","superscript":"Horní index","subscript":"Dolní index","createLink":"Vytvořit odkaz","undo":"Zpět","fullScreen":"Přepnout režim celé obrazovky","italic":"Kurzíva","fontName":"Název písma","justifyLeft":"Zarovnat vlevo","unlink":"Odebrat odkaz","toggleTableBorder":"Přepnout ohraničení tabulky","viewSource":"Zobrazit zdroj ve formátu HTML","fontSize":"Velikost písma","systemShortcut":"Akce \"${0}\" je v prohlížeči dostupná pouze prostřednictvím klávesové zkratky. Použijte klávesovou zkratku ${1}.","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é","tabIndent":"Odsazení tabulátoru","justifyRight":"Zarovnat vpravo","appleKey":"⌘${0}","ctrlKey":"ctrl+${0}"})
\ No newline at end of file +({"removeFormat":"Odebrat formát","copy":"Kopírovat","paste":"Vložit","selectAll":"Vybrat vše","insertOrderedList":"Číslovaný seznam","insertTable":"Vložit/upravit tabulku","print":"Tisk","underline":"Podtržení","foreColor":"Barva popředí","htmlToggle":"Zdroj HTML","formatBlock":"Styl odstavce","newPage":"Nová stránka","insertHorizontalRule":"Vodorovná čára","delete":"Odstranit","insertUnorderedList":"Seznam s odrážkami","tableProp":"Vlastnost tabulky","insertImage":"Vložit obrázek","superscript":"Horní index","subscript":"Dolní index","createLink":"Vytvořit odkaz","undo":"Zpět","fullScreen":"Přepnout celou obrazovku","italic":"Kurzíva","fontName":"Název písma","justifyLeft":"Zarovnat vlevo","unlink":"Odebrat odkaz","toggleTableBorder":"Přepnout ohraničení tabulky","viewSource":"Zobrazit zdroj HTML","fontSize":"Velikost písma","systemShortcut":"Akce \"${0}\" je v prohlížeči dostupná pouze prostřednictvím klávesové zkratky. Použijte klávesovou zkratku ${1}.","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é","tabIndent":"Odsazení tabulátoru","justifyRight":"Zarovnat vpravo","appleKey":"⌘${0}","ctrlKey":"ctrl+${0}"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/da/FontChoice.js b/lib/dijit/_editor/nls/da/FontChoice.js index 5b380ece6..a45c55bc5 100644 --- a/lib/dijit/_editor/nls/da/FontChoice.js +++ b/lib/dijit/_editor/nls/da/FontChoice.js @@ -1 +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":"Afsnit","pre":"Forudformateret","sans-serif":"sans-serif","fontName":"Skrifttype","h1":"Overskrift","h2":"Underoverskrift","h3":"Underunderoverskrift","monospace":"monospace","fontSize":"Størrelse","cursive":"kursiv","noFormat":"None"})
\ No newline at end of file +({"noFormat":"Ingen","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":"Afsnit","pre":"Forudformateret","sans-serif":"sans-serif","fontName":"Skrifttype","h1":"Overskrift","h2":"Underoverskrift","h3":"Underunderoverskrift","monospace":"monospace","fontSize":"Størrelse","cursive":"kursiv"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/da/commands.js b/lib/dijit/_editor/nls/da/commands.js index d2d93547e..fca175c80 100644 --- a/lib/dijit/_editor/nls/da/commands.js +++ b/lib/dijit/_editor/nls/da/commands.js @@ -1 +1 @@ -({"removeFormat":"Fjern format","copy":"Kopiér","paste":"Sæt ind","selectAll":"Markér alle","insertOrderedList":"Nummereret liste","insertTable":"Indsæt/redigér tabel","print":"Udskriv","underline":"Understreget","foreColor":"Forgrundsfarve","htmlToggle":"HTML-kilde","formatBlock":"Afsnitstypografi","newPage":"Ny side","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","fullScreen":"Aktivér/deaktivér fuldskærm","italic":"Kursiv","fontName":"Skriftnavn","justifyLeft":"Venstrejusteret","unlink":"Fjern link","toggleTableBorder":"Skift tabelramme","viewSource":"Vis HTML-kilde","ctrlKey":"Ctrl+${0}","fontSize":"Skriftstørrelse","systemShortcut":"Funktionen \"${0}\" kan kun bruges i din browser med en tastaturgenvej. Brug ${1}.","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","tabIndent":"Indrykning med tabulator","justifyRight":"Højrejusteret","appleKey":"⌘${0}"})
\ No newline at end of file +({"removeFormat":"Fjern format","copy":"Kopiér","paste":"Sæt ind","selectAll":"Markér alle","insertOrderedList":"Nummereret liste","insertTable":"Indsæt/redigér tabel","print":"Udskriv","underline":"Understreget","foreColor":"Forgrundsfarve","htmlToggle":"HTML-kilde","formatBlock":"Afsnitstypografi","newPage":"Ny side","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","fullScreen":"Aktivér/deaktivér fuldskærm","italic":"Kursiv","fontName":"Skriftnavn","justifyLeft":"Venstrejusteret","unlink":"Fjern link","toggleTableBorder":"Skift tabelramme","viewSource":"Vis HTML-kilde","fontSize":"Skriftstørrelse","systemShortcut":"Funktionen \"${0}\" kan kun bruges i din browser med en tastaturgenvej. Brug ${1}.","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","tabIndent":"Indrykning med tabulator","justifyRight":"Højrejusteret","appleKey":"⌘${0}","ctrlKey":"ctrl+${0}"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/de/FontChoice.js b/lib/dijit/_editor/nls/de/FontChoice.js index ed65ff3e7..c584c1812 100644 --- a/lib/dijit/_editor/nls/de/FontChoice.js +++ b/lib/dijit/_editor/nls/de/FontChoice.js @@ -1 +1 @@ -({"1":"XXS","2":"XS","formatBlock":"Format","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","monospace":"Monospaceschrift","fontSize":"Größe","cursive":"Kursiv","noFormat":"None"})
\ No newline at end of file +({"noFormat":"Keine Angabe","1":"XXS","2":"XS","formatBlock":"Format","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","monospace":"Monospaceschrift","fontSize":"Größe","cursive":"Kursiv"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/el/FontChoice.js b/lib/dijit/_editor/nls/el/FontChoice.js index 13c661c63..a529fe873 100644 --- a/lib/dijit/_editor/nls/el/FontChoice.js +++ b/lib/dijit/_editor/nls/el/FontChoice.js @@ -1 +1 @@ -({"1":"xx-μικρά","2":"x-μικρά","formatBlock":"Μορφή","3":"μικρά","4":"μεσαία","5":"μεγάλα","6":"x-μεγάλα","7":"xx-μεγάλα","fantasy":"φαντασίας","serif":"με πατούρες (serif)","p":"Παράγραφος","pre":"Προ-μορφοποιημένο","sans-serif":"χωρίς πατούρες (sans-serif)","fontName":"Γραμματοσειρά","h1":"Επικεφαλίδα","h2":"Δευτερεύουσα επικεφαλίδα","h3":"Δευτερεύουσα επικεφαλίδα τρίτου επιπέδου","monospace":"σταθερού πλάτους","fontSize":"Μέγεθος","cursive":"πλάγιοι","noFormat":"None"})
\ No newline at end of file +({"noFormat":"Χωρίς","1":"xx-μικρά","2":"x-μικρά","formatBlock":"Μορφή","3":"μικρά","4":"μεσαία","5":"μεγάλα","6":"x-μεγάλα","7":"xx-μεγάλα","fantasy":"φαντασίας","serif":"με πατούρες (serif)","p":"Παράγραφος","pre":"Προ-μορφοποιημένο","sans-serif":"χωρίς πατούρες (sans-serif)","fontName":"Γραμματοσειρά","h1":"Επικεφαλίδα","h2":"Δευτερεύουσα επικεφαλίδα","h3":"Δευτερεύουσα επικεφαλίδα τρίτου επιπέδου","monospace":"σταθερού πλάτους","fontSize":"Μέγεθος","cursive":"πλάγιοι"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/es/FontChoice.js b/lib/dijit/_editor/nls/es/FontChoice.js index 905a5609a..fd7d96590 100644 --- a/lib/dijit/_editor/nls/es/FontChoice.js +++ b/lib/dijit/_editor/nls/es/FontChoice.js @@ -1 +1 @@ -({"1":"xx-pequeño","2":"x-pequeño","formatBlock":"Formato","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","monospace":"espacio sencillo","fontSize":"Tamaño","cursive":"cursiva","noFormat":"None"})
\ No newline at end of file +({"noFormat":"Ninguno","1":"xx-pequeño","2":"x-pequeño","formatBlock":"Formato","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","monospace":"espacio sencillo","fontSize":"Tamaño","cursive":"cursiva"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/es/LinkDialog.js b/lib/dijit/_editor/nls/es/LinkDialog.js index 15802d77a..7d69bdb80 100644 --- a/lib/dijit/_editor/nls/es/LinkDialog.js +++ b/lib/dijit/_editor/nls/es/LinkDialog.js @@ -1 +1 @@ -({"text":"Descripción: ","insertImageTitle":"Propiedades de la imagen","set":"Establecer","newWindow":"Nueva ventana","topWindow":"Ventana superior","target":"Destino: ","createLinkTitle":"Propiedades del enlace","parentWindow":"Ventana padre","currentWindow":"Ventana actual","url":"URL:"})
\ No newline at end of file +({"text":"Descripción:","insertImageTitle":"Propiedades de la imagen","set":"Establecer","newWindow":"Nueva ventana","topWindow":"Ventana superior","target":"Destino:","createLinkTitle":"Propiedades del enlace","parentWindow":"Ventana padre","currentWindow":"Ventana actual","url":"URL:"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/fi/FontChoice.js b/lib/dijit/_editor/nls/fi/FontChoice.js index 7107971c7..02c68e986 100644 --- a/lib/dijit/_editor/nls/fi/FontChoice.js +++ b/lib/dijit/_editor/nls/fi/FontChoice.js @@ -1 +1 @@ -({"1":"xx-small","2":"x-small","formatBlock":"Muoto","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","monospace":"monospace","fontSize":"Koko","cursive":"cursive","noFormat":"None"})
\ No newline at end of file +({"noFormat":"Ei mitään","1":"xx-small","2":"x-small","formatBlock":"Muoto","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","monospace":"monospace","fontSize":"Koko","cursive":"cursive"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/fr/FontChoice.js b/lib/dijit/_editor/nls/fr/FontChoice.js index a96fac045..2e3a97803 100644 --- a/lib/dijit/_editor/nls/fr/FontChoice.js +++ b/lib/dijit/_editor/nls/fr/FontChoice.js @@ -1 +1 @@ -({"1":"xxs","2":"xs","formatBlock":"Mise en forme","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","monospace":"espacement fixe","fontSize":"Taille","cursive":"cursive","noFormat":"None"})
\ No newline at end of file +({"noFormat":"Néant","1":"xxs","2":"xs","formatBlock":"Mise en forme","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","monospace":"espacement fixe","fontSize":"Taille","cursive":"cursive"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/fr/LinkDialog.js b/lib/dijit/_editor/nls/fr/LinkDialog.js index 70946013a..8103ae329 100644 --- a/lib/dijit/_editor/nls/fr/LinkDialog.js +++ b/lib/dijit/_editor/nls/fr/LinkDialog.js @@ -1 +1 @@ -({"text":"Description :","insertImageTitle":"Propriétés des images","set":"Définir","newWindow":"Nouvelle fenêtre","topWindow":"Première fenêtre","target":"Cible :","createLinkTitle":"Propriétés des liens","parentWindow":"Fenêtre parent","currentWindow":"Fenêtre en cours","url":"URL :"})
\ No newline at end of file +({"text":"Description :","insertImageTitle":"Propriétés de l'image","set":"Définir","newWindow":"Nouvelle fenêtre","topWindow":"Fenêtre supérieure","target":"Cible :","createLinkTitle":"Propriétés du lien","parentWindow":"Fenêtre parent","currentWindow":"Fenêtre actuelle","url":"URL :"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/fr/commands.js b/lib/dijit/_editor/nls/fr/commands.js index df8cb3b92..532ac1347 100644 --- a/lib/dijit/_editor/nls/fr/commands.js +++ b/lib/dijit/_editor/nls/fr/commands.js @@ -1 +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","print":"Imprimer","underline":"Souligner","foreColor":"Couleur avant-plan","htmlToggle":"Source HTML","formatBlock":"Style de paragraphe","newPage":"Nouvelle page","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","fullScreen":"Basculer vers le mode plein écran","italic":"Italique","fontName":"Nom de police","justifyLeft":"Aligner à gauche","unlink":"Supprimer le lien","toggleTableBorder":"Afficher/Masquer la bordure du tableau","viewSource":"Afficher la source HTML","fontSize":"Taille de police","systemShortcut":"Action \"${0}\" uniquement disponible dans votre navigateur via un raccourci clavier. Utilisez ${1}.","indent":"Retrait","redo":"Rétablir","strikethrough":"Barrer","justifyFull":"Justifier","justifyCenter":"Aligner au centre","hiliteColor":"Couleur arrière-plan","deleteTable":"Supprimer le tableau","outdent":"Retrait négatif","cut":"Couper","plainFormatBlock":"Style de paragraphe","toggleDir":"Changer de sens","bold":"Gras","tabIndent":"Retrait de tabulation","justifyRight":"Aligner à droite","appleKey":"⌘${0}","ctrlKey":"ctrl+${0}"})
\ No newline at end of file +({"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","print":"Imprimer","underline":"Souligner","foreColor":"Couleur d'avant-plan","htmlToggle":"Source HTML","formatBlock":"Style de paragraphe","newPage":"Nouvelle page","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","fullScreen":"Basculer en plein écran","italic":"Italique","fontName":"Nom de police","justifyLeft":"Aligner à gauche","unlink":"Supprimer le lien","toggleTableBorder":"Afficher/Masquer la bordure du tableau","viewSource":"Afficher la source HTML","fontSize":"Taille de police","systemShortcut":"L'action \"${0}\" est disponible dans votre navigateur uniquement, par le biais d'un raccourci-clavier. Utilisez ${1}.","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":"Changer de sens","bold":"Gras","tabIndent":"Retrait de tabulation","justifyRight":"Aligner à droite","appleKey":"⌘${0}","ctrlKey":"ctrl+${0}"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/he/FontChoice.js b/lib/dijit/_editor/nls/he/FontChoice.js index 37140fb00..4c2e16f50 100644 --- a/lib/dijit/_editor/nls/he/FontChoice.js +++ b/lib/dijit/_editor/nls/he/FontChoice.js @@ -1 +1 @@ -({"1":"קטן ביות","2":"קטן מאוד","formatBlock":"עיצוב","3":"קטן","4":"בינוני","5":"גדול","6":"גדול מאוד","7":"גדול ביותר","fantasy":"fantasy","serif":"serif","p":"פיסקה","pre":"מעוצב מראש","sans-serif":"sans-serif","fontName":"גופן","h1":"כותרת","h2":"תת-כותרת","h3":"תת-תת-כותרת","monospace":"monospace","fontSize":"גודל","cursive":"cursive","noFormat":"None"})
\ No newline at end of file +({"noFormat":"ללא ","1":"קטן ביות","2":"קטן מאוד","formatBlock":"עיצוב","3":"קטן","4":"בינוני","5":"גדול","6":"גדול מאוד","7":"גדול ביותר","fantasy":"fantasy","serif":"serif","p":"פיסקה","pre":"מעוצב מראש","sans-serif":"sans-serif","fontName":"גופן","h1":"כותרת","h2":"תת-כותרת","h3":"תת-תת-כותרת","monospace":"monospace","fontSize":"גודל","cursive":"cursive"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/he/LinkDialog.js b/lib/dijit/_editor/nls/he/LinkDialog.js index 7b75850de..493974ca6 100644 --- a/lib/dijit/_editor/nls/he/LinkDialog.js +++ b/lib/dijit/_editor/nls/he/LinkDialog.js @@ -1 +1 @@ -({"text":"תיאור:","insertImageTitle":"תכונות תמונה","set":"הגדרה","newWindow":"חלון חדש","topWindow":"חלון עליון ","target":"יעד:","createLinkTitle":"תכונות קישור","parentWindow":"חלון אב","currentWindow":"חלון נוכחי ","url":"URL:"})
\ No newline at end of file +({"text":"תיאור:","insertImageTitle":"תכונות תמונה","set":"הגדרה","newWindow":"חלון חדש","topWindow":"חלון עליון","target":"יעד:","createLinkTitle":"תכונות קישור","parentWindow":"חלון אב","currentWindow":"חלון נוכחי","url":"URL:"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/he/commands.js b/lib/dijit/_editor/nls/he/commands.js index 75e95ab3e..39d598e94 100644 --- a/lib/dijit/_editor/nls/he/commands.js +++ b/lib/dijit/_editor/nls/he/commands.js @@ -1 +1 @@ -({"removeFormat":"סילוק עיצוב","copy":"עותק","paste":"הדבקה","selectAll":"בחירת הכל","insertOrderedList":"רשימה ממוספרת","insertTable":"הוספת/עריכת טבלה","print":"הדפסה","underline":"קו תחתי","foreColor":"צבע חזית","htmlToggle":"מקור HTML","formatBlock":"סגנון פיסקה","newPage":"דף חדש ","insertHorizontalRule":"קו אופקי","delete":"מחיקה","appleKey":"⌘${0}","insertUnorderedList":"רשימה עם תבליטים","tableProp":"תכונת טבלה","insertImage":"הוספת תמונה","superscript":"כתב עילי","subscript":"כתב תחתי","createLink":"יצירת קישור","undo":"ביטול פעולה","fullScreen":"מיתוג מסך מלא ","italic":"נטוי","fontName":"שם גופן","justifyLeft":"יישור לשמאל","unlink":"סילוק הקישור","toggleTableBorder":"מיתוג גבול טבלה","viewSource":"הצגת מקור HTML ","ctrlKey":"ctrl+${0}","fontSize":"גופן יחסי","systemShortcut":"הפעולה \"${0}\" זמינה בדפדפן רק באמצעות קיצור דרך במקלדת. השתמשו בקיצור ${1}.","indent":"הגדלת כניסה","redo":"שחזור פעולה","strikethrough":"קו חוצה","justifyFull":"יישור דו-צדדי","justifyCenter":"יישור למרכז","hiliteColor":"צבע רקע","deleteTable":"מחיקת טבלה","outdent":"הקטנת כניסה","cut":"גזירה","plainFormatBlock":"סגנון פיסקה","toggleDir":"מיתוג כיוון","bold":"מודגש","tabIndent":"כניסת טאב","justifyRight":"יישור לימין"})
\ No newline at end of file +({"removeFormat":"סילוק עיצוב","copy":"עותק","paste":"הדבקה","selectAll":"בחירת הכל","insertOrderedList":"רשימה ממוספרת","insertTable":"הוספת/עריכת טבלה","print":"הדפסה","underline":"קו תחתי","foreColor":"צבע חזית","htmlToggle":"מקור HTML","formatBlock":"סגנון פיסקה","newPage":"דף חדש","insertHorizontalRule":"קו אופקי","delete":"מחיקה","appleKey":"⌘${0}","insertUnorderedList":"רשימה עם תבליטים","tableProp":"תכונת טבלה","insertImage":"הוספת תמונה","superscript":"כתב עילי","subscript":"כתב תחתי","createLink":"יצירת קישור","undo":"ביטול פעולה","fullScreen":"מיתוג מסך מלא","italic":"נטוי","fontName":"שם גופן","justifyLeft":"יישור לשמאל","unlink":"סילוק הקישור","toggleTableBorder":"מיתוג גבול טבלה","viewSource":"הצגת מקור HTML","ctrlKey":"ctrl+${0}","fontSize":"גופן יחסי","systemShortcut":"הפעולה \"${0}\" זמינה בדפדפן רק באמצעות קיצור דרך במקלדת. השתמשו בקיצור ${1}.","indent":"הגדלת כניסה","redo":"שחזור פעולה","strikethrough":"קו חוצה","justifyFull":"יישור דו-צדדי","justifyCenter":"יישור למרכז","hiliteColor":"צבע רקע","deleteTable":"מחיקת טבלה","outdent":"הקטנת כניסה","cut":"גזירה","plainFormatBlock":"סגנון פיסקה","toggleDir":"מיתוג כיוון","bold":"מודגש","tabIndent":"כניסת טאב","justifyRight":"יישור לימין"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/hu/FontChoice.js b/lib/dijit/_editor/nls/hu/FontChoice.js index 7b67d13e9..831fe99c5 100644 --- a/lib/dijit/_editor/nls/hu/FontChoice.js +++ b/lib/dijit/_editor/nls/hu/FontChoice.js @@ -1 +1 @@ -({"1":"xx-kicsi","2":"x-kicsi","formatBlock":"Formátum","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","monospace":"rögzített szélességű","fontSize":"Méret","cursive":"kurzív","noFormat":"None"})
\ No newline at end of file +({"noFormat":"Nincs","1":"xx-kicsi","2":"x-kicsi","formatBlock":"Formátum","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","monospace":"rögzített szélességű","fontSize":"Méret","cursive":"kurzív"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/it/FontChoice.js b/lib/dijit/_editor/nls/it/FontChoice.js index 50f234087..a248473b5 100644 --- a/lib/dijit/_editor/nls/it/FontChoice.js +++ b/lib/dijit/_editor/nls/it/FontChoice.js @@ -1 +1 @@ -({"1":"xx-small","2":"x-small","formatBlock":"Formato","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","monospace":"spaziatura fissa","fontSize":"Dimensione","cursive":"corsivo","noFormat":"None"})
\ No newline at end of file +({"noFormat":"Nessuna","1":"xx-small","2":"x-small","formatBlock":"Formato","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","monospace":"spaziatura fissa","fontSize":"Dimensione","cursive":"corsivo"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/it/LinkDialog.js b/lib/dijit/_editor/nls/it/LinkDialog.js index ad3adef0e..94ebe18d2 100644 --- a/lib/dijit/_editor/nls/it/LinkDialog.js +++ b/lib/dijit/_editor/nls/it/LinkDialog.js @@ -1 +1 @@ -({"text":"Descrizione:","insertImageTitle":"Proprietà immagine","set":"Imposta","newWindow":"Nuova finestra","topWindow":"Finestra superiore","target":"Destinazione:","createLinkTitle":"Proprietà collegamento","parentWindow":"Finestra padre","currentWindow":"Finestra corrente","url":"URL:"})
\ No newline at end of file +({"text":"Descrizione:","insertImageTitle":"Proprietà immagine","set":"Imposta","newWindow":"Nuova finestra","topWindow":"Finestra in primo piano","target":"Destinazione:","createLinkTitle":"Proprietà collegamento","parentWindow":"Finestra parent","currentWindow":"Finestra corrente","url":"URL:"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/it/commands.js b/lib/dijit/_editor/nls/it/commands.js index 4abbd7ec8..2b08f8170 100644 --- a/lib/dijit/_editor/nls/it/commands.js +++ b/lib/dijit/_editor/nls/it/commands.js @@ -1 +1 @@ -({"removeFormat":"Rimuovi formato","copy":"Copia","paste":"Incolla","selectAll":"Seleziona tutto","insertOrderedList":"Elenco numerato","insertTable":"Inserisci/Modifica tabella","print":"Stampa","underline":"Sottolinea","foreColor":"Colore primo piano","htmlToggle":"Origine HTML","formatBlock":"Stile paragrafo","newPage":"Nuova pagina","insertHorizontalRule":"Righello orizzontale","delete":"Elimina","insertUnorderedList":"Elenco puntato","tableProp":"Proprietà tabella","insertImage":"Inserisci immagine","superscript":"Apice","subscript":"Pedice","createLink":"Crea collegamento","undo":"Annulla","fullScreen":"Attiva/Disattiva schermo intero","italic":"Corsivo","fontName":"Nome carattere","justifyLeft":"Allinea a sinistra","unlink":"Rimuovi collegamento","toggleTableBorder":"Attiva/Disattiva bordo tabella","viewSource":"Visualizza origine HTML","fontSize":"Dimensione carattere","systemShortcut":"La azione \"${0}\" è disponibile solo nel browser tramite un tasto di scelta rapida. Utilizzare ${1}.","indent":"Rientro","redo":"Ripristina","strikethrough":"Barrato","justifyFull":"Giustifica","justifyCenter":"Allinea al centro","hiliteColor":"Colore sfondo","deleteTable":"Elimina tabella","outdent":"Annulla rientro","cut":"Taglia","plainFormatBlock":"Stile paragrafo","toggleDir":"Attiva/Disattiva direzione","bold":"Grassetto","tabIndent":"Rientro tabulazione","justifyRight":"Allinea a destra","appleKey":"⌘${0}","ctrlKey":"ctrl+${0}"})
\ No newline at end of file +({"removeFormat":"Rimuovi formato","copy":"Copia","paste":"Incolla","selectAll":"Seleziona tutto","insertOrderedList":"Elenco numerato","insertTable":"Inserisci/Modifica tabella","print":"Stampa","underline":"Sottolineato","foreColor":"Colore primo piano","htmlToggle":"Origine HTML","formatBlock":"Stile paragrafo","newPage":"Nuova pagina","insertHorizontalRule":"Righello orizzontale","delete":"Elimina","insertUnorderedList":"Elenco puntato","tableProp":"Proprietà tabella","insertImage":"Inserisci immagine","superscript":"Apice","subscript":"Pedice","createLink":"Crea collegamento","undo":"Annulla","fullScreen":"Attiva/Disattiva schermo intero","italic":"Corsivo","fontName":"Nome carattere","justifyLeft":"Allinea a sinistra","unlink":"Rimuovi collegamento","toggleTableBorder":"Mostra/Nascondi margine tabella","viewSource":"Visualizza origine HTML","fontSize":"Dimensione carattere","systemShortcut":"Azione \"${0}\" disponibile sul proprio browser solo mediante i tasti di scelta rapida della tastiera. Utilizzare ${1}.","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","tabIndent":"Rientranza tabulazione","justifyRight":"Allinea a destra","appleKey":"⌘${0}","ctrlKey":"ctrl+${0}"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/ja/FontChoice.js b/lib/dijit/_editor/nls/ja/FontChoice.js index 6083ab381..647f90d2d 100644 --- a/lib/dijit/_editor/nls/ja/FontChoice.js +++ b/lib/dijit/_editor/nls/ja/FontChoice.js @@ -1 +1 @@ -({"1":"超極小","2":"極小","formatBlock":"フォーマット","3":"小","4":"標準","5":"大","6":"特大","7":"超特大","fantasy":"fantasy","serif":"serif","p":"段落","pre":"事前フォーマット済み","sans-serif":"sans-serif","fontName":"フォント","h1":"見出し","h2":"副見出し","h3":"副見出しの副見出し","monospace":"monospace","fontSize":"サイズ","cursive":"cursive","noFormat":"None"})
\ No newline at end of file +({"noFormat":"なし","1":"超極小","2":"極小","formatBlock":"フォーマット","3":"小","4":"標準","5":"大","6":"特大","7":"超特大","fantasy":"fantasy","serif":"serif","p":"段落","pre":"事前フォーマット済み","sans-serif":"sans-serif","fontName":"フォント","h1":"見出し","h2":"副見出し","h3":"副見出しの副見出し","monospace":"monospace","fontSize":"サイズ","cursive":"cursive"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/ja/commands.js b/lib/dijit/_editor/nls/ja/commands.js index 618746e23..2ba1d51bb 100644 --- a/lib/dijit/_editor/nls/ja/commands.js +++ b/lib/dijit/_editor/nls/ja/commands.js @@ -1 +1 @@ -({"removeFormat":"形式の除去","copy":"コピー","paste":"貼り付け","selectAll":"すべて選択","insertOrderedList":"番号付きリスト","insertTable":"テーブルの挿入/編集","print":"印刷","underline":"下線","foreColor":"前景色","htmlToggle":"HTML ソース","formatBlock":"段落スタイル","newPage":"新しいページ","insertHorizontalRule":"水平罫線","delete":"削除","insertUnorderedList":"黒丸付きリスト","tableProp":"テーブルプロパティ","insertImage":"イメージの挿入","superscript":"上付き文字","subscript":"下付き文字","createLink":"リンクの作成","undo":"元に戻す","fullScreen":"全画面表示に切り替え","italic":"斜体","fontName":"フォント名","justifyLeft":"左揃え","unlink":"リンクの削除","toggleTableBorder":"テーブルボーダーの切り替え","viewSource":"HTML ソースの表示","fontSize":"フォントサイズ","systemShortcut":"\"${0}\" アクションを使用できるのは、ブラウザーでキーボードショートカットを使用する場合のみです。 ${1} を使用してください。","indent":"インデント","redo":"やり直し","strikethrough":"取り消し線","justifyFull":"両端揃え","justifyCenter":"中央揃え","hiliteColor":"背景色","deleteTable":"テーブルの削除","outdent":"アウトデント","cut":"切り取り","plainFormatBlock":"段落スタイル","toggleDir":"方向の切り替え","bold":"太字","tabIndent":"タブインデント","justifyRight":"右揃え","appleKey":"⌘${0}","ctrlKey":"ctrl+${0}"})
\ No newline at end of file +({"removeFormat":"書式のクリア","copy":"コピー","paste":"貼り付け","selectAll":"すべて選択","insertOrderedList":"番号付きリスト","insertTable":"テーブルの挿入/編集","print":"印刷","underline":"下線","foreColor":"前景色","htmlToggle":"HTML ソース","formatBlock":"段落スタイル","newPage":"新規ページ","insertHorizontalRule":"水平罫線","delete":"削除","insertUnorderedList":"黒丸付きリスト","tableProp":"テーブル・プロパティー","insertImage":"イメージの挿入","superscript":"上付き文字","subscript":"下付き文字","createLink":"リンクの作成","undo":"元に戻す","fullScreen":"全画面表示に切り替え","italic":"イタリック","fontName":"フォント名","justifyLeft":"左揃え","unlink":"リンクの削除","toggleTableBorder":"テーブル・ボーダーの切り替え","viewSource":"HTML ソースの表示","ctrlKey":"Ctrl+${0}","fontSize":"フォント・サイズ","systemShortcut":"\"${0}\" アクションを使用できるのは、ブラウザーでキーボード・ショートカットを使用する場合のみです。${1} を使用してください。","indent":"インデント","redo":"やり直し","strikethrough":"取り消し線","justifyFull":"両端揃え","justifyCenter":"中央揃え","hiliteColor":"マーカー","deleteTable":"テーブルの削除","outdent":"アウトデント","cut":"切り取り","plainFormatBlock":"段落スタイル","toggleDir":"方向の切り替え","bold":"太字","tabIndent":"タブ・インデント","justifyRight":"右揃え","appleKey":"⌘${0}"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/kk/FontChoice.js b/lib/dijit/_editor/nls/kk/FontChoice.js new file mode 100644 index 000000000..6a9dbbff3 --- /dev/null +++ b/lib/dijit/_editor/nls/kk/FontChoice.js @@ -0,0 +1 @@ +({"noFormat":"Ешбір","1":"xx-кіші","2":"x-кіші","formatBlock":"Пішім","3":"кіші","4":"орташа","5":"үлкен","6":"x-үлкен","7":"xx-үлкен","fantasy":"қиял-ғажайып","serif":"serif","p":"Еже","pre":"Алдын ала пішімделген","sans-serif":"sans-serif","fontName":"Қаріп","h1":"Үстіңгі деректеме","h2":"Ішкі тақырып","h3":"Ішкі-ішкі тақырып","monospace":"monospace","fontSize":"Өлшемі","cursive":"көлбеу"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/kk/LinkDialog.js b/lib/dijit/_editor/nls/kk/LinkDialog.js new file mode 100644 index 000000000..c1c5ca2fa --- /dev/null +++ b/lib/dijit/_editor/nls/kk/LinkDialog.js @@ -0,0 +1 @@ +({"text":"Сипаттама:","insertImageTitle":"Сурет сипаттары","set":"Орнату","newWindow":"Жаңа терезе","topWindow":"Ең жоғарғы терезе","target":"Мақсат:","createLinkTitle":"Сілтеме сипаттары","parentWindow":"Басты терезе","currentWindow":"Ағымдағы терезе","url":"URL мекенжайы:"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/kk/commands.js b/lib/dijit/_editor/nls/kk/commands.js new file mode 100644 index 000000000..ac362d31e --- /dev/null +++ b/lib/dijit/_editor/nls/kk/commands.js @@ -0,0 +1 @@ +({"removeFormat":"Пішімді алып тастау","copy":"Көшіру","paste":"Қою","selectAll":"Барлығын таңдау","insertOrderedList":"Нөмірленген тізім","insertTable":"Кестені кірістіру/өңдеу","print":"Басып шығару","underline":"Асты сызылған","foreColor":"Алды түсі","htmlToggle":"HTML көзі","formatBlock":"Еже мәнері","newPage":"Жаңа бет","insertHorizontalRule":"Көлденең сызғыш","delete":"Жою","insertUnorderedList":"Таңбалауыш тізім","tableProp":"Кесте сипаты","insertImage":"Сурет кірістіру","superscript":"Жолүсті","subscript":"Жоласты","createLink":"Сілтеме жасау","undo":"Болдырмау ","fullScreen":"Толық экранды қосу","italic":"Көлбеу","fontName":"Қаріп атауы","justifyLeft":"Сол жақ бойынша туралау","unlink":"Сілтемені жою","toggleTableBorder":"Кесте жиегін қосу","viewSource":"HTML көзін қарау","fontSize":"Қаріп өлшемі","systemShortcut":"\"${0}\" әрекеті шолғышта тек пернелер тіркесімі арқылы қол жетімді. ${1} пайдаланыңыз.","indent":"Шегіндіру","redo":"Қайтару","strikethrough":"Сызылған","justifyFull":"Туралау","justifyCenter":"Ортасы бойынша туралау","hiliteColor":"Өң түсі","deleteTable":"Кестені жою","outdent":"Шығыңқы","cut":"Қиып алу","plainFormatBlock":"Еже мәнері","toggleDir":"Бағытты қосу","bold":"Қалың","tabIndent":"Қойынды шегінісі","justifyRight":"Оң жақ бойынша туралау","appleKey":"⌘${0}","ctrlKey":"ctrl+${0}"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/ko/FontChoice.js b/lib/dijit/_editor/nls/ko/FontChoice.js index fda733702..f3e2dc4ad 100644 --- a/lib/dijit/_editor/nls/ko/FontChoice.js +++ b/lib/dijit/_editor/nls/ko/FontChoice.js @@ -1 +1 @@ -({"1":"가장 작게","2":"조금 작게","formatBlock":"서식","3":"작게","4":"중간","5":"크게","6":"조금 크게","7":"가장 크게","fantasy":"fantasy","serif":"serif","p":"단락","pre":"서식이 지정됨","sans-serif":"sans-serif","fontName":"글꼴","h1":"제목","h2":"부제목","h3":"하위 부제목","monospace":"monospace","fontSize":"크기","cursive":"cursive","noFormat":"None"})
\ No newline at end of file +({"noFormat":"없음","1":"가장 작게","2":"조금 작게","formatBlock":"서식","3":"작게","4":"중간","5":"크게","6":"조금 크게","7":"가장 크게","fantasy":"fantasy","serif":"serif","p":"단락","pre":"서식이 지정됨","sans-serif":"sans-serif","fontName":"글꼴","h1":"제목","h2":"부제목","h3":"하위 부제목","monospace":"monospace","fontSize":"크기","cursive":"cursive"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/ko/LinkDialog.js b/lib/dijit/_editor/nls/ko/LinkDialog.js index 1f46bd71f..fd1e9d5b0 100644 --- a/lib/dijit/_editor/nls/ko/LinkDialog.js +++ b/lib/dijit/_editor/nls/ko/LinkDialog.js @@ -1 +1 @@ -({"text":"설명:","insertImageTitle":"이미지 특성","set":"설정","newWindow":"새 창","topWindow":"최상위 창","target":"대상:","createLinkTitle":"링크 특성","parentWindow":"상위 창","currentWindow":"현재 창","url":"URL:"})
\ No newline at end of file +({"text":"설명:","insertImageTitle":"이미지 등록 정보","set":"설정","newWindow":"새 창","topWindow":"최상위 창","target":"대상","createLinkTitle":"링크 등록 정보","parentWindow":"상위 창","currentWindow":"현재 창","url":"URL:"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/ko/commands.js b/lib/dijit/_editor/nls/ko/commands.js index 4c8f95493..972b047e3 100644 --- a/lib/dijit/_editor/nls/ko/commands.js +++ b/lib/dijit/_editor/nls/ko/commands.js @@ -1 +1 @@ -({"removeFormat":"형식 제거","copy":"복사","paste":"붙여넣기","selectAll":"모두 선택","insertOrderedList":"번호 목록","insertTable":"테이블 삽입/편집","print":"인쇄","underline":"밑줄","foreColor":"전경색","htmlToggle":"HTML 소스","formatBlock":"단락 스타일","newPage":"새 페이지","insertHorizontalRule":"수평 자","delete":"삭제","insertUnorderedList":"글머리표 목록","tableProp":"테이블 특성","insertImage":"이미지 삽입","superscript":"위첨자","subscript":"아래첨자","createLink":"링크 작성","undo":"실행 취소","fullScreen":"토글 전체 화면","italic":"기울임체","fontName":"글꼴 이름","justifyLeft":"왼쪽 맞춤","unlink":"링크 제거","toggleTableBorder":"토글 테이블 테두리","viewSource":"HTML 소스 보기","fontSize":"글꼴 크기","systemShortcut":"\"${0}\" 조치는 브라우저에서 키보드 단축키를 이용해서만 사용할 수 있습니다. ${1}을(를) 사용하십시오.","indent":"들여쓰기","redo":"다시 실행","strikethrough":"취소선","justifyFull":"양쪽 맞춤","justifyCenter":"가운데 맞춤","hiliteColor":"배경색","deleteTable":"테이블 삭제","outdent":"내어쓰기","cut":"잘라내기","plainFormatBlock":"단락 스타일","toggleDir":"토글 방향","bold":"굵은체","tabIndent":"탭 들여쓰기","justifyRight":"오른쪽 맞춤","appleKey":"⌘${0}","ctrlKey":"ctrl+${0}"})
\ No newline at end of file +({"removeFormat":"형식 제거","copy":"복사","paste":"붙여넣기","selectAll":"모두 선택","insertOrderedList":"번호 목록","insertTable":"테이블 삽입/편집","print":"인쇄","underline":"밑줄","foreColor":"전경색","htmlToggle":"HTML 소스","formatBlock":"단락 양식","newPage":"새 페이지","insertHorizontalRule":"수평 자","delete":"삭제","insertUnorderedList":"글머리표 목록","tableProp":"테이블 특성","insertImage":"이미지 삽입","superscript":"위첨자","subscript":"아래첨자","createLink":"링크 작성","undo":"실행 취소","fullScreen":"전체 화면 토글","italic":"기울임꼴","fontName":"글꼴 이름","justifyLeft":"왼쪽 맞춤","unlink":"링크 제거","toggleTableBorder":"테이블 외곽선 토글","viewSource":"HTML 소스 보기","fontSize":"글꼴 크기","systemShortcut":"\"${0}\" 조치는 브라우저에서 키보드 단축키를 통해서만 사용 가능합니다. ${1}을(를) 사용하십시오.","indent":"들여쓰기","redo":"다시 실행","strikethrough":"취소선","justifyFull":"양쪽 맞춤","justifyCenter":"가운데 맞춤","hiliteColor":"배경색","deleteTable":"테이블 삭제","outdent":"내어쓰기","cut":"잘라내기","plainFormatBlock":"단락 양식","toggleDir":"방향 토글","bold":"굵게","tabIndent":"탭 들여쓰기","justifyRight":"오른쪽 맞춤","appleKey":"⌘${0}","ctrlKey":"ctrl+${0}"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/nb/FontChoice.js b/lib/dijit/_editor/nls/nb/FontChoice.js index b1ad6abf2..c7c8f5dd5 100644 --- a/lib/dijit/_editor/nls/nb/FontChoice.js +++ b/lib/dijit/_editor/nls/nb/FontChoice.js @@ -1 +1 @@ -({"1":"xx-liten","2":"x-liten","formatBlock":"Format","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","monospace":"monospace","fontSize":"Størrelse","cursive":"kursiv","noFormat":"None"})
\ No newline at end of file +({"noFormat":"Ingen","1":"xx-liten","2":"x-liten","formatBlock":"Format","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","monospace":"monospace","fontSize":"Størrelse","cursive":"kursiv"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/nb/commands.js b/lib/dijit/_editor/nls/nb/commands.js index d1f215f52..daf828988 100644 --- a/lib/dijit/_editor/nls/nb/commands.js +++ b/lib/dijit/_editor/nls/nb/commands.js @@ -1 +1 @@ -({"removeFormat":"Fjern format","copy":"Kopier","paste":"Lim inn","selectAll":"Velg alle","insertOrderedList":"Nummerert liste","insertTable":"Sett inn/rediger tabell","print":"Skriv ut","underline":"Understreking","foreColor":"Forgrunnsfarge","htmlToggle":"HTML-kilde","formatBlock":"Avsnittsstil","newPage":"Ny side","insertHorizontalRule":"Vannrett strek","delete":"Slett","insertUnorderedList":"Punktliste","tableProp":"Tabellegenskap","insertImage":"Sett inn bilde","superscript":"Hevet skrift","subscript":"Senket skrift","createLink":"Opprett kobling","undo":"Angre","fullScreen":"Slå på/av full skjerm","italic":"Kursiv","fontName":"Skriftnavn","justifyLeft":"Venstrejuster","unlink":"Fjern kobling","toggleTableBorder":"Bytt tabellkant","viewSource":"Vis HTML-kilde","fontSize":"Skriftstørrelse","systemShortcut":"Handlingen \"${0}\" er bare tilgjengelig i nettleseren ved hjelp av en tastatursnarvei. Bruk ${1}.","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","tabIndent":"Tabulatorinnrykk","justifyRight":"Høyrejuster","appleKey":"⌘${0}","ctrlKey":"ctrl+${0}"})
\ No newline at end of file +({"removeFormat":"Fjern format","copy":"Kopier","paste":"Lim inn","selectAll":"Velg alle","insertOrderedList":"Nummerert liste","insertTable":"Sett inn/rediger tabell","print":"Skriv ut","underline":"Understreking","foreColor":"Forgrunnsfarge","htmlToggle":"HTML-kilde","formatBlock":"Avsnittsstil","newPage":"Ny side","insertHorizontalRule":"Vannrett strek","delete":"Slett","appleKey":"⌘${0}","insertUnorderedList":"Punktliste","tableProp":"Tabellegenskap","insertImage":"Sett inn bilde","superscript":"Hevet skrift","subscript":"Senket skrift","createLink":"Opprett kobling","undo":"Angre","fullScreen":"Slå på/av full skjerm","italic":"Kursiv","fontName":"Skriftnavn","justifyLeft":"Venstrejuster","unlink":"Fjern kobling","toggleTableBorder":"Bytt tabellkant","viewSource":"Vis HTML-kilde","ctrlKey":"ctrl+${0}","fontSize":"Skriftstørrelse","systemShortcut":"Handlingen \"${0}\" er bare tilgjengelig i nettleseren ved hjelp av en tastatursnarvei. Bruk ${1}.","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","tabIndent":"Tabulatorinnrykk","justifyRight":"Høyrejuster"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/nl/FontChoice.js b/lib/dijit/_editor/nls/nl/FontChoice.js index d3d4f19f3..2bdbd583e 100644 --- a/lib/dijit/_editor/nls/nl/FontChoice.js +++ b/lib/dijit/_editor/nls/nl/FontChoice.js @@ -1 +1 @@ -({"1":"xx-klein","2":"x-klein","formatBlock":"Opmaak","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","monospace":"monospace","fontSize":"Grootte","cursive":"cursief","noFormat":"None"})
\ No newline at end of file +({"noFormat":"Geen","1":"xx-klein","2":"x-klein","formatBlock":"Opmaak","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","monospace":"monospace","fontSize":"Grootte","cursive":"cursief"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/pl/FontChoice.js b/lib/dijit/_editor/nls/pl/FontChoice.js index 8beb6bf63..e555c2812 100644 --- a/lib/dijit/_editor/nls/pl/FontChoice.js +++ b/lib/dijit/_editor/nls/pl/FontChoice.js @@ -1 +1 @@ -({"1":"najmniejsza","2":"mniejsza","formatBlock":"Format","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","monospace":"czcionka o stałej szerokości","fontSize":"Wielkość","cursive":"kursywa","noFormat":"None"})
\ No newline at end of file +({"noFormat":"Brak","1":"najmniejsza","2":"mniejsza","formatBlock":"Format","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","monospace":"czcionka o stałej szerokości","fontSize":"Wielkość","cursive":"kursywa"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/pl/commands.js b/lib/dijit/_editor/nls/pl/commands.js index 8ee8acfa9..0615a6905 100644 --- a/lib/dijit/_editor/nls/pl/commands.js +++ b/lib/dijit/_editor/nls/pl/commands.js @@ -1 +1 @@ -({"removeFormat":"Usuń formatowanie","copy":"Kopiuj","paste":"Wklej","selectAll":"Wybierz wszystko","insertOrderedList":"Lista numerowana","insertTable":"Wstaw/edytuj tabelę","print":"Drukuj","underline":"Podkreślenie","foreColor":"Kolor pierwszego planu","htmlToggle":"Źródło HTML","formatBlock":"Styl akapitu","newPage":"Nowa strona","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","fullScreen":"Przełącz pełny ekran","italic":"Kursywa","fontName":"Nazwa czcionki","justifyLeft":"Wyrównaj do lewej","unlink":"Usuń odsyłacz","toggleTableBorder":"Przełącz ramkę tabeli","viewSource":"Wyświetl kod źródłowy HTML","ctrlKey":"Ctrl+${0}","fontSize":"Wielkość czcionki","systemShortcut":"Działanie ${0} jest dostępne w tej przeglądarce wyłącznie przy użyciu skrótu klawiaturowego. Należy użyć klawiszy ${1}.","indent":"Wcięcie","redo":"Ponów","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","tabIndent":"Wcięcie o tabulator","justifyRight":"Wyrównaj do prawej","appleKey":"⌘${0}"})
\ No newline at end of file +({"removeFormat":"Usuń formatowanie","copy":"Kopiuj","paste":"Wklej","selectAll":"Wybierz wszystko","insertOrderedList":"Lista numerowana","insertTable":"Wstaw/edytuj tabelę","print":"Drukuj","underline":"Podkreślenie","foreColor":"Kolor pierwszego planu","htmlToggle":"Kod źródłowy HTML","formatBlock":"Styl akapitu","newPage":"Nowa strona","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","fullScreen":"Przełącz pełny ekran","italic":"Kursywa","fontName":"Nazwa czcionki","justifyLeft":"Wyrównaj do lewej","unlink":"Usuń odsyłacz","toggleTableBorder":"Przełącz ramkę tabeli","viewSource":"Wyświetl kod źródłowy HTML","ctrlKey":"Ctrl+${0}","fontSize":"Wielkość czcionki","systemShortcut":"Działanie ${0} jest dostępne w tej przeglądarce wyłącznie przy użyciu skrótu klawiaturowego. Należy użyć klawiszy ${1}.","indent":"Wcięcie","redo":"Ponów","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","tabIndent":"Wcięcie o tabulator","justifyRight":"Wyrównaj do prawej","appleKey":"⌘${0}"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/pt-pt/FontChoice.js b/lib/dijit/_editor/nls/pt-pt/FontChoice.js index dec5354e1..b7b8405c4 100644 --- a/lib/dijit/_editor/nls/pt-pt/FontChoice.js +++ b/lib/dijit/_editor/nls/pt-pt/FontChoice.js @@ -1 +1 @@ -({"1":"xxs","2":"xs","formatBlock":"Formato","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","monospace":"monospace","fontSize":"Tamanho","cursive":"cursive","noFormat":"None"})
\ No newline at end of file +({"noFormat":"Nenhum","1":"xxs","2":"xs","formatBlock":"Formato","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","monospace":"monospace","fontSize":"Tamanho","cursive":"cursive"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/pt-pt/commands.js b/lib/dijit/_editor/nls/pt-pt/commands.js index fbf5182ef..1f4815dfe 100644 --- a/lib/dijit/_editor/nls/pt-pt/commands.js +++ b/lib/dijit/_editor/nls/pt-pt/commands.js @@ -1 +1 @@ -({"removeFormat":"Remover formato","copy":"Copiar","paste":"Colar","selectAll":"Seleccionar tudo","insertOrderedList":"Lista numerada","insertTable":"Inserir/Editar tabela","print":"Imprimir","underline":"Sublinhado","foreColor":"Cor de primeiro plano","htmlToggle":"Origem HTML","formatBlock":"Estilo de parágrafo","newPage":"Nova página","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","fullScreen":"Alternar ecrã completo","italic":"Itálico","fontName":"Nome do tipo de letra","justifyLeft":"Alinhar à esquerda","unlink":"Remover ligação","toggleTableBorder":"Alternar contorno da tabela","viewSource":"Ver origem HTML","fontSize":"Tamanho do tipo de letra","systemShortcut":"A acção \"${0}\" apenas está disponível no navegador utilizando um atalho de teclado. Utilize ${1}.","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","tabIndent":"Indentar com a tecla Tab","justifyRight":"Alinhar à direita","appleKey":"⌘${0}","ctrlKey":"ctrl+${0}"})
\ No newline at end of file +({"removeFormat":"Remover formato","copy":"Copiar","paste":"Colar","selectAll":"Seleccionar tudo","insertOrderedList":"Lista numerada","insertTable":"Inserir/Editar tabela","print":"Imprimir","underline":"Sublinhado","foreColor":"Cor de primeiro plano","htmlToggle":"Código-fonte de HTML","formatBlock":"Estilo de parágrafo","newPage":"Nova página","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","fullScreen":"Alternar ecrã completo","italic":"Itálico","fontName":"Nome do tipo de letra","justifyLeft":"Alinhar à esquerda","unlink":"Remover ligação","toggleTableBorder":"Alternar contorno da tabela","viewSource":"Ver origem HTML","fontSize":"Tamanho do tipo de letra","systemShortcut":"A acção \"${0}\" apenas está disponível no navegador utilizando um atalho de teclado. Utilize ${1}.","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","tabIndent":"Indentar com a tecla Tab","justifyRight":"Alinhar à direita","appleKey":"⌘${0}","ctrlKey":"ctrl+${0}"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/pt/FontChoice.js b/lib/dijit/_editor/nls/pt/FontChoice.js index 50de220af..2ce4785f3 100644 --- a/lib/dijit/_editor/nls/pt/FontChoice.js +++ b/lib/dijit/_editor/nls/pt/FontChoice.js @@ -1 +1 @@ -({"1":"extra-extra-pequeno","2":"extra-pequeno","formatBlock":"Formatar","3":"pequena","4":"médio","5":"grande","6":"extra-grande","7":"extra-extra-grande","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","monospace":"espaço simples","fontSize":"Tamanho","cursive":"cursiva","noFormat":"None"})
\ No newline at end of file +({"noFormat":"Nenhuma","1":"extra-extra-pequeno","2":"extra-pequeno","formatBlock":"Formatar","3":"pequena","4":"médio","5":"grande","6":"extra-grande","7":"extra-extra-grande","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","monospace":"espaço simples","fontSize":"Tamanho","cursive":"cursiva"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/pt/commands.js b/lib/dijit/_editor/nls/pt/commands.js index 271c6cf51..cef0a157e 100644 --- a/lib/dijit/_editor/nls/pt/commands.js +++ b/lib/dijit/_editor/nls/pt/commands.js @@ -1 +1 @@ -({"removeFormat":"Remover Formato","copy":"Copiar","paste":"Colar","selectAll":"Selecionar Todos","insertOrderedList":"Lista Numerada","insertTable":"Inserir/Editar Tabela","print":"Impressão","underline":"Sublinhado","foreColor":"Cor do Primeiro Plano","htmlToggle":"Origem HTML","formatBlock":"Estilo de Parágrafo","newPage":"Nova Página","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","fullScreen":"Comutar Tela Cheia","italic":"Itálico","fontName":"Nome da Fonte","justifyLeft":"Alinhar pela Esquerda","unlink":"Remover Link","toggleTableBorder":"Alternar Moldura da Tabela","viewSource":"Visualizar Origem HTML","fontSize":"Tamanho da Fonte","systemShortcut":"A ação \"${0}\" está disponível em seu navegador apenas usando um atalho do teclado. Use ${1}.","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":"Comutar Direção","bold":"Negrito","tabIndent":"Recuo de Guia","justifyRight":"Alinhar pela Direita","appleKey":"⌘${0}","ctrlKey":"ctrl+${0}"})
\ No newline at end of file +({"removeFormat":"Remover Formato","copy":"Copiar","paste":"Colar","selectAll":"Selecionar Todos","insertOrderedList":"Lista Numerada","insertTable":"Inserir/Editar Tabela","print":"Imprimir","underline":"Sublinhado","foreColor":"Cor do Primeiro Plano","htmlToggle":"Origem HTML","formatBlock":"Estilo de Parágrafo","newPage":"Nova Página","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","fullScreen":"Comutar Tela Cheia","italic":"Itálico","fontName":"Nome da Fonte","justifyLeft":"Alinhar à Esquerda","unlink":"Remover Link","toggleTableBorder":"Alternar Moldura da Tabela","viewSource":"Visualizar Origem HTML","fontSize":"Tamanho da Fonte","systemShortcut":"A ação \"${0}\" está disponível em seu navegador apenas usando um atalho de teclado. Use ${1}.","indent":"Recuar","redo":"Refazer","strikethrough":"Tachado","justifyFull":"Justificar","justifyCenter":"Alinhar pelo Centro","hiliteColor":"Cor do Segundo Plano","deleteTable":"Excluir Tabela","outdent":"Não chanfrado","cut":"Recortar","plainFormatBlock":"Estilo de Parágrafo","toggleDir":"Comutar Direção","bold":"Negrito","tabIndent":"Recuo de Guia","justifyRight":"Alinhar à Direita","appleKey":"⌘${0}","ctrlKey":"ctrl+${0}"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/ro/LinkDialog.js b/lib/dijit/_editor/nls/ro/LinkDialog.js index c3cfb3990..fba0a8423 100644 --- a/lib/dijit/_editor/nls/ro/LinkDialog.js +++ b/lib/dijit/_editor/nls/ro/LinkDialog.js @@ -1 +1 @@ -({"text":"Descriere:","insertImageTitle":"Proprietăţi imagine","set":"Setare","newWindow":"Fereastră nouă","topWindow":"Fereastra cea mai de sus","target":"Ţintă:","createLinkTitle":"Proprietăţi legătură","parentWindow":"Fereastra părinte","currentWindow":"Fereastra curentă","url":"URL:"})
\ No newline at end of file +({"text":"Descriere:","insertImageTitle":"Proprietăţi imagine","set":"Setare","newWindow":"Fereastra nouă","topWindow":"Fereastra cea mai de sus","target":"Destinaţie:","createLinkTitle":"Proprietăţi legătură","parentWindow":"Fereastra părinte","currentWindow":"Fereastra curentă","url":"URL:"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/ro/commands.js b/lib/dijit/_editor/nls/ro/commands.js index f73017cbf..776bcb3ae 100644 --- a/lib/dijit/_editor/nls/ro/commands.js +++ b/lib/dijit/_editor/nls/ro/commands.js @@ -1 +1 @@ -({"removeFormat":"Înlăturare format","copy":"Copiere","paste":"Lipire","selectAll":"Selectare toate","insertOrderedList":"Listă numerotată","insertTable":"Inserare/Editare tabelă","print":"Tipărire","underline":"Subliniere","foreColor":"Culoare prim plan","htmlToggle":"Sursă HTML","formatBlock":"Stil paragraf","newPage":"Pagină nouă","insertHorizontalRule":"Regulă orizontală","delete":"Ştergere","insertUnorderedList":"Listă cu marcaje","tableProp":"Proprietăţi tabelă","insertImage":"Inserare imagine","superscript":"Scriere indice superior","subscript":"Scriere indice inferior","createLink":"Creare legătură","undo":"Anulare acţiune","fullScreen":"Comutare ecran complet","italic":"Cursive","fontName":"Nume font","justifyLeft":"Aliniere la stânga","unlink":"Înlăturare legătură","toggleTableBorder":"Comutare bordură tabelă","viewSource":"Vizualizare sursă HTML","fontSize":"Dimensiune font","systemShortcut":"Acţiunea \"${0}\" este disponibilă în browser folosind o scurtătură de la tastatură. Folosiţi ${1}.","indent":"Indentare","redo":"Repetare acţiune","strikethrough":"Suprascriere linie","justifyFull":"Aliniere","justifyCenter":"Aliniere pe centru","hiliteColor":"Culoare fundal","deleteTable":"Ştergere tabelă","outdent":"Outdentare","cut":"Tăiere","plainFormatBlock":"Stil paragraf","toggleDir":"Comutare direcţie","bold":"Aldine","tabIndent":"Indentare cu tab","justifyRight":"Aliniere la dreapta","appleKey":"⌘${0}","ctrlKey":"ctrl+${0}"})
\ No newline at end of file +({"removeFormat":"Înlăturare format","copy":"Copiere","paste":"Lipire","selectAll":"Selectează tot","insertOrderedList":"Listă numerotată","insertTable":"Inserare/Editare tabelă","print":"Tipărire","underline":"Subliniere","foreColor":"Culoare de prim-plan","htmlToggle":"Sursă HTML","formatBlock":"Stil paragraf","newPage":"Pagină nouă","insertHorizontalRule":"Linie delimitatoare","delete":"Ştergere","insertUnorderedList":"Listă cu marcator","tableProp":"Proprietate tabelă","insertImage":"Inserare imagine","superscript":"Scriere indice superior","subscript":"Scriere indice inferior","createLink":"Creare legătură","undo":"Anulare acţiune","fullScreen":"Comutare ecran complet","italic":"Cursiv","fontName":"Nume font","justifyLeft":"Aliniere stânga","unlink":"Înlăturare legătură","toggleTableBorder":"Comutare bordură tabelă","viewSource":"Vizualizara sursă HTML","fontSize":"Dimensiune font","systemShortcut":"Acţiunea \"${0}\" este disponibilă în browser doar utilizând o comandă rapidă de la tastatură. Utilizaţi ${1}.","indent":"Micşorare indent","redo":"Refacere acţiune","strikethrough":"Tăiere text cu o linie","justifyFull":"Aliniere stânga-dreapta","justifyCenter":"Aliniere centru","hiliteColor":"Culoare de fundal","deleteTable":"Ştergere tabelă","outdent":"Mărire indent","cut":"Tăiere","plainFormatBlock":"Stil paragraf","toggleDir":"Comutare direcţie","bold":"Aldin","tabIndent":"Indentare Tab","justifyRight":"Aliniere dreapta","appleKey":"⌘${0}","ctrlKey":"ctrl+${0}"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/ru/FontChoice.js b/lib/dijit/_editor/nls/ru/FontChoice.js index bdc10430a..b836589cf 100644 --- a/lib/dijit/_editor/nls/ru/FontChoice.js +++ b/lib/dijit/_editor/nls/ru/FontChoice.js @@ -1 +1 @@ -({"1":"самый маленький","2":"очень маленький","formatBlock":"Формат","3":"маленький","4":"средний","5":"большой","6":"очень большой","7":"самый большой","fantasy":"артистический","serif":"с засечками","p":"Абзац","pre":"Заранее отформатированный","sans-serif":"без засечек","fontName":"Шрифт","h1":"Заголовок","h2":"Подзаголовок","h3":"Вложенный подзаголовок","monospace":"непропорциональный","fontSize":"Размер","cursive":"курсив","noFormat":"None"})
\ No newline at end of file +({"noFormat":"Нет","1":"самый маленький","2":"очень маленький","formatBlock":"Формат","3":"маленький","4":"средний","5":"большой","6":"очень большой","7":"самый большой","fantasy":"артистический","serif":"с засечками","p":"Абзац","pre":"Заранее отформатированный","sans-serif":"без засечек","fontName":"Шрифт","h1":"Заголовок","h2":"Подзаголовок","h3":"Вложенный подзаголовок","monospace":"непропорциональный","fontSize":"Размер","cursive":"курсив"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/ru/LinkDialog.js b/lib/dijit/_editor/nls/ru/LinkDialog.js index ddc2f7b0f..0b91f4c09 100644 --- a/lib/dijit/_editor/nls/ru/LinkDialog.js +++ b/lib/dijit/_editor/nls/ru/LinkDialog.js @@ -1 +1 @@ -({"text":"Описание:","insertImageTitle":"Свойства изображения","set":"Задать","newWindow":"Новое окно","topWindow":"Окно верхнего уровня","target":"Целевой объект:","createLinkTitle":"Свойства ссылки","parentWindow":"Родительское окно","currentWindow":"Текущее окно","url":"URL:"})
\ No newline at end of file +({"text":"Описание:","insertImageTitle":"Свойства изображения","set":"Задать","newWindow":"Новое окно","topWindow":"Верхнее окно","target":"Целевой объект:","createLinkTitle":"Свойства ссылки","parentWindow":"Родительское окно","currentWindow":"Текущее окно","url":"URL:"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/sk/FontChoice.js b/lib/dijit/_editor/nls/sk/FontChoice.js index b7415e83d..afe267bcc 100644 --- a/lib/dijit/_editor/nls/sk/FontChoice.js +++ b/lib/dijit/_editor/nls/sk/FontChoice.js @@ -1 +1 @@ -({"1":"xx-small","2":"x-small","formatBlock":"Formát","3":"small","4":"medium","5":"large","6":"x-large","7":"xx-large","fantasy":"fantasy","serif":"serif","p":"Odsek","pre":"Predformátované","sans-serif":"sans-serif","fontName":"Písmo","h1":"Hlavička","h2":"Podhlavička","h3":"Pod-podhlavička","monospace":"monospace","fontSize":"Veľkosť","cursive":"cursive","noFormat":"None"})
\ No newline at end of file +({"noFormat":"Žiadny","1":"xx-small","2":"x-small","formatBlock":"Formát","3":"small","4":"medium","5":"large","6":"x-large","7":"xx-large","fantasy":"fantasy","serif":"serif","p":"Odsek","pre":"Predformátované","sans-serif":"sans-serif","fontName":"Písmo","h1":"Hlavička","h2":"Podhlavička","h3":"Pod-podhlavička","monospace":"monospace","fontSize":"Veľkosť","cursive":"cursive"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/sl/FontChoice.js b/lib/dijit/_editor/nls/sl/FontChoice.js index 2dcfed191..e6fe9d303 100644 --- a/lib/dijit/_editor/nls/sl/FontChoice.js +++ b/lib/dijit/_editor/nls/sl/FontChoice.js @@ -1 +1 @@ -({"1":"xx-majhno","2":"x-majhno","formatBlock":"Oblika","3":"majhno","4":"srednje","5":"veliko","6":"x-veliko","7":"xx-veliko","fantasy":"fantasy","serif":"serif","p":"Odstavek","pre":"Vnaprej oblikovano","sans-serif":"sans-serif","fontName":"Pisava","h1":"Naslov","h2":"Podnaslov","h3":"Pod podnaslov","monospace":"monospace","fontSize":"Velikost","cursive":"cursive","noFormat":"None"})
\ No newline at end of file +({"noFormat":"Brez","1":"xx-majhno","2":"x-majhno","formatBlock":"Oblika","3":"majhno","4":"srednje","5":"veliko","6":"x-veliko","7":"xx-veliko","fantasy":"fantasy","serif":"serif","p":"Odstavek","pre":"Vnaprej oblikovan","sans-serif":"sans-serif","fontName":"Pisava","h1":"Naslovni slog","h2":"Podnaslovni slog","h3":"Pod-podnaslovni slog","monospace":"monospace","fontSize":"Velikost","cursive":"cursive"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/sl/LinkDialog.js b/lib/dijit/_editor/nls/sl/LinkDialog.js index bad7dd641..e485a4163 100644 --- a/lib/dijit/_editor/nls/sl/LinkDialog.js +++ b/lib/dijit/_editor/nls/sl/LinkDialog.js @@ -1 +1 @@ -({"text":"Opis:","insertImageTitle":"Lastnosti slike","set":"Nastavi","newWindow":"Novo okno","topWindow":"Najvišje okno","target":"Cilj:","createLinkTitle":"Lastnosti povezave","parentWindow":"Nadrejeno okno","currentWindow":"Trenutno okno","url":"URL:"})
\ No newline at end of file +({"text":"Opis:","insertImageTitle":"Lastnosti slike","set":"Nastavi","newWindow":"Novo okno","topWindow":"Okno na vrhu","target":"Cilj:","createLinkTitle":"Lastnosti povezave","parentWindow":"Nadrejeno okno","currentWindow":"Trenutno okno","url":"URL:"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/sl/commands.js b/lib/dijit/_editor/nls/sl/commands.js index 72431aa71..e40b8033b 100644 --- a/lib/dijit/_editor/nls/sl/commands.js +++ b/lib/dijit/_editor/nls/sl/commands.js @@ -1 +1 @@ -({"removeFormat":"Odstrani obliko zapisa","copy":"Prekopiraj","paste":"Prilepi","selectAll":"Izberi vse","insertOrderedList":"Oštevilčen seznam","insertTable":"Vstavi/uredi tabelo","print":"Natisni","underline":"Podčrtano","foreColor":"Barva ospredja","htmlToggle":"Izvorna koda HTML","formatBlock":"Slog odstavka","newPage":"Nova stran","insertHorizontalRule":"Vodoravno ravnilo","delete":"Izbriši","insertUnorderedList":"Naštevni seznam","tableProp":"Lastnost tabele","insertImage":"Vstavi sliko","superscript":"Nadpisano","subscript":"Podpisano","createLink":"Ustvari povezavo","undo":"Razveljavi","fullScreen":"Preklopi na celozaslonski način","italic":"Ležeče","fontName":"Ime pisave","justifyLeft":"Poravnaj levo","unlink":"Odstrani povezavo","toggleTableBorder":"Preklopi na rob tabele","viewSource":"Prikaži izvorno kodo HTML","fontSize":"Velikost pisave","systemShortcut":"Dejanje \"${0}\" lahko v vašem brskalniku uporabite samo z bližnjico na tipkovnici. Uporabite ${1}.","indent":"Zamik","redo":"Znova uveljavi","strikethrough":"Prečrtano","justifyFull":"Obojestranska poravnava","justifyCenter":"Poravnaj na sredino","hiliteColor":"Barva ozadja","deleteTable":"Izbriši tabelo","outdent":"Viseč odstavek","cut":"Izreži","plainFormatBlock":"Slog odstavka","toggleDir":"Preklopi na usmeritev","bold":"Krepko","tabIndent":"Zamik tabulatorja","justifyRight":"Poravnaj desno","appleKey":"⌘${0}","ctrlKey":"ctrl+${0}"})
\ No newline at end of file +({"removeFormat":"Odstrani oblikovanje","copy":"Prekopiraj","paste":"Prilepi","selectAll":"Izberi vse","insertOrderedList":"Oštevilčen seznam","insertTable":"Vstavi/uredi tabelo","print":"Natisni","underline":"Podčrtano","foreColor":"Barva ospredja","htmlToggle":"Izvorna koda HTML","formatBlock":"Slog odstavka","newPage":"Nova stran","insertHorizontalRule":"Vodoravno ravnilo","delete":"Izbriši","insertUnorderedList":"Naštevni seznam","tableProp":"Lastnost tabele","insertImage":"Vstavi sliko","superscript":"Nadpisano","subscript":"Podpisano","createLink":"Ustvari povezavo","undo":"Razveljavi","fullScreen":"Preklopi na celozaslonski način","italic":"Ležeče","fontName":"Ime pisave","justifyLeft":"Poravnaj levo","unlink":"Odstrani povezavo","toggleTableBorder":"Preklopi na rob tabele","viewSource":"Prikaži izvorno kodo HTML","fontSize":"Velikost pisave","systemShortcut":"Dejanje \"${0}\" lahko v vašem brskalniku uporabite samo z bližnjico na tipkovnici. Uporabite ${1}.","indent":"Zamik","redo":"Znova uveljavi","strikethrough":"Prečrtano","justifyFull":"Poravnaj obojestransko","justifyCenter":"Poravnaj na sredino","hiliteColor":"Barva ozadja","deleteTable":"Izbriši tabelo","outdent":"Primakni","cut":"Izreži","plainFormatBlock":"Slog odstavka","toggleDir":"Preklopi smer","bold":"Krepko","tabIndent":"Zamik tabulatorja","justifyRight":"Poravnaj desno","appleKey":"⌘${0}","ctrlKey":"ctrl+${0}"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/sv/FontChoice.js b/lib/dijit/_editor/nls/sv/FontChoice.js index a778cc83b..0637af9ff 100644 --- a/lib/dijit/_editor/nls/sv/FontChoice.js +++ b/lib/dijit/_editor/nls/sv/FontChoice.js @@ -1 +1 @@ -({"1":"mycket, mycket litet","2":"mycket litet","formatBlock":"Format","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","monospace":"monospace","fontSize":"Storlek","cursive":"kursivt","noFormat":"None"})
\ No newline at end of file +({"noFormat":"Ingen","1":"mycket, mycket litet","2":"mycket litet","formatBlock":"Format","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","monospace":"monospace","fontSize":"Storlek","cursive":"kursivt"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/th/FontChoice.js b/lib/dijit/_editor/nls/th/FontChoice.js index c3e8f811d..02688efaa 100644 --- a/lib/dijit/_editor/nls/th/FontChoice.js +++ b/lib/dijit/_editor/nls/th/FontChoice.js @@ -1 +1 @@ -({"1":"xx-small","2":"x-small","formatBlock":"รูปแบบ","3":"small","4":"medium","5":"large","6":"x-large","7":"xx-large","fantasy":"fantasy","serif":"serif","p":"ย่อหน้า","pre":"การกำหนดรูปแบบล่วงหน้า","sans-serif":"sans-serif","fontName":"ฟอนต์","h1":"ส่วนหัว","h2":"ส่วนหัวย่อย","h3":"ส่วนย่อยของส่วนหัวย่อย","monospace":"monospace","fontSize":"ขนาด","cursive":"cursive","noFormat":"None"})
\ No newline at end of file +({"noFormat":"ไม่มี","1":"xx-small","2":"x-small","formatBlock":"รูปแบบ","3":"small","4":"medium","5":"large","6":"x-large","7":"xx-large","fantasy":"fantasy","serif":"serif","p":"ย่อหน้า","pre":"การกำหนดรูปแบบล่วงหน้า","sans-serif":"sans-serif","fontName":"ฟอนต์","h1":"ส่วนหัว","h2":"ส่วนหัวย่อย","h3":"ส่วนย่อยของส่วนหัวย่อย","monospace":"monospace","fontSize":"ขนาด","cursive":"cursive"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/th/LinkDialog.js b/lib/dijit/_editor/nls/th/LinkDialog.js index d571c53b4..4d1aeb296 100644 --- a/lib/dijit/_editor/nls/th/LinkDialog.js +++ b/lib/dijit/_editor/nls/th/LinkDialog.js @@ -1 +1 @@ -({"text":"รายละเอียด","insertImageTitle":"คุณสมบัติอิมเมจ","set":"ตั้งค่า","newWindow":"หน้าต่างใหม่","topWindow":"หน้าต่างบนสุด","target":"เป้าหมาย:","createLinkTitle":"คุณสมบัติลิงก์","parentWindow":"หน้าต่างหลัก","currentWindow":"หน้าต่างปัจจุบัน","url":"URL:"})
\ No newline at end of file +({"text":"รายละเอียด:","insertImageTitle":"คุณสมบัติอิมเมจ","set":"ตั้งค่า","newWindow":"หน้าต่างใหม่","topWindow":"หน้าต่างบนสุด","target":"เป้าหมาย:","createLinkTitle":"คุณสมบัติลิงก์","parentWindow":"หน้าต่างหลัก","currentWindow":"หน้าต่างปัจจุบัน","url":"URL:"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/tr/FontChoice.js b/lib/dijit/_editor/nls/tr/FontChoice.js index c9cdfea53..28173c929 100644 --- a/lib/dijit/_editor/nls/tr/FontChoice.js +++ b/lib/dijit/_editor/nls/tr/FontChoice.js @@ -1 +1 @@ -({"1":"xx-küçük","2":"x-küçük","formatBlock":"Biçim","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","monospace":"tek aralıklı","fontSize":"Boyut","cursive":"el yazısı","noFormat":"None"})
\ No newline at end of file +({"noFormat":"Yok","1":"xx-küçük","2":"x-küçük","formatBlock":"Biçim","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","monospace":"tek aralıklı","fontSize":"Boyut","cursive":"el yazısı"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/zh-tw/FontChoice.js b/lib/dijit/_editor/nls/zh-tw/FontChoice.js index b821ec0ec..006977983 100644 --- a/lib/dijit/_editor/nls/zh-tw/FontChoice.js +++ b/lib/dijit/_editor/nls/zh-tw/FontChoice.js @@ -1 +1 @@ -({"1":"最小","2":"較小","formatBlock":"格式","3":"小","4":"中","5":"大","6":"較大","7":"最大","fantasy":"Fantasy","serif":"新細明體","p":"段落","pre":"預先格式化","sans-serif":"新細明體","fontName":"字型","h1":"標題","h2":"子標題","h3":"次子標題","monospace":"等寬","fontSize":"大小","cursive":"Cursive","noFormat":"None"})
\ No newline at end of file +({"noFormat":"無","1":"最小","2":"較小","formatBlock":"格式","3":"小","4":"中","5":"大","6":"較大","7":"最大","fantasy":"Fantasy","serif":"新細明體","p":"段落","pre":"預先格式化","sans-serif":"新細明體","fontName":"字型","h1":"標題","h2":"子標題","h3":"次子標題","monospace":"等寬","fontSize":"大小","cursive":"Cursive"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/zh-tw/commands.js b/lib/dijit/_editor/nls/zh-tw/commands.js index d72dc4ec4..17f6fea49 100644 --- a/lib/dijit/_editor/nls/zh-tw/commands.js +++ b/lib/dijit/_editor/nls/zh-tw/commands.js @@ -1 +1 @@ -({"removeFormat":"移除格式","copy":"複製","paste":"貼上","selectAll":"全選","insertOrderedList":"編號清單","insertTable":"插入/編輯表格","print":"列印","underline":"底線","foreColor":"前景顏色","htmlToggle":"HTML 原始檔","formatBlock":"段落樣式","newPage":"新建頁面","insertHorizontalRule":"水平尺規","delete":"刪除","insertUnorderedList":"項目符號清單","tableProp":"表格內容","insertImage":"插入影像","superscript":"上標","subscript":"下標","createLink":"建立鏈結","undo":"復原","fullScreen":"切換全螢幕","italic":"斜體","fontName":"字型名稱","justifyLeft":"靠左對齊","unlink":"移除鏈結","toggleTableBorder":"切換表格邊框","viewSource":"檢視 HTML 原始檔","fontSize":"字型大小","systemShortcut":"\"${0}\" 動作只能在瀏覽器中透過使用鍵盤快速鍵來使用。請使用 ${1}。","indent":"縮排","redo":"重做","strikethrough":"加刪除線","justifyFull":"對齊","justifyCenter":"置中對齊","hiliteColor":"背景顏色","deleteTable":"刪除表格","outdent":"凸排","cut":"剪下","plainFormatBlock":"段落樣式","toggleDir":"切換方向","bold":"粗體","tabIndent":"定位點縮排","justifyRight":"靠右對齊","appleKey":"⌘${0}","ctrlKey":"ctrl+${0}"})
\ No newline at end of file +({"removeFormat":"移除格式","copy":"複製","paste":"貼上","selectAll":"全選","insertOrderedList":"編號清單","insertTable":"插入/編輯表格","print":"列印","underline":"底線","foreColor":"前景顏色","htmlToggle":"HTML 原始檔","formatBlock":"段落樣式","newPage":"新頁面","insertHorizontalRule":"水平尺規","delete":"刪除","insertUnorderedList":"項目符號清單","tableProp":"表格內容","insertImage":"插入影像","superscript":"上標","subscript":"下標","createLink":"建立鏈結","undo":"復原","fullScreen":"切換全螢幕","italic":"斜體","fontName":"字型名稱","justifyLeft":"靠左對齊","unlink":"移除鏈結","toggleTableBorder":"切換表格邊框","viewSource":"檢視 HTML 原始檔","fontSize":"字型大小","systemShortcut":"\"${0}\" 動作在您的瀏覽器中,只能使用鍵盤快速鍵。請使用 ${1}。","indent":"縮排","redo":"重做","strikethrough":"刪除線","justifyFull":"對齊","justifyCenter":"置中對齊","hiliteColor":"背景顏色","deleteTable":"刪除表格","outdent":"凸排","cut":"剪下","plainFormatBlock":"段落樣式","toggleDir":"切換方向","bold":"粗體","tabIndent":"標籤縮排","justifyRight":"靠右對齊","appleKey":"⌘${0}","ctrlKey":"ctrl+${0}"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/zh/FontChoice.js b/lib/dijit/_editor/nls/zh/FontChoice.js index 4d52bb78e..a9850c7fd 100644 --- a/lib/dijit/_editor/nls/zh/FontChoice.js +++ b/lib/dijit/_editor/nls/zh/FontChoice.js @@ -1 +1 @@ -({"1":"XXS 号","2":"XS 号","formatBlock":"格式","3":"S 号","4":"M 号","5":"L 号","6":"XL 号","7":"XXL 号","fantasy":"虚线","serif":"有衬线","p":"段落","pre":"预设有格式的","sans-serif":"无衬线","fontName":"字体","h1":"标题","h2":"子标题","h3":"二级子标题","monospace":"等宽字体","fontSize":"大小","cursive":"草书","noFormat":"None"})
\ No newline at end of file +({"noFormat":"无","1":"XXS 号","2":"XS 号","formatBlock":"格式","3":"S 号","4":"M 号","5":"L 号","6":"XL 号","7":"XXL 号","fantasy":"虚线","serif":"有衬线","p":"段落","pre":"预设有格式的","sans-serif":"无衬线","fontName":"字体","h1":"标题","h2":"子标题","h3":"二级子标题","monospace":"等宽字体","fontSize":"大小","cursive":"草书"})
\ No newline at end of file diff --git a/lib/dijit/_editor/nls/zh/LinkDialog.js b/lib/dijit/_editor/nls/zh/LinkDialog.js index da4c50026..5b5390fbc 100644 --- a/lib/dijit/_editor/nls/zh/LinkDialog.js +++ b/lib/dijit/_editor/nls/zh/LinkDialog.js @@ -1 +1 @@ -({"text":"描述:","insertImageTitle":"图像属性","set":"设置","newWindow":"新窗口","topWindow":"最顶部窗口","target":"目标:","createLinkTitle":"链接属性","parentWindow":"父窗口","currentWindow":"当前窗口","url":"URL:"})
\ No newline at end of file +({"text":"描述:","insertImageTitle":"图像属性","set":"设置","newWindow":"新建窗口","topWindow":"顶层窗口","target":"目标:","createLinkTitle":"链接属性","parentWindow":"父窗口","currentWindow":"当前窗口","url":"URL:"})
\ No newline at end of file diff --git a/lib/dijit/_editor/plugins/AlwaysShowToolbar.js b/lib/dijit/_editor/plugins/AlwaysShowToolbar.js index 1e0e2ed3f..9d0b7ded8 100644 --- a/lib/dijit/_editor/plugins/AlwaysShowToolbar.js +++ b/lib/dijit/_editor/plugins/AlwaysShowToolbar.js @@ -1,119 +1,190 @@ /* - Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved. + Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved. Available via Academic Free License >= 2.1 OR the modified BSD license. see: http://dojotoolkit.org/license for details */ -if(!dojo._hasResource["dijit._editor.plugins.AlwaysShowToolbar"]){ -dojo._hasResource["dijit._editor.plugins.AlwaysShowToolbar"]=true; +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){ -if(!e.iframe){ -return; -} -this.editor=e; -e.onLoadDeferred.addCallback(dojo.hitch(this,this.enable)); -},enable:function(d){ -this._updateHeight(); -this.connect(window,"onscroll","globalOnScrollHandler"); -this.connect(this.editor,"onNormalizedDisplayChanged","_updateHeight"); -return d; -},_updateHeight:function(){ -var e=this.editor; -if(!e.isLoaded){ -return; -} -if(e.height){ -return; -} -var _1=dojo.marginBox(e.editNode).h; -if(dojo.isOpera){ -_1=e.editNode.scrollHeight; -} -if(!_1){ -_1=dojo.marginBox(e.document.body).h; -} -if(_1==0){ -return; -} -if(dojo.isIE<=7&&this.editor.minHeight){ -var _2=parseInt(this.editor.minHeight); -if(_1<_2){ -_1=_2; -} -} -if(_1!=this._lastHeight){ -this._lastHeight=_1; -dojo.marginBox(e.iframe,{h:this._lastHeight}); -} -},_lastHeight:0,globalOnScrollHandler:function(){ -var _3=dojo.isIE<7; -if(!this._handleScroll){ -return; -} -var _4=this.editor.header; -var db=dojo.body; -if(!this._scrollSetUp){ -this._scrollSetUp=true; -this._scrollThreshold=dojo.position(_4,true).y; -} -var _5=dojo._docScroll().y; -var s=_4.style; -if(_5>this._scrollThreshold&&_5<this._scrollThreshold+this._lastHeight){ -if(!this._fixEnabled){ -var _6=dojo.marginBox(_4); -this.editor.iframe.style.marginTop=_6.h+"px"; -if(_3){ -s.left=dojo.position(_4).x; -if(_4.previousSibling){ -this._IEOriginalPos=["after",_4.previousSibling]; -}else{ -if(_4.nextSibling){ -this._IEOriginalPos=["before",_4.nextSibling]; -}else{ -this._IEOriginalPos=["last",_4.parentNode]; -} -} -dojo.body().appendChild(_4); -dojo.addClass(_4,"dijitIEFixedToolbar"); -}else{ -s.position="fixed"; -s.top="0px"; -} -dojo.marginBox(_4,{w:_6.w}); -s.zIndex=2000; -this._fixEnabled=true; -} -var _7=(this.height)?parseInt(this.editor.height):this.editor._lastHeight; -s.display=(_5>this._scrollThreshold+_7)?"none":""; -}else{ -if(this._fixEnabled){ -this.editor.iframe.style.marginTop=""; -s.position=""; -s.top=""; -s.zIndex=""; -s.display=""; -if(_3){ -s.left=""; -dojo.removeClass(_4,"dijitIEFixedToolbar"); -if(this._IEOriginalPos){ -dojo.place(_4,this._IEOriginalPos[1],this._IEOriginalPos[0]); -this._IEOriginalPos=null; -}else{ -dojo.place(_4,this.editor.iframe,"before"); -} -} -s.width=""; -this._fixEnabled=false; -} -} -},destroy:function(){ -this._IEOriginalPos=null; -this._handleScroll=false; -dojo.forEach(this._connects,dojo.disconnect); -if(dojo.isIE<7){ -dojo.removeClass(this.editor.header,"dijitIEFixedToolbar"); -} -}}); +dojo.require("dijit._editor._Plugin"); + + +dojo.declare("dijit._editor.plugins.AlwaysShowToolbar", dijit._editor._Plugin, + { + // summary: + // This plugin is required for Editors in auto-expand mode. + // It handles the auto-expansion as the user adds/deletes text, + // and keeps the editor's toolbar visible even when the top of the editor + // has scrolled off the top of the viewport (usually when editing a long + // document). + // description: + // Specify this in extraPlugins (or plugins) parameter and also set + // height to "". + // example: + // | <div dojoType="dijit.Editor" height="" + // | extraPlugins="['dijit._editor.plugins.AlwaysShowToolbar']"> + + // _handleScroll: Boolean + // Enables/disables the handler for scroll events + _handleScroll: true, + + setEditor: function(e){ + // Overrides _Plugin.setEditor(). + if(!e.iframe){ + console.log('Port AlwaysShowToolbar plugin to work with Editor without iframe'); + return; + } + + this.editor = e; + + e.onLoadDeferred.addCallback(dojo.hitch(this, this.enable)); + }, + + enable: function(d){ + // summary: + // Enable plugin. Called when Editor has finished initializing. + // tags: + // private + + 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._getMarginSize(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._getMarginSize(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(dojo.isIE <= 7 && this.editor.minHeight){ + var min = parseInt(this.editor.minHeight); + if(height < min){ height = min; } + } + if(height != this._lastHeight){ + this._lastHeight = height; + // this.editorObject.style.height = this._lastHeight + "px"; + dojo.marginBox(e.iframe, { h: this._lastHeight }); + } + }, + + // _lastHeight: Integer + // Height in px of the editor at the last time we did sizing + _lastHeight: 0, + + globalOnScrollHandler: function(){ + // summary: + // Handler for scroll events that bubbled up to <html> + // tags: + // private + + var isIE6 = dojo.isIE < 7; + if(!this._handleScroll){ return; } + var tdn = this.editor.header; + var db = dojo.body; + + if(!this._scrollSetUp){ + this._scrollSetUp = true; + this._scrollThreshold = dojo.position(tdn, true).y; +// console.log("threshold:", this._scrollThreshold); + //what's this for?? comment out for now +// if((isIE6)&&(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._getMarginSize(tdn); + this.editor.iframe.style.marginTop = tdnbox.h+"px"; + + if(isIE6){ + s.left = dojo.position(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(isIE6){ + 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(){ + // Overrides _Plugin.destroy(). TODO: call this.inherited() rather than repeating code. + this._IEOriginalPos = null; + this._handleScroll = false; + dojo.forEach(this._connects, dojo.disconnect); +// clearInterval(this.scrollInterval); + + if(dojo.isIE < 7){ + dojo.removeClass(this.editor.header, 'dijitIEFixedToolbar'); + } + } +}); + } diff --git a/lib/dijit/_editor/plugins/EnterKeyHandling.js b/lib/dijit/_editor/plugins/EnterKeyHandling.js index 51a8fdde8..670d491ae 100644 --- a/lib/dijit/_editor/plugins/EnterKeyHandling.js +++ b/lib/dijit/_editor/plugins/EnterKeyHandling.js @@ -1,423 +1,604 @@ /* - Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved. + Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved. Available via Academic Free License >= 2.1 OR the modified BSD license. see: http://dojotoolkit.org/license for details */ -if(!dojo._hasResource["dijit._editor.plugins.EnterKeyHandling"]){ -dojo._hasResource["dijit._editor.plugins.EnterKeyHandling"]=true; +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.require("dojo.window"); -dojo.declare("dijit._editor.plugins.EnterKeyHandling",dijit._editor._Plugin,{blockNodeForEnter:"BR",constructor:function(_1){ -if(_1){ -dojo.mixin(this,_1); -} -},setEditor:function(_2){ -this.editor=_2; -if(this.blockNodeForEnter=="BR"){ -if(dojo.isIE){ -_2.contentDomPreFilters.push(dojo.hitch(this,"regularPsToSingleLinePs")); -_2.contentDomPostFilters.push(dojo.hitch(this,"singleLinePsToRegularPs")); -_2.onLoadDeferred.addCallback(dojo.hitch(this,"_fixNewLineBehaviorForIE")); -}else{ -_2.onLoadDeferred.addCallback(dojo.hitch(this,function(d){ -try{ -this.editor.document.execCommand("insertBrOnReturn",false,true); -} -catch(e){ -} -return d; -})); -} -}else{ -if(this.blockNodeForEnter){ -dojo["require"]("dijit._editor.range"); -var h=dojo.hitch(this,this.handleEnterKey); -_2.addKeyHandler(13,0,0,h); -_2.addKeyHandler(13,0,1,h); -this.connect(this.editor,"onKeyPressed","onKeyPressed"); -} -} -},onKeyPressed:function(e){ -if(this._checkListLater){ -if(dojo.withGlobal(this.editor.window,"isCollapsed",dijit)){ -var _3=dojo.withGlobal(this.editor.window,"getAncestorElement",dijit._editor.selection,["LI"]); -if(!_3){ -dijit._editor.RichText.prototype.execCommand.call(this.editor,"formatblock",this.blockNodeForEnter); -var _4=dojo.withGlobal(this.editor.window,"getAncestorElement",dijit._editor.selection,[this.blockNodeForEnter]); -if(_4){ -_4.innerHTML=this.bogusHtmlContent; -if(dojo.isIE){ -var r=this.editor.document.selection.createRange(); -r.move("character",-1); -r.select(); -} -}else{ -console.error("onKeyPressed: Cannot find the new block node"); -} -}else{ -if(dojo.isMoz){ -if(_3.parentNode.parentNode.nodeName=="LI"){ -_3=_3.parentNode.parentNode; -} -} -var fc=_3.firstChild; -if(fc&&fc.nodeType==1&&(fc.nodeName=="UL"||fc.nodeName=="OL")){ -_3.insertBefore(fc.ownerDocument.createTextNode(" "),fc); -var _5=dijit.range.create(this.editor.window); -_5.setStart(_3.firstChild,0); -var _6=dijit.range.getSelection(this.editor.window,true); -_6.removeAllRanges(); -_6.addRange(_5); -} -} -} -this._checkListLater=false; -} -if(this._pressedEnterInBlock){ -if(this._pressedEnterInBlock.previousSibling){ -this.removeTrailingBr(this._pressedEnterInBlock.previousSibling); -} -delete this._pressedEnterInBlock; -} -},bogusHtmlContent:" ",blockNodes:/^(?:P|H1|H2|H3|H4|H5|H6|LI)$/,handleEnterKey:function(e){ -var _7,_8,_9,_a=this.editor.document,br; -if(e.shiftKey){ -var _b=dojo.withGlobal(this.editor.window,"getParentElement",dijit._editor.selection); -var _c=dijit.range.getAncestor(_b,this.blockNodes); -if(_c){ -if(!e.shiftKey&&_c.tagName=="LI"){ -return true; -} -_7=dijit.range.getSelection(this.editor.window); -_8=_7.getRangeAt(0); -if(!_8.collapsed){ -_8.deleteContents(); -_7=dijit.range.getSelection(this.editor.window); -_8=_7.getRangeAt(0); -} -if(dijit.range.atBeginningOfContainer(_c,_8.startContainer,_8.startOffset)){ -if(e.shiftKey){ -br=_a.createElement("br"); -_9=dijit.range.create(this.editor.window); -_c.insertBefore(br,_c.firstChild); -_9.setStartBefore(br.nextSibling); -_7.removeAllRanges(); -_7.addRange(_9); -}else{ -dojo.place(br,_c,"before"); -} -}else{ -if(dijit.range.atEndOfContainer(_c,_8.startContainer,_8.startOffset)){ -_9=dijit.range.create(this.editor.window); -br=_a.createElement("br"); -if(e.shiftKey){ -_c.appendChild(br); -_c.appendChild(_a.createTextNode(" ")); -_9.setStart(_c.lastChild,0); -}else{ -dojo.place(br,_c,"after"); -_9.setStartAfter(_c); -} -_7.removeAllRanges(); -_7.addRange(_9); -}else{ -return true; -} -} -}else{ -dijit._editor.RichText.prototype.execCommand.call(this.editor,"inserthtml","<br>"); -} -return false; -} -var _d=true; -_7=dijit.range.getSelection(this.editor.window); -_8=_7.getRangeAt(0); -if(!_8.collapsed){ -_8.deleteContents(); -_7=dijit.range.getSelection(this.editor.window); -_8=_7.getRangeAt(0); -} -var _e=dijit.range.getBlockAncestor(_8.endContainer,null,this.editor.editNode); -var _f=_e.blockNode; -if((this._checkListLater=(_f&&(_f.nodeName=="LI"||_f.parentNode.nodeName=="LI")))){ -if(dojo.isMoz){ -this._pressedEnterInBlock=_f; -} -if(/^(\s| |\xA0|<span\b[^>]*\bclass=['"]Apple-style-span['"][^>]*>(\s| |\xA0)<\/span>)?(<br>)?$/.test(_f.innerHTML)){ -_f.innerHTML=""; -if(dojo.isWebKit){ -_9=dijit.range.create(this.editor.window); -_9.setStart(_f,0); -_7.removeAllRanges(); -_7.addRange(_9); -} -this._checkListLater=false; -} -return true; -} -if(!_e.blockNode||_e.blockNode===this.editor.editNode){ -try{ -dijit._editor.RichText.prototype.execCommand.call(this.editor,"formatblock",this.blockNodeForEnter); -} -catch(e2){ -} -_e={blockNode:dojo.withGlobal(this.editor.window,"getAncestorElement",dijit._editor.selection,[this.blockNodeForEnter]),blockContainer:this.editor.editNode}; -if(_e.blockNode){ -if(_e.blockNode!=this.editor.editNode&&(!(_e.blockNode.textContent||_e.blockNode.innerHTML).replace(/^\s+|\s+$/g,"").length)){ -this.removeTrailingBr(_e.blockNode); -return false; -} -}else{ -_e.blockNode=this.editor.editNode; -} -_7=dijit.range.getSelection(this.editor.window); -_8=_7.getRangeAt(0); -} -var _10=_a.createElement(this.blockNodeForEnter); -_10.innerHTML=this.bogusHtmlContent; -this.removeTrailingBr(_e.blockNode); -if(dijit.range.atEndOfContainer(_e.blockNode,_8.endContainer,_8.endOffset)){ -if(_e.blockNode===_e.blockContainer){ -_e.blockNode.appendChild(_10); -}else{ -dojo.place(_10,_e.blockNode,"after"); -} -_d=false; -_9=dijit.range.create(this.editor.window); -_9.setStart(_10,0); -_7.removeAllRanges(); -_7.addRange(_9); -if(this.editor.height){ -dojo.window.scrollIntoView(_10); -} -}else{ -if(dijit.range.atBeginningOfContainer(_e.blockNode,_8.startContainer,_8.startOffset)){ -dojo.place(_10,_e.blockNode,_e.blockNode===_e.blockContainer?"first":"before"); -if(_10.nextSibling&&this.editor.height){ -_9=dijit.range.create(this.editor.window); -_9.setStart(_10.nextSibling,0); -_7.removeAllRanges(); -_7.addRange(_9); -dojo.window.scrollIntoView(_10.nextSibling); -} -_d=false; -}else{ -if(_e.blockNode===_e.blockContainer){ -_e.blockNode.appendChild(_10); -}else{ -dojo.place(_10,_e.blockNode,"after"); -} -_d=false; -if(_e.blockNode.style){ -if(_10.style){ -if(_e.blockNode.style.cssText){ -_10.style.cssText=_e.blockNode.style.cssText; -} -} -} -var rs=_8.startContainer; -if(rs&&rs.nodeType==3){ -var _11,_12; -var txt=rs.nodeValue; -var _13=_a.createTextNode(txt.substring(0,_8.startOffset)); -var _14=_a.createTextNode(txt.substring(_8.startOffset,txt.length)); -dojo.place(_13,rs,"before"); -dojo.place(_14,rs,"after"); -dojo.destroy(rs); -var _15=_13.parentNode; -while(_15!==_e.blockNode){ -var tg=_15.tagName; -var _16=_a.createElement(tg); -if(_15.style){ -if(_16.style){ -if(_15.style.cssText){ -_16.style.cssText=_15.style.cssText; -} -} -} -_11=_14; -while(_11){ -_12=_11.nextSibling; -_16.appendChild(_11); -_11=_12; -} -dojo.place(_16,_15,"after"); -_13=_15; -_14=_16; -_15=_15.parentNode; -} -_11=_14; -if(_11.nodeType==1||(_11.nodeType==3&&_11.nodeValue)){ -_10.innerHTML=""; -} -while(_11){ -_12=_11.nextSibling; -_10.appendChild(_11); -_11=_12; -} -} -_9=dijit.range.create(this.editor.window); -_9.setStart(_10,0); -_7.removeAllRanges(); -_7.addRange(_9); -if(this.editor.height){ -dijit.scrollIntoView(_10); -} -if(dojo.isMoz){ -this._pressedEnterInBlock=_e.blockNode; -} -} -} -return _d; -},removeTrailingBr:function(_17){ -var _18=/P|DIV|LI/i.test(_17.tagName)?_17:dijit._editor.selection.getParentOfType(_17,["P","DIV","LI"]); -if(!_18){ -return; -} -if(_18.lastChild){ -if((_18.childNodes.length>1&&_18.lastChild.nodeType==3&&/^[\s\xAD]*$/.test(_18.lastChild.nodeValue))||_18.lastChild.tagName=="BR"){ -dojo.destroy(_18.lastChild); -} -} -if(!_18.childNodes.length){ -_18.innerHTML=this.bogusHtmlContent; -} -},_fixNewLineBehaviorForIE:function(d){ -var doc=this.editor.document; -if(doc.__INSERTED_EDITIOR_NEWLINE_CSS===undefined){ -var _19=dojo.create("style",{type:"text/css"},doc.getElementsByTagName("head")[0]); -_19.styleSheet.cssText="p{margin:0;}"; -this.editor.document.__INSERTED_EDITIOR_NEWLINE_CSS=true; -} -return d; -},regularPsToSingleLinePs:function(_1a,_1b){ -function _1c(el){ -function _1d(_1e){ -var _1f=_1e[0].ownerDocument.createElement("p"); -_1e[0].parentNode.insertBefore(_1f,_1e[0]); -dojo.forEach(_1e,function(_20){ -_1f.appendChild(_20); -}); -}; -var _21=0; -var _22=[]; -var _23; -while(_21<el.childNodes.length){ -_23=el.childNodes[_21]; -if(_23.nodeType==3||(_23.nodeType==1&&_23.nodeName!="BR"&&dojo.style(_23,"display")!="block")){ -_22.push(_23); -}else{ -var _24=_23.nextSibling; -if(_22.length){ -_1d(_22); -_21=(_21+1)-_22.length; -if(_23.nodeName=="BR"){ -dojo.destroy(_23); -} -} -_22=[]; -} -_21++; -} -if(_22.length){ -_1d(_22); -} -}; -function _25(el){ -var _26=null; -var _27=[]; -var _28=el.childNodes.length-1; -for(var i=_28;i>=0;i--){ -_26=el.childNodes[i]; -if(_26.nodeName=="BR"){ -var _29=_26.ownerDocument.createElement("p"); -dojo.place(_29,el,"after"); -if(_27.length==0&&i!=_28){ -_29.innerHTML=" "; -} -dojo.forEach(_27,function(_2a){ -_29.appendChild(_2a); -}); -dojo.destroy(_26); -_27=[]; -}else{ -_27.unshift(_26); -} -} -}; -var _2b=[]; -var ps=_1a.getElementsByTagName("p"); -dojo.forEach(ps,function(p){ -_2b.push(p); +dojo.require("dijit._editor._Plugin"); +dojo.require("dijit._editor.range"); + + +dojo.declare("dijit._editor.plugins.EnterKeyHandling", dijit._editor._Plugin, { + // summary: + // This plugin tries to make all browsers behave consistently with regard to + // how ENTER behaves in the editor window. It traps the ENTER key and alters + // the way DOM is constructed in certain cases to try to commonize the generated + // DOM and behaviors across browsers. + // + // description: + // This plugin has three modes: + // + // * blockModeForEnter=BR + // * blockModeForEnter=DIV + // * blockModeForEnter=P + // + // In blockModeForEnter=P, the ENTER key starts a new + // paragraph, and shift-ENTER starts a new line in the current paragraph. + // For example, the input: + // + // | first paragraph <shift-ENTER> + // | second line of first paragraph <ENTER> + // | second paragraph + // + // will generate: + // + // | <p> + // | first paragraph + // | <br/> + // | second line of first paragraph + // | </p> + // | <p> + // | second paragraph + // | </p> + // + // In BR and DIV mode, the ENTER key conceptually goes to a new line in the + // current paragraph, and users conceptually create a new paragraph by pressing ENTER twice. + // For example, if the user enters text into an editor like this: + // + // | one <ENTER> + // | two <ENTER> + // | three <ENTER> + // | <ENTER> + // | four <ENTER> + // | five <ENTER> + // | six <ENTER> + // + // It will appear on the screen as two 'paragraphs' of three lines each. Markupwise, this generates: + // + // BR: + // | one<br/> + // | two<br/> + // | three<br/> + // | <br/> + // | four<br/> + // | five<br/> + // | six<br/> + // + // DIV: + // | <div>one</div> + // | <div>two</div> + // | <div>three</div> + // | <div> </div> + // | <div>four</div> + // | <div>five</div> + // | <div>six</div> + + // 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. The default is 'BR' + // + // See class description for more details. + blockNodeForEnter: 'BR', + + constructor: function(args){ + if(args){ + if("blockNodeForEnter" in args){ + args.blockNodeForEnter = args.blockNodeForEnter.toUpperCase(); + } + dojo.mixin(this,args); + } + }, + + setEditor: function(editor){ + // Overrides _Plugin.setEditor(). + if(this.editor === editor) { return; } + this.editor = editor; + if(this.blockNodeForEnter == 'BR'){ + // While Moz has a mode tht mostly works, it's still a little different, + // So, try to just have a common mode and be consistent. Which means + // we need to enable customUndo, if not already enabled. + this.editor.customUndo = true; + editor.onLoadDeferred.addCallback(dojo.hitch(this,function(d){ + this.connect(editor.document, "onkeypress", function(e){ + if(e.charOrCode == dojo.keys.ENTER){ + // Just do it manually. The handleEnterKey has a shift mode that + // Always acts like <br>, so just use it. + var ne = dojo.mixin({},e); + ne.shiftKey = true; + if(!this.handleEnterKey(ne)){ + dojo.stopEvent(e); + } + } + }); + return d; + })); + }else if(this.blockNodeForEnter){ + // add enter key handler + // FIXME: need to port to the new event code!! + var h = dojo.hitch(this,this.handleEnterKey); + editor.addKeyHandler(13, 0, 0, h); //enter + editor.addKeyHandler(13, 0, 1, h); //shift+enter + this.connect(this.editor,'onKeyPressed','onKeyPressed'); + } + }, + onKeyPressed: function(e){ + // summary: + // Handler for keypress events. + // tags: + // private + if(this._checkListLater){ + if(dojo.withGlobal(this.editor.window, 'isCollapsed', dijit)){ + var liparent=dojo.withGlobal(this.editor.window, 'getAncestorElement', dijit._editor.selection, ['LI']); + if(!liparent){ + // circulate the undo detection code by calling RichText::execCommand directly + dijit._editor.RichText.prototype.execCommand.call(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){ + // move to the start by moving backwards one char + var r = this.editor.document.selection.createRange(); + r.move('character',-1); + r.select(); + } + }else{ + console.error('onKeyPressed: Cannot find the new block node'); // FIXME + } + }else{ + if(dojo.isMoz){ + if(liparent.parentNode.parentNode.nodeName == 'LI'){ + liparent=liparent.parentNode.parentNode; + } + } + var fc=liparent.firstChild; + if(fc && fc.nodeType == 1 && (fc.nodeName == 'UL' || fc.nodeName == 'OL')){ + liparent.insertBefore(fc.ownerDocument.createTextNode('\xA0'),fc); + var newrange = dijit.range.create(this.editor.window); + newrange.setStart(liparent.firstChild,0); + var selection = dijit.range.getSelection(this.editor.window, true); + selection.removeAllRanges(); + selection.addRange(newrange); + } + } + } + this._checkListLater = false; + } + if(this._pressedEnterInBlock){ + // the new created is the original current P, so we have previousSibling below + if(this._pressedEnterInBlock.previousSibling){ + this.removeTrailingBr(this._pressedEnterInBlock.previousSibling); + } + delete this._pressedEnterInBlock; + } + }, + + // bogusHtmlContent: [private] String + // HTML to stick into a new empty block + bogusHtmlContent: ' ', + + // blockNodes: [private] Regex + // Regex for testing if a given tag is a block level (display:block) tag + blockNodes: /^(?:P|H1|H2|H3|H4|H5|H6|LI)$/, + + handleEnterKey: function(e){ + // summary: + // Handler for enter key events when blockModeForEnter is DIV or P. + // description: + // Manually handle enter key event to make the behavior consistent across + // all supported browsers. See class description for details. + // tags: + // private + + var selection, range, newrange, startNode, endNode, brNode, doc=this.editor.document,br,rs,txt; + if(e.shiftKey){ // shift+enter always generates <br> + var parent = dojo.withGlobal(this.editor.window, "getParentElement", dijit._editor.selection); + var header = dijit.range.getAncestor(parent,this.blockNodes); + if(header){ + if(header.tagName == 'LI'){ + return true; // let browser handle + } + selection = dijit.range.getSelection(this.editor.window); + range = selection.getRangeAt(0); + if(!range.collapsed){ + range.deleteContents(); + selection = dijit.range.getSelection(this.editor.window); + range = selection.getRangeAt(0); + } + if(dijit.range.atBeginningOfContainer(header, range.startContainer, range.startOffset)){ + br=doc.createElement('br'); + newrange = dijit.range.create(this.editor.window); + header.insertBefore(br,header.firstChild); + newrange.setStartBefore(br.nextSibling); + selection.removeAllRanges(); + selection.addRange(newrange); + }else if(dijit.range.atEndOfContainer(header, range.startContainer, range.startOffset)){ + newrange = dijit.range.create(this.editor.window); + br=doc.createElement('br'); + header.appendChild(br); + header.appendChild(doc.createTextNode('\xA0')); + newrange.setStart(header.lastChild,0); + selection.removeAllRanges(); + selection.addRange(newrange); + }else{ + rs = range.startContainer; + if(rs && rs.nodeType == 3){ + // Text node, we have to split it. + txt = rs.nodeValue; + dojo.withGlobal(this.editor.window, function(){ + startNode = doc.createTextNode(txt.substring(0, range.startOffset)); + endNode = doc.createTextNode(txt.substring(range.startOffset)); + brNode = doc.createElement("br"); + + if(endNode.nodeValue == "" && dojo.isWebKit){ + endNode = doc.createTextNode('\xA0') + } + dojo.place(startNode, rs, "after"); + dojo.place(brNode, startNode, "after"); + dojo.place(endNode, brNode, "after"); + dojo.destroy(rs); + newrange = dijit.range.create(dojo.gobal); + newrange.setStart(endNode,0); + selection.removeAllRanges(); + selection.addRange(newrange); + }); + return false; + } + return true; // let browser handle + } + }else{ + selection = dijit.range.getSelection(this.editor.window); + if(selection.rangeCount){ + range = selection.getRangeAt(0); + if(range && range.startContainer){ + if(!range.collapsed){ + range.deleteContents(); + selection = dijit.range.getSelection(this.editor.window); + range = selection.getRangeAt(0); + } + rs = range.startContainer; + if(rs && rs.nodeType == 3){ + // Text node, we have to split it. + dojo.withGlobal(this.editor.window, dojo.hitch(this, function(){ + var endEmpty = false; + + var offset = range.startOffset; + if(rs.length < offset){ + //We are not splitting the right node, try to locate the correct one + ret = this._adjustNodeAndOffset(rs, offset); + rs = ret.node; + offset = ret.offset; + } + txt = rs.nodeValue; + + startNode = doc.createTextNode(txt.substring(0, offset)); + endNode = doc.createTextNode(txt.substring(offset)); + brNode = doc.createElement("br"); + + if(!endNode.length){ + endNode = doc.createTextNode('\xA0'); + endEmpty = true; + } + + if(startNode.length){ + dojo.place(startNode, rs, "after"); + }else{ + startNode = rs; + } + dojo.place(brNode, startNode, "after"); + dojo.place(endNode, brNode, "after"); + dojo.destroy(rs); + newrange = dijit.range.create(dojo.gobal); + newrange.setStart(endNode,0); + newrange.setEnd(endNode, endNode.length); + selection.removeAllRanges(); + selection.addRange(newrange); + if(endEmpty && !dojo.isWebKit){ + dijit._editor.selection.remove(); + }else{ + dijit._editor.selection.collapse(true); + } + })); + }else{ + dojo.withGlobal(this.editor.window, dojo.hitch(this, function(){ + var brNode = doc.createElement("br"); + rs.appendChild(brNode); + var endNode = doc.createTextNode('\xA0'); + rs.appendChild(endNode); + newrange = dijit.range.create(dojo.global); + newrange.setStart(endNode,0); + newrange.setEnd(endNode, endNode.length); + selection.removeAllRanges(); + selection.addRange(newrange); + dijit._editor.selection.collapse(true); + })); + } + } + }else{ + // don't change this: do not call this.execCommand, as that may have other logic in subclass + dijit._editor.RichText.prototype.execCommand.call(this.editor, 'inserthtml', '<br>'); + } + } + return false; + } + var _letBrowserHandle = true; + + // first remove selection + selection = dijit.range.getSelection(this.editor.window); + range = selection.getRangeAt(0); + if(!range.collapsed){ + range.deleteContents(); + selection = dijit.range.getSelection(this.editor.window); + range = selection.getRangeAt(0); + } + + var block = dijit.range.getBlockAncestor(range.endContainer, null, this.editor.editNode); + var blockNode = block.blockNode; + + // if this is under a LI or the parent of the blockNode is LI, just let browser to handle it + if((this._checkListLater = (blockNode && (blockNode.nodeName == 'LI' || blockNode.parentNode.nodeName == 'LI')))){ + if(dojo.isMoz){ + // press enter in middle of P may leave a trailing <br/>, let's remove it later + this._pressedEnterInBlock = blockNode; + } + // if this li only contains spaces, set the content to empty so the browser will outdent this item + if(/^(\s| |\xA0|<span\b[^>]*\bclass=['"]Apple-style-span['"][^>]*>(\s| |\xA0)<\/span>)?(<br>)?$/.test(blockNode.innerHTML)){ + // empty LI node + blockNode.innerHTML = ''; + if(dojo.isWebKit){ // WebKit tosses the range when innerHTML is reset + newrange = dijit.range.create(this.editor.window); + newrange.setStart(blockNode, 0); + selection.removeAllRanges(); + selection.addRange(newrange); + } + this._checkListLater = false; // nothing to check since the browser handles outdent + } + return true; + } + + // text node directly under body, let's wrap them in a node + if(!block.blockNode || block.blockNode===this.editor.editNode){ + try{ + dijit._editor.RichText.prototype.execCommand.call(this.editor, 'formatblock',this.blockNodeForEnter); + }catch(e2){ /*squelch FF3 exception bug when editor content is a single BR*/ } + // 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 != this.editor.editNode && + (!(block.blockNode.textContent || block.blockNode.innerHTML).replace(/^\s+|\s+$/g, "").length)){ + this.removeTrailingBr(block.blockNode); + return false; + } + }else{ // we shouldn't be here if formatblock worked + block.blockNode = this.editor.editNode; + } + selection = dijit.range.getSelection(this.editor.window); + range = selection.getRangeAt(0); + } + + var newblock = doc.createElement(this.blockNodeForEnter); + newblock.innerHTML=this.bogusHtmlContent; + this.removeTrailingBr(block.blockNode); + var endOffset = range.endOffset; + var node = range.endContainer; + if(node.length < endOffset){ + //We are not checking the right node, try to locate the correct one + var ret = this._adjustNodeAndOffset(node, endOffset); + node = ret.node; + endOffset = ret.offset; + } + if(dijit.range.atEndOfContainer(block.blockNode, node, 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(this.editor.window); + newrange.setStart(newblock, 0); + selection.removeAllRanges(); + selection.addRange(newrange); + if(this.editor.height){ + dojo.window.scrollIntoView(newblock); + } + }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){ + // position input caret - mostly WebKit needs this + newrange = dijit.range.create(this.editor.window); + newrange.setStart(newblock.nextSibling, 0); + selection.removeAllRanges(); + selection.addRange(newrange); + // browser does not scroll the caret position into view, do it manually + dojo.window.scrollIntoView(newblock.nextSibling); + } + _letBrowserHandle = false; + }else{ //press enter in the middle of P/DIV/Whatever/ + if(block.blockNode === block.blockContainer){ + block.blockNode.appendChild(newblock); + }else{ + dojo.place(newblock, block.blockNode, "after"); + } + _letBrowserHandle = false; + + // Clone any block level styles. + if(block.blockNode.style){ + if(newblock.style){ + if(block.blockNode.style.cssText){ + newblock.style.cssText = block.blockNode.style.cssText; + } + } + } + + // Okay, we probably have to split. + rs = range.startContainer; + var firstNodeMoved; + if(rs && rs.nodeType == 3){ + // Text node, we have to split it. + var nodeToMove, tNode; + endOffset = range.endOffset; + if(rs.length < endOffset){ + //We are not splitting the right node, try to locate the correct one + ret = this._adjustNodeAndOffset(rs, endOffset); + rs = ret.node; + endOffset = ret.offset; + } + + txt = rs.nodeValue; + startNode = doc.createTextNode(txt.substring(0, endOffset)); + endNode = doc.createTextNode(txt.substring(endOffset, txt.length)); + + // Place the split, then remove original nodes. + dojo.place(startNode, rs, "before"); + dojo.place(endNode, rs, "after"); + dojo.destroy(rs); + + // Okay, we split the text. Now we need to see if we're + // parented to the block element we're splitting and if + // not, we have to split all the way up. Ugh. + var parentC = startNode.parentNode; + while(parentC !== block.blockNode){ + var tg = parentC.tagName; + var newTg = doc.createElement(tg); + // Clone over any 'style' data. + if(parentC.style){ + if(newTg.style){ + if(parentC.style.cssText){ + newTg.style.cssText = parentC.style.cssText; + } + } + } + // If font also need to clone over any font data. + if(parentC.tagName === "FONT"){ + if(parentC.color){ + newTg.color = parentC.color; + } + if(parentC.face){ + newTg.face = parentC.face; + } + if(parentC.size){ // this check was necessary on IE + newTg.size = parentC.size; + } + } + + nodeToMove = endNode; + while(nodeToMove){ + tNode = nodeToMove.nextSibling; + newTg.appendChild(nodeToMove); + nodeToMove = tNode; + } + dojo.place(newTg, parentC, "after"); + startNode = parentC; + endNode = newTg; + parentC = parentC.parentNode; + } + + // Lastly, move the split out tags to the new block. + // as they should now be split properly. + nodeToMove = endNode; + if(nodeToMove.nodeType == 1 || (nodeToMove.nodeType == 3 && nodeToMove.nodeValue)){ + // Non-blank text and non-text nodes need to clear out that blank space + // before moving the contents. + newblock.innerHTML = ""; + } + firstNodeMoved = nodeToMove; + while(nodeToMove){ + tNode = nodeToMove.nextSibling; + newblock.appendChild(nodeToMove); + nodeToMove = tNode; + } + } + + //lets move caret to the newly created block + newrange = dijit.range.create(this.editor.window); + var nodeForCursor; + var innerMostFirstNodeMoved = firstNodeMoved; + if(this.blockNodeForEnter !== 'BR'){ + while(innerMostFirstNodeMoved){ + nodeForCursor = innerMostFirstNodeMoved; + tNode = innerMostFirstNodeMoved.firstChild; + innerMostFirstNodeMoved = tNode; + } + if(nodeForCursor && nodeForCursor.parentNode){ + newblock = nodeForCursor.parentNode; + newrange.setStart(newblock, 0); + selection.removeAllRanges(); + selection.addRange(newrange); + if(this.editor.height){ + dijit.scrollIntoView(newblock); + } + if(dojo.isMoz){ + // press enter in middle of P may leave a trailing <br/>, let's remove it later + this._pressedEnterInBlock = block.blockNode; + } + }else{ + _letBrowserHandle = true; + } + }else{ + newrange.setStart(newblock, 0); + selection.removeAllRanges(); + selection.addRange(newrange); + if(this.editor.height){ + dijit.scrollIntoView(newblock); + } + 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; + }, + + _adjustNodeAndOffset: function(/*DomNode*/node, /*Int*/offset){ + // summary: + // In the case there are multiple text nodes in a row the offset may not be within the node. If the offset is larger than the node length, it will attempt to find + // the next text sibling until it locates the text node in which the offset refers to + // node: + // The node to check. + // offset: + // The position to find within the text node + // tags: + // private. + while(node.length < offset && node.nextSibling && node.nextSibling.nodeType==3){ + //Adjust the offset and node in the case of multiple text nodes in a row + offset = offset - node.length; + node = node.nextSibling; + } + var ret = {"node": node, "offset": offset}; + return ret; + }, + + removeTrailingBr: function(container){ + // summary: + // If last child of container is a <br>, then remove it. + // tags: + // private + 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.tagName=='BR'){ + + dojo.destroy(para.lastChild); + } + } + if(!para.childNodes.length){ + para.innerHTML=this.bogusHtmlContent; + } + } }); -dojo.forEach(_2b,function(p){ -var _2c=p.previousSibling; -if((_2c)&&(_2c.nodeType==1)&&(_2c.nodeName=="P"||dojo.style(_2c,"display")!="block")){ -var _2d=p.parentNode.insertBefore(this.document.createElement("p"),p); -_2d.innerHTML=_1b?"":" "; -} -_25(p); -},this.editor); -_1c(_1a); -return _1a; -},singleLinePsToRegularPs:function(_2e){ -function _2f(_30){ -var ps=_30.getElementsByTagName("p"); -var _31=[]; -for(var i=0;i<ps.length;i++){ -var p=ps[i]; -var _32=false; -for(var k=0;k<_31.length;k++){ -if(_31[k]===p.parentNode){ -_32=true; -break; -} -} -if(!_32){ -_31.push(p.parentNode); -} -} -return _31; -}; -function _33(_34){ -return (!_34.childNodes.length||_34.innerHTML==" "); -}; -var _35=_2f(_2e); -for(var i=0;i<_35.length;i++){ -var _36=_35[i]; -var _37=null; -var _38=_36.firstChild; -var _39=null; -while(_38){ -if(_38.nodeType!=1||_38.tagName!="P"||(_38.getAttributeNode("style")||{}).specified){ -_37=null; -}else{ -if(_33(_38)){ -_39=_38; -_37=null; -}else{ -if(_37==null){ -_37=_38; -}else{ -if((!_37.lastChild||_37.lastChild.nodeName!="BR")&&(_38.firstChild)&&(_38.firstChild.nodeName!="BR")){ -_37.appendChild(this.editor.document.createElement("br")); -} -while(_38.firstChild){ -_37.appendChild(_38.firstChild); -} -_39=_38; -} -} -} -_38=_38.nextSibling; -if(_39){ -dojo.destroy(_39); -_39=null; -} -} -} -return _2e; -}}); + } diff --git a/lib/dijit/_editor/plugins/FontChoice.js b/lib/dijit/_editor/plugins/FontChoice.js index c5578e3fb..ef91fd676 100644 --- a/lib/dijit/_editor/plugins/FontChoice.js +++ b/lib/dijit/_editor/plugins/FontChoice.js @@ -1,12 +1,12 @@ /* - Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved. + Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved. Available via Academic Free License >= 2.1 OR the modified BSD license. see: http://dojotoolkit.org/license for details */ -if(!dojo._hasResource["dijit._editor.plugins.FontChoice"]){ -dojo._hasResource["dijit._editor.plugins.FontChoice"]=true; +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._editor.range"); @@ -14,252 +14,570 @@ dojo.require("dijit._editor.selection"); dojo.require("dijit.form.FilteringSelect"); dojo.require("dojo.data.ItemFileReadStore"); dojo.require("dojo.i18n"); -dojo.requireLocalization("dijit._editor","FontChoice",null,"ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,ko,nb,nl,pl,pt,pt-pt,ro,ru,sk,sl,sv,th,tr,zh,zh-tw"); -dojo.declare("dijit._editor.plugins._FontDropDown",[dijit._Widget,dijit._Templated],{label:"",widgetsInTemplate:true,plainText:false,templateString:"<span style='white-space: nowrap' class='dijit dijitReset dijitInline'>"+"<label class='dijitLeft dijitInline' for='${selectId}'>${label}</label>"+"<input dojoType='dijit.form.FilteringSelect' required=false labelType=html labelAttr=label searchAttr=name "+"tabIndex='-1' id='${selectId}' dojoAttachPoint='select' value=''/>"+"</span>",postMixInProperties:function(){ -this.inherited(arguments); -this.strings=dojo.i18n.getLocalization("dijit._editor","FontChoice"); -this.label=this.strings[this.command]; -this.id=dijit.getUniqueId(this.declaredClass.replace(/\./g,"_")); -this.selectId=this.id+"_select"; -this.inherited(arguments); -},postCreate:function(){ -var _1=dojo.map(this.values,function(_2){ -var _3=this.strings[_2]||_2; -return {label:this.getLabel(_2,_3),name:_3,value:_2}; -},this); -this.select.store=new dojo.data.ItemFileReadStore({data:{identifier:"value",items:_1}}); -this.select.set("value","",false); -this.disabled=this.select.get("disabled"); -},_setValueAttr:function(_4,_5){ -_5=_5!==false?true:false; -this.select.set("value",dojo.indexOf(this.values,_4)<0?"":_4,_5); -if(!_5){ -this.select._lastValueReported=null; -} -},_getValueAttr:function(){ -return this.select.get("value"); -},focus:function(){ -this.select.focus(); -},_setDisabledAttr:function(_6){ -this.disabled=_6; -this.select.set("disabled",_6); -}}); -dojo.declare("dijit._editor.plugins._FontNameDropDown",dijit._editor.plugins._FontDropDown,{generic:false,command:"fontName",postMixInProperties:function(){ -if(!this.values){ -this.values=this.generic?["serif","sans-serif","monospace","cursive","fantasy"]:["Arial","Times New Roman","Comic Sans MS","Courier New"]; -} -this.inherited(arguments); -},getLabel:function(_7,_8){ -if(this.plainText){ -return _8; -}else{ -return "<div style='font-family: "+_7+"'>"+_8+"</div>"; -} -},_setValueAttr:function(_9,_a){ -_a=_a!==false?true:false; -if(this.generic){ -var _b={"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"}; -_9=_b[_9]||_9; -} -this.inherited(arguments,[_9,_a]); -}}); -dojo.declare("dijit._editor.plugins._FontSizeDropDown",dijit._editor.plugins._FontDropDown,{command:"fontSize",values:[1,2,3,4,5,6,7],getLabel:function(_c,_d){ -if(this.plainText){ -return _d; -}else{ -return "<font size="+_c+"'>"+_d+"</font>"; -} -},_setValueAttr:function(_e,_f){ -_f=_f!==false?true:false; -if(_e.indexOf&&_e.indexOf("px")!=-1){ -var _10=parseInt(_e,10); -_e={10:1,13:2,16:3,18:4,24:5,32:6,48:7}[_10]||_e; -} -this.inherited(arguments,[_e,_f]); -}}); -dojo.declare("dijit._editor.plugins._FormatBlockDropDown",dijit._editor.plugins._FontDropDown,{command:"formatBlock",values:["noFormat","p","h1","h2","h3","pre"],postCreate:function(){ -this.inherited(arguments); -this.set("value","noFormat",false); -},getLabel:function(_11,_12){ -if(this.plainText){ -return _12; -}else{ -return "<"+_11+">"+_12+"</"+_11+">"; -} -},_execCommand:function(_13,_14,_15){ -if(_15==="noFormat"){ -var _16; -var end; -var sel=dijit.range.getSelection(_13.window); -if(sel&&sel.rangeCount>0){ -var _17=sel.getRangeAt(0); -var _18,tag; -if(_17){ -_16=_17.startContainer; -end=_17.endContainer; -while(_16&&_16!==_13.editNode&&_16!==_13.document.body&&_16.nodeType!==1){ -_16=_16.parentNode; -} -while(end&&end!==_13.editNode&&end!==_13.document.body&&end.nodeType!==1){ -end=end.parentNode; -} -var _19=dojo.hitch(this,function(_1a,_1b){ -if(_1a.childNodes&&_1a.childNodes.length){ -var i; -for(i=0;i<_1a.childNodes.length;i++){ -var c=_1a.childNodes[i]; -if(c.nodeType==1){ -if(dojo.withGlobal(_13.window,"inSelection",dijit._editor.selection,[c])){ -var tag=c.tagName?c.tagName.toLowerCase():""; -if(dojo.indexOf(this.values,tag)!==-1){ -_1b.push(c); -} -_19(c,_1b); -} -} -} -} +dojo.requireLocalization("dijit._editor", "FontChoice", null, "ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,kk,ko,nb,nl,pl,pt,pt-pt,ro,ru,sk,sl,sv,th,tr,zh,zh-tw"); + + +dojo.declare("dijit._editor.plugins._FontDropDown", + [dijit._Widget, dijit._Templated],{ + // summary: + // Base class for widgets that contains a label (like "Font:") + // and a FilteringSelect drop down to pick a value. + // Used as Toolbar entry. + + // label: [public] String + // The label to apply to this particular FontDropDown. + label: "", + + // widgetsInTemplate: [public] boolean + // Over-ride denoting the template has widgets to parse. + widgetsInTemplate: true, + + // plainText: [public] boolean + // Flag to indicate that the returned label should be plain text + // instead of an example. + plainText: false, + + // templateString: [public] String + // The template used to construct the labeled dropdown. + templateString: + "<span style='white-space: nowrap' class='dijit dijitReset dijitInline'>" + + "<label class='dijitLeft dijitInline' for='${selectId}'>${label}</label>" + + "<input dojoType='dijit.form.FilteringSelect' required='false' labelType='html' labelAttr='label' searchAttr='name' " + + "tabIndex='-1' id='${selectId}' dojoAttachPoint='select' value=''/>" + + "</span>", + + postMixInProperties: function(){ + // summary: + // Over-ride to set specific properties. + this.inherited(arguments); + + this.strings = dojo.i18n.getLocalization("dijit._editor", "FontChoice"); + + // Set some substitution variables used in the template + this.label = this.strings[this.command]; + this.id = dijit.getUniqueId(this.declaredClass.replace(/\./g,"_")); + this.selectId = this.id + "_select"; + + this.inherited(arguments); + }, + + postCreate: function(){ + // summary: + // Over-ride for the default postCreate action + // This establishes the filtering selects and the like. + + // Initialize the list of items in the drop down by creating data store with items like: + // {value: 1, name: "xx-small", label: "<font size=1>xx-small</font-size>" } + var items = dojo.map(this.values, function(value){ + var name = this.strings[value] || value; + return { + label: this.getLabel(value, name), + name: name, + value: value + }; + }, this); + + this.select.store = new dojo.data.ItemFileReadStore({ + data: { + identifier: "value", + items: items + } + }); + + this.select.set("value", "", false); + this.disabled = this.select.get("disabled"); + }, + + _setValueAttr: function(value, priorityChange){ + // summary: + // Over-ride for the default action of setting the + // widget value, maps the input to known values + // value: Object|String + // The value to set in the select. + // priorityChange: + // Optional parameter used to tell the select whether or not to fire + // onChange event. + + //if the value is not a permitted value, just set empty string to prevent showing the warning icon + priorityChange = priorityChange !== false?true:false; + this.select.set('value', dojo.indexOf(this.values,value) < 0 ? "" : value, priorityChange); + if(!priorityChange){ + // Clear the last state in case of updateState calls. Ref: #10466 + this.select._lastValueReported=null; + } + }, + + _getValueAttr: function(){ + // summary: + // Allow retreiving the value from the composite select on + // call to button.get("value"); + return this.select.get('value'); + }, + + focus: function(){ + // summary: + // Over-ride for focus control of this widget. Delegates focus down to the + // filtering select. + this.select.focus(); + }, + + _setDisabledAttr: function(value){ + // summary: + // Over-ride for the button's 'disabled' attribute so that it can be + // disabled programmatically. + + // Save off ths disabled state so the get retrieves it correctly + //without needing to have a function proxy it. + this.disabled = value; + this.select.set("disabled", value); + } }); -var _1c=dojo.hitch(this,function(_1d){ -if(_1d&&_1d.length){ -_13.beginEditing(); -while(_1d.length){ -this._removeFormat(_13,_1d.pop()); -} -_13.endEditing(); -} + + +dojo.declare("dijit._editor.plugins._FontNameDropDown", dijit._editor.plugins._FontDropDown, { + // summary: + // Dropdown to select a font; goes in editor toolbar. + + // generic: Boolean + // Use generic (web standard) font names + generic: false, + + // command: [public] String + // The editor 'command' implemented by this plugin. + command: "fontName", + + postMixInProperties: function(){ + // summary: + // Over-ride for the default posr mixin control + if(!this.values){ + this.values = this.generic ? + ["serif", "sans-serif", "monospace", "cursive", "fantasy"] : // CSS font-family generics + ["Arial", "Times New Roman", "Comic Sans MS", "Courier New"]; + } + this.inherited(arguments); + }, + + getLabel: function(value, name){ + // summary: + // Function used to generate the labels of the format dropdown + // will return a formatted, or plain label based on the value + // of the plainText option. + // value: String + // The 'insert value' associated with a name + // name: String + // The text name of the value + if(this.plainText){ + return name; + }else{ + return "<div style='font-family: "+value+"'>" + name + "</div>"; + } + }, + + _setValueAttr: function(value, priorityChange){ + // summary: + // Over-ride for the default action of setting the + // widget value, maps the input to known values + + priorityChange = priorityChange !== false?true:false; + if(this.generic){ + 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? + }; + value = map[value] || value; + } + this.inherited(arguments, [value, priorityChange]); + } }); -var _1e=[]; -if(_16==end){ -var _1f; -_18=_16; -while(_18&&_18!==_13.editNode&&_18!==_13.document.body){ -if(_18.nodeType==1){ -tag=_18.tagName?_18.tagName.toLowerCase():""; -if(dojo.indexOf(this.values,tag)!==-1){ -_1f=_18; -break; -} -} -_18=_18.parentNode; -} -_19(_16,_1e); -if(_1f){ -_1e=[_1f].concat(_1e); -} -_1c(_1e); -}else{ -_18=_16; -while(dojo.withGlobal(_13.window,"inSelection",dijit._editor.selection,[_18])){ -if(_18.nodeType==1){ -tag=_18.tagName?_18.tagName.toLowerCase():""; -if(dojo.indexOf(this.values,tag)!==-1){ -_1e.push(_18); -} -_19(_18,_1e); -} -_18=_18.nextSibling; -} -_1c(_1e); -} -_13.onDisplayChanged(); -} -} -}else{ -_13.execCommand(_14,_15); -} -},_removeFormat:function(_20,_21){ -if(_20.customUndo){ -while(_21.firstChild){ -dojo.place(_21.firstChild,_21,"before"); -} -_21.parentNode.removeChild(_21); -}else{ -dojo.withGlobal(_20.window,"selectElementChildren",dijit._editor.selection,[_21]); -var _22=dojo.withGlobal(_20.window,"getSelectedHtml",dijit._editor.selection,[null]); -dojo.withGlobal(_20.window,"selectElement",dijit._editor.selection,[_21]); -_20.execCommand("inserthtml",_22||""); -} -}}); -dojo.declare("dijit._editor.plugins.FontChoice",dijit._editor._Plugin,{useDefaultCommand:false,_initButton:function(){ -var _23={fontName:dijit._editor.plugins._FontNameDropDown,fontSize:dijit._editor.plugins._FontSizeDropDown,formatBlock:dijit._editor.plugins._FormatBlockDropDown}[this.command],_24=this.params; -if(this.params.custom){ -_24.values=this.params.custom; -} -var _25=this.editor; -this.button=new _23(dojo.delegate({dir:_25.dir,lang:_25.lang},_24)); -this.connect(this.button.select,"onChange",function(_26){ -this.editor.focus(); -if(this.command=="fontName"&&_26.indexOf(" ")!=-1){ -_26="'"+_26+"'"; -} -if(this.button._execCommand){ -this.button._execCommand(this.editor,this.command,_26); -}else{ -this.editor.execCommand(this.command,_26); -} -this.editor.customUndo=this.editor.customUndo||dojo.isWebKit; + +dojo.declare("dijit._editor.plugins._FontSizeDropDown", dijit._editor.plugins._FontDropDown, { + // summary: + // Dropdown to select a font size; goes in editor toolbar. + + // command: [public] String + // The editor 'command' implemented by this plugin. + command: "fontSize", + + // values: [public] Number[] + // The HTML font size values supported by this plugin + values: [1,2,3,4,5,6,7], // sizes according to the old HTML FONT SIZE + + getLabel: function(value, name){ + // summary: + // Function used to generate the labels of the format dropdown + // will return a formatted, or plain label based on the value + // of the plainText option. + // We're stuck using the deprecated FONT tag to correspond + // with the size measurements used by the editor + // value: String + // The 'insert value' associated with a name + // name: String + // The text name of the value + if(this.plainText){ + return name; + }else{ + return "<font size=" + value + "'>" + name + "</font>"; + } + }, + + _setValueAttr: function(value, priorityChange){ + // summary: + // Over-ride for the default action of setting the + // widget value, maps the input to known values + priorityChange = priorityChange !== false?true:false; + if(value.indexOf && value.indexOf("px") != -1){ + var pixels = parseInt(value, 10); + value = {10:1, 13:2, 16:3, 18:4, 24:5, 32:6, 48:7}[pixels] || value; + } + + this.inherited(arguments, [value, priorityChange]); + } }); -},updateState:function(){ -var _27=this.editor; -var _28=this.command; -if(!_27||!_27.isLoaded||!_28.length){ -return; -} -if(this.button){ -var _29; -try{ -_29=_27.queryCommandValue(_28)||""; -} -catch(e){ -_29=""; -} -var _2a=dojo.isString(_29)&&_29.match(/'([^']*)'/); -if(_2a){ -_29=_2a[1]; -} -if(_28==="formatBlock"){ -if(!_29||_29=="p"){ -_29=null; -var _2b; -var sel=dijit.range.getSelection(this.editor.window); -if(sel&&sel.rangeCount>0){ -var _2c=sel.getRangeAt(0); -if(_2c){ -_2b=_2c.endContainer; -} -} -while(_2b&&_2b!==_27.editNode&&_2b!==_27.document){ -var tg=_2b.tagName?_2b.tagName.toLowerCase():""; -if(tg&&dojo.indexOf(this.button.values,tg)>-1){ -_29=tg; -break; -} -_2b=_2b.parentNode; -} -if(!_29){ -_29="noFormat"; -} -}else{ -if(dojo.indexOf(this.button.values,_29)<0){ -_29="noFormat"; -} -} -} -if(_29!==this.button.get("value")){ -this.button.set("value",_29,false); -} -} -}}); -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,plainText:o.args.plainText?o.args.plainText:false}); -} + + +dojo.declare("dijit._editor.plugins._FormatBlockDropDown", dijit._editor.plugins._FontDropDown, { + // summary: + // Dropdown to select a format (like paragraph or heading); goes in editor toolbar. + + // command: [public] String + // The editor 'command' implemented by this plugin. + command: "formatBlock", + + // values: [public] Array + // The HTML format tags supported by this plugin + values: ["noFormat", "p", "h1", "h2", "h3", "pre"], + + postCreate: function(){ + // Init and set the default value to no formatting. Update state will adjust it + // as needed. + this.inherited(arguments); + this.set("value", "noFormat", false); + }, + + getLabel: function(value, name){ + // summary: + // Function used to generate the labels of the format dropdown + // will return a formatted, or plain label based on the value + // of the plainText option. + // value: String + // The 'insert value' associated with a name + // name: String + // The text name of the value + if(this.plainText || value == "noFormat"){ + return name; + }else{ + return "<" + value + ">" + name + "</" + value + ">"; + } + }, + + _execCommand: function(editor, command, choice){ + // summary: + // Over-ride for default exec-command label. + // Allows us to treat 'none' as special. + if(choice === "noFormat"){ + var start; + var end; + var sel = dijit.range.getSelection(editor.window); + if(sel && sel.rangeCount > 0){ + var range = sel.getRangeAt(0); + var node, tag; + if(range){ + start = range.startContainer; + end = range.endContainer; + + // find containing nodes of start/end. + while(start && start !== editor.editNode && + start !== editor.document.body && + start.nodeType !== 1){ + start = start.parentNode; + } + + while(end && end !== editor.editNode && + end !== editor.document.body && + end.nodeType !== 1){ + end = end.parentNode; + } + + var processChildren = dojo.hitch(this, function(node, array){ + if(node.childNodes && node.childNodes.length){ + var i; + for(i = 0; i < node.childNodes.length; i++){ + var c = node.childNodes[i]; + if(c.nodeType == 1){ + if(dojo.withGlobal(editor.window, "inSelection", dijit._editor.selection, [c])){ + var tag = c.tagName? c.tagName.toLowerCase(): ""; + if(dojo.indexOf(this.values, tag) !== -1){ + array.push(c); + } + processChildren(c,array); + } + } + } + } + }); + + var unformatNodes = dojo.hitch(this, function(nodes){ + // summary: + // Internal function to clear format nodes. + // nodes: + // The array of nodes to strip formatting from. + if(nodes && nodes.length){ + editor.beginEditing(); + while(nodes.length){ + this._removeFormat(editor, nodes.pop()); + } + editor.endEditing(); + } + }); + + var clearNodes = []; + if(start == end){ + //Contained within the same block, may be collapsed, but who cares, see if we + // have a block element to remove. + var block; + node = start; + while(node && node !== editor.editNode && node !== editor.document.body){ + if(node.nodeType == 1){ + tag = node.tagName? node.tagName.toLowerCase(): ""; + if(dojo.indexOf(this.values, tag) !== -1){ + block = node; + break; + } + } + node = node.parentNode; + } + + //Also look for all child nodes in the selection that may need to be + //cleared of formatting + processChildren(start, clearNodes); + if(block) { clearNodes = [block].concat(clearNodes); } + unformatNodes(clearNodes); + }else{ + // Probably a multi select, so we have to process it. Whee. + node = start; + while(dojo.withGlobal(editor.window, "inSelection", dijit._editor.selection, [node])){ + if(node.nodeType == 1){ + tag = node.tagName? node.tagName.toLowerCase(): ""; + if(dojo.indexOf(this.values, tag) !== -1){ + clearNodes.push(node); + } + processChildren(node,clearNodes); + } + node = node.nextSibling; + } + unformatNodes(clearNodes); + } + editor.onDisplayChanged(); + } + } + }else{ + editor.execCommand(command, choice); + } + }, + + _removeFormat: function(editor, node){ + // summary: + // function to remove the block format node. + // node: + // The block format node to remove (and leave the contents behind) + if(editor.customUndo){ + // So of course IE doesn't work right with paste-overs. + // We have to do this manually, which is okay since IE already uses + // customUndo and we turned it on for WebKit. WebKit pasted funny, + // so couldn't use the execCommand approach + while(node.firstChild){ + dojo.place(node.firstChild, node, "before"); + } + node.parentNode.removeChild(node); + }else{ + // Everyone else works fine this way, a paste-over and is native + // undo friendly. + dojo.withGlobal(editor.window, + "selectElementChildren", dijit._editor.selection, [node]); + var html = dojo.withGlobal(editor.window, + "getSelectedHtml", dijit._editor.selection, [null]); + dojo.withGlobal(editor.window, + "selectElement", dijit._editor.selection, [node]); + editor.execCommand("inserthtml", html||""); + } + } +}); + +// TODO: for 2.0, split into FontChoice plugin into three separate classes, +// one for each command (and change registry below) +dojo.declare("dijit._editor.plugins.FontChoice", dijit._editor._Plugin,{ + // summary: + // This plugin provides three drop downs for setting style in the editor + // (font, font size, and format block), as controlled by command. + // + // description: + // The commands provided by this plugin are: + // + // * fontName + // | Provides a drop down to select from a list of font names + // * fontSize + // | Provides a drop down to select from a list of font sizes + // * formatBlock + // | Provides a drop down to select from a list of block 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. + + // useDefaultCommand: [protected] booleam + // Override _Plugin.useDefaultCommand... + // processing is handled by this plugin, not by dijit.Editor. + useDefaultCommand: false, + + _initButton: function(){ + // summary: + // Overrides _Plugin._initButton(), to initialize the FilteringSelect+label in toolbar, + // rather than a simple button. + // tags: + // protected + + // Create the widget to go into the toolbar (the so-called "button") + var clazz = { + fontName: dijit._editor.plugins._FontNameDropDown, + fontSize: dijit._editor.plugins._FontSizeDropDown, + formatBlock: dijit._editor.plugins._FormatBlockDropDown + }[this.command], + params = this.params; + + // For back-compat reasons support setting custom values via "custom" parameter + // rather than "values" parameter + if(this.params.custom){ + params.values = this.params.custom; + } + + var editor = this.editor; + this.button = new clazz(dojo.delegate({dir: editor.dir, lang: editor.lang}, params)); + + // Reflect changes to the drop down in the editor + this.connect(this.button.select, "onChange", function(choice){ + // User invoked change, since all internal updates set priorityChange to false and will + // not trigger an onChange event. + this.editor.focus(); + + if(this.command == "fontName" && choice.indexOf(" ") != -1){ choice = "'" + choice + "'"; } + + // Invoke, the editor already normalizes commands called through its + // execCommand. + if(this.button._execCommand){ + this.button._execCommand(this.editor, this.command, choice); + }else{ + this.editor.execCommand(this.command, choice); + } + }); + }, + + updateState: function(){ + // summary: + // Overrides _Plugin.updateState(). This controls updating the menu + // options to the right values on state changes in the document (that trigger a + // test of the actions.) + // It set value of drop down in toolbar to reflect font/font size/format block + // of text at current caret position. + // tags: + // protected + var _e = this.editor; + var _c = this.command; + if(!_e || !_e.isLoaded || !_c.length){ return; } + + if(this.button){ + var disabled = this.get("disabled"); + this.button.set("disabled", disabled); + if(disabled){ return; } + var value; + try{ + value = _e.queryCommandValue(_c) || ""; + }catch(e){ + //Firefox may throw error above if the editor is just loaded, ignore it + value = ""; + } + + // strip off single quotes, if any + var quoted = dojo.isString(value) && value.match(/'([^']*)'/); + if(quoted){ value = quoted[1]; } + + if(_c === "formatBlock"){ + if(!value || value == "p"){ + // Some browsers (WebKit) doesn't actually get the tag info right. + // and IE returns paragraph when in a DIV!, so incorrect a lot, + // so we have double-check it. + value = null; + var elem; + // Try to find the current element where the caret is. + var sel = dijit.range.getSelection(this.editor.window); + if(sel && sel.rangeCount > 0){ + var range = sel.getRangeAt(0); + if(range){ + elem = range.endContainer; + } + } + + // Okay, now see if we can find one of the formatting types we're in. + while(elem && elem !== _e.editNode && elem !== _e.document){ + var tg = elem.tagName?elem.tagName.toLowerCase():""; + if(tg && dojo.indexOf(this.button.values, tg) > -1){ + value = tg; + break; + } + elem = elem.parentNode; + } + if(!value){ + // Still no value, so lets select 'none'. + value = "noFormat"; + } + }else{ + // Check that the block format is one allowed, if not, + // null it so that it gets set to empty. + if(dojo.indexOf(this.button.values, value) < 0){ + value = "noFormat"; + } + } + } + if(value !== this.button.get("value")){ + // Set the value, but denote it is not a priority change, so no + // onchange fires. + this.button.set('value', value, false); + } + } + } }); + +// Register this plugin. +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, + plainText: o.args.plainText?o.args.plainText:false + }); + } +}); + } diff --git a/lib/dijit/_editor/plugins/FullScreen.js b/lib/dijit/_editor/plugins/FullScreen.js index 7a6dac55d..6978252c8 100644 --- a/lib/dijit/_editor/plugins/FullScreen.js +++ b/lib/dijit/_editor/plugins/FullScreen.js @@ -1,232 +1,441 @@ /* - Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved. + Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved. Available via Academic Free License >= 2.1 OR the modified BSD license. see: http://dojotoolkit.org/license for details */ -if(!dojo._hasResource["dijit._editor.plugins.FullScreen"]){ -dojo._hasResource["dijit._editor.plugins.FullScreen"]=true; +if(!dojo._hasResource["dijit._editor.plugins.FullScreen"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dijit._editor.plugins.FullScreen"] = true; dojo.provide("dijit._editor.plugins.FullScreen"); dojo.require("dojo.window"); dojo.require("dojo.i18n"); dojo.require("dijit._editor._Plugin"); dojo.require("dijit.form.Button"); -dojo.requireLocalization("dijit._editor","commands",null,"ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,ko,nb,nl,pl,pt,pt-pt,ro,ru,sk,sl,sv,th,tr,zh,zh-tw"); -dojo.declare("dijit._editor.plugins.FullScreen",dijit._editor._Plugin,{zIndex:500,_origState:null,_origiFrameState:null,_resizeHandle:null,isFullscreen:false,toggle:function(){ -this.button.set("checked",!this.button.get("checked")); -},_initButton:function(){ -var _1=dojo.i18n.getLocalization("dijit._editor","commands"),_2=this.editor; -this.button=new dijit.form.ToggleButton({label:_1["fullScreen"],dir:_2.dir,lang:_2.lang,showLabel:false,iconClass:this.iconClassPrefix+" "+this.iconClassPrefix+"FullScreen",tabIndex:"-1",onChange:dojo.hitch(this,"_setFullScreen")}); -},setEditor:function(_3){ -this.editor=_3; -this._initButton(); -this.editor.addKeyHandler(dojo.keys.F11,true,true,dojo.hitch(this,function(e){ -this.toggle(); -dojo.stopEvent(e); -setTimeout(dojo.hitch(this,function(){ -this.editor.focus(); -}),250); -return true; -})); -this.connect(this.editor.domNode,"onkeydown","_containFocus"); -},_containFocus:function(e){ -if(this.isFullscreen){ -var ed=this.editor; -if(!ed.isTabIndent&&ed._fullscreen_oldOnKeyDown&&e.keyCode===dojo.keys.TAB){ -var f=dijit.getFocus(); -var _4=this._getAltViewNode(); -if(f.node==ed.iframe||(_4&&f.node===_4)){ -setTimeout(dojo.hitch(this,function(){ -ed.toolbar.focus(); -}),10); -}else{ -if(_4&&dojo.style(ed.iframe,"display")==="none"){ -setTimeout(dojo.hitch(this,function(){ -dijit.focus(_4); -}),10); -}else{ -setTimeout(dojo.hitch(this,function(){ -ed.focus(); -}),10); -} -} -dojo.stopEvent(e); -}else{ -if(ed._fullscreen_oldOnKeyDown){ -ed._fullscreen_oldOnKeyDown(e); -} -} -} -},_resizeEditor:function(){ -var vp=dojo.window.getBox(); -dojo.marginBox(this.editor.domNode,{w:vp.w,h:vp.h}); -var _5=this.editor.getHeaderHeight(); -var _6=this.editor.getFooterHeight(); -var _7=dojo._getPadBorderExtents(this.editor.domNode); -var _8=dojo._getPadBorderExtents(this.editor.iframe.parentNode); -var _9=dojo._getMarginExtents(this.editor.iframe.parentNode); -var _a=vp.h-(_5+_7.h+_6); -dojo.marginBox(this.editor.iframe.parentNode,{h:_a,w:vp.w}); -dojo.marginBox(this.editor.iframe,{h:_a-(_8.h+_9.h)}); -},_getAltViewNode:function(){ -},_setFullScreen:function(_b){ -var vp=dojo.window.getBox(); -var ed=this.editor; -var _c=dojo.body(); -var _d=ed.domNode.parentNode; -this.isFullscreen=_b; -if(_b){ -while(_d&&_d!==dojo.body()){ -dojo.addClass(_d,"dijitForceStatic"); -_d=_d.parentNode; -} -this._editorResizeHolder=this.editor.resize; -ed.resize=function(){ -}; -ed._fullscreen_oldOnKeyDown=ed.onKeyDown; -ed.onKeyDown=dojo.hitch(this,this._containFocus); -this._origState={}; -this._origiFrameState={}; -var _e=ed.domNode,_f=_e&&_e.style||{}; -this._origState={width:_f.width||"",height:_f.height||"",top:dojo.style(_e,"top")||"",left:dojo.style(_e,"left")||"",position:dojo.style(_e,"position")||"static",marginBox:dojo.marginBox(ed.domNode)}; -var _10=ed.iframe,_11=_10&&_10.style||{}; -var bc=dojo.style(ed.iframe,"backgroundColor"); -this._origiFrameState={backgroundColor:bc||"transparent",width:_11.width||"auto",height:_11.height||"auto",zIndex:_11.zIndex||""}; -dojo.style(ed.domNode,{position:"absolute",top:"0px",left:"0px",zIndex:this.zIndex,width:vp.w+"px",height:vp.h+"px"}); -dojo.style(ed.iframe,{height:"100%",width:"100%",zIndex:this.zIndex,backgroundColor:bc!=="transparent"&&bc!=="rgba(0, 0, 0, 0)"?bc:"white"}); -dojo.style(ed.iframe.parentNode,{height:"95%",width:"100%"}); -if(_c.style&&_c.style.overflow){ -this._oldOverflow=dojo.style(_c,"overflow"); -}else{ -this._oldOverflow=""; -} -if(dojo.isIE&&!dojo.isQuirks){ -if(_c.parentNode&&_c.parentNode.style&&_c.parentNode.style.overflow){ -this._oldBodyParentOverflow=_c.parentNode.style.overflow; -}else{ -try{ -this._oldBodyParentOverflow=dojo.style(_c.parentNode,"overflow"); -} -catch(e){ -this._oldBodyParentOverflow="scroll"; -} -} -dojo.style(_c.parentNode,"overflow","hidden"); -} -dojo.style(_c,"overflow","hidden"); -var _12=function(){ -var vp=dojo.window.getBox(); -if("_prevW" in this&&"_prevH" in this){ -if(vp.w===this._prevW&&vp.h===this._prevH){ -return; -} -}else{ -this._prevW=vp.w; -this._prevH=vp.h; -} -if(this._resizer){ -clearTimeout(this._resizer); -delete this._resizer; -} -this._resizer=setTimeout(dojo.hitch(this,function(){ -delete this._resizer; -this._resizeEditor(); -}),10); -}; -this._resizeHandle=dojo.connect(window,"onresize",this,_12); -this._resizeHandle2=dojo.connect(ed,"resize",dojo.hitch(this,function(){ -if(this._resizer){ -clearTimeout(this._resizer); -delete this._resizer; -} -this._resizer=setTimeout(dojo.hitch(this,function(){ -delete this._resizer; -this._resizeEditor(); -}),10); -})); -this._resizeEditor(); -var dn=this.editor.toolbar.domNode; -setTimeout(function(){ -dojo.window.scrollIntoView(dn); -},250); -}else{ -if(this._resizeHandle){ -dojo.disconnect(this._resizeHandle); -this._resizeHandle=null; -} -if(this._resizeHandle2){ -dojo.disconnect(this._resizeHandle2); -this._resizeHandle2=null; -} -if(this._rst){ -clearTimeout(this._rst); -this._rst=null; -} -while(_d&&_d!==dojo.body()){ -dojo.removeClass(_d,"dijitForceStatic"); -_d=_d.parentNode; -} -if(this._editorResizeHolder){ -this.editor.resize=this._editorResizeHolder; -} -if(!this._origState&&!this._origiFrameState){ -return; -} -if(ed._fullscreen_oldOnKeyDown){ -ed.onKeyDown=ed._fullscreen_oldOnKeyDown; -delete ed._fullscreen_oldOnKeyDown; -} -var _13=this; -setTimeout(function(){ -var mb=_13._origState.marginBox; -var oh=_13._origState.height; -if(dojo.isIE&&!dojo.isQuirks){ -_c.parentNode.style.overflow=_13._oldBodyParentOverflow; -delete _13._oldBodyParentOverflow; -} -dojo.style(_c,"overflow",_13._oldOverflow); -delete _13._oldOverflow; -dojo.style(ed.domNode,_13._origState); -dojo.style(ed.iframe.parentNode,{height:"",width:""}); -dojo.style(ed.iframe,_13._origiFrameState); -delete _13._origState; -delete _13._origiFrameState; -var _14=dijit.getEnclosingWidget(ed.domNode.parentNode); -if(_14&&_14.resize){ -_14.resize(); -}else{ -if(!oh||oh.indexOf("%")<0){ -setTimeout(dojo.hitch(this,function(){ -ed.resize({h:mb.h}); -}),0); -} -} -dojo.window.scrollIntoView(_13.editor.toolbar.domNode); -},100); -} -},destroy:function(){ -if(this._resizeHandle){ -dojo.disconnect(this._resizeHandle); -this._resizeHandle=null; -} -if(this._resizeHandle2){ -dojo.disconnect(this._resizeHandle2); -this._resizeHandle2=null; -} -if(this._resizer){ -clearTimeout(this._resizer); -this._resizer=null; -} -this.inherited(arguments); -}}); -dojo.subscribe(dijit._scopeName+".Editor.getPlugin",null,function(o){ -if(o.plugin){ -return; -} -var _15=o.args.name.toLowerCase(); -if(_15==="fullscreen"){ -o.plugin=new dijit._editor.plugins.FullScreen({zIndex:("zIndex" in o.args)?o.args.zIndex:500}); -} +dojo.requireLocalization("dijit._editor", "commands", null, "ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,kk,ko,nb,nl,pl,pt,pt-pt,ro,ru,sk,sl,sv,th,tr,zh,zh-tw"); + + +dojo.declare("dijit._editor.plugins.FullScreen",dijit._editor._Plugin,{ + // summary: + // This plugin provides FullScreen cabability to the editor. When + // toggled on, it will render the editor into the full window and + // overlay everything. It also binds to the hotkey: CTRL-SHIFT-F11 + // for toggling fullscreen mode. + + // zIndex: [public] Number + // zIndex value used for overlaying the full page. + // default is 500. + zIndex: 500, + + // _origState: [private] Object + // The original view state of the editor. + _origState: null, + + // _origiFrameState: [private] Object + // The original view state of the iframe of the editor. + _origiFrameState: null, + + // _resizeHandle: [private] Object + // Connection point used for handling resize when window resizes. + _resizeHandle: null, + + // isFullscreen: [const] boolean + // Read-Only variable used to denote of the editor is in fullscreen mode or not. + isFullscreen: false, + + toggle: function(){ + // summary: + // Function to allow programmatic toggling of the view. + this.button.set("checked", !this.button.get("checked")); + }, + + _initButton: function(){ + // summary: + // Over-ride for creation of the resize button. + var strings = dojo.i18n.getLocalization("dijit._editor", "commands"), + editor = this.editor; + this.button = new dijit.form.ToggleButton({ + label: strings["fullScreen"], + dir: editor.dir, + lang: editor.lang, + showLabel: false, + iconClass: this.iconClassPrefix + " " + this.iconClassPrefix + "FullScreen", + tabIndex: "-1", + onChange: dojo.hitch(this, "_setFullScreen") + }); + }, + + setEditor: function(editor){ + // summary: + // Over-ride for the setting of the editor. + // editor: Object + // The editor to configure for this plugin to use. + this.editor = editor; + this._initButton(); + + this.editor.addKeyHandler(dojo.keys.F11, true, true, dojo.hitch(this, function(e){ + // Enable the CTRL-SHIFT-F11 hotkey for fullscreen mode. + this.toggle(); + dojo.stopEvent(e); + setTimeout(dojo.hitch(this, function(){this.editor.focus();}), 250); + return true; + })); + this.connect(this.editor.domNode, "onkeydown", "_containFocus"); + }, + + _containFocus: function(e){ + // summary: + // When in Full Screen mode, it's good to try and retain focus in the editor + // so this function is intended to try and constrain the TAB key. + // e: Event + // The key event. + // tags: + // private + if(this.isFullscreen){ + var ed = this.editor; + if(!ed.isTabIndent && + ed._fullscreen_oldOnKeyDown && + e.keyCode === dojo.keys.TAB){ + // If we're in fullscreen mode, we want to take over how tab moves focus a bit. + // to keep it within the editor since it's hiding the rest of the page. + // IE hates changing focus IN the event handler, so need to put calls + // in a timeout. Gotta love IE. + // Also need to check for alternate view nodes if present and active. + var f = dijit.getFocus(); + var avn = this._getAltViewNode(); + if(f.node == ed.iframe || + (avn && f.node === avn)){ + setTimeout(dojo.hitch(this, function(){ + ed.toolbar.focus(); + }), 10); + }else{ + if(avn && dojo.style(ed.iframe, "display") === "none"){ + setTimeout(dojo.hitch(this, function(){ + dijit.focus(avn); + }), 10); + }else{ + setTimeout(dojo.hitch(this, function(){ + ed.focus(); + }), 10); + } + } + dojo.stopEvent(e); + }else if(ed._fullscreen_oldOnKeyDown){ + // Only call up when it's a different function. Traps corner case event issue + // on IE which caused stack overflow on handler cleanup. + ed._fullscreen_oldOnKeyDown(e); + } + } + }, + + _resizeEditor: function(){ + // summary: + // Function to handle resizing the editor as the viewport + // resizes (window scaled) + // tags: + // private + var vp = dojo.window.getBox(); + dojo.marginBox(this.editor.domNode, { + w: vp.w, + h: vp.h + }); + + //Adjust the inernal heights too, as they can be a bit off. + var hHeight = this.editor.getHeaderHeight(); + var fHeight = this.editor.getFooterHeight(); + var extents = dojo._getPadBorderExtents(this.editor.domNode); + var fcpExtents = dojo._getPadBorderExtents(this.editor.iframe.parentNode); + var fcmExtents = dojo._getMarginExtents(this.editor.iframe.parentNode); + + var cHeight = vp.h - (hHeight + extents.h + fHeight); + dojo.marginBox(this.editor.iframe.parentNode, { + h: cHeight, + w: vp.w + }); + dojo.marginBox(this.editor.iframe, { + h: cHeight - (fcpExtents.h + fcmExtents.h) + }); + }, + + _getAltViewNode: function(){ + // summary: + // This function is intended as a hook point for setting an + // alternate view node for when in full screen mode and the + // editable iframe is hidden. + // tags: + // protected. + }, + + _setFullScreen: function(full){ + // summary: + // Function to handle toggling between full screen and + // regular view. + // tags: + // private + var vp = dojo.window.getBox(); + + //Alias this for shorter code. + var ed = this.editor; + var body = dojo.body(); + var editorParent = ed.domNode.parentNode; + + this.isFullscreen = full; + + if(full){ + //Parent classes can royally screw up this plugin, so we + //have to set eveything to position static. + while(editorParent && editorParent !== dojo.body()){ + dojo.addClass(editorParent, "dijitForceStatic"); + editorParent = editorParent.parentNode; + } + + // Save off the resize function. We want to kill its behavior. + this._editorResizeHolder = this.editor.resize; + ed.resize = function() {} ; + + // Try to constrain focus control. + ed._fullscreen_oldOnKeyDown = ed.onKeyDown; + ed.onKeyDown = dojo.hitch(this, this._containFocus); + + this._origState = {}; + this._origiFrameState = {}; + + // Store the basic editor state we have to restore later. + // Not using dojo.style here, had problems, didn't + // give me stuff like 100%, gave me pixel calculated values. + // Need the exact original values. + var domNode = ed.domNode, + domStyle = domNode && domNode.style || {}; + this._origState = { + width: domStyle.width || "", + height: domStyle.height || "", + top: dojo.style(domNode, "top") || "", + left: dojo.style(domNode, "left") || "", + position: dojo.style(domNode, "position") || "static", + marginBox: dojo.marginBox(ed.domNode) + }; + + // Store the iframe state we have to restore later. + // Not using dojo.style here, had problems, didn't + // give me stuff like 100%, gave me pixel calculated values. + // Need the exact original values. + var iframe = ed.iframe, + iframeStyle = iframe && iframe.style || {}; + + var bc = dojo.style(ed.iframe, "backgroundColor"); + this._origiFrameState = { + backgroundColor: bc || "transparent", + width: iframeStyle.width || "auto", + height: iframeStyle.height || "auto", + zIndex: iframeStyle.zIndex || "" + }; + + // Okay, size everything. + dojo.style(ed.domNode, { + position: "absolute", + top: "0px", + left: "0px", + zIndex: this.zIndex, + width: vp.w + "px", + height: vp.h + "px" + }); + + dojo.style(ed.iframe, { + height: "100%", + width: "100%", + zIndex: this.zIndex, + backgroundColor: bc !== "transparent" && + bc !== "rgba(0, 0, 0, 0)"?bc:"white" + }); + + dojo.style(ed.iframe.parentNode, { + height: "95%", + width: "100%" + }); + + // Store the overflow state we have to restore later. + // IE had issues, so have to check that it's defined. Ugh. + if(body.style && body.style.overflow){ + this._oldOverflow = dojo.style(body, "overflow"); + }else{ + this._oldOverflow = ""; + } + + if(dojo.isIE && !dojo.isQuirks){ + // IE will put scrollbars in anyway, html (parent of body) + // also controls them in standards mode, so we have to + // remove them, argh. + if(body.parentNode && + body.parentNode.style && + body.parentNode.style.overflow){ + this._oldBodyParentOverflow = body.parentNode.style.overflow; + }else{ + try{ + this._oldBodyParentOverflow = dojo.style(body.parentNode, "overflow"); + }catch(e){ + this._oldBodyParentOverflow = "scroll"; + } + } + dojo.style(body.parentNode, "overflow", "hidden"); + } + dojo.style(body, "overflow", "hidden"); + + var resizer = function(){ + // function to handle resize events. + // Will check current VP and only resize if + // different. + var vp = dojo.window.getBox(); + if("_prevW" in this && "_prevH" in this){ + // No actual size change, ignore. + if(vp.w === this._prevW && vp.h === this._prevH){ + return; + } + }else{ + this._prevW = vp.w; + this._prevH = vp.h; + } + if(this._resizer){ + clearTimeout(this._resizer); + delete this._resizer; + } + // Timeout it to help avoid spamming resize on IE. + // Works for all browsers. + this._resizer = setTimeout(dojo.hitch(this, function(){ + delete this._resizer; + this._resizeEditor(); + }), 10); + }; + this._resizeHandle = dojo.connect(window, "onresize", this, resizer); + + // Also monitor for direct calls to resize and adapt editor. + this._resizeHandle2 = dojo.connect(ed, "resize", dojo.hitch(this, function(){ + if(this._resizer){ + clearTimeout(this._resizer); + delete this._resizer; + } + this._resizer = setTimeout(dojo.hitch(this, function(){ + delete this._resizer; + this._resizeEditor(); + }), 10); + })); + + // Call it once to work around IE glitchiness. Safe for other browsers too. + this._resizeEditor(); + var dn = this.editor.toolbar.domNode; + setTimeout(function(){dojo.window.scrollIntoView(dn);}, 250); + }else{ + if(this._resizeHandle){ + // Cleanup resizing listeners + dojo.disconnect(this._resizeHandle); + this._resizeHandle = null; + } + if(this._resizeHandle2){ + // Cleanup resizing listeners + dojo.disconnect(this._resizeHandle2); + this._resizeHandle2 = null; + } + if(this._rst){ + clearTimeout(this._rst); + this._rst = null; + } + + //Remove all position static class assigns. + while(editorParent && editorParent !== dojo.body()){ + dojo.removeClass(editorParent, "dijitForceStatic"); + editorParent = editorParent.parentNode; + } + + // Restore resize function + if(this._editorResizeHolder){ + this.editor.resize = this._editorResizeHolder; + } + + if(!this._origState && !this._origiFrameState){ + // If we actually didn't toggle, then don't do anything. + return; + } + if(ed._fullscreen_oldOnKeyDown){ + ed.onKeyDown = ed._fullscreen_oldOnKeyDown; + delete ed._fullscreen_oldOnKeyDown; + } + + // Add a timeout to make sure we don't have a resize firing in the + // background at the time of minimize. + var self = this; + setTimeout(function(){ + // Restore all the editor state. + var mb = self._origState.marginBox; + var oh = self._origState.height; + if(dojo.isIE && !dojo.isQuirks){ + body.parentNode.style.overflow = self._oldBodyParentOverflow; + delete self._oldBodyParentOverflow; + } + dojo.style(body, "overflow", self._oldOverflow); + delete self._oldOverflow; + + dojo.style(ed.domNode, self._origState); + dojo.style(ed.iframe.parentNode, { + height: "", + width: "" + }); + dojo.style(ed.iframe, self._origiFrameState); + delete self._origState; + delete self._origiFrameState; + // In case it is contained in a layout and the layout changed size, + // go ahead and call resize. + var pWidget = dijit.getEnclosingWidget(ed.domNode.parentNode); + if(pWidget && pWidget.resize){ + pWidget.resize(); + }else{ + if(!oh || oh.indexOf("%") < 0){ + // Resize if the original size wasn't set + // or wasn't in percent. Timeout is to avoid + // an IE crash in unit testing. + setTimeout(dojo.hitch(this, function(){ed.resize({h: mb.h});}), 0); + } + } + dojo.window.scrollIntoView(self.editor.toolbar.domNode); + }, 100); + } + }, + + updateState: function(){ + // summary: + // Over-ride for button state control for disabled to work. + this.button.set("disabled", this.get("disabled")); + }, + + destroy: function(){ + // summary: + // Over-ride to ensure the resize handle gets cleaned up. + if(this._resizeHandle){ + // Cleanup resizing listeners + dojo.disconnect(this._resizeHandle); + this._resizeHandle = null; + } + if(this._resizeHandle2){ + // Cleanup resizing listeners + dojo.disconnect(this._resizeHandle2); + this._resizeHandle2 = null; + } + if(this._resizer){ + clearTimeout(this._resizer); + this._resizer = null; + } + this.inherited(arguments); + } }); + + +// Register this plugin. +dojo.subscribe(dijit._scopeName + ".Editor.getPlugin",null,function(o){ + if(o.plugin){ return; } + var name = o.args.name.toLowerCase(); + if(name === "fullscreen"){ + o.plugin = new dijit._editor.plugins.FullScreen({ + zIndex: ("zIndex" in o.args)?o.args.zIndex:500 + }); + } +}); + } diff --git a/lib/dijit/_editor/plugins/LinkDialog.js b/lib/dijit/_editor/plugins/LinkDialog.js index 71de3ad8f..feb5cf9ec 100644 --- a/lib/dijit/_editor/plugins/LinkDialog.js +++ b/lib/dijit/_editor/plugins/LinkDialog.js @@ -1,236 +1,516 @@ /* - Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved. + Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved. Available via Academic Free License >= 2.1 OR the modified BSD license. see: http://dojotoolkit.org/license for details */ -if(!dojo._hasResource["dijit._editor.plugins.LinkDialog"]){ -dojo._hasResource["dijit._editor.plugins.LinkDialog"]=true; +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.TooltipDialog"); -dojo.require("dijit.form.Button"); +dojo.require("dijit.form.DropDownButton"); dojo.require("dijit.form.ValidationTextBox"); dojo.require("dijit.form.Select"); dojo.require("dijit._editor.range"); dojo.require("dojo.i18n"); dojo.require("dojo.string"); -dojo.requireLocalization("dijit","common",null,"ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,ko,nb,nl,pl,pt,pt-pt,ro,ru,sk,sl,sv,th,tr,zh,zh-tw"); -dojo.requireLocalization("dijit._editor","LinkDialog",null,"ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,ko,nb,nl,pl,pt,pt-pt,ro,ru,sk,sl,sv,th,tr,zh,zh-tw"); -dojo.declare("dijit._editor.plugins.LinkDialog",dijit._editor._Plugin,{buttonClass:dijit.form.DropDownButton,useDefaultCommand:false,urlRegExp:"((https?|ftps?|file)\\://|./|/|)(/[a-zA-Z]{1,1}:/|)(((?:(?:[\\da-zA-Z](?:[-\\da-zA-Z]{0,61}[\\da-zA-Z])?)\\.)*(?:[a-zA-Z](?:[-\\da-zA-Z]{0,80}[\\da-zA-Z])?)\\.?)|(((\\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])))(\\:\\d+)?(/(?:[^?#\\s/]+/)*(?:[^?#\\s/]+(?:\\?[^?#\\s/]*)?(?:#.*)?)?)?",emailRegExp:"<?(mailto\\:)([!#-'*+\\-\\/-9=?A-Z^-~]+[.])*[!#-'*+\\-\\/-9=?A-Z^-~]+"+"@"+"((?:(?:[\\da-zA-Z](?:[-\\da-zA-Z]{0,61}[\\da-zA-Z])?)\\.)+(?:[a-zA-Z](?:[-\\da-zA-Z]{0,6}[\\da-zA-Z])?)\\.?)|localhost|^[^-][a-zA-Z0-9_-]*>?",htmlTemplate:"<a href=\"${urlInput}\" _djrealurl=\"${urlInput}\""+" target=\"${targetSelect}\""+">${textInput}</a>",tag:"a",_hostRxp:new RegExp("^((([^\\[:]+):)?([^@]+)@)?(\\[([^\\]]+)\\]|([^\\[:]*))(:([0-9]+))?$"),_userAtRxp:new RegExp("^([!#-'*+\\-\\/-9=?A-Z^-~]+[.])*[!#-'*+\\-\\/-9=?A-Z^-~]+@","i"),linkDialogTemplate:["<table><tr><td>","<label for='${id}_urlInput'>${url}</label>","</td><td>","<input dojoType='dijit.form.ValidationTextBox' required='true' "+"id='${id}_urlInput' name='urlInput' intermediateChanges='true'>","</td></tr><tr><td>","<label for='${id}_textInput'>${text}</label>","</td><td>","<input dojoType='dijit.form.ValidationTextBox' required='true' id='${id}_textInput' "+"name='textInput' intermediateChanges='true'>","</td></tr><tr><td>","<label for='${id}_targetSelect'>${target}</label>","</td><td>","<select id='${id}_targetSelect' name='targetSelect' dojoType='dijit.form.Select'>","<option selected='selected' value='_self'>${currentWindow}</option>","<option value='_blank'>${newWindow}</option>","<option value='_top'>${topWindow}</option>","<option value='_parent'>${parentWindow}</option>","</select>","</td></tr><tr><td colspan='2'>","<button dojoType='dijit.form.Button' type='submit' id='${id}_setButton'>${set}</button>","<button dojoType='dijit.form.Button' type='button' id='${id}_cancelButton'>${buttonCancel}</button>","</td></tr></table>"].join(""),_initButton:function(){ -var _1=this; -this.tag=this.command=="insertImage"?"img":"a"; -var _2=dojo.mixin(dojo.i18n.getLocalization("dijit","common",this.lang),dojo.i18n.getLocalization("dijit._editor","LinkDialog",this.lang)); -var _3=(this.dropDown=new dijit.TooltipDialog({title:_2[this.command+"Title"],execute:dojo.hitch(this,"setValue"),onOpen:function(){ -_1._onOpenDialog(); -dijit.TooltipDialog.prototype.onOpen.apply(this,arguments); -},onCancel:function(){ -setTimeout(dojo.hitch(_1,"_onCloseDialog"),0); -}})); -_2.urlRegExp=this.urlRegExp; -_2.id=dijit.getUniqueId(this.editor.id); -this._uniqueId=_2.id; -this._setContent(_3.title+"<div style='border-bottom: 1px black solid;padding-bottom:2pt;margin-bottom:4pt'></div>"+dojo.string.substitute(this.linkDialogTemplate,_2)); -_3.startup(); -this._urlInput=dijit.byId(this._uniqueId+"_urlInput"); -this._textInput=dijit.byId(this._uniqueId+"_textInput"); -this._setButton=dijit.byId(this._uniqueId+"_setButton"); -this.connect(dijit.byId(this._uniqueId+"_cancelButton"),"onClick",function(){ -this.dropDown.onCancel(); +dojo.requireLocalization("dijit", "common", null, "ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,kk,ko,nb,nl,pl,pt,pt-pt,ro,ru,sk,sl,sv,th,tr,zh,zh-tw"); +dojo.requireLocalization("dijit._editor", "LinkDialog", null, "ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,kk,ko,nb,nl,pl,pt,pt-pt,ro,ru,sk,sl,sv,th,tr,zh,zh-tw"); + + +dojo.declare("dijit._editor.plugins.LinkDialog", dijit._editor._Plugin, { + // summary: + // This plugin provides the basis for an 'anchor' (link) dialog and an extension of it + // provides the image link dialog. + // + // description: + // The command provided by this plugin is: + // * createLink + + // Override _Plugin.buttonClass. This plugin is controlled by a DropDownButton + // (which triggers a TooltipDialog). + buttonClass: dijit.form.DropDownButton, + + // Override _Plugin.useDefaultCommand... processing is handled by this plugin, not by dijit.Editor. + useDefaultCommand: false, + + // urlRegExp: [protected] String + // Used for validating input as correct URL. While file:// urls are not terribly + // useful, they are technically valid. + urlRegExp: "((https?|ftps?|file)\\://|\./|/|)(/[a-zA-Z]{1,1}:/|)(((?:(?:[\\da-zA-Z](?:[-\\da-zA-Z]{0,61}[\\da-zA-Z])?)\\.)*(?:[a-zA-Z](?:[-\\da-zA-Z]{0,80}[\\da-zA-Z])?)\\.?)|(((\\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])))(\\:\\d+)?(/(?:[^?#\\s/]+/)*(?:[^?#\\s/]{0,}(?:\\?[^?#\\s/]*)?(?:#.*)?)?)?", + + // emailRegExp: [protected] String + // Used for validating input as correct email address. Taken from dojox.validate + emailRegExp: "<?(mailto\\:)([!#-'*+\\-\\/-9=?A-Z^-~]+[.])*[!#-'*+\\-\\/-9=?A-Z^-~]+" /*username*/ + "@" + + "((?:(?:[\\da-zA-Z](?:[-\\da-zA-Z]{0,61}[\\da-zA-Z])?)\\.)+(?:[a-zA-Z](?:[-\\da-zA-Z]{0,6}[\\da-zA-Z])?)\\.?)|localhost|^[^-][a-zA-Z0-9_-]*>?", // host. + + // htmlTemplate: [protected] String + // String used for templating the HTML to insert at the desired point. + htmlTemplate: "<a href=\"${urlInput}\" _djrealurl=\"${urlInput}\"" + + " target=\"${targetSelect}\"" + + ">${textInput}</a>", + + // tag: [protected] String + // Tag used for the link type. + tag: "a", + + // _hostRxp [private] RegExp + // Regular expression used to validate url fragments (ip address, hostname, etc) + _hostRxp: new RegExp("^((([^\\[:]+):)?([^@]+)@)?(\\[([^\\]]+)\\]|([^\\[:]*))(:([0-9]+))?$"), + + // _userAtRxp [private] RegExp + // Regular expression used to validate e-mail address fragment. + _userAtRxp: new RegExp("^([!#-'*+\\-\\/-9=?A-Z^-~]+[.])*[!#-'*+\\-\\/-9=?A-Z^-~]+@", "i"), + + // linkDialogTemplate: [protected] String + // Template for contents of TooltipDialog to pick URL + linkDialogTemplate: [ + "<table><tr><td>", + "<label for='${id}_urlInput'>${url}</label>", + "</td><td>", + "<input dojoType='dijit.form.ValidationTextBox' required='true' " + + "id='${id}_urlInput' name='urlInput' intermediateChanges='true'/>", + "</td></tr><tr><td>", + "<label for='${id}_textInput'>${text}</label>", + "</td><td>", + "<input dojoType='dijit.form.ValidationTextBox' required='true' id='${id}_textInput' " + + "name='textInput' intermediateChanges='true'/>", + "</td></tr><tr><td>", + "<label for='${id}_targetSelect'>${target}</label>", + "</td><td>", + "<select id='${id}_targetSelect' name='targetSelect' dojoType='dijit.form.Select'>", + "<option selected='selected' value='_self'>${currentWindow}</option>", + "<option value='_blank'>${newWindow}</option>", + "<option value='_top'>${topWindow}</option>", + "<option value='_parent'>${parentWindow}</option>", + "</select>", + "</td></tr><tr><td colspan='2'>", + "<button dojoType='dijit.form.Button' type='submit' id='${id}_setButton'>${set}</button>", + "<button dojoType='dijit.form.Button' type='button' id='${id}_cancelButton'>${buttonCancel}</button>", + "</td></tr></table>" + ].join(""), + + _initButton: function(){ + // Override _Plugin._initButton() to initialize DropDownButton and TooltipDialog. + var _this = this; + this.tag = this.command == 'insertImage' ? 'img' : 'a'; + var messages = dojo.mixin(dojo.i18n.getLocalization("dijit", "common", this.lang), + 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); + } + })); + messages.urlRegExp = this.urlRegExp; + messages.id = dijit.getUniqueId(this.editor.id); + this._uniqueId = messages.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._urlInput = dijit.byId(this._uniqueId + "_urlInput"); + this._textInput = dijit.byId(this._uniqueId + "_textInput"); + this._setButton = dijit.byId(this._uniqueId + "_setButton"); + this.connect(dijit.byId(this._uniqueId + "_cancelButton"), "onClick", function(){ + this.dropDown.onCancel(); + }); + if(this._urlInput){ + this.connect(this._urlInput, "onChange", "_checkAndFixInput"); + } + if(this._textInput){ + this.connect(this._textInput, "onChange", "_checkAndFixInput"); + } + + // Build up the dual check for http/https/file:, and mailto formats. + this._urlRegExp = new RegExp("^" + this.urlRegExp + "$", "i"); + this._emailRegExp = new RegExp("^" + this.emailRegExp + "$", "i"); + this._urlInput.isValid = dojo.hitch(this, function(){ + // Function over-ride of isValid to test if the input matches a url or a mailto style link. + var value = this._urlInput.get("value"); + return this._urlRegExp.test(value) || this._emailRegExp.test(value); + }); + + this._connectTagEvents(); + this.inherited(arguments); + }, + + _checkAndFixInput: function(){ + // summary: + // A function to listen for onChange events and test the input contents + // for valid information, such as valid urls with http/https/ftp and if + // not present, try and guess if the input url is relative or not, and if + // not, append http:// to it. Also validates other fields as determined by + // the internal _isValid function. + var self = this; + var url = this._urlInput.get("value"); + var fixupUrl = function(url){ + var appendHttp = false; + var appendMailto = false; + if(url && url.length > 1){ + url = dojo.trim(url); + if(url.indexOf("mailto:") !== 0){ + if(url.indexOf("/") > 0){ + if(url.indexOf("://") === -1){ + // Check that it doesn't start with / or ./, which would + // imply 'target server relativeness' + if(url.charAt(0) !== '/' && url.indexOf("./") !== 0){ + if(self._hostRxp.test(url)){ + appendHttp = true; + } + } + } + }else if(self._userAtRxp.test(url)){ + // If it looks like a foo@, append a mailto. + appendMailto = true; + } + } + } + if(appendHttp){ + self._urlInput.set("value", "http://" + url); + } + if(appendMailto){ + self._urlInput.set("value", "mailto:" + url); + } + self._setButton.set("disabled", !self._isValid()); + }; + if(this._delayedCheck){ + clearTimeout(this._delayedCheck); + this._delayedCheck = null; + } + this._delayedCheck = setTimeout(function(){ + fixupUrl(url); + }, 250); + }, + + _connectTagEvents: function(){ + // summary: + // Over-ridable function that connects tag specific events. + this.editor.onLoadDeferred.addCallback(dojo.hitch(this, function(){ + this.connect(this.editor.editNode, "ondblclick", this._onDblClick); + })); + }, + + _isValid: function(){ + // summary: + // Internal function to allow validating of the inputs + // for a link to determine if set should be disabled or not + // tags: + // protected + return this._urlInput.isValid() && this._textInput.isValid(); + }, + + _setContent: function(staticPanel){ + // summary: + // Helper for _initButton above. Not sure why it's a separate method. + this.dropDown.set({ + parserScope: "dojo", // make parser search for dojoType/data-dojo-type even if page is multi-version + content: staticPanel + }); + }, + + _checkValues: function(args){ + // summary: + // Function to check the values in args and 'fix' them up as needed. + // args: Object + // Content being set. + // tags: + // protected + if(args && args.urlInput){ + args.urlInput = args.urlInput.replace(/"/g, """); + } + return args; + }, + + setValue: function(args){ + // summary: + // Callback from the dialog when user presses "set" button. + // tags: + // private + //TODO: prevent closing popup if the text is empty + this._onCloseDialog(); + if(dojo.isIE < 9){ //see #4151 + var sel = dijit.range.getSelection(this.editor.window); + var range = sel.getRangeAt(0); + var a = range.endContainer; + if(a.nodeType === 3){ + // Text node, may be the link contents, so check parent. + // This plugin doesn't really support nested HTML elements + // in the link, it assumes all link content is text. + a = a.parentNode; + } + if(a && (a.nodeName && a.nodeName.toLowerCase() !== this.tag)){ + // Stll nothing, one last thing to try on IE, as it might be 'img' + // and thus considered a control. + a = dojo.withGlobal(this.editor.window, + "getSelectedElement", dijit._editor.selection, [this.tag]); + } + if(a && (a.nodeName && a.nodeName.toLowerCase() === this.tag)){ + // Okay, we do have a match. IE, for some reason, sometimes pastes before + // instead of removing the targetted paste-over element, so we unlink the + // old one first. If we do not the <a> tag remains, but it has no content, + // so isn't readily visible (but is wrong for the action). + if(this.editor.queryCommandEnabled("unlink")){ + // Select all the link childent, then unlink. The following insert will + // then replace the selected text. + dojo.withGlobal(this.editor.window, + "selectElementChildren", dijit._editor.selection, [a]); + this.editor.execCommand("unlink"); + } + } + } + // make sure values are properly escaped, etc. + args = this._checkValues(args); + this.editor.execCommand('inserthtml', + dojo.string.substitute(this.htmlTemplate, args)); + }, + + _onCloseDialog: function(){ + // summary: + // Handler for close event on the dialog + this.editor.focus(); + }, + + _getCurrentValues: function(a){ + // summary: + // Over-ride for getting the values to set in the dropdown. + // a: + // The anchor/link to process for data for the dropdown. + // tags: + // protected + var url, text, target; + if(a && a.tagName.toLowerCase() === this.tag){ + url = a.getAttribute('_djrealurl') || a.getAttribute('href'); + target = a.getAttribute('target') || "_self"; + text = 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); + } + return {urlInput: url || '', textInput: text || '', targetSelect: target || ''}; //Object; + }, + + _onOpenDialog: function(){ + // summary: + // Handler for when the dialog is opened. + // If the caret is currently in a URL then populate the URL's info into the dialog. + var a; + if(dojo.isIE < 9){ + // IE is difficult to select the element in, using the range unified + // API seems to work reasonably well. + var sel = dijit.range.getSelection(this.editor.window); + var range = sel.getRangeAt(0); + a = range.endContainer; + if(a.nodeType === 3){ + // Text node, may be the link contents, so check parent. + // This plugin doesn't really support nested HTML elements + // in the link, it assumes all link content is text. + a = a.parentNode; + } + if(a && (a.nodeName && a.nodeName.toLowerCase() !== this.tag)){ + // Stll nothing, one last thing to try on IE, as it might be 'img' + // and thus considered a control. + a = dojo.withGlobal(this.editor.window, + "getSelectedElement", dijit._editor.selection, [this.tag]); + } + }else{ + a = dojo.withGlobal(this.editor.window, + "getAncestorElement", dijit._editor.selection, [this.tag]); + } + this.dropDown.reset(); + this._setButton.set("disabled", true); + this.dropDown.set("value", this._getCurrentValues(a)); + }, + + _onDblClick: function(e){ + // summary: + // Function to define a behavior on double clicks on the element + // type this dialog edits to select it and pop up the editor + // dialog. + // e: Object + // The double-click event. + // tags: + // protected. + if(e && e.target){ + var t = e.target; + var tg = t.tagName? t.tagName.toLowerCase() : ""; + if(tg === this.tag && dojo.attr(t,"href")){ + dojo.withGlobal(this.editor.window, + "selectElement", + dijit._editor.selection, [t]); + this.editor.onDisplayChanged(); + + setTimeout(dojo.hitch(this, function(){ + // Focus shift outside the event handler. + // IE doesn't like focus changes in event handles. + this.button.set("disabled", false); + this.button.openDropDown(); + }), 10); + } + } + } }); -if(this._urlInput){ -this.connect(this._urlInput,"onChange","_checkAndFixInput"); -} -if(this._textInput){ -this.connect(this._textInput,"onChange","_checkAndFixInput"); -} -this._urlRegExp=new RegExp("^"+this.urlRegExp+"$","i"); -this._emailRegExp=new RegExp("^"+this.emailRegExp+"$","i"); -this._urlInput.isValid=dojo.hitch(this,function(){ -var _4=this._urlInput.get("value"); -return this._urlRegExp.test(_4)||this._emailRegExp.test(_4); + +dojo.declare("dijit._editor.plugins.ImgLinkDialog", [dijit._editor.plugins.LinkDialog], { + // summary: + // This plugin extends LinkDialog and adds in a plugin for handling image links. + // provides the image link dialog. + // + // description: + // The command provided by this plugin is: + // * insertImage + + // linkDialogTemplate: [protected] String + // Over-ride for template since img dialog doesn't need target that anchor tags may. + 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' intermediateChanges='true'/>", + "</td></tr><tr><td>", + "<label for='${id}_textInput'>${text}</label>", + "</td><td>", + "<input dojoType='dijit.form.ValidationTextBox' required='false' id='${id}_textInput' " + + "name='textInput' intermediateChanges='true'/>", + "</td></tr><tr><td>", + "</td><td>", + "</td></tr><tr><td colspan='2'>", + "<button dojoType='dijit.form.Button' type='submit' id='${id}_setButton'>${set}</button>", + "<button dojoType='dijit.form.Button' type='button' id='${id}_cancelButton'>${buttonCancel}</button>", + "</td></tr></table>" + ].join(""), + + // htmlTemplate: [protected] String + // String used for templating the <img> HTML to insert at the desired point. + htmlTemplate: "<img src=\"${urlInput}\" _djrealurl=\"${urlInput}\" alt=\"${textInput}\" />", + + // tag: [protected] String + // Tag used for the link type (img). + tag: "img", + + _getCurrentValues: function(img){ + // summary: + // Over-ride for getting the values to set in the dropdown. + // a: + // The anchor/link to process for data for the dropdown. + // tags: + // protected + var url, text; + if(img && img.tagName.toLowerCase() === this.tag){ + url = img.getAttribute('_djrealurl') || img.getAttribute('src'); + text = img.getAttribute('alt'); + dojo.withGlobal(this.editor.window, + "selectElement", dijit._editor.selection, [img, true]); + }else{ + text = dojo.withGlobal(this.editor.window, dijit._editor.selection.getSelectedText); + } + return {urlInput: url || '', textInput: text || ''}; //Object; + }, + + _isValid: function(){ + // summary: + // Over-ride for images. You can have alt text of blank, it is valid. + // tags: + // protected + return this._urlInput.isValid(); + }, + + _connectTagEvents: function(){ + // summary: + // Over-ridable function that connects tag specific events. + this.inherited(arguments); + this.editor.onLoadDeferred.addCallback(dojo.hitch(this, function(){ + // Use onmousedown instead of onclick. Seems that IE eats the first onclick + // to wrap it in a selector box, then the second one acts as onclick. See #10420 + this.connect(this.editor.editNode, "onmousedown", this._selectTag); + })); + }, + + _selectTag: function(e){ + // summary: + // A simple event handler that lets me select an image if it is clicked on. + // makes it easier to select images in a standard way across browsers. Otherwise + // selecting an image for edit becomes difficult. + // e: Event + // The mousedown event. + // tags: + // private + if(e && e.target){ + var t = e.target; + var tg = t.tagName? t.tagName.toLowerCase() : ""; + if(tg === this.tag){ + dojo.withGlobal(this.editor.window, + "selectElement", + dijit._editor.selection, [t]); + } + } + }, + + _checkValues: function(args){ + // summary: + // Function to check the values in args and 'fix' them up as needed + // (special characters in the url or alt text) + // args: Object + // Content being set. + // tags: + // protected + if(args && args.urlInput){ + args.urlInput = args.urlInput.replace(/"/g, """); + } + if(args && args.textInput){ + args.textInput = args.textInput.replace(/"/g, """); + } + return args; + }, + + _onDblClick: function(e){ + // summary: + // Function to define a behavior on double clicks on the element + // type this dialog edits to select it and pop up the editor + // dialog. + // e: Object + // The double-click event. + // tags: + // protected. + if(e && e.target){ + var t = e.target; + var tg = t.tagName? t.tagName.toLowerCase() : ""; + if(tg === this.tag && dojo.attr(t,"src")){ + dojo.withGlobal(this.editor.window, + "selectElement", + dijit._editor.selection, [t]); + this.editor.onDisplayChanged(); + setTimeout(dojo.hitch(this, function(){ + // Focus shift outside the event handler. + // IE doesn't like focus changes in event handles. + this.button.set("disabled", false); + this.button.openDropDown(); + }), 10); + } + } + } }); -this._connectTagEvents(); -this.inherited(arguments); -},_checkAndFixInput:function(){ -var _5=this; -var _6=this._urlInput.get("value"); -var _7=function(_8){ -var _9=false; -var _a=false; -if(_8&&_8.length>1){ -_8=dojo.trim(_8); -if(_8.indexOf("mailto:")!==0){ -if(_8.indexOf("/")>0){ -if(_8.indexOf("://")===-1){ -if(_8.charAt(0)!=="/"&&_8.indexOf("./")!==0){ -if(_5._hostRxp.test(_8)){ -_9=true; -} -} -} -}else{ -if(_5._userAtRxp.test(_8)){ -_a=true; -} -} -} -} -if(_9){ -_5._urlInput.set("value","http://"+_8); -} -if(_a){ -_5._urlInput.set("value","mailto:"+_8); -} -_5._setButton.set("disabled",!_5._isValid()); -}; -if(this._delayedCheck){ -clearTimeout(this._delayedCheck); -this._delayedCheck=null; -} -this._delayedCheck=setTimeout(function(){ -_7(_6); -},250); -},_connectTagEvents:function(){ -this.editor.onLoadDeferred.addCallback(dojo.hitch(this,function(){ -this.connect(this.editor.editNode,"ondblclick",this._onDblClick); -})); -},_isValid:function(){ -return this._urlInput.isValid()&&this._textInput.isValid(); -},_setContent:function(_b){ -this.dropDown.set("content",_b); -},_checkValues:function(_c){ -if(_c&&_c.urlInput){ -_c.urlInput=_c.urlInput.replace(/"/g,"""); -} -return _c; -},setValue:function(_d){ -this._onCloseDialog(); -if(dojo.isIE){ -var _e=dijit.range.getSelection(this.editor.window); -var _f=_e.getRangeAt(0); -var a=_f.endContainer; -if(a.nodeType===3){ -a=a.parentNode; -} -if(a&&(a.nodeName&&a.nodeName.toLowerCase()!==this.tag)){ -a=dojo.withGlobal(this.editor.window,"getSelectedElement",dijit._editor.selection,[this.tag]); -} -if(a&&(a.nodeName&&a.nodeName.toLowerCase()===this.tag)){ -if(this.editor.queryCommandEnabled("unlink")){ -dojo.withGlobal(this.editor.window,"selectElementChildren",dijit._editor.selection,[a]); -this.editor.execCommand("unlink"); -} -} -} -_d=this._checkValues(_d); -this.editor.execCommand("inserthtml",dojo.string.substitute(this.htmlTemplate,_d)); -},_onCloseDialog:function(){ -this.editor.focus(); -},_getCurrentValues:function(a){ -var url,_10,_11; -if(a&&a.tagName.toLowerCase()===this.tag){ -url=a.getAttribute("_djrealurl")||a.getAttribute("href"); -_11=a.getAttribute("target")||"_self"; -_10=a.textContent||a.innerText; -dojo.withGlobal(this.editor.window,"selectElement",dijit._editor.selection,[a,true]); -}else{ -_10=dojo.withGlobal(this.editor.window,dijit._editor.selection.getSelectedText); -} -return {urlInput:url||"",textInput:_10||"",targetSelect:_11||""}; -},_onOpenDialog:function(){ -var a; -if(dojo.isIE){ -var sel=dijit.range.getSelection(this.editor.window); -var _12=sel.getRangeAt(0); -a=_12.endContainer; -if(a.nodeType===3){ -a=a.parentNode; -} -if(a&&(a.nodeName&&a.nodeName.toLowerCase()!==this.tag)){ -a=dojo.withGlobal(this.editor.window,"getSelectedElement",dijit._editor.selection,[this.tag]); -} -}else{ -a=dojo.withGlobal(this.editor.window,"getAncestorElement",dijit._editor.selection,[this.tag]); -} -this.dropDown.reset(); -this._setButton.set("disabled",true); -this.dropDown.set("value",this._getCurrentValues(a)); -},_onDblClick:function(e){ -if(e&&e.target){ -var t=e.target; -var tg=t.tagName?t.tagName.toLowerCase():""; -if(tg===this.tag&&dojo.attr(t,"href")){ -dojo.withGlobal(this.editor.window,"selectElement",dijit._editor.selection,[t]); -this.editor.onDisplayChanged(); -setTimeout(dojo.hitch(this,function(){ -this.button.set("disabled",false); -this.button.openDropDown(); -}),10); -} -} -}}); -dojo.declare("dijit._editor.plugins.ImgLinkDialog",[dijit._editor.plugins.LinkDialog],{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' intermediateChanges='true'>","</td></tr><tr><td>","<label for='${id}_textInput'>${text}</label>","</td><td>","<input dojoType='dijit.form.ValidationTextBox' required='false' id='${id}_textInput' "+"name='textInput' intermediateChanges='true'>","</td></tr><tr><td>","</td><td>","</td></tr><tr><td colspan='2'>","<button dojoType='dijit.form.Button' type='submit' id='${id}_setButton'>${set}</button>","<button dojoType='dijit.form.Button' type='button' id='${id}_cancelButton'>${buttonCancel}</button>","</td></tr></table>"].join(""),htmlTemplate:"<img src=\"${urlInput}\" _djrealurl=\"${urlInput}\" alt=\"${textInput}\" />",tag:"img",_getCurrentValues:function(img){ -var url,_13; -if(img&&img.tagName.toLowerCase()===this.tag){ -url=img.getAttribute("_djrealurl")||img.getAttribute("src"); -_13=img.getAttribute("alt"); -dojo.withGlobal(this.editor.window,"selectElement",dijit._editor.selection,[img,true]); -}else{ -_13=dojo.withGlobal(this.editor.window,dijit._editor.selection.getSelectedText); -} -return {urlInput:url||"",textInput:_13||""}; -},_isValid:function(){ -return this._urlInput.isValid(); -},_connectTagEvents:function(){ -this.inherited(arguments); -this.editor.onLoadDeferred.addCallback(dojo.hitch(this,function(){ -this.connect(this.editor.editNode,"onmousedown",this._selectTag); -})); -},_selectTag:function(e){ -if(e&&e.target){ -var t=e.target; -var tg=t.tagName?t.tagName.toLowerCase():""; -if(tg===this.tag){ -dojo.withGlobal(this.editor.window,"selectElement",dijit._editor.selection,[t]); -} -} -},_checkValues:function(_14){ -if(_14&&_14.urlInput){ -_14.urlInput=_14.urlInput.replace(/"/g,"""); -} -if(_14&&_14.textInput){ -_14.textInput=_14.textInput.replace(/"/g,"""); -} -return _14; -},_onDblClick:function(e){ -if(e&&e.target){ -var t=e.target; -var tg=t.tagName?t.tagName.toLowerCase():""; -if(tg===this.tag&&dojo.attr(t,"src")){ -dojo.withGlobal(this.editor.window,"selectElement",dijit._editor.selection,[t]); -this.editor.onDisplayChanged(); -setTimeout(dojo.hitch(this,function(){ -this.button.set("disabled",false); -this.button.openDropDown(); -}),10); -} -} -}}); -dojo.subscribe(dijit._scopeName+".Editor.getPlugin",null,function(o){ -if(o.plugin){ -return; -} -switch(o.args.name){ -case "createLink": -o.plugin=new dijit._editor.plugins.LinkDialog({command:o.args.name}); -break; -case "insertImage": -o.plugin=new dijit._editor.plugins.ImgLinkDialog({command:o.args.name}); -break; -} + +// Register this plugin. +dojo.subscribe(dijit._scopeName + ".Editor.getPlugin",null,function(o){ + if(o.plugin){ return; } + switch(o.args.name){ + case "createLink": + o.plugin = new dijit._editor.plugins.LinkDialog({command: o.args.name}); + break; + case "insertImage": + o.plugin = new dijit._editor.plugins.ImgLinkDialog({command: o.args.name}); + break; + } }); + } diff --git a/lib/dijit/_editor/plugins/NewPage.js b/lib/dijit/_editor/plugins/NewPage.js index 14c2cfa62..7e628d364 100644 --- a/lib/dijit/_editor/plugins/NewPage.js +++ b/lib/dijit/_editor/plugins/NewPage.js @@ -1,36 +1,81 @@ /* - Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved. + Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved. Available via Academic Free License >= 2.1 OR the modified BSD license. see: http://dojotoolkit.org/license for details */ -if(!dojo._hasResource["dijit._editor.plugins.NewPage"]){ -dojo._hasResource["dijit._editor.plugins.NewPage"]=true; +if(!dojo._hasResource["dijit._editor.plugins.NewPage"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dijit._editor.plugins.NewPage"] = true; dojo.provide("dijit._editor.plugins.NewPage"); dojo.require("dijit._editor._Plugin"); dojo.require("dijit.form.Button"); dojo.require("dojo.i18n"); -dojo.requireLocalization("dijit._editor","commands",null,"ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,ko,nb,nl,pl,pt,pt-pt,ro,ru,sk,sl,sv,th,tr,zh,zh-tw"); -dojo.declare("dijit._editor.plugins.NewPage",dijit._editor._Plugin,{content:"<br>",_initButton:function(){ -var _1=dojo.i18n.getLocalization("dijit._editor","commands"),_2=this.editor; -this.button=new dijit.form.Button({label:_1["newPage"],dir:_2.dir,lang:_2.lang,showLabel:false,iconClass:this.iconClassPrefix+" "+this.iconClassPrefix+"NewPage",tabIndex:"-1",onClick:dojo.hitch(this,"_newPage")}); -},setEditor:function(_3){ -this.editor=_3; -this._initButton(); -},_newPage:function(){ -this.editor.beginEditing(); -this.editor.set("value",this.content); -this.editor.endEditing(); -this.editor.focus(); -}}); -dojo.subscribe(dijit._scopeName+".Editor.getPlugin",null,function(o){ -if(o.plugin){ -return; -} -var _4=o.args.name.toLowerCase(); -if(_4==="newpage"){ -o.plugin=new dijit._editor.plugins.NewPage({content:("content" in o.args)?o.args.content:"<br>"}); -} +dojo.requireLocalization("dijit._editor", "commands", null, "ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,kk,ko,nb,nl,pl,pt,pt-pt,ro,ru,sk,sl,sv,th,tr,zh,zh-tw"); + + +dojo.declare("dijit._editor.plugins.NewPage",dijit._editor._Plugin,{ + // summary: + // This plugin provides a simple 'new page' calability. In other + // words, set content to some default user defined string. + + // content: [public] String + // The default content to insert into the editor as the new page. + // The default is the <br> tag, a single blank line. + content: "<br>", + + _initButton: function(){ + // summary: + // Over-ride for creation of the Print button. + var strings = dojo.i18n.getLocalization("dijit._editor", "commands"), + editor = this.editor; + this.button = new dijit.form.Button({ + label: strings["newPage"], + dir: editor.dir, + lang: editor.lang, + showLabel: false, + iconClass: this.iconClassPrefix + " " + this.iconClassPrefix + "NewPage", + tabIndex: "-1", + onClick: dojo.hitch(this, "_newPage") + }); + }, + + setEditor: function(/*dijit.Editor*/ editor){ + // summary: + // Tell the plugin which Editor it is associated with. + // editor: Object + // The editor object to attach the newPage capability to. + this.editor = editor; + this._initButton(); + }, + + updateState: function(){ + // summary: + // Over-ride for button state control for disabled to work. + this.button.set("disabled", this.get("disabled")); + }, + + _newPage: function(){ + // summary: + // Function to set the content to blank. + // tags: + // private + this.editor.beginEditing(); + this.editor.set("value", this.content); + this.editor.endEditing(); + this.editor.focus(); + } }); + +// Register this plugin. +dojo.subscribe(dijit._scopeName + ".Editor.getPlugin",null,function(o){ + if(o.plugin){ return; } + var name = o.args.name.toLowerCase(); + if(name === "newpage"){ + o.plugin = new dijit._editor.plugins.NewPage({ + content: ("content" in o.args)?o.args.content:"<br>" + }); + } +}); + } diff --git a/lib/dijit/_editor/plugins/Print.js b/lib/dijit/_editor/plugins/Print.js index b2e739aee..83cf0ddc7 100644 --- a/lib/dijit/_editor/plugins/Print.js +++ b/lib/dijit/_editor/plugins/Print.js @@ -1,65 +1,125 @@ /* - Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved. + Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved. Available via Academic Free License >= 2.1 OR the modified BSD license. see: http://dojotoolkit.org/license for details */ -if(!dojo._hasResource["dijit._editor.plugins.Print"]){ -dojo._hasResource["dijit._editor.plugins.Print"]=true; +if(!dojo._hasResource["dijit._editor.plugins.Print"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dijit._editor.plugins.Print"] = true; dojo.provide("dijit._editor.plugins.Print"); dojo.require("dijit._editor._Plugin"); dojo.require("dijit.form.Button"); dojo.require("dojo.i18n"); -dojo.requireLocalization("dijit._editor","commands",null,"ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,ko,nb,nl,pl,pt,pt-pt,ro,ru,sk,sl,sv,th,tr,zh,zh-tw"); -dojo.declare("dijit._editor.plugins.Print",dijit._editor._Plugin,{_initButton:function(){ -var _1=dojo.i18n.getLocalization("dijit._editor","commands"),_2=this.editor; -this.button=new dijit.form.Button({label:_1["print"],dir:_2.dir,lang:_2.lang,showLabel:false,iconClass:this.iconClassPrefix+" "+this.iconClassPrefix+"Print",tabIndex:"-1",onClick:dojo.hitch(this,"_print")}); -},setEditor:function(_3){ -this.editor=_3; -this._initButton(); -this.editor.onLoadDeferred.addCallback(dojo.hitch(this,function(){ -if(!this.editor.iframe.contentWindow["print"]){ -this.button.set("disabled",true); -} -})); -},_print:function(){ -var _4=this.editor.iframe; -if(_4.contentWindow["print"]){ -if(!dojo.isOpera&&!dojo.isChrome){ -dijit.focus(_4); -_4.contentWindow.print(); -}else{ -var _5=this.editor.document; -var _6=this.editor.get("value"); -_6="<html><head><meta http-equiv='Content-Type' "+"content='text/html; charset='UTF-8'></head><body>"+_6+"</body></html>"; -var _7=window.open("javascript: ''","","status=0,menubar=0,location=0,toolbar=0,"+"width=1,height=1,resizable=0,scrollbars=0"); -_7.document.open(); -_7.document.write(_6); -_7.document.close(); -var _8=[]; -var _9=_5.getElementsByTagName("style"); -if(_9){ -var i; -for(i=0;i<_9.length;i++){ -var _a=_9[i].innerHTML; -var _b=_7.document.createElement("style"); -_b.appendChild(_7.document.createTextNode(_a)); -_7.document.getElementsByTagName("head")[0].appendChild(_b); -} -} -_7.print(); -_7.close(); -} -} -}}); -dojo.subscribe(dijit._scopeName+".Editor.getPlugin",null,function(o){ -if(o.plugin){ -return; -} -var _c=o.args.name.toLowerCase(); -if(_c==="print"){ -o.plugin=new dijit._editor.plugins.Print({command:"print"}); -} +dojo.requireLocalization("dijit._editor", "commands", null, "ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,kk,ko,nb,nl,pl,pt,pt-pt,ro,ru,sk,sl,sv,th,tr,zh,zh-tw"); + + +dojo.declare("dijit._editor.plugins.Print",dijit._editor._Plugin,{ + // summary: + // This plugin provides Print cabability to the editor. When + // clicked, the document in the editor frame will be printed. + + _initButton: function(){ + // summary: + // Over-ride for creation of the Print button. + var strings = dojo.i18n.getLocalization("dijit._editor", "commands"), + editor = this.editor; + this.button = new dijit.form.Button({ + label: strings["print"], + dir: editor.dir, + lang: editor.lang, + showLabel: false, + iconClass: this.iconClassPrefix + " " + this.iconClassPrefix + "Print", + tabIndex: "-1", + onClick: dojo.hitch(this, "_print") + }); + }, + + setEditor: function(/*dijit.Editor*/ editor){ + // summary: + // Tell the plugin which Editor it is associated with. + // editor: Object + // The editor object to attach the print capability to. + this.editor = editor; + this._initButton(); + + // Set up a check that we have a print function + // and disable button if we do not. + this.editor.onLoadDeferred.addCallback( + dojo.hitch(this, function(){ + if(!this.editor.iframe.contentWindow["print"]){ + this.button.set("disabled", true); + } + }) + ); + }, + + updateState: function(){ + // summary: + // Over-ride for button state control for disabled to work. + var disabled = this.get("disabled"); + if(!this.editor.iframe.contentWindow["print"]){ + disabled = true; + } + this.button.set("disabled", disabled); + }, + + _print: function(){ + // summary: + // Function to trigger printing of the editor document + // tags: + // private + var edFrame = this.editor.iframe; + if(edFrame.contentWindow["print"]){ + // IE requires the frame to be focused for + // print to work, but since this is okay for all + // no special casing. + if(!dojo.isOpera && !dojo.isChrome){ + dijit.focus(edFrame); + edFrame.contentWindow.print(); + }else{ + // Neither Opera nor Chrome 3 et you print single frames. + // So, open a new 'window', print it, and close it. + // Also, can't use size 0x0, have to use 1x1 + var edDoc = this.editor.document; + var content = this.editor.get("value"); + content = "<html><head><meta http-equiv='Content-Type' " + + "content='text/html; charset='UTF-8'></head><body>" + + content + "</body></html>"; + var win = window.open("javascript: ''", + "", + "status=0,menubar=0,location=0,toolbar=0," + + "width=1,height=1,resizable=0,scrollbars=0"); + win.document.open(); + win.document.write(content); + win.document.close(); + var styles = []; + var styleNodes = edDoc.getElementsByTagName("style"); + if(styleNodes){ + // Clone over any editor view styles, since we can't print the iframe + // directly. + var i; + for(i = 0; i < styleNodes.length; i++){ + var style = styleNodes[i].innerHTML; + var sNode = win.document.createElement("style"); + sNode.appendChild(win.document.createTextNode(style)); + win.document.getElementsByTagName("head")[0].appendChild(sNode); + } + } + win.print(); + win.close(); + } + } + } +}); + +// Register this plugin. +dojo.subscribe(dijit._scopeName + ".Editor.getPlugin",null,function(o){ + if(o.plugin){ return; } + var name = o.args.name.toLowerCase(); + if(name === "print"){ + o.plugin = new dijit._editor.plugins.Print({command: "print"}); + } }); + } diff --git a/lib/dijit/_editor/plugins/TabIndent.js b/lib/dijit/_editor/plugins/TabIndent.js index 74cda400f..eb27f69dd 100644 --- a/lib/dijit/_editor/plugins/TabIndent.js +++ b/lib/dijit/_editor/plugins/TabIndent.js @@ -1,33 +1,69 @@ /* - Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved. + Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved. Available via Academic Free License >= 2.1 OR the modified BSD license. see: http://dojotoolkit.org/license for details */ -if(!dojo._hasResource["dijit._editor.plugins.TabIndent"]){ -dojo._hasResource["dijit._editor.plugins.TabIndent"]=true; +if(!dojo._hasResource["dijit._editor.plugins.TabIndent"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dijit._editor.plugins.TabIndent"] = true; dojo.provide("dijit._editor.plugins.TabIndent"); -dojo.experimental("dijit._editor.plugins.TabIndent"); dojo.require("dijit._editor._Plugin"); dojo.require("dijit.form.ToggleButton"); -dojo.declare("dijit._editor.plugins.TabIndent",dijit._editor._Plugin,{useDefaultCommand:false,buttonClass:dijit.form.ToggleButton,command:"tabIndent",_initButton:function(){ -this.inherited(arguments); -var e=this.editor; -this.connect(this.button,"onChange",function(_1){ -e.set("isTabIndent",_1); -}); -this.updateState(); -},updateState:function(){ -this.button.set("checked",this.editor.isTabIndent,false); -}}); -dojo.subscribe(dijit._scopeName+".Editor.getPlugin",null,function(o){ -if(o.plugin){ -return; -} -switch(o.args.name){ -case "tabIndent": -o.plugin=new dijit._editor.plugins.TabIndent({command:o.args.name}); -} + + +dojo.experimental("dijit._editor.plugins.TabIndent"); + + +dojo.declare("dijit._editor.plugins.TabIndent", + dijit._editor._Plugin, + { + // summary: + // This plugin is used to allow the use of the tab and shift-tab keys + // to indent/outdent list items. This overrides the default behavior + // of moving focus from/to the toolbar + + // Override _Plugin.useDefaultCommand... processing is handled by this plugin, not by dijit.Editor. + useDefaultCommand: false, + + // Override _Plugin.buttonClass to use a ToggleButton for this plugin rather than a vanilla Button + buttonClass: dijit.form.ToggleButton, + + command: "tabIndent", + + _initButton: function(){ + // Override _Plugin._initButton() to setup listener on button click + this.inherited(arguments); + + var e = this.editor; + this.connect(this.button, "onChange", function(val){ + e.set("isTabIndent", val); + }); + + // Set initial checked state of button based on Editor.isTabIndent + this.updateState(); + }, + + updateState: function(){ + // Overrides _Plugin.updateState(). + // Ctrl-m in the editor will switch tabIndent mode on/off, so we need to react to that. + var disabled = this.get("disabled"); + this.button.set("disabled", disabled); + if(disabled){ + return; + } + this.button.set('checked', this.editor.isTabIndent, false); + } + } +); + +// Register this plugin. +dojo.subscribe(dijit._scopeName + ".Editor.getPlugin",null,function(o){ + if(o.plugin){ return; } + switch(o.args.name){ + case "tabIndent": + o.plugin = new dijit._editor.plugins.TabIndent({command: o.args.name}); + } }); + } diff --git a/lib/dijit/_editor/plugins/TextColor.js b/lib/dijit/_editor/plugins/TextColor.js index da7bbc9a6..2f24d0424 100644 --- a/lib/dijit/_editor/plugins/TextColor.js +++ b/lib/dijit/_editor/plugins/TextColor.js @@ -1,62 +1,105 @@ /* - Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved. + Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved. Available via Academic Free License >= 2.1 OR the modified BSD license. see: http://dojotoolkit.org/license for details */ -if(!dojo._hasResource["dijit._editor.plugins.TextColor"]){ -dojo._hasResource["dijit._editor.plugins.TextColor"]=true; +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,{buttonClass:dijit.form.DropDownButton,useDefaultCommand:false,constructor:function(){ -this.dropDown=new dijit.ColorPalette(); -this.connect(this.dropDown,"onChange",function(_1){ -this.editor.execCommand(this.command,_1); + + +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 + + // Override _Plugin.buttonClass to use DropDownButton (with ColorPalette) to control this plugin + buttonClass: dijit.form.DropDownButton, + + // useDefaultCommand: Boolean + // False as we do not use the default editor command/click behavior. + useDefaultCommand: false, + + constructor: function(){ + this.dropDown = new dijit.ColorPalette(); + this.connect(this.dropDown, "onChange", function(color){ + this.editor.execCommand(this.command, color); + + }); + }, + + updateState: function(){ + // summary: + // Overrides _Plugin.updateState(). This updates the ColorPalette + // to show the color of the currently selected text. + // tags: + // protected + + var _e = this.editor; + var _c = this.command; + if(!_e || !_e.isLoaded || !_c.length){ + return; + } + + if(this.button){ + var disabled = this.get("disabled"); + this.button.set("disabled", disabled); + if(disabled){ return; } + + var value; + try{ + value = _e.queryCommandValue(_c)|| ""; + }catch(e){ + //Firefox may throw error above if the editor is just loaded, ignore it + value = ""; + } + } + + if(value == ""){ + value = "#000000"; + } + if(value == "transparent"){ + value = "#ffffff"; + } + + if(typeof value == "string"){ + //if RGB value, convert to hex value + if(value.indexOf("rgb")> -1){ + value = dojo.colorFromRgb(value).toHex(); + } + }else{ //it's an integer(IE returns an MS access #) + value =((value & 0x0000ff)<< 16)|(value & 0x00ff00)|((value & 0xff0000)>>> 16); + value = value.toString(16); + value = "#000000".slice(0, 7 - value.length)+ value; + + } + + if(value !== this.dropDown.get('value')){ + this.dropDown.set('value', value, false); + } + } }); -},updateState:function(){ -var _2=this.editor; -var _3=this.command; -if(!_2||!_2.isLoaded||!_3.length){ -return; -} -if(this.button){ -var _4; -try{ -_4=_2.queryCommandValue(_3)||""; -} -catch(e){ -_4=""; -} -} -if(_4==""){ -_4="#000000"; -} -if(_4=="transparent"){ -_4="#ffffff"; -} -if(typeof _4=="string"){ -if(_4.indexOf("rgb")>-1){ -_4=dojo.colorFromRgb(_4).toHex(); -} -}else{ -_4=((_4&255)<<16)|(_4&65280)|((_4&16711680)>>>16); -_4=_4.toString(16); -_4="#000000".slice(0,7-_4.length)+_4; -} -if(_4!==this.dropDown.get("value")){ -this.dropDown.set("value",_4,false); -} -}}); -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}); -} + +// Register this plugin. +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/lib/dijit/_editor/plugins/ToggleDir.js b/lib/dijit/_editor/plugins/ToggleDir.js index f5ecb7909..92e3d91c8 100644 --- a/lib/dijit/_editor/plugins/ToggleDir.js +++ b/lib/dijit/_editor/plugins/ToggleDir.js @@ -1,42 +1,80 @@ /* - Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved. + Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved. Available via Academic Free License >= 2.1 OR the modified BSD license. see: http://dojotoolkit.org/license for details */ -if(!dojo._hasResource["dijit._editor.plugins.ToggleDir"]){ -dojo._hasResource["dijit._editor.plugins.ToggleDir"]=true; +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.require("dijit._editor._Plugin"); +dojo.require("dijit.form.ToggleButton"); + + dojo.experimental("dijit._editor.plugins.ToggleDir"); + dojo.require("dijit._editor._Plugin"); dojo.require("dijit.form.ToggleButton"); -dojo.declare("dijit._editor.plugins.ToggleDir",dijit._editor._Plugin,{useDefaultCommand:false,command:"toggleDir",buttonClass:dijit.form.ToggleButton,_initButton:function(){ -this.inherited(arguments); -this.editor.onLoadDeferred.addCallback(dojo.hitch(this,function(){ -var _1=this.editor.editorObject.contentWindow.document.documentElement; -_1=_1.getElementsByTagName("body")[0]; -var _2=dojo.getComputedStyle(_1).direction=="ltr"; -this.button.set("checked",!_2); -this.connect(this.button,"onChange","_setRtl"); -})); -},updateState:function(){ -},_setRtl:function(_3){ -var _4="ltr"; -if(_3){ -_4="rtl"; -} -var _5=this.editor.editorObject.contentWindow.document.documentElement; -_5=_5.getElementsByTagName("body")[0]; -_5.dir=_4; -}}); -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}); -} + +dojo.declare("dijit._editor.plugins.ToggleDir", + dijit._editor._Plugin, + { + // summary: + // This plugin is used to toggle direction of the edited document, + // independent of what direction the whole page is. + + // Override _Plugin.useDefaultCommand: processing is done in this plugin + // rather than by sending commands to the Editor + useDefaultCommand: false, + + command: "toggleDir", + + // Override _Plugin.buttonClass to use a ToggleButton for this plugin rather than a vanilla Button + buttonClass: dijit.form.ToggleButton, + + _initButton: function(){ + // Override _Plugin._initButton() to setup handler for button click events. + this.inherited(arguments); + this.editor.onLoadDeferred.addCallback(dojo.hitch(this, function(){ + var editDoc = this.editor.editorObject.contentWindow.document.documentElement; + //IE direction has to toggle on the body, not document itself. + //If you toggle just the document, things get very strange in the + //view. But, the nice thing is this works for all supported browsers. + editDoc = editDoc.getElementsByTagName("body")[0]; + var isLtr = dojo.getComputedStyle(editDoc).direction == "ltr"; + this.button.set("checked", !isLtr); + this.connect(this.button, "onChange", "_setRtl"); + })); + }, + + updateState: function(){ + // summary: + // Over-ride for button state control for disabled to work. + this.button.set("disabled", this.get("disabled")); + }, + + _setRtl: function(rtl){ + // summary: + // Handler for button click events, to switch the text direction of the editor + var dir = "ltr"; + if(rtl){ + dir = "rtl"; + } + var editDoc = this.editor.editorObject.contentWindow.document.documentElement; + editDoc = editDoc.getElementsByTagName("body")[0]; + editDoc.dir/*html node*/ = dir; + } + } +); + +// Register this plugin. +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/lib/dijit/_editor/plugins/ViewSource.js b/lib/dijit/_editor/plugins/ViewSource.js index 41ea2970f..e655ad21d 100644 --- a/lib/dijit/_editor/plugins/ViewSource.js +++ b/lib/dijit/_editor/plugins/ViewSource.js @@ -1,317 +1,555 @@ /* - Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved. + Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved. Available via Academic Free License >= 2.1 OR the modified BSD license. see: http://dojotoolkit.org/license for details */ -if(!dojo._hasResource["dijit._editor.plugins.ViewSource"]){ -dojo._hasResource["dijit._editor.plugins.ViewSource"]=true; +if(!dojo._hasResource["dijit._editor.plugins.ViewSource"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dijit._editor.plugins.ViewSource"] = true; dojo.provide("dijit._editor.plugins.ViewSource"); dojo.require("dojo.window"); dojo.require("dojo.i18n"); dojo.require("dijit._editor._Plugin"); dojo.require("dijit.form.Button"); -dojo.requireLocalization("dijit._editor","commands",null,"ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,ko,nb,nl,pl,pt,pt-pt,ro,ru,sk,sl,sv,th,tr,zh,zh-tw"); -dojo.declare("dijit._editor.plugins.ViewSource",dijit._editor._Plugin,{stripScripts:true,stripComments:true,stripIFrames:true,readOnly:false,_fsPlugin:null,toggle:function(){ -if(dojo.isWebKit){ -this._vsFocused=true; -} -this.button.set("checked",!this.button.get("checked")); -},_initButton:function(){ -var _1=dojo.i18n.getLocalization("dijit._editor","commands"),_2=this.editor; -this.button=new dijit.form.ToggleButton({label:_1["viewSource"],dir:_2.dir,lang:_2.lang,showLabel:false,iconClass:this.iconClassPrefix+" "+this.iconClassPrefix+"ViewSource",tabIndex:"-1",onChange:dojo.hitch(this,"_showSource")}); -if(dojo.isIE==7){ -this._ieFixNode=dojo.create("div",{style:{opacity:"0",zIndex:"-1000",position:"absolute",top:"-1000px"}},dojo.body()); -} -this.button.set("readOnly",false); -},setEditor:function(_3){ -this.editor=_3; -this._initButton(); -this.editor.addKeyHandler(dojo.keys.F12,true,true,dojo.hitch(this,function(e){ -this.button.focus(); -this.toggle(); -dojo.stopEvent(e); -setTimeout(dojo.hitch(this,function(){ -this.editor.focus(); -}),100); -})); -},_showSource:function(_4){ -var ed=this.editor; -var _5=ed._plugins; -var _6; -this._sourceShown=_4; -var _7=this; -try{ -if(!this.sourceArea){ -this._createSourceView(); -} -if(_4){ -ed._sourceQueryCommandEnabled=ed.queryCommandEnabled; -ed.queryCommandEnabled=function(_8){ -var _9=_8.toLowerCase(); -if(_9==="viewsource"){ -return true; -}else{ -return false; -} -}; -this.editor.onDisplayChanged(); -_6=ed.get("value"); -_6=this._filter(_6); -ed.set("value",_6); -this._pluginList=[]; -this._disabledPlugins=dojo.filter(_5,function(p){ -if(p&&p.button&&!p.button.get("disabled")&&!(p instanceof dijit._editor.plugins.ViewSource)){ -p._vs_updateState=p.updateState; -p.updateState=function(){ -return false; -}; -p.button.set("disabled",true); -if(p.command){ -switch(p.command){ -case "bold": -case "italic": -case "underline": -case "strikethrough": -case "superscript": -case "subscript": -p.button.set("checked",false); -break; -default: -break; -} -} -return true; -} -}); -if(this._fsPlugin){ -this._fsPlugin._getAltViewNode=function(){ -return _7.sourceArea; -}; -} -this.sourceArea.value=_6; -var is=dojo.marginBox(ed.iframe.parentNode); -dojo.marginBox(this.sourceArea,{w:is.w,h:is.h}); -dojo.style(ed.iframe,"display","none"); -dojo.style(this.sourceArea,{display:"block"}); -var _a=function(){ -var vp=dojo.window.getBox(); -if("_prevW" in this&&"_prevH" in this){ -if(vp.w===this._prevW&&vp.h===this._prevH){ -return; -}else{ -this._prevW=vp.w; -this._prevH=vp.h; -} -}else{ -this._prevW=vp.w; -this._prevH=vp.h; -} -if(this._resizer){ -clearTimeout(this._resizer); -delete this._resizer; -} -this._resizer=setTimeout(dojo.hitch(this,function(){ -delete this._resizer; -this._resize(); -}),10); -}; -this._resizeHandle=dojo.connect(window,"onresize",this,_a); -setTimeout(dojo.hitch(this,this._resize),100); -this.editor.onNormalizedDisplayChanged(); -}else{ -if(!ed._sourceQueryCommandEnabled){ -return; -} -dojo.disconnect(this._resizeHandle); -delete this._resizeHandle; -ed.queryCommandEnabled=ed._sourceQueryCommandEnabled; -if(!this._readOnly){ -_6=this.sourceArea.value; -_6=this._filter(_6); -ed.beginEditing(); -ed.set("value",_6); -ed.endEditing(); -} -dojo.forEach(this._disabledPlugins,function(p){ -p.button.set("disabled",false); -if(p._vs_updateState){ -p.updateState=p._vs_updateState; -} +dojo.requireLocalization("dijit._editor", "commands", null, "ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,kk,ko,nb,nl,pl,pt,pt-pt,ro,ru,sk,sl,sv,th,tr,zh,zh-tw"); + + +dojo.declare("dijit._editor.plugins.ViewSource",dijit._editor._Plugin,{ + // summary: + // This plugin provides a simple view source capability. When view + // source mode is enabled, it disables all other buttons/plugins on the RTE. + // It also binds to the hotkey: CTRL-SHIFT-F11 for toggling ViewSource mode. + + // stripScripts: [public] Boolean + // Boolean flag used to indicate if script tags should be stripped from the document. + // Defaults to true. + stripScripts: true, + + // stripComments: [public] Boolean + // Boolean flag used to indicate if comment tags should be stripped from the document. + // Defaults to true. + stripComments: true, + + // stripComments: [public] Boolean + // Boolean flag used to indicate if iframe tags should be stripped from the document. + // Defaults to true. + stripIFrames: true, + + // readOnly: [const] Boolean + // Boolean flag used to indicate if the source view should be readonly or not. + // Cannot be changed after initialization of the plugin. + // Defaults to false. + readOnly: false, + + // _fsPlugin: [private] Object + // Reference to a registered fullscreen plugin so that viewSource knows + // how to scale. + _fsPlugin: null, + + toggle: function(){ + // summary: + // Function to allow programmatic toggling of the view. + + // For Webkit, we have to focus a very particular way. + // when swapping views, otherwise focus doesn't shift right + // but can't focus this way all the time, only for VS changes. + // If we did it all the time, buttons like bold, italic, etc + // break. + if(dojo.isWebKit){this._vsFocused = true;} + this.button.set("checked", !this.button.get("checked")); + + }, + + _initButton: function(){ + // summary: + // Over-ride for creation of the resize button. + var strings = dojo.i18n.getLocalization("dijit._editor", "commands"), + editor = this.editor; + this.button = new dijit.form.ToggleButton({ + label: strings["viewSource"], + dir: editor.dir, + lang: editor.lang, + showLabel: false, + iconClass: this.iconClassPrefix + " " + this.iconClassPrefix + "ViewSource", + tabIndex: "-1", + onChange: dojo.hitch(this, "_showSource") + }); + + // IE 7 has a horrible bug with zoom, so we have to create this node + // to cross-check later. Sigh. + if(dojo.isIE == 7){ + this._ieFixNode = dojo.create("div", { + style: { + opacity: "0", + zIndex: "-1000", + position: "absolute", + top: "-1000px" + } + }, dojo.body()); + } + // Make sure readonly mode doesn't make the wrong cursor appear over the button. + this.button.set("readOnly", false); + }, + + + setEditor: function(/*dijit.Editor*/ editor){ + // summary: + // Tell the plugin which Editor it is associated with. + // editor: Object + // The editor object to attach the print capability to. + this.editor = editor; + this._initButton(); + + this.editor.addKeyHandler(dojo.keys.F12, true, true, dojo.hitch(this, function(e){ + // Move the focus before switching + // It'll focus back. Hiding a focused + // node causes issues. + this.button.focus(); + this.toggle(); + dojo.stopEvent(e); + + // Call the focus shift outside of the handler. + setTimeout(dojo.hitch(this, function(){ + // We over-ride focus, so we just need to call. + this.editor.focus(); + }), 100); + })); + }, + + _showSource: function(source){ + // summary: + // Function to toggle between the source and RTE views. + // source: boolean + // Boolean value indicating if it should be in source mode or not. + // tags: + // private + var ed = this.editor; + var edPlugins = ed._plugins; + var html; + this._sourceShown = source; + var self = this; + try{ + if(!this.sourceArea){ + this._createSourceView(); + } + if(source){ + // Update the QueryCommandEnabled function to disable everything but + // the source view mode. Have to over-ride a function, then kick all + // plugins to check their state. + ed._sourceQueryCommandEnabled = ed.queryCommandEnabled; + ed.queryCommandEnabled = function(cmd){ + var lcmd = cmd.toLowerCase(); + if(lcmd === "viewsource"){ + return true; + }else{ + return false; + } + }; + this.editor.onDisplayChanged(); + html = ed.get("value"); + html = this._filter(html); + ed.set("value", html); + this._pluginList = []; + dojo.forEach(edPlugins, function(p){ + // Turn off any plugins not controlled by queryCommandenabled. + if(!(p instanceof dijit._editor.plugins.ViewSource)){ + p.set("disabled", true) + } + }); + + // We actually do need to trap this plugin and adjust how we + // display the textarea. + if(this._fsPlugin){ + this._fsPlugin._getAltViewNode = function(){ + return self.sourceArea; + }; + } + + this.sourceArea.value = html; + var is = dojo._getMarginSize(ed.iframe.parentNode); + + dojo.marginBox(this.sourceArea, { + w: is.w, + h: is.h + }); + + dojo.style(ed.iframe, "display", "none"); + dojo.style(this.sourceArea, { + display: "block" + }); + + var resizer = function(){ + // function to handle resize events. + // Will check current VP and only resize if + // different. + var vp = dojo.window.getBox(); + + if("_prevW" in this && "_prevH" in this){ + // No actual size change, ignore. + if(vp.w === this._prevW && vp.h === this._prevH){ + return; + }else{ + this._prevW = vp.w; + this._prevH = vp.h; + } + }else{ + this._prevW = vp.w; + this._prevH = vp.h; + } + if(this._resizer){ + clearTimeout(this._resizer); + delete this._resizer; + } + // Timeout it to help avoid spamming resize on IE. + // Works for all browsers. + this._resizer = setTimeout(dojo.hitch(this, function(){ + delete this._resizer; + this._resize(); + }), 10); + }; + this._resizeHandle = dojo.connect(window, "onresize", this, resizer); + + //Call this on a delay once to deal with IE glitchiness on initial size. + setTimeout(dojo.hitch(this, this._resize), 100); + + //Trigger a check for command enablement/disablement. + this.editor.onNormalizedDisplayChanged(); + + this.editor.__oldGetValue = this.editor.getValue; + this.editor.getValue = dojo.hitch(this, function() { + var txt = this.sourceArea.value; + txt = this._filter(txt); + return txt; + }); + }else{ + // First check that we were in source view before doing anything. + // corner case for being called with a value of false and we hadn't + // actually been in source display mode. + if(!ed._sourceQueryCommandEnabled){ + return; + } + dojo.disconnect(this._resizeHandle); + delete this._resizeHandle; + + if(this.editor.__oldGetValue){ + this.editor.getValue = this.editor.__oldGetValue; + delete this.editor.__oldGetValue; + } + + // Restore all the plugin buttons state. + ed.queryCommandEnabled = ed._sourceQueryCommandEnabled; + if(!this._readOnly){ + html = this.sourceArea.value; + html = this._filter(html); + ed.beginEditing(); + ed.set("value", html); + ed.endEditing(); + } + + dojo.forEach(edPlugins, function(p){ + // Turn back on any plugins we turned off. + p.set("disabled", false); + }); + + dojo.style(this.sourceArea, "display", "none"); + dojo.style(ed.iframe, "display", "block"); + delete ed._sourceQueryCommandEnabled; + + //Trigger a check for command enablement/disablement. + this.editor.onDisplayChanged(); + } + // Call a delayed resize to wait for some things to display in header/footer. + setTimeout(dojo.hitch(this, function(){ + // Make resize calls. + var parent = ed.domNode.parentNode; + if(parent){ + var container = dijit.getEnclosingWidget(parent); + if(container && container.resize){ + container.resize(); + } + } + ed.resize(); + }), 300); + }catch(e){ + console.log(e); + } + }, + + updateState: function(){ + // summary: + // Over-ride for button state control for disabled to work. + this.button.set("disabled", this.get("disabled")); + }, + + _resize: function(){ + // summary: + // Internal function to resize the source view + // tags: + // private + var ed = this.editor; + var tbH = ed.getHeaderHeight(); + var fH = ed.getFooterHeight(); + var eb = dojo.position(ed.domNode); + + // Styles are now applied to the internal source container, so we have + // to subtract them off. + var containerPadding = dojo._getPadBorderExtents(ed.iframe.parentNode); + var containerMargin = dojo._getMarginExtents(ed.iframe.parentNode); + + var extents = dojo._getPadBorderExtents(ed.domNode); + var mExtents = dojo._getMarginExtents(ed.domNode); + var edb = { + w: eb.w - (extents.w + mExtents.w), + h: eb.h - (tbH + extents.h + mExtents.h + fH) + }; + + // Fullscreen gets odd, so we need to check for the FS plugin and + // adapt. + if(this._fsPlugin && this._fsPlugin.isFullscreen){ + //Okay, probably in FS, adjust. + var vp = dojo.window.getBox(); + edb.w = (vp.w - extents.w); + edb.h = (vp.h - (tbH + extents.h + fH)); + } + + if(dojo.isIE){ + // IE is always off by 2px, so we have to adjust here + // Note that IE ZOOM is broken here. I can't get + //it to scale right. + edb.h -= 2; + } + + // IE has a horrible zoom bug. So, we have to try and account for + // it and fix up the scaling. + if(this._ieFixNode){ + var _ie7zoom = -this._ieFixNode.offsetTop / 1000; + edb.w = Math.floor((edb.w + 0.9) / _ie7zoom); + edb.h = Math.floor((edb.h + 0.9) / _ie7zoom); + } + + dojo.marginBox(this.sourceArea, { + w: edb.w - (containerPadding.w + containerMargin.w), + h: edb.h - (containerPadding.h + containerMargin.h) + }); + + // Scale the parent container too in this case. + dojo.marginBox(ed.iframe.parentNode, { + h: edb.h + }); + }, + + _createSourceView: function(){ + // summary: + // Internal function for creating the source view area. + // tags: + // private + var ed = this.editor; + var edPlugins = ed._plugins; + this.sourceArea = dojo.create("textarea"); + if(this.readOnly){ + dojo.attr(this.sourceArea, "readOnly", true); + this._readOnly = true; + } + dojo.style(this.sourceArea, { + padding: "0px", + margin: "0px", + borderWidth: "0px", + borderStyle: "none" + }); + dojo.place(this.sourceArea, ed.iframe, "before"); + + if(dojo.isIE && ed.iframe.parentNode.lastChild !== ed.iframe){ + // There's some weirdo div in IE used for focus control + // But is messed up scaling the textarea if we don't config + // it some so it doesn't have a varying height. + dojo.style(ed.iframe.parentNode.lastChild,{ + width: "0px", + height: "0px", + padding: "0px", + margin: "0px", + borderWidth: "0px", + borderStyle: "none" + }); + } + + // We also need to take over editor focus a bit here, so that focus calls to + // focus the editor will focus to the right node when VS is active. + ed._viewsource_oldFocus = ed.focus; + var self = this; + ed.focus = function(){ + if(self._sourceShown){ + self.setSourceAreaCaret(); + }else{ + try{ + if(this._vsFocused){ + delete this._vsFocused; + // Must focus edit node in this case (webkit only) or + // focus doesn't shift right, but in normal + // cases we focus with the regular function. + dijit.focus(ed.editNode); + }else{ + ed._viewsource_oldFocus(); + } + }catch(e){ + console.log(e); + } + } + }; + + var i, p; + for(i = 0; i < edPlugins.length; i++){ + // We actually do need to trap this plugin and adjust how we + // display the textarea. + p = edPlugins[i]; + if(p && (p.declaredClass === "dijit._editor.plugins.FullScreen" || + p.declaredClass === (dijit._scopeName + + "._editor.plugins.FullScreen"))){ + this._fsPlugin = p; + break; + } + } + if(this._fsPlugin){ + // Found, we need to over-ride the alt-view node function + // on FullScreen with our own, chain up to parent call when appropriate. + this._fsPlugin._viewsource_getAltViewNode = this._fsPlugin._getAltViewNode; + this._fsPlugin._getAltViewNode = function(){ + return self._sourceShown?self.sourceArea:this._viewsource_getAltViewNode(); + }; + } + + // Listen to the source area for key events as well, as we need to be able to hotkey toggle + // it from there too. + this.connect(this.sourceArea, "onkeydown", dojo.hitch(this, function(e){ + if(this._sourceShown && e.keyCode == dojo.keys.F12 && e.ctrlKey && e.shiftKey){ + this.button.focus(); + this.button.set("checked", false); + setTimeout(dojo.hitch(this, function(){ed.focus();}), 100); + dojo.stopEvent(e); + } + })); + }, + + _stripScripts: function(html){ + // summary: + // Strips out script tags from the HTML used in editor. + // html: String + // The HTML to filter + // tags: + // private + if(html){ + // Look for closed and unclosed (malformed) script attacks. + html = html.replace(/<\s*script[^>]*>((.|\s)*?)<\\?\/\s*script\s*>/ig, ""); + html = html.replace(/<\s*script\b([^<>]|\s)*>?/ig, ""); + html = html.replace(/<[^>]*=(\s|)*[("|')]javascript:[^$1][(\s|.)]*[$1][^>]*>/ig, ""); + } + return html; + }, + + _stripComments: function(html){ + // summary: + // Strips out comments from the HTML used in editor. + // html: String + // The HTML to filter + // tags: + // private + if(html){ + html = html.replace(/<!--(.|\s){1,}?-->/g, ""); + } + return html; + }, + + _stripIFrames: function(html){ + // summary: + // Strips out iframe tags from the content, to avoid iframe script + // style injection attacks. + // html: String + // The HTML to filter + // tags: + // private + if(html){ + html = html.replace(/<\s*iframe[^>]*>((.|\s)*?)<\\?\/\s*iframe\s*>/ig, ""); + } + return html; + }, + + _filter: function(html){ + // summary: + // Internal function to perform some filtering on the HTML. + // html: String + // The HTML to filter + // tags: + // private + if(html){ + if(this.stripScripts){ + html = this._stripScripts(html); + } + if(this.stripComments){ + html = this._stripComments(html); + } + if(this.stripIFrames){ + html = this._stripIFrames(html); + } + } + return html; + }, + + setSourceAreaCaret: function(){ + // summary: + // Internal function to set the caret in the sourceArea + // to 0x0 + var win = dojo.global; + var elem = this.sourceArea; + dijit.focus(elem); + if(this._sourceShown && !this.readOnly){ + if(dojo.isIE){ + if(this.sourceArea.createTextRange){ + var range = elem.createTextRange(); + range.collapse(true); + range.moveStart("character", -99999); // move to 0 + range.moveStart("character", 0); // delta from 0 is the correct position + range.moveEnd("character", 0); + range.select(); + } + }else if(win.getSelection){ + if(elem.setSelectionRange){ + elem.setSelectionRange(0,0); + } + } + } + }, + + destroy: function(){ + // summary: + // Over-ride to remove the node used to correct for IE's + // zoom bug. + if(this._ieFixNode){ + dojo.body().removeChild(this._ieFixNode); + } + if(this._resizer){ + clearTimeout(this._resizer); + delete this._resizer; + } + if(this._resizeHandle){ + dojo.disconnect(this._resizeHandle); + delete this._resizeHandle; + } + this.inherited(arguments); + } }); -this._disabledPlugins=null; -dojo.style(this.sourceArea,"display","none"); -dojo.style(ed.iframe,"display","block"); -delete ed._sourceQueryCommandEnabled; -this.editor.onDisplayChanged(); -} -setTimeout(dojo.hitch(this,function(){ -var _b=ed.domNode.parentNode; -if(_b){ -var _c=dijit.getEnclosingWidget(_b); -if(_c&&_c.resize){ -_c.resize(); -} -} -ed.resize(); -}),300); -} -catch(e){ -} -},_resize:function(){ -var ed=this.editor; -var _d=ed.getHeaderHeight(); -var fH=ed.getFooterHeight(); -var eb=dojo.position(ed.domNode); -var _e=dojo._getPadBorderExtents(ed.iframe.parentNode); -var _f=dojo._getMarginExtents(ed.iframe.parentNode); -var _10=dojo._getPadBorderExtents(ed.domNode); -var _11=dojo._getMarginExtents(ed.domNode); -var edb={w:eb.w-(_10.w+_11.w),h:eb.h-(_d+_10.h+_11.h+fH)}; -if(this._fsPlugin&&this._fsPlugin.isFullscreen){ -var vp=dojo.window.getBox(); -edb.w=(vp.w-_10.w); -edb.h=(vp.h-(_d+_10.h+fH)); -} -if(dojo.isIE){ -edb.h-=2; -} -if(this._ieFixNode){ -var _12=-this._ieFixNode.offsetTop/1000; -edb.w=Math.floor((edb.w+0.9)/_12); -edb.h=Math.floor((edb.h+0.9)/_12); -} -dojo.marginBox(this.sourceArea,{w:edb.w-(_e.w+_f.w),h:edb.h-(_e.h+_f.h)}); -dojo.marginBox(ed.iframe.parentNode,{h:edb.h}); -},_createSourceView:function(){ -var ed=this.editor; -var _13=ed._plugins; -this.sourceArea=dojo.create("textarea"); -if(this.readOnly){ -dojo.attr(this.sourceArea,"readOnly",true); -this._readOnly=true; -} -dojo.style(this.sourceArea,{padding:"0px",margin:"0px",borderWidth:"0px",borderStyle:"none"}); -dojo.place(this.sourceArea,ed.iframe,"before"); -if(dojo.isIE&&ed.iframe.parentNode.lastChild!==ed.iframe){ -dojo.style(ed.iframe.parentNode.lastChild,{width:"0px",height:"0px",padding:"0px",margin:"0px",borderWidth:"0px",borderStyle:"none"}); -} -ed._viewsource_oldFocus=ed.focus; -var _14=this; -ed.focus=function(){ -if(_14._sourceShown){ -_14.setSourceAreaCaret(); -}else{ -try{ -if(this._vsFocused){ -delete this._vsFocused; -dijit.focus(ed.editNode); -}else{ -ed._viewsource_oldFocus(); -} -} -catch(e){ -} -} -}; -var i,p; -for(i=0;i<_13.length;i++){ -p=_13[i]; -if(p&&(p.declaredClass==="dijit._editor.plugins.FullScreen"||p.declaredClass===(dijit._scopeName+"._editor.plugins.FullScreen"))){ -this._fsPlugin=p; -break; -} -} -if(this._fsPlugin){ -this._fsPlugin._viewsource_getAltViewNode=this._fsPlugin._getAltViewNode; -this._fsPlugin._getAltViewNode=function(){ -return _14._sourceShown?_14.sourceArea:this._viewsource_getAltViewNode(); -}; -} -this.connect(this.sourceArea,"onkeydown",dojo.hitch(this,function(e){ -if(this._sourceShown&&e.keyCode==dojo.keys.F12&&e.ctrlKey&&e.shiftKey){ -this.button.focus(); -this.button.set("checked",false); -setTimeout(dojo.hitch(this,function(){ -ed.focus(); -}),100); -dojo.stopEvent(e); -} -})); -},_stripScripts:function(_15){ -if(_15){ -_15=_15.replace(/<\s*script[^>]*>((.|\s)*?)<\\?\/\s*script\s*>/ig,""); -_15=_15.replace(/<\s*script\b([^<>]|\s)*>?/ig,""); -_15=_15.replace(/<[^>]*=(\s|)*[("|')]javascript:[^$1][(\s|.)]*[$1][^>]*>/ig,""); -} -return _15; -},_stripComments:function(_16){ -if(_16){ -_16=_16.replace(/<!--(.|\s){1,}?-->/g,""); -} -return _16; -},_stripIFrames:function(_17){ -if(_17){ -_17=_17.replace(/<\s*iframe[^>]*>((.|\s)*?)<\\?\/\s*iframe\s*>/ig,""); -} -return _17; -},_filter:function(_18){ -if(_18){ -if(this.stripScripts){ -_18=this._stripScripts(_18); -} -if(this.stripComments){ -_18=this._stripComments(_18); -} -if(this.stripIFrames){ -_18=this._stripIFrames(_18); -} -} -return _18; -},setSourceAreaCaret:function(){ -var win=dojo.global; -var _19=this.sourceArea; -dijit.focus(_19); -if(this._sourceShown&&!this.readOnly){ -if(dojo.isIE){ -if(this.sourceArea.createTextRange){ -var _1a=_19.createTextRange(); -_1a.collapse(true); -_1a.moveStart("character",-99999); -_1a.moveStart("character",0); -_1a.moveEnd("character",0); -_1a.select(); -} -}else{ -if(win.getSelection){ -if(_19.setSelectionRange){ -_19.setSelectionRange(0,0); -} -} -} -} -},destroy:function(){ -if(this._ieFixNode){ -dojo.body().removeChild(this._ieFixNode); -} -if(this._resizer){ -clearTimeout(this._resizer); -delete this._resizer; -} -if(this._resizeHandle){ -dojo.disconnect(this._resizeHandle); -delete this._resizeHandle; -} -this.inherited(arguments); -}}); -dojo.subscribe(dijit._scopeName+".Editor.getPlugin",null,function(o){ -if(o.plugin){ -return; -} -var _1b=o.args.name.toLowerCase(); -if(_1b==="viewsource"){ -o.plugin=new dijit._editor.plugins.ViewSource({readOnly:("readOnly" in o.args)?o.args.readOnly:false,stripComments:("stripComments" in o.args)?o.args.stripComments:true,stripScripts:("stripScripts" in o.args)?o.args.stripScripts:true,stripIFrames:("stripIFrames" in o.args)?o.args.stripIFrames:true}); -} + +// Register this plugin. +dojo.subscribe(dijit._scopeName + ".Editor.getPlugin",null,function(o){ + if(o.plugin){ return; } + var name = o.args.name.toLowerCase(); + if(name === "viewsource"){ + o.plugin = new dijit._editor.plugins.ViewSource({ + readOnly: ("readOnly" in o.args)?o.args.readOnly:false, + stripComments: ("stripComments" in o.args)?o.args.stripComments:true, + stripScripts: ("stripScripts" in o.args)?o.args.stripScripts:true, + stripIFrames: ("stripIFrames" in o.args)?o.args.stripIFrames:true + }); + } }); + } diff --git a/lib/dijit/_editor/range.js b/lib/dijit/_editor/range.js index 2b1bd81e3..2e5074583 100644 --- a/lib/dijit/_editor/range.js +++ b/lib/dijit/_editor/range.js @@ -1,453 +1,541 @@ /* - Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved. + Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved. Available via Academic Free License >= 2.1 OR the modified BSD license. see: http://dojotoolkit.org/license for details */ -if(!dojo._hasResource["dijit._editor.range"]){ -dojo._hasResource["dijit._editor.range"]=true; +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(_1,_2){ -var _3=[],_4=[]; -var _5=_2; -var _6=_1; -var _7,n; -while(_1!=_5){ -var i=0; -_7=_1.parentNode; -while((n=_7.childNodes[i++])){ -if(n===_1){ ---i; -break; -} -} -_3.unshift(i); -_4.unshift(i-_7.childNodes.length); -_1=_7; -} -if(_3.length>0&&_6.nodeType==3){ -n=_6.previousSibling; -while(n&&n.nodeType==3){ -_3[_3.length-1]--; -n=n.previousSibling; -} -n=_6.nextSibling; -while(n&&n.nodeType==3){ -_4[_4.length-1]++; -n=n.nextSibling; -} -} -return {o:_3,r:_4}; -}; -dijit.range.getNode=function(_8,_9){ -if(!dojo.isArray(_8)||_8.length==0){ -return _9; -} -var _a=_9; -dojo.every(_8,function(i){ -if(i>=0&&i<_a.childNodes.length){ -_a=_a.childNodes[i]; -}else{ -_a=null; -return false; -} -return true; -}); -return _a; -}; -dijit.range.getCommonAncestor=function(n1,n2,_b){ -_b=_b||n1.ownerDocument.body; -var _c=function(n){ -var as=[]; -while(n){ -as.unshift(n); -if(n!==_b){ -n=n.parentNode; -}else{ -break; -} -} -return as; -}; -var _d=_c(n1); -var _e=_c(n2); -var m=Math.min(_d.length,_e.length); -var _f=_d[0]; -for(var i=1;i<m;i++){ -if(_d[i]===_e[i]){ -_f=_d[i]; -}else{ -break; -} -} -return _f; -}; -dijit.range.getAncestor=function(_10,_11,_12){ -_12=_12||_10.ownerDocument.body; -while(_10&&_10!==_12){ -var _13=_10.nodeName.toUpperCase(); -if(_11.test(_13)){ -return _10; -} -_10=_10.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(_14,_15,_16){ -_16=_16||_14.ownerDocument.body; -_15=_15||dijit.range.BlockTagNames; -var _17=null,_18; -while(_14&&_14!==_16){ -var _19=_14.nodeName.toUpperCase(); -if(!_17&&_15.test(_19)){ -_17=_14; -} -if(!_18&&(/^(?:BODY|TD|TH|CAPTION)$/).test(_19)){ -_18=_14; -} -_14=_14.parentNode; -} -return {blockNode:_17,blockContainer:_18||_14.ownerDocument.body}; -}; -dijit.range.atBeginningOfContainer=function(_1a,_1b,_1c){ -var _1d=false; -var _1e=(_1c==0); -if(!_1e&&_1b.nodeType==3){ -if(/^[\s\xA0]+$/.test(_1b.nodeValue.substr(0,_1c))){ -_1e=true; -} -} -if(_1e){ -var _1f=_1b; -_1d=true; -while(_1f&&_1f!==_1a){ -if(_1f.previousSibling){ -_1d=false; -break; -} -_1f=_1f.parentNode; -} -} -return _1d; -}; -dijit.range.atEndOfContainer=function(_20,_21,_22){ -var _23=false; -var _24=(_22==(_21.length||_21.childNodes.length)); -if(!_24&&_21.nodeType==3){ -if(/^[\s\xA0]+$/.test(_21.nodeValue.substr(_22))){ -_24=true; + +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; } -if(_24){ -var _25=_21; -_23=true; -while(_25&&_25!==_20){ -if(_25.nextSibling){ -_23=false; -break; + +dijit.range.getCommonAncestor = function(n1,n2,root){ + root = root||n1.ownerDocument.body; + var getAncestors = function(n){ + var as=[]; + while(n){ + as.unshift(n); + if(n !== root){ + n = n.parentNode; + }else{ + break; + } + } + return as; + }; + var n1as = getAncestors(n1); + var n2as = getAncestors(n2); + + 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; } -_25=_25.parentNode; + +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}; } -return _23; -}; -dijit.range.adjacentNoneTextNode=function(_26,_27){ -var _28=_26; -var len=(0-_26.length)||0; -var _29=_27?"nextSibling":"previousSibling"; -while(_28){ -if(_28.nodeType!=3){ -break; + +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(/^[\s\xA0]+$/.test(node.nodeValue.substr(0,offset))){ + offsetAtBeginning = true; + } + } + if(offsetAtBeginning){ + var cnode = node; + atBeginning = true; + while(cnode && cnode !== container){ + if(cnode.previousSibling){ + atBeginning = false; + break; + } + cnode = cnode.parentNode; + } + } + return atBeginning; } -len+=_28.length; -_28=_28[_29]; + +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(/^[\s\xA0]+$/.test(node.nodeValue.substr(offset))){ + offsetAtEnd = true; + } + } + if(offsetAtEnd){ + var cnode = node; + atEnd = true; + while(cnode && cnode !== container){ + if(cnode.nextSibling){ + atEnd = false; + break; + } + cnode = cnode.parentNode; + } + } + return atEnd; } -return [_28,len]; -}; -dijit.range._w3c=Boolean(window["getSelection"]); -dijit.range.create=function(win){ -if(dijit.range._w3c){ -return (win||dojo.global).document.createRange(); -}else{ -return new dijit.range.W3CRange; + +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.getSelection=function(win,_2a){ -if(dijit.range._w3c){ -return win.getSelection(); -}else{ -var s=new dijit.range.ie.selection(win); -if(!_2a){ -s._getCurrentSelection(); + +dijit.range._w3c = Boolean(window['getSelection']); +dijit.range.create = function(/*Window?*/win){ + if(dijit.range._w3c){ + return (win || dojo.global).document.createRange(); + }else{//IE + return new dijit.range.W3CRange; + } } -return s; + +dijit.range.getSelection = function(/*Window*/win, /*Boolean?*/ignoreUpdate){ + if(dijit.range._w3c){ + return win.getSelection(); + }else{//IE + var s = new dijit.range.ie.selection(win); + if(!ignoreUpdate){ + s._getCurrentSelection(); + } + return s; + } } -}; + if(!dijit.range._w3c){ -dijit.range.ie={cachedSelection:{},selection:function(win){ -this._ranges=[]; -this.addRange=function(r,_2b){ -this._ranges.push(r); -if(!_2b){ -r._select(); -} -this.rangeCount=this._ranges.length; -}; -this.removeAllRanges=function(){ -this._ranges=[]; -this.rangeCount=0; -}; -var _2c=function(){ -var r=win.document.selection.createRange(); -var _2d=win.document.selection.type.toUpperCase(); -if(_2d=="CONTROL"){ -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=_2c(); -if(r){ -this.addRange(r,true); -} -}; -},decomposeControlRange:function(_2e){ -var _2f=_2e.item(0),_30=_2e.item(_2e.length-1); -var _31=_2f.parentNode,_32=_30.parentNode; -var _33=dijit.range.getIndex(_2f,_31).o; -var _34=dijit.range.getIndex(_30,_32).o+1; -return [_31,_33,_32,_34]; -},getEndPoint:function(_35,end){ -var _36=_35.duplicate(); -_36.collapse(!end); -var _37="EndTo"+(end?"End":"Start"); -var _38=_36.parentElement(); -var _39,_3a,_3b; -if(_38.childNodes.length>0){ -dojo.every(_38.childNodes,function(_3c,i){ -var _3d; -if(_3c.nodeType!=3){ -_36.moveToElementText(_3c); -if(_36.compareEndPoints(_37,_35)>0){ -if(_3b&&_3b.nodeType==3){ -_39=_3b; -_3d=true; -}else{ -_39=_38; -_3a=i; -return false; -} -}else{ -if(i==_38.childNodes.length-1){ -_39=_38; -_3a=_38.childNodes.length; -return false; -} -} -}else{ -if(i==_38.childNodes.length-1){ -_39=_3c; -_3d=true; -} -} -if(_3d&&_39){ -var _3e=dijit.range.adjacentNoneTextNode(_39)[0]; -if(_3e){ -_39=_3e.nextSibling; -}else{ -_39=_38.firstChild; -} -var _3f=dijit.range.adjacentNoneTextNode(_39); -_3e=_3f[0]; -var _40=_3f[1]; -if(_3e){ -_36.moveToElementText(_3e); -_36.collapse(false); -}else{ -_36.moveToElementText(_38); -} -_36.setEndPoint(_37,_35); -_3a=_36.text.length-_40; -return false; + 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 shall 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 == 1 && startOffset == startnode.childNodes.length){ + var nextnode=startnode.nextSibling; + if(nextnode && nextnode.nodeType == 3){ + startnode = nextnode; + startOffset = 0; + } + } + return [startnode, startOffset]; + }, + setEndPoint: function(range, container, offset){ + //text node + var atmrange = range.duplicate(), node, len; + if(container.nodeType!=3){ //normal node + if(offset > 0){ + node = container.childNodes[offset-1]; + if(node){ + if(node.nodeType == 3){ + container = node; + offset = node.length; + //pass through + }else{ + if(node.nextSibling && node.nextSibling.nodeType == 3){ + container=node.nextSibling; + offset=0; + //pass through + }else{ + atmrange.moveToElementText(node.nextSibling?node:container); + var parent = node.parentNode; + var tempNode = parent.insertBefore(node.ownerDocument.createTextNode(' '), node.nextSibling); + atmrange.collapse(false); + parent.removeChild(tempNode); + } + } + } + }else{ + atmrange.moveToElementText(container); + atmrange.collapse(true); + } + } + 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.move('character',offset) != offset){ + console.error('Error when moving!'); + } + } + } + + return atmrange; + }, + decomposeTextRange: function(range){ + var tmpary = dijit.range.ie.getEndPoint(range); + var startContainer = tmpary[0], startOffset = tmpary[1]; + var endContainer = 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); + endContainer = tmpary[0], endOffset = tmpary[1]; +// if(startContainer.tagName == "BODY"){ +// startContainer = startContainer.firstChild; +// } + } + } + return [startContainer, startOffset, endContainer, endOffset]; + }, + setRange: function(range, startContainer, + startOffset, endContainer, endOffset, collapsed){ + var start=dijit.range.ie.setEndPoint(range, startContainer, startOffset); + + range.setEndPoint('StartToStart',start); + if(!collapsed){ + var end=dijit.range.ie.setEndPoint(range, endContainer, endOffset); + } + range.setEndPoint('EndToEnd',end || start); + + return range; + } + } + +dojo.declare("dijit.range.W3CRange",null, { + constructor: function(){ + if(arguments.length>0){ + this.setStart(arguments[0][0],arguments[0][1]); + this.setEnd(arguments[0][2],arguments[0][3]); + }else{ + this.commonAncestorContainer = null; + this.startContainer = null; + this.startOffset = 0; + this.endContainer = null; + this.endOffset = 0; + this.collapsed = true; + } + }, + _updateInternal: function(){ + if(this.startContainer !== this.endContainer){ + this.commonAncestorContainer = dijit.range.getCommonAncestor(this.startContainer, this.endContainer); + }else{ + this.commonAncestorContainer = this.startContainer; + } + this.collapsed = (this.startContainer === this.endContainer) && (this.startOffset == this.endOffset); + }, + setStart: function(node, offset){ + 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); + }else{ + this._updateInternal(); + } + }, + setEnd: function(node, offset){ + 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); + }else{ + this._updateInternal(); + } + }, + 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, this.collapsed); + 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; } -_3b=_3c; -return true; }); -}else{ -_39=_38; -_3a=0; -} -if(!end&&_39.nodeType==1&&_3a==_39.childNodes.length){ -var _41=_39.nextSibling; -if(_41&&_41.nodeType==3){ -_39=_41; -_3a=0; -} -} -return [_39,_3a]; -},setEndPoint:function(_42,_43,_44){ -var _45=_42.duplicate(),_46,len; -if(_43.nodeType!=3){ -if(_44>0){ -_46=_43.childNodes[_44-1]; -if(_46){ -if(_46.nodeType==3){ -_43=_46; -_44=_46.length; -}else{ -if(_46.nextSibling&&_46.nextSibling.nodeType==3){ -_43=_46.nextSibling; -_44=0; -}else{ -_45.moveToElementText(_46.nextSibling?_46:_43); -var _47=_46.parentNode; -var _48=_47.insertBefore(_46.ownerDocument.createTextNode(" "),_46.nextSibling); -_45.collapse(false); -_47.removeChild(_48); -} -} -} -}else{ -_45.moveToElementText(_43); -_45.collapse(true); -} -} -if(_43.nodeType==3){ -var _49=dijit.range.adjacentNoneTextNode(_43); -var _4a=_49[0]; -len=_49[1]; -if(_4a){ -_45.moveToElementText(_4a); -_45.collapse(false); -if(_4a.contentEditable!="inherit"){ -len++; -} -}else{ -_45.moveToElementText(_43.parentNode); -_45.collapse(true); -} -_44+=len; -if(_44>0){ -if(_45.move("character",_44)!=_44){ -console.error("Error when moving!"); -} -} -} -return _45; -},decomposeTextRange:function(_4b){ -var _4c=dijit.range.ie.getEndPoint(_4b); -var _4d=_4c[0],_4e=_4c[1]; -var _4f=_4c[0],_50=_4c[1]; -if(_4b.htmlText.length){ -if(_4b.htmlText==_4b.text){ -_50=_4e+_4b.text.length; -}else{ -_4c=dijit.range.ie.getEndPoint(_4b,true); -_4f=_4c[0],_50=_4c[1]; -} -} -return [_4d,_4e,_4f,_50]; -},setRange:function(_51,_52,_53,_54,_55,_56){ -var _57=dijit.range.ie.setEndPoint(_51,_52,_53); -_51.setEndPoint("StartToStart",_57); -if(!_56){ -var end=dijit.range.ie.setEndPoint(_51,_54,_55); -} -_51.setEndPoint("EndToEnd",end||_57); -return _51; -}}; -dojo.declare("dijit.range.W3CRange",null,{constructor:function(){ -if(arguments.length>0){ -this.setStart(arguments[0][0],arguments[0][1]); -this.setEnd(arguments[0][2],arguments[0][3]); -}else{ -this.commonAncestorContainer=null; -this.startContainer=null; -this.startOffset=0; -this.endContainer=null; -this.endOffset=0; -this.collapsed=true; -} -},_updateInternal:function(){ -if(this.startContainer!==this.endContainer){ -this.commonAncestorContainer=dijit.range.getCommonAncestor(this.startContainer,this.endContainer); -}else{ -this.commonAncestorContainer=this.startContainer; -} -this.collapsed=(this.startContainer===this.endContainer)&&(this.startOffset==this.endOffset); -},setStart:function(_58,_59){ -_59=parseInt(_59); -if(this.startContainer===_58&&this.startOffset==_59){ -return; -} -delete this._cachedBookmark; -this.startContainer=_58; -this.startOffset=_59; -if(!this.endContainer){ -this.setEnd(_58,_59); -}else{ -this._updateInternal(); -} -},setEnd:function(_5a,_5b){ -_5b=parseInt(_5b); -if(this.endContainer===_5a&&this.endOffset==_5b){ -return; -} -delete this._cachedBookmark; -this.endContainer=_5a; -this.endOffset=_5b; -if(!this.startContainer){ -this.setStart(_5a,_5b); -}else{ -this._updateInternal(); -} -},setStartAfter:function(_5c,_5d){ -this._setPoint("setStart",_5c,_5d,1); -},setStartBefore:function(_5e,_5f){ -this._setPoint("setStart",_5e,_5f,0); -},setEndAfter:function(_60,_61){ -this._setPoint("setEnd",_60,_61,1); -},setEndBefore:function(_62,_63){ -this._setPoint("setEnd",_62,_63,0); -},_setPoint:function(_64,_65,_66,ext){ -var _67=dijit.range.getIndex(_65,_65.parentNode).o; -this[_64](_65.parentNode,_67.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,this.collapsed); -return r; -},getBookmark:function(_68){ -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/lib/dijit/_editor/selection.js b/lib/dijit/_editor/selection.js index 3c99c0610..6fed82770 100644 --- a/lib/dijit/_editor/selection.js +++ b/lib/dijit/_editor/selection.js @@ -1,267 +1,369 @@ /* - Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved. + Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved. Available via Academic Free License >= 2.1 OR the modified BSD license. see: http://dojotoolkit.org/license for details */ -if(!dojo._hasResource["dijit._editor.selection"]){ -dojo._hasResource["dijit._editor.selection"]=true; +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"); -dojo.mixin(dijit._editor.selection,{getType:function(){ -if(dojo.isIE){ -return dojo.doc.selection.type.toLowerCase(); -}else{ -var _1="text"; -var _2; -try{ -_2=dojo.global.getSelection(); -} -catch(e){ -} -if(_2&&_2.rangeCount==1){ -var _3=_2.getRangeAt(0); -if((_3.startContainer==_3.endContainer)&&((_3.endOffset-_3.startOffset)==1)&&(_3.startContainer.nodeType!=3)){ -_1="control"; -} -} -return _1; -} -},getSelectedText:function(){ -if(dojo.isIE){ -if(dijit._editor.selection.getType()=="control"){ -return null; -} -return dojo.doc.selection.createRange().text; -}else{ -var _4=dojo.global.getSelection(); -if(_4){ -return _4.toString(); -} -} -return ""; -},getSelectedHtml:function(){ -if(dojo.isIE){ -if(dijit._editor.selection.getType()=="control"){ -return null; -} -return dojo.doc.selection.createRange().htmlText; -}else{ -var _5=dojo.global.getSelection(); -if(_5&&_5.rangeCount){ -var i; -var _6=""; -for(i=0;i<_5.rangeCount;i++){ -var _7=_5.getRangeAt(i).cloneContents(); -var _8=dojo.doc.createElement("div"); -_8.appendChild(_7); -_6+=_8.innerHTML; -} -return _6; -} -return null; -} -},getSelectedElement:function(){ -if(dijit._editor.selection.getType()=="control"){ -if(dojo.isIE){ -var _9=dojo.doc.selection.createRange(); -if(_9&&_9.item){ -return dojo.doc.selection.createRange().item(0); -} -}else{ -var _a=dojo.global.getSelection(); -return _a.anchorNode.childNodes[_a.anchorOffset]; -} -} -return null; -},getParentElement:function(){ -if(dijit._editor.selection.getType()=="control"){ -var p=this.getSelectedElement(); -if(p){ -return p.parentNode; -} -}else{ -if(dojo.isIE){ -var r=dojo.doc.selection.createRange(); -r.collapse(true); -return r.parentElement(); -}else{ -var _b=dojo.global.getSelection(); -if(_b){ -var _c=_b.anchorNode; -while(_c&&(_c.nodeType!=1)){ -_c=_c.parentNode; -} -return _c; -} -} -} -return null; -},hasAncestorElement:function(_d){ -return this.getAncestorElement.apply(this,arguments)!=null; -},getAncestorElement:function(_e){ -var _f=this.getSelectedElement()||this.getParentElement(); -return this.getParentOfType(_f,arguments); -},isTag:function(_10,_11){ -if(_10&&_10.tagName){ -var _12=_10.tagName.toLowerCase(); -for(var i=0;i<_11.length;i++){ -var _13=String(_11[i]).toLowerCase(); -if(_12==_13){ -return _13; -} -} -} -return ""; -},getParentOfType:function(_14,_15){ -while(_14){ -if(this.isTag(_14,_15).length){ -return _14; -} -_14=_14.parentNode; -} -return null; -},collapse:function(_16){ -if(window.getSelection){ -var _17=dojo.global.getSelection(); -if(_17.removeAllRanges){ -if(_16){ -_17.collapseToStart(); -}else{ -_17.collapseToEnd(); -} -}else{ -_17.collapse(_16); -} -}else{ -if(dojo.isIE){ -var _18=dojo.doc.selection.createRange(); -_18.collapse(_16); -_18.select(); -} -} -},remove:function(){ -var sel=dojo.doc.selection; -if(dojo.isIE){ -if(sel.type.toLowerCase()!="none"){ -sel.clear(); -} -return sel; -}else{ -sel=dojo.global.getSelection(); -sel.deleteFromDocument(); -return sel; -} -},selectElementChildren:function(_19,_1a){ -var win=dojo.global; -var doc=dojo.doc; -var _1b; -_19=dojo.byId(_19); -if(doc.selection&&dojo.isIE&&dojo.body().createTextRange){ -_1b=_19.ownerDocument.body.createTextRange(); -_1b.moveToElementText(_19); -if(!_1a){ -try{ -_1b.select(); -} -catch(e){ -} -} -}else{ -if(win.getSelection){ -var _1c=dojo.global.getSelection(); -if(dojo.isOpera){ -if(_1c.rangeCount){ -_1b=_1c.getRangeAt(0); -}else{ -_1b=doc.createRange(); -} -_1b.setStart(_19,0); -_1b.setEnd(_19,(_19.nodeType==3)?_19.length:_19.childNodes.length); -_1c.addRange(_1b); -}else{ -_1c.selectAllChildren(_19); -} -} -} -},selectElement:function(_1d,_1e){ -var _1f; -var doc=dojo.doc; -var win=dojo.global; -_1d=dojo.byId(_1d); -if(dojo.isIE&&dojo.body().createTextRange){ -try{ -_1f=dojo.body().createControlRange(); -_1f.addElement(_1d); -if(!_1e){ -_1f.select(); -} -} -catch(e){ -this.selectElementChildren(_1d,_1e); -} -}else{ -if(dojo.global.getSelection){ -var _20=win.getSelection(); -_1f=doc.createRange(); -if(_20.removeAllRanges){ -if(dojo.isOpera){ -if(_20.getRangeAt(0)){ -_1f=_20.getRangeAt(0); -} -} -_1f.selectNode(_1d); -_20.removeAllRanges(); -_20.addRange(_1f); -} -} -} -},inSelection:function(_21){ -if(_21){ -var _22; -var doc=dojo.doc; -var _23; -if(dojo.global.getSelection){ -var sel=dojo.global.getSelection(); -if(sel&&sel.rangeCount>0){ -_23=sel.getRangeAt(0); -} -if(_23&&_23.compareBoundaryPoints&&doc.createRange){ -try{ -_22=doc.createRange(); -_22.setStart(_21,0); -if(_23.compareBoundaryPoints(_23.START_TO_END,_22)===1){ -return true; -} -} -catch(e){ -} -} -}else{ -if(doc.selection){ -_23=doc.selection.createRange(); -try{ -_22=_21.ownerDocument.body.createControlRange(); -if(_22){ -_22.addElement(_21); -} -} -catch(e1){ -try{ -_22=_21.ownerDocument.body.createTextRange(); -_22.moveToElementText(_21); -} -catch(e2){ -} -} -if(_23&&_22){ -if(_23.compareEndPoints("EndToStart",_22)===1){ -return true; -} -} -} -} -} -return false; -}}); + + +dojo.getObject("_editor.selection", true, dijit); + +// 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.isIE < 9){ + 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; //String + } + }, + + getSelectedText: function(){ + // summary: + // Return the text (no html tags) included in the current selection or null if no text is selected + if(dojo.isIE < 9){ + 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(); //String + } + } + return ''; + }, + + getSelectedHtml: function(){ + // summary: + // Return the html text of the current selection or null if unavailable + if(dojo.isIE < 9){ + 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 i; + var html = ""; + for(i = 0; i < selection.rangeCount; i++){ + //Handle selections spanning ranges, such as Opera + var frag = selection.getRangeAt(i).cloneContents(); + var div = dojo.doc.createElement("div"); + div.appendChild(frag); + html += div.innerHTML; + } + return html; //String + } + 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(dijit._editor.selection.getType() == "control"){ + if(dojo.isIE < 9){ + 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(dijit._editor.selection.getType() == "control"){ + var p = this.getSelectedElement(); + if(p){ return p.parentNode; } + }else{ + if(dojo.isIE < 9){ + var r = dojo.doc.selection.createRange(); + r.collapse(true); + return r.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) + // tagName: String + // The tag name to determine if it has an ancestor of. + return this.getAncestorElement.apply(this, arguments) != null; //Boolean + }, + + 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) + // tagName: String + // The tag name to determine if it has an ancestor of. + var node = this.getSelectedElement() || this.getParentElement(); + return this.getParentOfType(node, arguments); //DOMNode + }, + + isTag: function(/*DomNode*/ node, /*String[]*/ tags){ + // summary: + // Function to determine if a node is one of an array of tags. + // node: + // The node to inspect. + // tags: + // An array of tag name strings to check to see if the node matches. + 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; // String + } + } + } + return ""; + }, + + getParentOfType: function(/*DomNode*/ node, /*String[]*/ tags){ + // summary: + // Function to locate a parent node that matches one of a set of tags + // node: + // The node to inspect. + // tags: + // An array of tag name strings to check to see if the node matches. + while(node){ + if(this.isTag(node, tags).length){ + return node; // DOMNode + } + node = node.parentNode; + } + return null; + }, + + collapse: function(/*Boolean*/beginning){ + // summary: + // Function to collapse (clear), the current selection + // beginning: Boolean + // Boolean to indicate whether to collapse the cursor to the beginning of the selection or end. + 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.isIE){ // IE + var range = dojo.doc.selection.createRange(); + range.collapse(beginning); + range.select(); + } + }, + + remove: function(){ + // summary: + // Function to delete the currently selected content from the document. + var sel = dojo.doc.selection; + if(dojo.isIE < 9){ + if(sel.type.toLowerCase() != "none"){ + sel.clear(); + } + return sel; //Selection + }else{ + sel = dojo.global.getSelection(); + sel.deleteFromDocument(); + return sel; //Selection + } + }, + + selectElementChildren: function(/*DomNode*/element,/*Boolean?*/nochangefocus){ + // summary: + // clear previous selection and select the content of the node + // (excluding the node itself) + // element: DOMNode + // The element you wish to select the children content of. + // nochangefocus: Boolean + // Boolean to indicate if the foxus should change or not. + var win = dojo.global; + var doc = dojo.doc; + var range; + element = dojo.byId(element); + if(doc.selection && dojo.isIE < 9 && dojo.body().createTextRange){ // IE + 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(win.getSelection){ + var selection = dojo.global.getSelection(); + if(dojo.isOpera){ + //Opera's selectAllChildren doesn't seem to work right + //against <body> nodes and possibly others ... so + //we use the W3C range API + if(selection.rangeCount){ + range = selection.getRangeAt(0); + }else{ + range = doc.createRange(); + } + range.setStart(element, 0); + range.setEnd(element,(element.nodeType == 3)?element.length:element.childNodes.length); + selection.addRange(range); + }else{ + selection.selectAllChildren(element); + } + } + }, + + selectElement: function(/*DomNode*/element,/*Boolean?*/nochangefocus){ + // summary: + // clear previous selection and select element (including all its children) + // element: DOMNode + // The element to select. + // nochangefocus: Boolean + // Boolean indicating if the focus should be changed. IE only. + var range; + var doc = dojo.doc; + var win = dojo.global; + element = dojo.byId(element); + if(dojo.isIE < 9 && dojo.body().createTextRange){ + try{ + var tg = element.tagName ? element.tagName.toLowerCase() : ""; + if(tg === "img" || tg === "table"){ + range = dojo.body().createControlRange(); + }else{ + range = dojo.body().createRange(); + } + range.addElement(element); + if(!nochangefocus){ + range.select(); + } + }catch(e){ + this.selectElementChildren(element,nochangefocus); + } + }else if(dojo.global.getSelection){ + var selection = win.getSelection(); + range = doc.createRange(); + if(selection.removeAllRanges){ // Mozilla + // FIXME: does this work on Safari? + if(dojo.isOpera){ + //Opera works if you use the current range on + //the selection if present. + if(selection.getRangeAt(0)){ + range = selection.getRangeAt(0); + } + } + range.selectNode(element); + selection.removeAllRanges(); + selection.addRange(range); + } + } + }, + + inSelection: function(node){ + // summary: + // This function determines if 'node' is + // in the current selection. + // tags: + // public + if(node){ + var newRange; + var doc = dojo.doc; + var range; + + if(dojo.global.getSelection){ + //WC3 + var sel = dojo.global.getSelection(); + if(sel && sel.rangeCount > 0){ + range = sel.getRangeAt(0); + } + if(range && range.compareBoundaryPoints && doc.createRange){ + try{ + newRange = doc.createRange(); + newRange.setStart(node, 0); + if(range.compareBoundaryPoints(range.START_TO_END, newRange) === 1){ + return true; + } + }catch(e){ /* squelch */} + } + }else if(doc.selection){ + // Probably IE, so we can't use the range object as the pseudo + // range doesn't implement the boundry checking, we have to + // use IE specific crud. + range = doc.selection.createRange(); + try{ + newRange = node.ownerDocument.body.createControlRange(); + if(newRange){ + newRange.addElement(node); + } + }catch(e1){ + try{ + newRange = node.ownerDocument.body.createTextRange(); + newRange.moveToElementText(node); + }catch(e2){/* squelch */} + } + if(range && newRange){ + // We can finally compare similar to W3C + if(range.compareEndPoints("EndToStart", newRange) === 1){ + return true; + } + } + } + } + return false; // boolean + } + +}); + } |