/* Product Name: dhtmlxSuite Version: 5.2.0 Edition: Professional License: content of this file is covered by DHTMLX Commercial or Enterprise license. Usage without proper license is prohibited. To obtain it contact sales@dhtmlx.com Copyright UAB Dinamenta http://www.dhtmlx.com */ function dhtmlXEditor(base, skin) { var that = this; this.conf = { // set content after load content: "", // first if set contentHTML: "", // second // resize resizeTM: null, resizeTMTime: 100, // readonly roMode: false, // extended toolbar toolbar: false, iconsPath: "", // frame events evs: ["focus", "blur", "keydown", "keyup", "keypress", "mouseup", "mousedown", "click", "touchend"], // touchend is dev_event for fix on iOS/iPad // focus fix on iOS/iPad iOSfix: (navigator.userAgent.match(/Mobile/gi) != null && navigator.userAgent.match(/iPad/gi) != null && navigator.userAgent.match(/AppleWebKit/gi) != null), // extended font conf extra_css: "", font: {family: "Tahoma", size: "12px", color: "black"} }; this._doOnFocusChanged = null; this._doOnAccess = null; if (typeof(base) == "object" && base != null && base.tagName == null) { skin = base.skin; if (base.content != null) this.conf.content = base.content; if (base.contentHTML != null) this.conf.contentHTML = base.contentHTML; if (base.iconsPath != null) this.conf.iconsPath = base.iconsPath; if (base.extraCss != null) this.conf.extra_css = base.extraCss; if (base.toolbar != null) this.conf.toolbar = window.dhx4.s2b(base.toolbar); if (base.onFocusChanged != null) this._doOnFocusChanged = base.onFocusChanged; if (base.onAccess != null) this._doOnAccess = base.onAccess; base = base.parent; } // skin config this.conf.skin = (skin||window.dhx4.skin||(typeof(dhtmlx)!="undefined"?dhtmlx.skin:null)||window.dhx4.skinDetect("dhxeditor")||"material"); // configure base if (typeof(base) == "string") base = document.getElementById(base); this.base = base; this.base.className += " dhxeditor_"+this.conf.skin; while (this.base.childNodes.length > 0) this.base.removeChild(this.base.childNodes[0]); // configure base for dhxcont var pos = (window.dhx4.isIE ? this.base.currentStyle["position"] : (window.getComputedStyle != null? window.getComputedStyle(this.base, null).getPropertyValue("position") : "" )); if (!(pos == "relative" || pos == "absolute")) this.base.style.position = "relative"; // init dhxcont this.cell = new dhtmlXEditorCell(window.dhx4.newId(), this); this.base.appendChild(this.cell.cell); this.cBlock = document.createElement("DIV"); this.cBlock.className = "dhxcont_content_blocker"; this.cBlock.style.display = "none"; this.base.appendChild(this.cBlock); // editable area this.editor = document.createElement("IFRAME"); this.editor.className = "dhxeditor_mainiframe"; this.editor.frameBorder = 0; if (window.dhx4.isOpera) this.editor.scrolling = "yes"; // adjust self this.setSizes(); // onAccess event - focus/blue as param var fr = this.editor; if (typeof(window.addEventListener) != "undefined") { fr.onload = function() { for (var q=0; q"+this.conf.extra_css+ ""+ ""); } else { if (window.dhx4.isKHTML) { edDoc.write(""+this.conf.extra_css+ ""+ ""); } else { if (window.dhx4.isIE) { // && navigator.appVersion.indexOf("MSIE 9.0")!= -1 edDoc.write(""+this.conf.extra_css+ ""+ ""); } else { edDoc.write(""+this.conf.extra_css+ ""+ ""); } } } edDoc.close(); if (window.dhx4.isIE) edDoc.contentEditable = (roMode!==true); else edDoc.designMode = (roMode!==true?"On":"Off"); if (window.dhx4.isFF) try { edDoc.execCommand("useCSS", false, true); } catch(e) {} if (saveContent === true && this.setContent != null) this.setContent(storedContent); } // fix this._prepareContent(); // resize this._doOnResize = function() { window.clearTimeout(that.conf.resizeTM); that.conf.resizeTM = window.setTimeout(function(){if(that.setSizes)that.setSizes();}, that.conf.resizeTMTime); } // toolbar buttons this._runCommand = function(name,param){ if (this.conf.roMode === true) return; if (arguments.length < 2) param = null; if (window.dhx4.isIE) this.edWin.focus(); try { var edDoc = this.editor.contentWindow.document edDoc.execCommand(name,false,param); } catch(e){} if (window.dhx4.isIE) { this.edWin.focus(); var self = this; window.setTimeout(function(){ self.edWin.focus(); self = null; },1); } } // commands this.applyBold = function() { this._runCommand("Bold"); } this.applyItalic = function() { this._runCommand("Italic"); } this.applyUnderscore = function() { this._runCommand("Underline"); } this.clearFormatting = function() { this._runCommand("RemoveFormat"); var k = this.getContent(); k = k.replace(/<\/?h\d>/gi, ""); this.setContent(k); } this._doOnClick = function(e) { var ev = e||window.event; var el = ev.target||ev.srcElement; that._showInfo(el); } this._doOnMouseDown = function(e) { // opera only var ev = e||window.event; var el = ev.target||ev.srcElement; that._showInfo(el); } this._doOnKeyUp = function(e) { var ev = e||window.event; var key = ev.keyCode; var el = ev.target||ev.srcElement; if ({37:1,38:1,39:1,40:1,13:1}[key] == 1) that._showInfo(el); } this._getParentByTag = function(node, tag_name) { tag_name = tag_name.toLowerCase(); var p = node; do { if (tag_name == '' || p.nodeName.toLowerCase() == tag_name) return p; } while (p = p.parentNode); return node; } this._isStyleProperty = function(node, tag_name, name, value){ tag_name = tag_name.toLowerCase(); var n = node; do { if ((n.nodeName.toLowerCase() == tag_name) && (n.style[name] == value)) return true; } while (n = n.parentNode); return false; } this._setStyleProperty = function(el, prop) { this.style[prop] = false; var n = this._getParentByTag(el, prop); if (n && (n.tagName.toLowerCase() == prop)) this.style[prop] = true; if (prop == "del" && this._getParentByTag(el, "strike") && this._getParentByTag(el,"strike").tagName.toLowerCase() == "strike") this.style.del = true; } this._showInfo = function(el) { var el = (this._getSelectionBounds().end)?this._getSelectionBounds().end : el; if (!el || !this._setStyleProperty) return; try { if (this.edWin.getComputedStyle) { var st = this.edWin.getComputedStyle(el, null); var fw = ((st.getPropertyValue("font-weight")==401)?700:st.getPropertyValue("font-weight")); this.style = { fontStyle : st.getPropertyValue("font-style"), fontSize : st.getPropertyValue("font-size"), textDecoration : st.getPropertyValue("text-decoration"), fontWeight : fw, fontFamily : st.getPropertyValue("font-family"), textAlign : st.getPropertyValue("text-align") }; if (window.dhx4.isKHTML) { // safari this.style.fontStyle = st.getPropertyValue("font-style"); this.style.vAlign = st.getPropertyValue("vertical-align"); this.style.del = this._isStyleProperty(el,"span","textDecoration","line-through"); this.style.u = this._isStyleProperty(el,"span","textDecoration","underline"); } } else { var st = el.currentStyle; this.style = { fontStyle : st.fontStyle, fontSize : st.fontSize, textDecoration : st.textDecoration, fontWeight : st.fontWeight, fontFamily : st.fontFamily, textAlign : st.textAlign }; } this._setStyleProperty(el,"h1"); this._setStyleProperty(el,"h2"); this._setStyleProperty(el,"h3"); this._setStyleProperty(el,"h4"); if (!window.dhx4.isKHTML) { this._setStyleProperty(el,"del"); this._setStyleProperty(el,"sub"); this._setStyleProperty(el,"sup"); this._setStyleProperty(el,"u"); } this.callEvent("onFocusChanged", [this.style, st]) } catch(e){ return null; } } this._getSelectionBounds = function() { var range, root, start, end; if (this.edWin.getSelection) { var selection = this.edWin.getSelection(); if (window.dhx4.isEdge && selection.rangeCount == 0) return {root: null, start: null, end: null}; range = selection.getRangeAt(selection.rangeCount-1); start = range.startContainer; end = range.endContainer; root = range.commonAncestorContainer; if (start.nodeName == "#text") root = root.parentNode; if (start.nodeName == "#text") start = start.parentNode; if (start.nodeName.toLowerCase() == "body") start = start.firstChild; if (end.nodeName == "#text") end = end.parentNode; if (end.nodeName.toLowerCase() == "body") end = end.lastChild; if (start == end) root = start; return { root: root, start: start, end: end }; } else if (this.edWin.document.selection) { range = this.edDoc.selection.createRange() if(!range.duplicate) return null; root = range.parentElement(); var r1 = range.duplicate(); var r2 = range.duplicate(); r1.collapse(true); r2.moveToElementText(r1.parentElement()); r2.setEndPoint("EndToStart",r1); start = r1.parentElement(); r1 = range.duplicate(); r2 = range.duplicate(); r2.collapse(false); r1.moveToElementText(r2.parentElement()); r1.setEndPoint("StartToEnd", r2); end = r2.parentElement(); if (start.nodeName.toLowerCase() == "body") start = start.firstChild; if (end.nodeName.toLowerCase() == "body") end = end.lastChild; if (start == end) root = start; return { root: root, start: start, end: end }; } return null; } this.getContent = function(){ if (!this.edDoc.body) { return ""; } else { if (window.dhx4.isFF || window.dhx4.isChrome) return this.editor.contentWindow.document.body.innerHTML.replace(/<\/{0,}br\/{0,}>\s{0,}$/gi,""); if (window.dhx4.isIE && this.edDoc.body.innerText.length == 0) return ""; return this.edDoc.body.innerHTML; } } this.setContent = function(str){ str = str||""; if (this.edDoc.body) { var ffTest = false; if (window.dhx4.isFF) { var k = navigator.userAgent.match(/Firefox\/(\d*)/); ffTest = (k != null && k[1] < 28); } if (ffTest) { if (typeof(this.conf.ffTest) == "undefined") { this.editor.contentWindow.document.body.innerHTML = ""; this._runCommand("InsertHTML", "test"); this.conf.ffTest = (this.editor.contentWindow.document.body.innerHTML.length > 0); } if (this.conf.ffTest) { // FF 4.x+ this.editor.contentWindow.document.body.innerHTML = str; } else { // FF 2.x, 3.x this.editor.contentWindow.document.body.innerHTML = ""; if (str.length == 0) str=" "; this._runCommand("InsertHTML", str); } } else { this.editor.contentWindow.document.body.innerHTML = str; } this.callEvent("onContentSet",[]); } else { if (!this.conf.firstLoadEv) { this.conf.firstLoadEv = true; this.conf.firstLoadData = str; this._onFirstLoad = function() { that.setContent(that.conf.firstLoadData); if (typeof(window.addEventListener) == "function") { that.edWin.removeEventListener("load", that._onFirstLoad, false); } else { that.edWin.detachEvent("onload", that._onFirstLoad); } that.conf.firstLoadData = null; that.conf.firstLoadEv = false; that._onFirstLoad = null; } if (typeof(window.addEventListener) == "function") { this.edWin.addEventListener("load", this._onFirstLoad, false); } else { this.edWin.attachEvent("onload", this._onFirstLoad); } } } } this.setContentHTML = function(url) { window.dhx4.ajax.get(url, function(r) { if (r.xmlDoc.responseText != null) that.setContent(r.xmlDoc.responseText); }); } // events window.dhx4._eventable(this); this.attachEvent("onFocusChanged", function(state){ if (typeof(this._doOnFocusChanged) == "function") { this._doOnFocusChanged(state); } else if (typeof(this._doOnFocusChanged) == "string" && typeof(window[this._doOnFocusChanged]) == "function") { window[this._doOnFocusChanged](state); } }); if (typeof(window.addEventListener) == "function") { window.addEventListener("resize", this._doOnResize, false); this.edDoc.addEventListener("click", this._doOnClick, false); this.edDoc.addEventListener("keyup", this._doOnKeyUp, false); if (window.dhx4.isOpera) this.edDoc.addEventListener("mousedown", this._doOnMouseDown, false); } else { window.attachEvent("onresize", this._doOnResize); this.edDoc.attachEvent("onclick", this._doOnClick); this.edDoc.attachEvent("onkeyup", this._doOnKeyUp); } this.unload = function() { // first detach events from iframe if (typeof(window.addEventListener) == "function") { window.removeEventListener("resize", this._doOnResize, false); this.edDoc.removeEventListener("click", this._doOnClick, false); this.edDoc.removeEventListener("keyup", this._doOnKeyUp, false); if (window.dhx4.isOpera) this.edDoc.removeEventListener("mousedown", this._doOnMouseDown, false); // editor's for (var q=0; q 0) this.base.removeChild(this.base.childNodes[0]); this.base = null; this._doOnClick = null; this._doOnKeyUp = null; this._doOnMouseDown = null; this._ev = null; this._focus = null; this._prepareContent = null; this._doOnResize = null; this.setIconsPath = null; this.init = null; this.setSizes = null; this._runCommand = null; this.applyBold = null; this.applyItalic = null; this.applyUnderscore = null; this.clearFormatting = null; this._showInfo = null; this._getSelectionBounds = null; this.getContent = null; this.setContent = null; this.setContentHTML = null; this.setReadonly = null; this.isReadonly = null; this.unload = null; that = fr = null; } // load extended toolbar if any if (this.conf.toolbar == true && typeof(this.attachToolbar) == "function" && typeof(window.dhtmlXToolbarObject) == "function") { this.attachToolbar(this.conf.iconsPath); if (this.conf.iOSfix == true) { this._doOnIOSFix = function() { that.editor.contentWindow.focus(); } this.tb.cont.addEventListener("touchend", this._doOnIOSFix, false); } } this.setIconsPath = function(iconsPath) { this.conf.iconsPath = iconsPath; } // load content if any if (this.conf.content.length > 0) { this.setContent(this.conf.content); this.conf.content = ""; } else if (this.conf.contentHTML.length > 0) { this.setContentHTML(this.conf.contentHTML); this.conf.contentHTML = ""; } return this; }; dhtmlXEditor.prototype.setSizes = function() { this.cell._setSize(0, 0, this.base.clientWidth, this.base.clientHeight); if (this.editor != null) { this.editor.style.left = "5px"; this.editor.style.width = this.base.clientWidth-5+"px"; } }; dhtmlXEditor.prototype.setReadonly = function(mode) { this.conf.roMode = (mode===true); this._prepareContent(true, this.conf.roMode); this.cBlock.style.display = (this.conf.roMode?"":"none"); }; dhtmlXEditor.prototype.isReadonly = function(mode) { return (this.conf.roMode||false); }; dhtmlXEditor.prototype.setSkin = function(skin) { this.base.className = String(this.base.className).replace(new RegExp("dhxeditor_"+this.conf.skin),"dhxeditor_"+skin); this.conf.skin = this.cell.conf.skin = skin; if (this.tb) { this.cell.detachToolbar(skin); this.tb = null; this.attachToolbar(); } this.setSizes(); }; dhtmlXEditor.prototype._fontConf = function() { if (this.conf.skin == "") { var data = {family: this.conf.font.family, size: this.conf.font.size, color: this.conf.font.color}; } else { var data = {family: "Roboto, Arial, Helvetica", size: "14px", color: "#404040"}; } return window.dhx4.template("font-size: #size#; font-family: #family#; color: #color#;", data); }; window.dhtmlXEditorCell = function(id, editor) { dhtmlXCellObject.apply(this, [id, "_editor"]); var that = this; this.editor = editor; this.conf.skin = this.editor.conf.skin; this.attachEvent("_onCellUnload", function(){ // unload simple toolbar this._stbUnload(); this.editor = null; that = null; }); // simple toolbar init this._stbInit(); return this; }; dhtmlXEditorCell.prototype = new dhtmlXCellObject(); // simple toolbar dhtmlXEditorCell.prototype._stbInit = function() { var that = this; var t = document.createElement("DIV"); t.className = "dhx_cell_stb"+(dhx4.isIE6||dhx4.isIE7||dhx4.isIE8?"":" dhx_cell_stb_shadow"); this.cell.insertBefore(t, this.cell.childNodes[this.conf.idx.cont]); t.onselectstart = function(e) { e = e||event; e.cancelBubble = true; if (e.preventDefault) e.preventDefault(); else e.returnValue = false; return false; } var items = { bold: "applyBold", italic: "applyItalic", underline: "applyUnderscore", clearformat: "clearFormatting" }; for (var k in items) { var a = document.createElement("A"); a.href = "javascript:void(0);"; a.tabIndex = -1; t.appendChild(a); a.onmousedown = a.onclick = function(e){ e = e||event; if (e.preventDefault) e.preventDefault(); else e.returnValue = false; return false; } var d = document.createElement("DIV"); d.className = "dhx_cell_stb_button btn_"+k; d._actv = k.charAt(0); d._cmd = items[k]; a.appendChild(d); d.onclick = function(e){ e = e||event; if (e.preventDefault) e.preventDefault(); else e.returnValue = false; return false; } d.onmousedown = function(e){ e = e||event; if (e.preventDefault) e.preventDefault(); else e.returnValue = false; that.editor[this._cmd](); that.editor.callEvent("onToolbarClick",[this._actv]); } d = a = null; } t = null; this._stbUnload = function() { var t = this.cell.childNodes[this.conf.idx.stb]; t.onselectstart = null; while (t.childNodes.length > 0) { t.lastChild.onmousedown = t.lastChild.onclick = null; t.lastChild.firstChild.onmousedown = t.lastChild.firstChild.onclick = null; t.lastChild.firstChild._actv = t.lastChild.firstChild._cmd = null; t.lastChild.removeChild(t.lastChild.firstChild); t.removeChild(t.lastChild); } t.parentNode.removeChild(t); t = that = null; this.conf.idx_data.stb = this.conf.ofs_nodes.t._getStbHeight = null; delete this.conf.ofs_nodes.t._getStbHeight delete this.conf.idx_data.stb; this._updateIdx(); }; this.conf.stb_visible = true; // include into content top offset calculation this.conf.ofs_nodes.t._getStbHeight = "func"; // include into index this.conf.idx_data.stb = "dhx_cell_stb"; this._updateIdx(); }; dhtmlXEditorCell.prototype._stbHide = function() { this.cell.childNodes[this.conf.idx.stb].style.display = "none"; this.conf.stb_visible = false; }; dhtmlXEditorCell.prototype._getStbHeight = function() { if (this.conf.stb_visible == true && this.conf.skin == "material") { if (this.conf.stb_height == null) { this.conf.stb_height = window.dhx4.readFromCss("dhxeditor_material stb_height_detect", "scrollHeight", "
"); } return this.conf.stb_height; } return this.cell.childNodes[this.conf.idx.stb].offsetHeight; }; dhtmlXCellObject.prototype.attachEditor = function(conf) { this.callEvent("_onBeforeContentAttach",["editor"]); var obj = document.createElement("DIV"); obj.style.width = "100%"; obj.style.height = "100%"; obj.style.position = "relative"; obj.style.overflow = "hidden"; this._attachObject(obj); if (!(typeof(conf) == "object" && conf != null)) conf = {}; conf.parent = obj; this.dataType = "editor"; this.dataObj = new dhtmlXEditor(conf); obj = null; conf.parent = null; conf = null; // attach to portal extended logic if (typeof(window.dhtmlXPortalCell) == "function" && this instanceof window.dhtmlXPortalCell) { if (this.portal.conf.editor_ev == null) { var e1 = this.portal.attachEvent("onBeforeDrag", function(id) { if (this.cdata[id].dataType == "editor") { this.cdata[id].conf.editor_cont = this.cdata[id].dataObj.getContent(); } return true; }); var e2 = this.portal.attachEvent("onDrop", function(id) { if (this.cdata[id].dataType == "editor") { this.cdata[id].dataObj.setContent(this.cdata[id].conf.editor_cont); this.cdata[id].dataObj._prepareContent(true); this.cdata[id].conf.editor_cont = null; } }); this.portal.conf.editor_ev = [e1, e2]; } this.conf.editor_ev = this.attachEvent("_onBeforeContentDetach", function(){ this.detachEvent(this.conf.editor_ev); this.conf.editor_ev = null; if (this instanceof window.dhtmlXPortalCell) { var ed = false; for (var a in this.portal.cdata) { if (this.portal.cdata[a] != this && this.portal.cdata[a].dataType == "editor") { ed = true; // portal still have attached editors } } // no more editors, clear events if (ed == false) { for (var q=0; q