diff --git a/application/views/scripts/javascripts/vendor/tiny_mce/plugins/fullpage/editor_plugin.js b/application/views/scripts/javascripts/vendor/tiny_mce/plugins/fullpage/editor_plugin.js index 0dfd2cae4c..dcf76024dd 100644 --- a/application/views/scripts/javascripts/vendor/tiny_mce/plugins/fullpage/editor_plugin.js +++ b/application/views/scripts/javascripts/vendor/tiny_mce/plugins/fullpage/editor_plugin.js @@ -1 +1 @@ -(function(){var b=tinymce.each,a=tinymce.html.Node;tinymce.create("tinymce.plugins.FullPagePlugin",{init:function(c,d){var e=this;e.editor=c;c.addCommand("mceFullPageProperties",function(){c.windowManager.open({file:d+"/fullpage.htm",width:430+parseInt(c.getLang("fullpage.delta_width",0)),height:495+parseInt(c.getLang("fullpage.delta_height",0)),inline:1},{plugin_url:d,data:e._htmlToData()})});c.addButton("fullpage",{title:"fullpage.desc",cmd:"mceFullPageProperties"});c.onBeforeSetContent.add(e._setContent,e);c.onGetContent.add(e._getContent,e)},getInfo:function(){return{longname:"Fullpage",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/fullpage",version:tinymce.majorVersion+"."+tinymce.minorVersion}},_htmlToData:function(){var e=this._parseHeader(),g={},h,f,d=this.editor;function c(k,i){var j=k.attr(i);return j||""}g.fontface=d.getParam("fullpage_default_fontface","");g.fontsize=d.getParam("fullpage_default_fontsize","");h=e.firstChild;if(h.type==7){g.xml_pi=true;f=/encoding="([^"]+)"/.exec(h.value);if(f){g.docencoding=f[1]}}h=e.getAll("#doctype")[0];if(h){g.doctype=""}h=e.getAll("title")[0];if(h&&h.firstChild){g.metatitle=h.firstChild.value}b(e.getAll("meta"),function(l){var j=l.attr("name"),i=l.attr("http-equiv"),k;if(j){g["meta"+j.toLowerCase()]=l.attr("content")}else{if(i=="Content-Type"){k=/charset\s*=\s*(.*)\s*/gi.exec(l.attr("content"));if(k){g.docencoding=k[1]}}}});h=e.getAll("html")[0];if(h){g.langcode=c(h,"lang")||c(h,"xml:lang")}h=e.getAll("link")[0];if(h&&h.attr("rel")=="stylesheet"){g.stylesheet=h.attr("href")}h=e.getAll("body")[0];if(h){g.langdir=c(h,"dir");g.style=c(h,"style");g.visited_color=c(h,"vlink");g.link_color=c(h,"link");g.active_color=c(h,"alink")}return g},_dataToHtml:function(g){var f,d,h,j,k,e=this.editor.dom;function c(n,l,m){n.attr(l,m?m:undefined)}function i(l){if(d.firstChild){d.insert(l,d.firstChild)}else{d.append(l)}}f=this._parseHeader();d=f.getAll("head")[0];if(!d){j=f.getAll("html")[0];d=new a("head",1);if(j.firstChild){j.insert(d,j.firstChild,true)}else{j.append(d)}}j=f.firstChild;if(g.xml_pi){k='version="1.0"';if(g.docencoding){k+=' encoding="'+g.docencoding+'"'}if(j.type!=7){j=new a("xml",7);f.insert(j,f.firstChild,true)}j.value=k}else{if(j&&j.type==7){j.remove()}}j=f.getAll("#doctype")[0];if(g.doctype){if(!j){j=new a("#doctype",10);if(g.xml_pi){f.insert(j,f.firstChild)}else{i(j)}}j.value=g.doctype.substring(9,g.doctype.length-1)}else{if(j){j.remove()}}j=f.getAll("title")[0];if(g.metatitle){if(!j){j=new a("title",1);j.append(new a("#text",3)).value=g.metatitle;i(j)}}if(g.docencoding){j=null;b(f.getAll("meta"),function(l){if(l.attr("http-equiv")=="Content-Type"){j=l}});if(!j){j=new a("meta",1);j.attr("http-equiv","Content-Type");j.shortEnded=true;i(j)}j.attr("content","text/html; charset="+g.docencoding)}b("keywords,description,author,copyright,robots".split(","),function(m){var l=f.getAll("meta"),n,p,o=g["meta"+m];for(n=0;n"))},_parseHeader:function(){return new tinymce.html.DomParser({validate:false,root_name:"#document"}).parse(this.head)},_setContent:function(g,d){var m=this,i,c,h=d.content,f,l="",e=m.editor.dom,j;function k(n){return n.replace(/<\/?[A-Z]+/g,function(o){return o.toLowerCase()})}if(d.format=="raw"&&m.head){return}if(d.source_view&&g.getParam("fullpage_hide_in_source_view")){return}h=h.replace(/<(\/?)BODY/gi,"<$1body");i=h.indexOf("",i);m.head=k(h.substring(0,i+1));c=h.indexOf("\n"}f=m._parseHeader();b(f.getAll("style"),function(n){if(n.firstChild){l+=n.firstChild.value}});j=f.getAll("body")[0];if(j){e.setAttribs(m.editor.getBody(),{style:j.attr("style")||"",dir:j.attr("dir")||"",vLink:j.attr("vlink")||"",link:j.attr("link")||"",aLink:j.attr("alink")||""})}e.remove("fullpage_styles");if(l){e.add(m.editor.getDoc().getElementsByTagName("head")[0],"style",{id:"fullpage_styles"},l);j=e.get("fullpage_styles");if(j.styleSheet){j.styleSheet.cssText=l}}},_getDefaultHeader:function(){var f="",c=this.editor,e,d="";if(c.getParam("fullpage_default_xml_pi")){f+='\n'}f+=c.getParam("fullpage_default_doctype",'');f+="\n\n\n";if(e=c.getParam("fullpage_default_title")){f+=""+e+"\n"}if(e=c.getParam("fullpage_default_encoding")){f+='\n'}if(e=c.getParam("fullpage_default_font_family")){d+="font-family: "+e+";"}if(e=c.getParam("fullpage_default_font_size")){d+="font-size: "+e+";"}if(e=c.getParam("fullpage_default_text_color")){d+="color: "+e+";"}f+="\n\n";return f},_getContent:function(d,e){var c=this;if(!e.source_view||!d.getParam("fullpage_hide_in_source_view")){e.content=tinymce.trim(c.head)+"\n"+tinymce.trim(e.content)+"\n"+tinymce.trim(c.foot)}}});tinymce.PluginManager.add("fullpage",tinymce.plugins.FullPagePlugin)})(); \ No newline at end of file +(function(){var b=tinymce.each,a=tinymce.html.Node;tinymce.create("tinymce.plugins.FullPagePlugin",{init:function(c,d){var e=this;e.editor=c;c.addCommand("mceFullPageProperties",function(){c.windowManager.open({file:d+"/fullpage.htm",width:430+parseInt(c.getLang("fullpage.delta_width",0)),height:495+parseInt(c.getLang("fullpage.delta_height",0)),inline:1},{plugin_url:d,data:e._htmlToData()})});c.addButton("fullpage",{title:"fullpage.desc",cmd:"mceFullPageProperties"});c.onBeforeSetContent.add(e._setContent,e);c.onGetContent.add(e._getContent,e)},getInfo:function(){return{longname:"Fullpage",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/fullpage",version:tinymce.majorVersion+"."+tinymce.minorVersion}},_htmlToData:function(){var f=this._parseHeader(),h={},c,i,g,e=this.editor;function d(l,j){var k=l.attr(j);return k||""}h.fontface=e.getParam("fullpage_default_fontface","");h.fontsize=e.getParam("fullpage_default_fontsize","");i=f.firstChild;if(i.type==7){h.xml_pi=true;g=/encoding="([^"]+)"/.exec(i.value);if(g){h.docencoding=g[1]}}i=f.getAll("#doctype")[0];if(i){h.doctype=""}i=f.getAll("title")[0];if(i&&i.firstChild){h.metatitle=i.firstChild.value}b(f.getAll("meta"),function(m){var k=m.attr("name"),j=m.attr("http-equiv"),l;if(k){h["meta"+k.toLowerCase()]=m.attr("content")}else{if(j=="Content-Type"){l=/charset\s*=\s*(.*)\s*/gi.exec(m.attr("content"));if(l){h.docencoding=l[1]}}}});i=f.getAll("html")[0];if(i){h.langcode=d(i,"lang")||d(i,"xml:lang")}i=f.getAll("link")[0];if(i&&i.attr("rel")=="stylesheet"){h.stylesheet=i.attr("href")}i=f.getAll("body")[0];if(i){h.langdir=d(i,"dir");h.style=d(i,"style");h.visited_color=d(i,"vlink");h.link_color=d(i,"link");h.active_color=d(i,"alink")}return h},_dataToHtml:function(g){var f,d,h,j,k,e=this.editor.dom;function c(n,l,m){n.attr(l,m?m:undefined)}function i(l){if(d.firstChild){d.insert(l,d.firstChild)}else{d.append(l)}}f=this._parseHeader();d=f.getAll("head")[0];if(!d){j=f.getAll("html")[0];d=new a("head",1);if(j.firstChild){j.insert(d,j.firstChild,true)}else{j.append(d)}}j=f.firstChild;if(g.xml_pi){k='version="1.0"';if(g.docencoding){k+=' encoding="'+g.docencoding+'"'}if(j.type!=7){j=new a("xml",7);f.insert(j,f.firstChild,true)}j.value=k}else{if(j&&j.type==7){j.remove()}}j=f.getAll("#doctype")[0];if(g.doctype){if(!j){j=new a("#doctype",10);if(g.xml_pi){f.insert(j,f.firstChild)}else{i(j)}}j.value=g.doctype.substring(9,g.doctype.length-1)}else{if(j){j.remove()}}j=f.getAll("title")[0];if(g.metatitle){if(!j){j=new a("title",1);j.append(new a("#text",3)).value=g.metatitle;i(j)}}if(g.docencoding){j=null;b(f.getAll("meta"),function(l){if(l.attr("http-equiv")=="Content-Type"){j=l}});if(!j){j=new a("meta",1);j.attr("http-equiv","Content-Type");j.shortEnded=true;i(j)}j.attr("content","text/html; charset="+g.docencoding)}b("keywords,description,author,copyright,robots".split(","),function(m){var l=f.getAll("meta"),n,p,o=g["meta"+m];for(n=0;n"))},_parseHeader:function(){return new tinymce.html.DomParser({validate:false,root_name:"#document"}).parse(this.head)},_setContent:function(g,d){var m=this,i,c,h=d.content,f,l="",e=m.editor.dom,j;function k(n){return n.replace(/<\/?[A-Z]+/g,function(o){return o.toLowerCase()})}if(d.format=="raw"&&m.head){return}if(d.source_view&&g.getParam("fullpage_hide_in_source_view")){return}h=h.replace(/<(\/?)BODY/gi,"<$1body");i=h.indexOf("",i);m.head=k(h.substring(0,i+1));c=h.indexOf("\n"}f=m._parseHeader();b(f.getAll("style"),function(n){if(n.firstChild){l+=n.firstChild.value}});j=f.getAll("body")[0];if(j){e.setAttribs(m.editor.getBody(),{style:j.attr("style")||"",dir:j.attr("dir")||"",vLink:j.attr("vlink")||"",link:j.attr("link")||"",aLink:j.attr("alink")||""})}e.remove("fullpage_styles");if(l){e.add(m.editor.getDoc().getElementsByTagName("head")[0],"style",{id:"fullpage_styles"},l);j=e.get("fullpage_styles");if(j.styleSheet){j.styleSheet.cssText=l}}},_getDefaultHeader:function(){var f="",c=this.editor,e,d="";if(c.getParam("fullpage_default_xml_pi")){f+='\n'}f+=c.getParam("fullpage_default_doctype",'');f+="\n\n\n";if(e=c.getParam("fullpage_default_title")){f+=""+e+"\n"}if(e=c.getParam("fullpage_default_encoding")){f+='\n'}if(e=c.getParam("fullpage_default_font_family")){d+="font-family: "+e+";"}if(e=c.getParam("fullpage_default_font_size")){d+="font-size: "+e+";"}if(e=c.getParam("fullpage_default_text_color")){d+="color: "+e+";"}f+="\n\n";return f},_getContent:function(d,e){var c=this;if(!e.source_view||!d.getParam("fullpage_hide_in_source_view")){e.content=tinymce.trim(c.head)+"\n"+tinymce.trim(e.content)+"\n"+tinymce.trim(c.foot)}}});tinymce.PluginManager.add("fullpage",tinymce.plugins.FullPagePlugin)})(); \ No newline at end of file diff --git a/application/views/scripts/javascripts/vendor/tiny_mce/plugins/fullpage/editor_plugin_src.js b/application/views/scripts/javascripts/vendor/tiny_mce/plugins/fullpage/editor_plugin_src.js index 7663a14acf..23de7c5a1a 100644 --- a/application/views/scripts/javascripts/vendor/tiny_mce/plugins/fullpage/editor_plugin_src.js +++ b/application/views/scripts/javascripts/vendor/tiny_mce/plugins/fullpage/editor_plugin_src.js @@ -50,13 +50,13 @@ // Private plugin internal methods _htmlToData : function() { - var headerFragment = this._parseHeader(), data = {}, elm, matches, editor = this.editor; + var headerFragment = this._parseHeader(), data = {}, nodes, elm, matches, editor = this.editor; function getAttr(elm, name) { var value = elm.attr(name); return value || ''; - } + }; // Default some values data.fontface = editor.getParam("fullpage_default_fontface", ""); @@ -67,16 +67,14 @@ if (elm.type == 7) { data.xml_pi = true; matches = /encoding="([^"]+)"/.exec(elm.value); - if (matches) { + if (matches) data.docencoding = matches[1]; - } } // Parse doctype elm = headerFragment.getAll('#doctype')[0]; - if (elm) { + if (elm) data.doctype = '"; - } // Parse title element elm = headerFragment.getAll('title')[0]; @@ -88,28 +86,25 @@ each(headerFragment.getAll('meta'), function(meta) { var name = meta.attr('name'), httpEquiv = meta.attr('http-equiv'), matches; - if (name) { + if (name) data['meta' + name.toLowerCase()] = meta.attr('content'); - } else if (httpEquiv == "Content-Type") { + else if (httpEquiv == "Content-Type") { matches = /charset\s*=\s*(.*)\s*/gi.exec(meta.attr('content')); - if (matches) { + if (matches) data.docencoding = matches[1]; - } } }); // Parse html attribs elm = headerFragment.getAll('html')[0]; - if (elm) { + if (elm) data.langcode = getAttr(elm, 'lang') || getAttr(elm, 'xml:lang'); - } // Parse stylesheet elm = headerFragment.getAll('link')[0]; - if (elm && elm.attr('rel') == 'stylesheet') { + if (elm && elm.attr('rel') == 'stylesheet') data.stylesheet = elm.attr('href'); - } // Parse body parts elm = headerFragment.getAll('body')[0]; @@ -129,15 +124,14 @@ function setAttr(elm, name, value) { elm.attr(name, value ? value : undefined); - } + }; function addHeadNode(node) { - if (headElement.firstChild) { + if (headElement.firstChild) headElement.insert(node, headElement.firstChild); - } else { + else headElement.append(node); - } - } + }; headerFragment = this._parseHeader(); headElement = headerFragment.getAll('head')[0]; @@ -145,11 +139,10 @@ elm = headerFragment.getAll('html')[0]; headElement = new Node('head', 1); - if (elm.firstChild) { + if (elm.firstChild) elm.insert(headElement, elm.firstChild, true); - } else { + else elm.append(headElement); - } } // Add/update/remove XML-PI @@ -157,9 +150,8 @@ if (data.xml_pi) { value = 'version="1.0"'; - if (data.docencoding) { + if (data.docencoding) value += ' encoding="' + data.docencoding + '"'; - } if (elm.type != 7) { elm = new Node('xml', 7); @@ -167,9 +159,8 @@ } elm.value = value; - } else if (elm && elm.type == 7) { + } else if (elm && elm.type == 7) elm.remove(); - } // Add/update/remove doctype elm = headerFragment.getAll('#doctype')[0]; @@ -177,17 +168,15 @@ if (!elm) { elm = new Node('#doctype', 10); - if (data.xml_pi) { + if (data.xml_pi) headerFragment.insert(elm, headerFragment.firstChild); - } else { + else addHeadNode(elm); - } } elm.value = data.doctype.substring(9, data.doctype.length - 1); - } else if (elm) { + } else if (elm) elm.remove(); - } // Add/update/remove title elm = headerFragment.getAll('title')[0]; @@ -203,9 +192,8 @@ if (data.docencoding) { elm = null; each(headerFragment.getAll('meta'), function(meta) { - if (meta.attr('http-equiv') == 'Content-Type') { + if (meta.attr('http-equiv') == 'Content-Type') elm = meta; - } }); if (!elm) { @@ -226,11 +214,10 @@ meta = nodes[i]; if (meta.attr('name') == name) { - if (value) { + if (value) meta.attr('content', value); - } else { + else meta.remove(); - } return; } @@ -249,11 +236,10 @@ // Add/update/delete link elm = headerFragment.getAll('link')[0]; if (elm && elm.attr('rel') == 'stylesheet') { - if (data.stylesheet) { + if (data.stylesheet) elm.attr('href', data.stylesheet); - } else { + else elm.remove(); - } } else if (data.stylesheet) { elm = new Node('link', 1); elm.attr({ @@ -318,17 +304,15 @@ function low(s) { return s.replace(/<\/?[A-Z]+/g, function(a) { return a.toLowerCase(); - }); - } + }) + }; // Ignore raw updated if we already have a head, this will fix issues with undo/redo keeping the head/foot separate - if (o.format == 'raw' && self.head) { + if (o.format == 'raw' && self.head) return; - } - if (o.source_view && ed.getParam('fullpage_hide_in_source_view')) { + if (o.source_view && ed.getParam('fullpage_hide_in_source_view')) return; - } // Parse out head, body and footer content = content.replace(/<(\/?)BODY/gi, '<$1body'); @@ -339,9 +323,8 @@ self.head = low(content.substring(0, startPos + 1)); endPos = content.indexOf('\n'; - } header += editor.getParam('fullpage_default_doctype', ''); header += '\n\n\n'; - if (value = editor.getParam('fullpage_default_title')) { + if (value = editor.getParam('fullpage_default_title')) header += '' + value + '\n'; - } - if (value = editor.getParam('fullpage_default_encoding')) { + if (value = editor.getParam('fullpage_default_encoding')) header += '\n'; - } - if (value = editor.getParam('fullpage_default_font_family')) { + if (value = editor.getParam('fullpage_default_font_family')) styles += 'font-family: ' + value + ';'; - } - if (value = editor.getParam('fullpage_default_font_size')) { + if (value = editor.getParam('fullpage_default_font_size')) styles += 'font-size: ' + value + ';'; - } - if (value = editor.getParam('fullpage_default_text_color')) { + if (value = editor.getParam('fullpage_default_text_color')) styles += 'color: ' + value + ';'; - } header += '\n\n'; @@ -420,9 +395,8 @@ _getContent : function(ed, o) { var self = this; - if (!o.source_view || !ed.getParam('fullpage_hide_in_source_view')) { + if (!o.source_view || !ed.getParam('fullpage_hide_in_source_view')) o.content = tinymce.trim(self.head) + '\n' + tinymce.trim(o.content) + '\n' + tinymce.trim(self.foot); - } } }); diff --git a/application/views/scripts/javascripts/vendor/tiny_mce/plugins/fullpage/js/fullpage.js b/application/views/scripts/javascripts/vendor/tiny_mce/plugins/fullpage/js/fullpage.js index 435a046e35..3f672ad3ba 100644 --- a/application/views/scripts/javascripts/vendor/tiny_mce/plugins/fullpage/js/fullpage.js +++ b/application/views/scripts/javascripts/vendor/tiny_mce/plugins/fullpage/js/fullpage.js @@ -11,7 +11,7 @@ (function() { tinyMCEPopup.requireLangPack(); - var defaultDocTypes = + var defaultDocTypes = 'XHTML 1.0 Transitional=,' + 'XHTML 1.0 Frameset=,' + 'XHTML 1.0 Strict=,' + @@ -20,7 +20,7 @@ 'HTML 4.01 Strict=,' + 'HTML 4.01 Frameset='; - var defaultEncodings = + var defaultEncodings = 'Western european (iso-8859-1)=iso-8859-1,' + 'Central European (iso-8859-2)=iso-8859-2,' + 'Unicode (UTF-8)=utf-8,' + @@ -31,7 +31,7 @@ 'Korean (iso-2022-kr)=iso-2022-kr,' + 'ASCII (us-ascii)=us-ascii'; - var defaultFontNames = 'Arial=arial,helvetica,sans-serif;Courier New=courier new,courier,monospace;Georgia=georgia,times new roman,times,serif;Tahoma=tahoma,arial,helvetica,sans-serif;Times New Roman=times new roman,times,serif;Verdana=verdana,arial,helvetica,sans-serif;Impact=impact,sans-serif;WingDings=wingdings'; + var defaultFontNames = 'Arial=arial,helvetica,sans-serif;Courier New=courier new,courier,monospace;Georgia=georgia,times new roman,times,serif;Tahoma=tahoma,arial,helvetica,sans-serif;Times New Roman=times new roman,times,serif;Verdana=verdana,arial,helvetica,sans-serif;Impact=impact;WingDings=wingdings'; var defaultFontSizes = '10px,11px,12px,13px,14px,15px,16px'; function setVal(id, value) { @@ -40,29 +40,26 @@ if (elm) { value = value || ''; - if (elm.nodeName == "SELECT") { + if (elm.nodeName == "SELECT") selectByValue(document.forms[0], id, value); - } else if (elm.type == "checkbox") { + else if (elm.type == "checkbox") elm.checked = !!value; - } else { + else elm.value = value; - } } - } + }; function getVal(id) { var elm = document.getElementById(id); - if (elm.nodeName == "SELECT") { + if (elm.nodeName == "SELECT") return elm.options[elm.selectedIndex].value; - } - if (elm.type == "checkbox") { + if (elm.type == "checkbox") return elm.checked; - } return elm.value; - } + }; window.FullPageDialog = { changedStyle : function() { @@ -72,11 +69,10 @@ setVal('fontsize', styles['font-size']); setVal('textcolor', styles['color']); - if (val = styles['background-image']) { + if (val = styles['background-image']) setVal('bgimage', val.replace(new RegExp("url\\('?([^']*)'?\\)", 'gi'), "$1")); - } else { + else setVal('bgimage', ''); - } setVal('bgcolor', styles['background-color']); @@ -95,21 +91,17 @@ styles['margin-left'] = val[3] || val[0] || ''; } - if (val = styles['margin-top']) { + if (val = styles['margin-top']) setVal('topmargin', val.replace(/px/, '')); - } - if (val = styles['margin-right']) { + if (val = styles['margin-right']) setVal('rightmargin', val.replace(/px/, '')); - } - if (val = styles['margin-bottom']) { + if (val = styles['margin-bottom']) setVal('bottommargin', val.replace(/px/, '')); - } - if (val = styles['margin-left']) { + if (val = styles['margin-left']) setVal('leftmargin', val.replace(/px/, '')); - } updateColor('bgcolor_pick', 'bgcolor'); updateColor('textcolor_pick', 'textcolor'); @@ -117,7 +109,7 @@ changedStyleProp : function() { var val, dom = tinyMCEPopup.editor.dom, styles = dom.parseStyle(getVal('style')); - + styles['font-face'] = getVal('fontface'); styles['font-size'] = getVal('fontsize'); styles['color'] = getVal('textcolor'); @@ -154,7 +146,7 @@ setVal('style', dom.serializeStyle(dom.parseStyle(dom.serializeStyle(styles)))); this.changedStyle(); }, - + update : function() { var data = {}; @@ -166,7 +158,7 @@ tinyMCEPopup.close(); } }; - + function init() { var form = document.forms[0], i, item, list, editor = tinyMCEPopup.editor; diff --git a/application/views/scripts/javascripts/vendor/tiny_mce/plugins/media/editor_plugin.js b/application/views/scripts/javascripts/vendor/tiny_mce/plugins/media/editor_plugin.js index 778d838e54..9ac42e0d21 100644 --- a/application/views/scripts/javascripts/vendor/tiny_mce/plugins/media/editor_plugin.js +++ b/application/views/scripts/javascripts/vendor/tiny_mce/plugins/media/editor_plugin.js @@ -1 +1 @@ -(function(){var a=tinymce.explode("id,name,style,align,class,hspace,vspace,bgcolor,type"),c=tinymce.makeMap(a.join(",")),d=a.concat(tinymce.explode("width, height")),b=tinymce.makeMap(d.join(",")),h=tinymce.html.Node,g,j,i=tinymce.util.JSON;g=[["Flash","d27cdb6e-ae6d-11cf-96b8-444553540000","application/x-shockwave-flash","http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"],["ShockWave","166b1bca-3f9c-11cf-8075-444553540000","application/x-director","http://download.macromedia.com/pub/shockwave/cabs/director/sw.cab#version=8,5,1,0"],["WindowsMedia","6bf52a52-394a-11d3-b153-00c04f79faa6,22d6f312-b0f6-11d0-94ab-0080c74c7e95,05589fa1-c356-11ce-bf01-00aa0055595a","application/x-mplayer2","http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=5,1,52,701"],["QuickTime","02bf25d5-8c17-4b23-bc80-d3488abddc6b","video/quicktime","http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0"],["RealMedia","cfcdaa03-8be4-11cf-b84b-0020afbbccfa","audio/x-pn-realaudio-plugin","http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"],["Java","8ad9c840-044e-11d1-b3e9-00805f499d93","application/x-java-applet","http://java.sun.com/products/plugin/autodl/jinstall-1_5_0-windows-i586.cab#Version=1,5,0,0"],["Silverlight","dfeaf541-f3e1-4c24-acac-99c30715084a","application/x-silverlight-2"],["Iframe"],["Video"],["EmbeddedAudio"],["Audio"],["Object"]];function f(k){return typeof(k)=="string"?k.replace(/[^0-9%]/g,""):k}function e(m){var k,l;if(m&&!m.splice){k=[];for(l=0;true;l++){if(m[l]){k[l]=m[l]}else{break}}return k}return m}tinymce.create("tinymce.plugins.MediaPlugin",{init:function(o,k){var s=this,m={},n,q,r,l;function p(t){return t&&t.nodeName==="IMG"&&o.dom.hasClass(t,"mceItemMedia")}s.editor=o;s.url=k;j="";for(n=0;n0){N+=(N?"&":"")+O+"="+escape(P)}});if(N.length){F.params.flashvars=N}K=q.getParam("flash_video_player_params",{allowfullscreen:true,allowscriptaccess:true});tinymce.each(K,function(P,O){F.params[O]=""+P})}}function x(K,J,I,L){G=new h("object",1).attr({id:K.attr("id"),width:f(K.attr("width")),height:f(K.attr("height")),style:J});tinymce.each(I,function(N){var O=L[N];if(N=="class"&&O){O=O.replace(/mceItem.+ ?/g,"")}if(O&&N!="type"){G.attr(N,O)}});for(var n in L.params){var M;M=new h("param",1);M.shortEnded=true;y=L.params[n];if(n==="src"&&r.name==="WindowsMedia"){n="url"}M.attr({name:n,value:y});G.append(M)}if(L.object_html){y=new h("#text",3);y.raw=true;y.value=L.object_html;G.append(y)}if(D){D.append(G)}return G}F=z.attr("data-mce-json");if(!F){return}F=i.parse(F);r=this.getType(z.attr("class"));C=z.attr("data-mce-style");if(!C){C=z.attr("style");if(C){C=q.dom.serializeStyle(q.dom.parseStyle(C,"img"))}}F.width=z.attr("width")||F.width;F.height=z.attr("height")||F.height;if(r.name==="Iframe"){A=new h("iframe",1);tinymce.each(d,function(n){var I=z.attr(n);if(n=="class"&&I){I=I.replace(/mceItem.+ ?/g,"")}if(I&&I.length>0){A.attr(n,I)}});for(H in F.params){A.attr(H,F.params[H])}A.attr({style:C,src:F.params.src});z.replace(A);return}if(this.editor.settings.media_use_script){A=new h("script",1).attr("type","text/javascript");y=new h("#text",3);y.value="write"+r.name+"("+i.serialize(tinymce.extend(F.params,{width:z.attr("width"),height:z.attr("height")}))+");";A.append(y);z.replace(A);return}if(r.name==="Video"&&F.video.sources[0]){D=new h("video",1).attr(tinymce.extend({id:z.attr("id"),width:f(z.attr("width")),height:f(z.attr("height")),style:C},F.video.attrs));if(F.video.attrs){m=F.video.attrs.poster}l=F.video.sources=e(F.video.sources);for(B=0;B0){O+=(O?"&":"")+P+"="+escape(Q)}});if(O.length){G.params.flashvars=O}L=p.getParam("flash_video_player_params",{allowfullscreen:true,allowscriptaccess:true});tinymce.each(L,function(Q,P){G.params[P]=""+Q})}}G=z.attr("data-mce-json");if(!G){return}G=h.parse(G);q=this.getType(z.attr("class"));B=z.attr("data-mce-style");if(!B){B=z.attr("style");if(B){B=p.dom.serializeStyle(p.dom.parseStyle(B,"img"))}}G.width=z.attr("width")||G.width;G.height=z.attr("height")||G.height;if(q.name==="Iframe"){x=new f("iframe",1);tinymce.each(b,function(n){var J=z.attr(n);if(n=="class"&&J){J=J.replace(/mceItem.+ ?/g,"")}if(J&&J.length>0){x.attr(n,J)}});for(I in G.params){x.attr(I,G.params[I])}x.attr({style:B,src:G.params.src});z.replace(x);return}if(this.editor.settings.media_use_script){x=new f("script",1).attr("type","text/javascript");y=new f("#text",3);y.value="write"+q.name+"("+h.serialize(tinymce.extend(G.params,{width:z.attr("width"),height:z.attr("height")}))+");";x.append(y);z.replace(x);return}if(q.name==="Video"&&G.video.sources[0]){C=new f("video",1).attr(tinymce.extend({id:z.attr("id"),width:e(z.attr("width")),height:e(z.attr("height")),style:B},G.video.attrs));if(G.video.attrs){l=G.video.attrs.poster}k=G.video.sources=c(G.video.sources);for(A=0;A 0) { + if (value.length > 0) flashVarsOutput += (flashVarsOutput ? '&' : '') + name + '=' + escape(value); - } }); - if (flashVarsOutput.length) { + if (flashVarsOutput.length) data.params.flashvars = flashVarsOutput; - } params = editor.getParam('flash_video_player_params', { allowfullscreen: true, @@ -390,62 +373,11 @@ data.params[name] = "" + value; }); } - } - - function createObject (node, style, rootAttributes, data) { - object = new Node('object', 1).attr({ - id : node.attr('id'), - width: normalizeSize(node.attr('width')), - height: normalizeSize(node.attr('height')), - style : style - }); - - tinymce.each(rootAttributes, function(name) { - var value = data[name]; - - if (name == 'class' && value) { - value = value.replace(/mceItem.+ ?/g, ''); - } - - if (value && name != 'type') { - object.attr(name, value); - } - }); - - for (var name in data.params) { - var param; - param = new Node('param', 1); - param.shortEnded = true; - value = data.params[name]; - - // Windows media needs to use url instead of src for the media URL - if (name === 'src' && typeItem.name === 'WindowsMedia') { - name = 'url'; - } - - param.attr({name: name, value: value}); - object.append(param); - } - - if (data.object_html) { - value = new Node('#text', 3); - value.raw = true; - value.value = data.object_html; - object.append(value); - } - - // Append object to video element if it exists - if (video) { - video.append(object); - } - - return object; - } + }; data = node.attr('data-mce-json'); - if (!data) { + if (!data) return; - } data = JSON.parse(data); typeItem = this.getType(node.attr('class')); @@ -454,9 +386,8 @@ if (!style) { style = node.attr('style'); - if (style) { + if (style) style = editor.dom.serializeStyle(editor.dom.parseStyle(style, 'img')); - } } // Use node width/height to override the data width/height when the placeholder is resized @@ -470,18 +401,15 @@ tinymce.each(rootAttributes, function(name) { var value = node.attr(name); - if (name == 'class' && value) { + if (name == 'class' && value) value = value.replace(/mceItem.+ ?/g, ''); - } - if (value && value.length > 0) { + if (value && value.length > 0) replacement.attr(name, value); - } }); - for (name in data.params) { + for (name in data.params) replacement.attr(name, data.params[name]); - } replacement.attr({ style: style, @@ -520,15 +448,13 @@ }, data.video.attrs)); // Get poster source and use that for flash fallback - if (data.video.attrs) { + if (data.video.attrs) posterSrc = data.video.attrs.poster; - } sources = data.video.sources = toArray(data.video.sources); for (i = 0; i < sources.length; i++) { - if (/\.mp4$/.test(sources[i].src)) { + if (/\.mp4$/.test(sources[i].src)) mp4Source = sources[i].src; - } } if (!sources[0].type) { @@ -546,9 +472,8 @@ if (mp4Source) { addPlayer(mp4Source, posterSrc); typeItem = self.getType('flash'); - } else { + } else data.params.src = ''; - } } // Add HTML5 audio element @@ -562,9 +487,8 @@ }, data.video.attrs)); // Get poster source and use that for flash fallback - if (data.video.attrs) { + if (data.video.attrs) posterSrc = data.video.attrs.poster; - } sources = data.video.sources = toArray(data.video.sources); if (!sources[0].type) { @@ -592,14 +516,12 @@ type: node.attr('type') }); - for (name in data.params) { + for (name in data.params) embed.attr(name, data.params[name]); - } tinymce.each(rootAttributes, function(name) { - if (data[name] && name != 'type') { + if (data[name] && name != 'type') embed.attr(name, data[name]); - } }); data.params.src = ''; @@ -608,15 +530,43 @@ // Do we have a params src then we can generate object if (data.params.src) { // Is flv movie add player for it - if (/\.flv$/i.test(data.params.src)) { + if (/\.flv$/i.test(data.params.src)) addPlayer(data.params.src, ''); - } - if (args && args.force_absolute) { + if (args && args.force_absolute) data.params.src = editor.documentBaseURI.toAbsolute(data.params.src); - } - object = createObject(node, style, rootAttributes, data, video); + // Create new object element + object = new Node('object', 1).attr({ + id : node.attr('id'), + width: normalizeSize(node.attr('width')), + height: normalizeSize(node.attr('height')), + style : style + }); + + tinymce.each(rootAttributes, function(name) { + var value = data[name]; + + if (name == 'class' && value) + value = value.replace(/mceItem.+ ?/g, ''); + + if (value && name != 'type') + object.attr(name, value); + }); + + // Add params + for (name in data.params) { + param = new Node('param', 1); + param.shortEnded = true; + value = data.params[name]; + + // Windows media needs to use url instead of src for the media URL + if (name === 'src' && typeItem.name === 'WindowsMedia') + name = 'url'; + + param.attr({name: name, value: value}); + object.append(param); + } // Setup add type and classid if strict is disabled if (this.editor.getParam('media_strict', true)) { @@ -625,12 +575,10 @@ type: typeItem.mimes[0] }); } else { - if(typeItem.clsids[0]) { - object.attr({ - classid: "clsid:" + typeItem.clsids[0], - codebase: typeItem.codebase - }); - } + object.attr({ + classid: "clsid:" + typeItem.clsids[0], + codebase: typeItem.codebase + }); embed = new Node('embed', 1); embed.shortEnded = true; @@ -642,22 +590,28 @@ type: typeItem.mimes[0] }); - for (name in data.params) { + for (name in data.params) embed.attr(name, data.params[name]); - } tinymce.each(rootAttributes, function(name) { - if (data[name] && name != 'type') { + if (data[name] && name != 'type') embed.attr(name, data[name]); - } }); + object.append(embed); } - } else if (typeItem.name === 'Object') { - // Remove data.params.src since not in the original object - delete data.params.src; - object = createObject(node, style, rootAttributes, data, video); + // Insert raw HTML + if (data.object_html) { + value = new Node('#text', 3); + value.raw = true; + value.value = data.object_html; + object.append(value); + } + + // Append object to video element if it exists + if (video) + video.append(object); } if (video) { @@ -681,11 +635,10 @@ } var n = video || audio || object || embed; - if (n) { + if (n) node.replace(n); - } else { + else node.remove(); - } }, /** @@ -709,7 +662,7 @@ inner: true, validate: false }).serialize(node); - } + }; function lookupAttribute(o, attr) { return lookup[(o.attr(attr) || '').toLowerCase()]; @@ -721,19 +674,16 @@ } // If node isn't in document - if (!node.parent) { + if (!node.parent) return; - } // Handle media scripts - if (node.name === 'script') { - if (node.firstChild) { + if (node.name === 'script') { + if (node.firstChild) matches = scriptRegExp.exec(node.firstChild.value); - } - if (!matches) { + if (!matches) return; - } type = matches[1]; data = {video : {}, params : JSON.parse(matches[2])}; @@ -766,14 +716,12 @@ // Get all video attributes attrs = data.video.attrs; - for (name in video.attributes.map) { + for (name in video.attributes.map) attrs[name] = video.attributes.map[name]; - } source = node.attr('src'); - if (source) { + if (source) data.video.sources.push({src : urlConverter.call(urlConverterScope, source, 'src', node.name)}); - } // Get all sources sources = video.getAll("source"); @@ -788,9 +736,8 @@ } // Convert the poster URL - if (attrs.poster) { + if (attrs.poster) attrs.poster = urlConverter.call(urlConverterScope, attrs.poster, 'poster', node.name); - } } // Object element @@ -800,9 +747,8 @@ } // Embed element - if (node.name === 'embed') { + if (node.name === 'embed') embed = node; - } // Iframe element if (node.name === 'iframe') { @@ -812,6 +758,8 @@ if (object) { // Get width/height + width = width || object.attr('width'); + height = height || object.attr('height'); style = style || object.attr('style'); id = id || object.attr('id'); hspace = hspace || object.attr('hspace'); @@ -819,23 +767,17 @@ align = align || object.attr('align'); bgcolor = bgcolor || object.attr('bgcolor'); data.name = object.attr('name'); - data["class"] = object.attr('class'); // Get all object params params = object.getAll("param"); - for (i = 0; i < params.length; i++) { param = params[i]; name = param.remove().attr('name'); - if (!subExcludedAttrs[name]) { + if (!excludedAttrs[name]) data.params[name] = param.attr('value'); - } } - width = width || object.attr('width') || data.params.width; - height = height || object.attr('height') || data.params.height; - data.params.src = data.params.src || object.attr('data'); } @@ -852,11 +794,9 @@ // Get all embed attributes for (name in embed.attributes.map) { - if (!excludedAttrs[name] && !data.params[name]) { + if (!excludedAttrs[name] && !data.params[name]) data.params[name] = embed.attributes.map[name]; - } } - } if (iframe) { @@ -876,9 +816,8 @@ // Get all iframe attributes for (name in iframe.attributes.map) { - if (!excludedAttrs[name] && !data.params[name]) { + if (!excludedAttrs[name] && !data.params[name]) data.params[name] = iframe.attributes.map[name]; - } } } @@ -889,25 +828,22 @@ } // Convert the URL to relative/absolute depending on configuration - if (data.params.src) { + if (data.params.src) data.params.src = urlConverter.call(urlConverterScope, data.params.src, 'src', 'object'); - } if (video) { - if (node.name === 'video') { + if (node.name === 'video') type = lookup.video.name; - } else if (node.name === 'audio') { + else if (node.name === 'audio') type = lookup.audio.name; - } } - if (embed && !type) { + if (object && !type) + type = (lookupAttribute(object, 'clsid') || lookupAttribute(object, 'classid') || lookupAttribute(object, 'type') || {}).name; + + if (embed && !type) type = (lookupAttribute(embed, 'type') || lookupExtension(data.params.src) || {}).name; - } - if (object && !type) { - type = (lookupAttribute(object, 'clsid') || lookupAttribute(object, 'classid') || lookupAttribute(object, 'type') || {name: 'Object'}).name; - } // for embedded audio we preserve the original specified type if (embed && type == 'EmbeddedAudio') { data.params.type = embed.attr('type'); @@ -916,25 +852,24 @@ // Replace the video/object/embed element with a placeholder image containing the data node.replace(img); - if (embed) { + // Remove embed + if (embed) embed.remove(); - } // Serialize the inner HTML of the object element if (object) { html = getInnerHTML(object.remove()); - if (html) { + + if (html) data.object_html = html; - } } // Serialize the inner HTML of the video element if (video) { html = getInnerHTML(video.remove()); - if (html) { + if (html) data.video_html = html; - } } data.hspace = hspace; diff --git a/application/views/scripts/javascripts/vendor/tiny_mce/plugins/noneditable/editor_plugin.js b/application/views/scripts/javascripts/vendor/tiny_mce/plugins/noneditable/editor_plugin.js index 9da0e2bd40..da411ebc09 100644 --- a/application/views/scripts/javascripts/vendor/tiny_mce/plugins/noneditable/editor_plugin.js +++ b/application/views/scripts/javascripts/vendor/tiny_mce/plugins/noneditable/editor_plugin.js @@ -1 +1 @@ -(function(){var h=tinymce.dom.TreeWalker;var d="contenteditable",c="data-mce-"+d;var i=tinymce.VK;var e,j,b;function g(t){var p=t.dom,v=t.selection,u="mce_noneditablecaret",x="\uFEFF",m=t.getParam("noneditable_prevent_delete");function s(z){var y;if(z.nodeType===1){y=z.getAttribute(c);if(y&&y!=="inherit"){return y}y=z.contentEditable;if(y!=="inherit"){return y}}return null}function l(y){var z;while(y){z=s(y);if(z){return z==="false"?y:null}y=y.parentNode}}function r(y){while(y){if(y.id===u){return y}y=y.parentNode}}function q(y){var z;if(y){z=new h(y,y);for(y=z.current();y;y=z.next()){if(y.nodeType===3){return y}}}}function k(B,A){var y,z;if(s(B)==="false"){if(p.isBlock(B)){v.select(B);return}}z=p.createRng();if(s(B)==="true"){if(!B.firstChild){B.appendChild(t.getDoc().createTextNode("\u00a0"))}B=B.firstChild;A=true}y=p.create("span",{id:u,"data-mce-bogus":true},x);if(A){B.parentNode.insertBefore(y,B)}else{p.insertAfter(y,B)}z.setStart(y.firstChild,1);z.collapse(true);v.setRng(z);return y}function o(y){var C,A,B,z;if(y){z=v.getRng(true);z.setStartBefore(y);z.setEndBefore(y);C=q(y);if(C&&C.nodeValue.charAt(0)==x){C=C.deleteData(0,1)}p.remove(y,true);v.setRng(z)}else{A=r(v.getStart());while((y=p.get(u))&&y!==B){if(A!==y){C=q(y);if(C&&C.nodeValue.charAt(0)==x){C=C.deleteData(0,1)}p.remove(y,true)}B=y}}}function w(){var y,C,A,z,B;function D(G,I){var F,K,J,H,E;F=z.startContainer;K=z.startOffset;if(F.nodeType==3){E=F.nodeValue.length;if((K>0&&K0?K-1:K;F=F.childNodes[L];if(F.hasChildNodes()){F=F.firstChild}}else{return !I?G:null}}J=new h(F,G);while(H=J[I?"prev":"next"]()){if(H.nodeType===3&&H.nodeValue.length>0){return}else{if(s(H)==="true"){return H}}}return G}o();A=v.isCollapsed();y=l(v.getStart());C=l(v.getEnd());if(y||C){z=v.getRng(true);if(A){y=y||C;if(D(y,true)){B=D(y,true);k(B,true)}else{if(D(y,false)){B=D(y,false);k(B,false)}else{v.select(y)}}}else{z=v.getRng(true);if(y){z.setStartBefore(y)}if(C){z.setEndAfter(C)}v.setRng(z)}}}function n(D,Q){var G=Q.keyCode,S,J,y,F,A,I=false,z;function B(U,T){while(U=U[T?"previousSibling":"nextSibling"]){if(U.nodeType!==3||U.nodeValue.length>0){return U}}}function K(T,U){v.select(T);v.collapse(U)}function P(X){var W,V,Z,U;function T(ab){var aa=V;while(aa){if(aa===ab){return}aa=aa.parentNode}p.remove(ab);w()}function Y(){var ab,ac,aa=D.schema.getNonEmptyElements();ac=new tinymce.dom.TreeWalker(V,D.getBody());while(ab=(X?ac.prev():ac.next())){if(aa[ab.nodeName.toLowerCase()]){break}if(ab.nodeType===3&&tinymce.trim(ab.nodeValue).length>0){break}if(s(ab)==="false"){if(!m){T(ab)}return true}}if(l(ab)){return true}return false}W=v.getRng(true);V=W.startContainer;Z=W.startOffset;V=r(V)||V;if(v.isCollapsed()){if(U=l(V)){T(U);return false}if(V.nodeType==3&&(X?Z>0:Z124)&&G!=i.DELETE&&G!=i.BACKSPACE){if((tinymce.isMac?Q.metaKey:Q.ctrlKey)&&(G==67||G==88||G==86)){return}Q.preventDefault();if(G==i.LEFT||G==i.RIGHT){var C=G==i.LEFT;if(D.dom.isBlock(S)){var H=C?S.previousSibling:S.nextSibling;var N=new h(H,H);var L=C?N.prev():N.next();K(L,!C)}else{K(S,C)}}}else{if(G==i.LEFT||G==i.RIGHT||G==i.BACKSPACE||G==i.DELETE){J=r(y);if(J){O(G,J,Q)}if((G==i.BACKSPACE||G==i.DELETE)&&!P(G==i.BACKSPACE)){Q.preventDefault();return false}if(m&&I){var R=confirm(D.getLang("noneditable.confirm_delete"));if(!R){Q.preventDefault();return false}}}}}t.onMouseUp.addToTop(w);t.onMouseDown.addToTop(w);t.onKeyDown.addToTop(n);t.onKeyUp.addToTop(w)}function a(k){return" "+tinymce.trim(k.getParam("noneditable_editable_class","mceEditable"))+" "}function f(k){return" "+tinymce.trim(k.getParam("noneditable_noneditable_class","mceNonEditable"))+" "}tinymce.PluginManager.requireLangPack("noneditable");tinymce.create("tinymce.plugins.NonEditablePlugin",{init:function(l){function k(n,o){var p=b.length,q=o.content,m=tinymce.trim(j);if(o.format=="raw"){return}while(p--){q=q.replace(b[p],function(t){var s=arguments,r=s[s.length-2];if(r>0&&q.charAt(r-1)=='"'){return t}return''+n.dom.encode(typeof(s[1])==="string"?s[1]:s[0])+""})}o.content=q}e=a(l);j=f(l);b=l.getParam("noneditable_regexp");if(b&&!b.length){b=[b]}l.onPreInit.add(function(){g(l);if(b){l.selection.onBeforeSetContent.add(k);l.onBeforeSetContent.add(k)}l.parser.addAttributeFilter("class",function(m){var n=m.length,o,p;while(n--){p=m[n];o=" "+p.attr("class")+" ";if(o.indexOf(e)!==-1){p.attr(c,"true")}else{if(o.indexOf(j)!==-1){p.attr(c,"false")}}}});l.serializer.addAttributeFilter(c,function(m){var n=m.length,o;while(n--){o=m[n];if(b&&o.attr("data-mce-content")){o.name="#text";o.type=3;o.raw=true;o.value=o.attr("data-mce-content")}else{o.attr(d,null);o.attr(c,null)}}});l.parser.addAttributeFilter(d,function(m){var n=m.length,o;while(n--){o=m[n];o.attr(c,o.attr(d));o.attr(d,null)}})})},getInfo:function(){return{longname:"Non editable elements",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/noneditable",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.PluginManager.add("noneditable",tinymce.plugins.NonEditablePlugin)})(); \ No newline at end of file +(function(){var c=tinymce.dom.TreeWalker;var a="contenteditable",d="data-mce-"+a;var e=tinymce.VK;function b(n){var j=n.dom,p=n.selection,r,o="mce_noneditablecaret",r="\uFEFF";function m(t){var s;if(t.nodeType===1){s=t.getAttribute(d);if(s&&s!=="inherit"){return s}s=t.contentEditable;if(s!=="inherit"){return s}}return null}function g(s){var t;while(s){t=m(s);if(t){return t==="false"?s:null}s=s.parentNode}}function l(s){while(s){if(s.id===o){return s}s=s.parentNode}}function k(s){var t;if(s){t=new c(s,s);for(s=t.current();s;s=t.next()){if(s.nodeType===3){return s}}}}function f(v,u){var s,t;if(m(v)==="false"){if(j.isBlock(v)){p.select(v);return}}t=j.createRng();if(m(v)==="true"){if(!v.firstChild){v.appendChild(n.getDoc().createTextNode("\u00a0"))}v=v.firstChild;u=true}s=j.create("span",{id:o,"data-mce-bogus":true},r);if(u){v.parentNode.insertBefore(s,v)}else{j.insertAfter(s,v)}t.setStart(s.firstChild,1);t.collapse(true);p.setRng(t);return s}function i(s){var v,t,u;if(s){rng=p.getRng(true);rng.setStartBefore(s);rng.setEndBefore(s);v=k(s);if(v&&v.nodeValue.charAt(0)==r){v=v.deleteData(0,1)}j.remove(s,true);p.setRng(rng)}else{t=l(p.getStart());while((s=j.get(o))&&s!==u){if(t!==s){v=k(s);if(v&&v.nodeValue.charAt(0)==r){v=v.deleteData(0,1)}j.remove(s,true)}u=s}}}function q(){var s,w,u,t,v;function x(B,D){var A,F,E,C,z;A=t.startContainer;F=t.startOffset;if(A.nodeType==3){z=A.nodeValue.length;if((F>0&&F0?F-1:F;A=A.childNodes[G];if(A.hasChildNodes()){A=A.firstChild}}else{return !D?B:null}}E=new c(A,B);while(C=E[D?"prev":"next"]()){if(C.nodeType===3&&C.nodeValue.length>0){return}else{if(m(C)==="true"){return C}}}return B}i();u=p.isCollapsed();s=g(p.getStart());w=g(p.getEnd());if(s||w){t=p.getRng(true);if(u){s=s||w;var y=p.getStart();if(v=x(s,true)){f(v,true)}else{if(v=x(s,false)){f(v,false)}else{p.select(s)}}}else{t=p.getRng(true);if(s){t.setStartBefore(s)}if(w){t.setEndAfter(w)}p.setRng(t)}}}function h(z,B){var F=B.keyCode,x,C,D,v;function u(H,G){while(H=H[G?"previousSibling":"nextSibling"]){if(H.nodeType!==3||H.nodeValue.length>0){return H}}}function y(G,H){p.select(G);p.collapse(H)}function t(K){var J,I,M,H;function G(O){var N=I;while(N){if(N===O){return}N=N.parentNode}j.remove(O);q()}function L(){var O,P,N=z.schema.getNonEmptyElements();P=new tinymce.dom.TreeWalker(I,z.getBody());while(O=(K?P.prev():P.next())){if(N[O.nodeName.toLowerCase()]){break}if(O.nodeType===3&&tinymce.trim(O.nodeValue).length>0){break}if(m(O)==="false"){G(O);return true}}if(g(O)){return true}return false}if(p.isCollapsed()){J=p.getRng(true);I=J.startContainer;M=J.startOffset;I=l(I)||I;if(H=g(I)){G(H);return false}if(I.nodeType==3&&(K?M>0:M124)&&F!=e.DELETE&&F!=e.BACKSPACE){if((tinymce.isMac?B.metaKey:B.ctrlKey)&&(F==67||F==88||F==86)){return}B.preventDefault();if(F==e.LEFT||F==e.RIGHT){var w=F==e.LEFT;if(z.dom.isBlock(x)){var A=w?x.previousSibling:x.nextSibling;var s=new c(A,A);var E=w?s.prev():s.next();y(E,!w)}else{y(x,w)}}}else{if(F==e.LEFT||F==e.RIGHT||F==e.BACKSPACE||F==e.DELETE){C=l(D);if(C){if(F==e.LEFT||F==e.BACKSPACE){x=u(C,true);if(x&&m(x)==="false"){B.preventDefault();if(F==e.LEFT){y(x,true)}else{j.remove(x);return}}else{i(C)}}if(F==e.RIGHT||F==e.DELETE){x=u(C);if(x&&m(x)==="false"){B.preventDefault();if(F==e.RIGHT){y(x,false)}else{j.remove(x);return}}else{i(C)}}}if((F==e.BACKSPACE||F==e.DELETE)&&!t(F==e.BACKSPACE)){B.preventDefault();return false}}}}n.onMouseDown.addToTop(function(s,u){var t=s.selection.getNode();if(m(t)==="false"&&t==u.target){q()}});n.onMouseUp.addToTop(q);n.onKeyDown.addToTop(h);n.onKeyUp.addToTop(q)}tinymce.create("tinymce.plugins.NonEditablePlugin",{init:function(i,k){var h,g,j;function f(m,n){var o=j.length,p=n.content,l=tinymce.trim(g);if(n.format=="raw"){return}while(o--){p=p.replace(j[o],function(s){var r=arguments,q=r[r.length-2];if(q>0&&p.charAt(q-1)=='"'){return s}return''+m.dom.encode(typeof(r[1])==="string"?r[1]:r[0])+""})}n.content=p}h=" "+tinymce.trim(i.getParam("noneditable_editable_class","mceEditable"))+" ";g=" "+tinymce.trim(i.getParam("noneditable_noneditable_class","mceNonEditable"))+" ";j=i.getParam("noneditable_regexp");if(j&&!j.length){j=[j]}i.onPreInit.add(function(){b(i);if(j){i.selection.onBeforeSetContent.add(f);i.onBeforeSetContent.add(f)}i.parser.addAttributeFilter("class",function(l){var m=l.length,n,o;while(m--){o=l[m];n=" "+o.attr("class")+" ";if(n.indexOf(h)!==-1){o.attr(d,"true")}else{if(n.indexOf(g)!==-1){o.attr(d,"false")}}}});i.serializer.addAttributeFilter(d,function(l,m){var n=l.length,o;while(n--){o=l[n];if(j&&o.attr("data-mce-content")){o.name="#text";o.type=3;o.raw=true;o.value=o.attr("data-mce-content")}else{o.attr(a,null);o.attr(d,null)}}});i.parser.addAttributeFilter(a,function(l,m){var n=l.length,o;while(n--){o=l[n];o.attr(d,o.attr(a));o.attr(a,null)}})})},getInfo:function(){return{longname:"Non editable elements",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/noneditable",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.PluginManager.add("noneditable",tinymce.plugins.NonEditablePlugin)})(); \ No newline at end of file diff --git a/application/views/scripts/javascripts/vendor/tiny_mce/plugins/noneditable/editor_plugin_src.js b/application/views/scripts/javascripts/vendor/tiny_mce/plugins/noneditable/editor_plugin_src.js index d561b7d1a5..a18bcd786a 100644 --- a/application/views/scripts/javascripts/vendor/tiny_mce/plugins/noneditable/editor_plugin_src.js +++ b/application/views/scripts/javascripts/vendor/tiny_mce/plugins/noneditable/editor_plugin_src.js @@ -12,12 +12,9 @@ var TreeWalker = tinymce.dom.TreeWalker; var externalName = 'contenteditable', internalName = 'data-mce-' + externalName; var VK = tinymce.VK; - var editClass, nonEditClass, nonEditableRegExps; function handleContentEditableSelection(ed) { - var dom = ed.dom, selection = ed.selection, caretContainerId = 'mce_noneditablecaret', invisibleChar = '\uFEFF', - nondeletable = ed.getParam('noneditable_prevent_delete'); - + var dom = ed.dom, selection = ed.selection, invisibleChar, caretContainerId = 'mce_noneditablecaret', invisibleChar = '\uFEFF'; // Returns the content editable state of a node "true/false" or null function getContentEditable(node) { @@ -122,7 +119,7 @@ // Removes any caret container except the one we might be in function removeCaretContainer(caretContainer) { - var child, currentCaretContainer, lastContainer, rng; + var child, currentCaretContainer, lastContainer; if (caretContainer) { rng = selection.getRng(true); @@ -216,13 +213,11 @@ // If it's a caret selection then look left/right to see if we need to move the caret out side or expand if (isCollapsed) { nonEditableStart = nonEditableStart || nonEditableEnd; - - if (hasSideContent(nonEditableStart, true)) { - element = hasSideContent(nonEditableStart, true); + var start = selection.getStart(); + if (element = hasSideContent(nonEditableStart, true)) { // We have no contents to the left of the caret then insert a caret container before the noneditable element insertCaretContainerOrExpandToBlock(element, true); - } else if (hasSideContent(nonEditableStart, false)) { - element = hasSideContent(nonEditableStart, false); + } else if (element = hasSideContent(nonEditableStart, false)) { // We have no contents to the right of the caret then insert a caret container after the noneditable element insertCaretContainerOrExpandToBlock(element, false); } else { @@ -248,8 +243,7 @@ }; function handleKey(ed, e) { - var keyCode = e.keyCode, nonEditableParent, caretContainer, startElement, endElement, htmlSelection, - selectionContainsNonEditable = false, selectedRegion; + var keyCode = e.keyCode, nonEditableParent, caretContainer, startElement, endElement; function getNonEmptyTextNodeSibling(node, prev) { while (node = node[prev ? 'previousSibling' : 'nextSibling']) { @@ -299,9 +293,7 @@ // Found non editable node if (getContentEditable(node) === "false") { - if (!nondeletable) - removeNodeIfNotParent(node); - + removeNodeIfNotParent(node); return true; } } @@ -314,12 +306,12 @@ return false; } - rng = selection.getRng(true); - container = rng.startContainer; - offset = rng.startOffset; - container = getParentCaretContainer(container) || container; - if (selection.isCollapsed()) { + rng = selection.getRng(true); + container = rng.startContainer; + offset = rng.startOffset; + container = getParentCaretContainer(container) || container; + // Is in noneditable parent if (nonEditableParent = getNonEditableParent(container)) { removeNodeIfNotParent(nonEditableParent); @@ -342,79 +334,14 @@ } } - // Is in noneditable parent - if (getNonEditableParent(container)) { - nonEditableParent = getNonEditableParent(container); - removeNodeIfNotParent(nonEditableParent); - return false; - } - return true; - } - - /** - * handleDirectionalStroke handles when the user presses a button within a caret container, and - * make sure the direction of the cursor or of the deletion is within the - * user expectations. - * - * @param {string} keyCode is the current keycode - * @param {object} caretContainer is the caretContainer - * @param {string} side left (backspace and left arrow) or right (delete and right arrow) - * @param {object} e is the currenlty handled event - * @return {null} - */ - function handleDirectionalStroke(keyCode, caretContainer, e) { - var nonEditableParent; - var side = (keyCode === VK.LEFT) || (keyCode === VK.BACKSPACE) ? 'left' : 'right'; - var arrow = side === 'left' ? VK.LEFT : VK.RIGHT; - var action = side === 'left' ? VK.BACKSPACE : VK.DELETE; - var next = side === 'left' ? true : false; - var caret = selection.getRng(true); - - - if (keyCode === arrow || keyCode === action) { - nonEditableParent = getNonEmptyTextNodeSibling(caretContainer, next); - - if (nonEditableParent && getContentEditable(nonEditableParent) === "false") { - - if (keyCode === arrow) { - positionCaretOnElement(nonEditableParent, next); - } - - if (keyCode === action && (caretContainer.innerHTML === invisibleChar || !tinymce.trim(caretContainer.innerText || caretContainer.textContent)) ) { - e.preventDefault(); - positionCaretOnElement(nonEditableParent, next); - if (!nondeletable) { - dom.remove(nonEditableParent); - return; - } - } - - } else if (!nondeletable) { - removeCaretContainer(caretContainer); - } - - } } - - startElement = selection.getStart(); + startElement = selection.getStart() endElement = selection.getEnd(); // Disable all key presses in contentEditable=false except delete or backspace nonEditableParent = getNonEditableParent(startElement) || getNonEditableParent(endElement); - - if (nondeletable && !selection.isCollapsed()) { - var rng = selection.getRng(true); - var rngContents = rng.cloneContents(); - - var selectionContainsNonEditable = false; - tinymce.walk(rngContents, function(n) { - selectionContainsNonEditable = getContentEditable(n) === 'false'; - return !selectionContainsNonEditable; - }, 'childNodes'); - } - if (nonEditableParent && (keyCode < 112 || keyCode > 124) && keyCode != VK.DELETE && keyCode != VK.BACKSPACE) { // Is Ctrl+c, Ctrl+v or Ctrl+x then use default browser behavior if ((tinymce.isMac ? e.metaKey : e.ctrlKey) && (keyCode == 67 || keyCode == 88 || keyCode == 86)) { @@ -441,42 +368,68 @@ if (keyCode == VK.LEFT || keyCode == VK.RIGHT || keyCode == VK.BACKSPACE || keyCode == VK.DELETE) { caretContainer = getParentCaretContainer(startElement); if (caretContainer) { - handleDirectionalStroke(keyCode, caretContainer, e); + // Arrow left or backspace + if (keyCode == VK.LEFT || keyCode == VK.BACKSPACE) { + nonEditableParent = getNonEmptyTextNodeSibling(caretContainer, true); + + if (nonEditableParent && getContentEditable(nonEditableParent) === "false") { + e.preventDefault(); + + if (keyCode == VK.LEFT) { + positionCaretOnElement(nonEditableParent, true); + } else { + dom.remove(nonEditableParent); + return; + } + } else { + removeCaretContainer(caretContainer); + } + } + + // Arrow right or delete + if (keyCode == VK.RIGHT || keyCode == VK.DELETE) { + nonEditableParent = getNonEmptyTextNodeSibling(caretContainer); + + if (nonEditableParent && getContentEditable(nonEditableParent) === "false") { + e.preventDefault(); + + if (keyCode == VK.RIGHT) { + positionCaretOnElement(nonEditableParent, false); + } else { + dom.remove(nonEditableParent); + return; + } + } else { + removeCaretContainer(caretContainer); + } + } } if ((keyCode == VK.BACKSPACE || keyCode == VK.DELETE) && !canDelete(keyCode == VK.BACKSPACE)) { e.preventDefault(); return false; } - - if (nondeletable && selectionContainsNonEditable) { - var confirmDeleting = confirm(ed.getLang("noneditable.confirm_delete")); - if (!confirmDeleting) { - e.preventDefault(); - return false; - } - } } } - } - + }; + + ed.onMouseDown.addToTop(function(ed, e) { + var node = ed.selection.getNode(); + + if (getContentEditable(node) === "false" && node == e.target) { + // Expand selection on mouse down we can't block the default event since it's used for drag/drop + moveSelection(); + } + }); + ed.onMouseUp.addToTop(moveSelection); - ed.onMouseDown.addToTop(moveSelection); ed.onKeyDown.addToTop(handleKey); ed.onKeyUp.addToTop(moveSelection); }; - function getEditClass(ed) { - return " " + tinymce.trim(ed.getParam("noneditable_editable_class", "mceEditable")) + " "; - } - function getNonEditClass(ed) { - return " " + tinymce.trim(ed.getParam("noneditable_noneditable_class", "mceNonEditable")) + " "; - } - - tinymce.PluginManager.requireLangPack('noneditable'); - tinymce.create('tinymce.plugins.NonEditablePlugin', { - init : function(ed) { + init : function(ed, url) { + var editClass, nonEditClass, nonEditableRegExps; // Converts configured regexps to noneditable span items function convertRegExpsToNonEditable(ed, args) { @@ -501,10 +454,10 @@ } args.content = content; - } + }; - editClass = getEditClass(ed); - nonEditClass = getNonEditClass(ed); + editClass = " " + tinymce.trim(ed.getParam("noneditable_editable_class", "mceEditable")) + " "; + nonEditClass = " " + tinymce.trim(ed.getParam("noneditable_noneditable_class", "mceNonEditable")) + " "; // Setup noneditable regexps array nonEditableRegExps = ed.getParam("noneditable_regexp"); @@ -537,7 +490,7 @@ }); // Remove internal name - ed.serializer.addAttributeFilter(internalName, function(nodes) { + ed.serializer.addAttributeFilter(internalName, function(nodes, name) { var i = nodes.length, node; while (i--) { @@ -556,7 +509,7 @@ }); // Convert external name into internal name - ed.parser.addAttributeFilter(externalName, function(nodes) { + ed.parser.addAttributeFilter(externalName, function(nodes, name) { var i = nodes.length, node; while (i--) { diff --git a/application/views/scripts/javascripts/vendor/tiny_mce/plugins/noneditable/langs/en.js b/application/views/scripts/javascripts/vendor/tiny_mce/plugins/noneditable/langs/en.js deleted file mode 100644 index 0e9c654756..0000000000 --- a/application/views/scripts/javascripts/vendor/tiny_mce/plugins/noneditable/langs/en.js +++ /dev/null @@ -1 +0,0 @@ -tinyMCE.addI18n('en.noneditable',{ confirm_delete : 'The selection contains non-editable text. Are you sure you want to continue?' }); \ No newline at end of file diff --git a/application/views/scripts/javascripts/vendor/tiny_mce/plugins/searchreplace/js/searchreplace.js b/application/views/scripts/javascripts/vendor/tiny_mce/plugins/searchreplace/js/searchreplace.js index d8522f0ed3..35cfb2b04d 100644 --- a/application/views/scripts/javascripts/vendor/tiny_mce/plugins/searchreplace/js/searchreplace.js +++ b/application/views/scripts/javascripts/vendor/tiny_mce/plugins/searchreplace/js/searchreplace.js @@ -40,8 +40,9 @@ var SearchReplaceDialog = { searchNext : function(a) { var ed = tinyMCEPopup.editor, se = ed.selection, r = se.getRng(), f, m = this.lastMode, s, b, fl = 0, w = ed.getWin(), wm = ed.windowManager, fo = 0; - function createTextRange() { - return ed.getDoc().selection ? ed.getDoc().selection.createRange() : ed.getDoc().body.createTextRange(); + if (tinymce.isIE11 && !window.find) { + ed.windowManager.alert("This feature is not available in IE 11+. Upgrade TinyMCE to 4.x to get this functionallity back."); + return; } // Get input @@ -52,7 +53,7 @@ var SearchReplaceDialog = { rs = f['replace_panel_replacestring'].value; if (tinymce.isIE) { - r = createTextRange(); + r = ed.getDoc().selection.createRange(); } if (s == '') @@ -82,7 +83,7 @@ var SearchReplaceDialog = { if (tinymce.isIE) { ed.focus(); - r = createTextRange(); + r = ed.getDoc().selection.createRange(); while (r.findText(s, b ? -1 : 1, fl)) { r.scrollIntoView(); @@ -130,7 +131,7 @@ var SearchReplaceDialog = { if (tinymce.isIE) { ed.focus(); - r = createTextRange(); + r = ed.getDoc().selection.createRange(); if (r.findText(s, b ? -1 : 1, fl)) { r.scrollIntoView(); diff --git a/application/views/scripts/javascripts/vendor/tiny_mce/plugins/table/cell.htm b/application/views/scripts/javascripts/vendor/tiny_mce/plugins/table/cell.htm index 1be54542bf..a72a8d6973 100644 --- a/application/views/scripts/javascripts/vendor/tiny_mce/plugins/table/cell.htm +++ b/application/views/scripts/javascripts/vendor/tiny_mce/plugins/table/cell.htm @@ -35,7 +35,7 @@ - + + @@ -94,8 +95,8 @@ - - + + @@ -104,25 +105,25 @@ - + + - + + - + + - + + - + +
- + + + -
-
@@ -130,11 +131,11 @@
 
-
@@ -142,11 +143,11 @@
 
-
@@ -154,7 +155,7 @@
 
-
diff --git a/application/views/scripts/javascripts/vendor/tiny_mce/plugins/table/editor_plugin.js b/application/views/scripts/javascripts/vendor/tiny_mce/plugins/table/editor_plugin.js index dbdadd184b..4a92e1b364 100644 --- a/application/views/scripts/javascripts/vendor/tiny_mce/plugins/table/editor_plugin.js +++ b/application/views/scripts/javascripts/vendor/tiny_mce/plugins/table/editor_plugin.js @@ -1 +1 @@ -(function(d){var e=d.each;function c(g,h){var i=h.ownerDocument,f=i.createRange(),j;f.setStartBefore(h);f.setEnd(g.endContainer,g.endOffset);j=i.createElement("body");j.appendChild(f.cloneContents());return j.innerHTML.replace(/<(br|img|object|embed|input|textarea)[^>]*>/gi,"-").replace(/<[^>]+>/g,"").length===0}function a(g,f){return parseInt(g.getAttribute(f)||1,10)}function b(E,D,H){var g,I,A,n;function x(K,J){K=K.cloneNode(J);K.removeAttribute("id");return K}function s(){var J=0;g=[];e(["thead","tbody","tfoot"],function(K){var L=D.select("> "+K+" tr",E);e(L,function(M,N){N+=J;e(D.select("> td, > th",M),function(T,O){var P,Q,R,S;if(g[N]){while(g[N][O]){O++}}R=a(T,"rowspan");S=a(T,"colspan");for(Q=N;Q'}return false}},"childNodes");J=x(J,false);r(J,"rowSpan",1);r(J,"colSpan",1);if(K){J.appendChild(K)}else{if(!d.isIE||d.isIE11){J.innerHTML='
'}}return J}function p(){var J=D.createRng(),K;e(D.select("tr",E),function(L){if(L.cells.length===0){D.remove(L)}});if(D.select("tr",E).length===0){J.setStartAfter(E);J.setEndAfter(E);H.setRng(J);D.remove(E);return}e(D.select("thead,tbody,tfoot",E),function(L){if(L.rows.length===0){D.remove(L)}});s();K=g[Math.min(g.length-1,I.y)];if(K){H.select(K[Math.min(K.length-1,I.x)].elm,true);H.collapse(true)}}function t(P,N,R,O){var M,K,J,L,Q;M=g[N][P].elm.parentNode;for(J=1;J<=R;J++){M=D.getNext(M,"tr");if(M){for(K=P;K>=0;K--){Q=g[N+J][K].elm;if(Q.parentNode==M){for(L=1;L<=O;L++){D.insertAfter(f(Q),Q)}break}}if(K==-1){for(L=1;L<=O;L++){M.insertBefore(f(M.cells[0]),M.cells[0])}}}}}function z(){e(g,function(J,K){e(J,function(M,L){var P,O,N;if(i(M)){M=M.elm;P=a(M,"colspan");O=a(M,"rowspan");if(P>1||O>1){r(M,"rowSpan",1);r(M,"colSpan",1);for(N=0;N1){r(P,"rowSpan",L+1);continue}}else{if(J>0&&g[J-1][O]){S=g[J-1][O].elm;L=a(S,"rowSpan");if(L>1){r(S,"rowSpan",L+1);continue}}}K=f(P);r(K,"colSpan",P.colSpan);R.appendChild(K);M=P}}if(R.hasChildNodes()){if(!N){D.insertAfter(R,Q)}else{Q.parentNode.insertBefore(R,Q)}}}function h(K){var L,J;e(g,function(M){e(M,function(O,N){if(i(O)){L=N;if(K){return false}}});if(K){return !L}});e(g,function(P,Q){var M,N,O;if(!P[L]){return}M=P[L].elm;if(M!=J){O=a(M,"colspan");N=a(M,"rowspan");if(O==1){if(!K){D.insertAfter(f(M),M);t(L,Q,N-1,O)}else{M.parentNode.insertBefore(f(M),M);t(L,Q,N-1,O)}}else{r(M,"colSpan",M.colSpan+1)}J=M}})}function m(){var J=[];e(g,function(K){e(K,function(M,L){if(i(M)&&d.inArray(J,L)===-1){e(g,function(P){var N=P[L].elm,O;O=a(N,"colSpan");if(O>1){r(N,"colSpan",O-1)}else{D.remove(N)}});J.push(L)}})});p()}function l(){var K;function J(M){var N,L;e(M.cells,function(O){var P=a(O,"rowSpan");if(P>1){r(O,"rowSpan",P-1);N=C(O);t(N.x,N.y,1,1)}});N=C(M.cells[0]);e(g[N.y],function(O){var P;O=O.elm;if(O!=L){P=a(O,"rowSpan");if(P<=1){D.remove(O)}else{r(O,"rowSpan",P-1)}L=O}})}K=j();e(K.reverse(),function(L){J(L)});p()}function B(){var J=j();D.remove(J);p();return J}function G(){var J=j();e(J,function(L,K){J[K]=x(L,true)});return J}function y(L,K){if(!L){return}var M=j(),J=M[K?0:M.length-1],N=J.cells.length;e(g,function(P){var O;N=0;e(P,function(Q){if(Q.real){N+=Q.colspan}if(Q.elm.parentNode==J){O=1}});if(O){return false}});if(!K){L.reverse()}e(L,function(R){var Q=R.cells.length,O,P;for(P=0;PK){K=N}if(M>J){J=M}if(O.real){Q=O.colspan-1;P=O.rowspan-1;if(Q){if(N+Q>K){K=N+Q}}if(P){if(M+P>J){J=M+P}}}}})});return{x:K,y:J}}function u(R){var M,L,T,S,K,J,N,O,P,Q;A=C(R);if(I&&A){M=Math.min(I.x,A.x);L=Math.min(I.y,A.y);T=Math.max(I.x,A.x);S=Math.max(I.y,A.y);K=T;J=S;for(P=L;P<=J;P++){R=g[P][M];if(!R.real){if(M-(R.colspan-1)K){K=Q+N}}if(O){if(P+O>J){J=P+O}}}}}D.removeClass(D.select("td.mceSelected,th.mceSelected"),"mceSelected");for(P=L;P<=J;P++){for(Q=M;Q<=K;Q++){if(g[P][Q]){D.addClass(g[P][Q].elm,"mceSelected")}}}}}s();n=D.getParent(H.getStart(),"th,td");if(n){I=C(n);A=F();n=w(I.x,I.y)}d.extend(this,{deleteTable:q,split:z,merge:o,insertRow:k,insertCol:h,deleteCols:m,deleteRows:l,cutRows:B,copyRows:G,pasteRows:y,getPos:C,setStartCell:v,setEndCell:u})}d.create("tinymce.plugins.TablePlugin",{init:function(g,h){var f,l,i=true;function k(o){var n=g.selection,m=g.dom.getParent(o||n.getNode(),"table");if(m){return new b(m,g.dom,n)}}function j(){g.getBody().style.webkitUserSelect="";if(i){g.dom.removeClass(g.dom.select("td.mceSelected,th.mceSelected"),"mceSelected");i=false}}e([["table","table.desc","mceInsertTable",true],["delete_table","table.del","mceTableDelete"],["delete_col","table.delete_col_desc","mceTableDeleteCol"],["delete_row","table.delete_row_desc","mceTableDeleteRow"],["col_after","table.col_after_desc","mceTableInsertColAfter"],["col_before","table.col_before_desc","mceTableInsertColBefore"],["row_after","table.row_after_desc","mceTableInsertRowAfter"],["row_before","table.row_before_desc","mceTableInsertRowBefore"],["row_props","table.row_desc","mceTableRowProps",true],["cell_props","table.cell_desc","mceTableCellProps",true],["split_cells","table.split_cells_desc","mceTableSplitCells",true],["merge_cells","table.merge_cells_desc","mceTableMergeCells",true]],function(m){g.addButton(m[0],{title:m[1],cmd:m[2],ui:m[3]})});if(!d.isIE){g.onClick.add(function(m,n){n=n.target;if(n.nodeName==="TABLE"){m.selection.select(n);m.nodeChanged()}})}g.onPreProcess.add(function(n,o){var m,p,q,s=n.dom,r;m=s.select("table",o.node);p=m.length;while(p--){q=m[p];s.setAttrib(q,"data-mce-style","");if((r=s.getAttrib(q,"width"))){s.setStyle(q,"width",r);s.setAttrib(q,"width","")}if((r=s.getAttrib(q,"height"))){s.setStyle(q,"height",r);s.setAttrib(q,"height","")}}});g.onNodeChange.add(function(o,m,r){var q;r=o.selection.getStart();q=o.dom.getParent(r,"td,th,caption");m.setActive("table",r.nodeName==="TABLE"||!!q);if(q&&q.nodeName==="CAPTION"){q=0}m.setDisabled("delete_table",!q);m.setDisabled("delete_col",!q);m.setDisabled("delete_table",!q);m.setDisabled("delete_row",!q);m.setDisabled("col_after",!q);m.setDisabled("col_before",!q);m.setDisabled("row_after",!q);m.setDisabled("row_before",!q);m.setDisabled("row_props",!q);m.setDisabled("cell_props",!q);m.setDisabled("split_cells",!q);m.setDisabled("merge_cells",!q)});g.onInit.add(function(q){var o,s,p=q.dom,t;f=q.windowManager;q.onMouseDown.add(function(v,w){if(w.button!=2){j();s=p.getParent(w.target,"td,th");o=p.getParent(s,"table")}});p.bind(q.getDoc(),"mouseover",function(z){var x,w,y=z.target;if(s&&(t||y!=s)&&(y.nodeName=="TD"||y.nodeName=="TH")){w=p.getParent(y,"table");if(w==o){if(!t){t=k(w);t.setStartCell(s);q.getBody().style.webkitUserSelect="none"}t.setEndCell(y);i=true}x=q.selection.getSel();try{if(x.removeAllRanges){x.removeAllRanges()}else{x.empty()}}catch(v){}z.preventDefault()}});q.onMouseUp.add(function(y){var w,B=y.selection,v,C,A,z;function x(D,F){var E=new d.dom.TreeWalker(D,D);do{if(D.nodeType==3&&d.trim(D.nodeValue).length!==0){if(F){w.setStart(D,0)}else{w.setEnd(D,D.nodeValue.length)}return}if(D.nodeName=="BR"){if(F){w.setStartBefore(D)}else{w.setEndBefore(D)}return}D=(F?E.next():E.prev())}while(D)}if(s){if(t){y.getBody().style.webkitUserSelect=""}v=p.select("td.mceSelected,th.mceSelected");if(v.length>0){w=p.createRng();A=v[0];w.setStartBefore(A);w.setEndAfter(A);x(A,1);C=new d.dom.TreeWalker(A,p.getParent(v[0],"table"));do{if(A.nodeName=="TD"||A.nodeName=="TH"){if(!p.hasClass(A,"mceSelected")){break}z=A}A=C.next()}while(A);x(z);B.setRng(w)}y.nodeChanged();s=t=o=null}});q.onKeyUp.add(function(){j()});q.onKeyDown.add(function(v){m(v)});q.onMouseDown.add(function(v,w){if(w.button!=2){m(v)}});function n(A,w,x,C){var y=3,D=A.dom.getParent(w.startContainer,"TABLE"),z,v,B;if(D){z=D.parentNode}v=w.startContainer.nodeType==y&&w.startOffset===0&&w.endOffset===0&&C&&(x.nodeName==="TR"||x===z);B=(x.nodeName==="TD"||x.nodeName==="TH")&&!C;return v||B}function m(x){if(!d.isWebKit){return}var w=x.selection.getRng();var z=x.selection.getNode();var y=x.dom.getParent(w.startContainer,"TD,TH");if(!n(x,w,z,y)){return}if(!y){y=z}var v=y.lastChild;while(v.lastChild){v=v.lastChild}w.setEnd(v,v.nodeValue.length);x.selection.setRng(w)}q.plugins.table.fixTableCellSelection=m;if(q&&q.plugins.contextmenu){q.plugins.contextmenu.onContextMenu.add(function(x,v,z){var A,y=q.selection,w=y.getNode()||q.getBody();if(q.dom.getParent(z,"td")||q.dom.getParent(z,"th")||q.dom.select("td.mceSelected,th.mceSelected").length){v.removeAll();if(w.nodeName=="A"&&!q.dom.getAttrib(w,"name")){v.add({title:"advanced.link_desc",icon:"link",cmd:q.plugins.advlink?"mceAdvLink":"mceLink",ui:true});v.add({title:"advanced.unlink_desc",icon:"unlink",cmd:"UnLink"});v.addSeparator()}if(w.nodeName=="IMG"&&w.className.indexOf("mceItem")==-1){v.add({title:"advanced.image_desc",icon:"image",cmd:q.plugins.advimage?"mceAdvImage":"mceImage",ui:true});v.addSeparator()}v.add({title:"table.desc",icon:"table",cmd:"mceInsertTable",value:{action:"insert"}});v.add({title:"table.props_desc",icon:"table_props",cmd:"mceInsertTable"});v.add({title:"table.del",icon:"delete_table",cmd:"mceTableDelete"});v.addSeparator();A=v.addMenu({title:"table.cell"});A.add({title:"table.cell_desc",icon:"cell_props",cmd:"mceTableCellProps"});A.add({title:"table.split_cells_desc",icon:"split_cells",cmd:"mceTableSplitCells"});A.add({title:"table.merge_cells_desc",icon:"merge_cells",cmd:"mceTableMergeCells"});A=v.addMenu({title:"table.row"});A.add({title:"table.row_desc",icon:"row_props",cmd:"mceTableRowProps"});A.add({title:"table.row_before_desc",icon:"row_before",cmd:"mceTableInsertRowBefore"});A.add({title:"table.row_after_desc",icon:"row_after",cmd:"mceTableInsertRowAfter"});A.add({title:"table.delete_row_desc",icon:"delete_row",cmd:"mceTableDeleteRow"});A.addSeparator();A.add({title:"table.cut_row_desc",icon:"cut",cmd:"mceTableCutRow"});A.add({title:"table.copy_row_desc",icon:"copy",cmd:"mceTableCopyRow"});A.add({title:"table.paste_row_before_desc",icon:"paste",cmd:"mceTablePasteRowBefore"}).setDisabled(!l);A.add({title:"table.paste_row_after_desc",icon:"paste",cmd:"mceTablePasteRowAfter"}).setDisabled(!l);A=v.addMenu({title:"table.col"});A.add({title:"table.col_before_desc",icon:"col_before",cmd:"mceTableInsertColBefore"});A.add({title:"table.col_after_desc",icon:"col_after",cmd:"mceTableInsertColAfter"});A.add({title:"table.delete_col_desc",icon:"delete_col",cmd:"mceTableDeleteCol"})}else{v.add({title:"table.desc",icon:"table",cmd:"mceInsertTable"})}})}function u(z,K){var I=d.VK;var N=K.keyCode;function L(V,R,P){var Q=V?"previousSibling":"nextSibling";var W=z.dom.getParent(R,"tr");var U=W[Q];if(U){w(z,R,U,V);d.dom.Event.cancel(P);return true}else{var X=z.dom.getParent(W,"table");var T=W.parentNode;var O=T.nodeName.toLowerCase();if(O==="tbody"||O===(V?"tfoot":"thead")){var S=v(V,X,T,"tbody");if(S!==null){return H(V,S,R,P)}}return J(V,W,Q,X,P)}}function v(S,Q,R,U){var P=z.dom.select(">"+U,Q);var O=P.indexOf(R);if(S&&O===0||!S&&O===P.length-1){return y(S,Q)}else{if(O===-1){var T=R.tagName.toLowerCase()==="thead"?0:P.length-1;return P[T]}else{return P[O+(S?-1:1)]}}}function y(R,Q){var P=R?"thead":"tfoot";var O=z.dom.select(">"+P,Q);return O.length!==0?O[0]:null}function H(S,Q,P,R){var O=G(Q,S);if(O){w(z,P,O,S)}d.dom.Event.cancel(R);return true}function J(V,R,O,U,T){var P=U[O];if(P){C(P);return true}else{var S=z.dom.getParent(U,"td,th");if(S){return L(V,S,T)}else{var Q=G(R,!V);C(Q);return d.dom.Event.cancel(T)}}}function G(P,O){var Q=P&&P[O?"lastChild":"firstChild"];return Q&&Q.nodeName==="BR"?z.dom.getParent(Q,"td,th"):Q}function C(O){z.selection.setCursorLocation(O,0)}function x(){return N==I.UP||N==I.DOWN}function A(O){var Q=O.selection.getNode();var P=O.dom.getParent(Q,"tr");return P!==null}function M(P){var O=0;var Q=P;while(Q.previousSibling){Q=Q.previousSibling;O=O+a(Q,"colspan")}return O}function B(Q,O){var R=0;var P=0;e(Q.children,function(S,T){R=R+a(S,"colspan");P=T;if(R>O){return false}});return P}function w(Q,T,V,S){var U=M(Q.dom.getParent(T,"td,th"));var P=B(V,U);var O=V.childNodes[P];var R=G(O,S);C(R||O)}function E(O){var Q=z.selection.getNode();var R=z.dom.getParent(Q,"td,th");var P=z.dom.getParent(O,"td,th");return R&&R!==P&&F(R,P)}function F(P,O){return z.dom.getParent(P,"TABLE")===z.dom.getParent(O,"TABLE")}if(x()&&A(z)){var D=z.selection.getNode();setTimeout(function(){if(E(D)){L(!K.shiftKey&&N===I.UP,D,K)}},0)}}if(d.isWebKit){q.onKeyDown.add(u)}function r(){var v;v=q.getBody().lastChild;while(v&&v.nodeType==3&&!v.nodeValue.length){v=v.previousSibling}if(v&&v.nodeName==="TABLE"){if(q.settings.forced_root_block){q.dom.add(q.getBody(),q.settings.forced_root_block,null,d.isIE&&!d.isIE11?" ":'
')}else{q.dom.add(q.getBody(),"br",{"data-mce-bogus":"1"})}}}if(d.isGecko){q.onKeyDown.add(function(w,y){var v,x,z=w.dom;if(y.keyCode==37||y.keyCode==38){v=w.selection.getRng();x=z.getParent(v.startContainer,"table");if(x&&w.getBody().firstChild==x){if(c(v,x)){v=z.createRng();v.setStartBefore(x);v.setEndBefore(x);w.selection.setRng(v);y.preventDefault()}}}})}q.onKeyUp.add(r);q.onSetContent.add(r);q.onVisualAid.add(r);q.onPreProcess.add(function(v,x){var w=x.node.lastChild;if(w&&(w.nodeName=="BR"||(w.childNodes.length==1&&(w.firstChild.nodeName=="BR"||w.firstChild.nodeValue=="\u00a0")))&&w.previousSibling&&w.previousSibling.nodeName=="TABLE"){v.dom.remove(w)}});r();q.startContent=q.getContent({format:"raw"})});e({mceTableSplitCells:function(m){m.split()},mceTableMergeCells:function(n){var o,p,m;m=g.dom.getParent(g.selection.getNode(),"th,td");if(m){o=m.rowSpan;p=m.colSpan}if(!g.dom.select("td.mceSelected,th.mceSelected").length){f.open({url:h+"/merge_cells.htm",width:240+parseInt(g.getLang("table.merge_cells_delta_width",0),10),height:110+parseInt(g.getLang("table.merge_cells_delta_height",0),10),inline:1},{rows:o,cols:p,onaction:function(q){n.merge(m,q.cols,q.rows)},plugin_url:h})}else{n.merge()}},mceTableInsertRowBefore:function(m){m.insertRow(true)},mceTableInsertRowAfter:function(m){m.insertRow()},mceTableInsertColBefore:function(m){m.insertCol(true)},mceTableInsertColAfter:function(m){m.insertCol()},mceTableDeleteCol:function(m){m.deleteCols()},mceTableDeleteRow:function(m){m.deleteRows()},mceTableCutRow:function(m){l=m.cutRows()},mceTableCopyRow:function(m){l=m.copyRows()},mceTablePasteRowBefore:function(m){m.pasteRows(l,true)},mceTablePasteRowAfter:function(m){m.pasteRows(l)},mceTableDelete:function(m){m.deleteTable()}},function(n,m){g.addCommand(m,function(){var o=k();if(o){n(o);g.execCommand("mceRepaint");j()}})});e({mceInsertTable:function(m){f.open({url:h+"/table.htm",width:400+parseInt(g.getLang("table.table_delta_width",0),10),height:320+parseInt(g.getLang("table.table_delta_height",0),10),inline:1},{plugin_url:h,action:m?m.action:0})},mceTableRowProps:function(){f.open({url:h+"/row.htm",width:400+parseInt(g.getLang("table.rowprops_delta_width",0),10),height:295+parseInt(g.getLang("table.rowprops_delta_height",0),10),inline:1},{plugin_url:h})},mceTableCellProps:function(){f.open({url:h+"/cell.htm",width:400+parseInt(g.getLang("table.cellprops_delta_width",0),10),height:295+parseInt(g.getLang("table.cellprops_delta_height",0),10),inline:1},{plugin_url:h})}},function(n,m){g.addCommand(m,function(o,p){n(p)})})}});d.PluginManager.add("table",d.plugins.TablePlugin)})(tinymce); \ No newline at end of file +(function(d){var e=d.each;function c(g,h){var j=h.ownerDocument,f=j.createRange(),k;f.setStartBefore(h);f.setEnd(g.endContainer,g.endOffset);k=j.createElement("body");k.appendChild(f.cloneContents());return k.innerHTML.replace(/<(br|img|object|embed|input|textarea)[^>]*>/gi,"-").replace(/<[^>]+>/g,"").length==0}function a(g,f){return parseInt(g.getAttribute(f)||1)}function b(H,G,K){var g,L,D,o;t();o=G.getParent(K.getStart(),"th,td");if(o){L=F(o);D=I();o=z(L.x,L.y)}function A(N,M){N=N.cloneNode(M);N.removeAttribute("id");return N}function t(){var M=0;g=[];e(["thead","tbody","tfoot"],function(N){var O=G.select("> "+N+" tr",H);e(O,function(P,Q){Q+=M;e(G.select("> td, > th",P),function(W,R){var S,T,U,V;if(g[Q]){while(g[Q][R]){R++}}U=a(W,"rowspan");V=a(W,"colspan");for(T=Q;T'}return false}},"childNodes");M=A(M,false);s(M,"rowSpan",1);s(M,"colSpan",1);if(N){M.appendChild(N)}else{if(!d.isIE||d.isIE11){M.innerHTML='
'}}return M}function q(){var M=G.createRng();e(G.select("tr",H),function(N){if(N.cells.length==0){G.remove(N)}});if(G.select("tr",H).length==0){M.setStartAfter(H);M.setEndAfter(H);K.setRng(M);G.remove(H);return}e(G.select("thead,tbody,tfoot",H),function(N){if(N.rows.length==0){G.remove(N)}});t();row=g[Math.min(g.length-1,L.y)];if(row){K.select(row[Math.min(row.length-1,L.x)].elm,true);K.collapse(true)}}function u(S,Q,U,R){var P,N,M,O,T;P=g[Q][S].elm.parentNode;for(M=1;M<=U;M++){P=G.getNext(P,"tr");if(P){for(N=S;N>=0;N--){T=g[Q+M][N].elm;if(T.parentNode==P){for(O=1;O<=R;O++){G.insertAfter(f(T),T)}break}}if(N==-1){for(O=1;O<=R;O++){P.insertBefore(f(P.cells[0]),P.cells[0])}}}}}function C(){e(g,function(M,N){e(M,function(P,O){var S,R,T,Q;if(j(P)){P=P.elm;S=a(P,"colspan");R=a(P,"rowspan");if(S>1||R>1){s(P,"rowSpan",1);s(P,"colSpan",1);for(Q=0;Q1){s(S,"rowSpan",O+1);continue}}else{if(M>0&&g[M-1][R]){V=g[M-1][R].elm;O=a(V,"rowSpan");if(O>1){s(V,"rowSpan",O+1);continue}}}N=f(S);s(N,"colSpan",S.colSpan);U.appendChild(N);P=S}}if(U.hasChildNodes()){if(!Q){G.insertAfter(U,T)}else{T.parentNode.insertBefore(U,T)}}}function h(N){var O,M;e(g,function(P,Q){e(P,function(S,R){if(j(S)){O=R;if(N){return false}}});if(N){return !O}});e(g,function(S,T){var P,Q,R;if(!S[O]){return}P=S[O].elm;if(P!=M){R=a(P,"colspan");Q=a(P,"rowspan");if(R==1){if(!N){G.insertAfter(f(P),P);u(O,T,Q-1,R)}else{P.parentNode.insertBefore(f(P),P);u(O,T,Q-1,R)}}else{s(P,"colSpan",P.colSpan+1)}M=P}})}function n(){var M=[];e(g,function(N,O){e(N,function(Q,P){if(j(Q)&&d.inArray(M,P)===-1){e(g,function(T){var R=T[P].elm,S;S=a(R,"colSpan");if(S>1){s(R,"colSpan",S-1)}else{G.remove(R)}});M.push(P)}})});q()}function m(){var N;function M(Q){var P,R,O;P=G.getNext(Q,"tr");e(Q.cells,function(S){var T=a(S,"rowSpan");if(T>1){s(S,"rowSpan",T-1);R=F(S);u(R.x,R.y,1,1)}});R=F(Q.cells[0]);e(g[R.y],function(S){var T;S=S.elm;if(S!=O){T=a(S,"rowSpan");if(T<=1){G.remove(S)}else{s(S,"rowSpan",T-1)}O=S}})}N=k();e(N.reverse(),function(O){M(O)});q()}function E(){var M=k();G.remove(M);q();return M}function J(){var M=k();e(M,function(O,N){M[N]=A(O,true)});return M}function B(O,N){if(!O){return}var P=k(),M=P[N?0:P.length-1],Q=M.cells.length;e(g,function(S){var R;Q=0;e(S,function(U,T){if(U.real){Q+=U.colspan}if(U.elm.parentNode==M){R=1}});if(R){return false}});if(!N){O.reverse()}e(O,function(T){var S=T.cells.length,R;for(i=0;iN){N=R}if(Q>M){M=Q}if(S.real){U=S.colspan-1;T=S.rowspan-1;if(U){if(R+U>N){N=R+U}}if(T){if(Q+T>M){M=Q+T}}}}})});return{x:N,y:M}}function v(S){var P,O,U,T,N,M,Q,R;D=F(S);if(L&&D){P=Math.min(L.x,D.x);O=Math.min(L.y,D.y);U=Math.max(L.x,D.x);T=Math.max(L.y,D.y);N=U;M=T;for(y=O;y<=M;y++){S=g[y][P];if(!S.real){if(P-(S.colspan-1)N){N=x+Q}}if(R){if(y+R>M){M=y+R}}}}}G.removeClass(G.select("td.mceSelected,th.mceSelected"),"mceSelected");for(y=O;y<=M;y++){for(x=P;x<=N;x++){if(g[y][x]){G.addClass(g[y][x].elm,"mceSelected")}}}}}d.extend(this,{deleteTable:r,split:C,merge:p,insertRow:l,insertCol:h,deleteCols:n,deleteRows:m,cutRows:E,copyRows:J,pasteRows:B,getPos:F,setStartCell:w,setEndCell:v})}d.create("tinymce.plugins.TablePlugin",{init:function(g,h){var f,m,j=true;function l(p){var o=g.selection,n=g.dom.getParent(p||o.getNode(),"table");if(n){return new b(n,g.dom,o)}}function k(){g.getBody().style.webkitUserSelect="";if(j){g.dom.removeClass(g.dom.select("td.mceSelected,th.mceSelected"),"mceSelected");j=false}}e([["table","table.desc","mceInsertTable",true],["delete_table","table.del","mceTableDelete"],["delete_col","table.delete_col_desc","mceTableDeleteCol"],["delete_row","table.delete_row_desc","mceTableDeleteRow"],["col_after","table.col_after_desc","mceTableInsertColAfter"],["col_before","table.col_before_desc","mceTableInsertColBefore"],["row_after","table.row_after_desc","mceTableInsertRowAfter"],["row_before","table.row_before_desc","mceTableInsertRowBefore"],["row_props","table.row_desc","mceTableRowProps",true],["cell_props","table.cell_desc","mceTableCellProps",true],["split_cells","table.split_cells_desc","mceTableSplitCells",true],["merge_cells","table.merge_cells_desc","mceTableMergeCells",true]],function(n){g.addButton(n[0],{title:n[1],cmd:n[2],ui:n[3]})});if(!d.isIE){g.onClick.add(function(n,o){o=o.target;if(o.nodeName==="TABLE"){n.selection.select(o);n.nodeChanged()}})}g.onPreProcess.add(function(o,p){var n,q,r,t=o.dom,s;n=t.select("table",p.node);q=n.length;while(q--){r=n[q];t.setAttrib(r,"data-mce-style","");if((s=t.getAttrib(r,"width"))){t.setStyle(r,"width",s);t.setAttrib(r,"width","")}if((s=t.getAttrib(r,"height"))){t.setStyle(r,"height",s);t.setAttrib(r,"height","")}}});g.onNodeChange.add(function(q,o,s){var r;s=q.selection.getStart();r=q.dom.getParent(s,"td,th,caption");o.setActive("table",s.nodeName==="TABLE"||!!r);if(r&&r.nodeName==="CAPTION"){r=0}o.setDisabled("delete_table",!r);o.setDisabled("delete_col",!r);o.setDisabled("delete_table",!r);o.setDisabled("delete_row",!r);o.setDisabled("col_after",!r);o.setDisabled("col_before",!r);o.setDisabled("row_after",!r);o.setDisabled("row_before",!r);o.setDisabled("row_props",!r);o.setDisabled("cell_props",!r);o.setDisabled("split_cells",!r);o.setDisabled("merge_cells",!r)});g.onInit.add(function(r){var p,t,q=r.dom,u;f=r.windowManager;r.onMouseDown.add(function(w,z){if(z.button!=2){k();t=q.getParent(z.target,"td,th");p=q.getParent(t,"table")}});q.bind(r.getDoc(),"mouseover",function(C){var A,z,B=C.target;if(t&&(u||B!=t)&&(B.nodeName=="TD"||B.nodeName=="TH")){z=q.getParent(B,"table");if(z==p){if(!u){u=l(z);u.setStartCell(t);r.getBody().style.webkitUserSelect="none"}u.setEndCell(B);j=true}A=r.selection.getSel();try{if(A.removeAllRanges){A.removeAllRanges()}else{A.empty()}}catch(w){}C.preventDefault()}});r.onMouseUp.add(function(F,G){var z,B=F.selection,H,I=B.getSel(),w,C,A,E;if(t){if(u){F.getBody().style.webkitUserSelect=""}function D(J,L){var K=new d.dom.TreeWalker(J,J);do{if(J.nodeType==3&&d.trim(J.nodeValue).length!=0){if(L){z.setStart(J,0)}else{z.setEnd(J,J.nodeValue.length)}return}if(J.nodeName=="BR"){if(L){z.setStartBefore(J)}else{z.setEndBefore(J)}return}}while(J=(L?K.next():K.prev()))}H=q.select("td.mceSelected,th.mceSelected");if(H.length>0){z=q.createRng();C=H[0];E=H[H.length-1];z.setStartBefore(C);z.setEndAfter(C);D(C,1);w=new d.dom.TreeWalker(C,q.getParent(H[0],"table"));do{if(C.nodeName=="TD"||C.nodeName=="TH"){if(!q.hasClass(C,"mceSelected")){break}A=C}}while(C=w.next());D(A);B.setRng(z)}F.nodeChanged();t=u=p=null}});r.onKeyUp.add(function(w,z){k()});r.onKeyDown.add(function(w,z){n(w)});r.onMouseDown.add(function(w,z){if(z.button!=2){n(w)}});function o(D,z,A,F){var B=3,G=D.dom.getParent(z.startContainer,"TABLE"),C,w,E;if(G){C=G.parentNode}w=z.startContainer.nodeType==B&&z.startOffset==0&&z.endOffset==0&&F&&(A.nodeName=="TR"||A==C);E=(A.nodeName=="TD"||A.nodeName=="TH")&&!F;return w||E}function n(A){if(!d.isWebKit){return}var z=A.selection.getRng();var C=A.selection.getNode();var B=A.dom.getParent(z.startContainer,"TD,TH");if(!o(A,z,C,B)){return}if(!B){B=C}var w=B.lastChild;while(w.lastChild){w=w.lastChild}z.setEnd(w,w.nodeValue.length);A.selection.setRng(z)}r.plugins.table.fixTableCellSelection=n;if(r&&r.plugins.contextmenu){r.plugins.contextmenu.onContextMenu.add(function(A,w,C){var D,B=r.selection,z=B.getNode()||r.getBody();if(r.dom.getParent(C,"td")||r.dom.getParent(C,"th")||r.dom.select("td.mceSelected,th.mceSelected").length){w.removeAll();if(z.nodeName=="A"&&!r.dom.getAttrib(z,"name")){w.add({title:"advanced.link_desc",icon:"link",cmd:r.plugins.advlink?"mceAdvLink":"mceLink",ui:true});w.add({title:"advanced.unlink_desc",icon:"unlink",cmd:"UnLink"});w.addSeparator()}if(z.nodeName=="IMG"&&z.className.indexOf("mceItem")==-1){w.add({title:"advanced.image_desc",icon:"image",cmd:r.plugins.advimage?"mceAdvImage":"mceImage",ui:true});w.addSeparator()}w.add({title:"table.desc",icon:"table",cmd:"mceInsertTable",value:{action:"insert"}});w.add({title:"table.props_desc",icon:"table_props",cmd:"mceInsertTable"});w.add({title:"table.del",icon:"delete_table",cmd:"mceTableDelete"});w.addSeparator();D=w.addMenu({title:"table.cell"});D.add({title:"table.cell_desc",icon:"cell_props",cmd:"mceTableCellProps"});D.add({title:"table.split_cells_desc",icon:"split_cells",cmd:"mceTableSplitCells"});D.add({title:"table.merge_cells_desc",icon:"merge_cells",cmd:"mceTableMergeCells"});D=w.addMenu({title:"table.row"});D.add({title:"table.row_desc",icon:"row_props",cmd:"mceTableRowProps"});D.add({title:"table.row_before_desc",icon:"row_before",cmd:"mceTableInsertRowBefore"});D.add({title:"table.row_after_desc",icon:"row_after",cmd:"mceTableInsertRowAfter"});D.add({title:"table.delete_row_desc",icon:"delete_row",cmd:"mceTableDeleteRow"});D.addSeparator();D.add({title:"table.cut_row_desc",icon:"cut",cmd:"mceTableCutRow"});D.add({title:"table.copy_row_desc",icon:"copy",cmd:"mceTableCopyRow"});D.add({title:"table.paste_row_before_desc",icon:"paste",cmd:"mceTablePasteRowBefore"}).setDisabled(!m);D.add({title:"table.paste_row_after_desc",icon:"paste",cmd:"mceTablePasteRowAfter"}).setDisabled(!m);D=w.addMenu({title:"table.col"});D.add({title:"table.col_before_desc",icon:"col_before",cmd:"mceTableInsertColBefore"});D.add({title:"table.col_after_desc",icon:"col_after",cmd:"mceTableInsertColAfter"});D.add({title:"table.delete_col_desc",icon:"delete_col",cmd:"mceTableDeleteCol"})}else{w.add({title:"table.desc",icon:"table",cmd:"mceInsertTable"})}})}if(d.isWebKit){function v(C,N){var L=d.VK;var Q=N.keyCode;function O(Y,U,S){var T=Y?"previousSibling":"nextSibling";var Z=C.dom.getParent(U,"tr");var X=Z[T];if(X){z(C,U,X,Y);d.dom.Event.cancel(S);return true}else{var aa=C.dom.getParent(Z,"table");var W=Z.parentNode;var R=W.nodeName.toLowerCase();if(R==="tbody"||R===(Y?"tfoot":"thead")){var V=w(Y,aa,W,"tbody");if(V!==null){return K(Y,V,U,S)}}return M(Y,Z,T,aa,S)}}function w(V,T,U,X){var S=C.dom.select(">"+X,T);var R=S.indexOf(U);if(V&&R===0||!V&&R===S.length-1){return B(V,T)}else{if(R===-1){var W=U.tagName.toLowerCase()==="thead"?0:S.length-1;return S[W]}else{return S[R+(V?-1:1)]}}}function B(U,T){var S=U?"thead":"tfoot";var R=C.dom.select(">"+S,T);return R.length!==0?R[0]:null}function K(V,T,S,U){var R=J(T,V);R&&z(C,S,R,V);d.dom.Event.cancel(U);return true}function M(Y,U,R,X,W){var S=X[R];if(S){F(S);return true}else{var V=C.dom.getParent(X,"td,th");if(V){return O(Y,V,W)}else{var T=J(U,!Y);F(T);return d.dom.Event.cancel(W)}}}function J(S,R){var T=S&&S[R?"lastChild":"firstChild"];return T&&T.nodeName==="BR"?C.dom.getParent(T,"td,th"):T}function F(R){C.selection.setCursorLocation(R,0)}function A(){return Q==L.UP||Q==L.DOWN}function D(R){var T=R.selection.getNode();var S=R.dom.getParent(T,"tr");return S!==null}function P(S){var R=0;var T=S;while(T.previousSibling){T=T.previousSibling;R=R+a(T,"colspan")}return R}function E(T,R){var U=0;var S=0;e(T.children,function(V,W){U=U+a(V,"colspan");S=W;if(U>R){return false}});return S}function z(T,W,Y,V){var X=P(T.dom.getParent(W,"td,th"));var S=E(Y,X);var R=Y.childNodes[S];var U=J(R,V);F(U||R)}function H(R){var T=C.selection.getNode();var U=C.dom.getParent(T,"td,th");var S=C.dom.getParent(R,"td,th");return U&&U!==S&&I(U,S)}function I(S,R){return C.dom.getParent(S,"TABLE")===C.dom.getParent(R,"TABLE")}if(A()&&D(C)){var G=C.selection.getNode();setTimeout(function(){if(H(G)){O(!N.shiftKey&&Q===L.UP,G,N)}},0)}}r.onKeyDown.add(v)}function s(){var w;for(w=r.getBody().lastChild;w&&w.nodeType==3&&!w.nodeValue.length;w=w.previousSibling){}if(w&&w.nodeName=="TABLE"){if(r.settings.forced_root_block){r.dom.add(r.getBody(),r.settings.forced_root_block,null,d.isIE&&!d.isIE11?" ":'
')}else{r.dom.add(r.getBody(),"br",{"data-mce-bogus":"1"})}}}if(d.isGecko){r.onKeyDown.add(function(z,B){var w,A,C=z.dom;if(B.keyCode==37||B.keyCode==38){w=z.selection.getRng();A=C.getParent(w.startContainer,"table");if(A&&z.getBody().firstChild==A){if(c(w,A)){w=C.createRng();w.setStartBefore(A);w.setEndBefore(A);z.selection.setRng(w);B.preventDefault()}}}})}r.onKeyUp.add(s);r.onSetContent.add(s);r.onVisualAid.add(s);r.onPreProcess.add(function(w,A){var z=A.node.lastChild;if(z&&(z.nodeName=="BR"||(z.childNodes.length==1&&(z.firstChild.nodeName=="BR"||z.firstChild.nodeValue=="\u00a0")))&&z.previousSibling&&z.previousSibling.nodeName=="TABLE"){w.dom.remove(z)}});s();r.startContent=r.getContent({format:"raw"})});e({mceTableSplitCells:function(n){n.split()},mceTableMergeCells:function(o){var p,q,n;n=g.dom.getParent(g.selection.getNode(),"th,td");if(n){p=n.rowSpan;q=n.colSpan}if(!g.dom.select("td.mceSelected,th.mceSelected").length){f.open({url:h+"/merge_cells.htm",width:240+parseInt(g.getLang("table.merge_cells_delta_width",0)),height:110+parseInt(g.getLang("table.merge_cells_delta_height",0)),inline:1},{rows:p,cols:q,onaction:function(r){o.merge(n,r.cols,r.rows)},plugin_url:h})}else{o.merge()}},mceTableInsertRowBefore:function(n){n.insertRow(true)},mceTableInsertRowAfter:function(n){n.insertRow()},mceTableInsertColBefore:function(n){n.insertCol(true)},mceTableInsertColAfter:function(n){n.insertCol()},mceTableDeleteCol:function(n){n.deleteCols()},mceTableDeleteRow:function(n){n.deleteRows()},mceTableCutRow:function(n){m=n.cutRows()},mceTableCopyRow:function(n){m=n.copyRows()},mceTablePasteRowBefore:function(n){n.pasteRows(m,true)},mceTablePasteRowAfter:function(n){n.pasteRows(m)},mceTableDelete:function(n){n.deleteTable()}},function(o,n){g.addCommand(n,function(){var p=l();if(p){o(p);g.execCommand("mceRepaint");k()}})});e({mceInsertTable:function(n){f.open({url:h+"/table.htm",width:400+parseInt(g.getLang("table.table_delta_width",0)),height:320+parseInt(g.getLang("table.table_delta_height",0)),inline:1},{plugin_url:h,action:n?n.action:0})},mceTableRowProps:function(){f.open({url:h+"/row.htm",width:400+parseInt(g.getLang("table.rowprops_delta_width",0)),height:295+parseInt(g.getLang("table.rowprops_delta_height",0)),inline:1},{plugin_url:h})},mceTableCellProps:function(){f.open({url:h+"/cell.htm",width:400+parseInt(g.getLang("table.cellprops_delta_width",0)),height:295+parseInt(g.getLang("table.cellprops_delta_height",0)),inline:1},{plugin_url:h})}},function(o,n){g.addCommand(n,function(p,q){o(q)})})}});d.PluginManager.add("table",d.plugins.TablePlugin)})(tinymce); \ No newline at end of file diff --git a/application/views/scripts/javascripts/vendor/tiny_mce/plugins/table/editor_plugin_src.js b/application/views/scripts/javascripts/vendor/tiny_mce/plugins/table/editor_plugin_src.js index dc6a53a6e4..045648376d 100644 --- a/application/views/scripts/javascripts/vendor/tiny_mce/plugins/table/editor_plugin_src.js +++ b/application/views/scripts/javascripts/vendor/tiny_mce/plugins/table/editor_plugin_src.js @@ -7,7 +7,7 @@ * License: http://tinymce.moxiecode.com/license * Contributing: http://tinymce.moxiecode.com/contributing */ -/* jshint loopfunc: true */ + (function(tinymce) { var each = tinymce.each; @@ -22,11 +22,11 @@ elm.appendChild(rng2.cloneContents()); // Check for text characters of other elements that should be treated as content - return elm.innerHTML.replace(/<(br|img|object|embed|input|textarea)[^>]*>/gi, '-').replace(/<[^>]+>/g, '').length === 0; - } + return elm.innerHTML.replace(/<(br|img|object|embed|input|textarea)[^>]*>/gi, '-').replace(/<[^>]+>/g, '').length == 0; + }; function getSpanVal(td, name) { - return parseInt(td.getAttribute(name) || 1, 10); + return parseInt(td.getAttribute(name) || 1); } /** @@ -35,6 +35,14 @@ function TableGrid(table, dom, selection) { var grid, startPos, endPos, selectedCell; + buildGrid(); + selectedCell = dom.getParent(selection.getStart(), 'th,td'); + if (selectedCell) { + startPos = getPos(selectedCell); + endPos = findEndPos(); + selectedCell = getCell(startPos.x, startPos.y); + } + function cloneNode(node, children) { node = node.cloneNode(children); node.removeAttribute('id'); @@ -58,9 +66,8 @@ // Skip over existing cells produced by rowspan if (grid[y]) { - while (grid[y][x]) { + while (grid[y][x]) x++; - } } // Get col/rowspan from cell @@ -69,9 +76,8 @@ // Fill out rowspan/colspan right and down for (y2 = y; y2 < y + rowspan; y2++) { - if (!grid[y2]) { + if (!grid[y2]) grid[y2] = []; - } for (x2 = x; x2 < x + colspan; x2++) { grid[y2][x2] = { @@ -88,32 +94,30 @@ startY += rows.length; }); - } + }; function getCell(x, y) { var row; row = grid[y]; - if (row) { + if (row) return row[x]; - } - } + }; function setSpanVal(td, name, val) { if (td) { - val = parseInt(val, 10); + val = parseInt(val); - if (val === 1) { + if (val === 1) td.removeAttribute(name, 1); - } else { + else td.setAttribute(name, val, 1); - } } } function isCellSelected(cell) { return cell && (dom.hasClass(cell.elm, 'mceSelected') || cell == selectedCell); - } + }; function getSelectedRows() { var rows = []; @@ -128,7 +132,7 @@ }); return rows; - } + }; function deleteTable() { var rng = dom.createRng(); @@ -139,7 +143,7 @@ selection.setRng(rng); dom.remove(table); - } + }; function cloneCell(cell) { var formatNode; @@ -152,19 +156,17 @@ each(dom.getParents(node.parentNode, null, cell).reverse(), function(node) { node = cloneNode(node, false); - if (!formatNode) { + if (!formatNode) formatNode = curNode = node; - } else if (curNode) { + else if (curNode) curNode.appendChild(node); - } curNode = node; }); // Add something to the inner node - if (curNode) { + if (curNode) curNode.innerHTML = tinymce.isIE && !tinymce.isIE11 ? ' ' : '
'; - } return false; } @@ -177,26 +179,24 @@ if (formatNode) { cell.appendChild(formatNode); } else { - if (!tinymce.isIE || tinymce.isIE11) { + if (!tinymce.isIE || tinymce.isIE11) cell.innerHTML = '
'; - } } return cell; - } + }; function cleanup() { - var rng = dom.createRng(), row; + var rng = dom.createRng(); // Empty rows each(dom.select('tr', table), function(tr) { - if (tr.cells.length === 0) { + if (tr.cells.length == 0) dom.remove(tr); - } }); // Empty table - if (dom.select('tr', table).length === 0) { + if (dom.select('tr', table).length == 0) { rng.setStartAfter(table); rng.setEndAfter(table); selection.setRng(rng); @@ -206,9 +206,8 @@ // Empty header/body/footer each(dom.select('thead,tbody,tfoot', table), function(part) { - if (part.rows.length === 0) { + if (part.rows.length == 0) dom.remove(part); - } }); // Restore selection to start position if it still exists @@ -220,7 +219,7 @@ selection.select(row[Math.min(row.length - 1, startPos.x)].elm, true); selection.collapse(true); } - } + }; function fillLeftDown(x, y, rows, cols) { var tr, x2, r, c, cell; @@ -236,9 +235,8 @@ if (cell.parentNode == tr) { // Append clones after - for (c = 1; c <= cols; c++) { + for (c = 1; c <= cols; c++) dom.insertAfter(cloneCell(cell), cell); - } break; } @@ -246,18 +244,17 @@ if (x2 == -1) { // Insert nodes before first cell - for (c = 1; c <= cols; c++) { + for (c = 1; c <= cols; c++) tr.insertBefore(cloneCell(tr.cells[0]), tr.cells[0]); - } } } } - } + }; function split() { each(grid, function(row, y) { each(row, function(cell, x) { - var colSpan, rowSpan, i; + var colSpan, rowSpan, newCell, i; if (isCellSelected(cell)) { cell = cell.elm; @@ -269,19 +266,18 @@ setSpanVal(cell, 'colSpan', 1); // Insert cells right - for (i = 0; i < colSpan - 1; i++) { + for (i = 0; i < colSpan - 1; i++) dom.insertAfter(cloneCell(cell), cell); - } fillLeftDown(x, y, rowSpan - 1, colSpan); } } }); }); - } + }; function merge(cell, cols, rows) { - var startX, startY, endX, endY, x, y, startCell, endCell, children, count, pos; + var startX, startY, endX, endY, x, y, startCell, endCell, cell, children, count; // Use specified cell and cols/rows if (cell) { @@ -331,9 +327,8 @@ // Remove other cells and add it's contents to the start cell for (y = startY; y <= endY; y++) { for (x = startX; x <= endX; x++) { - if (!grid[y] || !grid[y][x]) { + if (!grid[y] || !grid[y][x]) continue; - } cell = grid[y][x].elm; @@ -349,12 +344,11 @@ children = tinymce.grep(startCell.childNodes); count = 0; each(children, function(node) { - if (node.nodeName == 'BR' && dom.getAttrib(node, 'data-mce-bogus') && count++ < children.length - 1) { + if (node.nodeName == 'BR' && dom.getAttrib(node, 'data-mce-bogus') && count++ < children.length - 1) startCell.removeChild(node); - } }); } - + // Remove cell dom.remove(cell); } @@ -364,36 +358,33 @@ // Remove empty rows etc and restore caret location cleanup(); } - } + }; function insertRow(before) { var posY, cell, lastCell, x, rowElm, newRow, newCell, otherCell, rowSpan; // Find first/last row each(grid, function(row, y) { - each(row, function(cell) { + each(row, function(cell, x) { if (isCellSelected(cell)) { cell = cell.elm; rowElm = cell.parentNode; newRow = cloneNode(rowElm, false); posY = y; - if (before) { + if (before) return false; - } } }); - if (before) { + if (before) return !posY; - } }); for (x = 0; x < grid[0].length; x++) { // Cell not found could be because of an invalid table structure - if (!grid[posY][x]) { + if (!grid[posY][x]) continue; - } cell = grid[posY][x].elm; @@ -427,40 +418,36 @@ } if (newRow.hasChildNodes()) { - if (!before) { + if (!before) dom.insertAfter(newRow, rowElm); - } else { + else rowElm.parentNode.insertBefore(newRow, rowElm); - } } - } + }; function insertCol(before) { var posX, lastCell; // Find first/last column - each(grid, function(row) { + each(grid, function(row, y) { each(row, function(cell, x) { if (isCellSelected(cell)) { posX = x; - if (before) { + if (before) return false; - } } }); - if (before) { + if (before) return !posX; - } }); each(grid, function(row, y) { var cell, rowSpan, colSpan; - if (!row[posX]) { + if (!row[posX]) return; - } cell = row[posX].elm; if (cell != lastCell) { @@ -475,20 +462,19 @@ cell.parentNode.insertBefore(cloneCell(cell), cell); fillLeftDown(posX, y, rowSpan - 1, colSpan); } - } else { + } else setSpanVal(cell, 'colSpan', cell.colSpan + 1); - } lastCell = cell; } }); - } + }; function deleteCols() { var cols = []; // Get selected column indexes - each(grid, function(row) { + each(grid, function(row, y) { each(row, function(cell, x) { if (isCellSelected(cell) && tinymce.inArray(cols, x) === -1) { each(grid, function(row) { @@ -496,11 +482,10 @@ colSpan = getSpanVal(cell, 'colSpan'); - if (colSpan > 1) { + if (colSpan > 1) setSpanVal(cell, 'colSpan', colSpan - 1); - } else { + else dom.remove(cell); - } }); cols.push(x); @@ -509,15 +494,15 @@ }); cleanup(); - } + }; function deleteRows() { var rows; function deleteRow(tr) { - var pos, lastCell; + var nextTr, pos, lastCell; - // nextTr = dom.getNext(tr, 'tr'); + nextTr = dom.getNext(tr, 'tr'); // Move down row spanned cells each(tr.cells, function(cell) { @@ -540,16 +525,15 @@ if (cell != lastCell) { rowSpan = getSpanVal(cell, 'rowSpan'); - if (rowSpan <= 1) { + if (rowSpan <= 1) dom.remove(cell); - } else { + else setSpanVal(cell, 'rowSpan', rowSpan - 1); - } lastCell = cell; } }); - } + }; // Get selected rows and move selection out of scope rows = getSelectedRows(); @@ -560,7 +544,7 @@ }); cleanup(); - } + }; function cutRows() { var rows = getSelectedRows(); @@ -569,7 +553,7 @@ cleanup(); return rows; - } + }; function copyRows() { var rows = getSelectedRows(); @@ -579,13 +563,12 @@ }); return rows; - } + }; function pasteRows(rows, before) { // If we don't have any rows in the clipboard, return immediately - if (!rows) { + if(!rows) return; - } var selectedRows = getSelectedRows(), targetRow = selectedRows[before ? 0 : selectedRows.length - 1], @@ -596,27 +579,23 @@ var match; targetCellCount = 0; - each(row, function(cell) { - if (cell.real) { + each(row, function(cell, x) { + if (cell.real) targetCellCount += cell.colspan; - } - if (cell.elm.parentNode == targetRow) { + if (cell.elm.parentNode == targetRow) match = 1; - } }); - if (match) { + if (match) return false; - } }); - if (!before) { + if (!before) rows.reverse(); - } each(rows, function(row) { - var cellCount = row.cells.length, cell, i; + var cellCount = row.cells.length, cell; // Remove col/rowspans for (i = 0; i < cellCount; i++) { @@ -626,26 +605,23 @@ } // Needs more cells - for (i = cellCount; i < targetCellCount; i++) { + for (i = cellCount; i < targetCellCount; i++) row.appendChild(cloneCell(row.cells[cellCount - 1])); - } // Needs less cells - for (i = targetCellCount; i < cellCount; i++) { + for (i = targetCellCount; i < cellCount; i++) dom.remove(row.cells[i]); - } // Add before/after - if (before) { + if (before) targetRow.parentNode.insertBefore(row, targetRow); - } else { + else dom.insertAfter(row, targetRow); - } }); // Remove current selection dom.removeClass(dom.select('td.mceSelected,th.mceSelected'), 'mceSelected'); - } + }; function getPos(target) { var pos; @@ -662,14 +638,14 @@ }); return pos; - } + }; function setStartCell(cell) { startPos = getPos(cell); - } + }; function findEndPos() { - var maxX, maxY; + var pos, maxX, maxY; maxX = maxY = 0; @@ -680,28 +656,24 @@ if (isCellSelected(cell)) { cell = grid[y][x]; - if (x > maxX) { + if (x > maxX) maxX = x; - } - if (y > maxY) { + if (y > maxY) maxY = y; - } if (cell.real) { colSpan = cell.colspan - 1; rowSpan = cell.rowspan - 1; if (colSpan) { - if (x + colSpan > maxX) { + if (x + colSpan > maxX) maxX = x + colSpan; - } } if (rowSpan) { - if (y + rowSpan > maxY) { + if (y + rowSpan > maxY) maxY = y + rowSpan; - } } } } @@ -709,10 +681,10 @@ }); return {x : maxX, y : maxY}; - } + }; function setEndCell(cell) { - var startX, startY, endX, endY, maxX, maxY, colSpan, rowSpan, y, x; + var startX, startY, endX, endY, maxX, maxY, colSpan, rowSpan; endPos = getPos(cell); @@ -732,9 +704,8 @@ cell = grid[y][startX]; if (!cell.real) { - if (startX - (cell.colspan - 1) < startX) { + if (startX - (cell.colspan - 1) < startX) startX -= cell.colspan - 1; - } } } @@ -743,9 +714,8 @@ cell = grid[startY][x]; if (!cell.real) { - if (startY - (cell.rowspan - 1) < startY) { + if (startY - (cell.rowspan - 1) < startY) startY -= cell.rowspan - 1; - } } } @@ -759,15 +729,13 @@ rowSpan = cell.rowspan - 1; if (colSpan) { - if (x + colSpan > maxX) { + if (x + colSpan > maxX) maxX = x + colSpan; - } } if (rowSpan) { - if (y + rowSpan > maxY) { + if (y + rowSpan > maxY) maxY = y + rowSpan; - } } } } @@ -779,21 +747,12 @@ // Add new selection for (y = startY; y <= maxY; y++) { for (x = startX; x <= maxX; x++) { - if (grid[y][x]) { + if (grid[y][x]) dom.addClass(grid[y][x].elm, 'mceSelected'); - } } } } - } - - buildGrid(); - selectedCell = dom.getParent(selection.getStart(), 'th,td'); - if (selectedCell) { - startPos = getPos(selectedCell); - endPos = findEndPos(); - selectedCell = getCell(startPos.x, startPos.y); - } + }; // Expose to public tinymce.extend(this, { @@ -811,7 +770,7 @@ setStartCell : setStartCell, setEndCell : setEndCell }); - } + }; tinymce.create('tinymce.plugins.TablePlugin', { init : function(ed, url) { @@ -820,10 +779,9 @@ function createTableGrid(node) { var selection = ed.selection, tblElm = ed.dom.getParent(node || selection.getNode(), 'table'); - if (tblElm) { + if (tblElm) return new TableGrid(tblElm, ed.dom, selection); - } - } + }; function cleanup() { // Restore selection possibilities @@ -833,7 +791,7 @@ ed.dom.removeClass(ed.dom.select('td.mceSelected,th.mceSelected'), 'mceSelected'); hasCellSelection = false; } - } + }; // Register buttons each([ @@ -895,9 +853,8 @@ cm.setActive('table', n.nodeName === 'TABLE' || !!p); // Disable table tools if we are in caption - if (p && p.nodeName === 'CAPTION') { + if (p && p.nodeName === 'CAPTION') p = 0; - } cm.setDisabled('delete_table', !p); cm.setDisabled('delete_col', !p); @@ -949,11 +906,10 @@ sel = ed.selection.getSel(); try { - if (sel.removeAllRanges) { + if (sel.removeAllRanges) sel.removeAllRanges(); - } else { + else sel.empty(); - } } catch (ex) { // IE9 might throw errors here } @@ -962,41 +918,38 @@ } }); - ed.onMouseUp.add(function(ed) { - var rng, sel = ed.selection, selectedCells, walker, node, lastNode; + ed.onMouseUp.add(function(ed, e) { + var rng, sel = ed.selection, selectedCells, nativeSel = sel.getSel(), walker, node, lastNode, endNode; + + // Move selection to startCell + if (startCell) { + if (tableGrid) + ed.getBody().style.webkitUserSelect = ''; - function setPoint(node, start) { - var walker = new tinymce.dom.TreeWalker(node, node); + function setPoint(node, start) { + var walker = new tinymce.dom.TreeWalker(node, node); - do { - // Text node - if (node.nodeType == 3 && tinymce.trim(node.nodeValue).length !== 0) { - if (start) { - rng.setStart(node, 0); - } else { - rng.setEnd(node, node.nodeValue.length); + do { + // Text node + if (node.nodeType == 3 && tinymce.trim(node.nodeValue).length != 0) { + if (start) + rng.setStart(node, 0); + else + rng.setEnd(node, node.nodeValue.length); + + return; } - return; - } + // BR element + if (node.nodeName == 'BR') { + if (start) + rng.setStartBefore(node); + else + rng.setEndBefore(node); - // BR element - if (node.nodeName == 'BR') { - if (start) { - rng.setStartBefore(node); - } else { - rng.setEndBefore(node); + return; } - - return; - } - node = (start ? walker.next() : walker.prev()); - } while (node); - } - // Move selection to startCell - if (startCell) { - if (tableGrid) { - ed.getBody().style.webkitUserSelect = ''; + } while (node = (start ? walker.next() : walker.prev())); } // Try to expand text selection as much as we can only Gecko supports cell selection @@ -1004,7 +957,7 @@ if (selectedCells.length > 0) { rng = dom.createRng(); node = selectedCells[0]; - // endNode = selectedCells[selectedCells.length - 1]; + endNode = selectedCells[selectedCells.length - 1]; rng.setStartBefore(node); rng.setEndAfter(node); @@ -1013,14 +966,12 @@ do { if (node.nodeName == 'TD' || node.nodeName == 'TH') { - if (!dom.hasClass(node, 'mceSelected')) { + if (!dom.hasClass(node, 'mceSelected')) break; - } lastNode = node; } - node = walker.next(); - } while (node); + } while (node = walker.next()); setPoint(lastNode); @@ -1032,68 +983,63 @@ } }); - ed.onKeyUp.add(function() { + ed.onKeyUp.add(function(ed, e) { cleanup(); }); - ed.onKeyDown.add(function(ed) { + ed.onKeyDown.add(function (ed, e) { fixTableCellSelection(ed); }); - ed.onMouseDown.add(function(ed, e) { + ed.onMouseDown.add(function (ed, e) { if (e.button != 2) { fixTableCellSelection(ed); } }); function tableCellSelected(ed, rng, n, currentCell) { // The decision of when a table cell is selected is somewhat involved. The fact that this code is - // required is actually a pointer to the root cause of this bug. A cell is selected when the start + // required is actually a pointer to the root cause of this bug. A cell is selected when the start // and end offsets are 0, the start container is a text, and the selection node is either a TR (most cases) // or the parent of the table (in the case of the selection containing the last cell of a table). - var TEXT_NODE = 3, table = ed.dom.getParent(rng.startContainer, 'TABLE'), - tableParent, allOfCellSelected, tableCellSelection; - if (table) { - tableParent = table.parentNode; - } - allOfCellSelected = rng.startContainer.nodeType == TEXT_NODE && - rng.startOffset === 0 && - rng.endOffset === 0 && - currentCell && - (n.nodeName === "TR" || n === tableParent); - tableCellSelection = (n.nodeName === "TD" || n.nodeName === "TH") && !currentCell; - return allOfCellSelected || tableCellSelection; + var TEXT_NODE = 3, table = ed.dom.getParent(rng.startContainer, 'TABLE'), + tableParent, allOfCellSelected, tableCellSelection; + if (table) + tableParent = table.parentNode; + allOfCellSelected =rng.startContainer.nodeType == TEXT_NODE && + rng.startOffset == 0 && + rng.endOffset == 0 && + currentCell && + (n.nodeName=="TR" || n==tableParent); + tableCellSelection = (n.nodeName=="TD"||n.nodeName=="TH")&& !currentCell; + return allOfCellSelected || tableCellSelection; // return false; } - + // this nasty hack is here to work around some WebKit selection bugs. function fixTableCellSelection(ed) { - if (!tinymce.isWebKit) { + if (!tinymce.isWebKit) return; - } var rng = ed.selection.getRng(); var n = ed.selection.getNode(); var currentCell = ed.dom.getParent(rng.startContainer, 'TD,TH'); - - if (!tableCellSelected(ed, rng, n, currentCell)) { + + if (!tableCellSelected(ed, rng, n, currentCell)) return; - } - - if (!currentCell) { - currentCell = n; - } - + if (!currentCell) { + currentCell=n; + } + // Get the very last node inside the table cell var end = currentCell.lastChild; - while (end.lastChild) { + while (end.lastChild) end = end.lastChild; - } - + // Select the entire table cell. Nothing outside of the table cell should be selected. rng.setEnd(end, end.nodeValue.length); ed.selection.setRng(rng); } - ed.plugins.table.fixTableCellSelection = fixTableCellSelection; + ed.plugins.table.fixTableCellSelection=fixTableCellSelection; // Add context menu if (ed && ed.plugins.contextmenu) { @@ -1142,157 +1088,154 @@ sm.add({title : 'table.col_before_desc', icon : 'col_before', cmd : 'mceTableInsertColBefore'}); sm.add({title : 'table.col_after_desc', icon : 'col_after', cmd : 'mceTableInsertColAfter'}); sm.add({title : 'table.delete_col_desc', icon : 'delete_col', cmd : 'mceTableDeleteCol'}); - } else { + } else m.add({title : 'table.desc', icon : 'table', cmd : 'mceInsertTable'}); - } }); } // Fix to allow navigating up and down in a table in WebKit browsers. - function moveSelection(ed, e) { - var VK = tinymce.VK; - var key = e.keyCode; - - function handle(upBool, sourceNode, event) { - var siblingDirection = upBool ? 'previousSibling' : 'nextSibling'; - var currentRow = ed.dom.getParent(sourceNode, 'tr'); - var siblingRow = currentRow[siblingDirection]; - - if (siblingRow) { - moveCursorToRow(ed, sourceNode, siblingRow, upBool); - tinymce.dom.Event.cancel(event); - return true; - } else { - var tableNode = ed.dom.getParent(currentRow, 'table'); - var middleNode = currentRow.parentNode; - var parentNodeName = middleNode.nodeName.toLowerCase(); - if (parentNodeName === 'tbody' || parentNodeName === (upBool ? 'tfoot' : 'thead')) { - var targetParent = getTargetParent(upBool, tableNode, middleNode, 'tbody'); - if (targetParent !== null) { - return moveToRowInTarget(upBool, targetParent, sourceNode, event); + if (tinymce.isWebKit) { + function moveSelection(ed, e) { + var VK = tinymce.VK; + var key = e.keyCode; + + function handle(upBool, sourceNode, event) { + var siblingDirection = upBool ? 'previousSibling' : 'nextSibling'; + var currentRow = ed.dom.getParent(sourceNode, 'tr'); + var siblingRow = currentRow[siblingDirection]; + + if (siblingRow) { + moveCursorToRow(ed, sourceNode, siblingRow, upBool); + tinymce.dom.Event.cancel(event); + return true; + } else { + var tableNode = ed.dom.getParent(currentRow, 'table'); + var middleNode = currentRow.parentNode; + var parentNodeName = middleNode.nodeName.toLowerCase(); + if (parentNodeName === 'tbody' || parentNodeName === (upBool ? 'tfoot' : 'thead')) { + var targetParent = getTargetParent(upBool, tableNode, middleNode, 'tbody'); + if (targetParent !== null) { + return moveToRowInTarget(upBool, targetParent, sourceNode, event); + } } + return escapeTable(upBool, currentRow, siblingDirection, tableNode, event); } - return escapeTable(upBool, currentRow, siblingDirection, tableNode, event); } - } - function getTargetParent(upBool, topNode, secondNode, nodeName) { - var tbodies = ed.dom.select('>' + nodeName, topNode); - var position = tbodies.indexOf(secondNode); - if (upBool && position === 0 || !upBool && position === tbodies.length - 1) { - return getFirstHeadOrFoot(upBool, topNode); - } else if (position === -1) { - var topOrBottom = secondNode.tagName.toLowerCase() === 'thead' ? 0 : tbodies.length - 1; - return tbodies[topOrBottom]; - } else { - return tbodies[position + (upBool ? -1 : 1)]; + function getTargetParent(upBool, topNode, secondNode, nodeName) { + var tbodies = ed.dom.select('>' + nodeName, topNode); + var position = tbodies.indexOf(secondNode); + if (upBool && position === 0 || !upBool && position === tbodies.length - 1) { + return getFirstHeadOrFoot(upBool, topNode); + } else if (position === -1) { + var topOrBottom = secondNode.tagName.toLowerCase() === 'thead' ? 0 : tbodies.length - 1; + return tbodies[topOrBottom]; + } else { + return tbodies[position + (upBool ? -1 : 1)]; + } } - } - - function getFirstHeadOrFoot(upBool, parent) { - var tagName = upBool ? 'thead' : 'tfoot'; - var headOrFoot = ed.dom.select('>' + tagName, parent); - return headOrFoot.length !== 0 ? headOrFoot[0] : null; - } - function moveToRowInTarget(upBool, targetParent, sourceNode, event) { - var targetRow = getChildForDirection(targetParent, upBool); - if (targetRow) { - moveCursorToRow(ed, sourceNode, targetRow, upBool); + function getFirstHeadOrFoot(upBool, parent) { + var tagName = upBool ? 'thead' : 'tfoot'; + var headOrFoot = ed.dom.select('>' + tagName, parent); + return headOrFoot.length !== 0 ? headOrFoot[0] : null; } - tinymce.dom.Event.cancel(event); - return true; - } - function escapeTable(upBool, currentRow, siblingDirection, table, event) { - var tableSibling = table[siblingDirection]; - if (tableSibling) { - moveCursorToStartOfElement(tableSibling); + function moveToRowInTarget(upBool, targetParent, sourceNode, event) { + var targetRow = getChildForDirection(targetParent, upBool); + targetRow && moveCursorToRow(ed, sourceNode, targetRow, upBool); + tinymce.dom.Event.cancel(event); return true; - } else { - var parentCell = ed.dom.getParent(table, 'td,th'); - if (parentCell) { - return handle(upBool, parentCell, event); + } + + function escapeTable(upBool, currentRow, siblingDirection, table, event) { + var tableSibling = table[siblingDirection]; + if (tableSibling) { + moveCursorToStartOfElement(tableSibling); + return true; } else { - var backUpSibling = getChildForDirection(currentRow, !upBool); - moveCursorToStartOfElement(backUpSibling); - return tinymce.dom.Event.cancel(event); + var parentCell = ed.dom.getParent(table, 'td,th'); + if (parentCell) { + return handle(upBool, parentCell, event); + } else { + var backUpSibling = getChildForDirection(currentRow, !upBool); + moveCursorToStartOfElement(backUpSibling); + return tinymce.dom.Event.cancel(event); + } } } - } - function getChildForDirection(parent, up) { - var child = parent && parent[up ? 'lastChild' : 'firstChild']; - // BR is not a valid table child to return in this case we return the table cell - return child && child.nodeName === 'BR' ? ed.dom.getParent(child, 'td,th') : child; - } - - function moveCursorToStartOfElement(n) { - ed.selection.setCursorLocation(n, 0); - } + function getChildForDirection(parent, up) { + var child = parent && parent[up ? 'lastChild' : 'firstChild']; + // BR is not a valid table child to return in this case we return the table cell + return child && child.nodeName === 'BR' ? ed.dom.getParent(child, 'td,th') : child; + } - function isVerticalMovement() { - return key == VK.UP || key == VK.DOWN; - } + function moveCursorToStartOfElement(n) { + ed.selection.setCursorLocation(n, 0); + } - function isInTable(ed) { - var node = ed.selection.getNode(); - var currentRow = ed.dom.getParent(node, 'tr'); - return currentRow !== null; - } + function isVerticalMovement() { + return key == VK.UP || key == VK.DOWN; + } - function columnIndex(column) { - var colIndex = 0; - var c = column; - while (c.previousSibling) { - c = c.previousSibling; - colIndex = colIndex + getSpanVal(c, "colspan"); + function isInTable(ed) { + var node = ed.selection.getNode(); + var currentRow = ed.dom.getParent(node, 'tr'); + return currentRow !== null; } - return colIndex; - } - function findColumn(rowElement, columnIndex) { - var c = 0; - var r = 0; - each(rowElement.children, function(cell, i) { - c = c + getSpanVal(cell, "colspan"); - r = i; - if (c > columnIndex) { - return false; + function columnIndex(column) { + var colIndex = 0; + var c = column; + while (c.previousSibling) { + c = c.previousSibling; + colIndex = colIndex + getSpanVal(c, "colspan"); } - }); - return r; - } + return colIndex; + } - function moveCursorToRow(ed, node, row, upBool) { - var srcColumnIndex = columnIndex(ed.dom.getParent(node, 'td,th')); - var tgtColumnIndex = findColumn(row, srcColumnIndex); - var tgtNode = row.childNodes[tgtColumnIndex]; - var rowCellTarget = getChildForDirection(tgtNode, upBool); - moveCursorToStartOfElement(rowCellTarget || tgtNode); - } + function findColumn(rowElement, columnIndex) { + var c = 0; + var r = 0; + each(rowElement.children, function(cell, i) { + c = c + getSpanVal(cell, "colspan"); + r = i; + if (c > columnIndex) + return false; + }); + return r; + } - function shouldFixCaret(preBrowserNode) { - var newNode = ed.selection.getNode(); - var newParent = ed.dom.getParent(newNode, 'td,th'); - var oldParent = ed.dom.getParent(preBrowserNode, 'td,th'); - return newParent && newParent !== oldParent && checkSameParentTable(newParent, oldParent); - } + function moveCursorToRow(ed, node, row, upBool) { + var srcColumnIndex = columnIndex(ed.dom.getParent(node, 'td,th')); + var tgtColumnIndex = findColumn(row, srcColumnIndex); + var tgtNode = row.childNodes[tgtColumnIndex]; + var rowCellTarget = getChildForDirection(tgtNode, upBool); + moveCursorToStartOfElement(rowCellTarget || tgtNode); + } - function checkSameParentTable(nodeOne, NodeTwo) { - return ed.dom.getParent(nodeOne, 'TABLE') === ed.dom.getParent(NodeTwo, 'TABLE'); - } + function shouldFixCaret(preBrowserNode) { + var newNode = ed.selection.getNode(); + var newParent = ed.dom.getParent(newNode, 'td,th'); + var oldParent = ed.dom.getParent(preBrowserNode, 'td,th'); + return newParent && newParent !== oldParent && checkSameParentTable(newParent, oldParent) + } - if (isVerticalMovement() && isInTable(ed)) { - var preBrowserNode = ed.selection.getNode(); - setTimeout(function() { - if (shouldFixCaret(preBrowserNode)) { - handle(!e.shiftKey && key === VK.UP, preBrowserNode, e); - } - }, 0); + function checkSameParentTable(nodeOne, NodeTwo) { + return ed.dom.getParent(nodeOne, 'TABLE') === ed.dom.getParent(NodeTwo, 'TABLE'); + } + + if (isVerticalMovement() && isInTable(ed)) { + var preBrowserNode = ed.selection.getNode(); + setTimeout(function() { + if (shouldFixCaret(preBrowserNode)) { + handle(!e.shiftKey && key === VK.UP, preBrowserNode, e); + } + }, 0); + } } - } - if (tinymce.isWebKit) { + ed.onKeyDown.add(moveSelection); } @@ -1302,19 +1245,15 @@ var last; // Skip empty text nodes form the end - last = ed.getBody().lastChild; - while (last && last.nodeType == 3 && !last.nodeValue.length) { - last = last.previousSibling; - } + for (last = ed.getBody().lastChild; last && last.nodeType == 3 && !last.nodeValue.length; last = last.previousSibling) ; - if (last && last.nodeName === 'TABLE') { - if (ed.settings.forced_root_block) { + if (last && last.nodeName == 'TABLE') { + if (ed.settings.forced_root_block) ed.dom.add(ed.getBody(), ed.settings.forced_root_block, null, tinymce.isIE && !tinymce.isIE11 ? ' ' : '
'); - } else { + else ed.dom.add(ed.getBody(), 'br', {'data-mce-bogus': '1'}); - } } - } + }; // Fixes an bug where it's impossible to place the caret before a table in Gecko // this fix solves it by detecting when the caret is at the beginning of such a table @@ -1356,6 +1295,7 @@ } }); + /** * Fixes bug in Gecko where shift-enter in table cell does not place caret on new line * @@ -1398,8 +1338,8 @@ if (!ed.dom.select('td.mceSelected,th.mceSelected').length) { winMan.open({ url : url + '/merge_cells.htm', - width : 240 + parseInt(ed.getLang('table.merge_cells_delta_width', 0), 10), - height : 110 + parseInt(ed.getLang('table.merge_cells_delta_height', 0), 10), + width : 240 + parseInt(ed.getLang('table.merge_cells_delta_width', 0)), + height : 110 + parseInt(ed.getLang('table.merge_cells_delta_height', 0)), inline : 1 }, { rows : rowSpan, @@ -1409,9 +1349,8 @@ }, plugin_url : url }); - } else { + } else grid.merge(); - } }, mceTableInsertRowBefore : function(grid) { @@ -1474,8 +1413,8 @@ mceInsertTable : function(val) { winMan.open({ url : url + '/table.htm', - width : 400 + parseInt(ed.getLang('table.table_delta_width', 0), 10), - height : 320 + parseInt(ed.getLang('table.table_delta_height', 0), 10), + width : 400 + parseInt(ed.getLang('table.table_delta_width', 0)), + height : 320 + parseInt(ed.getLang('table.table_delta_height', 0)), inline : 1 }, { plugin_url : url, @@ -1486,8 +1425,8 @@ mceTableRowProps : function() { winMan.open({ url : url + '/row.htm', - width : 400 + parseInt(ed.getLang('table.rowprops_delta_width', 0), 10), - height : 295 + parseInt(ed.getLang('table.rowprops_delta_height', 0), 10), + width : 400 + parseInt(ed.getLang('table.rowprops_delta_width', 0)), + height : 295 + parseInt(ed.getLang('table.rowprops_delta_height', 0)), inline : 1 }, { plugin_url : url @@ -1497,8 +1436,8 @@ mceTableCellProps : function() { winMan.open({ url : url + '/cell.htm', - width : 400 + parseInt(ed.getLang('table.cellprops_delta_width', 0), 10), - height : 295 + parseInt(ed.getLang('table.cellprops_delta_height', 0), 10), + width : 400 + parseInt(ed.getLang('table.cellprops_delta_width', 0)), + height : 295 + parseInt(ed.getLang('table.cellprops_delta_height', 0)), inline : 1 }, { plugin_url : url diff --git a/application/views/scripts/javascripts/vendor/tiny_mce/plugins/table/js/cell.js b/application/views/scripts/javascripts/vendor/tiny_mce/plugins/table/js/cell.js index d68dc07a91..02ecf22c8a 100644 --- a/application/views/scripts/javascripts/vendor/tiny_mce/plugins/table/js/cell.js +++ b/application/views/scripts/javascripts/vendor/tiny_mce/plugins/table/js/cell.js @@ -17,8 +17,8 @@ function init() { // Get table cell data var celltype = tdElm.nodeName.toLowerCase(); - var align = ed.dom.getAttrib(tdElm, 'align') || getStyle(tdElm, 'text-align'); - var valign = ed.dom.getAttrib(tdElm, 'valign') || getStyle(tdElm, 'vertical-align'); + var align = ed.dom.getAttrib(tdElm, 'align'); + var valign = ed.dom.getAttrib(tdElm, 'valign'); var width = trimSize(getStyle(tdElm, 'width', 'width')); var height = trimSize(getStyle(tdElm, 'height', 'height')); var bordercolor = convertRGBToHex(getStyle(tdElm, 'bordercolor', 'borderLeftColor')); @@ -201,6 +201,8 @@ function updateCell(td, skip_id) { if (!skip_id) dom.setAttrib(td, 'id', formObj.id.value); + dom.setAttrib(td, 'align', formObj.align.value); + dom.setAttrib(td, 'vAlign', formObj.valign.value); dom.setAttrib(td, 'lang', formObj.lang.value); dom.setAttrib(td, 'dir', getSelectValue(formObj, 'dir')); dom.setAttrib(td, 'style', ed.dom.serializeStyle(ed.dom.parseStyle(formObj.style.value))); @@ -208,8 +210,6 @@ function updateCell(td, skip_id) { dom.setAttrib(td, 'class', getSelectValue(formObj, 'class')); // Clear deprecated attributes - ed.dom.setAttrib(td, 'align', ''); - ed.dom.setAttrib(td, 'vAlign', ''); ed.dom.setAttrib(td, 'width', ''); ed.dom.setAttrib(td, 'height', ''); ed.dom.setAttrib(td, 'bgColor', ''); @@ -219,9 +219,13 @@ function updateCell(td, skip_id) { // Set styles td.style.width = getCSSSize(formObj.width.value); td.style.height = getCSSSize(formObj.height.value); - td.style.textAlign = formObj.align.value; - td.style.verticalAlign = formObj.valign.value; - td.style.borderColor = formObj.bordercolor.value; + if (formObj.bordercolor.value != "") { + td.style.borderColor = formObj.bordercolor.value; + td.style.borderStyle = td.style.borderStyle == "" ? "solid" : td.style.borderStyle; + td.style.borderWidth = td.style.borderWidth == "" ? "1px" : td.style.borderWidth; + } else + td.style.borderColor = ''; + td.style.backgroundColor = formObj.bgcolor.value; if (formObj.backgroundimage.value != "") @@ -310,12 +314,6 @@ function changedStyle() { formObj.bordercolor.value = st['border-color']; updateColor('bordercolor_pick','bordercolor'); } - - if (st['text-align']) - formObj.align.value = st['text-align']; - - if (st['vertical-align']) - formObj.valign.value = st['vertical-align']; } tinyMCEPopup.onInit.add(init); diff --git a/application/views/scripts/javascripts/vendor/tiny_mce/plugins/table/js/table.js b/application/views/scripts/javascripts/vendor/tiny_mce/plugins/table/js/table.js index 545d720c1f..f427f5f87e 100644 --- a/application/views/scripts/javascripts/vendor/tiny_mce/plugins/table/js/table.js +++ b/application/views/scripts/javascripts/vendor/tiny_mce/plugins/table/js/table.js @@ -8,7 +8,6 @@ function insertTable() { var cols = 2, rows = 2, border = 0, cellpadding = -1, cellspacing = -1, align, width, height, className, caption, frame, rules; var html = '', capEl, elm; var cellLimit, rowLimit, colLimit; - var cellStyles, newCellStyles, parsedStyles; tinyMCEPopup.restoreSelection(); @@ -22,9 +21,9 @@ function insertTable() { // Get form data cols = formObj.elements['cols'].value; rows = formObj.elements['rows'].value; - border = formObj.elements['border'].value !== "" ? formObj.elements['border'].value : ""; - cellpadding = formObj.elements['cellpadding'].value !== "" ? formObj.elements['cellpadding'].value : ""; - cellspacing = formObj.elements['cellspacing'].value !== "" ? formObj.elements['cellspacing'].value : ""; + border = formObj.elements['border'].value != "" ? formObj.elements['border'].value : 0; + cellpadding = formObj.elements['cellpadding'].value != "" ? formObj.elements['cellpadding'].value : ""; + cellspacing = formObj.elements['cellspacing'].value != "" ? formObj.elements['cellspacing'].value : ""; align = getSelectValue(formObj, "align"); frame = getSelectValue(formObj, "tframe"); rules = getSelectValue(formObj, "rules"); @@ -59,6 +58,20 @@ function insertTable() { // Update table if (action == "update") { + dom.setAttrib(elm, 'cellPadding', cellpadding, true); + dom.setAttrib(elm, 'cellSpacing', cellspacing, true); + + if (!isCssSize(border)) { + dom.setAttrib(elm, 'border', border); + } else { + dom.setAttrib(elm, 'border', ''); + } + + if (border == '') { + dom.setStyle(elm, 'border-width', ''); + dom.setStyle(elm, 'border', ''); + dom.setAttrib(elm, 'border', ''); + } dom.setAttrib(elm, 'align', align); dom.setAttrib(elm, 'frame', frame); @@ -115,54 +128,12 @@ function insertTable() { elm.style.width = getCSSSize(width); }*/ - if (!inst.settings.table_style_by_css) { - dom.setAttrib(elm, 'cellPadding', nonCssSize(cellpadding), true); - } else { - dom.setAttrib(elm, 'cellPadding', ''); - } - - if (cellspacing !== "") { - elm.style.borderSpacing = cssSize(cellspacing); - } else { - elm.style.borderSpacing = ""; - } - - if (!inst.settings.table_style_by_css && !isCssSize(border)) { - dom.setAttrib(elm, 'border', border); - } else if (inst.settings.table_style_by_css || (border !== '' && isCssSize(border))) { - dom.setAttrib(elm, 'border', ''); - } - - if (border === "") { - dom.setStyle(elm, 'border-width', ''); - dom.setStyle(elm, 'border', ''); - dom.setAttrib(elm, 'border', ''); - } - - elm.style.borderColor = bordercolor; - - if (inst.settings.table_style_by_css) { - - parsedStyles = dom.parseStyle(style); - - if (parsedStyles.border) { - styleTDTH(elm, "border", parsedStyles.border); - } - if (border !== "") { - styleTDTH(elm, "border-width", cssSize(border)); - } else { - styleTDTH(elm, "border-width", ''); - } - if (cellpadding !== "") { - styleTDTH(elm, "padding", cssSize(cellpadding)); - } else { - styleTDTH(elm, "padding", ''); - } - - styleTDTH(elm, "border-color", bordercolor); - - styleTDTH(elm, "border-style", elm.style.borderStyle); - } + if (bordercolor != "") { + elm.style.borderColor = bordercolor; + elm.style.borderStyle = elm.style.borderStyle == "" ? "solid" : elm.style.borderStyle; + elm.style.borderWidth = cssSize(border); + } else + elm.style.borderColor = ''; elm.style.backgroundColor = bgcolor; elm.style.height = getCSSSize(height); @@ -187,14 +158,12 @@ function insertTable() { html += '
'; + html += '
'; else - html += ''; + html += ''; } html += ""; @@ -316,7 +254,7 @@ function insertTable() { } try { - // IE9 might fail to do this selection + // IE9 might fail to do this selection inst.selection.setCursorLocation(tdorth[0], 0); } catch (ex) { // Ignore @@ -331,42 +269,6 @@ function insertTable() { tinyMCEPopup.close(); } -function styleTDTH (elm, name, value) { - if (elm.tagName === "TD" || elm.tagName === "TH") { - dom.setStyle(elm, name, value); - } else { - if (elm.children) { - for (var i = 0; i < elm.children.length; i++) { - styleTDTH(elm.children[i], name, value); - } - } - } -} - -function getTDTHOverallStyle (elm, name) { - var cells = dom.select("td,th", elm), firstChildStyle; - - function checkChildren(firstChildStyle, elms) { - - for (var i = 0; i < elms.length; i++) { - var currentStyle = dom.getStyle(elms[i], name); - if (typeof firstChildStyle === "undefined") { - firstChildStyle = currentStyle; - } - if (firstChildStyle != currentStyle) { - return ""; - } - } - - return firstChildStyle; - - } - - firstChildStyle = checkChildren(firstChildStyle, cells); - - return firstChildStyle; -} - function makeAttrib(attrib, value) { var formObj = document.forms[0]; var valueElm = formObj.elements[attrib]; @@ -398,9 +300,9 @@ function init() { document.getElementById('bordercolor_pickcontainer').innerHTML = getColorPickerHTML('bordercolor_pick','bordercolor'); document.getElementById('bgcolor_pickcontainer').innerHTML = getColorPickerHTML('bgcolor_pick','bgcolor'); - var cols = 2, rows = 2, border = tinyMCEPopup.getParam('table_default_border', ''), cellpadding = tinyMCEPopup.getParam('table_default_cellpadding', ''), cellspacing = tinyMCEPopup.getParam('table_default_cellspacing', ''); + var cols = 2, rows = 2, border = tinyMCEPopup.getParam('table_default_border', '0'), cellpadding = tinyMCEPopup.getParam('table_default_cellpadding', ''), cellspacing = tinyMCEPopup.getParam('table_default_cellspacing', ''); var align = "", width = "", height = "", bordercolor = "", bgcolor = "", className = ""; - var id = "", summary = "", style = "", dir = "", lang = "", background = "", rules = "", frame = ""; + var id = "", summary = "", style = "", dir = "", lang = "", background = "", bgcolor = "", bordercolor = "", rules = "", frame = ""; var inst = tinyMCEPopup.editor, dom = inst.dom; var formObj = document.forms[0]; var elm = dom.getParent(inst.selection.getNode(), "table"); @@ -421,7 +323,7 @@ function init() { if (elm && action != "insert") { var rowsAr = elm.rows; - cols = 0; + var cols = 0; for (var i=0; i cols) cols = rowsAr[i].cells.length; @@ -431,8 +333,8 @@ function init() { st = dom.parseStyle(dom.getAttrib(elm, "style")); border = trimSize(getStyle(elm, 'border', 'borderWidth')); - cellpadding = dom.getAttrib(elm, 'cellpadding', '') || getTDTHOverallStyle(elm, 'padding'); - cellspacing = dom.getAttrib(elm, 'cellspacing', '') || trimSize(getStyle(elm, 'border-spacing')); + cellpadding = dom.getAttrib(elm, 'cellpadding', ""); + cellspacing = dom.getAttrib(elm, 'cellspacing', ""); width = trimSize(getStyle(elm, 'width', 'width')); height = trimSize(getStyle(elm, 'height', 'height')); bordercolor = convertRGBToHex(getStyle(elm, 'bordercolor', 'borderLeftColor')); @@ -527,11 +429,6 @@ function cssSize(value, def) { return value; } -function nonCssSize(value) { - var parsedInt = parseInt(value, 10) || ""; - return parsedInt.toString(); -} - function changedBackgroundImage() { var formObj = document.forms[0]; var st = dom.parseStyle(formObj.style.value); @@ -546,7 +443,7 @@ function changedBorder() { var st = dom.parseStyle(formObj.style.value); // Update border width if the element has a color - if (formObj.border.value !== "" && (tinyMCEPopup.editor.settings.table_style_by_css || isCssSize(formObj.border.value))) + if (formObj.border.value != "" && (isCssSize(formObj.border.value) || formObj.bordercolor.value != "")) st['border-width'] = cssSize(formObj.border.value); else { if (!formObj.border.value) { @@ -558,26 +455,19 @@ function changedBorder() { formObj.style.value = dom.serializeStyle(st); } -function changedCellSpacing() { - var formObj = document.forms[0]; - var st = dom.parseStyle(formObj.style.value); - - if (formObj.cellspacing.value !== "") - st['border-spacing'] = cssSize(formObj.cellspacing.value); - else { - st['border-spacing'] = ''; - } - - formObj.style.value = dom.serializeStyle(st); -} - function changedColor() { var formObj = document.forms[0]; var st = dom.parseStyle(formObj.style.value); st['background-color'] = formObj.bgcolor.value; - st['border-color'] = formObj.bordercolor.value; + if (formObj.bordercolor.value != "") { + st['border-color'] = formObj.bordercolor.value; + + // Add border-width if it's missing + if (!st['border-width']) + st['border-width'] = cssSize(formObj.border.value, 1); + } formObj.style.value = dom.serializeStyle(st); } diff --git a/application/views/scripts/javascripts/vendor/tiny_mce/plugins/table/table.htm b/application/views/scripts/javascripts/vendor/tiny_mce/plugins/table/table.htm index 1cedbf130b..b92fa741eb 100644 --- a/application/views/scripts/javascripts/vendor/tiny_mce/plugins/table/table.htm +++ b/application/views/scripts/javascripts/vendor/tiny_mce/plugins/table/table.htm @@ -33,9 +33,9 @@ - + - + @@ -62,8 +62,8 @@ - - + + @@ -75,13 +75,13 @@ - - + + - - + + @@ -90,14 +90,14 @@ - + + - + + - + + - + + - + + - + + - + +
-
@@ -105,54 +105,54 @@
 
-
- - - - - - - - - + + + + + + + + -
- + -
- + + + -
@@ -160,11 +160,11 @@
 
-
@@ -172,7 +172,7 @@
 
-
diff --git a/application/views/scripts/javascripts/vendor/tiny_mce/themes/advanced/editor_template.js b/application/views/scripts/javascripts/vendor/tiny_mce/themes/advanced/editor_template.js index 16c17134f8..4b8d563757 100644 --- a/application/views/scripts/javascripts/vendor/tiny_mce/themes/advanced/editor_template.js +++ b/application/views/scripts/javascripts/vendor/tiny_mce/themes/advanced/editor_template.js @@ -1 +1 @@ -(function(i){var k=i.DOM,h=i.dom.Event,c=i.extend,f=i.each,a=i.util.Cookie,e,d=i.explode;var g=function(m,n){var o=n.theme_advanced_default_font_size;var l=n.theme_advanced_default_font_family;if(o){m.style.fontSize=o}if(l){m.style.fontFamily=l}};var j=function(m){var n=m.theme_advanced_default_font_size;var l=m.theme_advanced_default_font_family;return !!(n||l)};function b(r,o){var m,n,q=r.dom,l="",p,t;previewStyles=r.settings.preview_styles;if(previewStyles===false){return""}if(!previewStyles){previewStyles="font-family font-size font-weight text-decoration text-transform color background-color"}function s(u){return u.replace(/%(\w+)/g,"")}m=o.block||o.inline||"span";n=q.create(m);f(o.styles,function(v,u){v=s(v);if(v){q.setStyle(n,u,v)}});f(o.attributes,function(v,u){v=s(v);if(v){q.setAttrib(n,u,v)}});f(o.classes,function(u){u=s(u);if(!q.hasClass(n,u)){q.addClass(n,u)}});q.setStyles(n,{position:"absolute",left:-65535});r.getBody().appendChild(n);p=q.getStyle(r.getBody(),"fontSize",true);p=/px$/.test(p)?parseInt(p,10):0;f(previewStyles.split(" "),function(u){var v=q.getStyle(n,u,true);if(u=="background-color"&&/transparent|rgba\s*\([^)]+,\s*0\)/.test(v)){v=q.getStyle(r.getBody(),u,true);if(q.toHex(v).toLowerCase()=="#ffffff"){return}}if(u=="font-size"){if(/em|%$/.test(v)){if(p===0){return}v=parseFloat(v,10)/(/%$/.test(v)?100:1);v=(v*p)+"px"}}l+=u+":"+v+";"});q.remove(n);return l}i.ThemeManager.requireLangPack("advanced");i.create("tinymce.themes.AdvancedTheme",{sizes:[8,10,12,14,18,24,36],controls:{bold:["bold_desc","Bold"],italic:["italic_desc","Italic"],underline:["underline_desc","Underline"],strikethrough:["striketrough_desc","Strikethrough"],justifyleft:["justifyleft_desc","JustifyLeft"],justifycenter:["justifycenter_desc","JustifyCenter"],justifyright:["justifyright_desc","JustifyRight"],justifyfull:["justifyfull_desc","JustifyFull"],bullist:["bullist_desc","InsertUnorderedList"],numlist:["numlist_desc","InsertOrderedList"],outdent:["outdent_desc","Outdent"],indent:["indent_desc","Indent"],cut:["cut_desc","Cut"],copy:["copy_desc","Copy"],paste:["paste_desc","Paste"],undo:["undo_desc","Undo"],redo:["redo_desc","Redo"],link:["link_desc","mceLink"],unlink:["unlink_desc","unlink"],image:["image_desc","mceImage"],cleanup:["cleanup_desc","mceCleanup"],help:["help_desc","mceHelp"],code:["code_desc","mceCodeEditor"],hr:["hr_desc","InsertHorizontalRule"],removeformat:["removeformat_desc","RemoveFormat"],sub:["sub_desc","subscript"],sup:["sup_desc","superscript"],forecolor:["forecolor_desc","ForeColor"],forecolorpicker:["forecolor_desc","mceForeColor"],backcolor:["backcolor_desc","HiliteColor"],backcolorpicker:["backcolor_desc","mceBackColor"],charmap:["charmap_desc","mceCharMap"],visualaid:["visualaid_desc","mceToggleVisualAid"],anchor:["anchor_desc","mceInsertAnchor"],newdocument:["newdocument_desc","mceNewDocument"],blockquote:["blockquote_desc","mceBlockQuote"]},stateControls:["bold","italic","underline","strikethrough","bullist","numlist","justifyleft","justifycenter","justifyright","justifyfull","sub","sup","blockquote"],init:function(m,n){var p=this,q,l,r;p.editor=m;p.url=n;p.onResolveName=new i.util.Dispatcher(this);q=m.settings;m.forcedHighContrastMode=m.settings.detect_highcontrast&&p._isHighContrast();m.settings.skin=m.forcedHighContrastMode?"highcontrast":m.settings.skin;if(!q.theme_advanced_buttons1){q=c({theme_advanced_buttons1:"bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,|,styleselect,formatselect",theme_advanced_buttons2:"bullist,numlist,|,outdent,indent,|,undo,redo,|,link,unlink,anchor,image,cleanup,help,code",theme_advanced_buttons3:"hr,removeformat,visualaid,|,sub,sup,|,charmap"},q)}p.settings=q=c({theme_advanced_path:true,theme_advanced_toolbar_location:"top",theme_advanced_blockformats:"p,address,pre,h1,h2,h3,h4,h5,h6",theme_advanced_toolbar_align:"left",theme_advanced_statusbar_location:"bottom",theme_advanced_fonts:"Andale Mono=andale mono,monospace;Arial=arial,helvetica,sans-serif;Arial Black=arial black,sans-serif;Book Antiqua=book antiqua,palatino,serif;Comic Sans MS=comic sans ms,sans-serif;Courier New=courier new,courier,monospace;Georgia=georgia,palatino,serif;Helvetica=helvetica,arial,sans-serif;Impact=impact,sans-serif;Symbol=symbol;Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal,monaco,monospace;Times New Roman=times new roman,times,serif;Trebuchet MS=trebuchet ms,geneva,sans-serif;Verdana=verdana,geneva,sans-serif;Webdings=webdings;Wingdings=wingdings,zapf dingbats",theme_advanced_more_colors:1,theme_advanced_row_height:23,theme_advanced_resize_horizontal:1,theme_advanced_resizing_use_cookie:1,theme_advanced_font_sizes:"1,2,3,4,5,6,7",theme_advanced_font_selector:"span",theme_advanced_show_current_color:0,readonly:m.settings.readonly},q);if(!q.font_size_style_values){q.font_size_style_values="8pt,10pt,12pt,14pt,18pt,24pt,36pt"}if(i.is(q.theme_advanced_font_sizes,"string")){q.font_size_style_values=i.explode(q.font_size_style_values);q.font_size_classes=i.explode(q.font_size_classes||"");r={};m.settings.theme_advanced_font_sizes=q.theme_advanced_font_sizes;f(m.getParam("theme_advanced_font_sizes","","hash"),function(t,s){var o;if(s==t&&t>=1&&t<=7){s=t+" ("+p.sizes[t-1]+"pt)";o=q.font_size_classes[t-1];t=q.font_size_style_values[t-1]||(p.sizes[t-1]+"pt")}if(/^\s*\./.test(t)){o=t.replace(/\./g,"")}r[s]=o?{"class":o}:{fontSize:t}});q.theme_advanced_font_sizes=r}if((l=q.theme_advanced_path_location)&&l!="none"){q.theme_advanced_statusbar_location=q.theme_advanced_path_location}if(q.theme_advanced_statusbar_location=="none"){q.theme_advanced_statusbar_location=0}if(m.settings.content_css!==false){m.contentCSS.push(m.baseURI.toAbsolute(n+"/skins/"+m.settings.skin+"/content.css"))}m.onInit.add(function(){if(!m.settings.readonly){m.onNodeChange.add(p._nodeChanged,p);m.onKeyUp.add(p._updateUndoStatus,p);m.onMouseUp.add(p._updateUndoStatus,p);m.dom.bind(m.dom.getRoot(),"dragend",function(){p._updateUndoStatus(m)})}g(m.getBody(),m.settings)});m.onSetProgressState.add(function(t,o,u){var v,w=t.id,s;if(o){p.progressTimer=setTimeout(function(){v=t.getContainer();v=v.insertBefore(k.create("DIV",{style:"position:relative"}),v.firstChild);s=k.get(t.id+"_tbl");k.add(v,"div",{id:w+"_blocker","class":"mceBlocker",style:{width:s.clientWidth+2,height:s.clientHeight+2}});k.add(v,"div",{id:w+"_progress","class":"mceProgress",style:{left:s.clientWidth/2,top:s.clientHeight/2}})},u||0)}else{k.remove(w+"_blocker");k.remove(w+"_progress");clearTimeout(p.progressTimer)}});k.loadCSS(q.editor_css?m.documentBaseURI.toAbsolute(q.editor_css):n+"/skins/"+m.settings.skin+"/ui.css");if(q.skin_variant){k.loadCSS(n+"/skins/"+m.settings.skin+"/ui_"+q.skin_variant+".css")}},_isHighContrast:function(){var l,m=k.add(k.getRoot(),"div",{style:"background-color: rgb(171,239,86);"});l=(k.getStyle(m,"background-color",true)+"").toLowerCase().replace(/ /g,"");k.remove(m);return l!="rgb(171,239,86)"&&l!="#abef56"},createControl:function(p,l){var m,o;if(o=l.createControl(p)){return o}switch(p){case"styleselect":return this._createStyleSelect();case"formatselect":return this._createBlockFormats();case"fontselect":return this._createFontSelect();case"fontsizeselect":return this._createFontSizeSelect();case"forecolor":return this._createForeColorMenu();case"backcolor":return this._createBackColorMenu()}if((m=this.controls[p])){return l.createButton(p,{title:"advanced."+m[0],cmd:m[1],ui:m[2],value:m[3]})}},execCommand:function(n,m,o){var l=this["_"+n];if(l){l.call(this,m,o);return true}return false},_importClasses:function(n){var l=this.editor,m=l.controlManager.get("styleselect");if(m.getLength()==0){f(l.dom.getClasses(),function(s,p){var r="style_"+p,q;q={inline:"span",attributes:{"class":s["class"]},selector:"*"};l.formatter.register(r,q);m.add(s["class"],r,{style:function(){return b(l,q)}})})}},_createStyleSelect:function(q){var o=this,l=o.editor,m=l.controlManager,p;p=m.createListBox("styleselect",{title:"advanced.style_select",onselect:function(s){var t,n=[],r;f(p.items,function(u){n.push(u.value)});l.focus();l.undoManager.add();t=l.formatter.matchAll(n);i.each(t,function(u){if(!s||u==s){if(u){l.formatter.remove(u)}r=true}});if(!r){l.formatter.apply(s)}l.undoManager.add();l.nodeChanged();return false}});l.onPreInit.add(function(){var r=0,n=l.getParam("style_formats");if(n){f(n,function(s){var t,u=0;f(s,function(){u++});if(u>1){t=s.name=s.name||"style_"+(r++);l.formatter.register(t,s);p.add(s.title,t,{style:function(){return b(l,s)}})}else{p.add(s.title)}})}else{f(l.getParam("theme_advanced_styles","","hash"),function(v,u){var t,s;if(v){t="style_"+(r++);s={inline:"span",classes:v,selector:"*"};l.formatter.register(t,s);p.add(o.editor.translate(u),t,{style:function(){return b(l,s)}})}})}});if(p.getLength()==0){p.onPostRender.add(function(r,s){if(!p.NativeListBox){h.add(s.id+"_text","focus",o._importClasses,o);h.add(s.id+"_text","mousedown",o._importClasses,o);h.add(s.id+"_open","focus",o._importClasses,o);h.add(s.id+"_open","mousedown",o._importClasses,o)}else{h.add(s.id,"focus",o._importClasses,o)}})}return p},_createFontSelect:function(){var n,m=this,l=m.editor;n=l.controlManager.createListBox("fontselect",{title:"advanced.fontdefault",onselect:function(o){var p=n.items[n.selectedIndex];if(!o&&p){l.execCommand("FontName",false,p.value);return}l.execCommand("FontName",false,o);n.select(function(q){return o==q});if(p&&p.value==o){n.select(null)}return false}});if(n){f(l.getParam("theme_advanced_fonts",m.settings.theme_advanced_fonts,"hash"),function(p,o){n.add(l.translate(o),p,{style:p.indexOf("dings")==-1?"font-family:"+p:""})})}return n},_createFontSizeSelect:function(){var o=this,m=o.editor,p,n=0,l=[];p=m.controlManager.createListBox("fontsizeselect",{title:"advanced.font_size",onselect:function(q){var r=p.items[p.selectedIndex];if(!q&&r){r=r.value;if(r["class"]){m.formatter.toggle("fontsize_class",{value:r["class"]});m.undoManager.add();m.nodeChanged()}else{m.execCommand("FontSize",false,r.fontSize)}return}if(q["class"]){m.focus();m.undoManager.add();m.formatter.toggle("fontsize_class",{value:q["class"]});m.undoManager.add();m.nodeChanged()}else{m.execCommand("FontSize",false,q.fontSize)}p.select(function(s){return q==s});if(r&&(r.value.fontSize==q.fontSize||r.value["class"]&&r.value["class"]==q["class"])){p.select(null)}return false}});if(p){f(o.settings.theme_advanced_font_sizes,function(r,q){var s=r.fontSize;if(s>=1&&s<=7){s=o.sizes[parseInt(s)-1]+"pt"}p.add(q,r,{style:"font-size:"+s,"class":"mceFontSize"+(n++)+(" "+(r["class"]||""))})})}return p},_createBlockFormats:function(){var n,l={p:"advanced.paragraph",address:"advanced.address",pre:"advanced.pre",h1:"advanced.h1",h2:"advanced.h2",h3:"advanced.h3",h4:"advanced.h4",h5:"advanced.h5",h6:"advanced.h6",div:"advanced.div",blockquote:"advanced.blockquote",code:"advanced.code",dt:"advanced.dt",dd:"advanced.dd",samp:"advanced.samp"},m=this;n=m.editor.controlManager.createListBox("formatselect",{title:"advanced.block",onselect:function(o){m.editor.execCommand("FormatBlock",false,o);return false}});if(n){f(m.editor.getParam("theme_advanced_blockformats",m.settings.theme_advanced_blockformats,"hash"),function(p,o){n.add(m.editor.translate(o!=p?o:l[p]),p,{"class":"mce_formatPreview mce_"+p,style:function(){return b(m.editor,{block:p})}})})}return n},_createForeColorMenu:function(){var q,m=this,n=m.settings,p={},l;if(n.theme_advanced_more_colors){p.more_colors_func=function(){m._mceColorPicker(0,{color:q.value,func:function(o){q.setColor(o)}})}}if(l=n.theme_advanced_text_colors){p.colors=l}if(n.theme_advanced_default_foreground_color){p.default_color=n.theme_advanced_default_foreground_color}p.title="advanced.forecolor_desc";p.cmd="ForeColor";p.scope=this;q=m.editor.controlManager.createColorSplitButton("forecolor",p);return q},_createBackColorMenu:function(){var q,m=this,n=m.settings,p={},l;if(n.theme_advanced_more_colors){p.more_colors_func=function(){m._mceColorPicker(0,{color:q.value,func:function(o){q.setColor(o)}})}}if(l=n.theme_advanced_background_colors){p.colors=l}if(n.theme_advanced_default_background_color){p.default_color=n.theme_advanced_default_background_color}p.title="advanced.backcolor_desc";p.cmd="HiliteColor";p.scope=this;q=m.editor.controlManager.createColorSplitButton("backcolor",p);return q},renderUI:function(q){var u,r,v,y=this,w=y.editor,z=y.settings,x,m,l;if(w.settings){w.settings.aria_label=z.aria_label+w.getLang("advanced.help_shortcut")}u=m=k.create("span",{role:"application","aria-labelledby":w.id+"_voice",id:w.id+"_parent","class":"mceEditor "+w.settings.skin+"Skin"+(z.skin_variant?" "+w.settings.skin+"Skin"+y._ufirst(z.skin_variant):"")+(w.settings.directionality=="rtl"?" mceRtl":"")});k.add(u,"span",{"class":"mceVoiceLabel",style:"display:none;",id:w.id+"_voice"},z.aria_label);if(!k.boxModel){u=k.add(u,"div",{"class":"mceOldBoxModel"})}u=x=k.add(u,"table",{role:"presentation",id:w.id+"_tbl","class":"mceLayout",cellSpacing:0,cellPadding:0});u=v=k.add(u,"tbody");switch((z.theme_advanced_layout_manager||"").toLowerCase()){case"rowlayout":r=y._rowLayout(z,v,q);break;case"customlayout":r=w.execCallback("theme_advanced_custom_layout",z,v,q,m);break;default:r=y._simpleLayout(z,v,q,m)}u=q.targetNode;l=x.rows;k.addClass(l[0],"mceFirst");k.addClass(l[l.length-1],"mceLast");f(k.select("tr",v),function(o){k.addClass(o.firstChild,"mceFirst");k.addClass(o.childNodes[o.childNodes.length-1],"mceLast")});if(k.get(z.theme_advanced_toolbar_container)){k.get(z.theme_advanced_toolbar_container).appendChild(m)}else{k.insertAfter(m,u)}h.add(w.id+"_path_row","click",function(n){n=n.target;if(n.nodeName=="A"){y._sel(n.className.replace(/^.*mcePath_([0-9]+).*$/,"$1"));return false}});if(!w.getParam("accessibility_focus")){h.add(k.add(m,"a",{href:"#"},""),"focus",function(){tinyMCE.get(w.id).focus()})}if(z.theme_advanced_toolbar_location=="external"){q.deltaHeight=0}y.deltaHeight=q.deltaHeight;q.targetNode=null;w.onKeyDown.add(function(p,n){var s=121,o=122;if(n.altKey){if(n.keyCode===s){if(i.isWebKit){window.focus()}y.toolbarGroup.focus();return h.cancel(n)}else{if(n.keyCode===o){k.get(p.id+"_path_row").focus();return h.cancel(n)}}}});w.addShortcut("alt+0","","mceShortcuts",y);return{iframeContainer:r,editorContainer:w.id+"_parent",sizeContainer:x,deltaHeight:q.deltaHeight}},getInfo:function(){return{longname:"Advanced theme",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",version:i.majorVersion+"."+i.minorVersion}},resizeBy:function(l,m){var n=k.get(this.editor.id+"_ifr");this.resizeTo(n.clientWidth+l,n.clientHeight+m)},resizeTo:function(l,p,n){var m=this.editor,o=this.settings,q=k.get(m.id+"_tbl"),r=k.get(m.id+"_ifr");l=Math.max(o.theme_advanced_resizing_min_width||100,l);p=Math.max(o.theme_advanced_resizing_min_height||100,p);l=Math.min(o.theme_advanced_resizing_max_width||65535,l);p=Math.min(o.theme_advanced_resizing_max_height||65535,p);k.setStyle(q,"height","");k.setStyle(r,"height",p);if(o.theme_advanced_resize_horizontal){k.setStyle(q,"width","");k.setStyle(r,"width",l);if(l"));k.setHTML(p,w.join(""))},_addStatusBar:function(u,m){var p,y=this,v=y.editor,z=y.settings,l,w,x,q;p=k.add(u,"tr");p=q=k.add(p,"td",{"class":"mceStatusbar"});p=k.add(p,"div",{id:v.id+"_path_row",role:"group","aria-labelledby":v.id+"_path_voice"});if(z.theme_advanced_path){k.add(p,"span",{id:v.id+"_path_voice"},v.translate("advanced.path"));k.add(p,"span",{},": ")}else{k.add(p,"span",{}," ")}if(z.theme_advanced_resizing){k.add(q,"a",{id:v.id+"_resize",href:"javascript:;",onclick:"return false;","class":"mceResize",tabIndex:"-1"});if(z.theme_advanced_resizing_use_cookie){v.onPostRender.add(function(){var n=a.getHash("TinyMCE_"+v.id+"_size"),r=k.get(v.id+"_tbl");if(!n){return}y.resizeTo(n.cw,n.ch)})}v.onPostRender.add(function(){h.add(v.id+"_resize","click",function(n){n.preventDefault()});h.add(v.id+"_resize","mousedown",function(G){var t,r,s,o,F,C,D,I,n,H,A;function B(J){J.preventDefault();n=D+(J.screenX-F);H=I+(J.screenY-C);y.resizeTo(n,H)}function E(J){h.remove(k.doc,"mousemove",t);h.remove(v.getDoc(),"mousemove",r);h.remove(k.doc,"mouseup",s);h.remove(v.getDoc(),"mouseup",o);n=D+(J.screenX-F);H=I+(J.screenY-C);y.resizeTo(n,H,true);v.nodeChanged()}G.preventDefault();F=G.screenX;C=G.screenY;A=k.get(y.editor.id+"_ifr");D=n=A.clientWidth;I=H=A.clientHeight;t=h.add(k.doc,"mousemove",B);r=h.add(v.getDoc(),"mousemove",B);s=h.add(k.doc,"mouseup",E);o=h.add(v.getDoc(),"mouseup",E)})})}m.deltaHeight-=21;p=u=null},_updateUndoStatus:function(m){var l=m.controlManager,n=m.undoManager;l.setDisabled("undo",!n.hasUndo()&&!n.typing);l.setDisabled("redo",!n.hasRedo())},_nodeChanged:function(u,z,I,y,J){var D=this,H,K=0,C,L,E=D.settings,B,q,A,G,r,o,m;i.each(D.stateControls,function(n){z.setActive(n,u.queryCommandState(D.controls[n][1]))});var x=function(t,n){var p,t,s=n;if(typeof(n)=="string"){s=function(v){return v.nodeName==n}}for(p=0;p0){L.mark(p)}})}if(L=z.get("formatselect")){H=w(u.dom.isBlock);if(H){L.select(H.nodeName.toLowerCase())}}l(function(s){var p;if(s.nodeName==="SPAN"){if(!B&&s.className){B=s.className}}p=u.dom.is(s,E.theme_advanced_font_selector);if(p||j(u.settings)){if(!q&&s.style.fontSize){q=s.style.fontSize}if(!A&&s.style.fontFamily){A=s.style.fontFamily.replace(/[\"\']+/g,"").replace(/^([^,]+).*/,"$1").toLowerCase()}if(!G&&s.style.color){G=s.style.color}if(!r&&s.style.backgroundColor){r=s.style.backgroundColor}}return false});if(L=z.get("fontselect")){L.select(function(n){return n.replace(/^([^,]+).*/,"$1").toLowerCase()==A})}if(L=z.get("fontsizeselect")){if(E.theme_advanced_runtime_fontsize&&!q&&!B){q=u.dom.getStyle(I,"fontSize",true)}L.select(function(n){if(n.fontSize&&n.fontSize===q){return true}if(n["class"]&&n["class"]===B){return true}})}if(E.theme_advanced_show_current_color){function F(p,n){if(L=z.get(p)){if(!n){n=L.settings.default_color}if(n!==L.value){L.displayColor(n)}}}F("forecolor",G);F("backcolor",r)}if(E.theme_advanced_show_current_color){function F(p,n){if(L=z.get(p)){if(!n){n=L.settings.default_color}if(n!==L.value){L.displayColor(n)}}}F("forecolor",G);F("backcolor",r)}if(E.theme_advanced_path&&E.theme_advanced_statusbar_location){H=k.get(u.id+"_path")||k.add(u.id+"_path_row","span",{id:u.id+"_path"});if(D.statusKeyboardNavigation){D.statusKeyboardNavigation.destroy();D.statusKeyboardNavigation=null}k.setHTML(H,"");w(function(M){var p=M.nodeName.toLowerCase(),s,v,t="";if(M.nodeType!=1||p==="br"||M.getAttribute("data-mce-bogus")||k.hasClass(M,"mceItemHidden")||k.hasClass(M,"mceItemRemoved")){return}if(i.isIE&&M.scopeName!=="HTML"&&M.scopeName){p=M.scopeName+":"+p}p=p.replace(/mce\:/g,"");switch(p){case"b":p="strong";break;case"i":p="em";break;case"img":if(C=k.getAttrib(M,"src")){t+="src: "+C+" "}break;case"a":if(C=k.getAttrib(M,"name")){t+="name: "+C+" ";p+="#"+C}if(C=k.getAttrib(M,"href")){t+="href: "+C+" "}break;case"font":if(C=k.getAttrib(M,"face")){t+="font: "+C+" "}if(C=k.getAttrib(M,"size")){t+="size: "+C+" "}if(C=k.getAttrib(M,"color")){t+="color: "+C+" "}break;case"span":if(C=k.getAttrib(M,"style")){t+="style: "+C+" "}break}if(C=k.getAttrib(M,"id")){t+="id: "+C+" "}if(C=M.className){C=C.replace(/\b\s*(webkit|mce|Apple-)\w+\s*\b/g,"");if(C){t+="class: "+C+" ";if(u.dom.isBlock(M)||p=="img"||p=="span"){p+="."+C}}}p=p.replace(/(html:)/g,"");p={name:p,node:M,title:t};D.onResolveName.dispatch(D,p);t=p.title;p=p.name;v=k.create("a",{href:"javascript:;",role:"button",onmousedown:"return false;",title:t,"class":"mcePath_"+(K++)},p);if(H.hasChildNodes()){H.insertBefore(k.create("span",{"aria-hidden":"true"},"\u00a0\u00bb "),H.firstChild);H.insertBefore(v,H.firstChild)}else{H.appendChild(v)}},u.getBody());if(k.select("a",H).length>0){D.statusKeyboardNavigation=new i.ui.KeyboardNavigation({root:u.id+"_path_row",items:k.select("a",H),excludeFromTabOrder:true,onCancel:function(){u.focus()}},k)}}},_sel:function(l){this.editor.execCommand("mceSelectNodeDepth",false,l)},_mceInsertAnchor:function(n,m){var l=this.editor;l.windowManager.open({url:this.url+"/anchor.htm",width:320+parseInt(l.getLang("advanced.anchor_delta_width",0)),height:90+parseInt(l.getLang("advanced.anchor_delta_height",0)),inline:true},{theme_url:this.url})},_mceCharMap:function(){var l=this.editor;l.windowManager.open({url:this.url+"/charmap.htm",width:550+parseInt(l.getLang("advanced.charmap_delta_width",0)),height:265+parseInt(l.getLang("advanced.charmap_delta_height",0)),inline:true},{theme_url:this.url})},_mceHelp:function(){var l=this.editor;l.windowManager.open({url:this.url+"/about.htm",width:480,height:380,inline:true},{theme_url:this.url})},_mceShortcuts:function(){var l=this.editor;l.windowManager.open({url:this.url+"/shortcuts.htm",width:480,height:380,inline:true},{theme_url:this.url})},_mceColorPicker:function(n,m){var l=this.editor;m=m||{};l.windowManager.open({url:this.url+"/color_picker.htm",width:375+parseInt(l.getLang("advanced.colorpicker_delta_width",0)),height:250+parseInt(l.getLang("advanced.colorpicker_delta_height",0)),close_previous:false,inline:true},{input_color:m.color,func:m.func,theme_url:this.url})},_mceCodeEditor:function(m,n){var l=this.editor;l.windowManager.open({url:this.url+"/source_editor.htm",width:parseInt(l.getParam("theme_advanced_source_editor_width",720)),height:parseInt(l.getParam("theme_advanced_source_editor_height",580)),inline:true,resizable:true,maximizable:true},{theme_url:this.url})},_mceImage:function(m,n){var l=this.editor;if(l.dom.getAttrib(l.selection.getNode(),"class","").indexOf("mceItem")!=-1){return}l.windowManager.open({url:this.url+"/image.htm",width:355+parseInt(l.getLang("advanced.image_delta_width",0)),height:275+parseInt(l.getLang("advanced.image_delta_height",0)),inline:true},{theme_url:this.url})},_mceLink:function(m,n){var l=this.editor;l.windowManager.open({url:this.url+"/link.htm",width:310+parseInt(l.getLang("advanced.link_delta_width",0)),height:200+parseInt(l.getLang("advanced.link_delta_height",0)),inline:true},{theme_url:this.url})},_mceNewDocument:function(){var l=this.editor;l.windowManager.confirm("advanced.newdocument",function(m){if(m){l.execCommand("mceSetContent",false,"")}})},_mceForeColor:function(){var l=this;this._mceColorPicker(0,{color:l.fgColor,func:function(m){l.fgColor=m;l.editor.execCommand("ForeColor",false,m)}})},_mceBackColor:function(){var l=this;this._mceColorPicker(0,{color:l.bgColor,func:function(m){l.bgColor=m;l.editor.execCommand("HiliteColor",false,m)}})},_ufirst:function(l){return l.substring(0,1).toUpperCase()+l.substring(1)}});i.ThemeManager.add("advanced",i.themes.AdvancedTheme)}(tinymce)); \ No newline at end of file +(function(h){var i=h.DOM,g=h.dom.Event,c=h.extend,f=h.each,a=h.util.Cookie,e,d=h.explode;function b(p,m){var k,l,o=p.dom,j="",n,r;previewStyles=p.settings.preview_styles;if(previewStyles===false){return""}if(!previewStyles){previewStyles="font-family font-size font-weight text-decoration text-transform color background-color"}function q(s){return s.replace(/%(\w+)/g,"")}k=m.block||m.inline||"span";l=o.create(k);f(m.styles,function(t,s){t=q(t);if(t){o.setStyle(l,s,t)}});f(m.attributes,function(t,s){t=q(t);if(t){o.setAttrib(l,s,t)}});f(m.classes,function(s){s=q(s);if(!o.hasClass(l,s)){o.addClass(l,s)}});o.setStyles(l,{position:"absolute",left:-65535});p.getBody().appendChild(l);n=o.getStyle(p.getBody(),"fontSize",true);n=/px$/.test(n)?parseInt(n,10):0;f(previewStyles.split(" "),function(s){var t=o.getStyle(l,s,true);if(s=="background-color"&&/transparent|rgba\s*\([^)]+,\s*0\)/.test(t)){t=o.getStyle(p.getBody(),s,true);if(o.toHex(t).toLowerCase()=="#ffffff"){return}}if(s=="font-size"){if(/em|%$/.test(t)){if(n===0){return}t=parseFloat(t,10)/(/%$/.test(t)?100:1);t=(t*n)+"px"}}j+=s+":"+t+";"});o.remove(l);return j}h.ThemeManager.requireLangPack("advanced");h.create("tinymce.themes.AdvancedTheme",{sizes:[8,10,12,14,18,24,36],controls:{bold:["bold_desc","Bold"],italic:["italic_desc","Italic"],underline:["underline_desc","Underline"],strikethrough:["striketrough_desc","Strikethrough"],justifyleft:["justifyleft_desc","JustifyLeft"],justifycenter:["justifycenter_desc","JustifyCenter"],justifyright:["justifyright_desc","JustifyRight"],justifyfull:["justifyfull_desc","JustifyFull"],bullist:["bullist_desc","InsertUnorderedList"],numlist:["numlist_desc","InsertOrderedList"],outdent:["outdent_desc","Outdent"],indent:["indent_desc","Indent"],cut:["cut_desc","Cut"],copy:["copy_desc","Copy"],paste:["paste_desc","Paste"],undo:["undo_desc","Undo"],redo:["redo_desc","Redo"],link:["link_desc","mceLink"],unlink:["unlink_desc","unlink"],image:["image_desc","mceImage"],cleanup:["cleanup_desc","mceCleanup"],help:["help_desc","mceHelp"],code:["code_desc","mceCodeEditor"],hr:["hr_desc","InsertHorizontalRule"],removeformat:["removeformat_desc","RemoveFormat"],sub:["sub_desc","subscript"],sup:["sup_desc","superscript"],forecolor:["forecolor_desc","ForeColor"],forecolorpicker:["forecolor_desc","mceForeColor"],backcolor:["backcolor_desc","HiliteColor"],backcolorpicker:["backcolor_desc","mceBackColor"],charmap:["charmap_desc","mceCharMap"],visualaid:["visualaid_desc","mceToggleVisualAid"],anchor:["anchor_desc","mceInsertAnchor"],newdocument:["newdocument_desc","mceNewDocument"],blockquote:["blockquote_desc","mceBlockQuote"]},stateControls:["bold","italic","underline","strikethrough","bullist","numlist","justifyleft","justifycenter","justifyright","justifyfull","sub","sup","blockquote"],init:function(k,l){var m=this,n,j,p;m.editor=k;m.url=l;m.onResolveName=new h.util.Dispatcher(this);n=k.settings;k.forcedHighContrastMode=k.settings.detect_highcontrast&&m._isHighContrast();k.settings.skin=k.forcedHighContrastMode?"highcontrast":k.settings.skin;if(!n.theme_advanced_buttons1){n=c({theme_advanced_buttons1:"bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,|,styleselect,formatselect",theme_advanced_buttons2:"bullist,numlist,|,outdent,indent,|,undo,redo,|,link,unlink,anchor,image,cleanup,help,code",theme_advanced_buttons3:"hr,removeformat,visualaid,|,sub,sup,|,charmap"},n)}m.settings=n=c({theme_advanced_path:true,theme_advanced_toolbar_location:"top",theme_advanced_blockformats:"p,address,pre,h1,h2,h3,h4,h5,h6",theme_advanced_toolbar_align:"left",theme_advanced_statusbar_location:"bottom",theme_advanced_fonts:"Andale Mono=andale mono,times;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;Comic Sans MS=comic sans ms,sans-serif;Courier New=courier new,courier;Georgia=georgia,palatino;Helvetica=helvetica;Impact=impact,chicago;Symbol=symbol;Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal,monaco;Times New Roman=times new roman,times;Trebuchet MS=trebuchet ms,geneva;Verdana=verdana,geneva;Webdings=webdings;Wingdings=wingdings,zapf dingbats",theme_advanced_more_colors:1,theme_advanced_row_height:23,theme_advanced_resize_horizontal:1,theme_advanced_resizing_use_cookie:1,theme_advanced_font_sizes:"1,2,3,4,5,6,7",theme_advanced_font_selector:"span",theme_advanced_show_current_color:0,readonly:k.settings.readonly},n);if(!n.font_size_style_values){n.font_size_style_values="8pt,10pt,12pt,14pt,18pt,24pt,36pt"}if(h.is(n.theme_advanced_font_sizes,"string")){n.font_size_style_values=h.explode(n.font_size_style_values);n.font_size_classes=h.explode(n.font_size_classes||"");p={};k.settings.theme_advanced_font_sizes=n.theme_advanced_font_sizes;f(k.getParam("theme_advanced_font_sizes","","hash"),function(r,q){var o;if(q==r&&r>=1&&r<=7){q=r+" ("+m.sizes[r-1]+"pt)";o=n.font_size_classes[r-1];r=n.font_size_style_values[r-1]||(m.sizes[r-1]+"pt")}if(/^\s*\./.test(r)){o=r.replace(/\./g,"")}p[q]=o?{"class":o}:{fontSize:r}});n.theme_advanced_font_sizes=p}if((j=n.theme_advanced_path_location)&&j!="none"){n.theme_advanced_statusbar_location=n.theme_advanced_path_location}if(n.theme_advanced_statusbar_location=="none"){n.theme_advanced_statusbar_location=0}if(k.settings.content_css!==false){k.contentCSS.push(k.baseURI.toAbsolute(l+"/skins/"+k.settings.skin+"/content.css"))}k.onInit.add(function(){if(!k.settings.readonly){k.onNodeChange.add(m._nodeChanged,m);k.onKeyUp.add(m._updateUndoStatus,m);k.onMouseUp.add(m._updateUndoStatus,m);k.dom.bind(k.dom.getRoot(),"dragend",function(){m._updateUndoStatus(k)})}});k.onSetProgressState.add(function(r,o,s){var t,u=r.id,q;if(o){m.progressTimer=setTimeout(function(){t=r.getContainer();t=t.insertBefore(i.create("DIV",{style:"position:relative"}),t.firstChild);q=i.get(r.id+"_tbl");i.add(t,"div",{id:u+"_blocker","class":"mceBlocker",style:{width:q.clientWidth+2,height:q.clientHeight+2}});i.add(t,"div",{id:u+"_progress","class":"mceProgress",style:{left:q.clientWidth/2,top:q.clientHeight/2}})},s||0)}else{i.remove(u+"_blocker");i.remove(u+"_progress");clearTimeout(m.progressTimer)}});i.loadCSS(n.editor_css?k.documentBaseURI.toAbsolute(n.editor_css):l+"/skins/"+k.settings.skin+"/ui.css");if(n.skin_variant){i.loadCSS(l+"/skins/"+k.settings.skin+"/ui_"+n.skin_variant+".css")}},_isHighContrast:function(){var j,k=i.add(i.getRoot(),"div",{style:"background-color: rgb(171,239,86);"});j=(i.getStyle(k,"background-color",true)+"").toLowerCase().replace(/ /g,"");i.remove(k);return j!="rgb(171,239,86)"&&j!="#abef56"},createControl:function(m,j){var k,l;if(l=j.createControl(m)){return l}switch(m){case"styleselect":return this._createStyleSelect();case"formatselect":return this._createBlockFormats();case"fontselect":return this._createFontSelect();case"fontsizeselect":return this._createFontSizeSelect();case"forecolor":return this._createForeColorMenu();case"backcolor":return this._createBackColorMenu()}if((k=this.controls[m])){return j.createButton(m,{title:"advanced."+k[0],cmd:k[1],ui:k[2],value:k[3]})}},execCommand:function(l,k,m){var j=this["_"+l];if(j){j.call(this,k,m);return true}return false},_importClasses:function(l){var j=this.editor,k=j.controlManager.get("styleselect");if(k.getLength()==0){f(j.dom.getClasses(),function(q,m){var p="style_"+m,n;n={inline:"span",attributes:{"class":q["class"]},selector:"*"};j.formatter.register(p,n);k.add(q["class"],p,{style:function(){return b(j,n)}})})}},_createStyleSelect:function(o){var l=this,j=l.editor,k=j.controlManager,m;m=k.createListBox("styleselect",{title:"advanced.style_select",onselect:function(q){var r,n=[],p;f(m.items,function(s){n.push(s.value)});j.focus();j.undoManager.add();r=j.formatter.matchAll(n);h.each(r,function(s){if(!q||s==q){if(s){j.formatter.remove(s)}p=true}});if(!p){j.formatter.apply(q)}j.undoManager.add();j.nodeChanged();return false}});j.onPreInit.add(function(){var p=0,n=j.getParam("style_formats");if(n){f(n,function(q){var r,s=0;f(q,function(){s++});if(s>1){r=q.name=q.name||"style_"+(p++);j.formatter.register(r,q);m.add(q.title,r,{style:function(){return b(j,q)}})}else{m.add(q.title)}})}else{f(j.getParam("theme_advanced_styles","","hash"),function(t,s){var r,q;if(t){r="style_"+(p++);q={inline:"span",classes:t,selector:"*"};j.formatter.register(r,q);m.add(l.editor.translate(s),r,{style:function(){return b(j,q)}})}})}});if(m.getLength()==0){m.onPostRender.add(function(p,q){if(!m.NativeListBox){g.add(q.id+"_text","focus",l._importClasses,l);g.add(q.id+"_text","mousedown",l._importClasses,l);g.add(q.id+"_open","focus",l._importClasses,l);g.add(q.id+"_open","mousedown",l._importClasses,l)}else{g.add(q.id,"focus",l._importClasses,l)}})}return m},_createFontSelect:function(){var l,k=this,j=k.editor;l=j.controlManager.createListBox("fontselect",{title:"advanced.fontdefault",onselect:function(m){var n=l.items[l.selectedIndex];if(!m&&n){j.execCommand("FontName",false,n.value);return}j.execCommand("FontName",false,m);l.select(function(o){return m==o});if(n&&n.value==m){l.select(null)}return false}});if(l){f(j.getParam("theme_advanced_fonts",k.settings.theme_advanced_fonts,"hash"),function(n,m){l.add(j.translate(m),n,{style:n.indexOf("dings")==-1?"font-family:"+n:""})})}return l},_createFontSizeSelect:function(){var m=this,k=m.editor,n,l=0,j=[];n=k.controlManager.createListBox("fontsizeselect",{title:"advanced.font_size",onselect:function(o){var p=n.items[n.selectedIndex];if(!o&&p){p=p.value;if(p["class"]){k.formatter.toggle("fontsize_class",{value:p["class"]});k.undoManager.add();k.nodeChanged()}else{k.execCommand("FontSize",false,p.fontSize)}return}if(o["class"]){k.focus();k.undoManager.add();k.formatter.toggle("fontsize_class",{value:o["class"]});k.undoManager.add();k.nodeChanged()}else{k.execCommand("FontSize",false,o.fontSize)}n.select(function(q){return o==q});if(p&&(p.value.fontSize==o.fontSize||p.value["class"]&&p.value["class"]==o["class"])){n.select(null)}return false}});if(n){f(m.settings.theme_advanced_font_sizes,function(p,o){var q=p.fontSize;if(q>=1&&q<=7){q=m.sizes[parseInt(q)-1]+"pt"}n.add(o,p,{style:"font-size:"+q,"class":"mceFontSize"+(l++)+(" "+(p["class"]||""))})})}return n},_createBlockFormats:function(){var l,j={p:"advanced.paragraph",address:"advanced.address",pre:"advanced.pre",h1:"advanced.h1",h2:"advanced.h2",h3:"advanced.h3",h4:"advanced.h4",h5:"advanced.h5",h6:"advanced.h6",div:"advanced.div",blockquote:"advanced.blockquote",code:"advanced.code",dt:"advanced.dt",dd:"advanced.dd",samp:"advanced.samp"},k=this;l=k.editor.controlManager.createListBox("formatselect",{title:"advanced.block",onselect:function(m){k.editor.execCommand("FormatBlock",false,m);return false}});if(l){f(k.editor.getParam("theme_advanced_blockformats",k.settings.theme_advanced_blockformats,"hash"),function(n,m){l.add(k.editor.translate(m!=n?m:j[n]),n,{"class":"mce_formatPreview mce_"+n,style:function(){return b(k.editor,{block:n})}})})}return l},_createForeColorMenu:function(){var n,k=this,l=k.settings,m={},j;if(l.theme_advanced_more_colors){m.more_colors_func=function(){k._mceColorPicker(0,{color:n.value,func:function(o){n.setColor(o)}})}}if(j=l.theme_advanced_text_colors){m.colors=j}if(l.theme_advanced_default_foreground_color){m.default_color=l.theme_advanced_default_foreground_color}m.title="advanced.forecolor_desc";m.cmd="ForeColor";m.scope=this;n=k.editor.controlManager.createColorSplitButton("forecolor",m);return n},_createBackColorMenu:function(){var n,k=this,l=k.settings,m={},j;if(l.theme_advanced_more_colors){m.more_colors_func=function(){k._mceColorPicker(0,{color:n.value,func:function(o){n.setColor(o)}})}}if(j=l.theme_advanced_background_colors){m.colors=j}if(l.theme_advanced_default_background_color){m.default_color=l.theme_advanced_default_background_color}m.title="advanced.backcolor_desc";m.cmd="HiliteColor";m.scope=this;n=k.editor.controlManager.createColorSplitButton("backcolor",m);return n},renderUI:function(l){var q,m,r,w=this,u=w.editor,x=w.settings,v,k,j;if(u.settings){u.settings.aria_label=x.aria_label+u.getLang("advanced.help_shortcut")}q=k=i.create("span",{role:"application","aria-labelledby":u.id+"_voice",id:u.id+"_parent","class":"mceEditor "+u.settings.skin+"Skin"+(x.skin_variant?" "+u.settings.skin+"Skin"+w._ufirst(x.skin_variant):"")+(u.settings.directionality=="rtl"?" mceRtl":"")});i.add(q,"span",{"class":"mceVoiceLabel",style:"display:none;",id:u.id+"_voice"},x.aria_label);if(!i.boxModel){q=i.add(q,"div",{"class":"mceOldBoxModel"})}q=v=i.add(q,"table",{role:"presentation",id:u.id+"_tbl","class":"mceLayout",cellSpacing:0,cellPadding:0});q=r=i.add(q,"tbody");switch((x.theme_advanced_layout_manager||"").toLowerCase()){case"rowlayout":m=w._rowLayout(x,r,l);break;case"customlayout":m=u.execCallback("theme_advanced_custom_layout",x,r,l,k);break;default:m=w._simpleLayout(x,r,l,k)}q=l.targetNode;j=v.rows;i.addClass(j[0],"mceFirst");i.addClass(j[j.length-1],"mceLast");f(i.select("tr",r),function(o){i.addClass(o.firstChild,"mceFirst");i.addClass(o.childNodes[o.childNodes.length-1],"mceLast")});if(i.get(x.theme_advanced_toolbar_container)){i.get(x.theme_advanced_toolbar_container).appendChild(k)}else{i.insertAfter(k,q)}g.add(u.id+"_path_row","click",function(n){n=n.target;if(n.nodeName=="A"){w._sel(n.className.replace(/^.*mcePath_([0-9]+).*$/,"$1"));return false}});if(!u.getParam("accessibility_focus")){g.add(i.add(k,"a",{href:"#"},""),"focus",function(){tinyMCE.get(u.id).focus()})}if(x.theme_advanced_toolbar_location=="external"){l.deltaHeight=0}w.deltaHeight=l.deltaHeight;l.targetNode=null;u.onKeyDown.add(function(p,n){var s=121,o=122;if(n.altKey){if(n.keyCode===s){if(h.isWebKit){window.focus()}w.toolbarGroup.focus();return g.cancel(n)}else{if(n.keyCode===o){i.get(p.id+"_path_row").focus();return g.cancel(n)}}}});u.addShortcut("alt+0","","mceShortcuts",w);return{iframeContainer:m,editorContainer:u.id+"_parent",sizeContainer:v,deltaHeight:l.deltaHeight}},getInfo:function(){return{longname:"Advanced theme",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",version:h.majorVersion+"."+h.minorVersion}},resizeBy:function(j,k){var l=i.get(this.editor.id+"_ifr");this.resizeTo(l.clientWidth+j,l.clientHeight+k)},resizeTo:function(j,n,l){var k=this.editor,m=this.settings,o=i.get(k.id+"_tbl"),p=i.get(k.id+"_ifr");j=Math.max(m.theme_advanced_resizing_min_width||100,j);n=Math.max(m.theme_advanced_resizing_min_height||100,n);j=Math.min(m.theme_advanced_resizing_max_width||65535,j);n=Math.min(m.theme_advanced_resizing_max_height||65535,n);i.setStyle(o,"height","");i.setStyle(p,"height",n);if(m.theme_advanced_resize_horizontal){i.setStyle(o,"width","");i.setStyle(p,"width",j);if(j"));i.setHTML(l,r.join(""))},_addStatusBar:function(p,k){var l,w=this,q=w.editor,x=w.settings,j,u,v,m;l=i.add(p,"tr");l=m=i.add(l,"td",{"class":"mceStatusbar"});l=i.add(l,"div",{id:q.id+"_path_row",role:"group","aria-labelledby":q.id+"_path_voice"});if(x.theme_advanced_path){i.add(l,"span",{id:q.id+"_path_voice"},q.translate("advanced.path"));i.add(l,"span",{},": ")}else{i.add(l,"span",{}," ")}if(x.theme_advanced_resizing){i.add(m,"a",{id:q.id+"_resize",href:"javascript:;",onclick:"return false;","class":"mceResize",tabIndex:"-1"});if(x.theme_advanced_resizing_use_cookie){q.onPostRender.add(function(){var n=a.getHash("TinyMCE_"+q.id+"_size"),r=i.get(q.id+"_tbl");if(!n){return}w.resizeTo(n.cw,n.ch)})}q.onPostRender.add(function(){g.add(q.id+"_resize","click",function(n){n.preventDefault()});g.add(q.id+"_resize","mousedown",function(E){var t,r,s,o,D,A,B,G,n,F,y;function z(H){H.preventDefault();n=B+(H.screenX-D);F=G+(H.screenY-A);w.resizeTo(n,F)}function C(H){g.remove(i.doc,"mousemove",t);g.remove(q.getDoc(),"mousemove",r);g.remove(i.doc,"mouseup",s);g.remove(q.getDoc(),"mouseup",o);n=B+(H.screenX-D);F=G+(H.screenY-A);w.resizeTo(n,F,true);q.nodeChanged()}E.preventDefault();D=E.screenX;A=E.screenY;y=i.get(w.editor.id+"_ifr");B=n=y.clientWidth;G=F=y.clientHeight;t=g.add(i.doc,"mousemove",z);r=g.add(q.getDoc(),"mousemove",z);s=g.add(i.doc,"mouseup",C);o=g.add(q.getDoc(),"mouseup",C)})})}k.deltaHeight-=21;l=p=null},_updateUndoStatus:function(k){var j=k.controlManager,l=k.undoManager;j.setDisabled("undo",!l.hasUndo()&&!l.typing);j.setDisabled("redo",!l.hasRedo())},_nodeChanged:function(o,u,E,r,F){var z=this,D,G=0,y,H,A=z.settings,x,l,w,C,m,k,j;h.each(z.stateControls,function(n){u.setActive(n,o.queryCommandState(z.controls[n][1]))});function q(p){var s,n=F.parents,t=p;if(typeof(p)=="string"){t=function(v){return v.nodeName==p}}for(s=0;s0){H.mark(p)}})}if(H=u.get("formatselect")){D=q(o.dom.isBlock);if(D){H.select(D.nodeName.toLowerCase())}}q(function(p){if(p.nodeName==="SPAN"){if(!x&&p.className){x=p.className}}if(o.dom.is(p,A.theme_advanced_font_selector)){if(!l&&p.style.fontSize){l=p.style.fontSize}if(!w&&p.style.fontFamily){w=p.style.fontFamily.replace(/[\"\']+/g,"").replace(/^([^,]+).*/,"$1").toLowerCase()}if(!C&&p.style.color){C=p.style.color}if(!m&&p.style.backgroundColor){m=p.style.backgroundColor}}return false});if(H=u.get("fontselect")){H.select(function(n){return n.replace(/^([^,]+).*/,"$1").toLowerCase()==w})}if(H=u.get("fontsizeselect")){if(A.theme_advanced_runtime_fontsize&&!l&&!x){l=o.dom.getStyle(E,"fontSize",true)}H.select(function(n){if(n.fontSize&&n.fontSize===l){return true}if(n["class"]&&n["class"]===x){return true}})}if(A.theme_advanced_show_current_color){function B(p,n){if(H=u.get(p)){if(!n){n=H.settings.default_color}if(n!==H.value){H.displayColor(n)}}}B("forecolor",C);B("backcolor",m)}if(A.theme_advanced_show_current_color){function B(p,n){if(H=u.get(p)){if(!n){n=H.settings.default_color}if(n!==H.value){H.displayColor(n)}}}B("forecolor",C);B("backcolor",m)}if(A.theme_advanced_path&&A.theme_advanced_statusbar_location){D=i.get(o.id+"_path")||i.add(o.id+"_path_row","span",{id:o.id+"_path"});if(z.statusKeyboardNavigation){z.statusKeyboardNavigation.destroy();z.statusKeyboardNavigation=null}i.setHTML(D,"");q(function(I){var p=I.nodeName.toLowerCase(),s,v,t="";if(I.nodeType!=1||p==="br"||I.getAttribute("data-mce-bogus")||i.hasClass(I,"mceItemHidden")||i.hasClass(I,"mceItemRemoved")){return}if(h.isIE&&I.scopeName!=="HTML"&&I.scopeName){p=I.scopeName+":"+p}p=p.replace(/mce\:/g,"");switch(p){case"b":p="strong";break;case"i":p="em";break;case"img":if(y=i.getAttrib(I,"src")){t+="src: "+y+" "}break;case"a":if(y=i.getAttrib(I,"name")){t+="name: "+y+" ";p+="#"+y}if(y=i.getAttrib(I,"href")){t+="href: "+y+" "}break;case"font":if(y=i.getAttrib(I,"face")){t+="font: "+y+" "}if(y=i.getAttrib(I,"size")){t+="size: "+y+" "}if(y=i.getAttrib(I,"color")){t+="color: "+y+" "}break;case"span":if(y=i.getAttrib(I,"style")){t+="style: "+y+" "}break}if(y=i.getAttrib(I,"id")){t+="id: "+y+" "}if(y=I.className){y=y.replace(/\b\s*(webkit|mce|Apple-)\w+\s*\b/g,"");if(y){t+="class: "+y+" ";if(o.dom.isBlock(I)||p=="img"||p=="span"){p+="."+y}}}p=p.replace(/(html:)/g,"");p={name:p,node:I,title:t};z.onResolveName.dispatch(z,p);t=p.title;p=p.name;v=i.create("a",{href:"javascript:;",role:"button",onmousedown:"return false;",title:t,"class":"mcePath_"+(G++)},p);if(D.hasChildNodes()){D.insertBefore(i.create("span",{"aria-hidden":"true"},"\u00a0\u00bb "),D.firstChild);D.insertBefore(v,D.firstChild)}else{D.appendChild(v)}},o.getBody());if(i.select("a",D).length>0){z.statusKeyboardNavigation=new h.ui.KeyboardNavigation({root:o.id+"_path_row",items:i.select("a",D),excludeFromTabOrder:true,onCancel:function(){o.focus()}},i)}}},_sel:function(j){this.editor.execCommand("mceSelectNodeDepth",false,j)},_mceInsertAnchor:function(l,k){var j=this.editor;j.windowManager.open({url:this.url+"/anchor.htm",width:320+parseInt(j.getLang("advanced.anchor_delta_width",0)),height:90+parseInt(j.getLang("advanced.anchor_delta_height",0)),inline:true},{theme_url:this.url})},_mceCharMap:function(){var j=this.editor;j.windowManager.open({url:this.url+"/charmap.htm",width:550+parseInt(j.getLang("advanced.charmap_delta_width",0)),height:265+parseInt(j.getLang("advanced.charmap_delta_height",0)),inline:true},{theme_url:this.url})},_mceHelp:function(){var j=this.editor;j.windowManager.open({url:this.url+"/about.htm",width:480,height:380,inline:true},{theme_url:this.url})},_mceShortcuts:function(){var j=this.editor;j.windowManager.open({url:this.url+"/shortcuts.htm",width:480,height:380,inline:true},{theme_url:this.url})},_mceColorPicker:function(l,k){var j=this.editor;k=k||{};j.windowManager.open({url:this.url+"/color_picker.htm",width:375+parseInt(j.getLang("advanced.colorpicker_delta_width",0)),height:250+parseInt(j.getLang("advanced.colorpicker_delta_height",0)),close_previous:false,inline:true},{input_color:k.color,func:k.func,theme_url:this.url})},_mceCodeEditor:function(k,l){var j=this.editor;j.windowManager.open({url:this.url+"/source_editor.htm",width:parseInt(j.getParam("theme_advanced_source_editor_width",720)),height:parseInt(j.getParam("theme_advanced_source_editor_height",580)),inline:true,resizable:true,maximizable:true},{theme_url:this.url})},_mceImage:function(k,l){var j=this.editor;if(j.dom.getAttrib(j.selection.getNode(),"class","").indexOf("mceItem")!=-1){return}j.windowManager.open({url:this.url+"/image.htm",width:355+parseInt(j.getLang("advanced.image_delta_width",0)),height:275+parseInt(j.getLang("advanced.image_delta_height",0)),inline:true},{theme_url:this.url})},_mceLink:function(k,l){var j=this.editor;j.windowManager.open({url:this.url+"/link.htm",width:310+parseInt(j.getLang("advanced.link_delta_width",0)),height:200+parseInt(j.getLang("advanced.link_delta_height",0)),inline:true},{theme_url:this.url})},_mceNewDocument:function(){var j=this.editor;j.windowManager.confirm("advanced.newdocument",function(k){if(k){j.execCommand("mceSetContent",false,"")}})},_mceForeColor:function(){var j=this;this._mceColorPicker(0,{color:j.fgColor,func:function(k){j.fgColor=k;j.editor.execCommand("ForeColor",false,k)}})},_mceBackColor:function(){var j=this;this._mceColorPicker(0,{color:j.bgColor,func:function(k){j.bgColor=k;j.editor.execCommand("HiliteColor",false,k)}})},_ufirst:function(j){return j.substring(0,1).toUpperCase()+j.substring(1)}});h.ThemeManager.add("advanced",h.themes.AdvancedTheme)}(tinymce)); \ No newline at end of file diff --git a/application/views/scripts/javascripts/vendor/tiny_mce/themes/advanced/editor_template_src.js b/application/views/scripts/javascripts/vendor/tiny_mce/themes/advanced/editor_template_src.js index f5f49cd660..82166dcb68 100644 --- a/application/views/scripts/javascripts/vendor/tiny_mce/themes/advanced/editor_template_src.js +++ b/application/views/scripts/javascripts/vendor/tiny_mce/themes/advanced/editor_template_src.js @@ -11,25 +11,6 @@ (function(tinymce) { var DOM = tinymce.DOM, Event = tinymce.dom.Event, extend = tinymce.extend, each = tinymce.each, Cookie = tinymce.util.Cookie, lastExtID, explode = tinymce.explode; - var applyDefaultFont = function (body, settings) { - var fontSize = settings.theme_advanced_default_font_size; - var fontFamily = settings.theme_advanced_default_font_family; - - if (fontSize) { - body.style.fontSize = fontSize; - } - - if (fontFamily) { - body.style.fontFamily = fontFamily; - } - }; - - var hasDefaultFontSizeOrFamily = function (settings) { - var fontSize = settings.theme_advanced_default_font_size; - var fontFamily = settings.theme_advanced_default_font_family; - return !!(fontSize || fontFamily); - }; - // Generates a preview for a format function getPreviewCss(ed, fmt) { var name, previewElm, dom = ed.dom, previewCss = '', parentFontSize, previewStylesName; @@ -194,7 +175,7 @@ theme_advanced_blockformats : "p,address,pre,h1,h2,h3,h4,h5,h6", theme_advanced_toolbar_align : "left", theme_advanced_statusbar_location : "bottom", - theme_advanced_fonts : "Andale Mono=andale mono,monospace;Arial=arial,helvetica,sans-serif;Arial Black=arial black,sans-serif;Book Antiqua=book antiqua,palatino,serif;Comic Sans MS=comic sans ms,sans-serif;Courier New=courier new,courier,monospace;Georgia=georgia,palatino,serif;Helvetica=helvetica,arial,sans-serif;Impact=impact,sans-serif;Symbol=symbol;Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal,monaco,monospace;Times New Roman=times new roman,times,serif;Trebuchet MS=trebuchet ms,geneva,sans-serif;Verdana=verdana,geneva,sans-serif;Webdings=webdings;Wingdings=wingdings,zapf dingbats", + theme_advanced_fonts : "Andale Mono=andale mono,times;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;Comic Sans MS=comic sans ms,sans-serif;Courier New=courier new,courier;Georgia=georgia,palatino;Helvetica=helvetica;Impact=impact,chicago;Symbol=symbol;Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal,monaco;Times New Roman=times new roman,times;Trebuchet MS=trebuchet ms,geneva;Verdana=verdana,geneva;Webdings=webdings;Wingdings=wingdings,zapf dingbats", theme_advanced_more_colors : 1, theme_advanced_row_height : 23, theme_advanced_resize_horizontal : 1, @@ -253,8 +234,6 @@ t._updateUndoStatus(ed); }); } - - applyDefaultFont(ed.getBody(), ed.settings); }); ed.onSetProgressState.add(function(ed, b, ti) { @@ -1100,8 +1079,8 @@ cm.setActive(c, ed.queryCommandState(t.controls[c][1])); }); - var getElement = function (elements, name) { - var i, elements, func = name; + function getParent(name) { + var i, parents = ob.parents, func = name; if (typeof(name) == 'string') { func = function(node) { @@ -1109,20 +1088,12 @@ }; } - for (i = 0; i < elements.length; i++) { - if (func(elements[i])) - return elements[i]; + for (i = 0; i < parents.length; i++) { + if (func(parents[i])) + return parents[i]; } }; - function getParent(name) { - return getElement(ob.parents, name); - }; - - function getParentIncBody(name) { - return getElement([].concat(ob.parents).concat([ed.getBody()]), name); - }; - cm.setActive('visualaid', ed.hasVisual); t._updateUndoStatus(ed); cm.setDisabled('outdent', !ed.queryCommandState('Outdent')); @@ -1171,16 +1142,13 @@ } // Find out current fontSize, fontFamily and fontClass - getParentIncBody(function(n) { - var matchesSelector; - + getParent(function(n) { if (n.nodeName === 'SPAN') { if (!cl && n.className) cl = n.className; } - matchesSelector = ed.dom.is(n, s.theme_advanced_font_selector); - if (matchesSelector || hasDefaultFontSizeOrFamily(ed.settings)) { + if (ed.dom.is(n, s.theme_advanced_font_selector)) { if (!fz && n.style.fontSize) fz = n.style.fontSize; diff --git a/application/views/scripts/javascripts/vendor/tiny_mce/themes/advanced/skins/default/content.css b/application/views/scripts/javascripts/vendor/tiny_mce/themes/advanced/skins/default/content.css index 757e090243..2fd94a1f9c 100644 --- a/application/views/scripts/javascripts/vendor/tiny_mce/themes/advanced/skins/default/content.css +++ b/application/views/scripts/javascripts/vendor/tiny_mce/themes/advanced/skins/default/content.css @@ -45,7 +45,6 @@ font[face=mceinline] {font-family:inherit !important} .mceItemRealMedia {background-image:url(../../img/realmedia.gif)} .mceItemVideo {background-image:url(../../img/video.gif)} .mceItemAudio {background-image:url(../../img/video.gif)} -.mceItemObject {background-image:url(../../img/video.gif)} .mceItemEmbeddedAudio {background-image:url(../../img/video.gif)} .mceItemIframe {background-image:url(../../img/iframe.gif)} .mcePageBreak {display:block;border:0;width:100%;height:12px;border-top:1px dotted #ccc;margin-top:15px;background:#fff url(../../img/pagebreak.gif) no-repeat center top;} diff --git a/application/views/scripts/javascripts/vendor/tiny_mce/tiny_mce.js b/application/views/scripts/javascripts/vendor/tiny_mce/tiny_mce.js index 37f4d2f129..53b68042af 100644 --- a/application/views/scripts/javascripts/vendor/tiny_mce/tiny_mce.js +++ b/application/views/scripts/javascripts/vendor/tiny_mce/tiny_mce.js @@ -1 +1 @@ -(function(e){var a=/^\s*|\s*$/g,b,d="B".replace(/A(.)|B/,"$1")==="$1";var c={majorVersion:"3",minorVersion:"5.12",releaseDate:"2016-10-31",_init:function(){var s=this,q=document,o=navigator,g=o.userAgent,m,f,l,k,j,r;s.isIE11=g.indexOf("Trident/")!=-1&&(g.indexOf("rv:")!=-1||o.appName.indexOf("Netscape")!=-1);s.isOpera=e.opera&&opera.buildNumber;s.isWebKit=/WebKit/.test(g);s.isIE=!s.isWebKit&&!s.isOpera&&(/MSIE/gi).test(g)&&(/Explorer/gi).test(o.appName)||s.isIE11;s.isIE6=s.isIE&&/MSIE [56]/.test(g);s.isIE7=s.isIE&&/MSIE [7]/.test(g);s.isIE8=s.isIE&&/MSIE [8]/.test(g);s.isIE9=s.isIE&&/MSIE [9]/.test(g);s.isGecko=!s.isWebKit&&!s.isIE11&&/Gecko/.test(g);s.isMac=g.indexOf("Mac")!=-1;s.isAir=/adobeair/i.test(g);s.isIDevice=/(iPad|iPhone)/.test(g);s.isIOS5=s.isIDevice&&g.match(/AppleWebKit\/(\d*)/)[1]>=534;s.isIE12=(document.msElementsFromPoint&&!s.isIE&&!s.isIE11);if(s.isIE12){s.isIE11=true;s.isWebKit=false}if(e.tinyMCEPreInit){s.suffix=tinyMCEPreInit.suffix;s.baseURL=tinyMCEPreInit.base;s.query=tinyMCEPreInit.query;return}s.suffix="";f=q.getElementsByTagName("base");for(m=0;m0?b:[f.scope]);if(e===false){break}}a.inDispatch=false;return e}});(function(){var a=tinymce.each;tinymce.create("tinymce.util.URI",{URI:function(e,g){var f=this,i,d,c,h;e=tinymce.trim(e);g=f.settings=g||{};if(/^([\w\-]+):([^\/]{2})/i.test(e)||/^\s*#/.test(e)){f.source=e;return}if(e.indexOf("/")===0&&e.indexOf("//")!==0){e=(g.base_uri?g.base_uri.protocol||"http":"http")+"://mce_host"+e}if(!/^[\w\-]*:?\/\//.test(e)){h=g.base_uri?g.base_uri.path:new tinymce.util.URI(location.href).directory;e=((g.base_uri&&g.base_uri.protocol)||"http")+"://mce_host"+f.toAbsPath(h,e)}e=e.replace(/@@/g,"(mce_at)");e=/^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@\/]*):?([^:@\/]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/.exec(e);a(["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],function(b,j){var k=e[j];if(k){k=k.replace(/\(mce_at\)/g,"@@")}f[b]=k});c=g.base_uri;if(c){if(!f.protocol){f.protocol=c.protocol}if(!f.userInfo){f.userInfo=c.userInfo}if(!f.port&&f.host==="mce_host"){f.port=c.port}if(!f.host||f.host==="mce_host"){f.host=c.host}f.source=""}},setPath:function(c){var b=this;c=/^(.*?)\/?(\w+)?$/.exec(c);b.path=c[0];b.directory=c[1];b.file=c[2];b.source="";b.getURI()},toRelative:function(b){var d=this,f;if(b==="./"){return b}b=new tinymce.util.URI(b,{base_uri:d});if((b.host!="mce_host"&&d.host!=b.host&&b.host)||d.port!=b.port||d.protocol!=b.protocol){return b.getURI()}var c=d.getURI(),e=b.getURI();if(c==e||(c.charAt(c.length-1)=="/"&&c.substr(0,c.length-1)==e)){return c}f=d.toRelPath(d.path,b.path);if(b.query){f+="?"+b.query}if(b.anchor){f+="#"+b.anchor}return f},toAbsolute:function(b,c){b=new tinymce.util.URI(b,{base_uri:this});return b.getURI(this.host==b.host&&this.protocol==b.protocol?c:0)},toRelPath:function(g,h){var c,f=0,d="",e,b;g=g.substring(0,g.lastIndexOf("/"));g=g.split("/");c=h.split("/");if(g.length>=c.length){for(e=0,b=g.length;e=c.length||g[e]!=c[e]){f=e+1;break}}}if(g.length=g.length||g[e]!=c[e]){f=e+1;break}}}if(f===1){return h}for(e=0,b=g.length-(f-1);e=0;c--){if(f[c].length===0||f[c]==="."){continue}if(f[c]===".."){b++;continue}if(b>0){b--;continue}h.push(f[c])}c=e.length-b;if(c<=0){g=h.reverse().join("/")}else{g=e.slice(0,c).join("/")+"/"+h.reverse().join("/")}if(g.indexOf("/")!==0){g="/"+g}if(d&&g.lastIndexOf("/")!==g.length-1){g+=d}return g},getURI:function(d){var c,b=this;if(!b.source||d){c="";if(!d){if(b.protocol){c+=b.protocol+"://"}if(b.userInfo){c+=b.userInfo+"@"}if(b.host){c+=b.host}if(b.port){c+=":"+b.port}}if(b.path){c+=b.path}if(b.query){c+="?"+b.query}if(b.anchor){c+="#"+b.anchor}b.source=c}return b.source}})})();(function(){var a=tinymce.each;tinymce.create("static tinymce.util.Cookie",{getHash:function(d){var b=this.get(d),c;if(b){a(b.split("&"),function(e){e=e.split("=");c=c||{};c[unescape(e[0])]=unescape(e[1])})}return c},setHash:function(j,b,g,f,i,c){var h="";a(b,function(e,d){h+=(!h?"":"&")+escape(d)+"="+escape(e)});this.set(j,h,g,f,i,c)},get:function(i){var h=document.cookie,g,f=i+"=",d;if(!h){return}d=h.indexOf("; "+f);if(d==-1){d=h.indexOf(f);if(d!==0){return null}}else{d+=2}g=h.indexOf(";",d);if(g==-1){g=h.length}return unescape(h.substring(d+f.length,g))},set:function(i,b,g,f,h,c){document.cookie=i+"="+escape(b)+((g)?"; expires="+g.toGMTString():"")+((f)?"; path="+escape(f):"")+((h)?"; domain="+h:"")+((c)?"; secure":"")},remove:function(c,e,d){var b=new Date();b.setTime(b.getTime()-1000);this.set(c,"",b,e,d)}})})();(function(){function serialize(o,quote){var i,v,t,name;quote=quote||'"';if(o==null){return"null"}t=typeof o;if(t=="string"){v="\bb\tt\nn\ff\rr\"\"''\\\\";return quote+o.replace(/([\u0080-\uFFFF\x00-\x1f\"\'\\])/g,function(a,b){if(quote==='"'&&a==="'"){return a}i=v.indexOf(b);if(i+1){return"\\"+v.charAt(i+1)}a=b.charCodeAt().toString(16);return"\\u"+"0000".substring(a.length)+a})+quote}if(t=="object"){if(o.hasOwnProperty&&Object.prototype.toString.call(o)==="[object Array]"){for(i=0,v="[";i0?",":"")+serialize(o[i],quote)}return v+"]"}v="{";for(name in o){if(o.hasOwnProperty(name)){v+=typeof o[name]!="function"?(v.length>1?","+quote:quote)+name+quote+":"+serialize(o[name],quote):""}}return v+"}"}return""+o}tinymce.util.JSON={serialize:serialize,parse:function(s){try{return eval("("+s+")")}catch(ex){}}}})();tinymce.create("static tinymce.util.XHR",{send:function(g){var a,e,b=window,h=0;function f(){if(!g.async||a.readyState==4||h++>10000){if(g.success&&h<10000&&a.status==200){g.success.call(g.success_scope,""+a.responseText,a,g)}else{if(g.error){g.error.call(g.error_scope,h>10000?"TIMED_OUT":"GENERAL",a,g)}}a=null}else{b.setTimeout(f,10)}}g.scope=g.scope||this;g.success_scope=g.success_scope||g.scope;g.error_scope=g.error_scope||g.scope;g.async=g.async===false?false:true;g.data=g.data||"";function d(i){a=0;try{a=new ActiveXObject(i)}catch(c){}return a}a=b.XMLHttpRequest?new XMLHttpRequest():d("Microsoft.XMLHTTP")||d("Msxml2.XMLHTTP");if(a){if(a.overrideMimeType){a.overrideMimeType(g.content_type)}a.open(g.type||(g.data?"POST":"GET"),g.url,g.async);if(g.content_type){a.setRequestHeader("Content-Type",g.content_type)}a.setRequestHeader("X-Requested-With","XMLHttpRequest");a.send(g.data);if(!g.async){return f()}e=b.setTimeout(f,10)}}});(function(){var c=tinymce.extend,b=tinymce.util.JSON,a=tinymce.util.XHR;tinymce.create("tinymce.util.JSONRequest",{JSONRequest:function(d){this.settings=c({},d);this.count=0},send:function(f){var e=f.error,d=f.success;f=c(this.settings,f);f.success=function(h,g){h=b.parse(h);if(typeof(h)=="undefined"){h={error:"JSON Parse error."}}if(h.error){e.call(f.error_scope||f.scope,h.error,g)}else{d.call(f.success_scope||f.scope,h.result)}};f.error=function(h,g){if(e){e.call(f.error_scope||f.scope,h,g)}};f.data=b.serialize({id:f.id||"c"+(this.count++),method:f.method,params:f.params});f.content_type="application/json";a.send(f)},"static":{sendRPC:function(d){return new tinymce.util.JSONRequest().send(d)}}})}());(function(a){a.VK={BACKSPACE:8,DELETE:46,DOWN:40,ENTER:13,LEFT:37,RIGHT:39,SPACEBAR:32,TAB:9,UP:38,modifierPressed:function(b){return b.shiftKey||b.ctrlKey||b.altKey},metaKeyPressed:function(b){return a.isMac?b.metaKey:b.ctrlKey&&!b.altKey}}})(tinymce);tinymce.util.Quirks=function(a){var j=tinymce.VK,f=j.BACKSPACE,l=j.DELETE,e=a.dom,n=a.selection,J=a.settings,y=a.parser,q=a.serializer,G=tinymce.each;function C(P,O){try{a.getDoc().execCommand(P,false,O)}catch(N){}}function p(){var N=a.getDoc().documentMode;return N?N:6}function B(N){return N.isDefaultPrevented()}function L(){function N(T){var P,R,O,U,Q,S,V;function W(){if(Q.nodeType==3){if(T&&S==Q.length){return true}if(!T&&S===0){return true}}}P=n.getRng();var X=[P.startContainer,P.startOffset,P.endContainer,P.endOffset];if(!P.collapsed){T=true}Q=P[(T?"start":"end")+"Container"];S=P[(T?"start":"end")+"Offset"];if(Q.nodeType==3){R=e.getParent(P.startContainer,e.isBlock);if(T){R=e.getNext(R,e.isBlock)}if(R&&(W()||!P.collapsed)){O=e.create("em",{id:"__mceDel"});G(tinymce.grep(R.childNodes),function(Y){O.appendChild(Y)});R.appendChild(O)}}P=e.createRng();P.setStart(X[0],X[1]);P.setEnd(X[2],X[3]);n.setRng(P);a.getDoc().execCommand(T?"ForwardDelete":"Delete",false,null);if(O){U=n.getBookmark();while(V=e.get("__mceDel")){e.remove(V,true)}n.moveToBookmark(U)}}a.onKeyDown.add(function(O,Q){var P;P=Q.keyCode==l;if(!B(Q)&&(P||Q.keyCode==f)&&!j.modifierPressed(Q)){Q.preventDefault();N(P)}});a.addCommand("Delete",function(){N()})}function s(){function N(Q){var P=e.create("body");var R=Q.cloneContents();P.appendChild(R);return n.serializer.serialize(P,{format:"html"})}function O(P){var R=N(P);var S=e.createRng();S.selectNode(a.getBody());var Q=N(S);return R===Q}a.onKeyDown.add(function(Q,S){var R=S.keyCode,P;if(!B(S)&&(R==l||R==f)){P=Q.selection.isCollapsed();if(P&&!e.isEmpty(Q.getBody())){return}if(tinymce.isIE&&!P){return}if(!P&&!O(Q.selection.getRng())){return}Q.setContent("");Q.selection.setCursorLocation(Q.getBody(),0);Q.nodeChanged()}})}function K(){a.onKeyDown.add(function(N,O){if(!B(O)&&O.keyCode==65&&j.metaKeyPressed(O)){O.preventDefault();N.execCommand("SelectAll")}})}function M(){if(!a.settings.content_editable){e.bind(a.getDoc(),"focusin",function(N){n.setRng(n.getRng())});e.bind(a.getDoc(),"mousedown",function(N){if(N.target==a.getDoc().documentElement){a.getWin().focus();n.setRng(n.getRng())}})}}function D(){a.onKeyDown.add(function(N,Q){if(!B(Q)&&Q.keyCode===f){if(n.isCollapsed()&&n.getRng(true).startOffset===0){var P=n.getNode();var O=P.previousSibling;if(O&&O.nodeName&&O.nodeName.toLowerCase()==="hr"){e.remove(O);tinymce.dom.Event.cancel(Q)}}}})}function A(){if(!Range.prototype.getClientRects){a.onMouseDown.add(function(O,P){if(!B(P)&&P.target.nodeName==="HTML"){var N=O.getBody();N.blur();setTimeout(function(){N.focus()},0)}})}}function h(){a.onClick.add(function(N,O){O=O.target;if(/^(IMG|HR)$/.test(O.nodeName)){n.getSel().setBaseAndExtent(O,0,O,1)}if(O.nodeName=="A"&&e.hasClass(O,"mceItemAnchor")){n.select(O)}N.nodeChanged()})}function c(){function O(){var Q=e.getAttribs(n.getStart().cloneNode(false));return function(){var R=n.getStart();if(R!==a.getBody()){e.setAttrib(R,"style",null);G(Q,function(S){R.setAttributeNode(S.cloneNode(true))})}}}function N(){return !n.isCollapsed()&&e.getParent(n.getStart(),e.isBlock)!=e.getParent(n.getEnd(),e.isBlock)}function P(Q,R){R.preventDefault();return false}a.onKeyPress.add(function(Q,S){var R;if(!B(S)&&(S.keyCode==8||S.keyCode==46)&&N()){R=O();Q.getDoc().execCommand("delete",false,null);R();S.preventDefault();return false}});e.bind(a.getDoc(),"cut",function(R){var Q;if(!B(R)&&N()){Q=O();a.onKeyUp.addToTop(P);setTimeout(function(){Q();a.onKeyUp.remove(P)},0)}})}function b(){var O,N;e.bind(a.getDoc(),"selectionchange",function(){if(N){clearTimeout(N);N=0}N=window.setTimeout(function(){var P=n.getRng();if(!O||!tinymce.dom.RangeUtils.compareRanges(P,O)){a.nodeChanged();O=P}},50)})}function z(){document.body.setAttribute("role","application")}function v(){a.onKeyDown.add(function(N,P){if(!B(P)&&P.keyCode===f){if(n.isCollapsed()&&n.getRng(true).startOffset===0){var O=n.getNode().previousSibling;if(O&&O.nodeName&&O.nodeName.toLowerCase()==="table"){return tinymce.dom.Event.cancel(P)}}}})}function E(){if(p()>7){return}C("RespectVisibilityInDesign",true);a.contentStyles.push(".mceHideBrInPre pre br {display: none}");e.addClass(a.getBody(),"mceHideBrInPre");y.addNodeFilter("pre",function(N,P){var Q=N.length,S,O,T,R;while(Q--){S=N[Q].getAll("br");O=S.length;while(O--){T=S[O];R=T.prev;if(R&&R.type===3&&R.value.charAt(R.value-1)!="\n"){R.value+="\n"}else{T.parent.insert(new tinymce.html.Node("#text",3),T,true).value="\n"}}}});q.addNodeFilter("pre",function(N,P){var Q=N.length,S,O,T,R;while(Q--){S=N[Q].getAll("br");O=S.length;while(O--){T=S[O];R=T.prev;if(R&&R.type==3){R.value=R.value.replace(/\r?\n$/,"")}}}})}function g(){e.bind(a.getBody(),"mouseup",function(P){var O,N=n.getNode();if(N.nodeName=="IMG"){if(O=e.getStyle(N,"width")){e.setAttrib(N,"width",O.replace(/[^0-9%]+/g,""));e.setStyle(N,"width","")}if(O=e.getStyle(N,"height")){e.setAttrib(N,"height",O.replace(/[^0-9%]+/g,""));e.setStyle(N,"height","")}}})}function d(){a.onKeyDown.add(function(T,U){var S,N,O,Q,R,V,P;S=U.keyCode==l;if(!B(U)&&(S||U.keyCode==f)&&!j.modifierPressed(U)){N=n.getRng();O=N.startContainer;Q=N.startOffset;P=N.collapsed;if(O.nodeType==3&&O.nodeValue.length>0&&((Q===0&&!P)||(P&&Q===(S?0:1)))){V=O.previousSibling;if(V&&V.nodeName=="IMG"){return}nonEmptyElements=T.schema.getNonEmptyElements();U.preventDefault();R=e.create("br",{id:"__tmp"});O.parentNode.insertBefore(R,O);T.getDoc().execCommand(S?"ForwardDelete":"Delete",false,null);O=n.getRng().startContainer;V=O.previousSibling;if(V&&V.nodeType==1&&!e.isBlock(V)&&e.isEmpty(V)&&!nonEmptyElements[V.nodeName.toLowerCase()]){e.remove(V)}e.remove("__tmp")}}})}function I(){a.onKeyDown.add(function(R,S){var P,O,T,N,Q;if(B(S)||S.keyCode!=j.BACKSPACE){return}P=n.getRng();O=P.startContainer;T=P.startOffset;N=e.getRoot();Q=O;if(!P.collapsed||T!==0){return}while(Q&&Q.parentNode&&Q.parentNode.firstChild==Q&&Q.parentNode!=N){Q=Q.parentNode}if(Q.tagName==="BLOCKQUOTE"){R.formatter.toggle("blockquote",null,Q);P=e.createRng();P.setStart(O,0);P.setEnd(O,0);n.setRng(P)}})}function H(){function N(){a._refreshContentEditable();C("StyleWithCSS",false);C("enableInlineTableEditing",false);if(!J.object_resizing){C("enableObjectResizing",false)}}if(!J.readonly){a.onBeforeExecCommand.add(N);a.onMouseDown.add(N)}}function u(){function N(O,P){G(e.select("a"),function(S){var Q=S.parentNode,R=e.getRoot();if(Q.lastChild===S){while(Q&&!e.isBlock(Q)){if(Q.parentNode.lastChild!==Q||Q===R){return}Q=Q.parentNode}e.add(Q,"br",{"data-mce-bogus":1})}})}a.onExecCommand.add(function(O,P){if(P==="CreateLink"){N(O)}});a.onSetContent.add(n.onSetContent.add(N))}function o(){if(J.forced_root_block){a.onInit.add(function(){C("DefaultParagraphSeparator",J.forced_root_block)})}}function r(){function N(P,O){if(!P||!O.initial){a.execCommand("mceRepaint")}}a.onUndo.add(N);a.onRedo.add(N);a.onSetContent.add(N)}function i(){a.onKeyDown.add(function(O,P){var N;if(!B(P)&&P.keyCode==f){N=O.getDoc().selection.createRange();if(N&&N.item){P.preventDefault();O.undoManager.beforeChange();e.remove(N.item(0));O.undoManager.add()}}})}function t(){var N;if(p()>=10){N="";G("p div h1 h2 h3 h4 h5 h6".split(" "),function(O,P){N+=(P>0?",":"")+O+":empty"});a.contentStyles.push(N+"{padding-right: 1px !important}")}}function x(){var P,O,af,N,aa,ad,ab,ae,Q,R,ac,Y,X,Z=document,V=a.getDoc();if(!J.object_resizing||J.webkit_fake_resize===false){return}C("enableObjectResizing",false);ac={n:[0.5,0,0,-1],e:[1,0.5,1,0],s:[0.5,1,0,1],w:[0,0.5,-1,0],nw:[0,0,-1,-1],ne:[1,0,1,-1],se:[1,1,1,1],sw:[0,1,-1,1]};function T(aj){var ai,ah;ai=aj.screenX-ad;ah=aj.screenY-ab;Y=ai*aa[2]+ae;X=ah*aa[3]+Q;Y=Y<5?5:Y;X=X<5?5:X;if(j.modifierPressed(aj)||(af.nodeName=="IMG"&&aa[2]*aa[3]!==0)){Y=Math.round(X/R);X=Math.round(Y*R)}e.setStyles(N,{width:Y,height:X});if(aa[2]<0&&N.clientWidth<=Y){e.setStyle(N,"left",P+(ae-Y))}if(aa[3]<0&&N.clientHeight<=X){e.setStyle(N,"top",O+(Q-X))}}function ag(){function ah(ai,aj){if(aj){if(af.style[ai]||!a.schema.isValid(af.nodeName.toLowerCase(),ai)){e.setStyle(af,ai,aj)}else{e.setAttrib(af,ai,aj)}}}ah("width",Y);ah("height",X);e.unbind(V,"mousemove",T);e.unbind(V,"mouseup",ag);if(Z!=V){e.unbind(Z,"mousemove",T);e.unbind(Z,"mouseup",ag)}e.remove(N);S(af)}function S(ak){var ai,aj,ah;U();ai=e.getPos(ak);P=ai.x;O=ai.y;aj=ak.offsetWidth;ah=ak.offsetHeight;if(af!=ak){af=ak;Y=X=0}G(ac,function(an,al){var am;am=e.get("mceResizeHandle"+al);if(!am){am=e.add(V.documentElement,"div",{id:"mceResizeHandle"+al,"class":"mceResizeHandle",style:"cursor:"+al+"-resize; margin:0; padding:0"});e.bind(am,"mousedown",function(ao){ao.preventDefault();ag();ad=ao.screenX;ab=ao.screenY;ae=af.clientWidth;Q=af.clientHeight;R=Q/ae;aa=an;N=af.cloneNode(true);e.addClass(N,"mceClonedResizable");e.setStyles(N,{left:P,top:O,margin:0});V.documentElement.appendChild(N);e.bind(V,"mousemove",T);e.bind(V,"mouseup",ag);if(Z!=V){e.bind(Z,"mousemove",T);e.bind(Z,"mouseup",ag)}})}else{e.show(am)}e.setStyles(am,{left:(aj*an[0]+P)-(am.offsetWidth/2),top:(ah*an[1]+O)-(am.offsetHeight/2)})});if(!tinymce.isOpera&&af.nodeName=="IMG"){af.setAttribute("data-mce-selected","1")}}function U(){if(af){af.removeAttribute("data-mce-selected")}for(var ah in ac){e.hide("mceResizeHandle"+ah)}}a.contentStyles.push(".mceResizeHandle {position: absolute;border: 1px solid black;background: #FFF;width: 5px;height: 5px;z-index: 10000}.mceResizeHandle:hover {background: #000}img[data-mce-selected] {outline: 1px solid black}img.mceClonedResizable, table.mceClonedResizable {position: absolute;outline: 1px dashed black;opacity: .5;z-index: 10000}");function W(){var ah=e.getParent(n.getNode(),"table,img");G(e.select("img[data-mce-selected]"),function(ai){ai.removeAttribute("data-mce-selected")});if(ah){S(ah)}else{U()}}a.onNodeChange.add(W);e.bind(V,"selectionchange",W);a.serializer.addAttributeFilter("data-mce-selected",function(ah,ai){var aj=ah.length;while(aj--){ah[aj].attr(ai,null)}})}function F(){if(p()<9){y.addNodeFilter("noscript",function(N){var O=N.length,P,Q;while(O--){P=N[O];Q=P.firstChild;if(Q){P.attr("data-mce-innertext",Q.value)}}});q.addNodeFilter("noscript",function(N){var O=N.length,P,R,Q;while(O--){P=N[O];R=N[O].firstChild;if(R){R.value=tinymce.html.Entities.decode(R.value)}else{Q=P.attributes.map["data-mce-innertext"];if(Q){P.attr("data-mce-innertext",null);R=new tinymce.html.Node("#text",3);R.value=Q;R.raw=true;P.append(R)}}}})}}function m(){a.contentStyles.push("body {min-height: 100px}");a.onClick.add(function(N,O){if(O.target.nodeName=="HTML"){a.execCommand("SelectAll");a.selection.collapse(true);a.nodeChanged()}})}function k(){a.onInit.add(function(){var N;a.getBody().addEventListener("mscontrolselect",function(O){setTimeout(function(){if(a.selection.getNode()!=O.target){N=a.selection.getRng();n.fakeRng=a.dom.createRng();n.fakeRng.setStartBefore(O.target);n.fakeRng.setEndAfter(O.target)}},0)},false);a.getDoc().addEventListener("selectionchange",function(O){if(N&&!tinymce.dom.RangeUtils.compareRanges(a.selection.getRng(),N)){n.fakeRng=N=null}},false)})}v();I();s();if(tinymce.isWebKit){d();L();M();h();o();if(tinymce.isIDevice){b()}else{x();K()}}if(tinymce.isIE&&!tinymce.isIE11){D();z();E();g();i();t();F()}if(tinymce.isIE11){m();k()}if(tinymce.isGecko&&!tinymce.isIE11){D();A();c();H();u();r()}if(tinymce.isOpera){x()}};(function(j){var a,g,d,k=/[&<>\"\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,b=/[<>&\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,f=/[<>&\"\']/g,c=/&(#x|#)?([\w]+);/g,i={128:"\u20AC",130:"\u201A",131:"\u0192",132:"\u201E",133:"\u2026",134:"\u2020",135:"\u2021",136:"\u02C6",137:"\u2030",138:"\u0160",139:"\u2039",140:"\u0152",142:"\u017D",145:"\u2018",146:"\u2019",147:"\u201C",148:"\u201D",149:"\u2022",150:"\u2013",151:"\u2014",152:"\u02DC",153:"\u2122",154:"\u0161",155:"\u203A",156:"\u0153",158:"\u017E",159:"\u0178"};g={'"':""","'":"'","<":"<",">":">","&":"&"};d={"<":"<",">":">","&":"&",""":'"',"'":"'"};function h(l){var m;m=document.createElement("div");m.innerHTML=l;return m.textContent||m.innerText||l}function e(m,p){var n,o,l,q={};if(m){m=m.split(",");p=p||10;for(n=0;n1){return"&#"+(((n.charCodeAt(0)-55296)*1024)+(n.charCodeAt(1)-56320)+65536)+";"}return g[n]||"&#"+n.charCodeAt(0)+";"})},encodeNamed:function(n,l,m){m=m||a;return n.replace(l?k:b,function(o){return g[o]||m[o]||o})},getEncodeFunc:function(l,o){var p=j.html.Entities;o=e(o)||a;function m(r,q){return r.replace(q?k:b,function(s){return g[s]||o[s]||"&#"+s.charCodeAt(0)+";"||s})}function n(r,q){return p.encodeNamed(r,q,o)}l=j.makeMap(l.replace(/\+/g,","));if(l.named&&l.numeric){return m}if(l.named){if(o){return n}return p.encodeNamed}if(l.numeric){return p.encodeNumeric}return p.encodeRaw},decode:function(l){return l.replace(c,function(n,m,o){if(m){o=parseInt(o,m.length===2?16:10);if(o>65535){o-=65536;return String.fromCharCode(55296+(o>>10),56320+(o&1023))}else{return i[o]||String.fromCharCode(o)}}return d[n]||a[n]||h(n)})}}})(tinymce);tinymce.html.Styles=function(d,f){var k=/rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)/gi,h=/(?:url(?:(?:\(\s*\"([^\"]+)\"\s*\))|(?:\(\s*\'([^\']+)\'\s*\))|(?:\(\s*([^)\s]+)\s*\))))|(?:\'([^\']+)\')|(?:\"([^\"]+)\")/gi,b=/\s*([^:]+):\s*([^;]+);?/g,l=/\s+$/,m=/rgb/,e,g,a={},j;d=d||{};j="\\\" \\' \\; \\: ; : \uFEFF".split(" ");for(g=0;g1?r:"0"+r}return"#"+o(q)+o(p)+o(i)}return{toHex:function(i){return i.replace(k,c)},parse:function(s){var z={},q,n,x,r,v=d.url_converter,y=d.url_converter_scope||this;function p(D,G){var F,C,B,E;if(z["border-image"]==="none"){delete z["border-image"]}F=z[D+"-top"+G];if(!F){return}C=z[D+"-right"+G];if(F!=C){return}B=z[D+"-bottom"+G];if(C!=B){return}E=z[D+"-left"+G];if(B!=E){return}z[D+G]=E;delete z[D+"-top"+G];delete z[D+"-right"+G];delete z[D+"-bottom"+G];delete z[D+"-left"+G]}function u(C){var D=z[C],B;if(!D||D.indexOf(" ")<0){return}D=D.split(" ");B=D.length;while(B--){if(D[B]!==D[0]){return false}}z[C]=D[0];return true}function A(D,C,B,E){if(!u(C)){return}if(!u(B)){return}if(!u(E)){return}z[D]=z[C]+" "+z[B]+" "+z[E];delete z[C];delete z[B];delete z[E]}function t(B){r=true;return a[B]}function i(C,B){if(r){C=C.replace(/\uFEFF[0-9]/g,function(D){return a[D]})}if(!B){C=C.replace(/\\([\'\";:])/g,"$1")}return C}function o(C,B,F,E,G,D){G=G||D;if(G){G=i(G);return"'"+G.replace(/\'/g,"\\'")+"'"}B=i(B||F||E);if(v){B=v.call(y,B,"style")}return"url('"+B.replace(/\'/g,"\\'")+"')"}if(s){s=s.replace(/\\[\"\';:\uFEFF]/g,t).replace(/\"[^\"]+\"|\'[^\']+\'/g,function(B){return B.replace(/[;:]/g,t)});while(q=b.exec(s)){n=q[1].replace(l,"").toLowerCase();x=q[2].replace(l,"");if(n&&x.length>0){if(n==="font-weight"&&x==="700"){x="bold"}else{if(n==="color"||n==="background-color"){x=x.toLowerCase()}}x=x.replace(k,c);x=x.replace(h,o);z[n]=r?i(x,true):x}b.lastIndex=q.index+q[0].length}p("border","");p("border","-width");p("border","-color");p("border","-style");p("padding","");p("margin","");A("border","border-width","border-style","border-color");if(z.border==="medium none"){delete z.border}}return z},serialize:function(p,r){var o="",n,q;function i(t){var x,u,s,v;x=f.styles[t];if(x){for(u=0,s=x.length;u0){o+=(o.length>0?" ":"")+t+": "+v+";"}}}}if(r&&f&&f.styles){i("*");i(r)}else{for(n in p){q=p[n];if(q!==e&&q.length>0){o+=(o.length>0?" ":"")+n+": "+q+";"}}}return o}}};(function(f){var a={},e=f.makeMap,g=f.each;function d(j,i){return j.split(i||",")}function h(m,l){var j,k={};function i(n){return n.replace(/[A-Z]+/g,function(o){return i(m[o])})}for(j in m){if(m.hasOwnProperty(j)){m[j]=i(m[j])}}i(l).replace(/#/g,"#text").replace(/(\w+)\[([^\]]+)\]\[([^\]]*)\]/g,function(q,o,n,p){n=d(n,"|");k[o]={attributes:e(n),attributesOrder:n,children:e(p,"|",{"#comment":{}})}});return k}function b(){var i=a.html5;if(!i){i=a.html5=h({A:"id|accesskey|class|dir|draggable|item|hidden|itemprop|role|spellcheck|style|subject|title|onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup",B:"#|a|abbr|area|audio|b|bdo|br|button|canvas|cite|code|command|datalist|del|dfn|em|embed|i|iframe|img|input|ins|kbd|keygen|label|link|map|mark|meta|meter|noscript|object|output|progress|q|ruby|samp|script|select|small|span|strong|sub|sup|svg|textarea|time|var|video|wbr",C:"#|a|abbr|area|address|article|aside|audio|b|bdo|blockquote|br|button|canvas|cite|code|command|datalist|del|details|dfn|dialog|div|dl|em|embed|fieldset|figure|footer|form|h1|h2|h3|h4|h5|h6|header|hgroup|hr|i|iframe|img|input|ins|kbd|keygen|label|link|map|mark|menu|meta|meter|nav|noscript|ol|object|output|p|pre|progress|q|ruby|samp|script|section|select|small|span|strong|style|sub|sup|svg|table|textarea|time|ul|var|video"},"html[A|manifest][body|head]head[A][base|command|link|meta|noscript|script|style|title]title[A][#]base[A|href|target][]link[A|href|rel|media|type|sizes][]meta[A|http-equiv|name|content|charset][]style[A|type|media|scoped][#]script[A|charset|type|src|defer|async][#]noscript[A][C]body[A][C]section[A][C]nav[A][C]article[A][C]aside[A][C]h1[A][B]h2[A][B]h3[A][B]h4[A][B]h5[A][B]h6[A][B]hgroup[A][h1|h2|h3|h4|h5|h6]header[A][C]footer[A][C]address[A][C]p[A][B]br[A][]pre[A][B]dialog[A][dd|dt]blockquote[A|cite][C]ol[A|start|reversed][li]ul[A][li]li[A|value][C]dl[A][dd|dt]dt[A][B]dd[A][C]a[A|href|target|ping|rel|media|type][B]em[A][B]strong[A][B]small[A][B]cite[A][B]q[A|cite][B]dfn[A][B]abbr[A][B]code[A][B]var[A][B]samp[A][B]kbd[A][B]sub[A][B]sup[A][B]i[A][B]b[A][B]mark[A][B]progress[A|value|max][B]meter[A|value|min|max|low|high|optimum][B]time[A|datetime][B]ruby[A][B|rt|rp]rt[A][B]rp[A][B]bdo[A][B]span[A][B]ins[A|cite|datetime][B]del[A|cite|datetime][B]figure[A][C|legend|figcaption]figcaption[A][C]img[A|alt|src|height|width|usemap|ismap][]iframe[A|name|src|height|width|sandbox|seamless][]embed[A|src|height|width|type][]object[A|data|type|height|width|usemap|name|form|classid][param]param[A|name|value][]details[A|open][C|legend]command[A|type|label|icon|disabled|checked|radiogroup][]menu[A|type|label][C|li]legend[A][C|B]div[A][C]source[A|src|type|media][]audio[A|src|autobuffer|autoplay|loop|controls][source]video[A|src|autobuffer|autoplay|loop|controls|width|height|poster][source]hr[A][]form[A|accept-charset|action|autocomplete|enctype|method|name|novalidate|target][C]fieldset[A|disabled|form|name][C|legend]label[A|form|for][B]input[A|type|accept|alt|autocomplete|autofocus|checked|disabled|form|formaction|formenctype|formmethod|formnovalidate|formtarget|height|list|max|maxlength|min|multiple|pattern|placeholder|readonly|required|size|src|step|width|files|value|name][]button[A|autofocus|disabled|form|formaction|formenctype|formmethod|formnovalidate|formtarget|name|value|type][B]select[A|autofocus|disabled|form|multiple|name|size][option|optgroup]datalist[A][B|option]optgroup[A|disabled|label][option]option[A|disabled|selected|label|value][]textarea[A|autofocus|disabled|form|maxlength|name|placeholder|readonly|required|rows|cols|wrap][]keygen[A|autofocus|challenge|disabled|form|keytype|name][]output[A|for|form|name][B]canvas[A|width|height][]map[A|name][B|C]area[A|shape|coords|href|alt|target|media|rel|ping|type][]mathml[A][]svg[A][]table[A|border][caption|colgroup|thead|tfoot|tbody|tr]caption[A][C]colgroup[A|span][col]col[A|span][]thead[A][tr]tfoot[A][tr]tbody[A][tr]tr[A][th|td]th[A|headers|rowspan|colspan|scope][B]td[A|headers|rowspan|colspan][C]wbr[A][]")}return i}function c(){var i=a.html4;if(!i){i=a.html4=h({Z:"H|K|N|O|P",Y:"X|form|R|Q",ZG:"E|span|width|align|char|charoff|valign",X:"p|T|div|U|W|isindex|fieldset|table",ZF:"E|align|char|charoff|valign",W:"pre|hr|blockquote|address|center|noframes",ZE:"abbr|axis|headers|scope|rowspan|colspan|align|char|charoff|valign|nowrap|bgcolor|width|height",ZD:"[E][S]",U:"ul|ol|dl|menu|dir",ZC:"p|Y|div|U|W|table|br|span|bdo|object|applet|img|map|K|N|Q",T:"h1|h2|h3|h4|h5|h6",ZB:"X|S|Q",S:"R|P",ZA:"a|G|J|M|O|P",R:"a|H|K|N|O",Q:"noscript|P",P:"ins|del|script",O:"input|select|textarea|label|button",N:"M|L",M:"em|strong|dfn|code|q|samp|kbd|var|cite|abbr|acronym",L:"sub|sup",K:"J|I",J:"tt|i|b|u|s|strike",I:"big|small|font|basefont",H:"G|F",G:"br|span|bdo",F:"object|applet|img|map|iframe",E:"A|B|C",D:"accesskey|tabindex|onfocus|onblur",C:"onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup",B:"lang|xml:lang|dir",A:"id|class|style|title"},"script[id|charset|type|language|src|defer|xml:space][]style[B|id|type|media|title|xml:space][]object[E|declare|classid|codebase|data|type|codetype|archive|standby|width|height|usemap|name|tabindex|align|border|hspace|vspace][#|param|Y]param[id|name|value|valuetype|type][]p[E|align][#|S]a[E|D|charset|type|name|href|hreflang|rel|rev|shape|coords|target][#|Z]br[A|clear][]span[E][#|S]bdo[A|C|B][#|S]applet[A|codebase|archive|code|object|alt|name|width|height|align|hspace|vspace][#|param|Y]h1[E|align][#|S]img[E|src|alt|name|longdesc|width|height|usemap|ismap|align|border|hspace|vspace][]map[B|C|A|name][X|form|Q|area]h2[E|align][#|S]iframe[A|longdesc|name|src|frameborder|marginwidth|marginheight|scrolling|align|width|height][#|Y]h3[E|align][#|S]tt[E][#|S]i[E][#|S]b[E][#|S]u[E][#|S]s[E][#|S]strike[E][#|S]big[E][#|S]small[E][#|S]font[A|B|size|color|face][#|S]basefont[id|size|color|face][]em[E][#|S]strong[E][#|S]dfn[E][#|S]code[E][#|S]q[E|cite][#|S]samp[E][#|S]kbd[E][#|S]var[E][#|S]cite[E][#|S]abbr[E][#|S]acronym[E][#|S]sub[E][#|S]sup[E][#|S]input[E|D|type|name|value|checked|disabled|readonly|size|maxlength|src|alt|usemap|onselect|onchange|accept|align][]select[E|name|size|multiple|disabled|tabindex|onfocus|onblur|onchange][optgroup|option]optgroup[E|disabled|label][option]option[E|selected|disabled|label|value][]textarea[E|D|name|rows|cols|disabled|readonly|onselect|onchange][]label[E|for|accesskey|onfocus|onblur][#|S]button[E|D|name|value|type|disabled][#|p|T|div|U|W|table|G|object|applet|img|map|K|N|Q]h4[E|align][#|S]ins[E|cite|datetime][#|Y]h5[E|align][#|S]del[E|cite|datetime][#|Y]h6[E|align][#|S]div[E|align][#|Y]ul[E|type|compact][li]li[E|type|value][#|Y]ol[E|type|compact|start][li]dl[E|compact][dt|dd]dt[E][#|S]dd[E][#|Y]menu[E|compact][li]dir[E|compact][li]pre[E|width|xml:space][#|ZA]hr[E|align|noshade|size|width][]blockquote[E|cite][#|Y]address[E][#|S|p]center[E][#|Y]noframes[E][#|Y]isindex[A|B|prompt][]fieldset[E][#|legend|Y]legend[E|accesskey|align][#|S]table[E|summary|width|border|frame|rules|cellspacing|cellpadding|align|bgcolor][caption|col|colgroup|thead|tfoot|tbody|tr]caption[E|align][#|S]col[ZG][]colgroup[ZG][col]thead[ZF][tr]tr[ZF|bgcolor][th|td]th[E|ZE][#|Y]form[E|action|method|name|enctype|onsubmit|onreset|accept|accept-charset|target][#|X|R|Q]noscript[E][#|Y]td[E|ZE][#|Y]tfoot[ZF][tr]tbody[ZF][tr]area[E|D|shape|coords|href|nohref|alt|target][]base[id|href|target][]body[E|onload|onunload|background|bgcolor|text|link|vlink|alink][#|Y]")}return i}f.html.Schema=function(A){var u=this,s={},k={},j=[],D,y;var o,q,z,r,v,n,p={};function m(F,E,H){var G=A[F];if(!G){G=a[F];if(!G){G=e(E," ",e(E.toUpperCase()," "));G=f.extend(G,H);a[F]=G}}else{G=e(G,",",e(G.toUpperCase()," "))}return G}A=A||{};y=A.schema=="html5"?b():c();if(A.verify_html===false){A.valid_elements="*[*]"}if(A.valid_styles){D={};g(A.valid_styles,function(F,E){D[E]=f.explode(F)})}o=m("whitespace_elements","pre script noscript style textarea");q=m("self_closing_elements","colgroup dd dt li option p td tfoot th thead tr");z=m("short_ended_elements","area base basefont br col frame hr img input isindex link meta param embed source wbr");r=m("boolean_attributes","checked compact declare defer disabled ismap multiple nohref noresize noshade nowrap readonly selected autoplay loop controls");n=m("non_empty_elements","td th iframe video audio object script",z);textBlockElementsMap=m("text_block_elements","h1 h2 h3 h4 h5 h6 p div address pre form blockquote center dir fieldset header footer article section hgroup aside nav figure");v=m("block_elements","hr table tbody thead tfoot th tr td li ol ul caption dl dt dd noscript menu isindex samp option datalist select optgroup",textBlockElementsMap);function i(E){return new RegExp("^"+E.replace(/([?+*])/g,".$1")+"$")}function C(L){var K,G,Z,V,aa,F,I,U,X,Q,Y,ac,O,J,W,E,S,H,ab,ad,P,T,N=/^([#+\-])?([^\[\/]+)(?:\/([^\[]+))?(?:\[([^\]]+)\])?$/,R=/^([!\-])?(\w+::\w+|[^=:<]+)?(?:([=:<])(.*))?$/,M=/[*?+]/;if(L){L=d(L);if(s["@"]){S=s["@"].attributes;H=s["@"].attributesOrder}for(K=0,G=L.length;K=0){for(U=A.length-1;U>=V;U--){T=A[U];if(T.valid){n.end(T.name)}}A.length=V}}function p(U,T,Y,X,W){var Z,V;T=T.toLowerCase();Y=T in H?T:j(Y||X||W||"");if(v&&!z&&T.indexOf("data-")!==0){Z=P[T];if(!Z&&F){V=F.length;while(V--){Z=F[V];if(Z.pattern.test(T)){break}}if(V===-1){Z=null}}if(!Z){return}if(Z.validValues&&!(Y in Z.validValues)){return}}N.map[T]=Y;N.push({name:T,value:Y})}l=new RegExp("<(?:(?:!--([\\w\\W]*?)-->)|(?:!\\[CDATA\\[([\\w\\W]*?)\\]\\]>)|(?:!DOCTYPE([\\w\\W]*?)>)|(?:\\?([^\\s\\/<>]+) ?([\\w\\W]*?)[?/]>)|(?:\\/([^>]+)>)|(?:([A-Za-z0-9\\-\\:\\.]+)((?:\\s+[^\"'>]+(?:(?:\"[^\"]*\")|(?:'[^']*')|[^>]*))*|\\/|\\s+)>))","g");D=/([\w:\-]+)(?:\s*=\s*(?:(?:\"((?:[^\"])*)\")|(?:\'((?:[^\'])*)\')|([^>\s]+)))?/g;K={script:/<\/script[^>]*>/gi,style:/<\/style[^>]*>/gi,noscript:/<\/noscript[^>]*>/gi};M=e.getShortEndedElements();J=c.self_closing_elements||e.getSelfClosingElements();H=e.getBoolAttrs();v=c.validate;s=c.remove_internals;y=c.fix_self_closing;q=a.isIE;o=/^:/;while(g=l.exec(E)){if(G0&&A[A.length-1].name===I){u(I)}if(!v||(m=e.getElementRule(I))){k=true;if(v){P=m.attributes;F=m.attributePatterns}if(R=g[8]){z=R.indexOf("data-mce-type")!==-1;if(z&&s){k=false}N=[];N.map={};R.replace(D,p)}else{N=[];N.map={}}if(v&&!z){S=m.attributesRequired;L=m.attributesDefault;f=m.attributesForced;if(f){Q=f.length;while(Q--){t=f[Q];r=t.name;h=t.value;if(h==="{$uid}"){h="mce_"+x++}N.map[r]=h;N.push({name:r,value:h})}}if(L){Q=L.length;while(Q--){t=L[Q];r=t.name;if(!(r in N.map)){h=t.value;if(h==="{$uid}"){h="mce_"+x++}N.map[r]=h;N.push({name:r,value:h})}}}if(S){Q=S.length;while(Q--){if(S[Q] in N.map){break}}if(Q===-1){k=false}}if(N.map["data-mce-bogus"]){k=false}}if(k){n.start(I,N,O)}}else{k=false}if(B=K[I]){B.lastIndex=G=g.index+g[0].length;if(g=B.exec(E)){if(k){C=E.substr(G,g.index-G)}G=g.index+g[0].length}else{C=E.substr(G);G=E.length}if(k&&C.length>0){n.text(C,true)}if(k){n.end(I)}l.lastIndex=G;continue}if(!O){if(!R||R.indexOf("/")!=R.length-1){A.push({name:I,valid:k})}else{if(k){n.end(I)}}}}else{if(I=g[1]){n.comment(I)}else{if(I=g[2]){n.cdata(I)}else{if(I=g[3]){n.doctype(I)}else{if(I=g[4]){n.pi(I,g[5])}}}}}}G=g.index+g[0].length}if(G=0;Q--){I=A[Q];if(I.valid){n.end(I.name)}}}}})(tinymce);(function(d){var c=/^[ \t\r\n]*$/,e={"#text":3,"#comment":8,"#cdata":4,"#pi":7,"#doctype":10,"#document-fragment":11};function a(k,l,j){var i,h,f=j?"lastChild":"firstChild",g=j?"prev":"next";if(k[f]){return k[f]}if(k!==l){i=k[g];if(i){return i}for(h=k.parent;h&&h!==l;h=h.parent){i=h[g];if(i){return i}}}}function b(f,g){this.name=f;this.type=g;if(g===1){this.attributes=[];this.attributes.map={}}}d.extend(b.prototype,{replace:function(g){var f=this;if(g.parent){g.remove()}f.insert(g,f);f.remove();return f},attr:function(h,l){var f=this,g,j,k;if(typeof h!=="string"){for(j in h){f.attr(j,h[j])}return f}if(g=f.attributes){if(l!==k){if(l===null){if(h in g.map){delete g.map[h];j=g.length;while(j--){if(g[j].name===h){g=g.splice(j,1);return f}}}return f}if(h in g.map){j=g.length;while(j--){if(g[j].name===h){g[j].value=l;break}}}else{g.push({name:h,value:l})}g.map[h]=l;return f}else{return g.map[h]}}},clone:function(){var g=this,n=new b(g.name,g.type),h,f,m,j,k;if(m=g.attributes){k=[];k.map={};for(h=0,f=m.length;h1){x.reverse();A=o=f.filterNode(x[0].clone());for(u=0;u0){Q.value=l;Q=Q.prev}else{O=Q.prev;Q.remove();Q=O}}}function H(O){var P,l={};for(P in O){if(P!=="li"&&P!="p"){l[P]=O[P]}}return l}n=new b.html.SaxParser({validate:z,self_closing_elements:H(h.getSelfClosingElements()),cdata:function(l){B.append(K("#cdata",4)).value=l},text:function(P,l){var O;if(!L){P=P.replace(k," ");if(B.lastChild&&o[B.lastChild.name]){P=P.replace(E,"")}}if(P.length!==0){O=K("#text",3);O.raw=!!l;B.append(O).value=P}},comment:function(l){B.append(K("#comment",8)).value=l},pi:function(l,O){B.append(K(l,7)).value=O;I(B)},doctype:function(O){var l;l=B.append(K("#doctype",10));l.value=O;I(B)},start:function(l,W,P){var U,R,Q,O,S,X,V,T;Q=z?h.getElementRule(l):{};if(Q){U=K(Q.outputName||l,1);U.attributes=W;U.shortEnded=P;B.append(U);T=p[B.name];if(T&&p[U.name]&&!T[U.name]){M.push(U)}R=d.length;while(R--){S=d[R].name;if(S in W.map){F=c[S];if(F){F.push(U)}else{c[S]=[U]}}}if(o[l]){I(U)}if(!P){B=U}if(!L&&s[l]){L=true}}},end:function(l){var S,P,R,O,Q;P=z?h.getElementRule(l):{};if(P){if(o[l]){if(!L){S=B.firstChild;if(S&&S.type===3){R=S.value.replace(E,"");if(R.length>0){S.value=R;S=S.next}else{O=S.next;S.remove();S=O;while(S&&S.type===3){R=S.value;O=S.next;if(R.length===0||y.test(R)){S.remove();S=O}S=O}}}S=B.lastChild;if(S&&S.type===3){R=S.value.replace(t,"");if(R.length>0){S.value=R;S=S.prev}else{O=S.prev;S.remove();S=O;while(S&&S.type===3){R=S.value;O=S.prev;if(R.length===0||y.test(R)){S.remove();S=O}S=O}}}}}if(L&&s[l]){L=false}if(P.removeEmpty||P.paddEmpty){if(B.isEmpty(u)){if(P.paddEmpty){B.empty().append(new a("#text","3")).value="\u00a0"}else{if(!B.attributes.map.name&&!B.attributes.map.id){Q=B.parent;if(o[B.name]){B.empty().remove()}else{B.unwrap()}B=Q;return}}}}B=B.parent}}},h);J=B=new a(m.context||g.root_name,11);n.parse(v);if(z&&M.length){if(!m.context){j(M)}else{m.invalid=true}}if(q&&J.name=="body"){G()}if(!m.invalid){for(N in i){F=e[N];A=i[N];x=A.length;while(x--){if(!A[x].parent){A.splice(x,1)}}for(D=0,C=F.length;D0){o=c[c.length-1];if(o.length>0&&o!=="\n"){c.push("\n")}}c.push("<",m);if(k){for(n=0,j=k.length;n0){o=c[c.length-1];if(o.length>0&&o!=="\n"){c.push("\n")}}},end:function(h){var i;c.push("");if(a&&d[h]&&c.length>0){i=c[c.length-1];if(i.length>0&&i!=="\n"){c.push("\n")}}},text:function(i,h){if(i.length>0){c[c.length]=h?i:f(i)}},cdata:function(h){c.push("")},comment:function(h){c.push("")},pi:function(h,i){if(i){c.push("")}else{c.push("")}if(a){c.push("\n")}},doctype:function(h){c.push("",a?"\n":"")},reset:function(){c.length=0},getContent:function(){return c.join("").replace(/\n$/,"")}}};(function(a){a.html.Serializer=function(c,d){var b=this,e=new a.html.Writer(c);c=c||{};c.validate="validate" in c?c.validate:true;b.schema=d=d||new a.html.Schema();b.writer=e;b.serialize=function(h){var g,i;i=c.validate;g={3:function(k,j){e.text(k.value,k.raw)},8:function(j){e.comment(j.value)},7:function(j){e.pi(j.name,j.value)},10:function(j){e.doctype(j.value)},4:function(j){e.cdata(j.value)},11:function(j){if((j=j.firstChild)){do{f(j)}while(j=j.next)}}};e.reset();function f(k){var t=g[k.type],j,o,s,r,p,u,n,m,q;if(!t){j=k.name;o=k.shortEnded;s=k.attributes;if(i&&s&&s.length>1){u=[];u.map={};q=d.getElementRule(k.name);for(n=0,m=q.attributesOrder.length;n=8;k.boxModel=!e.isIE||o.compatMode=="CSS1Compat"||k.stdMode;k.hasOuterHTML="outerHTML" in o.createElement("a");k.settings=l=e.extend({keep_values:false,hex_colors:1},l);k.schema=l.schema;k.styles=new e.html.Styles({url_converter:l.url_converter,url_converter_scope:l.url_converter_scope},l.schema);if(e.isIE6){try{o.execCommand("BackgroundImageCache",false,true)}catch(m){k.cssFlicker=true}}k.fixDoc(o);k.events=l.ownEvents?new e.dom.EventUtils(l.proxy):e.dom.Event;e.addUnload(k.destroy,k);n=l.schema?l.schema.getBlockElements():{};k.isBlock=function(q){if(!q){return false}var p=q.nodeType;if(p){return !!(p===1&&n[q.nodeName])}return !!n[q]}},fixDoc:function(k){var j=this.settings,i;if(b&&!e.isIE11&&j.schema){("abbr article aside audio canvas details figcaption figure footer header hgroup mark menu meter nav output progress section summary time video").replace(/\w+/g,function(l){k.createElement(l)});for(i in j.schema.getCustomElements()){k.createElement(i)}}},clone:function(k,i){var j=this,m,l;if(!b||e.isIE11||k.nodeType!==1||i){return k.cloneNode(i)}l=j.doc;if(!i){m=l.createElement(k.nodeName);g(j.getAttribs(k),function(n){j.setAttrib(m,n.nodeName,j.getAttrib(k,n.nodeName))});return m}return m.firstChild},getRoot:function(){var i=this,j=i.settings;return(j&&i.get(j.root_element))||i.doc.body},getViewPort:function(j){var k,i;j=!j?this.win:j;k=j.document;i=this.boxModel?k.documentElement:k.body;return{x:j.pageXOffset||i.scrollLeft,y:j.pageYOffset||i.scrollTop,w:j.innerWidth||i.clientWidth,h:j.innerHeight||i.clientHeight}},getRect:function(l){var k,i=this,j;l=i.get(l);k=i.getPos(l);j=i.getSize(l);return{x:k.x,y:k.y,w:j.w,h:j.h}},getSize:function(l){var j=this,i,k;l=j.get(l);i=j.getStyle(l,"width");k=j.getStyle(l,"height");if(i.indexOf("px")===-1){i=0}if(k.indexOf("px")===-1){k=0}return{w:parseInt(i,10)||l.offsetWidth||l.clientWidth,h:parseInt(k,10)||l.offsetHeight||l.clientHeight}},getParent:function(k,j,i){return this.getParents(k,j,i,false)},getParents:function(s,m,k,q){var j=this,i,l=j.settings,p=[];s=j.get(s);q=q===undefined;if(l.strict_root){k=k||j.getRoot()}if(d(m,"string")){i=m;if(m==="*"){m=function(o){return o.nodeType==1}}else{m=function(o){return j.is(o,i)}}}while(s){if(s==k||!s.nodeType||s.nodeType===9){break}if(!m||m(s)){if(q){p.push(s)}else{return s}}s=s.parentNode}return q?p:null},get:function(i){var j;if(i&&this.doc&&typeof(i)=="string"){j=i;i=this.doc.getElementById(i);if(i&&i.id!==j){return this.doc.getElementsByName(j)[1]}}return i},getNext:function(j,i){return this._findSib(j,i,"nextSibling")},getPrev:function(j,i){return this._findSib(j,i,"previousSibling")},select:function(k,j){var i=this;return e.dom.Sizzle(k,i.get(j)||i.get(i.settings.root_element)||i.doc,[])},is:function(l,j){var k;if(l.length===undefined){if(j==="*"){return l.nodeType==1}if(c.test(j)){j=j.toLowerCase().split(/,/);l=l.nodeName.toLowerCase();for(k=j.length-1;k>=0;k--){if(j[k]==l){return true}}return false}}return e.dom.Sizzle.matches(j,l.nodeType?[l]:l).length>0},add:function(l,o,i,k,m){var j=this;return this.run(l,function(r){var q,n;q=d(o,"string")?j.doc.createElement(o):o;j.setAttribs(q,i);if(k){if(k.nodeType){q.appendChild(k)}else{j.setHTML(q,k)}}return !m?r.appendChild(q):q})},create:function(k,i,j){return this.add(this.doc.createElement(k),k,i,j,1)},createHTML:function(q,i,m){var p="",l=this,j;p+="<"+q;for(j in i){if(i.hasOwnProperty(j)){p+=" "+j+'="'+l.encode(i[j])+'"'}}if(typeof(m)!="undefined"){return p+">"+m+""}return p+" />"},remove:function(i,j){return this.run(i,function(l){var m,k=l.parentNode;if(!k){return null}if(j){while(m=l.firstChild){if(!e.isIE||m.nodeType!==3||m.nodeValue){k.insertBefore(m,l)}else{l.removeChild(m)}}}return k.removeChild(l)})},setStyle:function(l,i,j){var k=this;return k.run(l,function(o){var n,m;n=o.style;i=i.replace(/-(\D)/g,function(q,p){return p.toUpperCase()});if(k.pixelStyles.test(i)&&(e.is(j,"number")||/^[\-0-9\.]+$/.test(j))){j+="px"}switch(i){case"opacity":if(b&&!e.isIE11){n.filter=j===""?"":"alpha(opacity="+(j*100)+")";if(!l.currentStyle||!l.currentStyle.hasLayout){n.display="inline-block"}}n[i]=n["-moz-opacity"]=n["-khtml-opacity"]=j||"";break;case"float":(b&&!e.isIE11)?n.styleFloat=j:n.cssFloat=j;break;default:n[i]=j||""}if(k.settings.update_styles){k.setAttrib(o,"data-mce-style")}})},getStyle:function(l,i,k){l=this.get(l);if(!l){return}if(this.doc.defaultView&&k){i=i.replace(/[A-Z]/g,function(m){return"-"+m});try{return this.doc.defaultView.getComputedStyle(l,null).getPropertyValue(i)}catch(j){return null}}i=i.replace(/-(\D)/g,function(n,m){return m.toUpperCase()});if(i=="float"){i=b?"styleFloat":"cssFloat"}if(l.currentStyle&&k){return l.currentStyle[i]}return l.style?l.style[i]:undefined},setStyles:function(l,m){var j=this,k=j.settings,i;i=k.update_styles;k.update_styles=0;g(m,function(o,p){j.setStyle(l,p,o)});k.update_styles=i;if(k.update_styles){j.setAttrib(l,k.cssText)}},removeAllAttribs:function(i){return this.run(i,function(l){var k,j=l.attributes;for(k=j.length-1;k>=0;k--){l.removeAttributeNode(j.item(k))}})},setAttrib:function(k,l,i){var j=this;if(!k||!l){return}if(j.settings.strict){l=l.toLowerCase()}return this.run(k,function(p){var o=j.settings;var m=p.getAttribute(l);if(i!==null){switch(l){case"style":if(!d(i,"string")){g(i,function(q,r){j.setStyle(p,r,q)});return}if(o.keep_values){if(i&&!j._isRes(i)){p.setAttribute("data-mce-style",i,2)}else{p.removeAttribute("data-mce-style",2)}}p.style.cssText=i;break;case"class":p.className=i||"";break;case"src":case"href":if(o.keep_values){if(o.url_converter){i=o.url_converter.call(o.url_converter_scope||j,i,l,p)}j.setAttrib(p,"data-mce-"+l,i,2)}break;case"shape":p.setAttribute("data-mce-style",i);break}}if(d(i)&&i!==null&&i.length!==0){p.setAttribute(l,""+i,2)}else{p.removeAttribute(l,2)}if(tinyMCE.activeEditor&&m!=i){var n=tinyMCE.activeEditor;n.onSetAttrib.dispatch(n,p,l,i)}})},setAttribs:function(j,k){var i=this;return this.run(j,function(l){g(k,function(m,o){i.setAttrib(l,o,m)})})},getAttrib:function(m,o,k){var i,j=this,l;m=j.get(m);if(!m||m.nodeType!==1){return k===l?false:k}if(!d(k)){k=""}if(/^(src|href|style|coords|shape)$/.test(o)){i=m.getAttribute("data-mce-"+o);if(i){return i}}if(b&&j.props[o]){i=m[j.props[o]];i=i&&i.nodeValue?i.nodeValue:i}if(!i){i=m.getAttribute(o,2)}if(/^(checked|compact|declare|defer|disabled|ismap|multiple|nohref|noshade|nowrap|readonly|selected)$/.test(o)){if(m[j.props[o]]===true&&i===""){return o}return i?o:""}if(m.nodeName==="FORM"&&m.getAttributeNode(o)){return m.getAttributeNode(o).nodeValue}if(o==="style"){i=i||m.style.cssText;if(i){i=j.serializeStyle(j.parseStyle(i),m.nodeName);if(j.settings.keep_values&&!j._isRes(i)){m.setAttribute("data-mce-style",i)}}}if(f&&o==="class"&&i){i=i.replace(/(apple|webkit)\-[a-z\-]+/gi,"")}if(b){switch(o){case"rowspan":case"colspan":if(i===1){i=""}break;case"size":if(i==="+0"||i===20||i===0){i=""}break;case"width":case"height":case"vspace":case"checked":case"disabled":case"readonly":if(i===0){i=""}break;case"hspace":if(i===-1){i=""}break;case"maxlength":case"tabindex":if(i===32768||i===2147483647||i==="32768"){i=""}break;case"multiple":case"compact":case"noshade":case"nowrap":if(i===65535){return o}return k;case"shape":i=i.toLowerCase();break;default:if(o.indexOf("on")===0&&i){i=e._replace(/^function\s+\w+\(\)\s+\{\s+(.*)\s+\}$/,"$1",""+i)}}}return(i!==l&&i!==null&&i!=="")?""+i:k},getPos:function(q,l){var j=this,i=0,p=0,m,o=j.doc,k;q=j.get(q);l=l||o.body;if(q){if(q.getBoundingClientRect){q=q.getBoundingClientRect();m=j.boxModel?o.documentElement:o.body;i=q.left+(o.documentElement.scrollLeft||o.body.scrollLeft)-m.clientTop;p=q.top+(o.documentElement.scrollTop||o.body.scrollTop)-m.clientLeft;return{x:i,y:p}}k=q;while(k&&k!=l&&k.nodeType){i+=k.offsetLeft||0;p+=k.offsetTop||0;k=k.offsetParent}k=q.parentNode;while(k&&k!=l&&k.nodeType){i-=k.scrollLeft||0;p-=k.scrollTop||0;k=k.parentNode}}return{x:i,y:p}},parseStyle:function(i){return this.styles.parse(i)},serializeStyle:function(j,i){return this.styles.serialize(j,i)},addStyle:function(j){var k=this.doc,i;styleElm=k.getElementById("mceDefaultStyles");if(!styleElm){styleElm=k.createElement("style"),styleElm.id="mceDefaultStyles";styleElm.type="text/css";i=k.getElementsByTagName("head")[0];if(i.firstChild){i.insertBefore(styleElm,i.firstChild)}else{i.appendChild(styleElm)}}if(styleElm.styleSheet){styleElm.styleSheet.cssText+=j}else{styleElm.appendChild(k.createTextNode(j))}},loadCSS:function(i){var k=this,l=k.doc,j;if(!i){i=""}j=l.getElementsByTagName("head")[0];g(i.split(","),function(m){var n;if(k.files[m]){return}k.files[m]=true;n=k.create("link",{rel:"stylesheet",href:e._addVer(m)});if(b&&!e.isIE11&&l.documentMode&&l.recalc){n.onload=function(){if(l.recalc){l.recalc()}n.onload=null}}j.appendChild(n)})},addClass:function(i,j){return this.run(i,function(k){var l;if(!j){return 0}if(this.hasClass(k,j)){return k.className}l=this.removeClass(k,j);return k.className=(l!=""?(l+" "):"")+j})},removeClass:function(k,l){var i=this,j;return i.run(k,function(n){var m;if(i.hasClass(n,l)){if(!j){j=new RegExp("(^|\\s+)"+l+"(\\s+|$)","g")}m=n.className.replace(j," ");m=e.trim(m!=" "?m:"");n.className=m;if(!m){n.removeAttribute("class");n.removeAttribute("className")}return m}return n.className})},hasClass:function(j,i){j=this.get(j);if(!j||!i){return false}return(" "+j.className+" ").indexOf(" "+i+" ")!==-1},show:function(i){return this.setStyle(i,"display","block")},hide:function(i){return this.setStyle(i,"display","none")},isHidden:function(i){i=this.get(i);return !i||i.style.display=="none"||this.getStyle(i,"display")=="none"},uniqueId:function(i){return(!i?"mce_":i)+(this.counter++)},setHTML:function(k,j){var i=this;return i.run(k,function(m){if(b){while(m.firstChild){m.removeChild(m.firstChild)}try{m.innerHTML="
"+j;m.removeChild(m.firstChild)}catch(l){var n=i.create("div");n.innerHTML="
"+j;g(e.grep(n.childNodes),function(p,o){if(o&&m.canHaveHTML){m.appendChild(p)}})}}else{m.innerHTML=j}return j})},getOuterHTML:function(k){var j,i=this;k=i.get(k);if(!k){return null}if(k.nodeType===1&&i.hasOuterHTML){return k.outerHTML}j=(k.ownerDocument||i.doc).createElement("body");j.appendChild(k.cloneNode(true));return j.innerHTML},setOuterHTML:function(l,j,m){var i=this;function k(p,o,r){var s,q;q=r.createElement("body");q.innerHTML=o;s=q.lastChild;while(s){i.insertAfter(s.cloneNode(true),p);s=s.previousSibling}i.remove(p)}return this.run(l,function(o){o=i.get(o);if(o.nodeType==1){m=m||o.ownerDocument||i.doc;if(b){try{if(b&&o.nodeType==1){o.outerHTML=j}else{k(o,j,m)}}catch(n){k(o,j,m)}}else{k(o,j,m)}}})},decode:h.decode,encode:h.encodeAllRaw,insertAfter:function(i,j){j=this.get(j);return this.run(i,function(l){var k,m;k=j.parentNode;m=j.nextSibling;if(m){k.insertBefore(l,m)}else{k.appendChild(l)}return l})},replace:function(m,l,i){var j=this;if(d(l,"array")){m=m.cloneNode(true)}return j.run(l,function(k){if(i){g(e.grep(k.childNodes),function(n){m.appendChild(n)})}return k.parentNode.replaceChild(m,k)})},rename:function(l,i){var k=this,j;if(l.nodeName!=i.toUpperCase()){j=k.create(i);g(k.getAttribs(l),function(m){k.setAttrib(j,m.nodeName,k.getAttrib(l,m.nodeName))});k.replace(j,l,1)}return j||l},findCommonAncestor:function(k,i){var l=k,j;while(l){j=i;while(j&&l!=j){j=j.parentNode}if(l==j){break}l=l.parentNode}if(!l&&k.ownerDocument){return k.ownerDocument.documentElement}return l},toHex:function(i){var k=/^\s*rgb\s*?\(\s*?([0-9]+)\s*?,\s*?([0-9]+)\s*?,\s*?([0-9]+)\s*?\)\s*$/i.exec(i);function j(l){l=parseInt(l,10).toString(16);return l.length>1?l:"0"+l}if(k){i="#"+j(k[1])+j(k[2])+j(k[3]);return i}return i},getClasses:function(){var n=this,j=[],m,o={},p=n.settings.class_filter,l;if(n.classes){return n.classes}function q(i){g(i.imports,function(s){q(s)});g(i.cssRules||i.rules,function(t){switch(t.type||1){case 1:if(t.selectorText){g(t.selectorText.split(","),function(r){r=r.replace(/^\s*|\s*$|^\s\./g,"");if(/\.mce/.test(r)||!/\.[\w\-]+$/.test(r)){return}l=r;r=e._replace(/.*\.([a-z0-9_\-]+).*/i,"$1",r);if(p&&!(r=p(r,l))){return}if(!o[r]){j.push({"class":r});o[r]=1}})}break;case 3:try{q(t.styleSheet)}catch(s){}break}})}try{g(n.doc.styleSheets,q)}catch(k){}if(j.length>0){n.classes=j}return j},run:function(l,k,j){var i=this,m;if(i.doc&&typeof(l)==="string"){l=i.get(l)}if(!l){return false}j=j||this;if(!l.nodeType&&(l.length||l.length===0)){m=[];g(l,function(o,n){if(o){if(typeof(o)=="string"){o=i.doc.getElementById(o)}m.push(k.call(j,o,n))}});return m}return k.call(j,l)},getAttribs:function(j){var i;j=this.get(j);if(!j){return[]}if(b){i=[];if(j.nodeName=="OBJECT"){return j.attributes}if(j.nodeName==="OPTION"&&this.getAttrib(j,"selected")){i.push({specified:1,nodeName:"selected"})}j.cloneNode(false).outerHTML.replace(/<\/?[\w:\-]+ ?|=[\"][^\"]+\"|=\'[^\']+\'|=[\w\-]+|>/gi,"").replace(/[\w:\-]+/gi,function(k){i.push({specified:1,nodeName:k})});return i}return j.attributes},isEmpty:function(m,k){var r=this,o,n,q,j,l,p=0;m=m.firstChild;if(m){j=new e.dom.TreeWalker(m,m.parentNode);k=k||r.schema?r.schema.getNonEmptyElements():null;do{q=m.nodeType;if(q===1){if(m.getAttribute("data-mce-bogus")){continue}l=m.nodeName.toLowerCase();if(k&&k[l]){if(l==="br"){p++;continue}return false}n=r.getAttribs(m);o=m.attributes.length;while(o--){l=m.attributes[o].nodeName;if(l==="name"||l==="data-mce-bookmark"){return false}}}if(q==8){return false}if((q===3&&!a.test(m.nodeValue))){return false}}while(m=j.next())}return p<=1},destroy:function(j){var i=this;i.win=i.doc=i.root=i.events=i.frag=null;if(!j){e.removeUnload(i.destroy)}},createRng:function(){var i=this.doc;return i.createRange?i.createRange():new e.dom.Range(this)},nodeIndex:function(m,n){var i=0,k,l,j;if(m){for(k=m.nodeType,m=m.previousSibling,l=m;m;m=m.previousSibling){j=m.nodeType;if(n&&j==3){if(j==k||!m.nodeValue.length){continue}}i++;k=j}}return i},split:function(m,l,p){var q=this,i=q.createRng(),n,k,o;function j(v){var t,s=v.childNodes,u=v.nodeType;function x(A){var z=A.previousSibling&&A.previousSibling.nodeName=="SPAN";var y=A.nextSibling&&A.nextSibling.nodeName=="SPAN";return z&&y}if(u==1&&v.getAttribute("data-mce-type")=="bookmark"){return}for(t=s.length-1;t>=0;t--){j(s[t])}if(u!=9){if(u==3&&v.nodeValue.length>0){var r=e.trim(v.nodeValue).length;if(!q.isBlock(v.parentNode)||r>0||r===0&&x(v)){return}}else{if(u==1){s=v.childNodes;if(s.length==1&&s[0]&&s[0].nodeType==1&&s[0].getAttribute("data-mce-type")=="bookmark"){v.parentNode.insertBefore(s[0],v)}if(s.length||/^(br|hr|input|img)$/i.test(v.nodeName)){return}}}q.remove(v)}return v}if(m&&l){i.setStart(m.parentNode,q.nodeIndex(m));i.setEnd(l.parentNode,q.nodeIndex(l));n=i.extractContents();i=q.createRng();i.setStart(l.parentNode,q.nodeIndex(l)+1);i.setEnd(m.parentNode,q.nodeIndex(m)+1);k=i.extractContents();o=m.parentNode;o.insertBefore(j(n),m);if(p){o.replaceChild(p,l)}else{o.insertBefore(l,m)}o.insertBefore(j(k),m);q.remove(m);return p||l}},bind:function(l,i,k,j){return this.events.add(l,i,k,j||this)},unbind:function(k,i,j){return this.events.remove(k,i,j)},fire:function(k,j,i){return this.events.fire(k,j,i)},getContentEditable:function(j){var i;if(j.nodeType!=1){return null}i=j.getAttribute("data-mce-contenteditable");if(i&&i!=="inherit"){return i}return j.contentEditable!=="inherit"?j.contentEditable:null},_findSib:function(l,i,j){var k=this,m=i;if(l){if(d(m,"string")){m=function(n){return k.is(n,i)}}for(l=l[j];l;l=l[j]){if(m(l)){return l}}}return null},_isRes:function(i){return/^(top|left|bottom|right|width|height)/i.test(i)||/;\s*(top|left|bottom|right|width|height)/i.test(i)}});e.DOM=new e.dom.DOMUtils(document,{process_html:0})})(tinymce);(function(a){function b(c){var O=this,e=c.doc,U=0,F=1,j=2,E=true,S=false,W="startOffset",h="startContainer",Q="endContainer",A="endOffset",k=tinymce.extend,n=c.nodeIndex;k(O,{startContainer:e,startOffset:0,endContainer:e,endOffset:0,collapsed:E,commonAncestorContainer:e,START_TO_START:0,START_TO_END:1,END_TO_END:2,END_TO_START:3,setStart:q,setEnd:s,setStartBefore:g,setStartAfter:J,setEndBefore:K,setEndAfter:u,collapse:B,selectNode:y,selectNodeContents:G,compareBoundaryPoints:v,deleteContents:p,extractContents:I,cloneContents:d,insertNode:D,surroundContents:N,cloneRange:L,toStringIE:T});function x(){return e.createDocumentFragment()}function q(X,t){C(E,X,t)}function s(X,t){C(S,X,t)}function g(t){q(t.parentNode,n(t))}function J(t){q(t.parentNode,n(t)+1)}function K(t){s(t.parentNode,n(t))}function u(t){s(t.parentNode,n(t)+1)}function B(t){if(t){O[Q]=O[h];O[A]=O[W]}else{O[h]=O[Q];O[W]=O[A]}O.collapsed=E}function y(t){g(t);u(t)}function G(t){q(t,0);s(t,t.nodeType===1?t.childNodes.length:t.nodeValue.length)}function v(aa,t){var ad=O[h],Y=O[W],ac=O[Q],X=O[A],ab=t.startContainer,af=t.startOffset,Z=t.endContainer,ae=t.endOffset;if(aa===0){return H(ad,Y,ab,af)}if(aa===1){return H(ac,X,ab,af)}if(aa===2){return H(ac,X,Z,ae)}if(aa===3){return H(ad,Y,Z,ae)}}function p(){l(j)}function I(){return l(U)}function d(){return l(F)}function D(aa){var X=this[h],t=this[W],Z,Y;if((X.nodeType===3||X.nodeType===4)&&X.nodeValue){if(!t){X.parentNode.insertBefore(aa,X)}else{if(t>=X.nodeValue.length){c.insertAfter(aa,X)}else{Z=X.splitText(t);X.parentNode.insertBefore(aa,Z)}}}else{if(X.childNodes.length>0){Y=X.childNodes[t]}if(Y){X.insertBefore(aa,Y)}else{X.appendChild(aa)}}}function N(X){var t=O.extractContents();O.insertNode(X);X.appendChild(t);O.selectNode(X)}function L(){return k(new b(c),{startContainer:O[h],startOffset:O[W],endContainer:O[Q],endOffset:O[A],collapsed:O.collapsed,commonAncestorContainer:O.commonAncestorContainer})}function P(t,X){var Y;if(t.nodeType==3){return t}if(X<0){return t}Y=t.firstChild;while(Y&&X>0){--X;Y=Y.nextSibling}if(Y){return Y}return t}function m(){return(O[h]==O[Q]&&O[W]==O[A])}function H(Z,ab,X,aa){var ac,Y,t,ad,af,ae;if(Z==X){if(ab==aa){return 0}if(ab0){O.collapse(X)}}else{O.collapse(X)}O.collapsed=m();O.commonAncestorContainer=c.findCommonAncestor(O[h],O[Q])}function l(ad){var ac,Z=0,af=0,X,ab,Y,aa,t,ae;if(O[h]==O[Q]){return f(ad)}for(ac=O[Q],X=ac.parentNode;X;ac=X,X=X.parentNode){if(X==O[h]){return r(ac,ad)}++Z}for(ac=O[h],X=ac.parentNode;X;ac=X,X=X.parentNode){if(X==O[Q]){return V(ac,ad)}++af}ab=af-Z;Y=O[h];while(ab>0){Y=Y.parentNode;ab--}aa=O[Q];while(ab<0){aa=aa.parentNode;ab++}for(t=Y.parentNode,ae=aa.parentNode;t!=ae;t=t.parentNode,ae=ae.parentNode){Y=t;aa=ae}return o(Y,aa,ad)}function f(ac){var ae,af,t,Y,Z,ad,aa,X,ab;if(ac!=j){ae=x()}if(O[W]==O[A]){return ae}if(O[h].nodeType==3){af=O[h].nodeValue;t=af.substring(O[W],O[A]);if(ac!=F){Y=O[h];X=O[W];ab=O[A]-O[W];if(X===0&&ab>=Y.nodeValue.length-1){Y.parentNode.removeChild(Y)}else{Y.deleteData(X,ab)}O.collapse(E)}if(ac==j){return}if(t.length>0){ae.appendChild(e.createTextNode(t))}return ae}Y=P(O[h],O[W]);Z=O[A]-O[W];while(Y&&Z>0){ad=Y.nextSibling;aa=z(Y,ac);if(ae){ae.appendChild(aa)}--Z;Y=ad}if(ac!=F){O.collapse(E)}return ae}function r(ad,aa){var ac,ab,X,t,Z,Y;if(aa!=j){ac=x()}ab=i(ad,aa);if(ac){ac.appendChild(ab)}X=n(ad);t=X-O[W];if(t<=0){if(aa!=F){O.setEndBefore(ad);O.collapse(S)}return ac}ab=ad.previousSibling;while(t>0){Z=ab.previousSibling;Y=z(ab,aa);if(ac){ac.insertBefore(Y,ac.firstChild)}--t;ab=Z}if(aa!=F){O.setEndBefore(ad);O.collapse(S)}return ac}function V(ab,aa){var ad,X,ac,t,Z,Y;if(aa!=j){ad=x()}ac=R(ab,aa);if(ad){ad.appendChild(ac)}X=n(ab);++X;t=O[A]-X;ac=ab.nextSibling;while(ac&&t>0){Z=ac.nextSibling;Y=z(ac,aa);if(ad){ad.appendChild(Y)}--t;ac=Z}if(aa!=F){O.setStartAfter(ab);O.collapse(E)}return ad}function o(ab,t,ae){var Y,ag,aa,ac,ad,X,af,Z;if(ae!=j){ag=x()}Y=R(ab,ae);if(ag){ag.appendChild(Y)}aa=ab.parentNode;ac=n(ab);ad=n(t);++ac;X=ad-ac;af=ab.nextSibling;while(X>0){Z=af.nextSibling;Y=z(af,ae);if(ag){ag.appendChild(Y)}af=Z;--X}Y=i(t,ae);if(ag){ag.appendChild(Y)}if(ae!=F){O.setStartAfter(ab);O.collapse(E)}return ag}function i(ac,ad){var Y=P(O[Q],O[A]-1),ae,ab,aa,t,X,Z=Y!=O[Q];if(Y==ac){return M(Y,Z,S,ad)}ae=Y.parentNode;ab=M(ae,S,S,ad);while(ae){while(Y){aa=Y.previousSibling;t=M(Y,Z,S,ad);if(ad!=j){ab.insertBefore(t,ab.firstChild)}Z=E;Y=aa}if(ae==ac){return ab}Y=ae.previousSibling;ae=ae.parentNode;X=M(ae,S,S,ad);if(ad!=j){X.appendChild(ab)}ab=X}}function R(ac,ad){var Z=P(O[h],O[W]),aa=Z!=O[h],ae,ab,Y,t,X;if(Z==ac){return M(Z,aa,E,ad)}ae=Z.parentNode;ab=M(ae,S,E,ad);while(ae){while(Z){Y=Z.nextSibling;t=M(Z,aa,E,ad);if(ad!=j){ab.appendChild(t)}aa=E;Z=Y}if(ae==ac){return ab}Z=ae.nextSibling;ae=ae.parentNode;X=M(ae,S,E,ad);if(ad!=j){X.appendChild(ab)}ab=X}}function M(t,aa,ad,ae){var Z,Y,ab,X,ac;if(aa){return z(t,ae)}if(t.nodeType==3){Z=t.nodeValue;if(ad){X=O[W];Y=Z.substring(X);ab=Z.substring(0,X)}else{X=O[A];Y=Z.substring(0,X);ab=Z.substring(X)}if(ae!=F){t.nodeValue=ab}if(ae==j){return}ac=c.clone(t,S);ac.nodeValue=Y;return ac}if(ae==j){return}return c.clone(t,S)}function z(X,t){if(t!=j){return t==F?c.clone(X,E):X}X.parentNode.removeChild(X)}function T(){return c.create("body",null,d()).outerText}return O}a.Range=b;b.prototype.toString=function(){return this.toStringIE()}})(tinymce.dom);(function(){function a(d){var b=this,h=d.dom,c=true,f=false;function e(i,j){var k,t=0,q,n,m,l,o,r,p=-1,s;k=i.duplicate();k.collapse(j);s=k.parentElement();if(s.ownerDocument!==d.dom.doc){return}while(s.contentEditable==="false"){s=s.parentNode}if(!s.hasChildNodes()){return{node:s,inside:1}}m=s.children;q=m.length-1;while(t<=q){r=Math.floor((t+q)/2);l=m[r];k.moveToElementText(l);p=k.compareEndPoints(j?"StartToStart":"EndToEnd",i);if(p>0){q=r-1}else{if(p<0){t=r+1}else{return{node:l}}}}if(p<0){if(!l){k.moveToElementText(s);k.collapse(true);l=s;n=true}else{k.collapse(false)}o=0;while(k.compareEndPoints(j?"StartToStart":"StartToEnd",i)!==0){if(k.move("character",1)===0||s!=k.parentElement()){break}o++}}else{k.collapse(true);o=0;while(k.compareEndPoints(j?"StartToStart":"StartToEnd",i)!==0){if(k.move("character",-1)===0||s!=k.parentElement()){break}o++}}return{node:l,position:p,offset:o,inside:n}}function g(){var i=d.getRng(),r=h.createRng(),l,k,p,q,m,j;l=i.item?i.item(0):i.parentElement();if(l.ownerDocument!=h.doc){return r}k=d.isCollapsed();if(i.item){r.setStart(l.parentNode,h.nodeIndex(l));r.setEnd(r.startContainer,r.startOffset+1);return r}function o(A){var u=e(i,A),s,y,z=0,x,v,t;s=u.node;y=u.offset;if(u.inside&&!s.hasChildNodes()){r[A?"setStart":"setEnd"](s,0);return}if(y===v){r[A?"setStartBefore":"setEndAfter"](s);return}if(u.position<0){x=u.inside?s.firstChild:s.nextSibling;if(!x){r[A?"setStartAfter":"setEndAfter"](s);return}if(!y){if(x.nodeType==3){r[A?"setStart":"setEnd"](x,0)}else{r[A?"setStartBefore":"setEndBefore"](x)}return}while(x){t=x.nodeValue;z+=t.length;if(z>=y){s=x;z-=y;z=t.length-z;break}x=x.nextSibling}}else{x=s.previousSibling;if(!x){return r[A?"setStartBefore":"setEndBefore"](s)}if(!y){if(s.nodeType==3){r[A?"setStart":"setEnd"](x,s.nodeValue.length)}else{r[A?"setStartAfter":"setEndAfter"](x)}return}while(x){z+=x.nodeValue.length;if(z>=y){s=x;z-=y;break}x=x.previousSibling}}r[A?"setStart":"setEnd"](s,z)}try{o(true);if(!k){o()}}catch(n){if(n.number==-2147024809){m=b.getBookmark(2);p=i.duplicate();p.collapse(true);l=p.parentElement();if(!k){p=i.duplicate();p.collapse(false);q=p.parentElement();q.innerHTML=q.innerHTML}l.innerHTML=l.innerHTML;b.moveToBookmark(m);i=d.getRng();o(true);if(!k){o()}}else{throw n}}return r}this.getBookmark=function(m){var j=d.getRng(),o,i,l={};function n(u){var t,p,s,r,q=[];t=u.parentNode;p=h.getRoot().parentNode;while(t!=p&&t.nodeType!==9){s=t.children;r=s.length;while(r--){if(u===s[r]){q.push(r);break}}u=t;t=t.parentNode}return q}function k(q){var p;p=e(j,q);if(p){return{position:p.position,offset:p.offset,indexes:n(p.node),inside:p.inside}}}if(m===2){if(!j.item){l.start=k(true);if(!d.isCollapsed()){l.end=k()}}else{l.start={ctrl:true,indexes:n(j.item(0))}}}return l};this.moveToBookmark=function(k){var j,i=h.doc.body;function m(o){var r,q,n,p;r=h.getRoot();for(q=o.length-1;q>=0;q--){p=r.children;n=o[q];if(n<=p.length-1){r=p[n]}}return r}function l(r){var n=k[r?"start":"end"],q,p,o;if(n){q=n.position>0;p=i.createTextRange();p.moveToElementText(m(n.indexes));offset=n.offset;if(offset!==o){p.collapse(n.inside||q);p.moveStart("character",q?-offset:offset)}else{p.collapse(r)}j.setEndPoint(r?"StartToStart":"EndToStart",p);if(r){j.collapse(true)}}}if(k.start){if(k.start.ctrl){j=i.createControlRange();j.addElement(m(k.start.indexes));j.select()}else{j=i.createTextRange();l(true);l();j.select()}}};this.addRange=function(i){var n,l,k,p,v,q,t,s=d.dom.doc,m=s.body,r,u;function j(C){var y,B,x,A,z;x=h.create("a");y=C?k:v;B=C?p:q;A=n.duplicate();if(y==s||y==s.documentElement){y=m;B=0}if(y.nodeType==3){y.parentNode.insertBefore(x,y);A.moveToElementText(x);A.moveStart("character",B);h.remove(x);n.setEndPoint(C?"StartToStart":"EndToEnd",A)}else{z=y.childNodes;if(z.length){if(B>=z.length){h.insertAfter(x,z[z.length-1])}else{y.insertBefore(x,z[B])}A.moveToElementText(x)}else{if(y.canHaveHTML){y.innerHTML="\uFEFF";x=y.firstChild;A.moveToElementText(x);A.collapse(f)}}n.setEndPoint(C?"StartToStart":"EndToEnd",A);h.remove(x)}}k=i.startContainer;p=i.startOffset;v=i.endContainer;q=i.endOffset;n=m.createTextRange();if(k==v&&k.nodeType==1){if(p==q&&!k.hasChildNodes()){if(k.canHaveHTML){t=k.previousSibling;if(t&&!t.hasChildNodes()&&h.isBlock(t)){t.innerHTML="\uFEFF"}else{t=null}k.innerHTML="\uFEFF\uFEFF";n.moveToElementText(k.lastChild);n.select();h.doc.selection.clear();k.innerHTML="";if(t){t.innerHTML=""}return}else{p=h.nodeIndex(k);k=k.parentNode}}if(p==q-1){try{u=k.childNodes[p];l=m.createControlRange();l.addElement(u);l.select();r=d.getRng();if(r.item&&u===r.item(0)){return}}catch(o){}}}j(true);j();n.select()};this.getRangeAt=g}tinymce.dom.TridentSelection=a})();(function(){var n=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,i="sizcache",o=0,r=Object.prototype.toString,h=false,g=true,q=/\\/g,u=/\r\n/g,x=/\W/;[0,0].sort(function(){g=false;return 0});var d=function(C,e,F,G){F=F||[];e=e||document;var I=e;if(e.nodeType!==1&&e.nodeType!==9){return[]}if(!C||typeof C!=="string"){return F}var z,K,N,y,J,M,L,E,B=true,A=d.isXML(e),D=[],H=C;do{n.exec("");z=n.exec(H);if(z){H=z[3];D.push(z[1]);if(z[2]){y=z[3];break}}}while(z);if(D.length>1&&j.exec(C)){if(D.length===2&&k.relative[D[0]]){K=s(D[0]+D[1],e,G)}else{K=k.relative[D[0]]?[e]:d(D.shift(),e);while(D.length){C=D.shift();if(k.relative[C]){C+=D.shift()}K=s(C,K,G)}}}else{if(!G&&D.length>1&&e.nodeType===9&&!A&&k.match.ID.test(D[0])&&!k.match.ID.test(D[D.length-1])){J=d.find(D.shift(),e,A);e=J.expr?d.filter(J.expr,J.set)[0]:J.set[0]}if(e){J=G?{expr:D.pop(),set:l(G)}:d.find(D.pop(),D.length===1&&(D[0]==="~"||D[0]==="+")&&e.parentNode?e.parentNode:e,A);K=J.expr?d.filter(J.expr,J.set):J.set;if(D.length>0){N=l(K)}else{B=false}while(D.length){M=D.pop();L=M;if(!k.relative[M]){M=""}else{L=D.pop()}if(L==null){L=e}k.relative[M](N,L,A)}}else{N=D=[]}}if(!N){N=K}if(!N){d.error(M||C)}if(r.call(N)==="[object Array]"){if(!B){F.push.apply(F,N)}else{if(e&&e.nodeType===1){for(E=0;N[E]!=null;E++){if(N[E]&&(N[E]===true||N[E].nodeType===1&&d.contains(e,N[E]))){F.push(K[E])}}}else{for(E=0;N[E]!=null;E++){if(N[E]&&N[E].nodeType===1){F.push(K[E])}}}}}else{l(N,F)}if(y){d(y,I,F,G);d.uniqueSort(F)}return F};d.uniqueSort=function(y){if(p){h=g;y.sort(p);if(h){for(var e=1;e0};d.find=function(E,e,F){var D,z,B,A,C,y;if(!E){return[]}for(z=0,B=k.order.length;z":function(D,y){var C,B=typeof y==="string",z=0,e=D.length;if(B&&!x.test(y)){y=y.toLowerCase();for(;z=0)){if(!z){e.push(C)}}else{if(z){y[B]=false}}}}return false},ID:function(e){return e[1].replace(q,"")},TAG:function(y,e){return y[1].replace(q,"").toLowerCase()},CHILD:function(e){if(e[1]==="nth"){if(!e[2]){d.error(e[0])}e[2]=e[2].replace(/^\+|\s*/g,"");var y=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(e[2]==="even"&&"2n"||e[2]==="odd"&&"2n+1"||!/\D/.test(e[2])&&"0n+"+e[2]||e[2]);e[2]=(y[1]+(y[2]||1))-0;e[3]=y[3]-0}else{if(e[2]){d.error(e[0])}}e[0]=o++;return e},ATTR:function(B,y,z,e,C,D){var A=B[1]=B[1].replace(q,"");if(!D&&k.attrMap[A]){B[1]=k.attrMap[A]}B[4]=(B[4]||B[5]||"").replace(q,"");if(B[2]==="~="){B[4]=" "+B[4]+" "}return B},PSEUDO:function(B,y,z,e,C){if(B[1]==="not"){if((n.exec(B[3])||"").length>1||/^\w/.test(B[3])){B[3]=d(B[3],null,null,y)}else{var A=d.filter(B[3],y,z,true^C);if(!z){e.push.apply(e,A)}return false}}else{if(k.match.POS.test(B[0])||k.match.CHILD.test(B[0])){return true}}return B},POS:function(e){e.unshift(true);return e}},filters:{enabled:function(e){return e.disabled===false&&e.type!=="hidden"},disabled:function(e){return e.disabled===true},checked:function(e){return e.checked===true},selected:function(e){if(e.parentNode){e.parentNode.selectedIndex}return e.selected===true},parent:function(e){return !!e.firstChild},empty:function(e){return !e.firstChild},has:function(z,y,e){return !!d(e[3],z).length},header:function(e){return(/h\d/i).test(e.nodeName)},text:function(z){var e=z.getAttribute("type"),y=z.type;return z.nodeName.toLowerCase()==="input"&&"text"===y&&(e===y||e===null)},radio:function(e){return e.nodeName.toLowerCase()==="input"&&"radio"===e.type},checkbox:function(e){return e.nodeName.toLowerCase()==="input"&&"checkbox"===e.type},file:function(e){return e.nodeName.toLowerCase()==="input"&&"file"===e.type},password:function(e){return e.nodeName.toLowerCase()==="input"&&"password"===e.type},submit:function(y){var e=y.nodeName.toLowerCase();return(e==="input"||e==="button")&&"submit"===y.type},image:function(e){return e.nodeName.toLowerCase()==="input"&&"image"===e.type},reset:function(y){var e=y.nodeName.toLowerCase();return(e==="input"||e==="button")&&"reset"===y.type},button:function(y){var e=y.nodeName.toLowerCase();return e==="input"&&"button"===y.type||e==="button"},input:function(e){return(/input|select|textarea|button/i).test(e.nodeName)},focus:function(e){return e===e.ownerDocument.activeElement}},setFilters:{first:function(y,e){return e===0},last:function(z,y,e,A){return y===A.length-1},even:function(y,e){return e%2===0},odd:function(y,e){return e%2===1},lt:function(z,y,e){return ye[3]-0},nth:function(z,y,e){return e[3]-0===y},eq:function(z,y,e){return e[3]-0===y}},filter:{PSEUDO:function(z,E,D,F){var e=E[1],y=k.filters[e];if(y){return y(z,D,E,F)}else{if(e==="contains"){return(z.textContent||z.innerText||b([z])||"").indexOf(E[3])>=0}else{if(e==="not"){var A=E[3];for(var C=0,B=A.length;C=0)}}},ID:function(y,e){return y.nodeType===1&&y.getAttribute("id")===e},TAG:function(y,e){return(e==="*"&&y.nodeType===1)||!!y.nodeName&&y.nodeName.toLowerCase()===e},CLASS:function(y,e){return(" "+(y.className||y.getAttribute("class"))+" ").indexOf(e)>-1},ATTR:function(C,A){var z=A[1],e=d.attr?d.attr(C,z):k.attrHandle[z]?k.attrHandle[z](C):C[z]!=null?C[z]:C.getAttribute(z),D=e+"",B=A[2],y=A[4];return e==null?B==="!=":!B&&d.attr?e!=null:B==="="?D===y:B==="*="?D.indexOf(y)>=0:B==="~="?(" "+D+" ").indexOf(y)>=0:!y?D&&e!==false:B==="!="?D!==y:B==="^="?D.indexOf(y)===0:B==="$="?D.substr(D.length-y.length)===y:B==="|="?D===y||D.substr(0,y.length+1)===y+"-":false},POS:function(B,y,z,C){var e=y[2],A=k.setFilters[e];if(A){return A(B,z,y,C)}}}};var j=k.match.POS,c=function(y,e){return"\\"+(e-0+1)};for(var f in k.match){k.match[f]=new RegExp(k.match[f].source+(/(?![^\[]*\])(?![^\(]*\))/.source));k.leftMatch[f]=new RegExp(/(^(?:.|\r|\n)*?)/.source+k.match[f].source.replace(/\\(\d+)/g,c))}k.match.globalPOS=j;var l=function(y,e){y=Array.prototype.slice.call(y,0);if(e){e.push.apply(e,y);return e}return y};try{Array.prototype.slice.call(document.documentElement.childNodes,0)[0].nodeType}catch(v){l=function(B,A){var z=0,y=A||[];if(r.call(B)==="[object Array]"){Array.prototype.push.apply(y,B)}else{if(typeof B.length==="number"){for(var e=B.length;z";e.insertBefore(y,e.firstChild);if(document.getElementById(z)){k.find.ID=function(B,C,D){if(typeof C.getElementById!=="undefined"&&!D){var A=C.getElementById(B[1]);return A?A.id===B[1]||typeof A.getAttributeNode!=="undefined"&&A.getAttributeNode("id").nodeValue===B[1]?[A]:undefined:[]}};k.filter.ID=function(C,A){var B=typeof C.getAttributeNode!=="undefined"&&C.getAttributeNode("id");return C.nodeType===1&&B&&B.nodeValue===A}}e.removeChild(y);e=y=null})();(function(){var e=document.createElement("div");e.appendChild(document.createComment(""));if(e.getElementsByTagName("*").length>0){k.find.TAG=function(y,C){var B=C.getElementsByTagName(y[1]);if(y[1]==="*"){var A=[];for(var z=0;B[z];z++){if(B[z].nodeType===1){A.push(B[z])}}B=A}return B}}e.innerHTML="";if(e.firstChild&&typeof e.firstChild.getAttribute!=="undefined"&&e.firstChild.getAttribute("href")!=="#"){k.attrHandle.href=function(y){return y.getAttribute("href",2)}}e=null})();if(document.querySelectorAll){(function(){var e=d,A=document.createElement("div"),z="__sizzle__";A.innerHTML="

";if(A.querySelectorAll&&A.querySelectorAll(".TEST").length===0){return}d=function(L,C,G,K){C=C||document;if(!K&&!d.isXML(C)){var J=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(L);if(J&&(C.nodeType===1||C.nodeType===9)){if(J[1]){return l(C.getElementsByTagName(L),G)}else{if(J[2]&&k.find.CLASS&&C.getElementsByClassName){return l(C.getElementsByClassName(J[2]),G)}}}if(C.nodeType===9){if(L==="body"&&C.body){return l([C.body],G)}else{if(J&&J[3]){var F=C.getElementById(J[3]);if(F&&F.parentNode){if(F.id===J[3]){return l([F],G)}}else{return l([],G)}}}try{return l(C.querySelectorAll(L),G)}catch(H){}}else{if(C.nodeType===1&&C.nodeName.toLowerCase()!=="object"){var D=C,E=C.getAttribute("id"),B=E||z,N=C.parentNode,M=/^\s*[+~]/.test(L);if(!E){C.setAttribute("id",B)}else{B=B.replace(/'/g,"\\$&")}if(M&&N){C=C.parentNode}try{if(!M||N){return l(C.querySelectorAll("[id='"+B+"'] "+L),G)}}catch(I){}finally{if(!E){D.removeAttribute("id")}}}}}return e(L,C,G,K)};for(var y in e){d[y]=e[y]}A=null})()}(function(){var e=document.documentElement,z=e.matchesSelector||e.mozMatchesSelector||e.webkitMatchesSelector||e.msMatchesSelector;if(z){var B=!z.call(document.createElement("div"),"div"),y=false;try{z.call(document.documentElement,"[test!='']:sizzle")}catch(A){y=true}d.matchesSelector=function(D,F){F=F.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!d.isXML(D)){try{if(y||!k.match.PSEUDO.test(F)&&!/!=/.test(F)){var C=z.call(D,F);if(C||!B||D.document&&D.document.nodeType!==11){return C}}}catch(E){}}return d(F,null,null,[D]).length>0}}})();(function(){var e=document.createElement("div");e.innerHTML="
";if(!e.getElementsByClassName||e.getElementsByClassName("e").length===0){return}e.lastChild.className="e";if(e.getElementsByClassName("e").length===1){return}k.order.splice(1,0,"CLASS");k.find.CLASS=function(y,z,A){if(typeof z.getElementsByClassName!=="undefined"&&!A){return z.getElementsByClassName(y[1])}};e=null})();function a(y,D,C,G,E,F){for(var A=0,z=G.length;A0){B=e;break}}}e=e[y]}G[A]=B}}}if(document.documentElement.contains){d.contains=function(y,e){return y!==e&&(y.contains?y.contains(e):true)}}else{if(document.documentElement.compareDocumentPosition){d.contains=function(y,e){return !!(y.compareDocumentPosition(e)&16)}}else{d.contains=function(){return false}}}d.isXML=function(e){var y=(e?e.ownerDocument||e:0).documentElement;return y?y.nodeName!=="HTML":false};var s=function(z,e,D){var C,E=[],B="",F=e.nodeType?[e]:e;while((C=k.match.PSEUDO.exec(z))){B+=C[0];z=z.replace(k.match.PSEUDO,"")}z=k.relative[z]?z+"*":z;for(var A=0,y=F.length;A"+(i.item?i.item(0).outerHTML:i.htmlText);m.removeChild(m.firstChild)}else{m.innerHTML=i.toString()}}if(/^\s/.test(m.innerHTML)){j=" "}if(/\s+$/.test(m.innerHTML)){l=" "}h.getInner=true;h.content=g.isCollapsed()?"":j+g.serializer.serialize(m,h)+l;g.onGetContent.dispatch(g,h);return h.content},setContent:function(h,j){var o=this,g=o.getRng(),k,l=o.win.document,n,m;j=j||{format:"html"};j.set=true;h=j.content=h;if(!j.no_events){o.onBeforeSetContent.dispatch(o,j)}h=j.content;if(g.insertNode){h+='_';if(g.startContainer==l&&g.endContainer==l){l.body.innerHTML=h}else{g.deleteContents();if(l.body.childNodes.length===0){l.body.innerHTML=h}else{if(g.createContextualFragment){g.insertNode(g.createContextualFragment(h))}else{n=l.createDocumentFragment();m=l.createElement("div");n.appendChild(m);m.outerHTML=h;g.insertNode(n)}}}k=o.dom.get("__caret");g=l.createRange();g.setStartBefore(k);g.setEndBefore(k);o.setRng(g);o.dom.remove("__caret");try{o.setRng(g)}catch(i){}}else{if(g.item){l.execCommand("Delete",false,null);g=o.getRng()}if(/^\s+/.test(h)){g.pasteHTML('_'+h);o.dom.remove("__mce_tmp")}else{g.pasteHTML(h)}}if(!j.no_events){o.onSetContent.dispatch(o,j)}},getStart:function(){var i=this,h=i.getRng(),j,g,l,k;if(h.duplicate||h.item){if(h.item){return h.item(0)}l=h.duplicate();l.collapse(1);j=l.parentElement();if(j.ownerDocument!==i.dom.doc){j=i.dom.getRoot()}g=k=h.parentElement();while(k=k.parentNode){if(k==j){j=g;break}}return j}else{j=h.startContainer;if(j.nodeType==1&&j.hasChildNodes()){j=j.childNodes[Math.min(j.childNodes.length-1,h.startOffset)]}if(j&&j.nodeType==3){return j.parentNode}return j}},getEnd:function(){var h=this,g=h.getRng(),j,i;if(g.duplicate||g.item){if(g.item){return g.item(0)}g=g.duplicate();g.collapse(0);j=g.parentElement();if(j.ownerDocument!==h.dom.doc){j=h.dom.getRoot()}if(j&&j.nodeName=="BODY"){return j.lastChild||j}return j}else{j=g.endContainer;i=g.endOffset;if(j.nodeType==1&&j.hasChildNodes()){j=j.childNodes[i>0?i-1:i]}if(j&&j.nodeType==3){return j.parentNode}return j}},getBookmark:function(s,v){var y=this,n=y.dom,h,k,j,o,i,p,q,m="\uFEFF",x;function g(z,A){var t=0;e(n.select(z),function(C,B){if(C==A){t=B}});return t}function u(t){function z(E){var A,D,C,B=E?"start":"end";A=t[B+"Container"];D=t[B+"Offset"];if(A.nodeType==1&&A.nodeName=="TR"){C=A.childNodes;A=C[Math.min(E?D:D-1,C.length-1)];if(A){D=E?0:A.childNodes.length;t["set"+(E?"Start":"End")](A,D)}}}z(true);z();return t}function l(){var z=y.getRng(true),t=n.getRoot(),A={};function B(E,J){var D=E[J?"startContainer":"endContainer"],I=E[J?"startOffset":"endOffset"],C=[],F,H,G=0;if(D.nodeType==3){if(v){for(F=D.previousSibling;F&&F.nodeType==3;F=F.previousSibling){I+=F.nodeValue.length}}C.push(I)}else{H=D.childNodes;if(I>=H.length&&H.length){G=1;I=Math.max(0,H.length-1)}C.push(y.dom.nodeIndex(H[I],v)+G)}for(;D&&D!=t;D=D.parentNode){C.push(y.dom.nodeIndex(D,v))}return C}A.start=B(z,true);if(!y.isCollapsed()){A.end=B(z)}return A}if(s==2){if(y.tridentSel){return y.tridentSel.getBookmark(s)}return l()}if(s){h=y.getRng();if(h.setStart){h={startContainer:h.startContainer,startOffset:h.startOffset,endContainer:h.endContainer,endOffset:h.endOffset}}return{rng:h}}h=y.getRng();j=n.uniqueId();o=tinyMCE.activeEditor.selection.isCollapsed();x="overflow:hidden;line-height:0px";if(h.duplicate||h.item){if(!h.item){k=h.duplicate();try{h.collapse();h.pasteHTML(''+m+"");if(!o){k.collapse(false);h.moveToElementText(k.parentElement());if(h.compareEndPoints("StartToEnd",k)===0){k.move("character",-1)}k.pasteHTML(''+m+"")}}catch(r){return null}}else{p=h.item(0);i=p.nodeName;return{name:i,index:g(i,p)}}}else{p=y.getNode();i=p.nodeName;if(i=="IMG"){return{name:i,index:g(i,p)}}k=u(h.cloneRange());if(!o){k.collapse(false);k.insertNode(n.create("span",{"data-mce-type":"bookmark",id:j+"_end",style:x},m))}h=u(h);h.collapse(true);h.insertNode(n.create("span",{"data-mce-type":"bookmark",id:j+"_start",style:x},m))}y.moveToBookmark({id:j,keep:1});return{id:j}},moveToBookmark:function(q){var v=this,n=v.dom,l,j,g,i,u,k,x,r,s;function h(C){var t=q[C?"start":"end"],z,A,B,y;if(t){B=t[0];for(A=u,z=t.length-1;z>=1;z--){y=A.childNodes;if(t[z]>y.length-1){return}A=y[t[z]]}if(A.nodeType===3){B=Math.min(t[0],A.nodeValue.length)}if(A.nodeType===1){B=Math.min(t[0],A.childNodes.length)}if(C){g.setStart(A,B)}else{g.setEnd(A,B)}}return true}function m(D){var y=n.get(q.id+"_"+D),C,t,A,B,z=q.keep;if(y){C=y.parentNode;if(D=="start"){if(!z){t=n.nodeIndex(y)}else{C=y.firstChild;t=1}k=x=C;r=s=t}else{if(!z){t=n.nodeIndex(y)}else{C=y.firstChild;t=1}x=C;s=t}if(!z){B=y.previousSibling;A=y.nextSibling;e(d.grep(y.childNodes),function(E){if(E.nodeType==3){E.nodeValue=E.nodeValue.replace(/\uFEFF/g,"")}});while(y=n.get(q.id+"_"+D)){n.remove(y,1)}if(B&&A&&B.nodeType==A.nodeType&&B.nodeType==3&&!d.isOpera){t=B.nodeValue.length;B.appendData(A.nodeValue);n.remove(A);if(D=="start"){k=x=B;r=s=t}else{x=B;s=t}}}}}function o(t){if(n.isBlock(t)&&!t.innerHTML&&!b){t.innerHTML='
'}return t}if(q){if(q.start){g=n.createRng();u=n.getRoot();if(v.tridentSel){return v.tridentSel.moveToBookmark(q)}if(h(true)&&h()){v.setRng(g)}}else{if(q.id){m("start");m("end");if(k){g=n.createRng();g.setStart(o(k),r);g.setEnd(o(x),s);v.setRng(g)}}else{if(q.name){v.select(n.select(q.name)[q.index])}else{if(q.rng){g=q.rng;if(g.startContainer){i=v.dom.createRng();try{i.setStart(g.startContainer,g.startOffset);i.setEnd(g.endContainer,g.endOffset)}catch(p){}g=i}v.setRng(g)}}}}}},select:function(l,k){var j=this,m=j.dom,h=m.createRng(),g;function i(n,p){var o=new a(n,n);do{if(n.nodeType==3&&d.trim(n.nodeValue).length!==0){if(p){h.setStart(n,0)}else{h.setEnd(n,n.nodeValue.length)}return}if(n.nodeName=="BR"){if(p){h.setStartBefore(n)}else{h.setEndBefore(n)}return}}while(n=(p?o.next():o.prev()))}if(l){g=m.nodeIndex(l);h.setStart(l.parentNode,g);h.setEnd(l.parentNode,g+1);if(k){i(l,1);i(l)}j.setRng(h)}return l},isCollapsed:function(){var g=this,i=g.getRng(),h=g.getSel();if(!i||i.item){return false}if(i.compareEndPoints){return i.compareEndPoints("StartToEnd",i)===0}return !h||i.collapsed},collapse:function(g){var i=this,h=i.getRng(),j;if(h.item){j=h.item(0);h=i.win.document.body.createTextRange();h.moveToElementText(j)}h.collapse(!!g);i.setRng(h)},getSel:function(){var h=this,g=this.win;return g.getSelection?g.getSelection():g.document.selection},getRng:function(m){var h=this,j,g,l,k=h.win.document;if(h.fakeRng){return h.fakeRng}if(m&&h.tridentSel){return h.tridentSel.getRangeAt(0)}try{if(j=h.getSel()){g=j.rangeCount>0?j.getRangeAt(0):(j.createRange?j.createRange():k.createRange())}}catch(i){}if(d.isIE&&!d.isIE11&&g&&g.setStart&&k.selection.createRange().item){l=k.selection.createRange().item(0);g=k.createRange();g.setStartBefore(l);g.setEndAfter(l)}if(!g){g=k.createRange?k.createRange():k.body.createTextRange()}if(g.setStart&&g.startContainer.nodeType===9&&g.collapsed){l=h.dom.getRoot();g.setStart(l,0);g.setEnd(l,0)}if(h.selectedRange&&h.explicitRange){if(g.compareBoundaryPoints(g.START_TO_START,h.selectedRange)===0&&g.compareBoundaryPoints(g.END_TO_END,h.selectedRange)===0){g=h.explicitRange}else{h.selectedRange=null;h.explicitRange=null}}return g},setRng:function(k,g){var j,i=this;if(!i.tridentSel){j=i.getSel();if(j){i.explicitRange=k;try{j.removeAllRanges()}catch(h){}j.addRange(k);if(g===false&&j.extend){j.collapse(k.endContainer,k.endOffset);j.extend(k.startContainer,k.startOffset)}i.selectedRange=j.rangeCount>0?j.getRangeAt(0):null}}else{if(k.cloneRange){try{i.tridentSel.addRange(k);return}catch(h){}}try{k.select()}catch(h){}}},setNode:function(h){var g=this;g.setContent(g.dom.getOuterHTML(h));return h},getNode:function(){var i=this,h=i.getRng(),j=i.getSel(),m,l=h.startContainer,g=h.endContainer;function k(q,o){var p=q;while(q&&q.nodeType===3&&q.length===0){q=o?q.nextSibling:q.previousSibling}return q||p}if(!h){return i.dom.getRoot()}if(h.setStart){m=h.commonAncestorContainer;if(!h.collapsed){if(h.startContainer==h.endContainer){if(h.endOffset-h.startOffset<2){if(h.startContainer.hasChildNodes()){m=h.startContainer.childNodes[h.startOffset]}}}if(l.nodeType===3&&g.nodeType===3){if(l.length===h.startOffset){l=k(l.nextSibling,true)}else{l=l.parentNode}if(h.endOffset===0){g=k(g.previousSibling,false)}else{g=g.parentNode}if(l&&l===g){return l}}}if(m&&m.nodeType==3){return m.parentNode}return m}return h.item?h.item(0):h.parentElement()},getSelectedBlocks:function(p,h){var o=this,k=o.dom,m,l,i,j=[];m=k.getParent(p||o.getStart(),k.isBlock);l=k.getParent(h||o.getEnd(),k.isBlock);if(m){j.push(m)}if(m&&l&&m!=l){i=m;var g=new a(m,k.getRoot());while((i=g.next())&&i!=l){if(k.isBlock(i)){j.push(i)}}}if(l&&m!=l){j.push(l)}return j},isForward:function(){var i=this.dom,g=this.getSel(),j,h;if(!g||g.anchorNode==null||g.focusNode==null){return true}j=i.createRng();j.setStart(g.anchorNode,g.anchorOffset);j.collapse(true);h=i.createRng();h.setStart(g.focusNode,g.focusOffset);h.collapse(true);return j.compareBoundaryPoints(j.START_TO_START,h)<=0},normalize:function(){var h=this,g,m,l,j,i;function k(p){var o,r,n,s=h.dom,u=s.getRoot(),q,t,v;function y(z,A){var B=new a(z,s.getParent(z.parentNode,s.isBlock)||u);while(z=B[A?"prev":"next"]()){if(z.nodeName==="BR"){return true}}}function x(B,z){var C,A;z=z||o;C=new a(z,s.getParent(z.parentNode,s.isBlock)||u);while(q=C[B?"prev":"next"]()){if(q.nodeType===3&&q.nodeValue.length>0){o=q;r=B?q.nodeValue.length:0;m=true;return}if(s.isBlock(q)||t[q.nodeName.toLowerCase()]){return}A=q}if(l&&A){o=A;m=true;r=0}}o=g[(p?"start":"end")+"Container"];r=g[(p?"start":"end")+"Offset"];t=s.schema.getNonEmptyElements();if(o.nodeType===9){o=s.getRoot();r=0}if(o===u){if(p){q=o.childNodes[r>0?r-1:0];if(q){v=q.nodeName.toLowerCase();if(t[q.nodeName]||q.nodeName=="TABLE"){return}}}if(o.hasChildNodes()){o=o.childNodes[Math.min(!p&&r>0?r-1:r,o.childNodes.length-1)];r=0;if(o.hasChildNodes()&&!/TABLE/.test(o.nodeName)){q=o;n=new a(o,u);do{if(q.nodeType===3&&q.nodeValue.length>0){r=p?0:q.nodeValue.length;o=q;m=true;break}if(t[q.nodeName.toLowerCase()]){r=s.nodeIndex(q);o=q.parentNode;if(q.nodeName=="IMG"&&!p){r++}m=true;break}}while(q=(p?n.next():n.prev()))}}}if(l){if(o.nodeType===3&&r===0){x(true)}if(o.nodeType===1){q=o.childNodes[r];if(q&&q.nodeName==="BR"&&!y(q)&&!y(q,true)){x(true,o.childNodes[r])}}}if(p&&!l&&o.nodeType===3&&r===o.nodeValue.length){x(false)}if(m){g["set"+(p?"Start":"End")](o,r)}}if(d.isIE){return}g=h.getRng();l=g.collapsed;k(true);if(!l){k()}if(m){if(l){g.collapse(true)}h.setRng(g,h.isForward())}},selectorChanged:function(g,j){var h=this,i;if(!h.selectorChangedData){h.selectorChangedData={};i={};h.editor.onNodeChange.addToTop(function(l,k,o){var p=h.dom,m=p.getParents(o,null,p.getRoot()),n={};e(h.selectorChangedData,function(r,q){e(m,function(s){if(p.is(s,q)){if(!i[q]){e(r,function(t){t(true,{node:s,selector:q,parents:m})});i[q]=r}n[q]=r;return false}})});e(i,function(r,q){if(!n[q]){delete i[q];e(r,function(s){s(false,{node:o,selector:q,parents:m})})}})})}if(!h.selectorChangedData[g]){h.selectorChangedData[g]=[]}h.selectorChangedData[g].push(j);return h},scrollIntoView:function(k){var j,h,g=this,i=g.dom;h=i.getViewPort(g.editor.getWin());j=i.getPos(k).y;if(jh.y+h.h){g.editor.getWin().scrollTo(0,j0){p.setEndPoint("StartToStart",o)}else{p.setEndPoint("EndToEnd",o)}p.select()}}else{l()}}function l(){var p=n.selection.createRange();if(o&&!p.item&&p.compareEndPoints("StartToEnd",p)===0){o.select()}h.unbind(n,"mouseup",l);h.unbind(n,"mousemove",m);o=k=0}n.documentElement.unselectable=true;h.bind(n,["mousedown","contextmenu"],function(p){if(p.target.nodeName==="HTML"){if(k){l()}g=n.documentElement;if(g.scrollHeight>g.clientHeight){return}k=1;o=j(p.x,p.y);if(o){h.bind(n,"mouseup",l);h.bind(n,"mousemove",m);h.win.focus();o.select()}}})}})})(tinymce);(function(a){a.dom.Serializer=function(e,i,f){var h,b,d=a.isIE,g=a.each,c;if(!e.apply_source_formatting){e.indent=false}i=i||a.DOM;f=f||new a.html.Schema(e);e.entity_encoding=e.entity_encoding||"named";e.remove_trailing_brs="remove_trailing_brs" in e?e.remove_trailing_brs:true;h=new a.util.Dispatcher(self);b=new a.util.Dispatcher(self);c=new a.html.DomParser(e,f);c.addAttributeFilter("src,href,style",function(k,j){var o=k.length,l,q,n="data-mce-"+j,p=e.url_converter,r=e.url_converter_scope,m;while(o--){l=k[o];q=l.attributes.map[n];if(q!==m){l.attr(j,q.length>0?q:null);l.attr(n,null)}else{q=l.attributes.map[j];if(j==="style"){q=i.serializeStyle(i.parseStyle(q),l.name)}else{if(p){q=p.call(r,q,j,l.name)}}l.attr(j,q.length>0?q:null)}}});c.addAttributeFilter("class",function(j,k){var l=j.length,m,n;while(l--){m=j[l];n=m.attr("class").replace(/(?:^|\s)mce(Item\w+|Selected)(?!\S)/g,"");m.attr("class",n.length>0?n:null)}});c.addAttributeFilter("data-mce-type",function(j,l,k){var m=j.length,n;while(m--){n=j[m];if(n.attributes.map["data-mce-type"]==="bookmark"&&!k.cleanup){n.remove()}}});c.addAttributeFilter("data-mce-expando",function(j,l,k){var m=j.length;while(m--){j[m].attr(l,null)}});c.addNodeFilter("noscript",function(j){var k=j.length,l;while(k--){l=j[k].firstChild;if(l){l.value=a.html.Entities.decode(l.value)}}});c.addNodeFilter("script,style",function(k,l){var m=k.length,n,o;function j(p){return p.replace(/()/g,"\n").replace(/^[\r\n]*|[\r\n]*$/g,"").replace(/^\s*(()?|\s*\/\/\s*\]\]>(-->)?|\/\/\s*(-->)?|\]\]>|\/\*\s*-->\s*\*\/|\s*-->\s*)\s*$/g,"")}while(m--){n=k[m];o=n.firstChild?n.firstChild.value:"";if(l==="script"){n.attr("type",(n.attr("type")||"text/javascript").replace(/^mce\-/,""));if(o.length>0){n.firstChild.value="// "}}else{if(o.length>0){n.firstChild.value=""}}}});c.addNodeFilter("#comment",function(j,k){var l=j.length,m;while(l--){m=j[l];if(m.value.indexOf("[CDATA[")===0){m.name="#cdata";m.type=4;m.value=m.value.replace(/^\[CDATA\[|\]\]$/g,"")}else{if(m.value.indexOf("mce:protected ")===0){m.name="#text";m.type=3;m.raw=true;m.value=unescape(m.value).substr(14)}}}});c.addNodeFilter("xml:namespace,input",function(j,k){var l=j.length,m;while(l--){m=j[l];if(m.type===7){m.remove()}else{if(m.type===1){if(k==="input"&&!("type" in m.attributes.map)){m.attr("type","text")}}}}});if(e.fix_list_elements){c.addNodeFilter("ul,ol",function(k,l){var m=k.length,n,j;while(m--){n=k[m];j=n.parent;if(j.name==="ul"||j.name==="ol"){if(n.prev&&n.prev.name==="li"){n.prev.append(n)}}}})}c.addAttributeFilter("data-mce-src,data-mce-href,data-mce-style",function(j,k){var l=j.length;while(l--){j[l].attr(k,null)}});return{schema:f,addNodeFilter:c.addNodeFilter,addAttributeFilter:c.addAttributeFilter,onPreProcess:h,onPostProcess:b,serialize:function(o,m){var l,p,k,j,n;if(d&&i.select("script,style,select,map").length>0){n=o.innerHTML;o=o.cloneNode(false);i.setHTML(o,n)}else{o=o.cloneNode(true)}l=o.ownerDocument.implementation;if(l.createHTMLDocument){p=l.createHTMLDocument("");g(o.nodeName=="BODY"?o.childNodes:[o],function(q){p.body.appendChild(p.importNode(q,true))});if(o.nodeName!="BODY"){o=p.body.firstChild}else{o=p.body}k=i.doc;i.doc=p}m=m||{};m.format=m.format||"html";if(!m.no_events){m.node=o;h.dispatch(self,m)}j=new a.html.Serializer(e,f);m.content=j.serialize(c.parse(a.trim(m.getInner?o.innerHTML:i.getOuterHTML(o)),m));if(!m.cleanup){m.content=m.content.replace(/\uFEFF/g,"")}if(!m.no_events){b.dispatch(self,m)}if(k){i.doc=k}m.node=null;return m.content},addRules:function(j){f.addValidElements(j)},setRules:function(j){f.setValidElements(j)}}}})(tinymce);(function(a){a.dom.ScriptLoader=function(h){var c=0,k=1,i=2,l={},j=[],e={},d=[],g=0,f;function b(m,v){var x=this,q=a.DOM,s,o,r,n;function p(){q.remove(n);if(s){s.onreadystatechange=s.onload=s=null}v()}function u(){if(typeof(console)!=="undefined"&&console.log){console.log("Failed to load: "+m)}}n=q.uniqueId();if(a.isIE6){o=new a.util.URI(m);r=location;if(o.host==r.hostname&&o.port==r.port&&(o.protocol+":")==r.protocol&&o.protocol.toLowerCase()!="file"){a.util.XHR.send({url:a._addVer(o.getURI()),success:function(y){var t=q.create("script",{type:"text/javascript"});t.text=y;document.getElementsByTagName("head")[0].appendChild(t);q.remove(t);p()},error:u});return}}s=document.createElement("script");s.id=n;s.type="text/javascript";s.src=a._addVer(m);if(!a.isIE||a.isIE11){s.onload=p}s.onerror=u;if(!a.isOpera){s.onreadystatechange=function(){var t=s.readyState;if(t=="complete"||t=="loaded"){p()}}}(document.getElementsByTagName("head")[0]||document.body).appendChild(s)}this.isDone=function(m){return l[m]==i};this.markDone=function(m){l[m]=i};this.add=this.load=function(m,q,n){var o,p=l[m];if(p==f){j.push(m);l[m]=c}if(q){if(!e[m]){e[m]=[]}e[m].push({func:q,scope:n||this})}};this.loadQueue=function(n,m){this.loadScripts(j,n,m)};this.loadScripts=function(m,q,p){var o;function n(r){a.each(e[r],function(s){s.func.call(s.scope)});e[r]=f}d.push({func:q,scope:p||this});o=function(){var r=a.grep(m);m.length=0;a.each(r,function(s){if(l[s]==i){n(s);return}if(l[s]!=k){l[s]=k;g++;b(s,function(){l[s]=i;g--;n(s);o()})}});if(!g){a.each(d,function(s){s.func.call(s.scope)});d.length=0}};o()}};a.ScriptLoader=new a.dom.ScriptLoader()})(tinymce);(function(a){a.dom.RangeUtils=function(c){var b="\uFEFF";this.walk=function(d,s){var i=d.startContainer,l=d.startOffset,t=d.endContainer,m=d.endOffset,j,g,o,h,r,q,e;e=c.select("td.mceSelected,th.mceSelected");if(e.length>0){a.each(e,function(u){s([u])});return}function f(u){var v;v=u[0];if(v.nodeType===3&&v===i&&l>=v.nodeValue.length){u.splice(0,1)}v=u[u.length-1];if(m===0&&u.length>0&&v===t&&v.nodeType===3){u.splice(u.length-1,1)}return u}function p(x,v,u){var y=[];for(;x&&x!=u;x=x[v]){y.push(x)}return y}function n(v,u){do{if(v.parentNode==u){return v}v=v.parentNode}while(v)}function k(x,v,y){var u=y?"nextSibling":"previousSibling";for(h=x,r=h.parentNode;h&&h!=v;h=r){r=h.parentNode;q=p(h==x?h:h[u],u);if(q.length){if(!y){q.reverse()}s(f(q))}}}if(i.nodeType==1&&i.hasChildNodes()){i=i.childNodes[l]}if(t.nodeType==1&&t.hasChildNodes()){t=t.childNodes[Math.min(m-1,t.childNodes.length-1)]}if(i==t){return s(f([i]))}j=c.findCommonAncestor(i,t);for(h=i;h;h=h.parentNode){if(h===t){return k(i,j,true)}if(h===j){break}}for(h=t;h;h=h.parentNode){if(h===i){return k(t,j)}if(h===j){break}}g=n(i,j)||i;o=n(t,j)||t;k(i,g,true);q=p(g==i?g:g.nextSibling,"nextSibling",o==t?o.nextSibling:o);if(q.length){s(f(q))}k(t,o)};this.split=function(e){var h=e.startContainer,d=e.startOffset,i=e.endContainer,g=e.endOffset;function f(j,k){return j.splitText(k)}if(h==i&&h.nodeType==3){if(d>0&&dd){g=g-d;h=i=f(i,g).previousSibling;g=i.nodeValue.length;d=0}else{g=0}}}else{if(h.nodeType==3&&d>0&&d0&&g=m.length){r=0}}t=m[r];f.setAttrib(g,"tabindex","-1");f.setAttrib(t.id,"tabindex","0");f.get(t.id).focus();if(e.actOnFocus){e.onAction(t.id)}if(s){a.cancel(s)}};p=function(z){var v=37,u=39,y=38,A=40,r=27,t=14,s=13,x=32;switch(z.keyCode){case v:if(i){q.moveFocus(-1)}a.cancel(z);break;case u:if(i){q.moveFocus(1)}a.cancel(z);break;case y:if(o){q.moveFocus(-1)}a.cancel(z);break;case A:if(o){q.moveFocus(1)}a.cancel(z);break;case r:if(e.onCancel){e.onCancel();a.cancel(z)}break;case t:case s:case x:if(e.onAction){e.onAction(g);a.cancel(z)}break}};c(m,function(t,r){var s,u;if(!t.id){t.id=f.uniqueId("_mce_item_")}u=f.get(t.id);if(l){f.bind(u,"blur",h);s="-1"}else{s=(r===0?"0":"-1")}u.setAttribute("tabindex",s);f.bind(u,"focus",k)});if(m[0]){g=m[0].id}f.setAttrib(n,"tabindex","-1");var j=f.get(n);f.bind(j,"focus",d);f.bind(j,"keydown",p)}})})(tinymce);(function(c){var b=c.DOM,a=c.is;c.create("tinymce.ui.Control",{Control:function(f,e,d){this.id=f;this.settings=e=e||{};this.rendered=false;this.onRender=new c.util.Dispatcher(this);this.classPrefix="";this.scope=e.scope||this;this.disabled=0;this.active=0;this.editor=d},setAriaProperty:function(f,e){var d=b.get(this.id+"_aria")||b.get(this.id);if(d){b.setAttrib(d,"aria-"+f,!!e)}},focus:function(){b.get(this.id).focus()},setDisabled:function(d){if(d!=this.disabled){this.setAriaProperty("disabled",d);this.setState("Disabled",d);this.setState("Enabled",!d);this.disabled=d}},isDisabled:function(){return this.disabled},setActive:function(d){if(d!=this.active){this.setState("Active",d);this.active=d;this.setAriaProperty("pressed",d)}},isActive:function(){return this.active},setState:function(f,d){var e=b.get(this.id);f=this.classPrefix+f;if(d){b.addClass(e,f)}else{b.removeClass(e,f)}},isRendered:function(){return this.rendered},renderHTML:function(){},renderTo:function(d){b.setHTML(d,this.renderHTML())},postRender:function(){var e=this,d;if(a(e.disabled)){d=e.disabled;e.disabled=-1;e.setDisabled(d)}if(a(e.active)){d=e.active;e.active=-1;e.setActive(d)}},remove:function(){b.remove(this.id);this.destroy()},destroy:function(){c.dom.Event.clear(this.id)}})})(tinymce);tinymce.create("tinymce.ui.Container:tinymce.ui.Control",{Container:function(c,b,a){this.parent(c,b,a);this.controls=[];this.lookup={}},add:function(a){this.lookup[a.id]=a;this.controls.push(a);return a},get:function(a){return this.lookup[a]}});tinymce.create("tinymce.ui.Separator:tinymce.ui.Control",{Separator:function(b,a){this.parent(b,a);this.classPrefix="mceSeparator";this.setDisabled(true)},renderHTML:function(){return tinymce.DOM.createHTML("span",{"class":this.classPrefix,role:"separator","aria-orientation":"vertical",tabindex:"-1"})}});(function(d){var c=d.is,b=d.DOM,e=d.each,a=d.walk;d.create("tinymce.ui.MenuItem:tinymce.ui.Control",{MenuItem:function(g,f){this.parent(g,f);this.classPrefix="mceMenuItem"},setSelected:function(f){this.setState("Selected",f);this.setAriaProperty("checked",!!f);this.selected=f},isSelected:function(){return this.selected},postRender:function(){var f=this;f.parent();if(c(f.selected)){f.setSelected(f.selected)}}})})(tinymce);(function(d){var c=d.is,b=d.DOM,e=d.each,a=d.walk;d.create("tinymce.ui.Menu:tinymce.ui.MenuItem",{Menu:function(h,g){var f=this;f.parent(h,g);f.items={};f.collapsed=false;f.menuCount=0;f.onAddItem=new d.util.Dispatcher(this)},expand:function(g){var f=this;if(g){a(f,function(h){if(h.expand){h.expand()}},"items",f)}f.collapsed=false},collapse:function(g){var f=this;if(g){a(f,function(h){if(h.collapse){h.collapse()}},"items",f)}f.collapsed=true},isCollapsed:function(){return this.collapsed},add:function(f){if(!f.settings){f=new d.ui.MenuItem(f.id||b.uniqueId(),f)}this.onAddItem.dispatch(this,f);return this.items[f.id]=f},addSeparator:function(){return this.add({separator:true})},addMenu:function(f){if(!f.collapse){f=this.createMenu(f)}this.menuCount++;return this.add(f)},hasMenus:function(){return this.menuCount!==0},remove:function(f){delete this.items[f.id]},removeAll:function(){var f=this;a(f,function(g){if(g.removeAll){g.removeAll()}else{g.remove()}g.destroy()},"items",f);f.items={}},createMenu:function(g){var f=new d.ui.Menu(g.id||b.uniqueId(),g);f.onAddItem.add(this.onAddItem.dispatch,this.onAddItem);return f}})})(tinymce);(function(e){var d=e.is,c=e.DOM,f=e.each,a=e.dom.Event,b=e.dom.Element;e.create("tinymce.ui.DropMenu:tinymce.ui.Menu",{DropMenu:function(h,g){g=g||{};g.container=g.container||c.doc.body;g.offset_x=g.offset_x||0;g.offset_y=g.offset_y||0;g.vp_offset_x=g.vp_offset_x||0;g.vp_offset_y=g.vp_offset_y||0;if(d(g.icons)&&!g.icons){g["class"]+=" mceNoIcons"}this.parent(h,g);this.onShowMenu=new e.util.Dispatcher(this);this.onHideMenu=new e.util.Dispatcher(this);this.classPrefix="mceMenu"},createMenu:function(j){var h=this,i=h.settings,g;j.container=j.container||i.container;j.parent=h;j.constrain=j.constrain||i.constrain;j["class"]=j["class"]||i["class"];j.vp_offset_x=j.vp_offset_x||i.vp_offset_x;j.vp_offset_y=j.vp_offset_y||i.vp_offset_y;j.keyboard_focus=i.keyboard_focus;g=new e.ui.DropMenu(j.id||c.uniqueId(),j);g.onAddItem.add(h.onAddItem.dispatch,h.onAddItem);return g},focus:function(){var g=this;if(g.keyboardNav){g.keyboardNav.focus()}},update:function(){var i=this,j=i.settings,g=c.get("menu_"+i.id+"_tbl"),l=c.get("menu_"+i.id+"_co"),h,k;h=j.max_width?Math.min(g.offsetWidth,j.max_width):g.offsetWidth;k=j.max_height?Math.min(g.offsetHeight,j.max_height):g.offsetHeight;if(!c.boxModel){i.element.setStyles({width:h+2,height:k+2})}else{i.element.setStyles({width:h,height:k})}if(j.max_width){c.setStyle(l,"width",h)}if(j.max_height){c.setStyle(l,"height",k);if(g.clientHeightv){p=r?r-u:Math.max(0,(v-A.vp_offset_x)-u)}if((n+A.vp_offset_y+l)>q){n=Math.max(0,(q-A.vp_offset_y)-l)}}c.setStyles(o,{left:p,top:n});z.element.update();z.isMenuVisible=1;z.mouseClickFunc=a.add(o,"click",function(s){var h;s=s.target;if(s&&(s=c.getParent(s,"tr"))&&!c.hasClass(s,m+"ItemSub")){h=z.items[s.id];if(h.isDisabled()){return}k=z;while(k){if(k.hideMenu){k.hideMenu()}k=k.settings.parent}if(h.settings.onclick){h.settings.onclick(s)}return false}});if(z.hasMenus()){z.mouseOverFunc=a.add(o,"mouseover",function(x){var h,t,s;x=x.target;if(x&&(x=c.getParent(x,"tr"))){h=z.items[x.id];if(z.lastMenu){z.lastMenu.collapse(1)}if(h.isDisabled()){return}if(x&&c.hasClass(x,m+"ItemSub")){t=c.getRect(x);h.showMenu((t.x+t.w-i),t.y-i,t.x);z.lastMenu=h;c.addClass(c.get(h.id).firstChild,m+"ItemActive")}}})}a.add(o,"keydown",z._keyHandler,z);z.onShowMenu.dispatch(z);if(A.keyboard_focus){z._setupKeyboardNav()}},hideMenu:function(j){var g=this,i=c.get("menu_"+g.id),h;if(!g.isMenuVisible){return}if(g.keyboardNav){g.keyboardNav.destroy()}a.remove(i,"mouseover",g.mouseOverFunc);a.remove(i,"click",g.mouseClickFunc);a.remove(i,"keydown",g._keyHandler);c.hide(i);g.isMenuVisible=0;if(!j){g.collapse(1)}if(g.element){g.element.hide()}if(h=c.get(g.id)){c.removeClass(h.firstChild,g.classPrefix+"ItemActive")}g.onHideMenu.dispatch(g)},add:function(i){var g=this,h;i=g.parent(i);if(g.isRendered&&(h=c.get("menu_"+g.id))){g._add(c.select("tbody",h)[0],i)}return i},collapse:function(g){this.parent(g);this.hideMenu(1)},remove:function(g){c.remove(g.id);this.destroy();return this.parent(g)},destroy:function(){var g=this,h=c.get("menu_"+g.id);if(g.keyboardNav){g.keyboardNav.destroy()}a.remove(h,"mouseover",g.mouseOverFunc);a.remove(c.select("a",h),"focus",g.mouseOverFunc);a.remove(h,"click",g.mouseClickFunc);a.remove(h,"keydown",g._keyHandler);if(g.element){g.element.remove()}c.remove(h)},renderNode:function(){var i=this,j=i.settings,l,h,k,g;g=c.create("div",{role:"listbox",id:"menu_"+i.id,"class":j["class"],style:"position:absolute;left:0;top:0;z-index:200000;outline:0"});if(i.settings.parent){c.setAttrib(g,"aria-parent","menu_"+i.settings.parent.id)}k=c.add(g,"div",{role:"presentation",id:"menu_"+i.id+"_co","class":i.classPrefix+(j["class"]?" "+j["class"]:"")});i.element=new b("menu_"+i.id,{blocker:1,container:j.container});if(j.menu_line){c.add(k,"span",{"class":i.classPrefix+"Line"})}l=c.add(k,"table",{role:"presentation",id:"menu_"+i.id+"_tbl",border:0,cellPadding:0,cellSpacing:0});h=c.add(l,"tbody");f(i.items,function(m){i._add(h,m)});i.rendered=true;return g},_setupKeyboardNav:function(){var i,h,g=this;i=c.get("menu_"+g.id);h=c.select("a[role=option]","menu_"+g.id);h.splice(0,0,i);g.keyboardNav=new e.ui.KeyboardNavigation({root:"menu_"+g.id,items:h,onCancel:function(){g.hideMenu()},enableUpDown:true});i.focus()},_keyHandler:function(g){var h=this,i;switch(g.keyCode){case 37:if(h.settings.parent){h.hideMenu();h.settings.parent.focus();a.cancel(g)}break;case 39:if(h.mouseOverFunc){h.mouseOverFunc(g)}break}},_add:function(j,h){var i,q=h.settings,p,l,k,m=this.classPrefix,g;if(q.separator){l=c.add(j,"tr",{id:h.id,"class":m+"ItemSeparator"});c.add(l,"td",{"class":m+"ItemSeparator"});if(i=l.previousSibling){c.addClass(i,"mceLast")}return}i=l=c.add(j,"tr",{id:h.id,"class":m+"Item "+m+"ItemEnabled"});i=k=c.add(i,q.titleItem?"th":"td");i=p=c.add(i,"a",{id:h.id+"_aria",role:q.titleItem?"presentation":"option",href:"javascript:;",onclick:"return false;",onmousedown:"return false;"});if(q.parent){c.setAttrib(p,"aria-haspopup","true");c.setAttrib(p,"aria-owns","menu_"+h.id)}c.addClass(k,q["class"]);g=c.add(i,"span",{"class":"mceIcon"+(q.icon?" mce_"+q.icon:"")});if(q.icon_src){c.add(g,"img",{src:q.icon_src})}i=c.add(i,q.element||"span",{"class":"mceText",title:h.settings.title},h.settings.title);if(h.settings.style){if(typeof h.settings.style=="function"){h.settings.style=h.settings.style()}c.setAttrib(i,"style",h.settings.style)}if(j.childNodes.length==1){c.addClass(l,"mceFirst")}if((i=l.previousSibling)&&c.hasClass(i,m+"ItemSeparator")){c.addClass(l,"mceFirst")}if(h.collapse){c.addClass(l,m+"ItemSub")}if(i=l.previousSibling){c.removeClass(i,"mceLast")}c.addClass(l,"mceLast")}})})(tinymce);(function(b){var a=b.DOM;b.create("tinymce.ui.Button:tinymce.ui.Control",{Button:function(e,d,c){this.parent(e,d,c);this.classPrefix="mceButton"},renderHTML:function(){var f=this.classPrefix,e=this.settings,d,c;c=a.encode(e.label||"");d='';if(e.image&&!(this.editor&&this.editor.forcedHighContrastMode)){d+=''+a.encode(e.title)+''+(c?''+c+"":"")}else{d+=''+(c?''+c+"":"")}d+='";d+="";return d},postRender:function(){var d=this,e=d.settings,c;if(b.isIE&&d.editor){b.dom.Event.add(d.id,"mousedown",function(f){var g=d.editor.selection.getNode().nodeName;c=g==="IMG"?d.editor.selection.getBookmark():null})}b.dom.Event.add(d.id,"click",function(f){if(!d.isDisabled()){if(b.isIE&&d.editor&&c!==null){d.editor.selection.moveToBookmark(c)}return e.onclick.call(e.scope,f)}});b.dom.Event.add(d.id,"keydown",function(f){if(!d.isDisabled()&&f.keyCode==b.VK.SPACEBAR){b.dom.Event.cancel(f);return e.onclick.call(e.scope,f)}})}})})(tinymce);(function(e){var d=e.DOM,b=e.dom.Event,f=e.each,a=e.util.Dispatcher,c;e.create("tinymce.ui.ListBox:tinymce.ui.Control",{ListBox:function(j,i,g){var h=this;h.parent(j,i,g);h.items=[];h.onChange=new a(h);h.onPostRender=new a(h);h.onAdd=new a(h);h.onRenderMenu=new e.util.Dispatcher(this);h.classPrefix="mceListBox";h.marked={}},select:function(h){var g=this,j,i;g.marked={};if(h==c){return g.selectByIndex(-1)}if(h&&typeof(h)=="function"){i=h}else{i=function(k){return k==h}}if(h!=g.selectedValue){f(g.items,function(l,k){if(i(l.value)){j=1;g.selectByIndex(k);return false}});if(!j){g.selectByIndex(-1)}}},selectByIndex:function(g){var i=this,j,k,h;i.marked={};if(g!=i.selectedIndex){j=d.get(i.id+"_text");h=d.get(i.id+"_voiceDesc");k=i.items[g];if(k){i.selectedValue=k.value;i.selectedIndex=g;d.setHTML(j,d.encode(k.title));d.setHTML(h,i.settings.title+" - "+k.title);d.removeClass(j,"mceTitle");d.setAttrib(i.id,"aria-valuenow",k.title)}else{d.setHTML(j,d.encode(i.settings.title));d.setHTML(h,d.encode(i.settings.title));d.addClass(j,"mceTitle");i.selectedValue=i.selectedIndex=null;d.setAttrib(i.id,"aria-valuenow",i.settings.title)}j=0}},mark:function(g){this.marked[g]=true},add:function(j,g,i){var h=this;i=i||{};i=e.extend(i,{title:j,value:g});h.items.push(i);h.onAdd.dispatch(h,i)},getLength:function(){return this.items.length},renderHTML:function(){var j="",g=this,i=g.settings,k=g.classPrefix;j='';j+="";j+="";j+="";return j},showMenu:function(){var h=this,j,i=d.get(this.id),g;if(h.isDisabled()||h.items.length===0){return}if(h.menu&&h.menu.isMenuVisible){return h.hideMenu()}if(!h.isMenuRendered){h.renderMenu();h.isMenuRendered=true}j=d.getPos(i);g=h.menu;g.settings.offset_x=j.x;g.settings.offset_y=j.y;g.settings.keyboard_focus=!e.isOpera;f(h.items,function(k){if(g.items[k.id]){g.items[k.id].setSelected(0)}});f(h.items,function(k){if(g.items[k.id]&&h.marked[k.value]){g.items[k.id].setSelected(1)}if(k.value===h.selectedValue){g.items[k.id].setSelected(1)}});g.showMenu(0,i.clientHeight);b.add(d.doc,"mousedown",h.hideMenu,h);d.addClass(h.id,h.classPrefix+"Selected")},hideMenu:function(h){var g=this;if(g.menu&&g.menu.isMenuVisible){d.removeClass(g.id,g.classPrefix+"Selected");if(h&&h.type=="mousedown"&&(h.target.id==g.id+"_text"||h.target.id==g.id+"_open")){return}if(!h||!d.getParent(h.target,".mceMenu")){d.removeClass(g.id,g.classPrefix+"Selected");b.remove(d.doc,"mousedown",g.hideMenu,g);g.menu.hideMenu()}}},renderMenu:function(){var h=this,g;g=h.settings.control_manager.createDropMenu(h.id+"_menu",{menu_line:1,"class":h.classPrefix+"Menu mceNoIcons",max_width:250,max_height:150});g.onHideMenu.add(function(){h.hideMenu();h.focus()});g.add({title:h.settings.title,"class":"mceMenuItemTitle",onclick:function(){if(h.settings.onselect("")!==false){h.select("")}}});f(h.items,function(i){if(i.value===c){g.add({title:i.title,role:"option","class":"mceMenuItemTitle",onclick:function(){if(h.settings.onselect("")!==false){h.select("")}}})}else{i.id=d.uniqueId();i.role="option";i.onclick=function(){if(h.settings.onselect(i.value)!==false){h.select(i.value)}};g.add(i)}});h.onRenderMenu.dispatch(h,g);h.menu=g},postRender:function(){var g=this,h=g.classPrefix;b.add(g.id,"click",g.showMenu,g);b.add(g.id,"keydown",function(i){if(i.keyCode==32){g.showMenu(i);b.cancel(i)}});b.add(g.id,"focus",function(){if(!g._focused){g.keyDownHandler=b.add(g.id,"keydown",function(i){if(i.keyCode==40){g.showMenu();b.cancel(i)}});g.keyPressHandler=b.add(g.id,"keypress",function(j){var i;if(j.keyCode==13){i=g.selectedValue;g.selectedValue=null;b.cancel(j);g.settings.onselect(i)}})}g._focused=1});b.add(g.id,"blur",function(){b.remove(g.id,"keydown",g.keyDownHandler);b.remove(g.id,"keypress",g.keyPressHandler);g._focused=0});if(e.isIE6||!d.boxModel){b.add(g.id,"mouseover",function(){if(!d.hasClass(g.id,h+"Disabled")){d.addClass(g.id,h+"Hover")}});b.add(g.id,"mouseout",function(){if(!d.hasClass(g.id,h+"Disabled")){d.removeClass(g.id,h+"Hover")}})}g.onPostRender.dispatch(g,d.get(g.id))},destroy:function(){this.parent();b.clear(this.id+"_text");b.clear(this.id+"_open")}})})(tinymce);(function(e){var d=e.DOM,b=e.dom.Event,f=e.each,a=e.util.Dispatcher,c;e.create("tinymce.ui.NativeListBox:tinymce.ui.ListBox",{NativeListBox:function(h,g){this.parent(h,g);this.classPrefix="mceNativeListBox"},setDisabled:function(g){d.get(this.id).disabled=g;this.setAriaProperty("disabled",g)},isDisabled:function(){return d.get(this.id).disabled},select:function(h){var g=this,j,i;if(h==c){return g.selectByIndex(-1)}if(h&&typeof(h)=="function"){i=h}else{i=function(k){return k==h}}if(h!=g.selectedValue){f(g.items,function(l,k){if(i(l.value)){j=1;g.selectByIndex(k);return false}});if(!j){g.selectByIndex(-1)}}},selectByIndex:function(g){d.get(this.id).selectedIndex=g+1;this.selectedValue=this.items[g]?this.items[g].value:null},add:function(k,h,g){var j,i=this;g=g||{};g.value=h;if(i.isRendered()){d.add(d.get(this.id),"option",g,k)}j={title:k,value:h,attribs:g};i.items.push(j);i.onAdd.dispatch(i,j)},getLength:function(){return this.items.length},renderHTML:function(){var i,g=this;i=d.createHTML("option",{value:""},"-- "+g.settings.title+" --");f(g.items,function(h){i+=d.createHTML("option",{value:h.value},h.title)});i=d.createHTML("select",{id:g.id,"class":"mceNativeListBox","aria-labelledby":g.id+"_aria"},i);i+=d.createHTML("span",{id:g.id+"_aria",style:"display: none"},g.settings.title);return i},postRender:function(){var h=this,i,j=true;h.rendered=true;function g(l){var k=h.items[l.target.selectedIndex-1];if(k&&(k=k.value)){h.onChange.dispatch(h,k);if(h.settings.onselect){h.settings.onselect(k)}}}b.add(h.id,"change",g);b.add(h.id,"keydown",function(q){var n,p=37,m=39,l=38,r=40,k=13,o=32;b.remove(h.id,"change",i);j=false;n=b.add(h.id,"blur",function(){if(j){return}j=true;b.add(h.id,"change",g);b.remove(h.id,"blur",n)});if(q.keyCode==k||q.keyCode==o){g(q);return b.cancel(q)}else{if(q.keyCode==r||q.keyCode==l){q.stopImmediatePropagation()}}});h.onPostRender.dispatch(h,d.get(h.id))}})})(tinymce);(function(c){var b=c.DOM,a=c.dom.Event,d=c.each;c.create("tinymce.ui.MenuButton:tinymce.ui.Button",{MenuButton:function(g,f,e){this.parent(g,f,e);this.onRenderMenu=new c.util.Dispatcher(this);f.menu_container=f.menu_container||b.doc.body},showMenu:function(){var g=this,j,i,h=b.get(g.id),f;if(g.isDisabled()){return}if(!g.isMenuRendered){g.renderMenu();g.isMenuRendered=true}if(g.isMenuVisible){return g.hideMenu()}j=b.getPos(g.settings.menu_container);i=b.getPos(h);f=g.menu;f.settings.offset_x=i.x;f.settings.offset_y=i.y;f.settings.vp_offset_x=i.x;f.settings.vp_offset_y=i.y;f.settings.keyboard_focus=g._focused;f.showMenu(0,h.firstChild.clientHeight);a.add(b.doc,"mousedown",g.hideMenu,g);g.setState("Selected",1);g.isMenuVisible=1},renderMenu:function(){var f=this,e;e=f.settings.control_manager.createDropMenu(f.id+"_menu",{menu_line:1,"class":this.classPrefix+"Menu",icons:f.settings.icons});e.onHideMenu.add(function(){f.hideMenu();f.focus()});f.onRenderMenu.dispatch(f,e);f.menu=e},hideMenu:function(g){var f=this;if(g&&g.type=="mousedown"&&b.getParent(g.target,function(h){return h.id===f.id||h.id===f.id+"_open"})){return}if(!g||!b.getParent(g.target,".mceMenu")){f.setState("Selected",0);a.remove(b.doc,"mousedown",f.hideMenu,f);if(f.menu){f.menu.hideMenu()}}f.isMenuVisible=0},postRender:function(){var e=this,f=e.settings;a.add(e.id,"click",function(){if(!e.isDisabled()){if(f.onclick){f.onclick(e.value)}e.showMenu()}})}})})(tinymce);(function(c){var b=c.DOM,a=c.dom.Event,d=c.each;c.create("tinymce.ui.SplitButton:tinymce.ui.MenuButton",{SplitButton:function(g,f,e){this.parent(g,f,e);this.classPrefix="mceSplitButton"},renderHTML:function(){var i,f=this,g=f.settings,e;i="";if(g.image){e=b.createHTML("img ",{src:g.image,role:"presentation","class":"mceAction "+g["class"]})}else{e=b.createHTML("span",{"class":"mceAction "+g["class"]},"")}e+=b.createHTML("span",{"class":"mceVoiceLabel mceIconOnly",id:f.id+"_voice",style:"display:none;"},g.title);i+=""+b.createHTML("a",{role:"button",id:f.id+"_action",tabindex:"-1",href:"javascript:;","class":"mceAction "+g["class"],onclick:"return false;",onmousedown:"return false;",title:g.title},e)+"";e=b.createHTML("span",{"class":"mceOpen "+g["class"]},'');i+=""+b.createHTML("a",{role:"button",id:f.id+"_open",tabindex:"-1",href:"javascript:;","class":"mceOpen "+g["class"],onclick:"return false;",onmousedown:"return false;",title:g.title},e)+"";i+="";i=b.createHTML("table",{role:"presentation","class":"mceSplitButton mceSplitButtonEnabled "+g["class"],cellpadding:"0",cellspacing:"0",title:g.title},i);return b.createHTML("div",{id:f.id,role:"button",tabindex:"0","aria-labelledby":f.id+"_voice","aria-haspopup":"true"},i)},postRender:function(){var e=this,g=e.settings,f;if(g.onclick){f=function(h){if(!e.isDisabled()){g.onclick(e.value);a.cancel(h)}};a.add(e.id+"_action","click",f);a.add(e.id,["click","keydown"],function(h){var k=32,m=14,i=13,j=38,l=40;if((h.keyCode===32||h.keyCode===13||h.keyCode===14)&&!h.altKey&&!h.ctrlKey&&!h.metaKey){f();a.cancel(h)}else{if(h.type==="click"||h.keyCode===l){e.showMenu();a.cancel(h)}}})}a.add(e.id+"_open","click",function(h){e.showMenu();a.cancel(h)});a.add([e.id,e.id+"_open"],"focus",function(){e._focused=1});a.add([e.id,e.id+"_open"],"blur",function(){e._focused=0});if(c.isIE6||!b.boxModel){a.add(e.id,"mouseover",function(){if(!b.hasClass(e.id,"mceSplitButtonDisabled")){b.addClass(e.id,"mceSplitButtonHover")}});a.add(e.id,"mouseout",function(){if(!b.hasClass(e.id,"mceSplitButtonDisabled")){b.removeClass(e.id,"mceSplitButtonHover")}})}},destroy:function(){this.parent();a.clear(this.id+"_action");a.clear(this.id+"_open");a.clear(this.id)}})})(tinymce);(function(d){var c=d.DOM,a=d.dom.Event,b=d.is,e=d.each;d.create("tinymce.ui.ColorSplitButton:tinymce.ui.SplitButton",{ColorSplitButton:function(i,h,f){var g=this;g.parent(i,h,f);g.settings=h=d.extend({colors:"000000,993300,333300,003300,003366,000080,333399,333333,800000,FF6600,808000,008000,008080,0000FF,666699,808080,FF0000,FF9900,99CC00,339966,33CCCC,3366FF,800080,999999,FF00FF,FFCC00,FFFF00,00FF00,00FFFF,00CCFF,993366,C0C0C0,FF99CC,FFCC99,FFFF99,CCFFCC,CCFFFF,99CCFF,CC99FF,FFFFFF",grid_width:8,default_color:"#888888"},g.settings);g.onShowMenu=new d.util.Dispatcher(g);g.onHideMenu=new d.util.Dispatcher(g);g.value=h.default_color},showMenu:function(){var f=this,g,j,i,h;if(f.isDisabled()){return}if(!f.isMenuRendered){f.renderMenu();f.isMenuRendered=true}if(f.isMenuVisible){return f.hideMenu()}i=c.get(f.id);c.show(f.id+"_menu");c.addClass(i,"mceSplitButtonSelected");h=c.getPos(i);c.setStyles(f.id+"_menu",{left:h.x,top:h.y+i.firstChild.clientHeight,zIndex:200000});i=0;a.add(c.doc,"mousedown",f.hideMenu,f);f.onShowMenu.dispatch(f);if(f._focused){f._keyHandler=a.add(f.id+"_menu","keydown",function(k){if(k.keyCode==27){f.hideMenu()}});c.select("a",f.id+"_menu")[0].focus()}f.keyboardNav=new d.ui.KeyboardNavigation({root:f.id+"_menu",items:c.select("a",f.id+"_menu"),onCancel:function(){f.hideMenu();f.focus()}});f.keyboardNav.focus();f.isMenuVisible=1},hideMenu:function(g){var f=this;if(f.isMenuVisible){if(g&&g.type=="mousedown"&&c.getParent(g.target,function(h){return h.id===f.id+"_open"})){return}if(!g||!c.getParent(g.target,".mceSplitButtonMenu")){c.removeClass(f.id,"mceSplitButtonSelected");a.remove(c.doc,"mousedown",f.hideMenu,f);a.remove(f.id+"_menu","keydown",f._keyHandler);c.hide(f.id+"_menu")}f.isMenuVisible=0;f.onHideMenu.dispatch();f.keyboardNav.destroy()}},renderMenu:function(){var p=this,h,k=0,q=p.settings,g,j,l,o,f;o=c.add(q.menu_container,"div",{role:"listbox",id:p.id+"_menu","class":q.menu_class+" "+q["class"],style:"position:absolute;left:0;top:-1000px;"});h=c.add(o,"div",{"class":q["class"]+" mceSplitButtonMenu"});c.add(h,"span",{"class":"mceMenuLine"});g=c.add(h,"table",{role:"presentation","class":"mceColorSplitMenu"});j=c.add(g,"tbody");k=0;e(b(q.colors,"array")?q.colors:q.colors.split(","),function(m){m=m.replace(/^#/,"");if(!k--){l=c.add(j,"tr");k=q.grid_width-1}g=c.add(l,"td");var i={href:"javascript:;",style:{backgroundColor:"#"+m},title:p.editor.getLang("colors."+m,m),"data-mce-color":"#"+m};if(!d.isIE){i.role="option"}g=c.add(g,"a",i);if(p.editor.forcedHighContrastMode){g=c.add(g,"canvas",{width:16,height:16,"aria-hidden":"true"});if(g.getContext&&(f=g.getContext("2d"))){f.fillStyle="#"+m;f.fillRect(0,0,16,16)}else{c.remove(g)}}});if(q.more_colors_func){g=c.add(j,"tr");g=c.add(g,"td",{colspan:q.grid_width,"class":"mceMoreColors"});g=c.add(g,"a",{role:"option",id:p.id+"_more",href:"javascript:;",onclick:"return false;","class":"mceMoreColors"},q.more_colors_title);a.add(g,"click",function(i){q.more_colors_func.call(q.more_colors_scope||this);return a.cancel(i)})}c.addClass(h,"mceColorSplitMenu");a.add(p.id+"_menu","mousedown",function(i){return a.cancel(i)});a.add(p.id+"_menu","click",function(i){var m;i=c.getParent(i.target,"a",j);if(i&&i.nodeName.toLowerCase()=="a"&&(m=i.getAttribute("data-mce-color"))){p.setColor(m)}return false});return o},setColor:function(f){this.displayColor(f);this.hideMenu();this.settings.onselect(f)},displayColor:function(g){var f=this;c.setStyle(f.id+"_preview","backgroundColor",g);f.value=g},postRender:function(){var f=this,g=f.id;f.parent();c.add(g+"_action","div",{id:g+"_preview","class":"mceColorPreview"});c.setStyle(f.id+"_preview","backgroundColor",f.value)},destroy:function(){var f=this;f.parent();a.clear(f.id+"_menu");a.clear(f.id+"_more");c.remove(f.id+"_menu");if(f.keyboardNav){f.keyboardNav.destroy()}}})})(tinymce);(function(b){var d=b.DOM,c=b.each,a=b.dom.Event;b.create("tinymce.ui.ToolbarGroup:tinymce.ui.Container",{renderHTML:function(){var f=this,i=[],e=f.controls,j=b.each,g=f.settings;i.push('
');i.push("");i.push('");j(e,function(h){i.push(h.renderHTML())});i.push("");i.push("
");return i.join("")},focus:function(){var e=this;d.get(e.id).focus()},postRender:function(){var f=this,e=[];c(f.controls,function(g){c(g.controls,function(h){if(h.id){e.push(h)}})});f.keyNav=new b.ui.KeyboardNavigation({root:f.id,items:e,onCancel:function(){if(b.isWebKit){d.get(f.editor.id+"_ifr").focus()}f.editor.focus()},excludeFromTabOrder:!f.settings.tab_focus_toolbar})},destroy:function(){var e=this;e.parent();e.keyNav.destroy();a.clear(e.id)}})})(tinymce);(function(a){var c=a.DOM,b=a.each;a.create("tinymce.ui.Toolbar:tinymce.ui.Container",{renderHTML:function(){var m=this,f="",j,k,n=m.settings,e,d,g,l;l=m.controls;for(e=0;e"))}if(d&&k.ListBox){if(d.Button||d.SplitButton){f+=c.createHTML("td",{"class":"mceToolbarEnd"},c.createHTML("span",null,""))}}if(c.stdMode){f+=''+k.renderHTML()+""}else{f+=""+k.renderHTML()+""}if(g&&k.ListBox){if(g.Button||g.SplitButton){f+=c.createHTML("td",{"class":"mceToolbarStart"},c.createHTML("span",null,""))}}}j="mceToolbarEnd";if(k.Button){j+=" mceToolbarEndButton"}else{if(k.SplitButton){j+=" mceToolbarEndSplitButton"}else{if(k.ListBox){j+=" mceToolbarEndListBox"}}}f+=c.createHTML("td",{"class":j},c.createHTML("span",null,""));return c.createHTML("table",{id:m.id,"class":"mceToolbar"+(n["class"]?" "+n["class"]:""),cellpadding:"0",cellspacing:"0",align:m.settings.align||"",role:"presentation",tabindex:"-1"},""+f+"")}})})(tinymce);(function(b){var a=b.util.Dispatcher,c=b.each;b.create("tinymce.AddOnManager",{AddOnManager:function(){var d=this;d.items=[];d.urls={};d.lookup={};d.onAdd=new a(d)},get:function(d){if(this.lookup[d]){return this.lookup[d].instance}else{return undefined}},dependencies:function(e){var d;if(this.lookup[e]){d=this.lookup[e].dependencies}return d||[]},requireLangPack:function(e){var d=b.settings;if(d&&d.language&&d.language_load!==false){b.ScriptLoader.add(this.urls[e]+"/langs/"+d.language+".js")}},add:function(f,e,d){this.items.push(e);this.lookup[f]={instance:e,dependencies:d};this.onAdd.dispatch(this,f,e);return e},createUrl:function(d,e){if(typeof e==="object"){return e}else{return{prefix:d.prefix,resource:e,suffix:d.suffix}}},addComponents:function(f,d){var e=this.urls[f];b.each(d,function(g){b.ScriptLoader.add(e+"/"+g)})},load:function(j,f,d,h){var g=this,e=f;function i(){var k=g.dependencies(j);b.each(k,function(m){var l=g.createUrl(f,m);g.load(l.resource,l,undefined,undefined)});if(d){if(h){d.call(h)}else{d.call(b.ScriptLoader)}}}if(g.urls[j]){return}if(typeof f==="object"){e=f.prefix+f.resource+f.suffix}if(e.indexOf("/")!==0&&e.indexOf("://")==-1){e=b.baseURL+"/"+e}g.urls[j]=e.substring(0,e.lastIndexOf("/"));if(g.lookup[j]){i()}else{b.ScriptLoader.add(e,i,h)}}});b.PluginManager=new b.AddOnManager();b.ThemeManager=new b.AddOnManager()}(tinymce));(function(j){var g=j.each,d=j.extend,k=j.DOM,i=j.dom.Event,f=j.ThemeManager,b=j.PluginManager,e=j.explode,h=j.util.Dispatcher,a,c=0;j.documentBaseURL=window.location.href.replace(/[\?#].*$/,"").replace(/[\/\\][^\/]+$/,"");if(!/[\/\\]$/.test(j.documentBaseURL)){j.documentBaseURL+="/"}j.baseURL=new j.util.URI(j.documentBaseURL).toAbsolute(j.baseURL);j.baseURI=new j.util.URI(j.baseURL);j.onBeforeUnload=new h(j);i.add(window,"beforeunload",function(l){j.onBeforeUnload.dispatch(j,l)});j.onAddEditor=new h(j);j.onRemoveEditor=new h(j);j.EditorManager=d(j,{editors:[],i18n:{},activeEditor:null,init:function(x){var v=this,o,n=j.ScriptLoader,u,l=[],r;function q(t){var s=t.id;if(!s){s=t.name;if(s&&!k.get(s)){s=t.name}else{s=k.uniqueId()}t.setAttribute("id",s)}return s}function m(z,A,t){var y=z[A];if(!y){return}if(j.is(y,"string")){t=y.replace(/\.\w+$/,"");t=t?j.resolve(t):0;y=j.resolve(y)}return y.apply(t||this,Array.prototype.slice.call(arguments,2))}function p(t,s){return s.constructor===RegExp?s.test(t.className):k.hasClass(t,s)}v.settings=x;i.bind(window,"ready",function(){var s,t;m(x,"onpageload");switch(x.mode){case"exact":s=x.elements||"";if(s.length>0){g(e(s),function(y){if(k.get(y)){r=new j.Editor(y,x);l.push(r);r.render(1)}else{g(document.forms,function(z){g(z.elements,function(A){if(A.name===y){y="mce_editor_"+c++;k.setAttrib(A,"id",y);r=new j.Editor(y,x);l.push(r);r.render(1)}})})}})}break;case"textareas":case"specific_textareas":g(k.select("textarea"),function(y){if(x.editor_deselector&&p(y,x.editor_deselector)){return}if(!x.editor_selector||p(y,x.editor_selector)){r=new j.Editor(q(y),x);l.push(r);r.render(1)}});break;default:if(x.types){g(x.types,function(y){g(k.select(y.selector),function(A){var z=new j.Editor(q(A),j.extend({},x,y));l.push(z);z.render(1)})})}else{if(x.selector){g(k.select(x.selector),function(z){var y=new j.Editor(q(z),x);l.push(y);y.render(1)})}}}if(x.oninit){s=t=0;g(l,function(y){t++;if(!y.initialized){y.onInit.add(function(){s++;if(s==t){m(x,"oninit")}})}else{s++}if(s==t){m(x,"oninit")}})}})},get:function(l){if(l===a){return this.editors}if(!this.editors.hasOwnProperty(l)){return a}return this.editors[l]},getInstanceById:function(l){return this.get(l)},add:function(m){var l=this,n=l.editors;n[m.id]=m;n.push(m);l._setActive(m);l.onAddEditor.dispatch(l,m);return m},remove:function(n){var m=this,l,o=m.editors;if(!o[n.id]){return null}delete o[n.id];for(l=0;l':"",visual:n,font_size_style_values:"xx-small,x-small,small,medium,large,x-large,xx-large",font_size_legacy_values:"xx-small,small,medium,large,x-large,xx-large,300%",apply_source_formatting:n,directionality:"ltr",forced_root_block:"p",hidden_input:n,padd_empty_editor:n,render_ui:n,indentation:"30px",fix_table_elements:n,inline_styles:n,convert_fonts_to_spans:n,indent:"simple",indent_before:"p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,li,area,table,thead,tfoot,tbody,tr,section,article,hgroup,aside,figure,option,optgroup,datalist",indent_after:"p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,li,area,table,thead,tfoot,tbody,tr,section,article,hgroup,aside,figure,option,optgroup,datalist",validate:n,entity_encoding:"named",url_converter:m.convertURL,url_converter_scope:m,ie7_compat:n},o);m.id=m.editorId=p;m.isNotDirty=false;m.plugins={};m.documentBaseURI=new k.util.URI(o.document_base_url||k.documentBaseURL,{base_uri:tinyMCE.baseURI});m.baseURI=k.baseURI;m.contentCSS=[];m.contentStyles=[];m.setupEvents();m.execCommands={};m.queryStateCommands={};m.queryValueCommands={};m.execCallback("setup",m)},render:function(o){var p=this,q=p.settings,r=p.id,m=k.ScriptLoader;if(!j.domLoaded){j.add(window,"ready",function(){p.render()});return}tinyMCE.settings=q;if(!p.getElement()){return}if(k.isIDevice&&!k.isIOS5){return}if(!/TEXTAREA|INPUT/i.test(p.getElement().nodeName)&&q.hidden_input&&l.getParent(r,"form")){l.insertAfter(l.create("input",{type:"hidden",name:r}),r)}if(!q.content_editable){p.orgVisibility=p.getElement().style.visibility;p.getElement().style.visibility="hidden"}if(k.WindowManager){p.windowManager=new k.WindowManager(p)}if(q.encoding=="xml"){p.onGetContent.add(function(s,t){if(t.save){t.content=l.encode(t.content)}})}if(q.add_form_submit_trigger){p.onSubmit.addToTop(function(){if(p.initialized){p.save();p.isNotDirty=1}})}if(q.add_unload_trigger){p._beforeUnload=tinyMCE.onBeforeUnload.add(function(){if(p.initialized&&!p.destroyed&&!p.isHidden()){p.save({format:"raw",no_events:true})}})}k.addUnload(p.destroy,p);if(q.submit_patch){p.onBeforeRenderUI.add(function(){var s=p.getElement().form;if(!s){return}if(s._mceOldSubmit){return}if(!s.submit.nodeType&&!s.submit.length){p.formElement=s;s._mceOldSubmit=s.submit;s.submit=function(){k.triggerSave();p.isNotDirty=1;return p.formElement._mceOldSubmit(p.formElement)}}s=null})}function n(){if(q.language&&q.language_load!==false){m.add(k.baseURL+"/langs/"+q.language+".js")}if(q.theme&&typeof q.theme!="function"&&q.theme.charAt(0)!="-"&&!h.urls[q.theme]){h.load(q.theme,"themes/"+q.theme+"/editor_template"+k.suffix+".js")}i(g(q.plugins),function(t){if(t&&!c.urls[t]){if(t.charAt(0)=="-"){t=t.substr(1,t.length);var s=c.dependencies(t);i(s,function(v){var u={prefix:"plugins/",resource:v,suffix:"/editor_plugin"+k.suffix+".js"};v=c.createUrl(u,v);c.load(v.resource,v)})}else{if(t=="safari"){return}c.load(t,{prefix:"plugins/",resource:t,suffix:"/editor_plugin"+k.suffix+".js"})}}});m.loadQueue(function(){if(!p.removed){p.init()}})}n()},init:function(){var q,G=this,H=G.settings,D,y,z,C=G.getElement(),p,m,E,v,B,F,x,r=[];k.add(G);H.aria_label=H.aria_label||l.getAttrib(C,"aria-label",G.getLang("aria.rich_text_area"));if(H.theme){if(typeof H.theme!="function"){H.theme=H.theme.replace(/-/,"");p=h.get(H.theme);G.theme=new p();if(G.theme.init){G.theme.init(G,h.urls[H.theme]||k.documentBaseURL.replace(/\/$/,""))}}else{G.theme=H.theme}}function A(s){var t=c.get(s),o=c.urls[s]||k.documentBaseURL.replace(/\/$/,""),n;if(t&&k.inArray(r,s)===-1){i(c.dependencies(s),function(u){A(u)});n=new t(G,o);G.plugins[s]=n;if(n.init){n.init(G,o);r.push(s)}}}i(g(H.plugins.replace(/\-/g,"")),A);if(H.popup_css!==false){if(H.popup_css){H.popup_css=G.documentBaseURI.toAbsolute(H.popup_css)}else{H.popup_css=G.baseURI.toAbsolute("themes/"+H.theme+"/skins/"+H.skin+"/dialog.css")}}if(H.popup_css_add){H.popup_css+=","+G.documentBaseURI.toAbsolute(H.popup_css_add)}G.controlManager=new k.ControlManager(G);G.onBeforeRenderUI.dispatch(G,G.controlManager);if(H.render_ui&&G.theme){G.orgDisplay=C.style.display;if(typeof H.theme!="function"){D=H.width||C.style.width||C.offsetWidth;y=H.height||C.style.height||C.offsetHeight;z=H.min_height||100;F=/^[0-9\.]+(|px)$/i;if(F.test(""+D)){D=Math.max(parseInt(D,10)+(p.deltaWidth||0),100)}if(F.test(""+y)){y=Math.max(parseInt(y,10)+(p.deltaHeight||0),z)}p=G.theme.renderUI({targetNode:C,width:D,height:y,deltaWidth:H.delta_width,deltaHeight:H.delta_height});l.setStyles(p.sizeContainer||p.editorContainer,{width:D,height:y});y=(p.iframeHeight||y)+(typeof(y)=="number"?(p.deltaHeight||0):"");if(y';if(H.document_base_url!=k.documentBaseURL){G.iframeHTML+=''}if(k.isIE8){if(H.ie7_compat){G.iframeHTML+=''}else{G.iframeHTML+=''}}G.iframeHTML+='';for(x=0;x'}G.contentCSS=[];v=H.body_id||"tinymce";if(v.indexOf("=")!=-1){v=G.getParam("body_id","","hash");v=v[G.id]||v}B=H.body_class||"";if(B.indexOf("=")!=-1){B=G.getParam("body_class","","hash");B=B[G.id]||""}G.iframeHTML+='
";if(k.relaxedDomain&&(b||(k.isOpera&&parseFloat(opera.version())<11))){E='javascript:(function(){document.open();document.domain="'+document.domain+'";var ed = window.parent.tinyMCE.get("'+G.id+'");document.write(ed.iframeHTML);document.close();ed.initContentBody();})()'}q=l.add(p.iframeContainer,"iframe",{id:G.id+"_ifr",src:E||'javascript:""',frameBorder:"0",allowTransparency:"true",title:H.aria_label,style:{width:"100%",height:y,display:"block"}});G.contentAreaContainer=p.iframeContainer;if(p.editorContainer){l.get(p.editorContainer).style.display=G.orgDisplay}C.style.visibility=G.orgVisibility;l.get(G.id).style.display="none";l.setAttrib(G.id,"aria-hidden",true);if(!k.relaxedDomain||!E){G.initContentBody()}C=q=p=null},initContentBody:function(){var n=this,p=n.settings,q=l.get(n.id),r=n.getDoc(),o,m,s;if((!b||!k.relaxedDomain)&&!p.content_editable){r.open();r.write(n.iframeHTML);r.close();if(k.relaxedDomain){r.domain=k.relaxedDomain}}if(p.content_editable){l.addClass(q,"mceContentBody");n.contentDocument=r=p.content_document||document;n.contentWindow=p.content_window||window;n.bodyElement=q;p.content_document=p.content_window=null}m=n.getBody();m.disabled=true;if(!p.readonly){m.contentEditable=n.getParam("content_editable_state",true)}m.disabled=false;n.schema=new k.html.Schema(p);n.dom=new k.dom.DOMUtils(r,{keep_values:true,url_converter:n.convertURL,url_converter_scope:n,hex_colors:p.force_hex_style_colors,class_filter:p.class_filter,update_styles:true,root_element:p.content_editable?n.id:null,schema:n.schema});n.parser=new k.html.DomParser(p,n.schema);n.parser.addAttributeFilter("src,href,style",function(t,u){var v=t.length,y,A=n.dom,z,x;while(v--){y=t[v];z=y.attr(u);x="data-mce-"+u;if(!y.attributes.map[x]){if(u==="style"){y.attr(x,A.serializeStyle(A.parseStyle(z),y.name))}else{y.attr(x,n.convertURL(z,u,y.name))}}}});n.parser.addNodeFilter("script",function(t,u){var v=t.length,x;while(v--){x=t[v];x.attr("type","mce-"+(x.attr("type")||"text/javascript"))}});n.parser.addNodeFilter("#cdata",function(t,u){var v=t.length,x;while(v--){x=t[v];x.type=8;x.name="#comment";x.value="[CDATA["+x.value+"]]"}});n.parser.addNodeFilter("p,h1,h2,h3,h4,h5,h6,div",function(u,v){var x=u.length,y,t=n.schema.getNonEmptyElements();while(x--){y=u[x];if(y.isEmpty(t)){y.empty().append(new k.html.Node("br",1)).shortEnded=true}}});n.serializer=new k.dom.Serializer(p,n.dom,n.schema);n.selection=new k.dom.Selection(n.dom,n.getWin(),n.serializer,n);n.formatter=new k.Formatter(n);n.undoManager=new k.UndoManager(n);n.forceBlocks=new k.ForceBlocks(n);n.enterKey=new k.EnterKey(n);n.editorCommands=new k.EditorCommands(n);n.onExecCommand.add(function(t,u){if(!/^(FontName|FontSize)$/.test(u)){n.nodeChanged()}});n.serializer.onPreProcess.add(function(t,u){return n.onPreProcess.dispatch(n,u,t)});n.serializer.onPostProcess.add(function(t,u){return n.onPostProcess.dispatch(n,u,t)});n.onPreInit.dispatch(n);if(!p.browser_spellcheck&&!p.gecko_spellcheck){r.body.spellcheck=false}if(!p.readonly){n.bindNativeEvents()}n.controlManager.onPostRender.dispatch(n,n.controlManager);n.onPostRender.dispatch(n);n.quirks=k.util.Quirks(n);if(p.directionality){m.dir=p.directionality}if(p.nowrap){m.style.whiteSpace="nowrap"}if(p.protect){n.onBeforeSetContent.add(function(t,u){i(p.protect,function(v){u.content=u.content.replace(v,function(x){return""})})})}n.onSetContent.add(function(){n.addVisual(n.getBody())});if(p.padd_empty_editor){n.onPostProcess.add(function(t,u){u.content=u.content.replace(/^(]*>( | |\s|\u00a0|)<\/p>[\r\n]*|
[\r\n]*)$/,"")})}n.load({initial:true,format:"html"});n.startContent=n.getContent({format:"raw"});n.initialized=true;n.onInit.dispatch(n);n.execCallback("setupcontent_callback",n.id,m,r);n.execCallback("init_instance_callback",n);n.focus(true);n.nodeChanged({initial:true});if(n.contentStyles.length>0){s="";i(n.contentStyles,function(t){s+=t+"\r\n"});n.dom.addStyle(s)}i(n.contentCSS,function(t){n.dom.loadCSS(t)});if(p.auto_focus){setTimeout(function(){var t=k.get(p.auto_focus);t.selection.select(t.getBody(),1);t.selection.collapse(1);t.getBody().focus();t.getWin().focus()},100)}q=r=m=null},focus:function(p){var o,u=this,t=u.selection,q=u.settings.content_editable,n,r,s=u.getDoc(),m;if(!p){if(u.bookmark){t.moveToBookmark(u.bookmark);u.bookmark=null}n=t.getRng();if(n.item){r=n.item(0)}u._refreshContentEditable();if(!q){u.getWin().focus()}if(k.isGecko||q){m=u.getBody();if(m.setActive&&!k.isIE11){m.setActive()}else{m.focus()}if(q){t.normalize()}}if(r&&r.ownerDocument==s){n=s.body.createControlRange();n.addElement(r);n.select()}}if(k.activeEditor!=u){if((o=k.activeEditor)!=null){o.onDeactivate.dispatch(o,u)}u.onActivate.dispatch(u,o)}k._setActive(u)},execCallback:function(q){var m=this,p=m.settings[q],o;if(!p){return}if(m.callbackLookup&&(o=m.callbackLookup[q])){p=o.func;o=o.scope}if(d(p,"string")){o=p.replace(/\.\w+$/,"");o=o?k.resolve(o):0;p=k.resolve(p);m.callbackLookup=m.callbackLookup||{};m.callbackLookup[q]={func:p,scope:o}}return p.apply(o||m,Array.prototype.slice.call(arguments,1))},translate:function(m){var o=this.settings.language||"en",n=k.i18n;if(!m){return""}return n[o+"."+m]||m.replace(/\{\#([^\}]+)\}/g,function(q,p){return n[o+"."+p]||"{#"+p+"}"})},getLang:function(o,m){return k.i18n[(this.settings.language||"en")+"."+o]||(d(m)?m:"{#"+o+"}")},getParam:function(t,q,m){var r=k.trim,p=d(this.settings[t])?this.settings[t]:q,s;if(m==="hash"){s={};if(d(p,"string")){i(p.indexOf("=")>0?p.split(/[;,](?![^=;,]*(?:[;,]|$))/):p.split(","),function(n){n=n.split("=");if(n.length>1){s[r(n[0])]=r(n[1])}else{s[r(n[0])]=r(n)}})}else{s=p}return s}return p},nodeChanged:function(q){var m=this,n=m.selection,p;if(!m.initialized){return}q=q||{};p=n.getStart()||m.getBody();p=b&&p.ownerDocument!=m.getDoc()?m.getBody():p;q.parents=[];m.dom.getParent(p,function(o){if(o.nodeName=="BODY"){return true}q.parents.push(o)});m.onNodeChange.dispatch(m,q?q.controlManager||m.controlManager:m.controlManager,p,n.isCollapsed(),q)},addButton:function(n,o){var m=this;m.buttons=m.buttons||{};m.buttons[n]=o},addCommand:function(m,o,n){this.execCommands[m]={func:o,scope:n||this}},addQueryStateHandler:function(m,o,n){this.queryStateCommands[m]={func:o,scope:n||this}},addQueryValueHandler:function(m,o,n){this.queryValueCommands[m]={func:o,scope:n||this}},addShortcut:function(o,q,m,p){var n=this,r;if(n.settings.custom_shortcuts===false){return false}n.shortcuts=n.shortcuts||{};if(d(m,"string")){r=m;m=function(){n.execCommand(r,false,null)}}if(d(m,"object")){r=m;m=function(){n.execCommand(r[0],r[1],r[2])}}i(g(o),function(s){var t={func:m,scope:p||this,desc:n.translate(q),alt:false,ctrl:false,shift:false};i(g(s,"+"),function(u){switch(u){case"alt":case"ctrl":case"shift":t[u]=true;break;default:t.charCode=u.charCodeAt(0);t.keyCode=u.toUpperCase().charCodeAt(0)}});n.shortcuts[(t.ctrl?"ctrl":"")+","+(t.alt?"alt":"")+","+(t.shift?"shift":"")+","+t.keyCode]=t});return true},execCommand:function(u,r,x,m){var p=this,q=0,v,n;if(!/^(mceAddUndoLevel|mceEndUndoLevel|mceBeginUndoLevel|mceRepaint|SelectAll)$/.test(u)&&(!m||!m.skip_focus)){p.focus()}m=f({},m);p.onBeforeExecCommand.dispatch(p,u,r,x,m);if(m.terminate){return false}if(p.execCallback("execcommand_callback",p.id,p.selection.getNode(),u,r,x)){p.onExecCommand.dispatch(p,u,r,x,m);return true}if(v=p.execCommands[u]){n=v.func.call(v.scope,r,x);if(n!==true){p.onExecCommand.dispatch(p,u,r,x,m);return n}}i(p.plugins,function(o){if(o.execCommand&&o.execCommand(u,r,x)){p.onExecCommand.dispatch(p,u,r,x,m);q=1;return false}});if(q){return true}if(p.theme&&p.theme.execCommand&&p.theme.execCommand(u,r,x)){p.onExecCommand.dispatch(p,u,r,x,m);return true}if(p.editorCommands.execCommand(u,r,x)){p.onExecCommand.dispatch(p,u,r,x,m);return true}p.getDoc().execCommand(u,r,x);p.onExecCommand.dispatch(p,u,r,x,m)},queryCommandState:function(q){var n=this,r,p;if(n._isHidden()){return}if(r=n.queryStateCommands[q]){p=r.func.call(r.scope);if(p!==true){return p}}r=n.editorCommands.queryCommandState(q);if(r!==-1){return r}try{return this.getDoc().queryCommandState(q)}catch(m){}},queryCommandValue:function(r){var n=this,q,p;if(n._isHidden()){return}if(q=n.queryValueCommands[r]){p=q.func.call(q.scope);if(p!==true){return p}}q=n.editorCommands.queryCommandValue(r);if(d(q)){return q}try{return this.getDoc().queryCommandValue(r)}catch(m){}},show:function(){var m=this;l.show(m.getContainer());l.hide(m.id);m.load()},hide:function(){var m=this,n=m.getDoc();if(b&&n){n.execCommand("SelectAll")}m.save();l.hide(m.getContainer());l.setStyle(m.id,"display",m.orgDisplay)},isHidden:function(){return !l.isHidden(this.id)},setProgressState:function(m,n,p){this.onSetProgressState.dispatch(this,m,n,p);return m},load:function(q){var m=this,p=m.getElement(),n;if(p){q=q||{};q.load=true;n=m.setContent(d(p.value)?p.value:p.innerHTML,q);q.element=p;if(!q.no_events){m.onLoadContent.dispatch(m,q)}q.element=p=null;return n}},save:function(r){var m=this,q=m.getElement(),n,p;if(!q||!m.initialized){return}r=r||{};r.save=true;r.element=q;n=r.content=m.getContent(r);if(!r.no_events){m.onSaveContent.dispatch(m,r)}n=r.content;if(!/TEXTAREA|INPUT/i.test(q.nodeName)){q.innerHTML=n;if(p=l.getParent(m.id,"form")){i(p.elements,function(o){if(o.name==m.id){o.value=n;return false}})}}else{q.value=n}r.element=q=null;return n},setContent:function(q,o){var n=this,m=n.getBody(),p;o=o||{};o.format=o.format||"html";o.set=true;o.content=q;if(!o.no_events){n.onBeforeSetContent.dispatch(n,o)}q=o.content;if(q.length===0||/^\s+$/.test(q)){p=n.settings.forced_root_block;if(p&&n.schema.isValidChild(m.nodeName.toLowerCase(),p.toLowerCase())){if(b){q="<"+p+">"}else{q="<"+p+'>
"}}else{if(!b){q='
'}}m.innerHTML=q;n.selection.select(m,true);n.selection.collapse(true);return}if(o.format!=="raw"){q=new k.html.Serializer({},n.schema).serialize(n.parser.parse(q))}o.content=k.trim(q);n.dom.setHTML(m,o.content);if(!o.no_events){n.onSetContent.dispatch(n,o)}if(!n.settings.content_editable||document.activeElement===n.getBody()){n.selection.normalize()}return o.content},getContent:function(o){var n=this,p,m=n.getBody();o=o||{};o.format=o.format||"html";o.get=true;o.getInner=true;if(!o.no_events){n.onBeforeGetContent.dispatch(n,o)}if(o.format=="raw"){p=m.innerHTML}else{if(o.format=="text"){p=m.innerText||m.textContent}else{p=n.serializer.serialize(m,o)}}if(o.format!="text"){o.content=k.trim(p)}else{o.content=p}if(!o.no_events){n.onGetContent.dispatch(n,o)}return o.content},isDirty:function(){var m=this;return k.trim(m.startContent)!==k.trim(m.getContent({format:"raw"}))&&!m.isNotDirty},getContainer:function(){var m=this;if(!m.container){m.container=l.get(m.editorContainer||m.id+"_parent")}return m.container},getContentAreaContainer:function(){return this.contentAreaContainer},getElement:function(){return l.get(this.settings.content_element||this.id)},getWin:function(){var m=this,n;if(!m.contentWindow){n=l.get(m.id+"_ifr");if(n){m.contentWindow=n.contentWindow}}return m.contentWindow},getDoc:function(){var m=this,n;if(!m.contentDocument){n=m.getWin();if(n){m.contentDocument=n.document}}return m.contentDocument},getBody:function(){return this.bodyElement||this.getDoc().body},convertURL:function(o,n,q){var m=this,p=m.settings;if(p.urlconverter_callback){return m.execCallback("urlconverter_callback",o,q,true,n)}if(!p.convert_urls||(q&&q.nodeName=="LINK")||o.indexOf("file:")===0){return o}if(p.relative_urls){return m.documentBaseURI.toRelative(o)}o=m.documentBaseURI.toAbsolute(o,p.remove_script_host);return o},addVisual:function(q){var n=this,o=n.settings,p=n.dom,m;q=q||n.getBody();if(!d(n.hasVisual)){n.hasVisual=o.visual}i(p.select("table,a",q),function(s){var r;switch(s.nodeName){case"TABLE":m=o.visual_table_class||"mceItemTable";r=p.getAttrib(s,"border");if(!r||r=="0"){if(n.hasVisual){p.addClass(s,m)}else{p.removeClass(s,m)}}return;case"A":if(!p.getAttrib(s,"href",false)){r=p.getAttrib(s,"name")||s.id;m="mceItemAnchor";if(r){if(n.hasVisual){p.addClass(s,m)}else{p.removeClass(s,m)}}}return}});n.onVisualAid.dispatch(n,q,n.hasVisual)},remove:function(){var m=this,o=m.getContainer(),n=m.getDoc();if(!m.removed){m.removed=1;if(b&&n){n.execCommand("SelectAll")}m.save();l.setStyle(m.id,"display",m.orgDisplay);if(!m.settings.content_editable){j.unbind(m.getWin());j.unbind(m.getDoc())}j.unbind(m.getBody());j.clear(o);m.execCallback("remove_instance_callback",m);m.onRemove.dispatch(m);m.onExecCommand.listeners=[];k.remove(m);l.remove(o)}},destroy:function(n){var m=this;if(m.destroyed){return}if(a){j.unbind(m.getDoc());j.unbind(m.getWin());j.unbind(m.getBody())}if(!n){k.removeUnload(m.destroy);tinyMCE.onBeforeUnload.remove(m._beforeUnload);if(m.theme&&m.theme.destroy){m.theme.destroy()}m.controlManager.destroy();m.selection.destroy();m.dom.destroy()}if(m.formElement){m.formElement.submit=m.formElement._mceOldSubmit;m.formElement._mceOldSubmit=null}m.contentAreaContainer=m.formElement=m.container=m.settings.content_element=m.bodyElement=m.contentDocument=m.contentWindow=null;if(m.selection){m.selection=m.selection.win=m.selection.dom=m.selection.dom.doc=null}m.destroyed=1},_refreshContentEditable:function(){var n=this,m,o;if(n._isHidden()){m=n.getBody();o=m.parentNode;o.removeChild(m);o.appendChild(m);m.focus()}},_isHidden:function(){var m;if(!a){return 0}m=this.selection.getSel();return(!m||!m.rangeCount||m.rangeCount===0)}})})(tinymce);(function(a){var b=a.each;a.Editor.prototype.setupEvents=function(){var c=this,d=c.settings;b(["onPreInit","onBeforeRenderUI","onPostRender","onLoad","onInit","onRemove","onActivate","onDeactivate","onClick","onEvent","onMouseUp","onMouseDown","onDblClick","onKeyDown","onKeyUp","onKeyPress","onContextMenu","onSubmit","onReset","onPaste","onPreProcess","onPostProcess","onBeforeSetContent","onBeforeGetContent","onSetContent","onGetContent","onLoadContent","onSaveContent","onNodeChange","onChange","onBeforeExecCommand","onExecCommand","onUndo","onRedo","onVisualAid","onSetProgressState","onSetAttrib"],function(e){c[e]=new a.util.Dispatcher(c)});if(d.cleanup_callback){c.onBeforeSetContent.add(function(e,f){f.content=e.execCallback("cleanup_callback","insert_to_editor",f.content,f)});c.onPreProcess.add(function(e,f){if(f.set){e.execCallback("cleanup_callback","insert_to_editor_dom",f.node,f)}if(f.get){e.execCallback("cleanup_callback","get_from_editor_dom",f.node,f)}});c.onPostProcess.add(function(e,f){if(f.set){f.content=e.execCallback("cleanup_callback","insert_to_editor",f.content,f)}if(f.get){f.content=e.execCallback("cleanup_callback","get_from_editor",f.content,f)}})}if(d.save_callback){c.onGetContent.add(function(e,f){if(f.save){f.content=e.execCallback("save_callback",e.id,f.content,e.getBody())}})}if(d.handle_event_callback){c.onEvent.add(function(f,g,h){if(c.execCallback("handle_event_callback",g,f,h)===false){g.preventDefault();g.stopPropagation()}})}if(d.handle_node_change_callback){c.onNodeChange.add(function(f,e,g){f.execCallback("handle_node_change_callback",f.id,g,-1,-1,true,f.selection.isCollapsed())})}if(d.save_callback){c.onSaveContent.add(function(e,g){var f=e.execCallback("save_callback",e.id,g.content,e.getBody());if(f){g.content=f}})}if(d.onchange_callback){c.onChange.add(function(f,e){f.execCallback("onchange_callback",f,e)})}};a.Editor.prototype.bindNativeEvents=function(){var l=this,f,d=l.settings,e=l.dom,h;h={mouseup:"onMouseUp",mousedown:"onMouseDown",click:"onClick",keyup:"onKeyUp",keydown:"onKeyDown",keypress:"onKeyPress",submit:"onSubmit",reset:"onReset",contextmenu:"onContextMenu",dblclick:"onDblClick",paste:"onPaste"};function c(i,m){var n=i.type;if(l.removed){return}if(l.onEvent.dispatch(l,i,m)!==false){l[h[i.fakeType||i.type]].dispatch(l,i,m)}}function j(i){l.focus(true)}function k(i,m){if(m.keyCode!=65||!a.VK.metaKeyPressed(m)){l.selection.normalize()}l.nodeChanged()}b(h,function(m,n){var i=d.content_editable?l.getBody():l.getDoc();switch(n){case"contextmenu":e.bind(i,n,c);break;case"paste":e.bind(l.getBody(),n,c);break;case"submit":case"reset":e.bind(l.getElement().form||a.DOM.getParent(l.id,"form"),n,c);break;default:e.bind(i,n,c)}});e.bind(d.content_editable?l.getBody():(a.isGecko?l.getDoc():l.getWin()),"focus",function(i){l.focus(true)});if(d.content_editable&&a.isOpera){e.bind(l.getBody(),"click",j);e.bind(l.getBody(),"keydown",j)}l.onMouseUp.add(k);l.onKeyUp.add(function(i,n){var m=n.keyCode;if((m>=33&&m<=36)||(m>=37&&m<=40)||m==13||m==45||m==46||m==8||(a.isMac&&(m==91||m==93))||n.ctrlKey){k(i,n)}});l.onReset.add(function(){l.setContent(l.startContent,{format:"raw"})});function g(m,i){if(m.altKey||m.ctrlKey||m.metaKey){b(l.shortcuts,function(n){var o=a.isMac?m.metaKey:m.ctrlKey;if(n.ctrl!=o||n.alt!=m.altKey||n.shift!=m.shiftKey){return}if(m.keyCode==n.keyCode||(m.charCode&&m.charCode==n.charCode)){m.preventDefault();if(i){n.func.call(n.scope)}return true}})}}l.onKeyUp.add(function(i,m){g(m)});l.onKeyPress.add(function(i,m){g(m)});l.onKeyDown.add(function(i,m){g(m,true)});if(a.isOpera){l.onClick.add(function(i,m){m.preventDefault()})}}})(tinymce);(function(d){var e=d.each,b,a=true,c=false;d.EditorCommands=function(n){var m=n.dom,p=n.selection,j={state:{},exec:{},value:{}},k=n.settings,q=n.formatter,o;function r(z,y,x){var v;z=z.toLowerCase();if(v=j.exec[z]){v(z,y,x);return a}return c}function l(x){var v;x=x.toLowerCase();if(v=j.state[x]){return v(x)}return -1}function h(x){var v;x=x.toLowerCase();if(v=j.value[x]){return v(x)}return c}function u(v,x){x=x||"exec";e(v,function(z,y){e(y.toLowerCase().split(","),function(A){j[x][A]=z})})}d.extend(this,{execCommand:r,queryCommandState:l,queryCommandValue:h,addCommands:u});function f(y,x,v){if(x===b){x=c}if(v===b){v=null}return n.getDoc().execCommand(y,x,v)}function t(v){return q.match(v)}function s(v,x){q.toggle(v,x?{value:x}:b)}function i(v){o=p.getBookmark(v)}function g(){p.moveToBookmark(o)}u({"mceResetDesignMode,mceBeginUndoLevel":function(){},"mceEndUndoLevel,mceAddUndoLevel":function(){n.undoManager.add()},"Cut,Copy,Paste":function(z){var y=n.getDoc(),v;try{f(z)}catch(x){v=a}if(v||!y.queryCommandSupported(z)){if(d.isGecko){n.windowManager.confirm(n.getLang("clipboard_msg"),function(A){if(A){open("http://www.mozilla.org/editor/midasdemo/securityprefs.html","_blank")}})}else{n.windowManager.alert(n.getLang("clipboard_no_support"))}}},unlink:function(v){if(p.isCollapsed()){p.select(p.getNode())}f(v);p.collapse(c)},"JustifyLeft,JustifyCenter,JustifyRight,JustifyFull":function(v){var x=v.substring(7);e("left,center,right,full".split(","),function(y){if(x!=y){q.remove("align"+y)}});s("align"+x);r("mceRepaint")},"InsertUnorderedList,InsertOrderedList":function(y){var v,x;f(y);v=m.getParent(p.getNode(),"ol,ul");if(v){x=v.parentNode;if(/^(H[1-6]|P|ADDRESS|PRE)$/.test(x.nodeName)){i();m.split(x,v);g()}}},"Bold,Italic,Underline,Strikethrough,Superscript,Subscript":function(v){s(v)},"ForeColor,HiliteColor,FontName":function(y,x,v){s(y,v)},FontSize:function(z,y,x){var v,A;if(x>=1&&x<=7){A=d.explode(k.font_size_style_values);v=d.explode(k.font_size_classes);if(v){x=v[x-1]||x}else{x=A[x-1]||x}}s(z,x)},RemoveFormat:function(v){q.remove(v)},mceBlockQuote:function(v){s("blockquote")},FormatBlock:function(y,x,v){return s(v||"p")},mceCleanup:function(){var v=p.getBookmark();n.setContent(n.getContent({cleanup:a}),{cleanup:a});p.moveToBookmark(v)},mceRemoveNode:function(z,y,x){var v=x||p.getNode();if(v!=n.getBody()){i();n.dom.remove(v,a);g()}},mceSelectNodeDepth:function(z,y,x){var v=0;m.getParent(p.getNode(),function(A){if(A.nodeType==1&&v++==x){p.select(A);return c}},n.getBody())},mceSelectNode:function(y,x,v){p.select(v)},mceInsertContent:function(B,I,K){var y,J,E,z,F,G,D,C,L,x,A,M,v,H;y=n.parser;J=new d.html.Serializer({},n.schema);v='\uFEFF';G={content:K,format:"html"};p.onBeforeSetContent.dispatch(p,G);K=G.content;if(K.indexOf("{$caret}")==-1){K+="{$caret}"}K=K.replace(/\{\$caret\}/,v);if(!p.isCollapsed()){n.getDoc().execCommand("Delete",false,null)}E=p.getNode();G={context:E.nodeName.toLowerCase()};F=y.parse(K,G);A=F.lastChild;if(A.attr("id")=="mce_marker"){D=A;for(A=A.prev;A;A=A.walk(true)){if(A.type==3||!m.isBlock(A.name)){A.parent.insert(D,A,A.name==="br");break}}}if(!G.invalid){K=J.serialize(F);A=E.firstChild;M=E.lastChild;if(!A||(A===M&&A.nodeName==="BR")){m.setHTML(E,K)}else{p.setContent(K)}}else{p.setContent(v);E=p.getNode();z=n.getBody();if(E.nodeType==9){E=A=z}else{A=E}while(A!==z){E=A;A=A.parentNode}K=E==z?z.innerHTML:m.getOuterHTML(E);K=J.serialize(y.parse(K.replace(//i,function(){return J.serialize(F)})));if(E==z){m.setHTML(z,K)}else{m.setOuterHTML(E,K)}}D=m.get("mce_marker");C=m.getRect(D);L=m.getViewPort(n.getWin());if((C.y+C.h>L.y+L.h||C.yL.x+L.w||C.x")},mceToggleVisualAid:function(){n.hasVisual=!n.hasVisual;n.addVisual()},mceReplaceContent:function(y,x,v){n.execCommand("mceInsertContent",false,v.replace(/\{\$selection\}/g,p.getContent({format:"text"})))},mceInsertLink:function(z,y,x){var v;if(typeof(x)=="string"){x={href:x}}v=m.getParent(p.getNode(),"a");x.href=x.href.replace(" ","%20");if(!v||!x.href){q.remove("link")}if(x.href){q.apply("link",x,v)}},selectAll:function(){var x=m.getRoot(),v=m.createRng();if(p.getRng().setStart){v.setStart(x,0);v.setEnd(x,x.childNodes.length);p.setRng(v)}else{f("SelectAll")}}});u({"JustifyLeft,JustifyCenter,JustifyRight,JustifyFull":function(z){var x="align"+z.substring(7);var v=p.isCollapsed()?[m.getParent(p.getNode(),m.isBlock)]:p.getSelectedBlocks();var y=d.map(v,function(A){return !!q.matchNode(A,x)});return d.inArray(y,a)!==-1},"Bold,Italic,Underline,Strikethrough,Superscript,Subscript":function(v){return t(v)},mceBlockQuote:function(){return t("blockquote")},Outdent:function(){var v;if(k.inline_styles){if((v=m.getParent(p.getStart(),m.isBlock))&&parseInt(v.style.paddingLeft)>0){return a}if((v=m.getParent(p.getEnd(),m.isBlock))&&parseInt(v.style.paddingLeft)>0){return a}}return l("InsertUnorderedList")||l("InsertOrderedList")||(!k.inline_styles&&!!m.getParent(p.getNode(),"BLOCKQUOTE"))},"InsertUnorderedList,InsertOrderedList":function(x){var v=m.getParent(p.getNode(),"ul,ol");return v&&(x==="insertunorderedlist"&&v.tagName==="UL"||x==="insertorderedlist"&&v.tagName==="OL")}},"state");u({"FontSize,FontName":function(y){var x=0,v;if(v=m.getParent(p.getNode(),"span")){if(y=="fontsize"){x=v.style.fontSize}else{x=v.style.fontFamily.replace(/, /g,",").replace(/[\'\"]/g,"").toLowerCase()}}return x}},"value");u({Undo:function(){n.undoManager.undo()},Redo:function(){n.undoManager.redo()}})}})(tinymce);(function(b){var a=b.util.Dispatcher;b.UndoManager=function(h){var l,i=0,e=[],g,k,j,f;function c(){return b.trim(h.getContent({format:"raw",no_events:1}).replace(/]+data-mce-bogus[^>]+>[\u200B\uFEFF]+<\/span>/g,""))}function d(){l.typing=false;l.add()}onBeforeAdd=new a(l);k=new a(l);j=new a(l);f=new a(l);k.add(function(m,n){if(m.hasUndo()){return h.onChange.dispatch(h,n,m)}});j.add(function(m,n){return h.onUndo.dispatch(h,n,m)});f.add(function(m,n){return h.onRedo.dispatch(h,n,m)});h.onInit.add(function(){l.add()});h.onBeforeExecCommand.add(function(m,p,o,q,n){if(p!="Undo"&&p!="Redo"&&p!="mceRepaint"&&(!n||!n.skip_undo)){l.beforeChange()}});h.onExecCommand.add(function(m,p,o,q,n){if(p!="Undo"&&p!="Redo"&&p!="mceRepaint"&&(!n||!n.skip_undo)){l.add()}});h.onSaveContent.add(d);h.dom.bind(h.dom.getRoot(),"dragend",d);h.dom.bind(h.getBody(),"focusout",function(m){if(!h.removed&&l.typing){d()}});h.onKeyUp.add(function(m,o){var n=o.keyCode;if((n>=33&&n<=36)||(n>=37&&n<=40)||n==45||n==13||o.ctrlKey){d()}});h.onKeyDown.add(function(m,o){var n=o.keyCode;if((n>=33&&n<=36)||(n>=37&&n<=40)||n==45){if(l.typing){d()}return}if((n<16||n>20)&&n!=224&&n!=91&&!l.typing){l.beforeChange();l.typing=true;l.add()}});h.onMouseDown.add(function(m,n){if(l.typing){d()}});h.addShortcut("ctrl+z","undo_desc","Undo");h.addShortcut("ctrl+y","redo_desc","Redo");l={data:e,typing:false,onBeforeAdd:onBeforeAdd,onAdd:k,onUndo:j,onRedo:f,beforeChange:function(){g=h.selection.getBookmark(2,true)},add:function(p){var m,n=h.settings,o;p=p||{};p.content=c();l.onBeforeAdd.dispatch(l,p);o=e[i];if(o&&o.content==p.content){return null}if(e[i]){e[i].beforeBookmark=g}if(n.custom_undo_redo_levels){if(e.length>n.custom_undo_redo_levels){for(m=0;m0){n=e[--i];h.setContent(n.content,{format:"raw"});h.selection.moveToBookmark(n.beforeBookmark);l.onUndo.dispatch(l,n)}return n},redo:function(){var m;if(i0||this.typing},hasRedo:function(){return i0){g.moveEnd("character",q)}g.select()}catch(n){}}}c.nodeChanged()}}if(b.forced_root_block){c.onKeyUp.add(f);c.onNodeChange.add(f)}};(function(c){var b=c.DOM,a=c.dom.Event,d=c.each,e=c.extend;c.create("tinymce.ControlManager",{ControlManager:function(f,j){var h=this,g;j=j||{};h.editor=f;h.controls={};h.onAdd=new c.util.Dispatcher(h);h.onPostRender=new c.util.Dispatcher(h);h.prefix=j.prefix||f.id+"_";h._cls={};h.onPostRender.add(function(){d(h.controls,function(i){i.postRender()})})},get:function(f){return this.controls[this.prefix+f]||this.controls[f]},setActive:function(h,f){var g=null;if(g=this.get(h)){g.setActive(f)}return g},setDisabled:function(h,f){var g=null;if(g=this.get(h)){g.setDisabled(f)}return g},add:function(g){var f=this;if(g){f.controls[g.id]=g;f.onAdd.dispatch(g,f)}return g},createControl:function(j){var o,k,g,h=this,m=h.editor,n,f;if(!h.controlFactories){h.controlFactories=[];d(m.plugins,function(i){if(i.createControl){h.controlFactories.push(i)}})}n=h.controlFactories;for(k=0,g=n.length;k1||ae==ax||ae.tagName=="BR"){return ae}}}var ap=Z.selection.getRng();var au=ap.startContainer;var ao=ap.endContainer;if(au!=ao&&ap.endOffset===0){var at=aq(au,ao);var ar=at.nodeType==3?at.length:at.childNodes.length;ap.setEnd(at,ar)}return ap}function ah(ao){var aq=-1;var ap;S(ao.childNodes,function(at,ar){if(at.nodeName==="UL"||at.nodeName==="OL"){aq=ar;ap=at;return false}});return{listIndex:aq,list:ap}}function al(ap,ao){var ar=-1;var aq=-1;S(ap.childNodes,function(au,at){if(au.nodeName==="SPAN"&&c.getAttrib(au,"data-mce-type")=="bookmark"){if(au.id==ao.id+"_start"){ar=at}else{if(au.id==ao.id+"_end"){aq=at}}}});return{startIndex:ar,endIndex:aq}}function am(ap,ar,av){var ao=[],au,aq,at=true;au=ak.inline||ak.block;aq=c.create(au);aa(aq);M.walk(ap,function(aw){var ax;function ay(aA){var aF,aD,aB,aC,aE;aE=at;aF=aA.nodeName.toLowerCase();aD=aA.parentNode.nodeName.toLowerCase();if(aA.nodeType===1&&x(aA)){aE=at;at=x(aA)==="true";aC=true}if(f(aF,"br")){ax=0;if(ak.block){c.remove(aA)}return}if(ak.wrapper&&y(aA,ac,aj)){ax=0;return}if(at&&!aC&&ak.block&&!ak.wrapper&&H(aF)){aA=c.rename(aA,au);aa(aA);ao.push(aA);ax=0;return}if(ak.selector){S(af,function(aG){if("collapsed" in aG&&aG.collapsed!==ag){return}if(c.is(aA,aG.selector)&&!b(aA)){aa(aA,aG);aB=true}});if(!ak.inline||aB){ax=0;return}}function az(aG){return aG.nodeType===3&&aG.nodeValue.length===1&&aG.nodeValue.charCodeAt(0)===65279}if(at&&!aC&&k(au,aF)&&k(aD,au)&&!(!av&&az(aA))&&!b(aA)&&(!ak.inline||!G(aA))){if(!ax){ax=c.clone(aq,W);aA.parentNode.insertBefore(ax,aA);ao.push(ax)}ax.appendChild(aA)}else{ax=0;S(a.grep(aA.childNodes),ay);if(aC){at=aE}ax=0}}S(aw,ay)});if(ak.wrap_links===false){S(ao,function(aw){function ax(aB){var aA,az,ay;if(aB.nodeName==="A"){az=c.clone(aq,W);ao.push(az);ay=a.grep(aB.childNodes);for(aA=0;aA1||!G(ay))&&aw===0){c.remove(ay,1);return}if(ak.inline||ak.wrapper){if(!ak.exact&&aw===1){ay=ax(ay)}S(af,function(aA){S(c.select(aA.inline,ay),function(aC){var aB;if(aA.wrap_links===false){aB=aC.parentNode;do{if(aB.nodeName==="A"){return}aB=aB.parentNode}while(aB)}Y(aA,aj,aC,aA.exact?aC:null)})});if(y(ay.parentNode,ac,aj)){c.remove(ay,1);ay=0;return B}if(ak.merge_with_parents){c.getParent(ay.parentNode,function(aA){if(y(aA,ac,aj)){c.remove(ay,1);ay=0;return B}})}if(ay&&ak.merge_siblings!==false){ay=u(D(ay),ay);ay=u(ay,D(ay,B))}}})}if(ak){if(ae){if(ae.nodeType){ab=c.createRng();ab.setStartBefore(ae);ab.setEndAfter(ae);am(p(ab,af),null,true)}else{am(ae,null,true)}}else{if(!ag||!ak.inline||c.select("td.mceSelected,th.mceSelected").length){var an=Z.selection.getNode();if(!m&&af[0].defaultBlock&&!c.getParent(an,c.isBlock)){X(af[0].defaultBlock)}Z.selection.setRng(ad());ai=r.getBookmark();am(p(r.getRng(B),af),ai);if(ak.styles&&(ak.styles.color||ak.styles.textDecoration)){a.walk(an,K,"childNodes");K(an)}r.moveToBookmark(ai);Q(r.getRng(B));Z.nodeChanged()}else{T("apply",ac,aj)}}}}function A(ac,aj,ae){var af=U(ac),am=af[0],ai,ab,ak=true;function ad(ar){var aq,ap,ao,au,at;if(ar.nodeType===3){return}if(ar.nodeType===1&&x(ar)){au=ak;ak=x(ar)==="true";at=true}aq=a.grep(ar.childNodes);if(ak&&!at){for(ap=0,ao=af.length;ap=0;ab--){aa=ag[ab].selector;if(!aa){return B}for(af=ac.length-1;af>=0;af--){if(c.is(ac[af],aa)){return B}}}}return W}function I(aa,ad,ab){var ac;if(!O){O={};ac={};Z.onNodeChange.addToTop(function(af,ae,ah){var ag=n(ah),ai={};S(O,function(aj,ak){S(ag,function(al){if(y(al,ak,{},aj.similar)){if(!ac[ak]){S(aj,function(am){am(true,{node:al,format:ak,parents:ag})});ac[ak]=aj}ai[ak]=aj;return false}})});S(ac,function(aj,ak){if(!ai[ak]){delete ac[ak];S(aj,function(al){al(false,{node:ah,format:ak,parents:ag})})}})})}S(aa.split(","),function(ae){if(!O[ae]){O[ae]=[];O[ae].similar=ab}O[ae].push(ad)});return this}a.extend(this,{get:U,register:l,apply:X,remove:A,toggle:E,match:j,matchAll:v,matchNode:y,canApply:z,formatChanged:I});i();V();function g(aa,ab){if(f(aa,ab.inline)){return B}if(f(aa,ab.block)){return B}if(ab.selector){return c.is(aa,ab.selector)}}function f(ab,aa){ab=ab||"";aa=aa||"";ab=""+(ab.nodeName||ab);aa=""+(aa.nodeName||aa);return ab.toLowerCase()==aa.toLowerCase()}function N(ab,aa){var ac=c.getStyle(ab,aa);if(aa=="color"||aa=="backgroundColor"){ac=c.toHex(ac)}if(aa=="fontWeight"&&ac==700){ac="bold"}return""+ac}function q(aa,ab){if(typeof(aa)!="string"){aa=aa(ab)}else{if(ab){aa=aa.replace(/%(\w+)/g,function(ad,ac){return ab[ac]||ad})}}return aa}function e(aa){return aa&&aa.nodeType===3&&/^([\t \r\n]+|)$/.test(aa.nodeValue)}function R(ac,ab,aa){var ad=c.create(ab,aa);ac.parentNode.insertBefore(ad,ac);ad.appendChild(ac);return ad}function p(aa,al,ad){var am,ag,ak,ac=aa.startContainer,ah=aa.startOffset,ap=aa.endContainer,aj=aa.endOffset;function an(ax){var ar,av,au,at,aq;ar=av=ax?ac:ap;at=ax?"previousSibling":"nextSibling";aq=c.getRoot();function aw(ay){return ay.nodeName=="BR"&&ay.getAttribute("data-mce-bogus")&&!ay.nextSibling}if(ar.nodeType==3&&!e(ar)){if(ax?ah>0:ajam?am:ah];if(ac&&ac.nodeType==3){ah=0}}if(ap.nodeType==1&&ap.hasChildNodes()){am=ap.childNodes.length-1;ap=ap.childNodes[aj>am?am:aj-1];if(ap&&ap.nodeType==3){aj=ap.nodeValue.length}}function ao(ar){var aq=ar;while(aq){if(aq.nodeType===1&&x(aq)){return x(aq)==="false"?aq:ar}aq=aq.parentNode}return ar}function ai(ar,aw,ay){var av,at,ax,aq;function au(aA,aC){var aD,az,aB=aA.nodeValue;if(typeof(aC)=="undefined"){aC=ay?aB.length:0}if(ay){aD=aB.lastIndexOf(" ",aC);az=aB.lastIndexOf("\u00a0",aC);aD=aD>az?aD:az;if(aD!==-1&&!ad){aD++}}else{aD=aB.indexOf(" ",aC);az=aB.indexOf("\u00a0",aC);aD=aD!==-1&&(az===-1||aD0&&ag.node.nodeType===3&&ag.node.nodeValue.charAt(ag.offset-1)===" "){if(ag.offset>1){ap=ag.node;ap.splitText(ag.offset-1)}}}}if(al[0].inline||al[0].block_expand){if(!al[0].inline||(ac.nodeType!=3||ah===0)){ac=an(true)}if(!al[0].inline||(ap.nodeType!=3||aj===ap.nodeValue.length)){ap=an()}}if(al[0].selector&&al[0].expand!==W&&!al[0].inline){ac=ae(ac,"previousSibling");ap=ae(ap,"nextSibling")}if(al[0].block||al[0].selector){ac=ab(ac,"previousSibling");ap=ab(ap,"nextSibling");if(al[0].block){if(!G(ac)){ac=an(true)}if(!G(ap)){ap=an()}}}if(ac.nodeType==1){ah=s(ac);ac=ac.parentNode}if(ap.nodeType==1){aj=s(ap)+1;ap=ap.parentNode}return{startContainer:ac,startOffset:ah,endContainer:ap,endOffset:aj}}function Y(ag,af,ad,aa){var ac,ab,ae;if(!g(ad,ag)){return W}if(ag.remove!="all"){S(ag.styles,function(ai,ah){ai=q(ai,af);if(typeof(ah)==="number"){ah=ai;aa=0}if(!aa||f(N(aa,ah),ai)){c.setStyle(ad,ah,"")}ae=1});if(ae&&c.getAttrib(ad,"style")===""){ad.removeAttribute("style");ad.removeAttribute("data-mce-style")}S(ag.attributes,function(aj,ah){var ai;aj=q(aj,af);if(typeof(ah)==="number"){ah=aj;aa=0}if(!aa||f(c.getAttrib(aa,ah),aj)){if(ah=="class"){aj=c.getAttrib(ad,ah);if(aj){ai="";S(aj.split(/\s+/),function(ak){if(/mce\w+/.test(ak)){ai+=(ai?" ":"")+ak}});if(ai){c.setAttrib(ad,ah,ai);return}}}if(ah=="class"){ad.removeAttribute("className")}if(d.test(ah)){ad.removeAttribute("data-mce-"+ah)}ad.removeAttribute(ah)}});S(ag.classes,function(ah){ah=q(ah,af);if(!aa||c.hasClass(aa,ah)){c.removeClass(ad,ah)}});ab=c.getAttribs(ad);for(ac=0;acac?ac:ad]}if(aa.nodeType===3&&ae&&ad>=aa.nodeValue.length){aa=new t(aa,Z.getBody()).next()||aa}if(aa.nodeType===3&&!ae&&ad===0){aa=new t(aa,Z.getBody()).prev()||aa}return aa}function T(ak,aa,ai){var am="_mce_caret",ab=Z.settings.caret_debug;function ac(aq){var ap=c.create("span",{id:am,"data-mce-bogus":true,style:ab?"color:red":""});if(aq){ap.appendChild(Z.getDoc().createTextNode(F))}return ap}function aj(aq,ap){while(aq){if((aq.nodeType===3&&aq.nodeValue!==F)||aq.childNodes.length>1){return false}if(ap&&aq.nodeType===1){ap.push(aq)}aq=aq.firstChild}return true}function af(ap){while(ap){if(ap.id===am){return ap}ap=ap.parentNode}}function ae(ap){var aq;if(ap){aq=new t(ap,ap);for(ap=aq.current();ap;ap=aq.next()){if(ap.nodeType===3){return ap}}}}function ad(ar,aq){var at,ap;if(!ar){ar=af(r.getStart());if(!ar){while(ar=c.get(am)){ad(ar,false)}}}else{ap=r.getRng(true);if(aj(ar)){if(aq!==false){ap.setStartBefore(ar);ap.setEndBefore(ar)}c.remove(ar)}else{at=ae(ar);if(at.nodeValue.charAt(0)===F){at=at.deleteData(0,1)}c.remove(ar,1)}r.setRng(ap)}}function al(aq){var ap=aq.nodeName.toLowerCase();switch(ap){case"html","#document":return false;case"body":return true;default:return al(aq.parentNode)}}function ag(ap){return al(ap.startContainer)||al(ap.endContainer)}function ah(){var ar,ap,aw,av,at,aq,au;ar=r.getRng(true);av=ar.startOffset;aq=ar.startContainer;au=aq.nodeValue;ap=af(r.getStart());if(ap){aw=ae(ap)}if(au&&av>0&&av=0;av--){ar.appendChild(c.clone(az[av],false));ar=ar.firstChild}ar.appendChild(c.doc.createTextNode(F));ar=ar.firstChild;var at=c.getParent(aA,H);if(at&&c.isEmpty(at)){aA.parentNode.replaceChild(ay,aA)}else{c.insertAfter(ay,aA)}r.setCursorLocation(ar,1);if(c.isEmpty(aA)){c.remove(aA)}}}function ao(){var ap;ap=af(r.getStart());if(ap&&!c.isEmpty(ap)){a.walk(ap,function(aq){if(aq.nodeType==1&&aq.id!==am&&!c.isEmpty(aq)){c.setAttrib(aq,"data-mce-bogus",null)}},"childNodes")}}if(!Z._hasCaretEvents){Z.onBeforeGetContent.addToTop(function(){var ap=[],aq;if(aj(af(r.getStart()),ap)){aq=ap.length;while(aq--){c.setAttrib(ap[aq],"data-mce-bogus","1")}}});a.each("onMouseUp onKeyUp".split(" "),function(ap){Z[ap].addToTop(function(){ad();ao()})});Z.onKeyDown.addToTop(function(ap,ar){var aq=ar.keyCode;if(aq==8||aq==37||aq==39){ad(af(r.getStart()))}ao()});r.onSetContent.add(ao);Z._hasCaretEvents=true}if(ak=="apply"){ah()}else{an()}}function Q(ab){var aa=ab.startContainer,ah=ab.startOffset,ad,ag,af,ac,ae;if(aa.nodeType==3&&ah>=aa.nodeValue.length){ah=s(aa);aa=aa.parentNode;ad=true}if(aa.nodeType==1){ac=aa.childNodes;aa=ac[Math.min(ah,ac.length-1)];ag=new t(aa,c.getParent(aa,c.isBlock));if(ah>ac.length-1||ad){ag.next()}for(af=ag.current();af;af=ag.next()){if(af.nodeType==3&&!e(af)){ae=c.create("a",null,F);af.parentNode.insertBefore(ae,af);ab.setStart(af,0);r.setRng(ab);c.remove(ae);return}}}}}})(tinymce);tinymce.onAddEditor.add(function(e,a){var d,h,g,c=a.settings;function b(j,i){e.each(i,function(l,k){if(l){g.setStyle(j,k,l)}});g.rename(j,"span")}function f(i,j){g=i.dom;if(c.convert_fonts_to_spans){e.each(g.select("font,u,strike",j.node),function(k){d[k.nodeName.toLowerCase()](a.dom,k)})}}if(c.inline_styles){h=e.explode(c.font_size_legacy_values);d={font:function(j,i){b(i,{backgroundColor:i.style.backgroundColor,color:i.color,fontFamily:i.face,fontSize:h[parseInt(i.size,10)-1]})},u:function(j,i){b(i,{textDecoration:"underline"})},strike:function(j,i){b(i,{textDecoration:"line-through"})}};a.onPreProcess.add(f);a.onSetContent.add(f);a.onInit.add(function(){a.selection.onSetContent.add(f)})}});(function(b){var a=b.dom.TreeWalker;b.EnterKey=function(f){var i=f.dom,e=f.selection,d=f.settings,h=f.undoManager,c=f.schema.getNonEmptyElements();function g(B){var v=e.getRng(true),G,j,A,u,p,M,C,o,k,n,t,J,x,D;function E(N){return N&&i.isBlock(N)&&!/^(TD|TH|CAPTION|FORM)$/.test(N.nodeName)&&!/^(fixed|absolute)/i.test(N.style.position)&&i.getContentEditable(N)!=="true"}function F(O){var N;if(b.isIE&&!b.isIE11&&i.isBlock(O)){N=e.getRng();O.appendChild(i.create("span",null,"\u00a0"));e.select(O);O.lastChild.outerHTML="";e.setRng(N)}}function z(P){var O=P,Q=[],N;while(O=O.firstChild){if(i.isBlock(O)){return}if(O.nodeType==1&&!c[O.nodeName.toLowerCase()]){Q.push(O)}}N=Q.length;while(N--){O=Q[N];if(!O.hasChildNodes()||(O.firstChild==O.lastChild&&O.firstChild.nodeValue==="")){i.remove(O)}else{if(O.nodeName=="A"&&(O.innerText||O.textContent)===" "){i.remove(O)}}}}function m(O){var T,R,N,U,S,Q=O,P;N=i.createRng();if(O.hasChildNodes()){T=new a(O,O);while(R=T.current()){if(R.nodeType==3){N.setStart(R,0);N.setEnd(R,0);break}if(c[R.nodeName.toLowerCase()]){N.setStartBefore(R);N.setEndBefore(R);break}Q=R;R=T.next()}if(!R){N.setStart(Q,0);N.setEnd(Q,0)}}else{if(O.nodeName=="BR"){if(O.nextSibling&&i.isBlock(O.nextSibling)){if(!M||M<9){P=i.create("br");O.parentNode.insertBefore(P,O)}N.setStartBefore(O);N.setEndBefore(O)}else{N.setStartAfter(O);N.setEndAfter(O)}}else{N.setStart(O,0);N.setEnd(O,0)}}e.setRng(N);i.remove(P);S=i.getViewPort(f.getWin());U=i.getPos(O).y;if(US.y+S.h){f.getWin().scrollTo(0,U'}return R}function q(Q){var P,O,N;if(A.nodeType==3&&(Q?u>0:u0){return true}}}function L(){var P,O,N;if(A&&A.nodeType==3&&u>=A.nodeValue.length){if((!b.isIE||b.isIE11)&&!y()){P=i.create("br");v.insertNode(P);v.setStartAfter(P);v.setEndAfter(P);O=true}}P=i.create("br");v.insertNode(P);if((b.isIE&&!b.isIE11)&&t=="PRE"&&(!M||M<8)){P.parentNode.insertBefore(i.doc.createTextNode("\r"),P)}N=i.create("span",{}," ");P.parentNode.insertBefore(N,P);e.scrollIntoView(N);i.remove(N);if(!O){v.setStartAfter(P);v.setEndAfter(P)}else{v.setStartBefore(P);v.setEndBefore(P)}e.setRng(v);h.add()}function s(N){do{if(N.nodeType===3){N.nodeValue=N.nodeValue.replace(/^[\r\n]+/,"")}N=N.firstChild}while(N)}function K(P){var N=i.getRoot(),O,Q;O=P;while(O!==N&&i.getContentEditable(O)!=="false"){if(i.getContentEditable(O)==="true"){Q=O}O=O.parentNode}return O!==N?Q:N}function I(O){var N;if(!b.isIE||b.isIE11){O.normalize();N=O.lastChild;if(!N||(/^(left|right)$/gi.test(i.getStyle(N,"float",true)))){i.add(O,"br")}}}if(!v.collapsed){f.execCommand("Delete");return}if(B.isDefaultPrevented()){return}A=v.startContainer;u=v.startOffset;x=(d.force_p_newlines?"p":"")||d.forced_root_block;x=x?x.toUpperCase():"";M=i.doc.documentMode;C=B.shiftKey;if(A.nodeType==1&&A.hasChildNodes()){D=u>A.childNodes.length-1;A=A.childNodes[Math.min(u,A.childNodes.length-1)]||A;if(D&&A.nodeType==3){u=A.nodeValue.length}else{u=0}}j=K(A);if(!j){return}h.beforeChange();if(!i.isBlock(j)&&j!=i.getRoot()){if(!x||C){L()}return}if((x&&!C)||(!x&&C)){A=l(A,u)}p=i.getParent(A,i.isBlock);n=p?i.getParent(p.parentNode,i.isBlock):null;t=p?p.nodeName.toUpperCase():"";J=n?n.nodeName.toUpperCase():"";if(J=="LI"&&!B.ctrlKey){p=n;t=J}if(t=="LI"){if(!x&&C){L();return}if(i.isEmpty(p)){if(/^(UL|OL|LI)$/.test(n.parentNode.nodeName)){return false}H();return}}if(t=="PRE"&&d.br_in_pre!==false){if(!C){L();return}}else{if((!x&&!C&&t!="LI")||(x&&C)){L();return}}x=x||"P";if(q()){if(/^(H[1-6]|PRE)$/.test(t)&&J!="HGROUP"){o=r(x)}else{o=r()}if(d.end_container_on_empty_block&&E(n)&&i.isEmpty(p)){o=i.split(n,p)}else{i.insertAfter(o,p)}m(o)}else{if(q(true)){o=p.parentNode.insertBefore(r(),p);F(o)}else{G=v.cloneRange();G.setEndAfter(p);k=G.extractContents();s(k);o=k.firstChild;i.insertAfter(k,p);z(o);I(p);m(o)}}i.setAttrib(o,"id","");h.add()}f.onKeyDown.add(function(k,j){if(j.keyCode==13){if(g(j)!==false){j.preventDefault()}}})}})(tinymce); \ No newline at end of file +(function(e){var a=/^\s*|\s*$/g,b,d="B".replace(/A(.)|B/,"$1")==="$1";var c={majorVersion:"3",minorVersion:"5.11",releaseDate:"2014-05-08",_init:function(){var s=this,q=document,o=navigator,g=o.userAgent,m,f,l,k,j,r;s.isIE11=g.indexOf("Trident/")!=-1&&(g.indexOf("rv:")!=-1||o.appName.indexOf("Netscape")!=-1);s.isOpera=e.opera&&opera.buildNumber;s.isWebKit=/WebKit/.test(g);s.isIE=!s.isWebKit&&!s.isOpera&&(/MSIE/gi).test(g)&&(/Explorer/gi).test(o.appName)||s.isIE11;s.isIE6=s.isIE&&/MSIE [56]/.test(g);s.isIE7=s.isIE&&/MSIE [7]/.test(g);s.isIE8=s.isIE&&/MSIE [8]/.test(g);s.isIE9=s.isIE&&/MSIE [9]/.test(g);s.isGecko=!s.isWebKit&&!s.isIE11&&/Gecko/.test(g);s.isMac=g.indexOf("Mac")!=-1;s.isAir=/adobeair/i.test(g);s.isIDevice=/(iPad|iPhone)/.test(g);s.isIOS5=s.isIDevice&&g.match(/AppleWebKit\/(\d*)/)[1]>=534;if(e.tinyMCEPreInit){s.suffix=tinyMCEPreInit.suffix;s.baseURL=tinyMCEPreInit.base;s.query=tinyMCEPreInit.query;return}s.suffix="";f=q.getElementsByTagName("base");for(m=0;m0?b:[f.scope]);if(e===false){break}}a.inDispatch=false;return e}});(function(){var a=tinymce.each;tinymce.create("tinymce.util.URI",{URI:function(e,g){var f=this,i,d,c,h;e=tinymce.trim(e);g=f.settings=g||{};if(/^([\w\-]+):([^\/]{2})/i.test(e)||/^\s*#/.test(e)){f.source=e;return}if(e.indexOf("/")===0&&e.indexOf("//")!==0){e=(g.base_uri?g.base_uri.protocol||"http":"http")+"://mce_host"+e}if(!/^[\w\-]*:?\/\//.test(e)){h=g.base_uri?g.base_uri.path:new tinymce.util.URI(location.href).directory;e=((g.base_uri&&g.base_uri.protocol)||"http")+"://mce_host"+f.toAbsPath(h,e)}e=e.replace(/@@/g,"(mce_at)");e=/^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@\/]*):?([^:@\/]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/.exec(e);a(["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],function(b,j){var k=e[j];if(k){k=k.replace(/\(mce_at\)/g,"@@")}f[b]=k});c=g.base_uri;if(c){if(!f.protocol){f.protocol=c.protocol}if(!f.userInfo){f.userInfo=c.userInfo}if(!f.port&&f.host==="mce_host"){f.port=c.port}if(!f.host||f.host==="mce_host"){f.host=c.host}f.source=""}},setPath:function(c){var b=this;c=/^(.*?)\/?(\w+)?$/.exec(c);b.path=c[0];b.directory=c[1];b.file=c[2];b.source="";b.getURI()},toRelative:function(b){var d=this,f;if(b==="./"){return b}b=new tinymce.util.URI(b,{base_uri:d});if((b.host!="mce_host"&&d.host!=b.host&&b.host)||d.port!=b.port||d.protocol!=b.protocol){return b.getURI()}var c=d.getURI(),e=b.getURI();if(c==e||(c.charAt(c.length-1)=="/"&&c.substr(0,c.length-1)==e)){return c}f=d.toRelPath(d.path,b.path);if(b.query){f+="?"+b.query}if(b.anchor){f+="#"+b.anchor}return f},toAbsolute:function(b,c){b=new tinymce.util.URI(b,{base_uri:this});return b.getURI(this.host==b.host&&this.protocol==b.protocol?c:0)},toRelPath:function(g,h){var c,f=0,d="",e,b;g=g.substring(0,g.lastIndexOf("/"));g=g.split("/");c=h.split("/");if(g.length>=c.length){for(e=0,b=g.length;e=c.length||g[e]!=c[e]){f=e+1;break}}}if(g.length=g.length||g[e]!=c[e]){f=e+1;break}}}if(f===1){return h}for(e=0,b=g.length-(f-1);e=0;c--){if(f[c].length===0||f[c]==="."){continue}if(f[c]===".."){b++;continue}if(b>0){b--;continue}h.push(f[c])}c=e.length-b;if(c<=0){g=h.reverse().join("/")}else{g=e.slice(0,c).join("/")+"/"+h.reverse().join("/")}if(g.indexOf("/")!==0){g="/"+g}if(d&&g.lastIndexOf("/")!==g.length-1){g+=d}return g},getURI:function(d){var c,b=this;if(!b.source||d){c="";if(!d){if(b.protocol){c+=b.protocol+"://"}if(b.userInfo){c+=b.userInfo+"@"}if(b.host){c+=b.host}if(b.port){c+=":"+b.port}}if(b.path){c+=b.path}if(b.query){c+="?"+b.query}if(b.anchor){c+="#"+b.anchor}b.source=c}return b.source}})})();(function(){var a=tinymce.each;tinymce.create("static tinymce.util.Cookie",{getHash:function(d){var b=this.get(d),c;if(b){a(b.split("&"),function(e){e=e.split("=");c=c||{};c[unescape(e[0])]=unescape(e[1])})}return c},setHash:function(j,b,g,f,i,c){var h="";a(b,function(e,d){h+=(!h?"":"&")+escape(d)+"="+escape(e)});this.set(j,h,g,f,i,c)},get:function(i){var h=document.cookie,g,f=i+"=",d;if(!h){return}d=h.indexOf("; "+f);if(d==-1){d=h.indexOf(f);if(d!==0){return null}}else{d+=2}g=h.indexOf(";",d);if(g==-1){g=h.length}return unescape(h.substring(d+f.length,g))},set:function(i,b,g,f,h,c){document.cookie=i+"="+escape(b)+((g)?"; expires="+g.toGMTString():"")+((f)?"; path="+escape(f):"")+((h)?"; domain="+h:"")+((c)?"; secure":"")},remove:function(c,e,d){var b=new Date();b.setTime(b.getTime()-1000);this.set(c,"",b,e,d)}})})();(function(){function serialize(o,quote){var i,v,t,name;quote=quote||'"';if(o==null){return"null"}t=typeof o;if(t=="string"){v="\bb\tt\nn\ff\rr\"\"''\\\\";return quote+o.replace(/([\u0080-\uFFFF\x00-\x1f\"\'\\])/g,function(a,b){if(quote==='"'&&a==="'"){return a}i=v.indexOf(b);if(i+1){return"\\"+v.charAt(i+1)}a=b.charCodeAt().toString(16);return"\\u"+"0000".substring(a.length)+a})+quote}if(t=="object"){if(o.hasOwnProperty&&Object.prototype.toString.call(o)==="[object Array]"){for(i=0,v="[";i0?",":"")+serialize(o[i],quote)}return v+"]"}v="{";for(name in o){if(o.hasOwnProperty(name)){v+=typeof o[name]!="function"?(v.length>1?","+quote:quote)+name+quote+":"+serialize(o[name],quote):""}}return v+"}"}return""+o}tinymce.util.JSON={serialize:serialize,parse:function(s){try{return eval("("+s+")")}catch(ex){}}}})();tinymce.create("static tinymce.util.XHR",{send:function(g){var a,e,b=window,h=0;function f(){if(!g.async||a.readyState==4||h++>10000){if(g.success&&h<10000&&a.status==200){g.success.call(g.success_scope,""+a.responseText,a,g)}else{if(g.error){g.error.call(g.error_scope,h>10000?"TIMED_OUT":"GENERAL",a,g)}}a=null}else{b.setTimeout(f,10)}}g.scope=g.scope||this;g.success_scope=g.success_scope||g.scope;g.error_scope=g.error_scope||g.scope;g.async=g.async===false?false:true;g.data=g.data||"";function d(i){a=0;try{a=new ActiveXObject(i)}catch(c){}return a}a=b.XMLHttpRequest?new XMLHttpRequest():d("Microsoft.XMLHTTP")||d("Msxml2.XMLHTTP");if(a){if(a.overrideMimeType){a.overrideMimeType(g.content_type)}a.open(g.type||(g.data?"POST":"GET"),g.url,g.async);if(g.content_type){a.setRequestHeader("Content-Type",g.content_type)}a.setRequestHeader("X-Requested-With","XMLHttpRequest");a.send(g.data);if(!g.async){return f()}e=b.setTimeout(f,10)}}});(function(){var c=tinymce.extend,b=tinymce.util.JSON,a=tinymce.util.XHR;tinymce.create("tinymce.util.JSONRequest",{JSONRequest:function(d){this.settings=c({},d);this.count=0},send:function(f){var e=f.error,d=f.success;f=c(this.settings,f);f.success=function(h,g){h=b.parse(h);if(typeof(h)=="undefined"){h={error:"JSON Parse error."}}if(h.error){e.call(f.error_scope||f.scope,h.error,g)}else{d.call(f.success_scope||f.scope,h.result)}};f.error=function(h,g){if(e){e.call(f.error_scope||f.scope,h,g)}};f.data=b.serialize({id:f.id||"c"+(this.count++),method:f.method,params:f.params});f.content_type="application/json";a.send(f)},"static":{sendRPC:function(d){return new tinymce.util.JSONRequest().send(d)}}})}());(function(a){a.VK={BACKSPACE:8,DELETE:46,DOWN:40,ENTER:13,LEFT:37,RIGHT:39,SPACEBAR:32,TAB:9,UP:38,modifierPressed:function(b){return b.shiftKey||b.ctrlKey||b.altKey},metaKeyPressed:function(b){return a.isMac?b.metaKey:b.ctrlKey&&!b.altKey}}})(tinymce);tinymce.util.Quirks=function(a){var j=tinymce.VK,f=j.BACKSPACE,l=j.DELETE,e=a.dom,n=a.selection,J=a.settings,y=a.parser,q=a.serializer,G=tinymce.each;function C(P,O){try{a.getDoc().execCommand(P,false,O)}catch(N){}}function p(){var N=a.getDoc().documentMode;return N?N:6}function B(N){return N.isDefaultPrevented()}function L(){function N(T){var P,R,O,U,Q,S,V;function W(){if(Q.nodeType==3){if(T&&S==Q.length){return true}if(!T&&S===0){return true}}}P=n.getRng();var X=[P.startContainer,P.startOffset,P.endContainer,P.endOffset];if(!P.collapsed){T=true}Q=P[(T?"start":"end")+"Container"];S=P[(T?"start":"end")+"Offset"];if(Q.nodeType==3){R=e.getParent(P.startContainer,e.isBlock);if(T){R=e.getNext(R,e.isBlock)}if(R&&(W()||!P.collapsed)){O=e.create("em",{id:"__mceDel"});G(tinymce.grep(R.childNodes),function(Y){O.appendChild(Y)});R.appendChild(O)}}P=e.createRng();P.setStart(X[0],X[1]);P.setEnd(X[2],X[3]);n.setRng(P);a.getDoc().execCommand(T?"ForwardDelete":"Delete",false,null);if(O){U=n.getBookmark();while(V=e.get("__mceDel")){e.remove(V,true)}n.moveToBookmark(U)}}a.onKeyDown.add(function(O,Q){var P;P=Q.keyCode==l;if(!B(Q)&&(P||Q.keyCode==f)&&!j.modifierPressed(Q)){Q.preventDefault();N(P)}});a.addCommand("Delete",function(){N()})}function s(){function N(Q){var P=e.create("body");var R=Q.cloneContents();P.appendChild(R);return n.serializer.serialize(P,{format:"html"})}function O(P){var R=N(P);var S=e.createRng();S.selectNode(a.getBody());var Q=N(S);return R===Q}a.onKeyDown.add(function(Q,S){var R=S.keyCode,P;if(!B(S)&&(R==l||R==f)){P=Q.selection.isCollapsed();if(P&&!e.isEmpty(Q.getBody())){return}if(tinymce.isIE&&!P){return}if(!P&&!O(Q.selection.getRng())){return}Q.setContent("");Q.selection.setCursorLocation(Q.getBody(),0);Q.nodeChanged()}})}function K(){a.onKeyDown.add(function(N,O){if(!B(O)&&O.keyCode==65&&j.metaKeyPressed(O)){O.preventDefault();N.execCommand("SelectAll")}})}function M(){if(!a.settings.content_editable){e.bind(a.getDoc(),"focusin",function(N){n.setRng(n.getRng())});e.bind(a.getDoc(),"mousedown",function(N){if(N.target==a.getDoc().documentElement){a.getWin().focus();n.setRng(n.getRng())}})}}function D(){a.onKeyDown.add(function(N,Q){if(!B(Q)&&Q.keyCode===f){if(n.isCollapsed()&&n.getRng(true).startOffset===0){var P=n.getNode();var O=P.previousSibling;if(O&&O.nodeName&&O.nodeName.toLowerCase()==="hr"){e.remove(O);tinymce.dom.Event.cancel(Q)}}}})}function A(){if(!Range.prototype.getClientRects){a.onMouseDown.add(function(O,P){if(!B(P)&&P.target.nodeName==="HTML"){var N=O.getBody();N.blur();setTimeout(function(){N.focus()},0)}})}}function h(){a.onClick.add(function(N,O){O=O.target;if(/^(IMG|HR)$/.test(O.nodeName)){n.getSel().setBaseAndExtent(O,0,O,1)}if(O.nodeName=="A"&&e.hasClass(O,"mceItemAnchor")){n.select(O)}N.nodeChanged()})}function c(){function O(){var Q=e.getAttribs(n.getStart().cloneNode(false));return function(){var R=n.getStart();if(R!==a.getBody()){e.setAttrib(R,"style",null);G(Q,function(S){R.setAttributeNode(S.cloneNode(true))})}}}function N(){return !n.isCollapsed()&&e.getParent(n.getStart(),e.isBlock)!=e.getParent(n.getEnd(),e.isBlock)}function P(Q,R){R.preventDefault();return false}a.onKeyPress.add(function(Q,S){var R;if(!B(S)&&(S.keyCode==8||S.keyCode==46)&&N()){R=O();Q.getDoc().execCommand("delete",false,null);R();S.preventDefault();return false}});e.bind(a.getDoc(),"cut",function(R){var Q;if(!B(R)&&N()){Q=O();a.onKeyUp.addToTop(P);setTimeout(function(){Q();a.onKeyUp.remove(P)},0)}})}function b(){var O,N;e.bind(a.getDoc(),"selectionchange",function(){if(N){clearTimeout(N);N=0}N=window.setTimeout(function(){var P=n.getRng();if(!O||!tinymce.dom.RangeUtils.compareRanges(P,O)){a.nodeChanged();O=P}},50)})}function z(){document.body.setAttribute("role","application")}function v(){a.onKeyDown.add(function(N,P){if(!B(P)&&P.keyCode===f){if(n.isCollapsed()&&n.getRng(true).startOffset===0){var O=n.getNode().previousSibling;if(O&&O.nodeName&&O.nodeName.toLowerCase()==="table"){return tinymce.dom.Event.cancel(P)}}}})}function E(){if(p()>7){return}C("RespectVisibilityInDesign",true);a.contentStyles.push(".mceHideBrInPre pre br {display: none}");e.addClass(a.getBody(),"mceHideBrInPre");y.addNodeFilter("pre",function(N,P){var Q=N.length,S,O,T,R;while(Q--){S=N[Q].getAll("br");O=S.length;while(O--){T=S[O];R=T.prev;if(R&&R.type===3&&R.value.charAt(R.value-1)!="\n"){R.value+="\n"}else{T.parent.insert(new tinymce.html.Node("#text",3),T,true).value="\n"}}}});q.addNodeFilter("pre",function(N,P){var Q=N.length,S,O,T,R;while(Q--){S=N[Q].getAll("br");O=S.length;while(O--){T=S[O];R=T.prev;if(R&&R.type==3){R.value=R.value.replace(/\r?\n$/,"")}}}})}function g(){e.bind(a.getBody(),"mouseup",function(P){var O,N=n.getNode();if(N.nodeName=="IMG"){if(O=e.getStyle(N,"width")){e.setAttrib(N,"width",O.replace(/[^0-9%]+/g,""));e.setStyle(N,"width","")}if(O=e.getStyle(N,"height")){e.setAttrib(N,"height",O.replace(/[^0-9%]+/g,""));e.setStyle(N,"height","")}}})}function d(){a.onKeyDown.add(function(T,U){var S,N,O,Q,R,V,P;S=U.keyCode==l;if(!B(U)&&(S||U.keyCode==f)&&!j.modifierPressed(U)){N=n.getRng();O=N.startContainer;Q=N.startOffset;P=N.collapsed;if(O.nodeType==3&&O.nodeValue.length>0&&((Q===0&&!P)||(P&&Q===(S?0:1)))){V=O.previousSibling;if(V&&V.nodeName=="IMG"){return}nonEmptyElements=T.schema.getNonEmptyElements();U.preventDefault();R=e.create("br",{id:"__tmp"});O.parentNode.insertBefore(R,O);T.getDoc().execCommand(S?"ForwardDelete":"Delete",false,null);O=n.getRng().startContainer;V=O.previousSibling;if(V&&V.nodeType==1&&!e.isBlock(V)&&e.isEmpty(V)&&!nonEmptyElements[V.nodeName.toLowerCase()]){e.remove(V)}e.remove("__tmp")}}})}function I(){a.onKeyDown.add(function(R,S){var P,O,T,N,Q;if(B(S)||S.keyCode!=j.BACKSPACE){return}P=n.getRng();O=P.startContainer;T=P.startOffset;N=e.getRoot();Q=O;if(!P.collapsed||T!==0){return}while(Q&&Q.parentNode&&Q.parentNode.firstChild==Q&&Q.parentNode!=N){Q=Q.parentNode}if(Q.tagName==="BLOCKQUOTE"){R.formatter.toggle("blockquote",null,Q);P=e.createRng();P.setStart(O,0);P.setEnd(O,0);n.setRng(P)}})}function H(){function N(){a._refreshContentEditable();C("StyleWithCSS",false);C("enableInlineTableEditing",false);if(!J.object_resizing){C("enableObjectResizing",false)}}if(!J.readonly){a.onBeforeExecCommand.add(N);a.onMouseDown.add(N)}}function u(){function N(O,P){G(e.select("a"),function(S){var Q=S.parentNode,R=e.getRoot();if(Q.lastChild===S){while(Q&&!e.isBlock(Q)){if(Q.parentNode.lastChild!==Q||Q===R){return}Q=Q.parentNode}e.add(Q,"br",{"data-mce-bogus":1})}})}a.onExecCommand.add(function(O,P){if(P==="CreateLink"){N(O)}});a.onSetContent.add(n.onSetContent.add(N))}function o(){if(J.forced_root_block){a.onInit.add(function(){C("DefaultParagraphSeparator",J.forced_root_block)})}}function r(){function N(P,O){if(!P||!O.initial){a.execCommand("mceRepaint")}}a.onUndo.add(N);a.onRedo.add(N);a.onSetContent.add(N)}function i(){a.onKeyDown.add(function(O,P){var N;if(!B(P)&&P.keyCode==f){N=O.getDoc().selection.createRange();if(N&&N.item){P.preventDefault();O.undoManager.beforeChange();e.remove(N.item(0));O.undoManager.add()}}})}function t(){var N;if(p()>=10){N="";G("p div h1 h2 h3 h4 h5 h6".split(" "),function(O,P){N+=(P>0?",":"")+O+":empty"});a.contentStyles.push(N+"{padding-right: 1px !important}")}}function x(){var P,O,af,N,aa,ad,ab,ae,Q,R,ac,Y,X,Z=document,V=a.getDoc();if(!J.object_resizing||J.webkit_fake_resize===false){return}C("enableObjectResizing",false);ac={n:[0.5,0,0,-1],e:[1,0.5,1,0],s:[0.5,1,0,1],w:[0,0.5,-1,0],nw:[0,0,-1,-1],ne:[1,0,1,-1],se:[1,1,1,1],sw:[0,1,-1,1]};function T(aj){var ai,ah;ai=aj.screenX-ad;ah=aj.screenY-ab;Y=ai*aa[2]+ae;X=ah*aa[3]+Q;Y=Y<5?5:Y;X=X<5?5:X;if(j.modifierPressed(aj)||(af.nodeName=="IMG"&&aa[2]*aa[3]!==0)){Y=Math.round(X/R);X=Math.round(Y*R)}e.setStyles(N,{width:Y,height:X});if(aa[2]<0&&N.clientWidth<=Y){e.setStyle(N,"left",P+(ae-Y))}if(aa[3]<0&&N.clientHeight<=X){e.setStyle(N,"top",O+(Q-X))}}function ag(){function ah(ai,aj){if(aj){if(af.style[ai]||!a.schema.isValid(af.nodeName.toLowerCase(),ai)){e.setStyle(af,ai,aj)}else{e.setAttrib(af,ai,aj)}}}ah("width",Y);ah("height",X);e.unbind(V,"mousemove",T);e.unbind(V,"mouseup",ag);if(Z!=V){e.unbind(Z,"mousemove",T);e.unbind(Z,"mouseup",ag)}e.remove(N);S(af)}function S(ak){var ai,aj,ah;U();ai=e.getPos(ak);P=ai.x;O=ai.y;aj=ak.offsetWidth;ah=ak.offsetHeight;if(af!=ak){af=ak;Y=X=0}G(ac,function(an,al){var am;am=e.get("mceResizeHandle"+al);if(!am){am=e.add(V.documentElement,"div",{id:"mceResizeHandle"+al,"class":"mceResizeHandle",style:"cursor:"+al+"-resize; margin:0; padding:0"});e.bind(am,"mousedown",function(ao){ao.preventDefault();ag();ad=ao.screenX;ab=ao.screenY;ae=af.clientWidth;Q=af.clientHeight;R=Q/ae;aa=an;N=af.cloneNode(true);e.addClass(N,"mceClonedResizable");e.setStyles(N,{left:P,top:O,margin:0});V.documentElement.appendChild(N);e.bind(V,"mousemove",T);e.bind(V,"mouseup",ag);if(Z!=V){e.bind(Z,"mousemove",T);e.bind(Z,"mouseup",ag)}})}else{e.show(am)}e.setStyles(am,{left:(aj*an[0]+P)-(am.offsetWidth/2),top:(ah*an[1]+O)-(am.offsetHeight/2)})});if(!tinymce.isOpera&&af.nodeName=="IMG"){af.setAttribute("data-mce-selected","1")}}function U(){if(af){af.removeAttribute("data-mce-selected")}for(var ah in ac){e.hide("mceResizeHandle"+ah)}}a.contentStyles.push(".mceResizeHandle {position: absolute;border: 1px solid black;background: #FFF;width: 5px;height: 5px;z-index: 10000}.mceResizeHandle:hover {background: #000}img[data-mce-selected] {outline: 1px solid black}img.mceClonedResizable, table.mceClonedResizable {position: absolute;outline: 1px dashed black;opacity: .5;z-index: 10000}");function W(){var ah=e.getParent(n.getNode(),"table,img");G(e.select("img[data-mce-selected]"),function(ai){ai.removeAttribute("data-mce-selected")});if(ah){S(ah)}else{U()}}a.onNodeChange.add(W);e.bind(V,"selectionchange",W);a.serializer.addAttributeFilter("data-mce-selected",function(ah,ai){var aj=ah.length;while(aj--){ah[aj].attr(ai,null)}})}function F(){if(p()<9){y.addNodeFilter("noscript",function(N){var O=N.length,P,Q;while(O--){P=N[O];Q=P.firstChild;if(Q){P.attr("data-mce-innertext",Q.value)}}});q.addNodeFilter("noscript",function(N){var O=N.length,P,R,Q;while(O--){P=N[O];R=N[O].firstChild;if(R){R.value=tinymce.html.Entities.decode(R.value)}else{Q=P.attributes.map["data-mce-innertext"];if(Q){P.attr("data-mce-innertext",null);R=new tinymce.html.Node("#text",3);R.value=Q;R.raw=true;P.append(R)}}}})}}function m(){a.contentStyles.push("body {min-height: 100px}");a.onClick.add(function(N,O){if(O.target.nodeName=="HTML"){a.execCommand("SelectAll");a.selection.collapse(true);a.nodeChanged()}})}function k(){a.onInit.add(function(){var N;a.getBody().addEventListener("mscontrolselect",function(O){setTimeout(function(){if(a.selection.getNode()!=O.target){N=a.selection.getRng();n.fakeRng=a.dom.createRng();n.fakeRng.setStartBefore(O.target);n.fakeRng.setEndAfter(O.target)}},0)},false);a.getDoc().addEventListener("selectionchange",function(O){if(N&&!tinymce.dom.RangeUtils.compareRanges(a.selection.getRng(),N)){n.fakeRng=N=null}},false)})}v();I();s();if(tinymce.isWebKit){d();L();M();h();o();if(tinymce.isIDevice){b()}else{x();K()}}if(tinymce.isIE&&!tinymce.isIE11){D();z();E();g();i();t();F()}if(tinymce.isIE11){m();k()}if(tinymce.isGecko&&!tinymce.isIE11){D();A();c();H();u();r()}if(tinymce.isOpera){x()}};(function(j){var a,g,d,k=/[&<>\"\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,b=/[<>&\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,f=/[<>&\"\']/g,c=/&(#x|#)?([\w]+);/g,i={128:"\u20AC",130:"\u201A",131:"\u0192",132:"\u201E",133:"\u2026",134:"\u2020",135:"\u2021",136:"\u02C6",137:"\u2030",138:"\u0160",139:"\u2039",140:"\u0152",142:"\u017D",145:"\u2018",146:"\u2019",147:"\u201C",148:"\u201D",149:"\u2022",150:"\u2013",151:"\u2014",152:"\u02DC",153:"\u2122",154:"\u0161",155:"\u203A",156:"\u0153",158:"\u017E",159:"\u0178"};g={'"':""","'":"'","<":"<",">":">","&":"&"};d={"<":"<",">":">","&":"&",""":'"',"'":"'"};function h(l){var m;m=document.createElement("div");m.innerHTML=l;return m.textContent||m.innerText||l}function e(m,p){var n,o,l,q={};if(m){m=m.split(",");p=p||10;for(n=0;n1){return"&#"+(((n.charCodeAt(0)-55296)*1024)+(n.charCodeAt(1)-56320)+65536)+";"}return g[n]||"&#"+n.charCodeAt(0)+";"})},encodeNamed:function(n,l,m){m=m||a;return n.replace(l?k:b,function(o){return g[o]||m[o]||o})},getEncodeFunc:function(l,o){var p=j.html.Entities;o=e(o)||a;function m(r,q){return r.replace(q?k:b,function(s){return g[s]||o[s]||"&#"+s.charCodeAt(0)+";"||s})}function n(r,q){return p.encodeNamed(r,q,o)}l=j.makeMap(l.replace(/\+/g,","));if(l.named&&l.numeric){return m}if(l.named){if(o){return n}return p.encodeNamed}if(l.numeric){return p.encodeNumeric}return p.encodeRaw},decode:function(l){return l.replace(c,function(n,m,o){if(m){o=parseInt(o,m.length===2?16:10);if(o>65535){o-=65536;return String.fromCharCode(55296+(o>>10),56320+(o&1023))}else{return i[o]||String.fromCharCode(o)}}return d[n]||a[n]||h(n)})}}})(tinymce);tinymce.html.Styles=function(d,f){var k=/rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)/gi,h=/(?:url(?:(?:\(\s*\"([^\"]+)\"\s*\))|(?:\(\s*\'([^\']+)\'\s*\))|(?:\(\s*([^)\s]+)\s*\))))|(?:\'([^\']+)\')|(?:\"([^\"]+)\")/gi,b=/\s*([^:]+):\s*([^;]+);?/g,l=/\s+$/,m=/rgb/,e,g,a={},j;d=d||{};j="\\\" \\' \\; \\: ; : \uFEFF".split(" ");for(g=0;g1?r:"0"+r}return"#"+o(q)+o(p)+o(i)}return{toHex:function(i){return i.replace(k,c)},parse:function(s){var z={},q,n,x,r,v=d.url_converter,y=d.url_converter_scope||this;function p(D,G){var F,C,B,E;if(z["border-image"]==="none"){delete z["border-image"]}F=z[D+"-top"+G];if(!F){return}C=z[D+"-right"+G];if(F!=C){return}B=z[D+"-bottom"+G];if(C!=B){return}E=z[D+"-left"+G];if(B!=E){return}z[D+G]=E;delete z[D+"-top"+G];delete z[D+"-right"+G];delete z[D+"-bottom"+G];delete z[D+"-left"+G]}function u(C){var D=z[C],B;if(!D||D.indexOf(" ")<0){return}D=D.split(" ");B=D.length;while(B--){if(D[B]!==D[0]){return false}}z[C]=D[0];return true}function A(D,C,B,E){if(!u(C)){return}if(!u(B)){return}if(!u(E)){return}z[D]=z[C]+" "+z[B]+" "+z[E];delete z[C];delete z[B];delete z[E]}function t(B){r=true;return a[B]}function i(C,B){if(r){C=C.replace(/\uFEFF[0-9]/g,function(D){return a[D]})}if(!B){C=C.replace(/\\([\'\";:])/g,"$1")}return C}function o(C,B,F,E,G,D){G=G||D;if(G){G=i(G);return"'"+G.replace(/\'/g,"\\'")+"'"}B=i(B||F||E);if(v){B=v.call(y,B,"style")}return"url('"+B.replace(/\'/g,"\\'")+"')"}if(s){s=s.replace(/\\[\"\';:\uFEFF]/g,t).replace(/\"[^\"]+\"|\'[^\']+\'/g,function(B){return B.replace(/[;:]/g,t)});while(q=b.exec(s)){n=q[1].replace(l,"").toLowerCase();x=q[2].replace(l,"");if(n&&x.length>0){if(n==="font-weight"&&x==="700"){x="bold"}else{if(n==="color"||n==="background-color"){x=x.toLowerCase()}}x=x.replace(k,c);x=x.replace(h,o);z[n]=r?i(x,true):x}b.lastIndex=q.index+q[0].length}p("border","");p("border","-width");p("border","-color");p("border","-style");p("padding","");p("margin","");A("border","border-width","border-style","border-color");if(z.border==="medium none"){delete z.border}}return z},serialize:function(p,r){var o="",n,q;function i(t){var x,u,s,v;x=f.styles[t];if(x){for(u=0,s=x.length;u0){o+=(o.length>0?" ":"")+t+": "+v+";"}}}}if(r&&f&&f.styles){i("*");i(r)}else{for(n in p){q=p[n];if(q!==e&&q.length>0){o+=(o.length>0?" ":"")+n+": "+q+";"}}}return o}}};(function(f){var a={},e=f.makeMap,g=f.each;function d(j,i){return j.split(i||",")}function h(m,l){var j,k={};function i(n){return n.replace(/[A-Z]+/g,function(o){return i(m[o])})}for(j in m){if(m.hasOwnProperty(j)){m[j]=i(m[j])}}i(l).replace(/#/g,"#text").replace(/(\w+)\[([^\]]+)\]\[([^\]]*)\]/g,function(q,o,n,p){n=d(n,"|");k[o]={attributes:e(n),attributesOrder:n,children:e(p,"|",{"#comment":{}})}});return k}function b(){var i=a.html5;if(!i){i=a.html5=h({A:"id|accesskey|class|dir|draggable|item|hidden|itemprop|role|spellcheck|style|subject|title|onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup",B:"#|a|abbr|area|audio|b|bdo|br|button|canvas|cite|code|command|datalist|del|dfn|em|embed|i|iframe|img|input|ins|kbd|keygen|label|link|map|mark|meta|meter|noscript|object|output|progress|q|ruby|samp|script|select|small|span|strong|sub|sup|svg|textarea|time|var|video|wbr",C:"#|a|abbr|area|address|article|aside|audio|b|bdo|blockquote|br|button|canvas|cite|code|command|datalist|del|details|dfn|dialog|div|dl|em|embed|fieldset|figure|footer|form|h1|h2|h3|h4|h5|h6|header|hgroup|hr|i|iframe|img|input|ins|kbd|keygen|label|link|map|mark|menu|meta|meter|nav|noscript|ol|object|output|p|pre|progress|q|ruby|samp|script|section|select|small|span|strong|style|sub|sup|svg|table|textarea|time|ul|var|video"},"html[A|manifest][body|head]head[A][base|command|link|meta|noscript|script|style|title]title[A][#]base[A|href|target][]link[A|href|rel|media|type|sizes][]meta[A|http-equiv|name|content|charset][]style[A|type|media|scoped][#]script[A|charset|type|src|defer|async][#]noscript[A][C]body[A][C]section[A][C]nav[A][C]article[A][C]aside[A][C]h1[A][B]h2[A][B]h3[A][B]h4[A][B]h5[A][B]h6[A][B]hgroup[A][h1|h2|h3|h4|h5|h6]header[A][C]footer[A][C]address[A][C]p[A][B]br[A][]pre[A][B]dialog[A][dd|dt]blockquote[A|cite][C]ol[A|start|reversed][li]ul[A][li]li[A|value][C]dl[A][dd|dt]dt[A][B]dd[A][C]a[A|href|target|ping|rel|media|type][B]em[A][B]strong[A][B]small[A][B]cite[A][B]q[A|cite][B]dfn[A][B]abbr[A][B]code[A][B]var[A][B]samp[A][B]kbd[A][B]sub[A][B]sup[A][B]i[A][B]b[A][B]mark[A][B]progress[A|value|max][B]meter[A|value|min|max|low|high|optimum][B]time[A|datetime][B]ruby[A][B|rt|rp]rt[A][B]rp[A][B]bdo[A][B]span[A][B]ins[A|cite|datetime][B]del[A|cite|datetime][B]figure[A][C|legend|figcaption]figcaption[A][C]img[A|alt|src|height|width|usemap|ismap][]iframe[A|name|src|height|width|sandbox|seamless][]embed[A|src|height|width|type][]object[A|data|type|height|width|usemap|name|form|classid][param]param[A|name|value][]details[A|open][C|legend]command[A|type|label|icon|disabled|checked|radiogroup][]menu[A|type|label][C|li]legend[A][C|B]div[A][C]source[A|src|type|media][]audio[A|src|autobuffer|autoplay|loop|controls][source]video[A|src|autobuffer|autoplay|loop|controls|width|height|poster][source]hr[A][]form[A|accept-charset|action|autocomplete|enctype|method|name|novalidate|target][C]fieldset[A|disabled|form|name][C|legend]label[A|form|for][B]input[A|type|accept|alt|autocomplete|autofocus|checked|disabled|form|formaction|formenctype|formmethod|formnovalidate|formtarget|height|list|max|maxlength|min|multiple|pattern|placeholder|readonly|required|size|src|step|width|files|value|name][]button[A|autofocus|disabled|form|formaction|formenctype|formmethod|formnovalidate|formtarget|name|value|type][B]select[A|autofocus|disabled|form|multiple|name|size][option|optgroup]datalist[A][B|option]optgroup[A|disabled|label][option]option[A|disabled|selected|label|value][]textarea[A|autofocus|disabled|form|maxlength|name|placeholder|readonly|required|rows|cols|wrap][]keygen[A|autofocus|challenge|disabled|form|keytype|name][]output[A|for|form|name][B]canvas[A|width|height][]map[A|name][B|C]area[A|shape|coords|href|alt|target|media|rel|ping|type][]mathml[A][]svg[A][]table[A|border][caption|colgroup|thead|tfoot|tbody|tr]caption[A][C]colgroup[A|span][col]col[A|span][]thead[A][tr]tfoot[A][tr]tbody[A][tr]tr[A][th|td]th[A|headers|rowspan|colspan|scope][B]td[A|headers|rowspan|colspan][C]wbr[A][]")}return i}function c(){var i=a.html4;if(!i){i=a.html4=h({Z:"H|K|N|O|P",Y:"X|form|R|Q",ZG:"E|span|width|align|char|charoff|valign",X:"p|T|div|U|W|isindex|fieldset|table",ZF:"E|align|char|charoff|valign",W:"pre|hr|blockquote|address|center|noframes",ZE:"abbr|axis|headers|scope|rowspan|colspan|align|char|charoff|valign|nowrap|bgcolor|width|height",ZD:"[E][S]",U:"ul|ol|dl|menu|dir",ZC:"p|Y|div|U|W|table|br|span|bdo|object|applet|img|map|K|N|Q",T:"h1|h2|h3|h4|h5|h6",ZB:"X|S|Q",S:"R|P",ZA:"a|G|J|M|O|P",R:"a|H|K|N|O",Q:"noscript|P",P:"ins|del|script",O:"input|select|textarea|label|button",N:"M|L",M:"em|strong|dfn|code|q|samp|kbd|var|cite|abbr|acronym",L:"sub|sup",K:"J|I",J:"tt|i|b|u|s|strike",I:"big|small|font|basefont",H:"G|F",G:"br|span|bdo",F:"object|applet|img|map|iframe",E:"A|B|C",D:"accesskey|tabindex|onfocus|onblur",C:"onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup",B:"lang|xml:lang|dir",A:"id|class|style|title"},"script[id|charset|type|language|src|defer|xml:space][]style[B|id|type|media|title|xml:space][]object[E|declare|classid|codebase|data|type|codetype|archive|standby|width|height|usemap|name|tabindex|align|border|hspace|vspace][#|param|Y]param[id|name|value|valuetype|type][]p[E|align][#|S]a[E|D|charset|type|name|href|hreflang|rel|rev|shape|coords|target][#|Z]br[A|clear][]span[E][#|S]bdo[A|C|B][#|S]applet[A|codebase|archive|code|object|alt|name|width|height|align|hspace|vspace][#|param|Y]h1[E|align][#|S]img[E|src|alt|name|longdesc|width|height|usemap|ismap|align|border|hspace|vspace][]map[B|C|A|name][X|form|Q|area]h2[E|align][#|S]iframe[A|longdesc|name|src|frameborder|marginwidth|marginheight|scrolling|align|width|height][#|Y]h3[E|align][#|S]tt[E][#|S]i[E][#|S]b[E][#|S]u[E][#|S]s[E][#|S]strike[E][#|S]big[E][#|S]small[E][#|S]font[A|B|size|color|face][#|S]basefont[id|size|color|face][]em[E][#|S]strong[E][#|S]dfn[E][#|S]code[E][#|S]q[E|cite][#|S]samp[E][#|S]kbd[E][#|S]var[E][#|S]cite[E][#|S]abbr[E][#|S]acronym[E][#|S]sub[E][#|S]sup[E][#|S]input[E|D|type|name|value|checked|disabled|readonly|size|maxlength|src|alt|usemap|onselect|onchange|accept|align][]select[E|name|size|multiple|disabled|tabindex|onfocus|onblur|onchange][optgroup|option]optgroup[E|disabled|label][option]option[E|selected|disabled|label|value][]textarea[E|D|name|rows|cols|disabled|readonly|onselect|onchange][]label[E|for|accesskey|onfocus|onblur][#|S]button[E|D|name|value|type|disabled][#|p|T|div|U|W|table|G|object|applet|img|map|K|N|Q]h4[E|align][#|S]ins[E|cite|datetime][#|Y]h5[E|align][#|S]del[E|cite|datetime][#|Y]h6[E|align][#|S]div[E|align][#|Y]ul[E|type|compact][li]li[E|type|value][#|Y]ol[E|type|compact|start][li]dl[E|compact][dt|dd]dt[E][#|S]dd[E][#|Y]menu[E|compact][li]dir[E|compact][li]pre[E|width|xml:space][#|ZA]hr[E|align|noshade|size|width][]blockquote[E|cite][#|Y]address[E][#|S|p]center[E][#|Y]noframes[E][#|Y]isindex[A|B|prompt][]fieldset[E][#|legend|Y]legend[E|accesskey|align][#|S]table[E|summary|width|border|frame|rules|cellspacing|cellpadding|align|bgcolor][caption|col|colgroup|thead|tfoot|tbody|tr]caption[E|align][#|S]col[ZG][]colgroup[ZG][col]thead[ZF][tr]tr[ZF|bgcolor][th|td]th[E|ZE][#|Y]form[E|action|method|name|enctype|onsubmit|onreset|accept|accept-charset|target][#|X|R|Q]noscript[E][#|Y]td[E|ZE][#|Y]tfoot[ZF][tr]tbody[ZF][tr]area[E|D|shape|coords|href|nohref|alt|target][]base[id|href|target][]body[E|onload|onunload|background|bgcolor|text|link|vlink|alink][#|Y]")}return i}f.html.Schema=function(A){var u=this,s={},k={},j=[],D,y;var o,q,z,r,v,n,p={};function m(F,E,H){var G=A[F];if(!G){G=a[F];if(!G){G=e(E," ",e(E.toUpperCase()," "));G=f.extend(G,H);a[F]=G}}else{G=e(G,",",e(G.toUpperCase()," "))}return G}A=A||{};y=A.schema=="html5"?b():c();if(A.verify_html===false){A.valid_elements="*[*]"}if(A.valid_styles){D={};g(A.valid_styles,function(F,E){D[E]=f.explode(F)})}o=m("whitespace_elements","pre script noscript style textarea");q=m("self_closing_elements","colgroup dd dt li option p td tfoot th thead tr");z=m("short_ended_elements","area base basefont br col frame hr img input isindex link meta param embed source wbr");r=m("boolean_attributes","checked compact declare defer disabled ismap multiple nohref noresize noshade nowrap readonly selected autoplay loop controls");n=m("non_empty_elements","td th iframe video audio object script",z);textBlockElementsMap=m("text_block_elements","h1 h2 h3 h4 h5 h6 p div address pre form blockquote center dir fieldset header footer article section hgroup aside nav figure");v=m("block_elements","hr table tbody thead tfoot th tr td li ol ul caption dl dt dd noscript menu isindex samp option datalist select optgroup",textBlockElementsMap);function i(E){return new RegExp("^"+E.replace(/([?+*])/g,".$1")+"$")}function C(L){var K,G,Z,V,aa,F,I,U,X,Q,Y,ac,O,J,W,E,S,H,ab,ad,P,T,N=/^([#+\-])?([^\[\/]+)(?:\/([^\[]+))?(?:\[([^\]]+)\])?$/,R=/^([!\-])?(\w+::\w+|[^=:<]+)?(?:([=:<])(.*))?$/,M=/[*?+]/;if(L){L=d(L);if(s["@"]){S=s["@"].attributes;H=s["@"].attributesOrder}for(K=0,G=L.length;K=0){for(U=A.length-1;U>=V;U--){T=A[U];if(T.valid){n.end(T.name)}}A.length=V}}function p(U,T,Y,X,W){var Z,V;T=T.toLowerCase();Y=T in H?T:j(Y||X||W||"");if(v&&!z&&T.indexOf("data-")!==0){Z=P[T];if(!Z&&F){V=F.length;while(V--){Z=F[V];if(Z.pattern.test(T)){break}}if(V===-1){Z=null}}if(!Z){return}if(Z.validValues&&!(Y in Z.validValues)){return}}N.map[T]=Y;N.push({name:T,value:Y})}l=new RegExp("<(?:(?:!--([\\w\\W]*?)-->)|(?:!\\[CDATA\\[([\\w\\W]*?)\\]\\]>)|(?:!DOCTYPE([\\w\\W]*?)>)|(?:\\?([^\\s\\/<>]+) ?([\\w\\W]*?)[?/]>)|(?:\\/([^>]+)>)|(?:([A-Za-z0-9\\-\\:\\.]+)((?:\\s+[^\"'>]+(?:(?:\"[^\"]*\")|(?:'[^']*')|[^>]*))*|\\/|\\s+)>))","g");D=/([\w:\-]+)(?:\s*=\s*(?:(?:\"((?:[^\"])*)\")|(?:\'((?:[^\'])*)\')|([^>\s]+)))?/g;K={script:/<\/script[^>]*>/gi,style:/<\/style[^>]*>/gi,noscript:/<\/noscript[^>]*>/gi};M=e.getShortEndedElements();J=c.self_closing_elements||e.getSelfClosingElements();H=e.getBoolAttrs();v=c.validate;s=c.remove_internals;y=c.fix_self_closing;q=a.isIE;o=/^:/;while(g=l.exec(E)){if(G0&&A[A.length-1].name===I){u(I)}if(!v||(m=e.getElementRule(I))){k=true;if(v){P=m.attributes;F=m.attributePatterns}if(R=g[8]){z=R.indexOf("data-mce-type")!==-1;if(z&&s){k=false}N=[];N.map={};R.replace(D,p)}else{N=[];N.map={}}if(v&&!z){S=m.attributesRequired;L=m.attributesDefault;f=m.attributesForced;if(f){Q=f.length;while(Q--){t=f[Q];r=t.name;h=t.value;if(h==="{$uid}"){h="mce_"+x++}N.map[r]=h;N.push({name:r,value:h})}}if(L){Q=L.length;while(Q--){t=L[Q];r=t.name;if(!(r in N.map)){h=t.value;if(h==="{$uid}"){h="mce_"+x++}N.map[r]=h;N.push({name:r,value:h})}}}if(S){Q=S.length;while(Q--){if(S[Q] in N.map){break}}if(Q===-1){k=false}}if(N.map["data-mce-bogus"]){k=false}}if(k){n.start(I,N,O)}}else{k=false}if(B=K[I]){B.lastIndex=G=g.index+g[0].length;if(g=B.exec(E)){if(k){C=E.substr(G,g.index-G)}G=g.index+g[0].length}else{C=E.substr(G);G=E.length}if(k&&C.length>0){n.text(C,true)}if(k){n.end(I)}l.lastIndex=G;continue}if(!O){if(!R||R.indexOf("/")!=R.length-1){A.push({name:I,valid:k})}else{if(k){n.end(I)}}}}else{if(I=g[1]){n.comment(I)}else{if(I=g[2]){n.cdata(I)}else{if(I=g[3]){n.doctype(I)}else{if(I=g[4]){n.pi(I,g[5])}}}}}}G=g.index+g[0].length}if(G=0;Q--){I=A[Q];if(I.valid){n.end(I.name)}}}}})(tinymce);(function(d){var c=/^[ \t\r\n]*$/,e={"#text":3,"#comment":8,"#cdata":4,"#pi":7,"#doctype":10,"#document-fragment":11};function a(k,l,j){var i,h,f=j?"lastChild":"firstChild",g=j?"prev":"next";if(k[f]){return k[f]}if(k!==l){i=k[g];if(i){return i}for(h=k.parent;h&&h!==l;h=h.parent){i=h[g];if(i){return i}}}}function b(f,g){this.name=f;this.type=g;if(g===1){this.attributes=[];this.attributes.map={}}}d.extend(b.prototype,{replace:function(g){var f=this;if(g.parent){g.remove()}f.insert(g,f);f.remove();return f},attr:function(h,l){var f=this,g,j,k;if(typeof h!=="string"){for(j in h){f.attr(j,h[j])}return f}if(g=f.attributes){if(l!==k){if(l===null){if(h in g.map){delete g.map[h];j=g.length;while(j--){if(g[j].name===h){g=g.splice(j,1);return f}}}return f}if(h in g.map){j=g.length;while(j--){if(g[j].name===h){g[j].value=l;break}}}else{g.push({name:h,value:l})}g.map[h]=l;return f}else{return g.map[h]}}},clone:function(){var g=this,n=new b(g.name,g.type),h,f,m,j,k;if(m=g.attributes){k=[];k.map={};for(h=0,f=m.length;h1){x.reverse();A=o=f.filterNode(x[0].clone());for(u=0;u0){Q.value=l;Q=Q.prev}else{O=Q.prev;Q.remove();Q=O}}}function H(O){var P,l={};for(P in O){if(P!=="li"&&P!="p"){l[P]=O[P]}}return l}n=new b.html.SaxParser({validate:z,self_closing_elements:H(h.getSelfClosingElements()),cdata:function(l){B.append(K("#cdata",4)).value=l},text:function(P,l){var O;if(!L){P=P.replace(k," ");if(B.lastChild&&o[B.lastChild.name]){P=P.replace(E,"")}}if(P.length!==0){O=K("#text",3);O.raw=!!l;B.append(O).value=P}},comment:function(l){B.append(K("#comment",8)).value=l},pi:function(l,O){B.append(K(l,7)).value=O;I(B)},doctype:function(O){var l;l=B.append(K("#doctype",10));l.value=O;I(B)},start:function(l,W,P){var U,R,Q,O,S,X,V,T;Q=z?h.getElementRule(l):{};if(Q){U=K(Q.outputName||l,1);U.attributes=W;U.shortEnded=P;B.append(U);T=p[B.name];if(T&&p[U.name]&&!T[U.name]){M.push(U)}R=d.length;while(R--){S=d[R].name;if(S in W.map){F=c[S];if(F){F.push(U)}else{c[S]=[U]}}}if(o[l]){I(U)}if(!P){B=U}if(!L&&s[l]){L=true}}},end:function(l){var S,P,R,O,Q;P=z?h.getElementRule(l):{};if(P){if(o[l]){if(!L){S=B.firstChild;if(S&&S.type===3){R=S.value.replace(E,"");if(R.length>0){S.value=R;S=S.next}else{O=S.next;S.remove();S=O}while(S&&S.type===3){R=S.value;O=S.next;if(R.length===0||y.test(R)){S.remove();S=O}S=O}}S=B.lastChild;if(S&&S.type===3){R=S.value.replace(t,"");if(R.length>0){S.value=R;S=S.prev}else{O=S.prev;S.remove();S=O}while(S&&S.type===3){R=S.value;O=S.prev;if(R.length===0||y.test(R)){S.remove();S=O}S=O}}}}if(L&&s[l]){L=false}if(P.removeEmpty||P.paddEmpty){if(B.isEmpty(u)){if(P.paddEmpty){B.empty().append(new a("#text","3")).value="\u00a0"}else{if(!B.attributes.map.name&&!B.attributes.map.id){Q=B.parent;B.empty().remove();B=Q;return}}}}B=B.parent}}},h);J=B=new a(m.context||g.root_name,11);n.parse(v);if(z&&M.length){if(!m.context){j(M)}else{m.invalid=true}}if(q&&J.name=="body"){G()}if(!m.invalid){for(N in i){F=e[N];A=i[N];x=A.length;while(x--){if(!A[x].parent){A.splice(x,1)}}for(D=0,C=F.length;D0){o=c[c.length-1];if(o.length>0&&o!=="\n"){c.push("\n")}}c.push("<",m);if(k){for(n=0,j=k.length;n0){o=c[c.length-1];if(o.length>0&&o!=="\n"){c.push("\n")}}},end:function(h){var i;c.push("");if(a&&d[h]&&c.length>0){i=c[c.length-1];if(i.length>0&&i!=="\n"){c.push("\n")}}},text:function(i,h){if(i.length>0){c[c.length]=h?i:f(i)}},cdata:function(h){c.push("")},comment:function(h){c.push("")},pi:function(h,i){if(i){c.push("")}else{c.push("")}if(a){c.push("\n")}},doctype:function(h){c.push("",a?"\n":"")},reset:function(){c.length=0},getContent:function(){return c.join("").replace(/\n$/,"")}}};(function(a){a.html.Serializer=function(c,d){var b=this,e=new a.html.Writer(c);c=c||{};c.validate="validate" in c?c.validate:true;b.schema=d=d||new a.html.Schema();b.writer=e;b.serialize=function(h){var g,i;i=c.validate;g={3:function(k,j){e.text(k.value,k.raw)},8:function(j){e.comment(j.value)},7:function(j){e.pi(j.name,j.value)},10:function(j){e.doctype(j.value)},4:function(j){e.cdata(j.value)},11:function(j){if((j=j.firstChild)){do{f(j)}while(j=j.next)}}};e.reset();function f(k){var t=g[k.type],j,o,s,r,p,u,n,m,q;if(!t){j=k.name;o=k.shortEnded;s=k.attributes;if(i&&s&&s.length>1){u=[];u.map={};q=d.getElementRule(k.name);for(n=0,m=q.attributesOrder.length;n=8;k.boxModel=!e.isIE||o.compatMode=="CSS1Compat"||k.stdMode;k.hasOuterHTML="outerHTML" in o.createElement("a");k.settings=l=e.extend({keep_values:false,hex_colors:1},l);k.schema=l.schema;k.styles=new e.html.Styles({url_converter:l.url_converter,url_converter_scope:l.url_converter_scope},l.schema);if(e.isIE6){try{o.execCommand("BackgroundImageCache",false,true)}catch(m){k.cssFlicker=true}}k.fixDoc(o);k.events=l.ownEvents?new e.dom.EventUtils(l.proxy):e.dom.Event;e.addUnload(k.destroy,k);n=l.schema?l.schema.getBlockElements():{};k.isBlock=function(q){if(!q){return false}var p=q.nodeType;if(p){return !!(p===1&&n[q.nodeName])}return !!n[q]}},fixDoc:function(k){var j=this.settings,i;if(b&&!e.isIE11&&j.schema){("abbr article aside audio canvas details figcaption figure footer header hgroup mark menu meter nav output progress section summary time video").replace(/\w+/g,function(l){k.createElement(l)});for(i in j.schema.getCustomElements()){k.createElement(i)}}},clone:function(k,i){var j=this,m,l;if(!b||e.isIE11||k.nodeType!==1||i){return k.cloneNode(i)}l=j.doc;if(!i){m=l.createElement(k.nodeName);g(j.getAttribs(k),function(n){j.setAttrib(m,n.nodeName,j.getAttrib(k,n.nodeName))});return m}return m.firstChild},getRoot:function(){var i=this,j=i.settings;return(j&&i.get(j.root_element))||i.doc.body},getViewPort:function(j){var k,i;j=!j?this.win:j;k=j.document;i=this.boxModel?k.documentElement:k.body;return{x:j.pageXOffset||i.scrollLeft,y:j.pageYOffset||i.scrollTop,w:j.innerWidth||i.clientWidth,h:j.innerHeight||i.clientHeight}},getRect:function(l){var k,i=this,j;l=i.get(l);k=i.getPos(l);j=i.getSize(l);return{x:k.x,y:k.y,w:j.w,h:j.h}},getSize:function(l){var j=this,i,k;l=j.get(l);i=j.getStyle(l,"width");k=j.getStyle(l,"height");if(i.indexOf("px")===-1){i=0}if(k.indexOf("px")===-1){k=0}return{w:parseInt(i,10)||l.offsetWidth||l.clientWidth,h:parseInt(k,10)||l.offsetHeight||l.clientHeight}},getParent:function(k,j,i){return this.getParents(k,j,i,false)},getParents:function(s,m,k,q){var j=this,i,l=j.settings,p=[];s=j.get(s);q=q===undefined;if(l.strict_root){k=k||j.getRoot()}if(d(m,"string")){i=m;if(m==="*"){m=function(o){return o.nodeType==1}}else{m=function(o){return j.is(o,i)}}}while(s){if(s==k||!s.nodeType||s.nodeType===9){break}if(!m||m(s)){if(q){p.push(s)}else{return s}}s=s.parentNode}return q?p:null},get:function(i){var j;if(i&&this.doc&&typeof(i)=="string"){j=i;i=this.doc.getElementById(i);if(i&&i.id!==j){return this.doc.getElementsByName(j)[1]}}return i},getNext:function(j,i){return this._findSib(j,i,"nextSibling")},getPrev:function(j,i){return this._findSib(j,i,"previousSibling")},add:function(l,o,i,k,m){var j=this;return this.run(l,function(r){var q,n;q=d(o,"string")?j.doc.createElement(o):o;j.setAttribs(q,i);if(k){if(k.nodeType){q.appendChild(k)}else{j.setHTML(q,k)}}return !m?r.appendChild(q):q})},create:function(k,i,j){return this.add(this.doc.createElement(k),k,i,j,1)},createHTML:function(q,i,m){var p="",l=this,j;p+="<"+q;for(j in i){if(i.hasOwnProperty(j)){p+=" "+j+'="'+l.encode(i[j])+'"'}}if(typeof(m)!="undefined"){return p+">"+m+""}return p+" />"},remove:function(i,j){return this.run(i,function(l){var m,k=l.parentNode;if(!k){return null}if(j){while(m=l.firstChild){if(!e.isIE||m.nodeType!==3||m.nodeValue){k.insertBefore(m,l)}else{l.removeChild(m)}}}return k.removeChild(l)})},setStyle:function(l,i,j){var k=this;return k.run(l,function(o){var n,m;n=o.style;i=i.replace(/-(\D)/g,function(q,p){return p.toUpperCase()});if(k.pixelStyles.test(i)&&(e.is(j,"number")||/^[\-0-9\.]+$/.test(j))){j+="px"}switch(i){case"opacity":if(b&&!e.isIE11){n.filter=j===""?"":"alpha(opacity="+(j*100)+")";if(!l.currentStyle||!l.currentStyle.hasLayout){n.display="inline-block"}}n[i]=n["-moz-opacity"]=n["-khtml-opacity"]=j||"";break;case"float":(b&&!e.isIE11)?n.styleFloat=j:n.cssFloat=j;break;default:n[i]=j||""}if(k.settings.update_styles){k.setAttrib(o,"data-mce-style")}})},getStyle:function(l,i,k){l=this.get(l);if(!l){return}if(this.doc.defaultView&&k){i=i.replace(/[A-Z]/g,function(m){return"-"+m});try{return this.doc.defaultView.getComputedStyle(l,null).getPropertyValue(i)}catch(j){return null}}i=i.replace(/-(\D)/g,function(n,m){return m.toUpperCase()});if(i=="float"){i=b?"styleFloat":"cssFloat"}if(l.currentStyle&&k){return l.currentStyle[i]}return l.style?l.style[i]:undefined},setStyles:function(l,m){var j=this,k=j.settings,i;i=k.update_styles;k.update_styles=0;g(m,function(o,p){j.setStyle(l,p,o)});k.update_styles=i;if(k.update_styles){j.setAttrib(l,k.cssText)}},removeAllAttribs:function(i){return this.run(i,function(l){var k,j=l.attributes;for(k=j.length-1;k>=0;k--){l.removeAttributeNode(j.item(k))}})},setAttrib:function(k,l,i){var j=this;if(!k||!l){return}if(j.settings.strict){l=l.toLowerCase()}return this.run(k,function(p){var o=j.settings;var m=p.getAttribute(l);if(i!==null){switch(l){case"style":if(!d(i,"string")){g(i,function(q,r){j.setStyle(p,r,q)});return}if(o.keep_values){if(i&&!j._isRes(i)){p.setAttribute("data-mce-style",i,2)}else{p.removeAttribute("data-mce-style",2)}}p.style.cssText=i;break;case"class":p.className=i||"";break;case"src":case"href":if(o.keep_values){if(o.url_converter){i=o.url_converter.call(o.url_converter_scope||j,i,l,p)}j.setAttrib(p,"data-mce-"+l,i,2)}break;case"shape":p.setAttribute("data-mce-style",i);break}}if(d(i)&&i!==null&&i.length!==0){p.setAttribute(l,""+i,2)}else{p.removeAttribute(l,2)}if(tinyMCE.activeEditor&&m!=i){var n=tinyMCE.activeEditor;n.onSetAttrib.dispatch(n,p,l,i)}})},setAttribs:function(j,k){var i=this;return this.run(j,function(l){g(k,function(m,o){i.setAttrib(l,o,m)})})},getAttrib:function(m,o,k){var i,j=this,l;m=j.get(m);if(!m||m.nodeType!==1){return k===l?false:k}if(!d(k)){k=""}if(/^(src|href|style|coords|shape)$/.test(o)){i=m.getAttribute("data-mce-"+o);if(i){return i}}if(b&&j.props[o]){i=m[j.props[o]];i=i&&i.nodeValue?i.nodeValue:i}if(!i){i=m.getAttribute(o,2)}if(/^(checked|compact|declare|defer|disabled|ismap|multiple|nohref|noshade|nowrap|readonly|selected)$/.test(o)){if(m[j.props[o]]===true&&i===""){return o}return i?o:""}if(m.nodeName==="FORM"&&m.getAttributeNode(o)){return m.getAttributeNode(o).nodeValue}if(o==="style"){i=i||m.style.cssText;if(i){i=j.serializeStyle(j.parseStyle(i),m.nodeName);if(j.settings.keep_values&&!j._isRes(i)){m.setAttribute("data-mce-style",i)}}}if(f&&o==="class"&&i){i=i.replace(/(apple|webkit)\-[a-z\-]+/gi,"")}if(b){switch(o){case"rowspan":case"colspan":if(i===1){i=""}break;case"size":if(i==="+0"||i===20||i===0){i=""}break;case"width":case"height":case"vspace":case"checked":case"disabled":case"readonly":if(i===0){i=""}break;case"hspace":if(i===-1){i=""}break;case"maxlength":case"tabindex":if(i===32768||i===2147483647||i==="32768"){i=""}break;case"multiple":case"compact":case"noshade":case"nowrap":if(i===65535){return o}return k;case"shape":i=i.toLowerCase();break;default:if(o.indexOf("on")===0&&i){i=e._replace(/^function\s+\w+\(\)\s+\{\s+(.*)\s+\}$/,"$1",""+i)}}}return(i!==l&&i!==null&&i!=="")?""+i:k},getPos:function(q,l){var j=this,i=0,p=0,m,o=j.doc,k;q=j.get(q);l=l||o.body;if(q){if(q.getBoundingClientRect){q=q.getBoundingClientRect();m=j.boxModel?o.documentElement:o.body;i=q.left+(o.documentElement.scrollLeft||o.body.scrollLeft)-m.clientTop;p=q.top+(o.documentElement.scrollTop||o.body.scrollTop)-m.clientLeft;return{x:i,y:p}}k=q;while(k&&k!=l&&k.nodeType){i+=k.offsetLeft||0;p+=k.offsetTop||0;k=k.offsetParent}k=q.parentNode;while(k&&k!=l&&k.nodeType){i-=k.scrollLeft||0;p-=k.scrollTop||0;k=k.parentNode}}return{x:i,y:p}},parseStyle:function(i){return this.styles.parse(i)},serializeStyle:function(j,i){return this.styles.serialize(j,i)},addStyle:function(j){var k=this.doc,i;styleElm=k.getElementById("mceDefaultStyles");if(!styleElm){styleElm=k.createElement("style"),styleElm.id="mceDefaultStyles";styleElm.type="text/css";i=k.getElementsByTagName("head")[0];if(i.firstChild){i.insertBefore(styleElm,i.firstChild)}else{i.appendChild(styleElm)}}if(styleElm.styleSheet){styleElm.styleSheet.cssText+=j}else{styleElm.appendChild(k.createTextNode(j))}},loadCSS:function(i){var k=this,l=k.doc,j;if(!i){i=""}j=l.getElementsByTagName("head")[0];g(i.split(","),function(m){var n;if(k.files[m]){return}k.files[m]=true;n=k.create("link",{rel:"stylesheet",href:e._addVer(m)});if(b&&!e.isIE11&&l.documentMode&&l.recalc){n.onload=function(){if(l.recalc){l.recalc()}n.onload=null}}j.appendChild(n)})},addClass:function(i,j){return this.run(i,function(k){var l;if(!j){return 0}if(this.hasClass(k,j)){return k.className}l=this.removeClass(k,j);return k.className=(l!=""?(l+" "):"")+j})},removeClass:function(k,l){var i=this,j;return i.run(k,function(n){var m;if(i.hasClass(n,l)){if(!j){j=new RegExp("(^|\\s+)"+l+"(\\s+|$)","g")}m=n.className.replace(j," ");m=e.trim(m!=" "?m:"");n.className=m;if(!m){n.removeAttribute("class");n.removeAttribute("className")}return m}return n.className})},hasClass:function(j,i){j=this.get(j);if(!j||!i){return false}return(" "+j.className+" ").indexOf(" "+i+" ")!==-1},show:function(i){return this.setStyle(i,"display","block")},hide:function(i){return this.setStyle(i,"display","none")},isHidden:function(i){i=this.get(i);return !i||i.style.display=="none"||this.getStyle(i,"display")=="none"},uniqueId:function(i){return(!i?"mce_":i)+(this.counter++)},setHTML:function(k,j){var i=this;return i.run(k,function(m){if(b){while(m.firstChild){m.removeChild(m.firstChild)}try{m.innerHTML="
"+j;m.removeChild(m.firstChild)}catch(l){var n=i.create("div");n.innerHTML="
"+j;g(e.grep(n.childNodes),function(p,o){if(o&&m.canHaveHTML){m.appendChild(p)}})}}else{m.innerHTML=j}return j})},getOuterHTML:function(k){var j,i=this;k=i.get(k);if(!k){return null}if(k.nodeType===1&&i.hasOuterHTML){return k.outerHTML}j=(k.ownerDocument||i.doc).createElement("body");j.appendChild(k.cloneNode(true));return j.innerHTML},setOuterHTML:function(l,j,m){var i=this;function k(p,o,r){var s,q;q=r.createElement("body");q.innerHTML=o;s=q.lastChild;while(s){i.insertAfter(s.cloneNode(true),p);s=s.previousSibling}i.remove(p)}return this.run(l,function(o){o=i.get(o);if(o.nodeType==1){m=m||o.ownerDocument||i.doc;if(b){try{if(b&&o.nodeType==1){o.outerHTML=j}else{k(o,j,m)}}catch(n){k(o,j,m)}}else{k(o,j,m)}}})},decode:h.decode,encode:h.encodeAllRaw,insertAfter:function(i,j){j=this.get(j);return this.run(i,function(l){var k,m;k=j.parentNode;m=j.nextSibling;if(m){k.insertBefore(l,m)}else{k.appendChild(l)}return l})},replace:function(m,l,i){var j=this;if(d(l,"array")){m=m.cloneNode(true)}return j.run(l,function(k){if(i){g(e.grep(k.childNodes),function(n){m.appendChild(n)})}return k.parentNode.replaceChild(m,k)})},rename:function(l,i){var k=this,j;if(l.nodeName!=i.toUpperCase()){j=k.create(i);g(k.getAttribs(l),function(m){k.setAttrib(j,m.nodeName,k.getAttrib(l,m.nodeName))});k.replace(j,l,1)}return j||l},findCommonAncestor:function(k,i){var l=k,j;while(l){j=i;while(j&&l!=j){j=j.parentNode}if(l==j){break}l=l.parentNode}if(!l&&k.ownerDocument){return k.ownerDocument.documentElement}return l},toHex:function(i){var k=/^\s*rgb\s*?\(\s*?([0-9]+)\s*?,\s*?([0-9]+)\s*?,\s*?([0-9]+)\s*?\)\s*$/i.exec(i);function j(l){l=parseInt(l,10).toString(16);return l.length>1?l:"0"+l}if(k){i="#"+j(k[1])+j(k[2])+j(k[3]);return i}return i},getClasses:function(){var n=this,j=[],m,o={},p=n.settings.class_filter,l;if(n.classes){return n.classes}function q(i){g(i.imports,function(s){q(s)});g(i.cssRules||i.rules,function(t){switch(t.type||1){case 1:if(t.selectorText){g(t.selectorText.split(","),function(r){r=r.replace(/^\s*|\s*$|^\s\./g,"");if(/\.mce/.test(r)||!/\.[\w\-]+$/.test(r)){return}l=r;r=e._replace(/.*\.([a-z0-9_\-]+).*/i,"$1",r);if(p&&!(r=p(r,l))){return}if(!o[r]){j.push({"class":r});o[r]=1}})}break;case 3:try{q(t.styleSheet)}catch(s){}break}})}try{g(n.doc.styleSheets,q)}catch(k){}if(j.length>0){n.classes=j}return j},run:function(l,k,j){var i=this,m;if(i.doc&&typeof(l)==="string"){l=i.get(l)}if(!l){return false}j=j||this;if(!l.nodeType&&(l.length||l.length===0)){m=[];g(l,function(o,n){if(o){if(typeof(o)=="string"){o=i.doc.getElementById(o)}m.push(k.call(j,o,n))}});return m}return k.call(j,l)},getAttribs:function(j){var i;j=this.get(j);if(!j){return[]}if(b){i=[];if(j.nodeName=="OBJECT"){return j.attributes}if(j.nodeName==="OPTION"&&this.getAttrib(j,"selected")){i.push({specified:1,nodeName:"selected"})}j.cloneNode(false).outerHTML.replace(/<\/?[\w:\-]+ ?|=[\"][^\"]+\"|=\'[^\']+\'|=[\w\-]+|>/gi,"").replace(/[\w:\-]+/gi,function(k){i.push({specified:1,nodeName:k})});return i}return j.attributes},isEmpty:function(m,k){var r=this,o,n,q,j,l,p=0;m=m.firstChild;if(m){j=new e.dom.TreeWalker(m,m.parentNode);k=k||r.schema?r.schema.getNonEmptyElements():null;do{q=m.nodeType;if(q===1){if(m.getAttribute("data-mce-bogus")){continue}l=m.nodeName.toLowerCase();if(k&&k[l]){if(l==="br"){p++;continue}return false}n=r.getAttribs(m);o=m.attributes.length;while(o--){l=m.attributes[o].nodeName;if(l==="name"||l==="data-mce-bookmark"){return false}}}if(q==8){return false}if((q===3&&!a.test(m.nodeValue))){return false}}while(m=j.next())}return p<=1},destroy:function(j){var i=this;i.win=i.doc=i.root=i.events=i.frag=null;if(!j){e.removeUnload(i.destroy)}},createRng:function(){var i=this.doc;return i.createRange?i.createRange():new e.dom.Range(this)},nodeIndex:function(m,n){var i=0,k,l,j;if(m){for(k=m.nodeType,m=m.previousSibling,l=m;m;m=m.previousSibling){j=m.nodeType;if(n&&j==3){if(j==k||!m.nodeValue.length){continue}}i++;k=j}}return i},split:function(m,l,p){var q=this,i=q.createRng(),n,k,o;function j(v){var t,s=v.childNodes,u=v.nodeType;function x(A){var z=A.previousSibling&&A.previousSibling.nodeName=="SPAN";var y=A.nextSibling&&A.nextSibling.nodeName=="SPAN";return z&&y}if(u==1&&v.getAttribute("data-mce-type")=="bookmark"){return}for(t=s.length-1;t>=0;t--){j(s[t])}if(u!=9){if(u==3&&v.nodeValue.length>0){var r=e.trim(v.nodeValue).length;if(!q.isBlock(v.parentNode)||r>0||r===0&&x(v)){return}}else{if(u==1){s=v.childNodes;if(s.length==1&&s[0]&&s[0].nodeType==1&&s[0].getAttribute("data-mce-type")=="bookmark"){v.parentNode.insertBefore(s[0],v)}if(s.length||/^(br|hr|input|img)$/i.test(v.nodeName)){return}}}q.remove(v)}return v}if(m&&l){i.setStart(m.parentNode,q.nodeIndex(m));i.setEnd(l.parentNode,q.nodeIndex(l));n=i.extractContents();i=q.createRng();i.setStart(l.parentNode,q.nodeIndex(l)+1);i.setEnd(m.parentNode,q.nodeIndex(m)+1);k=i.extractContents();o=m.parentNode;o.insertBefore(j(n),m);if(p){o.replaceChild(p,l)}else{o.insertBefore(l,m)}o.insertBefore(j(k),m);q.remove(m);return p||l}},bind:function(l,i,k,j){return this.events.add(l,i,k,j||this)},unbind:function(k,i,j){return this.events.remove(k,i,j)},fire:function(k,j,i){return this.events.fire(k,j,i)},getContentEditable:function(j){var i;if(j.nodeType!=1){return null}i=j.getAttribute("data-mce-contenteditable");if(i&&i!=="inherit"){return i}return j.contentEditable!=="inherit"?j.contentEditable:null},_findSib:function(l,i,j){var k=this,m=i;if(l){if(d(m,"string")){m=function(n){return k.is(n,i)}}for(l=l[j];l;l=l[j]){if(m(l)){return l}}}return null},_isRes:function(i){return/^(top|left|bottom|right|width|height)/i.test(i)||/;\s*(top|left|bottom|right|width|height)/i.test(i)}});e.DOM=new e.dom.DOMUtils(document,{process_html:0})})(tinymce);(function(a){function b(c){var O=this,e=c.doc,U=0,F=1,j=2,E=true,S=false,W="startOffset",h="startContainer",Q="endContainer",A="endOffset",k=tinymce.extend,n=c.nodeIndex;k(O,{startContainer:e,startOffset:0,endContainer:e,endOffset:0,collapsed:E,commonAncestorContainer:e,START_TO_START:0,START_TO_END:1,END_TO_END:2,END_TO_START:3,setStart:q,setEnd:s,setStartBefore:g,setStartAfter:J,setEndBefore:K,setEndAfter:u,collapse:B,selectNode:y,selectNodeContents:G,compareBoundaryPoints:v,deleteContents:p,extractContents:I,cloneContents:d,insertNode:D,surroundContents:N,cloneRange:L,toStringIE:T});function x(){return e.createDocumentFragment()}function q(X,t){C(E,X,t)}function s(X,t){C(S,X,t)}function g(t){q(t.parentNode,n(t))}function J(t){q(t.parentNode,n(t)+1)}function K(t){s(t.parentNode,n(t))}function u(t){s(t.parentNode,n(t)+1)}function B(t){if(t){O[Q]=O[h];O[A]=O[W]}else{O[h]=O[Q];O[W]=O[A]}O.collapsed=E}function y(t){g(t);u(t)}function G(t){q(t,0);s(t,t.nodeType===1?t.childNodes.length:t.nodeValue.length)}function v(aa,t){var ad=O[h],Y=O[W],ac=O[Q],X=O[A],ab=t.startContainer,af=t.startOffset,Z=t.endContainer,ae=t.endOffset;if(aa===0){return H(ad,Y,ab,af)}if(aa===1){return H(ac,X,ab,af)}if(aa===2){return H(ac,X,Z,ae)}if(aa===3){return H(ad,Y,Z,ae)}}function p(){l(j)}function I(){return l(U)}function d(){return l(F)}function D(aa){var X=this[h],t=this[W],Z,Y;if((X.nodeType===3||X.nodeType===4)&&X.nodeValue){if(!t){X.parentNode.insertBefore(aa,X)}else{if(t>=X.nodeValue.length){c.insertAfter(aa,X)}else{Z=X.splitText(t);X.parentNode.insertBefore(aa,Z)}}}else{if(X.childNodes.length>0){Y=X.childNodes[t]}if(Y){X.insertBefore(aa,Y)}else{X.appendChild(aa)}}}function N(X){var t=O.extractContents();O.insertNode(X);X.appendChild(t);O.selectNode(X)}function L(){return k(new b(c),{startContainer:O[h],startOffset:O[W],endContainer:O[Q],endOffset:O[A],collapsed:O.collapsed,commonAncestorContainer:O.commonAncestorContainer})}function P(t,X){var Y;if(t.nodeType==3){return t}if(X<0){return t}Y=t.firstChild;while(Y&&X>0){--X;Y=Y.nextSibling}if(Y){return Y}return t}function m(){return(O[h]==O[Q]&&O[W]==O[A])}function H(Z,ab,X,aa){var ac,Y,t,ad,af,ae;if(Z==X){if(ab==aa){return 0}if(ab0){O.collapse(X)}}else{O.collapse(X)}O.collapsed=m();O.commonAncestorContainer=c.findCommonAncestor(O[h],O[Q])}function l(ad){var ac,Z=0,af=0,X,ab,Y,aa,t,ae;if(O[h]==O[Q]){return f(ad)}for(ac=O[Q],X=ac.parentNode;X;ac=X,X=X.parentNode){if(X==O[h]){return r(ac,ad)}++Z}for(ac=O[h],X=ac.parentNode;X;ac=X,X=X.parentNode){if(X==O[Q]){return V(ac,ad)}++af}ab=af-Z;Y=O[h];while(ab>0){Y=Y.parentNode;ab--}aa=O[Q];while(ab<0){aa=aa.parentNode;ab++}for(t=Y.parentNode,ae=aa.parentNode;t!=ae;t=t.parentNode,ae=ae.parentNode){Y=t;aa=ae}return o(Y,aa,ad)}function f(ac){var ae,af,t,Y,Z,ad,aa,X,ab;if(ac!=j){ae=x()}if(O[W]==O[A]){return ae}if(O[h].nodeType==3){af=O[h].nodeValue;t=af.substring(O[W],O[A]);if(ac!=F){Y=O[h];X=O[W];ab=O[A]-O[W];if(X===0&&ab>=Y.nodeValue.length-1){Y.parentNode.removeChild(Y)}else{Y.deleteData(X,ab)}O.collapse(E)}if(ac==j){return}if(t.length>0){ae.appendChild(e.createTextNode(t))}return ae}Y=P(O[h],O[W]);Z=O[A]-O[W];while(Y&&Z>0){ad=Y.nextSibling;aa=z(Y,ac);if(ae){ae.appendChild(aa)}--Z;Y=ad}if(ac!=F){O.collapse(E)}return ae}function r(ad,aa){var ac,ab,X,t,Z,Y;if(aa!=j){ac=x()}ab=i(ad,aa);if(ac){ac.appendChild(ab)}X=n(ad);t=X-O[W];if(t<=0){if(aa!=F){O.setEndBefore(ad);O.collapse(S)}return ac}ab=ad.previousSibling;while(t>0){Z=ab.previousSibling;Y=z(ab,aa);if(ac){ac.insertBefore(Y,ac.firstChild)}--t;ab=Z}if(aa!=F){O.setEndBefore(ad);O.collapse(S)}return ac}function V(ab,aa){var ad,X,ac,t,Z,Y;if(aa!=j){ad=x()}ac=R(ab,aa);if(ad){ad.appendChild(ac)}X=n(ab);++X;t=O[A]-X;ac=ab.nextSibling;while(ac&&t>0){Z=ac.nextSibling;Y=z(ac,aa);if(ad){ad.appendChild(Y)}--t;ac=Z}if(aa!=F){O.setStartAfter(ab);O.collapse(E)}return ad}function o(ab,t,ae){var Y,ag,aa,ac,ad,X,af,Z;if(ae!=j){ag=x()}Y=R(ab,ae);if(ag){ag.appendChild(Y)}aa=ab.parentNode;ac=n(ab);ad=n(t);++ac;X=ad-ac;af=ab.nextSibling;while(X>0){Z=af.nextSibling;Y=z(af,ae);if(ag){ag.appendChild(Y)}af=Z;--X}Y=i(t,ae);if(ag){ag.appendChild(Y)}if(ae!=F){O.setStartAfter(ab);O.collapse(E)}return ag}function i(ac,ad){var Y=P(O[Q],O[A]-1),ae,ab,aa,t,X,Z=Y!=O[Q];if(Y==ac){return M(Y,Z,S,ad)}ae=Y.parentNode;ab=M(ae,S,S,ad);while(ae){while(Y){aa=Y.previousSibling;t=M(Y,Z,S,ad);if(ad!=j){ab.insertBefore(t,ab.firstChild)}Z=E;Y=aa}if(ae==ac){return ab}Y=ae.previousSibling;ae=ae.parentNode;X=M(ae,S,S,ad);if(ad!=j){X.appendChild(ab)}ab=X}}function R(ac,ad){var Z=P(O[h],O[W]),aa=Z!=O[h],ae,ab,Y,t,X;if(Z==ac){return M(Z,aa,E,ad)}ae=Z.parentNode;ab=M(ae,S,E,ad);while(ae){while(Z){Y=Z.nextSibling;t=M(Z,aa,E,ad);if(ad!=j){ab.appendChild(t)}aa=E;Z=Y}if(ae==ac){return ab}Z=ae.nextSibling;ae=ae.parentNode;X=M(ae,S,E,ad);if(ad!=j){X.appendChild(ab)}ab=X}}function M(t,aa,ad,ae){var Z,Y,ab,X,ac;if(aa){return z(t,ae)}if(t.nodeType==3){Z=t.nodeValue;if(ad){X=O[W];Y=Z.substring(X);ab=Z.substring(0,X)}else{X=O[A];Y=Z.substring(0,X);ab=Z.substring(X)}if(ae!=F){t.nodeValue=ab}if(ae==j){return}ac=c.clone(t,S);ac.nodeValue=Y;return ac}if(ae==j){return}return c.clone(t,S)}function z(X,t){if(t!=j){return t==F?c.clone(X,E):X}X.parentNode.removeChild(X)}function T(){return c.create("body",null,d()).outerText}return O}a.Range=b;b.prototype.toString=function(){return this.toStringIE()}})(tinymce.dom);(function(){function a(d){var b=this,h=d.dom,c=true,f=false;function e(i,j){var k,t=0,q,n,m,l,o,r,p=-1,s;k=i.duplicate();k.collapse(j);s=k.parentElement();if(s.ownerDocument!==d.dom.doc){return}while(s.contentEditable==="false"){s=s.parentNode}if(!s.hasChildNodes()){return{node:s,inside:1}}m=s.children;q=m.length-1;while(t<=q){r=Math.floor((t+q)/2);l=m[r];k.moveToElementText(l);p=k.compareEndPoints(j?"StartToStart":"EndToEnd",i);if(p>0){q=r-1}else{if(p<0){t=r+1}else{return{node:l}}}}if(p<0){if(!l){k.moveToElementText(s);k.collapse(true);l=s;n=true}else{k.collapse(false)}o=0;while(k.compareEndPoints(j?"StartToStart":"StartToEnd",i)!==0){if(k.move("character",1)===0||s!=k.parentElement()){break}o++}}else{k.collapse(true);o=0;while(k.compareEndPoints(j?"StartToStart":"StartToEnd",i)!==0){if(k.move("character",-1)===0||s!=k.parentElement()){break}o++}}return{node:l,position:p,offset:o,inside:n}}function g(){var i=d.getRng(),r=h.createRng(),l,k,p,q,m,j;l=i.item?i.item(0):i.parentElement();if(l.ownerDocument!=h.doc){return r}k=d.isCollapsed();if(i.item){r.setStart(l.parentNode,h.nodeIndex(l));r.setEnd(r.startContainer,r.startOffset+1);return r}function o(A){var u=e(i,A),s,y,z=0,x,v,t;s=u.node;y=u.offset;if(u.inside&&!s.hasChildNodes()){r[A?"setStart":"setEnd"](s,0);return}if(y===v){r[A?"setStartBefore":"setEndAfter"](s);return}if(u.position<0){x=u.inside?s.firstChild:s.nextSibling;if(!x){r[A?"setStartAfter":"setEndAfter"](s);return}if(!y){if(x.nodeType==3){r[A?"setStart":"setEnd"](x,0)}else{r[A?"setStartBefore":"setEndBefore"](x)}return}while(x){t=x.nodeValue;z+=t.length;if(z>=y){s=x;z-=y;z=t.length-z;break}x=x.nextSibling}}else{x=s.previousSibling;if(!x){return r[A?"setStartBefore":"setEndBefore"](s)}if(!y){if(s.nodeType==3){r[A?"setStart":"setEnd"](x,s.nodeValue.length)}else{r[A?"setStartAfter":"setEndAfter"](x)}return}while(x){z+=x.nodeValue.length;if(z>=y){s=x;z-=y;break}x=x.previousSibling}}r[A?"setStart":"setEnd"](s,z)}try{o(true);if(!k){o()}}catch(n){if(n.number==-2147024809){m=b.getBookmark(2);p=i.duplicate();p.collapse(true);l=p.parentElement();if(!k){p=i.duplicate();p.collapse(false);q=p.parentElement();q.innerHTML=q.innerHTML}l.innerHTML=l.innerHTML;b.moveToBookmark(m);i=d.getRng();o(true);if(!k){o()}}else{throw n}}return r}this.getBookmark=function(m){var j=d.getRng(),o,i,l={};function n(u){var t,p,s,r,q=[];t=u.parentNode;p=h.getRoot().parentNode;while(t!=p&&t.nodeType!==9){s=t.children;r=s.length;while(r--){if(u===s[r]){q.push(r);break}}u=t;t=t.parentNode}return q}function k(q){var p;p=e(j,q);if(p){return{position:p.position,offset:p.offset,indexes:n(p.node),inside:p.inside}}}if(m===2){if(!j.item){l.start=k(true);if(!d.isCollapsed()){l.end=k()}}else{l.start={ctrl:true,indexes:n(j.item(0))}}}return l};this.moveToBookmark=function(k){var j,i=h.doc.body;function m(o){var r,q,n,p;r=h.getRoot();for(q=o.length-1;q>=0;q--){p=r.children;n=o[q];if(n<=p.length-1){r=p[n]}}return r}function l(r){var n=k[r?"start":"end"],q,p,o;if(n){q=n.position>0;p=i.createTextRange();p.moveToElementText(m(n.indexes));offset=n.offset;if(offset!==o){p.collapse(n.inside||q);p.moveStart("character",q?-offset:offset)}else{p.collapse(r)}j.setEndPoint(r?"StartToStart":"EndToStart",p);if(r){j.collapse(true)}}}if(k.start){if(k.start.ctrl){j=i.createControlRange();j.addElement(m(k.start.indexes));j.select()}else{j=i.createTextRange();l(true);l();j.select()}}};this.addRange=function(i){var n,l,k,p,v,q,t,s=d.dom.doc,m=s.body,r,u;function j(C){var y,B,x,A,z;x=h.create("a");y=C?k:v;B=C?p:q;A=n.duplicate();if(y==s||y==s.documentElement){y=m;B=0}if(y.nodeType==3){y.parentNode.insertBefore(x,y);A.moveToElementText(x);A.moveStart("character",B);h.remove(x);n.setEndPoint(C?"StartToStart":"EndToEnd",A)}else{z=y.childNodes;if(z.length){if(B>=z.length){h.insertAfter(x,z[z.length-1])}else{y.insertBefore(x,z[B])}A.moveToElementText(x)}else{if(y.canHaveHTML){y.innerHTML="\uFEFF";x=y.firstChild;A.moveToElementText(x);A.collapse(f)}}n.setEndPoint(C?"StartToStart":"EndToEnd",A);h.remove(x)}}k=i.startContainer;p=i.startOffset;v=i.endContainer;q=i.endOffset;n=m.createTextRange();if(k==v&&k.nodeType==1){if(p==q&&!k.hasChildNodes()){if(k.canHaveHTML){t=k.previousSibling;if(t&&!t.hasChildNodes()&&h.isBlock(t)){t.innerHTML="\uFEFF"}else{t=null}k.innerHTML="\uFEFF\uFEFF";n.moveToElementText(k.lastChild);n.select();h.doc.selection.clear();k.innerHTML="";if(t){t.innerHTML=""}return}else{p=h.nodeIndex(k);k=k.parentNode}}if(p==q-1){try{u=k.childNodes[p];l=m.createControlRange();l.addElement(u);l.select();r=d.getRng();if(r.item&&u===r.item(0)){return}}catch(o){}}}j(true);j();n.select()};this.getRangeAt=g}tinymce.dom.TridentSelection=a})();(function(a){a.dom.Element=function(f,d){var b=this,e,c;b.settings=d=d||{};b.id=f;b.dom=e=d.dom||a.DOM;if(!a.isIE){c=e.get(b.id)}a.each(("getPos,getRect,getParent,add,setStyle,getStyle,setStyles,setAttrib,setAttribs,getAttrib,addClass,removeClass,hasClass,getOuterHTML,setOuterHTML,remove,show,hide,isHidden,setHTML,get").split(/,/),function(g){b[g]=function(){var h=[f],j;for(j=0;j"+(i.item?i.item(0).outerHTML:i.htmlText);m.removeChild(m.firstChild)}else{m.innerHTML=i.toString()}}if(/^\s/.test(m.innerHTML)){j=" "}if(/\s+$/.test(m.innerHTML)){l=" "}h.getInner=true;h.content=g.isCollapsed()?"":j+g.serializer.serialize(m,h)+l;g.onGetContent.dispatch(g,h);return h.content},setContent:function(h,j){var o=this,g=o.getRng(),k,l=o.win.document,n,m;j=j||{format:"html"};j.set=true;h=j.content=h;if(!j.no_events){o.onBeforeSetContent.dispatch(o,j)}h=j.content;if(g.insertNode){h+='_';if(g.startContainer==l&&g.endContainer==l){l.body.innerHTML=h}else{g.deleteContents();if(l.body.childNodes.length===0){l.body.innerHTML=h}else{if(g.createContextualFragment){g.insertNode(g.createContextualFragment(h))}else{n=l.createDocumentFragment();m=l.createElement("div");n.appendChild(m);m.outerHTML=h;g.insertNode(n)}}}k=o.dom.get("__caret");g=l.createRange();g.setStartBefore(k);g.setEndBefore(k);o.setRng(g);o.dom.remove("__caret");try{o.setRng(g)}catch(i){}}else{if(g.item){l.execCommand("Delete",false,null);g=o.getRng()}if(/^\s+/.test(h)){g.pasteHTML('_'+h);o.dom.remove("__mce_tmp")}else{g.pasteHTML(h)}}if(!j.no_events){o.onSetContent.dispatch(o,j)}},getStart:function(){var i=this,h=i.getRng(),j,g,l,k;if(h.duplicate||h.item){if(h.item){return h.item(0)}l=h.duplicate();l.collapse(1);j=l.parentElement();if(j.ownerDocument!==i.dom.doc){j=i.dom.getRoot()}g=k=h.parentElement();while(k=k.parentNode){if(k==j){j=g;break}}return j}else{j=h.startContainer;if(j.nodeType==1&&j.hasChildNodes()){j=j.childNodes[Math.min(j.childNodes.length-1,h.startOffset)]}if(j&&j.nodeType==3){return j.parentNode}return j}},getEnd:function(){var h=this,g=h.getRng(),j,i;if(g.duplicate||g.item){if(g.item){return g.item(0)}g=g.duplicate();g.collapse(0);j=g.parentElement();if(j.ownerDocument!==h.dom.doc){j=h.dom.getRoot()}if(j&&j.nodeName=="BODY"){return j.lastChild||j}return j}else{j=g.endContainer;i=g.endOffset;if(j.nodeType==1&&j.hasChildNodes()){j=j.childNodes[i>0?i-1:i]}if(j&&j.nodeType==3){return j.parentNode}return j}},getBookmark:function(s,v){var y=this,n=y.dom,h,k,j,o,i,p,q,m="\uFEFF",x;function g(z,A){var t=0;e(n.select(z),function(C,B){if(C==A){t=B}});return t}function u(t){function z(E){var A,D,C,B=E?"start":"end";A=t[B+"Container"];D=t[B+"Offset"];if(A.nodeType==1&&A.nodeName=="TR"){C=A.childNodes;A=C[Math.min(E?D:D-1,C.length-1)];if(A){D=E?0:A.childNodes.length;t["set"+(E?"Start":"End")](A,D)}}}z(true);z();return t}function l(){var z=y.getRng(true),t=n.getRoot(),A={};function B(E,J){var D=E[J?"startContainer":"endContainer"],I=E[J?"startOffset":"endOffset"],C=[],F,H,G=0;if(D.nodeType==3){if(v){for(F=D.previousSibling;F&&F.nodeType==3;F=F.previousSibling){I+=F.nodeValue.length}}C.push(I)}else{H=D.childNodes;if(I>=H.length&&H.length){G=1;I=Math.max(0,H.length-1)}C.push(y.dom.nodeIndex(H[I],v)+G)}for(;D&&D!=t;D=D.parentNode){C.push(y.dom.nodeIndex(D,v))}return C}A.start=B(z,true);if(!y.isCollapsed()){A.end=B(z)}return A}if(s==2){if(y.tridentSel){return y.tridentSel.getBookmark(s)}return l()}if(s){h=y.getRng();if(h.setStart){h={startContainer:h.startContainer,startOffset:h.startOffset,endContainer:h.endContainer,endOffset:h.endOffset}}return{rng:h}}h=y.getRng();j=n.uniqueId();o=tinyMCE.activeEditor.selection.isCollapsed();x="overflow:hidden;line-height:0px";if(h.duplicate||h.item){if(!h.item){k=h.duplicate();try{h.collapse();h.pasteHTML(''+m+"");if(!o){k.collapse(false);h.moveToElementText(k.parentElement());if(h.compareEndPoints("StartToEnd",k)===0){k.move("character",-1)}k.pasteHTML(''+m+"")}}catch(r){return null}}else{p=h.item(0);i=p.nodeName;return{name:i,index:g(i,p)}}}else{p=y.getNode();i=p.nodeName;if(i=="IMG"){return{name:i,index:g(i,p)}}k=u(h.cloneRange());if(!o){k.collapse(false);k.insertNode(n.create("span",{"data-mce-type":"bookmark",id:j+"_end",style:x},m))}h=u(h);h.collapse(true);h.insertNode(n.create("span",{"data-mce-type":"bookmark",id:j+"_start",style:x},m))}y.moveToBookmark({id:j,keep:1});return{id:j}},moveToBookmark:function(q){var v=this,n=v.dom,l,j,g,i,u,k,x,r,s;function h(C){var t=q[C?"start":"end"],z,A,B,y;if(t){B=t[0];for(A=u,z=t.length-1;z>=1;z--){y=A.childNodes;if(t[z]>y.length-1){return}A=y[t[z]]}if(A.nodeType===3){B=Math.min(t[0],A.nodeValue.length)}if(A.nodeType===1){B=Math.min(t[0],A.childNodes.length)}if(C){g.setStart(A,B)}else{g.setEnd(A,B)}}return true}function m(D){var y=n.get(q.id+"_"+D),C,t,A,B,z=q.keep;if(y){C=y.parentNode;if(D=="start"){if(!z){t=n.nodeIndex(y)}else{C=y.firstChild;t=1}k=x=C;r=s=t}else{if(!z){t=n.nodeIndex(y)}else{C=y.firstChild;t=1}x=C;s=t}if(!z){B=y.previousSibling;A=y.nextSibling;e(d.grep(y.childNodes),function(E){if(E.nodeType==3){E.nodeValue=E.nodeValue.replace(/\uFEFF/g,"")}});while(y=n.get(q.id+"_"+D)){n.remove(y,1)}if(B&&A&&B.nodeType==A.nodeType&&B.nodeType==3&&!d.isOpera){t=B.nodeValue.length;B.appendData(A.nodeValue);n.remove(A);if(D=="start"){k=x=B;r=s=t}else{x=B;s=t}}}}}function o(t){if(n.isBlock(t)&&!t.innerHTML&&!b){t.innerHTML='
'}return t}if(q){if(q.start){g=n.createRng();u=n.getRoot();if(v.tridentSel){return v.tridentSel.moveToBookmark(q)}if(h(true)&&h()){v.setRng(g)}}else{if(q.id){m("start");m("end");if(k){g=n.createRng();g.setStart(o(k),r);g.setEnd(o(x),s);v.setRng(g)}}else{if(q.name){v.select(n.select(q.name)[q.index])}else{if(q.rng){g=q.rng;if(g.startContainer){i=v.dom.createRng();try{i.setStart(g.startContainer,g.startOffset);i.setEnd(g.endContainer,g.endOffset)}catch(p){}g=i}v.setRng(g)}}}}}},select:function(l,k){var j=this,m=j.dom,h=m.createRng(),g;function i(n,p){var o=new a(n,n);do{if(n.nodeType==3&&d.trim(n.nodeValue).length!==0){if(p){h.setStart(n,0)}else{h.setEnd(n,n.nodeValue.length)}return}if(n.nodeName=="BR"){if(p){h.setStartBefore(n)}else{h.setEndBefore(n)}return}}while(n=(p?o.next():o.prev()))}if(l){g=m.nodeIndex(l);h.setStart(l.parentNode,g);h.setEnd(l.parentNode,g+1);if(k){i(l,1);i(l)}j.setRng(h)}return l},isCollapsed:function(){var g=this,i=g.getRng(),h=g.getSel();if(!i||i.item){return false}if(i.compareEndPoints){return i.compareEndPoints("StartToEnd",i)===0}return !h||i.collapsed},collapse:function(g){var i=this,h=i.getRng(),j;if(h.item){j=h.item(0);h=i.win.document.body.createTextRange();h.moveToElementText(j)}h.collapse(!!g);i.setRng(h)},getSel:function(){var h=this,g=this.win;return g.getSelection?g.getSelection():g.document.selection},getRng:function(m){var h=this,j,g,l,k=h.win.document;if(h.fakeRng){return h.fakeRng}if(m&&h.tridentSel){return h.tridentSel.getRangeAt(0)}try{if(j=h.getSel()){g=j.rangeCount>0?j.getRangeAt(0):(j.createRange?j.createRange():k.createRange())}}catch(i){}if(d.isIE&&!d.isIE11&&g&&g.setStart&&k.selection.createRange().item){l=k.selection.createRange().item(0);g=k.createRange();g.setStartBefore(l);g.setEndAfter(l)}if(!g){g=k.createRange?k.createRange():k.body.createTextRange()}if(g.setStart&&g.startContainer.nodeType===9&&g.collapsed){l=h.dom.getRoot();g.setStart(l,0);g.setEnd(l,0)}if(h.selectedRange&&h.explicitRange){if(g.compareBoundaryPoints(g.START_TO_START,h.selectedRange)===0&&g.compareBoundaryPoints(g.END_TO_END,h.selectedRange)===0){g=h.explicitRange}else{h.selectedRange=null;h.explicitRange=null}}return g},setRng:function(k,g){var j,i=this;if(!i.tridentSel){j=i.getSel();if(j){i.explicitRange=k;try{j.removeAllRanges()}catch(h){}j.addRange(k);if(g===false&&j.extend){j.collapse(k.endContainer,k.endOffset);j.extend(k.startContainer,k.startOffset)}i.selectedRange=j.rangeCount>0?j.getRangeAt(0):null}}else{if(k.cloneRange){try{i.tridentSel.addRange(k);return}catch(h){}}try{k.select()}catch(h){}}},setNode:function(h){var g=this;g.setContent(g.dom.getOuterHTML(h));return h},getNode:function(){var i=this,h=i.getRng(),j=i.getSel(),m,l=h.startContainer,g=h.endContainer;function k(q,o){var p=q;while(q&&q.nodeType===3&&q.length===0){q=o?q.nextSibling:q.previousSibling}return q||p}if(!h){return i.dom.getRoot()}if(h.setStart){m=h.commonAncestorContainer;if(!h.collapsed){if(h.startContainer==h.endContainer){if(h.endOffset-h.startOffset<2){if(h.startContainer.hasChildNodes()){m=h.startContainer.childNodes[h.startOffset]}}}if(l.nodeType===3&&g.nodeType===3){if(l.length===h.startOffset){l=k(l.nextSibling,true)}else{l=l.parentNode}if(h.endOffset===0){g=k(g.previousSibling,false)}else{g=g.parentNode}if(l&&l===g){return l}}}if(m&&m.nodeType==3){return m.parentNode}return m}return h.item?h.item(0):h.parentElement()},getSelectedBlocks:function(p,h){var o=this,k=o.dom,m,l,i,j=[];m=k.getParent(p||o.getStart(),k.isBlock);l=k.getParent(h||o.getEnd(),k.isBlock);if(m){j.push(m)}if(m&&l&&m!=l){i=m;var g=new a(m,k.getRoot());while((i=g.next())&&i!=l){if(k.isBlock(i)){j.push(i)}}}if(l&&m!=l){j.push(l)}return j},isForward:function(){var i=this.dom,g=this.getSel(),j,h;if(!g||g.anchorNode==null||g.focusNode==null){return true}j=i.createRng();j.setStart(g.anchorNode,g.anchorOffset);j.collapse(true);h=i.createRng();h.setStart(g.focusNode,g.focusOffset);h.collapse(true);return j.compareBoundaryPoints(j.START_TO_START,h)<=0},normalize:function(){var h=this,g,m,l,j,i;function k(p){var o,r,n,s=h.dom,u=s.getRoot(),q,t,v;function y(z,A){var B=new a(z,s.getParent(z.parentNode,s.isBlock)||u);while(z=B[A?"prev":"next"]()){if(z.nodeName==="BR"){return true}}}function x(B,z){var C,A;z=z||o;C=new a(z,s.getParent(z.parentNode,s.isBlock)||u);while(q=C[B?"prev":"next"]()){if(q.nodeType===3&&q.nodeValue.length>0){o=q;r=B?q.nodeValue.length:0;m=true;return}if(s.isBlock(q)||t[q.nodeName.toLowerCase()]){return}A=q}if(l&&A){o=A;m=true;r=0}}o=g[(p?"start":"end")+"Container"];r=g[(p?"start":"end")+"Offset"];t=s.schema.getNonEmptyElements();if(o.nodeType===9){o=s.getRoot();r=0}if(o===u){if(p){q=o.childNodes[r>0?r-1:0];if(q){v=q.nodeName.toLowerCase();if(t[q.nodeName]||q.nodeName=="TABLE"){return}}}if(o.hasChildNodes()){o=o.childNodes[Math.min(!p&&r>0?r-1:r,o.childNodes.length-1)];r=0;if(o.hasChildNodes()&&!/TABLE/.test(o.nodeName)){q=o;n=new a(o,u);do{if(q.nodeType===3&&q.nodeValue.length>0){r=p?0:q.nodeValue.length;o=q;m=true;break}if(t[q.nodeName.toLowerCase()]){r=s.nodeIndex(q);o=q.parentNode;if(q.nodeName=="IMG"&&!p){r++}m=true;break}}while(q=(p?n.next():n.prev()))}}}if(l){if(o.nodeType===3&&r===0){x(true)}if(o.nodeType===1){q=o.childNodes[r];if(q&&q.nodeName==="BR"&&!y(q)&&!y(q,true)){x(true,o.childNodes[r])}}}if(p&&!l&&o.nodeType===3&&r===o.nodeValue.length){x(false)}if(m){g["set"+(p?"Start":"End")](o,r)}}if(d.isIE){return}g=h.getRng();l=g.collapsed;k(true);if(!l){k()}if(m){if(l){g.collapse(true)}h.setRng(g,h.isForward())}},selectorChanged:function(g,j){var h=this,i;if(!h.selectorChangedData){h.selectorChangedData={};i={};h.editor.onNodeChange.addToTop(function(l,k,o){var p=h.dom,m=p.getParents(o,null,p.getRoot()),n={};e(h.selectorChangedData,function(r,q){e(m,function(s){if(p.is(s,q)){if(!i[q]){e(r,function(t){t(true,{node:s,selector:q,parents:m})});i[q]=r}n[q]=r;return false}})});e(i,function(r,q){if(!n[q]){delete i[q];e(r,function(s){s(false,{node:o,selector:q,parents:m})})}})})}if(!h.selectorChangedData[g]){h.selectorChangedData[g]=[]}h.selectorChangedData[g].push(j);return h},scrollIntoView:function(k){var j,h,g=this,i=g.dom;h=i.getViewPort(g.editor.getWin());j=i.getPos(k).y;if(jh.y+h.h){g.editor.getWin().scrollTo(0,j0){p.setEndPoint("StartToStart",o)}else{p.setEndPoint("EndToEnd",o)}p.select()}}else{l()}}function l(){var p=n.selection.createRange();if(o&&!p.item&&p.compareEndPoints("StartToEnd",p)===0){o.select()}h.unbind(n,"mouseup",l);h.unbind(n,"mousemove",m);o=k=0}n.documentElement.unselectable=true;h.bind(n,["mousedown","contextmenu"],function(p){if(p.target.nodeName==="HTML"){if(k){l()}g=n.documentElement;if(g.scrollHeight>g.clientHeight){return}k=1;o=j(p.x,p.y);if(o){h.bind(n,"mouseup",l);h.bind(n,"mousemove",m);h.win.focus();o.select()}}})}})})(tinymce);(function(a){a.dom.Serializer=function(e,i,f){var h,b,d=a.isIE,g=a.each,c;if(!e.apply_source_formatting){e.indent=false}i=i||a.DOM;f=f||new a.html.Schema(e);e.entity_encoding=e.entity_encoding||"named";e.remove_trailing_brs="remove_trailing_brs" in e?e.remove_trailing_brs:true;h=new a.util.Dispatcher(self);b=new a.util.Dispatcher(self);c=new a.html.DomParser(e,f);c.addAttributeFilter("src,href,style",function(k,j){var o=k.length,l,q,n="data-mce-"+j,p=e.url_converter,r=e.url_converter_scope,m;while(o--){l=k[o];q=l.attributes.map[n];if(q!==m){l.attr(j,q.length>0?q:null);l.attr(n,null)}else{q=l.attributes.map[j];if(j==="style"){q=i.serializeStyle(i.parseStyle(q),l.name)}else{if(p){q=p.call(r,q,j,l.name)}}l.attr(j,q.length>0?q:null)}}});c.addAttributeFilter("class",function(j,k){var l=j.length,m,n;while(l--){m=j[l];n=m.attr("class").replace(/(?:^|\s)mce(Item\w+|Selected)(?!\S)/g,"");m.attr("class",n.length>0?n:null)}});c.addAttributeFilter("data-mce-type",function(j,l,k){var m=j.length,n;while(m--){n=j[m];if(n.attributes.map["data-mce-type"]==="bookmark"&&!k.cleanup){n.remove()}}});c.addAttributeFilter("data-mce-expando",function(j,l,k){var m=j.length;while(m--){j[m].attr(l,null)}});c.addNodeFilter("noscript",function(j){var k=j.length,l;while(k--){l=j[k].firstChild;if(l){l.value=a.html.Entities.decode(l.value)}}});c.addNodeFilter("script,style",function(k,l){var m=k.length,n,o;function j(p){return p.replace(/()/g,"\n").replace(/^[\r\n]*|[\r\n]*$/g,"").replace(/^\s*(()?|\s*\/\/\s*\]\]>(-->)?|\/\/\s*(-->)?|\]\]>|\/\*\s*-->\s*\*\/|\s*-->\s*)\s*$/g,"")}while(m--){n=k[m];o=n.firstChild?n.firstChild.value:"";if(l==="script"){n.attr("type",(n.attr("type")||"text/javascript").replace(/^mce\-/,""));if(o.length>0){n.firstChild.value="// "}}else{if(o.length>0){n.firstChild.value=""}}}});c.addNodeFilter("#comment",function(j,k){var l=j.length,m;while(l--){m=j[l];if(m.value.indexOf("[CDATA[")===0){m.name="#cdata";m.type=4;m.value=m.value.replace(/^\[CDATA\[|\]\]$/g,"")}else{if(m.value.indexOf("mce:protected ")===0){m.name="#text";m.type=3;m.raw=true;m.value=unescape(m.value).substr(14)}}}});c.addNodeFilter("xml:namespace,input",function(j,k){var l=j.length,m;while(l--){m=j[l];if(m.type===7){m.remove()}else{if(m.type===1){if(k==="input"&&!("type" in m.attributes.map)){m.attr("type","text")}}}}});if(e.fix_list_elements){c.addNodeFilter("ul,ol",function(k,l){var m=k.length,n,j;while(m--){n=k[m];j=n.parent;if(j.name==="ul"||j.name==="ol"){if(n.prev&&n.prev.name==="li"){n.prev.append(n)}}}})}c.addAttributeFilter("data-mce-src,data-mce-href,data-mce-style",function(j,k){var l=j.length;while(l--){j[l].attr(k,null)}});return{schema:f,addNodeFilter:c.addNodeFilter,addAttributeFilter:c.addAttributeFilter,onPreProcess:h,onPostProcess:b,serialize:function(o,m){var l,p,k,j,n;if(d&&i.select("script,style,select,map").length>0){n=o.innerHTML;o=o.cloneNode(false);i.setHTML(o,n)}else{o=o.cloneNode(true)}l=o.ownerDocument.implementation;if(l.createHTMLDocument){p=l.createHTMLDocument("");g(o.nodeName=="BODY"?o.childNodes:[o],function(q){p.body.appendChild(p.importNode(q,true))});if(o.nodeName!="BODY"){o=p.body.firstChild}else{o=p.body}k=i.doc;i.doc=p}m=m||{};m.format=m.format||"html";if(!m.no_events){m.node=o;h.dispatch(self,m)}j=new a.html.Serializer(e,f);m.content=j.serialize(c.parse(a.trim(m.getInner?o.innerHTML:i.getOuterHTML(o)),m));if(!m.cleanup){m.content=m.content.replace(/\uFEFF/g,"")}if(!m.no_events){b.dispatch(self,m)}if(k){i.doc=k}m.node=null;return m.content},addRules:function(j){f.addValidElements(j)},setRules:function(j){f.setValidElements(j)}}}})(tinymce);(function(a){a.dom.ScriptLoader=function(h){var c=0,k=1,i=2,l={},j=[],e={},d=[],g=0,f;function b(m,v){var x=this,q=a.DOM,s,o,r,n;function p(){q.remove(n);if(s){s.onreadystatechange=s.onload=s=null}v()}function u(){if(typeof(console)!=="undefined"&&console.log){console.log("Failed to load: "+m)}}n=q.uniqueId();if(a.isIE6){o=new a.util.URI(m);r=location;if(o.host==r.hostname&&o.port==r.port&&(o.protocol+":")==r.protocol&&o.protocol.toLowerCase()!="file"){a.util.XHR.send({url:a._addVer(o.getURI()),success:function(y){var t=q.create("script",{type:"text/javascript"});t.text=y;document.getElementsByTagName("head")[0].appendChild(t);q.remove(t);p()},error:u});return}}s=document.createElement("script");s.id=n;s.type="text/javascript";s.src=a._addVer(m);if(!a.isIE||a.isIE11){s.onload=p}s.onerror=u;if(!a.isOpera){s.onreadystatechange=function(){var t=s.readyState;if(t=="complete"||t=="loaded"){p()}}}(document.getElementsByTagName("head")[0]||document.body).appendChild(s)}this.isDone=function(m){return l[m]==i};this.markDone=function(m){l[m]=i};this.add=this.load=function(m,q,n){var o,p=l[m];if(p==f){j.push(m);l[m]=c}if(q){if(!e[m]){e[m]=[]}e[m].push({func:q,scope:n||this})}};this.loadQueue=function(n,m){this.loadScripts(j,n,m)};this.loadScripts=function(m,q,p){var o;function n(r){a.each(e[r],function(s){s.func.call(s.scope)});e[r]=f}d.push({func:q,scope:p||this});o=function(){var r=a.grep(m);m.length=0;a.each(r,function(s){if(l[s]==i){n(s);return}if(l[s]!=k){l[s]=k;g++;b(s,function(){l[s]=i;g--;n(s);o()})}});if(!g){a.each(d,function(s){s.func.call(s.scope)});d.length=0}};o()}};a.ScriptLoader=new a.dom.ScriptLoader()})(tinymce);(function(a){a.dom.RangeUtils=function(c){var b="\uFEFF";this.walk=function(d,s){var i=d.startContainer,l=d.startOffset,t=d.endContainer,m=d.endOffset,j,g,o,h,r,q,e;e=c.select("td.mceSelected,th.mceSelected");if(e.length>0){a.each(e,function(u){s([u])});return}function f(u){var v;v=u[0];if(v.nodeType===3&&v===i&&l>=v.nodeValue.length){u.splice(0,1)}v=u[u.length-1];if(m===0&&u.length>0&&v===t&&v.nodeType===3){u.splice(u.length-1,1)}return u}function p(x,v,u){var y=[];for(;x&&x!=u;x=x[v]){y.push(x)}return y}function n(v,u){do{if(v.parentNode==u){return v}v=v.parentNode}while(v)}function k(x,v,y){var u=y?"nextSibling":"previousSibling";for(h=x,r=h.parentNode;h&&h!=v;h=r){r=h.parentNode;q=p(h==x?h:h[u],u);if(q.length){if(!y){q.reverse()}s(f(q))}}}if(i.nodeType==1&&i.hasChildNodes()){i=i.childNodes[l]}if(t.nodeType==1&&t.hasChildNodes()){t=t.childNodes[Math.min(m-1,t.childNodes.length-1)]}if(i==t){return s(f([i]))}j=c.findCommonAncestor(i,t);for(h=i;h;h=h.parentNode){if(h===t){return k(i,j,true)}if(h===j){break}}for(h=t;h;h=h.parentNode){if(h===i){return k(t,j)}if(h===j){break}}g=n(i,j)||i;o=n(t,j)||t;k(i,g,true);q=p(g==i?g:g.nextSibling,"nextSibling",o==t?o.nextSibling:o);if(q.length){s(f(q))}k(t,o)};this.split=function(e){var h=e.startContainer,d=e.startOffset,i=e.endContainer,g=e.endOffset;function f(j,k){return j.splitText(k)}if(h==i&&h.nodeType==3){if(d>0&&dd){g=g-d;h=i=f(i,g).previousSibling;g=i.nodeValue.length;d=0}else{g=0}}}else{if(h.nodeType==3&&d>0&&d0&&g=m.length){r=0}}t=m[r];f.setAttrib(g,"tabindex","-1");f.setAttrib(t.id,"tabindex","0");f.get(t.id).focus();if(e.actOnFocus){e.onAction(t.id)}if(s){a.cancel(s)}};p=function(z){var v=37,u=39,y=38,A=40,r=27,t=14,s=13,x=32;switch(z.keyCode){case v:if(i){q.moveFocus(-1)}a.cancel(z);break;case u:if(i){q.moveFocus(1)}a.cancel(z);break;case y:if(o){q.moveFocus(-1)}a.cancel(z);break;case A:if(o){q.moveFocus(1)}a.cancel(z);break;case r:if(e.onCancel){e.onCancel();a.cancel(z)}break;case t:case s:case x:if(e.onAction){e.onAction(g);a.cancel(z)}break}};c(m,function(t,r){var s,u;if(!t.id){t.id=f.uniqueId("_mce_item_")}u=f.get(t.id);if(l){f.bind(u,"blur",h);s="-1"}else{s=(r===0?"0":"-1")}u.setAttribute("tabindex",s);f.bind(u,"focus",k)});if(m[0]){g=m[0].id}f.setAttrib(n,"tabindex","-1");var j=f.get(n);f.bind(j,"focus",d);f.bind(j,"keydown",p)}})})(tinymce);(function(c){var b=c.DOM,a=c.is;c.create("tinymce.ui.Control",{Control:function(f,e,d){this.id=f;this.settings=e=e||{};this.rendered=false;this.onRender=new c.util.Dispatcher(this);this.classPrefix="";this.scope=e.scope||this;this.disabled=0;this.active=0;this.editor=d},setAriaProperty:function(f,e){var d=b.get(this.id+"_aria")||b.get(this.id);if(d){b.setAttrib(d,"aria-"+f,!!e)}},focus:function(){b.get(this.id).focus()},setDisabled:function(d){if(d!=this.disabled){this.setAriaProperty("disabled",d);this.setState("Disabled",d);this.setState("Enabled",!d);this.disabled=d}},isDisabled:function(){return this.disabled},setActive:function(d){if(d!=this.active){this.setState("Active",d);this.active=d;this.setAriaProperty("pressed",d)}},isActive:function(){return this.active},setState:function(f,d){var e=b.get(this.id);f=this.classPrefix+f;if(d){b.addClass(e,f)}else{b.removeClass(e,f)}},isRendered:function(){return this.rendered},renderHTML:function(){},renderTo:function(d){b.setHTML(d,this.renderHTML())},postRender:function(){var e=this,d;if(a(e.disabled)){d=e.disabled;e.disabled=-1;e.setDisabled(d)}if(a(e.active)){d=e.active;e.active=-1;e.setActive(d)}},remove:function(){b.remove(this.id);this.destroy()},destroy:function(){c.dom.Event.clear(this.id)}})})(tinymce);tinymce.create("tinymce.ui.Container:tinymce.ui.Control",{Container:function(c,b,a){this.parent(c,b,a);this.controls=[];this.lookup={}},add:function(a){this.lookup[a.id]=a;this.controls.push(a);return a},get:function(a){return this.lookup[a]}});tinymce.create("tinymce.ui.Separator:tinymce.ui.Control",{Separator:function(b,a){this.parent(b,a);this.classPrefix="mceSeparator";this.setDisabled(true)},renderHTML:function(){return tinymce.DOM.createHTML("span",{"class":this.classPrefix,role:"separator","aria-orientation":"vertical",tabindex:"-1"})}});(function(d){var c=d.is,b=d.DOM,e=d.each,a=d.walk;d.create("tinymce.ui.MenuItem:tinymce.ui.Control",{MenuItem:function(g,f){this.parent(g,f);this.classPrefix="mceMenuItem"},setSelected:function(f){this.setState("Selected",f);this.setAriaProperty("checked",!!f);this.selected=f},isSelected:function(){return this.selected},postRender:function(){var f=this;f.parent();if(c(f.selected)){f.setSelected(f.selected)}}})})(tinymce);(function(d){var c=d.is,b=d.DOM,e=d.each,a=d.walk;d.create("tinymce.ui.Menu:tinymce.ui.MenuItem",{Menu:function(h,g){var f=this;f.parent(h,g);f.items={};f.collapsed=false;f.menuCount=0;f.onAddItem=new d.util.Dispatcher(this)},expand:function(g){var f=this;if(g){a(f,function(h){if(h.expand){h.expand()}},"items",f)}f.collapsed=false},collapse:function(g){var f=this;if(g){a(f,function(h){if(h.collapse){h.collapse()}},"items",f)}f.collapsed=true},isCollapsed:function(){return this.collapsed},add:function(f){if(!f.settings){f=new d.ui.MenuItem(f.id||b.uniqueId(),f)}this.onAddItem.dispatch(this,f);return this.items[f.id]=f},addSeparator:function(){return this.add({separator:true})},addMenu:function(f){if(!f.collapse){f=this.createMenu(f)}this.menuCount++;return this.add(f)},hasMenus:function(){return this.menuCount!==0},remove:function(f){delete this.items[f.id]},removeAll:function(){var f=this;a(f,function(g){if(g.removeAll){g.removeAll()}else{g.remove()}g.destroy()},"items",f);f.items={}},createMenu:function(g){var f=new d.ui.Menu(g.id||b.uniqueId(),g);f.onAddItem.add(this.onAddItem.dispatch,this.onAddItem);return f}})})(tinymce);(function(e){var d=e.is,c=e.DOM,f=e.each,a=e.dom.Event,b=e.dom.Element;e.create("tinymce.ui.DropMenu:tinymce.ui.Menu",{DropMenu:function(h,g){g=g||{};g.container=g.container||c.doc.body;g.offset_x=g.offset_x||0;g.offset_y=g.offset_y||0;g.vp_offset_x=g.vp_offset_x||0;g.vp_offset_y=g.vp_offset_y||0;if(d(g.icons)&&!g.icons){g["class"]+=" mceNoIcons"}this.parent(h,g);this.onShowMenu=new e.util.Dispatcher(this);this.onHideMenu=new e.util.Dispatcher(this);this.classPrefix="mceMenu"},createMenu:function(j){var h=this,i=h.settings,g;j.container=j.container||i.container;j.parent=h;j.constrain=j.constrain||i.constrain;j["class"]=j["class"]||i["class"];j.vp_offset_x=j.vp_offset_x||i.vp_offset_x;j.vp_offset_y=j.vp_offset_y||i.vp_offset_y;j.keyboard_focus=i.keyboard_focus;g=new e.ui.DropMenu(j.id||c.uniqueId(),j);g.onAddItem.add(h.onAddItem.dispatch,h.onAddItem);return g},focus:function(){var g=this;if(g.keyboardNav){g.keyboardNav.focus()}},update:function(){var i=this,j=i.settings,g=c.get("menu_"+i.id+"_tbl"),l=c.get("menu_"+i.id+"_co"),h,k;h=j.max_width?Math.min(g.offsetWidth,j.max_width):g.offsetWidth;k=j.max_height?Math.min(g.offsetHeight,j.max_height):g.offsetHeight;if(!c.boxModel){i.element.setStyles({width:h+2,height:k+2})}else{i.element.setStyles({width:h,height:k})}if(j.max_width){c.setStyle(l,"width",h)}if(j.max_height){c.setStyle(l,"height",k);if(g.clientHeightv){p=r?r-u:Math.max(0,(v-A.vp_offset_x)-u)}if((n+A.vp_offset_y+l)>q){n=Math.max(0,(q-A.vp_offset_y)-l)}}c.setStyles(o,{left:p,top:n});z.element.update();z.isMenuVisible=1;z.mouseClickFunc=a.add(o,"click",function(s){var h;s=s.target;if(s&&(s=c.getParent(s,"tr"))&&!c.hasClass(s,m+"ItemSub")){h=z.items[s.id];if(h.isDisabled()){return}k=z;while(k){if(k.hideMenu){k.hideMenu()}k=k.settings.parent}if(h.settings.onclick){h.settings.onclick(s)}return false}});if(z.hasMenus()){z.mouseOverFunc=a.add(o,"mouseover",function(x){var h,t,s;x=x.target;if(x&&(x=c.getParent(x,"tr"))){h=z.items[x.id];if(z.lastMenu){z.lastMenu.collapse(1)}if(h.isDisabled()){return}if(x&&c.hasClass(x,m+"ItemSub")){t=c.getRect(x);h.showMenu((t.x+t.w-i),t.y-i,t.x);z.lastMenu=h;c.addClass(c.get(h.id).firstChild,m+"ItemActive")}}})}a.add(o,"keydown",z._keyHandler,z);z.onShowMenu.dispatch(z);if(A.keyboard_focus){z._setupKeyboardNav()}},hideMenu:function(j){var g=this,i=c.get("menu_"+g.id),h;if(!g.isMenuVisible){return}if(g.keyboardNav){g.keyboardNav.destroy()}a.remove(i,"mouseover",g.mouseOverFunc);a.remove(i,"click",g.mouseClickFunc);a.remove(i,"keydown",g._keyHandler);c.hide(i);g.isMenuVisible=0;if(!j){g.collapse(1)}if(g.element){g.element.hide()}if(h=c.get(g.id)){c.removeClass(h.firstChild,g.classPrefix+"ItemActive")}g.onHideMenu.dispatch(g)},add:function(i){var g=this,h;i=g.parent(i);if(g.isRendered&&(h=c.get("menu_"+g.id))){g._add(c.select("tbody",h)[0],i)}return i},collapse:function(g){this.parent(g);this.hideMenu(1)},remove:function(g){c.remove(g.id);this.destroy();return this.parent(g)},destroy:function(){var g=this,h=c.get("menu_"+g.id);if(g.keyboardNav){g.keyboardNav.destroy()}a.remove(h,"mouseover",g.mouseOverFunc);a.remove(c.select("a",h),"focus",g.mouseOverFunc);a.remove(h,"click",g.mouseClickFunc);a.remove(h,"keydown",g._keyHandler);if(g.element){g.element.remove()}c.remove(h)},renderNode:function(){var i=this,j=i.settings,l,h,k,g;g=c.create("div",{role:"listbox",id:"menu_"+i.id,"class":j["class"],style:"position:absolute;left:0;top:0;z-index:200000;outline:0"});if(i.settings.parent){c.setAttrib(g,"aria-parent","menu_"+i.settings.parent.id)}k=c.add(g,"div",{role:"presentation",id:"menu_"+i.id+"_co","class":i.classPrefix+(j["class"]?" "+j["class"]:"")});i.element=new b("menu_"+i.id,{blocker:1,container:j.container});if(j.menu_line){c.add(k,"span",{"class":i.classPrefix+"Line"})}l=c.add(k,"table",{role:"presentation",id:"menu_"+i.id+"_tbl",border:0,cellPadding:0,cellSpacing:0});h=c.add(l,"tbody");f(i.items,function(m){i._add(h,m)});i.rendered=true;return g},_setupKeyboardNav:function(){var i,h,g=this;i=c.get("menu_"+g.id);h=c.select("a[role=option]","menu_"+g.id);h.splice(0,0,i);g.keyboardNav=new e.ui.KeyboardNavigation({root:"menu_"+g.id,items:h,onCancel:function(){g.hideMenu()},enableUpDown:true});i.focus()},_keyHandler:function(g){var h=this,i;switch(g.keyCode){case 37:if(h.settings.parent){h.hideMenu();h.settings.parent.focus();a.cancel(g)}break;case 39:if(h.mouseOverFunc){h.mouseOverFunc(g)}break}},_add:function(j,h){var i,q=h.settings,p,l,k,m=this.classPrefix,g;if(q.separator){l=c.add(j,"tr",{id:h.id,"class":m+"ItemSeparator"});c.add(l,"td",{"class":m+"ItemSeparator"});if(i=l.previousSibling){c.addClass(i,"mceLast")}return}i=l=c.add(j,"tr",{id:h.id,"class":m+"Item "+m+"ItemEnabled"});i=k=c.add(i,q.titleItem?"th":"td");i=p=c.add(i,"a",{id:h.id+"_aria",role:q.titleItem?"presentation":"option",href:"javascript:;",onclick:"return false;",onmousedown:"return false;"});if(q.parent){c.setAttrib(p,"aria-haspopup","true");c.setAttrib(p,"aria-owns","menu_"+h.id)}c.addClass(k,q["class"]);g=c.add(i,"span",{"class":"mceIcon"+(q.icon?" mce_"+q.icon:"")});if(q.icon_src){c.add(g,"img",{src:q.icon_src})}i=c.add(i,q.element||"span",{"class":"mceText",title:h.settings.title},h.settings.title);if(h.settings.style){if(typeof h.settings.style=="function"){h.settings.style=h.settings.style()}c.setAttrib(i,"style",h.settings.style)}if(j.childNodes.length==1){c.addClass(l,"mceFirst")}if((i=l.previousSibling)&&c.hasClass(i,m+"ItemSeparator")){c.addClass(l,"mceFirst")}if(h.collapse){c.addClass(l,m+"ItemSub")}if(i=l.previousSibling){c.removeClass(i,"mceLast")}c.addClass(l,"mceLast")}})})(tinymce);(function(b){var a=b.DOM;b.create("tinymce.ui.Button:tinymce.ui.Control",{Button:function(e,d,c){this.parent(e,d,c);this.classPrefix="mceButton"},renderHTML:function(){var f=this.classPrefix,e=this.settings,d,c;c=a.encode(e.label||"");d='';if(e.image&&!(this.editor&&this.editor.forcedHighContrastMode)){d+=''+a.encode(e.title)+''+(c?''+c+"":"")}else{d+=''+(c?''+c+"":"")}d+='";d+="";return d},postRender:function(){var d=this,e=d.settings,c;if(b.isIE&&d.editor){b.dom.Event.add(d.id,"mousedown",function(f){var g=d.editor.selection.getNode().nodeName;c=g==="IMG"?d.editor.selection.getBookmark():null})}b.dom.Event.add(d.id,"click",function(f){if(!d.isDisabled()){if(b.isIE&&d.editor&&c!==null){d.editor.selection.moveToBookmark(c)}return e.onclick.call(e.scope,f)}});b.dom.Event.add(d.id,"keydown",function(f){if(!d.isDisabled()&&f.keyCode==b.VK.SPACEBAR){b.dom.Event.cancel(f);return e.onclick.call(e.scope,f)}})}})})(tinymce);(function(e){var d=e.DOM,b=e.dom.Event,f=e.each,a=e.util.Dispatcher,c;e.create("tinymce.ui.ListBox:tinymce.ui.Control",{ListBox:function(j,i,g){var h=this;h.parent(j,i,g);h.items=[];h.onChange=new a(h);h.onPostRender=new a(h);h.onAdd=new a(h);h.onRenderMenu=new e.util.Dispatcher(this);h.classPrefix="mceListBox";h.marked={}},select:function(h){var g=this,j,i;g.marked={};if(h==c){return g.selectByIndex(-1)}if(h&&typeof(h)=="function"){i=h}else{i=function(k){return k==h}}if(h!=g.selectedValue){f(g.items,function(l,k){if(i(l.value)){j=1;g.selectByIndex(k);return false}});if(!j){g.selectByIndex(-1)}}},selectByIndex:function(g){var i=this,j,k,h;i.marked={};if(g!=i.selectedIndex){j=d.get(i.id+"_text");h=d.get(i.id+"_voiceDesc");k=i.items[g];if(k){i.selectedValue=k.value;i.selectedIndex=g;d.setHTML(j,d.encode(k.title));d.setHTML(h,i.settings.title+" - "+k.title);d.removeClass(j,"mceTitle");d.setAttrib(i.id,"aria-valuenow",k.title)}else{d.setHTML(j,d.encode(i.settings.title));d.setHTML(h,d.encode(i.settings.title));d.addClass(j,"mceTitle");i.selectedValue=i.selectedIndex=null;d.setAttrib(i.id,"aria-valuenow",i.settings.title)}j=0}},mark:function(g){this.marked[g]=true},add:function(j,g,i){var h=this;i=i||{};i=e.extend(i,{title:j,value:g});h.items.push(i);h.onAdd.dispatch(h,i)},getLength:function(){return this.items.length},renderHTML:function(){var j="",g=this,i=g.settings,k=g.classPrefix;j='';j+="";j+="";j+="";return j},showMenu:function(){var h=this,j,i=d.get(this.id),g;if(h.isDisabled()||h.items.length===0){return}if(h.menu&&h.menu.isMenuVisible){return h.hideMenu()}if(!h.isMenuRendered){h.renderMenu();h.isMenuRendered=true}j=d.getPos(i);g=h.menu;g.settings.offset_x=j.x;g.settings.offset_y=j.y;g.settings.keyboard_focus=!e.isOpera;f(h.items,function(k){if(g.items[k.id]){g.items[k.id].setSelected(0)}});f(h.items,function(k){if(g.items[k.id]&&h.marked[k.value]){g.items[k.id].setSelected(1)}if(k.value===h.selectedValue){g.items[k.id].setSelected(1)}});g.showMenu(0,i.clientHeight);b.add(d.doc,"mousedown",h.hideMenu,h);d.addClass(h.id,h.classPrefix+"Selected")},hideMenu:function(h){var g=this;if(g.menu&&g.menu.isMenuVisible){d.removeClass(g.id,g.classPrefix+"Selected");if(h&&h.type=="mousedown"&&(h.target.id==g.id+"_text"||h.target.id==g.id+"_open")){return}if(!h||!d.getParent(h.target,".mceMenu")){d.removeClass(g.id,g.classPrefix+"Selected");b.remove(d.doc,"mousedown",g.hideMenu,g);g.menu.hideMenu()}}},renderMenu:function(){var h=this,g;g=h.settings.control_manager.createDropMenu(h.id+"_menu",{menu_line:1,"class":h.classPrefix+"Menu mceNoIcons",max_width:250,max_height:150});g.onHideMenu.add(function(){h.hideMenu();h.focus()});g.add({title:h.settings.title,"class":"mceMenuItemTitle",onclick:function(){if(h.settings.onselect("")!==false){h.select("")}}});f(h.items,function(i){if(i.value===c){g.add({title:i.title,role:"option","class":"mceMenuItemTitle",onclick:function(){if(h.settings.onselect("")!==false){h.select("")}}})}else{i.id=d.uniqueId();i.role="option";i.onclick=function(){if(h.settings.onselect(i.value)!==false){h.select(i.value)}};g.add(i)}});h.onRenderMenu.dispatch(h,g);h.menu=g},postRender:function(){var g=this,h=g.classPrefix;b.add(g.id,"click",g.showMenu,g);b.add(g.id,"keydown",function(i){if(i.keyCode==32){g.showMenu(i);b.cancel(i)}});b.add(g.id,"focus",function(){if(!g._focused){g.keyDownHandler=b.add(g.id,"keydown",function(i){if(i.keyCode==40){g.showMenu();b.cancel(i)}});g.keyPressHandler=b.add(g.id,"keypress",function(j){var i;if(j.keyCode==13){i=g.selectedValue;g.selectedValue=null;b.cancel(j);g.settings.onselect(i)}})}g._focused=1});b.add(g.id,"blur",function(){b.remove(g.id,"keydown",g.keyDownHandler);b.remove(g.id,"keypress",g.keyPressHandler);g._focused=0});if(e.isIE6||!d.boxModel){b.add(g.id,"mouseover",function(){if(!d.hasClass(g.id,h+"Disabled")){d.addClass(g.id,h+"Hover")}});b.add(g.id,"mouseout",function(){if(!d.hasClass(g.id,h+"Disabled")){d.removeClass(g.id,h+"Hover")}})}g.onPostRender.dispatch(g,d.get(g.id))},destroy:function(){this.parent();b.clear(this.id+"_text");b.clear(this.id+"_open")}})})(tinymce);(function(e){var d=e.DOM,b=e.dom.Event,f=e.each,a=e.util.Dispatcher,c;e.create("tinymce.ui.NativeListBox:tinymce.ui.ListBox",{NativeListBox:function(h,g){this.parent(h,g);this.classPrefix="mceNativeListBox"},setDisabled:function(g){d.get(this.id).disabled=g;this.setAriaProperty("disabled",g)},isDisabled:function(){return d.get(this.id).disabled},select:function(h){var g=this,j,i;if(h==c){return g.selectByIndex(-1)}if(h&&typeof(h)=="function"){i=h}else{i=function(k){return k==h}}if(h!=g.selectedValue){f(g.items,function(l,k){if(i(l.value)){j=1;g.selectByIndex(k);return false}});if(!j){g.selectByIndex(-1)}}},selectByIndex:function(g){d.get(this.id).selectedIndex=g+1;this.selectedValue=this.items[g]?this.items[g].value:null},add:function(k,h,g){var j,i=this;g=g||{};g.value=h;if(i.isRendered()){d.add(d.get(this.id),"option",g,k)}j={title:k,value:h,attribs:g};i.items.push(j);i.onAdd.dispatch(i,j)},getLength:function(){return this.items.length},renderHTML:function(){var i,g=this;i=d.createHTML("option",{value:""},"-- "+g.settings.title+" --");f(g.items,function(h){i+=d.createHTML("option",{value:h.value},h.title)});i=d.createHTML("select",{id:g.id,"class":"mceNativeListBox","aria-labelledby":g.id+"_aria"},i);i+=d.createHTML("span",{id:g.id+"_aria",style:"display: none"},g.settings.title);return i},postRender:function(){var h=this,i,j=true;h.rendered=true;function g(l){var k=h.items[l.target.selectedIndex-1];if(k&&(k=k.value)){h.onChange.dispatch(h,k);if(h.settings.onselect){h.settings.onselect(k)}}}b.add(h.id,"change",g);b.add(h.id,"keydown",function(q){var n,p=37,m=39,l=38,r=40,k=13,o=32;b.remove(h.id,"change",i);j=false;n=b.add(h.id,"blur",function(){if(j){return}j=true;b.add(h.id,"change",g);b.remove(h.id,"blur",n)});if(q.keyCode==k||q.keyCode==o){g(q);return b.cancel(q)}else{if(q.keyCode==r||q.keyCode==l){q.stopImmediatePropagation()}}});h.onPostRender.dispatch(h,d.get(h.id))}})})(tinymce);(function(c){var b=c.DOM,a=c.dom.Event,d=c.each;c.create("tinymce.ui.MenuButton:tinymce.ui.Button",{MenuButton:function(g,f,e){this.parent(g,f,e);this.onRenderMenu=new c.util.Dispatcher(this);f.menu_container=f.menu_container||b.doc.body},showMenu:function(){var g=this,j,i,h=b.get(g.id),f;if(g.isDisabled()){return}if(!g.isMenuRendered){g.renderMenu();g.isMenuRendered=true}if(g.isMenuVisible){return g.hideMenu()}j=b.getPos(g.settings.menu_container);i=b.getPos(h);f=g.menu;f.settings.offset_x=i.x;f.settings.offset_y=i.y;f.settings.vp_offset_x=i.x;f.settings.vp_offset_y=i.y;f.settings.keyboard_focus=g._focused;f.showMenu(0,h.firstChild.clientHeight);a.add(b.doc,"mousedown",g.hideMenu,g);g.setState("Selected",1);g.isMenuVisible=1},renderMenu:function(){var f=this,e;e=f.settings.control_manager.createDropMenu(f.id+"_menu",{menu_line:1,"class":this.classPrefix+"Menu",icons:f.settings.icons});e.onHideMenu.add(function(){f.hideMenu();f.focus()});f.onRenderMenu.dispatch(f,e);f.menu=e},hideMenu:function(g){var f=this;if(g&&g.type=="mousedown"&&b.getParent(g.target,function(h){return h.id===f.id||h.id===f.id+"_open"})){return}if(!g||!b.getParent(g.target,".mceMenu")){f.setState("Selected",0);a.remove(b.doc,"mousedown",f.hideMenu,f);if(f.menu){f.menu.hideMenu()}}f.isMenuVisible=0},postRender:function(){var e=this,f=e.settings;a.add(e.id,"click",function(){if(!e.isDisabled()){if(f.onclick){f.onclick(e.value)}e.showMenu()}})}})})(tinymce);(function(c){var b=c.DOM,a=c.dom.Event,d=c.each;c.create("tinymce.ui.SplitButton:tinymce.ui.MenuButton",{SplitButton:function(g,f,e){this.parent(g,f,e);this.classPrefix="mceSplitButton"},renderHTML:function(){var i,f=this,g=f.settings,e;i="";if(g.image){e=b.createHTML("img ",{src:g.image,role:"presentation","class":"mceAction "+g["class"]})}else{e=b.createHTML("span",{"class":"mceAction "+g["class"]},"")}e+=b.createHTML("span",{"class":"mceVoiceLabel mceIconOnly",id:f.id+"_voice",style:"display:none;"},g.title);i+=""+b.createHTML("a",{role:"button",id:f.id+"_action",tabindex:"-1",href:"javascript:;","class":"mceAction "+g["class"],onclick:"return false;",onmousedown:"return false;",title:g.title},e)+"";e=b.createHTML("span",{"class":"mceOpen "+g["class"]},'');i+=""+b.createHTML("a",{role:"button",id:f.id+"_open",tabindex:"-1",href:"javascript:;","class":"mceOpen "+g["class"],onclick:"return false;",onmousedown:"return false;",title:g.title},e)+"";i+="";i=b.createHTML("table",{role:"presentation","class":"mceSplitButton mceSplitButtonEnabled "+g["class"],cellpadding:"0",cellspacing:"0",title:g.title},i);return b.createHTML("div",{id:f.id,role:"button",tabindex:"0","aria-labelledby":f.id+"_voice","aria-haspopup":"true"},i)},postRender:function(){var e=this,g=e.settings,f;if(g.onclick){f=function(h){if(!e.isDisabled()){g.onclick(e.value);a.cancel(h)}};a.add(e.id+"_action","click",f);a.add(e.id,["click","keydown"],function(h){var k=32,m=14,i=13,j=38,l=40;if((h.keyCode===32||h.keyCode===13||h.keyCode===14)&&!h.altKey&&!h.ctrlKey&&!h.metaKey){f();a.cancel(h)}else{if(h.type==="click"||h.keyCode===l){e.showMenu();a.cancel(h)}}})}a.add(e.id+"_open","click",function(h){e.showMenu();a.cancel(h)});a.add([e.id,e.id+"_open"],"focus",function(){e._focused=1});a.add([e.id,e.id+"_open"],"blur",function(){e._focused=0});if(c.isIE6||!b.boxModel){a.add(e.id,"mouseover",function(){if(!b.hasClass(e.id,"mceSplitButtonDisabled")){b.addClass(e.id,"mceSplitButtonHover")}});a.add(e.id,"mouseout",function(){if(!b.hasClass(e.id,"mceSplitButtonDisabled")){b.removeClass(e.id,"mceSplitButtonHover")}})}},destroy:function(){this.parent();a.clear(this.id+"_action");a.clear(this.id+"_open");a.clear(this.id)}})})(tinymce);(function(d){var c=d.DOM,a=d.dom.Event,b=d.is,e=d.each;d.create("tinymce.ui.ColorSplitButton:tinymce.ui.SplitButton",{ColorSplitButton:function(i,h,f){var g=this;g.parent(i,h,f);g.settings=h=d.extend({colors:"000000,993300,333300,003300,003366,000080,333399,333333,800000,FF6600,808000,008000,008080,0000FF,666699,808080,FF0000,FF9900,99CC00,339966,33CCCC,3366FF,800080,999999,FF00FF,FFCC00,FFFF00,00FF00,00FFFF,00CCFF,993366,C0C0C0,FF99CC,FFCC99,FFFF99,CCFFCC,CCFFFF,99CCFF,CC99FF,FFFFFF",grid_width:8,default_color:"#888888"},g.settings);g.onShowMenu=new d.util.Dispatcher(g);g.onHideMenu=new d.util.Dispatcher(g);g.value=h.default_color},showMenu:function(){var f=this,g,j,i,h;if(f.isDisabled()){return}if(!f.isMenuRendered){f.renderMenu();f.isMenuRendered=true}if(f.isMenuVisible){return f.hideMenu()}i=c.get(f.id);c.show(f.id+"_menu");c.addClass(i,"mceSplitButtonSelected");h=c.getPos(i);c.setStyles(f.id+"_menu",{left:h.x,top:h.y+i.firstChild.clientHeight,zIndex:200000});i=0;a.add(c.doc,"mousedown",f.hideMenu,f);f.onShowMenu.dispatch(f);if(f._focused){f._keyHandler=a.add(f.id+"_menu","keydown",function(k){if(k.keyCode==27){f.hideMenu()}});c.select("a",f.id+"_menu")[0].focus()}f.keyboardNav=new d.ui.KeyboardNavigation({root:f.id+"_menu",items:c.select("a",f.id+"_menu"),onCancel:function(){f.hideMenu();f.focus()}});f.keyboardNav.focus();f.isMenuVisible=1},hideMenu:function(g){var f=this;if(f.isMenuVisible){if(g&&g.type=="mousedown"&&c.getParent(g.target,function(h){return h.id===f.id+"_open"})){return}if(!g||!c.getParent(g.target,".mceSplitButtonMenu")){c.removeClass(f.id,"mceSplitButtonSelected");a.remove(c.doc,"mousedown",f.hideMenu,f);a.remove(f.id+"_menu","keydown",f._keyHandler);c.hide(f.id+"_menu")}f.isMenuVisible=0;f.onHideMenu.dispatch();f.keyboardNav.destroy()}},renderMenu:function(){var p=this,h,k=0,q=p.settings,g,j,l,o,f;o=c.add(q.menu_container,"div",{role:"listbox",id:p.id+"_menu","class":q.menu_class+" "+q["class"],style:"position:absolute;left:0;top:-1000px;"});h=c.add(o,"div",{"class":q["class"]+" mceSplitButtonMenu"});c.add(h,"span",{"class":"mceMenuLine"});g=c.add(h,"table",{role:"presentation","class":"mceColorSplitMenu"});j=c.add(g,"tbody");k=0;e(b(q.colors,"array")?q.colors:q.colors.split(","),function(m){m=m.replace(/^#/,"");if(!k--){l=c.add(j,"tr");k=q.grid_width-1}g=c.add(l,"td");var i={href:"javascript:;",style:{backgroundColor:"#"+m},title:p.editor.getLang("colors."+m,m),"data-mce-color":"#"+m};if(!d.isIE){i.role="option"}g=c.add(g,"a",i);if(p.editor.forcedHighContrastMode){g=c.add(g,"canvas",{width:16,height:16,"aria-hidden":"true"});if(g.getContext&&(f=g.getContext("2d"))){f.fillStyle="#"+m;f.fillRect(0,0,16,16)}else{c.remove(g)}}});if(q.more_colors_func){g=c.add(j,"tr");g=c.add(g,"td",{colspan:q.grid_width,"class":"mceMoreColors"});g=c.add(g,"a",{role:"option",id:p.id+"_more",href:"javascript:;",onclick:"return false;","class":"mceMoreColors"},q.more_colors_title);a.add(g,"click",function(i){q.more_colors_func.call(q.more_colors_scope||this);return a.cancel(i)})}c.addClass(h,"mceColorSplitMenu");a.add(p.id+"_menu","mousedown",function(i){return a.cancel(i)});a.add(p.id+"_menu","click",function(i){var m;i=c.getParent(i.target,"a",j);if(i&&i.nodeName.toLowerCase()=="a"&&(m=i.getAttribute("data-mce-color"))){p.setColor(m)}return false});return o},setColor:function(f){this.displayColor(f);this.hideMenu();this.settings.onselect(f)},displayColor:function(g){var f=this;c.setStyle(f.id+"_preview","backgroundColor",g);f.value=g},postRender:function(){var f=this,g=f.id;f.parent();c.add(g+"_action","div",{id:g+"_preview","class":"mceColorPreview"});c.setStyle(f.id+"_preview","backgroundColor",f.value)},destroy:function(){var f=this;f.parent();a.clear(f.id+"_menu");a.clear(f.id+"_more");c.remove(f.id+"_menu");if(f.keyboardNav){f.keyboardNav.destroy()}}})})(tinymce);(function(b){var d=b.DOM,c=b.each,a=b.dom.Event;b.create("tinymce.ui.ToolbarGroup:tinymce.ui.Container",{renderHTML:function(){var f=this,i=[],e=f.controls,j=b.each,g=f.settings;i.push('
');i.push("");i.push('");j(e,function(h){i.push(h.renderHTML())});i.push("");i.push("
");return i.join("")},focus:function(){var e=this;d.get(e.id).focus()},postRender:function(){var f=this,e=[];c(f.controls,function(g){c(g.controls,function(h){if(h.id){e.push(h)}})});f.keyNav=new b.ui.KeyboardNavigation({root:f.id,items:e,onCancel:function(){if(b.isWebKit){d.get(f.editor.id+"_ifr").focus()}f.editor.focus()},excludeFromTabOrder:!f.settings.tab_focus_toolbar})},destroy:function(){var e=this;e.parent();e.keyNav.destroy();a.clear(e.id)}})})(tinymce);(function(a){var c=a.DOM,b=a.each;a.create("tinymce.ui.Toolbar:tinymce.ui.Container",{renderHTML:function(){var m=this,f="",j,k,n=m.settings,e,d,g,l;l=m.controls;for(e=0;e"))}if(d&&k.ListBox){if(d.Button||d.SplitButton){f+=c.createHTML("td",{"class":"mceToolbarEnd"},c.createHTML("span",null,""))}}if(c.stdMode){f+=''+k.renderHTML()+""}else{f+=""+k.renderHTML()+""}if(g&&k.ListBox){if(g.Button||g.SplitButton){f+=c.createHTML("td",{"class":"mceToolbarStart"},c.createHTML("span",null,""))}}}j="mceToolbarEnd";if(k.Button){j+=" mceToolbarEndButton"}else{if(k.SplitButton){j+=" mceToolbarEndSplitButton"}else{if(k.ListBox){j+=" mceToolbarEndListBox"}}}f+=c.createHTML("td",{"class":j},c.createHTML("span",null,""));return c.createHTML("table",{id:m.id,"class":"mceToolbar"+(n["class"]?" "+n["class"]:""),cellpadding:"0",cellspacing:"0",align:m.settings.align||"",role:"presentation",tabindex:"-1"},""+f+"")}})})(tinymce);(function(b){var a=b.util.Dispatcher,c=b.each;b.create("tinymce.AddOnManager",{AddOnManager:function(){var d=this;d.items=[];d.urls={};d.lookup={};d.onAdd=new a(d)},get:function(d){if(this.lookup[d]){return this.lookup[d].instance}else{return undefined}},dependencies:function(e){var d;if(this.lookup[e]){d=this.lookup[e].dependencies}return d||[]},requireLangPack:function(e){var d=b.settings;if(d&&d.language&&d.language_load!==false){b.ScriptLoader.add(this.urls[e]+"/langs/"+d.language+".js")}},add:function(f,e,d){this.items.push(e);this.lookup[f]={instance:e,dependencies:d};this.onAdd.dispatch(this,f,e);return e},createUrl:function(d,e){if(typeof e==="object"){return e}else{return{prefix:d.prefix,resource:e,suffix:d.suffix}}},addComponents:function(f,d){var e=this.urls[f];b.each(d,function(g){b.ScriptLoader.add(e+"/"+g)})},load:function(j,f,d,h){var g=this,e=f;function i(){var k=g.dependencies(j);b.each(k,function(m){var l=g.createUrl(f,m);g.load(l.resource,l,undefined,undefined)});if(d){if(h){d.call(h)}else{d.call(b.ScriptLoader)}}}if(g.urls[j]){return}if(typeof f==="object"){e=f.prefix+f.resource+f.suffix}if(e.indexOf("/")!==0&&e.indexOf("://")==-1){e=b.baseURL+"/"+e}g.urls[j]=e.substring(0,e.lastIndexOf("/"));if(g.lookup[j]){i()}else{b.ScriptLoader.add(e,i,h)}}});b.PluginManager=new b.AddOnManager();b.ThemeManager=new b.AddOnManager()}(tinymce));(function(j){var g=j.each,d=j.extend,k=j.DOM,i=j.dom.Event,f=j.ThemeManager,b=j.PluginManager,e=j.explode,h=j.util.Dispatcher,a,c=0;j.documentBaseURL=window.location.href.replace(/[\?#].*$/,"").replace(/[\/\\][^\/]+$/,"");if(!/[\/\\]$/.test(j.documentBaseURL)){j.documentBaseURL+="/"}j.baseURL=new j.util.URI(j.documentBaseURL).toAbsolute(j.baseURL);j.baseURI=new j.util.URI(j.baseURL);j.onBeforeUnload=new h(j);i.add(window,"beforeunload",function(l){j.onBeforeUnload.dispatch(j,l)});j.onAddEditor=new h(j);j.onRemoveEditor=new h(j);j.EditorManager=d(j,{editors:[],i18n:{},activeEditor:null,init:function(x){var v=this,o,n=j.ScriptLoader,u,l=[],r;function q(t){var s=t.id;if(!s){s=t.name;if(s&&!k.get(s)){s=t.name}else{s=k.uniqueId()}t.setAttribute("id",s)}return s}function m(z,A,t){var y=z[A];if(!y){return}if(j.is(y,"string")){t=y.replace(/\.\w+$/,"");t=t?j.resolve(t):0;y=j.resolve(y)}return y.apply(t||this,Array.prototype.slice.call(arguments,2))}function p(t,s){return s.constructor===RegExp?s.test(t.className):k.hasClass(t,s)}v.settings=x;i.bind(window,"ready",function(){var s,t;m(x,"onpageload");switch(x.mode){case"exact":s=x.elements||"";if(s.length>0){g(e(s),function(y){if(k.get(y)){r=new j.Editor(y,x);l.push(r);r.render(1)}else{g(document.forms,function(z){g(z.elements,function(A){if(A.name===y){y="mce_editor_"+c++;k.setAttrib(A,"id",y);r=new j.Editor(y,x);l.push(r);r.render(1)}})})}})}break;case"textareas":case"specific_textareas":g(k.select("textarea"),function(y){if(x.editor_deselector&&p(y,x.editor_deselector)){return}if(!x.editor_selector||p(y,x.editor_selector)){r=new j.Editor(q(y),x);l.push(r);r.render(1)}});break;default:if(x.types){g(x.types,function(y){g(k.select(y.selector),function(A){var z=new j.Editor(q(A),j.extend({},x,y));l.push(z);z.render(1)})})}else{if(x.selector){g(k.select(x.selector),function(z){var y=new j.Editor(q(z),x);l.push(y);y.render(1)})}}}if(x.oninit){s=t=0;g(l,function(y){t++;if(!y.initialized){y.onInit.add(function(){s++;if(s==t){m(x,"oninit")}})}else{s++}if(s==t){m(x,"oninit")}})}})},get:function(l){if(l===a){return this.editors}if(!this.editors.hasOwnProperty(l)){return a}return this.editors[l]},getInstanceById:function(l){return this.get(l)},add:function(m){var l=this,n=l.editors;n[m.id]=m;n.push(m);l._setActive(m);l.onAddEditor.dispatch(l,m);if(j.adapter){j.adapter.patchEditor(m)}return m},remove:function(n){var m=this,l,o=m.editors;if(!o[n.id]){return null}delete o[n.id];for(l=0;l':"",visual:n,font_size_style_values:"xx-small,x-small,small,medium,large,x-large,xx-large",font_size_legacy_values:"xx-small,small,medium,large,x-large,xx-large,300%",apply_source_formatting:n,directionality:"ltr",forced_root_block:"p",hidden_input:n,padd_empty_editor:n,render_ui:n,indentation:"30px",fix_table_elements:n,inline_styles:n,convert_fonts_to_spans:n,indent:"simple",indent_before:"p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,li,area,table,thead,tfoot,tbody,tr,section,article,hgroup,aside,figure,option,optgroup,datalist",indent_after:"p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,li,area,table,thead,tfoot,tbody,tr,section,article,hgroup,aside,figure,option,optgroup,datalist",validate:n,entity_encoding:"named",url_converter:m.convertURL,url_converter_scope:m,ie7_compat:n},o);m.id=m.editorId=p;m.isNotDirty=false;m.plugins={};m.documentBaseURI=new k.util.URI(o.document_base_url||k.documentBaseURL,{base_uri:tinyMCE.baseURI});m.baseURI=k.baseURI;m.contentCSS=[];m.contentStyles=[];m.setupEvents();m.execCommands={};m.queryStateCommands={};m.queryValueCommands={};m.execCallback("setup",m)},render:function(o){var p=this,q=p.settings,r=p.id,m=k.ScriptLoader;if(!j.domLoaded){j.add(window,"ready",function(){p.render()});return}tinyMCE.settings=q;if(!p.getElement()){return}if(k.isIDevice&&!k.isIOS5){return}if(!/TEXTAREA|INPUT/i.test(p.getElement().nodeName)&&q.hidden_input&&l.getParent(r,"form")){l.insertAfter(l.create("input",{type:"hidden",name:r}),r)}if(!q.content_editable){p.orgVisibility=p.getElement().style.visibility;p.getElement().style.visibility="hidden"}if(k.WindowManager){p.windowManager=new k.WindowManager(p)}if(q.encoding=="xml"){p.onGetContent.add(function(s,t){if(t.save){t.content=l.encode(t.content)}})}if(q.add_form_submit_trigger){p.onSubmit.addToTop(function(){if(p.initialized){p.save();p.isNotDirty=1}})}if(q.add_unload_trigger){p._beforeUnload=tinyMCE.onBeforeUnload.add(function(){if(p.initialized&&!p.destroyed&&!p.isHidden()){p.save({format:"raw",no_events:true})}})}k.addUnload(p.destroy,p);if(q.submit_patch){p.onBeforeRenderUI.add(function(){var s=p.getElement().form;if(!s){return}if(s._mceOldSubmit){return}if(!s.submit.nodeType&&!s.submit.length){p.formElement=s;s._mceOldSubmit=s.submit;s.submit=function(){k.triggerSave();p.isNotDirty=1;return p.formElement._mceOldSubmit(p.formElement)}}s=null})}function n(){if(q.language&&q.language_load!==false){m.add(k.baseURL+"/langs/"+q.language+".js")}if(q.theme&&typeof q.theme!="function"&&q.theme.charAt(0)!="-"&&!h.urls[q.theme]){h.load(q.theme,"themes/"+q.theme+"/editor_template"+k.suffix+".js")}i(g(q.plugins),function(t){if(t&&!c.urls[t]){if(t.charAt(0)=="-"){t=t.substr(1,t.length);var s=c.dependencies(t);i(s,function(v){var u={prefix:"plugins/",resource:v,suffix:"/editor_plugin"+k.suffix+".js"};v=c.createUrl(u,v);c.load(v.resource,v)})}else{if(t=="safari"){return}c.load(t,{prefix:"plugins/",resource:t,suffix:"/editor_plugin"+k.suffix+".js"})}}});m.loadQueue(function(){if(!p.removed){p.init()}})}n()},init:function(){var q,G=this,H=G.settings,D,y,z,C=G.getElement(),p,m,E,v,B,F,x,r=[];k.add(G);H.aria_label=H.aria_label||l.getAttrib(C,"aria-label",G.getLang("aria.rich_text_area"));if(H.theme){if(typeof H.theme!="function"){H.theme=H.theme.replace(/-/,"");p=h.get(H.theme);G.theme=new p();if(G.theme.init){G.theme.init(G,h.urls[H.theme]||k.documentBaseURL.replace(/\/$/,""))}}else{G.theme=H.theme}}function A(s){var t=c.get(s),o=c.urls[s]||k.documentBaseURL.replace(/\/$/,""),n;if(t&&k.inArray(r,s)===-1){i(c.dependencies(s),function(u){A(u)});n=new t(G,o);G.plugins[s]=n;if(n.init){n.init(G,o);r.push(s)}}}i(g(H.plugins.replace(/\-/g,"")),A);if(H.popup_css!==false){if(H.popup_css){H.popup_css=G.documentBaseURI.toAbsolute(H.popup_css)}else{H.popup_css=G.baseURI.toAbsolute("themes/"+H.theme+"/skins/"+H.skin+"/dialog.css")}}if(H.popup_css_add){H.popup_css+=","+G.documentBaseURI.toAbsolute(H.popup_css_add)}G.controlManager=new k.ControlManager(G);G.onBeforeRenderUI.dispatch(G,G.controlManager);if(H.render_ui&&G.theme){G.orgDisplay=C.style.display;if(typeof H.theme!="function"){D=H.width||C.style.width||C.offsetWidth;y=H.height||C.style.height||C.offsetHeight;z=H.min_height||100;F=/^[0-9\.]+(|px)$/i;if(F.test(""+D)){D=Math.max(parseInt(D,10)+(p.deltaWidth||0),100)}if(F.test(""+y)){y=Math.max(parseInt(y,10)+(p.deltaHeight||0),z)}p=G.theme.renderUI({targetNode:C,width:D,height:y,deltaWidth:H.delta_width,deltaHeight:H.delta_height});l.setStyles(p.sizeContainer||p.editorContainer,{width:D,height:y});y=(p.iframeHeight||y)+(typeof(y)=="number"?(p.deltaHeight||0):"");if(y';if(H.document_base_url!=k.documentBaseURL){G.iframeHTML+=''}if(k.isIE8){if(H.ie7_compat){G.iframeHTML+=''}else{G.iframeHTML+=''}}G.iframeHTML+='';for(x=0;x'}G.contentCSS=[];v=H.body_id||"tinymce";if(v.indexOf("=")!=-1){v=G.getParam("body_id","","hash");v=v[G.id]||v}B=H.body_class||"";if(B.indexOf("=")!=-1){B=G.getParam("body_class","","hash");B=B[G.id]||""}G.iframeHTML+='
";if(k.relaxedDomain&&(b||(k.isOpera&&parseFloat(opera.version())<11))){E='javascript:(function(){document.open();document.domain="'+document.domain+'";var ed = window.parent.tinyMCE.get("'+G.id+'");document.write(ed.iframeHTML);document.close();ed.initContentBody();})()'}q=l.add(p.iframeContainer,"iframe",{id:G.id+"_ifr",src:E||'javascript:""',frameBorder:"0",allowTransparency:"true",title:H.aria_label,style:{width:"100%",height:y,display:"block"}});G.contentAreaContainer=p.iframeContainer;if(p.editorContainer){l.get(p.editorContainer).style.display=G.orgDisplay}C.style.visibility=G.orgVisibility;l.get(G.id).style.display="none";l.setAttrib(G.id,"aria-hidden",true);if(!k.relaxedDomain||!E){G.initContentBody()}C=q=p=null},initContentBody:function(){var n=this,p=n.settings,q=l.get(n.id),r=n.getDoc(),o,m,s;if((!b||!k.relaxedDomain)&&!p.content_editable){r.open();r.write(n.iframeHTML);r.close();if(k.relaxedDomain){r.domain=k.relaxedDomain}}if(p.content_editable){l.addClass(q,"mceContentBody");n.contentDocument=r=p.content_document||document;n.contentWindow=p.content_window||window;n.bodyElement=q;p.content_document=p.content_window=null}m=n.getBody();m.disabled=true;if(!p.readonly){m.contentEditable=n.getParam("content_editable_state",true)}m.disabled=false;n.schema=new k.html.Schema(p);n.dom=new k.dom.DOMUtils(r,{keep_values:true,url_converter:n.convertURL,url_converter_scope:n,hex_colors:p.force_hex_style_colors,class_filter:p.class_filter,update_styles:true,root_element:p.content_editable?n.id:null,schema:n.schema});n.parser=new k.html.DomParser(p,n.schema);n.parser.addAttributeFilter("src,href,style",function(t,u){var v=t.length,y,A=n.dom,z,x;while(v--){y=t[v];z=y.attr(u);x="data-mce-"+u;if(!y.attributes.map[x]){if(u==="style"){y.attr(x,A.serializeStyle(A.parseStyle(z),y.name))}else{y.attr(x,n.convertURL(z,u,y.name))}}}});n.parser.addNodeFilter("script",function(t,u){var v=t.length,x;while(v--){x=t[v];x.attr("type","mce-"+(x.attr("type")||"text/javascript"))}});n.parser.addNodeFilter("#cdata",function(t,u){var v=t.length,x;while(v--){x=t[v];x.type=8;x.name="#comment";x.value="[CDATA["+x.value+"]]"}});n.parser.addNodeFilter("p,h1,h2,h3,h4,h5,h6,div",function(u,v){var x=u.length,y,t=n.schema.getNonEmptyElements();while(x--){y=u[x];if(y.isEmpty(t)){y.empty().append(new k.html.Node("br",1)).shortEnded=true}}});n.serializer=new k.dom.Serializer(p,n.dom,n.schema);n.selection=new k.dom.Selection(n.dom,n.getWin(),n.serializer,n);n.formatter=new k.Formatter(n);n.undoManager=new k.UndoManager(n);n.forceBlocks=new k.ForceBlocks(n);n.enterKey=new k.EnterKey(n);n.editorCommands=new k.EditorCommands(n);n.onExecCommand.add(function(t,u){if(!/^(FontName|FontSize)$/.test(u)){n.nodeChanged()}});n.serializer.onPreProcess.add(function(t,u){return n.onPreProcess.dispatch(n,u,t)});n.serializer.onPostProcess.add(function(t,u){return n.onPostProcess.dispatch(n,u,t)});n.onPreInit.dispatch(n);if(!p.browser_spellcheck&&!p.gecko_spellcheck){r.body.spellcheck=false}if(!p.readonly){n.bindNativeEvents()}n.controlManager.onPostRender.dispatch(n,n.controlManager);n.onPostRender.dispatch(n);n.quirks=k.util.Quirks(n);if(p.directionality){m.dir=p.directionality}if(p.nowrap){m.style.whiteSpace="nowrap"}if(p.protect){n.onBeforeSetContent.add(function(t,u){i(p.protect,function(v){u.content=u.content.replace(v,function(x){return""})})})}n.onSetContent.add(function(){n.addVisual(n.getBody())});if(p.padd_empty_editor){n.onPostProcess.add(function(t,u){u.content=u.content.replace(/^(]*>( | |\s|\u00a0|)<\/p>[\r\n]*|
[\r\n]*)$/,"")})}n.load({initial:true,format:"html"});n.startContent=n.getContent({format:"raw"});n.initialized=true;n.onInit.dispatch(n);n.execCallback("setupcontent_callback",n.id,m,r);n.execCallback("init_instance_callback",n);n.focus(true);n.nodeChanged({initial:true});if(n.contentStyles.length>0){s="";i(n.contentStyles,function(t){s+=t+"\r\n"});n.dom.addStyle(s)}i(n.contentCSS,function(t){n.dom.loadCSS(t)});if(p.auto_focus){setTimeout(function(){var t=k.get(p.auto_focus);t.selection.select(t.getBody(),1);t.selection.collapse(1);t.getBody().focus();t.getWin().focus()},100)}q=r=m=null},focus:function(p){var o,u=this,t=u.selection,q=u.settings.content_editable,n,r,s=u.getDoc(),m;if(!p){if(u.bookmark){t.moveToBookmark(u.bookmark);u.bookmark=null}n=t.getRng();if(n.item){r=n.item(0)}u._refreshContentEditable();if(!q){u.getWin().focus()}if(k.isGecko||q){m=u.getBody();if(m.setActive&&!k.isIE11){m.setActive()}else{m.focus()}if(q){t.normalize()}}if(r&&r.ownerDocument==s){n=s.body.createControlRange();n.addElement(r);n.select()}}if(k.activeEditor!=u){if((o=k.activeEditor)!=null){o.onDeactivate.dispatch(o,u)}u.onActivate.dispatch(u,o)}k._setActive(u)},execCallback:function(q){var m=this,p=m.settings[q],o;if(!p){return}if(m.callbackLookup&&(o=m.callbackLookup[q])){p=o.func;o=o.scope}if(d(p,"string")){o=p.replace(/\.\w+$/,"");o=o?k.resolve(o):0;p=k.resolve(p);m.callbackLookup=m.callbackLookup||{};m.callbackLookup[q]={func:p,scope:o}}return p.apply(o||m,Array.prototype.slice.call(arguments,1))},translate:function(m){var o=this.settings.language||"en",n=k.i18n;if(!m){return""}return n[o+"."+m]||m.replace(/\{\#([^\}]+)\}/g,function(q,p){return n[o+"."+p]||"{#"+p+"}"})},getLang:function(o,m){return k.i18n[(this.settings.language||"en")+"."+o]||(d(m)?m:"{#"+o+"}")},getParam:function(t,q,m){var r=k.trim,p=d(this.settings[t])?this.settings[t]:q,s;if(m==="hash"){s={};if(d(p,"string")){i(p.indexOf("=")>0?p.split(/[;,](?![^=;,]*(?:[;,]|$))/):p.split(","),function(n){n=n.split("=");if(n.length>1){s[r(n[0])]=r(n[1])}else{s[r(n[0])]=r(n)}})}else{s=p}return s}return p},nodeChanged:function(q){var m=this,n=m.selection,p;if(m.initialized){q=q||{};p=n.getStart()||m.getBody();p=b&&p.ownerDocument!=m.getDoc()?m.getBody():p;q.parents=[];m.dom.getParent(p,function(o){if(o.nodeName=="BODY"){return true}q.parents.push(o)});m.onNodeChange.dispatch(m,q?q.controlManager||m.controlManager:m.controlManager,p,n.isCollapsed(),q)}},addButton:function(n,o){var m=this;m.buttons=m.buttons||{};m.buttons[n]=o},addCommand:function(m,o,n){this.execCommands[m]={func:o,scope:n||this}},addQueryStateHandler:function(m,o,n){this.queryStateCommands[m]={func:o,scope:n||this}},addQueryValueHandler:function(m,o,n){this.queryValueCommands[m]={func:o,scope:n||this}},addShortcut:function(o,q,m,p){var n=this,r;if(n.settings.custom_shortcuts===false){return false}n.shortcuts=n.shortcuts||{};if(d(m,"string")){r=m;m=function(){n.execCommand(r,false,null)}}if(d(m,"object")){r=m;m=function(){n.execCommand(r[0],r[1],r[2])}}i(g(o),function(s){var t={func:m,scope:p||this,desc:n.translate(q),alt:false,ctrl:false,shift:false};i(g(s,"+"),function(u){switch(u){case"alt":case"ctrl":case"shift":t[u]=true;break;default:t.charCode=u.charCodeAt(0);t.keyCode=u.toUpperCase().charCodeAt(0)}});n.shortcuts[(t.ctrl?"ctrl":"")+","+(t.alt?"alt":"")+","+(t.shift?"shift":"")+","+t.keyCode]=t});return true},execCommand:function(u,r,x,m){var p=this,q=0,v,n;if(!/^(mceAddUndoLevel|mceEndUndoLevel|mceBeginUndoLevel|mceRepaint|SelectAll)$/.test(u)&&(!m||!m.skip_focus)){p.focus()}m=f({},m);p.onBeforeExecCommand.dispatch(p,u,r,x,m);if(m.terminate){return false}if(p.execCallback("execcommand_callback",p.id,p.selection.getNode(),u,r,x)){p.onExecCommand.dispatch(p,u,r,x,m);return true}if(v=p.execCommands[u]){n=v.func.call(v.scope,r,x);if(n!==true){p.onExecCommand.dispatch(p,u,r,x,m);return n}}i(p.plugins,function(o){if(o.execCommand&&o.execCommand(u,r,x)){p.onExecCommand.dispatch(p,u,r,x,m);q=1;return false}});if(q){return true}if(p.theme&&p.theme.execCommand&&p.theme.execCommand(u,r,x)){p.onExecCommand.dispatch(p,u,r,x,m);return true}if(p.editorCommands.execCommand(u,r,x)){p.onExecCommand.dispatch(p,u,r,x,m);return true}p.getDoc().execCommand(u,r,x);p.onExecCommand.dispatch(p,u,r,x,m)},queryCommandState:function(q){var n=this,r,p;if(n._isHidden()){return}if(r=n.queryStateCommands[q]){p=r.func.call(r.scope);if(p!==true){return p}}r=n.editorCommands.queryCommandState(q);if(r!==-1){return r}try{return this.getDoc().queryCommandState(q)}catch(m){}},queryCommandValue:function(r){var n=this,q,p;if(n._isHidden()){return}if(q=n.queryValueCommands[r]){p=q.func.call(q.scope);if(p!==true){return p}}q=n.editorCommands.queryCommandValue(r);if(d(q)){return q}try{return this.getDoc().queryCommandValue(r)}catch(m){}},show:function(){var m=this;l.show(m.getContainer());l.hide(m.id);m.load()},hide:function(){var m=this,n=m.getDoc();if(b&&n){n.execCommand("SelectAll")}m.save();l.hide(m.getContainer());l.setStyle(m.id,"display",m.orgDisplay)},isHidden:function(){return !l.isHidden(this.id)},setProgressState:function(m,n,p){this.onSetProgressState.dispatch(this,m,n,p);return m},load:function(q){var m=this,p=m.getElement(),n;if(p){q=q||{};q.load=true;n=m.setContent(d(p.value)?p.value:p.innerHTML,q);q.element=p;if(!q.no_events){m.onLoadContent.dispatch(m,q)}q.element=p=null;return n}},save:function(r){var m=this,q=m.getElement(),n,p;if(!q||!m.initialized){return}r=r||{};r.save=true;r.element=q;n=r.content=m.getContent(r);if(!r.no_events){m.onSaveContent.dispatch(m,r)}n=r.content;if(!/TEXTAREA|INPUT/i.test(q.nodeName)){q.innerHTML=n;if(p=l.getParent(m.id,"form")){i(p.elements,function(o){if(o.name==m.id){o.value=n;return false}})}}else{q.value=n}r.element=q=null;return n},setContent:function(r,p){var o=this,n,m=o.getBody(),q;p=p||{};p.format=p.format||"html";p.set=true;p.content=r;if(!p.no_events){o.onBeforeSetContent.dispatch(o,p)}r=p.content;if(!k.isIE&&(r.length===0||/^\s+$/.test(r))){q=o.settings.forced_root_block;if(q){r="<"+q+'>
"}else{r='
'}m.innerHTML=r;o.selection.select(m,true);o.selection.collapse(true);return}if(p.format!=="raw"){r=new k.html.Serializer({},o.schema).serialize(o.parser.parse(r))}p.content=k.trim(r);o.dom.setHTML(m,p.content);if(!p.no_events){o.onSetContent.dispatch(o,p)}if(!o.settings.content_editable||document.activeElement===o.getBody()){o.selection.normalize()}return p.content},getContent:function(o){var n=this,p,m=n.getBody();o=o||{};o.format=o.format||"html";o.get=true;o.getInner=true;if(!o.no_events){n.onBeforeGetContent.dispatch(n,o)}if(o.format=="raw"){p=m.innerHTML}else{if(o.format=="text"){p=m.innerText||m.textContent}else{p=n.serializer.serialize(m,o)}}if(o.format!="text"){o.content=k.trim(p)}else{o.content=p}if(!o.no_events){n.onGetContent.dispatch(n,o)}return o.content},isDirty:function(){var m=this;return k.trim(m.startContent)!=k.trim(m.getContent({format:"raw",no_events:1}))&&!m.isNotDirty},getContainer:function(){var m=this;if(!m.container){m.container=l.get(m.editorContainer||m.id+"_parent")}return m.container},getContentAreaContainer:function(){return this.contentAreaContainer},getElement:function(){return l.get(this.settings.content_element||this.id)},getWin:function(){var m=this,n;if(!m.contentWindow){n=l.get(m.id+"_ifr");if(n){m.contentWindow=n.contentWindow}}return m.contentWindow},getDoc:function(){var m=this,n;if(!m.contentDocument){n=m.getWin();if(n){m.contentDocument=n.document}}return m.contentDocument},getBody:function(){return this.bodyElement||this.getDoc().body},convertURL:function(o,n,q){var m=this,p=m.settings;if(p.urlconverter_callback){return m.execCallback("urlconverter_callback",o,q,true,n)}if(!p.convert_urls||(q&&q.nodeName=="LINK")||o.indexOf("file:")===0){return o}if(p.relative_urls){return m.documentBaseURI.toRelative(o)}o=m.documentBaseURI.toAbsolute(o,p.remove_script_host);return o},addVisual:function(q){var n=this,o=n.settings,p=n.dom,m;q=q||n.getBody();if(!d(n.hasVisual)){n.hasVisual=o.visual}i(p.select("table,a",q),function(s){var r;switch(s.nodeName){case"TABLE":m=o.visual_table_class||"mceItemTable";r=p.getAttrib(s,"border");if(!r||r=="0"){if(n.hasVisual){p.addClass(s,m)}else{p.removeClass(s,m)}}return;case"A":if(!p.getAttrib(s,"href",false)){r=p.getAttrib(s,"name")||s.id;m="mceItemAnchor";if(r){if(n.hasVisual){p.addClass(s,m)}else{p.removeClass(s,m)}}}return}});n.onVisualAid.dispatch(n,q,n.hasVisual)},remove:function(){var m=this,o=m.getContainer(),n=m.getDoc();if(!m.removed){m.removed=1;if(b&&n){n.execCommand("SelectAll")}m.save();l.setStyle(m.id,"display",m.orgDisplay);if(!m.settings.content_editable){j.unbind(m.getWin());j.unbind(m.getDoc())}j.unbind(m.getBody());j.clear(o);m.execCallback("remove_instance_callback",m);m.onRemove.dispatch(m);m.onExecCommand.listeners=[];k.remove(m);l.remove(o)}},destroy:function(n){var m=this;if(m.destroyed){return}if(a){j.unbind(m.getDoc());j.unbind(m.getWin());j.unbind(m.getBody())}if(!n){k.removeUnload(m.destroy);tinyMCE.onBeforeUnload.remove(m._beforeUnload);if(m.theme&&m.theme.destroy){m.theme.destroy()}m.controlManager.destroy();m.selection.destroy();m.dom.destroy()}if(m.formElement){m.formElement.submit=m.formElement._mceOldSubmit;m.formElement._mceOldSubmit=null}m.contentAreaContainer=m.formElement=m.container=m.settings.content_element=m.bodyElement=m.contentDocument=m.contentWindow=null;if(m.selection){m.selection=m.selection.win=m.selection.dom=m.selection.dom.doc=null}m.destroyed=1},_refreshContentEditable:function(){var n=this,m,o;if(n._isHidden()){m=n.getBody();o=m.parentNode;o.removeChild(m);o.appendChild(m);m.focus()}},_isHidden:function(){var m;if(!a){return 0}m=this.selection.getSel();return(!m||!m.rangeCount||m.rangeCount===0)}})})(tinymce);(function(a){var b=a.each;a.Editor.prototype.setupEvents=function(){var c=this,d=c.settings;b(["onPreInit","onBeforeRenderUI","onPostRender","onLoad","onInit","onRemove","onActivate","onDeactivate","onClick","onEvent","onMouseUp","onMouseDown","onDblClick","onKeyDown","onKeyUp","onKeyPress","onContextMenu","onSubmit","onReset","onPaste","onPreProcess","onPostProcess","onBeforeSetContent","onBeforeGetContent","onSetContent","onGetContent","onLoadContent","onSaveContent","onNodeChange","onChange","onBeforeExecCommand","onExecCommand","onUndo","onRedo","onVisualAid","onSetProgressState","onSetAttrib"],function(e){c[e]=new a.util.Dispatcher(c)});if(d.cleanup_callback){c.onBeforeSetContent.add(function(e,f){f.content=e.execCallback("cleanup_callback","insert_to_editor",f.content,f)});c.onPreProcess.add(function(e,f){if(f.set){e.execCallback("cleanup_callback","insert_to_editor_dom",f.node,f)}if(f.get){e.execCallback("cleanup_callback","get_from_editor_dom",f.node,f)}});c.onPostProcess.add(function(e,f){if(f.set){f.content=e.execCallback("cleanup_callback","insert_to_editor",f.content,f)}if(f.get){f.content=e.execCallback("cleanup_callback","get_from_editor",f.content,f)}})}if(d.save_callback){c.onGetContent.add(function(e,f){if(f.save){f.content=e.execCallback("save_callback",e.id,f.content,e.getBody())}})}if(d.handle_event_callback){c.onEvent.add(function(f,g,h){if(c.execCallback("handle_event_callback",g,f,h)===false){g.preventDefault();g.stopPropagation()}})}if(d.handle_node_change_callback){c.onNodeChange.add(function(f,e,g){f.execCallback("handle_node_change_callback",f.id,g,-1,-1,true,f.selection.isCollapsed())})}if(d.save_callback){c.onSaveContent.add(function(e,g){var f=e.execCallback("save_callback",e.id,g.content,e.getBody());if(f){g.content=f}})}if(d.onchange_callback){c.onChange.add(function(f,e){f.execCallback("onchange_callback",f,e)})}};a.Editor.prototype.bindNativeEvents=function(){var l=this,f,d=l.settings,e=l.dom,h;h={mouseup:"onMouseUp",mousedown:"onMouseDown",click:"onClick",keyup:"onKeyUp",keydown:"onKeyDown",keypress:"onKeyPress",submit:"onSubmit",reset:"onReset",contextmenu:"onContextMenu",dblclick:"onDblClick",paste:"onPaste"};function c(i,m){var n=i.type;if(l.removed){return}if(l.onEvent.dispatch(l,i,m)!==false){l[h[i.fakeType||i.type]].dispatch(l,i,m)}}function j(i){l.focus(true)}function k(i,m){if(m.keyCode!=65||!a.VK.metaKeyPressed(m)){l.selection.normalize()}l.nodeChanged()}b(h,function(m,n){var i=d.content_editable?l.getBody():l.getDoc();switch(n){case"contextmenu":e.bind(i,n,c);break;case"paste":e.bind(l.getBody(),n,c);break;case"submit":case"reset":e.bind(l.getElement().form||a.DOM.getParent(l.id,"form"),n,c);break;default:e.bind(i,n,c)}});e.bind(d.content_editable?l.getBody():(a.isGecko?l.getDoc():l.getWin()),"focus",function(i){l.focus(true)});if(d.content_editable&&a.isOpera){e.bind(l.getBody(),"click",j);e.bind(l.getBody(),"keydown",j)}l.onMouseUp.add(k);l.onKeyUp.add(function(i,n){var m=n.keyCode;if((m>=33&&m<=36)||(m>=37&&m<=40)||m==13||m==45||m==46||m==8||(a.isMac&&(m==91||m==93))||n.ctrlKey){k(i,n)}});l.onReset.add(function(){l.setContent(l.startContent,{format:"raw"})});function g(m,i){if(m.altKey||m.ctrlKey||m.metaKey){b(l.shortcuts,function(n){var o=a.isMac?m.metaKey:m.ctrlKey;if(n.ctrl!=o||n.alt!=m.altKey||n.shift!=m.shiftKey){return}if(m.keyCode==n.keyCode||(m.charCode&&m.charCode==n.charCode)){m.preventDefault();if(i){n.func.call(n.scope)}return true}})}}l.onKeyUp.add(function(i,m){g(m)});l.onKeyPress.add(function(i,m){g(m)});l.onKeyDown.add(function(i,m){g(m,true)});if(a.isOpera){l.onClick.add(function(i,m){m.preventDefault()})}}})(tinymce);(function(d){var e=d.each,b,a=true,c=false;d.EditorCommands=function(n){var m=n.dom,p=n.selection,j={state:{},exec:{},value:{}},k=n.settings,q=n.formatter,o;function r(z,y,x){var v;z=z.toLowerCase();if(v=j.exec[z]){v(z,y,x);return a}return c}function l(x){var v;x=x.toLowerCase();if(v=j.state[x]){return v(x)}return -1}function h(x){var v;x=x.toLowerCase();if(v=j.value[x]){return v(x)}return c}function u(v,x){x=x||"exec";e(v,function(z,y){e(y.toLowerCase().split(","),function(A){j[x][A]=z})})}d.extend(this,{execCommand:r,queryCommandState:l,queryCommandValue:h,addCommands:u});function f(y,x,v){if(x===b){x=c}if(v===b){v=null}return n.getDoc().execCommand(y,x,v)}function t(v){return q.match(v)}function s(v,x){q.toggle(v,x?{value:x}:b)}function i(v){o=p.getBookmark(v)}function g(){p.moveToBookmark(o)}u({"mceResetDesignMode,mceBeginUndoLevel":function(){},"mceEndUndoLevel,mceAddUndoLevel":function(){n.undoManager.add()},"Cut,Copy,Paste":function(z){var y=n.getDoc(),v;try{f(z)}catch(x){v=a}if(v||!y.queryCommandSupported(z)){if(d.isGecko){n.windowManager.confirm(n.getLang("clipboard_msg"),function(A){if(A){open("http://www.mozilla.org/editor/midasdemo/securityprefs.html","_blank")}})}else{n.windowManager.alert(n.getLang("clipboard_no_support"))}}},unlink:function(v){if(p.isCollapsed()){p.select(p.getNode())}f(v);p.collapse(c)},"JustifyLeft,JustifyCenter,JustifyRight,JustifyFull":function(v){var x=v.substring(7);e("left,center,right,full".split(","),function(y){if(x!=y){q.remove("align"+y)}});s("align"+x);r("mceRepaint")},"InsertUnorderedList,InsertOrderedList":function(y){var v,x;f(y);v=m.getParent(p.getNode(),"ol,ul");if(v){x=v.parentNode;if(/^(H[1-6]|P|ADDRESS|PRE)$/.test(x.nodeName)){i();m.split(x,v);g()}}},"Bold,Italic,Underline,Strikethrough,Superscript,Subscript":function(v){s(v)},"ForeColor,HiliteColor,FontName":function(y,x,v){s(y,v)},FontSize:function(z,y,x){var v,A;if(x>=1&&x<=7){A=d.explode(k.font_size_style_values);v=d.explode(k.font_size_classes);if(v){x=v[x-1]||x}else{x=A[x-1]||x}}s(z,x)},RemoveFormat:function(v){q.remove(v)},mceBlockQuote:function(v){s("blockquote")},FormatBlock:function(y,x,v){return s(v||"p")},mceCleanup:function(){var v=p.getBookmark();n.setContent(n.getContent({cleanup:a}),{cleanup:a});p.moveToBookmark(v)},mceRemoveNode:function(z,y,x){var v=x||p.getNode();if(v!=n.getBody()){i();n.dom.remove(v,a);g()}},mceSelectNodeDepth:function(z,y,x){var v=0;m.getParent(p.getNode(),function(A){if(A.nodeType==1&&v++==x){p.select(A);return c}},n.getBody())},mceSelectNode:function(y,x,v){p.select(v)},mceInsertContent:function(B,I,K){var y,J,E,z,F,G,D,C,L,x,A,M,v,H;y=n.parser;J=new d.html.Serializer({},n.schema);v='\uFEFF';G={content:K,format:"html"};p.onBeforeSetContent.dispatch(p,G);K=G.content;if(K.indexOf("{$caret}")==-1){K+="{$caret}"}K=K.replace(/\{\$caret\}/,v);if(!p.isCollapsed()){n.getDoc().execCommand("Delete",false,null)}E=p.getNode();G={context:E.nodeName.toLowerCase()};F=y.parse(K,G);A=F.lastChild;if(A.attr("id")=="mce_marker"){D=A;for(A=A.prev;A;A=A.walk(true)){if(A.type==3||!m.isBlock(A.name)){A.parent.insert(D,A,A.name==="br");break}}}if(!G.invalid){K=J.serialize(F);A=E.firstChild;M=E.lastChild;if(!A||(A===M&&A.nodeName==="BR")){m.setHTML(E,K)}else{p.setContent(K)}}else{p.setContent(v);E=p.getNode();z=n.getBody();if(E.nodeType==9){E=A=z}else{A=E}while(A!==z){E=A;A=A.parentNode}K=E==z?z.innerHTML:m.getOuterHTML(E);K=J.serialize(y.parse(K.replace(//i,function(){return J.serialize(F)})));if(E==z){m.setHTML(z,K)}else{m.setOuterHTML(E,K)}}D=m.get("mce_marker");C=m.getRect(D);L=m.getViewPort(n.getWin());if((C.y+C.h>L.y+L.h||C.yL.x+L.w||C.x")},mceToggleVisualAid:function(){n.hasVisual=!n.hasVisual;n.addVisual()},mceReplaceContent:function(y,x,v){n.execCommand("mceInsertContent",false,v.replace(/\{\$selection\}/g,p.getContent({format:"text"})))},mceInsertLink:function(z,y,x){var v;if(typeof(x)=="string"){x={href:x}}v=m.getParent(p.getNode(),"a");x.href=x.href.replace(" ","%20");if(!v||!x.href){q.remove("link")}if(x.href){q.apply("link",x,v)}},selectAll:function(){var x=m.getRoot(),v=m.createRng();if(p.getRng().setStart){v.setStart(x,0);v.setEnd(x,x.childNodes.length);p.setRng(v)}else{f("SelectAll")}}});u({"JustifyLeft,JustifyCenter,JustifyRight,JustifyFull":function(z){var x="align"+z.substring(7);var v=p.isCollapsed()?[m.getParent(p.getNode(),m.isBlock)]:p.getSelectedBlocks();var y=d.map(v,function(A){return !!q.matchNode(A,x)});return d.inArray(y,a)!==-1},"Bold,Italic,Underline,Strikethrough,Superscript,Subscript":function(v){return t(v)},mceBlockQuote:function(){return t("blockquote")},Outdent:function(){var v;if(k.inline_styles){if((v=m.getParent(p.getStart(),m.isBlock))&&parseInt(v.style.paddingLeft)>0){return a}if((v=m.getParent(p.getEnd(),m.isBlock))&&parseInt(v.style.paddingLeft)>0){return a}}return l("InsertUnorderedList")||l("InsertOrderedList")||(!k.inline_styles&&!!m.getParent(p.getNode(),"BLOCKQUOTE"))},"InsertUnorderedList,InsertOrderedList":function(x){var v=m.getParent(p.getNode(),"ul,ol");return v&&(x==="insertunorderedlist"&&v.tagName==="UL"||x==="insertorderedlist"&&v.tagName==="OL")}},"state");u({"FontSize,FontName":function(y){var x=0,v;if(v=m.getParent(p.getNode(),"span")){if(y=="fontsize"){x=v.style.fontSize}else{x=v.style.fontFamily.replace(/, /g,",").replace(/[\'\"]/g,"").toLowerCase()}}return x}},"value");u({Undo:function(){n.undoManager.undo()},Redo:function(){n.undoManager.redo()}})}})(tinymce);(function(b){var a=b.util.Dispatcher;b.UndoManager=function(h){var l,i=0,e=[],g,k,j,f;function c(){return b.trim(h.getContent({format:"raw",no_events:1}).replace(/]+data-mce-bogus[^>]+>[\u200B\uFEFF]+<\/span>/g,""))}function d(){l.typing=false;l.add()}onBeforeAdd=new a(l);k=new a(l);j=new a(l);f=new a(l);k.add(function(m,n){if(m.hasUndo()){return h.onChange.dispatch(h,n,m)}});j.add(function(m,n){return h.onUndo.dispatch(h,n,m)});f.add(function(m,n){return h.onRedo.dispatch(h,n,m)});h.onInit.add(function(){l.add()});h.onBeforeExecCommand.add(function(m,p,o,q,n){if(p!="Undo"&&p!="Redo"&&p!="mceRepaint"&&(!n||!n.skip_undo)){l.beforeChange()}});h.onExecCommand.add(function(m,p,o,q,n){if(p!="Undo"&&p!="Redo"&&p!="mceRepaint"&&(!n||!n.skip_undo)){l.add()}});h.onSaveContent.add(d);h.dom.bind(h.dom.getRoot(),"dragend",d);h.dom.bind(h.getBody(),"focusout",function(m){if(!h.removed&&l.typing){d()}});h.onKeyUp.add(function(m,o){var n=o.keyCode;if((n>=33&&n<=36)||(n>=37&&n<=40)||n==45||n==13||o.ctrlKey){d()}});h.onKeyDown.add(function(m,o){var n=o.keyCode;if((n>=33&&n<=36)||(n>=37&&n<=40)||n==45){if(l.typing){d()}return}if((n<16||n>20)&&n!=224&&n!=91&&!l.typing){l.beforeChange();l.typing=true;l.add()}});h.onMouseDown.add(function(m,n){if(l.typing){d()}});h.addShortcut("ctrl+z","undo_desc","Undo");h.addShortcut("ctrl+y","redo_desc","Redo");l={data:e,typing:false,onBeforeAdd:onBeforeAdd,onAdd:k,onUndo:j,onRedo:f,beforeChange:function(){g=h.selection.getBookmark(2,true)},add:function(p){var m,n=h.settings,o;p=p||{};p.content=c();l.onBeforeAdd.dispatch(l,p);o=e[i];if(o&&o.content==p.content){return null}if(e[i]){e[i].beforeBookmark=g}if(n.custom_undo_redo_levels){if(e.length>n.custom_undo_redo_levels){for(m=0;m0){n=e[--i];h.setContent(n.content,{format:"raw"});h.selection.moveToBookmark(n.beforeBookmark);l.onUndo.dispatch(l,n)}return n},redo:function(){var m;if(i0||this.typing},hasRedo:function(){return i0){g.moveEnd("character",q)}g.select()}catch(n){}}}c.nodeChanged()}}if(b.forced_root_block){c.onKeyUp.add(f);c.onNodeChange.add(f)}};(function(c){var b=c.DOM,a=c.dom.Event,d=c.each,e=c.extend;c.create("tinymce.ControlManager",{ControlManager:function(f,j){var h=this,g;j=j||{};h.editor=f;h.controls={};h.onAdd=new c.util.Dispatcher(h);h.onPostRender=new c.util.Dispatcher(h);h.prefix=j.prefix||f.id+"_";h._cls={};h.onPostRender.add(function(){d(h.controls,function(i){i.postRender()})})},get:function(f){return this.controls[this.prefix+f]||this.controls[f]},setActive:function(h,f){var g=null;if(g=this.get(h)){g.setActive(f)}return g},setDisabled:function(h,f){var g=null;if(g=this.get(h)){g.setDisabled(f)}return g},add:function(g){var f=this;if(g){f.controls[g.id]=g;f.onAdd.dispatch(g,f)}return g},createControl:function(j){var o,k,g,h=this,m=h.editor,n,f;if(!h.controlFactories){h.controlFactories=[];d(m.plugins,function(i){if(i.createControl){h.controlFactories.push(i)}})}n=h.controlFactories;for(k=0,g=n.length;k1||ag==ay||ag.tagName=="BR"){return ag}}}var aq=aa.selection.getRng();var av=aq.startContainer;var ap=aq.endContainer;if(av!=ap&&aq.endOffset===0){var au=ar(av,ap);var at=au.nodeType==3?au.length:au.childNodes.length;aq.setEnd(au,at)}return aq}function ad(at,ay,aw,av,aq){var ap=[],ar=-1,ax,aA=-1,au=-1,az;T(at.childNodes,function(aC,aB){if(aC.nodeName==="UL"||aC.nodeName==="OL"){ar=aB;ax=aC;return false}});T(at.childNodes,function(aC,aB){if(aC.nodeName==="SPAN"&&c.getAttrib(aC,"data-mce-type")=="bookmark"){if(aC.id==ay.id+"_start"){aA=aB}else{if(aC.id==ay.id+"_end"){au=aB}}}});if(ar<=0||(aAar)){T(a.grep(at.childNodes),aq);return 0}else{az=c.clone(aw,X);T(a.grep(at.childNodes),function(aC,aB){if((aAar&&aB>ar)){ap.push(aC);aC.parentNode.removeChild(aC)}});if(aAar){at.insertBefore(az,ax.nextSibling)}}av.push(az);T(ap,function(aB){az.appendChild(aB)});return az}}function an(aq,at,aw){var ap=[],av,ar,au=true;av=am.inline||am.block;ar=c.create(av);ab(ar);N.walk(aq,function(ax){var ay;function az(aA){var aF,aD,aB,aC,aE;aE=au;aF=aA.nodeName.toLowerCase();aD=aA.parentNode.nodeName.toLowerCase();if(aA.nodeType===1&&x(aA)){aE=au;au=x(aA)==="true";aC=true}if(g(aF,"br")){ay=0;if(am.block){c.remove(aA)}return}if(am.wrapper&&y(aA,ae,al)){ay=0;return}if(au&&!aC&&am.block&&!am.wrapper&&I(aF)){aA=c.rename(aA,av);ab(aA);ap.push(aA);ay=0;return}if(am.selector){T(ah,function(aG){if("collapsed" in aG&&aG.collapsed!==ai){return}if(c.is(aA,aG.selector)&&!b(aA)){ab(aA,aG);aB=true}});if(!am.inline||aB){ay=0;return}}if(au&&!aC&&d(av,aF)&&d(aD,av)&&!(!aw&&aA.nodeType===3&&aA.nodeValue.length===1&&aA.nodeValue.charCodeAt(0)===65279)&&!b(aA)&&(!am.inline||!H(aA))){if(!ay){ay=c.clone(ar,X);aA.parentNode.insertBefore(ay,aA);ap.push(ay)}ay.appendChild(aA)}else{if(aF=="li"&&at){ay=ad(aA,at,ar,ap,az)}else{ay=0;T(a.grep(aA.childNodes),az);if(aC){au=aE}ay=0}}}T(ax,az)});if(am.wrap_links===false){T(ap,function(ax){function ay(aC){var aB,aA,az;if(aC.nodeName==="A"){aA=c.clone(ar,X);ap.push(aA);az=a.grep(aC.childNodes);for(aB=0;aB1||!H(az))&&ax===0){c.remove(az,1);return}if(am.inline||am.wrapper){if(!am.exact&&ax===1){az=ay(az)}T(ah,function(aB){T(c.select(aB.inline,az),function(aD){var aC;if(aB.wrap_links===false){aC=aD.parentNode;do{if(aC.nodeName==="A"){return}}while(aC=aC.parentNode)}Z(aB,al,aD,aB.exact?aD:null)})});if(y(az.parentNode,ae,al)){c.remove(az,1);az=0;return C}if(am.merge_with_parents){c.getParent(az.parentNode,function(aB){if(y(aB,ae,al)){c.remove(az,1);az=0;return C}})}if(az&&am.merge_siblings!==false){az=u(E(az),az);az=u(az,E(az,C))}}})}if(am){if(ag){if(ag.nodeType){ac=c.createRng();ac.setStartBefore(ag);ac.setEndAfter(ag);an(p(ac,ah),null,true)}else{an(ag,null,true)}}else{if(!ai||!am.inline||c.select("td.mceSelected,th.mceSelected").length){var ao=aa.selection.getNode();if(!m&&ah[0].defaultBlock&&!c.getParent(ao,c.isBlock)){Y(ah[0].defaultBlock)}aa.selection.setRng(af());ak=r.getBookmark();an(p(r.getRng(C),ah),ak);if(am.styles&&(am.styles.color||am.styles.textDecoration)){a.walk(ao,L,"childNodes");L(ao)}r.moveToBookmark(ak);R(r.getRng(C));aa.nodeChanged()}else{U("apply",ae,al)}}}}function B(ad,am,af){var ag=V(ad),ao=ag[0],ak,aj,ac,al=true;function ae(av){var au,at,ar,aq,ax,aw;if(av.nodeType===3){return}if(av.nodeType===1&&x(av)){ax=al;al=x(av)==="true";aw=true}au=a.grep(av.childNodes);if(al&&!aw){for(at=0,ar=ag.length;at=0;ac--){ab=ah[ac].selector;if(!ab){return C}for(ag=ad.length-1;ag>=0;ag--){if(c.is(ad[ag],ab)){return C}}}}return X}function J(ab,ae,ac){var ad;if(!P){P={};ad={};aa.onNodeChange.addToTop(function(ag,af,ai){var ah=n(ai),aj={};T(P,function(ak,al){T(ah,function(am){if(y(am,al,{},ak.similar)){if(!ad[al]){T(ak,function(an){an(true,{node:am,format:al,parents:ah})});ad[al]=ak}aj[al]=ak;return false}})});T(ad,function(ak,al){if(!aj[al]){delete ad[al];T(ak,function(am){am(false,{node:ai,format:al,parents:ah})})}})})}T(ab.split(","),function(af){if(!P[af]){P[af]=[];P[af].similar=ac}P[af].push(ae)});return this}a.extend(this,{get:V,register:l,apply:Y,remove:B,toggle:F,match:k,matchAll:v,matchNode:y,canApply:z,formatChanged:J});j();W();function h(ab,ac){if(g(ab,ac.inline)){return C}if(g(ab,ac.block)){return C}if(ac.selector){return c.is(ab,ac.selector)}}function g(ac,ab){ac=ac||"";ab=ab||"";ac=""+(ac.nodeName||ac);ab=""+(ab.nodeName||ab);return ac.toLowerCase()==ab.toLowerCase()}function O(ac,ab){var ad=c.getStyle(ac,ab);if(ab=="color"||ab=="backgroundColor"){ad=c.toHex(ad)}if(ab=="fontWeight"&&ad==700){ad="bold"}return""+ad}function q(ab,ac){if(typeof(ab)!="string"){ab=ab(ac)}else{if(ac){ab=ab.replace(/%(\w+)/g,function(ae,ad){return ac[ad]||ae})}}return ab}function f(ab){return ab&&ab.nodeType===3&&/^([\t \r\n]+|)$/.test(ab.nodeValue)}function S(ad,ac,ab){var ae=c.create(ac,ab);ad.parentNode.insertBefore(ae,ad);ae.appendChild(ad);return ae}function p(ab,am,ae){var ap,an,ah,al,ad=ab.startContainer,ai=ab.startOffset,ar=ab.endContainer,ak=ab.endOffset;function ao(aA){var au,ax,az,aw,av,at;au=ax=aA?ad:ar;av=aA?"previousSibling":"nextSibling";at=c.getRoot();function ay(aB){return aB.nodeName=="BR"&&aB.getAttribute("data-mce-bogus")&&!aB.nextSibling}if(au.nodeType==3&&!f(au)){if(aA?ai>0:akan?an:ai];if(ad.nodeType==3){ai=0}}if(ar.nodeType==1&&ar.hasChildNodes()){an=ar.childNodes.length-1;ar=ar.childNodes[ak>an?an:ak-1];if(ar.nodeType==3){ak=ar.nodeValue.length}}function aq(au){var at=au;while(at){if(at.nodeType===1&&x(at)){return x(at)==="false"?at:au}at=at.parentNode}return au}function aj(au,ay,aA){var ax,av,az,at;function aw(aC,aE){var aF,aB,aD=aC.nodeValue;if(typeof(aE)=="undefined"){aE=aA?aD.length:0}if(aA){aF=aD.lastIndexOf(" ",aE);aB=aD.lastIndexOf("\u00a0",aE);aF=aF>aB?aF:aB;if(aF!==-1&&!ae){aF++}}else{aF=aD.indexOf(" ",aE);aB=aD.indexOf("\u00a0",aE);aF=aF!==-1&&(aB===-1||aF0&&ah.node.nodeType===3&&ah.node.nodeValue.charAt(ah.offset-1)===" "){if(ah.offset>1){ar=ah.node;ar.splitText(ah.offset-1)}}}}if(am[0].inline||am[0].block_expand){if(!am[0].inline||(ad.nodeType!=3||ai===0)){ad=ao(true)}if(!am[0].inline||(ar.nodeType!=3||ak===ar.nodeValue.length)){ar=ao()}}if(am[0].selector&&am[0].expand!==X&&!am[0].inline){ad=af(ad,"previousSibling");ar=af(ar,"nextSibling")}if(am[0].block||am[0].selector){ad=ac(ad,"previousSibling");ar=ac(ar,"nextSibling");if(am[0].block){if(!H(ad)){ad=ao(true)}if(!H(ar)){ar=ao()}}}if(ad.nodeType==1){ai=s(ad);ad=ad.parentNode}if(ar.nodeType==1){ak=s(ar)+1;ar=ar.parentNode}return{startContainer:ad,startOffset:ai,endContainer:ar,endOffset:ak}}function Z(ah,ag,ae,ab){var ad,ac,af;if(!h(ae,ah)){return X}if(ah.remove!="all"){T(ah.styles,function(aj,ai){aj=q(aj,ag);if(typeof(ai)==="number"){ai=aj;ab=0}if(!ab||g(O(ab,ai),aj)){c.setStyle(ae,ai,"")}af=1});if(af&&c.getAttrib(ae,"style")==""){ae.removeAttribute("style");ae.removeAttribute("data-mce-style")}T(ah.attributes,function(ak,ai){var aj;ak=q(ak,ag);if(typeof(ai)==="number"){ai=ak;ab=0}if(!ab||g(c.getAttrib(ab,ai),ak)){if(ai=="class"){ak=c.getAttrib(ae,ai);if(ak){aj="";T(ak.split(/\s+/),function(al){if(/mce\w+/.test(al)){aj+=(aj?" ":"")+al}});if(aj){c.setAttrib(ae,ai,aj);return}}}if(ai=="class"){ae.removeAttribute("className")}if(e.test(ai)){ae.removeAttribute("data-mce-"+ai)}ae.removeAttribute(ai)}});T(ah.classes,function(ai){ai=q(ai,ag);if(!ab||c.hasClass(ab,ai)){c.removeClass(ae,ai)}});ac=c.getAttribs(ae);for(ad=0;adad?ad:af]}if(ab.nodeType===3&&ag&&af>=ab.nodeValue.length){ab=new t(ab,aa.getBody()).next()||ab}if(ab.nodeType===3&&!ag&&af===0){ab=new t(ab,aa.getBody()).prev()||ab}return ab}function U(ak,ab,ai){var al="_mce_caret",ac=aa.settings.caret_debug;function ad(ap){var ao=c.create("span",{id:al,"data-mce-bogus":true,style:ac?"color:red":""});if(ap){ao.appendChild(aa.getDoc().createTextNode(G))}return ao}function aj(ap,ao){while(ap){if((ap.nodeType===3&&ap.nodeValue!==G)||ap.childNodes.length>1){return false}if(ao&&ap.nodeType===1){ao.push(ap)}ap=ap.firstChild}return true}function ag(ao){while(ao){if(ao.id===al){return ao}ao=ao.parentNode}}function af(ao){var ap;if(ao){ap=new t(ao,ao);for(ao=ap.current();ao;ao=ap.next()){if(ao.nodeType===3){return ao}}}}function ae(aq,ap){var ar,ao;if(!aq){aq=ag(r.getStart());if(!aq){while(aq=c.get(al)){ae(aq,false)}}}else{ao=r.getRng(true);if(aj(aq)){if(ap!==false){ao.setStartBefore(aq);ao.setEndBefore(aq)}c.remove(aq)}else{ar=af(aq);if(ar.nodeValue.charAt(0)===G){ar=ar.deleteData(0,1)}c.remove(aq,1)}r.setRng(ao)}}function ah(){var aq,ao,av,au,ar,ap,at;aq=r.getRng(true);au=aq.startOffset;ap=aq.startContainer;at=ap.nodeValue;ao=ag(r.getStart());if(ao){av=af(ao)}if(at&&au>0&&au=0;au--){aq.appendChild(c.clone(ay[au],false));aq=aq.firstChild}aq.appendChild(c.doc.createTextNode(G));aq=aq.firstChild;var ar=c.getParent(az,I);if(ar&&c.isEmpty(ar)){az.parentNode.replaceChild(ax,az)}else{c.insertAfter(ax,az)}r.setCursorLocation(aq,1);if(c.isEmpty(az)){c.remove(az)}}}function an(){var ap,ao,aq;ao=ag(r.getStart());if(ao&&!c.isEmpty(ao)){a.walk(ao,function(ar){if(ar.nodeType==1&&ar.id!==al&&!c.isEmpty(ar)){c.setAttrib(ar,"data-mce-bogus",null)}},"childNodes")}}if(!self._hasCaretEvents){aa.onBeforeGetContent.addToTop(function(){var ao=[],ap;if(aj(ag(r.getStart()),ao)){ap=ao.length;while(ap--){c.setAttrib(ao[ap],"data-mce-bogus","1")}}});a.each("onMouseUp onKeyUp".split(" "),function(ao){aa[ao].addToTop(function(){ae();an()})});aa.onKeyDown.addToTop(function(ao,aq){var ap=aq.keyCode;if(ap==8||ap==37||ap==39){ae(ag(r.getStart()))}an()});r.onSetContent.add(an);self._hasCaretEvents=true}if(ak=="apply"){ah()}else{am()}}function R(ac){var ab=ac.startContainer,ai=ac.startOffset,ae,ah,ag,ad,af;if(ab.nodeType==3&&ai>=ab.nodeValue.length){ai=s(ab);ab=ab.parentNode;ae=true}if(ab.nodeType==1){ad=ab.childNodes;ab=ad[Math.min(ai,ad.length-1)];ah=new t(ab,c.getParent(ab,c.isBlock));if(ai>ad.length-1||ae){ah.next()}for(ag=ah.current();ag;ag=ah.next()){if(ag.nodeType==3&&!f(ag)){af=c.create("a",null,G);ag.parentNode.insertBefore(af,ag);ac.setStart(ag,0);r.setRng(ac);c.remove(af);return}}}}}})(tinymce);tinymce.onAddEditor.add(function(e,a){var d,h,g,c=a.settings;function b(j,i){e.each(i,function(l,k){if(l){g.setStyle(j,k,l)}});g.rename(j,"span")}function f(i,j){g=i.dom;if(c.convert_fonts_to_spans){e.each(g.select("font,u,strike",j.node),function(k){d[k.nodeName.toLowerCase()](a.dom,k)})}}if(c.inline_styles){h=e.explode(c.font_size_legacy_values);d={font:function(j,i){b(i,{backgroundColor:i.style.backgroundColor,color:i.color,fontFamily:i.face,fontSize:h[parseInt(i.size,10)-1]})},u:function(j,i){b(i,{textDecoration:"underline"})},strike:function(j,i){b(i,{textDecoration:"line-through"})}};a.onPreProcess.add(f);a.onSetContent.add(f);a.onInit.add(function(){a.selection.onSetContent.add(f)})}});(function(b){var a=b.dom.TreeWalker;b.EnterKey=function(f){var i=f.dom,e=f.selection,d=f.settings,h=f.undoManager,c=f.schema.getNonEmptyElements();function g(B){var v=e.getRng(true),G,j,A,u,p,M,C,o,k,n,t,J,x,D;function E(N){return N&&i.isBlock(N)&&!/^(TD|TH|CAPTION|FORM)$/.test(N.nodeName)&&!/^(fixed|absolute)/i.test(N.style.position)&&i.getContentEditable(N)!=="true"}function F(O){var N;if(b.isIE&&!b.isIE11&&i.isBlock(O)){N=e.getRng();O.appendChild(i.create("span",null,"\u00a0"));e.select(O);O.lastChild.outerHTML="";e.setRng(N)}}function z(P){var O=P,Q=[],N;while(O=O.firstChild){if(i.isBlock(O)){return}if(O.nodeType==1&&!c[O.nodeName.toLowerCase()]){Q.push(O)}}N=Q.length;while(N--){O=Q[N];if(!O.hasChildNodes()||(O.firstChild==O.lastChild&&O.firstChild.nodeValue==="")){i.remove(O)}else{if(O.nodeName=="A"&&(O.innerText||O.textContent)===" "){i.remove(O)}}}}function m(O){var T,R,N,U,S,Q=O,P;N=i.createRng();if(O.hasChildNodes()){T=new a(O,O);while(R=T.current()){if(R.nodeType==3){N.setStart(R,0);N.setEnd(R,0);break}if(c[R.nodeName.toLowerCase()]){N.setStartBefore(R);N.setEndBefore(R);break}Q=R;R=T.next()}if(!R){N.setStart(Q,0);N.setEnd(Q,0)}}else{if(O.nodeName=="BR"){if(O.nextSibling&&i.isBlock(O.nextSibling)){if(!M||M<9){P=i.create("br");O.parentNode.insertBefore(P,O)}N.setStartBefore(O);N.setEndBefore(O)}else{N.setStartAfter(O);N.setEndAfter(O)}}else{N.setStart(O,0);N.setEnd(O,0)}}e.setRng(N);i.remove(P);S=i.getViewPort(f.getWin());U=i.getPos(O).y;if(US.y+S.h){f.getWin().scrollTo(0,U'}return R}function q(Q){var P,O,N;if(A.nodeType==3&&(Q?u>0:u0){return true}}}function L(){var P,O,N;if(A&&A.nodeType==3&&u>=A.nodeValue.length){if((!b.isIE||b.isIE11)&&!y()){P=i.create("br");v.insertNode(P);v.setStartAfter(P);v.setEndAfter(P);O=true}}P=i.create("br");v.insertNode(P);if((b.isIE&&!b.isIE11)&&t=="PRE"&&(!M||M<8)){P.parentNode.insertBefore(i.doc.createTextNode("\r"),P)}N=i.create("span",{}," ");P.parentNode.insertBefore(N,P);e.scrollIntoView(N);i.remove(N);if(!O){v.setStartAfter(P);v.setEndAfter(P)}else{v.setStartBefore(P);v.setEndBefore(P)}e.setRng(v);h.add()}function s(N){do{if(N.nodeType===3){N.nodeValue=N.nodeValue.replace(/^[\r\n]+/,"")}N=N.firstChild}while(N)}function K(P){var N=i.getRoot(),O,Q;O=P;while(O!==N&&i.getContentEditable(O)!=="false"){if(i.getContentEditable(O)==="true"){Q=O}O=O.parentNode}return O!==N?Q:N}function I(O){var N;if(!b.isIE||b.isIE11){O.normalize();N=O.lastChild;if(!N||(/^(left|right)$/gi.test(i.getStyle(N,"float",true)))){i.add(O,"br")}}}if(!v.collapsed){f.execCommand("Delete");return}if(B.isDefaultPrevented()){return}A=v.startContainer;u=v.startOffset;x=(d.force_p_newlines?"p":"")||d.forced_root_block;x=x?x.toUpperCase():"";M=i.doc.documentMode;C=B.shiftKey;if(A.nodeType==1&&A.hasChildNodes()){D=u>A.childNodes.length-1;A=A.childNodes[Math.min(u,A.childNodes.length-1)]||A;if(D&&A.nodeType==3){u=A.nodeValue.length}else{u=0}}j=K(A);if(!j){return}h.beforeChange();if(!i.isBlock(j)&&j!=i.getRoot()){if(!x||C){L()}return}if((x&&!C)||(!x&&C)){A=l(A,u)}p=i.getParent(A,i.isBlock);n=p?i.getParent(p.parentNode,i.isBlock):null;t=p?p.nodeName.toUpperCase():"";J=n?n.nodeName.toUpperCase():"";if(J=="LI"&&!B.ctrlKey){p=n;t=J}if(t=="LI"){if(!x&&C){L();return}if(i.isEmpty(p)){if(/^(UL|OL|LI)$/.test(n.parentNode.nodeName)){return false}H();return}}if(t=="PRE"&&d.br_in_pre!==false){if(!C){L();return}}else{if((!x&&!C&&t!="LI")||(x&&C)){L();return}}x=x||"P";if(q()){if(/^(H[1-6]|PRE)$/.test(t)&&J!="HGROUP"){o=r(x)}else{o=r()}if(d.end_container_on_empty_block&&E(n)&&i.isEmpty(p)){o=i.split(n,p)}else{i.insertAfter(o,p)}m(o)}else{if(q(true)){o=p.parentNode.insertBefore(r(),p);F(o)}else{G=v.cloneRange();G.setEndAfter(p);k=G.extractContents();s(k);o=k.firstChild;i.insertAfter(k,p);z(o);I(p);m(o)}}i.setAttrib(o,"id","");h.add()}f.onKeyDown.add(function(k,j){if(j.keyCode==13){if(g(j)!==false){j.preventDefault()}}})}})(tinymce); \ No newline at end of file diff --git a/application/views/scripts/javascripts/vendor/tiny_mce/tiny_mce_src.js b/application/views/scripts/javascripts/vendor/tiny_mce/tiny_mce_src.js index ce6a7ef8b1..70ec2b7db7 100644 --- a/application/views/scripts/javascripts/vendor/tiny_mce/tiny_mce_src.js +++ b/application/views/scripts/javascripts/vendor/tiny_mce/tiny_mce_src.js @@ -1,19271 +1,17942 @@ -// FILE IS GENERATED BY COMBINING THE SOURCES IN THE "classes" DIRECTORY SO DON'T MODIFY THIS FILE DIRECTLY -(function(win) { - var whiteSpaceRe = /^\s*|\s*$/g, - undef, isRegExpBroken = 'B'.replace(/A(.)|B/, '$1') === '$1'; - - var tinymce = { - majorVersion : '3', - - minorVersion : '5.12', - - releaseDate : '2016-10-31', - - _init : function() { - var t = this, d = document, na = navigator, ua = na.userAgent, i, nl, n, base, p, v; - - t.isIE11 = ua.indexOf('Trident/') != -1 && (ua.indexOf('rv:') != -1 || na.appName.indexOf('Netscape') != -1); - - t.isOpera = win.opera && opera.buildNumber; - - t.isWebKit = /WebKit/.test(ua); - - t.isIE = !t.isWebKit && !t.isOpera && (/MSIE/gi).test(ua) && (/Explorer/gi).test(na.appName) || t.isIE11; - - t.isIE6 = t.isIE && /MSIE [56]/.test(ua); - - t.isIE7 = t.isIE && /MSIE [7]/.test(ua); - - t.isIE8 = t.isIE && /MSIE [8]/.test(ua); - - t.isIE9 = t.isIE && /MSIE [9]/.test(ua); - - t.isGecko = !t.isWebKit && !t.isIE11 && /Gecko/.test(ua); - - t.isMac = ua.indexOf('Mac') != -1; - - t.isAir = /adobeair/i.test(ua); - - t.isIDevice = /(iPad|iPhone)/.test(ua); - - t.isIOS5 = t.isIDevice && ua.match(/AppleWebKit\/(\d*)/)[1]>=534; - - // Handle IE 12 sniffing - t.isIE12 = (document.msElementsFromPoint && !t.isIE && !t.isIE11); - if (t.isIE12) { - t.isIE11 = true; - t.isWebKit = false; - } - - // TinyMCE .NET webcontrol might be setting the values for TinyMCE - if (win.tinyMCEPreInit) { - t.suffix = tinyMCEPreInit.suffix; - t.baseURL = tinyMCEPreInit.base; - t.query = tinyMCEPreInit.query; - return; - } - - // Get suffix and base - t.suffix = ''; - - // If base element found, add that infront of baseURL - nl = d.getElementsByTagName('base'); - for (i=0; i : - s = /^((static) )?([\w.]+)(:([\w.]+))?/.exec(s); - cn = s[3].match(/(^|\.)(\w+)$/i)[2]; // Class name - - // Create namespace for new class - ns = t.createNS(s[3].replace(/\.\w+$/, ''), root); - - // Class already exists - if (ns[cn]) - return; - - // Make pure static class - if (s[2] == 'static') { - ns[cn] = p; - - if (this.onCreate) - this.onCreate(s[2], s[3], ns[cn]); - - return; - } - - // Create default constructor - if (!p[cn]) { - p[cn] = function() {}; - de = 1; - } - - // Add constructor and methods - ns[cn] = p[cn]; - t.extend(ns[cn].prototype, p); - - // Extend - if (s[5]) { - sp = t.resolve(s[5]).prototype; - scn = s[5].match(/\.(\w+)$/i)[1]; // Class name - - // Extend constructor - c = ns[cn]; - if (de) { - // Add passthrough constructor - ns[cn] = function() { - return sp[scn].apply(this, arguments); - }; - } else { - // Add inherit constructor - ns[cn] = function() { - this.parent = sp[scn]; - return c.apply(this, arguments); - }; - } - ns[cn].prototype[cn] = ns[cn]; - - // Add super methods - t.each(sp, function(f, n) { - ns[cn].prototype[n] = sp[n]; - }); - - // Add overridden methods - t.each(p, function(f, n) { - // Extend methods if needed - if (sp[n]) { - ns[cn].prototype[n] = function() { - this.parent = sp[n]; - return f.apply(this, arguments); - }; - } else { - if (n != cn) - ns[cn].prototype[n] = f; - } - }); - } - - // Add static methods - t.each(p['static'], function(f, n) { - ns[cn][n] = f; - }); - - if (this.onCreate) - this.onCreate(s[2], s[3], ns[cn].prototype); - }, - - walk : function(o, f, n, s) { - s = s || this; - - if (o) { - if (n) - o = o[n]; - - tinymce.each(o, function(o, i) { - if (f.call(s, o, i, n) === false) - return false; - - tinymce.walk(o, f, n, s); - }); - } - }, - - createNS : function(n, o) { - var i, v; - - o = o || win; - - n = n.split('.'); - for (i=0; i 0 ? args : [listener.scope]); - - if (returnValue === false) - break; - } - - self.inDispatch = false; - - return returnValue; - } - - }); -(function() { - var each = tinymce.each; - - tinymce.create('tinymce.util.URI', { - URI : function(u, s) { - var t = this, o, a, b, base_url; - - // Trim whitespace - u = tinymce.trim(u); - - // Default settings - s = t.settings = s || {}; - - // Strange app protocol that isn't http/https or local anchor - // For example: mailto,skype,tel etc. - if (/^([\w\-]+):([^\/]{2})/i.test(u) || /^\s*#/.test(u)) { - t.source = u; - return; - } - - // Absolute path with no host, fake host and protocol - if (u.indexOf('/') === 0 && u.indexOf('//') !== 0) - u = (s.base_uri ? s.base_uri.protocol || 'http' : 'http') + '://mce_host' + u; - - // Relative path http:// or protocol relative //path - if (!/^[\w\-]*:?\/\//.test(u)) { - base_url = s.base_uri ? s.base_uri.path : new tinymce.util.URI(location.href).directory; - u = ((s.base_uri && s.base_uri.protocol) || 'http') + '://mce_host' + t.toAbsPath(base_url, u); - } - - // Parse URL (Credits goes to Steave, http://blog.stevenlevithan.com/archives/parseuri) - u = u.replace(/@@/g, '(mce_at)'); // Zope 3 workaround, they use @@something - u = /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@\/]*):?([^:@\/]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/.exec(u); - each(["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"], function(v, i) { - var s = u[i]; - - // Zope 3 workaround, they use @@something - if (s) - s = s.replace(/\(mce_at\)/g, '@@'); - - t[v] = s; - }); - - b = s.base_uri; - if (b) { - if (!t.protocol) - t.protocol = b.protocol; - - if (!t.userInfo) - t.userInfo = b.userInfo; - - if (!t.port && t.host === 'mce_host') - t.port = b.port; - - if (!t.host || t.host === 'mce_host') - t.host = b.host; - - t.source = ''; - } - - //t.path = t.path || '/'; - }, - - setPath : function(p) { - var t = this; - - p = /^(.*?)\/?(\w+)?$/.exec(p); - - // Update path parts - t.path = p[0]; - t.directory = p[1]; - t.file = p[2]; - - // Rebuild source - t.source = ''; - t.getURI(); - }, - - toRelative : function(u) { - var t = this, o; - - if (u === "./") - return u; - - u = new tinymce.util.URI(u, {base_uri : t}); - - // Not on same domain/port or protocol - if ((u.host != 'mce_host' && t.host != u.host && u.host) || t.port != u.port || t.protocol != u.protocol) - return u.getURI(); - - var tu = t.getURI(), uu = u.getURI(); - - // Allow usage of the base_uri when relative_urls = true - if(tu == uu || (tu.charAt(tu.length - 1) == "/" && tu.substr(0, tu.length - 1) == uu)) - return tu; - - o = t.toRelPath(t.path, u.path); - - // Add query - if (u.query) - o += '?' + u.query; - - // Add anchor - if (u.anchor) - o += '#' + u.anchor; - - return o; - }, - - toAbsolute : function(u, nh) { - u = new tinymce.util.URI(u, {base_uri : this}); - - return u.getURI(this.host == u.host && this.protocol == u.protocol ? nh : 0); - }, - - toRelPath : function(base, path) { - var items, bp = 0, out = '', i, l; - - // Split the paths - base = base.substring(0, base.lastIndexOf('/')); - base = base.split('/'); - items = path.split('/'); - - if (base.length >= items.length) { - for (i = 0, l = base.length; i < l; i++) { - if (i >= items.length || base[i] != items[i]) { - bp = i + 1; - break; - } - } - } - - if (base.length < items.length) { - for (i = 0, l = items.length; i < l; i++) { - if (i >= base.length || base[i] != items[i]) { - bp = i + 1; - break; - } - } - } - - if (bp === 1) - return path; - - for (i = 0, l = base.length - (bp - 1); i < l; i++) - out += "../"; - - for (i = bp - 1, l = items.length; i < l; i++) { - if (i != bp - 1) - out += "/" + items[i]; - else - out += items[i]; - } - - return out; - }, - - toAbsPath : function(base, path) { - var i, nb = 0, o = [], tr, outPath; - - // Split paths - tr = /\/$/.test(path) ? '/' : ''; - base = base.split('/'); - path = path.split('/'); - - // Remove empty chunks - each(base, function(k) { - if (k) - o.push(k); - }); - - base = o; - - // Merge relURLParts chunks - for (i = path.length - 1, o = []; i >= 0; i--) { - // Ignore empty or . - if (path[i].length === 0 || path[i] === ".") - continue; - - // Is parent - if (path[i] === '..') { - nb++; - continue; - } - - // Move up - if (nb > 0) { - nb--; - continue; - } - - o.push(path[i]); - } - - i = base.length - nb; - - // If /a/b/c or / - if (i <= 0) - outPath = o.reverse().join('/'); - else - outPath = base.slice(0, i).join('/') + '/' + o.reverse().join('/'); - - // Add front / if it's needed - if (outPath.indexOf('/') !== 0) - outPath = '/' + outPath; - - // Add traling / if it's needed - if (tr && outPath.lastIndexOf('/') !== outPath.length - 1) - outPath += tr; - - return outPath; - }, - - getURI : function(nh) { - var s, t = this; - - // Rebuild source - if (!t.source || nh) { - s = ''; - - if (!nh) { - if (t.protocol) - s += t.protocol + '://'; - - if (t.userInfo) - s += t.userInfo + '@'; - - if (t.host) - s += t.host; - - if (t.port) - s += ':' + t.port; - } - - if (t.path) - s += t.path; - - if (t.query) - s += '?' + t.query; - - if (t.anchor) - s += '#' + t.anchor; - - t.source = s; - } - - return t.source; - } - }); -})(); -(function() { - var each = tinymce.each; - - tinymce.create('static tinymce.util.Cookie', { - getHash : function(n) { - var v = this.get(n), h; - - if (v) { - each(v.split('&'), function(v) { - v = v.split('='); - h = h || {}; - h[unescape(v[0])] = unescape(v[1]); - }); - } - - return h; - }, - - setHash : function(n, v, e, p, d, s) { - var o = ''; - - each(v, function(v, k) { - o += (!o ? '' : '&') + escape(k) + '=' + escape(v); - }); - - this.set(n, o, e, p, d, s); - }, - - get : function(n) { - var c = document.cookie, e, p = n + "=", b; - - // Strict mode - if (!c) - return; - - b = c.indexOf("; " + p); - - if (b == -1) { - b = c.indexOf(p); - - if (b !== 0) - return null; - } else - b += 2; - - e = c.indexOf(";", b); - - if (e == -1) - e = c.length; - - return unescape(c.substring(b + p.length, e)); - }, - - set : function(n, v, e, p, d, s) { - document.cookie = n + "=" + escape(v) + - ((e) ? "; expires=" + e.toGMTString() : "") + - ((p) ? "; path=" + escape(p) : "") + - ((d) ? "; domain=" + d : "") + - ((s) ? "; secure" : ""); - }, - - remove : function(name, path, domain) { - var date = new Date(); - - date.setTime(date.getTime() - 1000); - - this.set(name, '', date, path, domain); - } - }); -})(); -(function() { - function serialize(o, quote) { - var i, v, t, name; - - quote = quote || '"'; - - if (o == null) - return 'null'; - - t = typeof o; - - if (t == 'string') { - v = '\bb\tt\nn\ff\rr\""\'\'\\\\'; - - return quote + o.replace(/([\u0080-\uFFFF\x00-\x1f\"\'\\])/g, function(a, b) { - // Make sure single quotes never get encoded inside double quotes for JSON compatibility - if (quote === '"' && a === "'") - return a; - - i = v.indexOf(b); - - if (i + 1) - return '\\' + v.charAt(i + 1); - - a = b.charCodeAt().toString(16); - - return '\\u' + '0000'.substring(a.length) + a; - }) + quote; - } - - if (t == 'object') { - if (o.hasOwnProperty && Object.prototype.toString.call(o) === '[object Array]') { - for (i=0, v = '['; i 0 ? ',' : '') + serialize(o[i], quote); - - return v + ']'; - } - - v = '{'; - - for (name in o) { - if (o.hasOwnProperty(name)) { - v += typeof o[name] != 'function' ? (v.length > 1 ? ',' + quote : quote) + name + quote +':' + serialize(o[name], quote) : ''; - } - } - - return v + '}'; - } - - return '' + o; - }; - - tinymce.util.JSON = { - serialize: serialize, - - parse: function(s) { - try { - return eval('(' + s + ')'); - } catch (ex) { - // Ignore - } - } - - }; -})(); -tinymce.create('static tinymce.util.XHR', { - send : function(o) { - var x, t, w = window, c = 0; - - function ready() { - if (!o.async || x.readyState == 4 || c++ > 10000) { - if (o.success && c < 10000 && x.status == 200) - o.success.call(o.success_scope, '' + x.responseText, x, o); - else if (o.error) - o.error.call(o.error_scope, c > 10000 ? 'TIMED_OUT' : 'GENERAL', x, o); - - x = null; - } else - w.setTimeout(ready, 10); - }; - - // Default settings - o.scope = o.scope || this; - o.success_scope = o.success_scope || o.scope; - o.error_scope = o.error_scope || o.scope; - o.async = o.async === false ? false : true; - o.data = o.data || ''; - - function get(s) { - x = 0; - - try { - x = new ActiveXObject(s); - } catch (ex) { - } - - return x; - }; - - x = w.XMLHttpRequest ? new XMLHttpRequest() : get('Microsoft.XMLHTTP') || get('Msxml2.XMLHTTP'); - - if (x) { - if (x.overrideMimeType) - x.overrideMimeType(o.content_type); - - x.open(o.type || (o.data ? 'POST' : 'GET'), o.url, o.async); - - if (o.content_type) - x.setRequestHeader('Content-Type', o.content_type); - - x.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); - - x.send(o.data); - - // Syncronous request - if (!o.async) - return ready(); - - // Wait for response, onReadyStateChange can not be used since it leaks memory in IE - t = w.setTimeout(ready, 10); - } - } -}); -(function() { - var extend = tinymce.extend, JSON = tinymce.util.JSON, XHR = tinymce.util.XHR; - - tinymce.create('tinymce.util.JSONRequest', { - JSONRequest : function(s) { - this.settings = extend({ - }, s); - this.count = 0; - }, - - send : function(o) { - var ecb = o.error, scb = o.success; - - o = extend(this.settings, o); - - o.success = function(c, x) { - c = JSON.parse(c); - - if (typeof(c) == 'undefined') { - c = { - error : 'JSON Parse error.' - }; - } - - if (c.error) - ecb.call(o.error_scope || o.scope, c.error, x); - else - scb.call(o.success_scope || o.scope, c.result); - }; - - o.error = function(ty, x) { - if (ecb) - ecb.call(o.error_scope || o.scope, ty, x); - }; - - o.data = JSON.serialize({ - id : o.id || 'c' + (this.count++), - method : o.method, - params : o.params - }); - - // JSON content type for Ruby on rails. Bug: #1883287 - o.content_type = 'application/json'; - - XHR.send(o); - }, - - 'static' : { - sendRPC : function(o) { - return new tinymce.util.JSONRequest().send(o); - } - } - }); -}()); -(function(tinymce){ - tinymce.VK = { - BACKSPACE: 8, - DELETE: 46, - DOWN: 40, - ENTER: 13, - LEFT: 37, - RIGHT: 39, - SPACEBAR: 32, - TAB: 9, - UP: 38, - - modifierPressed: function (e) { - return e.shiftKey || e.ctrlKey || e.altKey; - }, - - metaKeyPressed: function(e) { - // Check if ctrl or meta key is pressed also check if alt is false for Polish users - return tinymce.isMac ? e.metaKey : e.ctrlKey && !e.altKey; - } - }; -})(tinymce); -tinymce.util.Quirks = function(editor) { - var VK = tinymce.VK, BACKSPACE = VK.BACKSPACE, DELETE = VK.DELETE, dom = editor.dom, selection = editor.selection, - settings = editor.settings, parser = editor.parser, serializer = editor.serializer, each = tinymce.each; - - function setEditorCommandState(cmd, state) { - try { - editor.getDoc().execCommand(cmd, false, state); - } catch (ex) { - // Ignore - } - } - - function getDocumentMode() { - var documentMode = editor.getDoc().documentMode; - - return documentMode ? documentMode : 6; - }; - - function isDefaultPrevented(e) { - return e.isDefaultPrevented(); - }; - - function cleanupStylesWhenDeleting() { - function removeMergedFormatSpans(isDelete) { - var rng, blockElm, wrapperElm, bookmark, container, offset, elm; - - function isAtStartOrEndOfElm() { - if (container.nodeType == 3) { - if (isDelete && offset == container.length) { - return true; - } - - if (!isDelete && offset === 0) { - return true; - } - } - } - - rng = selection.getRng(); - var tmpRng = [rng.startContainer, rng.startOffset, rng.endContainer, rng.endOffset]; - - if (!rng.collapsed) { - isDelete = true; - } - - container = rng[(isDelete ? 'start' : 'end') + 'Container']; - offset = rng[(isDelete ? 'start' : 'end') + 'Offset']; - - if (container.nodeType == 3) { - blockElm = dom.getParent(rng.startContainer, dom.isBlock); - - // On delete clone the root span of the next block element - if (isDelete) { - blockElm = dom.getNext(blockElm, dom.isBlock); - } - - if (blockElm && (isAtStartOrEndOfElm() || !rng.collapsed)) { - // Wrap children of block in a EM and let WebKit stick is - // runtime styles junk into that EM - wrapperElm = dom.create('em', {'id': '__mceDel'}); - - each(tinymce.grep(blockElm.childNodes), function(node) { - wrapperElm.appendChild(node); - }); - - blockElm.appendChild(wrapperElm); - } - } - - // Do the backspace/delete action - rng = dom.createRng(); - rng.setStart(tmpRng[0], tmpRng[1]); - rng.setEnd(tmpRng[2], tmpRng[3]); - selection.setRng(rng); - editor.getDoc().execCommand(isDelete ? 'ForwardDelete' : 'Delete', false, null); - - // Remove temp wrapper element - if (wrapperElm) { - bookmark = selection.getBookmark(); - - while (elm = dom.get('__mceDel')) { - dom.remove(elm, true); - } - - selection.moveToBookmark(bookmark); - } - } - - editor.onKeyDown.add(function(editor, e) { - var isDelete; - - isDelete = e.keyCode == DELETE; - if (!isDefaultPrevented(e) && (isDelete || e.keyCode == BACKSPACE) && !VK.modifierPressed(e)) { - e.preventDefault(); - removeMergedFormatSpans(isDelete); - } - }); - - editor.addCommand('Delete', function() {removeMergedFormatSpans();}); - }; - - function emptyEditorWhenDeleting() { - function serializeRng(rng) { - var body = dom.create("body"); - var contents = rng.cloneContents(); - body.appendChild(contents); - return selection.serializer.serialize(body, {format: 'html'}); - } - - function allContentsSelected(rng) { - var selection = serializeRng(rng); - - var allRng = dom.createRng(); - allRng.selectNode(editor.getBody()); - - var allSelection = serializeRng(allRng); - return selection === allSelection; - } - - editor.onKeyDown.add(function(editor, e) { - var keyCode = e.keyCode, isCollapsed; - - // Empty the editor if it's needed for example backspace at

|

- if (!isDefaultPrevented(e) && (keyCode == DELETE || keyCode == BACKSPACE)) { - isCollapsed = editor.selection.isCollapsed(); - - // Selection is collapsed but the editor isn't empty - if (isCollapsed && !dom.isEmpty(editor.getBody())) { - return; - } - - // IE deletes all contents correctly when everything is selected - if (tinymce.isIE && !isCollapsed) { - return; - } - - // Selection isn't collapsed but not all the contents is selected - if (!isCollapsed && !allContentsSelected(editor.selection.getRng())) { - return; - } - - // Manually empty the editor - editor.setContent(''); - editor.selection.setCursorLocation(editor.getBody(), 0); - editor.nodeChanged(); - } - }); - }; - - function selectAll() { - editor.onKeyDown.add(function(editor, e) { - if (!isDefaultPrevented(e) && e.keyCode == 65 && VK.metaKeyPressed(e)) { - e.preventDefault(); - editor.execCommand('SelectAll'); - } - }); - }; - - function inputMethodFocus() { - if (!editor.settings.content_editable) { - // Case 1 IME doesn't initialize if you focus the document - dom.bind(editor.getDoc(), 'focusin', function(e) { - selection.setRng(selection.getRng()); - }); - - // Case 2 IME doesn't initialize if you click the documentElement it also doesn't properly fire the focusin event - dom.bind(editor.getDoc(), 'mousedown', function(e) { - if (e.target == editor.getDoc().documentElement) { - editor.getWin().focus(); - selection.setRng(selection.getRng()); - } - }); - } - }; - - function removeHrOnBackspace() { - editor.onKeyDown.add(function(editor, e) { - if (!isDefaultPrevented(e) && e.keyCode === BACKSPACE) { - if (selection.isCollapsed() && selection.getRng(true).startOffset === 0) { - var node = selection.getNode(); - var previousSibling = node.previousSibling; - - if (previousSibling && previousSibling.nodeName && previousSibling.nodeName.toLowerCase() === "hr") { - dom.remove(previousSibling); - tinymce.dom.Event.cancel(e); - } - } - } - }) - } - - function focusBody() { - // Fix for a focus bug in FF 3.x where the body element - // wouldn't get proper focus if the user clicked on the HTML element - if (!Range.prototype.getClientRects) { // Detect getClientRects got introduced in FF 4 - editor.onMouseDown.add(function(editor, e) { - if (!isDefaultPrevented(e) && e.target.nodeName === "HTML") { - var body = editor.getBody(); - - // Blur the body it's focused but not correctly focused - body.blur(); - - // Refocus the body after a little while - setTimeout(function() { - body.focus(); - }, 0); - } - }); - } - }; - - function selectControlElements() { - editor.onClick.add(function(editor, e) { - e = e.target; - - // Workaround for bug, http://bugs.webkit.org/show_bug.cgi?id=12250 - // WebKit can't even do simple things like selecting an image - // Needs tobe the setBaseAndExtend or it will fail to select floated images - if (/^(IMG|HR)$/.test(e.nodeName)) { - selection.getSel().setBaseAndExtent(e, 0, e, 1); - } - - if (e.nodeName == 'A' && dom.hasClass(e, 'mceItemAnchor')) { - selection.select(e); - } - - editor.nodeChanged(); - }); - }; - - function removeStylesWhenDeletingAccrossBlockElements() { - function getAttributeApplyFunction() { - var template = dom.getAttribs(selection.getStart().cloneNode(false)); - - return function() { - var target = selection.getStart(); - - if (target !== editor.getBody()) { - dom.setAttrib(target, "style", null); - - each(template, function(attr) { - target.setAttributeNode(attr.cloneNode(true)); - }); - } - }; - } - - function isSelectionAcrossElements() { - return !selection.isCollapsed() && dom.getParent(selection.getStart(), dom.isBlock) != dom.getParent(selection.getEnd(), dom.isBlock); - } - - function blockEvent(editor, e) { - e.preventDefault(); - return false; - } - - editor.onKeyPress.add(function(editor, e) { - var applyAttributes; - - if (!isDefaultPrevented(e) && (e.keyCode == 8 || e.keyCode == 46) && isSelectionAcrossElements()) { - applyAttributes = getAttributeApplyFunction(); - editor.getDoc().execCommand('delete', false, null); - applyAttributes(); - e.preventDefault(); - return false; - } - }); - - dom.bind(editor.getDoc(), 'cut', function(e) { - var applyAttributes; - - if (!isDefaultPrevented(e) && isSelectionAcrossElements()) { - applyAttributes = getAttributeApplyFunction(); - editor.onKeyUp.addToTop(blockEvent); - - setTimeout(function() { - applyAttributes(); - editor.onKeyUp.remove(blockEvent); - }, 0); - } - }); - } - - function selectionChangeNodeChanged() { - var lastRng, selectionTimer; - - dom.bind(editor.getDoc(), 'selectionchange', function() { - if (selectionTimer) { - clearTimeout(selectionTimer); - selectionTimer = 0; - } - - selectionTimer = window.setTimeout(function() { - var rng = selection.getRng(); - - // Compare the ranges to see if it was a real change or not - if (!lastRng || !tinymce.dom.RangeUtils.compareRanges(rng, lastRng)) { - editor.nodeChanged(); - lastRng = rng; - } - }, 50); - }); - } - - function ensureBodyHasRoleApplication() { - document.body.setAttribute("role", "application"); - } - - function disableBackspaceIntoATable() { - editor.onKeyDown.add(function(editor, e) { - if (!isDefaultPrevented(e) && e.keyCode === BACKSPACE) { - if (selection.isCollapsed() && selection.getRng(true).startOffset === 0) { - var previousSibling = selection.getNode().previousSibling; - if (previousSibling && previousSibling.nodeName && previousSibling.nodeName.toLowerCase() === "table") { - return tinymce.dom.Event.cancel(e); - } - } - } - }) - } - - function addNewLinesBeforeBrInPre() { - // IE8+ rendering mode does the right thing with BR in PRE - if (getDocumentMode() > 7) { - return; - } - - // Enable display: none in area and add a specific class that hides all BR elements in PRE to - // avoid the caret from getting stuck at the BR elements while pressing the right arrow key - setEditorCommandState('RespectVisibilityInDesign', true); - editor.contentStyles.push('.mceHideBrInPre pre br {display: none}'); - dom.addClass(editor.getBody(), 'mceHideBrInPre'); - - // Adds a \n before all BR elements in PRE to get them visual - parser.addNodeFilter('pre', function(nodes, name) { - var i = nodes.length, brNodes, j, brElm, sibling; - - while (i--) { - brNodes = nodes[i].getAll('br'); - j = brNodes.length; - while (j--) { - brElm = brNodes[j]; - - // Add \n before BR in PRE elements on older IE:s so the new lines get rendered - sibling = brElm.prev; - if (sibling && sibling.type === 3 && sibling.value.charAt(sibling.value - 1) != '\n') { - sibling.value += '\n'; - } else { - brElm.parent.insert(new tinymce.html.Node('#text', 3), brElm, true).value = '\n'; - } - } - } - }); - - // Removes any \n before BR elements in PRE since other browsers and in contentEditable=false mode they will be visible - serializer.addNodeFilter('pre', function(nodes, name) { - var i = nodes.length, brNodes, j, brElm, sibling; - - while (i--) { - brNodes = nodes[i].getAll('br'); - j = brNodes.length; - while (j--) { - brElm = brNodes[j]; - sibling = brElm.prev; - if (sibling && sibling.type == 3) { - sibling.value = sibling.value.replace(/\r?\n$/, ''); - } - } - } - }); - } - - function removePreSerializedStylesWhenSelectingControls() { - dom.bind(editor.getBody(), 'mouseup', function(e) { - var value, node = selection.getNode(); - - // Moved styles to attributes on IMG eements - if (node.nodeName == 'IMG') { - // Convert style width to width attribute - if (value = dom.getStyle(node, 'width')) { - dom.setAttrib(node, 'width', value.replace(/[^0-9%]+/g, '')); - dom.setStyle(node, 'width', ''); - } - - // Convert style height to height attribute - if (value = dom.getStyle(node, 'height')) { - dom.setAttrib(node, 'height', value.replace(/[^0-9%]+/g, '')); - dom.setStyle(node, 'height', ''); - } - } - }); - } - - function keepInlineElementOnDeleteBackspace() { - editor.onKeyDown.add(function(editor, e) { - var isDelete, rng, container, offset, brElm, sibling, collapsed; - - isDelete = e.keyCode == DELETE; - if (!isDefaultPrevented(e) && (isDelete || e.keyCode == BACKSPACE) && !VK.modifierPressed(e)) { - rng = selection.getRng(); - container = rng.startContainer; - offset = rng.startOffset; - collapsed = rng.collapsed; - - // Override delete if the start container is a text node and is at the beginning of text or - // just before/after the last character to be deleted in collapsed mode - if (container.nodeType == 3 && container.nodeValue.length > 0 && ((offset === 0 && !collapsed) || (collapsed && offset === (isDelete ? 0 : 1)))) { - // Edge case when deleting

|x

- sibling = container.previousSibling; - if (sibling && sibling.nodeName == "IMG") { - return; - } - - nonEmptyElements = editor.schema.getNonEmptyElements(); - - // Prevent default logic since it's broken - e.preventDefault(); - - // Insert a BR before the text node this will prevent the containing element from being deleted/converted - brElm = dom.create('br', {id: '__tmp'}); - container.parentNode.insertBefore(brElm, container); - - // Do the browser delete - editor.getDoc().execCommand(isDelete ? 'ForwardDelete' : 'Delete', false, null); - - // Check if the previous sibling is empty after deleting for example:

|

- container = selection.getRng().startContainer; - sibling = container.previousSibling; - if (sibling && sibling.nodeType == 1 && !dom.isBlock(sibling) && dom.isEmpty(sibling) && !nonEmptyElements[sibling.nodeName.toLowerCase()]) { - dom.remove(sibling); - } - - // Remove the temp element we inserted - dom.remove('__tmp'); - } - } - }); - } - - function removeBlockQuoteOnBackSpace() { - // Add block quote deletion handler - editor.onKeyDown.add(function(editor, e) { - var rng, container, offset, root, parent; - - if (isDefaultPrevented(e) || e.keyCode != VK.BACKSPACE) { - return; - } - - rng = selection.getRng(); - container = rng.startContainer; - offset = rng.startOffset; - root = dom.getRoot(); - parent = container; - - if (!rng.collapsed || offset !== 0) { - return; - } - - while (parent && parent.parentNode && parent.parentNode.firstChild == parent && parent.parentNode != root) { - parent = parent.parentNode; - } - - // Is the cursor at the beginning of a blockquote? - if (parent.tagName === 'BLOCKQUOTE') { - // Remove the blockquote - editor.formatter.toggle('blockquote', null, parent); - - // Move the caret to the beginning of container - rng = dom.createRng(); - rng.setStart(container, 0); - rng.setEnd(container, 0); - selection.setRng(rng); - } - }); - }; - - function setGeckoEditingOptions() { - function setOpts() { - editor._refreshContentEditable(); - - setEditorCommandState("StyleWithCSS", false); - setEditorCommandState("enableInlineTableEditing", false); - - if (!settings.object_resizing) { - setEditorCommandState("enableObjectResizing", false); - } - }; - - if (!settings.readonly) { - editor.onBeforeExecCommand.add(setOpts); - editor.onMouseDown.add(setOpts); - } - }; - - function addBrAfterLastLinks() { - function fixLinks(editor, o) { - each(dom.select('a'), function(node) { - var parentNode = node.parentNode, root = dom.getRoot(); - - if (parentNode.lastChild === node) { - while (parentNode && !dom.isBlock(parentNode)) { - if (parentNode.parentNode.lastChild !== parentNode || parentNode === root) { - return; - } - - parentNode = parentNode.parentNode; - } - - dom.add(parentNode, 'br', {'data-mce-bogus' : 1}); - } - }); - }; - - editor.onExecCommand.add(function(editor, cmd) { - if (cmd === 'CreateLink') { - fixLinks(editor); - } - }); - - editor.onSetContent.add(selection.onSetContent.add(fixLinks)); - }; - - function setDefaultBlockType() { - if (settings.forced_root_block) { - editor.onInit.add(function() { - setEditorCommandState('DefaultParagraphSeparator', settings.forced_root_block); - }); - } - } - - function removeGhostSelection() { - function repaint(sender, args) { - if (!sender || !args.initial) { - editor.execCommand('mceRepaint'); - } - }; - - editor.onUndo.add(repaint); - editor.onRedo.add(repaint); - editor.onSetContent.add(repaint); - }; - - function deleteControlItemOnBackSpace() { - editor.onKeyDown.add(function(editor, e) { - var rng; - - if (!isDefaultPrevented(e) && e.keyCode == BACKSPACE) { - rng = editor.getDoc().selection.createRange(); - if (rng && rng.item) { - e.preventDefault(); - editor.undoManager.beforeChange(); - dom.remove(rng.item(0)); - editor.undoManager.add(); - } - } - }); - }; - - function renderEmptyBlocksFix() { - var emptyBlocksCSS; - - // IE10+ - if (getDocumentMode() >= 10) { - emptyBlocksCSS = ''; - each('p div h1 h2 h3 h4 h5 h6'.split(' '), function(name, i) { - emptyBlocksCSS += (i > 0 ? ',' : '') + name + ':empty'; - }); - - editor.contentStyles.push(emptyBlocksCSS + '{padding-right: 1px !important}'); - } - }; - - function fakeImageResize() { - var selectedElmX, selectedElmY, selectedElm, selectedElmGhost, selectedHandle, startX, startY, startW, startH, ratio, - resizeHandles, width, height, rootDocument = document, editableDoc = editor.getDoc(); - - if (!settings.object_resizing || settings.webkit_fake_resize === false) { - return; - } - - // Try disabling object resizing if WebKit implements resizing in the future - setEditorCommandState("enableObjectResizing", false); - - // Details about each resize handle how to scale etc - resizeHandles = { - // Name: x multiplier, y multiplier, delta size x, delta size y - n: [.5, 0, 0, -1], - e: [1, .5, 1, 0], - s: [.5, 1, 0, 1], - w: [0, .5, -1, 0], - nw: [0, 0, -1, -1], - ne: [1, 0, 1, -1], - se: [1, 1, 1, 1], - sw : [0, 1, -1, 1] - }; - - function resizeElement(e) { - var deltaX, deltaY; - - // Calc new width/height - deltaX = e.screenX - startX; - deltaY = e.screenY - startY; - - // Calc new size - width = deltaX * selectedHandle[2] + startW; - height = deltaY * selectedHandle[3] + startH; - - // Never scale down lower than 5 pixels - width = width < 5 ? 5 : width; - height = height < 5 ? 5 : height; - - // Constrain proportions when modifier key is pressed or if the nw, ne, sw, se corners are moved on an image - if (VK.modifierPressed(e) || (selectedElm.nodeName == "IMG" && selectedHandle[2] * selectedHandle[3] !== 0)) { - width = Math.round(height / ratio); - height = Math.round(width * ratio); - } - - // Update ghost size - dom.setStyles(selectedElmGhost, { - width: width, - height: height - }); - - // Update ghost X position if needed - if (selectedHandle[2] < 0 && selectedElmGhost.clientWidth <= width) { - dom.setStyle(selectedElmGhost, 'left', selectedElmX + (startW - width)); - } - - // Update ghost Y position if needed - if (selectedHandle[3] < 0 && selectedElmGhost.clientHeight <= height) { - dom.setStyle(selectedElmGhost, 'top', selectedElmY + (startH - height)); - } - } - - function endResize() { - function setSizeProp(name, value) { - if (value) { - // Resize by using style or attribute - if (selectedElm.style[name] || !editor.schema.isValid(selectedElm.nodeName.toLowerCase(), name)) { - dom.setStyle(selectedElm, name, value); - } else { - dom.setAttrib(selectedElm, name, value); - } - } - } - - // Set width/height properties - setSizeProp('width', width); - setSizeProp('height', height); - - dom.unbind(editableDoc, 'mousemove', resizeElement); - dom.unbind(editableDoc, 'mouseup', endResize); - - if (rootDocument != editableDoc) { - dom.unbind(rootDocument, 'mousemove', resizeElement); - dom.unbind(rootDocument, 'mouseup', endResize); - } - - // Remove ghost and update resize handle positions - dom.remove(selectedElmGhost); - showResizeRect(selectedElm); - } - - function showResizeRect(targetElm) { - var position, targetWidth, targetHeight; - - hideResizeRect(); - - // Get position and size of target - position = dom.getPos(targetElm); - selectedElmX = position.x; - selectedElmY = position.y; - targetWidth = targetElm.offsetWidth; - targetHeight = targetElm.offsetHeight; - - // Reset width/height if user selects a new image/table - if (selectedElm != targetElm) { - selectedElm = targetElm; - width = height = 0; - } - - each(resizeHandles, function(handle, name) { - var handleElm; - - // Get existing or render resize handle - handleElm = dom.get('mceResizeHandle' + name); - if (!handleElm) { - handleElm = dom.add(editableDoc.documentElement, 'div', { - id: 'mceResizeHandle' + name, - 'class': 'mceResizeHandle', - style: 'cursor:' + name + '-resize; margin:0; padding:0' - }); - - dom.bind(handleElm, 'mousedown', function(e) { - e.preventDefault(); - - endResize(); - - startX = e.screenX; - startY = e.screenY; - startW = selectedElm.clientWidth; - startH = selectedElm.clientHeight; - ratio = startH / startW; - selectedHandle = handle; - - selectedElmGhost = selectedElm.cloneNode(true); - dom.addClass(selectedElmGhost, 'mceClonedResizable'); - dom.setStyles(selectedElmGhost, { - left: selectedElmX, - top: selectedElmY, - margin: 0 - }); - - editableDoc.documentElement.appendChild(selectedElmGhost); - - dom.bind(editableDoc, 'mousemove', resizeElement); - dom.bind(editableDoc, 'mouseup', endResize); - - if (rootDocument != editableDoc) { - dom.bind(rootDocument, 'mousemove', resizeElement); - dom.bind(rootDocument, 'mouseup', endResize); - } - }); - } else { - dom.show(handleElm); - } - - // Position element - dom.setStyles(handleElm, { - left: (targetWidth * handle[0] + selectedElmX) - (handleElm.offsetWidth / 2), - top: (targetHeight * handle[1] + selectedElmY) - (handleElm.offsetHeight / 2) - }); - }); - - // Only add resize rectangle on WebKit and only on images - if (!tinymce.isOpera && selectedElm.nodeName == "IMG") { - selectedElm.setAttribute('data-mce-selected', '1'); - } - } - - function hideResizeRect() { - if (selectedElm) { - selectedElm.removeAttribute('data-mce-selected'); - } - - for (var name in resizeHandles) { - dom.hide('mceResizeHandle' + name); - } - } - - // Add CSS for resize handles, cloned element and selected - editor.contentStyles.push( - '.mceResizeHandle {' + - 'position: absolute;' + - 'border: 1px solid black;' + - 'background: #FFF;' + - 'width: 5px;' + - 'height: 5px;' + - 'z-index: 10000' + - '}' + - '.mceResizeHandle:hover {' + - 'background: #000' + - '}' + - 'img[data-mce-selected] {' + - 'outline: 1px solid black' + - '}' + - 'img.mceClonedResizable, table.mceClonedResizable {' + - 'position: absolute;' + - 'outline: 1px dashed black;' + - 'opacity: .5;' + - 'z-index: 10000' + - '}' - ); - - function updateResizeRect() { - var controlElm = dom.getParent(selection.getNode(), 'table,img'); - - // Remove data-mce-selected from all elements since they might have been copied using Ctrl+c/v - each(dom.select('img[data-mce-selected]'), function(img) { - img.removeAttribute('data-mce-selected'); - }); - - if (controlElm) { - showResizeRect(controlElm); - } else { - hideResizeRect(); - } - } - - // Show/hide resize rect when image is selected - editor.onNodeChange.add(updateResizeRect); - - // Fixes WebKit quirk where it returns IMG on getNode if caret is after last image in container - dom.bind(editableDoc, 'selectionchange', updateResizeRect); - - // Remove the internal attribute when serializing the DOM - editor.serializer.addAttributeFilter('data-mce-selected', function(nodes, name) { - var i = nodes.length; - - while (i--) { - nodes[i].attr(name, null); - } - }); - } - - function keepNoScriptContents() { - if (getDocumentMode() < 9) { - parser.addNodeFilter('noscript', function(nodes) { - var i = nodes.length, node, textNode; - - while (i--) { - node = nodes[i]; - textNode = node.firstChild; - - if (textNode) { - node.attr('data-mce-innertext', textNode.value); - } - } - }); - - serializer.addNodeFilter('noscript', function(nodes) { - var i = nodes.length, node, textNode, value; - - while (i--) { - node = nodes[i]; - textNode = nodes[i].firstChild; - - if (textNode) { - textNode.value = tinymce.html.Entities.decode(textNode.value); - } else { - // Old IE can't retain noscript value so an attribute is used to store it - value = node.attributes.map['data-mce-innertext']; - if (value) { - node.attr('data-mce-innertext', null); - textNode = new tinymce.html.Node('#text', 3); - textNode.value = value; - textNode.raw = true; - node.append(textNode); - } - } - } - }); - } - } - - function bodyHeight() { - editor.contentStyles.push('body {min-height: 100px}'); - editor.onClick.add(function(ed, e) { - if (e.target.nodeName == 'HTML') { - editor.execCommand('SelectAll'); - editor.selection.collapse(true); - editor.nodeChanged(); - } - }); - } - - function fixControlSelection() { - editor.onInit.add(function() { - var selectedRng; - - editor.getBody().addEventListener('mscontrolselect', function(e) { - setTimeout(function() { - if (editor.selection.getNode() != e.target) { - selectedRng = editor.selection.getRng(); - selection.fakeRng = editor.dom.createRng(); - selection.fakeRng.setStartBefore(e.target); - selection.fakeRng.setEndAfter(e.target); - } - }, 0); - }, false); - - editor.getDoc().addEventListener('selectionchange', function(e) { - if (selectedRng && !tinymce.dom.RangeUtils.compareRanges(editor.selection.getRng(), selectedRng)) { - selection.fakeRng = selectedRng = null; - } - }, false); - }); - } - - // All browsers - disableBackspaceIntoATable(); - removeBlockQuoteOnBackSpace(); - emptyEditorWhenDeleting(); - - // WebKit - if (tinymce.isWebKit) { - keepInlineElementOnDeleteBackspace(); - cleanupStylesWhenDeleting(); - inputMethodFocus(); - selectControlElements(); - setDefaultBlockType(); - - // iOS - if (tinymce.isIDevice) { - selectionChangeNodeChanged(); - } else { - fakeImageResize(); - selectAll(); - } - } - - // IE - if (tinymce.isIE && !tinymce.isIE11) { - removeHrOnBackspace(); - ensureBodyHasRoleApplication(); - addNewLinesBeforeBrInPre(); - removePreSerializedStylesWhenSelectingControls(); - deleteControlItemOnBackSpace(); - renderEmptyBlocksFix(); - keepNoScriptContents(); - } - - // IE 11+ - if (tinymce.isIE11) { - bodyHeight(); - fixControlSelection(); - } - - // Gecko - if (tinymce.isGecko && !tinymce.isIE11) { - removeHrOnBackspace(); - focusBody(); - removeStylesWhenDeletingAccrossBlockElements(); - setGeckoEditingOptions(); - addBrAfterLastLinks(); - removeGhostSelection(); - } - - // Opera - if (tinymce.isOpera) { - fakeImageResize(); - } -}; -(function(tinymce) { - var namedEntities, baseEntities, reverseEntities, - attrsCharsRegExp = /[&<>\"\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g, - textCharsRegExp = /[<>&\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g, - rawCharsRegExp = /[<>&\"\']/g, - entityRegExp = /&(#x|#)?([\w]+);/g, - asciiMap = { - 128 : "\u20AC", 130 : "\u201A", 131 : "\u0192", 132 : "\u201E", 133 : "\u2026", 134 : "\u2020", - 135 : "\u2021", 136 : "\u02C6", 137 : "\u2030", 138 : "\u0160", 139 : "\u2039", 140 : "\u0152", - 142 : "\u017D", 145 : "\u2018", 146 : "\u2019", 147 : "\u201C", 148 : "\u201D", 149 : "\u2022", - 150 : "\u2013", 151 : "\u2014", 152 : "\u02DC", 153 : "\u2122", 154 : "\u0161", 155 : "\u203A", - 156 : "\u0153", 158 : "\u017E", 159 : "\u0178" - }; - - // Raw entities - baseEntities = { - '\"' : '"', // Needs to be escaped since the YUI compressor would otherwise break the code - "'" : ''', - '<' : '<', - '>' : '>', - '&' : '&' - }; - - // Reverse lookup table for raw entities - reverseEntities = { - '<' : '<', - '>' : '>', - '&' : '&', - '"' : '"', - ''' : "'" - }; - - // Decodes text by using the browser - function nativeDecode(text) { - var elm; - - elm = document.createElement("div"); - elm.innerHTML = text; - - return elm.textContent || elm.innerText || text; - }; - - // Build a two way lookup table for the entities - function buildEntitiesLookup(items, radix) { - var i, chr, entity, lookup = {}; - - if (items) { - items = items.split(','); - radix = radix || 10; - - // Build entities lookup table - for (i = 0; i < items.length; i += 2) { - chr = String.fromCharCode(parseInt(items[i], radix)); - - // Only add non base entities - if (!baseEntities[chr]) { - entity = '&' + items[i + 1] + ';'; - lookup[chr] = entity; - lookup[entity] = chr; - } - } - - return lookup; - } - }; - - // Unpack entities lookup where the numbers are in radix 32 to reduce the size - namedEntities = buildEntitiesLookup( - '50,nbsp,51,iexcl,52,cent,53,pound,54,curren,55,yen,56,brvbar,57,sect,58,uml,59,copy,' + - '5a,ordf,5b,laquo,5c,not,5d,shy,5e,reg,5f,macr,5g,deg,5h,plusmn,5i,sup2,5j,sup3,5k,acute,' + - '5l,micro,5m,para,5n,middot,5o,cedil,5p,sup1,5q,ordm,5r,raquo,5s,frac14,5t,frac12,5u,frac34,' + - '5v,iquest,60,Agrave,61,Aacute,62,Acirc,63,Atilde,64,Auml,65,Aring,66,AElig,67,Ccedil,' + - '68,Egrave,69,Eacute,6a,Ecirc,6b,Euml,6c,Igrave,6d,Iacute,6e,Icirc,6f,Iuml,6g,ETH,6h,Ntilde,' + - '6i,Ograve,6j,Oacute,6k,Ocirc,6l,Otilde,6m,Ouml,6n,times,6o,Oslash,6p,Ugrave,6q,Uacute,' + - '6r,Ucirc,6s,Uuml,6t,Yacute,6u,THORN,6v,szlig,70,agrave,71,aacute,72,acirc,73,atilde,74,auml,' + - '75,aring,76,aelig,77,ccedil,78,egrave,79,eacute,7a,ecirc,7b,euml,7c,igrave,7d,iacute,7e,icirc,' + - '7f,iuml,7g,eth,7h,ntilde,7i,ograve,7j,oacute,7k,ocirc,7l,otilde,7m,ouml,7n,divide,7o,oslash,' + - '7p,ugrave,7q,uacute,7r,ucirc,7s,uuml,7t,yacute,7u,thorn,7v,yuml,ci,fnof,sh,Alpha,si,Beta,' + - 'sj,Gamma,sk,Delta,sl,Epsilon,sm,Zeta,sn,Eta,so,Theta,sp,Iota,sq,Kappa,sr,Lambda,ss,Mu,' + - 'st,Nu,su,Xi,sv,Omicron,t0,Pi,t1,Rho,t3,Sigma,t4,Tau,t5,Upsilon,t6,Phi,t7,Chi,t8,Psi,' + - 't9,Omega,th,alpha,ti,beta,tj,gamma,tk,delta,tl,epsilon,tm,zeta,tn,eta,to,theta,tp,iota,' + - 'tq,kappa,tr,lambda,ts,mu,tt,nu,tu,xi,tv,omicron,u0,pi,u1,rho,u2,sigmaf,u3,sigma,u4,tau,' + - 'u5,upsilon,u6,phi,u7,chi,u8,psi,u9,omega,uh,thetasym,ui,upsih,um,piv,812,bull,816,hellip,' + - '81i,prime,81j,Prime,81u,oline,824,frasl,88o,weierp,88h,image,88s,real,892,trade,89l,alefsym,' + - '8cg,larr,8ch,uarr,8ci,rarr,8cj,darr,8ck,harr,8dl,crarr,8eg,lArr,8eh,uArr,8ei,rArr,8ej,dArr,' + - '8ek,hArr,8g0,forall,8g2,part,8g3,exist,8g5,empty,8g7,nabla,8g8,isin,8g9,notin,8gb,ni,8gf,prod,' + - '8gh,sum,8gi,minus,8gn,lowast,8gq,radic,8gt,prop,8gu,infin,8h0,ang,8h7,and,8h8,or,8h9,cap,8ha,cup,' + - '8hb,int,8hk,there4,8hs,sim,8i5,cong,8i8,asymp,8j0,ne,8j1,equiv,8j4,le,8j5,ge,8k2,sub,8k3,sup,8k4,' + - 'nsub,8k6,sube,8k7,supe,8kl,oplus,8kn,otimes,8l5,perp,8m5,sdot,8o8,lceil,8o9,rceil,8oa,lfloor,8ob,' + - 'rfloor,8p9,lang,8pa,rang,9ea,loz,9j0,spades,9j3,clubs,9j5,hearts,9j6,diams,ai,OElig,aj,oelig,b0,' + - 'Scaron,b1,scaron,bo,Yuml,m6,circ,ms,tilde,802,ensp,803,emsp,809,thinsp,80c,zwnj,80d,zwj,80e,lrm,' + - '80f,rlm,80j,ndash,80k,mdash,80o,lsquo,80p,rsquo,80q,sbquo,80s,ldquo,80t,rdquo,80u,bdquo,810,dagger,' + - '811,Dagger,81g,permil,81p,lsaquo,81q,rsaquo,85c,euro', 32); - - tinymce.html = tinymce.html || {}; - - tinymce.html.Entities = { - encodeRaw : function(text, attr) { - return text.replace(attr ? attrsCharsRegExp : textCharsRegExp, function(chr) { - return baseEntities[chr] || chr; - }); - }, - - encodeAllRaw : function(text) { - return ('' + text).replace(rawCharsRegExp, function(chr) { - return baseEntities[chr] || chr; - }); - }, - - encodeNumeric : function(text, attr) { - return text.replace(attr ? attrsCharsRegExp : textCharsRegExp, function(chr) { - // Multi byte sequence convert it to a single entity - if (chr.length > 1) - return '&#' + (((chr.charCodeAt(0) - 0xD800) * 0x400) + (chr.charCodeAt(1) - 0xDC00) + 0x10000) + ';'; - - return baseEntities[chr] || '&#' + chr.charCodeAt(0) + ';'; - }); - }, - - encodeNamed : function(text, attr, entities) { - entities = entities || namedEntities; - - return text.replace(attr ? attrsCharsRegExp : textCharsRegExp, function(chr) { - return baseEntities[chr] || entities[chr] || chr; - }); - }, - - getEncodeFunc : function(name, entities) { - var Entities = tinymce.html.Entities; - - entities = buildEntitiesLookup(entities) || namedEntities; - - function encodeNamedAndNumeric(text, attr) { - return text.replace(attr ? attrsCharsRegExp : textCharsRegExp, function(chr) { - return baseEntities[chr] || entities[chr] || '&#' + chr.charCodeAt(0) + ';' || chr; - }); - }; - - function encodeCustomNamed(text, attr) { - return Entities.encodeNamed(text, attr, entities); - }; - - // Replace + with , to be compatible with previous TinyMCE versions - name = tinymce.makeMap(name.replace(/\+/g, ',')); - - // Named and numeric encoder - if (name.named && name.numeric) - return encodeNamedAndNumeric; - - // Named encoder - if (name.named) { - // Custom names - if (entities) - return encodeCustomNamed; - - return Entities.encodeNamed; - } - - // Numeric - if (name.numeric) - return Entities.encodeNumeric; - - // Raw encoder - return Entities.encodeRaw; - }, - - decode : function(text) { - return text.replace(entityRegExp, function(all, numeric, value) { - if (numeric) { - value = parseInt(value, numeric.length === 2 ? 16 : 10); - - // Support upper UTF - if (value > 0xFFFF) { - value -= 0x10000; - - return String.fromCharCode(0xD800 + (value >> 10), 0xDC00 + (value & 0x3FF)); - } else - return asciiMap[value] || String.fromCharCode(value); - } - - return reverseEntities[all] || namedEntities[all] || nativeDecode(all); - }); - } - }; -})(tinymce); -tinymce.html.Styles = function(settings, schema) { - var rgbRegExp = /rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)/gi, - urlOrStrRegExp = /(?:url(?:(?:\(\s*\"([^\"]+)\"\s*\))|(?:\(\s*\'([^\']+)\'\s*\))|(?:\(\s*([^)\s]+)\s*\))))|(?:\'([^\']+)\')|(?:\"([^\"]+)\")/gi, - styleRegExp = /\s*([^:]+):\s*([^;]+);?/g, - trimRightRegExp = /\s+$/, - urlColorRegExp = /rgb/, - undef, i, encodingLookup = {}, encodingItems; - - settings = settings || {}; - - encodingItems = '\\" \\\' \\; \\: ; : \uFEFF'.split(' '); - for (i = 0; i < encodingItems.length; i++) { - encodingLookup[encodingItems[i]] = '\uFEFF' + i; - encodingLookup['\uFEFF' + i] = encodingItems[i]; - } - - function toHex(match, r, g, b) { - function hex(val) { - val = parseInt(val).toString(16); - - return val.length > 1 ? val : '0' + val; // 0 -> 00 - }; - - return '#' + hex(r) + hex(g) + hex(b); - }; - - return { - toHex : function(color) { - return color.replace(rgbRegExp, toHex); - }, - - parse : function(css) { - var styles = {}, matches, name, value, isEncoded, urlConverter = settings.url_converter, urlConverterScope = settings.url_converter_scope || this; - - function compress(prefix, suffix) { - var top, right, bottom, left; - - // IE 11 will produce a border-image: none when getting the style attribute from

- // So lets asume it shouldn't be there - if (styles['border-image'] === 'none') { - delete styles['border-image']; - } - - // Get values and check it it needs compressing - top = styles[prefix + '-top' + suffix]; - if (!top) - return; - - right = styles[prefix + '-right' + suffix]; - if (top != right) - return; - - bottom = styles[prefix + '-bottom' + suffix]; - if (right != bottom) - return; - - left = styles[prefix + '-left' + suffix]; - if (bottom != left) - return; - - // Compress - styles[prefix + suffix] = left; - delete styles[prefix + '-top' + suffix]; - delete styles[prefix + '-right' + suffix]; - delete styles[prefix + '-bottom' + suffix]; - delete styles[prefix + '-left' + suffix]; - }; - - function canCompress(key) { - var value = styles[key], i; - - if (!value || value.indexOf(' ') < 0) - return; - - value = value.split(' '); - i = value.length; - while (i--) { - if (value[i] !== value[0]) - return false; - } - - styles[key] = value[0]; - - return true; - }; - - function compress2(target, a, b, c) { - if (!canCompress(a)) - return; - - if (!canCompress(b)) - return; - - if (!canCompress(c)) - return; - - // Compress - styles[target] = styles[a] + ' ' + styles[b] + ' ' + styles[c]; - delete styles[a]; - delete styles[b]; - delete styles[c]; - }; - - // Encodes the specified string by replacing all \" \' ; : with _ - function encode(str) { - isEncoded = true; - - return encodingLookup[str]; - }; - - // Decodes the specified string by replacing all _ with it's original value \" \' etc - // It will also decode the \" \' if keep_slashes is set to fale or omitted - function decode(str, keep_slashes) { - if (isEncoded) { - str = str.replace(/\uFEFF[0-9]/g, function(str) { - return encodingLookup[str]; - }); - } - - if (!keep_slashes) - str = str.replace(/\\([\'\";:])/g, "$1"); - - return str; - }; - - function processUrl(match, url, url2, url3, str, str2) { - str = str || str2; - - if (str) { - str = decode(str); - - // Force strings into single quote format - return "'" + str.replace(/\'/g, "\\'") + "'"; - } - - url = decode(url || url2 || url3); - - // Convert the URL to relative/absolute depending on config - if (urlConverter) - url = urlConverter.call(urlConverterScope, url, 'style'); - - // Output new URL format - return "url('" + url.replace(/\'/g, "\\'") + "')"; - }; - - if (css) { - // Encode \" \' % and ; and : inside strings so they don't interfere with the style parsing - css = css.replace(/\\[\"\';:\uFEFF]/g, encode).replace(/\"[^\"]+\"|\'[^\']+\'/g, function(str) { - return str.replace(/[;:]/g, encode); - }); - - // Parse styles - while (matches = styleRegExp.exec(css)) { - name = matches[1].replace(trimRightRegExp, '').toLowerCase(); - value = matches[2].replace(trimRightRegExp, ''); - - if (name && value.length > 0) { - // Opera will produce 700 instead of bold in their style values - if (name === 'font-weight' && value === '700') - value = 'bold'; - else if (name === 'color' || name === 'background-color') // Lowercase colors like RED - value = value.toLowerCase(); - - // Convert RGB colors to HEX - value = value.replace(rgbRegExp, toHex); - - // Convert URLs and force them into url('value') format - value = value.replace(urlOrStrRegExp, processUrl); - styles[name] = isEncoded ? decode(value, true) : value; - } - - styleRegExp.lastIndex = matches.index + matches[0].length; - } - - // Compress the styles to reduce it's size for example IE will expand styles - compress("border", ""); - compress("border", "-width"); - compress("border", "-color"); - compress("border", "-style"); - compress("padding", ""); - compress("margin", ""); - compress2('border', 'border-width', 'border-style', 'border-color'); - - // Remove pointless border, IE produces these - if (styles.border === 'medium none') - delete styles.border; - } - - return styles; - }, - - serialize : function(styles, element_name) { - var css = '', name, value; - - function serializeStyles(name) { - var styleList, i, l, value; - - styleList = schema.styles[name]; - if (styleList) { - for (i = 0, l = styleList.length; i < l; i++) { - name = styleList[i]; - value = styles[name]; - - if (value !== undef && value.length > 0) - css += (css.length > 0 ? ' ' : '') + name + ': ' + value + ';'; - } - } - }; - - // Serialize styles according to schema - if (element_name && schema && schema.styles) { - // Serialize global styles and element specific styles - serializeStyles('*'); - serializeStyles(element_name); - } else { - // Output the styles in the order they are inside the object - for (name in styles) { - value = styles[name]; - - if (value !== undef && value.length > 0) - css += (css.length > 0 ? ' ' : '') + name + ': ' + value + ';'; - } - } - - return css; - } - }; -}; -(function(tinymce) { - var mapCache = {}, makeMap = tinymce.makeMap, each = tinymce.each; - - function split(str, delim) { - return str.split(delim || ','); - }; - - function unpack(lookup, data) { - var key, elements = {}; - - function replace(value) { - return value.replace(/[A-Z]+/g, function(key) { - return replace(lookup[key]); - }); - }; - - // Unpack lookup - for (key in lookup) { - if (lookup.hasOwnProperty(key)) - lookup[key] = replace(lookup[key]); - } - - // Unpack and parse data into object map - replace(data).replace(/#/g, '#text').replace(/(\w+)\[([^\]]+)\]\[([^\]]*)\]/g, function(str, name, attributes, children) { - attributes = split(attributes, '|'); - - elements[name] = { - attributes : makeMap(attributes), - attributesOrder : attributes, - children : makeMap(children, '|', {'#comment' : {}}) - } - }); - - return elements; - }; - - function getHTML5() { - var html5 = mapCache.html5; - - if (!html5) { - html5 = mapCache.html5 = unpack({ - A : 'id|accesskey|class|dir|draggable|item|hidden|itemprop|role|spellcheck|style|subject|title|onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup', - B : '#|a|abbr|area|audio|b|bdo|br|button|canvas|cite|code|command|datalist|del|dfn|em|embed|i|iframe|img|input|ins|kbd|keygen|label|link|map|mark|meta|' + - 'meter|noscript|object|output|progress|q|ruby|samp|script|select|small|span|strong|sub|sup|svg|textarea|time|var|video|wbr', - C : '#|a|abbr|area|address|article|aside|audio|b|bdo|blockquote|br|button|canvas|cite|code|command|datalist|del|details|dfn|dialog|div|dl|em|embed|fieldset|' + - 'figure|footer|form|h1|h2|h3|h4|h5|h6|header|hgroup|hr|i|iframe|img|input|ins|kbd|keygen|label|link|map|mark|menu|meta|meter|nav|noscript|ol|object|output|' + - 'p|pre|progress|q|ruby|samp|script|section|select|small|span|strong|style|sub|sup|svg|table|textarea|time|ul|var|video' - }, 'html[A|manifest][body|head]' + - 'head[A][base|command|link|meta|noscript|script|style|title]' + - 'title[A][#]' + - 'base[A|href|target][]' + - 'link[A|href|rel|media|type|sizes][]' + - 'meta[A|http-equiv|name|content|charset][]' + - 'style[A|type|media|scoped][#]' + - 'script[A|charset|type|src|defer|async][#]' + - 'noscript[A][C]' + - 'body[A][C]' + - 'section[A][C]' + - 'nav[A][C]' + - 'article[A][C]' + - 'aside[A][C]' + - 'h1[A][B]' + - 'h2[A][B]' + - 'h3[A][B]' + - 'h4[A][B]' + - 'h5[A][B]' + - 'h6[A][B]' + - 'hgroup[A][h1|h2|h3|h4|h5|h6]' + - 'header[A][C]' + - 'footer[A][C]' + - 'address[A][C]' + - 'p[A][B]' + - 'br[A][]' + - 'pre[A][B]' + - 'dialog[A][dd|dt]' + - 'blockquote[A|cite][C]' + - 'ol[A|start|reversed][li]' + - 'ul[A][li]' + - 'li[A|value][C]' + - 'dl[A][dd|dt]' + - 'dt[A][B]' + - 'dd[A][C]' + - 'a[A|href|target|ping|rel|media|type][B]' + - 'em[A][B]' + - 'strong[A][B]' + - 'small[A][B]' + - 'cite[A][B]' + - 'q[A|cite][B]' + - 'dfn[A][B]' + - 'abbr[A][B]' + - 'code[A][B]' + - 'var[A][B]' + - 'samp[A][B]' + - 'kbd[A][B]' + - 'sub[A][B]' + - 'sup[A][B]' + - 'i[A][B]' + - 'b[A][B]' + - 'mark[A][B]' + - 'progress[A|value|max][B]' + - 'meter[A|value|min|max|low|high|optimum][B]' + - 'time[A|datetime][B]' + - 'ruby[A][B|rt|rp]' + - 'rt[A][B]' + - 'rp[A][B]' + - 'bdo[A][B]' + - 'span[A][B]' + - 'ins[A|cite|datetime][B]' + - 'del[A|cite|datetime][B]' + - 'figure[A][C|legend|figcaption]' + - 'figcaption[A][C]' + - 'img[A|alt|src|height|width|usemap|ismap][]' + - 'iframe[A|name|src|height|width|sandbox|seamless][]' + - 'embed[A|src|height|width|type][]' + - 'object[A|data|type|height|width|usemap|name|form|classid][param]' + - 'param[A|name|value][]' + - 'details[A|open][C|legend]' + - 'command[A|type|label|icon|disabled|checked|radiogroup][]' + - 'menu[A|type|label][C|li]' + - 'legend[A][C|B]' + - 'div[A][C]' + - 'source[A|src|type|media][]' + - 'audio[A|src|autobuffer|autoplay|loop|controls][source]' + - 'video[A|src|autobuffer|autoplay|loop|controls|width|height|poster][source]' + - 'hr[A][]' + - 'form[A|accept-charset|action|autocomplete|enctype|method|name|novalidate|target][C]' + - 'fieldset[A|disabled|form|name][C|legend]' + - 'label[A|form|for][B]' + - 'input[A|type|accept|alt|autocomplete|autofocus|checked|disabled|form|formaction|formenctype|formmethod|formnovalidate|formtarget|height|list|max|maxlength|min|' + - 'multiple|pattern|placeholder|readonly|required|size|src|step|width|files|value|name][]' + - 'button[A|autofocus|disabled|form|formaction|formenctype|formmethod|formnovalidate|formtarget|name|value|type][B]' + - 'select[A|autofocus|disabled|form|multiple|name|size][option|optgroup]' + - 'datalist[A][B|option]' + - 'optgroup[A|disabled|label][option]' + - 'option[A|disabled|selected|label|value][]' + - 'textarea[A|autofocus|disabled|form|maxlength|name|placeholder|readonly|required|rows|cols|wrap][]' + - 'keygen[A|autofocus|challenge|disabled|form|keytype|name][]' + - 'output[A|for|form|name][B]' + - 'canvas[A|width|height][]' + - 'map[A|name][B|C]' + - 'area[A|shape|coords|href|alt|target|media|rel|ping|type][]' + - 'mathml[A][]' + - 'svg[A][]' + - 'table[A|border][caption|colgroup|thead|tfoot|tbody|tr]' + - 'caption[A][C]' + - 'colgroup[A|span][col]' + - 'col[A|span][]' + - 'thead[A][tr]' + - 'tfoot[A][tr]' + - 'tbody[A][tr]' + - 'tr[A][th|td]' + - 'th[A|headers|rowspan|colspan|scope][B]' + - 'td[A|headers|rowspan|colspan][C]' + - 'wbr[A][]' - ); - } - - return html5; - }; - - function getHTML4() { - var html4 = mapCache.html4; - - if (!html4) { - // This is the XHTML 1.0 transitional elements with it's attributes and children packed to reduce it's size - html4 = mapCache.html4 = unpack({ - Z : 'H|K|N|O|P', - Y : 'X|form|R|Q', - ZG : 'E|span|width|align|char|charoff|valign', - X : 'p|T|div|U|W|isindex|fieldset|table', - ZF : 'E|align|char|charoff|valign', - W : 'pre|hr|blockquote|address|center|noframes', - ZE : 'abbr|axis|headers|scope|rowspan|colspan|align|char|charoff|valign|nowrap|bgcolor|width|height', - ZD : '[E][S]', - U : 'ul|ol|dl|menu|dir', - ZC : 'p|Y|div|U|W|table|br|span|bdo|object|applet|img|map|K|N|Q', - T : 'h1|h2|h3|h4|h5|h6', - ZB : 'X|S|Q', - S : 'R|P', - ZA : 'a|G|J|M|O|P', - R : 'a|H|K|N|O', - Q : 'noscript|P', - P : 'ins|del|script', - O : 'input|select|textarea|label|button', - N : 'M|L', - M : 'em|strong|dfn|code|q|samp|kbd|var|cite|abbr|acronym', - L : 'sub|sup', - K : 'J|I', - J : 'tt|i|b|u|s|strike', - I : 'big|small|font|basefont', - H : 'G|F', - G : 'br|span|bdo', - F : 'object|applet|img|map|iframe', - E : 'A|B|C', - D : 'accesskey|tabindex|onfocus|onblur', - C : 'onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup', - B : 'lang|xml:lang|dir', - A : 'id|class|style|title' - }, 'script[id|charset|type|language|src|defer|xml:space][]' + - 'style[B|id|type|media|title|xml:space][]' + - 'object[E|declare|classid|codebase|data|type|codetype|archive|standby|width|height|usemap|name|tabindex|align|border|hspace|vspace][#|param|Y]' + - 'param[id|name|value|valuetype|type][]' + - 'p[E|align][#|S]' + - 'a[E|D|charset|type|name|href|hreflang|rel|rev|shape|coords|target][#|Z]' + - 'br[A|clear][]' + - 'span[E][#|S]' + - 'bdo[A|C|B][#|S]' + - 'applet[A|codebase|archive|code|object|alt|name|width|height|align|hspace|vspace][#|param|Y]' + - 'h1[E|align][#|S]' + - 'img[E|src|alt|name|longdesc|width|height|usemap|ismap|align|border|hspace|vspace][]' + - 'map[B|C|A|name][X|form|Q|area]' + - 'h2[E|align][#|S]' + - 'iframe[A|longdesc|name|src|frameborder|marginwidth|marginheight|scrolling|align|width|height][#|Y]' + - 'h3[E|align][#|S]' + - 'tt[E][#|S]' + - 'i[E][#|S]' + - 'b[E][#|S]' + - 'u[E][#|S]' + - 's[E][#|S]' + - 'strike[E][#|S]' + - 'big[E][#|S]' + - 'small[E][#|S]' + - 'font[A|B|size|color|face][#|S]' + - 'basefont[id|size|color|face][]' + - 'em[E][#|S]' + - 'strong[E][#|S]' + - 'dfn[E][#|S]' + - 'code[E][#|S]' + - 'q[E|cite][#|S]' + - 'samp[E][#|S]' + - 'kbd[E][#|S]' + - 'var[E][#|S]' + - 'cite[E][#|S]' + - 'abbr[E][#|S]' + - 'acronym[E][#|S]' + - 'sub[E][#|S]' + - 'sup[E][#|S]' + - 'input[E|D|type|name|value|checked|disabled|readonly|size|maxlength|src|alt|usemap|onselect|onchange|accept|align][]' + - 'select[E|name|size|multiple|disabled|tabindex|onfocus|onblur|onchange][optgroup|option]' + - 'optgroup[E|disabled|label][option]' + - 'option[E|selected|disabled|label|value][]' + - 'textarea[E|D|name|rows|cols|disabled|readonly|onselect|onchange][]' + - 'label[E|for|accesskey|onfocus|onblur][#|S]' + - 'button[E|D|name|value|type|disabled][#|p|T|div|U|W|table|G|object|applet|img|map|K|N|Q]' + - 'h4[E|align][#|S]' + - 'ins[E|cite|datetime][#|Y]' + - 'h5[E|align][#|S]' + - 'del[E|cite|datetime][#|Y]' + - 'h6[E|align][#|S]' + - 'div[E|align][#|Y]' + - 'ul[E|type|compact][li]' + - 'li[E|type|value][#|Y]' + - 'ol[E|type|compact|start][li]' + - 'dl[E|compact][dt|dd]' + - 'dt[E][#|S]' + - 'dd[E][#|Y]' + - 'menu[E|compact][li]' + - 'dir[E|compact][li]' + - 'pre[E|width|xml:space][#|ZA]' + - 'hr[E|align|noshade|size|width][]' + - 'blockquote[E|cite][#|Y]' + - 'address[E][#|S|p]' + - 'center[E][#|Y]' + - 'noframes[E][#|Y]' + - 'isindex[A|B|prompt][]' + - 'fieldset[E][#|legend|Y]' + - 'legend[E|accesskey|align][#|S]' + - 'table[E|summary|width|border|frame|rules|cellspacing|cellpadding|align|bgcolor][caption|col|colgroup|thead|tfoot|tbody|tr]' + - 'caption[E|align][#|S]' + - 'col[ZG][]' + - 'colgroup[ZG][col]' + - 'thead[ZF][tr]' + - 'tr[ZF|bgcolor][th|td]' + - 'th[E|ZE][#|Y]' + - 'form[E|action|method|name|enctype|onsubmit|onreset|accept|accept-charset|target][#|X|R|Q]' + - 'noscript[E][#|Y]' + - 'td[E|ZE][#|Y]' + - 'tfoot[ZF][tr]' + - 'tbody[ZF][tr]' + - 'area[E|D|shape|coords|href|nohref|alt|target][]' + - 'base[id|href|target][]' + - 'body[E|onload|onunload|background|bgcolor|text|link|vlink|alink][#|Y]' - ); - } - - return html4; - }; - - tinymce.html.Schema = function(settings) { - var self = this, elements = {}, children = {}, patternElements = [], validStyles, schemaItems; - var whiteSpaceElementsMap, selfClosingElementsMap, shortEndedElementsMap, boolAttrMap, blockElementsMap, nonEmptyElementsMap, customElementsMap = {}; - - // Creates an lookup table map object for the specified option or the default value - function createLookupTable(option, default_value, extend) { - var value = settings[option]; - - if (!value) { - // Get cached default map or make it if needed - value = mapCache[option]; - - if (!value) { - value = makeMap(default_value, ' ', makeMap(default_value.toUpperCase(), ' ')); - value = tinymce.extend(value, extend); - - mapCache[option] = value; - } - } else { - // Create custom map - value = makeMap(value, ',', makeMap(value.toUpperCase(), ' ')); - } - - return value; - }; - - settings = settings || {}; - schemaItems = settings.schema == "html5" ? getHTML5() : getHTML4(); - - // Allow all elements and attributes if verify_html is set to false - if (settings.verify_html === false) - settings.valid_elements = '*[*]'; - - // Build styles list - if (settings.valid_styles) { - validStyles = {}; - - // Convert styles into a rule list - each(settings.valid_styles, function(value, key) { - validStyles[key] = tinymce.explode(value); - }); - } - - // Setup map objects - whiteSpaceElementsMap = createLookupTable('whitespace_elements', 'pre script noscript style textarea'); - selfClosingElementsMap = createLookupTable('self_closing_elements', 'colgroup dd dt li option p td tfoot th thead tr'); - shortEndedElementsMap = createLookupTable('short_ended_elements', 'area base basefont br col frame hr img input isindex link meta param embed source wbr'); - boolAttrMap = createLookupTable('boolean_attributes', 'checked compact declare defer disabled ismap multiple nohref noresize noshade nowrap readonly selected autoplay loop controls'); - nonEmptyElementsMap = createLookupTable('non_empty_elements', 'td th iframe video audio object script', shortEndedElementsMap); - textBlockElementsMap = createLookupTable('text_block_elements', 'h1 h2 h3 h4 h5 h6 p div address pre form ' + - 'blockquote center dir fieldset header footer article section hgroup aside nav figure'); - blockElementsMap = createLookupTable('block_elements', 'hr table tbody thead tfoot ' + - 'th tr td li ol ul caption dl dt dd noscript menu isindex samp option datalist select optgroup', textBlockElementsMap); - - // Converts a wildcard expression string to a regexp for example *a will become /.*a/. - function patternToRegExp(str) { - return new RegExp('^' + str.replace(/([?+*])/g, '.$1') + '$'); - }; - - // Parses the specified valid_elements string and adds to the current rules - // This function is a bit hard to read since it's heavily optimized for speed - function addValidElements(valid_elements) { - var ei, el, ai, al, yl, matches, element, attr, attrData, elementName, attrName, attrType, attributes, attributesOrder, - prefix, outputName, globalAttributes, globalAttributesOrder, transElement, key, childKey, value, - elementRuleRegExp = /^([#+\-])?([^\[\/]+)(?:\/([^\[]+))?(?:\[([^\]]+)\])?$/, - attrRuleRegExp = /^([!\-])?(\w+::\w+|[^=:<]+)?(?:([=:<])(.*))?$/, - hasPatternsRegExp = /[*?+]/; - - if (valid_elements) { - // Split valid elements into an array with rules - valid_elements = split(valid_elements); - - if (elements['@']) { - globalAttributes = elements['@'].attributes; - globalAttributesOrder = elements['@'].attributesOrder; - } - - // Loop all rules - for (ei = 0, el = valid_elements.length; ei < el; ei++) { - // Parse element rule - matches = elementRuleRegExp.exec(valid_elements[ei]); - if (matches) { - // Setup local names for matches - prefix = matches[1]; - elementName = matches[2]; - outputName = matches[3]; - attrData = matches[4]; - - // Create new attributes and attributesOrder - attributes = {}; - attributesOrder = []; - - // Create the new element - element = { - attributes : attributes, - attributesOrder : attributesOrder - }; - - // Padd empty elements prefix - if (prefix === '#') - element.paddEmpty = true; - - // Remove empty elements prefix - if (prefix === '-') - element.removeEmpty = true; - - // Copy attributes from global rule into current rule - if (globalAttributes) { - for (key in globalAttributes) - attributes[key] = globalAttributes[key]; - - attributesOrder.push.apply(attributesOrder, globalAttributesOrder); - } - - // Attributes defined - if (attrData) { - attrData = split(attrData, '|'); - for (ai = 0, al = attrData.length; ai < al; ai++) { - matches = attrRuleRegExp.exec(attrData[ai]); - if (matches) { - attr = {}; - attrType = matches[1]; - attrName = matches[2].replace(/::/g, ':'); - prefix = matches[3]; - value = matches[4]; - - // Required - if (attrType === '!') { - element.attributesRequired = element.attributesRequired || []; - element.attributesRequired.push(attrName); - attr.required = true; - } - - // Denied from global - if (attrType === '-') { - delete attributes[attrName]; - attributesOrder.splice(tinymce.inArray(attributesOrder, attrName), 1); - continue; - } - - // Default value - if (prefix) { - // Default value - if (prefix === '=') { - element.attributesDefault = element.attributesDefault || []; - element.attributesDefault.push({name: attrName, value: value}); - attr.defaultValue = value; - } - - // Forced value - if (prefix === ':') { - element.attributesForced = element.attributesForced || []; - element.attributesForced.push({name: attrName, value: value}); - attr.forcedValue = value; - } - - // Required values - if (prefix === '<') - attr.validValues = makeMap(value, '?'); - } - - // Check for attribute patterns - if (hasPatternsRegExp.test(attrName)) { - element.attributePatterns = element.attributePatterns || []; - attr.pattern = patternToRegExp(attrName); - element.attributePatterns.push(attr); - } else { - // Add attribute to order list if it doesn't already exist - if (!attributes[attrName]) - attributesOrder.push(attrName); - - attributes[attrName] = attr; - } - } - } - } - - // Global rule, store away these for later usage - if (!globalAttributes && elementName == '@') { - globalAttributes = attributes; - globalAttributesOrder = attributesOrder; - } - - // Handle substitute elements such as b/strong - if (outputName) { - element.outputName = elementName; - elements[outputName] = element; - } - - // Add pattern or exact element - if (hasPatternsRegExp.test(elementName)) { - element.pattern = patternToRegExp(elementName); - patternElements.push(element); - } else - elements[elementName] = element; - } - } - } - }; - - function setValidElements(valid_elements) { - elements = {}; - patternElements = []; - - addValidElements(valid_elements); - - each(schemaItems, function(element, name) { - children[name] = element.children; - }); - }; - - // Adds custom non HTML elements to the schema - function addCustomElements(custom_elements) { - var customElementRegExp = /^(~)?(.+)$/; - - if (custom_elements) { - each(split(custom_elements), function(rule) { - var matches = customElementRegExp.exec(rule), - inline = matches[1] === '~', - cloneName = inline ? 'span' : 'div', - name = matches[2]; - - children[name] = children[cloneName]; - customElementsMap[name] = cloneName; - - // If it's not marked as inline then add it to valid block elements - if (!inline) { - blockElementsMap[name.toUpperCase()] = {}; - blockElementsMap[name] = {}; - } - - // Add elements clone if needed - if (!elements[name]) { - elements[name] = elements[cloneName]; - } - - // Add custom elements at span/div positions - each(children, function(element, child) { - if (element[cloneName]) - element[name] = element[cloneName]; - }); - }); - } - }; - - // Adds valid children to the schema object - function addValidChildren(valid_children) { - var childRuleRegExp = /^([+\-]?)(\w+)\[([^\]]+)\]$/; - - if (valid_children) { - each(split(valid_children), function(rule) { - var matches = childRuleRegExp.exec(rule), parent, prefix; - - if (matches) { - prefix = matches[1]; - - // Add/remove items from default - if (prefix) - parent = children[matches[2]]; - else - parent = children[matches[2]] = {'#comment' : {}}; - - parent = children[matches[2]]; - - each(split(matches[3], '|'), function(child) { - if (prefix === '-') - delete parent[child]; - else - parent[child] = {}; - }); - } - }); - } - }; - - function getElementRule(name) { - var element = elements[name], i; - - // Exact match found - if (element) - return element; - - // No exact match then try the patterns - i = patternElements.length; - while (i--) { - element = patternElements[i]; - - if (element.pattern.test(name)) - return element; - } - }; - - if (!settings.valid_elements) { - // No valid elements defined then clone the elements from the schema spec - each(schemaItems, function(element, name) { - elements[name] = { - attributes : element.attributes, - attributesOrder : element.attributesOrder - }; - - children[name] = element.children; - }); - - // Switch these on HTML4 - if (settings.schema != "html5") { - each(split('strong/b,em/i'), function(item) { - item = split(item, '/'); - elements[item[1]].outputName = item[0]; - }); - } - - // Add default alt attribute for images - elements.img.attributesDefault = [{name: 'alt', value: ''}]; - - // Remove these if they are empty by default - each(split('ol,ul,sub,sup,blockquote,span,font,a,table,tbody,tr,strong,em,b,i'), function(name) { - if (elements[name]) { - elements[name].removeEmpty = true; - } - }); - - // Padd these by default - each(split('p,h1,h2,h3,h4,h5,h6,th,td,pre,div,address,caption'), function(name) { - elements[name].paddEmpty = true; - }); - } else - setValidElements(settings.valid_elements); - - addCustomElements(settings.custom_elements); - addValidChildren(settings.valid_children); - addValidElements(settings.extended_valid_elements); - - // Todo: Remove this when we fix list handling to be valid - addValidChildren('+ol[ul|ol],+ul[ul|ol]'); - - // Delete invalid elements - if (settings.invalid_elements) { - tinymce.each(tinymce.explode(settings.invalid_elements), function(item) { - if (elements[item]) - delete elements[item]; - }); - } - - // If the user didn't allow span only allow internal spans - if (!getElementRule('span')) - addValidElements('span[!data-mce-type|*]'); - - self.children = children; - - self.styles = validStyles; - - self.getBoolAttrs = function() { - return boolAttrMap; - }; - - self.getBlockElements = function() { - return blockElementsMap; - }; - - self.getTextBlockElements = function() { - return textBlockElementsMap; - }; - - self.getShortEndedElements = function() { - return shortEndedElementsMap; - }; - - self.getSelfClosingElements = function() { - return selfClosingElementsMap; - }; - - self.getNonEmptyElements = function() { - return nonEmptyElementsMap; - }; - - self.getWhiteSpaceElements = function() { - return whiteSpaceElementsMap; - }; - - self.isValidChild = function(name, child) { - var parent = children[name]; - - return !!(parent && parent[child]); - }; - - self.isValid = function(name, attr) { - var attrPatterns, i, rule = getElementRule(name); - - // Check if it's a valid element - if (rule) { - if (attr) { - // Check if attribute name exists - if (rule.attributes[attr]) { - return true; - } - - // Check if attribute matches a regexp pattern - attrPatterns = rule.attributePatterns; - if (attrPatterns) { - i = attrPatterns.length; - while (i--) { - if (attrPatterns[i].pattern.test(name)) { - return true; - } - } - } - } else { - return true; - } - } - - // No match - return false; - }; - - self.getElementRule = getElementRule; - - self.getCustomElements = function() { - return customElementsMap; - }; - - self.addValidElements = addValidElements; - - self.setValidElements = setValidElements; - - self.addCustomElements = addCustomElements; - - self.addValidChildren = addValidChildren; - - self.elements = elements; - }; -})(tinymce); -(function(tinymce) { - tinymce.html.SaxParser = function(settings, schema) { - var self = this, noop = function() {}; - - settings = settings || {}; - self.schema = schema = schema || new tinymce.html.Schema(); - - if (settings.fix_self_closing !== false) - settings.fix_self_closing = true; - - // Add handler functions from settings and setup default handlers - tinymce.each('comment cdata text start end pi doctype'.split(' '), function(name) { - if (name) - self[name] = settings[name] || noop; - }); - - self.parse = function(html) { - var self = this, matches, index = 0, value, endRegExp, stack = [], attrList, i, text, name, isInternalElement, removeInternalElements, - shortEndedElements, fillAttrsMap, isShortEnded, validate, elementRule, isValidElement, attr, attribsValue, invalidPrefixRegExp, - validAttributesMap, validAttributePatterns, attributesRequired, attributesDefault, attributesForced, selfClosing, - tokenRegExp, attrRegExp, specialElements, attrValue, idCount = 0, decode = tinymce.html.Entities.decode, fixSelfClosing, isIE; - - function processEndTag(name) { - var pos, i; - - // Find position of parent of the same type - pos = stack.length; - while (pos--) { - if (stack[pos].name === name) - break; - } - - // Found parent - if (pos >= 0) { - // Close all the open elements - for (i = stack.length - 1; i >= pos; i--) { - name = stack[i]; - - if (name.valid) - self.end(name.name); - } - - // Remove the open elements from the stack - stack.length = pos; - } - }; - - function parseAttribute(match, name, value, val2, val3) { - var attrRule, i; - - name = name.toLowerCase(); - value = name in fillAttrsMap ? name : decode(value || val2 || val3 || ''); // Handle boolean attribute than value attribute - - // Validate name and value - if (validate && !isInternalElement && name.indexOf('data-') !== 0) { - attrRule = validAttributesMap[name]; - - // Find rule by pattern matching - if (!attrRule && validAttributePatterns) { - i = validAttributePatterns.length; - while (i--) { - attrRule = validAttributePatterns[i]; - if (attrRule.pattern.test(name)) - break; - } - - // No rule matched - if (i === -1) - attrRule = null; - } - - // No attribute rule found - if (!attrRule) - return; - - // Validate value - if (attrRule.validValues && !(value in attrRule.validValues)) - return; - } - - // Add attribute to list and map - attrList.map[name] = value; - attrList.push({ - name: name, - value: value - }); - }; - - // Precompile RegExps and map objects - tokenRegExp = new RegExp('<(?:' + - '(?:!--([\\w\\W]*?)-->)|' + // Comment - '(?:!\\[CDATA\\[([\\w\\W]*?)\\]\\]>)|' + // CDATA - '(?:!DOCTYPE([\\w\\W]*?)>)|' + // DOCTYPE - '(?:\\?([^\\s\\/<>]+) ?([\\w\\W]*?)[?/]>)|' + // PI - '(?:\\/([^>]+)>)|' + // End element - '(?:([A-Za-z0-9\\-\\:\\.]+)((?:\\s+[^"\'>]+(?:(?:"[^"]*")|(?:\'[^\']*\')|[^>]*))*|\\/|\\s+)>)' + // Start element - ')', 'g'); - - attrRegExp = /([\w:\-]+)(?:\s*=\s*(?:(?:\"((?:[^\"])*)\")|(?:\'((?:[^\'])*)\')|([^>\s]+)))?/g; - specialElements = { - 'script' : /<\/script[^>]*>/gi, - 'style' : /<\/style[^>]*>/gi, - 'noscript' : /<\/noscript[^>]*>/gi - }; - - // Setup lookup tables for empty elements and boolean attributes - shortEndedElements = schema.getShortEndedElements(); - selfClosing = settings.self_closing_elements || schema.getSelfClosingElements(); - fillAttrsMap = schema.getBoolAttrs(); - validate = settings.validate; - removeInternalElements = settings.remove_internals; - fixSelfClosing = settings.fix_self_closing; - isIE = tinymce.isIE; - invalidPrefixRegExp = /^:/; - - while (matches = tokenRegExp.exec(html)) { - // Text - if (index < matches.index) - self.text(decode(html.substr(index, matches.index - index))); - - if (value = matches[6]) { // End element - value = value.toLowerCase(); - - // IE will add a ":" in front of elements it doesn't understand like custom elements or HTML5 elements - if (isIE && invalidPrefixRegExp.test(value)) - value = value.substr(1); - - processEndTag(value); - } else if (value = matches[7]) { // Start element - value = value.toLowerCase(); - - // IE will add a ":" in front of elements it doesn't understand like custom elements or HTML5 elements - if (isIE && invalidPrefixRegExp.test(value)) - value = value.substr(1); - - isShortEnded = value in shortEndedElements; - - // Is self closing tag for example an
  • after an open
  • - if (fixSelfClosing && selfClosing[value] && stack.length > 0 && stack[stack.length - 1].name === value) - processEndTag(value); - - // Validate element - if (!validate || (elementRule = schema.getElementRule(value))) { - isValidElement = true; - - // Grab attributes map and patters when validation is enabled - if (validate) { - validAttributesMap = elementRule.attributes; - validAttributePatterns = elementRule.attributePatterns; - } - - // Parse attributes - if (attribsValue = matches[8]) { - isInternalElement = attribsValue.indexOf('data-mce-type') !== -1; // Check if the element is an internal element - - // If the element has internal attributes then remove it if we are told to do so - if (isInternalElement && removeInternalElements) - isValidElement = false; - - attrList = []; - attrList.map = {}; - - attribsValue.replace(attrRegExp, parseAttribute); - } else { - attrList = []; - attrList.map = {}; - } - - // Process attributes if validation is enabled - if (validate && !isInternalElement) { - attributesRequired = elementRule.attributesRequired; - attributesDefault = elementRule.attributesDefault; - attributesForced = elementRule.attributesForced; - - // Handle forced attributes - if (attributesForced) { - i = attributesForced.length; - while (i--) { - attr = attributesForced[i]; - name = attr.name; - attrValue = attr.value; - - if (attrValue === '{$uid}') - attrValue = 'mce_' + idCount++; - - attrList.map[name] = attrValue; - attrList.push({name: name, value: attrValue}); - } - } - - // Handle default attributes - if (attributesDefault) { - i = attributesDefault.length; - while (i--) { - attr = attributesDefault[i]; - name = attr.name; - - if (!(name in attrList.map)) { - attrValue = attr.value; - - if (attrValue === '{$uid}') - attrValue = 'mce_' + idCount++; - - attrList.map[name] = attrValue; - attrList.push({name: name, value: attrValue}); - } - } - } - - // Handle required attributes - if (attributesRequired) { - i = attributesRequired.length; - while (i--) { - if (attributesRequired[i] in attrList.map) - break; - } - - // None of the required attributes where found - if (i === -1) - isValidElement = false; - } - - // Invalidate element if it's marked as bogus - if (attrList.map['data-mce-bogus']) - isValidElement = false; - } - - if (isValidElement) - self.start(value, attrList, isShortEnded); - } else - isValidElement = false; - - // Treat script, noscript and style a bit different since they may include code that looks like elements - if (endRegExp = specialElements[value]) { - endRegExp.lastIndex = index = matches.index + matches[0].length; - - if (matches = endRegExp.exec(html)) { - if (isValidElement) - text = html.substr(index, matches.index - index); - - index = matches.index + matches[0].length; - } else { - text = html.substr(index); - index = html.length; - } - - if (isValidElement && text.length > 0) - self.text(text, true); - - if (isValidElement) - self.end(value); - - tokenRegExp.lastIndex = index; - continue; - } - - // Push value on to stack - if (!isShortEnded) { - if (!attribsValue || attribsValue.indexOf('/') != attribsValue.length - 1) - stack.push({name: value, valid: isValidElement}); - else if (isValidElement) - self.end(value); - } - } else if (value = matches[1]) { // Comment - self.comment(value); - } else if (value = matches[2]) { // CDATA - self.cdata(value); - } else if (value = matches[3]) { // DOCTYPE - self.doctype(value); - } else if (value = matches[4]) { // PI - self.pi(value, matches[5]); - } - - index = matches.index + matches[0].length; - } - - // Text - if (index < html.length) - self.text(decode(html.substr(index))); - - // Close any open elements - for (i = stack.length - 1; i >= 0; i--) { - value = stack[i]; - - if (value.valid) - self.end(value.name); - } - }; - } -})(tinymce); -(function(tinymce) { - var whiteSpaceRegExp = /^[ \t\r\n]*$/, typeLookup = { - '#text' : 3, - '#comment' : 8, - '#cdata' : 4, - '#pi' : 7, - '#doctype' : 10, - '#document-fragment' : 11 - }; - - // Walks the tree left/right - function walk(node, root_node, prev) { - var sibling, parent, startName = prev ? 'lastChild' : 'firstChild', siblingName = prev ? 'prev' : 'next'; - - // Walk into nodes if it has a start - if (node[startName]) - return node[startName]; - - // Return the sibling if it has one - if (node !== root_node) { - sibling = node[siblingName]; - - if (sibling) - return sibling; - - // Walk up the parents to look for siblings - for (parent = node.parent; parent && parent !== root_node; parent = parent.parent) { - sibling = parent[siblingName]; - - if (sibling) - return sibling; - } - } - }; - - function Node(name, type) { - this.name = name; - this.type = type; - - if (type === 1) { - this.attributes = []; - this.attributes.map = {}; - } - } - - tinymce.extend(Node.prototype, { - replace : function(node) { - var self = this; - - if (node.parent) - node.remove(); - - self.insert(node, self); - self.remove(); - - return self; - }, - - attr : function(name, value) { - var self = this, attrs, i, undef; - - if (typeof name !== "string") { - for (i in name) - self.attr(i, name[i]); - - return self; - } - - if (attrs = self.attributes) { - if (value !== undef) { - // Remove attribute - if (value === null) { - if (name in attrs.map) { - delete attrs.map[name]; - - i = attrs.length; - while (i--) { - if (attrs[i].name === name) { - attrs = attrs.splice(i, 1); - return self; - } - } - } - - return self; - } - - // Set attribute - if (name in attrs.map) { - // Set attribute - i = attrs.length; - while (i--) { - if (attrs[i].name === name) { - attrs[i].value = value; - break; - } - } - } else - attrs.push({name: name, value: value}); - - attrs.map[name] = value; - - return self; - } else { - return attrs.map[name]; - } - } - }, - - clone : function() { - var self = this, clone = new Node(self.name, self.type), i, l, selfAttrs, selfAttr, cloneAttrs; - - // Clone element attributes - if (selfAttrs = self.attributes) { - cloneAttrs = []; - cloneAttrs.map = {}; - - for (i = 0, l = selfAttrs.length; i < l; i++) { - selfAttr = selfAttrs[i]; - - // Clone everything except id - if (selfAttr.name !== 'id') { - cloneAttrs[cloneAttrs.length] = {name: selfAttr.name, value: selfAttr.value}; - cloneAttrs.map[selfAttr.name] = selfAttr.value; - } - } - - clone.attributes = cloneAttrs; - } - - clone.value = self.value; - clone.shortEnded = self.shortEnded; - - return clone; - }, - - wrap : function(wrapper) { - var self = this; - - self.parent.insert(wrapper, self); - wrapper.append(self); - - return self; - }, - - unwrap : function() { - var self = this, node, next; - - for (node = self.firstChild; node; ) { - next = node.next; - self.insert(node, self, true); - node = next; - } - - self.remove(); - }, - - remove : function() { - var self = this, parent = self.parent, next = self.next, prev = self.prev; - - if (parent) { - if (parent.firstChild === self) { - parent.firstChild = next; - - if (next) - next.prev = null; - } else { - prev.next = next; - } - - if (parent.lastChild === self) { - parent.lastChild = prev; - - if (prev) - prev.next = null; - } else { - next.prev = prev; - } - - self.parent = self.next = self.prev = null; - } - - return self; - }, - - append : function(node) { - var self = this, last; - - if (node.parent) - node.remove(); - - last = self.lastChild; - if (last) { - last.next = node; - node.prev = last; - self.lastChild = node; - } else - self.lastChild = self.firstChild = node; - - node.parent = self; - - return node; - }, - - insert : function(node, ref_node, before) { - var parent; - - if (node.parent) - node.remove(); - - parent = ref_node.parent || this; - - if (before) { - if (ref_node === parent.firstChild) - parent.firstChild = node; - else - ref_node.prev.next = node; - - node.prev = ref_node.prev; - node.next = ref_node; - ref_node.prev = node; - } else { - if (ref_node === parent.lastChild) - parent.lastChild = node; - else - ref_node.next.prev = node; - - node.next = ref_node.next; - node.prev = ref_node; - ref_node.next = node; - } - - node.parent = parent; - - return node; - }, - - getAll : function(name) { - var self = this, node, collection = []; - - for (node = self.firstChild; node; node = walk(node, self)) { - if (node.name === name) - collection.push(node); - } - - return collection; - }, - - empty : function() { - var self = this, nodes, i, node; - - // Remove all children - if (self.firstChild) { - nodes = []; - - // Collect the children - for (node = self.firstChild; node; node = walk(node, self)) - nodes.push(node); - - // Remove the children - i = nodes.length; - while (i--) { - node = nodes[i]; - node.parent = node.firstChild = node.lastChild = node.next = node.prev = null; - } - } - - self.firstChild = self.lastChild = null; - - return self; - }, - - isEmpty : function(elements) { - var self = this, node = self.firstChild, i, name; - - if (node) { - do { - if (node.type === 1) { - // Ignore bogus elements - if (node.attributes.map['data-mce-bogus']) - continue; - - // Keep empty elements like - if (elements[node.name]) - return false; - - // Keep elements with data attributes or name attribute like - i = node.attributes.length; - while (i--) { - name = node.attributes[i].name; - if (name === "name" || name.indexOf('data-mce-') === 0) - return false; - } - } - - // Keep comments - if (node.type === 8) - return false; - - // Keep non whitespace text nodes - if ((node.type === 3 && !whiteSpaceRegExp.test(node.value))) - return false; - } while (node = walk(node, self)); - } - - return true; - }, - - walk : function(prev) { - return walk(this, null, prev); - } - }); - - tinymce.extend(Node, { - create : function(name, attrs) { - var node, attrName; - - // Create node - node = new Node(name, typeLookup[name] || 1); - - // Add attributes if needed - if (attrs) { - for (attrName in attrs) - node.attr(attrName, attrs[attrName]); - } - - return node; - } - }); - - tinymce.html.Node = Node; -})(tinymce); -(function(tinymce) { - var Node = tinymce.html.Node; - - tinymce.html.DomParser = function(settings, schema) { - var self = this, nodeFilters = {}, attributeFilters = [], matchedNodes = {}, matchedAttributes = {}; - - settings = settings || {}; - settings.validate = "validate" in settings ? settings.validate : true; - settings.root_name = settings.root_name || 'body'; - self.schema = schema = schema || new tinymce.html.Schema(); - - function fixInvalidChildren(nodes) { - var ni, node, parent, parents, newParent, currentNode, tempNode, childNode, i, - childClone, nonEmptyElements, nonSplitableElements, textBlockElements, sibling, nextNode; - - nonSplitableElements = tinymce.makeMap('tr,td,th,tbody,thead,tfoot,table'); - nonEmptyElements = schema.getNonEmptyElements(); - textBlockElements = schema.getTextBlockElements(); - - for (ni = 0; ni < nodes.length; ni++) { - node = nodes[ni]; - - // Already removed or fixed - if (!node.parent || node.fixed) - continue; - - // If the invalid element is a text block and the text block is within a parent LI element - // Then unwrap the first text block and convert other sibling text blocks to LI elements similar to Word/Open Office - if (textBlockElements[node.name] && node.parent.name == 'li') { - // Move sibling text blocks after LI element - sibling = node.next; - while (sibling) { - if (textBlockElements[sibling.name]) { - sibling.name = 'li'; - sibling.fixed = true; - node.parent.insert(sibling, node.parent); - } else { - break; - } - - sibling = sibling.next; - } - - // Unwrap current text block - node.unwrap(node); - continue; - } - - // Get list of all parent nodes until we find a valid parent to stick the child into - parents = [node]; - for (parent = node.parent; parent && !schema.isValidChild(parent.name, node.name) && !nonSplitableElements[parent.name]; parent = parent.parent) - parents.push(parent); - - // Found a suitable parent - if (parent && parents.length > 1) { - // Reverse the array since it makes looping easier - parents.reverse(); - - // Clone the related parent and insert that after the moved node - newParent = currentNode = self.filterNode(parents[0].clone()); - - // Start cloning and moving children on the left side of the target node - for (i = 0; i < parents.length - 1; i++) { - if (schema.isValidChild(currentNode.name, parents[i].name)) { - tempNode = self.filterNode(parents[i].clone()); - currentNode.append(tempNode); - } else - tempNode = currentNode; - - for (childNode = parents[i].firstChild; childNode && childNode != parents[i + 1]; ) { - nextNode = childNode.next; - tempNode.append(childNode); - childNode = nextNode; - } - - currentNode = tempNode; - } - - if (!newParent.isEmpty(nonEmptyElements)) { - parent.insert(newParent, parents[0], true); - parent.insert(node, newParent); - } else { - parent.insert(node, parents[0], true); - } - - // Check if the element is empty by looking through it's contents and special treatment for


    - parent = parents[0]; - if (parent.isEmpty(nonEmptyElements) || parent.firstChild === parent.lastChild && parent.firstChild.name === 'br') { - parent.empty().remove(); - } - } else if (node.parent) { - // If it's an LI try to find a UL/OL for it or wrap it - if (node.name === 'li') { - sibling = node.prev; - if (sibling && (sibling.name === 'ul' || sibling.name === 'ul')) { - sibling.append(node); - continue; - } - - sibling = node.next; - if (sibling && (sibling.name === 'ul' || sibling.name === 'ul')) { - sibling.insert(node, sibling.firstChild, true); - continue; - } - - node.wrap(self.filterNode(new Node('ul', 1))); - continue; - } - - // Try wrapping the element in a DIV - if (schema.isValidChild(node.parent.name, 'div') && schema.isValidChild('div', node.name)) { - node.wrap(self.filterNode(new Node('div', 1))); - } else { - // We failed wrapping it, then remove or unwrap it - if (node.name === 'style' || node.name === 'script') - node.empty().remove(); - else - node.unwrap(); - } - } - } - }; - - self.filterNode = function(node) { - var i, name, list; - - // Run element filters - if (name in nodeFilters) { - list = matchedNodes[name]; - - if (list) - list.push(node); - else - matchedNodes[name] = [node]; - } - - // Run attribute filters - i = attributeFilters.length; - while (i--) { - name = attributeFilters[i].name; - - if (name in node.attributes.map) { - list = matchedAttributes[name]; - - if (list) - list.push(node); - else - matchedAttributes[name] = [node]; - } - } - - return node; - }; - - self.addNodeFilter = function(name, callback) { - tinymce.each(tinymce.explode(name), function(name) { - var list = nodeFilters[name]; - - if (!list) - nodeFilters[name] = list = []; - - list.push(callback); - }); - }; - - self.addAttributeFilter = function(name, callback) { - tinymce.each(tinymce.explode(name), function(name) { - var i; - - for (i = 0; i < attributeFilters.length; i++) { - if (attributeFilters[i].name === name) { - attributeFilters[i].callbacks.push(callback); - return; - } - } - - attributeFilters.push({name: name, callbacks: [callback]}); - }); - }; - - self.parse = function(html, args) { - var parser, rootNode, node, nodes, i, l, fi, fl, list, name, validate, - blockElements, startWhiteSpaceRegExp, invalidChildren = [], isInWhiteSpacePreservedElement, - endWhiteSpaceRegExp, allWhiteSpaceRegExp, isAllWhiteSpaceRegExp, whiteSpaceElements, children, nonEmptyElements, rootBlockName; - - args = args || {}; - matchedNodes = {}; - matchedAttributes = {}; - blockElements = tinymce.extend(tinymce.makeMap('script,style,head,html,body,title,meta,param'), schema.getBlockElements()); - nonEmptyElements = schema.getNonEmptyElements(); - children = schema.children; - validate = settings.validate; - rootBlockName = "forced_root_block" in args ? args.forced_root_block : settings.forced_root_block; - - whiteSpaceElements = schema.getWhiteSpaceElements(); - startWhiteSpaceRegExp = /^[ \t\r\n]+/; - endWhiteSpaceRegExp = /[ \t\r\n]+$/; - allWhiteSpaceRegExp = /[ \t\r\n]+/g; - isAllWhiteSpaceRegExp = /^[ \t\r\n]+$/; - - function addRootBlocks() { - var node = rootNode.firstChild, next, rootBlockNode; - - while (node) { - next = node.next; - - if (node.type == 3 || (node.type == 1 && node.name !== 'p' && !blockElements[node.name] && !node.attr('data-mce-type'))) { - if (!rootBlockNode) { - // Create a new root block element - rootBlockNode = createNode(rootBlockName, 1); - rootNode.insert(rootBlockNode, node); - rootBlockNode.append(node); - } else - rootBlockNode.append(node); - } else { - rootBlockNode = null; - } - - node = next; - }; - }; - - function createNode(name, type) { - var node = new Node(name, type), list; - - if (name in nodeFilters) { - list = matchedNodes[name]; - - if (list) - list.push(node); - else - matchedNodes[name] = [node]; - } - - return node; - }; - - function removeWhitespaceBefore(node) { - var textNode, textVal, sibling; - - for (textNode = node.prev; textNode && textNode.type === 3; ) { - textVal = textNode.value.replace(endWhiteSpaceRegExp, ''); - - if (textVal.length > 0) { - textNode.value = textVal; - textNode = textNode.prev; - } else { - sibling = textNode.prev; - textNode.remove(); - textNode = sibling; - } - } - }; - - function cloneAndExcludeBlocks(input) { - var name, output = {}; - - for (name in input) { - if (name !== 'li' && name != 'p') { - output[name] = input[name]; - } - } - - return output; - }; - - parser = new tinymce.html.SaxParser({ - validate : validate, - - // Exclude P and LI from DOM parsing since it's treated better by the DOM parser - self_closing_elements: cloneAndExcludeBlocks(schema.getSelfClosingElements()), - - cdata: function(text) { - node.append(createNode('#cdata', 4)).value = text; - }, - - text: function(text, raw) { - var textNode; - - // Trim all redundant whitespace on non white space elements - if (!isInWhiteSpacePreservedElement) { - text = text.replace(allWhiteSpaceRegExp, ' '); - - if (node.lastChild && blockElements[node.lastChild.name]) - text = text.replace(startWhiteSpaceRegExp, ''); - } - - // Do we need to create the node - if (text.length !== 0) { - textNode = createNode('#text', 3); - textNode.raw = !!raw; - node.append(textNode).value = text; - } - }, - - comment: function(text) { - node.append(createNode('#comment', 8)).value = text; - }, - - pi: function(name, text) { - node.append(createNode(name, 7)).value = text; - removeWhitespaceBefore(node); - }, - - doctype: function(text) { - var newNode; - - newNode = node.append(createNode('#doctype', 10)); - newNode.value = text; - removeWhitespaceBefore(node); - }, - - start: function(name, attrs, empty) { - var newNode, attrFiltersLen, elementRule, textNode, attrName, text, sibling, parent; - - elementRule = validate ? schema.getElementRule(name) : {}; - if (elementRule) { - newNode = createNode(elementRule.outputName || name, 1); - newNode.attributes = attrs; - newNode.shortEnded = empty; - - node.append(newNode); - - // Check if node is valid child of the parent node is the child is - // unknown we don't collect it since it's probably a custom element - parent = children[node.name]; - if (parent && children[newNode.name] && !parent[newNode.name]) - invalidChildren.push(newNode); - - attrFiltersLen = attributeFilters.length; - while (attrFiltersLen--) { - attrName = attributeFilters[attrFiltersLen].name; - - if (attrName in attrs.map) { - list = matchedAttributes[attrName]; - - if (list) - list.push(newNode); - else - matchedAttributes[attrName] = [newNode]; - } - } - - // Trim whitespace before block - if (blockElements[name]) - removeWhitespaceBefore(newNode); - - // Change current node if the element wasn't empty i.e not
    or - if (!empty) - node = newNode; - - // Check if we are inside a whitespace preserved element - if (!isInWhiteSpacePreservedElement && whiteSpaceElements[name]) { - isInWhiteSpacePreservedElement = true; - } - } - }, - - end: function(name) { - var textNode, elementRule, text, sibling, tempNode; - - elementRule = validate ? schema.getElementRule(name) : {}; - if (elementRule) { - if (blockElements[name]) { - if (!isInWhiteSpacePreservedElement) { - // Trim whitespace of the first node in a block - textNode = node.firstChild; - if (textNode && textNode.type === 3) { - text = textNode.value.replace(startWhiteSpaceRegExp, ''); - - // Any characters left after trim or should we remove it - if (text.length > 0) { - textNode.value = text; - textNode = textNode.next; - } else { - sibling = textNode.next; - textNode.remove(); - textNode = sibling; - - - // Remove any pure whitespace siblings - while (textNode && textNode.type === 3) { - text = textNode.value; - sibling = textNode.next; - - if (text.length === 0 || isAllWhiteSpaceRegExp.test(text)) { - textNode.remove(); - textNode = sibling; - } - - textNode = sibling; - } - } - } - - // Trim whitespace of the last node in a block - textNode = node.lastChild; - if (textNode && textNode.type === 3) { - text = textNode.value.replace(endWhiteSpaceRegExp, ''); - - // Any characters left after trim or should we remove it - if (text.length > 0) { - textNode.value = text; - textNode = textNode.prev; - } else { - sibling = textNode.prev; - textNode.remove(); - textNode = sibling; - - - // Remove any pure whitespace siblings - while (textNode && textNode.type === 3) { - text = textNode.value; - sibling = textNode.prev; - - if (text.length === 0 || isAllWhiteSpaceRegExp.test(text)) { - textNode.remove(); - textNode = sibling; - } - - textNode = sibling; - } - } - } - } - } - - // Check if we exited a whitespace preserved element - if (isInWhiteSpacePreservedElement && whiteSpaceElements[name]) { - isInWhiteSpacePreservedElement = false; - } - - // Handle empty nodes - if (elementRule.removeEmpty || elementRule.paddEmpty) { - if (node.isEmpty(nonEmptyElements)) { - if (elementRule.paddEmpty) - node.empty().append(new Node('#text', '3')).value = '\u00a0'; - else { - // Leave nodes that have a name like - if (!node.attributes.map.name && !node.attributes.map.id) { - tempNode = node.parent; - - - if (blockElements[node.name]) { - node.empty().remove(); - } else { - node.unwrap(); - } - - node = tempNode; - return; - } - } - } - } - - node = node.parent; - } - } - }, schema); - - rootNode = node = new Node(args.context || settings.root_name, 11); - - parser.parse(html); - - // Fix invalid children or report invalid children in a contextual parsing - if (validate && invalidChildren.length) { - if (!args.context) - fixInvalidChildren(invalidChildren); - else - args.invalid = true; - } - - // Wrap nodes in the root into block elements if the root is body - if (rootBlockName && rootNode.name == 'body') - addRootBlocks(); - - // Run filters only when the contents is valid - if (!args.invalid) { - // Run node filters - for (name in matchedNodes) { - list = nodeFilters[name]; - nodes = matchedNodes[name]; - - // Remove already removed children - fi = nodes.length; - while (fi--) { - if (!nodes[fi].parent) - nodes.splice(fi, 1); - } - - for (i = 0, l = list.length; i < l; i++) - list[i](nodes, name, args); - } - - // Run attribute filters - for (i = 0, l = attributeFilters.length; i < l; i++) { - list = attributeFilters[i]; - - if (list.name in matchedAttributes) { - nodes = matchedAttributes[list.name]; - - // Remove already removed children - fi = nodes.length; - while (fi--) { - if (!nodes[fi].parent) - nodes.splice(fi, 1); - } - - for (fi = 0, fl = list.callbacks.length; fi < fl; fi++) - list.callbacks[fi](nodes, list.name, args); - } - } - } - - return rootNode; - }; - - // Remove
    at end of block elements Gecko and WebKit injects BR elements to - // make it possible to place the caret inside empty blocks. This logic tries to remove - // these elements and keep br elements that where intended to be there intact - if (settings.remove_trailing_brs) { - self.addNodeFilter('br', function(nodes, name) { - var i, l = nodes.length, node, blockElements = tinymce.extend({}, schema.getBlockElements()), - nonEmptyElements = schema.getNonEmptyElements(), parent, lastParent, prev, prevName; - - // Remove brs from body element as well - blockElements.body = 1; - - // Must loop forwards since it will otherwise remove all brs in

    a


    - for (i = 0; i < l; i++) { - node = nodes[i]; - parent = node.parent; - - if (blockElements[node.parent.name] && node === parent.lastChild) { - // Loop all nodes to the left of the current node and check for other BR elements - // excluding bookmarks since they are invisible - prev = node.prev; - while (prev) { - prevName = prev.name; - - // Ignore bookmarks - if (prevName !== "span" || prev.attr('data-mce-type') !== 'bookmark') { - // Found a non BR element - if (prevName !== "br") - break; - - // Found another br it's a

    structure then don't remove anything - if (prevName === 'br') { - node = null; - break; - } - } - - prev = prev.prev; - } - - if (node) { - node.remove(); - - // Is the parent to be considered empty after we removed the BR - if (parent.isEmpty(nonEmptyElements)) { - elementRule = schema.getElementRule(parent.name); - - // Remove or padd the element depending on schema rule - if (elementRule) { - if (elementRule.removeEmpty) - parent.remove(); - else if (elementRule.paddEmpty) - parent.empty().append(new tinymce.html.Node('#text', 3)).value = '\u00a0'; - } - } - } - } else { - // Replaces BR elements inside inline elements like


    so they become

     

    - lastParent = node; - while (parent.firstChild === lastParent && parent.lastChild === lastParent) { - lastParent = parent; - - if (blockElements[parent.name]) { - break; - } - - parent = parent.parent; - } - - if (lastParent === parent) { - textNode = new tinymce.html.Node('#text', 3); - textNode.value = '\u00a0'; - node.replace(textNode); - } - } - } - }); - } - - // Force anchor names closed, unless the setting "allow_html_in_named_anchor" is explicitly included. - if (!settings.allow_html_in_named_anchor) { - self.addAttributeFilter('id,name', function(nodes, name) { - var i = nodes.length, sibling, prevSibling, parent, node; - - while (i--) { - node = nodes[i]; - if (node.name === 'a' && node.firstChild && !node.attr('href')) { - parent = node.parent; - - // Move children after current node - sibling = node.lastChild; - do { - prevSibling = sibling.prev; - parent.insert(sibling, node); - sibling = prevSibling; - } while (sibling); - } - } - }); - } - } -})(tinymce); -tinymce.html.Writer = function(settings) { - var html = [], indent, indentBefore, indentAfter, encode, htmlOutput; - - settings = settings || {}; - indent = settings.indent; - indentBefore = tinymce.makeMap(settings.indent_before || ''); - indentAfter = tinymce.makeMap(settings.indent_after || ''); - encode = tinymce.html.Entities.getEncodeFunc(settings.entity_encoding || 'raw', settings.entities); - htmlOutput = settings.element_format == "html"; - - return { - start: function(name, attrs, empty) { - var i, l, attr, value; - - if (indent && indentBefore[name] && html.length > 0) { - value = html[html.length - 1]; - - if (value.length > 0 && value !== '\n') - html.push('\n'); - } - - html.push('<', name); - - if (attrs) { - for (i = 0, l = attrs.length; i < l; i++) { - attr = attrs[i]; - html.push(' ', attr.name, '="', encode(attr.value, true), '"'); - } - } - - if (!empty || htmlOutput) - html[html.length] = '>'; - else - html[html.length] = ' />'; - - if (empty && indent && indentAfter[name] && html.length > 0) { - value = html[html.length - 1]; - - if (value.length > 0 && value !== '\n') - html.push('\n'); - } - }, - - end: function(name) { - var value; - - /*if (indent && indentBefore[name] && html.length > 0) { - value = html[html.length - 1]; - - if (value.length > 0 && value !== '\n') - html.push('\n'); - }*/ - - html.push(''); - - if (indent && indentAfter[name] && html.length > 0) { - value = html[html.length - 1]; - - if (value.length > 0 && value !== '\n') - html.push('\n'); - } - }, - - text: function(text, raw) { - if (text.length > 0) - html[html.length] = raw ? text : encode(text); - }, - - cdata: function(text) { - html.push(''); - }, - - comment: function(text) { - html.push(''); - }, - - pi: function(name, text) { - if (text) - html.push(''); - else - html.push(''); - - if (indent) - html.push('\n'); - }, - - doctype: function(text) { - html.push('', indent ? '\n' : ''); - }, - - reset: function() { - html.length = 0; - }, - - getContent: function() { - return html.join('').replace(/\n$/, ''); - } - }; -}; -(function(tinymce) { - tinymce.html.Serializer = function(settings, schema) { - var self = this, writer = new tinymce.html.Writer(settings); - - settings = settings || {}; - settings.validate = "validate" in settings ? settings.validate : true; - - self.schema = schema = schema || new tinymce.html.Schema(); - self.writer = writer; - - self.serialize = function(node) { - var handlers, validate; - - validate = settings.validate; - - handlers = { - // #text - 3: function(node, raw) { - writer.text(node.value, node.raw); - }, - - // #comment - 8: function(node) { - writer.comment(node.value); - }, - - // Processing instruction - 7: function(node) { - writer.pi(node.name, node.value); - }, - - // Doctype - 10: function(node) { - writer.doctype(node.value); - }, - - // CDATA - 4: function(node) { - writer.cdata(node.value); - }, - - // Document fragment - 11: function(node) { - if ((node = node.firstChild)) { - do { - walk(node); - } while (node = node.next); - } - } - }; - - writer.reset(); - - function walk(node) { - var handler = handlers[node.type], name, isEmpty, attrs, attrName, attrValue, sortedAttrs, i, l, elementRule; - - if (!handler) { - name = node.name; - isEmpty = node.shortEnded; - attrs = node.attributes; - - // Sort attributes - if (validate && attrs && attrs.length > 1) { - sortedAttrs = []; - sortedAttrs.map = {}; - - elementRule = schema.getElementRule(node.name); - for (i = 0, l = elementRule.attributesOrder.length; i < l; i++) { - attrName = elementRule.attributesOrder[i]; - - if (attrName in attrs.map) { - attrValue = attrs.map[attrName]; - sortedAttrs.map[attrName] = attrValue; - sortedAttrs.push({name: attrName, value: attrValue}); - } - } - - for (i = 0, l = attrs.length; i < l; i++) { - attrName = attrs[i].name; - - if (!(attrName in sortedAttrs.map)) { - attrValue = attrs.map[attrName]; - sortedAttrs.map[attrName] = attrValue; - sortedAttrs.push({name: attrName, value: attrValue}); - } - } - - attrs = sortedAttrs; - } - - writer.start(node.name, attrs, isEmpty); - - if (!isEmpty) { - if ((node = node.firstChild)) { - do { - walk(node); - } while (node = node.next); - } - - writer.end(name); - } - } else - handler(node); - } - - // Serialize element and treat all non elements as fragments - if (node.type == 1 && !settings.inner) - walk(node); - else - handlers[11](node); - - return writer.getContent(); - }; - } -})(tinymce); -// JSLint defined globals -/*global tinymce:false, window:false */ - -tinymce.dom = {}; - -(function(namespace, expando) { - var w3cEventModel = !!document.addEventListener; - - function addEvent(target, name, callback, capture) { - if (target.addEventListener) { - target.addEventListener(name, callback, capture || false); - } else if (target.attachEvent) { - target.attachEvent('on' + name, callback); - } - } - - function removeEvent(target, name, callback, capture) { - if (target.removeEventListener) { - target.removeEventListener(name, callback, capture || false); - } else if (target.detachEvent) { - target.detachEvent('on' + name, callback); - } - } - - function fix(original_event, data) { - var name, event = data || {}; - - // Dummy function that gets replaced on the delegation state functions - function returnFalse() { - return false; - } - - // Dummy function that gets replaced on the delegation state functions - function returnTrue() { - return true; - } - - // Copy all properties from the original event - for (name in original_event) { - // layerX/layerY is deprecated in Chrome and produces a warning - if (name !== "layerX" && name !== "layerY") { - event[name] = original_event[name]; - } - } - - // Normalize target IE uses srcElement - if (!event.target) { - event.target = event.srcElement || document; - } - - // Add preventDefault method - event.preventDefault = function() { - event.isDefaultPrevented = returnTrue; - - // Execute preventDefault on the original event object - if (original_event) { - if (original_event.preventDefault) { - original_event.preventDefault(); - } else { - original_event.returnValue = false; // IE - } - } - }; - - // Add stopPropagation - event.stopPropagation = function() { - event.isPropagationStopped = returnTrue; - - // Execute stopPropagation on the original event object - if (original_event) { - if (original_event.stopPropagation) { - original_event.stopPropagation(); - } else { - original_event.cancelBubble = true; // IE - } - } - }; - - // Add stopImmediatePropagation - event.stopImmediatePropagation = function() { - event.isImmediatePropagationStopped = returnTrue; - event.stopPropagation(); - }; - - // Add event delegation states - if (!event.isDefaultPrevented) { - event.isDefaultPrevented = returnFalse; - event.isPropagationStopped = returnFalse; - event.isImmediatePropagationStopped = returnFalse; - } - - return event; - } - - function bindOnReady(win, callback, event_utils) { - var doc = win.document, event = {type: 'ready'}; - - // Gets called when the DOM is ready - function readyHandler() { - if (!event_utils.domLoaded) { - event_utils.domLoaded = true; - callback(event); - } - } - - // Page already loaded then fire it directly - if (doc.readyState == "complete") { - readyHandler(); - return; - } - - // Use W3C method - if (w3cEventModel) { - addEvent(win, 'DOMContentLoaded', readyHandler); - } else { - // Use IE method - addEvent(doc, "readystatechange", function() { - if (doc.readyState === "complete") { - removeEvent(doc, "readystatechange", arguments.callee); - readyHandler(); - } - }); - - // Wait until we can scroll, when we can the DOM is initialized - if (doc.documentElement.doScroll && win === win.top) { - (function() { - try { - // If IE is used, use the trick by Diego Perini licensed under MIT by request to the author. - // http://javascript.nwbox.com/IEContentLoaded/ - doc.documentElement.doScroll("left"); - } catch (ex) { - setTimeout(arguments.callee, 0); - return; - } - - readyHandler(); - })(); - } - } - - // Fallback if any of the above methods should fail for some odd reason - addEvent(win, 'load', readyHandler); - } - - function EventUtils(proxy) { - var self = this, events = {}, count, isFocusBlurBound, hasFocusIn, hasMouseEnterLeave, mouseEnterLeave; - - hasMouseEnterLeave = "onmouseenter" in document.documentElement; - hasFocusIn = "onfocusin" in document.documentElement; - mouseEnterLeave = {mouseenter: 'mouseover', mouseleave: 'mouseout'}; - count = 1; - - // State if the DOMContentLoaded was executed or not - self.domLoaded = false; - self.events = events; - - function executeHandlers(evt, id) { - var callbackList, i, l, callback; - - callbackList = events[id][evt.type]; - if (callbackList) { - for (i = 0, l = callbackList.length; i < l; i++) { - callback = callbackList[i]; - - // Check if callback exists might be removed if a unbind is called inside the callback - if (callback && callback.func.call(callback.scope, evt) === false) { - evt.preventDefault(); - } - - // Should we stop propagation to immediate listeners - if (evt.isImmediatePropagationStopped()) { - return; - } - } - } - } - - self.bind = function(target, names, callback, scope) { - var id, callbackList, i, name, fakeName, nativeHandler, capture, win = window; - - // Native event handler function patches the event and executes the callbacks for the expando - function defaultNativeHandler(evt) { - executeHandlers(fix(evt || win.event), id); - } - - // Don't bind to text nodes or comments - if (!target || target.nodeType === 3 || target.nodeType === 8) { - return; - } - - // Create or get events id for the target - if (!target[expando]) { - id = count++; - target[expando] = id; - events[id] = {}; - } else { - id = target[expando]; - - if (!events[id]) { - events[id] = {}; - } - } - - // Setup the specified scope or use the target as a default - scope = scope || target; - - // Split names and bind each event, enables you to bind multiple events with one call - names = names.split(' '); - i = names.length; - while (i--) { - name = names[i]; - nativeHandler = defaultNativeHandler; - fakeName = capture = false; - - // Use ready instead of DOMContentLoaded - if (name === "DOMContentLoaded") { - name = "ready"; - } - - // DOM is already ready - if ((self.domLoaded || target.readyState == 'complete') && name === "ready") { - self.domLoaded = true; - callback.call(scope, fix({type: name})); - continue; - } - - // Handle mouseenter/mouseleaver - if (!hasMouseEnterLeave) { - fakeName = mouseEnterLeave[name]; - - if (fakeName) { - nativeHandler = function(evt) { - var current, related; - - current = evt.currentTarget; - related = evt.relatedTarget; - - // Check if related is inside the current target if it's not then the event should be ignored since it's a mouseover/mouseout inside the element - if (related && current.contains) { - // Use contains for performance - related = current.contains(related); - } else { - while (related && related !== current) { - related = related.parentNode; - } - } - - // Fire fake event - if (!related) { - evt = fix(evt || win.event); - evt.type = evt.type === 'mouseout' ? 'mouseleave' : 'mouseenter'; - evt.target = current; - executeHandlers(evt, id); - } - }; - } - } - - // Fake bubbeling of focusin/focusout - if (!hasFocusIn && (name === "focusin" || name === "focusout")) { - capture = true; - fakeName = name === "focusin" ? "focus" : "blur"; - nativeHandler = function(evt) { - evt = fix(evt || win.event); - evt.type = evt.type === 'focus' ? 'focusin' : 'focusout'; - executeHandlers(evt, id); - }; - } - - // Setup callback list and bind native event - callbackList = events[id][name]; - if (!callbackList) { - events[id][name] = callbackList = [{func: callback, scope: scope}]; - callbackList.fakeName = fakeName; - callbackList.capture = capture; - - // Add the nativeHandler to the callback list so that we can later unbind it - callbackList.nativeHandler = nativeHandler; - if (!w3cEventModel) { - callbackList.proxyHandler = proxy(id); - } - - // Check if the target has native events support - if (name === "ready") { - bindOnReady(target, nativeHandler, self); - } else { - addEvent(target, fakeName || name, w3cEventModel ? nativeHandler : callbackList.proxyHandler, capture); - } - } else { - // If it already has an native handler then just push the callback - callbackList.push({func: callback, scope: scope}); - } - } - - target = callbackList = 0; // Clean memory for IE - - return callback; - }; - - self.unbind = function(target, names, callback) { - var id, callbackList, i, ci, name, eventMap; - - // Don't bind to text nodes or comments - if (!target || target.nodeType === 3 || target.nodeType === 8) { - return self; - } - - // Unbind event or events if the target has the expando - id = target[expando]; - if (id) { - eventMap = events[id]; - - // Specific callback - if (names) { - names = names.split(' '); - i = names.length; - while (i--) { - name = names[i]; - callbackList = eventMap[name]; - - // Unbind the event if it exists in the map - if (callbackList) { - // Remove specified callback - if (callback) { - ci = callbackList.length; - while (ci--) { - if (callbackList[ci].func === callback) { - callbackList.splice(ci, 1); - } - } - } - - // Remove all callbacks if there isn't a specified callback or there is no callbacks left - if (!callback || callbackList.length === 0) { - delete eventMap[name]; - removeEvent(target, callbackList.fakeName || name, w3cEventModel ? callbackList.nativeHandler : callbackList.proxyHandler, callbackList.capture); - } - } - } - } else { - // All events for a specific element - for (name in eventMap) { - callbackList = eventMap[name]; - removeEvent(target, callbackList.fakeName || name, w3cEventModel ? callbackList.nativeHandler : callbackList.proxyHandler, callbackList.capture); - } - - eventMap = {}; - } - - // Check if object is empty, if it isn't then we won't remove the expando map - for (name in eventMap) { - return self; - } - - // Delete event object - delete events[id]; - - // Remove expando from target - try { - // IE will fail here since it can't delete properties from window - delete target[expando]; - } catch (ex) { - // IE will set it to null - target[expando] = null; - } - } - - return self; - }; - - self.fire = function(target, name, args) { - var id, event; - - // Don't bind to text nodes or comments - if (!target || target.nodeType === 3 || target.nodeType === 8) { - return self; - } - - // Build event object by patching the args - event = fix(null, args); - event.type = name; - - do { - // Found an expando that means there is listeners to execute - id = target[expando]; - if (id) { - executeHandlers(event, id); - } - - // Walk up the DOM - target = target.parentNode || target.ownerDocument || target.defaultView || target.parentWindow; - } while (target && !event.isPropagationStopped()); - - return self; - }; - - self.clean = function(target) { - var i, children, unbind = self.unbind; - - // Don't bind to text nodes or comments - if (!target || target.nodeType === 3 || target.nodeType === 8) { - return self; - } - - // Unbind any element on the specificed target - if (target[expando]) { - unbind(target); - } - - // Target doesn't have getElementsByTagName it's probably a window object then use it's document to find the children - if (!target.getElementsByTagName) { - target = target.document; - } - - // Remove events from each child element - if (target && target.getElementsByTagName) { - unbind(target); - - children = target.getElementsByTagName('*'); - i = children.length; - while (i--) { - target = children[i]; - - if (target[expando]) { - unbind(target); - } - } - } - - return self; - }; - - self.callNativeHandler = function(id, evt) { - if (events) { - events[id][evt.type].nativeHandler(evt); - } - }; - - self.destory = function() { - events = {}; - }; - - // Legacy function calls - - self.add = function(target, events, func, scope) { - // Old API supported direct ID assignment - if (typeof(target) === "string") { - target = document.getElementById(target); - } - - // Old API supported multiple targets - if (target && target instanceof Array) { - var i = target.length; - - while (i--) { - self.add(target[i], events, func, scope); - } - - return; - } - - // Old API called ready init - if (events === "init") { - events = "ready"; - } - - return self.bind(target, events instanceof Array ? events.join(' ') : events, func, scope); - }; - - self.remove = function(target, events, func, scope) { - if (!target) { - return self; - } - - // Old API supported direct ID assignment - if (typeof(target) === "string") { - target = document.getElementById(target); - } - - // Old API supported multiple targets - if (target instanceof Array) { - var i = target.length; - - while (i--) { - self.remove(target[i], events, func, scope); - } - - return self; - } - - return self.unbind(target, events instanceof Array ? events.join(' ') : events, func); - }; - - self.clear = function(target) { - // Old API supported direct ID assignment - if (typeof(target) === "string") { - target = document.getElementById(target); - } - - return self.clean(target); - }; - - self.cancel = function(e) { - if (e) { - self.prevent(e); - self.stop(e); - } - - return false; - }; - - self.prevent = function(e) { - if (!e.preventDefault) { - e = fix(e); - } - - e.preventDefault(); - - return false; - }; - - self.stop = function(e) { - if (!e.stopPropagation) { - e = fix(e); - } - - e.stopPropagation(); - - return false; - }; - } - - namespace.EventUtils = EventUtils; - - namespace.Event = new EventUtils(function(id) { - return function(evt) { - tinymce.dom.Event.callNativeHandler(id, evt); - }; - }); - - // Bind ready event when tinymce script is loaded - namespace.Event.bind(window, 'ready', function() {}); - - namespace = 0; -})(tinymce.dom, 'data-mce-expando'); // Namespace and expando -tinymce.dom.TreeWalker = function(start_node, root_node) { - var node = start_node; - - function findSibling(node, start_name, sibling_name, shallow) { - var sibling, parent; - - if (node) { - // Walk into nodes if it has a start - if (!shallow && node[start_name]) - return node[start_name]; - - // Return the sibling if it has one - if (node != root_node) { - sibling = node[sibling_name]; - if (sibling) - return sibling; - - // Walk up the parents to look for siblings - for (parent = node.parentNode; parent && parent != root_node; parent = parent.parentNode) { - sibling = parent[sibling_name]; - if (sibling) - return sibling; - } - } - } - }; - - this.current = function() { - return node; - }; - - this.next = function(shallow) { - return (node = findSibling(node, 'firstChild', 'nextSibling', shallow)); - }; - - this.prev = function(shallow) { - return (node = findSibling(node, 'lastChild', 'previousSibling', shallow)); - }; -}; -(function(tinymce) { - // Shorten names - var each = tinymce.each, - is = tinymce.is, - isWebKit = tinymce.isWebKit, - isIE = tinymce.isIE, - Entities = tinymce.html.Entities, - simpleSelectorRe = /^([a-z0-9],?)+$/i, - whiteSpaceRegExp = /^[ \t\r\n]*$/; - - tinymce.create('tinymce.dom.DOMUtils', { - doc : null, - root : null, - files : null, - pixelStyles : /^(top|left|bottom|right|width|height|borderWidth)$/, - props : { - "for" : "htmlFor", - "class" : "className", - className : "className", - checked : "checked", - disabled : "disabled", - maxlength : "maxLength", - readonly : "readOnly", - selected : "selected", - value : "value", - id : "id", - name : "name", - type : "type" - }, - - DOMUtils : function(d, s) { - var t = this, globalStyle, name, blockElementsMap; - - t.doc = d; - t.win = window; - t.files = {}; - t.cssFlicker = false; - t.counter = 0; - t.stdMode = !tinymce.isIE || d.documentMode >= 8; - t.boxModel = !tinymce.isIE || d.compatMode == "CSS1Compat" || t.stdMode; - t.hasOuterHTML = "outerHTML" in d.createElement("a"); - - t.settings = s = tinymce.extend({ - keep_values : false, - hex_colors : 1 - }, s); - - t.schema = s.schema; - t.styles = new tinymce.html.Styles({ - url_converter : s.url_converter, - url_converter_scope : s.url_converter_scope - }, s.schema); - - // Fix IE6SP2 flicker and check it failed for pre SP2 - if (tinymce.isIE6) { - try { - d.execCommand('BackgroundImageCache', false, true); - } catch (e) { - t.cssFlicker = true; - } - } - - t.fixDoc(d); - t.events = s.ownEvents ? new tinymce.dom.EventUtils(s.proxy) : tinymce.dom.Event; - tinymce.addUnload(t.destroy, t); - blockElementsMap = s.schema ? s.schema.getBlockElements() : {}; - - t.isBlock = function(node) { - // Fix for #5446 - if (!node) { - return false; - } - - // This function is called in module pattern style since it might be executed with the wrong this scope - var type = node.nodeType; - - // If it's a node then check the type and use the nodeName - if (type) - return !!(type === 1 && blockElementsMap[node.nodeName]); - - return !!blockElementsMap[node]; - }; - }, - - fixDoc: function(doc) { - var settings = this.settings, name; - - if (isIE && !tinymce.isIE11 && settings.schema) { - // Add missing HTML 4/5 elements to IE - ('abbr article aside audio canvas ' + - 'details figcaption figure footer ' + - 'header hgroup mark menu meter nav ' + - 'output progress section summary ' + - 'time video').replace(/\w+/g, function(name) { - doc.createElement(name); - }); - - // Create all custom elements - for (name in settings.schema.getCustomElements()) { - doc.createElement(name); - } - } - }, - - clone: function(node, deep) { - var self = this, clone, doc; - - // TODO: Add feature detection here in the future - if (!isIE || tinymce.isIE11 || node.nodeType !== 1 || deep) { - return node.cloneNode(deep); - } - - doc = self.doc; - - // Make a HTML5 safe shallow copy - if (!deep) { - clone = doc.createElement(node.nodeName); - - // Copy attribs - each(self.getAttribs(node), function(attr) { - self.setAttrib(clone, attr.nodeName, self.getAttrib(node, attr.nodeName)); - }); - - return clone; - } -/* - // Setup HTML5 patched document fragment - if (!self.frag) { - self.frag = doc.createDocumentFragment(); - self.fixDoc(self.frag); - } - - // Make a deep copy by adding it to the document fragment then removing it this removed the :section - clone = doc.createElement('div'); - self.frag.appendChild(clone); - clone.innerHTML = node.outerHTML; - self.frag.removeChild(clone); -*/ - return clone.firstChild; - }, - - getRoot : function() { - var t = this, s = t.settings; - - return (s && t.get(s.root_element)) || t.doc.body; - }, - - getViewPort : function(w) { - var d, b; - - w = !w ? this.win : w; - d = w.document; - b = this.boxModel ? d.documentElement : d.body; - - // Returns viewport size excluding scrollbars - return { - x : w.pageXOffset || b.scrollLeft, - y : w.pageYOffset || b.scrollTop, - w : w.innerWidth || b.clientWidth, - h : w.innerHeight || b.clientHeight - }; - }, - - getRect : function(e) { - var p, t = this, sr; - - e = t.get(e); - p = t.getPos(e); - sr = t.getSize(e); - - return { - x : p.x, - y : p.y, - w : sr.w, - h : sr.h - }; - }, - - getSize : function(e) { - var t = this, w, h; - - e = t.get(e); - w = t.getStyle(e, 'width'); - h = t.getStyle(e, 'height'); - - // Non pixel value, then force offset/clientWidth - if (w.indexOf('px') === -1) - w = 0; - - // Non pixel value, then force offset/clientWidth - if (h.indexOf('px') === -1) - h = 0; - - return { - w : parseInt(w, 10) || e.offsetWidth || e.clientWidth, - h : parseInt(h, 10) || e.offsetHeight || e.clientHeight - }; - }, - - getParent : function(n, f, r) { - return this.getParents(n, f, r, false); - }, - - getParents : function(n, f, r, c) { - var t = this, na, se = t.settings, o = []; - - n = t.get(n); - c = c === undefined; - - if (se.strict_root) - r = r || t.getRoot(); - - // Wrap node name as func - if (is(f, 'string')) { - na = f; - - if (f === '*') { - f = function(n) {return n.nodeType == 1;}; - } else { - f = function(n) { - return t.is(n, na); - }; - } - } - - while (n) { - if (n == r || !n.nodeType || n.nodeType === 9) - break; - - if (!f || f(n)) { - if (c) - o.push(n); - else - return n; - } - - n = n.parentNode; - } - - return c ? o : null; - }, - - get : function(e) { - var n; - - if (e && this.doc && typeof(e) == 'string') { - n = e; - e = this.doc.getElementById(e); - - // IE and Opera returns meta elements when they match the specified input ID, but getElementsByName seems to do the trick - if (e && e.id !== n) - return this.doc.getElementsByName(n)[1]; - } - - return e; - }, - - getNext : function(node, selector) { - return this._findSib(node, selector, 'nextSibling'); - }, - - getPrev : function(node, selector) { - return this._findSib(node, selector, 'previousSibling'); - }, - - - select : function(pa, s) { - var t = this; - - return tinymce.dom.Sizzle(pa, t.get(s) || t.get(t.settings.root_element) || t.doc, []); - }, - - is : function(n, selector) { - var i; - - // If it isn't an array then try to do some simple selectors instead of Sizzle for to boost performance - if (n.length === undefined) { - // Simple all selector - if (selector === '*') - return n.nodeType == 1; - - // Simple selector just elements - if (simpleSelectorRe.test(selector)) { - selector = selector.toLowerCase().split(/,/); - n = n.nodeName.toLowerCase(); - - for (i = selector.length - 1; i >= 0; i--) { - if (selector[i] == n) - return true; - } - - return false; - } - } - - return tinymce.dom.Sizzle.matches(selector, n.nodeType ? [n] : n).length > 0; - }, - - - add : function(p, n, a, h, c) { - var t = this; - - return this.run(p, function(p) { - var e, k; - - e = is(n, 'string') ? t.doc.createElement(n) : n; - t.setAttribs(e, a); - - if (h) { - if (h.nodeType) - e.appendChild(h); - else - t.setHTML(e, h); - } - - return !c ? p.appendChild(e) : e; - }); - }, - - create : function(n, a, h) { - return this.add(this.doc.createElement(n), n, a, h, 1); - }, - - createHTML : function(n, a, h) { - var o = '', t = this, k; - - o += '<' + n; - - for (k in a) { - if (a.hasOwnProperty(k)) - o += ' ' + k + '="' + t.encode(a[k]) + '"'; - } - - // A call to tinymce.is doesn't work for some odd reason on IE9 possible bug inside their JS runtime - if (typeof(h) != "undefined") - return o + '>' + h + ''; - - return o + ' />'; - }, - - remove : function(node, keep_children) { - return this.run(node, function(node) { - var child, parent = node.parentNode; - - if (!parent) - return null; - - if (keep_children) { - while (child = node.firstChild) { - // IE 8 will crash if you don't remove completely empty text nodes - if (!tinymce.isIE || child.nodeType !== 3 || child.nodeValue) - parent.insertBefore(child, node); - else - node.removeChild(child); - } - } - - return parent.removeChild(node); - }); - }, - - setStyle : function(n, na, v) { - var t = this; - - return t.run(n, function(e) { - var s, i; - - s = e.style; - - // Camelcase it, if needed - na = na.replace(/-(\D)/g, function(a, b){ - return b.toUpperCase(); - }); - - // Default px suffix on these - if (t.pixelStyles.test(na) && (tinymce.is(v, 'number') || /^[\-0-9\.]+$/.test(v))) - v += 'px'; - - switch (na) { - case 'opacity': - // IE specific opacity - if (isIE && ! tinymce.isIE11) { - s.filter = v === '' ? '' : "alpha(opacity=" + (v * 100) + ")"; - - if (!n.currentStyle || !n.currentStyle.hasLayout) - s.display = 'inline-block'; - } - - // Fix for older browsers - s[na] = s['-moz-opacity'] = s['-khtml-opacity'] = v || ''; - break; - - case 'float': - (isIE && ! tinymce.isIE11) ? s.styleFloat = v : s.cssFloat = v; - break; - - default: - s[na] = v || ''; - } - - // Force update of the style data - if (t.settings.update_styles) - t.setAttrib(e, 'data-mce-style'); - }); - }, - - getStyle : function(n, na, c) { - n = this.get(n); - - if (!n) - return; - - // Gecko - if (this.doc.defaultView && c) { - // Remove camelcase - na = na.replace(/[A-Z]/g, function(a){ - return '-' + a; - }); - - try { - return this.doc.defaultView.getComputedStyle(n, null).getPropertyValue(na); - } catch (ex) { - // Old safari might fail - return null; - } - } - - // Camelcase it, if needed - na = na.replace(/-(\D)/g, function(a, b){ - return b.toUpperCase(); - }); - - if (na == 'float') - na = isIE ? 'styleFloat' : 'cssFloat'; - - // IE & Opera - if (n.currentStyle && c) - return n.currentStyle[na]; - - return n.style ? n.style[na] : undefined; - }, - - setStyles : function(e, o) { - var t = this, s = t.settings, ol; - - ol = s.update_styles; - s.update_styles = 0; - - each(o, function(v, n) { - t.setStyle(e, n, v); - }); - - // Update style info - s.update_styles = ol; - if (s.update_styles) - t.setAttrib(e, s.cssText); - }, - - removeAllAttribs: function(e) { - return this.run(e, function(e) { - var i, attrs = e.attributes; - for (i = attrs.length - 1; i >= 0; i--) { - e.removeAttributeNode(attrs.item(i)); - } - }); - }, - - setAttrib : function(e, n, v) { - var t = this; - - // Whats the point - if (!e || !n) - return; - - // Strict XML mode - if (t.settings.strict) - n = n.toLowerCase(); - - return this.run(e, function(e) { - var s = t.settings; - var originalValue = e.getAttribute(n); - if (v !== null) { - switch (n) { - case "style": - if (!is(v, 'string')) { - each(v, function(v, n) { - t.setStyle(e, n, v); - }); - - return; - } - - // No mce_style for elements with these since they might get resized by the user - if (s.keep_values) { - if (v && !t._isRes(v)) - e.setAttribute('data-mce-style', v, 2); - else - e.removeAttribute('data-mce-style', 2); - } - - e.style.cssText = v; - break; - - case "class": - e.className = v || ''; // Fix IE null bug - break; - - case "src": - case "href": - if (s.keep_values) { - if (s.url_converter) - v = s.url_converter.call(s.url_converter_scope || t, v, n, e); - - t.setAttrib(e, 'data-mce-' + n, v, 2); - } - - break; - - case "shape": - e.setAttribute('data-mce-style', v); - break; - } - } - if (is(v) && v !== null && v.length !== 0) - e.setAttribute(n, '' + v, 2); - else - e.removeAttribute(n, 2); - - // fire onChangeAttrib event for attributes that have changed - if (tinyMCE.activeEditor && originalValue != v) { - var ed = tinyMCE.activeEditor; - ed.onSetAttrib.dispatch(ed, e, n, v); - } - }); - }, - - setAttribs : function(e, o) { - var t = this; - - return this.run(e, function(e) { - each(o, function(v, n) { - t.setAttrib(e, n, v); - }); - }); - }, - - getAttrib : function(e, n, dv) { - var v, t = this, undef; - - e = t.get(e); - - if (!e || e.nodeType !== 1) - return dv === undef ? false : dv; - - if (!is(dv)) - dv = ''; - - // Try the mce variant for these - if (/^(src|href|style|coords|shape)$/.test(n)) { - v = e.getAttribute("data-mce-" + n); - - if (v) - return v; - } - - if (isIE && t.props[n]) { - v = e[t.props[n]]; - v = v && v.nodeValue ? v.nodeValue : v; - } - - if (!v) - v = e.getAttribute(n, 2); - - // Check boolean attribs - if (/^(checked|compact|declare|defer|disabled|ismap|multiple|nohref|noshade|nowrap|readonly|selected)$/.test(n)) { - if (e[t.props[n]] === true && v === '') - return n; - - return v ? n : ''; - } - - // Inner input elements will override attributes on form elements - if (e.nodeName === "FORM" && e.getAttributeNode(n)) - return e.getAttributeNode(n).nodeValue; - - if (n === 'style') { - v = v || e.style.cssText; - - if (v) { - v = t.serializeStyle(t.parseStyle(v), e.nodeName); - - if (t.settings.keep_values && !t._isRes(v)) - e.setAttribute('data-mce-style', v); - } - } - - // Remove Apple and WebKit stuff - if (isWebKit && n === "class" && v) - v = v.replace(/(apple|webkit)\-[a-z\-]+/gi, ''); - - // Handle IE issues - if (isIE) { - switch (n) { - case 'rowspan': - case 'colspan': - // IE returns 1 as default value - if (v === 1) - v = ''; - - break; - - case 'size': - // IE returns +0 as default value for size - if (v === '+0' || v === 20 || v === 0) - v = ''; - - break; - - case 'width': - case 'height': - case 'vspace': - case 'checked': - case 'disabled': - case 'readonly': - if (v === 0) - v = ''; - - break; - - case 'hspace': - // IE returns -1 as default value - if (v === -1) - v = ''; - - break; - - case 'maxlength': - case 'tabindex': - // IE returns default value - if (v === 32768 || v === 2147483647 || v === '32768') - v = ''; - - break; - - case 'multiple': - case 'compact': - case 'noshade': - case 'nowrap': - if (v === 65535) - return n; - - return dv; - - case 'shape': - v = v.toLowerCase(); - break; - - default: - // IE has odd anonymous function for event attributes - if (n.indexOf('on') === 0 && v) - v = tinymce._replace(/^function\s+\w+\(\)\s+\{\s+(.*)\s+\}$/, '$1', '' + v); - } - } - - return (v !== undef && v !== null && v !== '') ? '' + v : dv; - }, - - getPos : function(n, ro) { - var t = this, x = 0, y = 0, e, d = t.doc, r; - - n = t.get(n); - ro = ro || d.body; - - if (n) { - // Use getBoundingClientRect if it exists since it's faster than looping offset nodes - if (n.getBoundingClientRect) { - n = n.getBoundingClientRect(); - e = t.boxModel ? d.documentElement : d.body; - - // Add scroll offsets from documentElement or body since IE with the wrong box model will use d.body and so do WebKit - // Also remove the body/documentelement clientTop/clientLeft on IE 6, 7 since they offset the position - x = n.left + (d.documentElement.scrollLeft || d.body.scrollLeft) - e.clientTop; - y = n.top + (d.documentElement.scrollTop || d.body.scrollTop) - e.clientLeft; - - return {x : x, y : y}; - } - - r = n; - while (r && r != ro && r.nodeType) { - x += r.offsetLeft || 0; - y += r.offsetTop || 0; - r = r.offsetParent; - } - - r = n.parentNode; - while (r && r != ro && r.nodeType) { - x -= r.scrollLeft || 0; - y -= r.scrollTop || 0; - r = r.parentNode; - } - } - - return {x : x, y : y}; - }, - - parseStyle : function(st) { - return this.styles.parse(st); - }, - - serializeStyle : function(o, name) { - return this.styles.serialize(o, name); - }, - - addStyle: function(cssText) { - var doc = this.doc, head; - - // Create style element if needed - styleElm = doc.getElementById('mceDefaultStyles'); - if (!styleElm) { - styleElm = doc.createElement('style'), - styleElm.id = 'mceDefaultStyles'; - styleElm.type = 'text/css'; - - head = doc.getElementsByTagName('head')[0]; - if (head.firstChild) { - head.insertBefore(styleElm, head.firstChild); - } else { - head.appendChild(styleElm); - } - } - - // Append style data to old or new style element - if (styleElm.styleSheet) { - styleElm.styleSheet.cssText += cssText; - } else { - styleElm.appendChild(doc.createTextNode(cssText)); - } - }, - - loadCSS : function(u) { - var t = this, d = t.doc, head; - - if (!u) - u = ''; - - head = d.getElementsByTagName('head')[0]; - - each(u.split(','), function(u) { - var link; - - if (t.files[u]) - return; - - t.files[u] = true; - link = t.create('link', {rel : 'stylesheet', href : tinymce._addVer(u)}); - - // IE 8 has a bug where dynamically loading stylesheets would produce a 1 item remaining bug - // This fix seems to resolve that issue by realcing the document ones a stylesheet finishes loading - // It's ugly but it seems to work fine. - if (isIE && !tinymce.isIE11 && d.documentMode && d.recalc) { - link.onload = function() { - if (d.recalc) - d.recalc(); - - link.onload = null; - }; - } - - head.appendChild(link); - }); - }, - - addClass : function(e, c) { - return this.run(e, function(e) { - var o; - - if (!c) - return 0; - - if (this.hasClass(e, c)) - return e.className; - - o = this.removeClass(e, c); - - return e.className = (o != '' ? (o + ' ') : '') + c; - }); - }, - - removeClass : function(e, c) { - var t = this, re; - - return t.run(e, function(e) { - var v; - - if (t.hasClass(e, c)) { - if (!re) - re = new RegExp("(^|\\s+)" + c + "(\\s+|$)", "g"); - - v = e.className.replace(re, ' '); - v = tinymce.trim(v != ' ' ? v : ''); - - e.className = v; - - // Empty class attr - if (!v) { - e.removeAttribute('class'); - e.removeAttribute('className'); - } - - return v; - } - - return e.className; - }); - }, - - hasClass : function(n, c) { - n = this.get(n); - - if (!n || !c) - return false; - - return (' ' + n.className + ' ').indexOf(' ' + c + ' ') !== -1; - }, - - show : function(e) { - return this.setStyle(e, 'display', 'block'); - }, - - hide : function(e) { - return this.setStyle(e, 'display', 'none'); - }, - - isHidden : function(e) { - e = this.get(e); - - return !e || e.style.display == 'none' || this.getStyle(e, 'display') == 'none'; - }, - - uniqueId : function(p) { - return (!p ? 'mce_' : p) + (this.counter++); - }, - - setHTML : function(element, html) { - var self = this; - - return self.run(element, function(element) { - if (isIE) { - // Remove all child nodes, IE keeps empty text nodes in DOM - while (element.firstChild) - element.removeChild(element.firstChild); - - try { - // IE will remove comments from the beginning - // unless you padd the contents with something - element.innerHTML = '
    ' + html; - element.removeChild(element.firstChild); - } catch (ex) { - // IE sometimes produces an unknown runtime error on innerHTML if it's an block element within a block element for example a div inside a p - // This seems to fix this problem - - // Create new div with HTML contents and a BR infront to keep comments - var newElement = self.create('div'); - newElement.innerHTML = '
    ' + html; - - // Add all children from div to target - each (tinymce.grep(newElement.childNodes), function(node, i) { - // Skip br element - if (i && element.canHaveHTML) - element.appendChild(node); - }); - } - } else - element.innerHTML = html; - - return html; - }); - }, - - getOuterHTML : function(elm) { - var doc, self = this; - - elm = self.get(elm); - - if (!elm) - return null; - - if (elm.nodeType === 1 && self.hasOuterHTML) - return elm.outerHTML; - - doc = (elm.ownerDocument || self.doc).createElement("body"); - doc.appendChild(elm.cloneNode(true)); - - return doc.innerHTML; - }, - - setOuterHTML : function(e, h, d) { - var t = this; - - function setHTML(e, h, d) { - var n, tp; - - tp = d.createElement("body"); - tp.innerHTML = h; - - n = tp.lastChild; - while (n) { - t.insertAfter(n.cloneNode(true), e); - n = n.previousSibling; - } - - t.remove(e); - }; - - return this.run(e, function(e) { - e = t.get(e); - - // Only set HTML on elements - if (e.nodeType == 1) { - d = d || e.ownerDocument || t.doc; - - if (isIE) { - try { - // Try outerHTML for IE it sometimes produces an unknown runtime error - if (isIE && e.nodeType == 1) - e.outerHTML = h; - else - setHTML(e, h, d); - } catch (ex) { - // Fix for unknown runtime error - setHTML(e, h, d); - } - } else - setHTML(e, h, d); - } - }); - }, - - decode : Entities.decode, - - encode : Entities.encodeAllRaw, - - insertAfter : function(node, reference_node) { - reference_node = this.get(reference_node); - - return this.run(node, function(node) { - var parent, nextSibling; - - parent = reference_node.parentNode; - nextSibling = reference_node.nextSibling; - - if (nextSibling) - parent.insertBefore(node, nextSibling); - else - parent.appendChild(node); - - return node; - }); - }, - - replace : function(n, o, k) { - var t = this; - - if (is(o, 'array')) - n = n.cloneNode(true); - - return t.run(o, function(o) { - if (k) { - each(tinymce.grep(o.childNodes), function(c) { - n.appendChild(c); - }); - } - - return o.parentNode.replaceChild(n, o); - }); - }, - - rename : function(elm, name) { - var t = this, newElm; - - if (elm.nodeName != name.toUpperCase()) { - // Rename block element - newElm = t.create(name); - - // Copy attribs to new block - each(t.getAttribs(elm), function(attr_node) { - t.setAttrib(newElm, attr_node.nodeName, t.getAttrib(elm, attr_node.nodeName)); - }); - - // Replace block - t.replace(newElm, elm, 1); - } - - return newElm || elm; - }, - - findCommonAncestor : function(a, b) { - var ps = a, pe; - - while (ps) { - pe = b; - - while (pe && ps != pe) - pe = pe.parentNode; - - if (ps == pe) - break; - - ps = ps.parentNode; - } - - if (!ps && a.ownerDocument) - return a.ownerDocument.documentElement; - - return ps; - }, - - toHex : function(s) { - var c = /^\s*rgb\s*?\(\s*?([0-9]+)\s*?,\s*?([0-9]+)\s*?,\s*?([0-9]+)\s*?\)\s*$/i.exec(s); - - function hex(s) { - s = parseInt(s, 10).toString(16); - - return s.length > 1 ? s : '0' + s; // 0 -> 00 - }; - - if (c) { - s = '#' + hex(c[1]) + hex(c[2]) + hex(c[3]); - - return s; - } - - return s; - }, - - getClasses : function() { - var t = this, cl = [], i, lo = {}, f = t.settings.class_filter, ov; - - if (t.classes) - return t.classes; - - function addClasses(s) { - // IE style imports - each(s.imports, function(r) { - addClasses(r); - }); - - each(s.cssRules || s.rules, function(r) { - // Real type or fake it on IE - switch (r.type || 1) { - // Rule - case 1: - if (r.selectorText) { - each(r.selectorText.split(','), function(v) { - v = v.replace(/^\s*|\s*$|^\s\./g, ""); - - // Is internal or it doesn't contain a class - if (/\.mce/.test(v) || !/\.[\w\-]+$/.test(v)) - return; - - // Remove everything but class name - ov = v; - v = tinymce._replace(/.*\.([a-z0-9_\-]+).*/i, '$1', v); - - // Filter classes - if (f && !(v = f(v, ov))) - return; - - if (!lo[v]) { - cl.push({'class' : v}); - lo[v] = 1; - } - }); - } - break; - - // Import - case 3: - try { - addClasses(r.styleSheet); - } catch (ex) { - // Ignore - } - - break; - } - }); - }; - - try { - each(t.doc.styleSheets, addClasses); - } catch (ex) { - // Ignore - } - - if (cl.length > 0) - t.classes = cl; - - return cl; - }, - - run : function(e, f, s) { - var t = this, o; - - if (t.doc && typeof(e) === 'string') - e = t.get(e); - - if (!e) - return false; - - s = s || this; - if (!e.nodeType && (e.length || e.length === 0)) { - o = []; - - each(e, function(e, i) { - if (e) { - if (typeof(e) == 'string') - e = t.doc.getElementById(e); - - o.push(f.call(s, e, i)); - } - }); - - return o; - } - - return f.call(s, e); - }, - - getAttribs : function(n) { - var o; - - n = this.get(n); - - if (!n) - return []; - - if (isIE) { - o = []; - - // Object will throw exception in IE - if (n.nodeName == 'OBJECT') - return n.attributes; - - // IE doesn't keep the selected attribute if you clone option elements - if (n.nodeName === 'OPTION' && this.getAttrib(n, 'selected')) - o.push({specified : 1, nodeName : 'selected'}); - - // It's crazy that this is faster in IE but it's because it returns all attributes all the time - n.cloneNode(false).outerHTML.replace(/<\/?[\w:\-]+ ?|=[\"][^\"]+\"|=\'[^\']+\'|=[\w\-]+|>/gi, '').replace(/[\w:\-]+/gi, function(a) { - o.push({specified : 1, nodeName : a}); - }); - - return o; - } - - return n.attributes; - }, - - isEmpty : function(node, elements) { - var self = this, i, attributes, type, walker, name, brCount = 0; - - node = node.firstChild; - if (node) { - walker = new tinymce.dom.TreeWalker(node, node.parentNode); - elements = elements || self.schema ? self.schema.getNonEmptyElements() : null; - - do { - type = node.nodeType; - - if (type === 1) { - // Ignore bogus elements - if (node.getAttribute('data-mce-bogus')) - continue; - - // Keep empty elements like - name = node.nodeName.toLowerCase(); - if (elements && elements[name]) { - // Ignore single BR elements in blocks like


    or


    - if (name === 'br') { - brCount++; - continue; - } - - return false; - } - - // Keep elements with data-bookmark attributes or name attribute like
    - attributes = self.getAttribs(node); - i = node.attributes.length; - while (i--) { - name = node.attributes[i].nodeName; - if (name === "name" || name === 'data-mce-bookmark') - return false; - } - } - - // Keep comment nodes - if (type == 8) - return false; - - // Keep non whitespace text nodes - if ((type === 3 && !whiteSpaceRegExp.test(node.nodeValue))) - return false; - } while (node = walker.next()); - } - - return brCount <= 1; - }, - - destroy : function(s) { - var t = this; - - t.win = t.doc = t.root = t.events = t.frag = null; - - // Manual destroy then remove unload handler - if (!s) - tinymce.removeUnload(t.destroy); - }, - - createRng : function() { - var d = this.doc; - - return d.createRange ? d.createRange() : new tinymce.dom.Range(this); - }, - - nodeIndex : function(node, normalized) { - var idx = 0, lastNodeType, lastNode, nodeType; - - if (node) { - for (lastNodeType = node.nodeType, node = node.previousSibling, lastNode = node; node; node = node.previousSibling) { - nodeType = node.nodeType; - - // Normalize text nodes - if (normalized && nodeType == 3) { - if (nodeType == lastNodeType || !node.nodeValue.length) - continue; - } - idx++; - lastNodeType = nodeType; - } - } - - return idx; - }, - - split : function(pe, e, re) { - var t = this, r = t.createRng(), bef, aft, pa; - - // W3C valid browsers tend to leave empty nodes to the left/right side of the contents, this makes sense - // but we don't want that in our code since it serves no purpose for the end user - // For example if this is chopped: - //

    text 1CHOPtext 2

    - // would produce: - //

    text 1

    CHOP

    text 2

    - // this function will then trim of empty edges and produce: - //

    text 1

    CHOP

    text 2

    - function trim(node) { - var i, children = node.childNodes, type = node.nodeType; - - function surroundedBySpans(node) { - var previousIsSpan = node.previousSibling && node.previousSibling.nodeName == 'SPAN'; - var nextIsSpan = node.nextSibling && node.nextSibling.nodeName == 'SPAN'; - return previousIsSpan && nextIsSpan; - } - - if (type == 1 && node.getAttribute('data-mce-type') == 'bookmark') - return; - - for (i = children.length - 1; i >= 0; i--) - trim(children[i]); - - if (type != 9) { - // Keep non whitespace text nodes - if (type == 3 && node.nodeValue.length > 0) { - // If parent element isn't a block or there isn't any useful contents for example "

    " - // Also keep text nodes with only spaces if surrounded by spans. - // eg. "

    a b

    " should keep space between a and b - var trimmedLength = tinymce.trim(node.nodeValue).length; - if (!t.isBlock(node.parentNode) || trimmedLength > 0 || trimmedLength === 0 && surroundedBySpans(node)) - return; - } else if (type == 1) { - // If the only child is a bookmark then move it up - children = node.childNodes; - if (children.length == 1 && children[0] && children[0].nodeType == 1 && children[0].getAttribute('data-mce-type') == 'bookmark') - node.parentNode.insertBefore(children[0], node); - - // Keep non empty elements or img, hr etc - if (children.length || /^(br|hr|input|img)$/i.test(node.nodeName)) - return; - } - - t.remove(node); - } - - return node; - }; - - if (pe && e) { - // Get before chunk - r.setStart(pe.parentNode, t.nodeIndex(pe)); - r.setEnd(e.parentNode, t.nodeIndex(e)); - bef = r.extractContents(); - - // Get after chunk - r = t.createRng(); - r.setStart(e.parentNode, t.nodeIndex(e) + 1); - r.setEnd(pe.parentNode, t.nodeIndex(pe) + 1); - aft = r.extractContents(); - - // Insert before chunk - pa = pe.parentNode; - pa.insertBefore(trim(bef), pe); - - // Insert middle chunk - if (re) - pa.replaceChild(re, e); - else - pa.insertBefore(e, pe); - - // Insert after chunk - pa.insertBefore(trim(aft), pe); - t.remove(pe); - - return re || e; - } - }, - - bind : function(target, name, func, scope) { - return this.events.add(target, name, func, scope || this); - }, - - unbind : function(target, name, func) { - return this.events.remove(target, name, func); - }, - - fire : function(target, name, evt) { - return this.events.fire(target, name, evt); - }, - - // Returns the content editable state of a node - getContentEditable: function(node) { - var contentEditable; - - // Check type - if (node.nodeType != 1) { - return null; - } - - // Check for fake content editable - contentEditable = node.getAttribute("data-mce-contenteditable"); - if (contentEditable && contentEditable !== "inherit") { - return contentEditable; - } - - // Check for real content editable - return node.contentEditable !== "inherit" ? node.contentEditable : null; - }, - - - _findSib : function(node, selector, name) { - var t = this, f = selector; - - if (node) { - // If expression make a function of it using is - if (is(f, 'string')) { - f = function(node) { - return t.is(node, selector); - }; - } - - // Loop all siblings - for (node = node[name]; node; node = node[name]) { - if (f(node)) - return node; - } - } - - return null; - }, - - _isRes : function(c) { - // Is live resizble element - return /^(top|left|bottom|right|width|height)/i.test(c) || /;\s*(top|left|bottom|right|width|height)/i.test(c); - } - - /* - walk : function(n, f, s) { - var d = this.doc, w; - - if (d.createTreeWalker) { - w = d.createTreeWalker(n, NodeFilter.SHOW_TEXT, null, false); - - while ((n = w.nextNode()) != null) - f.call(s || this, n); - } else - tinymce.walk(n, f, 'childNodes', s); - } - */ - - /* - toRGB : function(s) { - var c = /^\s*?#([0-9A-F]{2})([0-9A-F]{1,2})([0-9A-F]{2})?\s*?$/.exec(s); - - if (c) { - // #FFF -> #FFFFFF - if (!is(c[3])) - c[3] = c[2] = c[1]; - - return "rgb(" + parseInt(c[1], 16) + "," + parseInt(c[2], 16) + "," + parseInt(c[3], 16) + ")"; - } - - return s; - } - */ - }); - - tinymce.DOM = new tinymce.dom.DOMUtils(document, {process_html : 0}); -})(tinymce); -(function(ns) { - // Range constructor - function Range(dom) { - var t = this, - doc = dom.doc, - EXTRACT = 0, - CLONE = 1, - DELETE = 2, - TRUE = true, - FALSE = false, - START_OFFSET = 'startOffset', - START_CONTAINER = 'startContainer', - END_CONTAINER = 'endContainer', - END_OFFSET = 'endOffset', - extend = tinymce.extend, - nodeIndex = dom.nodeIndex; - - extend(t, { - // Inital states - startContainer : doc, - startOffset : 0, - endContainer : doc, - endOffset : 0, - collapsed : TRUE, - commonAncestorContainer : doc, - - // Range constants - START_TO_START : 0, - START_TO_END : 1, - END_TO_END : 2, - END_TO_START : 3, - - // Public methods - setStart : setStart, - setEnd : setEnd, - setStartBefore : setStartBefore, - setStartAfter : setStartAfter, - setEndBefore : setEndBefore, - setEndAfter : setEndAfter, - collapse : collapse, - selectNode : selectNode, - selectNodeContents : selectNodeContents, - compareBoundaryPoints : compareBoundaryPoints, - deleteContents : deleteContents, - extractContents : extractContents, - cloneContents : cloneContents, - insertNode : insertNode, - surroundContents : surroundContents, - cloneRange : cloneRange, - toStringIE : toStringIE - }); - - function createDocumentFragment() { - return doc.createDocumentFragment(); - }; - - function setStart(n, o) { - _setEndPoint(TRUE, n, o); - }; - - function setEnd(n, o) { - _setEndPoint(FALSE, n, o); - }; - - function setStartBefore(n) { - setStart(n.parentNode, nodeIndex(n)); - }; - - function setStartAfter(n) { - setStart(n.parentNode, nodeIndex(n) + 1); - }; - - function setEndBefore(n) { - setEnd(n.parentNode, nodeIndex(n)); - }; - - function setEndAfter(n) { - setEnd(n.parentNode, nodeIndex(n) + 1); - }; - - function collapse(ts) { - if (ts) { - t[END_CONTAINER] = t[START_CONTAINER]; - t[END_OFFSET] = t[START_OFFSET]; - } else { - t[START_CONTAINER] = t[END_CONTAINER]; - t[START_OFFSET] = t[END_OFFSET]; - } - - t.collapsed = TRUE; - }; - - function selectNode(n) { - setStartBefore(n); - setEndAfter(n); - }; - - function selectNodeContents(n) { - setStart(n, 0); - setEnd(n, n.nodeType === 1 ? n.childNodes.length : n.nodeValue.length); - }; - - function compareBoundaryPoints(h, r) { - var sc = t[START_CONTAINER], so = t[START_OFFSET], ec = t[END_CONTAINER], eo = t[END_OFFSET], - rsc = r.startContainer, rso = r.startOffset, rec = r.endContainer, reo = r.endOffset; - - // Check START_TO_START - if (h === 0) - return _compareBoundaryPoints(sc, so, rsc, rso); - - // Check START_TO_END - if (h === 1) - return _compareBoundaryPoints(ec, eo, rsc, rso); - - // Check END_TO_END - if (h === 2) - return _compareBoundaryPoints(ec, eo, rec, reo); - - // Check END_TO_START - if (h === 3) - return _compareBoundaryPoints(sc, so, rec, reo); - }; - - function deleteContents() { - _traverse(DELETE); - }; - - function extractContents() { - return _traverse(EXTRACT); - }; - - function cloneContents() { - return _traverse(CLONE); - }; - - function insertNode(n) { - var startContainer = this[START_CONTAINER], - startOffset = this[START_OFFSET], nn, o; - - // Node is TEXT_NODE or CDATA - if ((startContainer.nodeType === 3 || startContainer.nodeType === 4) && startContainer.nodeValue) { - if (!startOffset) { - // At the start of text - startContainer.parentNode.insertBefore(n, startContainer); - } else if (startOffset >= startContainer.nodeValue.length) { - // At the end of text - dom.insertAfter(n, startContainer); - } else { - // Middle, need to split - nn = startContainer.splitText(startOffset); - startContainer.parentNode.insertBefore(n, nn); - } - } else { - // Insert element node - if (startContainer.childNodes.length > 0) - o = startContainer.childNodes[startOffset]; - - if (o) - startContainer.insertBefore(n, o); - else - startContainer.appendChild(n); - } - }; - - function surroundContents(n) { - var f = t.extractContents(); - - t.insertNode(n); - n.appendChild(f); - t.selectNode(n); - }; - - function cloneRange() { - return extend(new Range(dom), { - startContainer : t[START_CONTAINER], - startOffset : t[START_OFFSET], - endContainer : t[END_CONTAINER], - endOffset : t[END_OFFSET], - collapsed : t.collapsed, - commonAncestorContainer : t.commonAncestorContainer - }); - }; - - // Private methods - - function _getSelectedNode(container, offset) { - var child; - - if (container.nodeType == 3 /* TEXT_NODE */) - return container; - - if (offset < 0) - return container; - - child = container.firstChild; - while (child && offset > 0) { - --offset; - child = child.nextSibling; - } - - if (child) - return child; - - return container; - }; - - function _isCollapsed() { - return (t[START_CONTAINER] == t[END_CONTAINER] && t[START_OFFSET] == t[END_OFFSET]); - }; - - function _compareBoundaryPoints(containerA, offsetA, containerB, offsetB) { - var c, offsetC, n, cmnRoot, childA, childB; - - // In the first case the boundary-points have the same container. A is before B - // if its offset is less than the offset of B, A is equal to B if its offset is - // equal to the offset of B, and A is after B if its offset is greater than the - // offset of B. - if (containerA == containerB) { - if (offsetA == offsetB) - return 0; // equal - - if (offsetA < offsetB) - return -1; // before - - return 1; // after - } - - // In the second case a child node C of the container of A is an ancestor - // container of B. In this case, A is before B if the offset of A is less than or - // equal to the index of the child node C and A is after B otherwise. - c = containerB; - while (c && c.parentNode != containerA) - c = c.parentNode; - - if (c) { - offsetC = 0; - n = containerA.firstChild; - - while (n != c && offsetC < offsetA) { - offsetC++; - n = n.nextSibling; - } - - if (offsetA <= offsetC) - return -1; // before - - return 1; // after - } - - // In the third case a child node C of the container of B is an ancestor container - // of A. In this case, A is before B if the index of the child node C is less than - // the offset of B and A is after B otherwise. - c = containerA; - while (c && c.parentNode != containerB) { - c = c.parentNode; - } - - if (c) { - offsetC = 0; - n = containerB.firstChild; - - while (n != c && offsetC < offsetB) { - offsetC++; - n = n.nextSibling; - } - - if (offsetC < offsetB) - return -1; // before - - return 1; // after - } - - // In the fourth case, none of three other cases hold: the containers of A and B - // are siblings or descendants of sibling nodes. In this case, A is before B if - // the container of A is before the container of B in a pre-order traversal of the - // Ranges' context tree and A is after B otherwise. - cmnRoot = dom.findCommonAncestor(containerA, containerB); - childA = containerA; - - while (childA && childA.parentNode != cmnRoot) - childA = childA.parentNode; - - if (!childA) - childA = cmnRoot; - - childB = containerB; - while (childB && childB.parentNode != cmnRoot) - childB = childB.parentNode; - - if (!childB) - childB = cmnRoot; - - if (childA == childB) - return 0; // equal - - n = cmnRoot.firstChild; - while (n) { - if (n == childA) - return -1; // before - - if (n == childB) - return 1; // after - - n = n.nextSibling; - } - }; - - function _setEndPoint(st, n, o) { - var ec, sc; - - if (st) { - t[START_CONTAINER] = n; - t[START_OFFSET] = o; - } else { - t[END_CONTAINER] = n; - t[END_OFFSET] = o; - } - - // If one boundary-point of a Range is set to have a root container - // other than the current one for the Range, the Range is collapsed to - // the new position. This enforces the restriction that both boundary- - // points of a Range must have the same root container. - ec = t[END_CONTAINER]; - while (ec.parentNode) - ec = ec.parentNode; - - sc = t[START_CONTAINER]; - while (sc.parentNode) - sc = sc.parentNode; - - if (sc == ec) { - // The start position of a Range is guaranteed to never be after the - // end position. To enforce this restriction, if the start is set to - // be at a position after the end, the Range is collapsed to that - // position. - if (_compareBoundaryPoints(t[START_CONTAINER], t[START_OFFSET], t[END_CONTAINER], t[END_OFFSET]) > 0) - t.collapse(st); - } else - t.collapse(st); - - t.collapsed = _isCollapsed(); - t.commonAncestorContainer = dom.findCommonAncestor(t[START_CONTAINER], t[END_CONTAINER]); - }; - - function _traverse(how) { - var c, endContainerDepth = 0, startContainerDepth = 0, p, depthDiff, startNode, endNode, sp, ep; - - if (t[START_CONTAINER] == t[END_CONTAINER]) - return _traverseSameContainer(how); - - for (c = t[END_CONTAINER], p = c.parentNode; p; c = p, p = p.parentNode) { - if (p == t[START_CONTAINER]) - return _traverseCommonStartContainer(c, how); - - ++endContainerDepth; - } - - for (c = t[START_CONTAINER], p = c.parentNode; p; c = p, p = p.parentNode) { - if (p == t[END_CONTAINER]) - return _traverseCommonEndContainer(c, how); - - ++startContainerDepth; - } - - depthDiff = startContainerDepth - endContainerDepth; - - startNode = t[START_CONTAINER]; - while (depthDiff > 0) { - startNode = startNode.parentNode; - depthDiff--; - } - - endNode = t[END_CONTAINER]; - while (depthDiff < 0) { - endNode = endNode.parentNode; - depthDiff++; - } - - // ascend the ancestor hierarchy until we have a common parent. - for (sp = startNode.parentNode, ep = endNode.parentNode; sp != ep; sp = sp.parentNode, ep = ep.parentNode) { - startNode = sp; - endNode = ep; - } - - return _traverseCommonAncestors(startNode, endNode, how); - }; - - function _traverseSameContainer(how) { - var frag, s, sub, n, cnt, sibling, xferNode, start, len; - - if (how != DELETE) - frag = createDocumentFragment(); - - // If selection is empty, just return the fragment - if (t[START_OFFSET] == t[END_OFFSET]) - return frag; - - // Text node needs special case handling - if (t[START_CONTAINER].nodeType == 3 /* TEXT_NODE */) { - // get the substring - s = t[START_CONTAINER].nodeValue; - sub = s.substring(t[START_OFFSET], t[END_OFFSET]); - - // set the original text node to its new value - if (how != CLONE) { - n = t[START_CONTAINER]; - start = t[START_OFFSET]; - len = t[END_OFFSET] - t[START_OFFSET]; - - if (start === 0 && len >= n.nodeValue.length - 1) { - n.parentNode.removeChild(n); - } else { - n.deleteData(start, len); - } - - // Nothing is partially selected, so collapse to start point - t.collapse(TRUE); - } - - if (how == DELETE) - return; - - if (sub.length > 0) { - frag.appendChild(doc.createTextNode(sub)); - } - - return frag; - } - - // Copy nodes between the start/end offsets. - n = _getSelectedNode(t[START_CONTAINER], t[START_OFFSET]); - cnt = t[END_OFFSET] - t[START_OFFSET]; - - while (n && cnt > 0) { - sibling = n.nextSibling; - xferNode = _traverseFullySelected(n, how); - - if (frag) - frag.appendChild( xferNode ); - - --cnt; - n = sibling; - } - - // Nothing is partially selected, so collapse to start point - if (how != CLONE) - t.collapse(TRUE); - - return frag; - }; - - function _traverseCommonStartContainer(endAncestor, how) { - var frag, n, endIdx, cnt, sibling, xferNode; - - if (how != DELETE) - frag = createDocumentFragment(); - - n = _traverseRightBoundary(endAncestor, how); - - if (frag) - frag.appendChild(n); - - endIdx = nodeIndex(endAncestor); - cnt = endIdx - t[START_OFFSET]; - - if (cnt <= 0) { - // Collapse to just before the endAncestor, which - // is partially selected. - if (how != CLONE) { - t.setEndBefore(endAncestor); - t.collapse(FALSE); - } - - return frag; - } - - n = endAncestor.previousSibling; - while (cnt > 0) { - sibling = n.previousSibling; - xferNode = _traverseFullySelected(n, how); - - if (frag) - frag.insertBefore(xferNode, frag.firstChild); - - --cnt; - n = sibling; - } - - // Collapse to just before the endAncestor, which - // is partially selected. - if (how != CLONE) { - t.setEndBefore(endAncestor); - t.collapse(FALSE); - } - - return frag; - }; - - function _traverseCommonEndContainer(startAncestor, how) { - var frag, startIdx, n, cnt, sibling, xferNode; - - if (how != DELETE) - frag = createDocumentFragment(); - - n = _traverseLeftBoundary(startAncestor, how); - if (frag) - frag.appendChild(n); - - startIdx = nodeIndex(startAncestor); - ++startIdx; // Because we already traversed it - - cnt = t[END_OFFSET] - startIdx; - n = startAncestor.nextSibling; - while (n && cnt > 0) { - sibling = n.nextSibling; - xferNode = _traverseFullySelected(n, how); - - if (frag) - frag.appendChild(xferNode); - - --cnt; - n = sibling; - } - - if (how != CLONE) { - t.setStartAfter(startAncestor); - t.collapse(TRUE); - } - - return frag; - }; - - function _traverseCommonAncestors(startAncestor, endAncestor, how) { - var n, frag, commonParent, startOffset, endOffset, cnt, sibling, nextSibling; - - if (how != DELETE) - frag = createDocumentFragment(); - - n = _traverseLeftBoundary(startAncestor, how); - if (frag) - frag.appendChild(n); - - commonParent = startAncestor.parentNode; - startOffset = nodeIndex(startAncestor); - endOffset = nodeIndex(endAncestor); - ++startOffset; - - cnt = endOffset - startOffset; - sibling = startAncestor.nextSibling; - - while (cnt > 0) { - nextSibling = sibling.nextSibling; - n = _traverseFullySelected(sibling, how); - - if (frag) - frag.appendChild(n); - - sibling = nextSibling; - --cnt; - } - - n = _traverseRightBoundary(endAncestor, how); - - if (frag) - frag.appendChild(n); - - if (how != CLONE) { - t.setStartAfter(startAncestor); - t.collapse(TRUE); - } - - return frag; - }; - - function _traverseRightBoundary(root, how) { - var next = _getSelectedNode(t[END_CONTAINER], t[END_OFFSET] - 1), parent, clonedParent, prevSibling, clonedChild, clonedGrandParent, isFullySelected = next != t[END_CONTAINER]; - - if (next == root) - return _traverseNode(next, isFullySelected, FALSE, how); - - parent = next.parentNode; - clonedParent = _traverseNode(parent, FALSE, FALSE, how); - - while (parent) { - while (next) { - prevSibling = next.previousSibling; - clonedChild = _traverseNode(next, isFullySelected, FALSE, how); - - if (how != DELETE) - clonedParent.insertBefore(clonedChild, clonedParent.firstChild); - - isFullySelected = TRUE; - next = prevSibling; - } - - if (parent == root) - return clonedParent; - - next = parent.previousSibling; - parent = parent.parentNode; - - clonedGrandParent = _traverseNode(parent, FALSE, FALSE, how); - - if (how != DELETE) - clonedGrandParent.appendChild(clonedParent); - - clonedParent = clonedGrandParent; - } - }; - - function _traverseLeftBoundary(root, how) { - var next = _getSelectedNode(t[START_CONTAINER], t[START_OFFSET]), isFullySelected = next != t[START_CONTAINER], parent, clonedParent, nextSibling, clonedChild, clonedGrandParent; - - if (next == root) - return _traverseNode(next, isFullySelected, TRUE, how); - - parent = next.parentNode; - clonedParent = _traverseNode(parent, FALSE, TRUE, how); - - while (parent) { - while (next) { - nextSibling = next.nextSibling; - clonedChild = _traverseNode(next, isFullySelected, TRUE, how); - - if (how != DELETE) - clonedParent.appendChild(clonedChild); - - isFullySelected = TRUE; - next = nextSibling; - } - - if (parent == root) - return clonedParent; - - next = parent.nextSibling; - parent = parent.parentNode; - - clonedGrandParent = _traverseNode(parent, FALSE, TRUE, how); - - if (how != DELETE) - clonedGrandParent.appendChild(clonedParent); - - clonedParent = clonedGrandParent; - } - }; - - function _traverseNode(n, isFullySelected, isLeft, how) { - var txtValue, newNodeValue, oldNodeValue, offset, newNode; - - if (isFullySelected) - return _traverseFullySelected(n, how); - - if (n.nodeType == 3 /* TEXT_NODE */) { - txtValue = n.nodeValue; - - if (isLeft) { - offset = t[START_OFFSET]; - newNodeValue = txtValue.substring(offset); - oldNodeValue = txtValue.substring(0, offset); - } else { - offset = t[END_OFFSET]; - newNodeValue = txtValue.substring(0, offset); - oldNodeValue = txtValue.substring(offset); - } - - if (how != CLONE) - n.nodeValue = oldNodeValue; - - if (how == DELETE) - return; - - newNode = dom.clone(n, FALSE); - newNode.nodeValue = newNodeValue; - - return newNode; - } - - if (how == DELETE) - return; - - return dom.clone(n, FALSE); - }; - - function _traverseFullySelected(n, how) { - if (how != DELETE) - return how == CLONE ? dom.clone(n, TRUE) : n; - - n.parentNode.removeChild(n); - }; - - function toStringIE() { - return dom.create('body', null, cloneContents()).outerText; - } - - return t; - }; - - ns.Range = Range; - - // Older IE versions doesn't let you override toString by it's constructor so we have to stick it in the prototype - Range.prototype.toString = function() { - return this.toStringIE(); - }; -})(tinymce.dom); -(function() { - function Selection(selection) { - var self = this, dom = selection.dom, TRUE = true, FALSE = false; - - function getPosition(rng, start) { - var checkRng, startIndex = 0, endIndex, inside, - children, child, offset, index, position = -1, parent; - - // Setup test range, collapse it and get the parent - checkRng = rng.duplicate(); - checkRng.collapse(start); - parent = checkRng.parentElement(); - - // Check if the selection is within the right document - if (parent.ownerDocument !== selection.dom.doc) - return; - - // IE will report non editable elements as it's parent so look for an editable one - while (parent.contentEditable === "false") { - parent = parent.parentNode; - } - - // If parent doesn't have any children then return that we are inside the element - if (!parent.hasChildNodes()) { - return {node : parent, inside : 1}; - } - - // Setup node list and endIndex - children = parent.children; - endIndex = children.length - 1; - - // Perform a binary search for the position - while (startIndex <= endIndex) { - index = Math.floor((startIndex + endIndex) / 2); - - // Move selection to node and compare the ranges - child = children[index]; - checkRng.moveToElementText(child); - position = checkRng.compareEndPoints(start ? 'StartToStart' : 'EndToEnd', rng); - - // Before/after or an exact match - if (position > 0) { - endIndex = index - 1; - } else if (position < 0) { - startIndex = index + 1; - } else { - return {node : child}; - } - } - - // Check if child position is before or we didn't find a position - if (position < 0) { - // No element child was found use the parent element and the offset inside that - if (!child) { - checkRng.moveToElementText(parent); - checkRng.collapse(true); - child = parent; - inside = true; - } else - checkRng.collapse(false); - - // Walk character by character in text node until we hit the selected range endpoint, hit the end of document or parent isn't the right one - // We need to walk char by char since rng.text or rng.htmlText will trim line endings - offset = 0; - while (checkRng.compareEndPoints(start ? 'StartToStart' : 'StartToEnd', rng) !== 0) { - if (checkRng.move('character', 1) === 0 || parent != checkRng.parentElement()) { - break; - } - - offset++; - } - } else { - // Child position is after the selection endpoint - checkRng.collapse(true); - - // Walk character by character in text node until we hit the selected range endpoint, hit the end of document or parent isn't the right one - offset = 0; - while (checkRng.compareEndPoints(start ? 'StartToStart' : 'StartToEnd', rng) !== 0) { - if (checkRng.move('character', -1) === 0 || parent != checkRng.parentElement()) { - break; - } - - offset++; - } - } - - return {node : child, position : position, offset : offset, inside : inside}; - }; - - // Returns a W3C DOM compatible range object by using the IE Range API - function getRange() { - var ieRange = selection.getRng(), domRange = dom.createRng(), element, collapsed, tmpRange, element2, bookmark, fail; - - // If selection is outside the current document just return an empty range - element = ieRange.item ? ieRange.item(0) : ieRange.parentElement(); - if (element.ownerDocument != dom.doc) - return domRange; - - collapsed = selection.isCollapsed(); - - // Handle control selection - if (ieRange.item) { - domRange.setStart(element.parentNode, dom.nodeIndex(element)); - domRange.setEnd(domRange.startContainer, domRange.startOffset + 1); - - return domRange; - } - - function findEndPoint(start) { - var endPoint = getPosition(ieRange, start), container, offset, textNodeOffset = 0, sibling, undef, nodeValue; - - container = endPoint.node; - offset = endPoint.offset; - - if (endPoint.inside && !container.hasChildNodes()) { - domRange[start ? 'setStart' : 'setEnd'](container, 0); - return; - } - - if (offset === undef) { - domRange[start ? 'setStartBefore' : 'setEndAfter'](container); - return; - } - - if (endPoint.position < 0) { - sibling = endPoint.inside ? container.firstChild : container.nextSibling; - - if (!sibling) { - domRange[start ? 'setStartAfter' : 'setEndAfter'](container); - return; - } - - if (!offset) { - if (sibling.nodeType == 3) - domRange[start ? 'setStart' : 'setEnd'](sibling, 0); - else - domRange[start ? 'setStartBefore' : 'setEndBefore'](sibling); - - return; - } - - // Find the text node and offset - while (sibling) { - nodeValue = sibling.nodeValue; - textNodeOffset += nodeValue.length; - - // We are at or passed the position we where looking for - if (textNodeOffset >= offset) { - container = sibling; - textNodeOffset -= offset; - textNodeOffset = nodeValue.length - textNodeOffset; - break; - } - - sibling = sibling.nextSibling; - } - } else { - // Find the text node and offset - sibling = container.previousSibling; - - if (!sibling) - return domRange[start ? 'setStartBefore' : 'setEndBefore'](container); - - // If there isn't any text to loop then use the first position - if (!offset) { - if (container.nodeType == 3) - domRange[start ? 'setStart' : 'setEnd'](sibling, container.nodeValue.length); - else - domRange[start ? 'setStartAfter' : 'setEndAfter'](sibling); - - return; - } - - while (sibling) { - textNodeOffset += sibling.nodeValue.length; - - // We are at or passed the position we where looking for - if (textNodeOffset >= offset) { - container = sibling; - textNodeOffset -= offset; - break; - } - - sibling = sibling.previousSibling; - } - } - - domRange[start ? 'setStart' : 'setEnd'](container, textNodeOffset); - }; - - try { - // Find start point - findEndPoint(true); - - // Find end point if needed - if (!collapsed) - findEndPoint(); - } catch (ex) { - // IE has a nasty bug where text nodes might throw "invalid argument" when you - // access the nodeValue or other properties of text nodes. This seems to happend when - // text nodes are split into two nodes by a delete/backspace call. So lets detect it and try to fix it. - if (ex.number == -2147024809) { - // Get the current selection - bookmark = self.getBookmark(2); - - // Get start element - tmpRange = ieRange.duplicate(); - tmpRange.collapse(true); - element = tmpRange.parentElement(); - - // Get end element - if (!collapsed) { - tmpRange = ieRange.duplicate(); - tmpRange.collapse(false); - element2 = tmpRange.parentElement(); - element2.innerHTML = element2.innerHTML; - } - - // Remove the broken elements - element.innerHTML = element.innerHTML; - - // Restore the selection - self.moveToBookmark(bookmark); - - // Since the range has moved we need to re-get it - ieRange = selection.getRng(); - - // Find start point - findEndPoint(true); - - // Find end point if needed - if (!collapsed) - findEndPoint(); - } else - throw ex; // Throw other errors - } - - return domRange; - }; - - this.getBookmark = function(type) { - var rng = selection.getRng(), start, end, bookmark = {}; - - function getIndexes(node) { - var parent, root, children, i, indexes = []; - - parent = node.parentNode; - root = dom.getRoot().parentNode; - - while (parent != root && parent.nodeType !== 9) { - children = parent.children; - - i = children.length; - while (i--) { - if (node === children[i]) { - indexes.push(i); - break; - } - } - - node = parent; - parent = parent.parentNode; - } - - return indexes; - }; - - function getBookmarkEndPoint(start) { - var position; - - position = getPosition(rng, start); - if (position) { - return { - position : position.position, - offset : position.offset, - indexes : getIndexes(position.node), - inside : position.inside - }; - } - }; - - // Non ubstructive bookmark - if (type === 2) { - // Handle text selection - if (!rng.item) { - bookmark.start = getBookmarkEndPoint(true); - - if (!selection.isCollapsed()) - bookmark.end = getBookmarkEndPoint(); - } else - bookmark.start = {ctrl : true, indexes : getIndexes(rng.item(0))}; - } - - return bookmark; - }; - - this.moveToBookmark = function(bookmark) { - var rng, body = dom.doc.body; - - function resolveIndexes(indexes) { - var node, i, idx, children; - - node = dom.getRoot(); - for (i = indexes.length - 1; i >= 0; i--) { - children = node.children; - idx = indexes[i]; - - if (idx <= children.length - 1) { - node = children[idx]; - } - } - - return node; - }; - - function setBookmarkEndPoint(start) { - var endPoint = bookmark[start ? 'start' : 'end'], moveLeft, moveRng, undef; - - if (endPoint) { - moveLeft = endPoint.position > 0; - - moveRng = body.createTextRange(); - moveRng.moveToElementText(resolveIndexes(endPoint.indexes)); - - offset = endPoint.offset; - if (offset !== undef) { - moveRng.collapse(endPoint.inside || moveLeft); - moveRng.moveStart('character', moveLeft ? -offset : offset); - } else - moveRng.collapse(start); - - rng.setEndPoint(start ? 'StartToStart' : 'EndToStart', moveRng); - - if (start) - rng.collapse(true); - } - }; - - if (bookmark.start) { - if (bookmark.start.ctrl) { - rng = body.createControlRange(); - rng.addElement(resolveIndexes(bookmark.start.indexes)); - rng.select(); - } else { - rng = body.createTextRange(); - setBookmarkEndPoint(true); - setBookmarkEndPoint(); - rng.select(); - } - } - }; - - this.addRange = function(rng) { - var ieRng, ctrlRng, startContainer, startOffset, endContainer, endOffset, sibling, - doc = selection.dom.doc, body = doc.body, nativeRng, ctrlElm; - - function setEndPoint(start) { - var container, offset, marker, tmpRng, nodes; - - marker = dom.create('a'); - container = start ? startContainer : endContainer; - offset = start ? startOffset : endOffset; - tmpRng = ieRng.duplicate(); - - if (container == doc || container == doc.documentElement) { - container = body; - offset = 0; - } - - if (container.nodeType == 3) { - container.parentNode.insertBefore(marker, container); - tmpRng.moveToElementText(marker); - tmpRng.moveStart('character', offset); - dom.remove(marker); - ieRng.setEndPoint(start ? 'StartToStart' : 'EndToEnd', tmpRng); - } else { - nodes = container.childNodes; - - if (nodes.length) { - if (offset >= nodes.length) { - dom.insertAfter(marker, nodes[nodes.length - 1]); - } else { - container.insertBefore(marker, nodes[offset]); - } - - tmpRng.moveToElementText(marker); - } else if (container.canHaveHTML) { - // Empty node selection for example
    |
    - // Setting innerHTML with a span marker then remove that marker seems to keep empty block elements open - container.innerHTML = '\uFEFF'; - marker = container.firstChild; - tmpRng.moveToElementText(marker); - tmpRng.collapse(FALSE); // Collapse false works better than true for some odd reason - } - - ieRng.setEndPoint(start ? 'StartToStart' : 'EndToEnd', tmpRng); - dom.remove(marker); - } - } - - // Setup some shorter versions - startContainer = rng.startContainer; - startOffset = rng.startOffset; - endContainer = rng.endContainer; - endOffset = rng.endOffset; - ieRng = body.createTextRange(); - - // If single element selection then try making a control selection out of it - if (startContainer == endContainer && startContainer.nodeType == 1) { - // Trick to place the caret inside an empty block element like

    - if (startOffset == endOffset && !startContainer.hasChildNodes()) { - if (startContainer.canHaveHTML) { - // Check if previous sibling is an empty block if it is then we need to render it - // IE would otherwise move the caret into the sibling instead of the empty startContainer see: #5236 - // Example this:

    |

    would become this:

    |

    - sibling = startContainer.previousSibling; - if (sibling && !sibling.hasChildNodes() && dom.isBlock(sibling)) { - sibling.innerHTML = '\uFEFF'; - } else { - sibling = null; - } - - startContainer.innerHTML = '\uFEFF\uFEFF'; - ieRng.moveToElementText(startContainer.lastChild); - ieRng.select(); - dom.doc.selection.clear(); - startContainer.innerHTML = ''; - - if (sibling) { - sibling.innerHTML = ''; - } - return; - } else { - startOffset = dom.nodeIndex(startContainer); - startContainer = startContainer.parentNode; - } - } - - if (startOffset == endOffset - 1) { - try { - ctrlElm = startContainer.childNodes[startOffset]; - ctrlRng = body.createControlRange(); - ctrlRng.addElement(ctrlElm); - ctrlRng.select(); - - // Check if the range produced is on the correct element and is a control range - // On IE 8 it will select the parent contentEditable container if you select an inner element see: #5398 - nativeRng = selection.getRng(); - if (nativeRng.item && ctrlElm === nativeRng.item(0)) { - return; - } - } catch (ex) { - // Ignore - } - } - } - - // Set start/end point of selection - setEndPoint(true); - setEndPoint(); - - // Select the new range and scroll it into view - ieRng.select(); - }; - - // Expose range method - this.getRangeAt = getRange; - }; - - // Expose the selection object - tinymce.dom.TridentSelection = Selection; -})(); - -/* - * Sizzle CSS Selector Engine - * Copyright, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * More information: http://sizzlejs.com/ - */ -(function(){ - -var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, - expando = "sizcache", - done = 0, - toString = Object.prototype.toString, - hasDuplicate = false, - baseHasDuplicate = true, - rBackslash = /\\/g, - rReturn = /\r\n/g, - rNonWord = /\W/; - -// Here we check if the JavaScript engine is using some sort of -// optimization where it does not always call our comparision -// function. If that is the case, discard the hasDuplicate value. -// Thus far that includes Google Chrome. -[0, 0].sort(function() { - baseHasDuplicate = false; - return 0; -}); - -var Sizzle = function( selector, context, results, seed ) { - results = results || []; - context = context || document; - - var origContext = context; - - if ( context.nodeType !== 1 && context.nodeType !== 9 ) { - return []; - } - - if ( !selector || typeof selector !== "string" ) { - return results; - } - - var m, set, checkSet, extra, ret, cur, pop, i, - prune = true, - contextXML = Sizzle.isXML( context ), - parts = [], - soFar = selector; - - // Reset the position of the chunker regexp (start from head) - do { - chunker.exec( "" ); - m = chunker.exec( soFar ); - - if ( m ) { - soFar = m[3]; - - parts.push( m[1] ); - - if ( m[2] ) { - extra = m[3]; - break; - } - } - } while ( m ); - - if ( parts.length > 1 && origPOS.exec( selector ) ) { - - if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { - set = posProcess( parts[0] + parts[1], context, seed ); - - } else { - set = Expr.relative[ parts[0] ] ? - [ context ] : - Sizzle( parts.shift(), context ); - - while ( parts.length ) { - selector = parts.shift(); - - if ( Expr.relative[ selector ] ) { - selector += parts.shift(); - } - - set = posProcess( selector, set, seed ); - } - } - - } else { - // Take a shortcut and set the context if the root selector is an ID - // (but not if it'll be faster if the inner selector is an ID) - if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && - Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { - - ret = Sizzle.find( parts.shift(), context, contextXML ); - context = ret.expr ? - Sizzle.filter( ret.expr, ret.set )[0] : - ret.set[0]; - } - - if ( context ) { - ret = seed ? - { expr: parts.pop(), set: makeArray(seed) } : - Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); - - set = ret.expr ? - Sizzle.filter( ret.expr, ret.set ) : - ret.set; - - if ( parts.length > 0 ) { - checkSet = makeArray( set ); - - } else { - prune = false; - } - - while ( parts.length ) { - cur = parts.pop(); - pop = cur; - - if ( !Expr.relative[ cur ] ) { - cur = ""; - } else { - pop = parts.pop(); - } - - if ( pop == null ) { - pop = context; - } - - Expr.relative[ cur ]( checkSet, pop, contextXML ); - } - - } else { - checkSet = parts = []; - } - } - - if ( !checkSet ) { - checkSet = set; - } - - if ( !checkSet ) { - Sizzle.error( cur || selector ); - } - - if ( toString.call(checkSet) === "[object Array]" ) { - if ( !prune ) { - results.push.apply( results, checkSet ); - - } else if ( context && context.nodeType === 1 ) { - for ( i = 0; checkSet[i] != null; i++ ) { - if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) { - results.push( set[i] ); - } - } - - } else { - for ( i = 0; checkSet[i] != null; i++ ) { - if ( checkSet[i] && checkSet[i].nodeType === 1 ) { - results.push( set[i] ); - } - } - } - - } else { - makeArray( checkSet, results ); - } - - if ( extra ) { - Sizzle( extra, origContext, results, seed ); - Sizzle.uniqueSort( results ); - } - - return results; -}; - -Sizzle.uniqueSort = function( results ) { - if ( sortOrder ) { - hasDuplicate = baseHasDuplicate; - results.sort( sortOrder ); - - if ( hasDuplicate ) { - for ( var i = 1; i < results.length; i++ ) { - if ( results[i] === results[ i - 1 ] ) { - results.splice( i--, 1 ); - } - } - } - } - - return results; -}; - -Sizzle.matches = function( expr, set ) { - return Sizzle( expr, null, null, set ); -}; - -Sizzle.matchesSelector = function( node, expr ) { - return Sizzle( expr, null, null, [node] ).length > 0; -}; - -Sizzle.find = function( expr, context, isXML ) { - var set, i, len, match, type, left; - - if ( !expr ) { - return []; - } - - for ( i = 0, len = Expr.order.length; i < len; i++ ) { - type = Expr.order[i]; - - if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { - left = match[1]; - match.splice( 1, 1 ); - - if ( left.substr( left.length - 1 ) !== "\\" ) { - match[1] = (match[1] || "").replace( rBackslash, "" ); - set = Expr.find[ type ]( match, context, isXML ); - - if ( set != null ) { - expr = expr.replace( Expr.match[ type ], "" ); - break; - } - } - } - } - - if ( !set ) { - set = typeof context.getElementsByTagName !== "undefined" ? - context.getElementsByTagName( "*" ) : - []; - } - - return { set: set, expr: expr }; -}; - -Sizzle.filter = function( expr, set, inplace, not ) { - var match, anyFound, - type, found, item, filter, left, - i, pass, - old = expr, - result = [], - curLoop = set, - isXMLFilter = set && set[0] && Sizzle.isXML( set[0] ); - - while ( expr && set.length ) { - for ( type in Expr.filter ) { - if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { - filter = Expr.filter[ type ]; - left = match[1]; - - anyFound = false; - - match.splice(1,1); - - if ( left.substr( left.length - 1 ) === "\\" ) { - continue; - } - - if ( curLoop === result ) { - result = []; - } - - if ( Expr.preFilter[ type ] ) { - match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); - - if ( !match ) { - anyFound = found = true; - - } else if ( match === true ) { - continue; - } - } - - if ( match ) { - for ( i = 0; (item = curLoop[i]) != null; i++ ) { - if ( item ) { - found = filter( item, match, i, curLoop ); - pass = not ^ found; - - if ( inplace && found != null ) { - if ( pass ) { - anyFound = true; - - } else { - curLoop[i] = false; - } - - } else if ( pass ) { - result.push( item ); - anyFound = true; - } - } - } - } - - if ( found !== undefined ) { - if ( !inplace ) { - curLoop = result; - } - - expr = expr.replace( Expr.match[ type ], "" ); - - if ( !anyFound ) { - return []; - } - - break; - } - } - } - - // Improper expression - if ( expr === old ) { - if ( anyFound == null ) { - Sizzle.error( expr ); - - } else { - break; - } - } - - old = expr; - } - - return curLoop; -}; - -Sizzle.error = function( msg ) { - throw new Error( "Syntax error, unrecognized expression: " + msg ); -}; - -var getText = Sizzle.getText = function( elem ) { - var i, node, - nodeType = elem.nodeType, - ret = ""; - - if ( nodeType ) { - if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { - // Use textContent || innerText for elements - if ( typeof elem.textContent === 'string' ) { - return elem.textContent; - } else if ( typeof elem.innerText === 'string' ) { - // Replace IE's carriage returns - return elem.innerText.replace( rReturn, '' ); - } else { - // Traverse it's children - for ( elem = elem.firstChild; elem; elem = elem.nextSibling) { - ret += getText( elem ); - } - } - } else if ( nodeType === 3 || nodeType === 4 ) { - return elem.nodeValue; - } - } else { - - // If no nodeType, this is expected to be an array - for ( i = 0; (node = elem[i]); i++ ) { - // Do not traverse comment nodes - if ( node.nodeType !== 8 ) { - ret += getText( node ); - } - } - } - return ret; -}; - -var Expr = Sizzle.selectors = { - order: [ "ID", "NAME", "TAG" ], - - match: { - ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, - CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, - NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/, - ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/, - TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/, - CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/, - POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/, - PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/ - }, - - leftMatch: {}, - - attrMap: { - "class": "className", - "for": "htmlFor" - }, - - attrHandle: { - href: function( elem ) { - return elem.getAttribute( "href" ); - }, - type: function( elem ) { - return elem.getAttribute( "type" ); - } - }, - - relative: { - "+": function(checkSet, part){ - var isPartStr = typeof part === "string", - isTag = isPartStr && !rNonWord.test( part ), - isPartStrNotTag = isPartStr && !isTag; - - if ( isTag ) { - part = part.toLowerCase(); - } - - for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { - if ( (elem = checkSet[i]) ) { - while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} - - checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? - elem || false : - elem === part; - } - } - - if ( isPartStrNotTag ) { - Sizzle.filter( part, checkSet, true ); - } - }, - - ">": function( checkSet, part ) { - var elem, - isPartStr = typeof part === "string", - i = 0, - l = checkSet.length; - - if ( isPartStr && !rNonWord.test( part ) ) { - part = part.toLowerCase(); - - for ( ; i < l; i++ ) { - elem = checkSet[i]; - - if ( elem ) { - var parent = elem.parentNode; - checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; - } - } - - } else { - for ( ; i < l; i++ ) { - elem = checkSet[i]; - - if ( elem ) { - checkSet[i] = isPartStr ? - elem.parentNode : - elem.parentNode === part; - } - } - - if ( isPartStr ) { - Sizzle.filter( part, checkSet, true ); - } - } - }, - - "": function(checkSet, part, isXML){ - var nodeCheck, - doneName = done++, - checkFn = dirCheck; - - if ( typeof part === "string" && !rNonWord.test( part ) ) { - part = part.toLowerCase(); - nodeCheck = part; - checkFn = dirNodeCheck; - } - - checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML ); - }, - - "~": function( checkSet, part, isXML ) { - var nodeCheck, - doneName = done++, - checkFn = dirCheck; - - if ( typeof part === "string" && !rNonWord.test( part ) ) { - part = part.toLowerCase(); - nodeCheck = part; - checkFn = dirNodeCheck; - } - - checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML ); - } - }, - - find: { - ID: function( match, context, isXML ) { - if ( typeof context.getElementById !== "undefined" && !isXML ) { - var m = context.getElementById(match[1]); - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - return m && m.parentNode ? [m] : []; - } - }, - - NAME: function( match, context ) { - if ( typeof context.getElementsByName !== "undefined" ) { - var ret = [], - results = context.getElementsByName( match[1] ); - - for ( var i = 0, l = results.length; i < l; i++ ) { - if ( results[i].getAttribute("name") === match[1] ) { - ret.push( results[i] ); - } - } - - return ret.length === 0 ? null : ret; - } - }, - - TAG: function( match, context ) { - if ( typeof context.getElementsByTagName !== "undefined" ) { - return context.getElementsByTagName( match[1] ); - } - } - }, - preFilter: { - CLASS: function( match, curLoop, inplace, result, not, isXML ) { - match = " " + match[1].replace( rBackslash, "" ) + " "; - - if ( isXML ) { - return match; - } - - for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { - if ( elem ) { - if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) { - if ( !inplace ) { - result.push( elem ); - } - - } else if ( inplace ) { - curLoop[i] = false; - } - } - } - - return false; - }, - - ID: function( match ) { - return match[1].replace( rBackslash, "" ); - }, - - TAG: function( match, curLoop ) { - return match[1].replace( rBackslash, "" ).toLowerCase(); - }, - - CHILD: function( match ) { - if ( match[1] === "nth" ) { - if ( !match[2] ) { - Sizzle.error( match[0] ); - } - - match[2] = match[2].replace(/^\+|\s*/g, ''); - - // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' - var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec( - match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || - !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); - - // calculate the numbers (first)n+(last) including if they are negative - match[2] = (test[1] + (test[2] || 1)) - 0; - match[3] = test[3] - 0; - } - else if ( match[2] ) { - Sizzle.error( match[0] ); - } - - // TODO: Move to normal caching system - match[0] = done++; - - return match; - }, - - ATTR: function( match, curLoop, inplace, result, not, isXML ) { - var name = match[1] = match[1].replace( rBackslash, "" ); - - if ( !isXML && Expr.attrMap[name] ) { - match[1] = Expr.attrMap[name]; - } - - // Handle if an un-quoted value was used - match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" ); - - if ( match[2] === "~=" ) { - match[4] = " " + match[4] + " "; - } - - return match; - }, - - PSEUDO: function( match, curLoop, inplace, result, not ) { - if ( match[1] === "not" ) { - // If we're dealing with a complex expression, or a simple one - if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { - match[3] = Sizzle(match[3], null, null, curLoop); - - } else { - var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); - - if ( !inplace ) { - result.push.apply( result, ret ); - } - - return false; - } - - } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { - return true; - } - - return match; - }, - - POS: function( match ) { - match.unshift( true ); - - return match; - } - }, - - filters: { - enabled: function( elem ) { - return elem.disabled === false && elem.type !== "hidden"; - }, - - disabled: function( elem ) { - return elem.disabled === true; - }, - - checked: function( elem ) { - return elem.checked === true; - }, - - selected: function( elem ) { - // Accessing this property makes selected-by-default - // options in Safari work properly - if ( elem.parentNode ) { - elem.parentNode.selectedIndex; - } - - return elem.selected === true; - }, - - parent: function( elem ) { - return !!elem.firstChild; - }, - - empty: function( elem ) { - return !elem.firstChild; - }, - - has: function( elem, i, match ) { - return !!Sizzle( match[3], elem ).length; - }, - - header: function( elem ) { - return (/h\d/i).test( elem.nodeName ); - }, - - text: function( elem ) { - var attr = elem.getAttribute( "type" ), type = elem.type; - // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) - // use getAttribute instead to test this case - return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null ); - }, - - radio: function( elem ) { - return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type; - }, - - checkbox: function( elem ) { - return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type; - }, - - file: function( elem ) { - return elem.nodeName.toLowerCase() === "input" && "file" === elem.type; - }, - - password: function( elem ) { - return elem.nodeName.toLowerCase() === "input" && "password" === elem.type; - }, - - submit: function( elem ) { - var name = elem.nodeName.toLowerCase(); - return (name === "input" || name === "button") && "submit" === elem.type; - }, - - image: function( elem ) { - return elem.nodeName.toLowerCase() === "input" && "image" === elem.type; - }, - - reset: function( elem ) { - var name = elem.nodeName.toLowerCase(); - return (name === "input" || name === "button") && "reset" === elem.type; - }, - - button: function( elem ) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && "button" === elem.type || name === "button"; - }, - - input: function( elem ) { - return (/input|select|textarea|button/i).test( elem.nodeName ); - }, - - focus: function( elem ) { - return elem === elem.ownerDocument.activeElement; - } - }, - setFilters: { - first: function( elem, i ) { - return i === 0; - }, - - last: function( elem, i, match, array ) { - return i === array.length - 1; - }, - - even: function( elem, i ) { - return i % 2 === 0; - }, - - odd: function( elem, i ) { - return i % 2 === 1; - }, - - lt: function( elem, i, match ) { - return i < match[3] - 0; - }, - - gt: function( elem, i, match ) { - return i > match[3] - 0; - }, - - nth: function( elem, i, match ) { - return match[3] - 0 === i; - }, - - eq: function( elem, i, match ) { - return match[3] - 0 === i; - } - }, - filter: { - PSEUDO: function( elem, match, i, array ) { - var name = match[1], - filter = Expr.filters[ name ]; - - if ( filter ) { - return filter( elem, i, match, array ); - - } else if ( name === "contains" ) { - return (elem.textContent || elem.innerText || getText([ elem ]) || "").indexOf(match[3]) >= 0; - - } else if ( name === "not" ) { - var not = match[3]; - - for ( var j = 0, l = not.length; j < l; j++ ) { - if ( not[j] === elem ) { - return false; - } - } - - return true; - - } else { - Sizzle.error( name ); - } - }, - - CHILD: function( elem, match ) { - var first, last, - doneName, parent, cache, - count, diff, - type = match[1], - node = elem; - - switch ( type ) { - case "only": - case "first": - while ( (node = node.previousSibling) ) { - if ( node.nodeType === 1 ) { - return false; - } - } - - if ( type === "first" ) { - return true; - } - - node = elem; - - /* falls through */ - case "last": - while ( (node = node.nextSibling) ) { - if ( node.nodeType === 1 ) { - return false; - } - } - - return true; - - case "nth": - first = match[2]; - last = match[3]; - - if ( first === 1 && last === 0 ) { - return true; - } - - doneName = match[0]; - parent = elem.parentNode; - - if ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) { - count = 0; - - for ( node = parent.firstChild; node; node = node.nextSibling ) { - if ( node.nodeType === 1 ) { - node.nodeIndex = ++count; - } - } - - parent[ expando ] = doneName; - } - - diff = elem.nodeIndex - last; - - if ( first === 0 ) { - return diff === 0; - - } else { - return ( diff % first === 0 && diff / first >= 0 ); - } - } - }, - - ID: function( elem, match ) { - return elem.nodeType === 1 && elem.getAttribute("id") === match; - }, - - TAG: function( elem, match ) { - return (match === "*" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match; - }, - - CLASS: function( elem, match ) { - return (" " + (elem.className || elem.getAttribute("class")) + " ") - .indexOf( match ) > -1; - }, - - ATTR: function( elem, match ) { - var name = match[1], - result = Sizzle.attr ? - Sizzle.attr( elem, name ) : - Expr.attrHandle[ name ] ? - Expr.attrHandle[ name ]( elem ) : - elem[ name ] != null ? - elem[ name ] : - elem.getAttribute( name ), - value = result + "", - type = match[2], - check = match[4]; - - return result == null ? - type === "!=" : - !type && Sizzle.attr ? - result != null : - type === "=" ? - value === check : - type === "*=" ? - value.indexOf(check) >= 0 : - type === "~=" ? - (" " + value + " ").indexOf(check) >= 0 : - !check ? - value && result !== false : - type === "!=" ? - value !== check : - type === "^=" ? - value.indexOf(check) === 0 : - type === "$=" ? - value.substr(value.length - check.length) === check : - type === "|=" ? - value === check || value.substr(0, check.length + 1) === check + "-" : - false; - }, - - POS: function( elem, match, i, array ) { - var name = match[2], - filter = Expr.setFilters[ name ]; - - if ( filter ) { - return filter( elem, i, match, array ); - } - } - } -}; - -var origPOS = Expr.match.POS, - fescape = function(all, num){ - return "\\" + (num - 0 + 1); - }; - -for ( var type in Expr.match ) { - Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) ); - Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) ); -} -// Expose origPOS -// "global" as in regardless of relation to brackets/parens -Expr.match.globalPOS = origPOS; - -var makeArray = function( array, results ) { - array = Array.prototype.slice.call( array, 0 ); - - if ( results ) { - results.push.apply( results, array ); - return results; - } - - return array; -}; - -// Perform a simple check to determine if the browser is capable of -// converting a NodeList to an array using builtin methods. -// Also verifies that the returned array holds DOM nodes -// (which is not the case in the Blackberry browser) -try { - Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; - -// Provide a fallback method if it does not work -} catch( e ) { - makeArray = function( array, results ) { - var i = 0, - ret = results || []; - - if ( toString.call(array) === "[object Array]" ) { - Array.prototype.push.apply( ret, array ); - - } else { - if ( typeof array.length === "number" ) { - for ( var l = array.length; i < l; i++ ) { - ret.push( array[i] ); - } - - } else { - for ( ; array[i]; i++ ) { - ret.push( array[i] ); - } - } - } - - return ret; - }; -} - -var sortOrder, siblingCheck; - -if ( document.documentElement.compareDocumentPosition ) { - sortOrder = function( a, b ) { - if ( a === b ) { - hasDuplicate = true; - return 0; - } - - if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { - return a.compareDocumentPosition ? -1 : 1; - } - - return a.compareDocumentPosition(b) & 4 ? -1 : 1; - }; - -} else { - sortOrder = function( a, b ) { - // The nodes are identical, we can exit early - if ( a === b ) { - hasDuplicate = true; - return 0; - - // Fallback to using sourceIndex (in IE) if it's available on both nodes - } else if ( a.sourceIndex && b.sourceIndex ) { - return a.sourceIndex - b.sourceIndex; - } - - var al, bl, - ap = [], - bp = [], - aup = a.parentNode, - bup = b.parentNode, - cur = aup; - - // If the nodes are siblings (or identical) we can do a quick check - if ( aup === bup ) { - return siblingCheck( a, b ); - - // If no parents were found then the nodes are disconnected - } else if ( !aup ) { - return -1; - - } else if ( !bup ) { - return 1; - } - - // Otherwise they're somewhere else in the tree so we need - // to build up a full list of the parentNodes for comparison - while ( cur ) { - ap.unshift( cur ); - cur = cur.parentNode; - } - - cur = bup; - - while ( cur ) { - bp.unshift( cur ); - cur = cur.parentNode; - } - - al = ap.length; - bl = bp.length; - - // Start walking down the tree looking for a discrepancy - for ( var i = 0; i < al && i < bl; i++ ) { - if ( ap[i] !== bp[i] ) { - return siblingCheck( ap[i], bp[i] ); - } - } - - // We ended someplace up the tree so do a sibling check - return i === al ? - siblingCheck( a, bp[i], -1 ) : - siblingCheck( ap[i], b, 1 ); - }; - - siblingCheck = function( a, b, ret ) { - if ( a === b ) { - return ret; - } - - var cur = a.nextSibling; - - while ( cur ) { - if ( cur === b ) { - return -1; - } - - cur = cur.nextSibling; - } - - return 1; - }; -} - -// Check to see if the browser returns elements by name when -// querying by getElementById (and provide a workaround) -(function(){ - // We're going to inject a fake input element with a specified name - var form = document.createElement("div"), - id = "script" + (new Date()).getTime(), - root = document.documentElement; - - form.innerHTML = ""; - - // Inject it into the root element, check its status, and remove it quickly - root.insertBefore( form, root.firstChild ); - - // The workaround has to do additional checks after a getElementById - // Which slows things down for other browsers (hence the branching) - if ( document.getElementById( id ) ) { - Expr.find.ID = function( match, context, isXML ) { - if ( typeof context.getElementById !== "undefined" && !isXML ) { - var m = context.getElementById(match[1]); - - return m ? - m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? - [m] : - undefined : - []; - } - }; - - Expr.filter.ID = function( elem, match ) { - var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); - - return elem.nodeType === 1 && node && node.nodeValue === match; - }; - } - - root.removeChild( form ); - - // release memory in IE - root = form = null; -})(); - -(function(){ - // Check to see if the browser returns only elements - // when doing getElementsByTagName("*") - - // Create a fake element - var div = document.createElement("div"); - div.appendChild( document.createComment("") ); - - // Make sure no comments are found - if ( div.getElementsByTagName("*").length > 0 ) { - Expr.find.TAG = function( match, context ) { - var results = context.getElementsByTagName( match[1] ); - - // Filter out possible comments - if ( match[1] === "*" ) { - var tmp = []; - - for ( var i = 0; results[i]; i++ ) { - if ( results[i].nodeType === 1 ) { - tmp.push( results[i] ); - } - } - - results = tmp; - } - - return results; - }; - } - - // Check to see if an attribute returns normalized href attributes - div.innerHTML = ""; - - if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && - div.firstChild.getAttribute("href") !== "#" ) { - - Expr.attrHandle.href = function( elem ) { - return elem.getAttribute( "href", 2 ); - }; - } - - // release memory in IE - div = null; -})(); - -if ( document.querySelectorAll ) { - (function(){ - var oldSizzle = Sizzle, - div = document.createElement("div"), - id = "__sizzle__"; - - div.innerHTML = "

    "; - - // Safari can't handle uppercase or unicode characters when - // in quirks mode. - if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { - return; - } - - Sizzle = function( query, context, extra, seed ) { - context = context || document; - - // Only use querySelectorAll on non-XML documents - // (ID selectors don't work in non-HTML documents) - if ( !seed && !Sizzle.isXML(context) ) { - // See if we find a selector to speed up - var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query ); - - if ( match && (context.nodeType === 1 || context.nodeType === 9) ) { - // Speed-up: Sizzle("TAG") - if ( match[1] ) { - return makeArray( context.getElementsByTagName( query ), extra ); - - // Speed-up: Sizzle(".CLASS") - } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) { - return makeArray( context.getElementsByClassName( match[2] ), extra ); - } - } - - if ( context.nodeType === 9 ) { - // Speed-up: Sizzle("body") - // The body element only exists once, optimize finding it - if ( query === "body" && context.body ) { - return makeArray( [ context.body ], extra ); - - // Speed-up: Sizzle("#ID") - } else if ( match && match[3] ) { - var elem = context.getElementById( match[3] ); - - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - if ( elem && elem.parentNode ) { - // Handle the case where IE and Opera return items - // by name instead of ID - if ( elem.id === match[3] ) { - return makeArray( [ elem ], extra ); - } - - } else { - return makeArray( [], extra ); - } - } - - try { - return makeArray( context.querySelectorAll(query), extra ); - } catch(qsaError) {} - - // qSA works strangely on Element-rooted queries - // We can work around this by specifying an extra ID on the root - // and working up from there (Thanks to Andrew Dupont for the technique) - // IE 8 doesn't work on object elements - } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { - var oldContext = context, - old = context.getAttribute( "id" ), - nid = old || id, - hasParent = context.parentNode, - relativeHierarchySelector = /^\s*[+~]/.test( query ); - - if ( !old ) { - context.setAttribute( "id", nid ); - } else { - nid = nid.replace( /'/g, "\\$&" ); - } - if ( relativeHierarchySelector && hasParent ) { - context = context.parentNode; - } - - try { - if ( !relativeHierarchySelector || hasParent ) { - return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra ); - } - - } catch(pseudoError) { - } finally { - if ( !old ) { - oldContext.removeAttribute( "id" ); - } - } - } - } - - return oldSizzle(query, context, extra, seed); - }; - - for ( var prop in oldSizzle ) { - Sizzle[ prop ] = oldSizzle[ prop ]; - } - - // release memory in IE - div = null; - })(); -} - -(function(){ - var html = document.documentElement, - matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector; - - if ( matches ) { - // Check to see if it's possible to do matchesSelector - // on a disconnected node (IE 9 fails this) - var disconnectedMatch = !matches.call( document.createElement( "div" ), "div" ), - pseudoWorks = false; - - try { - // This should fail with an exception - // Gecko does not error, returns false instead - matches.call( document.documentElement, "[test!='']:sizzle" ); - - } catch( pseudoError ) { - pseudoWorks = true; - } - - Sizzle.matchesSelector = function( node, expr ) { - // Make sure that attribute selectors are quoted - expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']"); - - if ( !Sizzle.isXML( node ) ) { - try { - if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) { - var ret = matches.call( node, expr ); - - // IE 9's matchesSelector returns false on disconnected nodes - if ( ret || !disconnectedMatch || - // As well, disconnected nodes are said to be in a document - // fragment in IE 9, so check for that - node.document && node.document.nodeType !== 11 ) { - return ret; - } - } - } catch(e) {} - } - - return Sizzle(expr, null, null, [node]).length > 0; - }; - } -})(); - -(function(){ - var div = document.createElement("div"); - - div.innerHTML = "
    "; - - // Opera can't find a second classname (in 9.6) - // Also, make sure that getElementsByClassName actually exists - if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { - return; - } - - // Safari caches class attributes, doesn't catch changes (in 3.2) - div.lastChild.className = "e"; - - if ( div.getElementsByClassName("e").length === 1 ) { - return; - } - - Expr.order.splice(1, 0, "CLASS"); - Expr.find.CLASS = function( match, context, isXML ) { - if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { - return context.getElementsByClassName(match[1]); - } - }; - - // release memory in IE - div = null; -})(); - -function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { - for ( var i = 0, l = checkSet.length; i < l; i++ ) { - var elem = checkSet[i]; - - if ( elem ) { - var match = false; - - elem = elem[dir]; - - while ( elem ) { - if ( elem[ expando ] === doneName ) { - match = checkSet[elem.sizset]; - break; - } - - if ( elem.nodeType === 1 && !isXML ){ - elem[ expando ] = doneName; - elem.sizset = i; - } - - if ( elem.nodeName.toLowerCase() === cur ) { - match = elem; - break; - } - - elem = elem[dir]; - } - - checkSet[i] = match; - } - } -} - -function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { - for ( var i = 0, l = checkSet.length; i < l; i++ ) { - var elem = checkSet[i]; - - if ( elem ) { - var match = false; - - elem = elem[dir]; - - while ( elem ) { - if ( elem[ expando ] === doneName ) { - match = checkSet[elem.sizset]; - break; - } - - if ( elem.nodeType === 1 ) { - if ( !isXML ) { - elem[ expando ] = doneName; - elem.sizset = i; - } - - if ( typeof cur !== "string" ) { - if ( elem === cur ) { - match = true; - break; - } - - } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { - match = elem; - break; - } - } - - elem = elem[dir]; - } - - checkSet[i] = match; - } - } -} - -if ( document.documentElement.contains ) { - Sizzle.contains = function( a, b ) { - return a !== b && (a.contains ? a.contains(b) : true); - }; - -} else if ( document.documentElement.compareDocumentPosition ) { - Sizzle.contains = function( a, b ) { - return !!(a.compareDocumentPosition(b) & 16); - }; - -} else { - Sizzle.contains = function() { - return false; - }; -} - -Sizzle.isXML = function( elem ) { - // documentElement is verified for cases where it doesn't yet exist - // (such as loading iframes in IE - #4833) - var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; - - return documentElement ? documentElement.nodeName !== "HTML" : false; -}; - -var posProcess = function( selector, context, seed ) { - var match, - tmpSet = [], - later = "", - root = context.nodeType ? [context] : context; - - // Position selectors must be done after the filter - // And so must :not(positional) so we move all PSEUDOs to the end - while ( (match = Expr.match.PSEUDO.exec( selector )) ) { - later += match[0]; - selector = selector.replace( Expr.match.PSEUDO, "" ); - } - - selector = Expr.relative[selector] ? selector + "*" : selector; - - for ( var i = 0, l = root.length; i < l; i++ ) { - Sizzle( selector, root[i], tmpSet, seed ); - } - - return Sizzle.filter( later, tmpSet ); -}; - -// EXPOSE - -window.tinymce.dom.Sizzle = Sizzle; - -})(); - -(function(tinymce) { - tinymce.dom.Element = function(id, settings) { - var t = this, dom, el; - - t.settings = settings = settings || {}; - t.id = id; - t.dom = dom = settings.dom || tinymce.DOM; - - // Only IE leaks DOM references, this is a lot faster - if (!tinymce.isIE) - el = dom.get(t.id); - - tinymce.each( - ('getPos,getRect,getParent,add,setStyle,getStyle,setStyles,' + - 'setAttrib,setAttribs,getAttrib,addClass,removeClass,' + - 'hasClass,getOuterHTML,setOuterHTML,remove,show,hide,' + - 'isHidden,setHTML,get').split(/,/), function(k) { - t[k] = function() { - var a = [id], i; - - for (i = 0; i < arguments.length; i++) - a.push(arguments[i]); - - a = dom[k].apply(dom, a); - t.update(k); - - return a; - }; - } - ); - - tinymce.extend(t, { - on : function(n, f, s) { - return tinymce.dom.Event.add(t.id, n, f, s); - }, - - getXY : function() { - return { - x : parseInt(t.getStyle('left')), - y : parseInt(t.getStyle('top')) - }; - }, - - getSize : function() { - var n = dom.get(t.id); - - return { - w : parseInt(t.getStyle('width') || n.clientWidth), - h : parseInt(t.getStyle('height') || n.clientHeight) - }; - }, - - moveTo : function(x, y) { - t.setStyles({left : x, top : y}); - }, - - moveBy : function(x, y) { - var p = t.getXY(); - - t.moveTo(p.x + x, p.y + y); - }, - - resizeTo : function(w, h) { - t.setStyles({width : w, height : h}); - }, - - resizeBy : function(w, h) { - var s = t.getSize(); - - t.resizeTo(s.w + w, s.h + h); - }, - - update : function(k) { - var b; - - if (tinymce.isIE6 && settings.blocker) { - k = k || ''; - - // Ignore getters - if (k.indexOf('get') === 0 || k.indexOf('has') === 0 || k.indexOf('is') === 0) - return; - - // Remove blocker on remove - if (k == 'remove') { - dom.remove(t.blocker); - return; - } - - if (!t.blocker) { - t.blocker = dom.uniqueId(); - b = dom.add(settings.container || dom.getRoot(), 'iframe', {id : t.blocker, style : 'position:absolute;', frameBorder : 0, src : 'javascript:""'}); - dom.setStyle(b, 'opacity', 0); - } else - b = dom.get(t.blocker); - - dom.setStyles(b, { - left : t.getStyle('left', 1), - top : t.getStyle('top', 1), - width : t.getStyle('width', 1), - height : t.getStyle('height', 1), - display : t.getStyle('display', 1), - zIndex : parseInt(t.getStyle('zIndex', 1) || 0) - 1 - }); - } - } - }); - }; -})(tinymce); -(function(tinymce) { - function trimNl(s) { - return s.replace(/[\n\r]+/g, ''); - }; - - // Shorten names - var is = tinymce.is, isIE = tinymce.isIE, each = tinymce.each, TreeWalker = tinymce.dom.TreeWalker; - - tinymce.create('tinymce.dom.Selection', { - Selection : function(dom, win, serializer, editor) { - var t = this; - - t.dom = dom; - t.win = win; - t.serializer = serializer; - t.editor = editor; - - // Add events - each([ - 'onBeforeSetContent', - - 'onBeforeGetContent', - - 'onSetContent', - - 'onGetContent' - ], function(e) { - t[e] = new tinymce.util.Dispatcher(t); - }); - - // No W3C Range support - if (!t.win.getSelection) - t.tridentSel = new tinymce.dom.TridentSelection(t); - - if (tinymce.isIE && ! tinymce.isIE11 && dom.boxModel) - this._fixIESelection(); - - // Prevent leaks - tinymce.addUnload(t.destroy, t); - }, - - setCursorLocation: function(node, offset) { - var t = this; var r = t.dom.createRng(); - r.setStart(node, offset); - r.setEnd(node, offset); - t.setRng(r); - t.collapse(false); - }, - getContent : function(s) { - var t = this, r = t.getRng(), e = t.dom.create("body"), se = t.getSel(), wb, wa, n; - - s = s || {}; - wb = wa = ''; - s.get = true; - s.format = s.format || 'html'; - s.forced_root_block = ''; - t.onBeforeGetContent.dispatch(t, s); - - if (s.format == 'text') - return t.isCollapsed() ? '' : (r.text || (se.toString ? se.toString() : '')); - - if (r.cloneContents) { - n = r.cloneContents(); - - if (n) - e.appendChild(n); - } else if (is(r.item) || is(r.htmlText)) { - // IE will produce invalid markup if elements are present that - // it doesn't understand like custom elements or HTML5 elements. - // Adding a BR in front of the contents and then remoiving it seems to fix it though. - e.innerHTML = '
    ' + (r.item ? r.item(0).outerHTML : r.htmlText); - e.removeChild(e.firstChild); - } else - e.innerHTML = r.toString(); - - // Keep whitespace before and after - if (/^\s/.test(e.innerHTML)) - wb = ' '; - - if (/\s+$/.test(e.innerHTML)) - wa = ' '; - - s.getInner = true; - - s.content = t.isCollapsed() ? '' : wb + t.serializer.serialize(e, s) + wa; - t.onGetContent.dispatch(t, s); - - return s.content; - }, - - setContent : function(content, args) { - var self = this, rng = self.getRng(), caretNode, doc = self.win.document, frag, temp; - - args = args || {format : 'html'}; - args.set = true; - content = args.content = content; - - // Dispatch before set content event - if (!args.no_events) - self.onBeforeSetContent.dispatch(self, args); - - content = args.content; - - if (rng.insertNode) { - // Make caret marker since insertNode places the caret in the beginning of text after insert - content += '_'; - - // Delete and insert new node - if (rng.startContainer == doc && rng.endContainer == doc) { - // WebKit will fail if the body is empty since the range is then invalid and it can't insert contents - doc.body.innerHTML = content; - } else { - rng.deleteContents(); - - if (doc.body.childNodes.length === 0) { - doc.body.innerHTML = content; - } else { - // createContextualFragment doesn't exists in IE 9 DOMRanges - if (rng.createContextualFragment) { - rng.insertNode(rng.createContextualFragment(content)); - } else { - // Fake createContextualFragment call in IE 9 - frag = doc.createDocumentFragment(); - temp = doc.createElement('div'); - - frag.appendChild(temp); - temp.outerHTML = content; - - rng.insertNode(frag); - } - } - } - - // Move to caret marker - caretNode = self.dom.get('__caret'); - - // Make sure we wrap it compleatly, Opera fails with a simple select call - rng = doc.createRange(); - rng.setStartBefore(caretNode); - rng.setEndBefore(caretNode); - self.setRng(rng); - - // Remove the caret position - self.dom.remove('__caret'); - - try { - self.setRng(rng); - } catch (ex) { - // Might fail on Opera for some odd reason - } - } else { - if (rng.item) { - // Delete content and get caret text selection - doc.execCommand('Delete', false, null); - rng = self.getRng(); - } - - // Explorer removes spaces from the beginning of pasted contents - if (/^\s+/.test(content)) { - rng.pasteHTML('_' + content); - self.dom.remove('__mce_tmp'); - } else - rng.pasteHTML(content); - } - - // Dispatch set content event - if (!args.no_events) - self.onSetContent.dispatch(self, args); - }, - - getStart : function() { - var self = this, rng = self.getRng(), startElement, parentElement, checkRng, node; - - if (rng.duplicate || rng.item) { - // Control selection, return first item - if (rng.item) - return rng.item(0); - - // Get start element - checkRng = rng.duplicate(); - checkRng.collapse(1); - startElement = checkRng.parentElement(); - if (startElement.ownerDocument !== self.dom.doc) { - startElement = self.dom.getRoot(); - } - - // Check if range parent is inside the start element, then return the inner parent element - // This will fix issues when a single element is selected, IE would otherwise return the wrong start element - parentElement = node = rng.parentElement(); - while (node = node.parentNode) { - if (node == startElement) { - startElement = parentElement; - break; - } - } - - return startElement; - } else { - startElement = rng.startContainer; - - if (startElement.nodeType == 1 && startElement.hasChildNodes()) - startElement = startElement.childNodes[Math.min(startElement.childNodes.length - 1, rng.startOffset)]; - - if (startElement && startElement.nodeType == 3) - return startElement.parentNode; - - return startElement; - } - }, - - getEnd : function() { - var self = this, rng = self.getRng(), endElement, endOffset; - - if (rng.duplicate || rng.item) { - if (rng.item) - return rng.item(0); - - rng = rng.duplicate(); - rng.collapse(0); - endElement = rng.parentElement(); - if (endElement.ownerDocument !== self.dom.doc) { - endElement = self.dom.getRoot(); - } - - if (endElement && endElement.nodeName == 'BODY') - return endElement.lastChild || endElement; - - return endElement; - } else { - endElement = rng.endContainer; - endOffset = rng.endOffset; - - if (endElement.nodeType == 1 && endElement.hasChildNodes()) - endElement = endElement.childNodes[endOffset > 0 ? endOffset - 1 : endOffset]; - - if (endElement && endElement.nodeType == 3) - return endElement.parentNode; - - return endElement; - } - }, - - getBookmark : function(type, normalized) { - var t = this, dom = t.dom, rng, rng2, id, collapsed, name, element, index, chr = '\uFEFF', styles; - - function findIndex(name, element) { - var index = 0; - - each(dom.select(name), function(node, i) { - if (node == element) - index = i; - }); - - return index; - }; - - function normalizeTableCellSelection(rng) { - function moveEndPoint(start) { - var container, offset, childNodes, prefix = start ? 'start' : 'end'; - - container = rng[prefix + 'Container']; - offset = rng[prefix + 'Offset']; - - if (container.nodeType == 1 && container.nodeName == "TR") { - childNodes = container.childNodes; - container = childNodes[Math.min(start ? offset : offset - 1, childNodes.length - 1)]; - if (container) { - offset = start ? 0 : container.childNodes.length; - rng['set' + (start ? 'Start' : 'End')](container, offset); - } - } - }; - - moveEndPoint(true); - moveEndPoint(); - - return rng; - }; - - function getLocation() { - var rng = t.getRng(true), root = dom.getRoot(), bookmark = {}; - - function getPoint(rng, start) { - var container = rng[start ? 'startContainer' : 'endContainer'], - offset = rng[start ? 'startOffset' : 'endOffset'], point = [], node, childNodes, after = 0; - - if (container.nodeType == 3) { - if (normalized) { - for (node = container.previousSibling; node && node.nodeType == 3; node = node.previousSibling) - offset += node.nodeValue.length; - } - - point.push(offset); - } else { - childNodes = container.childNodes; - - if (offset >= childNodes.length && childNodes.length) { - after = 1; - offset = Math.max(0, childNodes.length - 1); - } - - point.push(t.dom.nodeIndex(childNodes[offset], normalized) + after); - } - - for (; container && container != root; container = container.parentNode) - point.push(t.dom.nodeIndex(container, normalized)); - - return point; - }; - - bookmark.start = getPoint(rng, true); - - if (!t.isCollapsed()) - bookmark.end = getPoint(rng); - - return bookmark; - }; - - if (type == 2) { - if (t.tridentSel) - return t.tridentSel.getBookmark(type); - - return getLocation(); - } - - // Handle simple range - if (type) { - rng = t.getRng(); - - if (rng.setStart) { - rng = { - startContainer: rng.startContainer, - startOffset: rng.startOffset, - endContainer: rng.endContainer, - endOffset: rng.endOffset - }; - } - - return {rng : rng}; - } - - rng = t.getRng(); - id = dom.uniqueId(); - collapsed = tinyMCE.activeEditor.selection.isCollapsed(); - styles = 'overflow:hidden;line-height:0px'; - - // Explorer method - if (rng.duplicate || rng.item) { - // Text selection - if (!rng.item) { - rng2 = rng.duplicate(); - - try { - // Insert start marker - rng.collapse(); - rng.pasteHTML('' + chr + ''); - - // Insert end marker - if (!collapsed) { - rng2.collapse(false); - - // Detect the empty space after block elements in IE and move the end back one character

    ] becomes

    ]

    - rng.moveToElementText(rng2.parentElement()); - if (rng.compareEndPoints('StartToEnd', rng2) === 0) - rng2.move('character', -1); - - rng2.pasteHTML('' + chr + ''); - } - } catch (ex) { - // IE might throw unspecified error so lets ignore it - return null; - } - } else { - // Control selection - element = rng.item(0); - name = element.nodeName; - - return {name : name, index : findIndex(name, element)}; - } - } else { - element = t.getNode(); - name = element.nodeName; - if (name == 'IMG') - return {name : name, index : findIndex(name, element)}; - - // W3C method - rng2 = normalizeTableCellSelection(rng.cloneRange()); - - // Insert end marker - if (!collapsed) { - rng2.collapse(false); - rng2.insertNode(dom.create('span', {'data-mce-type' : "bookmark", id : id + '_end', style : styles}, chr)); - } - - rng = normalizeTableCellSelection(rng); - rng.collapse(true); - rng.insertNode(dom.create('span', {'data-mce-type' : "bookmark", id : id + '_start', style : styles}, chr)); - } - - t.moveToBookmark({id : id, keep : 1}); - - return {id : id}; - }, - - moveToBookmark : function(bookmark) { - var t = this, dom = t.dom, marker1, marker2, rng, rng2, root, startContainer, endContainer, startOffset, endOffset; - - function setEndPoint(start) { - var point = bookmark[start ? 'start' : 'end'], i, node, offset, children; - - if (point) { - offset = point[0]; - - // Find container node - for (node = root, i = point.length - 1; i >= 1; i--) { - children = node.childNodes; - - if (point[i] > children.length - 1) - return; - - node = children[point[i]]; - } - - // Move text offset to best suitable location - if (node.nodeType === 3) - offset = Math.min(point[0], node.nodeValue.length); - - // Move element offset to best suitable location - if (node.nodeType === 1) - offset = Math.min(point[0], node.childNodes.length); - - // Set offset within container node - if (start) - rng.setStart(node, offset); - else - rng.setEnd(node, offset); - } - - return true; - }; - - function restoreEndPoint(suffix) { - var marker = dom.get(bookmark.id + '_' + suffix), node, idx, next, prev, keep = bookmark.keep; - - if (marker) { - node = marker.parentNode; - - if (suffix == 'start') { - if (!keep) { - idx = dom.nodeIndex(marker); - } else { - node = marker.firstChild; - idx = 1; - } - - startContainer = endContainer = node; - startOffset = endOffset = idx; - } else { - if (!keep) { - idx = dom.nodeIndex(marker); - } else { - node = marker.firstChild; - idx = 1; - } - - endContainer = node; - endOffset = idx; - } - - if (!keep) { - prev = marker.previousSibling; - next = marker.nextSibling; - - // Remove all marker text nodes - each(tinymce.grep(marker.childNodes), function(node) { - if (node.nodeType == 3) - node.nodeValue = node.nodeValue.replace(/\uFEFF/g, ''); - }); - - // Remove marker but keep children if for example contents where inserted into the marker - // Also remove duplicated instances of the marker for example by a split operation or by WebKit auto split on paste feature - while (marker = dom.get(bookmark.id + '_' + suffix)) - dom.remove(marker, 1); - - // If siblings are text nodes then merge them unless it's Opera since it some how removes the node - // and we are sniffing since adding a lot of detection code for a browser with 3% of the market isn't worth the effort. Sorry, Opera but it's just a fact - if (prev && next && prev.nodeType == next.nodeType && prev.nodeType == 3 && !tinymce.isOpera) { - idx = prev.nodeValue.length; - prev.appendData(next.nodeValue); - dom.remove(next); - - if (suffix == 'start') { - startContainer = endContainer = prev; - startOffset = endOffset = idx; - } else { - endContainer = prev; - endOffset = idx; - } - } - } - } - }; - - function addBogus(node) { - // Adds a bogus BR element for empty block elements - if (dom.isBlock(node) && !node.innerHTML && !isIE) - node.innerHTML = '
    '; - - return node; - }; - - if (bookmark) { - if (bookmark.start) { - rng = dom.createRng(); - root = dom.getRoot(); - - if (t.tridentSel) - return t.tridentSel.moveToBookmark(bookmark); - - if (setEndPoint(true) && setEndPoint()) { - t.setRng(rng); - } - } else if (bookmark.id) { - // Restore start/end points - restoreEndPoint('start'); - restoreEndPoint('end'); - - if (startContainer) { - rng = dom.createRng(); - rng.setStart(addBogus(startContainer), startOffset); - rng.setEnd(addBogus(endContainer), endOffset); - t.setRng(rng); - } - } else if (bookmark.name) { - t.select(dom.select(bookmark.name)[bookmark.index]); - } else if (bookmark.rng) { - rng = bookmark.rng; - - if (rng.startContainer) { - rng2 = t.dom.createRng(); - - try { - rng2.setStart(rng.startContainer, rng.startOffset); - rng2.setEnd(rng.endContainer, rng.endOffset); - } catch (e) { - // Might fail with index error - } - - rng = rng2; - } - - t.setRng(rng); - } - } - }, - - select : function(node, content) { - var t = this, dom = t.dom, rng = dom.createRng(), idx; - - function setPoint(node, start) { - var walker = new TreeWalker(node, node); - - do { - // Text node - if (node.nodeType == 3 && tinymce.trim(node.nodeValue).length !== 0) { - if (start) - rng.setStart(node, 0); - else - rng.setEnd(node, node.nodeValue.length); - - return; - } - - // BR element - if (node.nodeName == 'BR') { - if (start) - rng.setStartBefore(node); - else - rng.setEndBefore(node); - - return; - } - } while (node = (start ? walker.next() : walker.prev())); - }; - - if (node) { - idx = dom.nodeIndex(node); - rng.setStart(node.parentNode, idx); - rng.setEnd(node.parentNode, idx + 1); - - // Find first/last text node or BR element - if (content) { - setPoint(node, 1); - setPoint(node); - } - - t.setRng(rng); - } - - return node; - }, - - isCollapsed : function() { - var t = this, r = t.getRng(), s = t.getSel(); - - if (!r || r.item) - return false; - - if (r.compareEndPoints) - return r.compareEndPoints('StartToEnd', r) === 0; - - return !s || r.collapsed; - }, - - collapse : function(to_start) { - var self = this, rng = self.getRng(), node; - - // Control range on IE - if (rng.item) { - node = rng.item(0); - rng = self.win.document.body.createTextRange(); - rng.moveToElementText(node); - } - - rng.collapse(!!to_start); - self.setRng(rng); - }, - - getSel : function() { - var t = this, w = this.win; - - return w.getSelection ? w.getSelection() : w.document.selection; - }, - - getRng : function(w3c) { - var self = this, selection, rng, elm, doc = self.win.document; - - // Workaround for IE 11 not being able to select images properly see #6613 see quirk fix - if (self.fakeRng) { - return self.fakeRng; - } - - // Found tridentSel object then we need to use that one - if (w3c && self.tridentSel) { - return self.tridentSel.getRangeAt(0); - } - - try { - if (selection = self.getSel()) { - rng = selection.rangeCount > 0 ? selection.getRangeAt(0) : (selection.createRange ? selection.createRange() : doc.createRange()); - } - } catch (ex) { - // IE throws unspecified error here if TinyMCE is placed in a frame/iframe - } - - // We have W3C ranges and it's IE then fake control selection since IE9 doesn't handle that correctly yet - if (tinymce.isIE && ! tinymce.isIE11 && rng && rng.setStart && doc.selection.createRange().item) { - elm = doc.selection.createRange().item(0); - rng = doc.createRange(); - rng.setStartBefore(elm); - rng.setEndAfter(elm); - } - - // No range found then create an empty one - // This can occur when the editor is placed in a hidden container element on Gecko - // Or on IE when there was an exception - if (!rng) { - rng = doc.createRange ? doc.createRange() : doc.body.createTextRange(); - } - - // If range is at start of document then move it to start of body - if (rng.setStart && rng.startContainer.nodeType === 9 && rng.collapsed) { - elm = self.dom.getRoot(); - rng.setStart(elm, 0); - rng.setEnd(elm, 0); - } - - if (self.selectedRange && self.explicitRange) { - if (rng.compareBoundaryPoints(rng.START_TO_START, self.selectedRange) === 0 && rng.compareBoundaryPoints(rng.END_TO_END, self.selectedRange) === 0) { - // Safari, Opera and Chrome only ever select text which causes the range to change. - // This lets us use the originally set range if the selection hasn't been changed by the user. - rng = self.explicitRange; - } else { - self.selectedRange = null; - self.explicitRange = null; - } - } - - return rng; - }, - - setRng : function(r, forward) { - var s, t = this; - - if (!t.tridentSel) { - s = t.getSel(); - - if (s) { - t.explicitRange = r; - - try { - s.removeAllRanges(); - } catch (ex) { - // IE9 might throw errors here don't know why - } - - s.addRange(r); - - // Forward is set to false and we have an extend function - if (forward === false && s.extend) { - s.collapse(r.endContainer, r.endOffset); - s.extend(r.startContainer, r.startOffset); - } - - // adding range isn't always successful so we need to check range count otherwise an exception can occur - t.selectedRange = s.rangeCount > 0 ? s.getRangeAt(0) : null; - } - } else { - // Is W3C Range - if (r.cloneRange) { - try { - t.tridentSel.addRange(r); - return; - } catch (ex) { - //IE9 throws an error here if called before selection is placed in the editor - } - } - - // Is IE specific range - try { - r.select(); - } catch (ex) { - // Needed for some odd IE bug #1843306 - } - } - }, - - setNode : function(n) { - var t = this; - - t.setContent(t.dom.getOuterHTML(n)); - - return n; - }, - - getNode : function() { - var t = this, rng = t.getRng(), sel = t.getSel(), elm, start = rng.startContainer, end = rng.endContainer; - - function skipEmptyTextNodes(n, forwards) { - var orig = n; - while (n && n.nodeType === 3 && n.length === 0) { - n = forwards ? n.nextSibling : n.previousSibling; - } - return n || orig; - }; - - // Range maybe lost after the editor is made visible again - if (!rng) - return t.dom.getRoot(); - - if (rng.setStart) { - elm = rng.commonAncestorContainer; - - // Handle selection a image or other control like element such as anchors - if (!rng.collapsed) { - if (rng.startContainer == rng.endContainer) { - if (rng.endOffset - rng.startOffset < 2) { - if (rng.startContainer.hasChildNodes()) - elm = rng.startContainer.childNodes[rng.startOffset]; - } - } - - // If the anchor node is a element instead of a text node then return this element - //if (tinymce.isWebKit && sel.anchorNode && sel.anchorNode.nodeType == 1) - // return sel.anchorNode.childNodes[sel.anchorOffset]; - - // Handle cases where the selection is immediately wrapped around a node and return that node instead of it's parent. - // This happens when you double click an underlined word in FireFox. - if (start.nodeType === 3 && end.nodeType === 3) { - if (start.length === rng.startOffset) { - start = skipEmptyTextNodes(start.nextSibling, true); - } else { - start = start.parentNode; - } - if (rng.endOffset === 0) { - end = skipEmptyTextNodes(end.previousSibling, false); - } else { - end = end.parentNode; - } - - if (start && start === end) - return start; - } - } - - if (elm && elm.nodeType == 3) - return elm.parentNode; - - return elm; - } - - return rng.item ? rng.item(0) : rng.parentElement(); - }, - - getSelectedBlocks : function(st, en) { - var t = this, dom = t.dom, sb, eb, n, bl = []; - - sb = dom.getParent(st || t.getStart(), dom.isBlock); - eb = dom.getParent(en || t.getEnd(), dom.isBlock); - - if (sb) - bl.push(sb); - - if (sb && eb && sb != eb) { - n = sb; - - var walker = new TreeWalker(sb, dom.getRoot()); - while ((n = walker.next()) && n != eb) { - if (dom.isBlock(n)) - bl.push(n); - } - } - - if (eb && sb != eb) - bl.push(eb); - - return bl; - }, - - isForward: function(){ - var dom = this.dom, sel = this.getSel(), anchorRange, focusRange; - - // No support for selection direction then always return true - if (!sel || sel.anchorNode == null || sel.focusNode == null) { - return true; - } - - anchorRange = dom.createRng(); - anchorRange.setStart(sel.anchorNode, sel.anchorOffset); - anchorRange.collapse(true); - - focusRange = dom.createRng(); - focusRange.setStart(sel.focusNode, sel.focusOffset); - focusRange.collapse(true); - - return anchorRange.compareBoundaryPoints(anchorRange.START_TO_START, focusRange) <= 0; - }, - - normalize : function() { - var self = this, rng, normalized, collapsed, node, sibling; - - function normalizeEndPoint(start) { - var container, offset, walker, dom = self.dom, body = dom.getRoot(), node, nonEmptyElementsMap, nodeName; - - function hasBrBeforeAfter(node, left) { - var walker = new TreeWalker(node, dom.getParent(node.parentNode, dom.isBlock) || body); - - while (node = walker[left ? 'prev' : 'next']()) { - if (node.nodeName === "BR") { - return true; - } - } - }; - - // Walks the dom left/right to find a suitable text node to move the endpoint into - // It will only walk within the current parent block or body and will stop if it hits a block or a BR/IMG - function findTextNodeRelative(left, startNode) { - var walker, lastInlineElement; - - startNode = startNode || container; - walker = new TreeWalker(startNode, dom.getParent(startNode.parentNode, dom.isBlock) || body); - - // Walk left until we hit a text node we can move to or a block/br/img - while (node = walker[left ? 'prev' : 'next']()) { - // Found text node that has a length - if (node.nodeType === 3 && node.nodeValue.length > 0) { - container = node; - offset = left ? node.nodeValue.length : 0; - normalized = true; - return; - } - - // Break if we find a block or a BR/IMG/INPUT etc - if (dom.isBlock(node) || nonEmptyElementsMap[node.nodeName.toLowerCase()]) { - return; - } - - lastInlineElement = node; - } - - // Only fetch the last inline element when in caret mode for now - if (collapsed && lastInlineElement) { - container = lastInlineElement; - normalized = true; - offset = 0; - } - }; - - container = rng[(start ? 'start' : 'end') + 'Container']; - offset = rng[(start ? 'start' : 'end') + 'Offset']; - nonEmptyElementsMap = dom.schema.getNonEmptyElements(); - - // If the container is a document move it to the body element - if (container.nodeType === 9) { - container = dom.getRoot(); - offset = 0; - } - - // If the container is body try move it into the closest text node or position - if (container === body) { - // If start is before/after a image, table etc - if (start) { - node = container.childNodes[offset > 0 ? offset - 1 : 0]; - if (node) { - nodeName = node.nodeName.toLowerCase(); - if (nonEmptyElementsMap[node.nodeName] || node.nodeName == "TABLE") { - return; - } - } - } - - // Resolve the index - if (container.hasChildNodes()) { - container = container.childNodes[Math.min(!start && offset > 0 ? offset - 1 : offset, container.childNodes.length - 1)]; - offset = 0; - - // Don't walk into elements that doesn't have any child nodes like a IMG - if (container.hasChildNodes() && !/TABLE/.test(container.nodeName)) { - // Walk the DOM to find a text node to place the caret at or a BR - node = container; - walker = new TreeWalker(container, body); - - do { - // Found a text node use that position - if (node.nodeType === 3 && node.nodeValue.length > 0) { - offset = start ? 0 : node.nodeValue.length; - container = node; - normalized = true; - break; - } - - // Found a BR/IMG element that we can place the caret before - if (nonEmptyElementsMap[node.nodeName.toLowerCase()]) { - offset = dom.nodeIndex(node); - container = node.parentNode; - - // Put caret after image when moving the end point - if (node.nodeName == "IMG" && !start) { - offset++; - } - - normalized = true; - break; - } - } while (node = (start ? walker.next() : walker.prev())); - } - } - } - - // Lean the caret to the left if possible - if (collapsed) { - // So this: x|x - // Becomes: x|x - // Seems that only gecko has issues with this - if (container.nodeType === 3 && offset === 0) { - findTextNodeRelative(true); - } - - // Lean left into empty inline elements when the caret is before a BR - // So this: |
    - // Becomes: |
    - // Seems that only gecko has issues with this - if (container.nodeType === 1) { - node = container.childNodes[offset]; - if(node && node.nodeName === 'BR' && !hasBrBeforeAfter(node) && !hasBrBeforeAfter(node, true)) { - findTextNodeRelative(true, container.childNodes[offset]); - } - } - } - - // Lean the start of the selection right if possible - // So this: x[x] - // Becomes: x[x] - if (start && !collapsed && container.nodeType === 3 && offset === container.nodeValue.length) { - findTextNodeRelative(false); - } - - // Set endpoint if it was normalized - if (normalized) - rng['set' + (start ? 'Start' : 'End')](container, offset); - }; - - // Normalize only on non IE browsers for now - if (tinymce.isIE) - return; - - rng = self.getRng(); - collapsed = rng.collapsed; - - // Normalize the end points - normalizeEndPoint(true); - - if (!collapsed) - normalizeEndPoint(); - - // Set the selection if it was normalized - if (normalized) { - // If it was collapsed then make sure it still is - if (collapsed) { - rng.collapse(true); - } - - //console.log(self.dom.dumpRng(rng)); - self.setRng(rng, self.isForward()); - } - }, - - selectorChanged: function(selector, callback) { - var self = this, currentSelectors; - - if (!self.selectorChangedData) { - self.selectorChangedData = {}; - currentSelectors = {}; - - self.editor.onNodeChange.addToTop(function(ed, cm, node) { - var dom = self.dom, parents = dom.getParents(node, null, dom.getRoot()), matchedSelectors = {}; - - // Check for new matching selectors - each(self.selectorChangedData, function(callbacks, selector) { - each(parents, function(node) { - if (dom.is(node, selector)) { - if (!currentSelectors[selector]) { - // Execute callbacks - each(callbacks, function(callback) { - callback(true, {node: node, selector: selector, parents: parents}); - }); - - currentSelectors[selector] = callbacks; - } - - matchedSelectors[selector] = callbacks; - return false; - } - }); - }); - - // Check if current selectors still match - each(currentSelectors, function(callbacks, selector) { - if (!matchedSelectors[selector]) { - delete currentSelectors[selector]; - - each(callbacks, function(callback) { - callback(false, {node: node, selector: selector, parents: parents}); - }); - } - }); - }); - } - - // Add selector listeners - if (!self.selectorChangedData[selector]) { - self.selectorChangedData[selector] = []; - } - - self.selectorChangedData[selector].push(callback); - - return self; - }, - - scrollIntoView: function(elm) { - var y, viewPort, self = this, dom = self.dom; - - viewPort = dom.getViewPort(self.editor.getWin()); - y = dom.getPos(elm).y; - if (y < viewPort.y || y + 25 > viewPort.y + viewPort.h) { - self.editor.getWin().scrollTo(0, y < viewPort.y ? y : y - viewPort.h + 25); - } - }, - - destroy : function(manual) { - var self = this; - - self.win = null; - - // Manual destroy then remove unload handler - if (!manual) - tinymce.removeUnload(self.destroy); - }, - - // IE has an issue where you can't select/move the caret by clicking outside the body if the document is in standards mode - _fixIESelection : function() { - var dom = this.dom, doc = dom.doc, body = doc.body, started, startRng, htmlElm; - - // Return range from point or null if it failed - function rngFromPoint(x, y) { - var rng = body.createTextRange(); - - try { - rng.moveToPoint(x, y); - } catch (ex) { - // IE sometimes throws and exception, so lets just ignore it - rng = null; - } - - return rng; - }; - - // Fires while the selection is changing - function selectionChange(e) { - var pointRng; - - // Check if the button is down or not - if (e.button) { - // Create range from mouse position - pointRng = rngFromPoint(e.x, e.y); - - if (pointRng) { - // Check if pointRange is before/after selection then change the endPoint - if (pointRng.compareEndPoints('StartToStart', startRng) > 0) - pointRng.setEndPoint('StartToStart', startRng); - else - pointRng.setEndPoint('EndToEnd', startRng); - - pointRng.select(); - } - } else - endSelection(); - } - - // Removes listeners - function endSelection() { - var rng = doc.selection.createRange(); - - // If the range is collapsed then use the last start range - if (startRng && !rng.item && rng.compareEndPoints('StartToEnd', rng) === 0) - startRng.select(); - - dom.unbind(doc, 'mouseup', endSelection); - dom.unbind(doc, 'mousemove', selectionChange); - startRng = started = 0; - }; - - // Make HTML element unselectable since we are going to handle selection by hand - doc.documentElement.unselectable = true; - - // Detect when user selects outside BODY - dom.bind(doc, ['mousedown', 'contextmenu'], function(e) { - if (e.target.nodeName === 'HTML') { - if (started) - endSelection(); - - // Detect vertical scrollbar, since IE will fire a mousedown on the scrollbar and have target set as HTML - htmlElm = doc.documentElement; - if (htmlElm.scrollHeight > htmlElm.clientHeight) - return; - - started = 1; - // Setup start position - startRng = rngFromPoint(e.x, e.y); - if (startRng) { - // Listen for selection change events - dom.bind(doc, 'mouseup', endSelection); - dom.bind(doc, 'mousemove', selectionChange); - - dom.win.focus(); - startRng.select(); - } - } - }); - } - }); -})(tinymce); -(function(tinymce) { - tinymce.dom.Serializer = function(settings, dom, schema) { - var onPreProcess, onPostProcess, isIE = tinymce.isIE, each = tinymce.each, htmlParser; - - // Support the old apply_source_formatting option - if (!settings.apply_source_formatting) - settings.indent = false; - - // Default DOM and Schema if they are undefined - dom = dom || tinymce.DOM; - schema = schema || new tinymce.html.Schema(settings); - settings.entity_encoding = settings.entity_encoding || 'named'; - settings.remove_trailing_brs = "remove_trailing_brs" in settings ? settings.remove_trailing_brs : true; - - onPreProcess = new tinymce.util.Dispatcher(self); - - onPostProcess = new tinymce.util.Dispatcher(self); - - htmlParser = new tinymce.html.DomParser(settings, schema); - - // Convert move data-mce-src, data-mce-href and data-mce-style into nodes or process them if needed - htmlParser.addAttributeFilter('src,href,style', function(nodes, name) { - var i = nodes.length, node, value, internalName = 'data-mce-' + name, urlConverter = settings.url_converter, urlConverterScope = settings.url_converter_scope, undef; - - while (i--) { - node = nodes[i]; - - value = node.attributes.map[internalName]; - if (value !== undef) { - // Set external name to internal value and remove internal - node.attr(name, value.length > 0 ? value : null); - node.attr(internalName, null); - } else { - // No internal attribute found then convert the value we have in the DOM - value = node.attributes.map[name]; - - if (name === "style") - value = dom.serializeStyle(dom.parseStyle(value), node.name); - else if (urlConverter) - value = urlConverter.call(urlConverterScope, value, name, node.name); - - node.attr(name, value.length > 0 ? value : null); - } - } - }); - - // Remove internal classes mceItem<..> or mceSelected - htmlParser.addAttributeFilter('class', function(nodes, name) { - var i = nodes.length, node, value; - - while (i--) { - node = nodes[i]; - value = node.attr('class').replace(/(?:^|\s)mce(Item\w+|Selected)(?!\S)/g, ''); - node.attr('class', value.length > 0 ? value : null); - } - }); - - // Remove bookmark elements - htmlParser.addAttributeFilter('data-mce-type', function(nodes, name, args) { - var i = nodes.length, node; - - while (i--) { - node = nodes[i]; - - if (node.attributes.map['data-mce-type'] === 'bookmark' && !args.cleanup) - node.remove(); - } - }); - - // Remove expando attributes - htmlParser.addAttributeFilter('data-mce-expando', function(nodes, name, args) { - var i = nodes.length; - - while (i--) { - nodes[i].attr(name, null); - } - }); - - htmlParser.addNodeFilter('noscript', function(nodes) { - var i = nodes.length, node; - - while (i--) { - node = nodes[i].firstChild; - - if (node) { - node.value = tinymce.html.Entities.decode(node.value); - } - } - }); - - // Force script into CDATA sections and remove the mce- prefix also add comments around styles - htmlParser.addNodeFilter('script,style', function(nodes, name) { - var i = nodes.length, node, value; - - function trim(value) { - return value.replace(/()/g, '\n') - .replace(/^[\r\n]*|[\r\n]*$/g, '') - .replace(/^\s*(()?|\s*\/\/\s*\]\]>(-->)?|\/\/\s*(-->)?|\]\]>|\/\*\s*-->\s*\*\/|\s*-->\s*)\s*$/g, ''); - }; - - while (i--) { - node = nodes[i]; - value = node.firstChild ? node.firstChild.value : ''; - - if (name === "script") { - // Remove mce- prefix from script elements - node.attr('type', (node.attr('type') || 'text/javascript').replace(/^mce\-/, '')); - - if (value.length > 0) - node.firstChild.value = '// '; - } else { - if (value.length > 0) - node.firstChild.value = ''; - } - } - }); - - // Convert comments to cdata and handle protected comments - htmlParser.addNodeFilter('#comment', function(nodes, name) { - var i = nodes.length, node; - - while (i--) { - node = nodes[i]; - - if (node.value.indexOf('[CDATA[') === 0) { - node.name = '#cdata'; - node.type = 4; - node.value = node.value.replace(/^\[CDATA\[|\]\]$/g, ''); - } else if (node.value.indexOf('mce:protected ') === 0) { - node.name = "#text"; - node.type = 3; - node.raw = true; - node.value = unescape(node.value).substr(14); - } - } - }); - - htmlParser.addNodeFilter('xml:namespace,input', function(nodes, name) { - var i = nodes.length, node; - - while (i--) { - node = nodes[i]; - if (node.type === 7) - node.remove(); - else if (node.type === 1) { - if (name === "input" && !("type" in node.attributes.map)) - node.attr('type', 'text'); - } - } - }); - - // Fix list elements, TODO: Replace this later - if (settings.fix_list_elements) { - htmlParser.addNodeFilter('ul,ol', function(nodes, name) { - var i = nodes.length, node, parentNode; - - while (i--) { - node = nodes[i]; - parentNode = node.parent; - - if (parentNode.name === 'ul' || parentNode.name === 'ol') { - if (node.prev && node.prev.name === 'li') { - node.prev.append(node); - } - } - } - }); - } - - // Remove internal data attributes - htmlParser.addAttributeFilter('data-mce-src,data-mce-href,data-mce-style', function(nodes, name) { - var i = nodes.length; - - while (i--) { - nodes[i].attr(name, null); - } - }); - - // Return public methods - return { - schema : schema, - - addNodeFilter : htmlParser.addNodeFilter, - - addAttributeFilter : htmlParser.addAttributeFilter, - - onPreProcess : onPreProcess, - - onPostProcess : onPostProcess, - - serialize : function(node, args) { - var impl, doc, oldDoc, htmlSerializer, content; - - // Explorer won't clone contents of script and style and the - // selected index of select elements are cleared on a clone operation. - if (isIE && dom.select('script,style,select,map').length > 0) { - content = node.innerHTML; - node = node.cloneNode(false); - dom.setHTML(node, content); - } else - node = node.cloneNode(true); - - // Nodes needs to be attached to something in WebKit/Opera - // Older builds of Opera crashes if you attach the node to an document created dynamically - // and since we can't feature detect a crash we need to sniff the acutal build number - // This fix will make DOM ranges and make Sizzle happy! - impl = node.ownerDocument.implementation; - if (impl.createHTMLDocument) { - // Create an empty HTML document - doc = impl.createHTMLDocument(""); - - // Add the element or it's children if it's a body element to the new document - each(node.nodeName == 'BODY' ? node.childNodes : [node], function(node) { - doc.body.appendChild(doc.importNode(node, true)); - }); - - // Grab first child or body element for serialization - if (node.nodeName != 'BODY') - node = doc.body.firstChild; - else - node = doc.body; - - // set the new document in DOMUtils so createElement etc works - oldDoc = dom.doc; - dom.doc = doc; - } - - args = args || {}; - args.format = args.format || 'html'; - - // Pre process - if (!args.no_events) { - args.node = node; - onPreProcess.dispatch(self, args); - } - - // Setup serializer - htmlSerializer = new tinymce.html.Serializer(settings, schema); - - // Parse and serialize HTML - args.content = htmlSerializer.serialize( - htmlParser.parse(tinymce.trim(args.getInner ? node.innerHTML : dom.getOuterHTML(node)), args) - ); - - // Replace all BOM characters for now until we can find a better solution - if (!args.cleanup) - args.content = args.content.replace(/\uFEFF/g, ''); - - // Post process - if (!args.no_events) - onPostProcess.dispatch(self, args); - - // Restore the old document if it was changed - if (oldDoc) - dom.doc = oldDoc; - - args.node = null; - - return args.content; - }, - - addRules : function(rules) { - schema.addValidElements(rules); - }, - - setRules : function(rules) { - schema.setValidElements(rules); - } - }; - }; -})(tinymce); -(function(tinymce) { - tinymce.dom.ScriptLoader = function(settings) { - var QUEUED = 0, - LOADING = 1, - LOADED = 2, - states = {}, - queue = [], - scriptLoadedCallbacks = {}, - queueLoadedCallbacks = [], - loading = 0, - undef; - - function loadScript(url, callback) { - var t = this, dom = tinymce.DOM, elm, uri, loc, id; - - // Execute callback when script is loaded - function done() { - dom.remove(id); - - if (elm) - elm.onreadystatechange = elm.onload = elm = null; - - callback(); - }; - - function error() { - // Report the error so it's easier for people to spot loading errors - if (typeof(console) !== "undefined" && console.log) - console.log("Failed to load: " + url); - - // We can't mark it as done if there is a load error since - // A) We don't want to produce 404 errors on the server and - // B) the onerror event won't fire on all browsers. - // done(); - }; - - id = dom.uniqueId(); - - if (tinymce.isIE6) { - uri = new tinymce.util.URI(url); - loc = location; - - // If script is from same domain and we - // use IE 6 then use XHR since it's more reliable - if (uri.host == loc.hostname && uri.port == loc.port && (uri.protocol + ':') == loc.protocol && uri.protocol.toLowerCase() != 'file') { - tinymce.util.XHR.send({ - url : tinymce._addVer(uri.getURI()), - success : function(content) { - // Create new temp script element - var script = dom.create('script', { - type : 'text/javascript' - }); - - // Evaluate script in global scope - script.text = content; - document.getElementsByTagName('head')[0].appendChild(script); - dom.remove(script); - - done(); - }, - - error : error - }); - - return; - } - } - - // Create new script element - elm = document.createElement('script'); - elm.id = id; - elm.type = 'text/javascript'; - elm.src = tinymce._addVer(url); - - // Add onload listener for non IE browsers since IE9 - // fires onload event before the script is parsed and executed - if (!tinymce.isIE || tinymce.isIE11) - elm.onload = done; - - // Add onerror event will get fired on some browsers but not all of them - elm.onerror = error; - - // Opera 9.60 doesn't seem to fire the onreadystate event at correctly - if (!tinymce.isOpera) { - elm.onreadystatechange = function() { - var state = elm.readyState; - - // Loaded state is passed on IE 6 however there - // are known issues with this method but we can't use - // XHR in a cross domain loading - if (state == 'complete' || state == 'loaded') - done(); - }; - } - - // Most browsers support this feature so we report errors - // for those at least to help users track their missing plugins etc - // todo: Removed since it produced error if the document is unloaded by navigating away, re-add it as an option - /*elm.onerror = function() { - alert('Failed to load: ' + url); - };*/ - - // Add script to document - (document.getElementsByTagName('head')[0] || document.body).appendChild(elm); - }; - - this.isDone = function(url) { - return states[url] == LOADED; - }; - - this.markDone = function(url) { - states[url] = LOADED; - }; - - this.add = this.load = function(url, callback, scope) { - var item, state = states[url]; - - // Add url to load queue - if (state == undef) { - queue.push(url); - states[url] = QUEUED; - } - - if (callback) { - // Store away callback for later execution - if (!scriptLoadedCallbacks[url]) - scriptLoadedCallbacks[url] = []; - - scriptLoadedCallbacks[url].push({ - func : callback, - scope : scope || this - }); - } - }; - - this.loadQueue = function(callback, scope) { - this.loadScripts(queue, callback, scope); - }; - - this.loadScripts = function(scripts, callback, scope) { - var loadScripts; - - function execScriptLoadedCallbacks(url) { - // Execute URL callback functions - tinymce.each(scriptLoadedCallbacks[url], function(callback) { - callback.func.call(callback.scope); - }); - - scriptLoadedCallbacks[url] = undef; - }; - - queueLoadedCallbacks.push({ - func : callback, - scope : scope || this - }); - - loadScripts = function() { - var loadingScripts = tinymce.grep(scripts); - - // Current scripts has been handled - scripts.length = 0; - - // Load scripts that needs to be loaded - tinymce.each(loadingScripts, function(url) { - // Script is already loaded then execute script callbacks directly - if (states[url] == LOADED) { - execScriptLoadedCallbacks(url); - return; - } - - // Is script not loading then start loading it - if (states[url] != LOADING) { - states[url] = LOADING; - loading++; - - loadScript(url, function() { - states[url] = LOADED; - loading--; - - execScriptLoadedCallbacks(url); - - // Load more scripts if they where added by the recently loaded script - loadScripts(); - }); - } - }); - - // No scripts are currently loading then execute all pending queue loaded callbacks - if (!loading) { - tinymce.each(queueLoadedCallbacks, function(callback) { - callback.func.call(callback.scope); - }); - - queueLoadedCallbacks.length = 0; - } - }; - - loadScripts(); - }; - }; - - // Global script loader - tinymce.ScriptLoader = new tinymce.dom.ScriptLoader(); -})(tinymce); -(function(tinymce) { - tinymce.dom.RangeUtils = function(dom) { - var INVISIBLE_CHAR = '\uFEFF'; - - this.walk = function(rng, callback) { - var startContainer = rng.startContainer, - startOffset = rng.startOffset, - endContainer = rng.endContainer, - endOffset = rng.endOffset, - ancestor, startPoint, - endPoint, node, parent, siblings, nodes; - - // Handle table cell selection the table plugin enables - // you to fake select table cells and perform formatting actions on them - nodes = dom.select('td.mceSelected,th.mceSelected'); - if (nodes.length > 0) { - tinymce.each(nodes, function(node) { - callback([node]); - }); - - return; - } - - function exclude(nodes) { - var node; - - // First node is excluded - node = nodes[0]; - if (node.nodeType === 3 && node === startContainer && startOffset >= node.nodeValue.length) { - nodes.splice(0, 1); - } - - // Last node is excluded - node = nodes[nodes.length - 1]; - if (endOffset === 0 && nodes.length > 0 && node === endContainer && node.nodeType === 3) { - nodes.splice(nodes.length - 1, 1); - } - - return nodes; - }; - - function collectSiblings(node, name, end_node) { - var siblings = []; - - for (; node && node != end_node; node = node[name]) - siblings.push(node); - - return siblings; - }; - - function findEndPoint(node, root) { - do { - if (node.parentNode == root) - return node; - - node = node.parentNode; - } while(node); - }; - - function walkBoundary(start_node, end_node, next) { - var siblingName = next ? 'nextSibling' : 'previousSibling'; - - for (node = start_node, parent = node.parentNode; node && node != end_node; node = parent) { - parent = node.parentNode; - siblings = collectSiblings(node == start_node ? node : node[siblingName], siblingName); - - if (siblings.length) { - if (!next) - siblings.reverse(); - - callback(exclude(siblings)); - } - } - }; - - // If index based start position then resolve it - if (startContainer.nodeType == 1 && startContainer.hasChildNodes()) - startContainer = startContainer.childNodes[startOffset]; - - // If index based end position then resolve it - if (endContainer.nodeType == 1 && endContainer.hasChildNodes()) - endContainer = endContainer.childNodes[Math.min(endOffset - 1, endContainer.childNodes.length - 1)]; - - // Same container - if (startContainer == endContainer) - return callback(exclude([startContainer])); - - // Find common ancestor and end points - ancestor = dom.findCommonAncestor(startContainer, endContainer); - - // Process left side - for (node = startContainer; node; node = node.parentNode) { - if (node === endContainer) - return walkBoundary(startContainer, ancestor, true); - - if (node === ancestor) - break; - } - - // Process right side - for (node = endContainer; node; node = node.parentNode) { - if (node === startContainer) - return walkBoundary(endContainer, ancestor); - - if (node === ancestor) - break; - } - - // Find start/end point - startPoint = findEndPoint(startContainer, ancestor) || startContainer; - endPoint = findEndPoint(endContainer, ancestor) || endContainer; - - // Walk left leaf - walkBoundary(startContainer, startPoint, true); - - // Walk the middle from start to end point - siblings = collectSiblings( - startPoint == startContainer ? startPoint : startPoint.nextSibling, - 'nextSibling', - endPoint == endContainer ? endPoint.nextSibling : endPoint - ); - - if (siblings.length) - callback(exclude(siblings)); - - // Walk right leaf - walkBoundary(endContainer, endPoint); - }; - - this.split = function(rng) { - var startContainer = rng.startContainer, - startOffset = rng.startOffset, - endContainer = rng.endContainer, - endOffset = rng.endOffset; - - function splitText(node, offset) { - return node.splitText(offset); - }; - - // Handle single text node - if (startContainer == endContainer && startContainer.nodeType == 3) { - if (startOffset > 0 && startOffset < startContainer.nodeValue.length) { - endContainer = splitText(startContainer, startOffset); - startContainer = endContainer.previousSibling; - - if (endOffset > startOffset) { - endOffset = endOffset - startOffset; - startContainer = endContainer = splitText(endContainer, endOffset).previousSibling; - endOffset = endContainer.nodeValue.length; - startOffset = 0; - } else { - endOffset = 0; - } - } - } else { - // Split startContainer text node if needed - if (startContainer.nodeType == 3 && startOffset > 0 && startOffset < startContainer.nodeValue.length) { - startContainer = splitText(startContainer, startOffset); - startOffset = 0; - } - - // Split endContainer text node if needed - if (endContainer.nodeType == 3 && endOffset > 0 && endOffset < endContainer.nodeValue.length) { - endContainer = splitText(endContainer, endOffset).previousSibling; - endOffset = endContainer.nodeValue.length; - } - } - - return { - startContainer : startContainer, - startOffset : startOffset, - endContainer : endContainer, - endOffset : endOffset - }; - }; - - }; - - tinymce.dom.RangeUtils.compareRanges = function(rng1, rng2) { - if (rng1 && rng2) { - // Compare native IE ranges - if (rng1.item || rng1.duplicate) { - // Both are control ranges and the selected element matches - if (rng1.item && rng2.item && rng1.item(0) === rng2.item(0)) - return true; - - // Both are text ranges and the range matches - if (rng1.isEqual && rng2.isEqual && rng2.isEqual(rng1)) - return true; - } else { - // Compare w3c ranges - return rng1.startContainer == rng2.startContainer && rng1.startOffset == rng2.startOffset; - } - } - - return false; - }; -})(tinymce); -(function(tinymce) { - var Event = tinymce.dom.Event, each = tinymce.each; - - tinymce.create('tinymce.ui.KeyboardNavigation', { - KeyboardNavigation: function(settings, dom) { - var t = this, root = settings.root, items = settings.items, - enableUpDown = settings.enableUpDown, enableLeftRight = settings.enableLeftRight || !settings.enableUpDown, - excludeFromTabOrder = settings.excludeFromTabOrder, - itemFocussed, itemBlurred, rootKeydown, rootFocussed, focussedId; - - dom = dom || tinymce.DOM; - - itemFocussed = function(evt) { - focussedId = evt.target.id; - }; - - itemBlurred = function(evt) { - dom.setAttrib(evt.target.id, 'tabindex', '-1'); - }; - - rootFocussed = function(evt) { - var item = dom.get(focussedId); - dom.setAttrib(item, 'tabindex', '0'); - item.focus(); - }; - - t.focus = function() { - dom.get(focussedId).focus(); - }; - - t.destroy = function() { - each(items, function(item) { - var elm = dom.get(item.id); - - dom.unbind(elm, 'focus', itemFocussed); - dom.unbind(elm, 'blur', itemBlurred); - }); - - var rootElm = dom.get(root); - dom.unbind(rootElm, 'focus', rootFocussed); - dom.unbind(rootElm, 'keydown', rootKeydown); - - items = dom = root = t.focus = itemFocussed = itemBlurred = rootKeydown = rootFocussed = null; - t.destroy = function() {}; - }; - - t.moveFocus = function(dir, evt) { - var idx = -1, controls = t.controls, newFocus; - - if (!focussedId) - return; - - each(items, function(item, index) { - if (item.id === focussedId) { - idx = index; - return false; - } - }); - - idx += dir; - if (idx < 0) { - idx = items.length - 1; - } else if (idx >= items.length) { - idx = 0; - } - - newFocus = items[idx]; - dom.setAttrib(focussedId, 'tabindex', '-1'); - dom.setAttrib(newFocus.id, 'tabindex', '0'); - dom.get(newFocus.id).focus(); - - if (settings.actOnFocus) { - settings.onAction(newFocus.id); - } - - if (evt) - Event.cancel(evt); - }; - - rootKeydown = function(evt) { - var DOM_VK_LEFT = 37, DOM_VK_RIGHT = 39, DOM_VK_UP = 38, DOM_VK_DOWN = 40, DOM_VK_ESCAPE = 27, DOM_VK_ENTER = 14, DOM_VK_RETURN = 13, DOM_VK_SPACE = 32; - - switch (evt.keyCode) { - case DOM_VK_LEFT: - if (enableLeftRight) t.moveFocus(-1); - Event.cancel(evt); - break; - - case DOM_VK_RIGHT: - if (enableLeftRight) t.moveFocus(1); - Event.cancel(evt); - break; - - case DOM_VK_UP: - if (enableUpDown) t.moveFocus(-1); - Event.cancel(evt); - break; - - case DOM_VK_DOWN: - if (enableUpDown) t.moveFocus(1); - Event.cancel(evt); - break; - - case DOM_VK_ESCAPE: - if (settings.onCancel) { - settings.onCancel(); - Event.cancel(evt); - } - break; - - case DOM_VK_ENTER: - case DOM_VK_RETURN: - case DOM_VK_SPACE: - if (settings.onAction) { - settings.onAction(focussedId); - Event.cancel(evt); - } - break; - } - }; - - // Set up state and listeners for each item. - each(items, function(item, idx) { - var tabindex, elm; - - if (!item.id) { - item.id = dom.uniqueId('_mce_item_'); - } - - elm = dom.get(item.id); - - if (excludeFromTabOrder) { - dom.bind(elm, 'blur', itemBlurred); - tabindex = '-1'; - } else { - tabindex = (idx === 0 ? '0' : '-1'); - } - - elm.setAttribute('tabindex', tabindex); - dom.bind(elm, 'focus', itemFocussed); - }); - - // Setup initial state for root element. - if (items[0]){ - focussedId = items[0].id; - } - - dom.setAttrib(root, 'tabindex', '-1'); - - // Setup listeners for root element. - var rootElm = dom.get(root); - dom.bind(rootElm, 'focus', rootFocussed); - dom.bind(rootElm, 'keydown', rootKeydown); - } - }); -})(tinymce); -(function(tinymce) { - // Shorten class names - var DOM = tinymce.DOM, is = tinymce.is; - - tinymce.create('tinymce.ui.Control', { - Control : function(id, s, editor) { - this.id = id; - this.settings = s = s || {}; - this.rendered = false; - this.onRender = new tinymce.util.Dispatcher(this); - this.classPrefix = ''; - this.scope = s.scope || this; - this.disabled = 0; - this.active = 0; - this.editor = editor; - }, - - setAriaProperty : function(property, value) { - var element = DOM.get(this.id + '_aria') || DOM.get(this.id); - if (element) { - DOM.setAttrib(element, 'aria-' + property, !!value); - } - }, - - focus : function() { - DOM.get(this.id).focus(); - }, - - setDisabled : function(s) { - if (s != this.disabled) { - this.setAriaProperty('disabled', s); - - this.setState('Disabled', s); - this.setState('Enabled', !s); - this.disabled = s; - } - }, - - isDisabled : function() { - return this.disabled; - }, - - setActive : function(s) { - if (s != this.active) { - this.setState('Active', s); - this.active = s; - this.setAriaProperty('pressed', s); - } - }, - - isActive : function() { - return this.active; - }, - - setState : function(c, s) { - var n = DOM.get(this.id); - - c = this.classPrefix + c; - - if (s) - DOM.addClass(n, c); - else - DOM.removeClass(n, c); - }, - - isRendered : function() { - return this.rendered; - }, - - renderHTML : function() { - }, - - renderTo : function(n) { - DOM.setHTML(n, this.renderHTML()); - }, - - postRender : function() { - var t = this, b; - - // Set pending states - if (is(t.disabled)) { - b = t.disabled; - t.disabled = -1; - t.setDisabled(b); - } - - if (is(t.active)) { - b = t.active; - t.active = -1; - t.setActive(b); - } - }, - - remove : function() { - DOM.remove(this.id); - this.destroy(); - }, - - destroy : function() { - tinymce.dom.Event.clear(this.id); - } - }); -})(tinymce); -tinymce.create('tinymce.ui.Container:tinymce.ui.Control', { - Container : function(id, s, editor) { - this.parent(id, s, editor); - - this.controls = []; - - this.lookup = {}; - }, - - add : function(c) { - this.lookup[c.id] = c; - this.controls.push(c); - - return c; - }, - - get : function(n) { - return this.lookup[n]; - } -}); - -tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', { - Separator : function(id, s) { - this.parent(id, s); - this.classPrefix = 'mceSeparator'; - this.setDisabled(true); - }, - - renderHTML : function() { - return tinymce.DOM.createHTML('span', {'class' : this.classPrefix, role : 'separator', 'aria-orientation' : 'vertical', tabindex : '-1'}); - } -}); -(function(tinymce) { - var is = tinymce.is, DOM = tinymce.DOM, each = tinymce.each, walk = tinymce.walk; - - tinymce.create('tinymce.ui.MenuItem:tinymce.ui.Control', { - MenuItem : function(id, s) { - this.parent(id, s); - this.classPrefix = 'mceMenuItem'; - }, - - setSelected : function(s) { - this.setState('Selected', s); - this.setAriaProperty('checked', !!s); - this.selected = s; - }, - - isSelected : function() { - return this.selected; - }, - - postRender : function() { - var t = this; - - t.parent(); - - // Set pending state - if (is(t.selected)) - t.setSelected(t.selected); - } - }); -})(tinymce); -(function(tinymce) { - var is = tinymce.is, DOM = tinymce.DOM, each = tinymce.each, walk = tinymce.walk; - - tinymce.create('tinymce.ui.Menu:tinymce.ui.MenuItem', { - Menu : function(id, s) { - var t = this; - - t.parent(id, s); - t.items = {}; - t.collapsed = false; - t.menuCount = 0; - t.onAddItem = new tinymce.util.Dispatcher(this); - }, - - expand : function(d) { - var t = this; - - if (d) { - walk(t, function(o) { - if (o.expand) - o.expand(); - }, 'items', t); - } - - t.collapsed = false; - }, - - collapse : function(d) { - var t = this; - - if (d) { - walk(t, function(o) { - if (o.collapse) - o.collapse(); - }, 'items', t); - } - - t.collapsed = true; - }, - - isCollapsed : function() { - return this.collapsed; - }, - - add : function(o) { - if (!o.settings) - o = new tinymce.ui.MenuItem(o.id || DOM.uniqueId(), o); - - this.onAddItem.dispatch(this, o); - - return this.items[o.id] = o; - }, - - addSeparator : function() { - return this.add({separator : true}); - }, - - addMenu : function(o) { - if (!o.collapse) - o = this.createMenu(o); - - this.menuCount++; - - return this.add(o); - }, - - hasMenus : function() { - return this.menuCount !== 0; - }, - - remove : function(o) { - delete this.items[o.id]; - }, - - removeAll : function() { - var t = this; - - walk(t, function(o) { - if (o.removeAll) - o.removeAll(); - else - o.remove(); - - o.destroy(); - }, 'items', t); - - t.items = {}; - }, - - createMenu : function(o) { - var m = new tinymce.ui.Menu(o.id || DOM.uniqueId(), o); - - m.onAddItem.add(this.onAddItem.dispatch, this.onAddItem); - - return m; - } - }); -})(tinymce); -(function(tinymce) { - var is = tinymce.is, DOM = tinymce.DOM, each = tinymce.each, Event = tinymce.dom.Event, Element = tinymce.dom.Element; - - tinymce.create('tinymce.ui.DropMenu:tinymce.ui.Menu', { - DropMenu : function(id, s) { - s = s || {}; - s.container = s.container || DOM.doc.body; - s.offset_x = s.offset_x || 0; - s.offset_y = s.offset_y || 0; - s.vp_offset_x = s.vp_offset_x || 0; - s.vp_offset_y = s.vp_offset_y || 0; - - if (is(s.icons) && !s.icons) - s['class'] += ' mceNoIcons'; - - this.parent(id, s); - this.onShowMenu = new tinymce.util.Dispatcher(this); - this.onHideMenu = new tinymce.util.Dispatcher(this); - this.classPrefix = 'mceMenu'; - }, - - createMenu : function(s) { - var t = this, cs = t.settings, m; - - s.container = s.container || cs.container; - s.parent = t; - s.constrain = s.constrain || cs.constrain; - s['class'] = s['class'] || cs['class']; - s.vp_offset_x = s.vp_offset_x || cs.vp_offset_x; - s.vp_offset_y = s.vp_offset_y || cs.vp_offset_y; - s.keyboard_focus = cs.keyboard_focus; - m = new tinymce.ui.DropMenu(s.id || DOM.uniqueId(), s); - - m.onAddItem.add(t.onAddItem.dispatch, t.onAddItem); - - return m; - }, - - focus : function() { - var t = this; - if (t.keyboardNav) { - t.keyboardNav.focus(); - } - }, - - update : function() { - var t = this, s = t.settings, tb = DOM.get('menu_' + t.id + '_tbl'), co = DOM.get('menu_' + t.id + '_co'), tw, th; - - tw = s.max_width ? Math.min(tb.offsetWidth, s.max_width) : tb.offsetWidth; - th = s.max_height ? Math.min(tb.offsetHeight, s.max_height) : tb.offsetHeight; - - if (!DOM.boxModel) - t.element.setStyles({width : tw + 2, height : th + 2}); - else - t.element.setStyles({width : tw, height : th}); - - if (s.max_width) - DOM.setStyle(co, 'width', tw); - - if (s.max_height) { - DOM.setStyle(co, 'height', th); - - if (tb.clientHeight < s.max_height) - DOM.setStyle(co, 'overflow', 'hidden'); - } - }, - - showMenu : function(x, y, px) { - var t = this, s = t.settings, co, vp = DOM.getViewPort(), w, h, mx, my, ot = 2, dm, tb, cp = t.classPrefix; - - t.collapse(1); - - if (t.isMenuVisible) - return; - - if (!t.rendered) { - co = DOM.add(t.settings.container, t.renderNode()); - - each(t.items, function(o) { - o.postRender(); - }); - - t.element = new Element('menu_' + t.id, {blocker : 1, container : s.container}); - } else - co = DOM.get('menu_' + t.id); - - // Move layer out of sight unless it's Opera since it scrolls to top of page due to an bug - if (!tinymce.isOpera) - DOM.setStyles(co, {left : -0xFFFF , top : -0xFFFF}); - - DOM.show(co); - t.update(); - - x += s.offset_x || 0; - y += s.offset_y || 0; - vp.w -= 4; - vp.h -= 4; - - // Move inside viewport if not submenu - if (s.constrain) { - w = co.clientWidth - ot; - h = co.clientHeight - ot; - mx = vp.x + vp.w; - my = vp.y + vp.h; - - if ((x + s.vp_offset_x + w) > mx) - x = px ? px - w : Math.max(0, (mx - s.vp_offset_x) - w); - - if ((y + s.vp_offset_y + h) > my) - y = Math.max(0, (my - s.vp_offset_y) - h); - } - - DOM.setStyles(co, {left : x , top : y}); - t.element.update(); - - t.isMenuVisible = 1; - t.mouseClickFunc = Event.add(co, 'click', function(e) { - var m; - - e = e.target; - - if (e && (e = DOM.getParent(e, 'tr')) && !DOM.hasClass(e, cp + 'ItemSub')) { - m = t.items[e.id]; - - if (m.isDisabled()) - return; - - dm = t; - - while (dm) { - if (dm.hideMenu) - dm.hideMenu(); - - dm = dm.settings.parent; - } - - if (m.settings.onclick) - m.settings.onclick(e); - - return false; // Cancel to fix onbeforeunload problem - } - }); - - if (t.hasMenus()) { - t.mouseOverFunc = Event.add(co, 'mouseover', function(e) { - var m, r, mi; - - e = e.target; - if (e && (e = DOM.getParent(e, 'tr'))) { - m = t.items[e.id]; - - if (t.lastMenu) - t.lastMenu.collapse(1); - - if (m.isDisabled()) - return; - - if (e && DOM.hasClass(e, cp + 'ItemSub')) { - //p = DOM.getPos(s.container); - r = DOM.getRect(e); - m.showMenu((r.x + r.w - ot), r.y - ot, r.x); - t.lastMenu = m; - DOM.addClass(DOM.get(m.id).firstChild, cp + 'ItemActive'); - } - } - }); - } - - Event.add(co, 'keydown', t._keyHandler, t); - - t.onShowMenu.dispatch(t); - - if (s.keyboard_focus) { - t._setupKeyboardNav(); - } - }, - - hideMenu : function(c) { - var t = this, co = DOM.get('menu_' + t.id), e; - - if (!t.isMenuVisible) - return; - - if (t.keyboardNav) t.keyboardNav.destroy(); - Event.remove(co, 'mouseover', t.mouseOverFunc); - Event.remove(co, 'click', t.mouseClickFunc); - Event.remove(co, 'keydown', t._keyHandler); - DOM.hide(co); - t.isMenuVisible = 0; - - if (!c) - t.collapse(1); - - if (t.element) - t.element.hide(); - - if (e = DOM.get(t.id)) - DOM.removeClass(e.firstChild, t.classPrefix + 'ItemActive'); - - t.onHideMenu.dispatch(t); - }, - - add : function(o) { - var t = this, co; - - o = t.parent(o); - - if (t.isRendered && (co = DOM.get('menu_' + t.id))) - t._add(DOM.select('tbody', co)[0], o); - - return o; - }, - - collapse : function(d) { - this.parent(d); - this.hideMenu(1); - }, - - remove : function(o) { - DOM.remove(o.id); - this.destroy(); - - return this.parent(o); - }, - - destroy : function() { - var t = this, co = DOM.get('menu_' + t.id); - - if (t.keyboardNav) t.keyboardNav.destroy(); - Event.remove(co, 'mouseover', t.mouseOverFunc); - Event.remove(DOM.select('a', co), 'focus', t.mouseOverFunc); - Event.remove(co, 'click', t.mouseClickFunc); - Event.remove(co, 'keydown', t._keyHandler); - - if (t.element) - t.element.remove(); - - DOM.remove(co); - }, - - renderNode : function() { - var t = this, s = t.settings, n, tb, co, w; - - w = DOM.create('div', {role: 'listbox', id : 'menu_' + t.id, 'class' : s['class'], 'style' : 'position:absolute;left:0;top:0;z-index:200000;outline:0'}); - if (t.settings.parent) { - DOM.setAttrib(w, 'aria-parent', 'menu_' + t.settings.parent.id); - } - co = DOM.add(w, 'div', {role: 'presentation', id : 'menu_' + t.id + '_co', 'class' : t.classPrefix + (s['class'] ? ' ' + s['class'] : '')}); - t.element = new Element('menu_' + t.id, {blocker : 1, container : s.container}); - - if (s.menu_line) - DOM.add(co, 'span', {'class' : t.classPrefix + 'Line'}); - -// n = DOM.add(co, 'div', {id : 'menu_' + t.id + '_co', 'class' : 'mceMenuContainer'}); - n = DOM.add(co, 'table', {role: 'presentation', id : 'menu_' + t.id + '_tbl', border : 0, cellPadding : 0, cellSpacing : 0}); - tb = DOM.add(n, 'tbody'); - - each(t.items, function(o) { - t._add(tb, o); - }); - - t.rendered = true; - - return w; - }, - - // Internal functions - _setupKeyboardNav : function(){ - var contextMenu, menuItems, t=this; - contextMenu = DOM.get('menu_' + t.id); - menuItems = DOM.select('a[role=option]', 'menu_' + t.id); - menuItems.splice(0,0,contextMenu); - t.keyboardNav = new tinymce.ui.KeyboardNavigation({ - root: 'menu_' + t.id, - items: menuItems, - onCancel: function() { - t.hideMenu(); - }, - enableUpDown: true - }); - contextMenu.focus(); - }, - - _keyHandler : function(evt) { - var t = this, e; - switch (evt.keyCode) { - case 37: // Left - if (t.settings.parent) { - t.hideMenu(); - t.settings.parent.focus(); - Event.cancel(evt); - } - break; - case 39: // Right - if (t.mouseOverFunc) - t.mouseOverFunc(evt); - break; - } - }, - - _add : function(tb, o) { - var n, s = o.settings, a, ro, it, cp = this.classPrefix, ic; - - if (s.separator) { - ro = DOM.add(tb, 'tr', {id : o.id, 'class' : cp + 'ItemSeparator'}); - DOM.add(ro, 'td', {'class' : cp + 'ItemSeparator'}); - - if (n = ro.previousSibling) - DOM.addClass(n, 'mceLast'); - - return; - } - - n = ro = DOM.add(tb, 'tr', {id : o.id, 'class' : cp + 'Item ' + cp + 'ItemEnabled'}); - n = it = DOM.add(n, s.titleItem ? 'th' : 'td'); - n = a = DOM.add(n, 'a', {id: o.id + '_aria', role: s.titleItem ? 'presentation' : 'option', href : 'javascript:;', onclick : "return false;", onmousedown : 'return false;'}); - - if (s.parent) { - DOM.setAttrib(a, 'aria-haspopup', 'true'); - DOM.setAttrib(a, 'aria-owns', 'menu_' + o.id); - } - - DOM.addClass(it, s['class']); -// n = DOM.add(n, 'span', {'class' : 'item'}); - - ic = DOM.add(n, 'span', {'class' : 'mceIcon' + (s.icon ? ' mce_' + s.icon : '')}); - - if (s.icon_src) - DOM.add(ic, 'img', {src : s.icon_src}); - - n = DOM.add(n, s.element || 'span', {'class' : 'mceText', title : o.settings.title}, o.settings.title); - - if (o.settings.style) { - if (typeof o.settings.style == "function") - o.settings.style = o.settings.style(); - - DOM.setAttrib(n, 'style', o.settings.style); - } - - if (tb.childNodes.length == 1) - DOM.addClass(ro, 'mceFirst'); - - if ((n = ro.previousSibling) && DOM.hasClass(n, cp + 'ItemSeparator')) - DOM.addClass(ro, 'mceFirst'); - - if (o.collapse) - DOM.addClass(ro, cp + 'ItemSub'); - - if (n = ro.previousSibling) - DOM.removeClass(n, 'mceLast'); - - DOM.addClass(ro, 'mceLast'); - } - }); -})(tinymce); -(function(tinymce) { - var DOM = tinymce.DOM; - - tinymce.create('tinymce.ui.Button:tinymce.ui.Control', { - Button : function(id, s, ed) { - this.parent(id, s, ed); - this.classPrefix = 'mceButton'; - }, - - renderHTML : function() { - var cp = this.classPrefix, s = this.settings, h, l; - - l = DOM.encode(s.label || ''); - h = ''; - if (s.image && !(this.editor &&this.editor.forcedHighContrastMode) ) - h += '' + DOM.encode(s.title) + '' + (l ? '' + l + '' : ''); - else - h += '' + (l ? '' + l + '' : ''); - - h += ''; - h += ''; - return h; - }, - - postRender : function() { - var t = this, s = t.settings, imgBookmark; - - // In IE a large image that occupies the entire editor area will be deselected when a button is clicked, so - // need to keep the selection in case the selection is lost - if (tinymce.isIE && t.editor) { - tinymce.dom.Event.add(t.id, 'mousedown', function(e) { - var nodeName = t.editor.selection.getNode().nodeName; - imgBookmark = nodeName === 'IMG' ? t.editor.selection.getBookmark() : null; - }); - } - tinymce.dom.Event.add(t.id, 'click', function(e) { - if (!t.isDisabled()) { - // restore the selection in case the selection is lost in IE - if (tinymce.isIE && t.editor && imgBookmark !== null) { - t.editor.selection.moveToBookmark(imgBookmark); - } - return s.onclick.call(s.scope, e); - } - }); - tinymce.dom.Event.add(t.id, 'keydown', function(e) { - if (!t.isDisabled() && e.keyCode==tinymce.VK.SPACEBAR) { - tinymce.dom.Event.cancel(e); - return s.onclick.call(s.scope, e); - } - }); - } - }); -})(tinymce); -(function(tinymce) { - var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each, Dispatcher = tinymce.util.Dispatcher, undef; - - tinymce.create('tinymce.ui.ListBox:tinymce.ui.Control', { - ListBox : function(id, s, ed) { - var t = this; - - t.parent(id, s, ed); - - t.items = []; - - t.onChange = new Dispatcher(t); - - t.onPostRender = new Dispatcher(t); - - t.onAdd = new Dispatcher(t); - - t.onRenderMenu = new tinymce.util.Dispatcher(this); - - t.classPrefix = 'mceListBox'; - t.marked = {}; - }, - - select : function(va) { - var t = this, fv, f; - - t.marked = {}; - - if (va == undef) - return t.selectByIndex(-1); - - // Is string or number make function selector - if (va && typeof(va)=="function") - f = va; - else { - f = function(v) { - return v == va; - }; - } - - // Do we need to do something? - if (va != t.selectedValue) { - // Find item - each(t.items, function(o, i) { - if (f(o.value)) { - fv = 1; - t.selectByIndex(i); - return false; - } - }); - - if (!fv) - t.selectByIndex(-1); - } - }, - - selectByIndex : function(idx) { - var t = this, e, o, label; - - t.marked = {}; - - if (idx != t.selectedIndex) { - e = DOM.get(t.id + '_text'); - label = DOM.get(t.id + '_voiceDesc'); - o = t.items[idx]; - - if (o) { - t.selectedValue = o.value; - t.selectedIndex = idx; - DOM.setHTML(e, DOM.encode(o.title)); - DOM.setHTML(label, t.settings.title + " - " + o.title); - DOM.removeClass(e, 'mceTitle'); - DOM.setAttrib(t.id, 'aria-valuenow', o.title); - } else { - DOM.setHTML(e, DOM.encode(t.settings.title)); - DOM.setHTML(label, DOM.encode(t.settings.title)); - DOM.addClass(e, 'mceTitle'); - t.selectedValue = t.selectedIndex = null; - DOM.setAttrib(t.id, 'aria-valuenow', t.settings.title); - } - e = 0; - } - }, - - mark : function(value) { - this.marked[value] = true; - }, - - add : function(n, v, o) { - var t = this; - - o = o || {}; - o = tinymce.extend(o, { - title : n, - value : v - }); - - t.items.push(o); - t.onAdd.dispatch(t, o); - }, - - getLength : function() { - return this.items.length; - }, - - renderHTML : function() { - var h = '', t = this, s = t.settings, cp = t.classPrefix; - - h = ''; - h += ''; - h += ''; - h += ''; - - return h; - }, - - showMenu : function() { - var t = this, p2, e = DOM.get(this.id), m; - - if (t.isDisabled() || t.items.length === 0) - return; - - if (t.menu && t.menu.isMenuVisible) - return t.hideMenu(); - - if (!t.isMenuRendered) { - t.renderMenu(); - t.isMenuRendered = true; - } - - p2 = DOM.getPos(e); - - m = t.menu; - m.settings.offset_x = p2.x; - m.settings.offset_y = p2.y; - m.settings.keyboard_focus = !tinymce.isOpera; // Opera is buggy when it comes to auto focus - - // Select in menu - each(t.items, function(o) { - if (m.items[o.id]) { - m.items[o.id].setSelected(0); - } - }); - - each(t.items, function(o) { - if (m.items[o.id] && t.marked[o.value]) { - m.items[o.id].setSelected(1); - } - - if (o.value === t.selectedValue) { - m.items[o.id].setSelected(1); - } - }); - - m.showMenu(0, e.clientHeight); - - Event.add(DOM.doc, 'mousedown', t.hideMenu, t); - DOM.addClass(t.id, t.classPrefix + 'Selected'); - - //DOM.get(t.id + '_text').focus(); - }, - - hideMenu : function(e) { - var t = this; - - if (t.menu && t.menu.isMenuVisible) { - DOM.removeClass(t.id, t.classPrefix + 'Selected'); - - // Prevent double toogles by canceling the mouse click event to the button - if (e && e.type == "mousedown" && (e.target.id == t.id + '_text' || e.target.id == t.id + '_open')) - return; - - if (!e || !DOM.getParent(e.target, '.mceMenu')) { - DOM.removeClass(t.id, t.classPrefix + 'Selected'); - Event.remove(DOM.doc, 'mousedown', t.hideMenu, t); - t.menu.hideMenu(); - } - } - }, - - renderMenu : function() { - var t = this, m; - - m = t.settings.control_manager.createDropMenu(t.id + '_menu', { - menu_line : 1, - 'class' : t.classPrefix + 'Menu mceNoIcons', - max_width : 250, - max_height : 150 - }); - - m.onHideMenu.add(function() { - t.hideMenu(); - t.focus(); - }); - - m.add({ - title : t.settings.title, - 'class' : 'mceMenuItemTitle', - onclick : function() { - if (t.settings.onselect('') !== false) - t.select(''); // Must be runned after - } - }); - - each(t.items, function(o) { - // No value then treat it as a title - if (o.value === undef) { - m.add({ - title : o.title, - role : "option", - 'class' : 'mceMenuItemTitle', - onclick : function() { - if (t.settings.onselect('') !== false) - t.select(''); // Must be runned after - } - }); - } else { - o.id = DOM.uniqueId(); - o.role= "option"; - o.onclick = function() { - if (t.settings.onselect(o.value) !== false) - t.select(o.value); // Must be runned after - }; - - m.add(o); - } - }); - - t.onRenderMenu.dispatch(t, m); - t.menu = m; - }, - - postRender : function() { - var t = this, cp = t.classPrefix; - - Event.add(t.id, 'click', t.showMenu, t); - Event.add(t.id, 'keydown', function(evt) { - if (evt.keyCode == 32) { // Space - t.showMenu(evt); - Event.cancel(evt); - } - }); - Event.add(t.id, 'focus', function() { - if (!t._focused) { - t.keyDownHandler = Event.add(t.id, 'keydown', function(e) { - if (e.keyCode == 40) { - t.showMenu(); - Event.cancel(e); - } - }); - t.keyPressHandler = Event.add(t.id, 'keypress', function(e) { - var v; - if (e.keyCode == 13) { - // Fake select on enter - v = t.selectedValue; - t.selectedValue = null; // Needs to be null to fake change - Event.cancel(e); - t.settings.onselect(v); - } - }); - } - - t._focused = 1; - }); - Event.add(t.id, 'blur', function() { - Event.remove(t.id, 'keydown', t.keyDownHandler); - Event.remove(t.id, 'keypress', t.keyPressHandler); - t._focused = 0; - }); - - // Old IE doesn't have hover on all elements - if (tinymce.isIE6 || !DOM.boxModel) { - Event.add(t.id, 'mouseover', function() { - if (!DOM.hasClass(t.id, cp + 'Disabled')) - DOM.addClass(t.id, cp + 'Hover'); - }); - - Event.add(t.id, 'mouseout', function() { - if (!DOM.hasClass(t.id, cp + 'Disabled')) - DOM.removeClass(t.id, cp + 'Hover'); - }); - } - - t.onPostRender.dispatch(t, DOM.get(t.id)); - }, - - destroy : function() { - this.parent(); - - Event.clear(this.id + '_text'); - Event.clear(this.id + '_open'); - } - }); -})(tinymce); -(function(tinymce) { - var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each, Dispatcher = tinymce.util.Dispatcher, undef; - - tinymce.create('tinymce.ui.NativeListBox:tinymce.ui.ListBox', { - NativeListBox : function(id, s) { - this.parent(id, s); - this.classPrefix = 'mceNativeListBox'; - }, - - setDisabled : function(s) { - DOM.get(this.id).disabled = s; - this.setAriaProperty('disabled', s); - }, - - isDisabled : function() { - return DOM.get(this.id).disabled; - }, - - select : function(va) { - var t = this, fv, f; - - if (va == undef) - return t.selectByIndex(-1); - - // Is string or number make function selector - if (va && typeof(va)=="function") - f = va; - else { - f = function(v) { - return v == va; - }; - } - - // Do we need to do something? - if (va != t.selectedValue) { - // Find item - each(t.items, function(o, i) { - if (f(o.value)) { - fv = 1; - t.selectByIndex(i); - return false; - } - }); - - if (!fv) - t.selectByIndex(-1); - } - }, - - selectByIndex : function(idx) { - DOM.get(this.id).selectedIndex = idx + 1; - this.selectedValue = this.items[idx] ? this.items[idx].value : null; - }, - - add : function(n, v, a) { - var o, t = this; - - a = a || {}; - a.value = v; - - if (t.isRendered()) - DOM.add(DOM.get(this.id), 'option', a, n); - - o = { - title : n, - value : v, - attribs : a - }; - - t.items.push(o); - t.onAdd.dispatch(t, o); - }, - - getLength : function() { - return this.items.length; - }, - - renderHTML : function() { - var h, t = this; - - h = DOM.createHTML('option', {value : ''}, '-- ' + t.settings.title + ' --'); - - each(t.items, function(it) { - h += DOM.createHTML('option', {value : it.value}, it.title); - }); - - h = DOM.createHTML('select', {id : t.id, 'class' : 'mceNativeListBox', 'aria-labelledby': t.id + '_aria'}, h); - h += DOM.createHTML('span', {id : t.id + '_aria', 'style': 'display: none'}, t.settings.title); - return h; - }, - - postRender : function() { - var t = this, ch, changeListenerAdded = true; - - t.rendered = true; - - function onChange(e) { - var v = t.items[e.target.selectedIndex - 1]; - - if (v && (v = v.value)) { - t.onChange.dispatch(t, v); - - if (t.settings.onselect) - t.settings.onselect(v); - } - }; - - Event.add(t.id, 'change', onChange); - - // Accessibility keyhandler - Event.add(t.id, 'keydown', function(e) { - var bf, DOM_VK_LEFT = 37, DOM_VK_RIGHT = 39, DOM_VK_UP = 38, DOM_VK_DOWN = 40, DOM_VK_RETURN = 13, DOM_VK_SPACE = 32; - - Event.remove(t.id, 'change', ch); - changeListenerAdded = false; - - bf = Event.add(t.id, 'blur', function() { - if (changeListenerAdded) return; - changeListenerAdded = true; - Event.add(t.id, 'change', onChange); - Event.remove(t.id, 'blur', bf); - }); - - if (e.keyCode == DOM_VK_RETURN || e.keyCode == DOM_VK_SPACE) { - onChange(e); - return Event.cancel(e); - } else if (e.keyCode == DOM_VK_DOWN || e.keyCode == DOM_VK_UP) { - // allow native implementation (navigate select element options) - e.stopImmediatePropagation(); - } - }); - - t.onPostRender.dispatch(t, DOM.get(t.id)); - } - }); -})(tinymce); -(function(tinymce) { - var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each; - - tinymce.create('tinymce.ui.MenuButton:tinymce.ui.Button', { - MenuButton : function(id, s, ed) { - this.parent(id, s, ed); - - this.onRenderMenu = new tinymce.util.Dispatcher(this); - - s.menu_container = s.menu_container || DOM.doc.body; - }, - - showMenu : function() { - var t = this, p1, p2, e = DOM.get(t.id), m; - - if (t.isDisabled()) - return; - - if (!t.isMenuRendered) { - t.renderMenu(); - t.isMenuRendered = true; - } - - if (t.isMenuVisible) - return t.hideMenu(); - - p1 = DOM.getPos(t.settings.menu_container); - p2 = DOM.getPos(e); - - m = t.menu; - m.settings.offset_x = p2.x; - m.settings.offset_y = p2.y; - m.settings.vp_offset_x = p2.x; - m.settings.vp_offset_y = p2.y; - m.settings.keyboard_focus = t._focused; - m.showMenu(0, e.firstChild.clientHeight); - - Event.add(DOM.doc, 'mousedown', t.hideMenu, t); - t.setState('Selected', 1); - - t.isMenuVisible = 1; - }, - - renderMenu : function() { - var t = this, m; - - m = t.settings.control_manager.createDropMenu(t.id + '_menu', { - menu_line : 1, - 'class' : this.classPrefix + 'Menu', - icons : t.settings.icons - }); - - m.onHideMenu.add(function() { - t.hideMenu(); - t.focus(); - }); - - t.onRenderMenu.dispatch(t, m); - t.menu = m; - }, - - hideMenu : function(e) { - var t = this; - - // Prevent double toogles by canceling the mouse click event to the button - if (e && e.type == "mousedown" && DOM.getParent(e.target, function(e) {return e.id === t.id || e.id === t.id + '_open';})) - return; - - if (!e || !DOM.getParent(e.target, '.mceMenu')) { - t.setState('Selected', 0); - Event.remove(DOM.doc, 'mousedown', t.hideMenu, t); - if (t.menu) - t.menu.hideMenu(); - } - - t.isMenuVisible = 0; - }, - - postRender : function() { - var t = this, s = t.settings; - - Event.add(t.id, 'click', function() { - if (!t.isDisabled()) { - if (s.onclick) - s.onclick(t.value); - - t.showMenu(); - } - }); - } - }); -})(tinymce); -(function(tinymce) { - var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each; - - tinymce.create('tinymce.ui.SplitButton:tinymce.ui.MenuButton', { - SplitButton : function(id, s, ed) { - this.parent(id, s, ed); - this.classPrefix = 'mceSplitButton'; - }, - - renderHTML : function() { - var h, t = this, s = t.settings, h1; - - h = ''; - - if (s.image) - h1 = DOM.createHTML('img ', {src : s.image, role: 'presentation', 'class' : 'mceAction ' + s['class']}); - else - h1 = DOM.createHTML('span', {'class' : 'mceAction ' + s['class']}, ''); - - h1 += DOM.createHTML('span', {'class': 'mceVoiceLabel mceIconOnly', id: t.id + '_voice', style: 'display:none;'}, s.title); - h += '' + DOM.createHTML('a', {role: 'button', id : t.id + '_action', tabindex: '-1', href : 'javascript:;', 'class' : 'mceAction ' + s['class'], onclick : "return false;", onmousedown : 'return false;', title : s.title}, h1) + ''; - - h1 = DOM.createHTML('span', {'class' : 'mceOpen ' + s['class']}, ''); - h += '' + DOM.createHTML('a', {role: 'button', id : t.id + '_open', tabindex: '-1', href : 'javascript:;', 'class' : 'mceOpen ' + s['class'], onclick : "return false;", onmousedown : 'return false;', title : s.title}, h1) + ''; - - h += ''; - h = DOM.createHTML('table', { role: 'presentation', 'class' : 'mceSplitButton mceSplitButtonEnabled ' + s['class'], cellpadding : '0', cellspacing : '0', title : s.title}, h); - return DOM.createHTML('div', {id : t.id, role: 'button', tabindex: '0', 'aria-labelledby': t.id + '_voice', 'aria-haspopup': 'true'}, h); - }, - - postRender : function() { - var t = this, s = t.settings, activate; - - if (s.onclick) { - activate = function(evt) { - if (!t.isDisabled()) { - s.onclick(t.value); - Event.cancel(evt); - } - }; - Event.add(t.id + '_action', 'click', activate); - Event.add(t.id, ['click', 'keydown'], function(evt) { - var DOM_VK_SPACE = 32, DOM_VK_ENTER = 14, DOM_VK_RETURN = 13, DOM_VK_UP = 38, DOM_VK_DOWN = 40; - if ((evt.keyCode === 32 || evt.keyCode === 13 || evt.keyCode === 14) && !evt.altKey && !evt.ctrlKey && !evt.metaKey) { - activate(); - Event.cancel(evt); - } else if (evt.type === 'click' || evt.keyCode === DOM_VK_DOWN) { - t.showMenu(); - Event.cancel(evt); - } - }); - } - - Event.add(t.id + '_open', 'click', function (evt) { - t.showMenu(); - Event.cancel(evt); - }); - Event.add([t.id, t.id + '_open'], 'focus', function() {t._focused = 1;}); - Event.add([t.id, t.id + '_open'], 'blur', function() {t._focused = 0;}); - - // Old IE doesn't have hover on all elements - if (tinymce.isIE6 || !DOM.boxModel) { - Event.add(t.id, 'mouseover', function() { - if (!DOM.hasClass(t.id, 'mceSplitButtonDisabled')) - DOM.addClass(t.id, 'mceSplitButtonHover'); - }); - - Event.add(t.id, 'mouseout', function() { - if (!DOM.hasClass(t.id, 'mceSplitButtonDisabled')) - DOM.removeClass(t.id, 'mceSplitButtonHover'); - }); - } - }, - - destroy : function() { - this.parent(); - - Event.clear(this.id + '_action'); - Event.clear(this.id + '_open'); - Event.clear(this.id); - } - }); -})(tinymce); -(function(tinymce) { - var DOM = tinymce.DOM, Event = tinymce.dom.Event, is = tinymce.is, each = tinymce.each; - - tinymce.create('tinymce.ui.ColorSplitButton:tinymce.ui.SplitButton', { - ColorSplitButton : function(id, s, ed) { - var t = this; - - t.parent(id, s, ed); - - t.settings = s = tinymce.extend({ - colors : '000000,993300,333300,003300,003366,000080,333399,333333,800000,FF6600,808000,008000,008080,0000FF,666699,808080,FF0000,FF9900,99CC00,339966,33CCCC,3366FF,800080,999999,FF00FF,FFCC00,FFFF00,00FF00,00FFFF,00CCFF,993366,C0C0C0,FF99CC,FFCC99,FFFF99,CCFFCC,CCFFFF,99CCFF,CC99FF,FFFFFF', - grid_width : 8, - default_color : '#888888' - }, t.settings); - - t.onShowMenu = new tinymce.util.Dispatcher(t); - - t.onHideMenu = new tinymce.util.Dispatcher(t); - - t.value = s.default_color; - }, - - showMenu : function() { - var t = this, r, p, e, p2; - - if (t.isDisabled()) - return; - - if (!t.isMenuRendered) { - t.renderMenu(); - t.isMenuRendered = true; - } - - if (t.isMenuVisible) - return t.hideMenu(); - - e = DOM.get(t.id); - DOM.show(t.id + '_menu'); - DOM.addClass(e, 'mceSplitButtonSelected'); - p2 = DOM.getPos(e); - DOM.setStyles(t.id + '_menu', { - left : p2.x, - top : p2.y + e.firstChild.clientHeight, - zIndex : 200000 - }); - e = 0; - - Event.add(DOM.doc, 'mousedown', t.hideMenu, t); - t.onShowMenu.dispatch(t); - - if (t._focused) { - t._keyHandler = Event.add(t.id + '_menu', 'keydown', function(e) { - if (e.keyCode == 27) - t.hideMenu(); - }); - - DOM.select('a', t.id + '_menu')[0].focus(); // Select first link - } - - t.keyboardNav = new tinymce.ui.KeyboardNavigation({ - root: t.id + '_menu', - items: DOM.select('a', t.id + '_menu'), - onCancel: function() { - t.hideMenu(); - t.focus(); - } - }); - - t.keyboardNav.focus(); - t.isMenuVisible = 1; - }, - - hideMenu : function(e) { - var t = this; - - if (t.isMenuVisible) { - // Prevent double toogles by canceling the mouse click event to the button - if (e && e.type == "mousedown" && DOM.getParent(e.target, function(e) {return e.id === t.id + '_open';})) - return; - - if (!e || !DOM.getParent(e.target, '.mceSplitButtonMenu')) { - DOM.removeClass(t.id, 'mceSplitButtonSelected'); - Event.remove(DOM.doc, 'mousedown', t.hideMenu, t); - Event.remove(t.id + '_menu', 'keydown', t._keyHandler); - DOM.hide(t.id + '_menu'); - } - - t.isMenuVisible = 0; - t.onHideMenu.dispatch(); - t.keyboardNav.destroy(); - } - }, - - renderMenu : function() { - var t = this, m, i = 0, s = t.settings, n, tb, tr, w, context; - - w = DOM.add(s.menu_container, 'div', {role: 'listbox', id : t.id + '_menu', 'class' : s.menu_class + ' ' + s['class'], style : 'position:absolute;left:0;top:-1000px;'}); - m = DOM.add(w, 'div', {'class' : s['class'] + ' mceSplitButtonMenu'}); - DOM.add(m, 'span', {'class' : 'mceMenuLine'}); - - n = DOM.add(m, 'table', {role: 'presentation', 'class' : 'mceColorSplitMenu'}); - tb = DOM.add(n, 'tbody'); - - // Generate color grid - i = 0; - each(is(s.colors, 'array') ? s.colors : s.colors.split(','), function(c) { - c = c.replace(/^#/, ''); - - if (!i--) { - tr = DOM.add(tb, 'tr'); - i = s.grid_width - 1; - } - - n = DOM.add(tr, 'td'); - var settings = { - href : 'javascript:;', - style : { - backgroundColor : '#' + c - }, - 'title': t.editor.getLang('colors.' + c, c), - 'data-mce-color' : '#' + c - }; - - // adding a proper ARIA role = button causes JAWS to read things incorrectly on IE. - if (!tinymce.isIE ) { - settings.role = 'option'; - } - - n = DOM.add(n, 'a', settings); - - if (t.editor.forcedHighContrastMode) { - n = DOM.add(n, 'canvas', { width: 16, height: 16, 'aria-hidden': 'true' }); - if (n.getContext && (context = n.getContext("2d"))) { - context.fillStyle = '#' + c; - context.fillRect(0, 0, 16, 16); - } else { - // No point leaving a canvas element around if it's not supported for drawing on anyway. - DOM.remove(n); - } - } - }); - - if (s.more_colors_func) { - n = DOM.add(tb, 'tr'); - n = DOM.add(n, 'td', {colspan : s.grid_width, 'class' : 'mceMoreColors'}); - n = DOM.add(n, 'a', {role: 'option', id : t.id + '_more', href : 'javascript:;', onclick : 'return false;', 'class' : 'mceMoreColors'}, s.more_colors_title); - - Event.add(n, 'click', function(e) { - s.more_colors_func.call(s.more_colors_scope || this); - return Event.cancel(e); // Cancel to fix onbeforeunload problem - }); - } - - DOM.addClass(m, 'mceColorSplitMenu'); - - // Prevent IE from scrolling and hindering click to occur #4019 - Event.add(t.id + '_menu', 'mousedown', function(e) {return Event.cancel(e);}); - - Event.add(t.id + '_menu', 'click', function(e) { - var c; - - e = DOM.getParent(e.target, 'a', tb); - - if (e && e.nodeName.toLowerCase() == 'a' && (c = e.getAttribute('data-mce-color'))) - t.setColor(c); - - return false; // Prevent IE auto save warning - }); - - return w; - }, - - setColor : function(c) { - this.displayColor(c); - this.hideMenu(); - this.settings.onselect(c); - }, - - displayColor : function(c) { - var t = this; - - DOM.setStyle(t.id + '_preview', 'backgroundColor', c); - - t.value = c; - }, - - postRender : function() { - var t = this, id = t.id; - - t.parent(); - DOM.add(id + '_action', 'div', {id : id + '_preview', 'class' : 'mceColorPreview'}); - DOM.setStyle(t.id + '_preview', 'backgroundColor', t.value); - }, - - destroy : function() { - var self = this; - - self.parent(); - - Event.clear(self.id + '_menu'); - Event.clear(self.id + '_more'); - DOM.remove(self.id + '_menu'); - - if (self.keyboardNav) { - self.keyboardNav.destroy(); - } - } - }); -})(tinymce); -(function(tinymce) { -// Shorten class names -var dom = tinymce.DOM, each = tinymce.each, Event = tinymce.dom.Event; -tinymce.create('tinymce.ui.ToolbarGroup:tinymce.ui.Container', { - renderHTML : function() { - var t = this, h = [], controls = t.controls, each = tinymce.each, settings = t.settings; - - h.push('
    '); - //TODO: ACC test this out - adding a role = application for getting the landmarks working well. - h.push(""); - h.push(''); - each(controls, function(toolbar) { - h.push(toolbar.renderHTML()); - }); - h.push(""); - h.push('
    '); - - return h.join(''); - }, - - focus : function() { - var t = this; - dom.get(t.id).focus(); - }, - - postRender : function() { - var t = this, items = []; - - each(t.controls, function(toolbar) { - each (toolbar.controls, function(control) { - if (control.id) { - items.push(control); - } - }); - }); - - t.keyNav = new tinymce.ui.KeyboardNavigation({ - root: t.id, - items: items, - onCancel: function() { - //Move focus if webkit so that navigation back will read the item. - if (tinymce.isWebKit) { - dom.get(t.editor.id+"_ifr").focus(); - } - t.editor.focus(); - }, - excludeFromTabOrder: !t.settings.tab_focus_toolbar - }); - }, - - destroy : function() { - var self = this; - - self.parent(); - self.keyNav.destroy(); - Event.clear(self.id); - } -}); -})(tinymce); -(function(tinymce) { -// Shorten class names -var dom = tinymce.DOM, each = tinymce.each; -tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { - renderHTML : function() { - var t = this, h = '', c, co, s = t.settings, i, pr, nx, cl; - - cl = t.controls; - for (i=0; i')); - } - - // Add toolbar end before list box and after the previous button - // This is to fix the o2k7 editor skins - if (pr && co.ListBox) { - if (pr.Button || pr.SplitButton) - h += dom.createHTML('td', {'class' : 'mceToolbarEnd'}, dom.createHTML('span', null, '')); - } - - // Render control HTML - - // IE 8 quick fix, needed to propertly generate a hit area for anchors - if (dom.stdMode) - h += '' + co.renderHTML() + ''; - else - h += '' + co.renderHTML() + ''; - - // Add toolbar start after list box and before the next button - // This is to fix the o2k7 editor skins - if (nx && co.ListBox) { - if (nx.Button || nx.SplitButton) - h += dom.createHTML('td', {'class' : 'mceToolbarStart'}, dom.createHTML('span', null, '')); - } - } - - c = 'mceToolbarEnd'; - - if (co.Button) - c += ' mceToolbarEndButton'; - else if (co.SplitButton) - c += ' mceToolbarEndSplitButton'; - else if (co.ListBox) - c += ' mceToolbarEndListBox'; - - h += dom.createHTML('td', {'class' : c}, dom.createHTML('span', null, '')); - - return dom.createHTML('table', {id : t.id, 'class' : 'mceToolbar' + (s['class'] ? ' ' + s['class'] : ''), cellpadding : '0', cellspacing : '0', align : t.settings.align || '', role: 'presentation', tabindex: '-1'}, '' + h + ''); - } -}); -})(tinymce); -(function(tinymce) { - var Dispatcher = tinymce.util.Dispatcher, each = tinymce.each; - - tinymce.create('tinymce.AddOnManager', { - AddOnManager : function() { - var self = this; - - self.items = []; - self.urls = {}; - self.lookup = {}; - self.onAdd = new Dispatcher(self); - }, - - get : function(n) { - if (this.lookup[n]) { - return this.lookup[n].instance; - } else { - return undefined; - } - }, - - dependencies : function(n) { - var result; - if (this.lookup[n]) { - result = this.lookup[n].dependencies; - } - return result || []; - }, - - requireLangPack : function(n) { - var s = tinymce.settings; - - if (s && s.language && s.language_load !== false) - tinymce.ScriptLoader.add(this.urls[n] + '/langs/' + s.language + '.js'); - }, - - add : function(id, o, dependencies) { - this.items.push(o); - this.lookup[id] = {instance:o, dependencies:dependencies}; - this.onAdd.dispatch(this, id, o); - - return o; - }, - createUrl: function(baseUrl, dep) { - if (typeof dep === "object") { - return dep - } else { - return {prefix: baseUrl.prefix, resource: dep, suffix: baseUrl.suffix}; - } - }, - - addComponents: function(pluginName, scripts) { - var pluginUrl = this.urls[pluginName]; - tinymce.each(scripts, function(script){ - tinymce.ScriptLoader.add(pluginUrl+"/"+script); - }); - }, - - load : function(n, u, cb, s) { - var t = this, url = u; - - function loadDependencies() { - var dependencies = t.dependencies(n); - tinymce.each(dependencies, function(dep) { - var newUrl = t.createUrl(u, dep); - t.load(newUrl.resource, newUrl, undefined, undefined); - }); - if (cb) { - if (s) { - cb.call(s); - } else { - cb.call(tinymce.ScriptLoader); - } - } - } - - if (t.urls[n]) - return; - if (typeof u === "object") - url = u.prefix + u.resource + u.suffix; - - if (url.indexOf('/') !== 0 && url.indexOf('://') == -1) - url = tinymce.baseURL + '/' + url; - - t.urls[n] = url.substring(0, url.lastIndexOf('/')); - - if (t.lookup[n]) { - loadDependencies(); - } else { - tinymce.ScriptLoader.add(url, loadDependencies, s); - } - } - }); - - // Create plugin and theme managers - tinymce.PluginManager = new tinymce.AddOnManager(); - tinymce.ThemeManager = new tinymce.AddOnManager(); -}(tinymce)); - -(function(tinymce) { - // Shorten names - var each = tinymce.each, extend = tinymce.extend, - DOM = tinymce.DOM, Event = tinymce.dom.Event, - ThemeManager = tinymce.ThemeManager, PluginManager = tinymce.PluginManager, - explode = tinymce.explode, - Dispatcher = tinymce.util.Dispatcher, undef, instanceCounter = 0; - - // Setup some URLs where the editor API is located and where the document is - tinymce.documentBaseURL = window.location.href.replace(/[\?#].*$/, '').replace(/[\/\\][^\/]+$/, ''); - if (!/[\/\\]$/.test(tinymce.documentBaseURL)) - tinymce.documentBaseURL += '/'; - - tinymce.baseURL = new tinymce.util.URI(tinymce.documentBaseURL).toAbsolute(tinymce.baseURL); - - tinymce.baseURI = new tinymce.util.URI(tinymce.baseURL); - - // Add before unload listener - // This was required since IE was leaking memory if you added and removed beforeunload listeners - // with attachEvent/detatchEvent so this only adds one listener and instances can the attach to the onBeforeUnload event - tinymce.onBeforeUnload = new Dispatcher(tinymce); - - // Must be on window or IE will leak if the editor is placed in frame or iframe - Event.add(window, 'beforeunload', function(e) { - tinymce.onBeforeUnload.dispatch(tinymce, e); - }); - - tinymce.onAddEditor = new Dispatcher(tinymce); - - tinymce.onRemoveEditor = new Dispatcher(tinymce); - - tinymce.EditorManager = extend(tinymce, { - editors : [], - - i18n : {}, - - activeEditor : null, - - init : function(s) { - var t = this, pl, sl = tinymce.ScriptLoader, e, el = [], ed; - - function createId(elm) { - var id = elm.id; - - // Use element id, or unique name or generate a unique id - if (!id) { - id = elm.name; - - if (id && !DOM.get(id)) { - id = elm.name; - } else { - // Generate unique name - id = DOM.uniqueId(); - } - - elm.setAttribute('id', id); - } - - return id; - }; - - function execCallback(se, n, s) { - var f = se[n]; - - if (!f) - return; - - if (tinymce.is(f, 'string')) { - s = f.replace(/\.\w+$/, ''); - s = s ? tinymce.resolve(s) : 0; - f = tinymce.resolve(f); - } - - return f.apply(s || this, Array.prototype.slice.call(arguments, 2)); - }; - - function hasClass(n, c) { - return c.constructor === RegExp ? c.test(n.className) : DOM.hasClass(n, c); - }; - - t.settings = s; - - // Legacy call - Event.bind(window, 'ready', function() { - var l, co; - - execCallback(s, 'onpageload'); - - switch (s.mode) { - case "exact": - l = s.elements || ''; - - if(l.length > 0) { - each(explode(l), function(v) { - if (DOM.get(v)) { - ed = new tinymce.Editor(v, s); - el.push(ed); - ed.render(1); - } else { - each(document.forms, function(f) { - each(f.elements, function(e) { - if (e.name === v) { - v = 'mce_editor_' + instanceCounter++; - DOM.setAttrib(e, 'id', v); - - ed = new tinymce.Editor(v, s); - el.push(ed); - ed.render(1); - } - }); - }); - } - }); - } - break; - - case "textareas": - case "specific_textareas": - each(DOM.select('textarea'), function(elm) { - if (s.editor_deselector && hasClass(elm, s.editor_deselector)) - return; - - if (!s.editor_selector || hasClass(elm, s.editor_selector)) { - ed = new tinymce.Editor(createId(elm), s); - el.push(ed); - ed.render(1); - } - }); - break; - - default: - if (s.types) { - // Process type specific selector - each(s.types, function(type) { - each(DOM.select(type.selector), function(elm) { - var editor = new tinymce.Editor(createId(elm), tinymce.extend({}, s, type)); - el.push(editor); - editor.render(1); - }); - }); - } else if (s.selector) { - // Process global selector - each(DOM.select(s.selector), function(elm) { - var editor = new tinymce.Editor(createId(elm), s); - el.push(editor); - editor.render(1); - }); - } - } - - // Call onInit when all editors are initialized - if (s.oninit) { - l = co = 0; - - each(el, function(ed) { - co++; - - if (!ed.initialized) { - // Wait for it - ed.onInit.add(function() { - l++; - - // All done - if (l == co) - execCallback(s, 'oninit'); - }); - } else - l++; - - // All done - if (l == co) - execCallback(s, 'oninit'); - }); - } - }); - }, - - get : function(id) { - if (id === undef) - return this.editors; - - if (!this.editors.hasOwnProperty(id)) - return undef; - - return this.editors[id]; - }, - - getInstanceById : function(id) { - return this.get(id); - }, - - add : function(editor) { - var self = this, editors = self.editors; - - // Add named and index editor instance - editors[editor.id] = editor; - editors.push(editor); - - self._setActive(editor); - self.onAddEditor.dispatch(self, editor); - - - return editor; - }, - - remove : function(editor) { - var t = this, i, editors = t.editors; - - // Not in the collection - if (!editors[editor.id]) - return null; - - delete editors[editor.id]; - - for (i = 0; i < editors.length; i++) { - if (editors[i] == editor) { - editors.splice(i, 1); - break; - } - } - - // Select another editor since the active one was removed - if (t.activeEditor == editor) - t._setActive(editors[0]); - - editor.destroy(); - t.onRemoveEditor.dispatch(t, editor); - - return editor; - }, - - execCommand : function(c, u, v) { - var t = this, ed = t.get(v), w; - - function clr() { - ed.destroy(); - w.detachEvent('onunload', clr); - w = w.tinyMCE = w.tinymce = null; // IE leak - }; - - // Manager commands - switch (c) { - case "mceFocus": - ed.focus(); - return true; - - case "mceAddEditor": - case "mceAddControl": - if (!t.get(v)) - new tinymce.Editor(v, t.settings).render(); - - return true; - - case "mceAddFrameControl": - w = v.window; - - // Add tinyMCE global instance and tinymce namespace to specified window - w.tinyMCE = tinyMCE; - w.tinymce = tinymce; - - tinymce.DOM.doc = w.document; - tinymce.DOM.win = w; - - ed = new tinymce.Editor(v.element_id, v); - ed.render(); - - // Fix IE memory leaks - if (tinymce.isIE && ! tinymce.isIE11) { - w.attachEvent('onunload', clr); - } - - v.page_window = null; - - return true; - - case "mceRemoveEditor": - case "mceRemoveControl": - if (ed) - ed.remove(); - - return true; - - case 'mceToggleEditor': - if (!ed) { - t.execCommand('mceAddControl', 0, v); - return true; - } - - if (ed.isHidden()) - ed.show(); - else - ed.hide(); - - return true; - } - - // Run command on active editor - if (t.activeEditor) - return t.activeEditor.execCommand(c, u, v); - - return false; - }, - - execInstanceCommand : function(id, c, u, v) { - var ed = this.get(id); - - if (ed) - return ed.execCommand(c, u, v); - - return false; - }, - - triggerSave : function() { - each(this.editors, function(e) { - e.save(); - }); - }, - - addI18n : function(p, o) { - var lo, i18n = this.i18n; - - if (!tinymce.is(p, 'string')) { - each(p, function(o, lc) { - each(o, function(o, g) { - each(o, function(o, k) { - if (g === 'common') - i18n[lc + '.' + k] = o; - else - i18n[lc + '.' + g + '.' + k] = o; - }); - }); - }); - } else { - each(o, function(o, k) { - i18n[p + '.' + k] = o; - }); - } - }, - - // Private methods - - _setActive : function(editor) { - this.selectedInstance = this.activeEditor = editor; - } - }); -})(tinymce); - -(function(tinymce) { - // Shorten these names - var DOM = tinymce.DOM, Event = tinymce.dom.Event, extend = tinymce.extend, - each = tinymce.each, isGecko = tinymce.isGecko, - isIE = tinymce.isIE, isWebKit = tinymce.isWebKit, is = tinymce.is, - ThemeManager = tinymce.ThemeManager, PluginManager = tinymce.PluginManager, - explode = tinymce.explode; - - tinymce.create('tinymce.Editor', { - Editor : function(id, settings) { - var self = this, TRUE = true; - - self.settings = settings = extend({ - id : id, - language : 'en', - theme : 'advanced', - skin : 'default', - delta_width : 0, - delta_height : 0, - popup_css : '', - plugins : '', - document_base_url : tinymce.documentBaseURL, - add_form_submit_trigger : TRUE, - submit_patch : TRUE, - add_unload_trigger : TRUE, - convert_urls : TRUE, - relative_urls : TRUE, - remove_script_host : TRUE, - table_inline_editing : false, - object_resizing : TRUE, - accessibility_focus : TRUE, - doctype : tinymce.isIE6 ? '' : '', // Use old doctype on IE 6 to avoid horizontal scroll - visual : TRUE, - font_size_style_values : 'xx-small,x-small,small,medium,large,x-large,xx-large', - font_size_legacy_values : 'xx-small,small,medium,large,x-large,xx-large,300%', // See: http://www.w3.org/TR/CSS2/fonts.html#propdef-font-size - apply_source_formatting : TRUE, - directionality : 'ltr', - forced_root_block : 'p', - hidden_input : TRUE, - padd_empty_editor : TRUE, - render_ui : TRUE, - indentation : '30px', - fix_table_elements : TRUE, - inline_styles : TRUE, - convert_fonts_to_spans : TRUE, - indent : 'simple', - indent_before : 'p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,li,area,table,thead,tfoot,tbody,tr,section,article,hgroup,aside,figure,option,optgroup,datalist', - indent_after : 'p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,li,area,table,thead,tfoot,tbody,tr,section,article,hgroup,aside,figure,option,optgroup,datalist', - validate : TRUE, - entity_encoding : 'named', - url_converter : self.convertURL, - url_converter_scope : self, - ie7_compat : TRUE - }, settings); - - self.id = self.editorId = id; - - self.isNotDirty = false; - - self.plugins = {}; - - self.documentBaseURI = new tinymce.util.URI(settings.document_base_url || tinymce.documentBaseURL, { - base_uri : tinyMCE.baseURI - }); - - self.baseURI = tinymce.baseURI; - - self.contentCSS = []; - - self.contentStyles = []; - - // Creates all events like onClick, onSetContent etc see Editor.Events.js for the actual logic - self.setupEvents(); - - // Internal command handler objects - self.execCommands = {}; - self.queryStateCommands = {}; - self.queryValueCommands = {}; - - // Call setup - self.execCallback('setup', self); - }, - - render : function(nst) { - var t = this, s = t.settings, id = t.id, sl = tinymce.ScriptLoader; - - // Page is not loaded yet, wait for it - if (!Event.domLoaded) { - Event.add(window, 'ready', function() { - t.render(); - }); - return; - } - - tinyMCE.settings = s; - - // Element not found, then skip initialization - if (!t.getElement()) { - return; - } - - // Is a iPad/iPhone and not on iOS5, then skip initialization. We need to sniff - // here since the browser says it has contentEditable support but there is no visible caret. - if (tinymce.isIDevice && !tinymce.isIOS5) { - return; - } - - // Add hidden input for non input elements inside form elements - if (!/TEXTAREA|INPUT/i.test(t.getElement().nodeName) && s.hidden_input && DOM.getParent(id, 'form')) { - DOM.insertAfter(DOM.create('input', {type : 'hidden', name : id}), id); - } - - // Hide target element early to prevent content flashing - if (!s.content_editable) { - t.orgVisibility = t.getElement().style.visibility; - t.getElement().style.visibility = 'hidden'; - } - - if (tinymce.WindowManager) { - t.windowManager = new tinymce.WindowManager(t); - } - - if (s.encoding == 'xml') { - t.onGetContent.add(function(ed, o) { - if (o.save) { - o.content = DOM.encode(o.content); - } - }); - } - - if (s.add_form_submit_trigger) { - t.onSubmit.addToTop(function() { - if (t.initialized) { - t.save(); - t.isNotDirty = 1; - } - }); - } - - if (s.add_unload_trigger) { - t._beforeUnload = tinyMCE.onBeforeUnload.add(function() { - if (t.initialized && !t.destroyed && !t.isHidden()) { - t.save({format : 'raw', no_events : true}); - } - }); - } - - tinymce.addUnload(t.destroy, t); - - if (s.submit_patch) { - t.onBeforeRenderUI.add(function() { - var n = t.getElement().form; - - if (!n) { - return; - } - - // Already patched - if (n._mceOldSubmit) { - return; - } - - // Check page uses id="submit" or name="submit" for it's submit button - if (!n.submit.nodeType && !n.submit.length) { - t.formElement = n; - n._mceOldSubmit = n.submit; - n.submit = function() { - // Save all instances - tinymce.triggerSave(); - t.isNotDirty = 1; - - return t.formElement._mceOldSubmit(t.formElement); - }; - } - - n = null; - }); - } - - // Load scripts - function loadScripts() { - if (s.language && s.language_load !== false) { - sl.add(tinymce.baseURL + '/langs/' + s.language + '.js'); - } - - if (s.theme && typeof s.theme != "function" && s.theme.charAt(0) != '-' && !ThemeManager.urls[s.theme]) { - ThemeManager.load(s.theme, 'themes/' + s.theme + '/editor_template' + tinymce.suffix + '.js'); - } - - each(explode(s.plugins), function(p) { - if (p &&!PluginManager.urls[p]) { - if (p.charAt(0) == '-') { - p = p.substr(1, p.length); - var dependencies = PluginManager.dependencies(p); - each(dependencies, function(dep) { - var defaultSettings = {prefix:'plugins/', resource: dep, suffix:'/editor_plugin' + tinymce.suffix + '.js'}; - dep = PluginManager.createUrl(defaultSettings, dep); - PluginManager.load(dep.resource, dep); - }); - } else { - // Skip safari plugin, since it is removed as of 3.3b1 - if (p == 'safari') { - return; - } - PluginManager.load(p, {prefix:'plugins/', resource: p, suffix:'/editor_plugin' + tinymce.suffix + '.js'}); - } - } - }); - - // Init when que is loaded - sl.loadQueue(function() { - if (!t.removed) { - t.init(); - } - }); - } - - loadScripts(); - }, - - init : function() { - var n, t = this, s = t.settings, w, h, mh, e = t.getElement(), o, ti, u, bi, bc, re, i, initializedPlugins = []; - - tinymce.add(t); - - s.aria_label = s.aria_label || DOM.getAttrib(e, 'aria-label', t.getLang('aria.rich_text_area')); - - if (s.theme) { - if (typeof s.theme != "function") { - s.theme = s.theme.replace(/-/, ''); - o = ThemeManager.get(s.theme); - t.theme = new o(); - - if (t.theme.init) { - t.theme.init(t, ThemeManager.urls[s.theme] || tinymce.documentBaseURL.replace(/\/$/, '')); - } - } else { - t.theme = s.theme; - } - } - - function initPlugin(p) { - var c = PluginManager.get(p), u = PluginManager.urls[p] || tinymce.documentBaseURL.replace(/\/$/, ''), po; - if (c && tinymce.inArray(initializedPlugins,p) === -1) { - each(PluginManager.dependencies(p), function(dep){ - initPlugin(dep); - }); - po = new c(t, u); - - t.plugins[p] = po; - - if (po.init) { - po.init(t, u); - initializedPlugins.push(p); - } - } - } - - // Create all plugins - each(explode(s.plugins.replace(/\-/g, '')), initPlugin); - - // Setup popup CSS path(s) - if (s.popup_css !== false) { - if (s.popup_css) { - s.popup_css = t.documentBaseURI.toAbsolute(s.popup_css); - } else { - s.popup_css = t.baseURI.toAbsolute("themes/" + s.theme + "/skins/" + s.skin + "/dialog.css"); - } - } - - if (s.popup_css_add) { - s.popup_css += ',' + t.documentBaseURI.toAbsolute(s.popup_css_add); - } - - t.controlManager = new tinymce.ControlManager(t); - - // Enables users to override the control factory - t.onBeforeRenderUI.dispatch(t, t.controlManager); - - // Measure box - if (s.render_ui && t.theme) { - t.orgDisplay = e.style.display; - - if (typeof s.theme != "function") { - w = s.width || e.style.width || e.offsetWidth; - h = s.height || e.style.height || e.offsetHeight; - mh = s.min_height || 100; - re = /^[0-9\.]+(|px)$/i; - - if (re.test('' + w)) { - w = Math.max(parseInt(w, 10) + (o.deltaWidth || 0), 100); - } - - if (re.test('' + h)) { - h = Math.max(parseInt(h, 10) + (o.deltaHeight || 0), mh); - } - - // Render UI - o = t.theme.renderUI({ - targetNode : e, - width : w, - height : h, - deltaWidth : s.delta_width, - deltaHeight : s.delta_height - }); - - // Resize editor - DOM.setStyles(o.sizeContainer || o.editorContainer, { - width : w, - height : h - }); - - h = (o.iframeHeight || h) + (typeof(h) == 'number' ? (o.deltaHeight || 0) : ''); - if (h < mh) { - h = mh; - } - } else { - o = s.theme(t, e); - - // Convert element type to id:s - if (o.editorContainer.nodeType) { - o.editorContainer = o.editorContainer.id = o.editorContainer.id || t.id + "_parent"; - } - - // Convert element type to id:s - if (o.iframeContainer.nodeType) { - o.iframeContainer = o.iframeContainer.id = o.iframeContainer.id || t.id + "_iframecontainer"; - } - - // Use specified iframe height or the targets offsetHeight - h = o.iframeHeight || e.offsetHeight; - - // Store away the selection when it's changed to it can be restored later with a editor.focus() call - if (isIE) { - t.onInit.add(function(ed) { - ed.dom.bind(ed.getBody(), 'beforedeactivate keydown keyup', function() { - ed.bookmark = ed.selection.getBookmark(1); - }); - }); - - t.onNodeChange.add(function(ed) { - if (document.activeElement.id == ed.id + "_ifr") { - ed.bookmark = ed.selection.getBookmark(1); - } - }); - } - } - - t.editorContainer = o.editorContainer; - } - - // Load specified content CSS last - if (s.content_css) { - each(explode(s.content_css), function(u) { - t.contentCSS.push(t.documentBaseURI.toAbsolute(u)); - }); - } - - // Load specified content CSS last - if (s.content_style) { - t.contentStyles.push(s.content_style); - } - - // Content editable mode ends here - if (s.content_editable) { - e = n = o = null; // Fix IE leak - return t.initContentBody(); - } - - // User specified a document.domain value - if (document.domain && location.hostname != document.domain) { - tinymce.relaxedDomain = document.domain; - } - - t.iframeHTML = s.doctype + ''; - - // We only need to override paths if we have to - // IE has a bug where it remove site absolute urls to relative ones if this is specified - if (s.document_base_url != tinymce.documentBaseURL) { - t.iframeHTML += ''; - } - - // IE8 doesn't support carets behind images setting ie7_compat would force IE8+ to run in IE7 compat mode. - if (tinymce.isIE8) { - if (s.ie7_compat) { - t.iframeHTML += ''; - } else { - t.iframeHTML += ''; - } - } - - t.iframeHTML += ''; - - // Load the CSS by injecting them into the HTML this will reduce "flicker" - for (i = 0; i < t.contentCSS.length; i++) { - t.iframeHTML += ''; - } - - t.contentCSS = []; - - bi = s.body_id || 'tinymce'; - if (bi.indexOf('=') != -1) { - bi = t.getParam('body_id', '', 'hash'); - bi = bi[t.id] || bi; - } - - bc = s.body_class || ''; - if (bc.indexOf('=') != -1) { - bc = t.getParam('body_class', '', 'hash'); - bc = bc[t.id] || ''; - } - - t.iframeHTML += '
    '; - - // Domain relaxing enabled, then set document domain - if (tinymce.relaxedDomain && (isIE || (tinymce.isOpera && parseFloat(opera.version()) < 11))) { - // We need to write the contents here in IE since multiple writes messes up refresh button and back button - u = 'javascript:(function(){document.open();document.domain="' + document.domain + '";var ed = window.parent.tinyMCE.get("' + t.id + '");document.write(ed.iframeHTML);document.close();ed.initContentBody();})()'; - } - - // Create iframe - // TODO: ACC add the appropriate description on this. - n = DOM.add(o.iframeContainer, 'iframe', { - id : t.id + "_ifr", - src : u || 'javascript:""', // Workaround for HTTPS warning in IE6/7 - frameBorder : '0', - allowTransparency : "true", - title : s.aria_label, - style : { - width : '100%', - height : h, - display : 'block' // Important for Gecko to render the iframe correctly - } - }); - - t.contentAreaContainer = o.iframeContainer; - - if (o.editorContainer) { - DOM.get(o.editorContainer).style.display = t.orgDisplay; - } - - // Restore visibility on target element - e.style.visibility = t.orgVisibility; - - DOM.get(t.id).style.display = 'none'; - DOM.setAttrib(t.id, 'aria-hidden', true); - - if (!tinymce.relaxedDomain || !u) { - t.initContentBody(); - } - - e = n = o = null; // Cleanup - }, - - initContentBody : function() { - var self = this, settings = self.settings, targetElm = DOM.get(self.id), doc = self.getDoc(), html, body, contentCssText; - - // Setup iframe body - if ((!isIE || !tinymce.relaxedDomain) && !settings.content_editable) { - doc.open(); - doc.write(self.iframeHTML); - doc.close(); - - if (tinymce.relaxedDomain) { - doc.domain = tinymce.relaxedDomain; - } - } - - if (settings.content_editable) { - DOM.addClass(targetElm, 'mceContentBody'); - self.contentDocument = doc = settings.content_document || document; - self.contentWindow = settings.content_window || window; - self.bodyElement = targetElm; - - // Prevent leak in IE - settings.content_document = settings.content_window = null; - } - - // It will not steal focus while setting contentEditable - body = self.getBody(); - body.disabled = true; - - if (!settings.readonly) { - body.contentEditable = self.getParam('content_editable_state', true); - } - - body.disabled = false; - - self.schema = new tinymce.html.Schema(settings); - - self.dom = new tinymce.dom.DOMUtils(doc, { - keep_values : true, - url_converter : self.convertURL, - url_converter_scope : self, - hex_colors : settings.force_hex_style_colors, - class_filter : settings.class_filter, - update_styles : true, - root_element : settings.content_editable ? self.id : null, - schema : self.schema - }); - - self.parser = new tinymce.html.DomParser(settings, self.schema); - - // Convert src and href into data-mce-src, data-mce-href and data-mce-style - self.parser.addAttributeFilter('src,href,style', function(nodes, name) { - var i = nodes.length, node, dom = self.dom, value, internalName; - - while (i--) { - node = nodes[i]; - value = node.attr(name); - internalName = 'data-mce-' + name; - - // Add internal attribute if we need to we don't on a refresh of the document - if (!node.attributes.map[internalName]) { - if (name === "style") { - node.attr(internalName, dom.serializeStyle(dom.parseStyle(value), node.name)); - } else { - node.attr(internalName, self.convertURL(value, name, node.name)); - } - } - } - }); - - // Keep scripts from executing - self.parser.addNodeFilter('script', function(nodes, name) { - var i = nodes.length, node; - - while (i--) { - node = nodes[i]; - node.attr('type', 'mce-' + (node.attr('type') || 'text/javascript')); - } - }); - - self.parser.addNodeFilter('#cdata', function(nodes, name) { - var i = nodes.length, node; - - while (i--) { - node = nodes[i]; - node.type = 8; - node.name = '#comment'; - node.value = '[CDATA[' + node.value + ']]'; - } - }); - - self.parser.addNodeFilter('p,h1,h2,h3,h4,h5,h6,div', function(nodes, name) { - var i = nodes.length, node, nonEmptyElements = self.schema.getNonEmptyElements(); - - while (i--) { - node = nodes[i]; - - if (node.isEmpty(nonEmptyElements)) { - node.empty().append(new tinymce.html.Node('br', 1)).shortEnded = true; - } - } - }); - - self.serializer = new tinymce.dom.Serializer(settings, self.dom, self.schema); - - self.selection = new tinymce.dom.Selection(self.dom, self.getWin(), self.serializer, self); - - self.formatter = new tinymce.Formatter(self); - - self.undoManager = new tinymce.UndoManager(self); - - self.forceBlocks = new tinymce.ForceBlocks(self); - self.enterKey = new tinymce.EnterKey(self); - self.editorCommands = new tinymce.EditorCommands(self); - - self.onExecCommand.add(function(editor, command) { - // Don't refresh the select lists until caret move - if (!/^(FontName|FontSize)$/.test(command)) { - self.nodeChanged(); - } - }); - - // Pass through - self.serializer.onPreProcess.add(function(se, o) { - return self.onPreProcess.dispatch(self, o, se); - }); - - self.serializer.onPostProcess.add(function(se, o) { - return self.onPostProcess.dispatch(self, o, se); - }); - - self.onPreInit.dispatch(self); - - if (!settings.browser_spellcheck && !settings.gecko_spellcheck) { - doc.body.spellcheck = false; - } - - if (!settings.readonly) { - self.bindNativeEvents(); - } - - self.controlManager.onPostRender.dispatch(self, self.controlManager); - self.onPostRender.dispatch(self); - - self.quirks = tinymce.util.Quirks(self); - - if (settings.directionality) { - body.dir = settings.directionality; - } - - if (settings.nowrap) { - body.style.whiteSpace = "nowrap"; - } - - if (settings.protect) { - self.onBeforeSetContent.add(function(ed, o) { - each(settings.protect, function(pattern) { - o.content = o.content.replace(pattern, function(str) { - return ''; - }); - }); - }); - } - - // Add visual aids when new contents is added - self.onSetContent.add(function() { - self.addVisual(self.getBody()); - }); - - // Remove empty contents - if (settings.padd_empty_editor) { - self.onPostProcess.add(function(ed, o) { - o.content = o.content.replace(/^(]*>( | |\s|\u00a0|)<\/p>[\r\n]*|
    [\r\n]*)$/, ''); - }); - } - - self.load({initial : true, format : 'html'}); - self.startContent = self.getContent({format : 'raw'}); - - self.initialized = true; - - self.onInit.dispatch(self); - self.execCallback('setupcontent_callback', self.id, body, doc); - self.execCallback('init_instance_callback', self); - self.focus(true); - self.nodeChanged({initial : true}); - - // Add editor specific CSS styles - if (self.contentStyles.length > 0) { - contentCssText = ''; - - each(self.contentStyles, function(style) { - contentCssText += style + "\r\n"; - }); - - self.dom.addStyle(contentCssText); - } - - // Load specified content CSS last - each(self.contentCSS, function(url) { - self.dom.loadCSS(url); - }); - - // Handle auto focus - if (settings.auto_focus) { - setTimeout(function () { - var ed = tinymce.get(settings.auto_focus); - - ed.selection.select(ed.getBody(), 1); - ed.selection.collapse(1); - ed.getBody().focus(); - ed.getWin().focus(); - }, 100); - } - - // Clean up references for IE - targetElm = doc = body = null; - }, - - focus : function(skip_focus) { - var oed, self = this, selection = self.selection, contentEditable = self.settings.content_editable, ieRng, controlElm, doc = self.getDoc(), body; - - if (!skip_focus) { - if (self.bookmark) { - selection.moveToBookmark(self.bookmark); - self.bookmark = null; - } - - // Get selected control element - ieRng = selection.getRng(); - if (ieRng.item) { - controlElm = ieRng.item(0); - } - - self._refreshContentEditable(); - - // Focus the window iframe - if (!contentEditable) { - self.getWin().focus(); - } - - // Focus the body as well since it's contentEditable - if (tinymce.isGecko || contentEditable) { - body = self.getBody(); - - // Check for setActive since it doesn't scroll to the element - if (body.setActive && ! tinymce.isIE11) { - body.setActive(); - } else { - body.focus(); - } - - if (contentEditable) { - selection.normalize(); - } - } - - // Restore selected control element - // This is needed when for example an image is selected within a - // layer a call to focus will then remove the control selection - if (controlElm && controlElm.ownerDocument == doc) { - ieRng = doc.body.createControlRange(); - ieRng.addElement(controlElm); - ieRng.select(); - } - } - - if (tinymce.activeEditor != self) { - if ((oed = tinymce.activeEditor) != null) { - oed.onDeactivate.dispatch(oed, self); - } - - self.onActivate.dispatch(self, oed); - } - - tinymce._setActive(self); - }, - - execCallback : function(n) { - var t = this, f = t.settings[n], s; - - if (!f) { - return; - } - - // Look through lookup - if (t.callbackLookup && (s = t.callbackLookup[n])) { - f = s.func; - s = s.scope; - } - - if (is(f, 'string')) { - s = f.replace(/\.\w+$/, ''); - s = s ? tinymce.resolve(s) : 0; - f = tinymce.resolve(f); - t.callbackLookup = t.callbackLookup || {}; - t.callbackLookup[n] = {func : f, scope : s}; - } - - return f.apply(s || t, Array.prototype.slice.call(arguments, 1)); - }, - - translate : function(s) { - var c = this.settings.language || 'en', i18n = tinymce.i18n; - - if (!s) { - return ''; - } - - return i18n[c + '.' + s] || s.replace(/\{\#([^\}]+)\}/g, function(a, b) { - return i18n[c + '.' + b] || '{#' + b + '}'; - }); - }, - - getLang : function(n, dv) { - return tinymce.i18n[(this.settings.language || 'en') + '.' + n] || (is(dv) ? dv : '{#' + n + '}'); - }, - - getParam : function(n, dv, ty) { - var tr = tinymce.trim, v = is(this.settings[n]) ? this.settings[n] : dv, o; - - if (ty === 'hash') { - o = {}; - - if (is(v, 'string')) { - each(v.indexOf('=') > 0 ? v.split(/[;,](?![^=;,]*(?:[;,]|$))/) : v.split(','), function(v) { - v = v.split('='); - - if (v.length > 1) { - o[tr(v[0])] = tr(v[1]); - } else { - o[tr(v[0])] = tr(v); - } - }); - } else { - o = v; - } - - return o; - } - - return v; - }, - - nodeChanged : function(o) { - var self = this, selection = self.selection, node; - - // Fix for bug #1896577 it seems that this can not be fired while the editor is loading - if (!self.initialized) { - return; - } - - o = o || {}; - - // Get start node - node = selection.getStart() || self.getBody(); - node = isIE && node.ownerDocument != self.getDoc() ? self.getBody() : node; // Fix for IE initial state - - // Get parents and add them to object - o.parents = []; - self.dom.getParent(node, function(node) { - if (node.nodeName == 'BODY') { - return true; - } - - o.parents.push(node); - }); - - self.onNodeChange.dispatch( - self, - o ? o.controlManager || self.controlManager : self.controlManager, - node, - selection.isCollapsed(), - o - ); - }, - - addButton : function(name, settings) { - var self = this; - - self.buttons = self.buttons || {}; - self.buttons[name] = settings; - }, - - addCommand : function(name, callback, scope) { - this.execCommands[name] = {func : callback, scope : scope || this}; - }, - - addQueryStateHandler : function(name, callback, scope) { - this.queryStateCommands[name] = {func : callback, scope : scope || this}; - }, - - addQueryValueHandler : function(name, callback, scope) { - this.queryValueCommands[name] = {func : callback, scope : scope || this}; - }, - - addShortcut : function(pa, desc, cmd_func, sc) { - var t = this, c; - - if (t.settings.custom_shortcuts === false) { - return false; - } - - t.shortcuts = t.shortcuts || {}; - - if (is(cmd_func, 'string')) { - c = cmd_func; - - cmd_func = function() { - t.execCommand(c, false, null); - }; - } - - if (is(cmd_func, 'object')) { - c = cmd_func; - - cmd_func = function() { - t.execCommand(c[0], c[1], c[2]); - }; - } - - each(explode(pa), function(pa) { - var o = { - func : cmd_func, - scope : sc || this, - desc : t.translate(desc), - alt : false, - ctrl : false, - shift : false - }; - - each(explode(pa, '+'), function(v) { - switch (v) { - case 'alt': - case 'ctrl': - case 'shift': - o[v] = true; - break; - - default: - o.charCode = v.charCodeAt(0); - o.keyCode = v.toUpperCase().charCodeAt(0); - } - }); - - t.shortcuts[(o.ctrl ? 'ctrl' : '') + ',' + (o.alt ? 'alt' : '') + ',' + (o.shift ? 'shift' : '') + ',' + o.keyCode] = o; - }); - - return true; - }, - - execCommand : function(cmd, ui, val, a) { - var t = this, s = 0, o, st; - - if (!/^(mceAddUndoLevel|mceEndUndoLevel|mceBeginUndoLevel|mceRepaint|SelectAll)$/.test(cmd) && (!a || !a.skip_focus)) { - t.focus(); - } - - a = extend({}, a); - t.onBeforeExecCommand.dispatch(t, cmd, ui, val, a); - if (a.terminate) { - return false; - } - - // Command callback - if (t.execCallback('execcommand_callback', t.id, t.selection.getNode(), cmd, ui, val)) { - t.onExecCommand.dispatch(t, cmd, ui, val, a); - return true; - } - - // Registred commands - if (o = t.execCommands[cmd]) { - st = o.func.call(o.scope, ui, val); - - // Fall through on true - if (st !== true) { - t.onExecCommand.dispatch(t, cmd, ui, val, a); - return st; - } - } - - // Plugin commands - each(t.plugins, function(p) { - if (p.execCommand && p.execCommand(cmd, ui, val)) { - t.onExecCommand.dispatch(t, cmd, ui, val, a); - s = 1; - return false; - } - }); - - if (s) { - return true; - } - - // Theme commands - if (t.theme && t.theme.execCommand && t.theme.execCommand(cmd, ui, val)) { - t.onExecCommand.dispatch(t, cmd, ui, val, a); - return true; - } - - // Editor commands - if (t.editorCommands.execCommand(cmd, ui, val)) { - t.onExecCommand.dispatch(t, cmd, ui, val, a); - return true; - } - - // Browser commands - t.getDoc().execCommand(cmd, ui, val); - t.onExecCommand.dispatch(t, cmd, ui, val, a); - }, - - queryCommandState : function(cmd) { - var t = this, o, s; - - // Is hidden then return undefined - if (t._isHidden()) { - return; - } - - // Registred commands - if (o = t.queryStateCommands[cmd]) { - s = o.func.call(o.scope); - - // Fall though on true - if (s !== true) { - return s; - } - } - - // Registred commands - o = t.editorCommands.queryCommandState(cmd); - if (o !== -1) { - return o; - } - - // Browser commands - try { - return this.getDoc().queryCommandState(cmd); - } catch (ex) { - // Fails sometimes see bug: 1896577 - } - }, - - queryCommandValue : function(c) { - var t = this, o, s; - - // Is hidden then return undefined - if (t._isHidden()) { - return; - } - - // Registred commands - if (o = t.queryValueCommands[c]) { - s = o.func.call(o.scope); - - // Fall though on true - if (s !== true) { - return s; - } - } - - // Registred commands - o = t.editorCommands.queryCommandValue(c); - if (is(o)) { - return o; - } - - // Browser commands - try { - return this.getDoc().queryCommandValue(c); - } catch (ex) { - // Fails sometimes see bug: 1896577 - } - }, - - show : function() { - var self = this; - - DOM.show(self.getContainer()); - DOM.hide(self.id); - self.load(); - }, - - hide : function() { - var self = this, doc = self.getDoc(); - - // Fixed bug where IE has a blinking cursor left from the editor - if (isIE && doc) { - doc.execCommand('SelectAll'); - } - - // We must save before we hide so Safari doesn't crash - self.save(); - - // defer the call to hide to prevent an IE9 crash #4921 - DOM.hide(self.getContainer()); - DOM.setStyle(self.id, 'display', self.orgDisplay); - }, - - isHidden : function() { - return !DOM.isHidden(this.id); - }, - - setProgressState : function(b, ti, o) { - this.onSetProgressState.dispatch(this, b, ti, o); - - return b; - }, - - load : function(o) { - var t = this, e = t.getElement(), h; - - if (e) { - o = o || {}; - o.load = true; - - // Double encode existing entities in the value - h = t.setContent(is(e.value) ? e.value : e.innerHTML, o); - o.element = e; - - if (!o.no_events) { - t.onLoadContent.dispatch(t, o); - } - - o.element = e = null; - - return h; - } - }, - - save : function(o) { - var t = this, e = t.getElement(), h, f; - - if (!e || !t.initialized) { - return; - } - - o = o || {}; - o.save = true; - - o.element = e; - h = o.content = t.getContent(o); - - if (!o.no_events) { - t.onSaveContent.dispatch(t, o); - } - - h = o.content; - - if (!/TEXTAREA|INPUT/i.test(e.nodeName)) { - e.innerHTML = h; - - // Update hidden form element - if (f = DOM.getParent(t.id, 'form')) { - each(f.elements, function(e) { - if (e.name == t.id) { - e.value = h; - return false; - } - }); - } - } else { - e.value = h; - } - - o.element = e = null; - - return h; - }, - - setContent : function(content, args) { - var self = this, body = self.getBody(), forcedRootBlockName; - - // Setup args object - args = args || {}; - args.format = args.format || 'html'; - args.set = true; - args.content = content; - - // Do preprocessing - if (!args.no_events) { - self.onBeforeSetContent.dispatch(self, args); - } - - content = args.content; - - // Padd empty content in Gecko and Safari. Commands will otherwise fail on the content - // It will also be impossible to place the caret in the editor unless there is a BR element present - if (content.length === 0 || /^\s+$/.test(content)) { - forcedRootBlockName = self.settings.forced_root_block; - - // Check if forcedRootBlock is configured and that the block is a valid child of the body - if (forcedRootBlockName && self.schema.isValidChild(body.nodeName.toLowerCase(), forcedRootBlockName.toLowerCase())) { - if (isIE) { - // IE renders BR elements in blocks so lets just add an empty block - content = '<' + forcedRootBlockName + '>'; - } else { - content = '<' + forcedRootBlockName + '>
    '; - } - } else if (!isIE) { - // We need to add a BR when forced_root_block is disabled on non IE browsers to place the caret - content = '
    '; - } - - body.innerHTML = content; - self.selection.select(body, true); - self.selection.collapse(true); - return; - } - - // Parse and serialize the html - if (args.format !== 'raw') { - content = new tinymce.html.Serializer({}, self.schema).serialize( - self.parser.parse(content) - ); - } - - // Set the new cleaned contents to the editor - args.content = tinymce.trim(content); - self.dom.setHTML(body, args.content); - - // Do post processing - if (!args.no_events) { - self.onSetContent.dispatch(self, args); - } - - // Don't normalize selection if the focused element isn't the body in content editable mode since it will steal focus otherwise - if (!self.settings.content_editable || document.activeElement === self.getBody()) { - self.selection.normalize(); - } - - return args.content; - }, - - getContent : function(args) { - var self = this, content, body = self.getBody(); - - // Setup args object - args = args || {}; - args.format = args.format || 'html'; - args.get = true; - args.getInner = true; - - // Do preprocessing - if (!args.no_events) { - self.onBeforeGetContent.dispatch(self, args); - } - - // Get raw contents or by default the cleaned contents - if (args.format == 'raw') { - content = body.innerHTML; - } else if (args.format == 'text') { - content = body.innerText || body.textContent; - } else { - content = self.serializer.serialize(body, args); - } - - // Trim whitespace in beginning/end of HTML - if (args.format != 'text') { - args.content = tinymce.trim(content); - } else { - args.content = content; - } - - // Do post processing - if (!args.no_events) { - self.onGetContent.dispatch(self, args); - } - - return args.content; - }, - - isDirty : function() { - var self = this; - - return tinymce.trim(self.startContent) !== tinymce.trim(self.getContent({format : 'raw'})) && !self.isNotDirty; - }, - - getContainer : function() { - var self = this; - - if (!self.container) { - self.container = DOM.get(self.editorContainer || self.id + '_parent'); - } - - return self.container; - }, - - getContentAreaContainer : function() { - return this.contentAreaContainer; - }, - - getElement : function() { - return DOM.get(this.settings.content_element || this.id); - }, - - getWin : function() { - var self = this, elm; - - if (!self.contentWindow) { - elm = DOM.get(self.id + "_ifr"); - - if (elm) { - self.contentWindow = elm.contentWindow; - } - } - - return self.contentWindow; - }, - - getDoc : function() { - var self = this, win; - - if (!self.contentDocument) { - win = self.getWin(); - - if (win) { - self.contentDocument = win.document; - } - } - - return self.contentDocument; - }, - - getBody : function() { - return this.bodyElement || this.getDoc().body; - }, - - convertURL : function(url, name, elm) { - var self = this, settings = self.settings; - - // Use callback instead - if (settings.urlconverter_callback) - return self.execCallback('urlconverter_callback', url, elm, true, name); - - // Don't convert link href since thats the CSS files that gets loaded into the editor also skip local file URLs - if (!settings.convert_urls || (elm && elm.nodeName == 'LINK') || url.indexOf('file:') === 0) { - return url; - } - - // Convert to relative - if (settings.relative_urls) { - return self.documentBaseURI.toRelative(url); - } - - // Convert to absolute - url = self.documentBaseURI.toAbsolute(url, settings.remove_script_host); - - return url; - }, - - addVisual : function(elm) { - var self = this, settings = self.settings, dom = self.dom, cls; - - elm = elm || self.getBody(); - - if (!is(self.hasVisual)) - self.hasVisual = settings.visual; - - each(dom.select('table,a', elm), function(elm) { - var value; - - switch (elm.nodeName) { - case 'TABLE': - cls = settings.visual_table_class || 'mceItemTable'; - value = dom.getAttrib(elm, 'border'); - - if (!value || value == '0') { - if (self.hasVisual) { - dom.addClass(elm, cls); - } else { - dom.removeClass(elm, cls); - } - } - - return; - - case 'A': - if (!dom.getAttrib(elm, 'href', false)) { - value = dom.getAttrib(elm, 'name') || elm.id; - cls = 'mceItemAnchor'; - - if (value) { - if (self.hasVisual) { - dom.addClass(elm, cls); - } else { - dom.removeClass(elm, cls); - } - } - } - - return; - } - }); - - self.onVisualAid.dispatch(self, elm, self.hasVisual); - }, - - remove : function() { - var self = this, elm = self.getContainer(), doc = self.getDoc(); - - if (!self.removed) { - self.removed = 1; // Cancels post remove event execution - - // Fixed bug where IE has a blinking cursor left from the editor - if (isIE && doc) { - doc.execCommand('SelectAll'); - } - - // We must save before we hide so Safari doesn't crash - self.save(); - - DOM.setStyle(self.id, 'display', self.orgDisplay); - - // Don't clear the window or document if content editable - // is enabled since other instances might still be present - if (!self.settings.content_editable) { - Event.unbind(self.getWin()); - Event.unbind(self.getDoc()); - } - - Event.unbind(self.getBody()); - Event.clear(elm); - - self.execCallback('remove_instance_callback', self); - self.onRemove.dispatch(self); - - // Clear all execCommand listeners this is required to avoid errors if the editor was removed inside another command - self.onExecCommand.listeners = []; - - tinymce.remove(self); - DOM.remove(elm); - } - }, - - destroy : function(s) { - var t = this; - - // One time is enough - if (t.destroyed) { - return; - } - - // We must unbind on Gecko since it would otherwise produce the pesky "attempt to run compile-and-go script on a cleared scope" message - if (isGecko) { - Event.unbind(t.getDoc()); - Event.unbind(t.getWin()); - Event.unbind(t.getBody()); - } - - if (!s) { - tinymce.removeUnload(t.destroy); - tinyMCE.onBeforeUnload.remove(t._beforeUnload); - - // Manual destroy - if (t.theme && t.theme.destroy) { - t.theme.destroy(); - } - - // Destroy controls, selection and dom - t.controlManager.destroy(); - t.selection.destroy(); - t.dom.destroy(); - } - - if (t.formElement) { - t.formElement.submit = t.formElement._mceOldSubmit; - t.formElement._mceOldSubmit = null; - } - - t.contentAreaContainer = t.formElement = t.container = t.settings.content_element = t.bodyElement = t.contentDocument = t.contentWindow = null; - - if (t.selection) { - t.selection = t.selection.win = t.selection.dom = t.selection.dom.doc = null; - } - - t.destroyed = 1; - }, - - // Internal functions - - _refreshContentEditable : function() { - var self = this, body, parent; - - // Check if the editor was hidden and the re-initalize contentEditable mode by removing and adding the body again - if (self._isHidden()) { - body = self.getBody(); - parent = body.parentNode; - - parent.removeChild(body); - parent.appendChild(body); - - body.focus(); - } - }, - - _isHidden : function() { - var s; - - if (!isGecko) { - return 0; - } - - // Weird, wheres that cursor selection? - s = this.selection.getSel(); - return (!s || !s.rangeCount || s.rangeCount === 0); - } - }); -})(tinymce); -(function(tinymce) { - var each = tinymce.each; - - tinymce.Editor.prototype.setupEvents = function() { - var self = this, settings = self.settings; - - // Add events to the editor - each([ - 'onPreInit', - - 'onBeforeRenderUI', - - 'onPostRender', - - 'onLoad', - - 'onInit', - - 'onRemove', - - 'onActivate', - - 'onDeactivate', - - 'onClick', - - 'onEvent', - - 'onMouseUp', - - 'onMouseDown', - - 'onDblClick', - - 'onKeyDown', - - 'onKeyUp', - - 'onKeyPress', - - 'onContextMenu', - - 'onSubmit', - - 'onReset', - - 'onPaste', - - 'onPreProcess', - - 'onPostProcess', - - 'onBeforeSetContent', - - 'onBeforeGetContent', - - 'onSetContent', - - 'onGetContent', - - 'onLoadContent', - - 'onSaveContent', - - 'onNodeChange', - - 'onChange', - - 'onBeforeExecCommand', - - 'onExecCommand', - - 'onUndo', - - 'onRedo', - - 'onVisualAid', - - 'onSetProgressState', - - 'onSetAttrib' - ], function(name) { - self[name] = new tinymce.util.Dispatcher(self); - }); - - // Handle legacy cleanup_callback option - if (settings.cleanup_callback) { - self.onBeforeSetContent.add(function(ed, o) { - o.content = ed.execCallback('cleanup_callback', 'insert_to_editor', o.content, o); - }); - - self.onPreProcess.add(function(ed, o) { - if (o.set) - ed.execCallback('cleanup_callback', 'insert_to_editor_dom', o.node, o); - - if (o.get) - ed.execCallback('cleanup_callback', 'get_from_editor_dom', o.node, o); - }); - - self.onPostProcess.add(function(ed, o) { - if (o.set) - o.content = ed.execCallback('cleanup_callback', 'insert_to_editor', o.content, o); - - if (o.get) - o.content = ed.execCallback('cleanup_callback', 'get_from_editor', o.content, o); - }); - } - - // Handle legacy save_callback option - if (settings.save_callback) { - self.onGetContent.add(function(ed, o) { - if (o.save) - o.content = ed.execCallback('save_callback', ed.id, o.content, ed.getBody()); - }); - } - - // Handle legacy handle_event_callback option - if (settings.handle_event_callback) { - self.onEvent.add(function(ed, e, o) { - if (self.execCallback('handle_event_callback', e, ed, o) === false) { - e.preventDefault(); - e.stopPropagation(); - } - }); - } - - // Handle legacy handle_node_change_callback option - if (settings.handle_node_change_callback) { - self.onNodeChange.add(function(ed, cm, n) { - ed.execCallback('handle_node_change_callback', ed.id, n, -1, -1, true, ed.selection.isCollapsed()); - }); - } - - // Handle legacy save_callback option - if (settings.save_callback) { - self.onSaveContent.add(function(ed, o) { - var h = ed.execCallback('save_callback', ed.id, o.content, ed.getBody()); - - if (h) - o.content = h; - }); - } - - // Handle legacy onchange_callback option - if (settings.onchange_callback) { - self.onChange.add(function(ed, l) { - ed.execCallback('onchange_callback', ed, l); - }); - } - }; - - tinymce.Editor.prototype.bindNativeEvents = function() { - // 'focus', 'blur', 'dblclick', 'beforedeactivate', submit, reset - var self = this, i, settings = self.settings, dom = self.dom, nativeToDispatcherMap; - - nativeToDispatcherMap = { - mouseup : 'onMouseUp', - mousedown : 'onMouseDown', - click : 'onClick', - keyup : 'onKeyUp', - keydown : 'onKeyDown', - keypress : 'onKeyPress', - submit : 'onSubmit', - reset : 'onReset', - contextmenu : 'onContextMenu', - dblclick : 'onDblClick', - paste : 'onPaste' // Doesn't work in all browsers yet - }; - - // Handler that takes a native event and sends it out to a dispatcher like onKeyDown - function eventHandler(evt, args) { - var type = evt.type; - - // Don't fire events when it's removed - if (self.removed) - return; - - // Sends the native event out to a global dispatcher then to the specific event dispatcher - if (self.onEvent.dispatch(self, evt, args) !== false) { - self[nativeToDispatcherMap[evt.fakeType || evt.type]].dispatch(self, evt, args); - } - }; - - // Opera doesn't support focus event for contentEditable elements so we need to fake it - function doOperaFocus(e) { - self.focus(true); - }; - - function nodeChanged(ed, e) { - // Normalize selection for example a|a becomes a|a except for Ctrl+A since it selects everything - if (e.keyCode != 65 || !tinymce.VK.metaKeyPressed(e)) { - self.selection.normalize(); - } - - self.nodeChanged(); - } - - // Add DOM events - each(nativeToDispatcherMap, function(dispatcherName, nativeName) { - var root = settings.content_editable ? self.getBody() : self.getDoc(); - - switch (nativeName) { - case 'contextmenu': - dom.bind(root, nativeName, eventHandler); - break; - - case 'paste': - dom.bind(self.getBody(), nativeName, eventHandler); - break; - - case 'submit': - case 'reset': - dom.bind(self.getElement().form || tinymce.DOM.getParent(self.id, 'form'), nativeName, eventHandler); - break; - - default: - dom.bind(root, nativeName, eventHandler); - } - }); - - // Set the editor as active when focused - dom.bind(settings.content_editable ? self.getBody() : (tinymce.isGecko ? self.getDoc() : self.getWin()), 'focus', function(e) { - self.focus(true); - }); - - if (settings.content_editable && tinymce.isOpera) { - dom.bind(self.getBody(), 'click', doOperaFocus); - dom.bind(self.getBody(), 'keydown', doOperaFocus); - } - - // Add node change handler - self.onMouseUp.add(nodeChanged); - - self.onKeyUp.add(function(ed, e) { - var keyCode = e.keyCode; - - if ((keyCode >= 33 && keyCode <= 36) || (keyCode >= 37 && keyCode <= 40) || keyCode == 13 || keyCode == 45 || keyCode == 46 || keyCode == 8 || (tinymce.isMac && (keyCode == 91 || keyCode == 93)) || e.ctrlKey) - nodeChanged(ed, e); - }); - - // Add reset handler - self.onReset.add(function() { - self.setContent(self.startContent, {format : 'raw'}); - }); - - // Add shortcuts - function handleShortcut(e, execute) { - if (e.altKey || e.ctrlKey || e.metaKey) { - each(self.shortcuts, function(shortcut) { - var ctrlState = tinymce.isMac ? e.metaKey : e.ctrlKey; - - if (shortcut.ctrl != ctrlState || shortcut.alt != e.altKey || shortcut.shift != e.shiftKey) - return; - - if (e.keyCode == shortcut.keyCode || (e.charCode && e.charCode == shortcut.charCode)) { - e.preventDefault(); - - if (execute) { - shortcut.func.call(shortcut.scope); - } - - return true; - } - }); - } - }; - - self.onKeyUp.add(function(ed, e) { - handleShortcut(e); - }); - - self.onKeyPress.add(function(ed, e) { - handleShortcut(e); - }); - - self.onKeyDown.add(function(ed, e) { - handleShortcut(e, true); - }); - - if (tinymce.isOpera) { - self.onClick.add(function(ed, e) { - e.preventDefault(); - }); - } - }; -})(tinymce); -(function(tinymce) { - // Added for compression purposes - var each = tinymce.each, undef, TRUE = true, FALSE = false; - - tinymce.EditorCommands = function(editor) { - var dom = editor.dom, - selection = editor.selection, - commands = {state: {}, exec : {}, value : {}}, - settings = editor.settings, - formatter = editor.formatter, - bookmark; - - function execCommand(command, ui, value) { - var func; - - command = command.toLowerCase(); - if (func = commands.exec[command]) { - func(command, ui, value); - return TRUE; - } - - return FALSE; - }; - - function queryCommandState(command) { - var func; - - command = command.toLowerCase(); - if (func = commands.state[command]) - return func(command); - - return -1; - }; - - function queryCommandValue(command) { - var func; - - command = command.toLowerCase(); - if (func = commands.value[command]) - return func(command); - - return FALSE; - }; - - function addCommands(command_list, type) { - type = type || 'exec'; - - each(command_list, function(callback, command) { - each(command.toLowerCase().split(','), function(command) { - commands[type][command] = callback; - }); - }); - }; - - // Expose public methods - tinymce.extend(this, { - execCommand : execCommand, - queryCommandState : queryCommandState, - queryCommandValue : queryCommandValue, - addCommands : addCommands - }); - - // Private methods - - function execNativeCommand(command, ui, value) { - if (ui === undef) - ui = FALSE; - - if (value === undef) - value = null; - - return editor.getDoc().execCommand(command, ui, value); - }; - - function isFormatMatch(name) { - return formatter.match(name); - }; - - function toggleFormat(name, value) { - formatter.toggle(name, value ? {value : value} : undef); - }; - - function storeSelection(type) { - bookmark = selection.getBookmark(type); - }; - - function restoreSelection() { - selection.moveToBookmark(bookmark); - }; - - // Add execCommand overrides - addCommands({ - // Ignore these, added for compatibility - 'mceResetDesignMode,mceBeginUndoLevel' : function() {}, - - // Add undo manager logic - 'mceEndUndoLevel,mceAddUndoLevel' : function() { - editor.undoManager.add(); - }, - - 'Cut,Copy,Paste' : function(command) { - var doc = editor.getDoc(), failed; - - // Try executing the native command - try { - execNativeCommand(command); - } catch (ex) { - // Command failed - failed = TRUE; - } - - // Present alert message about clipboard access not being available - if (failed || !doc.queryCommandSupported(command)) { - if (tinymce.isGecko) { - editor.windowManager.confirm(editor.getLang('clipboard_msg'), function(state) { - if (state) - open('http://www.mozilla.org/editor/midasdemo/securityprefs.html', '_blank'); - }); - } else - editor.windowManager.alert(editor.getLang('clipboard_no_support')); - } - }, - - // Override unlink command - unlink : function(command) { - if (selection.isCollapsed()) - selection.select(selection.getNode()); - - execNativeCommand(command); - selection.collapse(FALSE); - }, - - // Override justify commands to use the text formatter engine - 'JustifyLeft,JustifyCenter,JustifyRight,JustifyFull' : function(command) { - var align = command.substring(7); - - // Remove all other alignments first - each('left,center,right,full'.split(','), function(name) { - if (align != name) - formatter.remove('align' + name); - }); - - toggleFormat('align' + align); - execCommand('mceRepaint'); - }, - - // Override list commands to fix WebKit bug - 'InsertUnorderedList,InsertOrderedList' : function(command) { - var listElm, listParent; - - execNativeCommand(command); - - // WebKit produces lists within block elements so we need to split them - // we will replace the native list creation logic to custom logic later on - // TODO: Remove this when the list creation logic is removed - listElm = dom.getParent(selection.getNode(), 'ol,ul'); - if (listElm) { - listParent = listElm.parentNode; - - // If list is within a text block then split that block - if (/^(H[1-6]|P|ADDRESS|PRE)$/.test(listParent.nodeName)) { - storeSelection(); - dom.split(listParent, listElm); - restoreSelection(); - } - } - }, - - // Override commands to use the text formatter engine - 'Bold,Italic,Underline,Strikethrough,Superscript,Subscript' : function(command) { - toggleFormat(command); - }, - - // Override commands to use the text formatter engine - 'ForeColor,HiliteColor,FontName' : function(command, ui, value) { - toggleFormat(command, value); - }, - - FontSize : function(command, ui, value) { - var fontClasses, fontSizes; - - // Convert font size 1-7 to styles - if (value >= 1 && value <= 7) { - fontSizes = tinymce.explode(settings.font_size_style_values); - fontClasses = tinymce.explode(settings.font_size_classes); - - if (fontClasses) - value = fontClasses[value - 1] || value; - else - value = fontSizes[value - 1] || value; - } - - toggleFormat(command, value); - }, - - RemoveFormat : function(command) { - formatter.remove(command); - }, - - mceBlockQuote : function(command) { - toggleFormat('blockquote'); - }, - - FormatBlock : function(command, ui, value) { - return toggleFormat(value || 'p'); - }, - - mceCleanup : function() { - var bookmark = selection.getBookmark(); - - editor.setContent(editor.getContent({cleanup : TRUE}), {cleanup : TRUE}); - - selection.moveToBookmark(bookmark); - }, - - mceRemoveNode : function(command, ui, value) { - var node = value || selection.getNode(); - - // Make sure that the body node isn't removed - if (node != editor.getBody()) { - storeSelection(); - editor.dom.remove(node, TRUE); - restoreSelection(); - } - }, - - mceSelectNodeDepth : function(command, ui, value) { - var counter = 0; - - dom.getParent(selection.getNode(), function(node) { - if (node.nodeType == 1 && counter++ == value) { - selection.select(node); - return FALSE; - } - }, editor.getBody()); - }, - - mceSelectNode : function(command, ui, value) { - selection.select(value); - }, - - mceInsertContent : function(command, ui, value) { - var parser, serializer, parentNode, rootNode, fragment, args, - marker, nodeRect, viewPortRect, rng, node, node2, bookmarkHtml, viewportBodyElement; - - //selection.normalize(); - - // Setup parser and serializer - parser = editor.parser; - serializer = new tinymce.html.Serializer({}, editor.schema); - bookmarkHtml = '\uFEFF'; - - // Run beforeSetContent handlers on the HTML to be inserted - args = {content: value, format: 'html'}; - selection.onBeforeSetContent.dispatch(selection, args); - value = args.content; - - // Add caret at end of contents if it's missing - if (value.indexOf('{$caret}') == -1) - value += '{$caret}'; - - // Replace the caret marker with a span bookmark element - value = value.replace(/\{\$caret\}/, bookmarkHtml); - - // Insert node maker where we will insert the new HTML and get it's parent - if (!selection.isCollapsed()) - editor.getDoc().execCommand('Delete', false, null); - - parentNode = selection.getNode(); - - // Parse the fragment within the context of the parent node - args = {context : parentNode.nodeName.toLowerCase()}; - fragment = parser.parse(value, args); - - // Move the caret to a more suitable location - node = fragment.lastChild; - if (node.attr('id') == 'mce_marker') { - marker = node; - - for (node = node.prev; node; node = node.walk(true)) { - if (node.type == 3 || !dom.isBlock(node.name)) { - node.parent.insert(marker, node, node.name === 'br'); - break; - } - } - } - - // If parser says valid we can insert the contents into that parent - if (!args.invalid) { - value = serializer.serialize(fragment); - - // Check if parent is empty or only has one BR element then set the innerHTML of that parent - node = parentNode.firstChild; - node2 = parentNode.lastChild; - if (!node || (node === node2 && node.nodeName === 'BR')) - dom.setHTML(parentNode, value); - else - selection.setContent(value); - } else { - // If the fragment was invalid within that context then we need - // to parse and process the parent it's inserted into - - // Insert bookmark node and get the parent - selection.setContent(bookmarkHtml); - parentNode = selection.getNode(); - rootNode = editor.getBody(); - - // Opera will return the document node when selection is in root - if (parentNode.nodeType == 9) - parentNode = node = rootNode; - else - node = parentNode; - - // Find the ancestor just before the root element - while (node !== rootNode) { - parentNode = node; - node = node.parentNode; - } - - // Get the outer/inner HTML depending on if we are in the root and parser and serialize that - value = parentNode == rootNode ? rootNode.innerHTML : dom.getOuterHTML(parentNode); - value = serializer.serialize( - parser.parse( - // Need to replace by using a function since $ in the contents would otherwise be a problem - value.replace(//i, function() { - return serializer.serialize(fragment); - }) - ) - ); - - // Set the inner/outer HTML depending on if we are in the root or not - if (parentNode == rootNode) - dom.setHTML(rootNode, value); - else - dom.setOuterHTML(parentNode, value); - } - - marker = dom.get('mce_marker'); - - // Scroll range into view scrollIntoView on element can't be used since it will scroll the main view port as well - nodeRect = dom.getRect(marker); - viewPortRect = dom.getViewPort(editor.getWin()); - - // Check if node is out side the viewport if it is then scroll to it - if ((nodeRect.y + nodeRect.h > viewPortRect.y + viewPortRect.h || nodeRect.y < viewPortRect.y) || - (nodeRect.x > viewPortRect.x + viewPortRect.w || nodeRect.x < viewPortRect.x)) { - viewportBodyElement = tinymce.isIE ? editor.getDoc().documentElement : editor.getBody(); - viewportBodyElement.scrollLeft = nodeRect.x; - viewportBodyElement.scrollTop = nodeRect.y - viewPortRect.h + 25; - } - - // Move selection before marker and remove it - rng = dom.createRng(); - - // If previous sibling is a text node set the selection to the end of that node - node = marker.previousSibling; - if (node && node.nodeType == 3) { - rng.setStart(node, node.nodeValue.length); - } else { - // If the previous sibling isn't a text node or doesn't exist set the selection before the marker node - rng.setStartBefore(marker); - rng.setEndBefore(marker); - } - - // Remove the marker node and set the new range - dom.remove(marker); - selection.setRng(rng); - - // Dispatch after event and add any visual elements needed - selection.onSetContent.dispatch(selection, args); - editor.addVisual(); - }, - - mceInsertRawHTML : function(command, ui, value) { - selection.setContent('tiny_mce_marker'); - editor.setContent(editor.getContent().replace(/tiny_mce_marker/g, function() { return value })); - }, - - mceToggleFormat : function(command, ui, value) { - toggleFormat(value); - }, - - mceSetContent : function(command, ui, value) { - editor.setContent(value); - }, - - 'Indent,Outdent' : function(command) { - var intentValue, indentUnit, value; - - // Setup indent level - intentValue = settings.indentation; - indentUnit = /[a-z%]+$/i.exec(intentValue); - intentValue = parseInt(intentValue); - - if (!queryCommandState('InsertUnorderedList') && !queryCommandState('InsertOrderedList')) { - // If forced_root_blocks is set to false we don't have a block to indent so lets create a div - if (!settings.forced_root_block && !dom.getParent(selection.getNode(), dom.isBlock)) { - formatter.apply('div'); - } - - each(selection.getSelectedBlocks(), function(element) { - if (command == 'outdent') { - value = Math.max(0, parseInt(element.style.paddingLeft || 0) - intentValue); - dom.setStyle(element, 'paddingLeft', value ? value + indentUnit : ''); - } else - dom.setStyle(element, 'paddingLeft', (parseInt(element.style.paddingLeft || 0) + intentValue) + indentUnit); - }); - } else - execNativeCommand(command); - }, - - mceRepaint : function() { - var bookmark; - - if (tinymce.isGecko) { - try { - storeSelection(TRUE); - - if (selection.getSel()) - selection.getSel().selectAllChildren(editor.getBody()); - - selection.collapse(TRUE); - restoreSelection(); - } catch (ex) { - // Ignore - } - } - }, - - mceToggleFormat : function(command, ui, value) { - formatter.toggle(value); - }, - - InsertHorizontalRule : function() { - editor.execCommand('mceInsertContent', false, '
    '); - }, - - mceToggleVisualAid : function() { - editor.hasVisual = !editor.hasVisual; - editor.addVisual(); - }, - - mceReplaceContent : function(command, ui, value) { - editor.execCommand('mceInsertContent', false, value.replace(/\{\$selection\}/g, selection.getContent({format : 'text'}))); - }, - - mceInsertLink : function(command, ui, value) { - var anchor; - - if (typeof(value) == 'string') - value = {href : value}; - - anchor = dom.getParent(selection.getNode(), 'a'); - - // Spaces are never valid in URLs and it's a very common mistake for people to make so we fix it here. - value.href = value.href.replace(' ', '%20'); - - // Remove existing links if there could be child links or that the href isn't specified - if (!anchor || !value.href) { - formatter.remove('link'); - } - - // Apply new link to selection - if (value.href) { - formatter.apply('link', value, anchor); - } - }, - - selectAll : function() { - var root = dom.getRoot(), rng = dom.createRng(); - - // Old IE does a better job with selectall than new versions - if (selection.getRng().setStart) { - rng.setStart(root, 0); - rng.setEnd(root, root.childNodes.length); - - selection.setRng(rng); - } else { - execNativeCommand('SelectAll'); - } - } - }); - - // Add queryCommandState overrides - addCommands({ - // Override justify commands - 'JustifyLeft,JustifyCenter,JustifyRight,JustifyFull' : function(command) { - var name = 'align' + command.substring(7); - var nodes = selection.isCollapsed() ? [dom.getParent(selection.getNode(), dom.isBlock)] : selection.getSelectedBlocks(); - var matches = tinymce.map(nodes, function(node) { - return !!formatter.matchNode(node, name); - }); - return tinymce.inArray(matches, TRUE) !== -1; - }, - - 'Bold,Italic,Underline,Strikethrough,Superscript,Subscript' : function(command) { - return isFormatMatch(command); - }, - - mceBlockQuote : function() { - return isFormatMatch('blockquote'); - }, - - Outdent : function() { - var node; - - if (settings.inline_styles) { - if ((node = dom.getParent(selection.getStart(), dom.isBlock)) && parseInt(node.style.paddingLeft) > 0) - return TRUE; - - if ((node = dom.getParent(selection.getEnd(), dom.isBlock)) && parseInt(node.style.paddingLeft) > 0) - return TRUE; - } - - return queryCommandState('InsertUnorderedList') || queryCommandState('InsertOrderedList') || (!settings.inline_styles && !!dom.getParent(selection.getNode(), 'BLOCKQUOTE')); - }, - - 'InsertUnorderedList,InsertOrderedList' : function(command) { - var list = dom.getParent(selection.getNode(), 'ul,ol'); - return list && - (command === 'insertunorderedlist' && list.tagName === 'UL' - || command === 'insertorderedlist' && list.tagName === 'OL'); - } - }, 'state'); - - // Add queryCommandValue overrides - addCommands({ - 'FontSize,FontName' : function(command) { - var value = 0, parent; - - if (parent = dom.getParent(selection.getNode(), 'span')) { - if (command == 'fontsize') - value = parent.style.fontSize; - else - value = parent.style.fontFamily.replace(/, /g, ',').replace(/[\'\"]/g, '').toLowerCase(); - } - - return value; - } - }, 'value'); - - // Add undo manager logic - addCommands({ - Undo : function() { - editor.undoManager.undo(); - }, - - Redo : function() { - editor.undoManager.redo(); - } - }); - }; -})(tinymce); -(function(tinymce) { - var Dispatcher = tinymce.util.Dispatcher; - - tinymce.UndoManager = function(editor) { - var self, index = 0, data = [], beforeBookmark, onAdd, onUndo, onRedo; - - function getContent() { - // Remove whitespace before/after and remove pure bogus nodes - return tinymce.trim(editor.getContent({format : 'raw', no_events : 1}).replace(/]+data-mce-bogus[^>]+>[\u200B\uFEFF]+<\/span>/g, '')); - }; - - function addNonTypingUndoLevel() { - self.typing = false; - self.add(); - }; - - // Create event instances - onBeforeAdd = new Dispatcher(self); - onAdd = new Dispatcher(self); - onUndo = new Dispatcher(self); - onRedo = new Dispatcher(self); - - // Pass though onAdd event from UndoManager to Editor as onChange - onAdd.add(function(undoman, level) { - if (undoman.hasUndo()) - return editor.onChange.dispatch(editor, level, undoman); - }); - - // Pass though onUndo event from UndoManager to Editor - onUndo.add(function(undoman, level) { - return editor.onUndo.dispatch(editor, level, undoman); - }); - - // Pass though onRedo event from UndoManager to Editor - onRedo.add(function(undoman, level) { - return editor.onRedo.dispatch(editor, level, undoman); - }); - - // Add initial undo level when the editor is initialized - editor.onInit.add(function() { - self.add(); - }); - - // Get position before an execCommand is processed - editor.onBeforeExecCommand.add(function(ed, cmd, ui, val, args) { - if (cmd != 'Undo' && cmd != 'Redo' && cmd != 'mceRepaint' && (!args || !args.skip_undo)) { - self.beforeChange(); - } - }); - - // Add undo level after an execCommand call was made - editor.onExecCommand.add(function(ed, cmd, ui, val, args) { - if (cmd != 'Undo' && cmd != 'Redo' && cmd != 'mceRepaint' && (!args || !args.skip_undo)) { - self.add(); - } - }); - - // Add undo level on save contents, drag end and blur/focusout - editor.onSaveContent.add(addNonTypingUndoLevel); - editor.dom.bind(editor.dom.getRoot(), 'dragend', addNonTypingUndoLevel); - editor.dom.bind(editor.getBody(), 'focusout', function(e) { - if (!editor.removed && self.typing) { - addNonTypingUndoLevel(); - } - }); - - editor.onKeyUp.add(function(editor, e) { - var keyCode = e.keyCode; - - if ((keyCode >= 33 && keyCode <= 36) || (keyCode >= 37 && keyCode <= 40) || keyCode == 45 || keyCode == 13 || e.ctrlKey) { - addNonTypingUndoLevel(); - } - }); - - editor.onKeyDown.add(function(editor, e) { - var keyCode = e.keyCode; - - // Is caracter positon keys left,right,up,down,home,end,pgdown,pgup,enter - if ((keyCode >= 33 && keyCode <= 36) || (keyCode >= 37 && keyCode <= 40) || keyCode == 45) { - if (self.typing) { - addNonTypingUndoLevel(); - } - - return; - } - - // If key isn't shift,ctrl,alt,capslock,metakey - if ((keyCode < 16 || keyCode > 20) && keyCode != 224 && keyCode != 91 && !self.typing) { - self.beforeChange(); - self.typing = true; - self.add(); - } - }); - - editor.onMouseDown.add(function(editor, e) { - if (self.typing) { - addNonTypingUndoLevel(); - } - }); - - // Add keyboard shortcuts for undo/redo keys - editor.addShortcut('ctrl+z', 'undo_desc', 'Undo'); - editor.addShortcut('ctrl+y', 'redo_desc', 'Redo'); - - self = { - // Explose for debugging reasons - data : data, - - typing : false, - - onBeforeAdd: onBeforeAdd, - - onAdd : onAdd, - - onUndo : onUndo, - - onRedo : onRedo, - - beforeChange : function() { - beforeBookmark = editor.selection.getBookmark(2, true); - }, - - add : function(level) { - var i, settings = editor.settings, lastLevel; - - level = level || {}; - level.content = getContent(); - - self.onBeforeAdd.dispatch(self, level); - - // Add undo level if needed - lastLevel = data[index]; - if (lastLevel && lastLevel.content == level.content) - return null; - - // Set before bookmark on previous level - if (data[index]) - data[index].beforeBookmark = beforeBookmark; - - // Time to compress - if (settings.custom_undo_redo_levels) { - if (data.length > settings.custom_undo_redo_levels) { - for (i = 0; i < data.length - 1; i++) - data[i] = data[i + 1]; - - data.length--; - index = data.length; - } - } - - // Get a non intrusive normalized bookmark - level.bookmark = editor.selection.getBookmark(2, true); - - // Crop array if needed - if (index < data.length - 1) - data.length = index + 1; - - data.push(level); - index = data.length - 1; - - self.onAdd.dispatch(self, level); - editor.isNotDirty = 0; - - return level; - }, - - undo : function() { - var level, i; - - if (self.typing) { - self.add(); - self.typing = false; - } - - if (index > 0) { - level = data[--index]; - - editor.setContent(level.content, {format : 'raw'}); - editor.selection.moveToBookmark(level.beforeBookmark); - - self.onUndo.dispatch(self, level); - } - - return level; - }, - - redo : function() { - var level; - - if (index < data.length - 1) { - level = data[++index]; - - editor.setContent(level.content, {format : 'raw'}); - editor.selection.moveToBookmark(level.bookmark); - - self.onRedo.dispatch(self, level); - } - - return level; - }, - - clear : function() { - data = []; - index = 0; - self.typing = false; - }, - - hasUndo : function() { - return index > 0 || this.typing; - }, - - hasRedo : function() { - return index < data.length - 1 && !this.typing; - } - }; - - return self; - }; -})(tinymce); -tinymce.ForceBlocks = function(editor) { - var settings = editor.settings, dom = editor.dom, selection = editor.selection, blockElements = editor.schema.getBlockElements(); - - function addRootBlocks() { - var node = selection.getStart(), rootNode = editor.getBody(), rng, startContainer, startOffset, endContainer, endOffset, rootBlockNode, tempNode, offset = -0xFFFFFF, wrapped, isInEditorDocument; - - if (!node || node.nodeType !== 1 || !settings.forced_root_block) - return; - - // Check if node is wrapped in block - while (node && node != rootNode) { - if (blockElements[node.nodeName]) - return; - - node = node.parentNode; - } - - // Get current selection - rng = selection.getRng(); - if (rng.setStart) { - startContainer = rng.startContainer; - startOffset = rng.startOffset; - endContainer = rng.endContainer; - endOffset = rng.endOffset; - } else { - // Force control range into text range - if (rng.item) { - node = rng.item(0); - rng = editor.getDoc().body.createTextRange(); - rng.moveToElementText(node); - } - - isInEditorDocument = rng.parentElement().ownerDocument === editor.getDoc(); - tmpRng = rng.duplicate(); - tmpRng.collapse(true); - startOffset = tmpRng.move('character', offset) * -1; - - if (!tmpRng.collapsed) { - tmpRng = rng.duplicate(); - tmpRng.collapse(false); - endOffset = (tmpRng.move('character', offset) * -1) - startOffset; - } - } - - // Wrap non block elements and text nodes - node = rootNode.firstChild; - while (node) { - if (node.nodeType === 3 || (node.nodeType == 1 && !blockElements[node.nodeName])) { - // Remove empty text nodes - if (node.nodeType === 3 && node.nodeValue.length == 0) { - tempNode = node; - node = node.nextSibling; - dom.remove(tempNode); - continue; - } - - if (!rootBlockNode) { - rootBlockNode = dom.create(settings.forced_root_block); - node.parentNode.insertBefore(rootBlockNode, node); - wrapped = true; - } - - tempNode = node; - node = node.nextSibling; - rootBlockNode.appendChild(tempNode); - } else { - rootBlockNode = null; - node = node.nextSibling; - } - } - - if (wrapped) { - if (rng.setStart) { - rng.setStart(startContainer, startOffset); - rng.setEnd(endContainer, endOffset); - selection.setRng(rng); - } else { - // Only select if the previous selection was inside the document to prevent auto focus in quirks mode - if (isInEditorDocument) { - try { - rng = editor.getDoc().body.createTextRange(); - rng.moveToElementText(rootNode); - rng.collapse(true); - rng.moveStart('character', startOffset); - - if (endOffset > 0) - rng.moveEnd('character', endOffset); - - rng.select(); - } catch (ex) { - // Ignore - } - } - } - - editor.nodeChanged(); - } - }; - - // Force root blocks - if (settings.forced_root_block) { - editor.onKeyUp.add(addRootBlocks); - editor.onNodeChange.add(addRootBlocks); - } -}; -(function(tinymce) { - // Shorten names - var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each, extend = tinymce.extend; - - tinymce.create('tinymce.ControlManager', { - ControlManager : function(ed, s) { - var t = this, i; - - s = s || {}; - t.editor = ed; - t.controls = {}; - t.onAdd = new tinymce.util.Dispatcher(t); - t.onPostRender = new tinymce.util.Dispatcher(t); - t.prefix = s.prefix || ed.id + '_'; - t._cls = {}; - - t.onPostRender.add(function() { - each(t.controls, function(c) { - c.postRender(); - }); - }); - }, - - get : function(id) { - return this.controls[this.prefix + id] || this.controls[id]; - }, - - setActive : function(id, s) { - var c = null; - - if (c = this.get(id)) - c.setActive(s); - - return c; - }, - - setDisabled : function(id, s) { - var c = null; - - if (c = this.get(id)) - c.setDisabled(s); - - return c; - }, - - add : function(c) { - var t = this; - - if (c) { - t.controls[c.id] = c; - t.onAdd.dispatch(c, t); - } - - return c; - }, - - createControl : function(name) { - var ctrl, i, l, self = this, editor = self.editor, factories, ctrlName; - - // Build control factory cache - if (!self.controlFactories) { - self.controlFactories = []; - each(editor.plugins, function(plugin) { - if (plugin.createControl) { - self.controlFactories.push(plugin); - } - }); - } - - // Create controls by asking cached factories - factories = self.controlFactories; - for (i = 0, l = factories.length; i < l; i++) { - ctrl = factories[i].createControl(name, self); - - if (ctrl) { - return self.add(ctrl); - } - } - - // Create sepearator - if (name === "|" || name === "separator") { - return self.createSeparator(); - } - - // Create control from button collection - if (editor.buttons && (ctrl = editor.buttons[name])) { - return self.createButton(name, ctrl); - } - - return self.add(ctrl); - }, - - createDropMenu : function(id, s, cc) { - var t = this, ed = t.editor, c, bm, v, cls; - - s = extend({ - 'class' : 'mceDropDown', - constrain : ed.settings.constrain_menus - }, s); - - s['class'] = s['class'] + ' ' + ed.getParam('skin') + 'Skin'; - if (v = ed.getParam('skin_variant')) - s['class'] += ' ' + ed.getParam('skin') + 'Skin' + v.substring(0, 1).toUpperCase() + v.substring(1); - - s['class'] += ed.settings.directionality == "rtl" ? ' mceRtl' : ''; - - id = t.prefix + id; - cls = cc || t._cls.dropmenu || tinymce.ui.DropMenu; - c = t.controls[id] = new cls(id, s); - c.onAddItem.add(function(c, o) { - var s = o.settings; - - s.title = ed.getLang(s.title, s.title); - - if (!s.onclick) { - s.onclick = function(v) { - if (s.cmd) - ed.execCommand(s.cmd, s.ui || false, s.value); - }; - } - }); - - ed.onRemove.add(function() { - c.destroy(); - }); - - // Fix for bug #1897785, #1898007 - if (tinymce.isIE) { - c.onShowMenu.add(function() { - // IE 8 needs focus in order to store away a range with the current collapsed caret location - ed.focus(); - - bm = ed.selection.getBookmark(1); - }); - - c.onHideMenu.add(function() { - if (bm) { - ed.selection.moveToBookmark(bm); - bm = 0; - } - }); - } - - return t.add(c); - }, - - createListBox : function(id, s, cc) { - var t = this, ed = t.editor, cmd, c, cls; - - if (t.get(id)) - return null; - - s.title = ed.translate(s.title); - s.scope = s.scope || ed; - - if (!s.onselect) { - s.onselect = function(v) { - ed.execCommand(s.cmd, s.ui || false, v || s.value); - }; - } - - s = extend({ - title : s.title, - 'class' : 'mce_' + id, - scope : s.scope, - control_manager : t - }, s); - - id = t.prefix + id; - - - function useNativeListForAccessibility(ed) { - return ed.settings.use_accessible_selects && !tinymce.isGecko - } - - if (ed.settings.use_native_selects || useNativeListForAccessibility(ed)) - c = new tinymce.ui.NativeListBox(id, s); - else { - cls = cc || t._cls.listbox || tinymce.ui.ListBox; - c = new cls(id, s, ed); - } - - t.controls[id] = c; - - // Fix focus problem in Safari - if (tinymce.isWebKit) { - c.onPostRender.add(function(c, n) { - // Store bookmark on mousedown - Event.add(n, 'mousedown', function() { - ed.bookmark = ed.selection.getBookmark(1); - }); - - // Restore on focus, since it might be lost - Event.add(n, 'focus', function() { - ed.selection.moveToBookmark(ed.bookmark); - ed.bookmark = null; - }); - }); - } - - if (c.hideMenu) - ed.onMouseDown.add(c.hideMenu, c); - - return t.add(c); - }, - - createButton : function(id, s, cc) { - var t = this, ed = t.editor, o, c, cls; - - if (t.get(id)) - return null; - - s.title = ed.translate(s.title); - s.label = ed.translate(s.label); - s.scope = s.scope || ed; - - if (!s.onclick && !s.menu_button) { - s.onclick = function() { - ed.execCommand(s.cmd, s.ui || false, s.value); - }; - } - - s = extend({ - title : s.title, - 'class' : 'mce_' + id, - unavailable_prefix : ed.getLang('unavailable', ''), - scope : s.scope, - control_manager : t - }, s); - - id = t.prefix + id; - - if (s.menu_button) { - cls = cc || t._cls.menubutton || tinymce.ui.MenuButton; - c = new cls(id, s, ed); - ed.onMouseDown.add(c.hideMenu, c); - } else { - cls = t._cls.button || tinymce.ui.Button; - c = new cls(id, s, ed); - } - - return t.add(c); - }, - - createMenuButton : function(id, s, cc) { - s = s || {}; - s.menu_button = 1; - - return this.createButton(id, s, cc); - }, - - createSplitButton : function(id, s, cc) { - var t = this, ed = t.editor, cmd, c, cls; - - if (t.get(id)) - return null; - - s.title = ed.translate(s.title); - s.scope = s.scope || ed; - - if (!s.onclick) { - s.onclick = function(v) { - ed.execCommand(s.cmd, s.ui || false, v || s.value); - }; - } - - if (!s.onselect) { - s.onselect = function(v) { - ed.execCommand(s.cmd, s.ui || false, v || s.value); - }; - } - - s = extend({ - title : s.title, - 'class' : 'mce_' + id, - scope : s.scope, - control_manager : t - }, s); - - id = t.prefix + id; - cls = cc || t._cls.splitbutton || tinymce.ui.SplitButton; - c = t.add(new cls(id, s, ed)); - ed.onMouseDown.add(c.hideMenu, c); - - return c; - }, - - createColorSplitButton : function(id, s, cc) { - var t = this, ed = t.editor, cmd, c, cls, bm; - - if (t.get(id)) - return null; - - s.title = ed.translate(s.title); - s.scope = s.scope || ed; - - if (!s.onclick) { - s.onclick = function(v) { - if (tinymce.isIE) - bm = ed.selection.getBookmark(1); - - ed.execCommand(s.cmd, s.ui || false, v || s.value); - }; - } - - if (!s.onselect) { - s.onselect = function(v) { - ed.execCommand(s.cmd, s.ui || false, v || s.value); - }; - } - - s = extend({ - title : s.title, - 'class' : 'mce_' + id, - 'menu_class' : ed.getParam('skin') + 'Skin', - scope : s.scope, - more_colors_title : ed.getLang('more_colors') - }, s); - - id = t.prefix + id; - cls = cc || t._cls.colorsplitbutton || tinymce.ui.ColorSplitButton; - c = new cls(id, s, ed); - ed.onMouseDown.add(c.hideMenu, c); - - // Remove the menu element when the editor is removed - ed.onRemove.add(function() { - c.destroy(); - }); - - // Fix for bug #1897785, #1898007 - if (tinymce.isIE) { - c.onShowMenu.add(function() { - // IE 8 needs focus in order to store away a range with the current collapsed caret location - ed.focus(); - bm = ed.selection.getBookmark(1); - }); - - c.onHideMenu.add(function() { - if (bm) { - ed.selection.moveToBookmark(bm); - bm = 0; - } - }); - } - - return t.add(c); - }, - - createToolbar : function(id, s, cc) { - var c, t = this, cls; - - id = t.prefix + id; - cls = cc || t._cls.toolbar || tinymce.ui.Toolbar; - c = new cls(id, s, t.editor); - - if (t.get(id)) - return null; - - return t.add(c); - }, - - createToolbarGroup : function(id, s, cc) { - var c, t = this, cls; - id = t.prefix + id; - cls = cc || this._cls.toolbarGroup || tinymce.ui.ToolbarGroup; - c = new cls(id, s, t.editor); - - if (t.get(id)) - return null; - - return t.add(c); - }, - - createSeparator : function(cc) { - var cls = cc || this._cls.separator || tinymce.ui.Separator; - - return new cls(); - }, - - setControlType : function(n, c) { - return this._cls[n.toLowerCase()] = c; - }, - - destroy : function() { - each(this.controls, function(c) { - c.destroy(); - }); - - this.controls = null; - } - }); -})(tinymce); -(function(tinymce) { - var Dispatcher = tinymce.util.Dispatcher, each = tinymce.each, isIE = tinymce.isIE, isOpera = tinymce.isOpera; - - tinymce.create('tinymce.WindowManager', { - WindowManager : function(ed) { - var t = this; - - t.editor = ed; - t.onOpen = new Dispatcher(t); - t.onClose = new Dispatcher(t); - t.params = {}; - t.features = {}; - }, - - open : function(s, p) { - var t = this, f = '', x, y, mo = t.editor.settings.dialog_type == 'modal', w, sw, sh, vp = tinymce.DOM.getViewPort(), u; - - // Default some options - s = s || {}; - p = p || {}; - sw = isOpera ? vp.w : screen.width; // Opera uses windows inside the Opera window - sh = isOpera ? vp.h : screen.height; - s.name = s.name || 'mc_' + new Date().getTime(); - s.width = parseInt(s.width || 320); - s.height = parseInt(s.height || 240); - s.resizable = true; - s.left = s.left || parseInt(sw / 2.0) - (s.width / 2.0); - s.top = s.top || parseInt(sh / 2.0) - (s.height / 2.0); - p.inline = false; - p.mce_width = s.width; - p.mce_height = s.height; - p.mce_auto_focus = s.auto_focus; - - if (mo) { - if (isIE) { - s.center = true; - s.help = false; - s.dialogWidth = s.width + 'px'; - s.dialogHeight = s.height + 'px'; - s.scroll = s.scrollbars || false; - } - } - - // Build features string - each(s, function(v, k) { - if (tinymce.is(v, 'boolean')) - v = v ? 'yes' : 'no'; - - if (!/^(name|url)$/.test(k)) { - if (isIE && mo) - f += (f ? ';' : '') + k + ':' + v; - else - f += (f ? ',' : '') + k + '=' + v; - } - }); - - t.features = s; - t.params = p; - t.onOpen.dispatch(t, s, p); - - u = s.url || s.file; - u = tinymce._addVer(u); - - try { - if (isIE && mo) { - w = 1; - window.showModalDialog(u, window, f); - } else - w = window.open(u, s.name, f); - } catch (ex) { - // Ignore - } - - if (!w) - alert(t.editor.getLang('popup_blocked')); - }, - - close : function(w) { - w.close(); - this.onClose.dispatch(this); - }, - - createInstance : function(cl, a, b, c, d, e) { - var f = tinymce.resolve(cl); - - return new f(a, b, c, d, e); - }, - - confirm : function(t, cb, s, w) { - w = w || window; - - cb.call(s || this, w.confirm(this._decode(this.editor.getLang(t, t)))); - }, - - alert : function(tx, cb, s, w) { - var t = this; - - w = w || window; - w.alert(t._decode(t.editor.getLang(tx, tx))); - - if (cb) - cb.call(s || t); - }, - - resizeBy : function(dw, dh, win) { - win.resizeBy(dw, dh); - }, - - // Internal functions - - _decode : function(s) { - return tinymce.DOM.decode(s).replace(/\\n/g, '\n'); - } - }); -}(tinymce)); -(function(tinymce) { - tinymce.Formatter = function(ed) { - var formats = {}, - each = tinymce.each, - dom = ed.dom, - selection = ed.selection, - TreeWalker = tinymce.dom.TreeWalker, - rangeUtils = new tinymce.dom.RangeUtils(dom), - isValidChild = ed.schema.isValidChild, - isBlock = dom.isBlock, - forcedRootBlock = ed.settings.forced_root_block, - nodeIndex = dom.nodeIndex, - INVISIBLE_CHAR = '\uFEFF', - MCE_ATTR_RE = /^(src|href|style)$/, - FALSE = false, - TRUE = true, - formatChangeData, - undef, - getContentEditable = dom.getContentEditable; - - function isTextBlock(name) { - if (name.nodeType) { - name = name.nodeName; - } - - return !!ed.schema.getTextBlockElements()[name.toLowerCase()]; - } - - function getParents(node, selector) { - return dom.getParents(node, selector, dom.getRoot()); - } - - function isCaretNode(node) { - return node.nodeType === 1 && node.id === '_mce_caret'; - } - - function defaultFormats() { - register({ - alignleft : [ - {selector : 'figure,p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li', styles : {textAlign : 'left'}, defaultBlock: 'div'}, - {selector : 'img,table', collapsed : false, styles : {'float' : 'left'}} - ], - - aligncenter : [ - {selector : 'figure,p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li', styles : {textAlign : 'center'}, defaultBlock: 'div'}, - {selector : 'img', collapsed : false, styles : {display : 'block', marginLeft : 'auto', marginRight : 'auto'}}, - {selector : 'table', collapsed : false, styles : {marginLeft : 'auto', marginRight : 'auto'}} - ], - - alignright : [ - {selector : 'figure,p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li', styles : {textAlign : 'right'}, defaultBlock: 'div'}, - {selector : 'img,table', collapsed : false, styles : {'float' : 'right'}} - ], - - alignfull : [ - {selector : 'figure,p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li', styles : {textAlign : 'justify'}, defaultBlock: 'div'} - ], - - bold : [ - {inline : 'strong', remove : 'all'}, - {inline : 'span', styles : {fontWeight : 'bold'}}, - {inline : 'b', remove : 'all'} - ], - - italic : [ - {inline : 'em', remove : 'all'}, - {inline : 'span', styles : {fontStyle : 'italic'}}, - {inline : 'i', remove : 'all'} - ], - - underline : [ - {inline : 'span', styles : {textDecoration : 'underline'}, exact : true}, - {inline : 'u', remove : 'all'} - ], - - strikethrough : [ - {inline : 'span', styles : {textDecoration : 'line-through'}, exact : true}, - {inline : 'strike', remove : 'all'} - ], - - forecolor : {inline : 'span', styles : {color : '%value'}, wrap_links : false}, - hilitecolor : {inline : 'span', styles : {backgroundColor : '%value'}, wrap_links : false}, - fontname : {inline : 'span', styles : {fontFamily : '%value'}}, - fontsize : {inline : 'span', styles : {fontSize : '%value'}}, - fontsize_class : {inline : 'span', attributes : {'class' : '%value'}}, - blockquote : {block : 'blockquote', wrapper : 1, remove : 'all'}, - subscript : {inline : 'sub'}, - superscript : {inline : 'sup'}, - - link : {inline : 'a', selector : 'a', remove : 'all', split : true, deep : true, - onmatch : function() { - return true; - }, - - onformat : function(elm, fmt, vars) { - each(vars, function(value, key) { - dom.setAttrib(elm, key, value); - }); - } - }, - - removeformat : [ - {selector : 'b,strong,em,i,font,u,strike', remove : 'all', split : true, expand : false, block_expand : true, deep : true}, - {selector : 'span', attributes : ['style', 'class'], remove : 'empty', split : true, expand : false, deep : true}, - {selector : '*', attributes : ['style', 'class'], split : false, expand : false, deep : true} - ] - }); - - // Register default block formats - each('p h1 h2 h3 h4 h5 h6 div address pre div code dt dd samp'.split(/\s/), function(name) { - register(name, {block : name, remove : 'all'}); - }); - - // Register user defined formats - register(ed.settings.formats); - } - - function addKeyboardShortcuts() { - // Add some inline shortcuts - ed.addShortcut('ctrl+b', 'bold_desc', 'Bold'); - ed.addShortcut('ctrl+i', 'italic_desc', 'Italic'); - ed.addShortcut('ctrl+u', 'underline_desc', 'Underline'); - - // BlockFormat shortcuts keys - for (var i = 1; i <= 6; i++) { - ed.addShortcut('ctrl+' + i, '', ['FormatBlock', false, 'h' + i]); - } - - ed.addShortcut('ctrl+7', '', ['FormatBlock', false, 'p']); - ed.addShortcut('ctrl+8', '', ['FormatBlock', false, 'div']); - ed.addShortcut('ctrl+9', '', ['FormatBlock', false, 'address']); - } - - // Public functions - - function get(name) { - return name ? formats[name] : formats; - } - - function register(name, format) { - if (name) { - if (typeof(name) !== 'string') { - each(name, function(format, name) { - register(name, format); - }); - } else { - // Force format into array and add it to internal collection - format = format.length ? format : [format]; - - each(format, function(format) { - // Set deep to false by default on selector formats this to avoid removing - // alignment on images inside paragraphs when alignment is changed on paragraphs - if (format.deep === undef) { - format.deep = !format.selector; - } - - // Default to true - if (format.split === undef) { - format.split = !format.selector || format.inline; - } - - // Default to true - if (format.remove === undef && format.selector && !format.inline) { - format.remove = 'none'; - } - - // Mark format as a mixed format inline + block level - if (format.selector && format.inline) { - format.mixed = true; - format.block_expand = true; - } - - // Split classes if needed - if (typeof(format.classes) === 'string') { - format.classes = format.classes.split(/\s+/); - } - }); - - formats[name] = format; - } - } - } - - var getTextDecoration = function(node) { - var decoration; - - ed.dom.getParent(node, function(n) { - decoration = ed.dom.getStyle(n, 'text-decoration'); - return decoration && decoration !== 'none'; - }); - - return decoration; - }; - - var processUnderlineAndColor = function(node) { - var textDecoration; - if (node.nodeType === 1 && node.parentNode && node.parentNode.nodeType === 1) { - textDecoration = getTextDecoration(node.parentNode); - if (ed.dom.getStyle(node, 'color') && textDecoration) { - ed.dom.setStyle(node, 'text-decoration', textDecoration); - } else if (ed.dom.getStyle(node, 'textdecoration') === textDecoration) { - ed.dom.setStyle(node, 'text-decoration', null); - } - } - }; - - function apply(name, vars, node) { - var formatList = get(name), format = formatList[0], bookmark, rng, isCollapsed = selection.isCollapsed(); - - function setElementFormat(elm, fmt) { - fmt = fmt || format; - - if (elm) { - if (fmt.onformat) { - fmt.onformat(elm, fmt, vars, node); - } - - each(fmt.styles, function(value, name) { - dom.setStyle(elm, name, replaceVars(value, vars)); - }); - - each(fmt.attributes, function(value, name) { - dom.setAttrib(elm, name, replaceVars(value, vars)); - }); - - each(fmt.classes, function(value) { - value = replaceVars(value, vars); - - if (!dom.hasClass(elm, value)) { - dom.addClass(elm, value); - } - }); - } - } - function adjustSelectionToVisibleSelection() { - function findSelectionEnd(start, end) { - var walker = new TreeWalker(end); - for (node = walker.current(); node; node = walker.prev()) { - if (node.childNodes.length > 1 || node == start || node.tagName == 'BR') { - return node; - } - } - } - - // Adjust selection so that a end container with a end offset of zero is not included in the selection - // as this isn't visible to the user. - var rng = ed.selection.getRng(); - var start = rng.startContainer; - var end = rng.endContainer; - - if (start != end && rng.endOffset === 0) { - var newEnd = findSelectionEnd(start, end); - var endOffset = newEnd.nodeType == 3 ? newEnd.length : newEnd.childNodes.length; - - rng.setEnd(newEnd, endOffset); - } - - return rng; - } - - function findNestedList(node) { - var listIndex = -1; - var list; - each(node.childNodes, function(n, index) { - if (n.nodeName === "UL" || n.nodeName === "OL") { - listIndex = index; - list = n; - return false; - } - }); - return { - listIndex: listIndex, - list: list - }; - } - - function getBookmarkIndex(node, bookmark) { - var startIndex = -1; - var endIndex = -1; - each(node.childNodes, function(n, index) { - if (n.nodeName === "SPAN" && dom.getAttrib(n, "data-mce-type") == "bookmark") { - if (n.id == bookmark.id + "_start") { - startIndex = index; - } else if (n.id == bookmark.id + "_end") { - endIndex = index; - } - } - }); - - return { - startIndex : startIndex, - endIndex : endIndex - }; - } - - function applyRngStyle(rng, bookmark, node_specific) { - var newWrappers = [], wrapName, wrapElm, contentEditable = true; - - // Setup wrapper element - wrapName = format.inline || format.block; - wrapElm = dom.create(wrapName); - setElementFormat(wrapElm); - - rangeUtils.walk(rng, function(nodes) { - var currentWrapElm; - - function process(node) { - var nodeName, parentName, found, hasContentEditableState, lastContentEditable; - - lastContentEditable = contentEditable; - nodeName = node.nodeName.toLowerCase(); - parentName = node.parentNode.nodeName.toLowerCase(); - - // Node has a contentEditable value - if (node.nodeType === 1 && getContentEditable(node)) { - lastContentEditable = contentEditable; - contentEditable = getContentEditable(node) === "true"; - hasContentEditableState = true; // We don't want to wrap the container only it's children - } - - // Stop wrapping on br elements - if (isEq(nodeName, 'br')) { - currentWrapElm = 0; - - // Remove any br elements when we wrap things - if (format.block) { - dom.remove(node); - } - - return; - } - - // If node is wrapper type - if (format.wrapper && matchNode(node, name, vars)) { - currentWrapElm = 0; - return; - } - - // Can we rename the block - if (contentEditable && !hasContentEditableState && format.block && !format.wrapper && isTextBlock(nodeName)) { - node = dom.rename(node, wrapName); - setElementFormat(node); - newWrappers.push(node); - currentWrapElm = 0; - return; - } - - // Handle selector patterns - if (format.selector) { - // Look for matching formats - each(formatList, function(format) { - // Check collapsed state if it exists - if ('collapsed' in format && format.collapsed !== isCollapsed) { - return; - } - - if (dom.is(node, format.selector) && !isCaretNode(node)) { - setElementFormat(node, format); - found = true; - } - }); - - // Continue processing if a selector match wasn't found and a inline element is defined - if (!format.inline || found) { - currentWrapElm = 0; - return; - } - } - - function isZWNBS(node) { - return node.nodeType === 3 && node.nodeValue.length === 1 && node.nodeValue.charCodeAt(0) === 65279; - } - - // Is it valid to wrap this item - if (contentEditable && !hasContentEditableState && isValidChild(wrapName, nodeName) && isValidChild(parentName, wrapName) && - !(!node_specific && isZWNBS(node)) && !isCaretNode(node) && (!format.inline || !isBlock(node))) { - // Start wrapping - if (!currentWrapElm) { - // Wrap the node - currentWrapElm = dom.clone(wrapElm, FALSE); - node.parentNode.insertBefore(currentWrapElm, node); - newWrappers.push(currentWrapElm); - } - - currentWrapElm.appendChild(node); - - } else { - // Start a new wrapper for possible children - currentWrapElm = 0; - - each(tinymce.grep(node.childNodes), process); - - if (hasContentEditableState) { - contentEditable = lastContentEditable; // Restore last contentEditable state from stack - } - - // End the last wrapper - currentWrapElm = 0; - } - } - - // Process siblings from range - each(nodes, process); - }); - - // Wrap links inside as well, for example color inside a link when the wrapper is around the link - if (format.wrap_links === false) { - each(newWrappers, function(node) { - function process(node) { - var i, currentWrapElm, children; - - if (node.nodeName === 'A') { - currentWrapElm = dom.clone(wrapElm, FALSE); - newWrappers.push(currentWrapElm); - - children = tinymce.grep(node.childNodes); - for (i = 0; i < children.length; i++) { - currentWrapElm.appendChild(children[i]); - } - - node.appendChild(currentWrapElm); - } - - each(tinymce.grep(node.childNodes), process); - } - - process(node); - }); - } - - // Cleanup - - each(newWrappers, function(node) { - var childCount; - - function getChildCount(node) { - var count = 0; - - each(node.childNodes, function(node) { - if (!isWhiteSpaceNode(node) && !isBookmarkNode(node)) { - count++; - } - }); - - return count; - } - - function mergeStyles(node) { - var child, clone; - - each(node.childNodes, function(node) { - if (node.nodeType == 1 && !isBookmarkNode(node) && !isCaretNode(node)) { - child = node; - return FALSE; // break loop - } - }); - - // If child was found and of the same type as the current node - if (child && matchName(child, format)) { - clone = dom.clone(child, FALSE); - setElementFormat(clone); - - dom.replace(clone, node, TRUE); - dom.remove(child, 1); - } - - return clone || node; - } - - childCount = getChildCount(node); - - // Remove empty nodes but only if there is multiple wrappers and they are not block - // elements so never remove single

    since that would remove the currrent empty block element where the caret is at - if ((newWrappers.length > 1 || !isBlock(node)) && childCount === 0) { - dom.remove(node, 1); - return; - } - - if (format.inline || format.wrapper) { - // Merges the current node with it's children of similar type to reduce the number of elements - if (!format.exact && childCount === 1) { - node = mergeStyles(node); - } - - // Remove/merge children - each(formatList, function(format) { - // Merge all children of similar type will move styles from child to parent - // this: text - // will become: text - each(dom.select(format.inline, node), function(child) { - var parent; - - // When wrap_links is set to false we don't want - // to remove the format on children within links - if (format.wrap_links === false) { - parent = child.parentNode; - - do { - if (parent.nodeName === 'A') { - return; - } - parent = parent.parentNode; - } while (parent); - } - - removeFormat(format, vars, child, format.exact ? child : null); - }); - }); - - // Remove child if direct parent is of same type - if (matchNode(node.parentNode, name, vars)) { - dom.remove(node, 1); - node = 0; - return TRUE; - } - - // Look for parent with similar style format - if (format.merge_with_parents) { - dom.getParent(node.parentNode, function(parent) { - if (matchNode(parent, name, vars)) { - dom.remove(node, 1); - node = 0; - return TRUE; - } - }); - } - - // Merge next and previous siblings if they are similar texttext becomes texttext - if (node && format.merge_siblings !== false) { - node = mergeSiblings(getNonWhiteSpaceSibling(node), node); - node = mergeSiblings(node, getNonWhiteSpaceSibling(node, TRUE)); - } - } - }); - } - - if (format) { - if (node) { - if (node.nodeType) { - rng = dom.createRng(); - rng.setStartBefore(node); - rng.setEndAfter(node); - applyRngStyle(expandRng(rng, formatList), null, true); - } else { - applyRngStyle(node, null, true); - } - } else { - if (!isCollapsed || !format.inline || dom.select('td.mceSelected,th.mceSelected').length) { - // Obtain selection node before selection is unselected by applyRngStyle() - var curSelNode = ed.selection.getNode(); - - // If the formats have a default block and we can't find a parent block then start wrapping it with a DIV this is for forced_root_blocks: false - // It's kind of a hack but people should be using the default block type P since all desktop editors work that way - if (!forcedRootBlock && formatList[0].defaultBlock && !dom.getParent(curSelNode, dom.isBlock)) { - apply(formatList[0].defaultBlock); - } - - // Apply formatting to selection - ed.selection.setRng(adjustSelectionToVisibleSelection()); - bookmark = selection.getBookmark(); - applyRngStyle(expandRng(selection.getRng(TRUE), formatList), bookmark); - - // Colored nodes should be underlined so that the color of the underline matches the text color. - if (format.styles && (format.styles.color || format.styles.textDecoration)) { - tinymce.walk(curSelNode, processUnderlineAndColor, 'childNodes'); - processUnderlineAndColor(curSelNode); - } - - selection.moveToBookmark(bookmark); - moveStart(selection.getRng(TRUE)); - ed.nodeChanged(); - } else { - performCaretAction('apply', name, vars); - } - } - } - } - - function remove(name, vars, node) { - var formatList = get(name), format = formatList[0], bookmark, rng, contentEditable = true; - - // Merges the styles for each node - function process(node) { - var children, i, l, lastContentEditable, hasContentEditableState; - - // Skip on text nodes as they have neither format to remove nor children - if (node.nodeType === 3) { - return; - } - - // Node has a contentEditable value - if (node.nodeType === 1 && getContentEditable(node)) { - lastContentEditable = contentEditable; - contentEditable = getContentEditable(node) === "true"; - hasContentEditableState = true; // We don't want to wrap the container only it's children - } - - // Grab the children first since the nodelist might be changed - children = tinymce.grep(node.childNodes); - - // Process current node - if (contentEditable && !hasContentEditableState) { - for (i = 0, l = formatList.length; i < l; i++) { - if (removeFormat(formatList[i], vars, node, node)) { - break; - } - } - } - - // Process the children - if (format.deep) { - if (children.length) { - for (i = 0, l = children.length; i < l; i++) { - process(children[i]); - } - - if (hasContentEditableState) { - contentEditable = lastContentEditable; // Restore last contentEditable state from stack - } - } - } - } - - function findFormatRoot(container) { - var formatRoot; - - // Find format root - each(getParents(container.parentNode).reverse(), function(parent) { - var format; - - // Find format root element - if (!formatRoot && parent.id != '_start' && parent.id != '_end') { - // Is the node matching the format we are looking for - format = matchNode(parent, name, vars); - if (format && format.split !== false) { - formatRoot = parent; - } - } - }); - - return formatRoot; - } - - function wrapAndSplit(format_root, container, target, split) { - var parent, clone, lastClone, firstClone, i, formatRootParent; - - // Format root found then clone formats and split it - if (format_root) { - formatRootParent = format_root.parentNode; - - for (parent = container.parentNode; parent && parent != formatRootParent; parent = parent.parentNode) { - clone = dom.clone(parent, FALSE); - - for (i = 0; i < formatList.length; i++) { - if (removeFormat(formatList[i], vars, clone, clone)) { - clone = 0; - break; - } - } - - // Build wrapper node - if (clone) { - if (lastClone) { - clone.appendChild(lastClone); - } - - if (!firstClone) { - firstClone = clone; - } - - lastClone = clone; - } - } - - // Never split block elements if the format is mixed - if (split && (!format.mixed || !isBlock(format_root))) { - container = dom.split(format_root, container); - } - - // Wrap container in cloned formats - if (lastClone) { - target.parentNode.insertBefore(lastClone, target); - firstClone.appendChild(target); - } - } - - return container; - } - - function splitToFormatRoot(container) { - return wrapAndSplit(findFormatRoot(container), container, container, true); - } - - function unwrap(start) { - var node = dom.get(start ? '_start' : '_end'), - out = node[start ? 'firstChild' : 'lastChild']; - - // If the end is placed within the start the result will be removed - // So this checks if the out node is a bookmark node if it is it - // checks for another more suitable node - if (isBookmarkNode(out)) { - out = out[start ? 'firstChild' : 'lastChild']; - } - - dom.remove(node, true); - - return out; - } - - function removeRngStyle(rng) { - var startContainer, endContainer; - - rng = expandRng(rng, formatList, TRUE); - - if (format.split) { - startContainer = getContainer(rng, TRUE); - endContainer = getContainer(rng); - - if (startContainer != endContainer) { - // WebKit will render the table incorrectly if we wrap a TD in a SPAN so lets see if the can use the first child instead - // This will happen if you tripple click a table cell and use remove formatting - if (/^(TR|TD)$/.test(startContainer.nodeName) && startContainer.firstChild) { - startContainer = (startContainer.nodeName == "TD" ? startContainer.firstChild : startContainer.firstChild.firstChild) || startContainer; - } - - // Wrap start/end nodes in span element since these might be cloned/moved - startContainer = wrap(startContainer, 'span', {id : '_start', 'data-mce-type' : 'bookmark'}); - endContainer = wrap(endContainer, 'span', {id : '_end', 'data-mce-type' : 'bookmark'}); - - // Split start/end - splitToFormatRoot(startContainer); - splitToFormatRoot(endContainer); - - // Unwrap start/end to get real elements again - startContainer = unwrap(TRUE); - endContainer = unwrap(); - } else { - startContainer = endContainer = splitToFormatRoot(startContainer); - } - - // Update range positions since they might have changed after the split operations - rng.startContainer = startContainer.parentNode; - rng.startOffset = nodeIndex(startContainer); - rng.endContainer = endContainer.parentNode; - rng.endOffset = nodeIndex(endContainer) + 1; - } - - // Remove items between start/end - rangeUtils.walk(rng, function(nodes) { - each(nodes, function(node) { - process(node); - - // Remove parent span if it only contains text-decoration: underline, yet a parent node is also underlined. - if (node.nodeType === 1 && ed.dom.getStyle(node, 'text-decoration') === 'underline' && node.parentNode && getTextDecoration(node.parentNode) === 'underline') { - removeFormat({'deep': false, 'exact': true, 'inline': 'span', 'styles': {'textDecoration' : 'underline'}}, null, node); - } - }); - }); - } - - // Handle node - if (node) { - if (node.nodeType) { - rng = dom.createRng(); - rng.setStartBefore(node); - rng.setEndAfter(node); - removeRngStyle(rng); - } else { - removeRngStyle(node); - } - - return; - } - - if (!selection.isCollapsed() || !format.inline || dom.select('td.mceSelected,th.mceSelected').length) { - bookmark = selection.getBookmark(); - removeRngStyle(selection.getRng(TRUE)); - selection.moveToBookmark(bookmark); - - // Check if start element still has formatting then we are at: "text|text" and need to move the start into the next text node - if (format.inline && match(name, vars, selection.getStart())) { - moveStart(selection.getRng(true)); - } - - ed.nodeChanged(); - } else { - performCaretAction('remove', name, vars); - } - } - - function toggle(name, vars, node) { - var fmt = get(name); - - if (match(name, vars, node) && (!('toggle' in fmt[0]) || fmt[0].toggle)) { - remove(name, vars, node); - } else { - apply(name, vars, node); - } - } - - function matchNode(node, name, vars, similar) { - var formatList = get(name), format, i, classes; - - function matchItems(node, format, item_name) { - var key, value, items = format[item_name], i; - - // Custom match - if (format.onmatch) { - return format.onmatch(node, format, item_name); - } - - // Check all items - if (items) { - // Non indexed object - if (items.length === undef) { - for (key in items) { - if (items.hasOwnProperty(key)) { - if (item_name === 'attributes') { - value = dom.getAttrib(node, key); - } else { - value = getStyle(node, key); - } - - if (similar && !value && !format.exact) { - return; - } - - if ((!similar || format.exact) && !isEq(value, replaceVars(items[key], vars))) { - return; - } - } - } - } else { - // Only one match needed for indexed arrays - for (i = 0; i < items.length; i++) { - if (item_name === 'attributes' ? dom.getAttrib(node, items[i]) : getStyle(node, items[i])) { - return format; - } - } - } - } - - return format; - } - - if (formatList && node) { - // Check each format in list - for (i = 0; i < formatList.length; i++) { - format = formatList[i]; - - // Name name, attributes, styles and classes - if (matchName(node, format) && matchItems(node, format, 'attributes') && matchItems(node, format, 'styles')) { - // Match classes - classes = format.classes; - if (classes) { - for (i = 0; i < classes.length; i++) { - if (!dom.hasClass(node, classes[i])) { - return; - } - } - } - - return format; - } - } - } - } - - function match(name, vars, node) { - var startNode; - - function matchParents(node) { - // Find first node with similar format settings - node = dom.getParent(node, function(node) { - return !!matchNode(node, name, vars, true); - }); - - // Do an exact check on the similar format element - return matchNode(node, name, vars); - } - - // Check specified node - if (node) { - return matchParents(node); - } - - // Check selected node - node = selection.getNode(); - if (matchParents(node)) { - return TRUE; - } - - // Check start node if it's different - startNode = selection.getStart(); - if (startNode != node) { - if (matchParents(startNode)) { - return TRUE; - } - } - - return FALSE; - } - - function matchAll(names, vars) { - var startElement, matchedFormatNames = [], checkedMap = {}; - - // Check start of selection for formats - startElement = selection.getStart(); - dom.getParent(startElement, function(node) { - var i, name; - - for (i = 0; i < names.length; i++) { - name = names[i]; - - if (!checkedMap[name] && matchNode(node, name, vars)) { - checkedMap[name] = true; - matchedFormatNames.push(name); - } - } - }, dom.getRoot()); - - return matchedFormatNames; - } - - function canApply(name) { - var formatList = get(name), startNode, parents, i, x, selector; - - if (formatList) { - startNode = selection.getStart(); - parents = getParents(startNode); - - for (x = formatList.length - 1; x >= 0; x--) { - selector = formatList[x].selector; - - // Format is not selector based, then always return TRUE - if (!selector) { - return TRUE; - } - - for (i = parents.length - 1; i >= 0; i--) { - if (dom.is(parents[i], selector)) { - return TRUE; - } - } - } - } - - return FALSE; - } - - function formatChanged(formats, callback, similar) { - var currentFormats; - - // Setup format node change logic - if (!formatChangeData) { - formatChangeData = {}; - currentFormats = {}; - - ed.onNodeChange.addToTop(function(ed, cm, node) { - var parents = getParents(node), matchedFormats = {}; - - // Check for new formats - each(formatChangeData, function(callbacks, format) { - each(parents, function(node) { - if (matchNode(node, format, {}, callbacks.similar)) { - if (!currentFormats[format]) { - // Execute callbacks - each(callbacks, function(callback) { - callback(true, {node: node, format: format, parents: parents}); - }); - - currentFormats[format] = callbacks; - } - - matchedFormats[format] = callbacks; - return false; - } - }); - }); - - // Check if current formats still match - each(currentFormats, function(callbacks, format) { - if (!matchedFormats[format]) { - delete currentFormats[format]; - - each(callbacks, function(callback) { - callback(false, {node: node, format: format, parents: parents}); - }); - } - }); - }); - } - - // Add format listeners - each(formats.split(','), function(format) { - if (!formatChangeData[format]) { - formatChangeData[format] = []; - formatChangeData[format].similar = similar; - } - - formatChangeData[format].push(callback); - }); - - return this; - } - - // Expose to public - tinymce.extend(this, { - get : get, - register : register, - apply : apply, - remove : remove, - toggle : toggle, - match : match, - matchAll : matchAll, - matchNode : matchNode, - canApply : canApply, - formatChanged: formatChanged - }); - - // Initialize - defaultFormats(); - addKeyboardShortcuts(); - - // Private functions - - function matchName(node, format) { - // Check for inline match - if (isEq(node, format.inline)) { - return TRUE; - } - - // Check for block match - if (isEq(node, format.block)) { - return TRUE; - } - - // Check for selector match - if (format.selector) { - return dom.is(node, format.selector); - } - } - - function isEq(str1, str2) { - str1 = str1 || ''; - str2 = str2 || ''; - - str1 = '' + (str1.nodeName || str1); - str2 = '' + (str2.nodeName || str2); - - return str1.toLowerCase() == str2.toLowerCase(); - } - - function getStyle(node, name) { - var styleVal = dom.getStyle(node, name); - - // Force the format to hex - if (name == 'color' || name == 'backgroundColor') { - styleVal = dom.toHex(styleVal); - } - - // Opera will return bold as 700 - if (name == 'fontWeight' && styleVal == 700) { - styleVal = 'bold'; - } - - return '' + styleVal; - } - - function replaceVars(value, vars) { - if (typeof(value) != "string") { - value = value(vars); - } else if (vars) { - value = value.replace(/%(\w+)/g, function(str, name) { - return vars[name] || str; - }); - } - - return value; - } - - function isWhiteSpaceNode(node) { - return node && node.nodeType === 3 && /^([\t \r\n]+|)$/.test(node.nodeValue); - } - - function wrap(node, name, attrs) { - var wrapper = dom.create(name, attrs); - - node.parentNode.insertBefore(wrapper, node); - wrapper.appendChild(node); - - return wrapper; - } - - function expandRng(rng, format, remove) { - var lastIdx, leaf, endPoint, - startContainer = rng.startContainer, - startOffset = rng.startOffset, - endContainer = rng.endContainer, - endOffset = rng.endOffset; - - // This function walks up the tree if there is no siblings before/after the node - function findParentContainer(start) { - var container, parent, sibling, siblingName, root; - - container = parent = start ? startContainer : endContainer; - siblingName = start ? 'previousSibling' : 'nextSibling'; - root = dom.getRoot(); - - function isBogusBr(node) { - return node.nodeName == "BR" && node.getAttribute('data-mce-bogus') && !node.nextSibling; - } - - // If it's a text node and the offset is inside the text - if (container.nodeType == 3 && !isWhiteSpaceNode(container)) { - if (start ? startOffset > 0 : endOffset < container.nodeValue.length) { - return container; - } - } - - for (;;) { - // Stop expanding on block elements - if (!format[0].block_expand && isBlock(parent)) { - return parent; - } - - // Walk left/right - for (sibling = parent[siblingName]; sibling; sibling = sibling[siblingName]) { - if (!isBookmarkNode(sibling) && !isWhiteSpaceNode(sibling) && !isBogusBr(sibling)) { - return parent; - } - } - - // Check if we can move up are we at root level or body level - if (parent.parentNode == root) { - container = parent; - break; - } - - parent = parent.parentNode; - } - - return container; - } - - // This function walks down the tree to find the leaf at the selection. - // The offset is also returned as if node initially a leaf, the offset may be in the middle of the text node. - function findLeaf(node, offset) { - if (offset === undef) { - offset = node.nodeType === 3 ? node.length : node.childNodes.length; - } - while (node && node.hasChildNodes()) { - node = node.childNodes[offset]; - if (node) { - offset = node.nodeType === 3 ? node.length : node.childNodes.length; - } - } - return { node: node, offset: offset }; - } - - // If index based start position then resolve it - if (startContainer.nodeType == 1 && startContainer.hasChildNodes()) { - lastIdx = startContainer.childNodes.length - 1; - startContainer = startContainer.childNodes[startOffset > lastIdx ? lastIdx : startOffset]; - - if (startContainer && startContainer.nodeType == 3) { - startOffset = 0; - } - } - - // If index based end position then resolve it - if (endContainer.nodeType == 1 && endContainer.hasChildNodes()) { - lastIdx = endContainer.childNodes.length - 1; - endContainer = endContainer.childNodes[endOffset > lastIdx ? lastIdx : endOffset - 1]; - - if (endContainer && endContainer.nodeType == 3) { - endOffset = endContainer.nodeValue.length; - } - } - - // Expands the node to the closes contentEditable false element if it exists - function findParentContentEditable(node) { - var parent = node; - - while (parent) { - if (parent.nodeType === 1 && getContentEditable(parent)) { - return getContentEditable(parent) === "false" ? parent : node; - } - - parent = parent.parentNode; - } - - return node; - } - - function findWordEndPoint(container, offset, start) { - var walker, node, pos, lastTextNode; - - function findSpace(node, offset) { - var pos, pos2, str = node.nodeValue; - - if (typeof(offset) == "undefined") { - offset = start ? str.length : 0; - } - - if (start) { - pos = str.lastIndexOf(' ', offset); - pos2 = str.lastIndexOf('\u00a0', offset); - pos = pos > pos2 ? pos : pos2; - - // Include the space on remove to avoid tag soup - if (pos !== -1 && !remove) { - pos++; - } - } else { - pos = str.indexOf(' ', offset); - pos2 = str.indexOf('\u00a0', offset); - pos = pos !== -1 && (pos2 === -1 || pos < pos2) ? pos : pos2; - } - - return pos; - } - - if (container.nodeType === 3) { - pos = findSpace(container, offset); - - if (pos !== -1) { - return {container : container, offset : pos}; - } - - lastTextNode = container; - } - - // Walk the nodes inside the block - walker = new TreeWalker(container, dom.getParent(container, isBlock) || ed.getBody()); - while (node = walker[start ? 'prev' : 'next']()) { - if (node.nodeType === 3) { - lastTextNode = node; - pos = findSpace(node); - - if (pos !== -1) { - return {container : node, offset : pos}; - } - } else if (isBlock(node)) { - break; - } - } - - if (lastTextNode) { - if (start) { - offset = 0; - } else { - offset = lastTextNode.length; - } - - return {container: lastTextNode, offset: offset}; - } - } - - function findSelectorEndPoint(container, sibling_name) { - var parents, i, y, curFormat; - - if (container.nodeType == 3 && container.nodeValue.length === 0 && container[sibling_name]) { - container = container[sibling_name]; - } - - parents = getParents(container); - for (i = 0; i < parents.length; i++) { - for (y = 0; y < format.length; y++) { - curFormat = format[y]; - - // If collapsed state is set then skip formats that doesn't match that - if ("collapsed" in curFormat && curFormat.collapsed !== rng.collapsed) { - continue; - } - - if (dom.is(parents[i], curFormat.selector)) { - return parents[i]; - } - } - } - - return container; - } - - function findBlockEndPoint(container, sibling_name) { - var node; - - // Expand to block of similar type - if (!format[0].wrapper) { - node = dom.getParent(container, format[0].block); - } - - // Expand to first wrappable block element or any block element - if (!node) { - node = dom.getParent(container.nodeType == 3 ? container.parentNode : container, isTextBlock); - } - - // Exclude inner lists from wrapping - if (node && format[0].wrapper) { - node = getParents(node, 'ul,ol').reverse()[0] || node; - } - - // Didn't find a block element look for first/last wrappable element - if (!node) { - node = container; - - while (node[sibling_name] && !isBlock(node[sibling_name])) { - node = node[sibling_name]; - - // Break on BR but include it will be removed later on - // we can't remove it now since we need to check if it can be wrapped - if (isEq(node, 'br')) { - break; - } - } - } - - return node || container; - } - - // Expand to closest contentEditable element - startContainer = findParentContentEditable(startContainer); - endContainer = findParentContentEditable(endContainer); - - // Exclude bookmark nodes if possible - if (isBookmarkNode(startContainer.parentNode) || isBookmarkNode(startContainer)) { - startContainer = isBookmarkNode(startContainer) ? startContainer : startContainer.parentNode; - startContainer = startContainer.nextSibling || startContainer; - - if (startContainer.nodeType == 3) { - startOffset = 0; - } - } - - if (isBookmarkNode(endContainer.parentNode) || isBookmarkNode(endContainer)) { - endContainer = isBookmarkNode(endContainer) ? endContainer : endContainer.parentNode; - endContainer = endContainer.previousSibling || endContainer; - - if (endContainer.nodeType == 3) { - endOffset = endContainer.length; - } - } - - if (format[0].inline) { - if (rng.collapsed) { - // Expand left to closest word boundery - endPoint = findWordEndPoint(startContainer, startOffset, true); - if (endPoint) { - startContainer = endPoint.container; - startOffset = endPoint.offset; - } - - // Expand right to closest word boundery - endPoint = findWordEndPoint(endContainer, endOffset); - if (endPoint) { - endContainer = endPoint.container; - endOffset = endPoint.offset; - } - } - - // Avoid applying formatting to a trailing space. - leaf = findLeaf(endContainer, endOffset); - if (leaf.node) { - while (leaf.node && leaf.offset === 0 && leaf.node.previousSibling) { - leaf = findLeaf(leaf.node.previousSibling); - } - - if (leaf.node && leaf.offset > 0 && leaf.node.nodeType === 3 && - leaf.node.nodeValue.charAt(leaf.offset - 1) === ' ') { - - if (leaf.offset > 1) { - endContainer = leaf.node; - endContainer.splitText(leaf.offset - 1); - } - } - } - } - - // Move start/end point up the tree if the leaves are sharp and if we are in different containers - // Example * becomes !: !

    *texttext*

    ! - // This will reduce the number of wrapper elements that needs to be created - // Move start point up the tree - if (format[0].inline || format[0].block_expand) { - if (!format[0].inline || (startContainer.nodeType != 3 || startOffset === 0)) { - startContainer = findParentContainer(true); - } - - if (!format[0].inline || (endContainer.nodeType != 3 || endOffset === endContainer.nodeValue.length)) { - endContainer = findParentContainer(); - } - } - - // Expand start/end container to matching selector - if (format[0].selector && format[0].expand !== FALSE && !format[0].inline) { - // Find new startContainer/endContainer if there is better one - startContainer = findSelectorEndPoint(startContainer, 'previousSibling'); - endContainer = findSelectorEndPoint(endContainer, 'nextSibling'); - } - - // Expand start/end container to matching block element or text node - if (format[0].block || format[0].selector) { - // Find new startContainer/endContainer if there is better one - startContainer = findBlockEndPoint(startContainer, 'previousSibling'); - endContainer = findBlockEndPoint(endContainer, 'nextSibling'); - - // Non block element then try to expand up the leaf - if (format[0].block) { - if (!isBlock(startContainer)) { - startContainer = findParentContainer(true); - } - - if (!isBlock(endContainer)) { - endContainer = findParentContainer(); - } - } - } - - // Setup index for startContainer - if (startContainer.nodeType == 1) { - startOffset = nodeIndex(startContainer); - startContainer = startContainer.parentNode; - } - - // Setup index for endContainer - if (endContainer.nodeType == 1) { - endOffset = nodeIndex(endContainer) + 1; - endContainer = endContainer.parentNode; - } - - // Return new range like object - return { - startContainer : startContainer, - startOffset : startOffset, - endContainer : endContainer, - endOffset : endOffset - }; - } - - function removeFormat(format, vars, node, compare_node) { - var i, attrs, stylesModified; - - // Check if node matches format - if (!matchName(node, format)) { - return FALSE; - } - - // Should we compare with format attribs and styles - if (format.remove != 'all') { - // Remove styles - each(format.styles, function(value, name) { - value = replaceVars(value, vars); - - // Indexed array - if (typeof(name) === 'number') { - name = value; - compare_node = 0; - } - - if (!compare_node || isEq(getStyle(compare_node, name), value)) { - dom.setStyle(node, name, ''); - } - - stylesModified = 1; - }); - - // Remove style attribute if it's empty - if (stylesModified && dom.getAttrib(node, 'style') === '') { - node.removeAttribute('style'); - node.removeAttribute('data-mce-style'); - } - - // Remove attributes - each(format.attributes, function(value, name) { - var valueOut; - - value = replaceVars(value, vars); - - // Indexed array - if (typeof(name) === 'number') { - name = value; - compare_node = 0; - } - - if (!compare_node || isEq(dom.getAttrib(compare_node, name), value)) { - // Keep internal classes - if (name == 'class') { - value = dom.getAttrib(node, name); - if (value) { - // Build new class value where everything is removed except the internal prefixed classes - valueOut = ''; - each(value.split(/\s+/), function(cls) { - if (/mce\w+/.test(cls)) { - valueOut += (valueOut ? ' ' : '') + cls; - } - }); - - // We got some internal classes left - if (valueOut) { - dom.setAttrib(node, name, valueOut); - return; - } - } - } - - // IE6 has a bug where the attribute doesn't get removed correctly - if (name == "class") { - node.removeAttribute('className'); - } - - // Remove mce prefixed attributes - if (MCE_ATTR_RE.test(name)) { - node.removeAttribute('data-mce-' + name); - } - - node.removeAttribute(name); - } - }); - - // Remove classes - each(format.classes, function(value) { - value = replaceVars(value, vars); - - if (!compare_node || dom.hasClass(compare_node, value)) { - dom.removeClass(node, value); - } - }); - - // Check for non internal attributes - attrs = dom.getAttribs(node); - for (i = 0; i < attrs.length; i++) { - if (attrs[i].nodeName.indexOf('_') !== 0) { - return FALSE; - } - } - } - - // Remove the inline child if it's empty for example or - if (format.remove != 'none') { - removeNode(node, format); - return TRUE; - } - } - - function removeNode(node, format) { - var parentNode = node.parentNode, rootBlockElm; - - function find(node, next, inc) { - node = getNonWhiteSpaceSibling(node, next, inc); - - return !node || (node.nodeName == 'BR' || isBlock(node)); - } - - if (format.block) { - if (!forcedRootBlock) { - // Append BR elements if needed before we remove the block - if (isBlock(node) && !isBlock(parentNode)) { - if (!find(node, FALSE) && !find(node.firstChild, TRUE, 1)) { - node.insertBefore(dom.create('br'), node.firstChild); - } - - if (!find(node, TRUE) && !find(node.lastChild, FALSE, 1)) { - node.appendChild(dom.create('br')); - } - } - } else { - // Wrap the block in a forcedRootBlock if we are at the root of document - if (parentNode == dom.getRoot()) { - if (!format.list_block || !isEq(node, format.list_block)) { - each(tinymce.grep(node.childNodes), function(node) { - if (isValidChild(forcedRootBlock, node.nodeName.toLowerCase())) { - if (!rootBlockElm) { - rootBlockElm = wrap(node, forcedRootBlock); - } else { - rootBlockElm.appendChild(node); - } - } else { - rootBlockElm = 0; - } - }); - } - } - } - } - - // Never remove nodes that isn't the specified inline element if a selector is specified too - if (format.selector && format.inline && !isEq(format.inline, node)) { - return; - } - - dom.remove(node, 1); - } - - function getNonWhiteSpaceSibling(node, next, inc) { - if (node) { - next = next ? 'nextSibling' : 'previousSibling'; - - for (node = inc ? node : node[next]; node; node = node[next]) { - if (node.nodeType == 1 || !isWhiteSpaceNode(node)) { - return node; - } - } - } - } - - function isBookmarkNode(node) { - return node && node.nodeType == 1 && node.getAttribute('data-mce-type') == 'bookmark'; - } - - function mergeSiblings(prev, next) { - var sibling, tmpSibling; - - function compareElements(node1, node2) { - // Not the same name - if (node1.nodeName != node2.nodeName) { - return FALSE; - } - - function getAttribs(node) { - var attribs = {}; - - each(dom.getAttribs(node), function(attr) { - var name = attr.nodeName.toLowerCase(); - - // Don't compare internal attributes or style - if (name.indexOf('_') !== 0 && name !== 'style') { - attribs[name] = dom.getAttrib(node, name); - } - }); - - return attribs; - } - - function compareObjects(obj1, obj2) { - var value, name; - - for (name in obj1) { - // Obj1 has item obj2 doesn't have - if (obj1.hasOwnProperty(name)) { - value = obj2[name]; - - // Obj2 doesn't have obj1 item - if (value === undef) { - return FALSE; - } - - // Obj2 item has a different value - if (obj1[name] != value) { - return FALSE; - } - - // Delete similar value - delete obj2[name]; - } - } - - // Check if obj 2 has something obj 1 doesn't have - for (name in obj2) { - // Obj2 has item obj1 doesn't have - if (obj2.hasOwnProperty(name)) { - return FALSE; - } - } - - return TRUE; - } - - // Attribs are not the same - if (!compareObjects(getAttribs(node1), getAttribs(node2))) { - return FALSE; - } - - // Styles are not the same - if (!compareObjects(dom.parseStyle(dom.getAttrib(node1, 'style')), dom.parseStyle(dom.getAttrib(node2, 'style')))) { - return FALSE; - } - - return TRUE; - } - - function findElementSibling(node, sibling_name) { - for (sibling = node; sibling; sibling = sibling[sibling_name]) { - if (sibling.nodeType == 3 && sibling.nodeValue.length !== 0) { - return node; - } - - if (sibling.nodeType == 1 && !isBookmarkNode(sibling)) { - return sibling; - } - } - - return node; - } - - // Check if next/prev exists and that they are elements - if (prev && next) { - // If previous sibling is empty then jump over it - prev = findElementSibling(prev, 'previousSibling'); - next = findElementSibling(next, 'nextSibling'); - - // Compare next and previous nodes - if (compareElements(prev, next)) { - // Append nodes between - for (sibling = prev.nextSibling; sibling && sibling != next;) { - tmpSibling = sibling; - sibling = sibling.nextSibling; - prev.appendChild(tmpSibling); - } - - // Remove next node - dom.remove(next); - - // Move children into prev node - each(tinymce.grep(next.childNodes), function(node) { - prev.appendChild(node); - }); - - return prev; - } - } - - return next; - } - - function getContainer(rng, start) { - var container, offset, lastIdx; - - container = rng[start ? 'startContainer' : 'endContainer']; - offset = rng[start ? 'startOffset' : 'endOffset']; - - if (container.nodeType == 1) { - lastIdx = container.childNodes.length - 1; - - if (!start && offset) { - offset--; - } - - container = container.childNodes[offset > lastIdx ? lastIdx : offset]; - } - - // If start text node is excluded then walk to the next node - if (container.nodeType === 3 && start && offset >= container.nodeValue.length) { - container = new TreeWalker(container, ed.getBody()).next() || container; - } - - // If end text node is excluded then walk to the previous node - if (container.nodeType === 3 && !start && offset === 0) { - container = new TreeWalker(container, ed.getBody()).prev() || container; - } - - return container; - } - - function performCaretAction(type, name, vars) { - var caretContainerId = '_mce_caret', debug = ed.settings.caret_debug; - - // Creates a caret container bogus element - function createCaretContainer(fill) { - var caretContainer = dom.create('span', {id: caretContainerId, 'data-mce-bogus': true, style: debug ? 'color:red' : ''}); - - if (fill) { - caretContainer.appendChild(ed.getDoc().createTextNode(INVISIBLE_CHAR)); - } - - return caretContainer; - } - - function isCaretContainerEmpty(node, nodes) { - while (node) { - if ((node.nodeType === 3 && node.nodeValue !== INVISIBLE_CHAR) || node.childNodes.length > 1) { - return false; - } - - // Collect nodes - if (nodes && node.nodeType === 1) { - nodes.push(node); - } - - node = node.firstChild; - } - - return true; - } - - // Returns any parent caret container element - function getParentCaretContainer(node) { - while (node) { - if (node.id === caretContainerId) { - return node; - } - - node = node.parentNode; - } - } - - // Finds the first text node in the specified node - function findFirstTextNode(node) { - var walker; - - if (node) { - walker = new TreeWalker(node, node); - - for (node = walker.current(); node; node = walker.next()) { - if (node.nodeType === 3) { - return node; - } - } - } - } - - // Removes the caret container for the specified node or all on the current document - function removeCaretContainer(node, move_caret) { - var child, rng; - - if (!node) { - node = getParentCaretContainer(selection.getStart()); - - if (!node) { - while (node = dom.get(caretContainerId)) { - removeCaretContainer(node, false); - } - } - } else { - rng = selection.getRng(true); - - if (isCaretContainerEmpty(node)) { - if (move_caret !== false) { - rng.setStartBefore(node); - rng.setEndBefore(node); - } - - dom.remove(node); - } else { - child = findFirstTextNode(node); - - if (child.nodeValue.charAt(0) === INVISIBLE_CHAR) { - child = child.deleteData(0, 1); - } - - dom.remove(node, 1); - } - - selection.setRng(rng); - } - } - - function rangeParentBody(rngContainer) { - var name = rngContainer.nodeName.toLowerCase(); - switch (name) { - case 'html', '#document': - return false; - case 'body': - return true; - default: - return rangeParentBody(rngContainer.parentNode); - } - } - - function rangeInBody(rng) { - return rangeParentBody(rng.startContainer) || rangeParentBody(rng.endContainer); - } - - // Applies formatting to the caret postion - function applyCaretFormat() { - var rng, caretContainer, textNode, offset, bookmark, container, text; - - rng = selection.getRng(true); - offset = rng.startOffset; - container = rng.startContainer; - text = container.nodeValue; - - caretContainer = getParentCaretContainer(selection.getStart()); - if (caretContainer) { - textNode = findFirstTextNode(caretContainer); - } - - // Expand to word is caret is in the middle of a text node and the char before/after is a alpha numeric character - if (text && offset > 0 && offset < text.length && /\w/.test(text.charAt(offset)) && /\w/.test(text.charAt(offset - 1))) { - // Get bookmark of caret position - bookmark = selection.getBookmark(); - - // Collapse bookmark range (WebKit) - rng.collapse(true); - - // Expand the range to the closest word and split it at those points - rng = expandRng(rng, get(name)); - rng = rangeUtils.split(rng); - - // Apply the format to the range - apply(name, vars, rng); - - // Move selection back to caret position - selection.moveToBookmark(bookmark); - } else { - if (!caretContainer || textNode.nodeValue !== INVISIBLE_CHAR) { - caretContainer = createCaretContainer(true); - textNode = caretContainer.firstChild; - - if (rangeInBody(rng)) { - rng.insertNode(caretContainer); - } else { - rng.startContainer.ownerDocument.body.appendChild(caretContainer); - } - - offset = 1; - - apply(name, vars, caretContainer); - } else { - apply(name, vars, caretContainer); - } - - // Move selection to text node - selection.setCursorLocation(textNode, offset); - } - } - - function removeCaretFormat() { - var rng = selection.getRng(true), container, offset, bookmark, - hasContentAfter, node, formatNode, parents = [], i, caretContainer; - - container = rng.startContainer; - offset = rng.startOffset; - node = container; - - if (container.nodeType == 3) { - if (offset != container.nodeValue.length || container.nodeValue === INVISIBLE_CHAR) { - hasContentAfter = true; - } - - node = node.parentNode; - } - - while (node) { - if (matchNode(node, name, vars)) { - formatNode = node; - break; - } - - if (node.nextSibling) { - hasContentAfter = true; - } - - parents.push(node); - node = node.parentNode; - } - - // Node doesn't have the specified format - if (!formatNode) { - return; - } - - // Is there contents after the caret then remove the format on the element - if (hasContentAfter) { - // Get bookmark of caret position - bookmark = selection.getBookmark(); - - // Collapse bookmark range (WebKit) - rng.collapse(true); - - // Expand the range to the closest word and split it at those points - rng = expandRng(rng, get(name), true); - rng = rangeUtils.split(rng); - - // Remove the format from the range - remove(name, vars, rng); - - // Move selection back to caret position - selection.moveToBookmark(bookmark); - } else { - caretContainer = createCaretContainer(); - - node = caretContainer; - for (i = parents.length - 1; i >= 0; i--) { - node.appendChild(dom.clone(parents[i], false)); - node = node.firstChild; - } - - // Insert invisible character into inner most format element - node.appendChild(dom.doc.createTextNode(INVISIBLE_CHAR)); - node = node.firstChild; - - var block = dom.getParent(formatNode, isTextBlock); - - if (block && dom.isEmpty(block)) { - // Replace formatNode with caretContainer when removing format from empty block like

    |

    - formatNode.parentNode.replaceChild(caretContainer, formatNode); - } else { - // Insert caret container after the formated node - dom.insertAfter(caretContainer, formatNode); - } - - // Move selection to text node - selection.setCursorLocation(node, 1); - - // If the formatNode is empty, we can remove it safely. - if (dom.isEmpty(formatNode)) { - dom.remove(formatNode); - } - } - } - - // Checks if the parent caret container node isn't empty if that is the case it - // will remove the bogus state on all children that isn't empty - function unmarkBogusCaretParents() { - var caretContainer; - - caretContainer = getParentCaretContainer(selection.getStart()); - if (caretContainer && !dom.isEmpty(caretContainer)) { - tinymce.walk(caretContainer, function(node) { - if (node.nodeType == 1 && node.id !== caretContainerId && !dom.isEmpty(node)) { - dom.setAttrib(node, 'data-mce-bogus', null); - } - }, 'childNodes'); - } - } - - // Only bind the caret events once - if (!ed._hasCaretEvents) { - // Mark current caret container elements as bogus when getting the contents so we don't end up with empty elements - ed.onBeforeGetContent.addToTop(function() { - var nodes = [], i; - if (isCaretContainerEmpty(getParentCaretContainer(selection.getStart()), nodes)) { - // Mark children - i = nodes.length; - while (i--) { - dom.setAttrib(nodes[i], 'data-mce-bogus', '1'); - } - } - }); - - // Remove caret container on mouse up and on key up - tinymce.each('onMouseUp onKeyUp'.split(' '), function(name) { - ed[name].addToTop(function() { - removeCaretContainer(); - unmarkBogusCaretParents(); - }); - }); - - // Remove caret container on keydown and it's a backspace, enter or left/right arrow keys - ed.onKeyDown.addToTop(function(ed, e) { - var keyCode = e.keyCode; - - if (keyCode == 8 || keyCode == 37 || keyCode == 39) { - removeCaretContainer(getParentCaretContainer(selection.getStart())); - } - - unmarkBogusCaretParents(); - }); - - // Remove bogus state if they got filled by contents using editor.selection.setContent - selection.onSetContent.add(unmarkBogusCaretParents); - - ed._hasCaretEvents = true; - } - - // Do apply or remove caret format - if (type == "apply") { - applyCaretFormat(); - } else { - removeCaretFormat(); - } - } - - function moveStart(rng) { - var container = rng.startContainer, - offset = rng.startOffset, isAtEndOfText, - walker, node, nodes, tmpNode; - - // Convert text node into index if possible - if (container.nodeType == 3 && offset >= container.nodeValue.length) { - // Get the parent container location and walk from there - offset = nodeIndex(container); - container = container.parentNode; - isAtEndOfText = true; - } - - // Move startContainer/startOffset in to a suitable node - if (container.nodeType == 1) { - nodes = container.childNodes; - container = nodes[Math.min(offset, nodes.length - 1)]; - walker = new TreeWalker(container, dom.getParent(container, dom.isBlock)); - - // If offset is at end of the parent node walk to the next one - if (offset > nodes.length - 1 || isAtEndOfText) { - walker.next(); - } - - for (node = walker.current(); node; node = walker.next()) { - if (node.nodeType == 3 && !isWhiteSpaceNode(node)) { - // IE has a "neat" feature where it moves the start node into the closest element - // we can avoid this by inserting an element before it and then remove it after we set the selection - tmpNode = dom.create('a', null, INVISIBLE_CHAR); - node.parentNode.insertBefore(tmpNode, node); - - // Set selection and remove tmpNode - rng.setStart(node, 0); - selection.setRng(rng); - dom.remove(tmpNode); - - return; - } - } - } - } - }; -})(tinymce); -tinymce.onAddEditor.add(function(tinymce, ed) { - var filters, fontSizes, dom, settings = ed.settings; - - function replaceWithSpan(node, styles) { - tinymce.each(styles, function(value, name) { - if (value) - dom.setStyle(node, name, value); - }); - - dom.rename(node, 'span'); - }; - - function convert(editor, params) { - dom = editor.dom; - - if (settings.convert_fonts_to_spans) { - tinymce.each(dom.select('font,u,strike', params.node), function(node) { - filters[node.nodeName.toLowerCase()](ed.dom, node); - }); - } - }; - - if (settings.inline_styles) { - fontSizes = tinymce.explode(settings.font_size_legacy_values); - - filters = { - font : function(dom, node) { - replaceWithSpan(node, { - backgroundColor : node.style.backgroundColor, - color : node.color, - fontFamily : node.face, - fontSize : fontSizes[parseInt(node.size, 10) - 1] - }); - }, - - u : function(dom, node) { - replaceWithSpan(node, { - textDecoration : 'underline' - }); - }, - - strike : function(dom, node) { - replaceWithSpan(node, { - textDecoration : 'line-through' - }); - } - }; - - ed.onPreProcess.add(convert); - ed.onSetContent.add(convert); - - ed.onInit.add(function() { - ed.selection.onSetContent.add(convert); - }); - } -}); -(function(tinymce) { - var TreeWalker = tinymce.dom.TreeWalker; - - tinymce.EnterKey = function(editor) { - var dom = editor.dom, selection = editor.selection, settings = editor.settings, undoManager = editor.undoManager, nonEmptyElementsMap = editor.schema.getNonEmptyElements(); - - function handleEnterKey(evt) { - var rng = selection.getRng(true), tmpRng, editableRoot, container, offset, parentBlock, documentMode, shiftKey, - newBlock, fragment, containerBlock, parentBlockName, containerBlockName, newBlockName, isAfterLastNodeInContainer; - - // Returns true if the block can be split into two blocks or not - function canSplitBlock(node) { - return node && - dom.isBlock(node) && - !/^(TD|TH|CAPTION|FORM)$/.test(node.nodeName) && - !/^(fixed|absolute)/i.test(node.style.position) && - dom.getContentEditable(node) !== "true"; - }; - - // Renders empty block on IE - function renderBlockOnIE(block) { - var oldRng; - - if (tinymce.isIE && !tinymce.isIE11 && dom.isBlock(block)) { - oldRng = selection.getRng(); - block.appendChild(dom.create('span', null, '\u00a0')); - selection.select(block); - block.lastChild.outerHTML = ''; - selection.setRng(oldRng); - } - }; - - // Remove the first empty inline element of the block so this:

    x

    becomes this:

    x

    - function trimInlineElementsOnLeftSideOfBlock(block) { - var node = block, firstChilds = [], i; - - // Find inner most first child ex:

    *

    - while (node = node.firstChild) { - if (dom.isBlock(node)) { - return; - } - - if (node.nodeType == 1 && !nonEmptyElementsMap[node.nodeName.toLowerCase()]) { - firstChilds.push(node); - } - } - - i = firstChilds.length; - while (i--) { - node = firstChilds[i]; - if (!node.hasChildNodes() || (node.firstChild == node.lastChild && node.firstChild.nodeValue === '')) { - dom.remove(node); - } else { - // Remove see #5381 - if (node.nodeName == "A" && (node.innerText || node.textContent) === ' ') { - dom.remove(node); - } - } - } - }; - - // Moves the caret to a suitable position within the root for example in the first non pure whitespace text node or before an image - function moveToCaretPosition(root) { - var walker, node, rng, y, viewPort, lastNode = root, tempElm; - - rng = dom.createRng(); - - if (root.hasChildNodes()) { - walker = new TreeWalker(root, root); - - while (node = walker.current()) { - if (node.nodeType == 3) { - rng.setStart(node, 0); - rng.setEnd(node, 0); - break; - } - - if (nonEmptyElementsMap[node.nodeName.toLowerCase()]) { - rng.setStartBefore(node); - rng.setEndBefore(node); - break; - } - - lastNode = node; - node = walker.next(); - } - - if (!node) { - rng.setStart(lastNode, 0); - rng.setEnd(lastNode, 0); - } - } else { - if (root.nodeName == 'BR') { - if (root.nextSibling && dom.isBlock(root.nextSibling)) { - // Trick on older IE versions to render the caret before the BR between two lists - if (!documentMode || documentMode < 9) { - tempElm = dom.create('br'); - root.parentNode.insertBefore(tempElm, root); - } - - rng.setStartBefore(root); - rng.setEndBefore(root); - } else { - rng.setStartAfter(root); - rng.setEndAfter(root); - } - } else { - rng.setStart(root, 0); - rng.setEnd(root, 0); - } - } - - selection.setRng(rng); - - // Remove tempElm created for old IE:s - dom.remove(tempElm); - - viewPort = dom.getViewPort(editor.getWin()); - - // scrollIntoView seems to scroll the parent window in most browsers now including FF 3.0b4 so it's time to stop using it and do it our selfs - y = dom.getPos(root).y; - if (y < viewPort.y || y + 25 > viewPort.y + viewPort.h) { - editor.getWin().scrollTo(0, y < viewPort.y ? y : y - viewPort.h + 25); // Needs to be hardcoded to roughly one line of text if a huge text block is broken into two blocks - } - }; - - // Creates a new block element by cloning the current one or creating a new one if the name is specified - // This function will also copy any text formatting from the parent block and add it to the new one - function createNewBlock(name) { - var node = container, block, clonedNode, caretNode; - - block = name || parentBlockName == "TABLE" ? dom.create(name || newBlockName) : parentBlock.cloneNode(false); - caretNode = block; - - // Clone any parent styles - if (settings.keep_styles !== false) { - do { - if (/^(SPAN|STRONG|B|EM|I|FONT|STRIKE|U)$/.test(node.nodeName)) { - // Never clone a caret containers - if (node.id == '_mce_caret') { - continue; - } - - clonedNode = node.cloneNode(false); - dom.setAttrib(clonedNode, 'id', ''); // Remove ID since it needs to be document unique - - if (block.hasChildNodes()) { - clonedNode.appendChild(block.firstChild); - block.appendChild(clonedNode); - } else { - caretNode = clonedNode; - block.appendChild(clonedNode); - } - } - } while (node = node.parentNode); - } - - // BR is needed in empty blocks on non IE browsers - if (!tinymce.isIE || tinymce.isIE11) { - caretNode.innerHTML = '
    '; - } - - return block; - }; - - // Returns true/false if the caret is at the start/end of the parent block element - function isCaretAtStartOrEndOfBlock(start) { - var walker, node, name; - - // Caret is in the middle of a text node like "a|b" - if (container.nodeType == 3 && (start ? offset > 0 : offset < container.nodeValue.length)) { - return false; - } - - // If after the last element in block node edge case for #5091 - if (container.parentNode == parentBlock && isAfterLastNodeInContainer && !start) { - return true; - } - - // If the caret if before the first element in parentBlock - if (start && container.nodeType == 1 && container == parentBlock.firstChild) { - return true; - } - - // Caret can be before/after a table - if (container.nodeName === "TABLE" || (container.previousSibling && container.previousSibling.nodeName == "TABLE")) { - return (isAfterLastNodeInContainer && !start) || (!isAfterLastNodeInContainer && start); - } - - // Walk the DOM and look for text nodes or non empty elements - walker = new TreeWalker(container, parentBlock); - - // If caret is in beginning or end of a text block then jump to the next/previous node - if (container.nodeType == 3) { - if (start && offset == 0) { - walker.prev(); - } else if (!start && offset == container.nodeValue.length) { - walker.next(); - } - } - - while (node = walker.current()) { - if (node.nodeType === 1) { - // Ignore bogus elements - if (!node.getAttribute('data-mce-bogus')) { - // Keep empty elements like but not trailing br:s like

    text|

    - name = node.nodeName.toLowerCase(); - if (nonEmptyElementsMap[name] && name !== 'br') { - return false; - } - } - } else if (node.nodeType === 3 && !/^[ \t\r\n]*$/.test(node.nodeValue)) { - return false; - } - - if (start) { - walker.prev(); - } else { - walker.next(); - } - } - - return true; - }; - - // Wraps any text nodes or inline elements in the specified forced root block name - function wrapSelfAndSiblingsInDefaultBlock(container, offset) { - var newBlock, parentBlock, startNode, node, next, blockName = newBlockName || 'P'; - - // Not in a block element or in a table cell or caption - parentBlock = dom.getParent(container, dom.isBlock); - if (!parentBlock || !canSplitBlock(parentBlock)) { - parentBlock = parentBlock || editableRoot; - - if (!parentBlock.hasChildNodes()) { - newBlock = dom.create(blockName); - parentBlock.appendChild(newBlock); - rng.setStart(newBlock, 0); - rng.setEnd(newBlock, 0); - return newBlock; - } - - // Find parent that is the first child of parentBlock - node = container; - while (node.parentNode != parentBlock) { - node = node.parentNode; - } - - // Loop left to find start node start wrapping at - while (node && !dom.isBlock(node)) { - startNode = node; - node = node.previousSibling; - } - - if (startNode) { - newBlock = dom.create(blockName); - startNode.parentNode.insertBefore(newBlock, startNode); - - // Start wrapping until we hit a block - node = startNode; - while (node && !dom.isBlock(node)) { - next = node.nextSibling; - newBlock.appendChild(node); - node = next; - } - - // Restore range to it's past location - rng.setStart(container, offset); - rng.setEnd(container, offset); - } - } - - return container; - }; - - // Inserts a block or br before/after or in the middle of a split list of the LI is empty - function handleEmptyListItem() { - function isFirstOrLastLi(first) { - var node = containerBlock[first ? 'firstChild' : 'lastChild']; - - // Find first/last element since there might be whitespace there - while (node) { - if (node.nodeType == 1) { - break; - } - - node = node[first ? 'nextSibling' : 'previousSibling']; - } - - return node === parentBlock; - }; - - newBlock = newBlockName ? createNewBlock(newBlockName) : dom.create('BR'); - - if (isFirstOrLastLi(true) && isFirstOrLastLi()) { - // Is first and last list item then replace the OL/UL with a text block - dom.replace(newBlock, containerBlock); - } else if (isFirstOrLastLi(true)) { - // First LI in list then remove LI and add text block before list - containerBlock.parentNode.insertBefore(newBlock, containerBlock); - } else if (isFirstOrLastLi()) { - // Last LI in list then temove LI and add text block after list - dom.insertAfter(newBlock, containerBlock); - renderBlockOnIE(newBlock); - } else { - // Middle LI in list the split the list and insert a text block in the middle - // Extract after fragment and insert it after the current block - tmpRng = rng.cloneRange(); - tmpRng.setStartAfter(parentBlock); - tmpRng.setEndAfter(containerBlock); - fragment = tmpRng.extractContents(); - dom.insertAfter(fragment, containerBlock); - dom.insertAfter(newBlock, containerBlock); - } - - dom.remove(parentBlock); - moveToCaretPosition(newBlock); - undoManager.add(); - }; - - // Walks the parent block to the right and look for any contents - function hasRightSideContent() { - var walker = new TreeWalker(container, parentBlock), node; - - while (node = walker.next()) { - if (nonEmptyElementsMap[node.nodeName.toLowerCase()] || node.length > 0) { - return true; - } - } - } - - // Inserts a BR element if the forced_root_block option is set to false or empty string - function insertBr() { - var brElm, extraBr, marker; - - if (container && container.nodeType == 3 && offset >= container.nodeValue.length) { - // Insert extra BR element at the end block elements - if ((!tinymce.isIE || tinymce.isIE11) && !hasRightSideContent()) { - brElm = dom.create('br'); - rng.insertNode(brElm); - rng.setStartAfter(brElm); - rng.setEndAfter(brElm); - extraBr = true; - } - } - - brElm = dom.create('br'); - rng.insertNode(brElm); - - // Rendering modes below IE8 doesn't display BR elements in PRE unless we have a \n before it - if ((tinymce.isIE && !tinymce.isIE11) && parentBlockName == 'PRE' && (!documentMode || documentMode < 8)) { - brElm.parentNode.insertBefore(dom.doc.createTextNode('\r'), brElm); - } - - // Insert temp marker and scroll to that - marker = dom.create('span', {}, ' '); - brElm.parentNode.insertBefore(marker, brElm); - selection.scrollIntoView(marker); - dom.remove(marker); - - if (!extraBr) { - rng.setStartAfter(brElm); - rng.setEndAfter(brElm); - } else { - rng.setStartBefore(brElm); - rng.setEndBefore(brElm); - } - - selection.setRng(rng); - undoManager.add(); - }; - - // Trims any linebreaks at the beginning of node user for example when pressing enter in a PRE element - function trimLeadingLineBreaks(node) { - do { - if (node.nodeType === 3) { - node.nodeValue = node.nodeValue.replace(/^[\r\n]+/, ''); - } - - node = node.firstChild; - } while (node); - }; - - function getEditableRoot(node) { - var root = dom.getRoot(), parent, editableRoot; - - // Get all parents until we hit a non editable parent or the root - parent = node; - while (parent !== root && dom.getContentEditable(parent) !== "false") { - if (dom.getContentEditable(parent) === "true") { - editableRoot = parent; - } - - parent = parent.parentNode; - } - - return parent !== root ? editableRoot : root; - }; - - // Adds a BR at the end of blocks that only contains an IMG or INPUT since these might be floated and then they won't expand the block - function addBrToBlockIfNeeded(block) { - var lastChild; - - // IE will render the blocks correctly other browsers needs a BR - if (!tinymce.isIE || tinymce.isIE11) { - block.normalize(); // Remove empty text nodes that got left behind by the extract - - // Check if the block is empty or contains a floated last child - lastChild = block.lastChild; - if (!lastChild || (/^(left|right)$/gi.test(dom.getStyle(lastChild, 'float', true)))) { - dom.add(block, 'br'); - } - } - }; - - // Delete any selected contents - if (!rng.collapsed) { - editor.execCommand('Delete'); - return; - } - - // Event is blocked by some other handler for example the lists plugin - if (evt.isDefaultPrevented()) { - return; - } - - // Setup range items and newBlockName - container = rng.startContainer; - offset = rng.startOffset; - newBlockName = (settings.force_p_newlines ? 'p' : '') || settings.forced_root_block; - newBlockName = newBlockName ? newBlockName.toUpperCase() : ''; - documentMode = dom.doc.documentMode; - shiftKey = evt.shiftKey; - - // Resolve node index - if (container.nodeType == 1 && container.hasChildNodes()) { - isAfterLastNodeInContainer = offset > container.childNodes.length - 1; - container = container.childNodes[Math.min(offset, container.childNodes.length - 1)] || container; - if (isAfterLastNodeInContainer && container.nodeType == 3) { - offset = container.nodeValue.length; - } else { - offset = 0; - } - } - - // Get editable root node normaly the body element but sometimes a div or span - editableRoot = getEditableRoot(container); - - // If there is no editable root then enter is done inside a contentEditable false element - if (!editableRoot) { - return; - } - - undoManager.beforeChange(); - - // If editable root isn't block nor the root of the editor - if (!dom.isBlock(editableRoot) && editableRoot != dom.getRoot()) { - if (!newBlockName || shiftKey) { - insertBr(); - } - - return; - } - - // Wrap the current node and it's sibling in a default block if it's needed. - // for example this text|text2 will become this

    text|text2

    - // This won't happen if root blocks are disabled or the shiftKey is pressed - if ((newBlockName && !shiftKey) || (!newBlockName && shiftKey)) { - container = wrapSelfAndSiblingsInDefaultBlock(container, offset); - } - - // Find parent block and setup empty block paddings - parentBlock = dom.getParent(container, dom.isBlock); - containerBlock = parentBlock ? dom.getParent(parentBlock.parentNode, dom.isBlock) : null; - - // Setup block names - parentBlockName = parentBlock ? parentBlock.nodeName.toUpperCase() : ''; // IE < 9 & HTML5 - containerBlockName = containerBlock ? containerBlock.nodeName.toUpperCase() : ''; // IE < 9 & HTML5 - - // Enter inside block contained within a LI then split or insert before/after LI - if (containerBlockName == 'LI' && !evt.ctrlKey) { - parentBlock = containerBlock; - parentBlockName = containerBlockName; - } - - // Handle enter in LI - if (parentBlockName == 'LI') { - if (!newBlockName && shiftKey) { - insertBr(); - return; - } - - // Handle enter inside an empty list item - if (dom.isEmpty(parentBlock)) { - // Let the list plugin or browser handle nested lists for now - if (/^(UL|OL|LI)$/.test(containerBlock.parentNode.nodeName)) { - return false; - } - - handleEmptyListItem(); - return; - } - } - - // Don't split PRE tags but insert a BR instead easier when writing code samples etc - if (parentBlockName == 'PRE' && settings.br_in_pre !== false) { - if (!shiftKey) { - insertBr(); - return; - } - } else { - // If no root block is configured then insert a BR by default or if the shiftKey is pressed - if ((!newBlockName && !shiftKey && parentBlockName != 'LI') || (newBlockName && shiftKey)) { - insertBr(); - return; - } - } - - // Default block name if it's not configured - newBlockName = newBlockName || 'P'; - - // Insert new block before/after the parent block depending on caret location - if (isCaretAtStartOrEndOfBlock()) { - // If the caret is at the end of a header we produce a P tag after it similar to Word unless we are in a hgroup - if (/^(H[1-6]|PRE)$/.test(parentBlockName) && containerBlockName != 'HGROUP') { - newBlock = createNewBlock(newBlockName); - } else { - newBlock = createNewBlock(); - } - - // Split the current container block element if enter is pressed inside an empty inner block element - if (settings.end_container_on_empty_block && canSplitBlock(containerBlock) && dom.isEmpty(parentBlock)) { - // Split container block for example a BLOCKQUOTE at the current blockParent location for example a P - newBlock = dom.split(containerBlock, parentBlock); - } else { - dom.insertAfter(newBlock, parentBlock); - } - - moveToCaretPosition(newBlock); - } else if (isCaretAtStartOrEndOfBlock(true)) { - // Insert new block before - newBlock = parentBlock.parentNode.insertBefore(createNewBlock(), parentBlock); - renderBlockOnIE(newBlock); - } else { - // Extract after fragment and insert it after the current block - tmpRng = rng.cloneRange(); - tmpRng.setEndAfter(parentBlock); - fragment = tmpRng.extractContents(); - trimLeadingLineBreaks(fragment); - newBlock = fragment.firstChild; - dom.insertAfter(fragment, parentBlock); - trimInlineElementsOnLeftSideOfBlock(newBlock); - addBrToBlockIfNeeded(parentBlock); - moveToCaretPosition(newBlock); - } - - dom.setAttrib(newBlock, 'id', ''); // Remove ID since it needs to be document unique - undoManager.add(); - } - - editor.onKeyDown.add(function(ed, evt) { - if (evt.keyCode == 13) { - if (handleEnterKey(evt) !== false) { - evt.preventDefault(); - } - } - }); - }; -})(tinymce); +// FILE IS GENERATED BY COMBINING THE SOURCES IN THE "classes" DIRECTORY SO DON'T MODIFY THIS FILE DIRECTLY +(function(win) { + var whiteSpaceRe = /^\s*|\s*$/g, + undef, isRegExpBroken = 'B'.replace(/A(.)|B/, '$1') === '$1'; + + var tinymce = { + majorVersion : '3', + + minorVersion : '5.11', + + releaseDate : '2014-05-08', + + _init : function() { + var t = this, d = document, na = navigator, ua = na.userAgent, i, nl, n, base, p, v; + + t.isIE11 = ua.indexOf('Trident/') != -1 && (ua.indexOf('rv:') != -1 || na.appName.indexOf('Netscape') != -1); + + t.isOpera = win.opera && opera.buildNumber; + + t.isWebKit = /WebKit/.test(ua); + + t.isIE = !t.isWebKit && !t.isOpera && (/MSIE/gi).test(ua) && (/Explorer/gi).test(na.appName) || t.isIE11; + + t.isIE6 = t.isIE && /MSIE [56]/.test(ua); + + t.isIE7 = t.isIE && /MSIE [7]/.test(ua); + + t.isIE8 = t.isIE && /MSIE [8]/.test(ua); + + t.isIE9 = t.isIE && /MSIE [9]/.test(ua); + + t.isGecko = !t.isWebKit && !t.isIE11 && /Gecko/.test(ua); + + t.isMac = ua.indexOf('Mac') != -1; + + t.isAir = /adobeair/i.test(ua); + + t.isIDevice = /(iPad|iPhone)/.test(ua); + + t.isIOS5 = t.isIDevice && ua.match(/AppleWebKit\/(\d*)/)[1]>=534; + + // TinyMCE .NET webcontrol might be setting the values for TinyMCE + if (win.tinyMCEPreInit) { + t.suffix = tinyMCEPreInit.suffix; + t.baseURL = tinyMCEPreInit.base; + t.query = tinyMCEPreInit.query; + return; + } + + // Get suffix and base + t.suffix = ''; + + // If base element found, add that infront of baseURL + nl = d.getElementsByTagName('base'); + for (i=0; i : + s = /^((static) )?([\w.]+)(:([\w.]+))?/.exec(s); + cn = s[3].match(/(^|\.)(\w+)$/i)[2]; // Class name + + // Create namespace for new class + ns = t.createNS(s[3].replace(/\.\w+$/, ''), root); + + // Class already exists + if (ns[cn]) + return; + + // Make pure static class + if (s[2] == 'static') { + ns[cn] = p; + + if (this.onCreate) + this.onCreate(s[2], s[3], ns[cn]); + + return; + } + + // Create default constructor + if (!p[cn]) { + p[cn] = function() {}; + de = 1; + } + + // Add constructor and methods + ns[cn] = p[cn]; + t.extend(ns[cn].prototype, p); + + // Extend + if (s[5]) { + sp = t.resolve(s[5]).prototype; + scn = s[5].match(/\.(\w+)$/i)[1]; // Class name + + // Extend constructor + c = ns[cn]; + if (de) { + // Add passthrough constructor + ns[cn] = function() { + return sp[scn].apply(this, arguments); + }; + } else { + // Add inherit constructor + ns[cn] = function() { + this.parent = sp[scn]; + return c.apply(this, arguments); + }; + } + ns[cn].prototype[cn] = ns[cn]; + + // Add super methods + t.each(sp, function(f, n) { + ns[cn].prototype[n] = sp[n]; + }); + + // Add overridden methods + t.each(p, function(f, n) { + // Extend methods if needed + if (sp[n]) { + ns[cn].prototype[n] = function() { + this.parent = sp[n]; + return f.apply(this, arguments); + }; + } else { + if (n != cn) + ns[cn].prototype[n] = f; + } + }); + } + + // Add static methods + t.each(p['static'], function(f, n) { + ns[cn][n] = f; + }); + + if (this.onCreate) + this.onCreate(s[2], s[3], ns[cn].prototype); + }, + + walk : function(o, f, n, s) { + s = s || this; + + if (o) { + if (n) + o = o[n]; + + tinymce.each(o, function(o, i) { + if (f.call(s, o, i, n) === false) + return false; + + tinymce.walk(o, f, n, s); + }); + } + }, + + createNS : function(n, o) { + var i, v; + + o = o || win; + + n = n.split('.'); + for (i=0; i 0 ? args : [listener.scope]); + + if (returnValue === false) + break; + } + + self.inDispatch = false; + + return returnValue; + } + + }); + +(function() { + var each = tinymce.each; + + tinymce.create('tinymce.util.URI', { + URI : function(u, s) { + var t = this, o, a, b, base_url; + + // Trim whitespace + u = tinymce.trim(u); + + // Default settings + s = t.settings = s || {}; + + // Strange app protocol that isn't http/https or local anchor + // For example: mailto,skype,tel etc. + if (/^([\w\-]+):([^\/]{2})/i.test(u) || /^\s*#/.test(u)) { + t.source = u; + return; + } + + // Absolute path with no host, fake host and protocol + if (u.indexOf('/') === 0 && u.indexOf('//') !== 0) + u = (s.base_uri ? s.base_uri.protocol || 'http' : 'http') + '://mce_host' + u; + + // Relative path http:// or protocol relative //path + if (!/^[\w\-]*:?\/\//.test(u)) { + base_url = s.base_uri ? s.base_uri.path : new tinymce.util.URI(location.href).directory; + u = ((s.base_uri && s.base_uri.protocol) || 'http') + '://mce_host' + t.toAbsPath(base_url, u); + } + + // Parse URL (Credits goes to Steave, http://blog.stevenlevithan.com/archives/parseuri) + u = u.replace(/@@/g, '(mce_at)'); // Zope 3 workaround, they use @@something + u = /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@\/]*):?([^:@\/]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/.exec(u); + each(["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"], function(v, i) { + var s = u[i]; + + // Zope 3 workaround, they use @@something + if (s) + s = s.replace(/\(mce_at\)/g, '@@'); + + t[v] = s; + }); + + b = s.base_uri; + if (b) { + if (!t.protocol) + t.protocol = b.protocol; + + if (!t.userInfo) + t.userInfo = b.userInfo; + + if (!t.port && t.host === 'mce_host') + t.port = b.port; + + if (!t.host || t.host === 'mce_host') + t.host = b.host; + + t.source = ''; + } + + //t.path = t.path || '/'; + }, + + setPath : function(p) { + var t = this; + + p = /^(.*?)\/?(\w+)?$/.exec(p); + + // Update path parts + t.path = p[0]; + t.directory = p[1]; + t.file = p[2]; + + // Rebuild source + t.source = ''; + t.getURI(); + }, + + toRelative : function(u) { + var t = this, o; + + if (u === "./") + return u; + + u = new tinymce.util.URI(u, {base_uri : t}); + + // Not on same domain/port or protocol + if ((u.host != 'mce_host' && t.host != u.host && u.host) || t.port != u.port || t.protocol != u.protocol) + return u.getURI(); + + var tu = t.getURI(), uu = u.getURI(); + + // Allow usage of the base_uri when relative_urls = true + if(tu == uu || (tu.charAt(tu.length - 1) == "/" && tu.substr(0, tu.length - 1) == uu)) + return tu; + + o = t.toRelPath(t.path, u.path); + + // Add query + if (u.query) + o += '?' + u.query; + + // Add anchor + if (u.anchor) + o += '#' + u.anchor; + + return o; + }, + + toAbsolute : function(u, nh) { + u = new tinymce.util.URI(u, {base_uri : this}); + + return u.getURI(this.host == u.host && this.protocol == u.protocol ? nh : 0); + }, + + toRelPath : function(base, path) { + var items, bp = 0, out = '', i, l; + + // Split the paths + base = base.substring(0, base.lastIndexOf('/')); + base = base.split('/'); + items = path.split('/'); + + if (base.length >= items.length) { + for (i = 0, l = base.length; i < l; i++) { + if (i >= items.length || base[i] != items[i]) { + bp = i + 1; + break; + } + } + } + + if (base.length < items.length) { + for (i = 0, l = items.length; i < l; i++) { + if (i >= base.length || base[i] != items[i]) { + bp = i + 1; + break; + } + } + } + + if (bp === 1) + return path; + + for (i = 0, l = base.length - (bp - 1); i < l; i++) + out += "../"; + + for (i = bp - 1, l = items.length; i < l; i++) { + if (i != bp - 1) + out += "/" + items[i]; + else + out += items[i]; + } + + return out; + }, + + toAbsPath : function(base, path) { + var i, nb = 0, o = [], tr, outPath; + + // Split paths + tr = /\/$/.test(path) ? '/' : ''; + base = base.split('/'); + path = path.split('/'); + + // Remove empty chunks + each(base, function(k) { + if (k) + o.push(k); + }); + + base = o; + + // Merge relURLParts chunks + for (i = path.length - 1, o = []; i >= 0; i--) { + // Ignore empty or . + if (path[i].length === 0 || path[i] === ".") + continue; + + // Is parent + if (path[i] === '..') { + nb++; + continue; + } + + // Move up + if (nb > 0) { + nb--; + continue; + } + + o.push(path[i]); + } + + i = base.length - nb; + + // If /a/b/c or / + if (i <= 0) + outPath = o.reverse().join('/'); + else + outPath = base.slice(0, i).join('/') + '/' + o.reverse().join('/'); + + // Add front / if it's needed + if (outPath.indexOf('/') !== 0) + outPath = '/' + outPath; + + // Add traling / if it's needed + if (tr && outPath.lastIndexOf('/') !== outPath.length - 1) + outPath += tr; + + return outPath; + }, + + getURI : function(nh) { + var s, t = this; + + // Rebuild source + if (!t.source || nh) { + s = ''; + + if (!nh) { + if (t.protocol) + s += t.protocol + '://'; + + if (t.userInfo) + s += t.userInfo + '@'; + + if (t.host) + s += t.host; + + if (t.port) + s += ':' + t.port; + } + + if (t.path) + s += t.path; + + if (t.query) + s += '?' + t.query; + + if (t.anchor) + s += '#' + t.anchor; + + t.source = s; + } + + return t.source; + } + }); +})(); + +(function() { + var each = tinymce.each; + + tinymce.create('static tinymce.util.Cookie', { + getHash : function(n) { + var v = this.get(n), h; + + if (v) { + each(v.split('&'), function(v) { + v = v.split('='); + h = h || {}; + h[unescape(v[0])] = unescape(v[1]); + }); + } + + return h; + }, + + setHash : function(n, v, e, p, d, s) { + var o = ''; + + each(v, function(v, k) { + o += (!o ? '' : '&') + escape(k) + '=' + escape(v); + }); + + this.set(n, o, e, p, d, s); + }, + + get : function(n) { + var c = document.cookie, e, p = n + "=", b; + + // Strict mode + if (!c) + return; + + b = c.indexOf("; " + p); + + if (b == -1) { + b = c.indexOf(p); + + if (b !== 0) + return null; + } else + b += 2; + + e = c.indexOf(";", b); + + if (e == -1) + e = c.length; + + return unescape(c.substring(b + p.length, e)); + }, + + set : function(n, v, e, p, d, s) { + document.cookie = n + "=" + escape(v) + + ((e) ? "; expires=" + e.toGMTString() : "") + + ((p) ? "; path=" + escape(p) : "") + + ((d) ? "; domain=" + d : "") + + ((s) ? "; secure" : ""); + }, + + remove : function(name, path, domain) { + var date = new Date(); + + date.setTime(date.getTime() - 1000); + + this.set(name, '', date, path, domain); + } + }); +})(); + +(function() { + function serialize(o, quote) { + var i, v, t, name; + + quote = quote || '"'; + + if (o == null) + return 'null'; + + t = typeof o; + + if (t == 'string') { + v = '\bb\tt\nn\ff\rr\""\'\'\\\\'; + + return quote + o.replace(/([\u0080-\uFFFF\x00-\x1f\"\'\\])/g, function(a, b) { + // Make sure single quotes never get encoded inside double quotes for JSON compatibility + if (quote === '"' && a === "'") + return a; + + i = v.indexOf(b); + + if (i + 1) + return '\\' + v.charAt(i + 1); + + a = b.charCodeAt().toString(16); + + return '\\u' + '0000'.substring(a.length) + a; + }) + quote; + } + + if (t == 'object') { + if (o.hasOwnProperty && Object.prototype.toString.call(o) === '[object Array]') { + for (i=0, v = '['; i 0 ? ',' : '') + serialize(o[i], quote); + + return v + ']'; + } + + v = '{'; + + for (name in o) { + if (o.hasOwnProperty(name)) { + v += typeof o[name] != 'function' ? (v.length > 1 ? ',' + quote : quote) + name + quote +':' + serialize(o[name], quote) : ''; + } + } + + return v + '}'; + } + + return '' + o; + }; + + tinymce.util.JSON = { + serialize: serialize, + + parse: function(s) { + try { + return eval('(' + s + ')'); + } catch (ex) { + // Ignore + } + } + + }; +})(); + +tinymce.create('static tinymce.util.XHR', { + send : function(o) { + var x, t, w = window, c = 0; + + function ready() { + if (!o.async || x.readyState == 4 || c++ > 10000) { + if (o.success && c < 10000 && x.status == 200) + o.success.call(o.success_scope, '' + x.responseText, x, o); + else if (o.error) + o.error.call(o.error_scope, c > 10000 ? 'TIMED_OUT' : 'GENERAL', x, o); + + x = null; + } else + w.setTimeout(ready, 10); + }; + + // Default settings + o.scope = o.scope || this; + o.success_scope = o.success_scope || o.scope; + o.error_scope = o.error_scope || o.scope; + o.async = o.async === false ? false : true; + o.data = o.data || ''; + + function get(s) { + x = 0; + + try { + x = new ActiveXObject(s); + } catch (ex) { + } + + return x; + }; + + x = w.XMLHttpRequest ? new XMLHttpRequest() : get('Microsoft.XMLHTTP') || get('Msxml2.XMLHTTP'); + + if (x) { + if (x.overrideMimeType) + x.overrideMimeType(o.content_type); + + x.open(o.type || (o.data ? 'POST' : 'GET'), o.url, o.async); + + if (o.content_type) + x.setRequestHeader('Content-Type', o.content_type); + + x.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); + + x.send(o.data); + + // Syncronous request + if (!o.async) + return ready(); + + // Wait for response, onReadyStateChange can not be used since it leaks memory in IE + t = w.setTimeout(ready, 10); + } + } +}); + +(function() { + var extend = tinymce.extend, JSON = tinymce.util.JSON, XHR = tinymce.util.XHR; + + tinymce.create('tinymce.util.JSONRequest', { + JSONRequest : function(s) { + this.settings = extend({ + }, s); + this.count = 0; + }, + + send : function(o) { + var ecb = o.error, scb = o.success; + + o = extend(this.settings, o); + + o.success = function(c, x) { + c = JSON.parse(c); + + if (typeof(c) == 'undefined') { + c = { + error : 'JSON Parse error.' + }; + } + + if (c.error) + ecb.call(o.error_scope || o.scope, c.error, x); + else + scb.call(o.success_scope || o.scope, c.result); + }; + + o.error = function(ty, x) { + if (ecb) + ecb.call(o.error_scope || o.scope, ty, x); + }; + + o.data = JSON.serialize({ + id : o.id || 'c' + (this.count++), + method : o.method, + params : o.params + }); + + // JSON content type for Ruby on rails. Bug: #1883287 + o.content_type = 'application/json'; + + XHR.send(o); + }, + + 'static' : { + sendRPC : function(o) { + return new tinymce.util.JSONRequest().send(o); + } + } + }); +}()); +(function(tinymce){ + tinymce.VK = { + BACKSPACE: 8, + DELETE: 46, + DOWN: 40, + ENTER: 13, + LEFT: 37, + RIGHT: 39, + SPACEBAR: 32, + TAB: 9, + UP: 38, + + modifierPressed: function (e) { + return e.shiftKey || e.ctrlKey || e.altKey; + }, + + metaKeyPressed: function(e) { + // Check if ctrl or meta key is pressed also check if alt is false for Polish users + return tinymce.isMac ? e.metaKey : e.ctrlKey && !e.altKey; + } + }; +})(tinymce); + +tinymce.util.Quirks = function(editor) { + var VK = tinymce.VK, BACKSPACE = VK.BACKSPACE, DELETE = VK.DELETE, dom = editor.dom, selection = editor.selection, + settings = editor.settings, parser = editor.parser, serializer = editor.serializer, each = tinymce.each; + + function setEditorCommandState(cmd, state) { + try { + editor.getDoc().execCommand(cmd, false, state); + } catch (ex) { + // Ignore + } + } + + function getDocumentMode() { + var documentMode = editor.getDoc().documentMode; + + return documentMode ? documentMode : 6; + }; + + function isDefaultPrevented(e) { + return e.isDefaultPrevented(); + }; + + function cleanupStylesWhenDeleting() { + function removeMergedFormatSpans(isDelete) { + var rng, blockElm, wrapperElm, bookmark, container, offset, elm; + + function isAtStartOrEndOfElm() { + if (container.nodeType == 3) { + if (isDelete && offset == container.length) { + return true; + } + + if (!isDelete && offset === 0) { + return true; + } + } + } + + rng = selection.getRng(); + var tmpRng = [rng.startContainer, rng.startOffset, rng.endContainer, rng.endOffset]; + + if (!rng.collapsed) { + isDelete = true; + } + + container = rng[(isDelete ? 'start' : 'end') + 'Container']; + offset = rng[(isDelete ? 'start' : 'end') + 'Offset']; + + if (container.nodeType == 3) { + blockElm = dom.getParent(rng.startContainer, dom.isBlock); + + // On delete clone the root span of the next block element + if (isDelete) { + blockElm = dom.getNext(blockElm, dom.isBlock); + } + + if (blockElm && (isAtStartOrEndOfElm() || !rng.collapsed)) { + // Wrap children of block in a EM and let WebKit stick is + // runtime styles junk into that EM + wrapperElm = dom.create('em', {'id': '__mceDel'}); + + each(tinymce.grep(blockElm.childNodes), function(node) { + wrapperElm.appendChild(node); + }); + + blockElm.appendChild(wrapperElm); + } + } + + // Do the backspace/delete action + rng = dom.createRng(); + rng.setStart(tmpRng[0], tmpRng[1]); + rng.setEnd(tmpRng[2], tmpRng[3]); + selection.setRng(rng); + editor.getDoc().execCommand(isDelete ? 'ForwardDelete' : 'Delete', false, null); + + // Remove temp wrapper element + if (wrapperElm) { + bookmark = selection.getBookmark(); + + while (elm = dom.get('__mceDel')) { + dom.remove(elm, true); + } + + selection.moveToBookmark(bookmark); + } + } + + editor.onKeyDown.add(function(editor, e) { + var isDelete; + + isDelete = e.keyCode == DELETE; + if (!isDefaultPrevented(e) && (isDelete || e.keyCode == BACKSPACE) && !VK.modifierPressed(e)) { + e.preventDefault(); + removeMergedFormatSpans(isDelete); + } + }); + + editor.addCommand('Delete', function() {removeMergedFormatSpans();}); + }; + + function emptyEditorWhenDeleting() { + function serializeRng(rng) { + var body = dom.create("body"); + var contents = rng.cloneContents(); + body.appendChild(contents); + return selection.serializer.serialize(body, {format: 'html'}); + } + + function allContentsSelected(rng) { + var selection = serializeRng(rng); + + var allRng = dom.createRng(); + allRng.selectNode(editor.getBody()); + + var allSelection = serializeRng(allRng); + return selection === allSelection; + } + + editor.onKeyDown.add(function(editor, e) { + var keyCode = e.keyCode, isCollapsed; + + // Empty the editor if it's needed for example backspace at

    |

    + if (!isDefaultPrevented(e) && (keyCode == DELETE || keyCode == BACKSPACE)) { + isCollapsed = editor.selection.isCollapsed(); + + // Selection is collapsed but the editor isn't empty + if (isCollapsed && !dom.isEmpty(editor.getBody())) { + return; + } + + // IE deletes all contents correctly when everything is selected + if (tinymce.isIE && !isCollapsed) { + return; + } + + // Selection isn't collapsed but not all the contents is selected + if (!isCollapsed && !allContentsSelected(editor.selection.getRng())) { + return; + } + + // Manually empty the editor + editor.setContent(''); + editor.selection.setCursorLocation(editor.getBody(), 0); + editor.nodeChanged(); + } + }); + }; + + function selectAll() { + editor.onKeyDown.add(function(editor, e) { + if (!isDefaultPrevented(e) && e.keyCode == 65 && VK.metaKeyPressed(e)) { + e.preventDefault(); + editor.execCommand('SelectAll'); + } + }); + }; + + function inputMethodFocus() { + if (!editor.settings.content_editable) { + // Case 1 IME doesn't initialize if you focus the document + dom.bind(editor.getDoc(), 'focusin', function(e) { + selection.setRng(selection.getRng()); + }); + + // Case 2 IME doesn't initialize if you click the documentElement it also doesn't properly fire the focusin event + dom.bind(editor.getDoc(), 'mousedown', function(e) { + if (e.target == editor.getDoc().documentElement) { + editor.getWin().focus(); + selection.setRng(selection.getRng()); + } + }); + } + }; + + function removeHrOnBackspace() { + editor.onKeyDown.add(function(editor, e) { + if (!isDefaultPrevented(e) && e.keyCode === BACKSPACE) { + if (selection.isCollapsed() && selection.getRng(true).startOffset === 0) { + var node = selection.getNode(); + var previousSibling = node.previousSibling; + + if (previousSibling && previousSibling.nodeName && previousSibling.nodeName.toLowerCase() === "hr") { + dom.remove(previousSibling); + tinymce.dom.Event.cancel(e); + } + } + } + }) + } + + function focusBody() { + // Fix for a focus bug in FF 3.x where the body element + // wouldn't get proper focus if the user clicked on the HTML element + if (!Range.prototype.getClientRects) { // Detect getClientRects got introduced in FF 4 + editor.onMouseDown.add(function(editor, e) { + if (!isDefaultPrevented(e) && e.target.nodeName === "HTML") { + var body = editor.getBody(); + + // Blur the body it's focused but not correctly focused + body.blur(); + + // Refocus the body after a little while + setTimeout(function() { + body.focus(); + }, 0); + } + }); + } + }; + + function selectControlElements() { + editor.onClick.add(function(editor, e) { + e = e.target; + + // Workaround for bug, http://bugs.webkit.org/show_bug.cgi?id=12250 + // WebKit can't even do simple things like selecting an image + // Needs tobe the setBaseAndExtend or it will fail to select floated images + if (/^(IMG|HR)$/.test(e.nodeName)) { + selection.getSel().setBaseAndExtent(e, 0, e, 1); + } + + if (e.nodeName == 'A' && dom.hasClass(e, 'mceItemAnchor')) { + selection.select(e); + } + + editor.nodeChanged(); + }); + }; + + function removeStylesWhenDeletingAccrossBlockElements() { + function getAttributeApplyFunction() { + var template = dom.getAttribs(selection.getStart().cloneNode(false)); + + return function() { + var target = selection.getStart(); + + if (target !== editor.getBody()) { + dom.setAttrib(target, "style", null); + + each(template, function(attr) { + target.setAttributeNode(attr.cloneNode(true)); + }); + } + }; + } + + function isSelectionAcrossElements() { + return !selection.isCollapsed() && dom.getParent(selection.getStart(), dom.isBlock) != dom.getParent(selection.getEnd(), dom.isBlock); + } + + function blockEvent(editor, e) { + e.preventDefault(); + return false; + } + + editor.onKeyPress.add(function(editor, e) { + var applyAttributes; + + if (!isDefaultPrevented(e) && (e.keyCode == 8 || e.keyCode == 46) && isSelectionAcrossElements()) { + applyAttributes = getAttributeApplyFunction(); + editor.getDoc().execCommand('delete', false, null); + applyAttributes(); + e.preventDefault(); + return false; + } + }); + + dom.bind(editor.getDoc(), 'cut', function(e) { + var applyAttributes; + + if (!isDefaultPrevented(e) && isSelectionAcrossElements()) { + applyAttributes = getAttributeApplyFunction(); + editor.onKeyUp.addToTop(blockEvent); + + setTimeout(function() { + applyAttributes(); + editor.onKeyUp.remove(blockEvent); + }, 0); + } + }); + } + + function selectionChangeNodeChanged() { + var lastRng, selectionTimer; + + dom.bind(editor.getDoc(), 'selectionchange', function() { + if (selectionTimer) { + clearTimeout(selectionTimer); + selectionTimer = 0; + } + + selectionTimer = window.setTimeout(function() { + var rng = selection.getRng(); + + // Compare the ranges to see if it was a real change or not + if (!lastRng || !tinymce.dom.RangeUtils.compareRanges(rng, lastRng)) { + editor.nodeChanged(); + lastRng = rng; + } + }, 50); + }); + } + + function ensureBodyHasRoleApplication() { + document.body.setAttribute("role", "application"); + } + + function disableBackspaceIntoATable() { + editor.onKeyDown.add(function(editor, e) { + if (!isDefaultPrevented(e) && e.keyCode === BACKSPACE) { + if (selection.isCollapsed() && selection.getRng(true).startOffset === 0) { + var previousSibling = selection.getNode().previousSibling; + if (previousSibling && previousSibling.nodeName && previousSibling.nodeName.toLowerCase() === "table") { + return tinymce.dom.Event.cancel(e); + } + } + } + }) + } + + function addNewLinesBeforeBrInPre() { + // IE8+ rendering mode does the right thing with BR in PRE + if (getDocumentMode() > 7) { + return; + } + + // Enable display: none in area and add a specific class that hides all BR elements in PRE to + // avoid the caret from getting stuck at the BR elements while pressing the right arrow key + setEditorCommandState('RespectVisibilityInDesign', true); + editor.contentStyles.push('.mceHideBrInPre pre br {display: none}'); + dom.addClass(editor.getBody(), 'mceHideBrInPre'); + + // Adds a \n before all BR elements in PRE to get them visual + parser.addNodeFilter('pre', function(nodes, name) { + var i = nodes.length, brNodes, j, brElm, sibling; + + while (i--) { + brNodes = nodes[i].getAll('br'); + j = brNodes.length; + while (j--) { + brElm = brNodes[j]; + + // Add \n before BR in PRE elements on older IE:s so the new lines get rendered + sibling = brElm.prev; + if (sibling && sibling.type === 3 && sibling.value.charAt(sibling.value - 1) != '\n') { + sibling.value += '\n'; + } else { + brElm.parent.insert(new tinymce.html.Node('#text', 3), brElm, true).value = '\n'; + } + } + } + }); + + // Removes any \n before BR elements in PRE since other browsers and in contentEditable=false mode they will be visible + serializer.addNodeFilter('pre', function(nodes, name) { + var i = nodes.length, brNodes, j, brElm, sibling; + + while (i--) { + brNodes = nodes[i].getAll('br'); + j = brNodes.length; + while (j--) { + brElm = brNodes[j]; + sibling = brElm.prev; + if (sibling && sibling.type == 3) { + sibling.value = sibling.value.replace(/\r?\n$/, ''); + } + } + } + }); + } + + function removePreSerializedStylesWhenSelectingControls() { + dom.bind(editor.getBody(), 'mouseup', function(e) { + var value, node = selection.getNode(); + + // Moved styles to attributes on IMG eements + if (node.nodeName == 'IMG') { + // Convert style width to width attribute + if (value = dom.getStyle(node, 'width')) { + dom.setAttrib(node, 'width', value.replace(/[^0-9%]+/g, '')); + dom.setStyle(node, 'width', ''); + } + + // Convert style height to height attribute + if (value = dom.getStyle(node, 'height')) { + dom.setAttrib(node, 'height', value.replace(/[^0-9%]+/g, '')); + dom.setStyle(node, 'height', ''); + } + } + }); + } + + function keepInlineElementOnDeleteBackspace() { + editor.onKeyDown.add(function(editor, e) { + var isDelete, rng, container, offset, brElm, sibling, collapsed; + + isDelete = e.keyCode == DELETE; + if (!isDefaultPrevented(e) && (isDelete || e.keyCode == BACKSPACE) && !VK.modifierPressed(e)) { + rng = selection.getRng(); + container = rng.startContainer; + offset = rng.startOffset; + collapsed = rng.collapsed; + + // Override delete if the start container is a text node and is at the beginning of text or + // just before/after the last character to be deleted in collapsed mode + if (container.nodeType == 3 && container.nodeValue.length > 0 && ((offset === 0 && !collapsed) || (collapsed && offset === (isDelete ? 0 : 1)))) { + // Edge case when deleting

    |x

    + sibling = container.previousSibling; + if (sibling && sibling.nodeName == "IMG") { + return; + } + + nonEmptyElements = editor.schema.getNonEmptyElements(); + + // Prevent default logic since it's broken + e.preventDefault(); + + // Insert a BR before the text node this will prevent the containing element from being deleted/converted + brElm = dom.create('br', {id: '__tmp'}); + container.parentNode.insertBefore(brElm, container); + + // Do the browser delete + editor.getDoc().execCommand(isDelete ? 'ForwardDelete' : 'Delete', false, null); + + // Check if the previous sibling is empty after deleting for example:

    |

    + container = selection.getRng().startContainer; + sibling = container.previousSibling; + if (sibling && sibling.nodeType == 1 && !dom.isBlock(sibling) && dom.isEmpty(sibling) && !nonEmptyElements[sibling.nodeName.toLowerCase()]) { + dom.remove(sibling); + } + + // Remove the temp element we inserted + dom.remove('__tmp'); + } + } + }); + } + + function removeBlockQuoteOnBackSpace() { + // Add block quote deletion handler + editor.onKeyDown.add(function(editor, e) { + var rng, container, offset, root, parent; + + if (isDefaultPrevented(e) || e.keyCode != VK.BACKSPACE) { + return; + } + + rng = selection.getRng(); + container = rng.startContainer; + offset = rng.startOffset; + root = dom.getRoot(); + parent = container; + + if (!rng.collapsed || offset !== 0) { + return; + } + + while (parent && parent.parentNode && parent.parentNode.firstChild == parent && parent.parentNode != root) { + parent = parent.parentNode; + } + + // Is the cursor at the beginning of a blockquote? + if (parent.tagName === 'BLOCKQUOTE') { + // Remove the blockquote + editor.formatter.toggle('blockquote', null, parent); + + // Move the caret to the beginning of container + rng = dom.createRng(); + rng.setStart(container, 0); + rng.setEnd(container, 0); + selection.setRng(rng); + } + }); + }; + + function setGeckoEditingOptions() { + function setOpts() { + editor._refreshContentEditable(); + + setEditorCommandState("StyleWithCSS", false); + setEditorCommandState("enableInlineTableEditing", false); + + if (!settings.object_resizing) { + setEditorCommandState("enableObjectResizing", false); + } + }; + + if (!settings.readonly) { + editor.onBeforeExecCommand.add(setOpts); + editor.onMouseDown.add(setOpts); + } + }; + + function addBrAfterLastLinks() { + function fixLinks(editor, o) { + each(dom.select('a'), function(node) { + var parentNode = node.parentNode, root = dom.getRoot(); + + if (parentNode.lastChild === node) { + while (parentNode && !dom.isBlock(parentNode)) { + if (parentNode.parentNode.lastChild !== parentNode || parentNode === root) { + return; + } + + parentNode = parentNode.parentNode; + } + + dom.add(parentNode, 'br', {'data-mce-bogus' : 1}); + } + }); + }; + + editor.onExecCommand.add(function(editor, cmd) { + if (cmd === 'CreateLink') { + fixLinks(editor); + } + }); + + editor.onSetContent.add(selection.onSetContent.add(fixLinks)); + }; + + function setDefaultBlockType() { + if (settings.forced_root_block) { + editor.onInit.add(function() { + setEditorCommandState('DefaultParagraphSeparator', settings.forced_root_block); + }); + } + } + + function removeGhostSelection() { + function repaint(sender, args) { + if (!sender || !args.initial) { + editor.execCommand('mceRepaint'); + } + }; + + editor.onUndo.add(repaint); + editor.onRedo.add(repaint); + editor.onSetContent.add(repaint); + }; + + function deleteControlItemOnBackSpace() { + editor.onKeyDown.add(function(editor, e) { + var rng; + + if (!isDefaultPrevented(e) && e.keyCode == BACKSPACE) { + rng = editor.getDoc().selection.createRange(); + if (rng && rng.item) { + e.preventDefault(); + editor.undoManager.beforeChange(); + dom.remove(rng.item(0)); + editor.undoManager.add(); + } + } + }); + }; + + function renderEmptyBlocksFix() { + var emptyBlocksCSS; + + // IE10+ + if (getDocumentMode() >= 10) { + emptyBlocksCSS = ''; + each('p div h1 h2 h3 h4 h5 h6'.split(' '), function(name, i) { + emptyBlocksCSS += (i > 0 ? ',' : '') + name + ':empty'; + }); + + editor.contentStyles.push(emptyBlocksCSS + '{padding-right: 1px !important}'); + } + }; + + function fakeImageResize() { + var selectedElmX, selectedElmY, selectedElm, selectedElmGhost, selectedHandle, startX, startY, startW, startH, ratio, + resizeHandles, width, height, rootDocument = document, editableDoc = editor.getDoc(); + + if (!settings.object_resizing || settings.webkit_fake_resize === false) { + return; + } + + // Try disabling object resizing if WebKit implements resizing in the future + setEditorCommandState("enableObjectResizing", false); + + // Details about each resize handle how to scale etc + resizeHandles = { + // Name: x multiplier, y multiplier, delta size x, delta size y + n: [.5, 0, 0, -1], + e: [1, .5, 1, 0], + s: [.5, 1, 0, 1], + w: [0, .5, -1, 0], + nw: [0, 0, -1, -1], + ne: [1, 0, 1, -1], + se: [1, 1, 1, 1], + sw : [0, 1, -1, 1] + }; + + function resizeElement(e) { + var deltaX, deltaY; + + // Calc new width/height + deltaX = e.screenX - startX; + deltaY = e.screenY - startY; + + // Calc new size + width = deltaX * selectedHandle[2] + startW; + height = deltaY * selectedHandle[3] + startH; + + // Never scale down lower than 5 pixels + width = width < 5 ? 5 : width; + height = height < 5 ? 5 : height; + + // Constrain proportions when modifier key is pressed or if the nw, ne, sw, se corners are moved on an image + if (VK.modifierPressed(e) || (selectedElm.nodeName == "IMG" && selectedHandle[2] * selectedHandle[3] !== 0)) { + width = Math.round(height / ratio); + height = Math.round(width * ratio); + } + + // Update ghost size + dom.setStyles(selectedElmGhost, { + width: width, + height: height + }); + + // Update ghost X position if needed + if (selectedHandle[2] < 0 && selectedElmGhost.clientWidth <= width) { + dom.setStyle(selectedElmGhost, 'left', selectedElmX + (startW - width)); + } + + // Update ghost Y position if needed + if (selectedHandle[3] < 0 && selectedElmGhost.clientHeight <= height) { + dom.setStyle(selectedElmGhost, 'top', selectedElmY + (startH - height)); + } + } + + function endResize() { + function setSizeProp(name, value) { + if (value) { + // Resize by using style or attribute + if (selectedElm.style[name] || !editor.schema.isValid(selectedElm.nodeName.toLowerCase(), name)) { + dom.setStyle(selectedElm, name, value); + } else { + dom.setAttrib(selectedElm, name, value); + } + } + } + + // Set width/height properties + setSizeProp('width', width); + setSizeProp('height', height); + + dom.unbind(editableDoc, 'mousemove', resizeElement); + dom.unbind(editableDoc, 'mouseup', endResize); + + if (rootDocument != editableDoc) { + dom.unbind(rootDocument, 'mousemove', resizeElement); + dom.unbind(rootDocument, 'mouseup', endResize); + } + + // Remove ghost and update resize handle positions + dom.remove(selectedElmGhost); + showResizeRect(selectedElm); + } + + function showResizeRect(targetElm) { + var position, targetWidth, targetHeight; + + hideResizeRect(); + + // Get position and size of target + position = dom.getPos(targetElm); + selectedElmX = position.x; + selectedElmY = position.y; + targetWidth = targetElm.offsetWidth; + targetHeight = targetElm.offsetHeight; + + // Reset width/height if user selects a new image/table + if (selectedElm != targetElm) { + selectedElm = targetElm; + width = height = 0; + } + + each(resizeHandles, function(handle, name) { + var handleElm; + + // Get existing or render resize handle + handleElm = dom.get('mceResizeHandle' + name); + if (!handleElm) { + handleElm = dom.add(editableDoc.documentElement, 'div', { + id: 'mceResizeHandle' + name, + 'class': 'mceResizeHandle', + style: 'cursor:' + name + '-resize; margin:0; padding:0' + }); + + dom.bind(handleElm, 'mousedown', function(e) { + e.preventDefault(); + + endResize(); + + startX = e.screenX; + startY = e.screenY; + startW = selectedElm.clientWidth; + startH = selectedElm.clientHeight; + ratio = startH / startW; + selectedHandle = handle; + + selectedElmGhost = selectedElm.cloneNode(true); + dom.addClass(selectedElmGhost, 'mceClonedResizable'); + dom.setStyles(selectedElmGhost, { + left: selectedElmX, + top: selectedElmY, + margin: 0 + }); + + editableDoc.documentElement.appendChild(selectedElmGhost); + + dom.bind(editableDoc, 'mousemove', resizeElement); + dom.bind(editableDoc, 'mouseup', endResize); + + if (rootDocument != editableDoc) { + dom.bind(rootDocument, 'mousemove', resizeElement); + dom.bind(rootDocument, 'mouseup', endResize); + } + }); + } else { + dom.show(handleElm); + } + + // Position element + dom.setStyles(handleElm, { + left: (targetWidth * handle[0] + selectedElmX) - (handleElm.offsetWidth / 2), + top: (targetHeight * handle[1] + selectedElmY) - (handleElm.offsetHeight / 2) + }); + }); + + // Only add resize rectangle on WebKit and only on images + if (!tinymce.isOpera && selectedElm.nodeName == "IMG") { + selectedElm.setAttribute('data-mce-selected', '1'); + } + } + + function hideResizeRect() { + if (selectedElm) { + selectedElm.removeAttribute('data-mce-selected'); + } + + for (var name in resizeHandles) { + dom.hide('mceResizeHandle' + name); + } + } + + // Add CSS for resize handles, cloned element and selected + editor.contentStyles.push( + '.mceResizeHandle {' + + 'position: absolute;' + + 'border: 1px solid black;' + + 'background: #FFF;' + + 'width: 5px;' + + 'height: 5px;' + + 'z-index: 10000' + + '}' + + '.mceResizeHandle:hover {' + + 'background: #000' + + '}' + + 'img[data-mce-selected] {' + + 'outline: 1px solid black' + + '}' + + 'img.mceClonedResizable, table.mceClonedResizable {' + + 'position: absolute;' + + 'outline: 1px dashed black;' + + 'opacity: .5;' + + 'z-index: 10000' + + '}' + ); + + function updateResizeRect() { + var controlElm = dom.getParent(selection.getNode(), 'table,img'); + + // Remove data-mce-selected from all elements since they might have been copied using Ctrl+c/v + each(dom.select('img[data-mce-selected]'), function(img) { + img.removeAttribute('data-mce-selected'); + }); + + if (controlElm) { + showResizeRect(controlElm); + } else { + hideResizeRect(); + } + } + + // Show/hide resize rect when image is selected + editor.onNodeChange.add(updateResizeRect); + + // Fixes WebKit quirk where it returns IMG on getNode if caret is after last image in container + dom.bind(editableDoc, 'selectionchange', updateResizeRect); + + // Remove the internal attribute when serializing the DOM + editor.serializer.addAttributeFilter('data-mce-selected', function(nodes, name) { + var i = nodes.length; + + while (i--) { + nodes[i].attr(name, null); + } + }); + } + + function keepNoScriptContents() { + if (getDocumentMode() < 9) { + parser.addNodeFilter('noscript', function(nodes) { + var i = nodes.length, node, textNode; + + while (i--) { + node = nodes[i]; + textNode = node.firstChild; + + if (textNode) { + node.attr('data-mce-innertext', textNode.value); + } + } + }); + + serializer.addNodeFilter('noscript', function(nodes) { + var i = nodes.length, node, textNode, value; + + while (i--) { + node = nodes[i]; + textNode = nodes[i].firstChild; + + if (textNode) { + textNode.value = tinymce.html.Entities.decode(textNode.value); + } else { + // Old IE can't retain noscript value so an attribute is used to store it + value = node.attributes.map['data-mce-innertext']; + if (value) { + node.attr('data-mce-innertext', null); + textNode = new tinymce.html.Node('#text', 3); + textNode.value = value; + textNode.raw = true; + node.append(textNode); + } + } + } + }); + } + } + + function bodyHeight() { + editor.contentStyles.push('body {min-height: 100px}'); + editor.onClick.add(function(ed, e) { + if (e.target.nodeName == 'HTML') { + editor.execCommand('SelectAll'); + editor.selection.collapse(true); + editor.nodeChanged(); + } + }); + } + + function fixControlSelection() { + editor.onInit.add(function() { + var selectedRng; + + editor.getBody().addEventListener('mscontrolselect', function(e) { + setTimeout(function() { + if (editor.selection.getNode() != e.target) { + selectedRng = editor.selection.getRng(); + selection.fakeRng = editor.dom.createRng(); + selection.fakeRng.setStartBefore(e.target); + selection.fakeRng.setEndAfter(e.target); + } + }, 0); + }, false); + + editor.getDoc().addEventListener('selectionchange', function(e) { + if (selectedRng && !tinymce.dom.RangeUtils.compareRanges(editor.selection.getRng(), selectedRng)) { + selection.fakeRng = selectedRng = null; + } + }, false); + }); + } + + // All browsers + disableBackspaceIntoATable(); + removeBlockQuoteOnBackSpace(); + emptyEditorWhenDeleting(); + + // WebKit + if (tinymce.isWebKit) { + keepInlineElementOnDeleteBackspace(); + cleanupStylesWhenDeleting(); + inputMethodFocus(); + selectControlElements(); + setDefaultBlockType(); + + // iOS + if (tinymce.isIDevice) { + selectionChangeNodeChanged(); + } else { + fakeImageResize(); + selectAll(); + } + } + + // IE + if (tinymce.isIE && !tinymce.isIE11) { + removeHrOnBackspace(); + ensureBodyHasRoleApplication(); + addNewLinesBeforeBrInPre(); + removePreSerializedStylesWhenSelectingControls(); + deleteControlItemOnBackSpace(); + renderEmptyBlocksFix(); + keepNoScriptContents(); + } + + // IE 11+ + if (tinymce.isIE11) { + bodyHeight(); + fixControlSelection(); + } + + // Gecko + if (tinymce.isGecko && !tinymce.isIE11) { + removeHrOnBackspace(); + focusBody(); + removeStylesWhenDeletingAccrossBlockElements(); + setGeckoEditingOptions(); + addBrAfterLastLinks(); + removeGhostSelection(); + } + + // Opera + if (tinymce.isOpera) { + fakeImageResize(); + } +}; +(function(tinymce) { + var namedEntities, baseEntities, reverseEntities, + attrsCharsRegExp = /[&<>\"\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g, + textCharsRegExp = /[<>&\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g, + rawCharsRegExp = /[<>&\"\']/g, + entityRegExp = /&(#x|#)?([\w]+);/g, + asciiMap = { + 128 : "\u20AC", 130 : "\u201A", 131 : "\u0192", 132 : "\u201E", 133 : "\u2026", 134 : "\u2020", + 135 : "\u2021", 136 : "\u02C6", 137 : "\u2030", 138 : "\u0160", 139 : "\u2039", 140 : "\u0152", + 142 : "\u017D", 145 : "\u2018", 146 : "\u2019", 147 : "\u201C", 148 : "\u201D", 149 : "\u2022", + 150 : "\u2013", 151 : "\u2014", 152 : "\u02DC", 153 : "\u2122", 154 : "\u0161", 155 : "\u203A", + 156 : "\u0153", 158 : "\u017E", 159 : "\u0178" + }; + + // Raw entities + baseEntities = { + '\"' : '"', // Needs to be escaped since the YUI compressor would otherwise break the code + "'" : ''', + '<' : '<', + '>' : '>', + '&' : '&' + }; + + // Reverse lookup table for raw entities + reverseEntities = { + '<' : '<', + '>' : '>', + '&' : '&', + '"' : '"', + ''' : "'" + }; + + // Decodes text by using the browser + function nativeDecode(text) { + var elm; + + elm = document.createElement("div"); + elm.innerHTML = text; + + return elm.textContent || elm.innerText || text; + }; + + // Build a two way lookup table for the entities + function buildEntitiesLookup(items, radix) { + var i, chr, entity, lookup = {}; + + if (items) { + items = items.split(','); + radix = radix || 10; + + // Build entities lookup table + for (i = 0; i < items.length; i += 2) { + chr = String.fromCharCode(parseInt(items[i], radix)); + + // Only add non base entities + if (!baseEntities[chr]) { + entity = '&' + items[i + 1] + ';'; + lookup[chr] = entity; + lookup[entity] = chr; + } + } + + return lookup; + } + }; + + // Unpack entities lookup where the numbers are in radix 32 to reduce the size + namedEntities = buildEntitiesLookup( + '50,nbsp,51,iexcl,52,cent,53,pound,54,curren,55,yen,56,brvbar,57,sect,58,uml,59,copy,' + + '5a,ordf,5b,laquo,5c,not,5d,shy,5e,reg,5f,macr,5g,deg,5h,plusmn,5i,sup2,5j,sup3,5k,acute,' + + '5l,micro,5m,para,5n,middot,5o,cedil,5p,sup1,5q,ordm,5r,raquo,5s,frac14,5t,frac12,5u,frac34,' + + '5v,iquest,60,Agrave,61,Aacute,62,Acirc,63,Atilde,64,Auml,65,Aring,66,AElig,67,Ccedil,' + + '68,Egrave,69,Eacute,6a,Ecirc,6b,Euml,6c,Igrave,6d,Iacute,6e,Icirc,6f,Iuml,6g,ETH,6h,Ntilde,' + + '6i,Ograve,6j,Oacute,6k,Ocirc,6l,Otilde,6m,Ouml,6n,times,6o,Oslash,6p,Ugrave,6q,Uacute,' + + '6r,Ucirc,6s,Uuml,6t,Yacute,6u,THORN,6v,szlig,70,agrave,71,aacute,72,acirc,73,atilde,74,auml,' + + '75,aring,76,aelig,77,ccedil,78,egrave,79,eacute,7a,ecirc,7b,euml,7c,igrave,7d,iacute,7e,icirc,' + + '7f,iuml,7g,eth,7h,ntilde,7i,ograve,7j,oacute,7k,ocirc,7l,otilde,7m,ouml,7n,divide,7o,oslash,' + + '7p,ugrave,7q,uacute,7r,ucirc,7s,uuml,7t,yacute,7u,thorn,7v,yuml,ci,fnof,sh,Alpha,si,Beta,' + + 'sj,Gamma,sk,Delta,sl,Epsilon,sm,Zeta,sn,Eta,so,Theta,sp,Iota,sq,Kappa,sr,Lambda,ss,Mu,' + + 'st,Nu,su,Xi,sv,Omicron,t0,Pi,t1,Rho,t3,Sigma,t4,Tau,t5,Upsilon,t6,Phi,t7,Chi,t8,Psi,' + + 't9,Omega,th,alpha,ti,beta,tj,gamma,tk,delta,tl,epsilon,tm,zeta,tn,eta,to,theta,tp,iota,' + + 'tq,kappa,tr,lambda,ts,mu,tt,nu,tu,xi,tv,omicron,u0,pi,u1,rho,u2,sigmaf,u3,sigma,u4,tau,' + + 'u5,upsilon,u6,phi,u7,chi,u8,psi,u9,omega,uh,thetasym,ui,upsih,um,piv,812,bull,816,hellip,' + + '81i,prime,81j,Prime,81u,oline,824,frasl,88o,weierp,88h,image,88s,real,892,trade,89l,alefsym,' + + '8cg,larr,8ch,uarr,8ci,rarr,8cj,darr,8ck,harr,8dl,crarr,8eg,lArr,8eh,uArr,8ei,rArr,8ej,dArr,' + + '8ek,hArr,8g0,forall,8g2,part,8g3,exist,8g5,empty,8g7,nabla,8g8,isin,8g9,notin,8gb,ni,8gf,prod,' + + '8gh,sum,8gi,minus,8gn,lowast,8gq,radic,8gt,prop,8gu,infin,8h0,ang,8h7,and,8h8,or,8h9,cap,8ha,cup,' + + '8hb,int,8hk,there4,8hs,sim,8i5,cong,8i8,asymp,8j0,ne,8j1,equiv,8j4,le,8j5,ge,8k2,sub,8k3,sup,8k4,' + + 'nsub,8k6,sube,8k7,supe,8kl,oplus,8kn,otimes,8l5,perp,8m5,sdot,8o8,lceil,8o9,rceil,8oa,lfloor,8ob,' + + 'rfloor,8p9,lang,8pa,rang,9ea,loz,9j0,spades,9j3,clubs,9j5,hearts,9j6,diams,ai,OElig,aj,oelig,b0,' + + 'Scaron,b1,scaron,bo,Yuml,m6,circ,ms,tilde,802,ensp,803,emsp,809,thinsp,80c,zwnj,80d,zwj,80e,lrm,' + + '80f,rlm,80j,ndash,80k,mdash,80o,lsquo,80p,rsquo,80q,sbquo,80s,ldquo,80t,rdquo,80u,bdquo,810,dagger,' + + '811,Dagger,81g,permil,81p,lsaquo,81q,rsaquo,85c,euro', 32); + + tinymce.html = tinymce.html || {}; + + tinymce.html.Entities = { + encodeRaw : function(text, attr) { + return text.replace(attr ? attrsCharsRegExp : textCharsRegExp, function(chr) { + return baseEntities[chr] || chr; + }); + }, + + encodeAllRaw : function(text) { + return ('' + text).replace(rawCharsRegExp, function(chr) { + return baseEntities[chr] || chr; + }); + }, + + encodeNumeric : function(text, attr) { + return text.replace(attr ? attrsCharsRegExp : textCharsRegExp, function(chr) { + // Multi byte sequence convert it to a single entity + if (chr.length > 1) + return '&#' + (((chr.charCodeAt(0) - 0xD800) * 0x400) + (chr.charCodeAt(1) - 0xDC00) + 0x10000) + ';'; + + return baseEntities[chr] || '&#' + chr.charCodeAt(0) + ';'; + }); + }, + + encodeNamed : function(text, attr, entities) { + entities = entities || namedEntities; + + return text.replace(attr ? attrsCharsRegExp : textCharsRegExp, function(chr) { + return baseEntities[chr] || entities[chr] || chr; + }); + }, + + getEncodeFunc : function(name, entities) { + var Entities = tinymce.html.Entities; + + entities = buildEntitiesLookup(entities) || namedEntities; + + function encodeNamedAndNumeric(text, attr) { + return text.replace(attr ? attrsCharsRegExp : textCharsRegExp, function(chr) { + return baseEntities[chr] || entities[chr] || '&#' + chr.charCodeAt(0) + ';' || chr; + }); + }; + + function encodeCustomNamed(text, attr) { + return Entities.encodeNamed(text, attr, entities); + }; + + // Replace + with , to be compatible with previous TinyMCE versions + name = tinymce.makeMap(name.replace(/\+/g, ',')); + + // Named and numeric encoder + if (name.named && name.numeric) + return encodeNamedAndNumeric; + + // Named encoder + if (name.named) { + // Custom names + if (entities) + return encodeCustomNamed; + + return Entities.encodeNamed; + } + + // Numeric + if (name.numeric) + return Entities.encodeNumeric; + + // Raw encoder + return Entities.encodeRaw; + }, + + decode : function(text) { + return text.replace(entityRegExp, function(all, numeric, value) { + if (numeric) { + value = parseInt(value, numeric.length === 2 ? 16 : 10); + + // Support upper UTF + if (value > 0xFFFF) { + value -= 0x10000; + + return String.fromCharCode(0xD800 + (value >> 10), 0xDC00 + (value & 0x3FF)); + } else + return asciiMap[value] || String.fromCharCode(value); + } + + return reverseEntities[all] || namedEntities[all] || nativeDecode(all); + }); + } + }; +})(tinymce); + +tinymce.html.Styles = function(settings, schema) { + var rgbRegExp = /rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)/gi, + urlOrStrRegExp = /(?:url(?:(?:\(\s*\"([^\"]+)\"\s*\))|(?:\(\s*\'([^\']+)\'\s*\))|(?:\(\s*([^)\s]+)\s*\))))|(?:\'([^\']+)\')|(?:\"([^\"]+)\")/gi, + styleRegExp = /\s*([^:]+):\s*([^;]+);?/g, + trimRightRegExp = /\s+$/, + urlColorRegExp = /rgb/, + undef, i, encodingLookup = {}, encodingItems; + + settings = settings || {}; + + encodingItems = '\\" \\\' \\; \\: ; : \uFEFF'.split(' '); + for (i = 0; i < encodingItems.length; i++) { + encodingLookup[encodingItems[i]] = '\uFEFF' + i; + encodingLookup['\uFEFF' + i] = encodingItems[i]; + } + + function toHex(match, r, g, b) { + function hex(val) { + val = parseInt(val).toString(16); + + return val.length > 1 ? val : '0' + val; // 0 -> 00 + }; + + return '#' + hex(r) + hex(g) + hex(b); + }; + + return { + toHex : function(color) { + return color.replace(rgbRegExp, toHex); + }, + + parse : function(css) { + var styles = {}, matches, name, value, isEncoded, urlConverter = settings.url_converter, urlConverterScope = settings.url_converter_scope || this; + + function compress(prefix, suffix) { + var top, right, bottom, left; + + // IE 11 will produce a border-image: none when getting the style attribute from

    + // So lets asume it shouldn't be there + if (styles['border-image'] === 'none') { + delete styles['border-image']; + } + + // Get values and check it it needs compressing + top = styles[prefix + '-top' + suffix]; + if (!top) + return; + + right = styles[prefix + '-right' + suffix]; + if (top != right) + return; + + bottom = styles[prefix + '-bottom' + suffix]; + if (right != bottom) + return; + + left = styles[prefix + '-left' + suffix]; + if (bottom != left) + return; + + // Compress + styles[prefix + suffix] = left; + delete styles[prefix + '-top' + suffix]; + delete styles[prefix + '-right' + suffix]; + delete styles[prefix + '-bottom' + suffix]; + delete styles[prefix + '-left' + suffix]; + }; + + function canCompress(key) { + var value = styles[key], i; + + if (!value || value.indexOf(' ') < 0) + return; + + value = value.split(' '); + i = value.length; + while (i--) { + if (value[i] !== value[0]) + return false; + } + + styles[key] = value[0]; + + return true; + }; + + function compress2(target, a, b, c) { + if (!canCompress(a)) + return; + + if (!canCompress(b)) + return; + + if (!canCompress(c)) + return; + + // Compress + styles[target] = styles[a] + ' ' + styles[b] + ' ' + styles[c]; + delete styles[a]; + delete styles[b]; + delete styles[c]; + }; + + // Encodes the specified string by replacing all \" \' ; : with _ + function encode(str) { + isEncoded = true; + + return encodingLookup[str]; + }; + + // Decodes the specified string by replacing all _ with it's original value \" \' etc + // It will also decode the \" \' if keep_slashes is set to fale or omitted + function decode(str, keep_slashes) { + if (isEncoded) { + str = str.replace(/\uFEFF[0-9]/g, function(str) { + return encodingLookup[str]; + }); + } + + if (!keep_slashes) + str = str.replace(/\\([\'\";:])/g, "$1"); + + return str; + }; + + function processUrl(match, url, url2, url3, str, str2) { + str = str || str2; + + if (str) { + str = decode(str); + + // Force strings into single quote format + return "'" + str.replace(/\'/g, "\\'") + "'"; + } + + url = decode(url || url2 || url3); + + // Convert the URL to relative/absolute depending on config + if (urlConverter) + url = urlConverter.call(urlConverterScope, url, 'style'); + + // Output new URL format + return "url('" + url.replace(/\'/g, "\\'") + "')"; + }; + + if (css) { + // Encode \" \' % and ; and : inside strings so they don't interfere with the style parsing + css = css.replace(/\\[\"\';:\uFEFF]/g, encode).replace(/\"[^\"]+\"|\'[^\']+\'/g, function(str) { + return str.replace(/[;:]/g, encode); + }); + + // Parse styles + while (matches = styleRegExp.exec(css)) { + name = matches[1].replace(trimRightRegExp, '').toLowerCase(); + value = matches[2].replace(trimRightRegExp, ''); + + if (name && value.length > 0) { + // Opera will produce 700 instead of bold in their style values + if (name === 'font-weight' && value === '700') + value = 'bold'; + else if (name === 'color' || name === 'background-color') // Lowercase colors like RED + value = value.toLowerCase(); + + // Convert RGB colors to HEX + value = value.replace(rgbRegExp, toHex); + + // Convert URLs and force them into url('value') format + value = value.replace(urlOrStrRegExp, processUrl); + styles[name] = isEncoded ? decode(value, true) : value; + } + + styleRegExp.lastIndex = matches.index + matches[0].length; + } + + // Compress the styles to reduce it's size for example IE will expand styles + compress("border", ""); + compress("border", "-width"); + compress("border", "-color"); + compress("border", "-style"); + compress("padding", ""); + compress("margin", ""); + compress2('border', 'border-width', 'border-style', 'border-color'); + + // Remove pointless border, IE produces these + if (styles.border === 'medium none') + delete styles.border; + } + + return styles; + }, + + serialize : function(styles, element_name) { + var css = '', name, value; + + function serializeStyles(name) { + var styleList, i, l, value; + + styleList = schema.styles[name]; + if (styleList) { + for (i = 0, l = styleList.length; i < l; i++) { + name = styleList[i]; + value = styles[name]; + + if (value !== undef && value.length > 0) + css += (css.length > 0 ? ' ' : '') + name + ': ' + value + ';'; + } + } + }; + + // Serialize styles according to schema + if (element_name && schema && schema.styles) { + // Serialize global styles and element specific styles + serializeStyles('*'); + serializeStyles(element_name); + } else { + // Output the styles in the order they are inside the object + for (name in styles) { + value = styles[name]; + + if (value !== undef && value.length > 0) + css += (css.length > 0 ? ' ' : '') + name + ': ' + value + ';'; + } + } + + return css; + } + }; +}; + +(function(tinymce) { + var mapCache = {}, makeMap = tinymce.makeMap, each = tinymce.each; + + function split(str, delim) { + return str.split(delim || ','); + }; + + function unpack(lookup, data) { + var key, elements = {}; + + function replace(value) { + return value.replace(/[A-Z]+/g, function(key) { + return replace(lookup[key]); + }); + }; + + // Unpack lookup + for (key in lookup) { + if (lookup.hasOwnProperty(key)) + lookup[key] = replace(lookup[key]); + } + + // Unpack and parse data into object map + replace(data).replace(/#/g, '#text').replace(/(\w+)\[([^\]]+)\]\[([^\]]*)\]/g, function(str, name, attributes, children) { + attributes = split(attributes, '|'); + + elements[name] = { + attributes : makeMap(attributes), + attributesOrder : attributes, + children : makeMap(children, '|', {'#comment' : {}}) + } + }); + + return elements; + }; + + function getHTML5() { + var html5 = mapCache.html5; + + if (!html5) { + html5 = mapCache.html5 = unpack({ + A : 'id|accesskey|class|dir|draggable|item|hidden|itemprop|role|spellcheck|style|subject|title|onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup', + B : '#|a|abbr|area|audio|b|bdo|br|button|canvas|cite|code|command|datalist|del|dfn|em|embed|i|iframe|img|input|ins|kbd|keygen|label|link|map|mark|meta|' + + 'meter|noscript|object|output|progress|q|ruby|samp|script|select|small|span|strong|sub|sup|svg|textarea|time|var|video|wbr', + C : '#|a|abbr|area|address|article|aside|audio|b|bdo|blockquote|br|button|canvas|cite|code|command|datalist|del|details|dfn|dialog|div|dl|em|embed|fieldset|' + + 'figure|footer|form|h1|h2|h3|h4|h5|h6|header|hgroup|hr|i|iframe|img|input|ins|kbd|keygen|label|link|map|mark|menu|meta|meter|nav|noscript|ol|object|output|' + + 'p|pre|progress|q|ruby|samp|script|section|select|small|span|strong|style|sub|sup|svg|table|textarea|time|ul|var|video' + }, 'html[A|manifest][body|head]' + + 'head[A][base|command|link|meta|noscript|script|style|title]' + + 'title[A][#]' + + 'base[A|href|target][]' + + 'link[A|href|rel|media|type|sizes][]' + + 'meta[A|http-equiv|name|content|charset][]' + + 'style[A|type|media|scoped][#]' + + 'script[A|charset|type|src|defer|async][#]' + + 'noscript[A][C]' + + 'body[A][C]' + + 'section[A][C]' + + 'nav[A][C]' + + 'article[A][C]' + + 'aside[A][C]' + + 'h1[A][B]' + + 'h2[A][B]' + + 'h3[A][B]' + + 'h4[A][B]' + + 'h5[A][B]' + + 'h6[A][B]' + + 'hgroup[A][h1|h2|h3|h4|h5|h6]' + + 'header[A][C]' + + 'footer[A][C]' + + 'address[A][C]' + + 'p[A][B]' + + 'br[A][]' + + 'pre[A][B]' + + 'dialog[A][dd|dt]' + + 'blockquote[A|cite][C]' + + 'ol[A|start|reversed][li]' + + 'ul[A][li]' + + 'li[A|value][C]' + + 'dl[A][dd|dt]' + + 'dt[A][B]' + + 'dd[A][C]' + + 'a[A|href|target|ping|rel|media|type][B]' + + 'em[A][B]' + + 'strong[A][B]' + + 'small[A][B]' + + 'cite[A][B]' + + 'q[A|cite][B]' + + 'dfn[A][B]' + + 'abbr[A][B]' + + 'code[A][B]' + + 'var[A][B]' + + 'samp[A][B]' + + 'kbd[A][B]' + + 'sub[A][B]' + + 'sup[A][B]' + + 'i[A][B]' + + 'b[A][B]' + + 'mark[A][B]' + + 'progress[A|value|max][B]' + + 'meter[A|value|min|max|low|high|optimum][B]' + + 'time[A|datetime][B]' + + 'ruby[A][B|rt|rp]' + + 'rt[A][B]' + + 'rp[A][B]' + + 'bdo[A][B]' + + 'span[A][B]' + + 'ins[A|cite|datetime][B]' + + 'del[A|cite|datetime][B]' + + 'figure[A][C|legend|figcaption]' + + 'figcaption[A][C]' + + 'img[A|alt|src|height|width|usemap|ismap][]' + + 'iframe[A|name|src|height|width|sandbox|seamless][]' + + 'embed[A|src|height|width|type][]' + + 'object[A|data|type|height|width|usemap|name|form|classid][param]' + + 'param[A|name|value][]' + + 'details[A|open][C|legend]' + + 'command[A|type|label|icon|disabled|checked|radiogroup][]' + + 'menu[A|type|label][C|li]' + + 'legend[A][C|B]' + + 'div[A][C]' + + 'source[A|src|type|media][]' + + 'audio[A|src|autobuffer|autoplay|loop|controls][source]' + + 'video[A|src|autobuffer|autoplay|loop|controls|width|height|poster][source]' + + 'hr[A][]' + + 'form[A|accept-charset|action|autocomplete|enctype|method|name|novalidate|target][C]' + + 'fieldset[A|disabled|form|name][C|legend]' + + 'label[A|form|for][B]' + + 'input[A|type|accept|alt|autocomplete|autofocus|checked|disabled|form|formaction|formenctype|formmethod|formnovalidate|formtarget|height|list|max|maxlength|min|' + + 'multiple|pattern|placeholder|readonly|required|size|src|step|width|files|value|name][]' + + 'button[A|autofocus|disabled|form|formaction|formenctype|formmethod|formnovalidate|formtarget|name|value|type][B]' + + 'select[A|autofocus|disabled|form|multiple|name|size][option|optgroup]' + + 'datalist[A][B|option]' + + 'optgroup[A|disabled|label][option]' + + 'option[A|disabled|selected|label|value][]' + + 'textarea[A|autofocus|disabled|form|maxlength|name|placeholder|readonly|required|rows|cols|wrap][]' + + 'keygen[A|autofocus|challenge|disabled|form|keytype|name][]' + + 'output[A|for|form|name][B]' + + 'canvas[A|width|height][]' + + 'map[A|name][B|C]' + + 'area[A|shape|coords|href|alt|target|media|rel|ping|type][]' + + 'mathml[A][]' + + 'svg[A][]' + + 'table[A|border][caption|colgroup|thead|tfoot|tbody|tr]' + + 'caption[A][C]' + + 'colgroup[A|span][col]' + + 'col[A|span][]' + + 'thead[A][tr]' + + 'tfoot[A][tr]' + + 'tbody[A][tr]' + + 'tr[A][th|td]' + + 'th[A|headers|rowspan|colspan|scope][B]' + + 'td[A|headers|rowspan|colspan][C]' + + 'wbr[A][]' + ); + } + + return html5; + }; + + function getHTML4() { + var html4 = mapCache.html4; + + if (!html4) { + // This is the XHTML 1.0 transitional elements with it's attributes and children packed to reduce it's size + html4 = mapCache.html4 = unpack({ + Z : 'H|K|N|O|P', + Y : 'X|form|R|Q', + ZG : 'E|span|width|align|char|charoff|valign', + X : 'p|T|div|U|W|isindex|fieldset|table', + ZF : 'E|align|char|charoff|valign', + W : 'pre|hr|blockquote|address|center|noframes', + ZE : 'abbr|axis|headers|scope|rowspan|colspan|align|char|charoff|valign|nowrap|bgcolor|width|height', + ZD : '[E][S]', + U : 'ul|ol|dl|menu|dir', + ZC : 'p|Y|div|U|W|table|br|span|bdo|object|applet|img|map|K|N|Q', + T : 'h1|h2|h3|h4|h5|h6', + ZB : 'X|S|Q', + S : 'R|P', + ZA : 'a|G|J|M|O|P', + R : 'a|H|K|N|O', + Q : 'noscript|P', + P : 'ins|del|script', + O : 'input|select|textarea|label|button', + N : 'M|L', + M : 'em|strong|dfn|code|q|samp|kbd|var|cite|abbr|acronym', + L : 'sub|sup', + K : 'J|I', + J : 'tt|i|b|u|s|strike', + I : 'big|small|font|basefont', + H : 'G|F', + G : 'br|span|bdo', + F : 'object|applet|img|map|iframe', + E : 'A|B|C', + D : 'accesskey|tabindex|onfocus|onblur', + C : 'onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup', + B : 'lang|xml:lang|dir', + A : 'id|class|style|title' + }, 'script[id|charset|type|language|src|defer|xml:space][]' + + 'style[B|id|type|media|title|xml:space][]' + + 'object[E|declare|classid|codebase|data|type|codetype|archive|standby|width|height|usemap|name|tabindex|align|border|hspace|vspace][#|param|Y]' + + 'param[id|name|value|valuetype|type][]' + + 'p[E|align][#|S]' + + 'a[E|D|charset|type|name|href|hreflang|rel|rev|shape|coords|target][#|Z]' + + 'br[A|clear][]' + + 'span[E][#|S]' + + 'bdo[A|C|B][#|S]' + + 'applet[A|codebase|archive|code|object|alt|name|width|height|align|hspace|vspace][#|param|Y]' + + 'h1[E|align][#|S]' + + 'img[E|src|alt|name|longdesc|width|height|usemap|ismap|align|border|hspace|vspace][]' + + 'map[B|C|A|name][X|form|Q|area]' + + 'h2[E|align][#|S]' + + 'iframe[A|longdesc|name|src|frameborder|marginwidth|marginheight|scrolling|align|width|height][#|Y]' + + 'h3[E|align][#|S]' + + 'tt[E][#|S]' + + 'i[E][#|S]' + + 'b[E][#|S]' + + 'u[E][#|S]' + + 's[E][#|S]' + + 'strike[E][#|S]' + + 'big[E][#|S]' + + 'small[E][#|S]' + + 'font[A|B|size|color|face][#|S]' + + 'basefont[id|size|color|face][]' + + 'em[E][#|S]' + + 'strong[E][#|S]' + + 'dfn[E][#|S]' + + 'code[E][#|S]' + + 'q[E|cite][#|S]' + + 'samp[E][#|S]' + + 'kbd[E][#|S]' + + 'var[E][#|S]' + + 'cite[E][#|S]' + + 'abbr[E][#|S]' + + 'acronym[E][#|S]' + + 'sub[E][#|S]' + + 'sup[E][#|S]' + + 'input[E|D|type|name|value|checked|disabled|readonly|size|maxlength|src|alt|usemap|onselect|onchange|accept|align][]' + + 'select[E|name|size|multiple|disabled|tabindex|onfocus|onblur|onchange][optgroup|option]' + + 'optgroup[E|disabled|label][option]' + + 'option[E|selected|disabled|label|value][]' + + 'textarea[E|D|name|rows|cols|disabled|readonly|onselect|onchange][]' + + 'label[E|for|accesskey|onfocus|onblur][#|S]' + + 'button[E|D|name|value|type|disabled][#|p|T|div|U|W|table|G|object|applet|img|map|K|N|Q]' + + 'h4[E|align][#|S]' + + 'ins[E|cite|datetime][#|Y]' + + 'h5[E|align][#|S]' + + 'del[E|cite|datetime][#|Y]' + + 'h6[E|align][#|S]' + + 'div[E|align][#|Y]' + + 'ul[E|type|compact][li]' + + 'li[E|type|value][#|Y]' + + 'ol[E|type|compact|start][li]' + + 'dl[E|compact][dt|dd]' + + 'dt[E][#|S]' + + 'dd[E][#|Y]' + + 'menu[E|compact][li]' + + 'dir[E|compact][li]' + + 'pre[E|width|xml:space][#|ZA]' + + 'hr[E|align|noshade|size|width][]' + + 'blockquote[E|cite][#|Y]' + + 'address[E][#|S|p]' + + 'center[E][#|Y]' + + 'noframes[E][#|Y]' + + 'isindex[A|B|prompt][]' + + 'fieldset[E][#|legend|Y]' + + 'legend[E|accesskey|align][#|S]' + + 'table[E|summary|width|border|frame|rules|cellspacing|cellpadding|align|bgcolor][caption|col|colgroup|thead|tfoot|tbody|tr]' + + 'caption[E|align][#|S]' + + 'col[ZG][]' + + 'colgroup[ZG][col]' + + 'thead[ZF][tr]' + + 'tr[ZF|bgcolor][th|td]' + + 'th[E|ZE][#|Y]' + + 'form[E|action|method|name|enctype|onsubmit|onreset|accept|accept-charset|target][#|X|R|Q]' + + 'noscript[E][#|Y]' + + 'td[E|ZE][#|Y]' + + 'tfoot[ZF][tr]' + + 'tbody[ZF][tr]' + + 'area[E|D|shape|coords|href|nohref|alt|target][]' + + 'base[id|href|target][]' + + 'body[E|onload|onunload|background|bgcolor|text|link|vlink|alink][#|Y]' + ); + } + + return html4; + }; + + tinymce.html.Schema = function(settings) { + var self = this, elements = {}, children = {}, patternElements = [], validStyles, schemaItems; + var whiteSpaceElementsMap, selfClosingElementsMap, shortEndedElementsMap, boolAttrMap, blockElementsMap, nonEmptyElementsMap, customElementsMap = {}; + + // Creates an lookup table map object for the specified option or the default value + function createLookupTable(option, default_value, extend) { + var value = settings[option]; + + if (!value) { + // Get cached default map or make it if needed + value = mapCache[option]; + + if (!value) { + value = makeMap(default_value, ' ', makeMap(default_value.toUpperCase(), ' ')); + value = tinymce.extend(value, extend); + + mapCache[option] = value; + } + } else { + // Create custom map + value = makeMap(value, ',', makeMap(value.toUpperCase(), ' ')); + } + + return value; + }; + + settings = settings || {}; + schemaItems = settings.schema == "html5" ? getHTML5() : getHTML4(); + + // Allow all elements and attributes if verify_html is set to false + if (settings.verify_html === false) + settings.valid_elements = '*[*]'; + + // Build styles list + if (settings.valid_styles) { + validStyles = {}; + + // Convert styles into a rule list + each(settings.valid_styles, function(value, key) { + validStyles[key] = tinymce.explode(value); + }); + } + + // Setup map objects + whiteSpaceElementsMap = createLookupTable('whitespace_elements', 'pre script noscript style textarea'); + selfClosingElementsMap = createLookupTable('self_closing_elements', 'colgroup dd dt li option p td tfoot th thead tr'); + shortEndedElementsMap = createLookupTable('short_ended_elements', 'area base basefont br col frame hr img input isindex link meta param embed source wbr'); + boolAttrMap = createLookupTable('boolean_attributes', 'checked compact declare defer disabled ismap multiple nohref noresize noshade nowrap readonly selected autoplay loop controls'); + nonEmptyElementsMap = createLookupTable('non_empty_elements', 'td th iframe video audio object script', shortEndedElementsMap); + textBlockElementsMap = createLookupTable('text_block_elements', 'h1 h2 h3 h4 h5 h6 p div address pre form ' + + 'blockquote center dir fieldset header footer article section hgroup aside nav figure'); + blockElementsMap = createLookupTable('block_elements', 'hr table tbody thead tfoot ' + + 'th tr td li ol ul caption dl dt dd noscript menu isindex samp option datalist select optgroup', textBlockElementsMap); + + // Converts a wildcard expression string to a regexp for example *a will become /.*a/. + function patternToRegExp(str) { + return new RegExp('^' + str.replace(/([?+*])/g, '.$1') + '$'); + }; + + // Parses the specified valid_elements string and adds to the current rules + // This function is a bit hard to read since it's heavily optimized for speed + function addValidElements(valid_elements) { + var ei, el, ai, al, yl, matches, element, attr, attrData, elementName, attrName, attrType, attributes, attributesOrder, + prefix, outputName, globalAttributes, globalAttributesOrder, transElement, key, childKey, value, + elementRuleRegExp = /^([#+\-])?([^\[\/]+)(?:\/([^\[]+))?(?:\[([^\]]+)\])?$/, + attrRuleRegExp = /^([!\-])?(\w+::\w+|[^=:<]+)?(?:([=:<])(.*))?$/, + hasPatternsRegExp = /[*?+]/; + + if (valid_elements) { + // Split valid elements into an array with rules + valid_elements = split(valid_elements); + + if (elements['@']) { + globalAttributes = elements['@'].attributes; + globalAttributesOrder = elements['@'].attributesOrder; + } + + // Loop all rules + for (ei = 0, el = valid_elements.length; ei < el; ei++) { + // Parse element rule + matches = elementRuleRegExp.exec(valid_elements[ei]); + if (matches) { + // Setup local names for matches + prefix = matches[1]; + elementName = matches[2]; + outputName = matches[3]; + attrData = matches[4]; + + // Create new attributes and attributesOrder + attributes = {}; + attributesOrder = []; + + // Create the new element + element = { + attributes : attributes, + attributesOrder : attributesOrder + }; + + // Padd empty elements prefix + if (prefix === '#') + element.paddEmpty = true; + + // Remove empty elements prefix + if (prefix === '-') + element.removeEmpty = true; + + // Copy attributes from global rule into current rule + if (globalAttributes) { + for (key in globalAttributes) + attributes[key] = globalAttributes[key]; + + attributesOrder.push.apply(attributesOrder, globalAttributesOrder); + } + + // Attributes defined + if (attrData) { + attrData = split(attrData, '|'); + for (ai = 0, al = attrData.length; ai < al; ai++) { + matches = attrRuleRegExp.exec(attrData[ai]); + if (matches) { + attr = {}; + attrType = matches[1]; + attrName = matches[2].replace(/::/g, ':'); + prefix = matches[3]; + value = matches[4]; + + // Required + if (attrType === '!') { + element.attributesRequired = element.attributesRequired || []; + element.attributesRequired.push(attrName); + attr.required = true; + } + + // Denied from global + if (attrType === '-') { + delete attributes[attrName]; + attributesOrder.splice(tinymce.inArray(attributesOrder, attrName), 1); + continue; + } + + // Default value + if (prefix) { + // Default value + if (prefix === '=') { + element.attributesDefault = element.attributesDefault || []; + element.attributesDefault.push({name: attrName, value: value}); + attr.defaultValue = value; + } + + // Forced value + if (prefix === ':') { + element.attributesForced = element.attributesForced || []; + element.attributesForced.push({name: attrName, value: value}); + attr.forcedValue = value; + } + + // Required values + if (prefix === '<') + attr.validValues = makeMap(value, '?'); + } + + // Check for attribute patterns + if (hasPatternsRegExp.test(attrName)) { + element.attributePatterns = element.attributePatterns || []; + attr.pattern = patternToRegExp(attrName); + element.attributePatterns.push(attr); + } else { + // Add attribute to order list if it doesn't already exist + if (!attributes[attrName]) + attributesOrder.push(attrName); + + attributes[attrName] = attr; + } + } + } + } + + // Global rule, store away these for later usage + if (!globalAttributes && elementName == '@') { + globalAttributes = attributes; + globalAttributesOrder = attributesOrder; + } + + // Handle substitute elements such as b/strong + if (outputName) { + element.outputName = elementName; + elements[outputName] = element; + } + + // Add pattern or exact element + if (hasPatternsRegExp.test(elementName)) { + element.pattern = patternToRegExp(elementName); + patternElements.push(element); + } else + elements[elementName] = element; + } + } + } + }; + + function setValidElements(valid_elements) { + elements = {}; + patternElements = []; + + addValidElements(valid_elements); + + each(schemaItems, function(element, name) { + children[name] = element.children; + }); + }; + + // Adds custom non HTML elements to the schema + function addCustomElements(custom_elements) { + var customElementRegExp = /^(~)?(.+)$/; + + if (custom_elements) { + each(split(custom_elements), function(rule) { + var matches = customElementRegExp.exec(rule), + inline = matches[1] === '~', + cloneName = inline ? 'span' : 'div', + name = matches[2]; + + children[name] = children[cloneName]; + customElementsMap[name] = cloneName; + + // If it's not marked as inline then add it to valid block elements + if (!inline) { + blockElementsMap[name.toUpperCase()] = {}; + blockElementsMap[name] = {}; + } + + // Add elements clone if needed + if (!elements[name]) { + elements[name] = elements[cloneName]; + } + + // Add custom elements at span/div positions + each(children, function(element, child) { + if (element[cloneName]) + element[name] = element[cloneName]; + }); + }); + } + }; + + // Adds valid children to the schema object + function addValidChildren(valid_children) { + var childRuleRegExp = /^([+\-]?)(\w+)\[([^\]]+)\]$/; + + if (valid_children) { + each(split(valid_children), function(rule) { + var matches = childRuleRegExp.exec(rule), parent, prefix; + + if (matches) { + prefix = matches[1]; + + // Add/remove items from default + if (prefix) + parent = children[matches[2]]; + else + parent = children[matches[2]] = {'#comment' : {}}; + + parent = children[matches[2]]; + + each(split(matches[3], '|'), function(child) { + if (prefix === '-') + delete parent[child]; + else + parent[child] = {}; + }); + } + }); + } + }; + + function getElementRule(name) { + var element = elements[name], i; + + // Exact match found + if (element) + return element; + + // No exact match then try the patterns + i = patternElements.length; + while (i--) { + element = patternElements[i]; + + if (element.pattern.test(name)) + return element; + } + }; + + if (!settings.valid_elements) { + // No valid elements defined then clone the elements from the schema spec + each(schemaItems, function(element, name) { + elements[name] = { + attributes : element.attributes, + attributesOrder : element.attributesOrder + }; + + children[name] = element.children; + }); + + // Switch these on HTML4 + if (settings.schema != "html5") { + each(split('strong/b,em/i'), function(item) { + item = split(item, '/'); + elements[item[1]].outputName = item[0]; + }); + } + + // Add default alt attribute for images + elements.img.attributesDefault = [{name: 'alt', value: ''}]; + + // Remove these if they are empty by default + each(split('ol,ul,sub,sup,blockquote,span,font,a,table,tbody,tr,strong,em,b,i'), function(name) { + if (elements[name]) { + elements[name].removeEmpty = true; + } + }); + + // Padd these by default + each(split('p,h1,h2,h3,h4,h5,h6,th,td,pre,div,address,caption'), function(name) { + elements[name].paddEmpty = true; + }); + } else + setValidElements(settings.valid_elements); + + addCustomElements(settings.custom_elements); + addValidChildren(settings.valid_children); + addValidElements(settings.extended_valid_elements); + + // Todo: Remove this when we fix list handling to be valid + addValidChildren('+ol[ul|ol],+ul[ul|ol]'); + + // Delete invalid elements + if (settings.invalid_elements) { + tinymce.each(tinymce.explode(settings.invalid_elements), function(item) { + if (elements[item]) + delete elements[item]; + }); + } + + // If the user didn't allow span only allow internal spans + if (!getElementRule('span')) + addValidElements('span[!data-mce-type|*]'); + + self.children = children; + + self.styles = validStyles; + + self.getBoolAttrs = function() { + return boolAttrMap; + }; + + self.getBlockElements = function() { + return blockElementsMap; + }; + + self.getTextBlockElements = function() { + return textBlockElementsMap; + }; + + self.getShortEndedElements = function() { + return shortEndedElementsMap; + }; + + self.getSelfClosingElements = function() { + return selfClosingElementsMap; + }; + + self.getNonEmptyElements = function() { + return nonEmptyElementsMap; + }; + + self.getWhiteSpaceElements = function() { + return whiteSpaceElementsMap; + }; + + self.isValidChild = function(name, child) { + var parent = children[name]; + + return !!(parent && parent[child]); + }; + + self.isValid = function(name, attr) { + var attrPatterns, i, rule = getElementRule(name); + + // Check if it's a valid element + if (rule) { + if (attr) { + // Check if attribute name exists + if (rule.attributes[attr]) { + return true; + } + + // Check if attribute matches a regexp pattern + attrPatterns = rule.attributePatterns; + if (attrPatterns) { + i = attrPatterns.length; + while (i--) { + if (attrPatterns[i].pattern.test(name)) { + return true; + } + } + } + } else { + return true; + } + } + + // No match + return false; + }; + + self.getElementRule = getElementRule; + + self.getCustomElements = function() { + return customElementsMap; + }; + + self.addValidElements = addValidElements; + + self.setValidElements = setValidElements; + + self.addCustomElements = addCustomElements; + + self.addValidChildren = addValidChildren; + + self.elements = elements; + }; +})(tinymce); + +(function(tinymce) { + tinymce.html.SaxParser = function(settings, schema) { + var self = this, noop = function() {}; + + settings = settings || {}; + self.schema = schema = schema || new tinymce.html.Schema(); + + if (settings.fix_self_closing !== false) + settings.fix_self_closing = true; + + // Add handler functions from settings and setup default handlers + tinymce.each('comment cdata text start end pi doctype'.split(' '), function(name) { + if (name) + self[name] = settings[name] || noop; + }); + + self.parse = function(html) { + var self = this, matches, index = 0, value, endRegExp, stack = [], attrList, i, text, name, isInternalElement, removeInternalElements, + shortEndedElements, fillAttrsMap, isShortEnded, validate, elementRule, isValidElement, attr, attribsValue, invalidPrefixRegExp, + validAttributesMap, validAttributePatterns, attributesRequired, attributesDefault, attributesForced, selfClosing, + tokenRegExp, attrRegExp, specialElements, attrValue, idCount = 0, decode = tinymce.html.Entities.decode, fixSelfClosing, isIE; + + function processEndTag(name) { + var pos, i; + + // Find position of parent of the same type + pos = stack.length; + while (pos--) { + if (stack[pos].name === name) + break; + } + + // Found parent + if (pos >= 0) { + // Close all the open elements + for (i = stack.length - 1; i >= pos; i--) { + name = stack[i]; + + if (name.valid) + self.end(name.name); + } + + // Remove the open elements from the stack + stack.length = pos; + } + }; + + function parseAttribute(match, name, value, val2, val3) { + var attrRule, i; + + name = name.toLowerCase(); + value = name in fillAttrsMap ? name : decode(value || val2 || val3 || ''); // Handle boolean attribute than value attribute + + // Validate name and value + if (validate && !isInternalElement && name.indexOf('data-') !== 0) { + attrRule = validAttributesMap[name]; + + // Find rule by pattern matching + if (!attrRule && validAttributePatterns) { + i = validAttributePatterns.length; + while (i--) { + attrRule = validAttributePatterns[i]; + if (attrRule.pattern.test(name)) + break; + } + + // No rule matched + if (i === -1) + attrRule = null; + } + + // No attribute rule found + if (!attrRule) + return; + + // Validate value + if (attrRule.validValues && !(value in attrRule.validValues)) + return; + } + + // Add attribute to list and map + attrList.map[name] = value; + attrList.push({ + name: name, + value: value + }); + }; + + // Precompile RegExps and map objects + tokenRegExp = new RegExp('<(?:' + + '(?:!--([\\w\\W]*?)-->)|' + // Comment + '(?:!\\[CDATA\\[([\\w\\W]*?)\\]\\]>)|' + // CDATA + '(?:!DOCTYPE([\\w\\W]*?)>)|' + // DOCTYPE + '(?:\\?([^\\s\\/<>]+) ?([\\w\\W]*?)[?/]>)|' + // PI + '(?:\\/([^>]+)>)|' + // End element + '(?:([A-Za-z0-9\\-\\:\\.]+)((?:\\s+[^"\'>]+(?:(?:"[^"]*")|(?:\'[^\']*\')|[^>]*))*|\\/|\\s+)>)' + // Start element + ')', 'g'); + + attrRegExp = /([\w:\-]+)(?:\s*=\s*(?:(?:\"((?:[^\"])*)\")|(?:\'((?:[^\'])*)\')|([^>\s]+)))?/g; + specialElements = { + 'script' : /<\/script[^>]*>/gi, + 'style' : /<\/style[^>]*>/gi, + 'noscript' : /<\/noscript[^>]*>/gi + }; + + // Setup lookup tables for empty elements and boolean attributes + shortEndedElements = schema.getShortEndedElements(); + selfClosing = settings.self_closing_elements || schema.getSelfClosingElements(); + fillAttrsMap = schema.getBoolAttrs(); + validate = settings.validate; + removeInternalElements = settings.remove_internals; + fixSelfClosing = settings.fix_self_closing; + isIE = tinymce.isIE; + invalidPrefixRegExp = /^:/; + + while (matches = tokenRegExp.exec(html)) { + // Text + if (index < matches.index) + self.text(decode(html.substr(index, matches.index - index))); + + if (value = matches[6]) { // End element + value = value.toLowerCase(); + + // IE will add a ":" in front of elements it doesn't understand like custom elements or HTML5 elements + if (isIE && invalidPrefixRegExp.test(value)) + value = value.substr(1); + + processEndTag(value); + } else if (value = matches[7]) { // Start element + value = value.toLowerCase(); + + // IE will add a ":" in front of elements it doesn't understand like custom elements or HTML5 elements + if (isIE && invalidPrefixRegExp.test(value)) + value = value.substr(1); + + isShortEnded = value in shortEndedElements; + + // Is self closing tag for example an
  • after an open
  • + if (fixSelfClosing && selfClosing[value] && stack.length > 0 && stack[stack.length - 1].name === value) + processEndTag(value); + + // Validate element + if (!validate || (elementRule = schema.getElementRule(value))) { + isValidElement = true; + + // Grab attributes map and patters when validation is enabled + if (validate) { + validAttributesMap = elementRule.attributes; + validAttributePatterns = elementRule.attributePatterns; + } + + // Parse attributes + if (attribsValue = matches[8]) { + isInternalElement = attribsValue.indexOf('data-mce-type') !== -1; // Check if the element is an internal element + + // If the element has internal attributes then remove it if we are told to do so + if (isInternalElement && removeInternalElements) + isValidElement = false; + + attrList = []; + attrList.map = {}; + + attribsValue.replace(attrRegExp, parseAttribute); + } else { + attrList = []; + attrList.map = {}; + } + + // Process attributes if validation is enabled + if (validate && !isInternalElement) { + attributesRequired = elementRule.attributesRequired; + attributesDefault = elementRule.attributesDefault; + attributesForced = elementRule.attributesForced; + + // Handle forced attributes + if (attributesForced) { + i = attributesForced.length; + while (i--) { + attr = attributesForced[i]; + name = attr.name; + attrValue = attr.value; + + if (attrValue === '{$uid}') + attrValue = 'mce_' + idCount++; + + attrList.map[name] = attrValue; + attrList.push({name: name, value: attrValue}); + } + } + + // Handle default attributes + if (attributesDefault) { + i = attributesDefault.length; + while (i--) { + attr = attributesDefault[i]; + name = attr.name; + + if (!(name in attrList.map)) { + attrValue = attr.value; + + if (attrValue === '{$uid}') + attrValue = 'mce_' + idCount++; + + attrList.map[name] = attrValue; + attrList.push({name: name, value: attrValue}); + } + } + } + + // Handle required attributes + if (attributesRequired) { + i = attributesRequired.length; + while (i--) { + if (attributesRequired[i] in attrList.map) + break; + } + + // None of the required attributes where found + if (i === -1) + isValidElement = false; + } + + // Invalidate element if it's marked as bogus + if (attrList.map['data-mce-bogus']) + isValidElement = false; + } + + if (isValidElement) + self.start(value, attrList, isShortEnded); + } else + isValidElement = false; + + // Treat script, noscript and style a bit different since they may include code that looks like elements + if (endRegExp = specialElements[value]) { + endRegExp.lastIndex = index = matches.index + matches[0].length; + + if (matches = endRegExp.exec(html)) { + if (isValidElement) + text = html.substr(index, matches.index - index); + + index = matches.index + matches[0].length; + } else { + text = html.substr(index); + index = html.length; + } + + if (isValidElement && text.length > 0) + self.text(text, true); + + if (isValidElement) + self.end(value); + + tokenRegExp.lastIndex = index; + continue; + } + + // Push value on to stack + if (!isShortEnded) { + if (!attribsValue || attribsValue.indexOf('/') != attribsValue.length - 1) + stack.push({name: value, valid: isValidElement}); + else if (isValidElement) + self.end(value); + } + } else if (value = matches[1]) { // Comment + self.comment(value); + } else if (value = matches[2]) { // CDATA + self.cdata(value); + } else if (value = matches[3]) { // DOCTYPE + self.doctype(value); + } else if (value = matches[4]) { // PI + self.pi(value, matches[5]); + } + + index = matches.index + matches[0].length; + } + + // Text + if (index < html.length) + self.text(decode(html.substr(index))); + + // Close any open elements + for (i = stack.length - 1; i >= 0; i--) { + value = stack[i]; + + if (value.valid) + self.end(value.name); + } + }; + } +})(tinymce); + +(function(tinymce) { + var whiteSpaceRegExp = /^[ \t\r\n]*$/, typeLookup = { + '#text' : 3, + '#comment' : 8, + '#cdata' : 4, + '#pi' : 7, + '#doctype' : 10, + '#document-fragment' : 11 + }; + + // Walks the tree left/right + function walk(node, root_node, prev) { + var sibling, parent, startName = prev ? 'lastChild' : 'firstChild', siblingName = prev ? 'prev' : 'next'; + + // Walk into nodes if it has a start + if (node[startName]) + return node[startName]; + + // Return the sibling if it has one + if (node !== root_node) { + sibling = node[siblingName]; + + if (sibling) + return sibling; + + // Walk up the parents to look for siblings + for (parent = node.parent; parent && parent !== root_node; parent = parent.parent) { + sibling = parent[siblingName]; + + if (sibling) + return sibling; + } + } + }; + + function Node(name, type) { + this.name = name; + this.type = type; + + if (type === 1) { + this.attributes = []; + this.attributes.map = {}; + } + } + + tinymce.extend(Node.prototype, { + replace : function(node) { + var self = this; + + if (node.parent) + node.remove(); + + self.insert(node, self); + self.remove(); + + return self; + }, + + attr : function(name, value) { + var self = this, attrs, i, undef; + + if (typeof name !== "string") { + for (i in name) + self.attr(i, name[i]); + + return self; + } + + if (attrs = self.attributes) { + if (value !== undef) { + // Remove attribute + if (value === null) { + if (name in attrs.map) { + delete attrs.map[name]; + + i = attrs.length; + while (i--) { + if (attrs[i].name === name) { + attrs = attrs.splice(i, 1); + return self; + } + } + } + + return self; + } + + // Set attribute + if (name in attrs.map) { + // Set attribute + i = attrs.length; + while (i--) { + if (attrs[i].name === name) { + attrs[i].value = value; + break; + } + } + } else + attrs.push({name: name, value: value}); + + attrs.map[name] = value; + + return self; + } else { + return attrs.map[name]; + } + } + }, + + clone : function() { + var self = this, clone = new Node(self.name, self.type), i, l, selfAttrs, selfAttr, cloneAttrs; + + // Clone element attributes + if (selfAttrs = self.attributes) { + cloneAttrs = []; + cloneAttrs.map = {}; + + for (i = 0, l = selfAttrs.length; i < l; i++) { + selfAttr = selfAttrs[i]; + + // Clone everything except id + if (selfAttr.name !== 'id') { + cloneAttrs[cloneAttrs.length] = {name: selfAttr.name, value: selfAttr.value}; + cloneAttrs.map[selfAttr.name] = selfAttr.value; + } + } + + clone.attributes = cloneAttrs; + } + + clone.value = self.value; + clone.shortEnded = self.shortEnded; + + return clone; + }, + + wrap : function(wrapper) { + var self = this; + + self.parent.insert(wrapper, self); + wrapper.append(self); + + return self; + }, + + unwrap : function() { + var self = this, node, next; + + for (node = self.firstChild; node; ) { + next = node.next; + self.insert(node, self, true); + node = next; + } + + self.remove(); + }, + + remove : function() { + var self = this, parent = self.parent, next = self.next, prev = self.prev; + + if (parent) { + if (parent.firstChild === self) { + parent.firstChild = next; + + if (next) + next.prev = null; + } else { + prev.next = next; + } + + if (parent.lastChild === self) { + parent.lastChild = prev; + + if (prev) + prev.next = null; + } else { + next.prev = prev; + } + + self.parent = self.next = self.prev = null; + } + + return self; + }, + + append : function(node) { + var self = this, last; + + if (node.parent) + node.remove(); + + last = self.lastChild; + if (last) { + last.next = node; + node.prev = last; + self.lastChild = node; + } else + self.lastChild = self.firstChild = node; + + node.parent = self; + + return node; + }, + + insert : function(node, ref_node, before) { + var parent; + + if (node.parent) + node.remove(); + + parent = ref_node.parent || this; + + if (before) { + if (ref_node === parent.firstChild) + parent.firstChild = node; + else + ref_node.prev.next = node; + + node.prev = ref_node.prev; + node.next = ref_node; + ref_node.prev = node; + } else { + if (ref_node === parent.lastChild) + parent.lastChild = node; + else + ref_node.next.prev = node; + + node.next = ref_node.next; + node.prev = ref_node; + ref_node.next = node; + } + + node.parent = parent; + + return node; + }, + + getAll : function(name) { + var self = this, node, collection = []; + + for (node = self.firstChild; node; node = walk(node, self)) { + if (node.name === name) + collection.push(node); + } + + return collection; + }, + + empty : function() { + var self = this, nodes, i, node; + + // Remove all children + if (self.firstChild) { + nodes = []; + + // Collect the children + for (node = self.firstChild; node; node = walk(node, self)) + nodes.push(node); + + // Remove the children + i = nodes.length; + while (i--) { + node = nodes[i]; + node.parent = node.firstChild = node.lastChild = node.next = node.prev = null; + } + } + + self.firstChild = self.lastChild = null; + + return self; + }, + + isEmpty : function(elements) { + var self = this, node = self.firstChild, i, name; + + if (node) { + do { + if (node.type === 1) { + // Ignore bogus elements + if (node.attributes.map['data-mce-bogus']) + continue; + + // Keep empty elements like + if (elements[node.name]) + return false; + + // Keep elements with data attributes or name attribute like + i = node.attributes.length; + while (i--) { + name = node.attributes[i].name; + if (name === "name" || name.indexOf('data-mce-') === 0) + return false; + } + } + + // Keep comments + if (node.type === 8) + return false; + + // Keep non whitespace text nodes + if ((node.type === 3 && !whiteSpaceRegExp.test(node.value))) + return false; + } while (node = walk(node, self)); + } + + return true; + }, + + walk : function(prev) { + return walk(this, null, prev); + } + }); + + tinymce.extend(Node, { + create : function(name, attrs) { + var node, attrName; + + // Create node + node = new Node(name, typeLookup[name] || 1); + + // Add attributes if needed + if (attrs) { + for (attrName in attrs) + node.attr(attrName, attrs[attrName]); + } + + return node; + } + }); + + tinymce.html.Node = Node; +})(tinymce); + +(function(tinymce) { + var Node = tinymce.html.Node; + + tinymce.html.DomParser = function(settings, schema) { + var self = this, nodeFilters = {}, attributeFilters = [], matchedNodes = {}, matchedAttributes = {}; + + settings = settings || {}; + settings.validate = "validate" in settings ? settings.validate : true; + settings.root_name = settings.root_name || 'body'; + self.schema = schema = schema || new tinymce.html.Schema(); + + function fixInvalidChildren(nodes) { + var ni, node, parent, parents, newParent, currentNode, tempNode, childNode, i, + childClone, nonEmptyElements, nonSplitableElements, textBlockElements, sibling, nextNode; + + nonSplitableElements = tinymce.makeMap('tr,td,th,tbody,thead,tfoot,table'); + nonEmptyElements = schema.getNonEmptyElements(); + textBlockElements = schema.getTextBlockElements(); + + for (ni = 0; ni < nodes.length; ni++) { + node = nodes[ni]; + + // Already removed or fixed + if (!node.parent || node.fixed) + continue; + + // If the invalid element is a text block and the text block is within a parent LI element + // Then unwrap the first text block and convert other sibling text blocks to LI elements similar to Word/Open Office + if (textBlockElements[node.name] && node.parent.name == 'li') { + // Move sibling text blocks after LI element + sibling = node.next; + while (sibling) { + if (textBlockElements[sibling.name]) { + sibling.name = 'li'; + sibling.fixed = true; + node.parent.insert(sibling, node.parent); + } else { + break; + } + + sibling = sibling.next; + } + + // Unwrap current text block + node.unwrap(node); + continue; + } + + // Get list of all parent nodes until we find a valid parent to stick the child into + parents = [node]; + for (parent = node.parent; parent && !schema.isValidChild(parent.name, node.name) && !nonSplitableElements[parent.name]; parent = parent.parent) + parents.push(parent); + + // Found a suitable parent + if (parent && parents.length > 1) { + // Reverse the array since it makes looping easier + parents.reverse(); + + // Clone the related parent and insert that after the moved node + newParent = currentNode = self.filterNode(parents[0].clone()); + + // Start cloning and moving children on the left side of the target node + for (i = 0; i < parents.length - 1; i++) { + if (schema.isValidChild(currentNode.name, parents[i].name)) { + tempNode = self.filterNode(parents[i].clone()); + currentNode.append(tempNode); + } else + tempNode = currentNode; + + for (childNode = parents[i].firstChild; childNode && childNode != parents[i + 1]; ) { + nextNode = childNode.next; + tempNode.append(childNode); + childNode = nextNode; + } + + currentNode = tempNode; + } + + if (!newParent.isEmpty(nonEmptyElements)) { + parent.insert(newParent, parents[0], true); + parent.insert(node, newParent); + } else { + parent.insert(node, parents[0], true); + } + + // Check if the element is empty by looking through it's contents and special treatment for


    + parent = parents[0]; + if (parent.isEmpty(nonEmptyElements) || parent.firstChild === parent.lastChild && parent.firstChild.name === 'br') { + parent.empty().remove(); + } + } else if (node.parent) { + // If it's an LI try to find a UL/OL for it or wrap it + if (node.name === 'li') { + sibling = node.prev; + if (sibling && (sibling.name === 'ul' || sibling.name === 'ul')) { + sibling.append(node); + continue; + } + + sibling = node.next; + if (sibling && (sibling.name === 'ul' || sibling.name === 'ul')) { + sibling.insert(node, sibling.firstChild, true); + continue; + } + + node.wrap(self.filterNode(new Node('ul', 1))); + continue; + } + + // Try wrapping the element in a DIV + if (schema.isValidChild(node.parent.name, 'div') && schema.isValidChild('div', node.name)) { + node.wrap(self.filterNode(new Node('div', 1))); + } else { + // We failed wrapping it, then remove or unwrap it + if (node.name === 'style' || node.name === 'script') + node.empty().remove(); + else + node.unwrap(); + } + } + } + }; + + self.filterNode = function(node) { + var i, name, list; + + // Run element filters + if (name in nodeFilters) { + list = matchedNodes[name]; + + if (list) + list.push(node); + else + matchedNodes[name] = [node]; + } + + // Run attribute filters + i = attributeFilters.length; + while (i--) { + name = attributeFilters[i].name; + + if (name in node.attributes.map) { + list = matchedAttributes[name]; + + if (list) + list.push(node); + else + matchedAttributes[name] = [node]; + } + } + + return node; + }; + + self.addNodeFilter = function(name, callback) { + tinymce.each(tinymce.explode(name), function(name) { + var list = nodeFilters[name]; + + if (!list) + nodeFilters[name] = list = []; + + list.push(callback); + }); + }; + + self.addAttributeFilter = function(name, callback) { + tinymce.each(tinymce.explode(name), function(name) { + var i; + + for (i = 0; i < attributeFilters.length; i++) { + if (attributeFilters[i].name === name) { + attributeFilters[i].callbacks.push(callback); + return; + } + } + + attributeFilters.push({name: name, callbacks: [callback]}); + }); + }; + + self.parse = function(html, args) { + var parser, rootNode, node, nodes, i, l, fi, fl, list, name, validate, + blockElements, startWhiteSpaceRegExp, invalidChildren = [], isInWhiteSpacePreservedElement, + endWhiteSpaceRegExp, allWhiteSpaceRegExp, isAllWhiteSpaceRegExp, whiteSpaceElements, children, nonEmptyElements, rootBlockName; + + args = args || {}; + matchedNodes = {}; + matchedAttributes = {}; + blockElements = tinymce.extend(tinymce.makeMap('script,style,head,html,body,title,meta,param'), schema.getBlockElements()); + nonEmptyElements = schema.getNonEmptyElements(); + children = schema.children; + validate = settings.validate; + rootBlockName = "forced_root_block" in args ? args.forced_root_block : settings.forced_root_block; + + whiteSpaceElements = schema.getWhiteSpaceElements(); + startWhiteSpaceRegExp = /^[ \t\r\n]+/; + endWhiteSpaceRegExp = /[ \t\r\n]+$/; + allWhiteSpaceRegExp = /[ \t\r\n]+/g; + isAllWhiteSpaceRegExp = /^[ \t\r\n]+$/; + + function addRootBlocks() { + var node = rootNode.firstChild, next, rootBlockNode; + + while (node) { + next = node.next; + + if (node.type == 3 || (node.type == 1 && node.name !== 'p' && !blockElements[node.name] && !node.attr('data-mce-type'))) { + if (!rootBlockNode) { + // Create a new root block element + rootBlockNode = createNode(rootBlockName, 1); + rootNode.insert(rootBlockNode, node); + rootBlockNode.append(node); + } else + rootBlockNode.append(node); + } else { + rootBlockNode = null; + } + + node = next; + }; + }; + + function createNode(name, type) { + var node = new Node(name, type), list; + + if (name in nodeFilters) { + list = matchedNodes[name]; + + if (list) + list.push(node); + else + matchedNodes[name] = [node]; + } + + return node; + }; + + function removeWhitespaceBefore(node) { + var textNode, textVal, sibling; + + for (textNode = node.prev; textNode && textNode.type === 3; ) { + textVal = textNode.value.replace(endWhiteSpaceRegExp, ''); + + if (textVal.length > 0) { + textNode.value = textVal; + textNode = textNode.prev; + } else { + sibling = textNode.prev; + textNode.remove(); + textNode = sibling; + } + } + }; + + function cloneAndExcludeBlocks(input) { + var name, output = {}; + + for (name in input) { + if (name !== 'li' && name != 'p') { + output[name] = input[name]; + } + } + + return output; + }; + + parser = new tinymce.html.SaxParser({ + validate : validate, + + // Exclude P and LI from DOM parsing since it's treated better by the DOM parser + self_closing_elements: cloneAndExcludeBlocks(schema.getSelfClosingElements()), + + cdata: function(text) { + node.append(createNode('#cdata', 4)).value = text; + }, + + text: function(text, raw) { + var textNode; + + // Trim all redundant whitespace on non white space elements + if (!isInWhiteSpacePreservedElement) { + text = text.replace(allWhiteSpaceRegExp, ' '); + + if (node.lastChild && blockElements[node.lastChild.name]) + text = text.replace(startWhiteSpaceRegExp, ''); + } + + // Do we need to create the node + if (text.length !== 0) { + textNode = createNode('#text', 3); + textNode.raw = !!raw; + node.append(textNode).value = text; + } + }, + + comment: function(text) { + node.append(createNode('#comment', 8)).value = text; + }, + + pi: function(name, text) { + node.append(createNode(name, 7)).value = text; + removeWhitespaceBefore(node); + }, + + doctype: function(text) { + var newNode; + + newNode = node.append(createNode('#doctype', 10)); + newNode.value = text; + removeWhitespaceBefore(node); + }, + + start: function(name, attrs, empty) { + var newNode, attrFiltersLen, elementRule, textNode, attrName, text, sibling, parent; + + elementRule = validate ? schema.getElementRule(name) : {}; + if (elementRule) { + newNode = createNode(elementRule.outputName || name, 1); + newNode.attributes = attrs; + newNode.shortEnded = empty; + + node.append(newNode); + + // Check if node is valid child of the parent node is the child is + // unknown we don't collect it since it's probably a custom element + parent = children[node.name]; + if (parent && children[newNode.name] && !parent[newNode.name]) + invalidChildren.push(newNode); + + attrFiltersLen = attributeFilters.length; + while (attrFiltersLen--) { + attrName = attributeFilters[attrFiltersLen].name; + + if (attrName in attrs.map) { + list = matchedAttributes[attrName]; + + if (list) + list.push(newNode); + else + matchedAttributes[attrName] = [newNode]; + } + } + + // Trim whitespace before block + if (blockElements[name]) + removeWhitespaceBefore(newNode); + + // Change current node if the element wasn't empty i.e not
    or + if (!empty) + node = newNode; + + // Check if we are inside a whitespace preserved element + if (!isInWhiteSpacePreservedElement && whiteSpaceElements[name]) { + isInWhiteSpacePreservedElement = true; + } + } + }, + + end: function(name) { + var textNode, elementRule, text, sibling, tempNode; + + elementRule = validate ? schema.getElementRule(name) : {}; + if (elementRule) { + if (blockElements[name]) { + if (!isInWhiteSpacePreservedElement) { + // Trim whitespace of the first node in a block + textNode = node.firstChild; + if (textNode && textNode.type === 3) { + text = textNode.value.replace(startWhiteSpaceRegExp, ''); + + // Any characters left after trim or should we remove it + if (text.length > 0) { + textNode.value = text; + textNode = textNode.next; + } else { + sibling = textNode.next; + textNode.remove(); + textNode = sibling; + } + + // Remove any pure whitespace siblings + while (textNode && textNode.type === 3) { + text = textNode.value; + sibling = textNode.next; + + if (text.length === 0 || isAllWhiteSpaceRegExp.test(text)) { + textNode.remove(); + textNode = sibling; + } + + textNode = sibling; + } + } + + // Trim whitespace of the last node in a block + textNode = node.lastChild; + if (textNode && textNode.type === 3) { + text = textNode.value.replace(endWhiteSpaceRegExp, ''); + + // Any characters left after trim or should we remove it + if (text.length > 0) { + textNode.value = text; + textNode = textNode.prev; + } else { + sibling = textNode.prev; + textNode.remove(); + textNode = sibling; + } + + // Remove any pure whitespace siblings + while (textNode && textNode.type === 3) { + text = textNode.value; + sibling = textNode.prev; + + if (text.length === 0 || isAllWhiteSpaceRegExp.test(text)) { + textNode.remove(); + textNode = sibling; + } + + textNode = sibling; + } + } + } + + // Trim start white space + // Removed due to: #5424 + /*textNode = node.prev; + if (textNode && textNode.type === 3) { + text = textNode.value.replace(startWhiteSpaceRegExp, ''); + + if (text.length > 0) + textNode.value = text; + else + textNode.remove(); + }*/ + } + + // Check if we exited a whitespace preserved element + if (isInWhiteSpacePreservedElement && whiteSpaceElements[name]) { + isInWhiteSpacePreservedElement = false; + } + + // Handle empty nodes + if (elementRule.removeEmpty || elementRule.paddEmpty) { + if (node.isEmpty(nonEmptyElements)) { + if (elementRule.paddEmpty) + node.empty().append(new Node('#text', '3')).value = '\u00a0'; + else { + // Leave nodes that have a name like + if (!node.attributes.map.name && !node.attributes.map.id) { + tempNode = node.parent; + node.empty().remove(); + node = tempNode; + return; + } + } + } + } + + node = node.parent; + } + } + }, schema); + + rootNode = node = new Node(args.context || settings.root_name, 11); + + parser.parse(html); + + // Fix invalid children or report invalid children in a contextual parsing + if (validate && invalidChildren.length) { + if (!args.context) + fixInvalidChildren(invalidChildren); + else + args.invalid = true; + } + + // Wrap nodes in the root into block elements if the root is body + if (rootBlockName && rootNode.name == 'body') + addRootBlocks(); + + // Run filters only when the contents is valid + if (!args.invalid) { + // Run node filters + for (name in matchedNodes) { + list = nodeFilters[name]; + nodes = matchedNodes[name]; + + // Remove already removed children + fi = nodes.length; + while (fi--) { + if (!nodes[fi].parent) + nodes.splice(fi, 1); + } + + for (i = 0, l = list.length; i < l; i++) + list[i](nodes, name, args); + } + + // Run attribute filters + for (i = 0, l = attributeFilters.length; i < l; i++) { + list = attributeFilters[i]; + + if (list.name in matchedAttributes) { + nodes = matchedAttributes[list.name]; + + // Remove already removed children + fi = nodes.length; + while (fi--) { + if (!nodes[fi].parent) + nodes.splice(fi, 1); + } + + for (fi = 0, fl = list.callbacks.length; fi < fl; fi++) + list.callbacks[fi](nodes, list.name, args); + } + } + } + + return rootNode; + }; + + // Remove
    at end of block elements Gecko and WebKit injects BR elements to + // make it possible to place the caret inside empty blocks. This logic tries to remove + // these elements and keep br elements that where intended to be there intact + if (settings.remove_trailing_brs) { + self.addNodeFilter('br', function(nodes, name) { + var i, l = nodes.length, node, blockElements = tinymce.extend({}, schema.getBlockElements()), + nonEmptyElements = schema.getNonEmptyElements(), parent, lastParent, prev, prevName; + + // Remove brs from body element as well + blockElements.body = 1; + + // Must loop forwards since it will otherwise remove all brs in

    a


    + for (i = 0; i < l; i++) { + node = nodes[i]; + parent = node.parent; + + if (blockElements[node.parent.name] && node === parent.lastChild) { + // Loop all nodes to the left of the current node and check for other BR elements + // excluding bookmarks since they are invisible + prev = node.prev; + while (prev) { + prevName = prev.name; + + // Ignore bookmarks + if (prevName !== "span" || prev.attr('data-mce-type') !== 'bookmark') { + // Found a non BR element + if (prevName !== "br") + break; + + // Found another br it's a

    structure then don't remove anything + if (prevName === 'br') { + node = null; + break; + } + } + + prev = prev.prev; + } + + if (node) { + node.remove(); + + // Is the parent to be considered empty after we removed the BR + if (parent.isEmpty(nonEmptyElements)) { + elementRule = schema.getElementRule(parent.name); + + // Remove or padd the element depending on schema rule + if (elementRule) { + if (elementRule.removeEmpty) + parent.remove(); + else if (elementRule.paddEmpty) + parent.empty().append(new tinymce.html.Node('#text', 3)).value = '\u00a0'; + } + } + } + } else { + // Replaces BR elements inside inline elements like


    so they become

     

    + lastParent = node; + while (parent.firstChild === lastParent && parent.lastChild === lastParent) { + lastParent = parent; + + if (blockElements[parent.name]) { + break; + } + + parent = parent.parent; + } + + if (lastParent === parent) { + textNode = new tinymce.html.Node('#text', 3); + textNode.value = '\u00a0'; + node.replace(textNode); + } + } + } + }); + } + + // Force anchor names closed, unless the setting "allow_html_in_named_anchor" is explicitly included. + if (!settings.allow_html_in_named_anchor) { + self.addAttributeFilter('id,name', function(nodes, name) { + var i = nodes.length, sibling, prevSibling, parent, node; + + while (i--) { + node = nodes[i]; + if (node.name === 'a' && node.firstChild && !node.attr('href')) { + parent = node.parent; + + // Move children after current node + sibling = node.lastChild; + do { + prevSibling = sibling.prev; + parent.insert(sibling, node); + sibling = prevSibling; + } while (sibling); + } + } + }); + } + } +})(tinymce); + +tinymce.html.Writer = function(settings) { + var html = [], indent, indentBefore, indentAfter, encode, htmlOutput; + + settings = settings || {}; + indent = settings.indent; + indentBefore = tinymce.makeMap(settings.indent_before || ''); + indentAfter = tinymce.makeMap(settings.indent_after || ''); + encode = tinymce.html.Entities.getEncodeFunc(settings.entity_encoding || 'raw', settings.entities); + htmlOutput = settings.element_format == "html"; + + return { + start: function(name, attrs, empty) { + var i, l, attr, value; + + if (indent && indentBefore[name] && html.length > 0) { + value = html[html.length - 1]; + + if (value.length > 0 && value !== '\n') + html.push('\n'); + } + + html.push('<', name); + + if (attrs) { + for (i = 0, l = attrs.length; i < l; i++) { + attr = attrs[i]; + html.push(' ', attr.name, '="', encode(attr.value, true), '"'); + } + } + + if (!empty || htmlOutput) + html[html.length] = '>'; + else + html[html.length] = ' />'; + + if (empty && indent && indentAfter[name] && html.length > 0) { + value = html[html.length - 1]; + + if (value.length > 0 && value !== '\n') + html.push('\n'); + } + }, + + end: function(name) { + var value; + + /*if (indent && indentBefore[name] && html.length > 0) { + value = html[html.length - 1]; + + if (value.length > 0 && value !== '\n') + html.push('\n'); + }*/ + + html.push(''); + + if (indent && indentAfter[name] && html.length > 0) { + value = html[html.length - 1]; + + if (value.length > 0 && value !== '\n') + html.push('\n'); + } + }, + + text: function(text, raw) { + if (text.length > 0) + html[html.length] = raw ? text : encode(text); + }, + + cdata: function(text) { + html.push(''); + }, + + comment: function(text) { + html.push(''); + }, + + pi: function(name, text) { + if (text) + html.push(''); + else + html.push(''); + + if (indent) + html.push('\n'); + }, + + doctype: function(text) { + html.push('', indent ? '\n' : ''); + }, + + reset: function() { + html.length = 0; + }, + + getContent: function() { + return html.join('').replace(/\n$/, ''); + } + }; +}; + +(function(tinymce) { + tinymce.html.Serializer = function(settings, schema) { + var self = this, writer = new tinymce.html.Writer(settings); + + settings = settings || {}; + settings.validate = "validate" in settings ? settings.validate : true; + + self.schema = schema = schema || new tinymce.html.Schema(); + self.writer = writer; + + self.serialize = function(node) { + var handlers, validate; + + validate = settings.validate; + + handlers = { + // #text + 3: function(node, raw) { + writer.text(node.value, node.raw); + }, + + // #comment + 8: function(node) { + writer.comment(node.value); + }, + + // Processing instruction + 7: function(node) { + writer.pi(node.name, node.value); + }, + + // Doctype + 10: function(node) { + writer.doctype(node.value); + }, + + // CDATA + 4: function(node) { + writer.cdata(node.value); + }, + + // Document fragment + 11: function(node) { + if ((node = node.firstChild)) { + do { + walk(node); + } while (node = node.next); + } + } + }; + + writer.reset(); + + function walk(node) { + var handler = handlers[node.type], name, isEmpty, attrs, attrName, attrValue, sortedAttrs, i, l, elementRule; + + if (!handler) { + name = node.name; + isEmpty = node.shortEnded; + attrs = node.attributes; + + // Sort attributes + if (validate && attrs && attrs.length > 1) { + sortedAttrs = []; + sortedAttrs.map = {}; + + elementRule = schema.getElementRule(node.name); + for (i = 0, l = elementRule.attributesOrder.length; i < l; i++) { + attrName = elementRule.attributesOrder[i]; + + if (attrName in attrs.map) { + attrValue = attrs.map[attrName]; + sortedAttrs.map[attrName] = attrValue; + sortedAttrs.push({name: attrName, value: attrValue}); + } + } + + for (i = 0, l = attrs.length; i < l; i++) { + attrName = attrs[i].name; + + if (!(attrName in sortedAttrs.map)) { + attrValue = attrs.map[attrName]; + sortedAttrs.map[attrName] = attrValue; + sortedAttrs.push({name: attrName, value: attrValue}); + } + } + + attrs = sortedAttrs; + } + + writer.start(node.name, attrs, isEmpty); + + if (!isEmpty) { + if ((node = node.firstChild)) { + do { + walk(node); + } while (node = node.next); + } + + writer.end(name); + } + } else + handler(node); + } + + // Serialize element and treat all non elements as fragments + if (node.type == 1 && !settings.inner) + walk(node); + else + handlers[11](node); + + return writer.getContent(); + }; + } +})(tinymce); + +// JSLint defined globals +/*global tinymce:false, window:false */ + +tinymce.dom = {}; + +(function(namespace, expando) { + var w3cEventModel = !!document.addEventListener; + + function addEvent(target, name, callback, capture) { + if (target.addEventListener) { + target.addEventListener(name, callback, capture || false); + } else if (target.attachEvent) { + target.attachEvent('on' + name, callback); + } + } + + function removeEvent(target, name, callback, capture) { + if (target.removeEventListener) { + target.removeEventListener(name, callback, capture || false); + } else if (target.detachEvent) { + target.detachEvent('on' + name, callback); + } + } + + function fix(original_event, data) { + var name, event = data || {}; + + // Dummy function that gets replaced on the delegation state functions + function returnFalse() { + return false; + } + + // Dummy function that gets replaced on the delegation state functions + function returnTrue() { + return true; + } + + // Copy all properties from the original event + for (name in original_event) { + // layerX/layerY is deprecated in Chrome and produces a warning + if (name !== "layerX" && name !== "layerY") { + event[name] = original_event[name]; + } + } + + // Normalize target IE uses srcElement + if (!event.target) { + event.target = event.srcElement || document; + } + + // Add preventDefault method + event.preventDefault = function() { + event.isDefaultPrevented = returnTrue; + + // Execute preventDefault on the original event object + if (original_event) { + if (original_event.preventDefault) { + original_event.preventDefault(); + } else { + original_event.returnValue = false; // IE + } + } + }; + + // Add stopPropagation + event.stopPropagation = function() { + event.isPropagationStopped = returnTrue; + + // Execute stopPropagation on the original event object + if (original_event) { + if (original_event.stopPropagation) { + original_event.stopPropagation(); + } else { + original_event.cancelBubble = true; // IE + } + } + }; + + // Add stopImmediatePropagation + event.stopImmediatePropagation = function() { + event.isImmediatePropagationStopped = returnTrue; + event.stopPropagation(); + }; + + // Add event delegation states + if (!event.isDefaultPrevented) { + event.isDefaultPrevented = returnFalse; + event.isPropagationStopped = returnFalse; + event.isImmediatePropagationStopped = returnFalse; + } + + return event; + } + + function bindOnReady(win, callback, event_utils) { + var doc = win.document, event = {type: 'ready'}; + + // Gets called when the DOM is ready + function readyHandler() { + if (!event_utils.domLoaded) { + event_utils.domLoaded = true; + callback(event); + } + } + + // Page already loaded then fire it directly + if (doc.readyState == "complete") { + readyHandler(); + return; + } + + // Use W3C method + if (w3cEventModel) { + addEvent(win, 'DOMContentLoaded', readyHandler); + } else { + // Use IE method + addEvent(doc, "readystatechange", function() { + if (doc.readyState === "complete") { + removeEvent(doc, "readystatechange", arguments.callee); + readyHandler(); + } + }); + + // Wait until we can scroll, when we can the DOM is initialized + if (doc.documentElement.doScroll && win === win.top) { + (function() { + try { + // If IE is used, use the trick by Diego Perini licensed under MIT by request to the author. + // http://javascript.nwbox.com/IEContentLoaded/ + doc.documentElement.doScroll("left"); + } catch (ex) { + setTimeout(arguments.callee, 0); + return; + } + + readyHandler(); + })(); + } + } + + // Fallback if any of the above methods should fail for some odd reason + addEvent(win, 'load', readyHandler); + } + + function EventUtils(proxy) { + var self = this, events = {}, count, isFocusBlurBound, hasFocusIn, hasMouseEnterLeave, mouseEnterLeave; + + hasMouseEnterLeave = "onmouseenter" in document.documentElement; + hasFocusIn = "onfocusin" in document.documentElement; + mouseEnterLeave = {mouseenter: 'mouseover', mouseleave: 'mouseout'}; + count = 1; + + // State if the DOMContentLoaded was executed or not + self.domLoaded = false; + self.events = events; + + function executeHandlers(evt, id) { + var callbackList, i, l, callback; + + callbackList = events[id][evt.type]; + if (callbackList) { + for (i = 0, l = callbackList.length; i < l; i++) { + callback = callbackList[i]; + + // Check if callback exists might be removed if a unbind is called inside the callback + if (callback && callback.func.call(callback.scope, evt) === false) { + evt.preventDefault(); + } + + // Should we stop propagation to immediate listeners + if (evt.isImmediatePropagationStopped()) { + return; + } + } + } + } + + self.bind = function(target, names, callback, scope) { + var id, callbackList, i, name, fakeName, nativeHandler, capture, win = window; + + // Native event handler function patches the event and executes the callbacks for the expando + function defaultNativeHandler(evt) { + executeHandlers(fix(evt || win.event), id); + } + + // Don't bind to text nodes or comments + if (!target || target.nodeType === 3 || target.nodeType === 8) { + return; + } + + // Create or get events id for the target + if (!target[expando]) { + id = count++; + target[expando] = id; + events[id] = {}; + } else { + id = target[expando]; + + if (!events[id]) { + events[id] = {}; + } + } + + // Setup the specified scope or use the target as a default + scope = scope || target; + + // Split names and bind each event, enables you to bind multiple events with one call + names = names.split(' '); + i = names.length; + while (i--) { + name = names[i]; + nativeHandler = defaultNativeHandler; + fakeName = capture = false; + + // Use ready instead of DOMContentLoaded + if (name === "DOMContentLoaded") { + name = "ready"; + } + + // DOM is already ready + if ((self.domLoaded || target.readyState == 'complete') && name === "ready") { + self.domLoaded = true; + callback.call(scope, fix({type: name})); + continue; + } + + // Handle mouseenter/mouseleaver + if (!hasMouseEnterLeave) { + fakeName = mouseEnterLeave[name]; + + if (fakeName) { + nativeHandler = function(evt) { + var current, related; + + current = evt.currentTarget; + related = evt.relatedTarget; + + // Check if related is inside the current target if it's not then the event should be ignored since it's a mouseover/mouseout inside the element + if (related && current.contains) { + // Use contains for performance + related = current.contains(related); + } else { + while (related && related !== current) { + related = related.parentNode; + } + } + + // Fire fake event + if (!related) { + evt = fix(evt || win.event); + evt.type = evt.type === 'mouseout' ? 'mouseleave' : 'mouseenter'; + evt.target = current; + executeHandlers(evt, id); + } + }; + } + } + + // Fake bubbeling of focusin/focusout + if (!hasFocusIn && (name === "focusin" || name === "focusout")) { + capture = true; + fakeName = name === "focusin" ? "focus" : "blur"; + nativeHandler = function(evt) { + evt = fix(evt || win.event); + evt.type = evt.type === 'focus' ? 'focusin' : 'focusout'; + executeHandlers(evt, id); + }; + } + + // Setup callback list and bind native event + callbackList = events[id][name]; + if (!callbackList) { + events[id][name] = callbackList = [{func: callback, scope: scope}]; + callbackList.fakeName = fakeName; + callbackList.capture = capture; + + // Add the nativeHandler to the callback list so that we can later unbind it + callbackList.nativeHandler = nativeHandler; + if (!w3cEventModel) { + callbackList.proxyHandler = proxy(id); + } + + // Check if the target has native events support + if (name === "ready") { + bindOnReady(target, nativeHandler, self); + } else { + addEvent(target, fakeName || name, w3cEventModel ? nativeHandler : callbackList.proxyHandler, capture); + } + } else { + // If it already has an native handler then just push the callback + callbackList.push({func: callback, scope: scope}); + } + } + + target = callbackList = 0; // Clean memory for IE + + return callback; + }; + + self.unbind = function(target, names, callback) { + var id, callbackList, i, ci, name, eventMap; + + // Don't bind to text nodes or comments + if (!target || target.nodeType === 3 || target.nodeType === 8) { + return self; + } + + // Unbind event or events if the target has the expando + id = target[expando]; + if (id) { + eventMap = events[id]; + + // Specific callback + if (names) { + names = names.split(' '); + i = names.length; + while (i--) { + name = names[i]; + callbackList = eventMap[name]; + + // Unbind the event if it exists in the map + if (callbackList) { + // Remove specified callback + if (callback) { + ci = callbackList.length; + while (ci--) { + if (callbackList[ci].func === callback) { + callbackList.splice(ci, 1); + } + } + } + + // Remove all callbacks if there isn't a specified callback or there is no callbacks left + if (!callback || callbackList.length === 0) { + delete eventMap[name]; + removeEvent(target, callbackList.fakeName || name, w3cEventModel ? callbackList.nativeHandler : callbackList.proxyHandler, callbackList.capture); + } + } + } + } else { + // All events for a specific element + for (name in eventMap) { + callbackList = eventMap[name]; + removeEvent(target, callbackList.fakeName || name, w3cEventModel ? callbackList.nativeHandler : callbackList.proxyHandler, callbackList.capture); + } + + eventMap = {}; + } + + // Check if object is empty, if it isn't then we won't remove the expando map + for (name in eventMap) { + return self; + } + + // Delete event object + delete events[id]; + + // Remove expando from target + try { + // IE will fail here since it can't delete properties from window + delete target[expando]; + } catch (ex) { + // IE will set it to null + target[expando] = null; + } + } + + return self; + }; + + self.fire = function(target, name, args) { + var id, event; + + // Don't bind to text nodes or comments + if (!target || target.nodeType === 3 || target.nodeType === 8) { + return self; + } + + // Build event object by patching the args + event = fix(null, args); + event.type = name; + + do { + // Found an expando that means there is listeners to execute + id = target[expando]; + if (id) { + executeHandlers(event, id); + } + + // Walk up the DOM + target = target.parentNode || target.ownerDocument || target.defaultView || target.parentWindow; + } while (target && !event.isPropagationStopped()); + + return self; + }; + + self.clean = function(target) { + var i, children, unbind = self.unbind; + + // Don't bind to text nodes or comments + if (!target || target.nodeType === 3 || target.nodeType === 8) { + return self; + } + + // Unbind any element on the specificed target + if (target[expando]) { + unbind(target); + } + + // Target doesn't have getElementsByTagName it's probably a window object then use it's document to find the children + if (!target.getElementsByTagName) { + target = target.document; + } + + // Remove events from each child element + if (target && target.getElementsByTagName) { + unbind(target); + + children = target.getElementsByTagName('*'); + i = children.length; + while (i--) { + target = children[i]; + + if (target[expando]) { + unbind(target); + } + } + } + + return self; + }; + + self.callNativeHandler = function(id, evt) { + if (events) { + events[id][evt.type].nativeHandler(evt); + } + }; + + self.destory = function() { + events = {}; + }; + + // Legacy function calls + + self.add = function(target, events, func, scope) { + // Old API supported direct ID assignment + if (typeof(target) === "string") { + target = document.getElementById(target); + } + + // Old API supported multiple targets + if (target && target instanceof Array) { + var i = target.length; + + while (i--) { + self.add(target[i], events, func, scope); + } + + return; + } + + // Old API called ready init + if (events === "init") { + events = "ready"; + } + + return self.bind(target, events instanceof Array ? events.join(' ') : events, func, scope); + }; + + self.remove = function(target, events, func, scope) { + if (!target) { + return self; + } + + // Old API supported direct ID assignment + if (typeof(target) === "string") { + target = document.getElementById(target); + } + + // Old API supported multiple targets + if (target instanceof Array) { + var i = target.length; + + while (i--) { + self.remove(target[i], events, func, scope); + } + + return self; + } + + return self.unbind(target, events instanceof Array ? events.join(' ') : events, func); + }; + + self.clear = function(target) { + // Old API supported direct ID assignment + if (typeof(target) === "string") { + target = document.getElementById(target); + } + + return self.clean(target); + }; + + self.cancel = function(e) { + if (e) { + self.prevent(e); + self.stop(e); + } + + return false; + }; + + self.prevent = function(e) { + if (!e.preventDefault) { + e = fix(e); + } + + e.preventDefault(); + + return false; + }; + + self.stop = function(e) { + if (!e.stopPropagation) { + e = fix(e); + } + + e.stopPropagation(); + + return false; + }; + } + + namespace.EventUtils = EventUtils; + + namespace.Event = new EventUtils(function(id) { + return function(evt) { + tinymce.dom.Event.callNativeHandler(id, evt); + }; + }); + + // Bind ready event when tinymce script is loaded + namespace.Event.bind(window, 'ready', function() {}); + + namespace = 0; +})(tinymce.dom, 'data-mce-expando'); // Namespace and expando + +tinymce.dom.TreeWalker = function(start_node, root_node) { + var node = start_node; + + function findSibling(node, start_name, sibling_name, shallow) { + var sibling, parent; + + if (node) { + // Walk into nodes if it has a start + if (!shallow && node[start_name]) + return node[start_name]; + + // Return the sibling if it has one + if (node != root_node) { + sibling = node[sibling_name]; + if (sibling) + return sibling; + + // Walk up the parents to look for siblings + for (parent = node.parentNode; parent && parent != root_node; parent = parent.parentNode) { + sibling = parent[sibling_name]; + if (sibling) + return sibling; + } + } + } + }; + + this.current = function() { + return node; + }; + + this.next = function(shallow) { + return (node = findSibling(node, 'firstChild', 'nextSibling', shallow)); + }; + + this.prev = function(shallow) { + return (node = findSibling(node, 'lastChild', 'previousSibling', shallow)); + }; +}; + +(function(tinymce) { + // Shorten names + var each = tinymce.each, + is = tinymce.is, + isWebKit = tinymce.isWebKit, + isIE = tinymce.isIE, + Entities = tinymce.html.Entities, + simpleSelectorRe = /^([a-z0-9],?)+$/i, + whiteSpaceRegExp = /^[ \t\r\n]*$/; + + tinymce.create('tinymce.dom.DOMUtils', { + doc : null, + root : null, + files : null, + pixelStyles : /^(top|left|bottom|right|width|height|borderWidth)$/, + props : { + "for" : "htmlFor", + "class" : "className", + className : "className", + checked : "checked", + disabled : "disabled", + maxlength : "maxLength", + readonly : "readOnly", + selected : "selected", + value : "value", + id : "id", + name : "name", + type : "type" + }, + + DOMUtils : function(d, s) { + var t = this, globalStyle, name, blockElementsMap; + + t.doc = d; + t.win = window; + t.files = {}; + t.cssFlicker = false; + t.counter = 0; + t.stdMode = !tinymce.isIE || d.documentMode >= 8; + t.boxModel = !tinymce.isIE || d.compatMode == "CSS1Compat" || t.stdMode; + t.hasOuterHTML = "outerHTML" in d.createElement("a"); + + t.settings = s = tinymce.extend({ + keep_values : false, + hex_colors : 1 + }, s); + + t.schema = s.schema; + t.styles = new tinymce.html.Styles({ + url_converter : s.url_converter, + url_converter_scope : s.url_converter_scope + }, s.schema); + + // Fix IE6SP2 flicker and check it failed for pre SP2 + if (tinymce.isIE6) { + try { + d.execCommand('BackgroundImageCache', false, true); + } catch (e) { + t.cssFlicker = true; + } + } + + t.fixDoc(d); + t.events = s.ownEvents ? new tinymce.dom.EventUtils(s.proxy) : tinymce.dom.Event; + tinymce.addUnload(t.destroy, t); + blockElementsMap = s.schema ? s.schema.getBlockElements() : {}; + + t.isBlock = function(node) { + // Fix for #5446 + if (!node) { + return false; + } + + // This function is called in module pattern style since it might be executed with the wrong this scope + var type = node.nodeType; + + // If it's a node then check the type and use the nodeName + if (type) + return !!(type === 1 && blockElementsMap[node.nodeName]); + + return !!blockElementsMap[node]; + }; + }, + + fixDoc: function(doc) { + var settings = this.settings, name; + + if (isIE && !tinymce.isIE11 && settings.schema) { + // Add missing HTML 4/5 elements to IE + ('abbr article aside audio canvas ' + + 'details figcaption figure footer ' + + 'header hgroup mark menu meter nav ' + + 'output progress section summary ' + + 'time video').replace(/\w+/g, function(name) { + doc.createElement(name); + }); + + // Create all custom elements + for (name in settings.schema.getCustomElements()) { + doc.createElement(name); + } + } + }, + + clone: function(node, deep) { + var self = this, clone, doc; + + // TODO: Add feature detection here in the future + if (!isIE || tinymce.isIE11 || node.nodeType !== 1 || deep) { + return node.cloneNode(deep); + } + + doc = self.doc; + + // Make a HTML5 safe shallow copy + if (!deep) { + clone = doc.createElement(node.nodeName); + + // Copy attribs + each(self.getAttribs(node), function(attr) { + self.setAttrib(clone, attr.nodeName, self.getAttrib(node, attr.nodeName)); + }); + + return clone; + } +/* + // Setup HTML5 patched document fragment + if (!self.frag) { + self.frag = doc.createDocumentFragment(); + self.fixDoc(self.frag); + } + + // Make a deep copy by adding it to the document fragment then removing it this removed the :section + clone = doc.createElement('div'); + self.frag.appendChild(clone); + clone.innerHTML = node.outerHTML; + self.frag.removeChild(clone); +*/ + return clone.firstChild; + }, + + getRoot : function() { + var t = this, s = t.settings; + + return (s && t.get(s.root_element)) || t.doc.body; + }, + + getViewPort : function(w) { + var d, b; + + w = !w ? this.win : w; + d = w.document; + b = this.boxModel ? d.documentElement : d.body; + + // Returns viewport size excluding scrollbars + return { + x : w.pageXOffset || b.scrollLeft, + y : w.pageYOffset || b.scrollTop, + w : w.innerWidth || b.clientWidth, + h : w.innerHeight || b.clientHeight + }; + }, + + getRect : function(e) { + var p, t = this, sr; + + e = t.get(e); + p = t.getPos(e); + sr = t.getSize(e); + + return { + x : p.x, + y : p.y, + w : sr.w, + h : sr.h + }; + }, + + getSize : function(e) { + var t = this, w, h; + + e = t.get(e); + w = t.getStyle(e, 'width'); + h = t.getStyle(e, 'height'); + + // Non pixel value, then force offset/clientWidth + if (w.indexOf('px') === -1) + w = 0; + + // Non pixel value, then force offset/clientWidth + if (h.indexOf('px') === -1) + h = 0; + + return { + w : parseInt(w, 10) || e.offsetWidth || e.clientWidth, + h : parseInt(h, 10) || e.offsetHeight || e.clientHeight + }; + }, + + getParent : function(n, f, r) { + return this.getParents(n, f, r, false); + }, + + getParents : function(n, f, r, c) { + var t = this, na, se = t.settings, o = []; + + n = t.get(n); + c = c === undefined; + + if (se.strict_root) + r = r || t.getRoot(); + + // Wrap node name as func + if (is(f, 'string')) { + na = f; + + if (f === '*') { + f = function(n) {return n.nodeType == 1;}; + } else { + f = function(n) { + return t.is(n, na); + }; + } + } + + while (n) { + if (n == r || !n.nodeType || n.nodeType === 9) + break; + + if (!f || f(n)) { + if (c) + o.push(n); + else + return n; + } + + n = n.parentNode; + } + + return c ? o : null; + }, + + get : function(e) { + var n; + + if (e && this.doc && typeof(e) == 'string') { + n = e; + e = this.doc.getElementById(e); + + // IE and Opera returns meta elements when they match the specified input ID, but getElementsByName seems to do the trick + if (e && e.id !== n) + return this.doc.getElementsByName(n)[1]; + } + + return e; + }, + + getNext : function(node, selector) { + return this._findSib(node, selector, 'nextSibling'); + }, + + getPrev : function(node, selector) { + return this._findSib(node, selector, 'previousSibling'); + }, + + + add : function(p, n, a, h, c) { + var t = this; + + return this.run(p, function(p) { + var e, k; + + e = is(n, 'string') ? t.doc.createElement(n) : n; + t.setAttribs(e, a); + + if (h) { + if (h.nodeType) + e.appendChild(h); + else + t.setHTML(e, h); + } + + return !c ? p.appendChild(e) : e; + }); + }, + + create : function(n, a, h) { + return this.add(this.doc.createElement(n), n, a, h, 1); + }, + + createHTML : function(n, a, h) { + var o = '', t = this, k; + + o += '<' + n; + + for (k in a) { + if (a.hasOwnProperty(k)) + o += ' ' + k + '="' + t.encode(a[k]) + '"'; + } + + // A call to tinymce.is doesn't work for some odd reason on IE9 possible bug inside their JS runtime + if (typeof(h) != "undefined") + return o + '>' + h + ''; + + return o + ' />'; + }, + + remove : function(node, keep_children) { + return this.run(node, function(node) { + var child, parent = node.parentNode; + + if (!parent) + return null; + + if (keep_children) { + while (child = node.firstChild) { + // IE 8 will crash if you don't remove completely empty text nodes + if (!tinymce.isIE || child.nodeType !== 3 || child.nodeValue) + parent.insertBefore(child, node); + else + node.removeChild(child); + } + } + + return parent.removeChild(node); + }); + }, + + setStyle : function(n, na, v) { + var t = this; + + return t.run(n, function(e) { + var s, i; + + s = e.style; + + // Camelcase it, if needed + na = na.replace(/-(\D)/g, function(a, b){ + return b.toUpperCase(); + }); + + // Default px suffix on these + if (t.pixelStyles.test(na) && (tinymce.is(v, 'number') || /^[\-0-9\.]+$/.test(v))) + v += 'px'; + + switch (na) { + case 'opacity': + // IE specific opacity + if (isIE && ! tinymce.isIE11) { + s.filter = v === '' ? '' : "alpha(opacity=" + (v * 100) + ")"; + + if (!n.currentStyle || !n.currentStyle.hasLayout) + s.display = 'inline-block'; + } + + // Fix for older browsers + s[na] = s['-moz-opacity'] = s['-khtml-opacity'] = v || ''; + break; + + case 'float': + (isIE && ! tinymce.isIE11) ? s.styleFloat = v : s.cssFloat = v; + break; + + default: + s[na] = v || ''; + } + + // Force update of the style data + if (t.settings.update_styles) + t.setAttrib(e, 'data-mce-style'); + }); + }, + + getStyle : function(n, na, c) { + n = this.get(n); + + if (!n) + return; + + // Gecko + if (this.doc.defaultView && c) { + // Remove camelcase + na = na.replace(/[A-Z]/g, function(a){ + return '-' + a; + }); + + try { + return this.doc.defaultView.getComputedStyle(n, null).getPropertyValue(na); + } catch (ex) { + // Old safari might fail + return null; + } + } + + // Camelcase it, if needed + na = na.replace(/-(\D)/g, function(a, b){ + return b.toUpperCase(); + }); + + if (na == 'float') + na = isIE ? 'styleFloat' : 'cssFloat'; + + // IE & Opera + if (n.currentStyle && c) + return n.currentStyle[na]; + + return n.style ? n.style[na] : undefined; + }, + + setStyles : function(e, o) { + var t = this, s = t.settings, ol; + + ol = s.update_styles; + s.update_styles = 0; + + each(o, function(v, n) { + t.setStyle(e, n, v); + }); + + // Update style info + s.update_styles = ol; + if (s.update_styles) + t.setAttrib(e, s.cssText); + }, + + removeAllAttribs: function(e) { + return this.run(e, function(e) { + var i, attrs = e.attributes; + for (i = attrs.length - 1; i >= 0; i--) { + e.removeAttributeNode(attrs.item(i)); + } + }); + }, + + setAttrib : function(e, n, v) { + var t = this; + + // Whats the point + if (!e || !n) + return; + + // Strict XML mode + if (t.settings.strict) + n = n.toLowerCase(); + + return this.run(e, function(e) { + var s = t.settings; + var originalValue = e.getAttribute(n); + if (v !== null) { + switch (n) { + case "style": + if (!is(v, 'string')) { + each(v, function(v, n) { + t.setStyle(e, n, v); + }); + + return; + } + + // No mce_style for elements with these since they might get resized by the user + if (s.keep_values) { + if (v && !t._isRes(v)) + e.setAttribute('data-mce-style', v, 2); + else + e.removeAttribute('data-mce-style', 2); + } + + e.style.cssText = v; + break; + + case "class": + e.className = v || ''; // Fix IE null bug + break; + + case "src": + case "href": + if (s.keep_values) { + if (s.url_converter) + v = s.url_converter.call(s.url_converter_scope || t, v, n, e); + + t.setAttrib(e, 'data-mce-' + n, v, 2); + } + + break; + + case "shape": + e.setAttribute('data-mce-style', v); + break; + } + } + if (is(v) && v !== null && v.length !== 0) + e.setAttribute(n, '' + v, 2); + else + e.removeAttribute(n, 2); + + // fire onChangeAttrib event for attributes that have changed + if (tinyMCE.activeEditor && originalValue != v) { + var ed = tinyMCE.activeEditor; + ed.onSetAttrib.dispatch(ed, e, n, v); + } + }); + }, + + setAttribs : function(e, o) { + var t = this; + + return this.run(e, function(e) { + each(o, function(v, n) { + t.setAttrib(e, n, v); + }); + }); + }, + + getAttrib : function(e, n, dv) { + var v, t = this, undef; + + e = t.get(e); + + if (!e || e.nodeType !== 1) + return dv === undef ? false : dv; + + if (!is(dv)) + dv = ''; + + // Try the mce variant for these + if (/^(src|href|style|coords|shape)$/.test(n)) { + v = e.getAttribute("data-mce-" + n); + + if (v) + return v; + } + + if (isIE && t.props[n]) { + v = e[t.props[n]]; + v = v && v.nodeValue ? v.nodeValue : v; + } + + if (!v) + v = e.getAttribute(n, 2); + + // Check boolean attribs + if (/^(checked|compact|declare|defer|disabled|ismap|multiple|nohref|noshade|nowrap|readonly|selected)$/.test(n)) { + if (e[t.props[n]] === true && v === '') + return n; + + return v ? n : ''; + } + + // Inner input elements will override attributes on form elements + if (e.nodeName === "FORM" && e.getAttributeNode(n)) + return e.getAttributeNode(n).nodeValue; + + if (n === 'style') { + v = v || e.style.cssText; + + if (v) { + v = t.serializeStyle(t.parseStyle(v), e.nodeName); + + if (t.settings.keep_values && !t._isRes(v)) + e.setAttribute('data-mce-style', v); + } + } + + // Remove Apple and WebKit stuff + if (isWebKit && n === "class" && v) + v = v.replace(/(apple|webkit)\-[a-z\-]+/gi, ''); + + // Handle IE issues + if (isIE) { + switch (n) { + case 'rowspan': + case 'colspan': + // IE returns 1 as default value + if (v === 1) + v = ''; + + break; + + case 'size': + // IE returns +0 as default value for size + if (v === '+0' || v === 20 || v === 0) + v = ''; + + break; + + case 'width': + case 'height': + case 'vspace': + case 'checked': + case 'disabled': + case 'readonly': + if (v === 0) + v = ''; + + break; + + case 'hspace': + // IE returns -1 as default value + if (v === -1) + v = ''; + + break; + + case 'maxlength': + case 'tabindex': + // IE returns default value + if (v === 32768 || v === 2147483647 || v === '32768') + v = ''; + + break; + + case 'multiple': + case 'compact': + case 'noshade': + case 'nowrap': + if (v === 65535) + return n; + + return dv; + + case 'shape': + v = v.toLowerCase(); + break; + + default: + // IE has odd anonymous function for event attributes + if (n.indexOf('on') === 0 && v) + v = tinymce._replace(/^function\s+\w+\(\)\s+\{\s+(.*)\s+\}$/, '$1', '' + v); + } + } + + return (v !== undef && v !== null && v !== '') ? '' + v : dv; + }, + + getPos : function(n, ro) { + var t = this, x = 0, y = 0, e, d = t.doc, r; + + n = t.get(n); + ro = ro || d.body; + + if (n) { + // Use getBoundingClientRect if it exists since it's faster than looping offset nodes + if (n.getBoundingClientRect) { + n = n.getBoundingClientRect(); + e = t.boxModel ? d.documentElement : d.body; + + // Add scroll offsets from documentElement or body since IE with the wrong box model will use d.body and so do WebKit + // Also remove the body/documentelement clientTop/clientLeft on IE 6, 7 since they offset the position + x = n.left + (d.documentElement.scrollLeft || d.body.scrollLeft) - e.clientTop; + y = n.top + (d.documentElement.scrollTop || d.body.scrollTop) - e.clientLeft; + + return {x : x, y : y}; + } + + r = n; + while (r && r != ro && r.nodeType) { + x += r.offsetLeft || 0; + y += r.offsetTop || 0; + r = r.offsetParent; + } + + r = n.parentNode; + while (r && r != ro && r.nodeType) { + x -= r.scrollLeft || 0; + y -= r.scrollTop || 0; + r = r.parentNode; + } + } + + return {x : x, y : y}; + }, + + parseStyle : function(st) { + return this.styles.parse(st); + }, + + serializeStyle : function(o, name) { + return this.styles.serialize(o, name); + }, + + addStyle: function(cssText) { + var doc = this.doc, head; + + // Create style element if needed + styleElm = doc.getElementById('mceDefaultStyles'); + if (!styleElm) { + styleElm = doc.createElement('style'), + styleElm.id = 'mceDefaultStyles'; + styleElm.type = 'text/css'; + + head = doc.getElementsByTagName('head')[0]; + if (head.firstChild) { + head.insertBefore(styleElm, head.firstChild); + } else { + head.appendChild(styleElm); + } + } + + // Append style data to old or new style element + if (styleElm.styleSheet) { + styleElm.styleSheet.cssText += cssText; + } else { + styleElm.appendChild(doc.createTextNode(cssText)); + } + }, + + loadCSS : function(u) { + var t = this, d = t.doc, head; + + if (!u) + u = ''; + + head = d.getElementsByTagName('head')[0]; + + each(u.split(','), function(u) { + var link; + + if (t.files[u]) + return; + + t.files[u] = true; + link = t.create('link', {rel : 'stylesheet', href : tinymce._addVer(u)}); + + // IE 8 has a bug where dynamically loading stylesheets would produce a 1 item remaining bug + // This fix seems to resolve that issue by realcing the document ones a stylesheet finishes loading + // It's ugly but it seems to work fine. + if (isIE && !tinymce.isIE11 && d.documentMode && d.recalc) { + link.onload = function() { + if (d.recalc) + d.recalc(); + + link.onload = null; + }; + } + + head.appendChild(link); + }); + }, + + addClass : function(e, c) { + return this.run(e, function(e) { + var o; + + if (!c) + return 0; + + if (this.hasClass(e, c)) + return e.className; + + o = this.removeClass(e, c); + + return e.className = (o != '' ? (o + ' ') : '') + c; + }); + }, + + removeClass : function(e, c) { + var t = this, re; + + return t.run(e, function(e) { + var v; + + if (t.hasClass(e, c)) { + if (!re) + re = new RegExp("(^|\\s+)" + c + "(\\s+|$)", "g"); + + v = e.className.replace(re, ' '); + v = tinymce.trim(v != ' ' ? v : ''); + + e.className = v; + + // Empty class attr + if (!v) { + e.removeAttribute('class'); + e.removeAttribute('className'); + } + + return v; + } + + return e.className; + }); + }, + + hasClass : function(n, c) { + n = this.get(n); + + if (!n || !c) + return false; + + return (' ' + n.className + ' ').indexOf(' ' + c + ' ') !== -1; + }, + + show : function(e) { + return this.setStyle(e, 'display', 'block'); + }, + + hide : function(e) { + return this.setStyle(e, 'display', 'none'); + }, + + isHidden : function(e) { + e = this.get(e); + + return !e || e.style.display == 'none' || this.getStyle(e, 'display') == 'none'; + }, + + uniqueId : function(p) { + return (!p ? 'mce_' : p) + (this.counter++); + }, + + setHTML : function(element, html) { + var self = this; + + return self.run(element, function(element) { + if (isIE) { + // Remove all child nodes, IE keeps empty text nodes in DOM + while (element.firstChild) + element.removeChild(element.firstChild); + + try { + // IE will remove comments from the beginning + // unless you padd the contents with something + element.innerHTML = '
    ' + html; + element.removeChild(element.firstChild); + } catch (ex) { + // IE sometimes produces an unknown runtime error on innerHTML if it's an block element within a block element for example a div inside a p + // This seems to fix this problem + + // Create new div with HTML contents and a BR infront to keep comments + var newElement = self.create('div'); + newElement.innerHTML = '
    ' + html; + + // Add all children from div to target + each (tinymce.grep(newElement.childNodes), function(node, i) { + // Skip br element + if (i && element.canHaveHTML) + element.appendChild(node); + }); + } + } else + element.innerHTML = html; + + return html; + }); + }, + + getOuterHTML : function(elm) { + var doc, self = this; + + elm = self.get(elm); + + if (!elm) + return null; + + if (elm.nodeType === 1 && self.hasOuterHTML) + return elm.outerHTML; + + doc = (elm.ownerDocument || self.doc).createElement("body"); + doc.appendChild(elm.cloneNode(true)); + + return doc.innerHTML; + }, + + setOuterHTML : function(e, h, d) { + var t = this; + + function setHTML(e, h, d) { + var n, tp; + + tp = d.createElement("body"); + tp.innerHTML = h; + + n = tp.lastChild; + while (n) { + t.insertAfter(n.cloneNode(true), e); + n = n.previousSibling; + } + + t.remove(e); + }; + + return this.run(e, function(e) { + e = t.get(e); + + // Only set HTML on elements + if (e.nodeType == 1) { + d = d || e.ownerDocument || t.doc; + + if (isIE) { + try { + // Try outerHTML for IE it sometimes produces an unknown runtime error + if (isIE && e.nodeType == 1) + e.outerHTML = h; + else + setHTML(e, h, d); + } catch (ex) { + // Fix for unknown runtime error + setHTML(e, h, d); + } + } else + setHTML(e, h, d); + } + }); + }, + + decode : Entities.decode, + + encode : Entities.encodeAllRaw, + + insertAfter : function(node, reference_node) { + reference_node = this.get(reference_node); + + return this.run(node, function(node) { + var parent, nextSibling; + + parent = reference_node.parentNode; + nextSibling = reference_node.nextSibling; + + if (nextSibling) + parent.insertBefore(node, nextSibling); + else + parent.appendChild(node); + + return node; + }); + }, + + replace : function(n, o, k) { + var t = this; + + if (is(o, 'array')) + n = n.cloneNode(true); + + return t.run(o, function(o) { + if (k) { + each(tinymce.grep(o.childNodes), function(c) { + n.appendChild(c); + }); + } + + return o.parentNode.replaceChild(n, o); + }); + }, + + rename : function(elm, name) { + var t = this, newElm; + + if (elm.nodeName != name.toUpperCase()) { + // Rename block element + newElm = t.create(name); + + // Copy attribs to new block + each(t.getAttribs(elm), function(attr_node) { + t.setAttrib(newElm, attr_node.nodeName, t.getAttrib(elm, attr_node.nodeName)); + }); + + // Replace block + t.replace(newElm, elm, 1); + } + + return newElm || elm; + }, + + findCommonAncestor : function(a, b) { + var ps = a, pe; + + while (ps) { + pe = b; + + while (pe && ps != pe) + pe = pe.parentNode; + + if (ps == pe) + break; + + ps = ps.parentNode; + } + + if (!ps && a.ownerDocument) + return a.ownerDocument.documentElement; + + return ps; + }, + + toHex : function(s) { + var c = /^\s*rgb\s*?\(\s*?([0-9]+)\s*?,\s*?([0-9]+)\s*?,\s*?([0-9]+)\s*?\)\s*$/i.exec(s); + + function hex(s) { + s = parseInt(s, 10).toString(16); + + return s.length > 1 ? s : '0' + s; // 0 -> 00 + }; + + if (c) { + s = '#' + hex(c[1]) + hex(c[2]) + hex(c[3]); + + return s; + } + + return s; + }, + + getClasses : function() { + var t = this, cl = [], i, lo = {}, f = t.settings.class_filter, ov; + + if (t.classes) + return t.classes; + + function addClasses(s) { + // IE style imports + each(s.imports, function(r) { + addClasses(r); + }); + + each(s.cssRules || s.rules, function(r) { + // Real type or fake it on IE + switch (r.type || 1) { + // Rule + case 1: + if (r.selectorText) { + each(r.selectorText.split(','), function(v) { + v = v.replace(/^\s*|\s*$|^\s\./g, ""); + + // Is internal or it doesn't contain a class + if (/\.mce/.test(v) || !/\.[\w\-]+$/.test(v)) + return; + + // Remove everything but class name + ov = v; + v = tinymce._replace(/.*\.([a-z0-9_\-]+).*/i, '$1', v); + + // Filter classes + if (f && !(v = f(v, ov))) + return; + + if (!lo[v]) { + cl.push({'class' : v}); + lo[v] = 1; + } + }); + } + break; + + // Import + case 3: + try { + addClasses(r.styleSheet); + } catch (ex) { + // Ignore + } + + break; + } + }); + }; + + try { + each(t.doc.styleSheets, addClasses); + } catch (ex) { + // Ignore + } + + if (cl.length > 0) + t.classes = cl; + + return cl; + }, + + run : function(e, f, s) { + var t = this, o; + + if (t.doc && typeof(e) === 'string') + e = t.get(e); + + if (!e) + return false; + + s = s || this; + if (!e.nodeType && (e.length || e.length === 0)) { + o = []; + + each(e, function(e, i) { + if (e) { + if (typeof(e) == 'string') + e = t.doc.getElementById(e); + + o.push(f.call(s, e, i)); + } + }); + + return o; + } + + return f.call(s, e); + }, + + getAttribs : function(n) { + var o; + + n = this.get(n); + + if (!n) + return []; + + if (isIE) { + o = []; + + // Object will throw exception in IE + if (n.nodeName == 'OBJECT') + return n.attributes; + + // IE doesn't keep the selected attribute if you clone option elements + if (n.nodeName === 'OPTION' && this.getAttrib(n, 'selected')) + o.push({specified : 1, nodeName : 'selected'}); + + // It's crazy that this is faster in IE but it's because it returns all attributes all the time + n.cloneNode(false).outerHTML.replace(/<\/?[\w:\-]+ ?|=[\"][^\"]+\"|=\'[^\']+\'|=[\w\-]+|>/gi, '').replace(/[\w:\-]+/gi, function(a) { + o.push({specified : 1, nodeName : a}); + }); + + return o; + } + + return n.attributes; + }, + + isEmpty : function(node, elements) { + var self = this, i, attributes, type, walker, name, brCount = 0; + + node = node.firstChild; + if (node) { + walker = new tinymce.dom.TreeWalker(node, node.parentNode); + elements = elements || self.schema ? self.schema.getNonEmptyElements() : null; + + do { + type = node.nodeType; + + if (type === 1) { + // Ignore bogus elements + if (node.getAttribute('data-mce-bogus')) + continue; + + // Keep empty elements like + name = node.nodeName.toLowerCase(); + if (elements && elements[name]) { + // Ignore single BR elements in blocks like


    or


    + if (name === 'br') { + brCount++; + continue; + } + + return false; + } + + // Keep elements with data-bookmark attributes or name attribute like
    + attributes = self.getAttribs(node); + i = node.attributes.length; + while (i--) { + name = node.attributes[i].nodeName; + if (name === "name" || name === 'data-mce-bookmark') + return false; + } + } + + // Keep comment nodes + if (type == 8) + return false; + + // Keep non whitespace text nodes + if ((type === 3 && !whiteSpaceRegExp.test(node.nodeValue))) + return false; + } while (node = walker.next()); + } + + return brCount <= 1; + }, + + destroy : function(s) { + var t = this; + + t.win = t.doc = t.root = t.events = t.frag = null; + + // Manual destroy then remove unload handler + if (!s) + tinymce.removeUnload(t.destroy); + }, + + createRng : function() { + var d = this.doc; + + return d.createRange ? d.createRange() : new tinymce.dom.Range(this); + }, + + nodeIndex : function(node, normalized) { + var idx = 0, lastNodeType, lastNode, nodeType; + + if (node) { + for (lastNodeType = node.nodeType, node = node.previousSibling, lastNode = node; node; node = node.previousSibling) { + nodeType = node.nodeType; + + // Normalize text nodes + if (normalized && nodeType == 3) { + if (nodeType == lastNodeType || !node.nodeValue.length) + continue; + } + idx++; + lastNodeType = nodeType; + } + } + + return idx; + }, + + split : function(pe, e, re) { + var t = this, r = t.createRng(), bef, aft, pa; + + // W3C valid browsers tend to leave empty nodes to the left/right side of the contents, this makes sense + // but we don't want that in our code since it serves no purpose for the end user + // For example if this is chopped: + //

    text 1CHOPtext 2

    + // would produce: + //

    text 1

    CHOP

    text 2

    + // this function will then trim of empty edges and produce: + //

    text 1

    CHOP

    text 2

    + function trim(node) { + var i, children = node.childNodes, type = node.nodeType; + + function surroundedBySpans(node) { + var previousIsSpan = node.previousSibling && node.previousSibling.nodeName == 'SPAN'; + var nextIsSpan = node.nextSibling && node.nextSibling.nodeName == 'SPAN'; + return previousIsSpan && nextIsSpan; + } + + if (type == 1 && node.getAttribute('data-mce-type') == 'bookmark') + return; + + for (i = children.length - 1; i >= 0; i--) + trim(children[i]); + + if (type != 9) { + // Keep non whitespace text nodes + if (type == 3 && node.nodeValue.length > 0) { + // If parent element isn't a block or there isn't any useful contents for example "

    " + // Also keep text nodes with only spaces if surrounded by spans. + // eg. "

    a b

    " should keep space between a and b + var trimmedLength = tinymce.trim(node.nodeValue).length; + if (!t.isBlock(node.parentNode) || trimmedLength > 0 || trimmedLength === 0 && surroundedBySpans(node)) + return; + } else if (type == 1) { + // If the only child is a bookmark then move it up + children = node.childNodes; + if (children.length == 1 && children[0] && children[0].nodeType == 1 && children[0].getAttribute('data-mce-type') == 'bookmark') + node.parentNode.insertBefore(children[0], node); + + // Keep non empty elements or img, hr etc + if (children.length || /^(br|hr|input|img)$/i.test(node.nodeName)) + return; + } + + t.remove(node); + } + + return node; + }; + + if (pe && e) { + // Get before chunk + r.setStart(pe.parentNode, t.nodeIndex(pe)); + r.setEnd(e.parentNode, t.nodeIndex(e)); + bef = r.extractContents(); + + // Get after chunk + r = t.createRng(); + r.setStart(e.parentNode, t.nodeIndex(e) + 1); + r.setEnd(pe.parentNode, t.nodeIndex(pe) + 1); + aft = r.extractContents(); + + // Insert before chunk + pa = pe.parentNode; + pa.insertBefore(trim(bef), pe); + + // Insert middle chunk + if (re) + pa.replaceChild(re, e); + else + pa.insertBefore(e, pe); + + // Insert after chunk + pa.insertBefore(trim(aft), pe); + t.remove(pe); + + return re || e; + } + }, + + bind : function(target, name, func, scope) { + return this.events.add(target, name, func, scope || this); + }, + + unbind : function(target, name, func) { + return this.events.remove(target, name, func); + }, + + fire : function(target, name, evt) { + return this.events.fire(target, name, evt); + }, + + // Returns the content editable state of a node + getContentEditable: function(node) { + var contentEditable; + + // Check type + if (node.nodeType != 1) { + return null; + } + + // Check for fake content editable + contentEditable = node.getAttribute("data-mce-contenteditable"); + if (contentEditable && contentEditable !== "inherit") { + return contentEditable; + } + + // Check for real content editable + return node.contentEditable !== "inherit" ? node.contentEditable : null; + }, + + + _findSib : function(node, selector, name) { + var t = this, f = selector; + + if (node) { + // If expression make a function of it using is + if (is(f, 'string')) { + f = function(node) { + return t.is(node, selector); + }; + } + + // Loop all siblings + for (node = node[name]; node; node = node[name]) { + if (f(node)) + return node; + } + } + + return null; + }, + + _isRes : function(c) { + // Is live resizble element + return /^(top|left|bottom|right|width|height)/i.test(c) || /;\s*(top|left|bottom|right|width|height)/i.test(c); + } + + /* + walk : function(n, f, s) { + var d = this.doc, w; + + if (d.createTreeWalker) { + w = d.createTreeWalker(n, NodeFilter.SHOW_TEXT, null, false); + + while ((n = w.nextNode()) != null) + f.call(s || this, n); + } else + tinymce.walk(n, f, 'childNodes', s); + } + */ + + /* + toRGB : function(s) { + var c = /^\s*?#([0-9A-F]{2})([0-9A-F]{1,2})([0-9A-F]{2})?\s*?$/.exec(s); + + if (c) { + // #FFF -> #FFFFFF + if (!is(c[3])) + c[3] = c[2] = c[1]; + + return "rgb(" + parseInt(c[1], 16) + "," + parseInt(c[2], 16) + "," + parseInt(c[3], 16) + ")"; + } + + return s; + } + */ + }); + + tinymce.DOM = new tinymce.dom.DOMUtils(document, {process_html : 0}); +})(tinymce); + +(function(ns) { + // Range constructor + function Range(dom) { + var t = this, + doc = dom.doc, + EXTRACT = 0, + CLONE = 1, + DELETE = 2, + TRUE = true, + FALSE = false, + START_OFFSET = 'startOffset', + START_CONTAINER = 'startContainer', + END_CONTAINER = 'endContainer', + END_OFFSET = 'endOffset', + extend = tinymce.extend, + nodeIndex = dom.nodeIndex; + + extend(t, { + // Inital states + startContainer : doc, + startOffset : 0, + endContainer : doc, + endOffset : 0, + collapsed : TRUE, + commonAncestorContainer : doc, + + // Range constants + START_TO_START : 0, + START_TO_END : 1, + END_TO_END : 2, + END_TO_START : 3, + + // Public methods + setStart : setStart, + setEnd : setEnd, + setStartBefore : setStartBefore, + setStartAfter : setStartAfter, + setEndBefore : setEndBefore, + setEndAfter : setEndAfter, + collapse : collapse, + selectNode : selectNode, + selectNodeContents : selectNodeContents, + compareBoundaryPoints : compareBoundaryPoints, + deleteContents : deleteContents, + extractContents : extractContents, + cloneContents : cloneContents, + insertNode : insertNode, + surroundContents : surroundContents, + cloneRange : cloneRange, + toStringIE : toStringIE + }); + + function createDocumentFragment() { + return doc.createDocumentFragment(); + }; + + function setStart(n, o) { + _setEndPoint(TRUE, n, o); + }; + + function setEnd(n, o) { + _setEndPoint(FALSE, n, o); + }; + + function setStartBefore(n) { + setStart(n.parentNode, nodeIndex(n)); + }; + + function setStartAfter(n) { + setStart(n.parentNode, nodeIndex(n) + 1); + }; + + function setEndBefore(n) { + setEnd(n.parentNode, nodeIndex(n)); + }; + + function setEndAfter(n) { + setEnd(n.parentNode, nodeIndex(n) + 1); + }; + + function collapse(ts) { + if (ts) { + t[END_CONTAINER] = t[START_CONTAINER]; + t[END_OFFSET] = t[START_OFFSET]; + } else { + t[START_CONTAINER] = t[END_CONTAINER]; + t[START_OFFSET] = t[END_OFFSET]; + } + + t.collapsed = TRUE; + }; + + function selectNode(n) { + setStartBefore(n); + setEndAfter(n); + }; + + function selectNodeContents(n) { + setStart(n, 0); + setEnd(n, n.nodeType === 1 ? n.childNodes.length : n.nodeValue.length); + }; + + function compareBoundaryPoints(h, r) { + var sc = t[START_CONTAINER], so = t[START_OFFSET], ec = t[END_CONTAINER], eo = t[END_OFFSET], + rsc = r.startContainer, rso = r.startOffset, rec = r.endContainer, reo = r.endOffset; + + // Check START_TO_START + if (h === 0) + return _compareBoundaryPoints(sc, so, rsc, rso); + + // Check START_TO_END + if (h === 1) + return _compareBoundaryPoints(ec, eo, rsc, rso); + + // Check END_TO_END + if (h === 2) + return _compareBoundaryPoints(ec, eo, rec, reo); + + // Check END_TO_START + if (h === 3) + return _compareBoundaryPoints(sc, so, rec, reo); + }; + + function deleteContents() { + _traverse(DELETE); + }; + + function extractContents() { + return _traverse(EXTRACT); + }; + + function cloneContents() { + return _traverse(CLONE); + }; + + function insertNode(n) { + var startContainer = this[START_CONTAINER], + startOffset = this[START_OFFSET], nn, o; + + // Node is TEXT_NODE or CDATA + if ((startContainer.nodeType === 3 || startContainer.nodeType === 4) && startContainer.nodeValue) { + if (!startOffset) { + // At the start of text + startContainer.parentNode.insertBefore(n, startContainer); + } else if (startOffset >= startContainer.nodeValue.length) { + // At the end of text + dom.insertAfter(n, startContainer); + } else { + // Middle, need to split + nn = startContainer.splitText(startOffset); + startContainer.parentNode.insertBefore(n, nn); + } + } else { + // Insert element node + if (startContainer.childNodes.length > 0) + o = startContainer.childNodes[startOffset]; + + if (o) + startContainer.insertBefore(n, o); + else + startContainer.appendChild(n); + } + }; + + function surroundContents(n) { + var f = t.extractContents(); + + t.insertNode(n); + n.appendChild(f); + t.selectNode(n); + }; + + function cloneRange() { + return extend(new Range(dom), { + startContainer : t[START_CONTAINER], + startOffset : t[START_OFFSET], + endContainer : t[END_CONTAINER], + endOffset : t[END_OFFSET], + collapsed : t.collapsed, + commonAncestorContainer : t.commonAncestorContainer + }); + }; + + // Private methods + + function _getSelectedNode(container, offset) { + var child; + + if (container.nodeType == 3 /* TEXT_NODE */) + return container; + + if (offset < 0) + return container; + + child = container.firstChild; + while (child && offset > 0) { + --offset; + child = child.nextSibling; + } + + if (child) + return child; + + return container; + }; + + function _isCollapsed() { + return (t[START_CONTAINER] == t[END_CONTAINER] && t[START_OFFSET] == t[END_OFFSET]); + }; + + function _compareBoundaryPoints(containerA, offsetA, containerB, offsetB) { + var c, offsetC, n, cmnRoot, childA, childB; + + // In the first case the boundary-points have the same container. A is before B + // if its offset is less than the offset of B, A is equal to B if its offset is + // equal to the offset of B, and A is after B if its offset is greater than the + // offset of B. + if (containerA == containerB) { + if (offsetA == offsetB) + return 0; // equal + + if (offsetA < offsetB) + return -1; // before + + return 1; // after + } + + // In the second case a child node C of the container of A is an ancestor + // container of B. In this case, A is before B if the offset of A is less than or + // equal to the index of the child node C and A is after B otherwise. + c = containerB; + while (c && c.parentNode != containerA) + c = c.parentNode; + + if (c) { + offsetC = 0; + n = containerA.firstChild; + + while (n != c && offsetC < offsetA) { + offsetC++; + n = n.nextSibling; + } + + if (offsetA <= offsetC) + return -1; // before + + return 1; // after + } + + // In the third case a child node C of the container of B is an ancestor container + // of A. In this case, A is before B if the index of the child node C is less than + // the offset of B and A is after B otherwise. + c = containerA; + while (c && c.parentNode != containerB) { + c = c.parentNode; + } + + if (c) { + offsetC = 0; + n = containerB.firstChild; + + while (n != c && offsetC < offsetB) { + offsetC++; + n = n.nextSibling; + } + + if (offsetC < offsetB) + return -1; // before + + return 1; // after + } + + // In the fourth case, none of three other cases hold: the containers of A and B + // are siblings or descendants of sibling nodes. In this case, A is before B if + // the container of A is before the container of B in a pre-order traversal of the + // Ranges' context tree and A is after B otherwise. + cmnRoot = dom.findCommonAncestor(containerA, containerB); + childA = containerA; + + while (childA && childA.parentNode != cmnRoot) + childA = childA.parentNode; + + if (!childA) + childA = cmnRoot; + + childB = containerB; + while (childB && childB.parentNode != cmnRoot) + childB = childB.parentNode; + + if (!childB) + childB = cmnRoot; + + if (childA == childB) + return 0; // equal + + n = cmnRoot.firstChild; + while (n) { + if (n == childA) + return -1; // before + + if (n == childB) + return 1; // after + + n = n.nextSibling; + } + }; + + function _setEndPoint(st, n, o) { + var ec, sc; + + if (st) { + t[START_CONTAINER] = n; + t[START_OFFSET] = o; + } else { + t[END_CONTAINER] = n; + t[END_OFFSET] = o; + } + + // If one boundary-point of a Range is set to have a root container + // other than the current one for the Range, the Range is collapsed to + // the new position. This enforces the restriction that both boundary- + // points of a Range must have the same root container. + ec = t[END_CONTAINER]; + while (ec.parentNode) + ec = ec.parentNode; + + sc = t[START_CONTAINER]; + while (sc.parentNode) + sc = sc.parentNode; + + if (sc == ec) { + // The start position of a Range is guaranteed to never be after the + // end position. To enforce this restriction, if the start is set to + // be at a position after the end, the Range is collapsed to that + // position. + if (_compareBoundaryPoints(t[START_CONTAINER], t[START_OFFSET], t[END_CONTAINER], t[END_OFFSET]) > 0) + t.collapse(st); + } else + t.collapse(st); + + t.collapsed = _isCollapsed(); + t.commonAncestorContainer = dom.findCommonAncestor(t[START_CONTAINER], t[END_CONTAINER]); + }; + + function _traverse(how) { + var c, endContainerDepth = 0, startContainerDepth = 0, p, depthDiff, startNode, endNode, sp, ep; + + if (t[START_CONTAINER] == t[END_CONTAINER]) + return _traverseSameContainer(how); + + for (c = t[END_CONTAINER], p = c.parentNode; p; c = p, p = p.parentNode) { + if (p == t[START_CONTAINER]) + return _traverseCommonStartContainer(c, how); + + ++endContainerDepth; + } + + for (c = t[START_CONTAINER], p = c.parentNode; p; c = p, p = p.parentNode) { + if (p == t[END_CONTAINER]) + return _traverseCommonEndContainer(c, how); + + ++startContainerDepth; + } + + depthDiff = startContainerDepth - endContainerDepth; + + startNode = t[START_CONTAINER]; + while (depthDiff > 0) { + startNode = startNode.parentNode; + depthDiff--; + } + + endNode = t[END_CONTAINER]; + while (depthDiff < 0) { + endNode = endNode.parentNode; + depthDiff++; + } + + // ascend the ancestor hierarchy until we have a common parent. + for (sp = startNode.parentNode, ep = endNode.parentNode; sp != ep; sp = sp.parentNode, ep = ep.parentNode) { + startNode = sp; + endNode = ep; + } + + return _traverseCommonAncestors(startNode, endNode, how); + }; + + function _traverseSameContainer(how) { + var frag, s, sub, n, cnt, sibling, xferNode, start, len; + + if (how != DELETE) + frag = createDocumentFragment(); + + // If selection is empty, just return the fragment + if (t[START_OFFSET] == t[END_OFFSET]) + return frag; + + // Text node needs special case handling + if (t[START_CONTAINER].nodeType == 3 /* TEXT_NODE */) { + // get the substring + s = t[START_CONTAINER].nodeValue; + sub = s.substring(t[START_OFFSET], t[END_OFFSET]); + + // set the original text node to its new value + if (how != CLONE) { + n = t[START_CONTAINER]; + start = t[START_OFFSET]; + len = t[END_OFFSET] - t[START_OFFSET]; + + if (start === 0 && len >= n.nodeValue.length - 1) { + n.parentNode.removeChild(n); + } else { + n.deleteData(start, len); + } + + // Nothing is partially selected, so collapse to start point + t.collapse(TRUE); + } + + if (how == DELETE) + return; + + if (sub.length > 0) { + frag.appendChild(doc.createTextNode(sub)); + } + + return frag; + } + + // Copy nodes between the start/end offsets. + n = _getSelectedNode(t[START_CONTAINER], t[START_OFFSET]); + cnt = t[END_OFFSET] - t[START_OFFSET]; + + while (n && cnt > 0) { + sibling = n.nextSibling; + xferNode = _traverseFullySelected(n, how); + + if (frag) + frag.appendChild( xferNode ); + + --cnt; + n = sibling; + } + + // Nothing is partially selected, so collapse to start point + if (how != CLONE) + t.collapse(TRUE); + + return frag; + }; + + function _traverseCommonStartContainer(endAncestor, how) { + var frag, n, endIdx, cnt, sibling, xferNode; + + if (how != DELETE) + frag = createDocumentFragment(); + + n = _traverseRightBoundary(endAncestor, how); + + if (frag) + frag.appendChild(n); + + endIdx = nodeIndex(endAncestor); + cnt = endIdx - t[START_OFFSET]; + + if (cnt <= 0) { + // Collapse to just before the endAncestor, which + // is partially selected. + if (how != CLONE) { + t.setEndBefore(endAncestor); + t.collapse(FALSE); + } + + return frag; + } + + n = endAncestor.previousSibling; + while (cnt > 0) { + sibling = n.previousSibling; + xferNode = _traverseFullySelected(n, how); + + if (frag) + frag.insertBefore(xferNode, frag.firstChild); + + --cnt; + n = sibling; + } + + // Collapse to just before the endAncestor, which + // is partially selected. + if (how != CLONE) { + t.setEndBefore(endAncestor); + t.collapse(FALSE); + } + + return frag; + }; + + function _traverseCommonEndContainer(startAncestor, how) { + var frag, startIdx, n, cnt, sibling, xferNode; + + if (how != DELETE) + frag = createDocumentFragment(); + + n = _traverseLeftBoundary(startAncestor, how); + if (frag) + frag.appendChild(n); + + startIdx = nodeIndex(startAncestor); + ++startIdx; // Because we already traversed it + + cnt = t[END_OFFSET] - startIdx; + n = startAncestor.nextSibling; + while (n && cnt > 0) { + sibling = n.nextSibling; + xferNode = _traverseFullySelected(n, how); + + if (frag) + frag.appendChild(xferNode); + + --cnt; + n = sibling; + } + + if (how != CLONE) { + t.setStartAfter(startAncestor); + t.collapse(TRUE); + } + + return frag; + }; + + function _traverseCommonAncestors(startAncestor, endAncestor, how) { + var n, frag, commonParent, startOffset, endOffset, cnt, sibling, nextSibling; + + if (how != DELETE) + frag = createDocumentFragment(); + + n = _traverseLeftBoundary(startAncestor, how); + if (frag) + frag.appendChild(n); + + commonParent = startAncestor.parentNode; + startOffset = nodeIndex(startAncestor); + endOffset = nodeIndex(endAncestor); + ++startOffset; + + cnt = endOffset - startOffset; + sibling = startAncestor.nextSibling; + + while (cnt > 0) { + nextSibling = sibling.nextSibling; + n = _traverseFullySelected(sibling, how); + + if (frag) + frag.appendChild(n); + + sibling = nextSibling; + --cnt; + } + + n = _traverseRightBoundary(endAncestor, how); + + if (frag) + frag.appendChild(n); + + if (how != CLONE) { + t.setStartAfter(startAncestor); + t.collapse(TRUE); + } + + return frag; + }; + + function _traverseRightBoundary(root, how) { + var next = _getSelectedNode(t[END_CONTAINER], t[END_OFFSET] - 1), parent, clonedParent, prevSibling, clonedChild, clonedGrandParent, isFullySelected = next != t[END_CONTAINER]; + + if (next == root) + return _traverseNode(next, isFullySelected, FALSE, how); + + parent = next.parentNode; + clonedParent = _traverseNode(parent, FALSE, FALSE, how); + + while (parent) { + while (next) { + prevSibling = next.previousSibling; + clonedChild = _traverseNode(next, isFullySelected, FALSE, how); + + if (how != DELETE) + clonedParent.insertBefore(clonedChild, clonedParent.firstChild); + + isFullySelected = TRUE; + next = prevSibling; + } + + if (parent == root) + return clonedParent; + + next = parent.previousSibling; + parent = parent.parentNode; + + clonedGrandParent = _traverseNode(parent, FALSE, FALSE, how); + + if (how != DELETE) + clonedGrandParent.appendChild(clonedParent); + + clonedParent = clonedGrandParent; + } + }; + + function _traverseLeftBoundary(root, how) { + var next = _getSelectedNode(t[START_CONTAINER], t[START_OFFSET]), isFullySelected = next != t[START_CONTAINER], parent, clonedParent, nextSibling, clonedChild, clonedGrandParent; + + if (next == root) + return _traverseNode(next, isFullySelected, TRUE, how); + + parent = next.parentNode; + clonedParent = _traverseNode(parent, FALSE, TRUE, how); + + while (parent) { + while (next) { + nextSibling = next.nextSibling; + clonedChild = _traverseNode(next, isFullySelected, TRUE, how); + + if (how != DELETE) + clonedParent.appendChild(clonedChild); + + isFullySelected = TRUE; + next = nextSibling; + } + + if (parent == root) + return clonedParent; + + next = parent.nextSibling; + parent = parent.parentNode; + + clonedGrandParent = _traverseNode(parent, FALSE, TRUE, how); + + if (how != DELETE) + clonedGrandParent.appendChild(clonedParent); + + clonedParent = clonedGrandParent; + } + }; + + function _traverseNode(n, isFullySelected, isLeft, how) { + var txtValue, newNodeValue, oldNodeValue, offset, newNode; + + if (isFullySelected) + return _traverseFullySelected(n, how); + + if (n.nodeType == 3 /* TEXT_NODE */) { + txtValue = n.nodeValue; + + if (isLeft) { + offset = t[START_OFFSET]; + newNodeValue = txtValue.substring(offset); + oldNodeValue = txtValue.substring(0, offset); + } else { + offset = t[END_OFFSET]; + newNodeValue = txtValue.substring(0, offset); + oldNodeValue = txtValue.substring(offset); + } + + if (how != CLONE) + n.nodeValue = oldNodeValue; + + if (how == DELETE) + return; + + newNode = dom.clone(n, FALSE); + newNode.nodeValue = newNodeValue; + + return newNode; + } + + if (how == DELETE) + return; + + return dom.clone(n, FALSE); + }; + + function _traverseFullySelected(n, how) { + if (how != DELETE) + return how == CLONE ? dom.clone(n, TRUE) : n; + + n.parentNode.removeChild(n); + }; + + function toStringIE() { + return dom.create('body', null, cloneContents()).outerText; + } + + return t; + }; + + ns.Range = Range; + + // Older IE versions doesn't let you override toString by it's constructor so we have to stick it in the prototype + Range.prototype.toString = function() { + return this.toStringIE(); + }; +})(tinymce.dom); + +(function() { + function Selection(selection) { + var self = this, dom = selection.dom, TRUE = true, FALSE = false; + + function getPosition(rng, start) { + var checkRng, startIndex = 0, endIndex, inside, + children, child, offset, index, position = -1, parent; + + // Setup test range, collapse it and get the parent + checkRng = rng.duplicate(); + checkRng.collapse(start); + parent = checkRng.parentElement(); + + // Check if the selection is within the right document + if (parent.ownerDocument !== selection.dom.doc) + return; + + // IE will report non editable elements as it's parent so look for an editable one + while (parent.contentEditable === "false") { + parent = parent.parentNode; + } + + // If parent doesn't have any children then return that we are inside the element + if (!parent.hasChildNodes()) { + return {node : parent, inside : 1}; + } + + // Setup node list and endIndex + children = parent.children; + endIndex = children.length - 1; + + // Perform a binary search for the position + while (startIndex <= endIndex) { + index = Math.floor((startIndex + endIndex) / 2); + + // Move selection to node and compare the ranges + child = children[index]; + checkRng.moveToElementText(child); + position = checkRng.compareEndPoints(start ? 'StartToStart' : 'EndToEnd', rng); + + // Before/after or an exact match + if (position > 0) { + endIndex = index - 1; + } else if (position < 0) { + startIndex = index + 1; + } else { + return {node : child}; + } + } + + // Check if child position is before or we didn't find a position + if (position < 0) { + // No element child was found use the parent element and the offset inside that + if (!child) { + checkRng.moveToElementText(parent); + checkRng.collapse(true); + child = parent; + inside = true; + } else + checkRng.collapse(false); + + // Walk character by character in text node until we hit the selected range endpoint, hit the end of document or parent isn't the right one + // We need to walk char by char since rng.text or rng.htmlText will trim line endings + offset = 0; + while (checkRng.compareEndPoints(start ? 'StartToStart' : 'StartToEnd', rng) !== 0) { + if (checkRng.move('character', 1) === 0 || parent != checkRng.parentElement()) { + break; + } + + offset++; + } + } else { + // Child position is after the selection endpoint + checkRng.collapse(true); + + // Walk character by character in text node until we hit the selected range endpoint, hit the end of document or parent isn't the right one + offset = 0; + while (checkRng.compareEndPoints(start ? 'StartToStart' : 'StartToEnd', rng) !== 0) { + if (checkRng.move('character', -1) === 0 || parent != checkRng.parentElement()) { + break; + } + + offset++; + } + } + + return {node : child, position : position, offset : offset, inside : inside}; + }; + + // Returns a W3C DOM compatible range object by using the IE Range API + function getRange() { + var ieRange = selection.getRng(), domRange = dom.createRng(), element, collapsed, tmpRange, element2, bookmark, fail; + + // If selection is outside the current document just return an empty range + element = ieRange.item ? ieRange.item(0) : ieRange.parentElement(); + if (element.ownerDocument != dom.doc) + return domRange; + + collapsed = selection.isCollapsed(); + + // Handle control selection + if (ieRange.item) { + domRange.setStart(element.parentNode, dom.nodeIndex(element)); + domRange.setEnd(domRange.startContainer, domRange.startOffset + 1); + + return domRange; + } + + function findEndPoint(start) { + var endPoint = getPosition(ieRange, start), container, offset, textNodeOffset = 0, sibling, undef, nodeValue; + + container = endPoint.node; + offset = endPoint.offset; + + if (endPoint.inside && !container.hasChildNodes()) { + domRange[start ? 'setStart' : 'setEnd'](container, 0); + return; + } + + if (offset === undef) { + domRange[start ? 'setStartBefore' : 'setEndAfter'](container); + return; + } + + if (endPoint.position < 0) { + sibling = endPoint.inside ? container.firstChild : container.nextSibling; + + if (!sibling) { + domRange[start ? 'setStartAfter' : 'setEndAfter'](container); + return; + } + + if (!offset) { + if (sibling.nodeType == 3) + domRange[start ? 'setStart' : 'setEnd'](sibling, 0); + else + domRange[start ? 'setStartBefore' : 'setEndBefore'](sibling); + + return; + } + + // Find the text node and offset + while (sibling) { + nodeValue = sibling.nodeValue; + textNodeOffset += nodeValue.length; + + // We are at or passed the position we where looking for + if (textNodeOffset >= offset) { + container = sibling; + textNodeOffset -= offset; + textNodeOffset = nodeValue.length - textNodeOffset; + break; + } + + sibling = sibling.nextSibling; + } + } else { + // Find the text node and offset + sibling = container.previousSibling; + + if (!sibling) + return domRange[start ? 'setStartBefore' : 'setEndBefore'](container); + + // If there isn't any text to loop then use the first position + if (!offset) { + if (container.nodeType == 3) + domRange[start ? 'setStart' : 'setEnd'](sibling, container.nodeValue.length); + else + domRange[start ? 'setStartAfter' : 'setEndAfter'](sibling); + + return; + } + + while (sibling) { + textNodeOffset += sibling.nodeValue.length; + + // We are at or passed the position we where looking for + if (textNodeOffset >= offset) { + container = sibling; + textNodeOffset -= offset; + break; + } + + sibling = sibling.previousSibling; + } + } + + domRange[start ? 'setStart' : 'setEnd'](container, textNodeOffset); + }; + + try { + // Find start point + findEndPoint(true); + + // Find end point if needed + if (!collapsed) + findEndPoint(); + } catch (ex) { + // IE has a nasty bug where text nodes might throw "invalid argument" when you + // access the nodeValue or other properties of text nodes. This seems to happend when + // text nodes are split into two nodes by a delete/backspace call. So lets detect it and try to fix it. + if (ex.number == -2147024809) { + // Get the current selection + bookmark = self.getBookmark(2); + + // Get start element + tmpRange = ieRange.duplicate(); + tmpRange.collapse(true); + element = tmpRange.parentElement(); + + // Get end element + if (!collapsed) { + tmpRange = ieRange.duplicate(); + tmpRange.collapse(false); + element2 = tmpRange.parentElement(); + element2.innerHTML = element2.innerHTML; + } + + // Remove the broken elements + element.innerHTML = element.innerHTML; + + // Restore the selection + self.moveToBookmark(bookmark); + + // Since the range has moved we need to re-get it + ieRange = selection.getRng(); + + // Find start point + findEndPoint(true); + + // Find end point if needed + if (!collapsed) + findEndPoint(); + } else + throw ex; // Throw other errors + } + + return domRange; + }; + + this.getBookmark = function(type) { + var rng = selection.getRng(), start, end, bookmark = {}; + + function getIndexes(node) { + var parent, root, children, i, indexes = []; + + parent = node.parentNode; + root = dom.getRoot().parentNode; + + while (parent != root && parent.nodeType !== 9) { + children = parent.children; + + i = children.length; + while (i--) { + if (node === children[i]) { + indexes.push(i); + break; + } + } + + node = parent; + parent = parent.parentNode; + } + + return indexes; + }; + + function getBookmarkEndPoint(start) { + var position; + + position = getPosition(rng, start); + if (position) { + return { + position : position.position, + offset : position.offset, + indexes : getIndexes(position.node), + inside : position.inside + }; + } + }; + + // Non ubstructive bookmark + if (type === 2) { + // Handle text selection + if (!rng.item) { + bookmark.start = getBookmarkEndPoint(true); + + if (!selection.isCollapsed()) + bookmark.end = getBookmarkEndPoint(); + } else + bookmark.start = {ctrl : true, indexes : getIndexes(rng.item(0))}; + } + + return bookmark; + }; + + this.moveToBookmark = function(bookmark) { + var rng, body = dom.doc.body; + + function resolveIndexes(indexes) { + var node, i, idx, children; + + node = dom.getRoot(); + for (i = indexes.length - 1; i >= 0; i--) { + children = node.children; + idx = indexes[i]; + + if (idx <= children.length - 1) { + node = children[idx]; + } + } + + return node; + }; + + function setBookmarkEndPoint(start) { + var endPoint = bookmark[start ? 'start' : 'end'], moveLeft, moveRng, undef; + + if (endPoint) { + moveLeft = endPoint.position > 0; + + moveRng = body.createTextRange(); + moveRng.moveToElementText(resolveIndexes(endPoint.indexes)); + + offset = endPoint.offset; + if (offset !== undef) { + moveRng.collapse(endPoint.inside || moveLeft); + moveRng.moveStart('character', moveLeft ? -offset : offset); + } else + moveRng.collapse(start); + + rng.setEndPoint(start ? 'StartToStart' : 'EndToStart', moveRng); + + if (start) + rng.collapse(true); + } + }; + + if (bookmark.start) { + if (bookmark.start.ctrl) { + rng = body.createControlRange(); + rng.addElement(resolveIndexes(bookmark.start.indexes)); + rng.select(); + } else { + rng = body.createTextRange(); + setBookmarkEndPoint(true); + setBookmarkEndPoint(); + rng.select(); + } + } + }; + + this.addRange = function(rng) { + var ieRng, ctrlRng, startContainer, startOffset, endContainer, endOffset, sibling, + doc = selection.dom.doc, body = doc.body, nativeRng, ctrlElm; + + function setEndPoint(start) { + var container, offset, marker, tmpRng, nodes; + + marker = dom.create('a'); + container = start ? startContainer : endContainer; + offset = start ? startOffset : endOffset; + tmpRng = ieRng.duplicate(); + + if (container == doc || container == doc.documentElement) { + container = body; + offset = 0; + } + + if (container.nodeType == 3) { + container.parentNode.insertBefore(marker, container); + tmpRng.moveToElementText(marker); + tmpRng.moveStart('character', offset); + dom.remove(marker); + ieRng.setEndPoint(start ? 'StartToStart' : 'EndToEnd', tmpRng); + } else { + nodes = container.childNodes; + + if (nodes.length) { + if (offset >= nodes.length) { + dom.insertAfter(marker, nodes[nodes.length - 1]); + } else { + container.insertBefore(marker, nodes[offset]); + } + + tmpRng.moveToElementText(marker); + } else if (container.canHaveHTML) { + // Empty node selection for example
    |
    + // Setting innerHTML with a span marker then remove that marker seems to keep empty block elements open + container.innerHTML = '\uFEFF'; + marker = container.firstChild; + tmpRng.moveToElementText(marker); + tmpRng.collapse(FALSE); // Collapse false works better than true for some odd reason + } + + ieRng.setEndPoint(start ? 'StartToStart' : 'EndToEnd', tmpRng); + dom.remove(marker); + } + } + + // Setup some shorter versions + startContainer = rng.startContainer; + startOffset = rng.startOffset; + endContainer = rng.endContainer; + endOffset = rng.endOffset; + ieRng = body.createTextRange(); + + // If single element selection then try making a control selection out of it + if (startContainer == endContainer && startContainer.nodeType == 1) { + // Trick to place the caret inside an empty block element like

    + if (startOffset == endOffset && !startContainer.hasChildNodes()) { + if (startContainer.canHaveHTML) { + // Check if previous sibling is an empty block if it is then we need to render it + // IE would otherwise move the caret into the sibling instead of the empty startContainer see: #5236 + // Example this:

    |

    would become this:

    |

    + sibling = startContainer.previousSibling; + if (sibling && !sibling.hasChildNodes() && dom.isBlock(sibling)) { + sibling.innerHTML = '\uFEFF'; + } else { + sibling = null; + } + + startContainer.innerHTML = '\uFEFF\uFEFF'; + ieRng.moveToElementText(startContainer.lastChild); + ieRng.select(); + dom.doc.selection.clear(); + startContainer.innerHTML = ''; + + if (sibling) { + sibling.innerHTML = ''; + } + return; + } else { + startOffset = dom.nodeIndex(startContainer); + startContainer = startContainer.parentNode; + } + } + + if (startOffset == endOffset - 1) { + try { + ctrlElm = startContainer.childNodes[startOffset]; + ctrlRng = body.createControlRange(); + ctrlRng.addElement(ctrlElm); + ctrlRng.select(); + + // Check if the range produced is on the correct element and is a control range + // On IE 8 it will select the parent contentEditable container if you select an inner element see: #5398 + nativeRng = selection.getRng(); + if (nativeRng.item && ctrlElm === nativeRng.item(0)) { + return; + } + } catch (ex) { + // Ignore + } + } + } + + // Set start/end point of selection + setEndPoint(true); + setEndPoint(); + + // Select the new range and scroll it into view + ieRng.select(); + }; + + // Expose range method + this.getRangeAt = getRange; + }; + + // Expose the selection object + tinymce.dom.TridentSelection = Selection; +})(); + + +(function(tinymce) { + tinymce.dom.Element = function(id, settings) { + var t = this, dom, el; + + t.settings = settings = settings || {}; + t.id = id; + t.dom = dom = settings.dom || tinymce.DOM; + + // Only IE leaks DOM references, this is a lot faster + if (!tinymce.isIE) + el = dom.get(t.id); + + tinymce.each( + ('getPos,getRect,getParent,add,setStyle,getStyle,setStyles,' + + 'setAttrib,setAttribs,getAttrib,addClass,removeClass,' + + 'hasClass,getOuterHTML,setOuterHTML,remove,show,hide,' + + 'isHidden,setHTML,get').split(/,/), function(k) { + t[k] = function() { + var a = [id], i; + + for (i = 0; i < arguments.length; i++) + a.push(arguments[i]); + + a = dom[k].apply(dom, a); + t.update(k); + + return a; + }; + } + ); + + tinymce.extend(t, { + on : function(n, f, s) { + return tinymce.dom.Event.add(t.id, n, f, s); + }, + + getXY : function() { + return { + x : parseInt(t.getStyle('left')), + y : parseInt(t.getStyle('top')) + }; + }, + + getSize : function() { + var n = dom.get(t.id); + + return { + w : parseInt(t.getStyle('width') || n.clientWidth), + h : parseInt(t.getStyle('height') || n.clientHeight) + }; + }, + + moveTo : function(x, y) { + t.setStyles({left : x, top : y}); + }, + + moveBy : function(x, y) { + var p = t.getXY(); + + t.moveTo(p.x + x, p.y + y); + }, + + resizeTo : function(w, h) { + t.setStyles({width : w, height : h}); + }, + + resizeBy : function(w, h) { + var s = t.getSize(); + + t.resizeTo(s.w + w, s.h + h); + }, + + update : function(k) { + var b; + + if (tinymce.isIE6 && settings.blocker) { + k = k || ''; + + // Ignore getters + if (k.indexOf('get') === 0 || k.indexOf('has') === 0 || k.indexOf('is') === 0) + return; + + // Remove blocker on remove + if (k == 'remove') { + dom.remove(t.blocker); + return; + } + + if (!t.blocker) { + t.blocker = dom.uniqueId(); + b = dom.add(settings.container || dom.getRoot(), 'iframe', {id : t.blocker, style : 'position:absolute;', frameBorder : 0, src : 'javascript:""'}); + dom.setStyle(b, 'opacity', 0); + } else + b = dom.get(t.blocker); + + dom.setStyles(b, { + left : t.getStyle('left', 1), + top : t.getStyle('top', 1), + width : t.getStyle('width', 1), + height : t.getStyle('height', 1), + display : t.getStyle('display', 1), + zIndex : parseInt(t.getStyle('zIndex', 1) || 0) - 1 + }); + } + } + }); + }; +})(tinymce); + +(function(tinymce) { + function trimNl(s) { + return s.replace(/[\n\r]+/g, ''); + }; + + // Shorten names + var is = tinymce.is, isIE = tinymce.isIE, each = tinymce.each, TreeWalker = tinymce.dom.TreeWalker; + + tinymce.create('tinymce.dom.Selection', { + Selection : function(dom, win, serializer, editor) { + var t = this; + + t.dom = dom; + t.win = win; + t.serializer = serializer; + t.editor = editor; + + // Add events + each([ + 'onBeforeSetContent', + + 'onBeforeGetContent', + + 'onSetContent', + + 'onGetContent' + ], function(e) { + t[e] = new tinymce.util.Dispatcher(t); + }); + + // No W3C Range support + if (!t.win.getSelection) + t.tridentSel = new tinymce.dom.TridentSelection(t); + + if (tinymce.isIE && ! tinymce.isIE11 && dom.boxModel) + this._fixIESelection(); + + // Prevent leaks + tinymce.addUnload(t.destroy, t); + }, + + setCursorLocation: function(node, offset) { + var t = this; var r = t.dom.createRng(); + r.setStart(node, offset); + r.setEnd(node, offset); + t.setRng(r); + t.collapse(false); + }, + getContent : function(s) { + var t = this, r = t.getRng(), e = t.dom.create("body"), se = t.getSel(), wb, wa, n; + + s = s || {}; + wb = wa = ''; + s.get = true; + s.format = s.format || 'html'; + s.forced_root_block = ''; + t.onBeforeGetContent.dispatch(t, s); + + if (s.format == 'text') + return t.isCollapsed() ? '' : (r.text || (se.toString ? se.toString() : '')); + + if (r.cloneContents) { + n = r.cloneContents(); + + if (n) + e.appendChild(n); + } else if (is(r.item) || is(r.htmlText)) { + // IE will produce invalid markup if elements are present that + // it doesn't understand like custom elements or HTML5 elements. + // Adding a BR in front of the contents and then remoiving it seems to fix it though. + e.innerHTML = '
    ' + (r.item ? r.item(0).outerHTML : r.htmlText); + e.removeChild(e.firstChild); + } else + e.innerHTML = r.toString(); + + // Keep whitespace before and after + if (/^\s/.test(e.innerHTML)) + wb = ' '; + + if (/\s+$/.test(e.innerHTML)) + wa = ' '; + + s.getInner = true; + + s.content = t.isCollapsed() ? '' : wb + t.serializer.serialize(e, s) + wa; + t.onGetContent.dispatch(t, s); + + return s.content; + }, + + setContent : function(content, args) { + var self = this, rng = self.getRng(), caretNode, doc = self.win.document, frag, temp; + + args = args || {format : 'html'}; + args.set = true; + content = args.content = content; + + // Dispatch before set content event + if (!args.no_events) + self.onBeforeSetContent.dispatch(self, args); + + content = args.content; + + if (rng.insertNode) { + // Make caret marker since insertNode places the caret in the beginning of text after insert + content += '_'; + + // Delete and insert new node + if (rng.startContainer == doc && rng.endContainer == doc) { + // WebKit will fail if the body is empty since the range is then invalid and it can't insert contents + doc.body.innerHTML = content; + } else { + rng.deleteContents(); + + if (doc.body.childNodes.length === 0) { + doc.body.innerHTML = content; + } else { + // createContextualFragment doesn't exists in IE 9 DOMRanges + if (rng.createContextualFragment) { + rng.insertNode(rng.createContextualFragment(content)); + } else { + // Fake createContextualFragment call in IE 9 + frag = doc.createDocumentFragment(); + temp = doc.createElement('div'); + + frag.appendChild(temp); + temp.outerHTML = content; + + rng.insertNode(frag); + } + } + } + + // Move to caret marker + caretNode = self.dom.get('__caret'); + + // Make sure we wrap it compleatly, Opera fails with a simple select call + rng = doc.createRange(); + rng.setStartBefore(caretNode); + rng.setEndBefore(caretNode); + self.setRng(rng); + + // Remove the caret position + self.dom.remove('__caret'); + + try { + self.setRng(rng); + } catch (ex) { + // Might fail on Opera for some odd reason + } + } else { + if (rng.item) { + // Delete content and get caret text selection + doc.execCommand('Delete', false, null); + rng = self.getRng(); + } + + // Explorer removes spaces from the beginning of pasted contents + if (/^\s+/.test(content)) { + rng.pasteHTML('_' + content); + self.dom.remove('__mce_tmp'); + } else + rng.pasteHTML(content); + } + + // Dispatch set content event + if (!args.no_events) + self.onSetContent.dispatch(self, args); + }, + + getStart : function() { + var self = this, rng = self.getRng(), startElement, parentElement, checkRng, node; + + if (rng.duplicate || rng.item) { + // Control selection, return first item + if (rng.item) + return rng.item(0); + + // Get start element + checkRng = rng.duplicate(); + checkRng.collapse(1); + startElement = checkRng.parentElement(); + if (startElement.ownerDocument !== self.dom.doc) { + startElement = self.dom.getRoot(); + } + + // Check if range parent is inside the start element, then return the inner parent element + // This will fix issues when a single element is selected, IE would otherwise return the wrong start element + parentElement = node = rng.parentElement(); + while (node = node.parentNode) { + if (node == startElement) { + startElement = parentElement; + break; + } + } + + return startElement; + } else { + startElement = rng.startContainer; + + if (startElement.nodeType == 1 && startElement.hasChildNodes()) + startElement = startElement.childNodes[Math.min(startElement.childNodes.length - 1, rng.startOffset)]; + + if (startElement && startElement.nodeType == 3) + return startElement.parentNode; + + return startElement; + } + }, + + getEnd : function() { + var self = this, rng = self.getRng(), endElement, endOffset; + + if (rng.duplicate || rng.item) { + if (rng.item) + return rng.item(0); + + rng = rng.duplicate(); + rng.collapse(0); + endElement = rng.parentElement(); + if (endElement.ownerDocument !== self.dom.doc) { + endElement = self.dom.getRoot(); + } + + if (endElement && endElement.nodeName == 'BODY') + return endElement.lastChild || endElement; + + return endElement; + } else { + endElement = rng.endContainer; + endOffset = rng.endOffset; + + if (endElement.nodeType == 1 && endElement.hasChildNodes()) + endElement = endElement.childNodes[endOffset > 0 ? endOffset - 1 : endOffset]; + + if (endElement && endElement.nodeType == 3) + return endElement.parentNode; + + return endElement; + } + }, + + getBookmark : function(type, normalized) { + var t = this, dom = t.dom, rng, rng2, id, collapsed, name, element, index, chr = '\uFEFF', styles; + + function findIndex(name, element) { + var index = 0; + + each(dom.select(name), function(node, i) { + if (node == element) + index = i; + }); + + return index; + }; + + function normalizeTableCellSelection(rng) { + function moveEndPoint(start) { + var container, offset, childNodes, prefix = start ? 'start' : 'end'; + + container = rng[prefix + 'Container']; + offset = rng[prefix + 'Offset']; + + if (container.nodeType == 1 && container.nodeName == "TR") { + childNodes = container.childNodes; + container = childNodes[Math.min(start ? offset : offset - 1, childNodes.length - 1)]; + if (container) { + offset = start ? 0 : container.childNodes.length; + rng['set' + (start ? 'Start' : 'End')](container, offset); + } + } + }; + + moveEndPoint(true); + moveEndPoint(); + + return rng; + }; + + function getLocation() { + var rng = t.getRng(true), root = dom.getRoot(), bookmark = {}; + + function getPoint(rng, start) { + var container = rng[start ? 'startContainer' : 'endContainer'], + offset = rng[start ? 'startOffset' : 'endOffset'], point = [], node, childNodes, after = 0; + + if (container.nodeType == 3) { + if (normalized) { + for (node = container.previousSibling; node && node.nodeType == 3; node = node.previousSibling) + offset += node.nodeValue.length; + } + + point.push(offset); + } else { + childNodes = container.childNodes; + + if (offset >= childNodes.length && childNodes.length) { + after = 1; + offset = Math.max(0, childNodes.length - 1); + } + + point.push(t.dom.nodeIndex(childNodes[offset], normalized) + after); + } + + for (; container && container != root; container = container.parentNode) + point.push(t.dom.nodeIndex(container, normalized)); + + return point; + }; + + bookmark.start = getPoint(rng, true); + + if (!t.isCollapsed()) + bookmark.end = getPoint(rng); + + return bookmark; + }; + + if (type == 2) { + if (t.tridentSel) + return t.tridentSel.getBookmark(type); + + return getLocation(); + } + + // Handle simple range + if (type) { + rng = t.getRng(); + + if (rng.setStart) { + rng = { + startContainer: rng.startContainer, + startOffset: rng.startOffset, + endContainer: rng.endContainer, + endOffset: rng.endOffset + }; + } + + return {rng : rng}; + } + + rng = t.getRng(); + id = dom.uniqueId(); + collapsed = tinyMCE.activeEditor.selection.isCollapsed(); + styles = 'overflow:hidden;line-height:0px'; + + // Explorer method + if (rng.duplicate || rng.item) { + // Text selection + if (!rng.item) { + rng2 = rng.duplicate(); + + try { + // Insert start marker + rng.collapse(); + rng.pasteHTML('' + chr + ''); + + // Insert end marker + if (!collapsed) { + rng2.collapse(false); + + // Detect the empty space after block elements in IE and move the end back one character

    ] becomes

    ]

    + rng.moveToElementText(rng2.parentElement()); + if (rng.compareEndPoints('StartToEnd', rng2) === 0) + rng2.move('character', -1); + + rng2.pasteHTML('' + chr + ''); + } + } catch (ex) { + // IE might throw unspecified error so lets ignore it + return null; + } + } else { + // Control selection + element = rng.item(0); + name = element.nodeName; + + return {name : name, index : findIndex(name, element)}; + } + } else { + element = t.getNode(); + name = element.nodeName; + if (name == 'IMG') + return {name : name, index : findIndex(name, element)}; + + // W3C method + rng2 = normalizeTableCellSelection(rng.cloneRange()); + + // Insert end marker + if (!collapsed) { + rng2.collapse(false); + rng2.insertNode(dom.create('span', {'data-mce-type' : "bookmark", id : id + '_end', style : styles}, chr)); + } + + rng = normalizeTableCellSelection(rng); + rng.collapse(true); + rng.insertNode(dom.create('span', {'data-mce-type' : "bookmark", id : id + '_start', style : styles}, chr)); + } + + t.moveToBookmark({id : id, keep : 1}); + + return {id : id}; + }, + + moveToBookmark : function(bookmark) { + var t = this, dom = t.dom, marker1, marker2, rng, rng2, root, startContainer, endContainer, startOffset, endOffset; + + function setEndPoint(start) { + var point = bookmark[start ? 'start' : 'end'], i, node, offset, children; + + if (point) { + offset = point[0]; + + // Find container node + for (node = root, i = point.length - 1; i >= 1; i--) { + children = node.childNodes; + + if (point[i] > children.length - 1) + return; + + node = children[point[i]]; + } + + // Move text offset to best suitable location + if (node.nodeType === 3) + offset = Math.min(point[0], node.nodeValue.length); + + // Move element offset to best suitable location + if (node.nodeType === 1) + offset = Math.min(point[0], node.childNodes.length); + + // Set offset within container node + if (start) + rng.setStart(node, offset); + else + rng.setEnd(node, offset); + } + + return true; + }; + + function restoreEndPoint(suffix) { + var marker = dom.get(bookmark.id + '_' + suffix), node, idx, next, prev, keep = bookmark.keep; + + if (marker) { + node = marker.parentNode; + + if (suffix == 'start') { + if (!keep) { + idx = dom.nodeIndex(marker); + } else { + node = marker.firstChild; + idx = 1; + } + + startContainer = endContainer = node; + startOffset = endOffset = idx; + } else { + if (!keep) { + idx = dom.nodeIndex(marker); + } else { + node = marker.firstChild; + idx = 1; + } + + endContainer = node; + endOffset = idx; + } + + if (!keep) { + prev = marker.previousSibling; + next = marker.nextSibling; + + // Remove all marker text nodes + each(tinymce.grep(marker.childNodes), function(node) { + if (node.nodeType == 3) + node.nodeValue = node.nodeValue.replace(/\uFEFF/g, ''); + }); + + // Remove marker but keep children if for example contents where inserted into the marker + // Also remove duplicated instances of the marker for example by a split operation or by WebKit auto split on paste feature + while (marker = dom.get(bookmark.id + '_' + suffix)) + dom.remove(marker, 1); + + // If siblings are text nodes then merge them unless it's Opera since it some how removes the node + // and we are sniffing since adding a lot of detection code for a browser with 3% of the market isn't worth the effort. Sorry, Opera but it's just a fact + if (prev && next && prev.nodeType == next.nodeType && prev.nodeType == 3 && !tinymce.isOpera) { + idx = prev.nodeValue.length; + prev.appendData(next.nodeValue); + dom.remove(next); + + if (suffix == 'start') { + startContainer = endContainer = prev; + startOffset = endOffset = idx; + } else { + endContainer = prev; + endOffset = idx; + } + } + } + } + }; + + function addBogus(node) { + // Adds a bogus BR element for empty block elements + if (dom.isBlock(node) && !node.innerHTML && !isIE) + node.innerHTML = '
    '; + + return node; + }; + + if (bookmark) { + if (bookmark.start) { + rng = dom.createRng(); + root = dom.getRoot(); + + if (t.tridentSel) + return t.tridentSel.moveToBookmark(bookmark); + + if (setEndPoint(true) && setEndPoint()) { + t.setRng(rng); + } + } else if (bookmark.id) { + // Restore start/end points + restoreEndPoint('start'); + restoreEndPoint('end'); + + if (startContainer) { + rng = dom.createRng(); + rng.setStart(addBogus(startContainer), startOffset); + rng.setEnd(addBogus(endContainer), endOffset); + t.setRng(rng); + } + } else if (bookmark.name) { + t.select(dom.select(bookmark.name)[bookmark.index]); + } else if (bookmark.rng) { + rng = bookmark.rng; + + if (rng.startContainer) { + rng2 = t.dom.createRng(); + + try { + rng2.setStart(rng.startContainer, rng.startOffset); + rng2.setEnd(rng.endContainer, rng.endOffset); + } catch (e) { + // Might fail with index error + } + + rng = rng2; + } + + t.setRng(rng); + } + } + }, + + select : function(node, content) { + var t = this, dom = t.dom, rng = dom.createRng(), idx; + + function setPoint(node, start) { + var walker = new TreeWalker(node, node); + + do { + // Text node + if (node.nodeType == 3 && tinymce.trim(node.nodeValue).length !== 0) { + if (start) + rng.setStart(node, 0); + else + rng.setEnd(node, node.nodeValue.length); + + return; + } + + // BR element + if (node.nodeName == 'BR') { + if (start) + rng.setStartBefore(node); + else + rng.setEndBefore(node); + + return; + } + } while (node = (start ? walker.next() : walker.prev())); + }; + + if (node) { + idx = dom.nodeIndex(node); + rng.setStart(node.parentNode, idx); + rng.setEnd(node.parentNode, idx + 1); + + // Find first/last text node or BR element + if (content) { + setPoint(node, 1); + setPoint(node); + } + + t.setRng(rng); + } + + return node; + }, + + isCollapsed : function() { + var t = this, r = t.getRng(), s = t.getSel(); + + if (!r || r.item) + return false; + + if (r.compareEndPoints) + return r.compareEndPoints('StartToEnd', r) === 0; + + return !s || r.collapsed; + }, + + collapse : function(to_start) { + var self = this, rng = self.getRng(), node; + + // Control range on IE + if (rng.item) { + node = rng.item(0); + rng = self.win.document.body.createTextRange(); + rng.moveToElementText(node); + } + + rng.collapse(!!to_start); + self.setRng(rng); + }, + + getSel : function() { + var t = this, w = this.win; + + return w.getSelection ? w.getSelection() : w.document.selection; + }, + + getRng : function(w3c) { + var self = this, selection, rng, elm, doc = self.win.document; + + // Workaround for IE 11 not being able to select images properly see #6613 see quirk fix + if (self.fakeRng) { + return self.fakeRng; + } + + // Found tridentSel object then we need to use that one + if (w3c && self.tridentSel) { + return self.tridentSel.getRangeAt(0); + } + + try { + if (selection = self.getSel()) { + rng = selection.rangeCount > 0 ? selection.getRangeAt(0) : (selection.createRange ? selection.createRange() : doc.createRange()); + } + } catch (ex) { + // IE throws unspecified error here if TinyMCE is placed in a frame/iframe + } + + // We have W3C ranges and it's IE then fake control selection since IE9 doesn't handle that correctly yet + if (tinymce.isIE && ! tinymce.isIE11 && rng && rng.setStart && doc.selection.createRange().item) { + elm = doc.selection.createRange().item(0); + rng = doc.createRange(); + rng.setStartBefore(elm); + rng.setEndAfter(elm); + } + + // No range found then create an empty one + // This can occur when the editor is placed in a hidden container element on Gecko + // Or on IE when there was an exception + if (!rng) { + rng = doc.createRange ? doc.createRange() : doc.body.createTextRange(); + } + + // If range is at start of document then move it to start of body + if (rng.setStart && rng.startContainer.nodeType === 9 && rng.collapsed) { + elm = self.dom.getRoot(); + rng.setStart(elm, 0); + rng.setEnd(elm, 0); + } + + if (self.selectedRange && self.explicitRange) { + if (rng.compareBoundaryPoints(rng.START_TO_START, self.selectedRange) === 0 && rng.compareBoundaryPoints(rng.END_TO_END, self.selectedRange) === 0) { + // Safari, Opera and Chrome only ever select text which causes the range to change. + // This lets us use the originally set range if the selection hasn't been changed by the user. + rng = self.explicitRange; + } else { + self.selectedRange = null; + self.explicitRange = null; + } + } + + return rng; + }, + + setRng : function(r, forward) { + var s, t = this; + + if (!t.tridentSel) { + s = t.getSel(); + + if (s) { + t.explicitRange = r; + + try { + s.removeAllRanges(); + } catch (ex) { + // IE9 might throw errors here don't know why + } + + s.addRange(r); + + // Forward is set to false and we have an extend function + if (forward === false && s.extend) { + s.collapse(r.endContainer, r.endOffset); + s.extend(r.startContainer, r.startOffset); + } + + // adding range isn't always successful so we need to check range count otherwise an exception can occur + t.selectedRange = s.rangeCount > 0 ? s.getRangeAt(0) : null; + } + } else { + // Is W3C Range + if (r.cloneRange) { + try { + t.tridentSel.addRange(r); + return; + } catch (ex) { + //IE9 throws an error here if called before selection is placed in the editor + } + } + + // Is IE specific range + try { + r.select(); + } catch (ex) { + // Needed for some odd IE bug #1843306 + } + } + }, + + setNode : function(n) { + var t = this; + + t.setContent(t.dom.getOuterHTML(n)); + + return n; + }, + + getNode : function() { + var t = this, rng = t.getRng(), sel = t.getSel(), elm, start = rng.startContainer, end = rng.endContainer; + + function skipEmptyTextNodes(n, forwards) { + var orig = n; + while (n && n.nodeType === 3 && n.length === 0) { + n = forwards ? n.nextSibling : n.previousSibling; + } + return n || orig; + }; + + // Range maybe lost after the editor is made visible again + if (!rng) + return t.dom.getRoot(); + + if (rng.setStart) { + elm = rng.commonAncestorContainer; + + // Handle selection a image or other control like element such as anchors + if (!rng.collapsed) { + if (rng.startContainer == rng.endContainer) { + if (rng.endOffset - rng.startOffset < 2) { + if (rng.startContainer.hasChildNodes()) + elm = rng.startContainer.childNodes[rng.startOffset]; + } + } + + // If the anchor node is a element instead of a text node then return this element + //if (tinymce.isWebKit && sel.anchorNode && sel.anchorNode.nodeType == 1) + // return sel.anchorNode.childNodes[sel.anchorOffset]; + + // Handle cases where the selection is immediately wrapped around a node and return that node instead of it's parent. + // This happens when you double click an underlined word in FireFox. + if (start.nodeType === 3 && end.nodeType === 3) { + if (start.length === rng.startOffset) { + start = skipEmptyTextNodes(start.nextSibling, true); + } else { + start = start.parentNode; + } + if (rng.endOffset === 0) { + end = skipEmptyTextNodes(end.previousSibling, false); + } else { + end = end.parentNode; + } + + if (start && start === end) + return start; + } + } + + if (elm && elm.nodeType == 3) + return elm.parentNode; + + return elm; + } + + return rng.item ? rng.item(0) : rng.parentElement(); + }, + + getSelectedBlocks : function(st, en) { + var t = this, dom = t.dom, sb, eb, n, bl = []; + + sb = dom.getParent(st || t.getStart(), dom.isBlock); + eb = dom.getParent(en || t.getEnd(), dom.isBlock); + + if (sb) + bl.push(sb); + + if (sb && eb && sb != eb) { + n = sb; + + var walker = new TreeWalker(sb, dom.getRoot()); + while ((n = walker.next()) && n != eb) { + if (dom.isBlock(n)) + bl.push(n); + } + } + + if (eb && sb != eb) + bl.push(eb); + + return bl; + }, + + isForward: function(){ + var dom = this.dom, sel = this.getSel(), anchorRange, focusRange; + + // No support for selection direction then always return true + if (!sel || sel.anchorNode == null || sel.focusNode == null) { + return true; + } + + anchorRange = dom.createRng(); + anchorRange.setStart(sel.anchorNode, sel.anchorOffset); + anchorRange.collapse(true); + + focusRange = dom.createRng(); + focusRange.setStart(sel.focusNode, sel.focusOffset); + focusRange.collapse(true); + + return anchorRange.compareBoundaryPoints(anchorRange.START_TO_START, focusRange) <= 0; + }, + + normalize : function() { + var self = this, rng, normalized, collapsed, node, sibling; + + function normalizeEndPoint(start) { + var container, offset, walker, dom = self.dom, body = dom.getRoot(), node, nonEmptyElementsMap, nodeName; + + function hasBrBeforeAfter(node, left) { + var walker = new TreeWalker(node, dom.getParent(node.parentNode, dom.isBlock) || body); + + while (node = walker[left ? 'prev' : 'next']()) { + if (node.nodeName === "BR") { + return true; + } + } + }; + + // Walks the dom left/right to find a suitable text node to move the endpoint into + // It will only walk within the current parent block or body and will stop if it hits a block or a BR/IMG + function findTextNodeRelative(left, startNode) { + var walker, lastInlineElement; + + startNode = startNode || container; + walker = new TreeWalker(startNode, dom.getParent(startNode.parentNode, dom.isBlock) || body); + + // Walk left until we hit a text node we can move to or a block/br/img + while (node = walker[left ? 'prev' : 'next']()) { + // Found text node that has a length + if (node.nodeType === 3 && node.nodeValue.length > 0) { + container = node; + offset = left ? node.nodeValue.length : 0; + normalized = true; + return; + } + + // Break if we find a block or a BR/IMG/INPUT etc + if (dom.isBlock(node) || nonEmptyElementsMap[node.nodeName.toLowerCase()]) { + return; + } + + lastInlineElement = node; + } + + // Only fetch the last inline element when in caret mode for now + if (collapsed && lastInlineElement) { + container = lastInlineElement; + normalized = true; + offset = 0; + } + }; + + container = rng[(start ? 'start' : 'end') + 'Container']; + offset = rng[(start ? 'start' : 'end') + 'Offset']; + nonEmptyElementsMap = dom.schema.getNonEmptyElements(); + + // If the container is a document move it to the body element + if (container.nodeType === 9) { + container = dom.getRoot(); + offset = 0; + } + + // If the container is body try move it into the closest text node or position + if (container === body) { + // If start is before/after a image, table etc + if (start) { + node = container.childNodes[offset > 0 ? offset - 1 : 0]; + if (node) { + nodeName = node.nodeName.toLowerCase(); + if (nonEmptyElementsMap[node.nodeName] || node.nodeName == "TABLE") { + return; + } + } + } + + // Resolve the index + if (container.hasChildNodes()) { + container = container.childNodes[Math.min(!start && offset > 0 ? offset - 1 : offset, container.childNodes.length - 1)]; + offset = 0; + + // Don't walk into elements that doesn't have any child nodes like a IMG + if (container.hasChildNodes() && !/TABLE/.test(container.nodeName)) { + // Walk the DOM to find a text node to place the caret at or a BR + node = container; + walker = new TreeWalker(container, body); + + do { + // Found a text node use that position + if (node.nodeType === 3 && node.nodeValue.length > 0) { + offset = start ? 0 : node.nodeValue.length; + container = node; + normalized = true; + break; + } + + // Found a BR/IMG element that we can place the caret before + if (nonEmptyElementsMap[node.nodeName.toLowerCase()]) { + offset = dom.nodeIndex(node); + container = node.parentNode; + + // Put caret after image when moving the end point + if (node.nodeName == "IMG" && !start) { + offset++; + } + + normalized = true; + break; + } + } while (node = (start ? walker.next() : walker.prev())); + } + } + } + + // Lean the caret to the left if possible + if (collapsed) { + // So this: x|x + // Becomes: x|x + // Seems that only gecko has issues with this + if (container.nodeType === 3 && offset === 0) { + findTextNodeRelative(true); + } + + // Lean left into empty inline elements when the caret is before a BR + // So this: |
    + // Becomes: |
    + // Seems that only gecko has issues with this + if (container.nodeType === 1) { + node = container.childNodes[offset]; + if(node && node.nodeName === 'BR' && !hasBrBeforeAfter(node) && !hasBrBeforeAfter(node, true)) { + findTextNodeRelative(true, container.childNodes[offset]); + } + } + } + + // Lean the start of the selection right if possible + // So this: x[x] + // Becomes: x[x] + if (start && !collapsed && container.nodeType === 3 && offset === container.nodeValue.length) { + findTextNodeRelative(false); + } + + // Set endpoint if it was normalized + if (normalized) + rng['set' + (start ? 'Start' : 'End')](container, offset); + }; + + // Normalize only on non IE browsers for now + if (tinymce.isIE) + return; + + rng = self.getRng(); + collapsed = rng.collapsed; + + // Normalize the end points + normalizeEndPoint(true); + + if (!collapsed) + normalizeEndPoint(); + + // Set the selection if it was normalized + if (normalized) { + // If it was collapsed then make sure it still is + if (collapsed) { + rng.collapse(true); + } + + //console.log(self.dom.dumpRng(rng)); + self.setRng(rng, self.isForward()); + } + }, + + selectorChanged: function(selector, callback) { + var self = this, currentSelectors; + + if (!self.selectorChangedData) { + self.selectorChangedData = {}; + currentSelectors = {}; + + self.editor.onNodeChange.addToTop(function(ed, cm, node) { + var dom = self.dom, parents = dom.getParents(node, null, dom.getRoot()), matchedSelectors = {}; + + // Check for new matching selectors + each(self.selectorChangedData, function(callbacks, selector) { + each(parents, function(node) { + if (dom.is(node, selector)) { + if (!currentSelectors[selector]) { + // Execute callbacks + each(callbacks, function(callback) { + callback(true, {node: node, selector: selector, parents: parents}); + }); + + currentSelectors[selector] = callbacks; + } + + matchedSelectors[selector] = callbacks; + return false; + } + }); + }); + + // Check if current selectors still match + each(currentSelectors, function(callbacks, selector) { + if (!matchedSelectors[selector]) { + delete currentSelectors[selector]; + + each(callbacks, function(callback) { + callback(false, {node: node, selector: selector, parents: parents}); + }); + } + }); + }); + } + + // Add selector listeners + if (!self.selectorChangedData[selector]) { + self.selectorChangedData[selector] = []; + } + + self.selectorChangedData[selector].push(callback); + + return self; + }, + + scrollIntoView: function(elm) { + var y, viewPort, self = this, dom = self.dom; + + viewPort = dom.getViewPort(self.editor.getWin()); + y = dom.getPos(elm).y; + if (y < viewPort.y || y + 25 > viewPort.y + viewPort.h) { + self.editor.getWin().scrollTo(0, y < viewPort.y ? y : y - viewPort.h + 25); + } + }, + + destroy : function(manual) { + var self = this; + + self.win = null; + + // Manual destroy then remove unload handler + if (!manual) + tinymce.removeUnload(self.destroy); + }, + + // IE has an issue where you can't select/move the caret by clicking outside the body if the document is in standards mode + _fixIESelection : function() { + var dom = this.dom, doc = dom.doc, body = doc.body, started, startRng, htmlElm; + + // Return range from point or null if it failed + function rngFromPoint(x, y) { + var rng = body.createTextRange(); + + try { + rng.moveToPoint(x, y); + } catch (ex) { + // IE sometimes throws and exception, so lets just ignore it + rng = null; + } + + return rng; + }; + + // Fires while the selection is changing + function selectionChange(e) { + var pointRng; + + // Check if the button is down or not + if (e.button) { + // Create range from mouse position + pointRng = rngFromPoint(e.x, e.y); + + if (pointRng) { + // Check if pointRange is before/after selection then change the endPoint + if (pointRng.compareEndPoints('StartToStart', startRng) > 0) + pointRng.setEndPoint('StartToStart', startRng); + else + pointRng.setEndPoint('EndToEnd', startRng); + + pointRng.select(); + } + } else + endSelection(); + } + + // Removes listeners + function endSelection() { + var rng = doc.selection.createRange(); + + // If the range is collapsed then use the last start range + if (startRng && !rng.item && rng.compareEndPoints('StartToEnd', rng) === 0) + startRng.select(); + + dom.unbind(doc, 'mouseup', endSelection); + dom.unbind(doc, 'mousemove', selectionChange); + startRng = started = 0; + }; + + // Make HTML element unselectable since we are going to handle selection by hand + doc.documentElement.unselectable = true; + + // Detect when user selects outside BODY + dom.bind(doc, ['mousedown', 'contextmenu'], function(e) { + if (e.target.nodeName === 'HTML') { + if (started) + endSelection(); + + // Detect vertical scrollbar, since IE will fire a mousedown on the scrollbar and have target set as HTML + htmlElm = doc.documentElement; + if (htmlElm.scrollHeight > htmlElm.clientHeight) + return; + + started = 1; + // Setup start position + startRng = rngFromPoint(e.x, e.y); + if (startRng) { + // Listen for selection change events + dom.bind(doc, 'mouseup', endSelection); + dom.bind(doc, 'mousemove', selectionChange); + + dom.win.focus(); + startRng.select(); + } + } + }); + } + }); +})(tinymce); + +(function(tinymce) { + tinymce.dom.Serializer = function(settings, dom, schema) { + var onPreProcess, onPostProcess, isIE = tinymce.isIE, each = tinymce.each, htmlParser; + + // Support the old apply_source_formatting option + if (!settings.apply_source_formatting) + settings.indent = false; + + // Default DOM and Schema if they are undefined + dom = dom || tinymce.DOM; + schema = schema || new tinymce.html.Schema(settings); + settings.entity_encoding = settings.entity_encoding || 'named'; + settings.remove_trailing_brs = "remove_trailing_brs" in settings ? settings.remove_trailing_brs : true; + + onPreProcess = new tinymce.util.Dispatcher(self); + + onPostProcess = new tinymce.util.Dispatcher(self); + + htmlParser = new tinymce.html.DomParser(settings, schema); + + // Convert move data-mce-src, data-mce-href and data-mce-style into nodes or process them if needed + htmlParser.addAttributeFilter('src,href,style', function(nodes, name) { + var i = nodes.length, node, value, internalName = 'data-mce-' + name, urlConverter = settings.url_converter, urlConverterScope = settings.url_converter_scope, undef; + + while (i--) { + node = nodes[i]; + + value = node.attributes.map[internalName]; + if (value !== undef) { + // Set external name to internal value and remove internal + node.attr(name, value.length > 0 ? value : null); + node.attr(internalName, null); + } else { + // No internal attribute found then convert the value we have in the DOM + value = node.attributes.map[name]; + + if (name === "style") + value = dom.serializeStyle(dom.parseStyle(value), node.name); + else if (urlConverter) + value = urlConverter.call(urlConverterScope, value, name, node.name); + + node.attr(name, value.length > 0 ? value : null); + } + } + }); + + // Remove internal classes mceItem<..> or mceSelected + htmlParser.addAttributeFilter('class', function(nodes, name) { + var i = nodes.length, node, value; + + while (i--) { + node = nodes[i]; + value = node.attr('class').replace(/(?:^|\s)mce(Item\w+|Selected)(?!\S)/g, ''); + node.attr('class', value.length > 0 ? value : null); + } + }); + + // Remove bookmark elements + htmlParser.addAttributeFilter('data-mce-type', function(nodes, name, args) { + var i = nodes.length, node; + + while (i--) { + node = nodes[i]; + + if (node.attributes.map['data-mce-type'] === 'bookmark' && !args.cleanup) + node.remove(); + } + }); + + // Remove expando attributes + htmlParser.addAttributeFilter('data-mce-expando', function(nodes, name, args) { + var i = nodes.length; + + while (i--) { + nodes[i].attr(name, null); + } + }); + + htmlParser.addNodeFilter('noscript', function(nodes) { + var i = nodes.length, node; + + while (i--) { + node = nodes[i].firstChild; + + if (node) { + node.value = tinymce.html.Entities.decode(node.value); + } + } + }); + + // Force script into CDATA sections and remove the mce- prefix also add comments around styles + htmlParser.addNodeFilter('script,style', function(nodes, name) { + var i = nodes.length, node, value; + + function trim(value) { + return value.replace(/()/g, '\n') + .replace(/^[\r\n]*|[\r\n]*$/g, '') + .replace(/^\s*(()?|\s*\/\/\s*\]\]>(-->)?|\/\/\s*(-->)?|\]\]>|\/\*\s*-->\s*\*\/|\s*-->\s*)\s*$/g, ''); + }; + + while (i--) { + node = nodes[i]; + value = node.firstChild ? node.firstChild.value : ''; + + if (name === "script") { + // Remove mce- prefix from script elements + node.attr('type', (node.attr('type') || 'text/javascript').replace(/^mce\-/, '')); + + if (value.length > 0) + node.firstChild.value = '// '; + } else { + if (value.length > 0) + node.firstChild.value = ''; + } + } + }); + + // Convert comments to cdata and handle protected comments + htmlParser.addNodeFilter('#comment', function(nodes, name) { + var i = nodes.length, node; + + while (i--) { + node = nodes[i]; + + if (node.value.indexOf('[CDATA[') === 0) { + node.name = '#cdata'; + node.type = 4; + node.value = node.value.replace(/^\[CDATA\[|\]\]$/g, ''); + } else if (node.value.indexOf('mce:protected ') === 0) { + node.name = "#text"; + node.type = 3; + node.raw = true; + node.value = unescape(node.value).substr(14); + } + } + }); + + htmlParser.addNodeFilter('xml:namespace,input', function(nodes, name) { + var i = nodes.length, node; + + while (i--) { + node = nodes[i]; + if (node.type === 7) + node.remove(); + else if (node.type === 1) { + if (name === "input" && !("type" in node.attributes.map)) + node.attr('type', 'text'); + } + } + }); + + // Fix list elements, TODO: Replace this later + if (settings.fix_list_elements) { + htmlParser.addNodeFilter('ul,ol', function(nodes, name) { + var i = nodes.length, node, parentNode; + + while (i--) { + node = nodes[i]; + parentNode = node.parent; + + if (parentNode.name === 'ul' || parentNode.name === 'ol') { + if (node.prev && node.prev.name === 'li') { + node.prev.append(node); + } + } + } + }); + } + + // Remove internal data attributes + htmlParser.addAttributeFilter('data-mce-src,data-mce-href,data-mce-style', function(nodes, name) { + var i = nodes.length; + + while (i--) { + nodes[i].attr(name, null); + } + }); + + // Return public methods + return { + schema : schema, + + addNodeFilter : htmlParser.addNodeFilter, + + addAttributeFilter : htmlParser.addAttributeFilter, + + onPreProcess : onPreProcess, + + onPostProcess : onPostProcess, + + serialize : function(node, args) { + var impl, doc, oldDoc, htmlSerializer, content; + + // Explorer won't clone contents of script and style and the + // selected index of select elements are cleared on a clone operation. + if (isIE && dom.select('script,style,select,map').length > 0) { + content = node.innerHTML; + node = node.cloneNode(false); + dom.setHTML(node, content); + } else + node = node.cloneNode(true); + + // Nodes needs to be attached to something in WebKit/Opera + // Older builds of Opera crashes if you attach the node to an document created dynamically + // and since we can't feature detect a crash we need to sniff the acutal build number + // This fix will make DOM ranges and make Sizzle happy! + impl = node.ownerDocument.implementation; + if (impl.createHTMLDocument) { + // Create an empty HTML document + doc = impl.createHTMLDocument(""); + + // Add the element or it's children if it's a body element to the new document + each(node.nodeName == 'BODY' ? node.childNodes : [node], function(node) { + doc.body.appendChild(doc.importNode(node, true)); + }); + + // Grab first child or body element for serialization + if (node.nodeName != 'BODY') + node = doc.body.firstChild; + else + node = doc.body; + + // set the new document in DOMUtils so createElement etc works + oldDoc = dom.doc; + dom.doc = doc; + } + + args = args || {}; + args.format = args.format || 'html'; + + // Pre process + if (!args.no_events) { + args.node = node; + onPreProcess.dispatch(self, args); + } + + // Setup serializer + htmlSerializer = new tinymce.html.Serializer(settings, schema); + + // Parse and serialize HTML + args.content = htmlSerializer.serialize( + htmlParser.parse(tinymce.trim(args.getInner ? node.innerHTML : dom.getOuterHTML(node)), args) + ); + + // Replace all BOM characters for now until we can find a better solution + if (!args.cleanup) + args.content = args.content.replace(/\uFEFF/g, ''); + + // Post process + if (!args.no_events) + onPostProcess.dispatch(self, args); + + // Restore the old document if it was changed + if (oldDoc) + dom.doc = oldDoc; + + args.node = null; + + return args.content; + }, + + addRules : function(rules) { + schema.addValidElements(rules); + }, + + setRules : function(rules) { + schema.setValidElements(rules); + } + }; + }; +})(tinymce); +(function(tinymce) { + tinymce.dom.ScriptLoader = function(settings) { + var QUEUED = 0, + LOADING = 1, + LOADED = 2, + states = {}, + queue = [], + scriptLoadedCallbacks = {}, + queueLoadedCallbacks = [], + loading = 0, + undef; + + function loadScript(url, callback) { + var t = this, dom = tinymce.DOM, elm, uri, loc, id; + + // Execute callback when script is loaded + function done() { + dom.remove(id); + + if (elm) + elm.onreadystatechange = elm.onload = elm = null; + + callback(); + }; + + function error() { + // Report the error so it's easier for people to spot loading errors + if (typeof(console) !== "undefined" && console.log) + console.log("Failed to load: " + url); + + // We can't mark it as done if there is a load error since + // A) We don't want to produce 404 errors on the server and + // B) the onerror event won't fire on all browsers. + // done(); + }; + + id = dom.uniqueId(); + + if (tinymce.isIE6) { + uri = new tinymce.util.URI(url); + loc = location; + + // If script is from same domain and we + // use IE 6 then use XHR since it's more reliable + if (uri.host == loc.hostname && uri.port == loc.port && (uri.protocol + ':') == loc.protocol && uri.protocol.toLowerCase() != 'file') { + tinymce.util.XHR.send({ + url : tinymce._addVer(uri.getURI()), + success : function(content) { + // Create new temp script element + var script = dom.create('script', { + type : 'text/javascript' + }); + + // Evaluate script in global scope + script.text = content; + document.getElementsByTagName('head')[0].appendChild(script); + dom.remove(script); + + done(); + }, + + error : error + }); + + return; + } + } + + // Create new script element + elm = document.createElement('script'); + elm.id = id; + elm.type = 'text/javascript'; + elm.src = tinymce._addVer(url); + + // Add onload listener for non IE browsers since IE9 + // fires onload event before the script is parsed and executed + if (!tinymce.isIE || tinymce.isIE11) + elm.onload = done; + + // Add onerror event will get fired on some browsers but not all of them + elm.onerror = error; + + // Opera 9.60 doesn't seem to fire the onreadystate event at correctly + if (!tinymce.isOpera) { + elm.onreadystatechange = function() { + var state = elm.readyState; + + // Loaded state is passed on IE 6 however there + // are known issues with this method but we can't use + // XHR in a cross domain loading + if (state == 'complete' || state == 'loaded') + done(); + }; + } + + // Most browsers support this feature so we report errors + // for those at least to help users track their missing plugins etc + // todo: Removed since it produced error if the document is unloaded by navigating away, re-add it as an option + /*elm.onerror = function() { + alert('Failed to load: ' + url); + };*/ + + // Add script to document + (document.getElementsByTagName('head')[0] || document.body).appendChild(elm); + }; + + this.isDone = function(url) { + return states[url] == LOADED; + }; + + this.markDone = function(url) { + states[url] = LOADED; + }; + + this.add = this.load = function(url, callback, scope) { + var item, state = states[url]; + + // Add url to load queue + if (state == undef) { + queue.push(url); + states[url] = QUEUED; + } + + if (callback) { + // Store away callback for later execution + if (!scriptLoadedCallbacks[url]) + scriptLoadedCallbacks[url] = []; + + scriptLoadedCallbacks[url].push({ + func : callback, + scope : scope || this + }); + } + }; + + this.loadQueue = function(callback, scope) { + this.loadScripts(queue, callback, scope); + }; + + this.loadScripts = function(scripts, callback, scope) { + var loadScripts; + + function execScriptLoadedCallbacks(url) { + // Execute URL callback functions + tinymce.each(scriptLoadedCallbacks[url], function(callback) { + callback.func.call(callback.scope); + }); + + scriptLoadedCallbacks[url] = undef; + }; + + queueLoadedCallbacks.push({ + func : callback, + scope : scope || this + }); + + loadScripts = function() { + var loadingScripts = tinymce.grep(scripts); + + // Current scripts has been handled + scripts.length = 0; + + // Load scripts that needs to be loaded + tinymce.each(loadingScripts, function(url) { + // Script is already loaded then execute script callbacks directly + if (states[url] == LOADED) { + execScriptLoadedCallbacks(url); + return; + } + + // Is script not loading then start loading it + if (states[url] != LOADING) { + states[url] = LOADING; + loading++; + + loadScript(url, function() { + states[url] = LOADED; + loading--; + + execScriptLoadedCallbacks(url); + + // Load more scripts if they where added by the recently loaded script + loadScripts(); + }); + } + }); + + // No scripts are currently loading then execute all pending queue loaded callbacks + if (!loading) { + tinymce.each(queueLoadedCallbacks, function(callback) { + callback.func.call(callback.scope); + }); + + queueLoadedCallbacks.length = 0; + } + }; + + loadScripts(); + }; + }; + + // Global script loader + tinymce.ScriptLoader = new tinymce.dom.ScriptLoader(); +})(tinymce); + +(function(tinymce) { + tinymce.dom.RangeUtils = function(dom) { + var INVISIBLE_CHAR = '\uFEFF'; + + this.walk = function(rng, callback) { + var startContainer = rng.startContainer, + startOffset = rng.startOffset, + endContainer = rng.endContainer, + endOffset = rng.endOffset, + ancestor, startPoint, + endPoint, node, parent, siblings, nodes; + + // Handle table cell selection the table plugin enables + // you to fake select table cells and perform formatting actions on them + nodes = dom.select('td.mceSelected,th.mceSelected'); + if (nodes.length > 0) { + tinymce.each(nodes, function(node) { + callback([node]); + }); + + return; + } + + function exclude(nodes) { + var node; + + // First node is excluded + node = nodes[0]; + if (node.nodeType === 3 && node === startContainer && startOffset >= node.nodeValue.length) { + nodes.splice(0, 1); + } + + // Last node is excluded + node = nodes[nodes.length - 1]; + if (endOffset === 0 && nodes.length > 0 && node === endContainer && node.nodeType === 3) { + nodes.splice(nodes.length - 1, 1); + } + + return nodes; + }; + + function collectSiblings(node, name, end_node) { + var siblings = []; + + for (; node && node != end_node; node = node[name]) + siblings.push(node); + + return siblings; + }; + + function findEndPoint(node, root) { + do { + if (node.parentNode == root) + return node; + + node = node.parentNode; + } while(node); + }; + + function walkBoundary(start_node, end_node, next) { + var siblingName = next ? 'nextSibling' : 'previousSibling'; + + for (node = start_node, parent = node.parentNode; node && node != end_node; node = parent) { + parent = node.parentNode; + siblings = collectSiblings(node == start_node ? node : node[siblingName], siblingName); + + if (siblings.length) { + if (!next) + siblings.reverse(); + + callback(exclude(siblings)); + } + } + }; + + // If index based start position then resolve it + if (startContainer.nodeType == 1 && startContainer.hasChildNodes()) + startContainer = startContainer.childNodes[startOffset]; + + // If index based end position then resolve it + if (endContainer.nodeType == 1 && endContainer.hasChildNodes()) + endContainer = endContainer.childNodes[Math.min(endOffset - 1, endContainer.childNodes.length - 1)]; + + // Same container + if (startContainer == endContainer) + return callback(exclude([startContainer])); + + // Find common ancestor and end points + ancestor = dom.findCommonAncestor(startContainer, endContainer); + + // Process left side + for (node = startContainer; node; node = node.parentNode) { + if (node === endContainer) + return walkBoundary(startContainer, ancestor, true); + + if (node === ancestor) + break; + } + + // Process right side + for (node = endContainer; node; node = node.parentNode) { + if (node === startContainer) + return walkBoundary(endContainer, ancestor); + + if (node === ancestor) + break; + } + + // Find start/end point + startPoint = findEndPoint(startContainer, ancestor) || startContainer; + endPoint = findEndPoint(endContainer, ancestor) || endContainer; + + // Walk left leaf + walkBoundary(startContainer, startPoint, true); + + // Walk the middle from start to end point + siblings = collectSiblings( + startPoint == startContainer ? startPoint : startPoint.nextSibling, + 'nextSibling', + endPoint == endContainer ? endPoint.nextSibling : endPoint + ); + + if (siblings.length) + callback(exclude(siblings)); + + // Walk right leaf + walkBoundary(endContainer, endPoint); + }; + + this.split = function(rng) { + var startContainer = rng.startContainer, + startOffset = rng.startOffset, + endContainer = rng.endContainer, + endOffset = rng.endOffset; + + function splitText(node, offset) { + return node.splitText(offset); + }; + + // Handle single text node + if (startContainer == endContainer && startContainer.nodeType == 3) { + if (startOffset > 0 && startOffset < startContainer.nodeValue.length) { + endContainer = splitText(startContainer, startOffset); + startContainer = endContainer.previousSibling; + + if (endOffset > startOffset) { + endOffset = endOffset - startOffset; + startContainer = endContainer = splitText(endContainer, endOffset).previousSibling; + endOffset = endContainer.nodeValue.length; + startOffset = 0; + } else { + endOffset = 0; + } + } + } else { + // Split startContainer text node if needed + if (startContainer.nodeType == 3 && startOffset > 0 && startOffset < startContainer.nodeValue.length) { + startContainer = splitText(startContainer, startOffset); + startOffset = 0; + } + + // Split endContainer text node if needed + if (endContainer.nodeType == 3 && endOffset > 0 && endOffset < endContainer.nodeValue.length) { + endContainer = splitText(endContainer, endOffset).previousSibling; + endOffset = endContainer.nodeValue.length; + } + } + + return { + startContainer : startContainer, + startOffset : startOffset, + endContainer : endContainer, + endOffset : endOffset + }; + }; + + }; + + tinymce.dom.RangeUtils.compareRanges = function(rng1, rng2) { + if (rng1 && rng2) { + // Compare native IE ranges + if (rng1.item || rng1.duplicate) { + // Both are control ranges and the selected element matches + if (rng1.item && rng2.item && rng1.item(0) === rng2.item(0)) + return true; + + // Both are text ranges and the range matches + if (rng1.isEqual && rng2.isEqual && rng2.isEqual(rng1)) + return true; + } else { + // Compare w3c ranges + return rng1.startContainer == rng2.startContainer && rng1.startOffset == rng2.startOffset; + } + } + + return false; + }; +})(tinymce); + +(function(tinymce) { + var Event = tinymce.dom.Event, each = tinymce.each; + + tinymce.create('tinymce.ui.KeyboardNavigation', { + KeyboardNavigation: function(settings, dom) { + var t = this, root = settings.root, items = settings.items, + enableUpDown = settings.enableUpDown, enableLeftRight = settings.enableLeftRight || !settings.enableUpDown, + excludeFromTabOrder = settings.excludeFromTabOrder, + itemFocussed, itemBlurred, rootKeydown, rootFocussed, focussedId; + + dom = dom || tinymce.DOM; + + itemFocussed = function(evt) { + focussedId = evt.target.id; + }; + + itemBlurred = function(evt) { + dom.setAttrib(evt.target.id, 'tabindex', '-1'); + }; + + rootFocussed = function(evt) { + var item = dom.get(focussedId); + dom.setAttrib(item, 'tabindex', '0'); + item.focus(); + }; + + t.focus = function() { + dom.get(focussedId).focus(); + }; + + t.destroy = function() { + each(items, function(item) { + var elm = dom.get(item.id); + + dom.unbind(elm, 'focus', itemFocussed); + dom.unbind(elm, 'blur', itemBlurred); + }); + + var rootElm = dom.get(root); + dom.unbind(rootElm, 'focus', rootFocussed); + dom.unbind(rootElm, 'keydown', rootKeydown); + + items = dom = root = t.focus = itemFocussed = itemBlurred = rootKeydown = rootFocussed = null; + t.destroy = function() {}; + }; + + t.moveFocus = function(dir, evt) { + var idx = -1, controls = t.controls, newFocus; + + if (!focussedId) + return; + + each(items, function(item, index) { + if (item.id === focussedId) { + idx = index; + return false; + } + }); + + idx += dir; + if (idx < 0) { + idx = items.length - 1; + } else if (idx >= items.length) { + idx = 0; + } + + newFocus = items[idx]; + dom.setAttrib(focussedId, 'tabindex', '-1'); + dom.setAttrib(newFocus.id, 'tabindex', '0'); + dom.get(newFocus.id).focus(); + + if (settings.actOnFocus) { + settings.onAction(newFocus.id); + } + + if (evt) + Event.cancel(evt); + }; + + rootKeydown = function(evt) { + var DOM_VK_LEFT = 37, DOM_VK_RIGHT = 39, DOM_VK_UP = 38, DOM_VK_DOWN = 40, DOM_VK_ESCAPE = 27, DOM_VK_ENTER = 14, DOM_VK_RETURN = 13, DOM_VK_SPACE = 32; + + switch (evt.keyCode) { + case DOM_VK_LEFT: + if (enableLeftRight) t.moveFocus(-1); + Event.cancel(evt); + break; + + case DOM_VK_RIGHT: + if (enableLeftRight) t.moveFocus(1); + Event.cancel(evt); + break; + + case DOM_VK_UP: + if (enableUpDown) t.moveFocus(-1); + Event.cancel(evt); + break; + + case DOM_VK_DOWN: + if (enableUpDown) t.moveFocus(1); + Event.cancel(evt); + break; + + case DOM_VK_ESCAPE: + if (settings.onCancel) { + settings.onCancel(); + Event.cancel(evt); + } + break; + + case DOM_VK_ENTER: + case DOM_VK_RETURN: + case DOM_VK_SPACE: + if (settings.onAction) { + settings.onAction(focussedId); + Event.cancel(evt); + } + break; + } + }; + + // Set up state and listeners for each item. + each(items, function(item, idx) { + var tabindex, elm; + + if (!item.id) { + item.id = dom.uniqueId('_mce_item_'); + } + + elm = dom.get(item.id); + + if (excludeFromTabOrder) { + dom.bind(elm, 'blur', itemBlurred); + tabindex = '-1'; + } else { + tabindex = (idx === 0 ? '0' : '-1'); + } + + elm.setAttribute('tabindex', tabindex); + dom.bind(elm, 'focus', itemFocussed); + }); + + // Setup initial state for root element. + if (items[0]){ + focussedId = items[0].id; + } + + dom.setAttrib(root, 'tabindex', '-1'); + + // Setup listeners for root element. + var rootElm = dom.get(root); + dom.bind(rootElm, 'focus', rootFocussed); + dom.bind(rootElm, 'keydown', rootKeydown); + } + }); +})(tinymce); + +(function(tinymce) { + // Shorten class names + var DOM = tinymce.DOM, is = tinymce.is; + + tinymce.create('tinymce.ui.Control', { + Control : function(id, s, editor) { + this.id = id; + this.settings = s = s || {}; + this.rendered = false; + this.onRender = new tinymce.util.Dispatcher(this); + this.classPrefix = ''; + this.scope = s.scope || this; + this.disabled = 0; + this.active = 0; + this.editor = editor; + }, + + setAriaProperty : function(property, value) { + var element = DOM.get(this.id + '_aria') || DOM.get(this.id); + if (element) { + DOM.setAttrib(element, 'aria-' + property, !!value); + } + }, + + focus : function() { + DOM.get(this.id).focus(); + }, + + setDisabled : function(s) { + if (s != this.disabled) { + this.setAriaProperty('disabled', s); + + this.setState('Disabled', s); + this.setState('Enabled', !s); + this.disabled = s; + } + }, + + isDisabled : function() { + return this.disabled; + }, + + setActive : function(s) { + if (s != this.active) { + this.setState('Active', s); + this.active = s; + this.setAriaProperty('pressed', s); + } + }, + + isActive : function() { + return this.active; + }, + + setState : function(c, s) { + var n = DOM.get(this.id); + + c = this.classPrefix + c; + + if (s) + DOM.addClass(n, c); + else + DOM.removeClass(n, c); + }, + + isRendered : function() { + return this.rendered; + }, + + renderHTML : function() { + }, + + renderTo : function(n) { + DOM.setHTML(n, this.renderHTML()); + }, + + postRender : function() { + var t = this, b; + + // Set pending states + if (is(t.disabled)) { + b = t.disabled; + t.disabled = -1; + t.setDisabled(b); + } + + if (is(t.active)) { + b = t.active; + t.active = -1; + t.setActive(b); + } + }, + + remove : function() { + DOM.remove(this.id); + this.destroy(); + }, + + destroy : function() { + tinymce.dom.Event.clear(this.id); + } + }); +})(tinymce); +tinymce.create('tinymce.ui.Container:tinymce.ui.Control', { + Container : function(id, s, editor) { + this.parent(id, s, editor); + + this.controls = []; + + this.lookup = {}; + }, + + add : function(c) { + this.lookup[c.id] = c; + this.controls.push(c); + + return c; + }, + + get : function(n) { + return this.lookup[n]; + } +}); + + +tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', { + Separator : function(id, s) { + this.parent(id, s); + this.classPrefix = 'mceSeparator'; + this.setDisabled(true); + }, + + renderHTML : function() { + return tinymce.DOM.createHTML('span', {'class' : this.classPrefix, role : 'separator', 'aria-orientation' : 'vertical', tabindex : '-1'}); + } +}); + +(function(tinymce) { + var is = tinymce.is, DOM = tinymce.DOM, each = tinymce.each, walk = tinymce.walk; + + tinymce.create('tinymce.ui.MenuItem:tinymce.ui.Control', { + MenuItem : function(id, s) { + this.parent(id, s); + this.classPrefix = 'mceMenuItem'; + }, + + setSelected : function(s) { + this.setState('Selected', s); + this.setAriaProperty('checked', !!s); + this.selected = s; + }, + + isSelected : function() { + return this.selected; + }, + + postRender : function() { + var t = this; + + t.parent(); + + // Set pending state + if (is(t.selected)) + t.setSelected(t.selected); + } + }); +})(tinymce); + +(function(tinymce) { + var is = tinymce.is, DOM = tinymce.DOM, each = tinymce.each, walk = tinymce.walk; + + tinymce.create('tinymce.ui.Menu:tinymce.ui.MenuItem', { + Menu : function(id, s) { + var t = this; + + t.parent(id, s); + t.items = {}; + t.collapsed = false; + t.menuCount = 0; + t.onAddItem = new tinymce.util.Dispatcher(this); + }, + + expand : function(d) { + var t = this; + + if (d) { + walk(t, function(o) { + if (o.expand) + o.expand(); + }, 'items', t); + } + + t.collapsed = false; + }, + + collapse : function(d) { + var t = this; + + if (d) { + walk(t, function(o) { + if (o.collapse) + o.collapse(); + }, 'items', t); + } + + t.collapsed = true; + }, + + isCollapsed : function() { + return this.collapsed; + }, + + add : function(o) { + if (!o.settings) + o = new tinymce.ui.MenuItem(o.id || DOM.uniqueId(), o); + + this.onAddItem.dispatch(this, o); + + return this.items[o.id] = o; + }, + + addSeparator : function() { + return this.add({separator : true}); + }, + + addMenu : function(o) { + if (!o.collapse) + o = this.createMenu(o); + + this.menuCount++; + + return this.add(o); + }, + + hasMenus : function() { + return this.menuCount !== 0; + }, + + remove : function(o) { + delete this.items[o.id]; + }, + + removeAll : function() { + var t = this; + + walk(t, function(o) { + if (o.removeAll) + o.removeAll(); + else + o.remove(); + + o.destroy(); + }, 'items', t); + + t.items = {}; + }, + + createMenu : function(o) { + var m = new tinymce.ui.Menu(o.id || DOM.uniqueId(), o); + + m.onAddItem.add(this.onAddItem.dispatch, this.onAddItem); + + return m; + } + }); +})(tinymce); +(function(tinymce) { + var is = tinymce.is, DOM = tinymce.DOM, each = tinymce.each, Event = tinymce.dom.Event, Element = tinymce.dom.Element; + + tinymce.create('tinymce.ui.DropMenu:tinymce.ui.Menu', { + DropMenu : function(id, s) { + s = s || {}; + s.container = s.container || DOM.doc.body; + s.offset_x = s.offset_x || 0; + s.offset_y = s.offset_y || 0; + s.vp_offset_x = s.vp_offset_x || 0; + s.vp_offset_y = s.vp_offset_y || 0; + + if (is(s.icons) && !s.icons) + s['class'] += ' mceNoIcons'; + + this.parent(id, s); + this.onShowMenu = new tinymce.util.Dispatcher(this); + this.onHideMenu = new tinymce.util.Dispatcher(this); + this.classPrefix = 'mceMenu'; + }, + + createMenu : function(s) { + var t = this, cs = t.settings, m; + + s.container = s.container || cs.container; + s.parent = t; + s.constrain = s.constrain || cs.constrain; + s['class'] = s['class'] || cs['class']; + s.vp_offset_x = s.vp_offset_x || cs.vp_offset_x; + s.vp_offset_y = s.vp_offset_y || cs.vp_offset_y; + s.keyboard_focus = cs.keyboard_focus; + m = new tinymce.ui.DropMenu(s.id || DOM.uniqueId(), s); + + m.onAddItem.add(t.onAddItem.dispatch, t.onAddItem); + + return m; + }, + + focus : function() { + var t = this; + if (t.keyboardNav) { + t.keyboardNav.focus(); + } + }, + + update : function() { + var t = this, s = t.settings, tb = DOM.get('menu_' + t.id + '_tbl'), co = DOM.get('menu_' + t.id + '_co'), tw, th; + + tw = s.max_width ? Math.min(tb.offsetWidth, s.max_width) : tb.offsetWidth; + th = s.max_height ? Math.min(tb.offsetHeight, s.max_height) : tb.offsetHeight; + + if (!DOM.boxModel) + t.element.setStyles({width : tw + 2, height : th + 2}); + else + t.element.setStyles({width : tw, height : th}); + + if (s.max_width) + DOM.setStyle(co, 'width', tw); + + if (s.max_height) { + DOM.setStyle(co, 'height', th); + + if (tb.clientHeight < s.max_height) + DOM.setStyle(co, 'overflow', 'hidden'); + } + }, + + showMenu : function(x, y, px) { + var t = this, s = t.settings, co, vp = DOM.getViewPort(), w, h, mx, my, ot = 2, dm, tb, cp = t.classPrefix; + + t.collapse(1); + + if (t.isMenuVisible) + return; + + if (!t.rendered) { + co = DOM.add(t.settings.container, t.renderNode()); + + each(t.items, function(o) { + o.postRender(); + }); + + t.element = new Element('menu_' + t.id, {blocker : 1, container : s.container}); + } else + co = DOM.get('menu_' + t.id); + + // Move layer out of sight unless it's Opera since it scrolls to top of page due to an bug + if (!tinymce.isOpera) + DOM.setStyles(co, {left : -0xFFFF , top : -0xFFFF}); + + DOM.show(co); + t.update(); + + x += s.offset_x || 0; + y += s.offset_y || 0; + vp.w -= 4; + vp.h -= 4; + + // Move inside viewport if not submenu + if (s.constrain) { + w = co.clientWidth - ot; + h = co.clientHeight - ot; + mx = vp.x + vp.w; + my = vp.y + vp.h; + + if ((x + s.vp_offset_x + w) > mx) + x = px ? px - w : Math.max(0, (mx - s.vp_offset_x) - w); + + if ((y + s.vp_offset_y + h) > my) + y = Math.max(0, (my - s.vp_offset_y) - h); + } + + DOM.setStyles(co, {left : x , top : y}); + t.element.update(); + + t.isMenuVisible = 1; + t.mouseClickFunc = Event.add(co, 'click', function(e) { + var m; + + e = e.target; + + if (e && (e = DOM.getParent(e, 'tr')) && !DOM.hasClass(e, cp + 'ItemSub')) { + m = t.items[e.id]; + + if (m.isDisabled()) + return; + + dm = t; + + while (dm) { + if (dm.hideMenu) + dm.hideMenu(); + + dm = dm.settings.parent; + } + + if (m.settings.onclick) + m.settings.onclick(e); + + return false; // Cancel to fix onbeforeunload problem + } + }); + + if (t.hasMenus()) { + t.mouseOverFunc = Event.add(co, 'mouseover', function(e) { + var m, r, mi; + + e = e.target; + if (e && (e = DOM.getParent(e, 'tr'))) { + m = t.items[e.id]; + + if (t.lastMenu) + t.lastMenu.collapse(1); + + if (m.isDisabled()) + return; + + if (e && DOM.hasClass(e, cp + 'ItemSub')) { + //p = DOM.getPos(s.container); + r = DOM.getRect(e); + m.showMenu((r.x + r.w - ot), r.y - ot, r.x); + t.lastMenu = m; + DOM.addClass(DOM.get(m.id).firstChild, cp + 'ItemActive'); + } + } + }); + } + + Event.add(co, 'keydown', t._keyHandler, t); + + t.onShowMenu.dispatch(t); + + if (s.keyboard_focus) { + t._setupKeyboardNav(); + } + }, + + hideMenu : function(c) { + var t = this, co = DOM.get('menu_' + t.id), e; + + if (!t.isMenuVisible) + return; + + if (t.keyboardNav) t.keyboardNav.destroy(); + Event.remove(co, 'mouseover', t.mouseOverFunc); + Event.remove(co, 'click', t.mouseClickFunc); + Event.remove(co, 'keydown', t._keyHandler); + DOM.hide(co); + t.isMenuVisible = 0; + + if (!c) + t.collapse(1); + + if (t.element) + t.element.hide(); + + if (e = DOM.get(t.id)) + DOM.removeClass(e.firstChild, t.classPrefix + 'ItemActive'); + + t.onHideMenu.dispatch(t); + }, + + add : function(o) { + var t = this, co; + + o = t.parent(o); + + if (t.isRendered && (co = DOM.get('menu_' + t.id))) + t._add(DOM.select('tbody', co)[0], o); + + return o; + }, + + collapse : function(d) { + this.parent(d); + this.hideMenu(1); + }, + + remove : function(o) { + DOM.remove(o.id); + this.destroy(); + + return this.parent(o); + }, + + destroy : function() { + var t = this, co = DOM.get('menu_' + t.id); + + if (t.keyboardNav) t.keyboardNav.destroy(); + Event.remove(co, 'mouseover', t.mouseOverFunc); + Event.remove(DOM.select('a', co), 'focus', t.mouseOverFunc); + Event.remove(co, 'click', t.mouseClickFunc); + Event.remove(co, 'keydown', t._keyHandler); + + if (t.element) + t.element.remove(); + + DOM.remove(co); + }, + + renderNode : function() { + var t = this, s = t.settings, n, tb, co, w; + + w = DOM.create('div', {role: 'listbox', id : 'menu_' + t.id, 'class' : s['class'], 'style' : 'position:absolute;left:0;top:0;z-index:200000;outline:0'}); + if (t.settings.parent) { + DOM.setAttrib(w, 'aria-parent', 'menu_' + t.settings.parent.id); + } + co = DOM.add(w, 'div', {role: 'presentation', id : 'menu_' + t.id + '_co', 'class' : t.classPrefix + (s['class'] ? ' ' + s['class'] : '')}); + t.element = new Element('menu_' + t.id, {blocker : 1, container : s.container}); + + if (s.menu_line) + DOM.add(co, 'span', {'class' : t.classPrefix + 'Line'}); + +// n = DOM.add(co, 'div', {id : 'menu_' + t.id + '_co', 'class' : 'mceMenuContainer'}); + n = DOM.add(co, 'table', {role: 'presentation', id : 'menu_' + t.id + '_tbl', border : 0, cellPadding : 0, cellSpacing : 0}); + tb = DOM.add(n, 'tbody'); + + each(t.items, function(o) { + t._add(tb, o); + }); + + t.rendered = true; + + return w; + }, + + // Internal functions + _setupKeyboardNav : function(){ + var contextMenu, menuItems, t=this; + contextMenu = DOM.get('menu_' + t.id); + menuItems = DOM.select('a[role=option]', 'menu_' + t.id); + menuItems.splice(0,0,contextMenu); + t.keyboardNav = new tinymce.ui.KeyboardNavigation({ + root: 'menu_' + t.id, + items: menuItems, + onCancel: function() { + t.hideMenu(); + }, + enableUpDown: true + }); + contextMenu.focus(); + }, + + _keyHandler : function(evt) { + var t = this, e; + switch (evt.keyCode) { + case 37: // Left + if (t.settings.parent) { + t.hideMenu(); + t.settings.parent.focus(); + Event.cancel(evt); + } + break; + case 39: // Right + if (t.mouseOverFunc) + t.mouseOverFunc(evt); + break; + } + }, + + _add : function(tb, o) { + var n, s = o.settings, a, ro, it, cp = this.classPrefix, ic; + + if (s.separator) { + ro = DOM.add(tb, 'tr', {id : o.id, 'class' : cp + 'ItemSeparator'}); + DOM.add(ro, 'td', {'class' : cp + 'ItemSeparator'}); + + if (n = ro.previousSibling) + DOM.addClass(n, 'mceLast'); + + return; + } + + n = ro = DOM.add(tb, 'tr', {id : o.id, 'class' : cp + 'Item ' + cp + 'ItemEnabled'}); + n = it = DOM.add(n, s.titleItem ? 'th' : 'td'); + n = a = DOM.add(n, 'a', {id: o.id + '_aria', role: s.titleItem ? 'presentation' : 'option', href : 'javascript:;', onclick : "return false;", onmousedown : 'return false;'}); + + if (s.parent) { + DOM.setAttrib(a, 'aria-haspopup', 'true'); + DOM.setAttrib(a, 'aria-owns', 'menu_' + o.id); + } + + DOM.addClass(it, s['class']); +// n = DOM.add(n, 'span', {'class' : 'item'}); + + ic = DOM.add(n, 'span', {'class' : 'mceIcon' + (s.icon ? ' mce_' + s.icon : '')}); + + if (s.icon_src) + DOM.add(ic, 'img', {src : s.icon_src}); + + n = DOM.add(n, s.element || 'span', {'class' : 'mceText', title : o.settings.title}, o.settings.title); + + if (o.settings.style) { + if (typeof o.settings.style == "function") + o.settings.style = o.settings.style(); + + DOM.setAttrib(n, 'style', o.settings.style); + } + + if (tb.childNodes.length == 1) + DOM.addClass(ro, 'mceFirst'); + + if ((n = ro.previousSibling) && DOM.hasClass(n, cp + 'ItemSeparator')) + DOM.addClass(ro, 'mceFirst'); + + if (o.collapse) + DOM.addClass(ro, cp + 'ItemSub'); + + if (n = ro.previousSibling) + DOM.removeClass(n, 'mceLast'); + + DOM.addClass(ro, 'mceLast'); + } + }); +})(tinymce); +(function(tinymce) { + var DOM = tinymce.DOM; + + tinymce.create('tinymce.ui.Button:tinymce.ui.Control', { + Button : function(id, s, ed) { + this.parent(id, s, ed); + this.classPrefix = 'mceButton'; + }, + + renderHTML : function() { + var cp = this.classPrefix, s = this.settings, h, l; + + l = DOM.encode(s.label || ''); + h = ''; + if (s.image && !(this.editor &&this.editor.forcedHighContrastMode) ) + h += '' + DOM.encode(s.title) + '' + (l ? '' + l + '' : ''); + else + h += '' + (l ? '' + l + '' : ''); + + h += ''; + h += ''; + return h; + }, + + postRender : function() { + var t = this, s = t.settings, imgBookmark; + + // In IE a large image that occupies the entire editor area will be deselected when a button is clicked, so + // need to keep the selection in case the selection is lost + if (tinymce.isIE && t.editor) { + tinymce.dom.Event.add(t.id, 'mousedown', function(e) { + var nodeName = t.editor.selection.getNode().nodeName; + imgBookmark = nodeName === 'IMG' ? t.editor.selection.getBookmark() : null; + }); + } + tinymce.dom.Event.add(t.id, 'click', function(e) { + if (!t.isDisabled()) { + // restore the selection in case the selection is lost in IE + if (tinymce.isIE && t.editor && imgBookmark !== null) { + t.editor.selection.moveToBookmark(imgBookmark); + } + return s.onclick.call(s.scope, e); + } + }); + tinymce.dom.Event.add(t.id, 'keydown', function(e) { + if (!t.isDisabled() && e.keyCode==tinymce.VK.SPACEBAR) { + tinymce.dom.Event.cancel(e); + return s.onclick.call(s.scope, e); + } + }); + } + }); +})(tinymce); + +(function(tinymce) { + var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each, Dispatcher = tinymce.util.Dispatcher, undef; + + tinymce.create('tinymce.ui.ListBox:tinymce.ui.Control', { + ListBox : function(id, s, ed) { + var t = this; + + t.parent(id, s, ed); + + t.items = []; + + t.onChange = new Dispatcher(t); + + t.onPostRender = new Dispatcher(t); + + t.onAdd = new Dispatcher(t); + + t.onRenderMenu = new tinymce.util.Dispatcher(this); + + t.classPrefix = 'mceListBox'; + t.marked = {}; + }, + + select : function(va) { + var t = this, fv, f; + + t.marked = {}; + + if (va == undef) + return t.selectByIndex(-1); + + // Is string or number make function selector + if (va && typeof(va)=="function") + f = va; + else { + f = function(v) { + return v == va; + }; + } + + // Do we need to do something? + if (va != t.selectedValue) { + // Find item + each(t.items, function(o, i) { + if (f(o.value)) { + fv = 1; + t.selectByIndex(i); + return false; + } + }); + + if (!fv) + t.selectByIndex(-1); + } + }, + + selectByIndex : function(idx) { + var t = this, e, o, label; + + t.marked = {}; + + if (idx != t.selectedIndex) { + e = DOM.get(t.id + '_text'); + label = DOM.get(t.id + '_voiceDesc'); + o = t.items[idx]; + + if (o) { + t.selectedValue = o.value; + t.selectedIndex = idx; + DOM.setHTML(e, DOM.encode(o.title)); + DOM.setHTML(label, t.settings.title + " - " + o.title); + DOM.removeClass(e, 'mceTitle'); + DOM.setAttrib(t.id, 'aria-valuenow', o.title); + } else { + DOM.setHTML(e, DOM.encode(t.settings.title)); + DOM.setHTML(label, DOM.encode(t.settings.title)); + DOM.addClass(e, 'mceTitle'); + t.selectedValue = t.selectedIndex = null; + DOM.setAttrib(t.id, 'aria-valuenow', t.settings.title); + } + e = 0; + } + }, + + mark : function(value) { + this.marked[value] = true; + }, + + add : function(n, v, o) { + var t = this; + + o = o || {}; + o = tinymce.extend(o, { + title : n, + value : v + }); + + t.items.push(o); + t.onAdd.dispatch(t, o); + }, + + getLength : function() { + return this.items.length; + }, + + renderHTML : function() { + var h = '', t = this, s = t.settings, cp = t.classPrefix; + + h = ''; + h += ''; + h += ''; + h += ''; + + return h; + }, + + showMenu : function() { + var t = this, p2, e = DOM.get(this.id), m; + + if (t.isDisabled() || t.items.length === 0) + return; + + if (t.menu && t.menu.isMenuVisible) + return t.hideMenu(); + + if (!t.isMenuRendered) { + t.renderMenu(); + t.isMenuRendered = true; + } + + p2 = DOM.getPos(e); + + m = t.menu; + m.settings.offset_x = p2.x; + m.settings.offset_y = p2.y; + m.settings.keyboard_focus = !tinymce.isOpera; // Opera is buggy when it comes to auto focus + + // Select in menu + each(t.items, function(o) { + if (m.items[o.id]) { + m.items[o.id].setSelected(0); + } + }); + + each(t.items, function(o) { + if (m.items[o.id] && t.marked[o.value]) { + m.items[o.id].setSelected(1); + } + + if (o.value === t.selectedValue) { + m.items[o.id].setSelected(1); + } + }); + + m.showMenu(0, e.clientHeight); + + Event.add(DOM.doc, 'mousedown', t.hideMenu, t); + DOM.addClass(t.id, t.classPrefix + 'Selected'); + + //DOM.get(t.id + '_text').focus(); + }, + + hideMenu : function(e) { + var t = this; + + if (t.menu && t.menu.isMenuVisible) { + DOM.removeClass(t.id, t.classPrefix + 'Selected'); + + // Prevent double toogles by canceling the mouse click event to the button + if (e && e.type == "mousedown" && (e.target.id == t.id + '_text' || e.target.id == t.id + '_open')) + return; + + if (!e || !DOM.getParent(e.target, '.mceMenu')) { + DOM.removeClass(t.id, t.classPrefix + 'Selected'); + Event.remove(DOM.doc, 'mousedown', t.hideMenu, t); + t.menu.hideMenu(); + } + } + }, + + renderMenu : function() { + var t = this, m; + + m = t.settings.control_manager.createDropMenu(t.id + '_menu', { + menu_line : 1, + 'class' : t.classPrefix + 'Menu mceNoIcons', + max_width : 250, + max_height : 150 + }); + + m.onHideMenu.add(function() { + t.hideMenu(); + t.focus(); + }); + + m.add({ + title : t.settings.title, + 'class' : 'mceMenuItemTitle', + onclick : function() { + if (t.settings.onselect('') !== false) + t.select(''); // Must be runned after + } + }); + + each(t.items, function(o) { + // No value then treat it as a title + if (o.value === undef) { + m.add({ + title : o.title, + role : "option", + 'class' : 'mceMenuItemTitle', + onclick : function() { + if (t.settings.onselect('') !== false) + t.select(''); // Must be runned after + } + }); + } else { + o.id = DOM.uniqueId(); + o.role= "option"; + o.onclick = function() { + if (t.settings.onselect(o.value) !== false) + t.select(o.value); // Must be runned after + }; + + m.add(o); + } + }); + + t.onRenderMenu.dispatch(t, m); + t.menu = m; + }, + + postRender : function() { + var t = this, cp = t.classPrefix; + + Event.add(t.id, 'click', t.showMenu, t); + Event.add(t.id, 'keydown', function(evt) { + if (evt.keyCode == 32) { // Space + t.showMenu(evt); + Event.cancel(evt); + } + }); + Event.add(t.id, 'focus', function() { + if (!t._focused) { + t.keyDownHandler = Event.add(t.id, 'keydown', function(e) { + if (e.keyCode == 40) { + t.showMenu(); + Event.cancel(e); + } + }); + t.keyPressHandler = Event.add(t.id, 'keypress', function(e) { + var v; + if (e.keyCode == 13) { + // Fake select on enter + v = t.selectedValue; + t.selectedValue = null; // Needs to be null to fake change + Event.cancel(e); + t.settings.onselect(v); + } + }); + } + + t._focused = 1; + }); + Event.add(t.id, 'blur', function() { + Event.remove(t.id, 'keydown', t.keyDownHandler); + Event.remove(t.id, 'keypress', t.keyPressHandler); + t._focused = 0; + }); + + // Old IE doesn't have hover on all elements + if (tinymce.isIE6 || !DOM.boxModel) { + Event.add(t.id, 'mouseover', function() { + if (!DOM.hasClass(t.id, cp + 'Disabled')) + DOM.addClass(t.id, cp + 'Hover'); + }); + + Event.add(t.id, 'mouseout', function() { + if (!DOM.hasClass(t.id, cp + 'Disabled')) + DOM.removeClass(t.id, cp + 'Hover'); + }); + } + + t.onPostRender.dispatch(t, DOM.get(t.id)); + }, + + destroy : function() { + this.parent(); + + Event.clear(this.id + '_text'); + Event.clear(this.id + '_open'); + } + }); +})(tinymce); + +(function(tinymce) { + var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each, Dispatcher = tinymce.util.Dispatcher, undef; + + tinymce.create('tinymce.ui.NativeListBox:tinymce.ui.ListBox', { + NativeListBox : function(id, s) { + this.parent(id, s); + this.classPrefix = 'mceNativeListBox'; + }, + + setDisabled : function(s) { + DOM.get(this.id).disabled = s; + this.setAriaProperty('disabled', s); + }, + + isDisabled : function() { + return DOM.get(this.id).disabled; + }, + + select : function(va) { + var t = this, fv, f; + + if (va == undef) + return t.selectByIndex(-1); + + // Is string or number make function selector + if (va && typeof(va)=="function") + f = va; + else { + f = function(v) { + return v == va; + }; + } + + // Do we need to do something? + if (va != t.selectedValue) { + // Find item + each(t.items, function(o, i) { + if (f(o.value)) { + fv = 1; + t.selectByIndex(i); + return false; + } + }); + + if (!fv) + t.selectByIndex(-1); + } + }, + + selectByIndex : function(idx) { + DOM.get(this.id).selectedIndex = idx + 1; + this.selectedValue = this.items[idx] ? this.items[idx].value : null; + }, + + add : function(n, v, a) { + var o, t = this; + + a = a || {}; + a.value = v; + + if (t.isRendered()) + DOM.add(DOM.get(this.id), 'option', a, n); + + o = { + title : n, + value : v, + attribs : a + }; + + t.items.push(o); + t.onAdd.dispatch(t, o); + }, + + getLength : function() { + return this.items.length; + }, + + renderHTML : function() { + var h, t = this; + + h = DOM.createHTML('option', {value : ''}, '-- ' + t.settings.title + ' --'); + + each(t.items, function(it) { + h += DOM.createHTML('option', {value : it.value}, it.title); + }); + + h = DOM.createHTML('select', {id : t.id, 'class' : 'mceNativeListBox', 'aria-labelledby': t.id + '_aria'}, h); + h += DOM.createHTML('span', {id : t.id + '_aria', 'style': 'display: none'}, t.settings.title); + return h; + }, + + postRender : function() { + var t = this, ch, changeListenerAdded = true; + + t.rendered = true; + + function onChange(e) { + var v = t.items[e.target.selectedIndex - 1]; + + if (v && (v = v.value)) { + t.onChange.dispatch(t, v); + + if (t.settings.onselect) + t.settings.onselect(v); + } + }; + + Event.add(t.id, 'change', onChange); + + // Accessibility keyhandler + Event.add(t.id, 'keydown', function(e) { + var bf, DOM_VK_LEFT = 37, DOM_VK_RIGHT = 39, DOM_VK_UP = 38, DOM_VK_DOWN = 40, DOM_VK_RETURN = 13, DOM_VK_SPACE = 32; + + Event.remove(t.id, 'change', ch); + changeListenerAdded = false; + + bf = Event.add(t.id, 'blur', function() { + if (changeListenerAdded) return; + changeListenerAdded = true; + Event.add(t.id, 'change', onChange); + Event.remove(t.id, 'blur', bf); + }); + + if (e.keyCode == DOM_VK_RETURN || e.keyCode == DOM_VK_SPACE) { + onChange(e); + return Event.cancel(e); + } else if (e.keyCode == DOM_VK_DOWN || e.keyCode == DOM_VK_UP) { + // allow native implementation (navigate select element options) + e.stopImmediatePropagation(); + } + }); + + t.onPostRender.dispatch(t, DOM.get(t.id)); + } + }); +})(tinymce); + +(function(tinymce) { + var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each; + + tinymce.create('tinymce.ui.MenuButton:tinymce.ui.Button', { + MenuButton : function(id, s, ed) { + this.parent(id, s, ed); + + this.onRenderMenu = new tinymce.util.Dispatcher(this); + + s.menu_container = s.menu_container || DOM.doc.body; + }, + + showMenu : function() { + var t = this, p1, p2, e = DOM.get(t.id), m; + + if (t.isDisabled()) + return; + + if (!t.isMenuRendered) { + t.renderMenu(); + t.isMenuRendered = true; + } + + if (t.isMenuVisible) + return t.hideMenu(); + + p1 = DOM.getPos(t.settings.menu_container); + p2 = DOM.getPos(e); + + m = t.menu; + m.settings.offset_x = p2.x; + m.settings.offset_y = p2.y; + m.settings.vp_offset_x = p2.x; + m.settings.vp_offset_y = p2.y; + m.settings.keyboard_focus = t._focused; + m.showMenu(0, e.firstChild.clientHeight); + + Event.add(DOM.doc, 'mousedown', t.hideMenu, t); + t.setState('Selected', 1); + + t.isMenuVisible = 1; + }, + + renderMenu : function() { + var t = this, m; + + m = t.settings.control_manager.createDropMenu(t.id + '_menu', { + menu_line : 1, + 'class' : this.classPrefix + 'Menu', + icons : t.settings.icons + }); + + m.onHideMenu.add(function() { + t.hideMenu(); + t.focus(); + }); + + t.onRenderMenu.dispatch(t, m); + t.menu = m; + }, + + hideMenu : function(e) { + var t = this; + + // Prevent double toogles by canceling the mouse click event to the button + if (e && e.type == "mousedown" && DOM.getParent(e.target, function(e) {return e.id === t.id || e.id === t.id + '_open';})) + return; + + if (!e || !DOM.getParent(e.target, '.mceMenu')) { + t.setState('Selected', 0); + Event.remove(DOM.doc, 'mousedown', t.hideMenu, t); + if (t.menu) + t.menu.hideMenu(); + } + + t.isMenuVisible = 0; + }, + + postRender : function() { + var t = this, s = t.settings; + + Event.add(t.id, 'click', function() { + if (!t.isDisabled()) { + if (s.onclick) + s.onclick(t.value); + + t.showMenu(); + } + }); + } + }); +})(tinymce); + +(function(tinymce) { + var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each; + + tinymce.create('tinymce.ui.SplitButton:tinymce.ui.MenuButton', { + SplitButton : function(id, s, ed) { + this.parent(id, s, ed); + this.classPrefix = 'mceSplitButton'; + }, + + renderHTML : function() { + var h, t = this, s = t.settings, h1; + + h = ''; + + if (s.image) + h1 = DOM.createHTML('img ', {src : s.image, role: 'presentation', 'class' : 'mceAction ' + s['class']}); + else + h1 = DOM.createHTML('span', {'class' : 'mceAction ' + s['class']}, ''); + + h1 += DOM.createHTML('span', {'class': 'mceVoiceLabel mceIconOnly', id: t.id + '_voice', style: 'display:none;'}, s.title); + h += '' + DOM.createHTML('a', {role: 'button', id : t.id + '_action', tabindex: '-1', href : 'javascript:;', 'class' : 'mceAction ' + s['class'], onclick : "return false;", onmousedown : 'return false;', title : s.title}, h1) + ''; + + h1 = DOM.createHTML('span', {'class' : 'mceOpen ' + s['class']}, ''); + h += '' + DOM.createHTML('a', {role: 'button', id : t.id + '_open', tabindex: '-1', href : 'javascript:;', 'class' : 'mceOpen ' + s['class'], onclick : "return false;", onmousedown : 'return false;', title : s.title}, h1) + ''; + + h += ''; + h = DOM.createHTML('table', { role: 'presentation', 'class' : 'mceSplitButton mceSplitButtonEnabled ' + s['class'], cellpadding : '0', cellspacing : '0', title : s.title}, h); + return DOM.createHTML('div', {id : t.id, role: 'button', tabindex: '0', 'aria-labelledby': t.id + '_voice', 'aria-haspopup': 'true'}, h); + }, + + postRender : function() { + var t = this, s = t.settings, activate; + + if (s.onclick) { + activate = function(evt) { + if (!t.isDisabled()) { + s.onclick(t.value); + Event.cancel(evt); + } + }; + Event.add(t.id + '_action', 'click', activate); + Event.add(t.id, ['click', 'keydown'], function(evt) { + var DOM_VK_SPACE = 32, DOM_VK_ENTER = 14, DOM_VK_RETURN = 13, DOM_VK_UP = 38, DOM_VK_DOWN = 40; + if ((evt.keyCode === 32 || evt.keyCode === 13 || evt.keyCode === 14) && !evt.altKey && !evt.ctrlKey && !evt.metaKey) { + activate(); + Event.cancel(evt); + } else if (evt.type === 'click' || evt.keyCode === DOM_VK_DOWN) { + t.showMenu(); + Event.cancel(evt); + } + }); + } + + Event.add(t.id + '_open', 'click', function (evt) { + t.showMenu(); + Event.cancel(evt); + }); + Event.add([t.id, t.id + '_open'], 'focus', function() {t._focused = 1;}); + Event.add([t.id, t.id + '_open'], 'blur', function() {t._focused = 0;}); + + // Old IE doesn't have hover on all elements + if (tinymce.isIE6 || !DOM.boxModel) { + Event.add(t.id, 'mouseover', function() { + if (!DOM.hasClass(t.id, 'mceSplitButtonDisabled')) + DOM.addClass(t.id, 'mceSplitButtonHover'); + }); + + Event.add(t.id, 'mouseout', function() { + if (!DOM.hasClass(t.id, 'mceSplitButtonDisabled')) + DOM.removeClass(t.id, 'mceSplitButtonHover'); + }); + } + }, + + destroy : function() { + this.parent(); + + Event.clear(this.id + '_action'); + Event.clear(this.id + '_open'); + Event.clear(this.id); + } + }); +})(tinymce); + +(function(tinymce) { + var DOM = tinymce.DOM, Event = tinymce.dom.Event, is = tinymce.is, each = tinymce.each; + + tinymce.create('tinymce.ui.ColorSplitButton:tinymce.ui.SplitButton', { + ColorSplitButton : function(id, s, ed) { + var t = this; + + t.parent(id, s, ed); + + t.settings = s = tinymce.extend({ + colors : '000000,993300,333300,003300,003366,000080,333399,333333,800000,FF6600,808000,008000,008080,0000FF,666699,808080,FF0000,FF9900,99CC00,339966,33CCCC,3366FF,800080,999999,FF00FF,FFCC00,FFFF00,00FF00,00FFFF,00CCFF,993366,C0C0C0,FF99CC,FFCC99,FFFF99,CCFFCC,CCFFFF,99CCFF,CC99FF,FFFFFF', + grid_width : 8, + default_color : '#888888' + }, t.settings); + + t.onShowMenu = new tinymce.util.Dispatcher(t); + + t.onHideMenu = new tinymce.util.Dispatcher(t); + + t.value = s.default_color; + }, + + showMenu : function() { + var t = this, r, p, e, p2; + + if (t.isDisabled()) + return; + + if (!t.isMenuRendered) { + t.renderMenu(); + t.isMenuRendered = true; + } + + if (t.isMenuVisible) + return t.hideMenu(); + + e = DOM.get(t.id); + DOM.show(t.id + '_menu'); + DOM.addClass(e, 'mceSplitButtonSelected'); + p2 = DOM.getPos(e); + DOM.setStyles(t.id + '_menu', { + left : p2.x, + top : p2.y + e.firstChild.clientHeight, + zIndex : 200000 + }); + e = 0; + + Event.add(DOM.doc, 'mousedown', t.hideMenu, t); + t.onShowMenu.dispatch(t); + + if (t._focused) { + t._keyHandler = Event.add(t.id + '_menu', 'keydown', function(e) { + if (e.keyCode == 27) + t.hideMenu(); + }); + + DOM.select('a', t.id + '_menu')[0].focus(); // Select first link + } + + t.keyboardNav = new tinymce.ui.KeyboardNavigation({ + root: t.id + '_menu', + items: DOM.select('a', t.id + '_menu'), + onCancel: function() { + t.hideMenu(); + t.focus(); + } + }); + + t.keyboardNav.focus(); + t.isMenuVisible = 1; + }, + + hideMenu : function(e) { + var t = this; + + if (t.isMenuVisible) { + // Prevent double toogles by canceling the mouse click event to the button + if (e && e.type == "mousedown" && DOM.getParent(e.target, function(e) {return e.id === t.id + '_open';})) + return; + + if (!e || !DOM.getParent(e.target, '.mceSplitButtonMenu')) { + DOM.removeClass(t.id, 'mceSplitButtonSelected'); + Event.remove(DOM.doc, 'mousedown', t.hideMenu, t); + Event.remove(t.id + '_menu', 'keydown', t._keyHandler); + DOM.hide(t.id + '_menu'); + } + + t.isMenuVisible = 0; + t.onHideMenu.dispatch(); + t.keyboardNav.destroy(); + } + }, + + renderMenu : function() { + var t = this, m, i = 0, s = t.settings, n, tb, tr, w, context; + + w = DOM.add(s.menu_container, 'div', {role: 'listbox', id : t.id + '_menu', 'class' : s.menu_class + ' ' + s['class'], style : 'position:absolute;left:0;top:-1000px;'}); + m = DOM.add(w, 'div', {'class' : s['class'] + ' mceSplitButtonMenu'}); + DOM.add(m, 'span', {'class' : 'mceMenuLine'}); + + n = DOM.add(m, 'table', {role: 'presentation', 'class' : 'mceColorSplitMenu'}); + tb = DOM.add(n, 'tbody'); + + // Generate color grid + i = 0; + each(is(s.colors, 'array') ? s.colors : s.colors.split(','), function(c) { + c = c.replace(/^#/, ''); + + if (!i--) { + tr = DOM.add(tb, 'tr'); + i = s.grid_width - 1; + } + + n = DOM.add(tr, 'td'); + var settings = { + href : 'javascript:;', + style : { + backgroundColor : '#' + c + }, + 'title': t.editor.getLang('colors.' + c, c), + 'data-mce-color' : '#' + c + }; + + // adding a proper ARIA role = button causes JAWS to read things incorrectly on IE. + if (!tinymce.isIE ) { + settings.role = 'option'; + } + + n = DOM.add(n, 'a', settings); + + if (t.editor.forcedHighContrastMode) { + n = DOM.add(n, 'canvas', { width: 16, height: 16, 'aria-hidden': 'true' }); + if (n.getContext && (context = n.getContext("2d"))) { + context.fillStyle = '#' + c; + context.fillRect(0, 0, 16, 16); + } else { + // No point leaving a canvas element around if it's not supported for drawing on anyway. + DOM.remove(n); + } + } + }); + + if (s.more_colors_func) { + n = DOM.add(tb, 'tr'); + n = DOM.add(n, 'td', {colspan : s.grid_width, 'class' : 'mceMoreColors'}); + n = DOM.add(n, 'a', {role: 'option', id : t.id + '_more', href : 'javascript:;', onclick : 'return false;', 'class' : 'mceMoreColors'}, s.more_colors_title); + + Event.add(n, 'click', function(e) { + s.more_colors_func.call(s.more_colors_scope || this); + return Event.cancel(e); // Cancel to fix onbeforeunload problem + }); + } + + DOM.addClass(m, 'mceColorSplitMenu'); + + // Prevent IE from scrolling and hindering click to occur #4019 + Event.add(t.id + '_menu', 'mousedown', function(e) {return Event.cancel(e);}); + + Event.add(t.id + '_menu', 'click', function(e) { + var c; + + e = DOM.getParent(e.target, 'a', tb); + + if (e && e.nodeName.toLowerCase() == 'a' && (c = e.getAttribute('data-mce-color'))) + t.setColor(c); + + return false; // Prevent IE auto save warning + }); + + return w; + }, + + setColor : function(c) { + this.displayColor(c); + this.hideMenu(); + this.settings.onselect(c); + }, + + displayColor : function(c) { + var t = this; + + DOM.setStyle(t.id + '_preview', 'backgroundColor', c); + + t.value = c; + }, + + postRender : function() { + var t = this, id = t.id; + + t.parent(); + DOM.add(id + '_action', 'div', {id : id + '_preview', 'class' : 'mceColorPreview'}); + DOM.setStyle(t.id + '_preview', 'backgroundColor', t.value); + }, + + destroy : function() { + var self = this; + + self.parent(); + + Event.clear(self.id + '_menu'); + Event.clear(self.id + '_more'); + DOM.remove(self.id + '_menu'); + + if (self.keyboardNav) { + self.keyboardNav.destroy(); + } + } + }); +})(tinymce); + +(function(tinymce) { +// Shorten class names +var dom = tinymce.DOM, each = tinymce.each, Event = tinymce.dom.Event; +tinymce.create('tinymce.ui.ToolbarGroup:tinymce.ui.Container', { + renderHTML : function() { + var t = this, h = [], controls = t.controls, each = tinymce.each, settings = t.settings; + + h.push('
    '); + //TODO: ACC test this out - adding a role = application for getting the landmarks working well. + h.push(""); + h.push(''); + each(controls, function(toolbar) { + h.push(toolbar.renderHTML()); + }); + h.push(""); + h.push('
    '); + + return h.join(''); + }, + + focus : function() { + var t = this; + dom.get(t.id).focus(); + }, + + postRender : function() { + var t = this, items = []; + + each(t.controls, function(toolbar) { + each (toolbar.controls, function(control) { + if (control.id) { + items.push(control); + } + }); + }); + + t.keyNav = new tinymce.ui.KeyboardNavigation({ + root: t.id, + items: items, + onCancel: function() { + //Move focus if webkit so that navigation back will read the item. + if (tinymce.isWebKit) { + dom.get(t.editor.id+"_ifr").focus(); + } + t.editor.focus(); + }, + excludeFromTabOrder: !t.settings.tab_focus_toolbar + }); + }, + + destroy : function() { + var self = this; + + self.parent(); + self.keyNav.destroy(); + Event.clear(self.id); + } +}); +})(tinymce); + +(function(tinymce) { +// Shorten class names +var dom = tinymce.DOM, each = tinymce.each; +tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { + renderHTML : function() { + var t = this, h = '', c, co, s = t.settings, i, pr, nx, cl; + + cl = t.controls; + for (i=0; i')); + } + + // Add toolbar end before list box and after the previous button + // This is to fix the o2k7 editor skins + if (pr && co.ListBox) { + if (pr.Button || pr.SplitButton) + h += dom.createHTML('td', {'class' : 'mceToolbarEnd'}, dom.createHTML('span', null, '')); + } + + // Render control HTML + + // IE 8 quick fix, needed to propertly generate a hit area for anchors + if (dom.stdMode) + h += '' + co.renderHTML() + ''; + else + h += '' + co.renderHTML() + ''; + + // Add toolbar start after list box and before the next button + // This is to fix the o2k7 editor skins + if (nx && co.ListBox) { + if (nx.Button || nx.SplitButton) + h += dom.createHTML('td', {'class' : 'mceToolbarStart'}, dom.createHTML('span', null, '')); + } + } + + c = 'mceToolbarEnd'; + + if (co.Button) + c += ' mceToolbarEndButton'; + else if (co.SplitButton) + c += ' mceToolbarEndSplitButton'; + else if (co.ListBox) + c += ' mceToolbarEndListBox'; + + h += dom.createHTML('td', {'class' : c}, dom.createHTML('span', null, '')); + + return dom.createHTML('table', {id : t.id, 'class' : 'mceToolbar' + (s['class'] ? ' ' + s['class'] : ''), cellpadding : '0', cellspacing : '0', align : t.settings.align || '', role: 'presentation', tabindex: '-1'}, '' + h + ''); + } +}); +})(tinymce); + +(function(tinymce) { + var Dispatcher = tinymce.util.Dispatcher, each = tinymce.each; + + tinymce.create('tinymce.AddOnManager', { + AddOnManager : function() { + var self = this; + + self.items = []; + self.urls = {}; + self.lookup = {}; + self.onAdd = new Dispatcher(self); + }, + + get : function(n) { + if (this.lookup[n]) { + return this.lookup[n].instance; + } else { + return undefined; + } + }, + + dependencies : function(n) { + var result; + if (this.lookup[n]) { + result = this.lookup[n].dependencies; + } + return result || []; + }, + + requireLangPack : function(n) { + var s = tinymce.settings; + + if (s && s.language && s.language_load !== false) + tinymce.ScriptLoader.add(this.urls[n] + '/langs/' + s.language + '.js'); + }, + + add : function(id, o, dependencies) { + this.items.push(o); + this.lookup[id] = {instance:o, dependencies:dependencies}; + this.onAdd.dispatch(this, id, o); + + return o; + }, + createUrl: function(baseUrl, dep) { + if (typeof dep === "object") { + return dep + } else { + return {prefix: baseUrl.prefix, resource: dep, suffix: baseUrl.suffix}; + } + }, + + addComponents: function(pluginName, scripts) { + var pluginUrl = this.urls[pluginName]; + tinymce.each(scripts, function(script){ + tinymce.ScriptLoader.add(pluginUrl+"/"+script); + }); + }, + + load : function(n, u, cb, s) { + var t = this, url = u; + + function loadDependencies() { + var dependencies = t.dependencies(n); + tinymce.each(dependencies, function(dep) { + var newUrl = t.createUrl(u, dep); + t.load(newUrl.resource, newUrl, undefined, undefined); + }); + if (cb) { + if (s) { + cb.call(s); + } else { + cb.call(tinymce.ScriptLoader); + } + } + } + + if (t.urls[n]) + return; + if (typeof u === "object") + url = u.prefix + u.resource + u.suffix; + + if (url.indexOf('/') !== 0 && url.indexOf('://') == -1) + url = tinymce.baseURL + '/' + url; + + t.urls[n] = url.substring(0, url.lastIndexOf('/')); + + if (t.lookup[n]) { + loadDependencies(); + } else { + tinymce.ScriptLoader.add(url, loadDependencies, s); + } + } + }); + + // Create plugin and theme managers + tinymce.PluginManager = new tinymce.AddOnManager(); + tinymce.ThemeManager = new tinymce.AddOnManager(); +}(tinymce)); + +(function(tinymce) { + // Shorten names + var each = tinymce.each, extend = tinymce.extend, + DOM = tinymce.DOM, Event = tinymce.dom.Event, + ThemeManager = tinymce.ThemeManager, PluginManager = tinymce.PluginManager, + explode = tinymce.explode, + Dispatcher = tinymce.util.Dispatcher, undef, instanceCounter = 0; + + // Setup some URLs where the editor API is located and where the document is + tinymce.documentBaseURL = window.location.href.replace(/[\?#].*$/, '').replace(/[\/\\][^\/]+$/, ''); + if (!/[\/\\]$/.test(tinymce.documentBaseURL)) + tinymce.documentBaseURL += '/'; + + tinymce.baseURL = new tinymce.util.URI(tinymce.documentBaseURL).toAbsolute(tinymce.baseURL); + + tinymce.baseURI = new tinymce.util.URI(tinymce.baseURL); + + // Add before unload listener + // This was required since IE was leaking memory if you added and removed beforeunload listeners + // with attachEvent/detatchEvent so this only adds one listener and instances can the attach to the onBeforeUnload event + tinymce.onBeforeUnload = new Dispatcher(tinymce); + + // Must be on window or IE will leak if the editor is placed in frame or iframe + Event.add(window, 'beforeunload', function(e) { + tinymce.onBeforeUnload.dispatch(tinymce, e); + }); + + tinymce.onAddEditor = new Dispatcher(tinymce); + + tinymce.onRemoveEditor = new Dispatcher(tinymce); + + tinymce.EditorManager = extend(tinymce, { + editors : [], + + i18n : {}, + + activeEditor : null, + + init : function(s) { + var t = this, pl, sl = tinymce.ScriptLoader, e, el = [], ed; + + function createId(elm) { + var id = elm.id; + + // Use element id, or unique name or generate a unique id + if (!id) { + id = elm.name; + + if (id && !DOM.get(id)) { + id = elm.name; + } else { + // Generate unique name + id = DOM.uniqueId(); + } + + elm.setAttribute('id', id); + } + + return id; + }; + + function execCallback(se, n, s) { + var f = se[n]; + + if (!f) + return; + + if (tinymce.is(f, 'string')) { + s = f.replace(/\.\w+$/, ''); + s = s ? tinymce.resolve(s) : 0; + f = tinymce.resolve(f); + } + + return f.apply(s || this, Array.prototype.slice.call(arguments, 2)); + }; + + function hasClass(n, c) { + return c.constructor === RegExp ? c.test(n.className) : DOM.hasClass(n, c); + }; + + t.settings = s; + + // Legacy call + Event.bind(window, 'ready', function() { + var l, co; + + execCallback(s, 'onpageload'); + + switch (s.mode) { + case "exact": + l = s.elements || ''; + + if(l.length > 0) { + each(explode(l), function(v) { + if (DOM.get(v)) { + ed = new tinymce.Editor(v, s); + el.push(ed); + ed.render(1); + } else { + each(document.forms, function(f) { + each(f.elements, function(e) { + if (e.name === v) { + v = 'mce_editor_' + instanceCounter++; + DOM.setAttrib(e, 'id', v); + + ed = new tinymce.Editor(v, s); + el.push(ed); + ed.render(1); + } + }); + }); + } + }); + } + break; + + case "textareas": + case "specific_textareas": + each(DOM.select('textarea'), function(elm) { + if (s.editor_deselector && hasClass(elm, s.editor_deselector)) + return; + + if (!s.editor_selector || hasClass(elm, s.editor_selector)) { + ed = new tinymce.Editor(createId(elm), s); + el.push(ed); + ed.render(1); + } + }); + break; + + default: + if (s.types) { + // Process type specific selector + each(s.types, function(type) { + each(DOM.select(type.selector), function(elm) { + var editor = new tinymce.Editor(createId(elm), tinymce.extend({}, s, type)); + el.push(editor); + editor.render(1); + }); + }); + } else if (s.selector) { + // Process global selector + each(DOM.select(s.selector), function(elm) { + var editor = new tinymce.Editor(createId(elm), s); + el.push(editor); + editor.render(1); + }); + } + } + + // Call onInit when all editors are initialized + if (s.oninit) { + l = co = 0; + + each(el, function(ed) { + co++; + + if (!ed.initialized) { + // Wait for it + ed.onInit.add(function() { + l++; + + // All done + if (l == co) + execCallback(s, 'oninit'); + }); + } else + l++; + + // All done + if (l == co) + execCallback(s, 'oninit'); + }); + } + }); + }, + + get : function(id) { + if (id === undef) + return this.editors; + + if (!this.editors.hasOwnProperty(id)) + return undef; + + return this.editors[id]; + }, + + getInstanceById : function(id) { + return this.get(id); + }, + + add : function(editor) { + var self = this, editors = self.editors; + + // Add named and index editor instance + editors[editor.id] = editor; + editors.push(editor); + + self._setActive(editor); + self.onAddEditor.dispatch(self, editor); + + + // Patch the tinymce.Editor instance with jQuery adapter logic + if (tinymce.adapter) + tinymce.adapter.patchEditor(editor); + + + return editor; + }, + + remove : function(editor) { + var t = this, i, editors = t.editors; + + // Not in the collection + if (!editors[editor.id]) + return null; + + delete editors[editor.id]; + + for (i = 0; i < editors.length; i++) { + if (editors[i] == editor) { + editors.splice(i, 1); + break; + } + } + + // Select another editor since the active one was removed + if (t.activeEditor == editor) + t._setActive(editors[0]); + + editor.destroy(); + t.onRemoveEditor.dispatch(t, editor); + + return editor; + }, + + execCommand : function(c, u, v) { + var t = this, ed = t.get(v), w; + + function clr() { + ed.destroy(); + w.detachEvent('onunload', clr); + w = w.tinyMCE = w.tinymce = null; // IE leak + }; + + // Manager commands + switch (c) { + case "mceFocus": + ed.focus(); + return true; + + case "mceAddEditor": + case "mceAddControl": + if (!t.get(v)) + new tinymce.Editor(v, t.settings).render(); + + return true; + + case "mceAddFrameControl": + w = v.window; + + // Add tinyMCE global instance and tinymce namespace to specified window + w.tinyMCE = tinyMCE; + w.tinymce = tinymce; + + tinymce.DOM.doc = w.document; + tinymce.DOM.win = w; + + ed = new tinymce.Editor(v.element_id, v); + ed.render(); + + // Fix IE memory leaks + if (tinymce.isIE && ! tinymce.isIE11) { + w.attachEvent('onunload', clr); + } + + v.page_window = null; + + return true; + + case "mceRemoveEditor": + case "mceRemoveControl": + if (ed) + ed.remove(); + + return true; + + case 'mceToggleEditor': + if (!ed) { + t.execCommand('mceAddControl', 0, v); + return true; + } + + if (ed.isHidden()) + ed.show(); + else + ed.hide(); + + return true; + } + + // Run command on active editor + if (t.activeEditor) + return t.activeEditor.execCommand(c, u, v); + + return false; + }, + + execInstanceCommand : function(id, c, u, v) { + var ed = this.get(id); + + if (ed) + return ed.execCommand(c, u, v); + + return false; + }, + + triggerSave : function() { + each(this.editors, function(e) { + e.save(); + }); + }, + + addI18n : function(p, o) { + var lo, i18n = this.i18n; + + if (!tinymce.is(p, 'string')) { + each(p, function(o, lc) { + each(o, function(o, g) { + each(o, function(o, k) { + if (g === 'common') + i18n[lc + '.' + k] = o; + else + i18n[lc + '.' + g + '.' + k] = o; + }); + }); + }); + } else { + each(o, function(o, k) { + i18n[p + '.' + k] = o; + }); + } + }, + + // Private methods + + _setActive : function(editor) { + this.selectedInstance = this.activeEditor = editor; + } + }); +})(tinymce); + +(function(tinymce) { + // Shorten these names + var DOM = tinymce.DOM, Event = tinymce.dom.Event, extend = tinymce.extend, + each = tinymce.each, isGecko = tinymce.isGecko, + isIE = tinymce.isIE, isWebKit = tinymce.isWebKit, is = tinymce.is, + ThemeManager = tinymce.ThemeManager, PluginManager = tinymce.PluginManager, + explode = tinymce.explode; + + tinymce.create('tinymce.Editor', { + Editor : function(id, settings) { + var self = this, TRUE = true; + + self.settings = settings = extend({ + id : id, + language : 'en', + theme : 'advanced', + skin : 'default', + delta_width : 0, + delta_height : 0, + popup_css : '', + plugins : '', + document_base_url : tinymce.documentBaseURL, + add_form_submit_trigger : TRUE, + submit_patch : TRUE, + add_unload_trigger : TRUE, + convert_urls : TRUE, + relative_urls : TRUE, + remove_script_host : TRUE, + table_inline_editing : false, + object_resizing : TRUE, + accessibility_focus : TRUE, + doctype : tinymce.isIE6 ? '' : '', // Use old doctype on IE 6 to avoid horizontal scroll + visual : TRUE, + font_size_style_values : 'xx-small,x-small,small,medium,large,x-large,xx-large', + font_size_legacy_values : 'xx-small,small,medium,large,x-large,xx-large,300%', // See: http://www.w3.org/TR/CSS2/fonts.html#propdef-font-size + apply_source_formatting : TRUE, + directionality : 'ltr', + forced_root_block : 'p', + hidden_input : TRUE, + padd_empty_editor : TRUE, + render_ui : TRUE, + indentation : '30px', + fix_table_elements : TRUE, + inline_styles : TRUE, + convert_fonts_to_spans : TRUE, + indent : 'simple', + indent_before : 'p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,li,area,table,thead,tfoot,tbody,tr,section,article,hgroup,aside,figure,option,optgroup,datalist', + indent_after : 'p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,li,area,table,thead,tfoot,tbody,tr,section,article,hgroup,aside,figure,option,optgroup,datalist', + validate : TRUE, + entity_encoding : 'named', + url_converter : self.convertURL, + url_converter_scope : self, + ie7_compat : TRUE + }, settings); + + self.id = self.editorId = id; + + self.isNotDirty = false; + + self.plugins = {}; + + self.documentBaseURI = new tinymce.util.URI(settings.document_base_url || tinymce.documentBaseURL, { + base_uri : tinyMCE.baseURI + }); + + self.baseURI = tinymce.baseURI; + + self.contentCSS = []; + + self.contentStyles = []; + + // Creates all events like onClick, onSetContent etc see Editor.Events.js for the actual logic + self.setupEvents(); + + // Internal command handler objects + self.execCommands = {}; + self.queryStateCommands = {}; + self.queryValueCommands = {}; + + // Call setup + self.execCallback('setup', self); + }, + + render : function(nst) { + var t = this, s = t.settings, id = t.id, sl = tinymce.ScriptLoader; + + // Page is not loaded yet, wait for it + if (!Event.domLoaded) { + Event.add(window, 'ready', function() { + t.render(); + }); + return; + } + + tinyMCE.settings = s; + + // Element not found, then skip initialization + if (!t.getElement()) + return; + + // Is a iPad/iPhone and not on iOS5, then skip initialization. We need to sniff + // here since the browser says it has contentEditable support but there is no visible caret. + if (tinymce.isIDevice && !tinymce.isIOS5) + return; + + // Add hidden input for non input elements inside form elements + if (!/TEXTAREA|INPUT/i.test(t.getElement().nodeName) && s.hidden_input && DOM.getParent(id, 'form')) + DOM.insertAfter(DOM.create('input', {type : 'hidden', name : id}), id); + + // Hide target element early to prevent content flashing + if (!s.content_editable) { + t.orgVisibility = t.getElement().style.visibility; + t.getElement().style.visibility = 'hidden'; + } + + if (tinymce.WindowManager) + t.windowManager = new tinymce.WindowManager(t); + + if (s.encoding == 'xml') { + t.onGetContent.add(function(ed, o) { + if (o.save) + o.content = DOM.encode(o.content); + }); + } + + if (s.add_form_submit_trigger) { + t.onSubmit.addToTop(function() { + if (t.initialized) { + t.save(); + t.isNotDirty = 1; + } + }); + } + + if (s.add_unload_trigger) { + t._beforeUnload = tinyMCE.onBeforeUnload.add(function() { + if (t.initialized && !t.destroyed && !t.isHidden()) + t.save({format : 'raw', no_events : true}); + }); + } + + tinymce.addUnload(t.destroy, t); + + if (s.submit_patch) { + t.onBeforeRenderUI.add(function() { + var n = t.getElement().form; + + if (!n) + return; + + // Already patched + if (n._mceOldSubmit) + return; + + // Check page uses id="submit" or name="submit" for it's submit button + if (!n.submit.nodeType && !n.submit.length) { + t.formElement = n; + n._mceOldSubmit = n.submit; + n.submit = function() { + // Save all instances + tinymce.triggerSave(); + t.isNotDirty = 1; + + return t.formElement._mceOldSubmit(t.formElement); + }; + } + + n = null; + }); + } + + // Load scripts + function loadScripts() { + if (s.language && s.language_load !== false) + sl.add(tinymce.baseURL + '/langs/' + s.language + '.js'); + + if (s.theme && typeof s.theme != "function" && s.theme.charAt(0) != '-' && !ThemeManager.urls[s.theme]) + ThemeManager.load(s.theme, 'themes/' + s.theme + '/editor_template' + tinymce.suffix + '.js'); + + each(explode(s.plugins), function(p) { + if (p &&!PluginManager.urls[p]) { + if (p.charAt(0) == '-') { + p = p.substr(1, p.length); + var dependencies = PluginManager.dependencies(p); + each(dependencies, function(dep) { + var defaultSettings = {prefix:'plugins/', resource: dep, suffix:'/editor_plugin' + tinymce.suffix + '.js'}; + dep = PluginManager.createUrl(defaultSettings, dep); + PluginManager.load(dep.resource, dep); + }); + } else { + // Skip safari plugin, since it is removed as of 3.3b1 + if (p == 'safari') { + return; + } + PluginManager.load(p, {prefix:'plugins/', resource: p, suffix:'/editor_plugin' + tinymce.suffix + '.js'}); + } + } + }); + + // Init when que is loaded + sl.loadQueue(function() { + if (!t.removed) + t.init(); + }); + }; + + loadScripts(); + }, + + init : function() { + var n, t = this, s = t.settings, w, h, mh, e = t.getElement(), o, ti, u, bi, bc, re, i, initializedPlugins = []; + + tinymce.add(t); + + s.aria_label = s.aria_label || DOM.getAttrib(e, 'aria-label', t.getLang('aria.rich_text_area')); + + if (s.theme) { + if (typeof s.theme != "function") { + s.theme = s.theme.replace(/-/, ''); + o = ThemeManager.get(s.theme); + t.theme = new o(); + + if (t.theme.init) + t.theme.init(t, ThemeManager.urls[s.theme] || tinymce.documentBaseURL.replace(/\/$/, '')); + } else { + t.theme = s.theme; + } + } + + function initPlugin(p) { + var c = PluginManager.get(p), u = PluginManager.urls[p] || tinymce.documentBaseURL.replace(/\/$/, ''), po; + if (c && tinymce.inArray(initializedPlugins,p) === -1) { + each(PluginManager.dependencies(p), function(dep){ + initPlugin(dep); + }); + po = new c(t, u); + + t.plugins[p] = po; + + if (po.init) { + po.init(t, u); + initializedPlugins.push(p); + } + } + } + + // Create all plugins + each(explode(s.plugins.replace(/\-/g, '')), initPlugin); + + // Setup popup CSS path(s) + if (s.popup_css !== false) { + if (s.popup_css) + s.popup_css = t.documentBaseURI.toAbsolute(s.popup_css); + else + s.popup_css = t.baseURI.toAbsolute("themes/" + s.theme + "/skins/" + s.skin + "/dialog.css"); + } + + if (s.popup_css_add) + s.popup_css += ',' + t.documentBaseURI.toAbsolute(s.popup_css_add); + + t.controlManager = new tinymce.ControlManager(t); + + // Enables users to override the control factory + t.onBeforeRenderUI.dispatch(t, t.controlManager); + + // Measure box + if (s.render_ui && t.theme) { + t.orgDisplay = e.style.display; + + if (typeof s.theme != "function") { + w = s.width || e.style.width || e.offsetWidth; + h = s.height || e.style.height || e.offsetHeight; + mh = s.min_height || 100; + re = /^[0-9\.]+(|px)$/i; + + if (re.test('' + w)) + w = Math.max(parseInt(w, 10) + (o.deltaWidth || 0), 100); + + if (re.test('' + h)) + h = Math.max(parseInt(h, 10) + (o.deltaHeight || 0), mh); + + // Render UI + o = t.theme.renderUI({ + targetNode : e, + width : w, + height : h, + deltaWidth : s.delta_width, + deltaHeight : s.delta_height + }); + + // Resize editor + DOM.setStyles(o.sizeContainer || o.editorContainer, { + width : w, + height : h + }); + + h = (o.iframeHeight || h) + (typeof(h) == 'number' ? (o.deltaHeight || 0) : ''); + if (h < mh) + h = mh; + } else { + o = s.theme(t, e); + + // Convert element type to id:s + if (o.editorContainer.nodeType) { + o.editorContainer = o.editorContainer.id = o.editorContainer.id || t.id + "_parent"; + } + + // Convert element type to id:s + if (o.iframeContainer.nodeType) { + o.iframeContainer = o.iframeContainer.id = o.iframeContainer.id || t.id + "_iframecontainer"; + } + + // Use specified iframe height or the targets offsetHeight + h = o.iframeHeight || e.offsetHeight; + + // Store away the selection when it's changed to it can be restored later with a editor.focus() call + if (isIE) { + t.onInit.add(function(ed) { + ed.dom.bind(ed.getBody(), 'beforedeactivate keydown keyup', function() { + ed.bookmark = ed.selection.getBookmark(1); + }); + }); + + t.onNodeChange.add(function(ed) { + if (document.activeElement.id == ed.id + "_ifr") { + ed.bookmark = ed.selection.getBookmark(1); + } + }); + } + } + + t.editorContainer = o.editorContainer; + } + + // Load specified content CSS last + if (s.content_css) { + each(explode(s.content_css), function(u) { + t.contentCSS.push(t.documentBaseURI.toAbsolute(u)); + }); + } + + // Load specified content CSS last + if (s.content_style) { + t.contentStyles.push(s.content_style); + } + + // Content editable mode ends here + if (s.content_editable) { + e = n = o = null; // Fix IE leak + return t.initContentBody(); + } + + // User specified a document.domain value + if (document.domain && location.hostname != document.domain) + tinymce.relaxedDomain = document.domain; + + t.iframeHTML = s.doctype + ''; + + // We only need to override paths if we have to + // IE has a bug where it remove site absolute urls to relative ones if this is specified + if (s.document_base_url != tinymce.documentBaseURL) + t.iframeHTML += ''; + + // IE8 doesn't support carets behind images setting ie7_compat would force IE8+ to run in IE7 compat mode. + if (tinymce.isIE8) { + if (s.ie7_compat) + t.iframeHTML += ''; + else + t.iframeHTML += ''; + } + + t.iframeHTML += ''; + + // Load the CSS by injecting them into the HTML this will reduce "flicker" + for (i = 0; i < t.contentCSS.length; i++) { + t.iframeHTML += ''; + } + + t.contentCSS = []; + + bi = s.body_id || 'tinymce'; + if (bi.indexOf('=') != -1) { + bi = t.getParam('body_id', '', 'hash'); + bi = bi[t.id] || bi; + } + + bc = s.body_class || ''; + if (bc.indexOf('=') != -1) { + bc = t.getParam('body_class', '', 'hash'); + bc = bc[t.id] || ''; + } + + t.iframeHTML += '
    '; + + // Domain relaxing enabled, then set document domain + if (tinymce.relaxedDomain && (isIE || (tinymce.isOpera && parseFloat(opera.version()) < 11))) { + // We need to write the contents here in IE since multiple writes messes up refresh button and back button + u = 'javascript:(function(){document.open();document.domain="' + document.domain + '";var ed = window.parent.tinyMCE.get("' + t.id + '");document.write(ed.iframeHTML);document.close();ed.initContentBody();})()'; + } + + // Create iframe + // TODO: ACC add the appropriate description on this. + n = DOM.add(o.iframeContainer, 'iframe', { + id : t.id + "_ifr", + src : u || 'javascript:""', // Workaround for HTTPS warning in IE6/7 + frameBorder : '0', + allowTransparency : "true", + title : s.aria_label, + style : { + width : '100%', + height : h, + display : 'block' // Important for Gecko to render the iframe correctly + } + }); + + t.contentAreaContainer = o.iframeContainer; + + if (o.editorContainer) { + DOM.get(o.editorContainer).style.display = t.orgDisplay; + } + + // Restore visibility on target element + e.style.visibility = t.orgVisibility; + + DOM.get(t.id).style.display = 'none'; + DOM.setAttrib(t.id, 'aria-hidden', true); + + if (!tinymce.relaxedDomain || !u) + t.initContentBody(); + + e = n = o = null; // Cleanup + }, + + initContentBody : function() { + var self = this, settings = self.settings, targetElm = DOM.get(self.id), doc = self.getDoc(), html, body, contentCssText; + + // Setup iframe body + if ((!isIE || !tinymce.relaxedDomain) && !settings.content_editable) { + doc.open(); + doc.write(self.iframeHTML); + doc.close(); + + if (tinymce.relaxedDomain) + doc.domain = tinymce.relaxedDomain; + } + + if (settings.content_editable) { + DOM.addClass(targetElm, 'mceContentBody'); + self.contentDocument = doc = settings.content_document || document; + self.contentWindow = settings.content_window || window; + self.bodyElement = targetElm; + + // Prevent leak in IE + settings.content_document = settings.content_window = null; + } + + // It will not steal focus while setting contentEditable + body = self.getBody(); + body.disabled = true; + + if (!settings.readonly) + body.contentEditable = self.getParam('content_editable_state', true); + + body.disabled = false; + + self.schema = new tinymce.html.Schema(settings); + + self.dom = new tinymce.dom.DOMUtils(doc, { + keep_values : true, + url_converter : self.convertURL, + url_converter_scope : self, + hex_colors : settings.force_hex_style_colors, + class_filter : settings.class_filter, + update_styles : true, + root_element : settings.content_editable ? self.id : null, + schema : self.schema + }); + + self.parser = new tinymce.html.DomParser(settings, self.schema); + + // Convert src and href into data-mce-src, data-mce-href and data-mce-style + self.parser.addAttributeFilter('src,href,style', function(nodes, name) { + var i = nodes.length, node, dom = self.dom, value, internalName; + + while (i--) { + node = nodes[i]; + value = node.attr(name); + internalName = 'data-mce-' + name; + + // Add internal attribute if we need to we don't on a refresh of the document + if (!node.attributes.map[internalName]) { + if (name === "style") + node.attr(internalName, dom.serializeStyle(dom.parseStyle(value), node.name)); + else + node.attr(internalName, self.convertURL(value, name, node.name)); + } + } + }); + + // Keep scripts from executing + self.parser.addNodeFilter('script', function(nodes, name) { + var i = nodes.length, node; + + while (i--) { + node = nodes[i]; + node.attr('type', 'mce-' + (node.attr('type') || 'text/javascript')); + } + }); + + self.parser.addNodeFilter('#cdata', function(nodes, name) { + var i = nodes.length, node; + + while (i--) { + node = nodes[i]; + node.type = 8; + node.name = '#comment'; + node.value = '[CDATA[' + node.value + ']]'; + } + }); + + self.parser.addNodeFilter('p,h1,h2,h3,h4,h5,h6,div', function(nodes, name) { + var i = nodes.length, node, nonEmptyElements = self.schema.getNonEmptyElements(); + + while (i--) { + node = nodes[i]; + + if (node.isEmpty(nonEmptyElements)) + node.empty().append(new tinymce.html.Node('br', 1)).shortEnded = true; + } + }); + + self.serializer = new tinymce.dom.Serializer(settings, self.dom, self.schema); + + self.selection = new tinymce.dom.Selection(self.dom, self.getWin(), self.serializer, self); + + self.formatter = new tinymce.Formatter(self); + + self.undoManager = new tinymce.UndoManager(self); + + self.forceBlocks = new tinymce.ForceBlocks(self); + self.enterKey = new tinymce.EnterKey(self); + self.editorCommands = new tinymce.EditorCommands(self); + + self.onExecCommand.add(function(editor, command) { + // Don't refresh the select lists until caret move + if (!/^(FontName|FontSize)$/.test(command)) + self.nodeChanged(); + }); + + // Pass through + self.serializer.onPreProcess.add(function(se, o) { + return self.onPreProcess.dispatch(self, o, se); + }); + + self.serializer.onPostProcess.add(function(se, o) { + return self.onPostProcess.dispatch(self, o, se); + }); + + self.onPreInit.dispatch(self); + + if (!settings.browser_spellcheck && !settings.gecko_spellcheck) + doc.body.spellcheck = false; + + if (!settings.readonly) { + self.bindNativeEvents(); + } + + self.controlManager.onPostRender.dispatch(self, self.controlManager); + self.onPostRender.dispatch(self); + + self.quirks = tinymce.util.Quirks(self); + + if (settings.directionality) + body.dir = settings.directionality; + + if (settings.nowrap) + body.style.whiteSpace = "nowrap"; + + if (settings.protect) { + self.onBeforeSetContent.add(function(ed, o) { + each(settings.protect, function(pattern) { + o.content = o.content.replace(pattern, function(str) { + return ''; + }); + }); + }); + } + + // Add visual aids when new contents is added + self.onSetContent.add(function() { + self.addVisual(self.getBody()); + }); + + // Remove empty contents + if (settings.padd_empty_editor) { + self.onPostProcess.add(function(ed, o) { + o.content = o.content.replace(/^(]*>( | |\s|\u00a0|)<\/p>[\r\n]*|
    [\r\n]*)$/, ''); + }); + } + + self.load({initial : true, format : 'html'}); + self.startContent = self.getContent({format : 'raw'}); + + self.initialized = true; + + self.onInit.dispatch(self); + self.execCallback('setupcontent_callback', self.id, body, doc); + self.execCallback('init_instance_callback', self); + self.focus(true); + self.nodeChanged({initial : true}); + + // Add editor specific CSS styles + if (self.contentStyles.length > 0) { + contentCssText = ''; + + each(self.contentStyles, function(style) { + contentCssText += style + "\r\n"; + }); + + self.dom.addStyle(contentCssText); + } + + // Load specified content CSS last + each(self.contentCSS, function(url) { + self.dom.loadCSS(url); + }); + + // Handle auto focus + if (settings.auto_focus) { + setTimeout(function () { + var ed = tinymce.get(settings.auto_focus); + + ed.selection.select(ed.getBody(), 1); + ed.selection.collapse(1); + ed.getBody().focus(); + ed.getWin().focus(); + }, 100); + } + + // Clean up references for IE + targetElm = doc = body = null; + }, + + focus : function(skip_focus) { + var oed, self = this, selection = self.selection, contentEditable = self.settings.content_editable, ieRng, controlElm, doc = self.getDoc(), body; + + if (!skip_focus) { + if (self.bookmark) { + selection.moveToBookmark(self.bookmark); + self.bookmark = null; + } + + // Get selected control element + ieRng = selection.getRng(); + if (ieRng.item) { + controlElm = ieRng.item(0); + } + + self._refreshContentEditable(); + + // Focus the window iframe + if (!contentEditable) { + self.getWin().focus(); + } + + // Focus the body as well since it's contentEditable + if (tinymce.isGecko || contentEditable) { + body = self.getBody(); + + // Check for setActive since it doesn't scroll to the element + if (body.setActive && ! tinymce.isIE11) { + body.setActive(); + } else { + body.focus(); + } + + if (contentEditable) { + selection.normalize(); + } + } + + // Restore selected control element + // This is needed when for example an image is selected within a + // layer a call to focus will then remove the control selection + if (controlElm && controlElm.ownerDocument == doc) { + ieRng = doc.body.createControlRange(); + ieRng.addElement(controlElm); + ieRng.select(); + } + } + + if (tinymce.activeEditor != self) { + if ((oed = tinymce.activeEditor) != null) + oed.onDeactivate.dispatch(oed, self); + + self.onActivate.dispatch(self, oed); + } + + tinymce._setActive(self); + }, + + execCallback : function(n) { + var t = this, f = t.settings[n], s; + + if (!f) + return; + + // Look through lookup + if (t.callbackLookup && (s = t.callbackLookup[n])) { + f = s.func; + s = s.scope; + } + + if (is(f, 'string')) { + s = f.replace(/\.\w+$/, ''); + s = s ? tinymce.resolve(s) : 0; + f = tinymce.resolve(f); + t.callbackLookup = t.callbackLookup || {}; + t.callbackLookup[n] = {func : f, scope : s}; + } + + return f.apply(s || t, Array.prototype.slice.call(arguments, 1)); + }, + + translate : function(s) { + var c = this.settings.language || 'en', i18n = tinymce.i18n; + + if (!s) + return ''; + + return i18n[c + '.' + s] || s.replace(/\{\#([^\}]+)\}/g, function(a, b) { + return i18n[c + '.' + b] || '{#' + b + '}'; + }); + }, + + getLang : function(n, dv) { + return tinymce.i18n[(this.settings.language || 'en') + '.' + n] || (is(dv) ? dv : '{#' + n + '}'); + }, + + getParam : function(n, dv, ty) { + var tr = tinymce.trim, v = is(this.settings[n]) ? this.settings[n] : dv, o; + + if (ty === 'hash') { + o = {}; + + if (is(v, 'string')) { + each(v.indexOf('=') > 0 ? v.split(/[;,](?![^=;,]*(?:[;,]|$))/) : v.split(','), function(v) { + v = v.split('='); + + if (v.length > 1) + o[tr(v[0])] = tr(v[1]); + else + o[tr(v[0])] = tr(v); + }); + } else + o = v; + + return o; + } + + return v; + }, + + nodeChanged : function(o) { + var self = this, selection = self.selection, node; + + // Fix for bug #1896577 it seems that this can not be fired while the editor is loading + if (self.initialized) { + o = o || {}; + + // Get start node + node = selection.getStart() || self.getBody(); + node = isIE && node.ownerDocument != self.getDoc() ? self.getBody() : node; // Fix for IE initial state + + // Get parents and add them to object + o.parents = []; + self.dom.getParent(node, function(node) { + if (node.nodeName == 'BODY') + return true; + + o.parents.push(node); + }); + + self.onNodeChange.dispatch( + self, + o ? o.controlManager || self.controlManager : self.controlManager, + node, + selection.isCollapsed(), + o + ); + } + }, + + addButton : function(name, settings) { + var self = this; + + self.buttons = self.buttons || {}; + self.buttons[name] = settings; + }, + + addCommand : function(name, callback, scope) { + this.execCommands[name] = {func : callback, scope : scope || this}; + }, + + addQueryStateHandler : function(name, callback, scope) { + this.queryStateCommands[name] = {func : callback, scope : scope || this}; + }, + + addQueryValueHandler : function(name, callback, scope) { + this.queryValueCommands[name] = {func : callback, scope : scope || this}; + }, + + addShortcut : function(pa, desc, cmd_func, sc) { + var t = this, c; + + if (t.settings.custom_shortcuts === false) + return false; + + t.shortcuts = t.shortcuts || {}; + + if (is(cmd_func, 'string')) { + c = cmd_func; + + cmd_func = function() { + t.execCommand(c, false, null); + }; + } + + if (is(cmd_func, 'object')) { + c = cmd_func; + + cmd_func = function() { + t.execCommand(c[0], c[1], c[2]); + }; + } + + each(explode(pa), function(pa) { + var o = { + func : cmd_func, + scope : sc || this, + desc : t.translate(desc), + alt : false, + ctrl : false, + shift : false + }; + + each(explode(pa, '+'), function(v) { + switch (v) { + case 'alt': + case 'ctrl': + case 'shift': + o[v] = true; + break; + + default: + o.charCode = v.charCodeAt(0); + o.keyCode = v.toUpperCase().charCodeAt(0); + } + }); + + t.shortcuts[(o.ctrl ? 'ctrl' : '') + ',' + (o.alt ? 'alt' : '') + ',' + (o.shift ? 'shift' : '') + ',' + o.keyCode] = o; + }); + + return true; + }, + + execCommand : function(cmd, ui, val, a) { + var t = this, s = 0, o, st; + + if (!/^(mceAddUndoLevel|mceEndUndoLevel|mceBeginUndoLevel|mceRepaint|SelectAll)$/.test(cmd) && (!a || !a.skip_focus)) + t.focus(); + + a = extend({}, a); + t.onBeforeExecCommand.dispatch(t, cmd, ui, val, a); + if (a.terminate) + return false; + + // Command callback + if (t.execCallback('execcommand_callback', t.id, t.selection.getNode(), cmd, ui, val)) { + t.onExecCommand.dispatch(t, cmd, ui, val, a); + return true; + } + + // Registred commands + if (o = t.execCommands[cmd]) { + st = o.func.call(o.scope, ui, val); + + // Fall through on true + if (st !== true) { + t.onExecCommand.dispatch(t, cmd, ui, val, a); + return st; + } + } + + // Plugin commands + each(t.plugins, function(p) { + if (p.execCommand && p.execCommand(cmd, ui, val)) { + t.onExecCommand.dispatch(t, cmd, ui, val, a); + s = 1; + return false; + } + }); + + if (s) + return true; + + // Theme commands + if (t.theme && t.theme.execCommand && t.theme.execCommand(cmd, ui, val)) { + t.onExecCommand.dispatch(t, cmd, ui, val, a); + return true; + } + + // Editor commands + if (t.editorCommands.execCommand(cmd, ui, val)) { + t.onExecCommand.dispatch(t, cmd, ui, val, a); + return true; + } + + // Browser commands + t.getDoc().execCommand(cmd, ui, val); + t.onExecCommand.dispatch(t, cmd, ui, val, a); + }, + + queryCommandState : function(cmd) { + var t = this, o, s; + + // Is hidden then return undefined + if (t._isHidden()) + return; + + // Registred commands + if (o = t.queryStateCommands[cmd]) { + s = o.func.call(o.scope); + + // Fall though on true + if (s !== true) + return s; + } + + // Registred commands + o = t.editorCommands.queryCommandState(cmd); + if (o !== -1) + return o; + + // Browser commands + try { + return this.getDoc().queryCommandState(cmd); + } catch (ex) { + // Fails sometimes see bug: 1896577 + } + }, + + queryCommandValue : function(c) { + var t = this, o, s; + + // Is hidden then return undefined + if (t._isHidden()) + return; + + // Registred commands + if (o = t.queryValueCommands[c]) { + s = o.func.call(o.scope); + + // Fall though on true + if (s !== true) + return s; + } + + // Registred commands + o = t.editorCommands.queryCommandValue(c); + if (is(o)) + return o; + + // Browser commands + try { + return this.getDoc().queryCommandValue(c); + } catch (ex) { + // Fails sometimes see bug: 1896577 + } + }, + + show : function() { + var self = this; + + DOM.show(self.getContainer()); + DOM.hide(self.id); + self.load(); + }, + + hide : function() { + var self = this, doc = self.getDoc(); + + // Fixed bug where IE has a blinking cursor left from the editor + if (isIE && doc) + doc.execCommand('SelectAll'); + + // We must save before we hide so Safari doesn't crash + self.save(); + + // defer the call to hide to prevent an IE9 crash #4921 + DOM.hide(self.getContainer()); + DOM.setStyle(self.id, 'display', self.orgDisplay); + }, + + isHidden : function() { + return !DOM.isHidden(this.id); + }, + + setProgressState : function(b, ti, o) { + this.onSetProgressState.dispatch(this, b, ti, o); + + return b; + }, + + load : function(o) { + var t = this, e = t.getElement(), h; + + if (e) { + o = o || {}; + o.load = true; + + // Double encode existing entities in the value + h = t.setContent(is(e.value) ? e.value : e.innerHTML, o); + o.element = e; + + if (!o.no_events) + t.onLoadContent.dispatch(t, o); + + o.element = e = null; + + return h; + } + }, + + save : function(o) { + var t = this, e = t.getElement(), h, f; + + if (!e || !t.initialized) + return; + + o = o || {}; + o.save = true; + + o.element = e; + h = o.content = t.getContent(o); + + if (!o.no_events) + t.onSaveContent.dispatch(t, o); + + h = o.content; + + if (!/TEXTAREA|INPUT/i.test(e.nodeName)) { + e.innerHTML = h; + + // Update hidden form element + if (f = DOM.getParent(t.id, 'form')) { + each(f.elements, function(e) { + if (e.name == t.id) { + e.value = h; + return false; + } + }); + } + } else + e.value = h; + + o.element = e = null; + + return h; + }, + + setContent : function(content, args) { + var self = this, rootNode, body = self.getBody(), forcedRootBlockName; + + // Setup args object + args = args || {}; + args.format = args.format || 'html'; + args.set = true; + args.content = content; + + // Do preprocessing + if (!args.no_events) + self.onBeforeSetContent.dispatch(self, args); + + content = args.content; + + // Padd empty content in Gecko and Safari. Commands will otherwise fail on the content + // It will also be impossible to place the caret in the editor unless there is a BR element present + if (!tinymce.isIE && (content.length === 0 || /^\s+$/.test(content))) { + forcedRootBlockName = self.settings.forced_root_block; + if (forcedRootBlockName) + content = '<' + forcedRootBlockName + '>
    '; + else + content = '
    '; + + body.innerHTML = content; + self.selection.select(body, true); + self.selection.collapse(true); + return; + } + + // Parse and serialize the html + if (args.format !== 'raw') { + content = new tinymce.html.Serializer({}, self.schema).serialize( + self.parser.parse(content) + ); + } + + // Set the new cleaned contents to the editor + args.content = tinymce.trim(content); + self.dom.setHTML(body, args.content); + + // Do post processing + if (!args.no_events) + self.onSetContent.dispatch(self, args); + + // Don't normalize selection if the focused element isn't the body in content editable mode since it will steal focus otherwise + if (!self.settings.content_editable || document.activeElement === self.getBody()) { + self.selection.normalize(); + } + + return args.content; + }, + + getContent : function(args) { + var self = this, content, body = self.getBody(); + + // Setup args object + args = args || {}; + args.format = args.format || 'html'; + args.get = true; + args.getInner = true; + + // Do preprocessing + if (!args.no_events) + self.onBeforeGetContent.dispatch(self, args); + + // Get raw contents or by default the cleaned contents + if (args.format == 'raw') + content = body.innerHTML; + else if (args.format == 'text') + content = body.innerText || body.textContent; + else + content = self.serializer.serialize(body, args); + + // Trim whitespace in beginning/end of HTML + if (args.format != 'text') { + args.content = tinymce.trim(content); + } else { + args.content = content; + } + + // Do post processing + if (!args.no_events) + self.onGetContent.dispatch(self, args); + + return args.content; + }, + + isDirty : function() { + var self = this; + + return tinymce.trim(self.startContent) != tinymce.trim(self.getContent({format : 'raw', no_events : 1})) && !self.isNotDirty; + }, + + getContainer : function() { + var self = this; + + if (!self.container) + self.container = DOM.get(self.editorContainer || self.id + '_parent'); + + return self.container; + }, + + getContentAreaContainer : function() { + return this.contentAreaContainer; + }, + + getElement : function() { + return DOM.get(this.settings.content_element || this.id); + }, + + getWin : function() { + var self = this, elm; + + if (!self.contentWindow) { + elm = DOM.get(self.id + "_ifr"); + + if (elm) + self.contentWindow = elm.contentWindow; + } + + return self.contentWindow; + }, + + getDoc : function() { + var self = this, win; + + if (!self.contentDocument) { + win = self.getWin(); + + if (win) + self.contentDocument = win.document; + } + + return self.contentDocument; + }, + + getBody : function() { + return this.bodyElement || this.getDoc().body; + }, + + convertURL : function(url, name, elm) { + var self = this, settings = self.settings; + + // Use callback instead + if (settings.urlconverter_callback) + return self.execCallback('urlconverter_callback', url, elm, true, name); + + // Don't convert link href since thats the CSS files that gets loaded into the editor also skip local file URLs + if (!settings.convert_urls || (elm && elm.nodeName == 'LINK') || url.indexOf('file:') === 0) + return url; + + // Convert to relative + if (settings.relative_urls) + return self.documentBaseURI.toRelative(url); + + // Convert to absolute + url = self.documentBaseURI.toAbsolute(url, settings.remove_script_host); + + return url; + }, + + addVisual : function(elm) { + var self = this, settings = self.settings, dom = self.dom, cls; + + elm = elm || self.getBody(); + + if (!is(self.hasVisual)) + self.hasVisual = settings.visual; + + each(dom.select('table,a', elm), function(elm) { + var value; + + switch (elm.nodeName) { + case 'TABLE': + cls = settings.visual_table_class || 'mceItemTable'; + value = dom.getAttrib(elm, 'border'); + + if (!value || value == '0') { + if (self.hasVisual) + dom.addClass(elm, cls); + else + dom.removeClass(elm, cls); + } + + return; + + case 'A': + if (!dom.getAttrib(elm, 'href', false)) { + value = dom.getAttrib(elm, 'name') || elm.id; + cls = 'mceItemAnchor'; + + if (value) { + if (self.hasVisual) + dom.addClass(elm, cls); + else + dom.removeClass(elm, cls); + } + } + + return; + } + }); + + self.onVisualAid.dispatch(self, elm, self.hasVisual); + }, + + remove : function() { + var self = this, elm = self.getContainer(), doc = self.getDoc(); + + if (!self.removed) { + self.removed = 1; // Cancels post remove event execution + + // Fixed bug where IE has a blinking cursor left from the editor + if (isIE && doc) + doc.execCommand('SelectAll'); + + // We must save before we hide so Safari doesn't crash + self.save(); + + DOM.setStyle(self.id, 'display', self.orgDisplay); + + // Don't clear the window or document if content editable + // is enabled since other instances might still be present + if (!self.settings.content_editable) { + Event.unbind(self.getWin()); + Event.unbind(self.getDoc()); + } + + Event.unbind(self.getBody()); + Event.clear(elm); + + self.execCallback('remove_instance_callback', self); + self.onRemove.dispatch(self); + + // Clear all execCommand listeners this is required to avoid errors if the editor was removed inside another command + self.onExecCommand.listeners = []; + + tinymce.remove(self); + DOM.remove(elm); + } + }, + + destroy : function(s) { + var t = this; + + // One time is enough + if (t.destroyed) + return; + + // We must unbind on Gecko since it would otherwise produce the pesky "attempt to run compile-and-go script on a cleared scope" message + if (isGecko) { + Event.unbind(t.getDoc()); + Event.unbind(t.getWin()); + Event.unbind(t.getBody()); + } + + if (!s) { + tinymce.removeUnload(t.destroy); + tinyMCE.onBeforeUnload.remove(t._beforeUnload); + + // Manual destroy + if (t.theme && t.theme.destroy) + t.theme.destroy(); + + // Destroy controls, selection and dom + t.controlManager.destroy(); + t.selection.destroy(); + t.dom.destroy(); + } + + if (t.formElement) { + t.formElement.submit = t.formElement._mceOldSubmit; + t.formElement._mceOldSubmit = null; + } + + t.contentAreaContainer = t.formElement = t.container = t.settings.content_element = t.bodyElement = t.contentDocument = t.contentWindow = null; + + if (t.selection) + t.selection = t.selection.win = t.selection.dom = t.selection.dom.doc = null; + + t.destroyed = 1; + }, + + // Internal functions + + _refreshContentEditable : function() { + var self = this, body, parent; + + // Check if the editor was hidden and the re-initalize contentEditable mode by removing and adding the body again + if (self._isHidden()) { + body = self.getBody(); + parent = body.parentNode; + + parent.removeChild(body); + parent.appendChild(body); + + body.focus(); + } + }, + + _isHidden : function() { + var s; + + if (!isGecko) + return 0; + + // Weird, wheres that cursor selection? + s = this.selection.getSel(); + return (!s || !s.rangeCount || s.rangeCount === 0); + } + }); +})(tinymce); +(function(tinymce) { + var each = tinymce.each; + + tinymce.Editor.prototype.setupEvents = function() { + var self = this, settings = self.settings; + + // Add events to the editor + each([ + 'onPreInit', + + 'onBeforeRenderUI', + + 'onPostRender', + + 'onLoad', + + 'onInit', + + 'onRemove', + + 'onActivate', + + 'onDeactivate', + + 'onClick', + + 'onEvent', + + 'onMouseUp', + + 'onMouseDown', + + 'onDblClick', + + 'onKeyDown', + + 'onKeyUp', + + 'onKeyPress', + + 'onContextMenu', + + 'onSubmit', + + 'onReset', + + 'onPaste', + + 'onPreProcess', + + 'onPostProcess', + + 'onBeforeSetContent', + + 'onBeforeGetContent', + + 'onSetContent', + + 'onGetContent', + + 'onLoadContent', + + 'onSaveContent', + + 'onNodeChange', + + 'onChange', + + 'onBeforeExecCommand', + + 'onExecCommand', + + 'onUndo', + + 'onRedo', + + 'onVisualAid', + + 'onSetProgressState', + + 'onSetAttrib' + ], function(name) { + self[name] = new tinymce.util.Dispatcher(self); + }); + + // Handle legacy cleanup_callback option + if (settings.cleanup_callback) { + self.onBeforeSetContent.add(function(ed, o) { + o.content = ed.execCallback('cleanup_callback', 'insert_to_editor', o.content, o); + }); + + self.onPreProcess.add(function(ed, o) { + if (o.set) + ed.execCallback('cleanup_callback', 'insert_to_editor_dom', o.node, o); + + if (o.get) + ed.execCallback('cleanup_callback', 'get_from_editor_dom', o.node, o); + }); + + self.onPostProcess.add(function(ed, o) { + if (o.set) + o.content = ed.execCallback('cleanup_callback', 'insert_to_editor', o.content, o); + + if (o.get) + o.content = ed.execCallback('cleanup_callback', 'get_from_editor', o.content, o); + }); + } + + // Handle legacy save_callback option + if (settings.save_callback) { + self.onGetContent.add(function(ed, o) { + if (o.save) + o.content = ed.execCallback('save_callback', ed.id, o.content, ed.getBody()); + }); + } + + // Handle legacy handle_event_callback option + if (settings.handle_event_callback) { + self.onEvent.add(function(ed, e, o) { + if (self.execCallback('handle_event_callback', e, ed, o) === false) { + e.preventDefault(); + e.stopPropagation(); + } + }); + } + + // Handle legacy handle_node_change_callback option + if (settings.handle_node_change_callback) { + self.onNodeChange.add(function(ed, cm, n) { + ed.execCallback('handle_node_change_callback', ed.id, n, -1, -1, true, ed.selection.isCollapsed()); + }); + } + + // Handle legacy save_callback option + if (settings.save_callback) { + self.onSaveContent.add(function(ed, o) { + var h = ed.execCallback('save_callback', ed.id, o.content, ed.getBody()); + + if (h) + o.content = h; + }); + } + + // Handle legacy onchange_callback option + if (settings.onchange_callback) { + self.onChange.add(function(ed, l) { + ed.execCallback('onchange_callback', ed, l); + }); + } + }; + + tinymce.Editor.prototype.bindNativeEvents = function() { + // 'focus', 'blur', 'dblclick', 'beforedeactivate', submit, reset + var self = this, i, settings = self.settings, dom = self.dom, nativeToDispatcherMap; + + nativeToDispatcherMap = { + mouseup : 'onMouseUp', + mousedown : 'onMouseDown', + click : 'onClick', + keyup : 'onKeyUp', + keydown : 'onKeyDown', + keypress : 'onKeyPress', + submit : 'onSubmit', + reset : 'onReset', + contextmenu : 'onContextMenu', + dblclick : 'onDblClick', + paste : 'onPaste' // Doesn't work in all browsers yet + }; + + // Handler that takes a native event and sends it out to a dispatcher like onKeyDown + function eventHandler(evt, args) { + var type = evt.type; + + // Don't fire events when it's removed + if (self.removed) + return; + + // Sends the native event out to a global dispatcher then to the specific event dispatcher + if (self.onEvent.dispatch(self, evt, args) !== false) { + self[nativeToDispatcherMap[evt.fakeType || evt.type]].dispatch(self, evt, args); + } + }; + + // Opera doesn't support focus event for contentEditable elements so we need to fake it + function doOperaFocus(e) { + self.focus(true); + }; + + function nodeChanged(ed, e) { + // Normalize selection for example a|a becomes a|a except for Ctrl+A since it selects everything + if (e.keyCode != 65 || !tinymce.VK.metaKeyPressed(e)) { + self.selection.normalize(); + } + + self.nodeChanged(); + } + + // Add DOM events + each(nativeToDispatcherMap, function(dispatcherName, nativeName) { + var root = settings.content_editable ? self.getBody() : self.getDoc(); + + switch (nativeName) { + case 'contextmenu': + dom.bind(root, nativeName, eventHandler); + break; + + case 'paste': + dom.bind(self.getBody(), nativeName, eventHandler); + break; + + case 'submit': + case 'reset': + dom.bind(self.getElement().form || tinymce.DOM.getParent(self.id, 'form'), nativeName, eventHandler); + break; + + default: + dom.bind(root, nativeName, eventHandler); + } + }); + + // Set the editor as active when focused + dom.bind(settings.content_editable ? self.getBody() : (tinymce.isGecko ? self.getDoc() : self.getWin()), 'focus', function(e) { + self.focus(true); + }); + + if (settings.content_editable && tinymce.isOpera) { + dom.bind(self.getBody(), 'click', doOperaFocus); + dom.bind(self.getBody(), 'keydown', doOperaFocus); + } + + // Add node change handler + self.onMouseUp.add(nodeChanged); + + self.onKeyUp.add(function(ed, e) { + var keyCode = e.keyCode; + + if ((keyCode >= 33 && keyCode <= 36) || (keyCode >= 37 && keyCode <= 40) || keyCode == 13 || keyCode == 45 || keyCode == 46 || keyCode == 8 || (tinymce.isMac && (keyCode == 91 || keyCode == 93)) || e.ctrlKey) + nodeChanged(ed, e); + }); + + // Add reset handler + self.onReset.add(function() { + self.setContent(self.startContent, {format : 'raw'}); + }); + + // Add shortcuts + function handleShortcut(e, execute) { + if (e.altKey || e.ctrlKey || e.metaKey) { + each(self.shortcuts, function(shortcut) { + var ctrlState = tinymce.isMac ? e.metaKey : e.ctrlKey; + + if (shortcut.ctrl != ctrlState || shortcut.alt != e.altKey || shortcut.shift != e.shiftKey) + return; + + if (e.keyCode == shortcut.keyCode || (e.charCode && e.charCode == shortcut.charCode)) { + e.preventDefault(); + + if (execute) { + shortcut.func.call(shortcut.scope); + } + + return true; + } + }); + } + }; + + self.onKeyUp.add(function(ed, e) { + handleShortcut(e); + }); + + self.onKeyPress.add(function(ed, e) { + handleShortcut(e); + }); + + self.onKeyDown.add(function(ed, e) { + handleShortcut(e, true); + }); + + if (tinymce.isOpera) { + self.onClick.add(function(ed, e) { + e.preventDefault(); + }); + } + }; +})(tinymce); +(function(tinymce) { + // Added for compression purposes + var each = tinymce.each, undef, TRUE = true, FALSE = false; + + tinymce.EditorCommands = function(editor) { + var dom = editor.dom, + selection = editor.selection, + commands = {state: {}, exec : {}, value : {}}, + settings = editor.settings, + formatter = editor.formatter, + bookmark; + + function execCommand(command, ui, value) { + var func; + + command = command.toLowerCase(); + if (func = commands.exec[command]) { + func(command, ui, value); + return TRUE; + } + + return FALSE; + }; + + function queryCommandState(command) { + var func; + + command = command.toLowerCase(); + if (func = commands.state[command]) + return func(command); + + return -1; + }; + + function queryCommandValue(command) { + var func; + + command = command.toLowerCase(); + if (func = commands.value[command]) + return func(command); + + return FALSE; + }; + + function addCommands(command_list, type) { + type = type || 'exec'; + + each(command_list, function(callback, command) { + each(command.toLowerCase().split(','), function(command) { + commands[type][command] = callback; + }); + }); + }; + + // Expose public methods + tinymce.extend(this, { + execCommand : execCommand, + queryCommandState : queryCommandState, + queryCommandValue : queryCommandValue, + addCommands : addCommands + }); + + // Private methods + + function execNativeCommand(command, ui, value) { + if (ui === undef) + ui = FALSE; + + if (value === undef) + value = null; + + return editor.getDoc().execCommand(command, ui, value); + }; + + function isFormatMatch(name) { + return formatter.match(name); + }; + + function toggleFormat(name, value) { + formatter.toggle(name, value ? {value : value} : undef); + }; + + function storeSelection(type) { + bookmark = selection.getBookmark(type); + }; + + function restoreSelection() { + selection.moveToBookmark(bookmark); + }; + + // Add execCommand overrides + addCommands({ + // Ignore these, added for compatibility + 'mceResetDesignMode,mceBeginUndoLevel' : function() {}, + + // Add undo manager logic + 'mceEndUndoLevel,mceAddUndoLevel' : function() { + editor.undoManager.add(); + }, + + 'Cut,Copy,Paste' : function(command) { + var doc = editor.getDoc(), failed; + + // Try executing the native command + try { + execNativeCommand(command); + } catch (ex) { + // Command failed + failed = TRUE; + } + + // Present alert message about clipboard access not being available + if (failed || !doc.queryCommandSupported(command)) { + if (tinymce.isGecko) { + editor.windowManager.confirm(editor.getLang('clipboard_msg'), function(state) { + if (state) + open('http://www.mozilla.org/editor/midasdemo/securityprefs.html', '_blank'); + }); + } else + editor.windowManager.alert(editor.getLang('clipboard_no_support')); + } + }, + + // Override unlink command + unlink : function(command) { + if (selection.isCollapsed()) + selection.select(selection.getNode()); + + execNativeCommand(command); + selection.collapse(FALSE); + }, + + // Override justify commands to use the text formatter engine + 'JustifyLeft,JustifyCenter,JustifyRight,JustifyFull' : function(command) { + var align = command.substring(7); + + // Remove all other alignments first + each('left,center,right,full'.split(','), function(name) { + if (align != name) + formatter.remove('align' + name); + }); + + toggleFormat('align' + align); + execCommand('mceRepaint'); + }, + + // Override list commands to fix WebKit bug + 'InsertUnorderedList,InsertOrderedList' : function(command) { + var listElm, listParent; + + execNativeCommand(command); + + // WebKit produces lists within block elements so we need to split them + // we will replace the native list creation logic to custom logic later on + // TODO: Remove this when the list creation logic is removed + listElm = dom.getParent(selection.getNode(), 'ol,ul'); + if (listElm) { + listParent = listElm.parentNode; + + // If list is within a text block then split that block + if (/^(H[1-6]|P|ADDRESS|PRE)$/.test(listParent.nodeName)) { + storeSelection(); + dom.split(listParent, listElm); + restoreSelection(); + } + } + }, + + // Override commands to use the text formatter engine + 'Bold,Italic,Underline,Strikethrough,Superscript,Subscript' : function(command) { + toggleFormat(command); + }, + + // Override commands to use the text formatter engine + 'ForeColor,HiliteColor,FontName' : function(command, ui, value) { + toggleFormat(command, value); + }, + + FontSize : function(command, ui, value) { + var fontClasses, fontSizes; + + // Convert font size 1-7 to styles + if (value >= 1 && value <= 7) { + fontSizes = tinymce.explode(settings.font_size_style_values); + fontClasses = tinymce.explode(settings.font_size_classes); + + if (fontClasses) + value = fontClasses[value - 1] || value; + else + value = fontSizes[value - 1] || value; + } + + toggleFormat(command, value); + }, + + RemoveFormat : function(command) { + formatter.remove(command); + }, + + mceBlockQuote : function(command) { + toggleFormat('blockquote'); + }, + + FormatBlock : function(command, ui, value) { + return toggleFormat(value || 'p'); + }, + + mceCleanup : function() { + var bookmark = selection.getBookmark(); + + editor.setContent(editor.getContent({cleanup : TRUE}), {cleanup : TRUE}); + + selection.moveToBookmark(bookmark); + }, + + mceRemoveNode : function(command, ui, value) { + var node = value || selection.getNode(); + + // Make sure that the body node isn't removed + if (node != editor.getBody()) { + storeSelection(); + editor.dom.remove(node, TRUE); + restoreSelection(); + } + }, + + mceSelectNodeDepth : function(command, ui, value) { + var counter = 0; + + dom.getParent(selection.getNode(), function(node) { + if (node.nodeType == 1 && counter++ == value) { + selection.select(node); + return FALSE; + } + }, editor.getBody()); + }, + + mceSelectNode : function(command, ui, value) { + selection.select(value); + }, + + mceInsertContent : function(command, ui, value) { + var parser, serializer, parentNode, rootNode, fragment, args, + marker, nodeRect, viewPortRect, rng, node, node2, bookmarkHtml, viewportBodyElement; + + //selection.normalize(); + + // Setup parser and serializer + parser = editor.parser; + serializer = new tinymce.html.Serializer({}, editor.schema); + bookmarkHtml = '\uFEFF'; + + // Run beforeSetContent handlers on the HTML to be inserted + args = {content: value, format: 'html'}; + selection.onBeforeSetContent.dispatch(selection, args); + value = args.content; + + // Add caret at end of contents if it's missing + if (value.indexOf('{$caret}') == -1) + value += '{$caret}'; + + // Replace the caret marker with a span bookmark element + value = value.replace(/\{\$caret\}/, bookmarkHtml); + + // Insert node maker where we will insert the new HTML and get it's parent + if (!selection.isCollapsed()) + editor.getDoc().execCommand('Delete', false, null); + + parentNode = selection.getNode(); + + // Parse the fragment within the context of the parent node + args = {context : parentNode.nodeName.toLowerCase()}; + fragment = parser.parse(value, args); + + // Move the caret to a more suitable location + node = fragment.lastChild; + if (node.attr('id') == 'mce_marker') { + marker = node; + + for (node = node.prev; node; node = node.walk(true)) { + if (node.type == 3 || !dom.isBlock(node.name)) { + node.parent.insert(marker, node, node.name === 'br'); + break; + } + } + } + + // If parser says valid we can insert the contents into that parent + if (!args.invalid) { + value = serializer.serialize(fragment); + + // Check if parent is empty or only has one BR element then set the innerHTML of that parent + node = parentNode.firstChild; + node2 = parentNode.lastChild; + if (!node || (node === node2 && node.nodeName === 'BR')) + dom.setHTML(parentNode, value); + else + selection.setContent(value); + } else { + // If the fragment was invalid within that context then we need + // to parse and process the parent it's inserted into + + // Insert bookmark node and get the parent + selection.setContent(bookmarkHtml); + parentNode = selection.getNode(); + rootNode = editor.getBody(); + + // Opera will return the document node when selection is in root + if (parentNode.nodeType == 9) + parentNode = node = rootNode; + else + node = parentNode; + + // Find the ancestor just before the root element + while (node !== rootNode) { + parentNode = node; + node = node.parentNode; + } + + // Get the outer/inner HTML depending on if we are in the root and parser and serialize that + value = parentNode == rootNode ? rootNode.innerHTML : dom.getOuterHTML(parentNode); + value = serializer.serialize( + parser.parse( + // Need to replace by using a function since $ in the contents would otherwise be a problem + value.replace(//i, function() { + return serializer.serialize(fragment); + }) + ) + ); + + // Set the inner/outer HTML depending on if we are in the root or not + if (parentNode == rootNode) + dom.setHTML(rootNode, value); + else + dom.setOuterHTML(parentNode, value); + } + + marker = dom.get('mce_marker'); + + // Scroll range into view scrollIntoView on element can't be used since it will scroll the main view port as well + nodeRect = dom.getRect(marker); + viewPortRect = dom.getViewPort(editor.getWin()); + + // Check if node is out side the viewport if it is then scroll to it + if ((nodeRect.y + nodeRect.h > viewPortRect.y + viewPortRect.h || nodeRect.y < viewPortRect.y) || + (nodeRect.x > viewPortRect.x + viewPortRect.w || nodeRect.x < viewPortRect.x)) { + viewportBodyElement = tinymce.isIE ? editor.getDoc().documentElement : editor.getBody(); + viewportBodyElement.scrollLeft = nodeRect.x; + viewportBodyElement.scrollTop = nodeRect.y - viewPortRect.h + 25; + } + + // Move selection before marker and remove it + rng = dom.createRng(); + + // If previous sibling is a text node set the selection to the end of that node + node = marker.previousSibling; + if (node && node.nodeType == 3) { + rng.setStart(node, node.nodeValue.length); + } else { + // If the previous sibling isn't a text node or doesn't exist set the selection before the marker node + rng.setStartBefore(marker); + rng.setEndBefore(marker); + } + + // Remove the marker node and set the new range + dom.remove(marker); + selection.setRng(rng); + + // Dispatch after event and add any visual elements needed + selection.onSetContent.dispatch(selection, args); + editor.addVisual(); + }, + + mceInsertRawHTML : function(command, ui, value) { + selection.setContent('tiny_mce_marker'); + editor.setContent(editor.getContent().replace(/tiny_mce_marker/g, function() { return value })); + }, + + mceToggleFormat : function(command, ui, value) { + toggleFormat(value); + }, + + mceSetContent : function(command, ui, value) { + editor.setContent(value); + }, + + 'Indent,Outdent' : function(command) { + var intentValue, indentUnit, value; + + // Setup indent level + intentValue = settings.indentation; + indentUnit = /[a-z%]+$/i.exec(intentValue); + intentValue = parseInt(intentValue); + + if (!queryCommandState('InsertUnorderedList') && !queryCommandState('InsertOrderedList')) { + // If forced_root_blocks is set to false we don't have a block to indent so lets create a div + if (!settings.forced_root_block && !dom.getParent(selection.getNode(), dom.isBlock)) { + formatter.apply('div'); + } + + each(selection.getSelectedBlocks(), function(element) { + if (command == 'outdent') { + value = Math.max(0, parseInt(element.style.paddingLeft || 0) - intentValue); + dom.setStyle(element, 'paddingLeft', value ? value + indentUnit : ''); + } else + dom.setStyle(element, 'paddingLeft', (parseInt(element.style.paddingLeft || 0) + intentValue) + indentUnit); + }); + } else + execNativeCommand(command); + }, + + mceRepaint : function() { + var bookmark; + + if (tinymce.isGecko) { + try { + storeSelection(TRUE); + + if (selection.getSel()) + selection.getSel().selectAllChildren(editor.getBody()); + + selection.collapse(TRUE); + restoreSelection(); + } catch (ex) { + // Ignore + } + } + }, + + mceToggleFormat : function(command, ui, value) { + formatter.toggle(value); + }, + + InsertHorizontalRule : function() { + editor.execCommand('mceInsertContent', false, '
    '); + }, + + mceToggleVisualAid : function() { + editor.hasVisual = !editor.hasVisual; + editor.addVisual(); + }, + + mceReplaceContent : function(command, ui, value) { + editor.execCommand('mceInsertContent', false, value.replace(/\{\$selection\}/g, selection.getContent({format : 'text'}))); + }, + + mceInsertLink : function(command, ui, value) { + var anchor; + + if (typeof(value) == 'string') + value = {href : value}; + + anchor = dom.getParent(selection.getNode(), 'a'); + + // Spaces are never valid in URLs and it's a very common mistake for people to make so we fix it here. + value.href = value.href.replace(' ', '%20'); + + // Remove existing links if there could be child links or that the href isn't specified + if (!anchor || !value.href) { + formatter.remove('link'); + } + + // Apply new link to selection + if (value.href) { + formatter.apply('link', value, anchor); + } + }, + + selectAll : function() { + var root = dom.getRoot(), rng = dom.createRng(); + + // Old IE does a better job with selectall than new versions + if (selection.getRng().setStart) { + rng.setStart(root, 0); + rng.setEnd(root, root.childNodes.length); + + selection.setRng(rng); + } else { + execNativeCommand('SelectAll'); + } + } + }); + + // Add queryCommandState overrides + addCommands({ + // Override justify commands + 'JustifyLeft,JustifyCenter,JustifyRight,JustifyFull' : function(command) { + var name = 'align' + command.substring(7); + var nodes = selection.isCollapsed() ? [dom.getParent(selection.getNode(), dom.isBlock)] : selection.getSelectedBlocks(); + var matches = tinymce.map(nodes, function(node) { + return !!formatter.matchNode(node, name); + }); + return tinymce.inArray(matches, TRUE) !== -1; + }, + + 'Bold,Italic,Underline,Strikethrough,Superscript,Subscript' : function(command) { + return isFormatMatch(command); + }, + + mceBlockQuote : function() { + return isFormatMatch('blockquote'); + }, + + Outdent : function() { + var node; + + if (settings.inline_styles) { + if ((node = dom.getParent(selection.getStart(), dom.isBlock)) && parseInt(node.style.paddingLeft) > 0) + return TRUE; + + if ((node = dom.getParent(selection.getEnd(), dom.isBlock)) && parseInt(node.style.paddingLeft) > 0) + return TRUE; + } + + return queryCommandState('InsertUnorderedList') || queryCommandState('InsertOrderedList') || (!settings.inline_styles && !!dom.getParent(selection.getNode(), 'BLOCKQUOTE')); + }, + + 'InsertUnorderedList,InsertOrderedList' : function(command) { + var list = dom.getParent(selection.getNode(), 'ul,ol'); + return list && + (command === 'insertunorderedlist' && list.tagName === 'UL' + || command === 'insertorderedlist' && list.tagName === 'OL'); + } + }, 'state'); + + // Add queryCommandValue overrides + addCommands({ + 'FontSize,FontName' : function(command) { + var value = 0, parent; + + if (parent = dom.getParent(selection.getNode(), 'span')) { + if (command == 'fontsize') + value = parent.style.fontSize; + else + value = parent.style.fontFamily.replace(/, /g, ',').replace(/[\'\"]/g, '').toLowerCase(); + } + + return value; + } + }, 'value'); + + // Add undo manager logic + addCommands({ + Undo : function() { + editor.undoManager.undo(); + }, + + Redo : function() { + editor.undoManager.redo(); + } + }); + }; +})(tinymce); + +(function(tinymce) { + var Dispatcher = tinymce.util.Dispatcher; + + tinymce.UndoManager = function(editor) { + var self, index = 0, data = [], beforeBookmark, onAdd, onUndo, onRedo; + + function getContent() { + // Remove whitespace before/after and remove pure bogus nodes + return tinymce.trim(editor.getContent({format : 'raw', no_events : 1}).replace(/]+data-mce-bogus[^>]+>[\u200B\uFEFF]+<\/span>/g, '')); + }; + + function addNonTypingUndoLevel() { + self.typing = false; + self.add(); + }; + + // Create event instances + onBeforeAdd = new Dispatcher(self); + onAdd = new Dispatcher(self); + onUndo = new Dispatcher(self); + onRedo = new Dispatcher(self); + + // Pass though onAdd event from UndoManager to Editor as onChange + onAdd.add(function(undoman, level) { + if (undoman.hasUndo()) + return editor.onChange.dispatch(editor, level, undoman); + }); + + // Pass though onUndo event from UndoManager to Editor + onUndo.add(function(undoman, level) { + return editor.onUndo.dispatch(editor, level, undoman); + }); + + // Pass though onRedo event from UndoManager to Editor + onRedo.add(function(undoman, level) { + return editor.onRedo.dispatch(editor, level, undoman); + }); + + // Add initial undo level when the editor is initialized + editor.onInit.add(function() { + self.add(); + }); + + // Get position before an execCommand is processed + editor.onBeforeExecCommand.add(function(ed, cmd, ui, val, args) { + if (cmd != 'Undo' && cmd != 'Redo' && cmd != 'mceRepaint' && (!args || !args.skip_undo)) { + self.beforeChange(); + } + }); + + // Add undo level after an execCommand call was made + editor.onExecCommand.add(function(ed, cmd, ui, val, args) { + if (cmd != 'Undo' && cmd != 'Redo' && cmd != 'mceRepaint' && (!args || !args.skip_undo)) { + self.add(); + } + }); + + // Add undo level on save contents, drag end and blur/focusout + editor.onSaveContent.add(addNonTypingUndoLevel); + editor.dom.bind(editor.dom.getRoot(), 'dragend', addNonTypingUndoLevel); + editor.dom.bind(editor.getBody(), 'focusout', function(e) { + if (!editor.removed && self.typing) { + addNonTypingUndoLevel(); + } + }); + + editor.onKeyUp.add(function(editor, e) { + var keyCode = e.keyCode; + + if ((keyCode >= 33 && keyCode <= 36) || (keyCode >= 37 && keyCode <= 40) || keyCode == 45 || keyCode == 13 || e.ctrlKey) { + addNonTypingUndoLevel(); + } + }); + + editor.onKeyDown.add(function(editor, e) { + var keyCode = e.keyCode; + + // Is caracter positon keys left,right,up,down,home,end,pgdown,pgup,enter + if ((keyCode >= 33 && keyCode <= 36) || (keyCode >= 37 && keyCode <= 40) || keyCode == 45) { + if (self.typing) { + addNonTypingUndoLevel(); + } + + return; + } + + // If key isn't shift,ctrl,alt,capslock,metakey + if ((keyCode < 16 || keyCode > 20) && keyCode != 224 && keyCode != 91 && !self.typing) { + self.beforeChange(); + self.typing = true; + self.add(); + } + }); + + editor.onMouseDown.add(function(editor, e) { + if (self.typing) { + addNonTypingUndoLevel(); + } + }); + + // Add keyboard shortcuts for undo/redo keys + editor.addShortcut('ctrl+z', 'undo_desc', 'Undo'); + editor.addShortcut('ctrl+y', 'redo_desc', 'Redo'); + + self = { + // Explose for debugging reasons + data : data, + + typing : false, + + onBeforeAdd: onBeforeAdd, + + onAdd : onAdd, + + onUndo : onUndo, + + onRedo : onRedo, + + beforeChange : function() { + beforeBookmark = editor.selection.getBookmark(2, true); + }, + + add : function(level) { + var i, settings = editor.settings, lastLevel; + + level = level || {}; + level.content = getContent(); + + self.onBeforeAdd.dispatch(self, level); + + // Add undo level if needed + lastLevel = data[index]; + if (lastLevel && lastLevel.content == level.content) + return null; + + // Set before bookmark on previous level + if (data[index]) + data[index].beforeBookmark = beforeBookmark; + + // Time to compress + if (settings.custom_undo_redo_levels) { + if (data.length > settings.custom_undo_redo_levels) { + for (i = 0; i < data.length - 1; i++) + data[i] = data[i + 1]; + + data.length--; + index = data.length; + } + } + + // Get a non intrusive normalized bookmark + level.bookmark = editor.selection.getBookmark(2, true); + + // Crop array if needed + if (index < data.length - 1) + data.length = index + 1; + + data.push(level); + index = data.length - 1; + + self.onAdd.dispatch(self, level); + editor.isNotDirty = 0; + + return level; + }, + + undo : function() { + var level, i; + + if (self.typing) { + self.add(); + self.typing = false; + } + + if (index > 0) { + level = data[--index]; + + editor.setContent(level.content, {format : 'raw'}); + editor.selection.moveToBookmark(level.beforeBookmark); + + self.onUndo.dispatch(self, level); + } + + return level; + }, + + redo : function() { + var level; + + if (index < data.length - 1) { + level = data[++index]; + + editor.setContent(level.content, {format : 'raw'}); + editor.selection.moveToBookmark(level.bookmark); + + self.onRedo.dispatch(self, level); + } + + return level; + }, + + clear : function() { + data = []; + index = 0; + self.typing = false; + }, + + hasUndo : function() { + return index > 0 || this.typing; + }, + + hasRedo : function() { + return index < data.length - 1 && !this.typing; + } + }; + + return self; + }; +})(tinymce); + +tinymce.ForceBlocks = function(editor) { + var settings = editor.settings, dom = editor.dom, selection = editor.selection, blockElements = editor.schema.getBlockElements(); + + function addRootBlocks() { + var node = selection.getStart(), rootNode = editor.getBody(), rng, startContainer, startOffset, endContainer, endOffset, rootBlockNode, tempNode, offset = -0xFFFFFF, wrapped, isInEditorDocument; + + if (!node || node.nodeType !== 1 || !settings.forced_root_block) + return; + + // Check if node is wrapped in block + while (node && node != rootNode) { + if (blockElements[node.nodeName]) + return; + + node = node.parentNode; + } + + // Get current selection + rng = selection.getRng(); + if (rng.setStart) { + startContainer = rng.startContainer; + startOffset = rng.startOffset; + endContainer = rng.endContainer; + endOffset = rng.endOffset; + } else { + // Force control range into text range + if (rng.item) { + node = rng.item(0); + rng = editor.getDoc().body.createTextRange(); + rng.moveToElementText(node); + } + + isInEditorDocument = rng.parentElement().ownerDocument === editor.getDoc(); + tmpRng = rng.duplicate(); + tmpRng.collapse(true); + startOffset = tmpRng.move('character', offset) * -1; + + if (!tmpRng.collapsed) { + tmpRng = rng.duplicate(); + tmpRng.collapse(false); + endOffset = (tmpRng.move('character', offset) * -1) - startOffset; + } + } + + // Wrap non block elements and text nodes + node = rootNode.firstChild; + while (node) { + if (node.nodeType === 3 || (node.nodeType == 1 && !blockElements[node.nodeName])) { + // Remove empty text nodes + if (node.nodeType === 3 && node.nodeValue.length == 0) { + tempNode = node; + node = node.nextSibling; + dom.remove(tempNode); + continue; + } + + if (!rootBlockNode) { + rootBlockNode = dom.create(settings.forced_root_block); + node.parentNode.insertBefore(rootBlockNode, node); + wrapped = true; + } + + tempNode = node; + node = node.nextSibling; + rootBlockNode.appendChild(tempNode); + } else { + rootBlockNode = null; + node = node.nextSibling; + } + } + + if (wrapped) { + if (rng.setStart) { + rng.setStart(startContainer, startOffset); + rng.setEnd(endContainer, endOffset); + selection.setRng(rng); + } else { + // Only select if the previous selection was inside the document to prevent auto focus in quirks mode + if (isInEditorDocument) { + try { + rng = editor.getDoc().body.createTextRange(); + rng.moveToElementText(rootNode); + rng.collapse(true); + rng.moveStart('character', startOffset); + + if (endOffset > 0) + rng.moveEnd('character', endOffset); + + rng.select(); + } catch (ex) { + // Ignore + } + } + } + + editor.nodeChanged(); + } + }; + + // Force root blocks + if (settings.forced_root_block) { + editor.onKeyUp.add(addRootBlocks); + editor.onNodeChange.add(addRootBlocks); + } +}; + +(function(tinymce) { + // Shorten names + var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each, extend = tinymce.extend; + + tinymce.create('tinymce.ControlManager', { + ControlManager : function(ed, s) { + var t = this, i; + + s = s || {}; + t.editor = ed; + t.controls = {}; + t.onAdd = new tinymce.util.Dispatcher(t); + t.onPostRender = new tinymce.util.Dispatcher(t); + t.prefix = s.prefix || ed.id + '_'; + t._cls = {}; + + t.onPostRender.add(function() { + each(t.controls, function(c) { + c.postRender(); + }); + }); + }, + + get : function(id) { + return this.controls[this.prefix + id] || this.controls[id]; + }, + + setActive : function(id, s) { + var c = null; + + if (c = this.get(id)) + c.setActive(s); + + return c; + }, + + setDisabled : function(id, s) { + var c = null; + + if (c = this.get(id)) + c.setDisabled(s); + + return c; + }, + + add : function(c) { + var t = this; + + if (c) { + t.controls[c.id] = c; + t.onAdd.dispatch(c, t); + } + + return c; + }, + + createControl : function(name) { + var ctrl, i, l, self = this, editor = self.editor, factories, ctrlName; + + // Build control factory cache + if (!self.controlFactories) { + self.controlFactories = []; + each(editor.plugins, function(plugin) { + if (plugin.createControl) { + self.controlFactories.push(plugin); + } + }); + } + + // Create controls by asking cached factories + factories = self.controlFactories; + for (i = 0, l = factories.length; i < l; i++) { + ctrl = factories[i].createControl(name, self); + + if (ctrl) { + return self.add(ctrl); + } + } + + // Create sepearator + if (name === "|" || name === "separator") { + return self.createSeparator(); + } + + // Create control from button collection + if (editor.buttons && (ctrl = editor.buttons[name])) { + return self.createButton(name, ctrl); + } + + return self.add(ctrl); + }, + + createDropMenu : function(id, s, cc) { + var t = this, ed = t.editor, c, bm, v, cls; + + s = extend({ + 'class' : 'mceDropDown', + constrain : ed.settings.constrain_menus + }, s); + + s['class'] = s['class'] + ' ' + ed.getParam('skin') + 'Skin'; + if (v = ed.getParam('skin_variant')) + s['class'] += ' ' + ed.getParam('skin') + 'Skin' + v.substring(0, 1).toUpperCase() + v.substring(1); + + s['class'] += ed.settings.directionality == "rtl" ? ' mceRtl' : ''; + + id = t.prefix + id; + cls = cc || t._cls.dropmenu || tinymce.ui.DropMenu; + c = t.controls[id] = new cls(id, s); + c.onAddItem.add(function(c, o) { + var s = o.settings; + + s.title = ed.getLang(s.title, s.title); + + if (!s.onclick) { + s.onclick = function(v) { + if (s.cmd) + ed.execCommand(s.cmd, s.ui || false, s.value); + }; + } + }); + + ed.onRemove.add(function() { + c.destroy(); + }); + + // Fix for bug #1897785, #1898007 + if (tinymce.isIE) { + c.onShowMenu.add(function() { + // IE 8 needs focus in order to store away a range with the current collapsed caret location + ed.focus(); + + bm = ed.selection.getBookmark(1); + }); + + c.onHideMenu.add(function() { + if (bm) { + ed.selection.moveToBookmark(bm); + bm = 0; + } + }); + } + + return t.add(c); + }, + + createListBox : function(id, s, cc) { + var t = this, ed = t.editor, cmd, c, cls; + + if (t.get(id)) + return null; + + s.title = ed.translate(s.title); + s.scope = s.scope || ed; + + if (!s.onselect) { + s.onselect = function(v) { + ed.execCommand(s.cmd, s.ui || false, v || s.value); + }; + } + + s = extend({ + title : s.title, + 'class' : 'mce_' + id, + scope : s.scope, + control_manager : t + }, s); + + id = t.prefix + id; + + + function useNativeListForAccessibility(ed) { + return ed.settings.use_accessible_selects && !tinymce.isGecko + } + + if (ed.settings.use_native_selects || useNativeListForAccessibility(ed)) + c = new tinymce.ui.NativeListBox(id, s); + else { + cls = cc || t._cls.listbox || tinymce.ui.ListBox; + c = new cls(id, s, ed); + } + + t.controls[id] = c; + + // Fix focus problem in Safari + if (tinymce.isWebKit) { + c.onPostRender.add(function(c, n) { + // Store bookmark on mousedown + Event.add(n, 'mousedown', function() { + ed.bookmark = ed.selection.getBookmark(1); + }); + + // Restore on focus, since it might be lost + Event.add(n, 'focus', function() { + ed.selection.moveToBookmark(ed.bookmark); + ed.bookmark = null; + }); + }); + } + + if (c.hideMenu) + ed.onMouseDown.add(c.hideMenu, c); + + return t.add(c); + }, + + createButton : function(id, s, cc) { + var t = this, ed = t.editor, o, c, cls; + + if (t.get(id)) + return null; + + s.title = ed.translate(s.title); + s.label = ed.translate(s.label); + s.scope = s.scope || ed; + + if (!s.onclick && !s.menu_button) { + s.onclick = function() { + ed.execCommand(s.cmd, s.ui || false, s.value); + }; + } + + s = extend({ + title : s.title, + 'class' : 'mce_' + id, + unavailable_prefix : ed.getLang('unavailable', ''), + scope : s.scope, + control_manager : t + }, s); + + id = t.prefix + id; + + if (s.menu_button) { + cls = cc || t._cls.menubutton || tinymce.ui.MenuButton; + c = new cls(id, s, ed); + ed.onMouseDown.add(c.hideMenu, c); + } else { + cls = t._cls.button || tinymce.ui.Button; + c = new cls(id, s, ed); + } + + return t.add(c); + }, + + createMenuButton : function(id, s, cc) { + s = s || {}; + s.menu_button = 1; + + return this.createButton(id, s, cc); + }, + + createSplitButton : function(id, s, cc) { + var t = this, ed = t.editor, cmd, c, cls; + + if (t.get(id)) + return null; + + s.title = ed.translate(s.title); + s.scope = s.scope || ed; + + if (!s.onclick) { + s.onclick = function(v) { + ed.execCommand(s.cmd, s.ui || false, v || s.value); + }; + } + + if (!s.onselect) { + s.onselect = function(v) { + ed.execCommand(s.cmd, s.ui || false, v || s.value); + }; + } + + s = extend({ + title : s.title, + 'class' : 'mce_' + id, + scope : s.scope, + control_manager : t + }, s); + + id = t.prefix + id; + cls = cc || t._cls.splitbutton || tinymce.ui.SplitButton; + c = t.add(new cls(id, s, ed)); + ed.onMouseDown.add(c.hideMenu, c); + + return c; + }, + + createColorSplitButton : function(id, s, cc) { + var t = this, ed = t.editor, cmd, c, cls, bm; + + if (t.get(id)) + return null; + + s.title = ed.translate(s.title); + s.scope = s.scope || ed; + + if (!s.onclick) { + s.onclick = function(v) { + if (tinymce.isIE) + bm = ed.selection.getBookmark(1); + + ed.execCommand(s.cmd, s.ui || false, v || s.value); + }; + } + + if (!s.onselect) { + s.onselect = function(v) { + ed.execCommand(s.cmd, s.ui || false, v || s.value); + }; + } + + s = extend({ + title : s.title, + 'class' : 'mce_' + id, + 'menu_class' : ed.getParam('skin') + 'Skin', + scope : s.scope, + more_colors_title : ed.getLang('more_colors') + }, s); + + id = t.prefix + id; + cls = cc || t._cls.colorsplitbutton || tinymce.ui.ColorSplitButton; + c = new cls(id, s, ed); + ed.onMouseDown.add(c.hideMenu, c); + + // Remove the menu element when the editor is removed + ed.onRemove.add(function() { + c.destroy(); + }); + + // Fix for bug #1897785, #1898007 + if (tinymce.isIE) { + c.onShowMenu.add(function() { + // IE 8 needs focus in order to store away a range with the current collapsed caret location + ed.focus(); + bm = ed.selection.getBookmark(1); + }); + + c.onHideMenu.add(function() { + if (bm) { + ed.selection.moveToBookmark(bm); + bm = 0; + } + }); + } + + return t.add(c); + }, + + createToolbar : function(id, s, cc) { + var c, t = this, cls; + + id = t.prefix + id; + cls = cc || t._cls.toolbar || tinymce.ui.Toolbar; + c = new cls(id, s, t.editor); + + if (t.get(id)) + return null; + + return t.add(c); + }, + + createToolbarGroup : function(id, s, cc) { + var c, t = this, cls; + id = t.prefix + id; + cls = cc || this._cls.toolbarGroup || tinymce.ui.ToolbarGroup; + c = new cls(id, s, t.editor); + + if (t.get(id)) + return null; + + return t.add(c); + }, + + createSeparator : function(cc) { + var cls = cc || this._cls.separator || tinymce.ui.Separator; + + return new cls(); + }, + + setControlType : function(n, c) { + return this._cls[n.toLowerCase()] = c; + }, + + destroy : function() { + each(this.controls, function(c) { + c.destroy(); + }); + + this.controls = null; + } + }); +})(tinymce); + +(function(tinymce) { + var Dispatcher = tinymce.util.Dispatcher, each = tinymce.each, isIE = tinymce.isIE, isOpera = tinymce.isOpera; + + tinymce.create('tinymce.WindowManager', { + WindowManager : function(ed) { + var t = this; + + t.editor = ed; + t.onOpen = new Dispatcher(t); + t.onClose = new Dispatcher(t); + t.params = {}; + t.features = {}; + }, + + open : function(s, p) { + var t = this, f = '', x, y, mo = t.editor.settings.dialog_type == 'modal', w, sw, sh, vp = tinymce.DOM.getViewPort(), u; + + // Default some options + s = s || {}; + p = p || {}; + sw = isOpera ? vp.w : screen.width; // Opera uses windows inside the Opera window + sh = isOpera ? vp.h : screen.height; + s.name = s.name || 'mc_' + new Date().getTime(); + s.width = parseInt(s.width || 320); + s.height = parseInt(s.height || 240); + s.resizable = true; + s.left = s.left || parseInt(sw / 2.0) - (s.width / 2.0); + s.top = s.top || parseInt(sh / 2.0) - (s.height / 2.0); + p.inline = false; + p.mce_width = s.width; + p.mce_height = s.height; + p.mce_auto_focus = s.auto_focus; + + if (mo) { + if (isIE) { + s.center = true; + s.help = false; + s.dialogWidth = s.width + 'px'; + s.dialogHeight = s.height + 'px'; + s.scroll = s.scrollbars || false; + } + } + + // Build features string + each(s, function(v, k) { + if (tinymce.is(v, 'boolean')) + v = v ? 'yes' : 'no'; + + if (!/^(name|url)$/.test(k)) { + if (isIE && mo) + f += (f ? ';' : '') + k + ':' + v; + else + f += (f ? ',' : '') + k + '=' + v; + } + }); + + t.features = s; + t.params = p; + t.onOpen.dispatch(t, s, p); + + u = s.url || s.file; + u = tinymce._addVer(u); + + try { + if (isIE && mo) { + w = 1; + window.showModalDialog(u, window, f); + } else + w = window.open(u, s.name, f); + } catch (ex) { + // Ignore + } + + if (!w) + alert(t.editor.getLang('popup_blocked')); + }, + + close : function(w) { + w.close(); + this.onClose.dispatch(this); + }, + + createInstance : function(cl, a, b, c, d, e) { + var f = tinymce.resolve(cl); + + return new f(a, b, c, d, e); + }, + + confirm : function(t, cb, s, w) { + w = w || window; + + cb.call(s || this, w.confirm(this._decode(this.editor.getLang(t, t)))); + }, + + alert : function(tx, cb, s, w) { + var t = this; + + w = w || window; + w.alert(t._decode(t.editor.getLang(tx, tx))); + + if (cb) + cb.call(s || t); + }, + + resizeBy : function(dw, dh, win) { + win.resizeBy(dw, dh); + }, + + // Internal functions + + _decode : function(s) { + return tinymce.DOM.decode(s).replace(/\\n/g, '\n'); + } + }); +}(tinymce)); +(function(tinymce) { + tinymce.Formatter = function(ed) { + var formats = {}, + each = tinymce.each, + dom = ed.dom, + selection = ed.selection, + TreeWalker = tinymce.dom.TreeWalker, + rangeUtils = new tinymce.dom.RangeUtils(dom), + isValid = ed.schema.isValidChild, + isArray = tinymce.isArray, + isBlock = dom.isBlock, + forcedRootBlock = ed.settings.forced_root_block, + nodeIndex = dom.nodeIndex, + INVISIBLE_CHAR = '\uFEFF', + MCE_ATTR_RE = /^(src|href|style)$/, + FALSE = false, + TRUE = true, + formatChangeData, + undef, + getContentEditable = dom.getContentEditable; + + function isTextBlock(name) { + if (name.nodeType) { + name = name.nodeName; + } + + return !!ed.schema.getTextBlockElements()[name.toLowerCase()]; + } + + function getParents(node, selector) { + return dom.getParents(node, selector, dom.getRoot()); + }; + + function isCaretNode(node) { + return node.nodeType === 1 && node.id === '_mce_caret'; + }; + + function defaultFormats() { + register({ + alignleft : [ + {selector : 'figure,p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li', styles : {textAlign : 'left'}, defaultBlock: 'div'}, + {selector : 'img,table', collapsed : false, styles : {'float' : 'left'}} + ], + + aligncenter : [ + {selector : 'figure,p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li', styles : {textAlign : 'center'}, defaultBlock: 'div'}, + {selector : 'img', collapsed : false, styles : {display : 'block', marginLeft : 'auto', marginRight : 'auto'}}, + {selector : 'table', collapsed : false, styles : {marginLeft : 'auto', marginRight : 'auto'}} + ], + + alignright : [ + {selector : 'figure,p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li', styles : {textAlign : 'right'}, defaultBlock: 'div'}, + {selector : 'img,table', collapsed : false, styles : {'float' : 'right'}} + ], + + alignfull : [ + {selector : 'figure,p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li', styles : {textAlign : 'justify'}, defaultBlock: 'div'} + ], + + bold : [ + {inline : 'strong', remove : 'all'}, + {inline : 'span', styles : {fontWeight : 'bold'}}, + {inline : 'b', remove : 'all'} + ], + + italic : [ + {inline : 'em', remove : 'all'}, + {inline : 'span', styles : {fontStyle : 'italic'}}, + {inline : 'i', remove : 'all'} + ], + + underline : [ + {inline : 'span', styles : {textDecoration : 'underline'}, exact : true}, + {inline : 'u', remove : 'all'} + ], + + strikethrough : [ + {inline : 'span', styles : {textDecoration : 'line-through'}, exact : true}, + {inline : 'strike', remove : 'all'} + ], + + forecolor : {inline : 'span', styles : {color : '%value'}, wrap_links : false}, + hilitecolor : {inline : 'span', styles : {backgroundColor : '%value'}, wrap_links : false}, + fontname : {inline : 'span', styles : {fontFamily : '%value'}}, + fontsize : {inline : 'span', styles : {fontSize : '%value'}}, + fontsize_class : {inline : 'span', attributes : {'class' : '%value'}}, + blockquote : {block : 'blockquote', wrapper : 1, remove : 'all'}, + subscript : {inline : 'sub'}, + superscript : {inline : 'sup'}, + + link : {inline : 'a', selector : 'a', remove : 'all', split : true, deep : true, + onmatch : function(node) { + return true; + }, + + onformat : function(elm, fmt, vars) { + each(vars, function(value, key) { + dom.setAttrib(elm, key, value); + }); + } + }, + + removeformat : [ + {selector : 'b,strong,em,i,font,u,strike', remove : 'all', split : true, expand : false, block_expand : true, deep : true}, + {selector : 'span', attributes : ['style', 'class'], remove : 'empty', split : true, expand : false, deep : true}, + {selector : '*', attributes : ['style', 'class'], split : false, expand : false, deep : true} + ] + }); + + // Register default block formats + each('p h1 h2 h3 h4 h5 h6 div address pre div code dt dd samp'.split(/\s/), function(name) { + register(name, {block : name, remove : 'all'}); + }); + + // Register user defined formats + register(ed.settings.formats); + }; + + function addKeyboardShortcuts() { + // Add some inline shortcuts + ed.addShortcut('ctrl+b', 'bold_desc', 'Bold'); + ed.addShortcut('ctrl+i', 'italic_desc', 'Italic'); + ed.addShortcut('ctrl+u', 'underline_desc', 'Underline'); + + // BlockFormat shortcuts keys + for (var i = 1; i <= 6; i++) { + ed.addShortcut('ctrl+' + i, '', ['FormatBlock', false, 'h' + i]); + } + + ed.addShortcut('ctrl+7', '', ['FormatBlock', false, 'p']); + ed.addShortcut('ctrl+8', '', ['FormatBlock', false, 'div']); + ed.addShortcut('ctrl+9', '', ['FormatBlock', false, 'address']); + }; + + // Public functions + + function get(name) { + return name ? formats[name] : formats; + }; + + function register(name, format) { + if (name) { + if (typeof(name) !== 'string') { + each(name, function(format, name) { + register(name, format); + }); + } else { + // Force format into array and add it to internal collection + format = format.length ? format : [format]; + + each(format, function(format) { + // Set deep to false by default on selector formats this to avoid removing + // alignment on images inside paragraphs when alignment is changed on paragraphs + if (format.deep === undef) + format.deep = !format.selector; + + // Default to true + if (format.split === undef) + format.split = !format.selector || format.inline; + + // Default to true + if (format.remove === undef && format.selector && !format.inline) + format.remove = 'none'; + + // Mark format as a mixed format inline + block level + if (format.selector && format.inline) { + format.mixed = true; + format.block_expand = true; + } + + // Split classes if needed + if (typeof(format.classes) === 'string') + format.classes = format.classes.split(/\s+/); + }); + + formats[name] = format; + } + } + }; + + var getTextDecoration = function(node) { + var decoration; + + ed.dom.getParent(node, function(n) { + decoration = ed.dom.getStyle(n, 'text-decoration'); + return decoration && decoration !== 'none'; + }); + + return decoration; + }; + + var processUnderlineAndColor = function(node) { + var textDecoration; + if (node.nodeType === 1 && node.parentNode && node.parentNode.nodeType === 1) { + textDecoration = getTextDecoration(node.parentNode); + if (ed.dom.getStyle(node, 'color') && textDecoration) { + ed.dom.setStyle(node, 'text-decoration', textDecoration); + } else if (ed.dom.getStyle(node, 'textdecoration') === textDecoration) { + ed.dom.setStyle(node, 'text-decoration', null); + } + } + }; + + function apply(name, vars, node) { + var formatList = get(name), format = formatList[0], bookmark, rng, i, isCollapsed = selection.isCollapsed(); + + function setElementFormat(elm, fmt) { + fmt = fmt || format; + + if (elm) { + if (fmt.onformat) { + fmt.onformat(elm, fmt, vars, node); + } + + each(fmt.styles, function(value, name) { + dom.setStyle(elm, name, replaceVars(value, vars)); + }); + + each(fmt.attributes, function(value, name) { + dom.setAttrib(elm, name, replaceVars(value, vars)); + }); + + each(fmt.classes, function(value) { + value = replaceVars(value, vars); + + if (!dom.hasClass(elm, value)) + dom.addClass(elm, value); + }); + } + }; + function adjustSelectionToVisibleSelection() { + function findSelectionEnd(start, end) { + var walker = new TreeWalker(end); + for (node = walker.current(); node; node = walker.prev()) { + if (node.childNodes.length > 1 || node == start || node.tagName == 'BR') { + return node; + } + } + }; + + // Adjust selection so that a end container with a end offset of zero is not included in the selection + // as this isn't visible to the user. + var rng = ed.selection.getRng(); + var start = rng.startContainer; + var end = rng.endContainer; + + if (start != end && rng.endOffset === 0) { + var newEnd = findSelectionEnd(start, end); + var endOffset = newEnd.nodeType == 3 ? newEnd.length : newEnd.childNodes.length; + + rng.setEnd(newEnd, endOffset); + } + + return rng; + } + + function applyStyleToList(node, bookmark, wrapElm, newWrappers, process){ + var nodes = [], listIndex = -1, list, startIndex = -1, endIndex = -1, currentWrapElm; + + // find the index of the first child list. + each(node.childNodes, function(n, index) { + if (n.nodeName === "UL" || n.nodeName === "OL") { + listIndex = index; + list = n; + return false; + } + }); + + // get the index of the bookmarks + each(node.childNodes, function(n, index) { + if (n.nodeName === "SPAN" && dom.getAttrib(n, "data-mce-type") == "bookmark") { + if (n.id == bookmark.id + "_start") { + startIndex = index; + } else if (n.id == bookmark.id + "_end") { + endIndex = index; + } + } + }); + + // if the selection spans across an embedded list, or there isn't an embedded list - handle processing normally + if (listIndex <= 0 || (startIndex < listIndex && endIndex > listIndex)) { + each(tinymce.grep(node.childNodes), process); + return 0; + } else { + currentWrapElm = dom.clone(wrapElm, FALSE); + + // create a list of the nodes on the same side of the list as the selection + each(tinymce.grep(node.childNodes), function(n, index) { + if ((startIndex < listIndex && index < listIndex) || (startIndex > listIndex && index > listIndex)) { + nodes.push(n); + n.parentNode.removeChild(n); + } + }); + + // insert the wrapping element either before or after the list. + if (startIndex < listIndex) { + node.insertBefore(currentWrapElm, list); + } else if (startIndex > listIndex) { + node.insertBefore(currentWrapElm, list.nextSibling); + } + + // add the new nodes to the list. + newWrappers.push(currentWrapElm); + + each(nodes, function(node) { + currentWrapElm.appendChild(node); + }); + + return currentWrapElm; + } + }; + + function applyRngStyle(rng, bookmark, node_specific) { + var newWrappers = [], wrapName, wrapElm, contentEditable = true; + + // Setup wrapper element + wrapName = format.inline || format.block; + wrapElm = dom.create(wrapName); + setElementFormat(wrapElm); + + rangeUtils.walk(rng, function(nodes) { + var currentWrapElm; + + function process(node) { + var nodeName, parentName, found, hasContentEditableState, lastContentEditable; + + lastContentEditable = contentEditable; + nodeName = node.nodeName.toLowerCase(); + parentName = node.parentNode.nodeName.toLowerCase(); + + // Node has a contentEditable value + if (node.nodeType === 1 && getContentEditable(node)) { + lastContentEditable = contentEditable; + contentEditable = getContentEditable(node) === "true"; + hasContentEditableState = true; // We don't want to wrap the container only it's children + } + + // Stop wrapping on br elements + if (isEq(nodeName, 'br')) { + currentWrapElm = 0; + + // Remove any br elements when we wrap things + if (format.block) + dom.remove(node); + + return; + } + + // If node is wrapper type + if (format.wrapper && matchNode(node, name, vars)) { + currentWrapElm = 0; + return; + } + + // Can we rename the block + if (contentEditable && !hasContentEditableState && format.block && !format.wrapper && isTextBlock(nodeName)) { + node = dom.rename(node, wrapName); + setElementFormat(node); + newWrappers.push(node); + currentWrapElm = 0; + return; + } + + // Handle selector patterns + if (format.selector) { + // Look for matching formats + each(formatList, function(format) { + // Check collapsed state if it exists + if ('collapsed' in format && format.collapsed !== isCollapsed) { + return; + } + + if (dom.is(node, format.selector) && !isCaretNode(node)) { + setElementFormat(node, format); + found = true; + } + }); + + // Continue processing if a selector match wasn't found and a inline element is defined + if (!format.inline || found) { + currentWrapElm = 0; + return; + } + } + + // Is it valid to wrap this item + if (contentEditable && !hasContentEditableState && isValid(wrapName, nodeName) && isValid(parentName, wrapName) && + !(!node_specific && node.nodeType === 3 && node.nodeValue.length === 1 && node.nodeValue.charCodeAt(0) === 65279) && !isCaretNode(node) && (!format.inline || !isBlock(node))) { + // Start wrapping + if (!currentWrapElm) { + // Wrap the node + currentWrapElm = dom.clone(wrapElm, FALSE); + node.parentNode.insertBefore(currentWrapElm, node); + newWrappers.push(currentWrapElm); + } + + currentWrapElm.appendChild(node); + } else if (nodeName == 'li' && bookmark) { + // Start wrapping - if we are in a list node and have a bookmark, then we will always begin by wrapping in a new element. + currentWrapElm = applyStyleToList(node, bookmark, wrapElm, newWrappers, process); + } else { + // Start a new wrapper for possible children + currentWrapElm = 0; + + each(tinymce.grep(node.childNodes), process); + + if (hasContentEditableState) { + contentEditable = lastContentEditable; // Restore last contentEditable state from stack + } + + // End the last wrapper + currentWrapElm = 0; + } + }; + + // Process siblings from range + each(nodes, process); + }); + + // Wrap links inside as well, for example color inside a link when the wrapper is around the link + if (format.wrap_links === false) { + each(newWrappers, function(node) { + function process(node) { + var i, currentWrapElm, children; + + if (node.nodeName === 'A') { + currentWrapElm = dom.clone(wrapElm, FALSE); + newWrappers.push(currentWrapElm); + + children = tinymce.grep(node.childNodes); + for (i = 0; i < children.length; i++) + currentWrapElm.appendChild(children[i]); + + node.appendChild(currentWrapElm); + } + + each(tinymce.grep(node.childNodes), process); + }; + + process(node); + }); + } + + // Cleanup + + each(newWrappers, function(node) { + var childCount; + + function getChildCount(node) { + var count = 0; + + each(node.childNodes, function(node) { + if (!isWhiteSpaceNode(node) && !isBookmarkNode(node)) + count++; + }); + + return count; + }; + + function mergeStyles(node) { + var child, clone; + + each(node.childNodes, function(node) { + if (node.nodeType == 1 && !isBookmarkNode(node) && !isCaretNode(node)) { + child = node; + return FALSE; // break loop + } + }); + + // If child was found and of the same type as the current node + if (child && matchName(child, format)) { + clone = dom.clone(child, FALSE); + setElementFormat(clone); + + dom.replace(clone, node, TRUE); + dom.remove(child, 1); + } + + return clone || node; + }; + + childCount = getChildCount(node); + + // Remove empty nodes but only if there is multiple wrappers and they are not block + // elements so never remove single

    since that would remove the currrent empty block element where the caret is at + if ((newWrappers.length > 1 || !isBlock(node)) && childCount === 0) { + dom.remove(node, 1); + return; + } + + if (format.inline || format.wrapper) { + // Merges the current node with it's children of similar type to reduce the number of elements + if (!format.exact && childCount === 1) + node = mergeStyles(node); + + // Remove/merge children + each(formatList, function(format) { + // Merge all children of similar type will move styles from child to parent + // this: text + // will become: text + each(dom.select(format.inline, node), function(child) { + var parent; + + // When wrap_links is set to false we don't want + // to remove the format on children within links + if (format.wrap_links === false) { + parent = child.parentNode; + + do { + if (parent.nodeName === 'A') + return; + } while (parent = parent.parentNode); + } + + removeFormat(format, vars, child, format.exact ? child : null); + }); + }); + + // Remove child if direct parent is of same type + if (matchNode(node.parentNode, name, vars)) { + dom.remove(node, 1); + node = 0; + return TRUE; + } + + // Look for parent with similar style format + if (format.merge_with_parents) { + dom.getParent(node.parentNode, function(parent) { + if (matchNode(parent, name, vars)) { + dom.remove(node, 1); + node = 0; + return TRUE; + } + }); + } + + // Merge next and previous siblings if they are similar texttext becomes texttext + if (node && format.merge_siblings !== false) { + node = mergeSiblings(getNonWhiteSpaceSibling(node), node); + node = mergeSiblings(node, getNonWhiteSpaceSibling(node, TRUE)); + } + } + }); + }; + + if (format) { + if (node) { + if (node.nodeType) { + rng = dom.createRng(); + rng.setStartBefore(node); + rng.setEndAfter(node); + applyRngStyle(expandRng(rng, formatList), null, true); + } else { + applyRngStyle(node, null, true); + } + } else { + if (!isCollapsed || !format.inline || dom.select('td.mceSelected,th.mceSelected').length) { + // Obtain selection node before selection is unselected by applyRngStyle() + var curSelNode = ed.selection.getNode(); + + // If the formats have a default block and we can't find a parent block then start wrapping it with a DIV this is for forced_root_blocks: false + // It's kind of a hack but people should be using the default block type P since all desktop editors work that way + if (!forcedRootBlock && formatList[0].defaultBlock && !dom.getParent(curSelNode, dom.isBlock)) { + apply(formatList[0].defaultBlock); + } + + // Apply formatting to selection + ed.selection.setRng(adjustSelectionToVisibleSelection()); + bookmark = selection.getBookmark(); + applyRngStyle(expandRng(selection.getRng(TRUE), formatList), bookmark); + + // Colored nodes should be underlined so that the color of the underline matches the text color. + if (format.styles && (format.styles.color || format.styles.textDecoration)) { + tinymce.walk(curSelNode, processUnderlineAndColor, 'childNodes'); + processUnderlineAndColor(curSelNode); + } + + selection.moveToBookmark(bookmark); + moveStart(selection.getRng(TRUE)); + ed.nodeChanged(); + } else + performCaretAction('apply', name, vars); + } + } + }; + + function remove(name, vars, node) { + var formatList = get(name), format = formatList[0], bookmark, i, rng, contentEditable = true; + + // Merges the styles for each node + function process(node) { + var children, i, l, localContentEditable, lastContentEditable, hasContentEditableState; + + // Skip on text nodes as they have neither format to remove nor children + if (node.nodeType === 3) { + return; + } + + // Node has a contentEditable value + if (node.nodeType === 1 && getContentEditable(node)) { + lastContentEditable = contentEditable; + contentEditable = getContentEditable(node) === "true"; + hasContentEditableState = true; // We don't want to wrap the container only it's children + } + + // Grab the children first since the nodelist might be changed + children = tinymce.grep(node.childNodes); + + // Process current node + if (contentEditable && !hasContentEditableState) { + for (i = 0, l = formatList.length; i < l; i++) { + if (removeFormat(formatList[i], vars, node, node)) + break; + } + } + + // Process the children + if (format.deep) { + if (children.length) { + for (i = 0, l = children.length; i < l; i++) + process(children[i]); + + if (hasContentEditableState) { + contentEditable = lastContentEditable; // Restore last contentEditable state from stack + } + } + } + }; + + function findFormatRoot(container) { + var formatRoot; + + // Find format root + each(getParents(container.parentNode).reverse(), function(parent) { + var format; + + // Find format root element + if (!formatRoot && parent.id != '_start' && parent.id != '_end') { + // Is the node matching the format we are looking for + format = matchNode(parent, name, vars); + if (format && format.split !== false) + formatRoot = parent; + } + }); + + return formatRoot; + }; + + function wrapAndSplit(format_root, container, target, split) { + var parent, clone, lastClone, firstClone, i, formatRootParent; + + // Format root found then clone formats and split it + if (format_root) { + formatRootParent = format_root.parentNode; + + for (parent = container.parentNode; parent && parent != formatRootParent; parent = parent.parentNode) { + clone = dom.clone(parent, FALSE); + + for (i = 0; i < formatList.length; i++) { + if (removeFormat(formatList[i], vars, clone, clone)) { + clone = 0; + break; + } + } + + // Build wrapper node + if (clone) { + if (lastClone) + clone.appendChild(lastClone); + + if (!firstClone) + firstClone = clone; + + lastClone = clone; + } + } + + // Never split block elements if the format is mixed + if (split && (!format.mixed || !isBlock(format_root))) + container = dom.split(format_root, container); + + // Wrap container in cloned formats + if (lastClone) { + target.parentNode.insertBefore(lastClone, target); + firstClone.appendChild(target); + } + } + + return container; + }; + + function splitToFormatRoot(container) { + return wrapAndSplit(findFormatRoot(container), container, container, true); + }; + + function unwrap(start) { + var node = dom.get(start ? '_start' : '_end'), + out = node[start ? 'firstChild' : 'lastChild']; + + // If the end is placed within the start the result will be removed + // So this checks if the out node is a bookmark node if it is it + // checks for another more suitable node + if (isBookmarkNode(out)) + out = out[start ? 'firstChild' : 'lastChild']; + + dom.remove(node, true); + + return out; + }; + + function removeRngStyle(rng) { + var startContainer, endContainer, node; + + rng = expandRng(rng, formatList, TRUE); + + if (format.split) { + startContainer = getContainer(rng, TRUE); + endContainer = getContainer(rng); + + if (startContainer != endContainer) { + // WebKit will render the table incorrectly if we wrap a TD in a SPAN so lets see if the can use the first child instead + // This will happen if you tripple click a table cell and use remove formatting + if (/^(TR|TD)$/.test(startContainer.nodeName) && startContainer.firstChild) { + startContainer = (startContainer.nodeName == "TD" ? startContainer.firstChild : startContainer.firstChild.firstChild) || startContainer; + } + + // Wrap start/end nodes in span element since these might be cloned/moved + startContainer = wrap(startContainer, 'span', {id : '_start', 'data-mce-type' : 'bookmark'}); + endContainer = wrap(endContainer, 'span', {id : '_end', 'data-mce-type' : 'bookmark'}); + + // Split start/end + splitToFormatRoot(startContainer); + splitToFormatRoot(endContainer); + + // Unwrap start/end to get real elements again + startContainer = unwrap(TRUE); + endContainer = unwrap(); + } else + startContainer = endContainer = splitToFormatRoot(startContainer); + + // Update range positions since they might have changed after the split operations + rng.startContainer = startContainer.parentNode; + rng.startOffset = nodeIndex(startContainer); + rng.endContainer = endContainer.parentNode; + rng.endOffset = nodeIndex(endContainer) + 1; + } + + // Remove items between start/end + rangeUtils.walk(rng, function(nodes) { + each(nodes, function(node) { + process(node); + + // Remove parent span if it only contains text-decoration: underline, yet a parent node is also underlined. + if (node.nodeType === 1 && ed.dom.getStyle(node, 'text-decoration') === 'underline' && node.parentNode && getTextDecoration(node.parentNode) === 'underline') { + removeFormat({'deep': false, 'exact': true, 'inline': 'span', 'styles': {'textDecoration' : 'underline'}}, null, node); + } + }); + }); + }; + + // Handle node + if (node) { + if (node.nodeType) { + rng = dom.createRng(); + rng.setStartBefore(node); + rng.setEndAfter(node); + removeRngStyle(rng); + } else { + removeRngStyle(node); + } + + return; + } + + if (!selection.isCollapsed() || !format.inline || dom.select('td.mceSelected,th.mceSelected').length) { + bookmark = selection.getBookmark(); + removeRngStyle(selection.getRng(TRUE)); + selection.moveToBookmark(bookmark); + + // Check if start element still has formatting then we are at: "text|text" and need to move the start into the next text node + if (format.inline && match(name, vars, selection.getStart())) { + moveStart(selection.getRng(true)); + } + + ed.nodeChanged(); + } else + performCaretAction('remove', name, vars); + }; + + function toggle(name, vars, node) { + var fmt = get(name); + + if (match(name, vars, node) && (!('toggle' in fmt[0]) || fmt[0].toggle)) + remove(name, vars, node); + else + apply(name, vars, node); + }; + + function matchNode(node, name, vars, similar) { + var formatList = get(name), format, i, classes; + + function matchItems(node, format, item_name) { + var key, value, items = format[item_name], i; + + // Custom match + if (format.onmatch) { + return format.onmatch(node, format, item_name); + } + + // Check all items + if (items) { + // Non indexed object + if (items.length === undef) { + for (key in items) { + if (items.hasOwnProperty(key)) { + if (item_name === 'attributes') + value = dom.getAttrib(node, key); + else + value = getStyle(node, key); + + if (similar && !value && !format.exact) + return; + + if ((!similar || format.exact) && !isEq(value, replaceVars(items[key], vars))) + return; + } + } + } else { + // Only one match needed for indexed arrays + for (i = 0; i < items.length; i++) { + if (item_name === 'attributes' ? dom.getAttrib(node, items[i]) : getStyle(node, items[i])) + return format; + } + } + } + + return format; + }; + + if (formatList && node) { + // Check each format in list + for (i = 0; i < formatList.length; i++) { + format = formatList[i]; + + // Name name, attributes, styles and classes + if (matchName(node, format) && matchItems(node, format, 'attributes') && matchItems(node, format, 'styles')) { + // Match classes + if (classes = format.classes) { + for (i = 0; i < classes.length; i++) { + if (!dom.hasClass(node, classes[i])) + return; + } + } + + return format; + } + } + } + }; + + function match(name, vars, node) { + var startNode; + + function matchParents(node) { + // Find first node with similar format settings + node = dom.getParent(node, function(node) { + return !!matchNode(node, name, vars, true); + }); + + // Do an exact check on the similar format element + return matchNode(node, name, vars); + }; + + // Check specified node + if (node) + return matchParents(node); + + // Check selected node + node = selection.getNode(); + if (matchParents(node)) + return TRUE; + + // Check start node if it's different + startNode = selection.getStart(); + if (startNode != node) { + if (matchParents(startNode)) + return TRUE; + } + + return FALSE; + }; + + function matchAll(names, vars) { + var startElement, matchedFormatNames = [], checkedMap = {}, i, ni, name; + + // Check start of selection for formats + startElement = selection.getStart(); + dom.getParent(startElement, function(node) { + var i, name; + + for (i = 0; i < names.length; i++) { + name = names[i]; + + if (!checkedMap[name] && matchNode(node, name, vars)) { + checkedMap[name] = true; + matchedFormatNames.push(name); + } + } + }, dom.getRoot()); + + return matchedFormatNames; + }; + + function canApply(name) { + var formatList = get(name), startNode, parents, i, x, selector; + + if (formatList) { + startNode = selection.getStart(); + parents = getParents(startNode); + + for (x = formatList.length - 1; x >= 0; x--) { + selector = formatList[x].selector; + + // Format is not selector based, then always return TRUE + if (!selector) + return TRUE; + + for (i = parents.length - 1; i >= 0; i--) { + if (dom.is(parents[i], selector)) + return TRUE; + } + } + } + + return FALSE; + }; + + function formatChanged(formats, callback, similar) { + var currentFormats; + + // Setup format node change logic + if (!formatChangeData) { + formatChangeData = {}; + currentFormats = {}; + + ed.onNodeChange.addToTop(function(ed, cm, node) { + var parents = getParents(node), matchedFormats = {}; + + // Check for new formats + each(formatChangeData, function(callbacks, format) { + each(parents, function(node) { + if (matchNode(node, format, {}, callbacks.similar)) { + if (!currentFormats[format]) { + // Execute callbacks + each(callbacks, function(callback) { + callback(true, {node: node, format: format, parents: parents}); + }); + + currentFormats[format] = callbacks; + } + + matchedFormats[format] = callbacks; + return false; + } + }); + }); + + // Check if current formats still match + each(currentFormats, function(callbacks, format) { + if (!matchedFormats[format]) { + delete currentFormats[format]; + + each(callbacks, function(callback) { + callback(false, {node: node, format: format, parents: parents}); + }); + } + }); + }); + } + + // Add format listeners + each(formats.split(','), function(format) { + if (!formatChangeData[format]) { + formatChangeData[format] = []; + formatChangeData[format].similar = similar; + } + + formatChangeData[format].push(callback); + }); + + return this; + }; + + // Expose to public + tinymce.extend(this, { + get : get, + register : register, + apply : apply, + remove : remove, + toggle : toggle, + match : match, + matchAll : matchAll, + matchNode : matchNode, + canApply : canApply, + formatChanged: formatChanged + }); + + // Initialize + defaultFormats(); + addKeyboardShortcuts(); + + // Private functions + + function matchName(node, format) { + // Check for inline match + if (isEq(node, format.inline)) + return TRUE; + + // Check for block match + if (isEq(node, format.block)) + return TRUE; + + // Check for selector match + if (format.selector) + return dom.is(node, format.selector); + }; + + function isEq(str1, str2) { + str1 = str1 || ''; + str2 = str2 || ''; + + str1 = '' + (str1.nodeName || str1); + str2 = '' + (str2.nodeName || str2); + + return str1.toLowerCase() == str2.toLowerCase(); + }; + + function getStyle(node, name) { + var styleVal = dom.getStyle(node, name); + + // Force the format to hex + if (name == 'color' || name == 'backgroundColor') + styleVal = dom.toHex(styleVal); + + // Opera will return bold as 700 + if (name == 'fontWeight' && styleVal == 700) + styleVal = 'bold'; + + return '' + styleVal; + }; + + function replaceVars(value, vars) { + if (typeof(value) != "string") + value = value(vars); + else if (vars) { + value = value.replace(/%(\w+)/g, function(str, name) { + return vars[name] || str; + }); + } + + return value; + }; + + function isWhiteSpaceNode(node) { + return node && node.nodeType === 3 && /^([\t \r\n]+|)$/.test(node.nodeValue); + }; + + function wrap(node, name, attrs) { + var wrapper = dom.create(name, attrs); + + node.parentNode.insertBefore(wrapper, node); + wrapper.appendChild(node); + + return wrapper; + }; + + function expandRng(rng, format, remove) { + var sibling, lastIdx, leaf, endPoint, + startContainer = rng.startContainer, + startOffset = rng.startOffset, + endContainer = rng.endContainer, + endOffset = rng.endOffset; + + // This function walks up the tree if there is no siblings before/after the node + function findParentContainer(start) { + var container, parent, child, sibling, siblingName, root; + + container = parent = start ? startContainer : endContainer; + siblingName = start ? 'previousSibling' : 'nextSibling'; + root = dom.getRoot(); + + function isBogusBr(node) { + return node.nodeName == "BR" && node.getAttribute('data-mce-bogus') && !node.nextSibling; + }; + + // If it's a text node and the offset is inside the text + if (container.nodeType == 3 && !isWhiteSpaceNode(container)) { + if (start ? startOffset > 0 : endOffset < container.nodeValue.length) { + return container; + } + } + + for (;;) { + // Stop expanding on block elements + if (!format[0].block_expand && isBlock(parent)) + return parent; + + // Walk left/right + for (sibling = parent[siblingName]; sibling; sibling = sibling[siblingName]) { + if (!isBookmarkNode(sibling) && !isWhiteSpaceNode(sibling) && !isBogusBr(sibling)) { + return parent; + } + } + + // Check if we can move up are we at root level or body level + if (parent.parentNode == root) { + container = parent; + break; + } + + parent = parent.parentNode; + } + + return container; + }; + + // This function walks down the tree to find the leaf at the selection. + // The offset is also returned as if node initially a leaf, the offset may be in the middle of the text node. + function findLeaf(node, offset) { + if (offset === undef) + offset = node.nodeType === 3 ? node.length : node.childNodes.length; + while (node && node.hasChildNodes()) { + node = node.childNodes[offset]; + if (node) + offset = node.nodeType === 3 ? node.length : node.childNodes.length; + } + return { node: node, offset: offset }; + } + + // If index based start position then resolve it + if (startContainer.nodeType == 1 && startContainer.hasChildNodes()) { + lastIdx = startContainer.childNodes.length - 1; + startContainer = startContainer.childNodes[startOffset > lastIdx ? lastIdx : startOffset]; + + if (startContainer.nodeType == 3) + startOffset = 0; + } + + // If index based end position then resolve it + if (endContainer.nodeType == 1 && endContainer.hasChildNodes()) { + lastIdx = endContainer.childNodes.length - 1; + endContainer = endContainer.childNodes[endOffset > lastIdx ? lastIdx : endOffset - 1]; + + if (endContainer.nodeType == 3) + endOffset = endContainer.nodeValue.length; + } + + // Expands the node to the closes contentEditable false element if it exists + function findParentContentEditable(node) { + var parent = node; + + while (parent) { + if (parent.nodeType === 1 && getContentEditable(parent)) { + return getContentEditable(parent) === "false" ? parent : node; + } + + parent = parent.parentNode; + } + + return node; + }; + + function findWordEndPoint(container, offset, start) { + var walker, node, pos, lastTextNode; + + function findSpace(node, offset) { + var pos, pos2, str = node.nodeValue; + + if (typeof(offset) == "undefined") { + offset = start ? str.length : 0; + } + + if (start) { + pos = str.lastIndexOf(' ', offset); + pos2 = str.lastIndexOf('\u00a0', offset); + pos = pos > pos2 ? pos : pos2; + + // Include the space on remove to avoid tag soup + if (pos !== -1 && !remove) { + pos++; + } + } else { + pos = str.indexOf(' ', offset); + pos2 = str.indexOf('\u00a0', offset); + pos = pos !== -1 && (pos2 === -1 || pos < pos2) ? pos : pos2; + } + + return pos; + }; + + if (container.nodeType === 3) { + pos = findSpace(container, offset); + + if (pos !== -1) { + return {container : container, offset : pos}; + } + + lastTextNode = container; + } + + // Walk the nodes inside the block + walker = new TreeWalker(container, dom.getParent(container, isBlock) || ed.getBody()); + while (node = walker[start ? 'prev' : 'next']()) { + if (node.nodeType === 3) { + lastTextNode = node; + pos = findSpace(node); + + if (pos !== -1) { + return {container : node, offset : pos}; + } + } else if (isBlock(node)) { + break; + } + } + + if (lastTextNode) { + if (start) { + offset = 0; + } else { + offset = lastTextNode.length; + } + + return {container: lastTextNode, offset: offset}; + } + }; + + function findSelectorEndPoint(container, sibling_name) { + var parents, i, y, curFormat; + + if (container.nodeType == 3 && container.nodeValue.length === 0 && container[sibling_name]) + container = container[sibling_name]; + + parents = getParents(container); + for (i = 0; i < parents.length; i++) { + for (y = 0; y < format.length; y++) { + curFormat = format[y]; + + // If collapsed state is set then skip formats that doesn't match that + if ("collapsed" in curFormat && curFormat.collapsed !== rng.collapsed) + continue; + + if (dom.is(parents[i], curFormat.selector)) + return parents[i]; + } + } + + return container; + }; + + function findBlockEndPoint(container, sibling_name, sibling_name2) { + var node; + + // Expand to block of similar type + if (!format[0].wrapper) + node = dom.getParent(container, format[0].block); + + // Expand to first wrappable block element or any block element + if (!node) + node = dom.getParent(container.nodeType == 3 ? container.parentNode : container, isTextBlock); + + // Exclude inner lists from wrapping + if (node && format[0].wrapper) + node = getParents(node, 'ul,ol').reverse()[0] || node; + + // Didn't find a block element look for first/last wrappable element + if (!node) { + node = container; + + while (node[sibling_name] && !isBlock(node[sibling_name])) { + node = node[sibling_name]; + + // Break on BR but include it will be removed later on + // we can't remove it now since we need to check if it can be wrapped + if (isEq(node, 'br')) + break; + } + } + + return node || container; + }; + + // Expand to closest contentEditable element + startContainer = findParentContentEditable(startContainer); + endContainer = findParentContentEditable(endContainer); + + // Exclude bookmark nodes if possible + if (isBookmarkNode(startContainer.parentNode) || isBookmarkNode(startContainer)) { + startContainer = isBookmarkNode(startContainer) ? startContainer : startContainer.parentNode; + startContainer = startContainer.nextSibling || startContainer; + + if (startContainer.nodeType == 3) + startOffset = 0; + } + + if (isBookmarkNode(endContainer.parentNode) || isBookmarkNode(endContainer)) { + endContainer = isBookmarkNode(endContainer) ? endContainer : endContainer.parentNode; + endContainer = endContainer.previousSibling || endContainer; + + if (endContainer.nodeType == 3) + endOffset = endContainer.length; + } + + if (format[0].inline) { + if (rng.collapsed) { + // Expand left to closest word boundery + endPoint = findWordEndPoint(startContainer, startOffset, true); + if (endPoint) { + startContainer = endPoint.container; + startOffset = endPoint.offset; + } + + // Expand right to closest word boundery + endPoint = findWordEndPoint(endContainer, endOffset); + if (endPoint) { + endContainer = endPoint.container; + endOffset = endPoint.offset; + } + } + + // Avoid applying formatting to a trailing space. + leaf = findLeaf(endContainer, endOffset); + if (leaf.node) { + while (leaf.node && leaf.offset === 0 && leaf.node.previousSibling) + leaf = findLeaf(leaf.node.previousSibling); + + if (leaf.node && leaf.offset > 0 && leaf.node.nodeType === 3 && + leaf.node.nodeValue.charAt(leaf.offset - 1) === ' ') { + + if (leaf.offset > 1) { + endContainer = leaf.node; + endContainer.splitText(leaf.offset - 1); + } + } + } + } + + // Move start/end point up the tree if the leaves are sharp and if we are in different containers + // Example * becomes !: !

    *texttext*

    ! + // This will reduce the number of wrapper elements that needs to be created + // Move start point up the tree + if (format[0].inline || format[0].block_expand) { + if (!format[0].inline || (startContainer.nodeType != 3 || startOffset === 0)) { + startContainer = findParentContainer(true); + } + + if (!format[0].inline || (endContainer.nodeType != 3 || endOffset === endContainer.nodeValue.length)) { + endContainer = findParentContainer(); + } + } + + // Expand start/end container to matching selector + if (format[0].selector && format[0].expand !== FALSE && !format[0].inline) { + // Find new startContainer/endContainer if there is better one + startContainer = findSelectorEndPoint(startContainer, 'previousSibling'); + endContainer = findSelectorEndPoint(endContainer, 'nextSibling'); + } + + // Expand start/end container to matching block element or text node + if (format[0].block || format[0].selector) { + // Find new startContainer/endContainer if there is better one + startContainer = findBlockEndPoint(startContainer, 'previousSibling'); + endContainer = findBlockEndPoint(endContainer, 'nextSibling'); + + // Non block element then try to expand up the leaf + if (format[0].block) { + if (!isBlock(startContainer)) + startContainer = findParentContainer(true); + + if (!isBlock(endContainer)) + endContainer = findParentContainer(); + } + } + + // Setup index for startContainer + if (startContainer.nodeType == 1) { + startOffset = nodeIndex(startContainer); + startContainer = startContainer.parentNode; + } + + // Setup index for endContainer + if (endContainer.nodeType == 1) { + endOffset = nodeIndex(endContainer) + 1; + endContainer = endContainer.parentNode; + } + + // Return new range like object + return { + startContainer : startContainer, + startOffset : startOffset, + endContainer : endContainer, + endOffset : endOffset + }; + } + + function removeFormat(format, vars, node, compare_node) { + var i, attrs, stylesModified; + + // Check if node matches format + if (!matchName(node, format)) + return FALSE; + + // Should we compare with format attribs and styles + if (format.remove != 'all') { + // Remove styles + each(format.styles, function(value, name) { + value = replaceVars(value, vars); + + // Indexed array + if (typeof(name) === 'number') { + name = value; + compare_node = 0; + } + + if (!compare_node || isEq(getStyle(compare_node, name), value)) + dom.setStyle(node, name, ''); + + stylesModified = 1; + }); + + // Remove style attribute if it's empty + if (stylesModified && dom.getAttrib(node, 'style') == '') { + node.removeAttribute('style'); + node.removeAttribute('data-mce-style'); + } + + // Remove attributes + each(format.attributes, function(value, name) { + var valueOut; + + value = replaceVars(value, vars); + + // Indexed array + if (typeof(name) === 'number') { + name = value; + compare_node = 0; + } + + if (!compare_node || isEq(dom.getAttrib(compare_node, name), value)) { + // Keep internal classes + if (name == 'class') { + value = dom.getAttrib(node, name); + if (value) { + // Build new class value where everything is removed except the internal prefixed classes + valueOut = ''; + each(value.split(/\s+/), function(cls) { + if (/mce\w+/.test(cls)) + valueOut += (valueOut ? ' ' : '') + cls; + }); + + // We got some internal classes left + if (valueOut) { + dom.setAttrib(node, name, valueOut); + return; + } + } + } + + // IE6 has a bug where the attribute doesn't get removed correctly + if (name == "class") + node.removeAttribute('className'); + + // Remove mce prefixed attributes + if (MCE_ATTR_RE.test(name)) + node.removeAttribute('data-mce-' + name); + + node.removeAttribute(name); + } + }); + + // Remove classes + each(format.classes, function(value) { + value = replaceVars(value, vars); + + if (!compare_node || dom.hasClass(compare_node, value)) + dom.removeClass(node, value); + }); + + // Check for non internal attributes + attrs = dom.getAttribs(node); + for (i = 0; i < attrs.length; i++) { + if (attrs[i].nodeName.indexOf('_') !== 0) + return FALSE; + } + } + + // Remove the inline child if it's empty for example or + if (format.remove != 'none') { + removeNode(node, format); + return TRUE; + } + }; + + function removeNode(node, format) { + var parentNode = node.parentNode, rootBlockElm; + + function find(node, next, inc) { + node = getNonWhiteSpaceSibling(node, next, inc); + + return !node || (node.nodeName == 'BR' || isBlock(node)); + }; + + if (format.block) { + if (!forcedRootBlock) { + // Append BR elements if needed before we remove the block + if (isBlock(node) && !isBlock(parentNode)) { + if (!find(node, FALSE) && !find(node.firstChild, TRUE, 1)) + node.insertBefore(dom.create('br'), node.firstChild); + + if (!find(node, TRUE) && !find(node.lastChild, FALSE, 1)) + node.appendChild(dom.create('br')); + } + } else { + // Wrap the block in a forcedRootBlock if we are at the root of document + if (parentNode == dom.getRoot()) { + if (!format.list_block || !isEq(node, format.list_block)) { + each(tinymce.grep(node.childNodes), function(node) { + if (isValid(forcedRootBlock, node.nodeName.toLowerCase())) { + if (!rootBlockElm) + rootBlockElm = wrap(node, forcedRootBlock); + else + rootBlockElm.appendChild(node); + } else + rootBlockElm = 0; + }); + } + } + } + } + + // Never remove nodes that isn't the specified inline element if a selector is specified too + if (format.selector && format.inline && !isEq(format.inline, node)) + return; + + dom.remove(node, 1); + }; + + function getNonWhiteSpaceSibling(node, next, inc) { + if (node) { + next = next ? 'nextSibling' : 'previousSibling'; + + for (node = inc ? node : node[next]; node; node = node[next]) { + if (node.nodeType == 1 || !isWhiteSpaceNode(node)) + return node; + } + } + }; + + function isBookmarkNode(node) { + return node && node.nodeType == 1 && node.getAttribute('data-mce-type') == 'bookmark'; + }; + + function mergeSiblings(prev, next) { + var marker, sibling, tmpSibling; + + function compareElements(node1, node2) { + // Not the same name + if (node1.nodeName != node2.nodeName) + return FALSE; + + function getAttribs(node) { + var attribs = {}; + + each(dom.getAttribs(node), function(attr) { + var name = attr.nodeName.toLowerCase(); + + // Don't compare internal attributes or style + if (name.indexOf('_') !== 0 && name !== 'style') + attribs[name] = dom.getAttrib(node, name); + }); + + return attribs; + }; + + function compareObjects(obj1, obj2) { + var value, name; + + for (name in obj1) { + // Obj1 has item obj2 doesn't have + if (obj1.hasOwnProperty(name)) { + value = obj2[name]; + + // Obj2 doesn't have obj1 item + if (value === undef) + return FALSE; + + // Obj2 item has a different value + if (obj1[name] != value) + return FALSE; + + // Delete similar value + delete obj2[name]; + } + } + + // Check if obj 2 has something obj 1 doesn't have + for (name in obj2) { + // Obj2 has item obj1 doesn't have + if (obj2.hasOwnProperty(name)) + return FALSE; + } + + return TRUE; + }; + + // Attribs are not the same + if (!compareObjects(getAttribs(node1), getAttribs(node2))) + return FALSE; + + // Styles are not the same + if (!compareObjects(dom.parseStyle(dom.getAttrib(node1, 'style')), dom.parseStyle(dom.getAttrib(node2, 'style')))) + return FALSE; + + return TRUE; + }; + + function findElementSibling(node, sibling_name) { + for (sibling = node; sibling; sibling = sibling[sibling_name]) { + if (sibling.nodeType == 3 && sibling.nodeValue.length !== 0) + return node; + + if (sibling.nodeType == 1 && !isBookmarkNode(sibling)) + return sibling; + } + + return node; + }; + + // Check if next/prev exists and that they are elements + if (prev && next) { + // If previous sibling is empty then jump over it + prev = findElementSibling(prev, 'previousSibling'); + next = findElementSibling(next, 'nextSibling'); + + // Compare next and previous nodes + if (compareElements(prev, next)) { + // Append nodes between + for (sibling = prev.nextSibling; sibling && sibling != next;) { + tmpSibling = sibling; + sibling = sibling.nextSibling; + prev.appendChild(tmpSibling); + } + + // Remove next node + dom.remove(next); + + // Move children into prev node + each(tinymce.grep(next.childNodes), function(node) { + prev.appendChild(node); + }); + + return prev; + } + } + + return next; + }; + + function getContainer(rng, start) { + var container, offset, lastIdx, walker; + + container = rng[start ? 'startContainer' : 'endContainer']; + offset = rng[start ? 'startOffset' : 'endOffset']; + + if (container.nodeType == 1) { + lastIdx = container.childNodes.length - 1; + + if (!start && offset) + offset--; + + container = container.childNodes[offset > lastIdx ? lastIdx : offset]; + } + + // If start text node is excluded then walk to the next node + if (container.nodeType === 3 && start && offset >= container.nodeValue.length) { + container = new TreeWalker(container, ed.getBody()).next() || container; + } + + // If end text node is excluded then walk to the previous node + if (container.nodeType === 3 && !start && offset === 0) { + container = new TreeWalker(container, ed.getBody()).prev() || container; + } + + return container; + }; + + function performCaretAction(type, name, vars) { + var caretContainerId = '_mce_caret', debug = ed.settings.caret_debug; + + // Creates a caret container bogus element + function createCaretContainer(fill) { + var caretContainer = dom.create('span', {id: caretContainerId, 'data-mce-bogus': true, style: debug ? 'color:red' : ''}); + + if (fill) { + caretContainer.appendChild(ed.getDoc().createTextNode(INVISIBLE_CHAR)); + } + + return caretContainer; + }; + + function isCaretContainerEmpty(node, nodes) { + while (node) { + if ((node.nodeType === 3 && node.nodeValue !== INVISIBLE_CHAR) || node.childNodes.length > 1) { + return false; + } + + // Collect nodes + if (nodes && node.nodeType === 1) { + nodes.push(node); + } + + node = node.firstChild; + } + + return true; + }; + + // Returns any parent caret container element + function getParentCaretContainer(node) { + while (node) { + if (node.id === caretContainerId) { + return node; + } + + node = node.parentNode; + } + }; + + // Finds the first text node in the specified node + function findFirstTextNode(node) { + var walker; + + if (node) { + walker = new TreeWalker(node, node); + + for (node = walker.current(); node; node = walker.next()) { + if (node.nodeType === 3) { + return node; + } + } + } + }; + + // Removes the caret container for the specified node or all on the current document + function removeCaretContainer(node, move_caret) { + var child, rng; + + if (!node) { + node = getParentCaretContainer(selection.getStart()); + + if (!node) { + while (node = dom.get(caretContainerId)) { + removeCaretContainer(node, false); + } + } + } else { + rng = selection.getRng(true); + + if (isCaretContainerEmpty(node)) { + if (move_caret !== false) { + rng.setStartBefore(node); + rng.setEndBefore(node); + } + + dom.remove(node); + } else { + child = findFirstTextNode(node); + + if (child.nodeValue.charAt(0) === INVISIBLE_CHAR) { + child = child.deleteData(0, 1); + } + + dom.remove(node, 1); + } + + selection.setRng(rng); + } + }; + + // Applies formatting to the caret postion + function applyCaretFormat() { + var rng, caretContainer, textNode, offset, bookmark, container, text; + + rng = selection.getRng(true); + offset = rng.startOffset; + container = rng.startContainer; + text = container.nodeValue; + + caretContainer = getParentCaretContainer(selection.getStart()); + if (caretContainer) { + textNode = findFirstTextNode(caretContainer); + } + + // Expand to word is caret is in the middle of a text node and the char before/after is a alpha numeric character + if (text && offset > 0 && offset < text.length && /\w/.test(text.charAt(offset)) && /\w/.test(text.charAt(offset - 1))) { + // Get bookmark of caret position + bookmark = selection.getBookmark(); + + // Collapse bookmark range (WebKit) + rng.collapse(true); + + // Expand the range to the closest word and split it at those points + rng = expandRng(rng, get(name)); + rng = rangeUtils.split(rng); + + // Apply the format to the range + apply(name, vars, rng); + + // Move selection back to caret position + selection.moveToBookmark(bookmark); + } else { + if (!caretContainer || textNode.nodeValue !== INVISIBLE_CHAR) { + caretContainer = createCaretContainer(true); + textNode = caretContainer.firstChild; + + rng.insertNode(caretContainer); + offset = 1; + + apply(name, vars, caretContainer); + } else { + apply(name, vars, caretContainer); + } + + // Move selection to text node + selection.setCursorLocation(textNode, offset); + } + }; + + function removeCaretFormat() { + var rng = selection.getRng(true), container, offset, bookmark, + hasContentAfter, node, formatNode, parents = [], i, caretContainer; + + container = rng.startContainer; + offset = rng.startOffset; + node = container; + + if (container.nodeType == 3) { + if (offset != container.nodeValue.length || container.nodeValue === INVISIBLE_CHAR) { + hasContentAfter = true; + } + + node = node.parentNode; + } + + while (node) { + if (matchNode(node, name, vars)) { + formatNode = node; + break; + } + + if (node.nextSibling) { + hasContentAfter = true; + } + + parents.push(node); + node = node.parentNode; + } + + // Node doesn't have the specified format + if (!formatNode) { + return; + } + + // Is there contents after the caret then remove the format on the element + if (hasContentAfter) { + // Get bookmark of caret position + bookmark = selection.getBookmark(); + + // Collapse bookmark range (WebKit) + rng.collapse(true); + + // Expand the range to the closest word and split it at those points + rng = expandRng(rng, get(name), true); + rng = rangeUtils.split(rng); + + // Remove the format from the range + remove(name, vars, rng); + + // Move selection back to caret position + selection.moveToBookmark(bookmark); + } else { + caretContainer = createCaretContainer(); + + node = caretContainer; + for (i = parents.length - 1; i >= 0; i--) { + node.appendChild(dom.clone(parents[i], false)); + node = node.firstChild; + } + + // Insert invisible character into inner most format element + node.appendChild(dom.doc.createTextNode(INVISIBLE_CHAR)); + node = node.firstChild; + + var block = dom.getParent(formatNode, isTextBlock); + + if (block && dom.isEmpty(block)) { + // Replace formatNode with caretContainer when removing format from empty block like

    |

    + formatNode.parentNode.replaceChild(caretContainer, formatNode); + } else { + // Insert caret container after the formated node + dom.insertAfter(caretContainer, formatNode); + } + + // Move selection to text node + selection.setCursorLocation(node, 1); + + // If the formatNode is empty, we can remove it safely. + if (dom.isEmpty(formatNode)) { + dom.remove(formatNode); + } + } + }; + + // Checks if the parent caret container node isn't empty if that is the case it + // will remove the bogus state on all children that isn't empty + function unmarkBogusCaretParents() { + var i, caretContainer, node; + + caretContainer = getParentCaretContainer(selection.getStart()); + if (caretContainer && !dom.isEmpty(caretContainer)) { + tinymce.walk(caretContainer, function(node) { + if (node.nodeType == 1 && node.id !== caretContainerId && !dom.isEmpty(node)) { + dom.setAttrib(node, 'data-mce-bogus', null); + } + }, 'childNodes'); + } + }; + + // Only bind the caret events once + if (!self._hasCaretEvents) { + // Mark current caret container elements as bogus when getting the contents so we don't end up with empty elements + ed.onBeforeGetContent.addToTop(function() { + var nodes = [], i; + + if (isCaretContainerEmpty(getParentCaretContainer(selection.getStart()), nodes)) { + // Mark children + i = nodes.length; + while (i--) { + dom.setAttrib(nodes[i], 'data-mce-bogus', '1'); + } + } + }); + + // Remove caret container on mouse up and on key up + tinymce.each('onMouseUp onKeyUp'.split(' '), function(name) { + ed[name].addToTop(function() { + removeCaretContainer(); + unmarkBogusCaretParents(); + }); + }); + + // Remove caret container on keydown and it's a backspace, enter or left/right arrow keys + ed.onKeyDown.addToTop(function(ed, e) { + var keyCode = e.keyCode; + + if (keyCode == 8 || keyCode == 37 || keyCode == 39) { + removeCaretContainer(getParentCaretContainer(selection.getStart())); + } + + unmarkBogusCaretParents(); + }); + + // Remove bogus state if they got filled by contents using editor.selection.setContent + selection.onSetContent.add(unmarkBogusCaretParents); + + self._hasCaretEvents = true; + } + + // Do apply or remove caret format + if (type == "apply") { + applyCaretFormat(); + } else { + removeCaretFormat(); + } + }; + + function moveStart(rng) { + var container = rng.startContainer, + offset = rng.startOffset, isAtEndOfText, + walker, node, nodes, tmpNode; + + // Convert text node into index if possible + if (container.nodeType == 3 && offset >= container.nodeValue.length) { + // Get the parent container location and walk from there + offset = nodeIndex(container); + container = container.parentNode; + isAtEndOfText = true; + } + + // Move startContainer/startOffset in to a suitable node + if (container.nodeType == 1) { + nodes = container.childNodes; + container = nodes[Math.min(offset, nodes.length - 1)]; + walker = new TreeWalker(container, dom.getParent(container, dom.isBlock)); + + // If offset is at end of the parent node walk to the next one + if (offset > nodes.length - 1 || isAtEndOfText) + walker.next(); + + for (node = walker.current(); node; node = walker.next()) { + if (node.nodeType == 3 && !isWhiteSpaceNode(node)) { + // IE has a "neat" feature where it moves the start node into the closest element + // we can avoid this by inserting an element before it and then remove it after we set the selection + tmpNode = dom.create('a', null, INVISIBLE_CHAR); + node.parentNode.insertBefore(tmpNode, node); + + // Set selection and remove tmpNode + rng.setStart(node, 0); + selection.setRng(rng); + dom.remove(tmpNode); + + return; + } + } + } + }; + }; +})(tinymce); + +tinymce.onAddEditor.add(function(tinymce, ed) { + var filters, fontSizes, dom, settings = ed.settings; + + function replaceWithSpan(node, styles) { + tinymce.each(styles, function(value, name) { + if (value) + dom.setStyle(node, name, value); + }); + + dom.rename(node, 'span'); + }; + + function convert(editor, params) { + dom = editor.dom; + + if (settings.convert_fonts_to_spans) { + tinymce.each(dom.select('font,u,strike', params.node), function(node) { + filters[node.nodeName.toLowerCase()](ed.dom, node); + }); + } + }; + + if (settings.inline_styles) { + fontSizes = tinymce.explode(settings.font_size_legacy_values); + + filters = { + font : function(dom, node) { + replaceWithSpan(node, { + backgroundColor : node.style.backgroundColor, + color : node.color, + fontFamily : node.face, + fontSize : fontSizes[parseInt(node.size, 10) - 1] + }); + }, + + u : function(dom, node) { + replaceWithSpan(node, { + textDecoration : 'underline' + }); + }, + + strike : function(dom, node) { + replaceWithSpan(node, { + textDecoration : 'line-through' + }); + } + }; + + ed.onPreProcess.add(convert); + ed.onSetContent.add(convert); + + ed.onInit.add(function() { + ed.selection.onSetContent.add(convert); + }); + } +}); + +(function(tinymce) { + var TreeWalker = tinymce.dom.TreeWalker; + + tinymce.EnterKey = function(editor) { + var dom = editor.dom, selection = editor.selection, settings = editor.settings, undoManager = editor.undoManager, nonEmptyElementsMap = editor.schema.getNonEmptyElements(); + + function handleEnterKey(evt) { + var rng = selection.getRng(true), tmpRng, editableRoot, container, offset, parentBlock, documentMode, shiftKey, + newBlock, fragment, containerBlock, parentBlockName, containerBlockName, newBlockName, isAfterLastNodeInContainer; + + // Returns true if the block can be split into two blocks or not + function canSplitBlock(node) { + return node && + dom.isBlock(node) && + !/^(TD|TH|CAPTION|FORM)$/.test(node.nodeName) && + !/^(fixed|absolute)/i.test(node.style.position) && + dom.getContentEditable(node) !== "true"; + }; + + // Renders empty block on IE + function renderBlockOnIE(block) { + var oldRng; + + if (tinymce.isIE && !tinymce.isIE11 && dom.isBlock(block)) { + oldRng = selection.getRng(); + block.appendChild(dom.create('span', null, '\u00a0')); + selection.select(block); + block.lastChild.outerHTML = ''; + selection.setRng(oldRng); + } + }; + + // Remove the first empty inline element of the block so this:

    x

    becomes this:

    x

    + function trimInlineElementsOnLeftSideOfBlock(block) { + var node = block, firstChilds = [], i; + + // Find inner most first child ex:

    *

    + while (node = node.firstChild) { + if (dom.isBlock(node)) { + return; + } + + if (node.nodeType == 1 && !nonEmptyElementsMap[node.nodeName.toLowerCase()]) { + firstChilds.push(node); + } + } + + i = firstChilds.length; + while (i--) { + node = firstChilds[i]; + if (!node.hasChildNodes() || (node.firstChild == node.lastChild && node.firstChild.nodeValue === '')) { + dom.remove(node); + } else { + // Remove see #5381 + if (node.nodeName == "A" && (node.innerText || node.textContent) === ' ') { + dom.remove(node); + } + } + } + }; + + // Moves the caret to a suitable position within the root for example in the first non pure whitespace text node or before an image + function moveToCaretPosition(root) { + var walker, node, rng, y, viewPort, lastNode = root, tempElm; + + rng = dom.createRng(); + + if (root.hasChildNodes()) { + walker = new TreeWalker(root, root); + + while (node = walker.current()) { + if (node.nodeType == 3) { + rng.setStart(node, 0); + rng.setEnd(node, 0); + break; + } + + if (nonEmptyElementsMap[node.nodeName.toLowerCase()]) { + rng.setStartBefore(node); + rng.setEndBefore(node); + break; + } + + lastNode = node; + node = walker.next(); + } + + if (!node) { + rng.setStart(lastNode, 0); + rng.setEnd(lastNode, 0); + } + } else { + if (root.nodeName == 'BR') { + if (root.nextSibling && dom.isBlock(root.nextSibling)) { + // Trick on older IE versions to render the caret before the BR between two lists + if (!documentMode || documentMode < 9) { + tempElm = dom.create('br'); + root.parentNode.insertBefore(tempElm, root); + } + + rng.setStartBefore(root); + rng.setEndBefore(root); + } else { + rng.setStartAfter(root); + rng.setEndAfter(root); + } + } else { + rng.setStart(root, 0); + rng.setEnd(root, 0); + } + } + + selection.setRng(rng); + + // Remove tempElm created for old IE:s + dom.remove(tempElm); + + viewPort = dom.getViewPort(editor.getWin()); + + // scrollIntoView seems to scroll the parent window in most browsers now including FF 3.0b4 so it's time to stop using it and do it our selfs + y = dom.getPos(root).y; + if (y < viewPort.y || y + 25 > viewPort.y + viewPort.h) { + editor.getWin().scrollTo(0, y < viewPort.y ? y : y - viewPort.h + 25); // Needs to be hardcoded to roughly one line of text if a huge text block is broken into two blocks + } + }; + + // Creates a new block element by cloning the current one or creating a new one if the name is specified + // This function will also copy any text formatting from the parent block and add it to the new one + function createNewBlock(name) { + var node = container, block, clonedNode, caretNode; + + block = name || parentBlockName == "TABLE" ? dom.create(name || newBlockName) : parentBlock.cloneNode(false); + caretNode = block; + + // Clone any parent styles + if (settings.keep_styles !== false) { + do { + if (/^(SPAN|STRONG|B|EM|I|FONT|STRIKE|U)$/.test(node.nodeName)) { + // Never clone a caret containers + if (node.id == '_mce_caret') { + continue; + } + + clonedNode = node.cloneNode(false); + dom.setAttrib(clonedNode, 'id', ''); // Remove ID since it needs to be document unique + + if (block.hasChildNodes()) { + clonedNode.appendChild(block.firstChild); + block.appendChild(clonedNode); + } else { + caretNode = clonedNode; + block.appendChild(clonedNode); + } + } + } while (node = node.parentNode); + } + + // BR is needed in empty blocks on non IE browsers + if (!tinymce.isIE || tinymce.isIE11) { + caretNode.innerHTML = '
    '; + } + + return block; + }; + + // Returns true/false if the caret is at the start/end of the parent block element + function isCaretAtStartOrEndOfBlock(start) { + var walker, node, name; + + // Caret is in the middle of a text node like "a|b" + if (container.nodeType == 3 && (start ? offset > 0 : offset < container.nodeValue.length)) { + return false; + } + + // If after the last element in block node edge case for #5091 + if (container.parentNode == parentBlock && isAfterLastNodeInContainer && !start) { + return true; + } + + // If the caret if before the first element in parentBlock + if (start && container.nodeType == 1 && container == parentBlock.firstChild) { + return true; + } + + // Caret can be before/after a table + if (container.nodeName === "TABLE" || (container.previousSibling && container.previousSibling.nodeName == "TABLE")) { + return (isAfterLastNodeInContainer && !start) || (!isAfterLastNodeInContainer && start); + } + + // Walk the DOM and look for text nodes or non empty elements + walker = new TreeWalker(container, parentBlock); + + // If caret is in beginning or end of a text block then jump to the next/previous node + if (container.nodeType == 3) { + if (start && offset == 0) { + walker.prev(); + } else if (!start && offset == container.nodeValue.length) { + walker.next(); + } + } + + while (node = walker.current()) { + if (node.nodeType === 1) { + // Ignore bogus elements + if (!node.getAttribute('data-mce-bogus')) { + // Keep empty elements like but not trailing br:s like

    text|

    + name = node.nodeName.toLowerCase(); + if (nonEmptyElementsMap[name] && name !== 'br') { + return false; + } + } + } else if (node.nodeType === 3 && !/^[ \t\r\n]*$/.test(node.nodeValue)) { + return false; + } + + if (start) { + walker.prev(); + } else { + walker.next(); + } + } + + return true; + }; + + // Wraps any text nodes or inline elements in the specified forced root block name + function wrapSelfAndSiblingsInDefaultBlock(container, offset) { + var newBlock, parentBlock, startNode, node, next, blockName = newBlockName || 'P'; + + // Not in a block element or in a table cell or caption + parentBlock = dom.getParent(container, dom.isBlock); + if (!parentBlock || !canSplitBlock(parentBlock)) { + parentBlock = parentBlock || editableRoot; + + if (!parentBlock.hasChildNodes()) { + newBlock = dom.create(blockName); + parentBlock.appendChild(newBlock); + rng.setStart(newBlock, 0); + rng.setEnd(newBlock, 0); + return newBlock; + } + + // Find parent that is the first child of parentBlock + node = container; + while (node.parentNode != parentBlock) { + node = node.parentNode; + } + + // Loop left to find start node start wrapping at + while (node && !dom.isBlock(node)) { + startNode = node; + node = node.previousSibling; + } + + if (startNode) { + newBlock = dom.create(blockName); + startNode.parentNode.insertBefore(newBlock, startNode); + + // Start wrapping until we hit a block + node = startNode; + while (node && !dom.isBlock(node)) { + next = node.nextSibling; + newBlock.appendChild(node); + node = next; + } + + // Restore range to it's past location + rng.setStart(container, offset); + rng.setEnd(container, offset); + } + } + + return container; + }; + + // Inserts a block or br before/after or in the middle of a split list of the LI is empty + function handleEmptyListItem() { + function isFirstOrLastLi(first) { + var node = containerBlock[first ? 'firstChild' : 'lastChild']; + + // Find first/last element since there might be whitespace there + while (node) { + if (node.nodeType == 1) { + break; + } + + node = node[first ? 'nextSibling' : 'previousSibling']; + } + + return node === parentBlock; + }; + + newBlock = newBlockName ? createNewBlock(newBlockName) : dom.create('BR'); + + if (isFirstOrLastLi(true) && isFirstOrLastLi()) { + // Is first and last list item then replace the OL/UL with a text block + dom.replace(newBlock, containerBlock); + } else if (isFirstOrLastLi(true)) { + // First LI in list then remove LI and add text block before list + containerBlock.parentNode.insertBefore(newBlock, containerBlock); + } else if (isFirstOrLastLi()) { + // Last LI in list then temove LI and add text block after list + dom.insertAfter(newBlock, containerBlock); + renderBlockOnIE(newBlock); + } else { + // Middle LI in list the split the list and insert a text block in the middle + // Extract after fragment and insert it after the current block + tmpRng = rng.cloneRange(); + tmpRng.setStartAfter(parentBlock); + tmpRng.setEndAfter(containerBlock); + fragment = tmpRng.extractContents(); + dom.insertAfter(fragment, containerBlock); + dom.insertAfter(newBlock, containerBlock); + } + + dom.remove(parentBlock); + moveToCaretPosition(newBlock); + undoManager.add(); + }; + + // Walks the parent block to the right and look for any contents + function hasRightSideContent() { + var walker = new TreeWalker(container, parentBlock), node; + + while (node = walker.next()) { + if (nonEmptyElementsMap[node.nodeName.toLowerCase()] || node.length > 0) { + return true; + } + } + } + + // Inserts a BR element if the forced_root_block option is set to false or empty string + function insertBr() { + var brElm, extraBr, marker; + + if (container && container.nodeType == 3 && offset >= container.nodeValue.length) { + // Insert extra BR element at the end block elements + if ((!tinymce.isIE || tinymce.isIE11) && !hasRightSideContent()) { + brElm = dom.create('br'); + rng.insertNode(brElm); + rng.setStartAfter(brElm); + rng.setEndAfter(brElm); + extraBr = true; + } + } + + brElm = dom.create('br'); + rng.insertNode(brElm); + + // Rendering modes below IE8 doesn't display BR elements in PRE unless we have a \n before it + if ((tinymce.isIE && !tinymce.isIE11) && parentBlockName == 'PRE' && (!documentMode || documentMode < 8)) { + brElm.parentNode.insertBefore(dom.doc.createTextNode('\r'), brElm); + } + + // Insert temp marker and scroll to that + marker = dom.create('span', {}, ' '); + brElm.parentNode.insertBefore(marker, brElm); + selection.scrollIntoView(marker); + dom.remove(marker); + + if (!extraBr) { + rng.setStartAfter(brElm); + rng.setEndAfter(brElm); + } else { + rng.setStartBefore(brElm); + rng.setEndBefore(brElm); + } + + selection.setRng(rng); + undoManager.add(); + }; + + // Trims any linebreaks at the beginning of node user for example when pressing enter in a PRE element + function trimLeadingLineBreaks(node) { + do { + if (node.nodeType === 3) { + node.nodeValue = node.nodeValue.replace(/^[\r\n]+/, ''); + } + + node = node.firstChild; + } while (node); + }; + + function getEditableRoot(node) { + var root = dom.getRoot(), parent, editableRoot; + + // Get all parents until we hit a non editable parent or the root + parent = node; + while (parent !== root && dom.getContentEditable(parent) !== "false") { + if (dom.getContentEditable(parent) === "true") { + editableRoot = parent; + } + + parent = parent.parentNode; + } + + return parent !== root ? editableRoot : root; + }; + + // Adds a BR at the end of blocks that only contains an IMG or INPUT since these might be floated and then they won't expand the block + function addBrToBlockIfNeeded(block) { + var lastChild; + + // IE will render the blocks correctly other browsers needs a BR + if (!tinymce.isIE || tinymce.isIE11) { + block.normalize(); // Remove empty text nodes that got left behind by the extract + + // Check if the block is empty or contains a floated last child + lastChild = block.lastChild; + if (!lastChild || (/^(left|right)$/gi.test(dom.getStyle(lastChild, 'float', true)))) { + dom.add(block, 'br'); + } + } + }; + + // Delete any selected contents + if (!rng.collapsed) { + editor.execCommand('Delete'); + return; + } + + // Event is blocked by some other handler for example the lists plugin + if (evt.isDefaultPrevented()) { + return; + } + + // Setup range items and newBlockName + container = rng.startContainer; + offset = rng.startOffset; + newBlockName = (settings.force_p_newlines ? 'p' : '') || settings.forced_root_block; + newBlockName = newBlockName ? newBlockName.toUpperCase() : ''; + documentMode = dom.doc.documentMode; + shiftKey = evt.shiftKey; + + // Resolve node index + if (container.nodeType == 1 && container.hasChildNodes()) { + isAfterLastNodeInContainer = offset > container.childNodes.length - 1; + container = container.childNodes[Math.min(offset, container.childNodes.length - 1)] || container; + if (isAfterLastNodeInContainer && container.nodeType == 3) { + offset = container.nodeValue.length; + } else { + offset = 0; + } + } + + // Get editable root node normaly the body element but sometimes a div or span + editableRoot = getEditableRoot(container); + + // If there is no editable root then enter is done inside a contentEditable false element + if (!editableRoot) { + return; + } + + undoManager.beforeChange(); + + // If editable root isn't block nor the root of the editor + if (!dom.isBlock(editableRoot) && editableRoot != dom.getRoot()) { + if (!newBlockName || shiftKey) { + insertBr(); + } + + return; + } + + // Wrap the current node and it's sibling in a default block if it's needed. + // for example this text|text2 will become this

    text|text2

    + // This won't happen if root blocks are disabled or the shiftKey is pressed + if ((newBlockName && !shiftKey) || (!newBlockName && shiftKey)) { + container = wrapSelfAndSiblingsInDefaultBlock(container, offset); + } + + // Find parent block and setup empty block paddings + parentBlock = dom.getParent(container, dom.isBlock); + containerBlock = parentBlock ? dom.getParent(parentBlock.parentNode, dom.isBlock) : null; + + // Setup block names + parentBlockName = parentBlock ? parentBlock.nodeName.toUpperCase() : ''; // IE < 9 & HTML5 + containerBlockName = containerBlock ? containerBlock.nodeName.toUpperCase() : ''; // IE < 9 & HTML5 + + // Enter inside block contained within a LI then split or insert before/after LI + if (containerBlockName == 'LI' && !evt.ctrlKey) { + parentBlock = containerBlock; + parentBlockName = containerBlockName; + } + + // Handle enter in LI + if (parentBlockName == 'LI') { + if (!newBlockName && shiftKey) { + insertBr(); + return; + } + + // Handle enter inside an empty list item + if (dom.isEmpty(parentBlock)) { + // Let the list plugin or browser handle nested lists for now + if (/^(UL|OL|LI)$/.test(containerBlock.parentNode.nodeName)) { + return false; + } + + handleEmptyListItem(); + return; + } + } + + // Don't split PRE tags but insert a BR instead easier when writing code samples etc + if (parentBlockName == 'PRE' && settings.br_in_pre !== false) { + if (!shiftKey) { + insertBr(); + return; + } + } else { + // If no root block is configured then insert a BR by default or if the shiftKey is pressed + if ((!newBlockName && !shiftKey && parentBlockName != 'LI') || (newBlockName && shiftKey)) { + insertBr(); + return; + } + } + + // Default block name if it's not configured + newBlockName = newBlockName || 'P'; + + // Insert new block before/after the parent block depending on caret location + if (isCaretAtStartOrEndOfBlock()) { + // If the caret is at the end of a header we produce a P tag after it similar to Word unless we are in a hgroup + if (/^(H[1-6]|PRE)$/.test(parentBlockName) && containerBlockName != 'HGROUP') { + newBlock = createNewBlock(newBlockName); + } else { + newBlock = createNewBlock(); + } + + // Split the current container block element if enter is pressed inside an empty inner block element + if (settings.end_container_on_empty_block && canSplitBlock(containerBlock) && dom.isEmpty(parentBlock)) { + // Split container block for example a BLOCKQUOTE at the current blockParent location for example a P + newBlock = dom.split(containerBlock, parentBlock); + } else { + dom.insertAfter(newBlock, parentBlock); + } + + moveToCaretPosition(newBlock); + } else if (isCaretAtStartOrEndOfBlock(true)) { + // Insert new block before + newBlock = parentBlock.parentNode.insertBefore(createNewBlock(), parentBlock); + renderBlockOnIE(newBlock); + } else { + // Extract after fragment and insert it after the current block + tmpRng = rng.cloneRange(); + tmpRng.setEndAfter(parentBlock); + fragment = tmpRng.extractContents(); + trimLeadingLineBreaks(fragment); + newBlock = fragment.firstChild; + dom.insertAfter(fragment, parentBlock); + trimInlineElementsOnLeftSideOfBlock(newBlock); + addBrToBlockIfNeeded(parentBlock); + moveToCaretPosition(newBlock); + } + + dom.setAttrib(newBlock, 'id', ''); // Remove ID since it needs to be document unique + undoManager.add(); + } + + editor.onKeyDown.add(function(ed, evt) { + if (evt.keyCode == 13) { + if (handleEnterKey(evt) !== false) { + evt.preventDefault(); + } + } + }); + }; +})(tinymce); +