| | |
| | |
|
| | | var tinymce = {
|
| | | majorVersion : '3',
|
| | | minorVersion : '0.6.2',
|
| | | releaseDate : '2008-04-07',
|
| | | minorVersion : '1.0.1',
|
| | | releaseDate : '2008-06-18',
|
| | |
|
| | | _init : function() {
|
| | | var t = this, ua = navigator.userAgent, i, nl, n, base;
|
| | | var t = this, d = document, w = window, na = navigator, ua = na.userAgent, i, nl, n, base, p, v;
|
| | |
|
| | | // Browser checks
|
| | | t.isOpera = window.opera && opera.buildNumber;
|
| | | t.isOpera = w.opera && opera.buildNumber;
|
| | | t.isWebKit = /WebKit/.test(ua);
|
| | | t.isOldWebKit = t.isWebKit && !window.getSelection().getRangeAt;
|
| | | t.isIE = !t.isWebKit && !t.isOpera && (/MSIE/gi).test(ua) && (/Explorer/gi).test(navigator.appName);
|
| | | t.isOldWebKit = t.isWebKit && !w.getSelection().getRangeAt;
|
| | | t.isIE = !t.isWebKit && !t.isOpera && (/MSIE/gi).test(ua) && (/Explorer/gi).test(na.appName);
|
| | | t.isIE6 = t.isIE && /MSIE [56]/.test(ua);
|
| | | t.isGecko = !t.isWebKit && /Gecko/.test(ua);
|
| | | t.isMac = ua.indexOf('Mac') != -1;
|
| | |
|
| | | // TinyMCE .NET webcontrol might be setting the values for TinyMCE
|
| | | if (window.tinyMCEPreInit) {
|
| | | if (w.tinyMCEPreInit) {
|
| | | t.suffix = tinyMCEPreInit.suffix;
|
| | | t.baseURL = tinyMCEPreInit.base;
|
| | | t.query = tinyMCEPreInit.query;
|
| | | return;
|
| | | }
|
| | |
|
| | |
| | | t.suffix = '';
|
| | |
|
| | | // If base element found, add that infront of baseURL
|
| | | nl = document.getElementsByTagName('base');
|
| | | nl = d.getElementsByTagName('base');
|
| | | for (i=0; i<nl.length; i++) {
|
| | | if (nl[i].href)
|
| | | base = nl[i].href;
|
| | | if (v = nl[i].href) {
|
| | | // Host only value like http://site.com or http://site.com:8008
|
| | | if (/^https?:\/\/[^\/]+$/.test(v))
|
| | | v += '/';
|
| | |
|
| | | base = v ? v.match(/.*\//)[0] : ''; // Get only directory
|
| | | }
|
| | | }
|
| | |
|
| | | function getBase(n) {
|
| | | if (n.src && /tiny_mce(|_dev|_src|_gzip|_jquery|_prototype).js/.test(n.src)) {
|
| | | if (/_(src|dev)\.js/g.test(n.src))
|
| | | t.suffix = '_src';
|
| | |
|
| | | if ((p = n.src.indexOf('?')) != -1)
|
| | | t.query = n.src.substring(p + 1);
|
| | |
|
| | | t.baseURL = n.src.substring(0, n.src.lastIndexOf('/'));
|
| | |
|
| | |
| | | };
|
| | |
|
| | | // Check document
|
| | | nl = document.getElementsByTagName('script');
|
| | | nl = d.getElementsByTagName('script');
|
| | | for (i=0; i<nl.length; i++) {
|
| | | if (getBase(nl[i]))
|
| | | return;
|
| | | }
|
| | |
|
| | | // Check head
|
| | | n = document.getElementsByTagName('head')[0];
|
| | | n = d.getElementsByTagName('head')[0];
|
| | | if (n) {
|
| | | nl = n.getElementsByTagName('script');
|
| | | for (i=0; i<nl.length; i++) {
|
| | |
| | | },
|
| | |
|
| | | addUnload : function(f, s) {
|
| | | var t = this, w = window, unload;
|
| | | var t = this, w = window;
|
| | |
|
| | | f = {func : f, scope : s || this};
|
| | |
|
| | | if (!t.unloads) {
|
| | | unload = function() {
|
| | | function unload() {
|
| | | var li = t.unloads, o, n;
|
| | |
|
| | | // Call unload handlers
|
| | | for (n in li) {
|
| | | o = li[n];
|
| | | if (li) {
|
| | | // Call unload handlers
|
| | | for (n in li) {
|
| | | o = li[n];
|
| | |
|
| | | if (o && o.func)
|
| | | o.func.call(o.scope, 1); // Send in one arg to distinct unload and user destroy
|
| | | if (o && o.func)
|
| | | o.func.call(o.scope, 1); // Send in one arg to distinct unload and user destroy
|
| | | }
|
| | |
|
| | | // Detach unload function
|
| | | if (w.detachEvent) {
|
| | | w.detachEvent('onbeforeunload', fakeUnload);
|
| | | w.detachEvent('onunload', unload);
|
| | | } else if (w.removeEventListener)
|
| | | w.removeEventListener('unload', unload, false);
|
| | |
|
| | | // Destroy references
|
| | | t.unloads = o = li = w = unload = null;
|
| | |
|
| | | // Run garbarge collector on IE
|
| | | if (window.CollectGarbage)
|
| | | window.CollectGarbage();
|
| | | }
|
| | | };
|
| | |
|
| | | // Detach unload function
|
| | | if (w.detachEvent)
|
| | | w.detachEvent('onunload', unload);
|
| | | else if (w.removeEventListener)
|
| | | w.removeEventListener('unload', unload, false);
|
| | | function fakeUnload() {
|
| | | var d = document;
|
| | |
|
| | | // Destroy references
|
| | | o = li = w = unload = null;
|
| | | // Is there things still loading, then do some magic
|
| | | if (d.readyState == 'interactive') {
|
| | | function stop() {
|
| | | // Prevent memory leak
|
| | | d.detachEvent('onstop', stop);
|
| | |
|
| | | // Run garbarge collector on IE
|
| | | if (window.CollectGarbage)
|
| | | window.CollectGarbage();
|
| | | // Call unload handler
|
| | | unload();
|
| | |
|
| | | d = null;
|
| | | };
|
| | |
|
| | | // Fire unload when the currently loading page is stopped
|
| | | d.attachEvent('onstop', stop);
|
| | |
|
| | | // Remove onstop listener after a while to prevent the unload function
|
| | | // to execute if the user presses cancel in an onbeforeunload
|
| | | // confirm dialog and then presses the browser stop button
|
| | | window.setTimeout(function() {
|
| | | d.detachEvent('onstop', stop);
|
| | | }, 0);
|
| | | }
|
| | | };
|
| | |
|
| | | // Attach unload handler
|
| | | if (w.attachEvent)
|
| | | if (w.attachEvent) {
|
| | | w.attachEvent('onunload', unload);
|
| | | else if (w.addEventListener)
|
| | | w.attachEvent('onbeforeunload', fakeUnload);
|
| | | } else if (w.addEventListener)
|
| | | w.addEventListener('unload', unload, false);
|
| | |
|
| | | // Setup initial unload handler array
|
| | |
| | | },
|
| | |
|
| | | explode : function(s, d) {
|
| | | return tinymce.map(s.split(d || ','), tinymce.trim);
|
| | | return s ? tinymce.map(s.split(d || ','), tinymce.trim) : s;
|
| | | },
|
| | |
|
| | | _addVer : function(u) {
|
| | | var v;
|
| | |
|
| | | if (!this.query)
|
| | | return u;
|
| | |
|
| | | v = (u.indexOf('?') == -1 ? '?' : '&') + this.query;
|
| | |
|
| | | if (u.indexOf('#') == -1)
|
| | | return u + v;
|
| | |
|
| | | return u.replace('#', v + '#');
|
| | | }
|
| | |
|
| | | };
|
| | |
| | |
|
| | | x.send(o.data);
|
| | |
|
| | | // Wait for response, onReadyStateChange can not be used since it leaks memory in IE
|
| | | t = w.setInterval(function() {
|
| | | if (x.readyState == 4 || c++ > 10000) {
|
| | | w.clearInterval(t);
|
| | |
|
| | | 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;
|
| | | }
|
| | | }, 10);
|
| | | } else
|
| | | w.setTimeout(ready, 10);
|
| | | };
|
| | |
|
| | | // 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);
|
| | | }
|
| | |
|
| | | }
|
| | |
| | | }
|
| | |
|
| | | each(na.split(','), function(v) {
|
| | | if (n.nodeType == 1 && ((se.strict && n.nodeName.toUpperCase() == v) || n.nodeName == v)) {
|
| | | if (n.nodeType == 1 && ((se.strict && n.nodeName.toUpperCase() == v) || n.nodeName.toUpperCase() == v)) {
|
| | | s = true;
|
| | | return false; // Break loop
|
| | | }
|
| | |
| | | get : function(e) {
|
| | | var n;
|
| | |
|
| | | if (this.doc && typeof(e) == 'string') {
|
| | | if (e && this.doc && typeof(e) == 'string') {
|
| | | n = e;
|
| | | e = this.doc.getElementById(e);
|
| | |
|
| | |
| | |
|
| | | switch (n) {
|
| | | case "style":
|
| | | // No mce_style for elements with these since they might get resized by the user
|
| | | if (s.keep_values) {
|
| | | if (v)
|
| | | if (v && !t._isRes(v))
|
| | | e.setAttribute('mce_style', v, 2);
|
| | | else
|
| | | e.removeAttribute('mce_style', 2);
|
| | |
| | | t.setAttrib(e, 'mce_' + n, v, 2);
|
| | | }
|
| | |
|
| | | break;
|
| | | |
| | | case "shape":
|
| | | e.setAttribute('mce_style', v);
|
| | | break;
|
| | | }
|
| | |
|
| | |
| | |
|
| | | e = t.get(e);
|
| | |
|
| | | if (!e)
|
| | | if (!e || e.nodeType !== 1)
|
| | | return false;
|
| | |
|
| | | if (!is(dv))
|
| | | dv = "";
|
| | |
|
| | | // Try the mce variant for these
|
| | | if (/^(src|href|style|coords)$/.test(n)) {
|
| | | if (/^(src|href|style|coords|shape)$/.test(n)) {
|
| | | v = e.getAttribute("mce_" + n);
|
| | |
|
| | | if (v)
|
| | |
| | | if (v) {
|
| | | v = t.serializeStyle(t.parseStyle(v));
|
| | |
|
| | | if (t.settings.keep_values)
|
| | | if (t.settings.keep_values && !t._isRes(v))
|
| | | e.setAttribute('mce_style', v);
|
| | | }
|
| | |
|
| | |
| | | break;
|
| | |
|
| | | case 'tabindex':
|
| | | // IE returns 32768 as default value
|
| | | // IE returns default value
|
| | | if (v === 32768)
|
| | | v = '';
|
| | |
|
| | | break;
|
| | |
|
| | | case 'maxlength':
|
| | | // IE returns default value
|
| | | if (v === 2147483647)
|
| | | v = '';
|
| | |
|
| | | break;
|
| | |
| | | delete o[c];
|
| | | };
|
| | |
|
| | | st = st.replace(/&(#?[a-z0-9]+);/g, '&$1_MCE_SEMI_'); // Protect entities
|
| | |
|
| | | each(st.split(';'), function(v) {
|
| | | var sv, ur = [];
|
| | |
|
| | | if (v) {
|
| | | v = v.replace(/_MCE_SEMI_/g, ';'); // Restore entities
|
| | | v = v.replace(/url\([^\)]+\)/g, function(v) {ur.push(v);return 'url(' + ur.length + ')';});
|
| | | v = v.split(':');
|
| | | sv = tinymce.trim(v[1]);
|
| | |
| | |
|
| | | if (s.url_converter) {
|
| | | sv = sv.replace(/url\([\'\"]?([^\)\'\"]+)[\'\"]?\)/g, function(x, c) {
|
| | | return 'url(' + t.encode(s.url_converter.call(s.url_converter_scope || t, t.decode(c), 'style', null)) + ')';
|
| | | return 'url(' + s.url_converter.call(s.url_converter_scope || t, t.decode(c), 'style', null) + ')';
|
| | | });
|
| | | }
|
| | |
|
| | |
| | |
|
| | | each(o, function(v, k) {
|
| | | if (k && v) {
|
| | | if (tinymce.isGecko && k.indexOf('-moz-') === 0)
|
| | | return;
|
| | |
|
| | | switch (k) {
|
| | | case 'color':
|
| | | case 'background-color':
|
| | |
| | | return;
|
| | |
|
| | | t.files[u] = true;
|
| | | t.add(t.select('head')[0], 'link', {rel : 'stylesheet', href : u});
|
| | | t.add(t.select('head')[0], 'link', {rel : 'stylesheet', href : tinymce._addVer(u)});
|
| | | });
|
| | | },
|
| | |
|
| | |
| | | if (tinymce.isGecko) {
|
| | | h = h.replace(/<(\/?)strong>|<strong( [^>]+)>/gi, '<$1b$2>');
|
| | | h = h.replace(/<(\/?)em>|<em( [^>]+)>/gi, '<$1i$2>');
|
| | | }
|
| | | } else if (isIE)
|
| | | h = h.replace(/'/g, '''); // IE can't handle apos
|
| | |
|
| | | // Fix some issues
|
| | | h = h.replace(/<a( )([^>]+)\/>|<a\/>/gi, '<a$1$2></a>'); // Force open
|
| | |
|
| | | // Store away src and href in mce_src and mce_href since browsers mess them up
|
| | | if (s.keep_values) {
|
| | | // Wrap scripts in comments for serialization purposes
|
| | | if (h.indexOf('<script') !== -1) {
|
| | | h = h.replace(/<script>/g, '<script type="text/javascript">');
|
| | | h = h.replace(/<script(|[^>]+)>(\s*<!--|\/\/\s*<\[CDATA\[)?[\r\n]*/g, '<mce:script$1><!--\n');
|
| | | h = h.replace(/\s*(\/\/\s*-->|\/\/\s*]]>)?<\/script>/g, '\n// --></mce:script>');
|
| | | h = h.replace(/<mce:script(|[^>]+)><!--\n\/\/ --><\/mce:script>/g, '<mce:script$1></mce:script>');
|
| | | // Wrap scripts and styles in comments for serialization purposes
|
| | | if (/<script|style/.test(h)) {
|
| | | function trim(s) {
|
| | | // Remove prefix and suffix code for element
|
| | | s = s.replace(/^[\r\n]*|[\r\n]*$/g, '');
|
| | | s = s.replace(/^\s*(\/\/\s*<!--|\/\/\s*<\[CDATA\[|<!--|<\[CDATA\[)[\r\n]*/g, '');
|
| | | s = s.replace(/\s*(\/\/\s*\]\]>|\/\/\s*-->|\]\]>|-->)\s*$/g, '');
|
| | |
|
| | | return s;
|
| | | };
|
| | |
|
| | | // Preserve script elements
|
| | | h = h.replace(/<script([^>]+|)>([\s\S]*?)<\/script>/g, function(v, a, b) {
|
| | | // Remove prefix and suffix code for script element
|
| | | b = trim(b);
|
| | |
|
| | | // Force type attribute
|
| | | if (!a)
|
| | | a = ' type="text/javascript"';
|
| | |
|
| | | // Wrap contents in a comment
|
| | | if (b)
|
| | | b = '<!--\n' + b + '\n// -->';
|
| | |
|
| | | // Output fake element
|
| | | return '<mce:script' + a + '>' + b + '</mce:script>';
|
| | | });
|
| | |
|
| | | // Preserve style elements
|
| | | h = h.replace(/<style([^>]+|)>([\s\S]*?)<\/style>/g, function(v, a, b) {
|
| | | b = trim(b);
|
| | | return '<mce:style' + a + '><!--\n' + b + '\n--></mce:style><style' + a + ' mce_bogus="1">' + b + '</style>';
|
| | | });
|
| | | }
|
| | |
|
| | | // Process all tags with src, href or style
|
| | | h = h.replace(/<([\w:]+) [^>]*(src|href|style|coords)[^>]*>/gi, function(a, n) {
|
| | | h = h.replace(/<([\w:]+) [^>]*(src|href|style|shape|coords)[^>]*>/gi, function(a, n) {
|
| | | function handle(m, b, c) {
|
| | | var u = c;
|
| | |
|
| | |
| | | //if (isIE)
|
| | | // u = t.serializeStyle(t.parseStyle(u));
|
| | |
|
| | | // No mce_style for elements with these since they might get resized by the user
|
| | | if (t._isRes(c))
|
| | | return m;
|
| | |
|
| | | if (s.hex_colors) {
|
| | | u = u.replace(/rgb\([^\)]+\)/g, function(v) {
|
| | | return t.toHex(v);
|
| | |
| | | return 'url(' + t.encode(s.url_converter.call(s.url_converter_scope || t, t.decode(c), b, n)) + ')';
|
| | | });
|
| | | }
|
| | | } else if (b != 'coords') {
|
| | | } else if (b != 'coords' && b != 'shape') {
|
| | | if (s.url_converter)
|
| | | u = t.encode(s.url_converter.call(s.url_converter_scope || t, t.decode(c), b, n));
|
| | | }
|
| | |
| | | return ' ' + b + '="' + c + '" mce_' + b + '="' + u + '"';
|
| | | };
|
| | |
|
| | | a = a.replace(/ (src|href|style|coords)=[\"]([^\"]+)[\"]/gi, handle); // W3C
|
| | | a = a.replace(/ (src|href|style|coords)=[\']([^\']+)[\']/gi, handle); // W3C
|
| | | a = a.replace(/ (src|href|style|coords|shape)=[\"]([^\"]+)[\"]/gi, handle); // W3C
|
| | | a = a.replace(/ (src|href|style|coords|shape)=[\']([^\']+)[\']/gi, handle); // W3C
|
| | |
|
| | | return a.replace(/ (src|href|style|coords)=([^\s\"\'>]+)/gi, handle); // IE
|
| | | return a.replace(/ (src|href|style|coords|shape)=([^\s\"\'>]+)/gi, handle); // IE
|
| | | });
|
| | | }
|
| | |
|
| | |
| | |
|
| | | n = n.nodeName || n;
|
| | |
|
| | | return /^(H[1-6]|HR|P|DIV|ADDRESS|PRE|FORM|TABLE|LI|OL|UL|TD|CAPTION|BLOCKQUOTE|CENTER|DL|DT|DD|DIR|FIELDSET|FORM|NOSCRIPT|NOFRAMES|MENU|ISINDEX|SAMP)$/.test(n);
|
| | | return /^(H[1-6]|HR|P|DIV|ADDRESS|PRE|FORM|TABLE|LI|OL|UL|TD|CAPTION|BLOCKQUOTE|CENTER|DL|DT|DD|DIR|FIELDSET|NOSCRIPT|NOFRAMES|MENU|ISINDEX|SAMP)$/.test(n);
|
| | | },
|
| | |
|
| | | // #if !jquery
|
| | |
| | | }
|
| | |
|
| | | // Fix IE psuedo leak for elements since replacing elements if fairly common
|
| | | if (isIE && o.nodeType === 1) {
|
| | | // Will break parentNode for some unknown reason
|
| | | /* if (isIE && o.nodeType === 1) {
|
| | | o.parentNode.insertBefore(n, o);
|
| | | o.outerHTML = '';
|
| | | return n;
|
| | | }
|
| | | }*/
|
| | |
|
| | | return o.parentNode.replaceChild(n, o);
|
| | | });
|
| | |
| | | // Manual destroy then remove unload handler
|
| | | if (!s)
|
| | | tinymce.removeUnload(t.destroy);
|
| | | },
|
| | |
|
| | | _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);
|
| | | }
|
| | |
|
| | | /*
|
| | |
| | | var t;
|
| | |
|
| | | // No need since the document is already loaded
|
| | | if (window.tinyMCE_GZ && tinyMCE_GZ.loaded)
|
| | | if (window.tinyMCE_GZ && tinyMCE_GZ.loaded) {
|
| | | Event.domLoaded = 1;
|
| | | return;
|
| | | }
|
| | |
|
| | | if (isIE && document.location.protocol != 'https:') {
|
| | | // Fake DOMContentLoaded on IE
|
| | |
| | | /* file:jscripts/tiny_mce/classes/dom/Selection.js */
|
| | |
|
| | | (function() {
|
| | | function trimNl(s) {
|
| | | return s.replace(/[\n\r]+/g, '');
|
| | | };
|
| | |
|
| | | // Shorten names
|
| | | var is = tinymce.is, isIE = tinymce.isIE, each = tinymce.each;
|
| | |
|
| | |
| | | },
|
| | |
|
| | | setContent : function(h, s) {
|
| | | var t = this, r = t.getRng(), d;
|
| | | var t = this, r = t.getRng(), d = t.win.document;
|
| | |
|
| | | s = s || {format : 'html'};
|
| | | s.set = true;
|
| | | h = t.dom.processHTML(h);
|
| | |
|
| | | if (r.insertNode) {
|
| | | d = t.win.document;
|
| | |
|
| | | // Gecko has a bug where if you insert using InsertHTML it will insert a space instead
|
| | | // So we simply check if the input is HTML or text and then insert text using the insertNode method
|
| | | if (tinymce.isGecko && h.indexOf('<') == -1) {
|
| | |
| | | r.insertNode(t.getRng().createContextualFragment(h));
|
| | | }
|
| | | } else {
|
| | | if (r.item)
|
| | | r.item(0).outerHTML = h;
|
| | | else
|
| | | r.pasteHTML(h);
|
| | | if (r.item) {
|
| | | // Delete content and get caret text selection
|
| | | d.execCommand('Delete', false, null);
|
| | | r = t.getRng();
|
| | | }
|
| | |
|
| | | r.pasteHTML(h);
|
| | | }
|
| | | },
|
| | |
|
| | |
| | | r.collapse(1);
|
| | | e = r.parentElement();
|
| | |
|
| | | if (e.nodeName == 'BODY')
|
| | | if (e && e.nodeName == 'BODY')
|
| | | return e.firstChild;
|
| | |
|
| | | return e;
|
| | |
| | | r.collapse(0);
|
| | | e = r.parentElement();
|
| | |
|
| | | if (e.nodeName == 'BODY')
|
| | | if (e && e.nodeName == 'BODY')
|
| | | return e.lastChild;
|
| | |
|
| | | return e;
|
| | |
| | | return d;
|
| | | }
|
| | |
|
| | | p += tinymce.trim(n.nodeValue || '').length;
|
| | | p += trimNl(n.nodeValue || '').length;
|
| | | }
|
| | |
|
| | | return null;
|
| | |
| | | return {scrollX : sx, scrollY : sy};
|
| | |
|
| | | // Count whitespace before
|
| | | (s.anchorNode.nodeValue || '').replace(/^\s+/, function(a) {wb = a.length;});
|
| | | trimNl(s.anchorNode.nodeValue || '').replace(/^\s+/, function(a) {wb = a.length;});
|
| | |
|
| | | return {
|
| | | start : Math.max(e.start + s.anchorOffset - wb, 0),
|
| | |
| | | e = getPos(ro, r.startContainer, r.endContainer);
|
| | |
|
| | | // Count whitespace before start and end container
|
| | | (r.startContainer.nodeValue || '').replace(/^\s+/, function(a) {wb = a.length;});
|
| | | (r.endContainer.nodeValue || '').replace(/^\s+/, function(a) {wa = a.length;});
|
| | | //(r.startContainer.nodeValue || '').replace(/^\s+/, function(a) {wb = a.length;});
|
| | | //(r.endContainer.nodeValue || '').replace(/^\s+/, function(a) {wa = a.length;});
|
| | |
|
| | | if (!e)
|
| | | return {scrollX : sx, scrollY : sy};
|
| | |
| | | wa = wb = 0;
|
| | |
|
| | | nv = n.nodeValue || '';
|
| | | nv.replace(/^\s+[^\s]/, function(a) {wb = a.length - 1;});
|
| | | nv.replace(/[^\s]\s+$/, function(a) {wa = a.length - 1;});
|
| | | //nv.replace(/^\s+[^\s]/, function(a) {wb = a.length - 1;});
|
| | | //nv.replace(/[^\s]\s+$/, function(a) {wa = a.length - 1;});
|
| | |
|
| | | nvl = tinymce.trim(nv).length;
|
| | | nvl = trimNl(nv).length;
|
| | | p += nvl;
|
| | |
|
| | | if (p >= sp && !d.startNode) {
|
| | |
| | | },
|
| | |
|
| | | writeComment : function(v) {
|
| | | this.node.appendChild(this.doc.createComment(v));
|
| | | this.node.appendChild(this.doc.createComment(v.replace(/\-\-/g, ' ')));
|
| | | },
|
| | |
|
| | | getContent : function() {
|
| | |
| | | // Internal functions
|
| | |
|
| | | _postProcess : function(o) {
|
| | | var t = this, s = t.settings, h = o.content, sc = [], p, l;
|
| | | var t = this, s = t.settings, h = o.content, sc = [], p;
|
| | |
|
| | | if (o.format == 'html') {
|
| | | // Protect some elements
|
| | | p = t._protect({
|
| | | content : h,
|
| | | patterns : [
|
| | | /(<script[^>]*>)(.*?)(<\/script>)/g,
|
| | | /(<style[^>]*>)(.*?)(<\/style>)/g,
|
| | | /(<pre[^>]*>)(.*?)(<\/pre>)/g
|
| | | {pattern : /(<script[^>]*>)(.*?)(<\/script>)/g},
|
| | | {pattern : /(<style[^>]*>)(.*?)(<\/style>)/g},
|
| | | {pattern : /(<pre[^>]*>)(.*?)(<\/pre>)/g, encode : 1}
|
| | | ]
|
| | | });
|
| | |
|
| | | h = p.content;
|
| | |
|
| | | // Entity encode
|
| | | if (s.entity_encoding !== 'raw') {
|
| | | if (s.entity_encoding.indexOf('named') != -1) {
|
| | | t.setEntities(s.entities);
|
| | | l = t.entityLookup;
|
| | |
|
| | | h = h.replace(t.entitiesRE, function(a) {
|
| | | var v;
|
| | |
|
| | | if (v = l[a])
|
| | | a = '&' + v + ';';
|
| | |
|
| | | return a;
|
| | | });
|
| | | }
|
| | |
|
| | | if (s.entity_encoding.indexOf('numeric') != -1) {
|
| | | h = h.replace(/[\u007E-\uFFFF]/g, function(a) {
|
| | | return '&#' + a.charCodeAt(0) + ';';
|
| | | });
|
| | | }
|
| | | }
|
| | | if (s.entity_encoding !== 'raw')
|
| | | h = t._encode(h);
|
| | |
|
| | | // Use BR instead of padded P elements inside editor and use <p> </p> outside editor
|
| | | /* if (o.set)
|
| | |
| | | },
|
| | |
|
| | | _protect : function(o) {
|
| | | var t = this;
|
| | |
|
| | | o.items = o.items || [];
|
| | |
|
| | | function enc(s) {
|
| | |
| | | };
|
| | |
|
| | | each(o.patterns, function(p) {
|
| | | o.content = dec(enc(o.content).replace(p, function(x, a, b, c) {
|
| | | o.items.push(dec(b));
|
| | | o.content = dec(enc(o.content).replace(p.pattern, function(x, a, b, c) {
|
| | | b = dec(b);
|
| | |
|
| | | if (p.encode)
|
| | | b = t._encode(b);
|
| | |
|
| | | o.items.push(b);
|
| | | return a + '<!--mce:' + (o.items.length - 1) + '-->' + c;
|
| | | }));
|
| | | });
|
| | |
| | | return h;
|
| | | },
|
| | |
|
| | | _encode : function(h) {
|
| | | var t = this, s = t.settings, l;
|
| | |
|
| | | // Entity encode
|
| | | if (s.entity_encoding !== 'raw') {
|
| | | if (s.entity_encoding.indexOf('named') != -1) {
|
| | | t.setEntities(s.entities);
|
| | | l = t.entityLookup;
|
| | |
|
| | | h = h.replace(t.entitiesRE, function(a) {
|
| | | var v;
|
| | |
|
| | | if (v = l[a])
|
| | | a = '&' + v + ';';
|
| | |
|
| | | return a;
|
| | | });
|
| | | }
|
| | |
|
| | | if (s.entity_encoding.indexOf('numeric') != -1) {
|
| | | h = h.replace(/[\u007E-\uFFFF]/g, function(a) {
|
| | | return '&#' + a.charCodeAt(0) + ';';
|
| | | });
|
| | | }
|
| | | }
|
| | |
|
| | | return h;
|
| | | },
|
| | |
|
| | | _setup : function() {
|
| | | var t = this, s = this.settings;
|
| | |
|
| | |
| | | t.addValidChildRules(s.valid_child_elements);
|
| | |
|
| | | if (s.invalid_elements)
|
| | | t.invalidElementsRE = new RegExp('^(' + wildcardToRE(s.invalid_elements.replace(',', '|').toLowerCase()) + ')$');
|
| | | t.invalidElementsRE = new RegExp('^(' + wildcardToRE(s.invalid_elements.replace(/,/g, '|').toLowerCase()) + ')$');
|
| | |
|
| | | if (s.attrib_value_filter)
|
| | | t.attribValueFilter = s.attribValueFilter;
|
| | |
| | | function loadScript(u) {
|
| | | if (tinymce.dom.Event.domLoaded || t.settings.strict_mode) {
|
| | | tinymce.util.XHR.send({
|
| | | url : u,
|
| | | url : tinymce._addVer(u),
|
| | | error : t.settings.error,
|
| | | async : false,
|
| | | success : function(co) {
|
| | |
| | | }
|
| | | });
|
| | | } else
|
| | | document.write('<script type="text/javascript" src="' + u + '"></script>');
|
| | | document.write('<script type="text/javascript" src="' + tinymce._addVer(u) + '"></script>');
|
| | | };
|
| | |
|
| | | if (!tinymce.is(u, 'string')) {
|
| | |
| | | ol += 'tinymce.dom.ScriptLoader._onLoad(this,\'' + u + '\',' + ix + ');"';
|
| | | }
|
| | |
|
| | | document.write('<script type="text/javascript" src="' + u + '"' + ol + '></script>');
|
| | | document.write('<script type="text/javascript" src="' + tinymce._addVer(u) + '"' + ol + '></script>');
|
| | |
|
| | | if (!o.func)
|
| | | done(o);
|
| | |
| | | this.onShowMenu = new tinymce.util.Dispatcher(this);
|
| | | this.onHideMenu = new tinymce.util.Dispatcher(this);
|
| | | this.classPrefix = 'mceMenu';
|
| | |
|
| | | // Fix for odd IE bug: #1903622
|
| | | this.fixIE = tinymce.isIE && DOM.win.top != DOM.win;
|
| | | },
|
| | |
|
| | | createMenu : function(s) {
|
| | |
| | | t.element.update();
|
| | |
|
| | | t.isMenuVisible = 1;
|
| | | t.mouseClickFunc = Event.add(co, t.fixIE ? 'mousedown' : 'click', function(e) {
|
| | | t.mouseClickFunc = Event.add(co, 'click', function(e) {
|
| | | var m;
|
| | |
|
| | | e = e.target;
|
| | |
| | | if (s.keyboard_focus) {
|
| | | Event.add(co, 'keydown', t._keyHandler, t);
|
| | | DOM.select('a', 'menu_' + t.id)[0].focus(); // Select first link
|
| | | t._focusIdx = 0;
|
| | | }
|
| | | },
|
| | |
|
| | |
| | | return;
|
| | |
|
| | | Event.remove(co, 'mouseover', t.mouseOverFunc);
|
| | | Event.remove(co, t.fixIE ? 'mousedown' : 'click', t.mouseClickFunc);
|
| | | Event.remove(co, 'click', t.mouseClickFunc);
|
| | | Event.remove(co, 'keydown', t._keyHandler);
|
| | | DOM.hide(co);
|
| | | t.isMenuVisible = 0;
|
| | |
| | | // Internal functions
|
| | |
|
| | | _keyHandler : function(e) {
|
| | | // Accessibility feature
|
| | | if (e.keyCode == 27)
|
| | | this.hideMenu();
|
| | | var t = this, kc = e.keyCode;
|
| | |
|
| | | function focus(d) {
|
| | | var i = t._focusIdx + d, e = DOM.select('a', 'menu_' + t.id)[i];
|
| | |
|
| | | if (e) {
|
| | | t._focusIdx = i;
|
| | | e.focus();
|
| | | }
|
| | | };
|
| | |
|
| | | switch (kc) {
|
| | | case 38:
|
| | | focus(-1); // Select first link
|
| | | return;
|
| | |
|
| | | case 40:
|
| | | focus(1);
|
| | | return;
|
| | |
|
| | | case 13:
|
| | | return;
|
| | |
|
| | | case 27:
|
| | | return this.hideMenu();
|
| | | }
|
| | | },
|
| | |
|
| | | _add : function(tb, o) {
|
| | |
| | | },
|
| | |
|
| | | renderHTML : function() {
|
| | | var cp = this.classPrefix, s = this.settings, h = '<a id="' + this.id + '" href="javascript:;" class="' + cp + ' ' + cp + 'Enabled ' + s['class'] + '" onmousedown="return false;" onclick="return false;" title="' + DOM.encode(s.title) + '">';
|
| | | var cp = this.classPrefix, s = this.settings, h, l;
|
| | |
|
| | | l = DOM.encode(s.label || '');
|
| | | h = '<a id="' + this.id + '" href="javascript:;" class="' + cp + ' ' + cp + 'Enabled ' + s['class'] + (l ? ' ' + cp + 'Labeled' : '') +'" onmousedown="return false;" onclick="return false;" title="' + DOM.encode(s.title) + '">';
|
| | |
|
| | | if (s.image)
|
| | | h += '<img class="mceIcon" src="' + s.image + '" /></a>';
|
| | | h += '<img class="mceIcon" src="' + s.image + '" />' + l + '</a>';
|
| | | else
|
| | | h += '<span class="mceIcon ' + s['class'] + '"></span></a>';
|
| | | h += '<span class="mceIcon ' + s['class'] + '"></span>' + (l ? '<span class="' + cp + 'Label">' + l + '</span>' : '') + '</a>';
|
| | |
|
| | | return h;
|
| | | },
|
| | |
| | | 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;
|
| | |
| | | m = t.menu;
|
| | | m.settings.offset_x = p2.x;
|
| | | m.settings.offset_y = p2.y;
|
| | | m.settings.keyboard_focus = t._focused;
|
| | | m.settings.keyboard_focus = !tinymce.isOpera; // Opera is buggy when it comes to auto focus
|
| | |
|
| | | // Select in menu
|
| | | if (t.oldID)
|
| | |
| | |
|
| | | 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;
|
| | |
|
| | | // 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, function(n) {return DOM.hasClass(n, 'mceMenu');})) {
|
| | | DOM.removeClass(t.id, t.classPrefix + 'Selected');
|
| | |
| | |
|
| | | m.add({
|
| | | title : t.settings.title,
|
| | | 'class' : 'mceMenuItemTitle'
|
| | | }).setDisabled(1);
|
| | | 'class' : 'mceMenuItemTitle',
|
| | | onclick : function() {
|
| | | if (t.settings.onselect('') !== false)
|
| | | t.select(''); // Must be runned after
|
| | | }
|
| | | });
|
| | |
|
| | | each(t.items, function(o) {
|
| | | o.id = DOM.uniqueId();
|
| | |
| | | var t = this, cp = t.classPrefix;
|
| | |
|
| | | Event.add(t.id, 'click', t.showMenu, t);
|
| | | Event.add(t.id + '_text', 'focus', function() {t._focused = 1;});
|
| | | Event.add(t.id + '_text', 'blur', function() {t._focused = 0;});
|
| | | Event.add(t.id + '_text', 'focus', function(e) {
|
| | | if (!t._focused) {
|
| | | t.keyDownHandler = Event.add(t.id + '_text', 'keydown', function(e) {
|
| | | var idx = -1, v, kc = e.keyCode;
|
| | |
|
| | | // Find current index
|
| | | each(t.items, function(v, i) {
|
| | | if (t.selectedValue == v.value)
|
| | | idx = i;
|
| | | });
|
| | |
|
| | | // Move up/down
|
| | | if (kc == 38)
|
| | | v = t.items[idx - 1];
|
| | | else if (kc == 40)
|
| | | v = t.items[idx + 1];
|
| | | else if (kc == 13) {
|
| | | // Fake select on enter
|
| | | v = t.selectedValue;
|
| | | t.selectedValue = null; // Needs to be null to fake change
|
| | | t.settings.onselect(v);
|
| | | return Event.cancel(e);
|
| | | }
|
| | |
|
| | | if (v) {
|
| | | t.hideMenu();
|
| | | t.select(v.value);
|
| | | }
|
| | | });
|
| | | }
|
| | |
|
| | | t._focused = 1;
|
| | | });
|
| | | Event.add(t.id + '_text', 'blur', function() {Event.remove(t.id + '_text', 'keydown', t.keyDownHandler); t._focused = 0;});
|
| | |
|
| | | // Old IE doesn't have hover on all elements
|
| | | if (tinymce.isIE6 || !DOM.boxModel) {
|
| | |
| | | t.isMenuRendered = true;
|
| | | }
|
| | |
|
| | | if (t.isMenuVisible)
|
| | | return t.hideMenu();
|
| | |
|
| | | p1 = DOM.getPos(t.settings.menu_container);
|
| | | p2 = DOM.getPos(e);
|
| | |
|
| | |
| | |
|
| | | Event.add(DOM.doc, 'mousedown', t.hideMenu, t);
|
| | | t.setState('Selected', 1);
|
| | |
|
| | | t.isMenuVisible = 1;
|
| | | },
|
| | |
|
| | | renderMenu : function() {
|
| | |
| | | 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, function(n) {return DOM.hasClass(n, 'mceMenu');})) {
|
| | | t.setState('Selected', 0);
|
| | | Event.remove(DOM.doc, 'mousedown', t.hideMenu, t);
|
| | | if (t.menu)
|
| | | t.menu.hideMenu();
|
| | | }
|
| | |
|
| | | t.isMenuVisible = 0;
|
| | | },
|
| | |
|
| | | postRender : function() {
|
| | |
| | | default_color : '#888888'
|
| | | }, t.settings);
|
| | |
|
| | | t.onShowMenu = new tinymce.util.Dispatcher(t);
|
| | | t.onHideMenu = new tinymce.util.Dispatcher(t);
|
| | |
|
| | | t.value = s.default_color;
|
| | | },
|
| | |
|
| | |
| | | t.renderMenu();
|
| | | t.isMenuRendered = true;
|
| | | }
|
| | |
|
| | | if (t.isMenuVisible)
|
| | | return t.hideMenu();
|
| | |
|
| | | e = DOM.get(t.id);
|
| | | DOM.show(t.id + '_menu');
|
| | |
| | |
|
| | | DOM.select('a', t.id + '_menu')[0].focus(); // Select first link
|
| | | }
|
| | |
|
| | | t.onShowMenu.dispatch(t);
|
| | |
|
| | | t.isMenuVisible = 1;
|
| | | },
|
| | |
|
| | | 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 + '_open';}))
|
| | | return;
|
| | |
|
| | | if (!e || !DOM.getParent(e.target, function(n) {return DOM.hasClass(n, 'mceSplitButtonMenu');})) {
|
| | | DOM.removeClass(t.id, 'mceSplitButtonSelected');
|
| | |
| | | Event.remove(t.id + '_menu', 'keydown', t._keyHandler);
|
| | | DOM.hide(t.id + '_menu');
|
| | | }
|
| | |
|
| | | t.onHideMenu.dispatch(t);
|
| | |
|
| | | t.isMenuVisible = 0;
|
| | | },
|
| | |
|
| | | renderMenu : function() {
|
| | |
| | |
|
| | | if (e.nodeName == 'A' && (c = e.getAttribute('mce_color')))
|
| | | t.setColor(c);
|
| | |
|
| | | return Event.cancel(e); // Prevent IE auto save warning
|
| | | });
|
| | |
|
| | | return w;
|
| | |
| | | },
|
| | |
|
| | | init : function(s) {
|
| | | var t = this, pl, sl = tinymce.ScriptLoader, c;
|
| | | var t = this, pl, sl = tinymce.ScriptLoader, c, e;
|
| | |
|
| | | function execCallback(se, n, s) {
|
| | | var f = se[n];
|
| | |
| | | case "textareas":
|
| | | case "specific_textareas":
|
| | | function hasClass(n, c) {
|
| | | return new RegExp('\\b' + c + '\\b', 'g').test(n.className);
|
| | | return c.constructor === RegExp ? c.test(n.className) : DOM.hasClass(n, c);
|
| | | };
|
| | |
|
| | | each(DOM.select('textarea'), function(v) {
|
| | |
| | | return;
|
| | |
|
| | | if (!s.editor_selector || hasClass(v, s.editor_selector)) {
|
| | | v.id = v.id || v.name;
|
| | | // Can we use the name
|
| | | e = DOM.get(v.name);
|
| | | if (!v.id && !e)
|
| | | v.id = v.name;
|
| | |
|
| | | // Generate unique name if missing or already exists
|
| | | if (!v.id || t.get(v.id))
|
| | |
| | |
|
| | | case "mceAddEditor":
|
| | | case "mceAddControl":
|
| | | new tinymce.Editor(v, t.settings).render();
|
| | | if (!t.get(v))
|
| | | new tinymce.Editor(v, t.settings).render();
|
| | |
|
| | | return true;
|
| | |
|
| | | case "mceAddFrameControl":
|
| | |
| | | apply_source_formatting : 1,
|
| | | directionality : 'ltr',
|
| | | forced_root_block : 'p',
|
| | | valid_elements : '@[id|class|style|title|dir<ltr?rtl|lang|xml::lang|onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup],a[rel|rev|charset|hreflang|tabindex|accesskey|type|name|href|target|title|class|onfocus|onblur],strong/b,em/i,strike,u,#p[align],-ol[type|compact],-ul[type|compact],-li,br,img[longdesc|usemap|src|border|alt=|title|hspace|vspace|width|height|align],-sub,-sup,-blockquote,-table[border=0|cellspacing|cellpadding|width|frame|rules|height|align|summary|bgcolor|background|bordercolor],-tr[rowspan|width|height|align|valign|bgcolor|background|bordercolor],tbody,thead,tfoot,#td[colspan|rowspan|width|height|align|valign|bgcolor|background|bordercolor|scope],#th[colspan|rowspan|width|height|align|valign|scope],caption,-div,-span,-code,-pre,address,-h1,-h2,-h3,-h4,-h5,-h6,hr[size|noshade],-font[face|size|color],dd,dl,dt,cite,abbr,acronym,del[datetime|cite],ins[datetime|cite],object[classid|width|height|codebase|*],param[name|value|_value],embed[type|width|height|src|*],script[src|type],map[name],area[shape|coords|href|alt|target],bdo,button,col[align|char|charoff|span|valign|width],colgroup[align|char|charoff|span|valign|width],dfn,fieldset,form[action|accept|accept-charset|enctype|method],input[accept|alt|checked|disabled|maxlength|name|readonly|size|src|type|value],kbd,label[for],legend,noscript,optgroup[label|disabled],option[disabled|label|selected|value],q[cite],samp,select[disabled|multiple|name|size],small,textarea[cols|rows|disabled|name|readonly],tt,var,big',
|
| | | valid_elements : '@[id|class|style|title|dir<ltr?rtl|lang|xml::lang|onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup],a[rel|rev|charset|hreflang|tabindex|accesskey|type|name|href|target|title|class|onfocus|onblur],strong/b,em/i,strike,u,#p[align],-ol[type|compact],-ul[type|compact],-li,br,img[longdesc|usemap|src|border|alt=|title|hspace|vspace|width|height|align],-sub,-sup,-blockquote[cite],-table[border=0|cellspacing|cellpadding|width|frame|rules|height|align|summary|bgcolor|background|bordercolor],-tr[rowspan|width|height|align|valign|bgcolor|background|bordercolor],tbody,thead,tfoot,#td[colspan|rowspan|width|height|align|valign|bgcolor|background|bordercolor|scope],#th[colspan|rowspan|width|height|align|valign|scope],caption,-div,-span,-code,-pre,address,-h1,-h2,-h3,-h4,-h5,-h6,hr[size|noshade],-font[face|size|color],dd,dl,dt,cite,abbr,acronym,del[datetime|cite],ins[datetime|cite],object[classid|width|height|codebase|*],param[name|value],embed[type|width|height|src|*],script[src|type],map[name],area[shape|coords|href|alt|target],bdo,button,col[align|char|charoff|span|valign|width],colgroup[align|char|charoff|span|valign|width],dfn,fieldset,form[action|accept|accept-charset|enctype|method],input[accept|alt|checked|disabled|maxlength|name|readonly|size|src|type|value],kbd,label[for],legend,noscript,optgroup[label|disabled],option[disabled|label|selected|value],q[cite],samp,select[disabled|multiple|name|size],small,textarea[cols|rows|disabled|name|readonly],tt,var,big',
|
| | | hidden_input : 1,
|
| | | padd_empty_editor : 1,
|
| | | render_ui : 1,
|
| | |
| | |
|
| | | if (s.encoding == 'xml') {
|
| | | t.onGetContent.add(function(ed, o) {
|
| | | if (o.get)
|
| | | if (o.save)
|
| | | o.content = DOM.encode(o.content);
|
| | | });
|
| | | }
|
| | |
| | | });
|
| | | }
|
| | |
|
| | | if (s.add_unload_trigger) {
|
| | | if (s.add_unload_trigger && !s.ask) {
|
| | | t._beforeUnload = tinyMCE.onBeforeUnload.add(function() {
|
| | | if (t.initialized && !t.destroyed)
|
| | | if (t.initialized && !t.destroyed && !t.isHidden())
|
| | | t.save({format : 'raw', no_events : true});
|
| | | });
|
| | | }
|
| | |
| | | sl.loadQueue(function() {
|
| | | if (s.ask) {
|
| | | function ask() {
|
| | | t.windowManager.confirm(t.getLang('edit_confirm'), function(s) {
|
| | | if (s)
|
| | | t.init();
|
| | | else
|
| | | Event.remove(t.id, 'focus', ask);
|
| | | });
|
| | | // Yield for awhile to avoid focus bug on FF 3 when cancel is pressed
|
| | | window.setTimeout(function() {
|
| | | Event.remove(t.id, 'focus', ask);
|
| | |
|
| | | t.windowManager.confirm(t.getLang('edit_confirm'), function(s) {
|
| | | if (s)
|
| | | t.init();
|
| | | });
|
| | | }, 0);
|
| | | };
|
| | |
|
| | | Event.add(t.id, 'focus', ask);
|
| | |
| | |
|
| | | // Pass through
|
| | | t.undoManager.onAdd.add(function(um, l) {
|
| | | return t.onChange.dispatch(t, l, um);
|
| | | if (!l.initial)
|
| | | return t.onChange.dispatch(t, l, um);
|
| | | });
|
| | |
|
| | | t.undoManager.onUndo.add(function(um, l) {
|
| | |
| | |
|
| | | // Measure box
|
| | | if (s.render_ui) {
|
| | | w = s.width || e.style.width || e.clientWidth;
|
| | | h = s.height || e.style.height || e.clientHeight;
|
| | | w = s.width || e.style.width || e.offsetWidth;
|
| | | h = s.height || e.style.height || e.offsetHeight;
|
| | | t.orgDisplay = e.style.display;
|
| | | re = /^[0-9\.]+(|px)$/i;
|
| | |
|
| | |
| | | if (h < 100)
|
| | | h = 100;
|
| | |
|
| | | t.iframeHTML = s.doctype + '<html><head xmlns="http://www.w3.org/1999/xhtml"><base href="' + t.documentBaseURI.getURI() + '"></base>';
|
| | | t.iframeHTML = s.doctype + '<html><head xmlns="http://www.w3.org/1999/xhtml"><base href="' + t.documentBaseURI.getURI() + '" />';
|
| | | t.iframeHTML += '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />';
|
| | |
|
| | | if (tinymce.relaxedDomain)
|
| | |
| | | // Remove empty contents
|
| | | if (s.padd_empty_editor) {
|
| | | t.onPostProcess.add(function(ed, o) {
|
| | | o.content = o.content.replace(/^<p>( |#160;|\s|\u00a0)<\/p>$/, '');
|
| | | o.content = o.content.replace(/^(<p>( | |\s|\u00a0|)<\/p>[\r\n]*|<br \/>[\r\n]*)$/, '');
|
| | | });
|
| | | }
|
| | |
|
| | |
| | |
|
| | |
|
| | | focus : function(sf) {
|
| | | var oed, t = this;
|
| | | var oed, t = this, ce = t.settings.content_editable;
|
| | |
|
| | | if (!sf) {
|
| | | t.getWin().focus();
|
| | | // Is not content editable or the selection is outside the area in IE
|
| | | // the IE statement is needed to avoid bluring if element selections inside layers since
|
| | | // the layer is like it's own document in IE
|
| | | if (!ce && (!isIE || t.selection.getNode().ownerDocument != t.getDoc()))
|
| | | t.getWin().focus();
|
| | |
|
| | | }
|
| | |
|
| | |
| | | },
|
| | |
|
| | | execCommand : function(cmd, ui, val, a) {
|
| | | var t = this, s = 0, o;
|
| | | var t = this, s = 0, o, st;
|
| | |
|
| | | if (!/^(mceAddUndoLevel|mceEndUndoLevel|mceBeginUndoLevel|mceRepaint|SelectAll)$/.test(cmd) && (!a || !a.skip_focus))
|
| | | t.focus();
|
| | |
| | | if (o.terminate)
|
| | | return false;
|
| | |
|
| | | // Comamnd callback
|
| | | // 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]) {
|
| | | s = o.func.call(o.scope, ui, val);
|
| | | t.onExecCommand.dispatch(t, cmd, ui, val, a);
|
| | | return s;
|
| | | 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
|
| | |
| | | },
|
| | |
|
| | | queryCommandState : function(c) {
|
| | | var t = this, o;
|
| | | var t = this, o, s;
|
| | |
|
| | | // Is hidden then return undefined
|
| | | if (t._isHidden())
|
| | | return;
|
| | |
|
| | | // Registred commands
|
| | | if (o = t.queryStateCommands[c])
|
| | | return o.func.call(o.scope);
|
| | | if (o = t.queryStateCommands[c]) {
|
| | | s = o.func.call(o.scope);
|
| | |
|
| | | // Fall though on true
|
| | | if (s !== true)
|
| | | return s;
|
| | | }
|
| | |
|
| | | // Registred commands
|
| | | o = t.editorCommands.queryCommandState(c);
|
| | |
| | | },
|
| | |
|
| | | queryCommandValue : function(c) {
|
| | | var t = this, o;
|
| | | var t = this, o, s;
|
| | |
|
| | | // Is hidden then return undefined
|
| | | if (t._isHidden())
|
| | | return;
|
| | |
|
| | | // Registred commands
|
| | | if (o = t.queryValueCommands[c])
|
| | | return o.func.call(o.scope);
|
| | | 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);
|
| | |
| | | o = o || {};
|
| | | o.save = true;
|
| | |
|
| | | // Add undo level will trigger onchange event
|
| | | if (!o.no_events) {
|
| | | t.undoManager.typing = 0;
|
| | | t.undoManager.add();
|
| | | }
|
| | |
|
| | | o.element = e;
|
| | | h = o.content = t.getContent(o);
|
| | |
|
| | |
| | | // 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 && (h.length === 0 || /^\s+$/.test(h))) {
|
| | | o.content = t.dom.setHTML(t.getBody(), '<br mce_bogus="1" />', 1);
|
| | | o.content = t.dom.setHTML(t.getBody(), '<br mce_bogus="1" />');
|
| | | o.format = 'raw';
|
| | | }
|
| | |
|
| | |
| | | h = t.getBody().innerHTML;
|
| | |
|
| | | h = h.replace(/^\s*|\s*$/g, '');
|
| | | o = {content : h};
|
| | | t.onGetContent.dispatch(t, o);
|
| | | o.content = h;
|
| | |
|
| | | if (!o.no_events)
|
| | | t.onGetContent.dispatch(t, o);
|
| | |
|
| | | return o.content;
|
| | | },
|
| | |
| | | t.dom.destroy();
|
| | |
|
| | | // Remove all events
|
| | | Event.clear(t.getWin());
|
| | | Event.clear(t.getDoc());
|
| | |
|
| | | // Don't clear the window or document if content editable
|
| | | // is enabled since other instances might still be present
|
| | | if (!t.settings.content_editable) {
|
| | | Event.clear(t.getWin());
|
| | | Event.clear(t.getDoc());
|
| | | }
|
| | |
|
| | | Event.clear(t.getBody());
|
| | | Event.clear(t.formElement);
|
| | | }
|
| | |
| | | case 'contextmenu':
|
| | | if (tinymce.isOpera) {
|
| | | // Fake contextmenu on Opera
|
| | | Event.add(t.getDoc(), 'mousedown', function(e) {
|
| | | Event.add(t.getBody(), 'mousedown', function(e) {
|
| | | if (e.ctrlKey) {
|
| | | e.fakeType = 'contextmenu';
|
| | | eventHandler(e);
|
| | | }
|
| | | });
|
| | | } else
|
| | | Event.add(t.getDoc(), k, eventHandler);
|
| | | Event.add(t.getBody(), k, eventHandler);
|
| | | break;
|
| | |
|
| | | case 'paste':
|
| | |
| | | } catch (ex) {
|
| | | // Use old method
|
| | | if (!t._isHidden())
|
| | | d.execCommand("useCSS", 0, true);
|
| | | try {d.execCommand("useCSS", 0, true);} catch (ex) {}
|
| | | }
|
| | |
|
| | | if (!s.table_inline_editing)
|
| | |
| | | var re = t.resizeInfo, cb;
|
| | |
|
| | | e = e.target;
|
| | | e.removeAttribute('mce_style'); // Remove this one since it might change
|
| | |
|
| | | // Don't do this action for non image elements
|
| | | if (e.nodeName !== 'IMG')
|
| | |
| | |
|
| | | case 'U':
|
| | | case 'STRIKE':
|
| | | sp = dom.create('span', {style : dom.getAttrib(n, 'style')});
|
| | | sp.style.textDecoration = n.nodeName == 'U' ? 'underline' : 'line-through';
|
| | | dom.setAttrib(sp, 'mce_style', '');
|
| | | dom.replace(sp, n, 1);
|
| | | //sp = dom.create('span', {style : dom.getAttrib(n, 'style')});
|
| | | n.style.textDecoration = n.nodeName == 'U' ? 'underline' : 'line-through';
|
| | | dom.setAttrib(n, 'mce_style', '');
|
| | | dom.setAttrib(n, 'mce_name', 'span');
|
| | | break;
|
| | | }
|
| | | });
|
| | | } else if (o.set) {
|
| | | each(t.dom.select('table,span', o.node), function(n) {
|
| | | each(t.dom.select('table,span', o.node).reverse(), function(n) {
|
| | | if (n.nodeName == 'TABLE') {
|
| | | if (v = dom.getStyle(n, 'height'))
|
| | | dom.setAttrib(n, 'height', v.replace(/[^0-9%]+/g, ''));
|
| | |
| | | t.onPreProcess.add(convert);
|
| | |
|
| | | if (!s.cleanup_on_startup) {
|
| | | t.onInit.add(function() {
|
| | | convert(t, {node : t.getBody(), set : 1});
|
| | | t.onSetContent.add(function(ed, o) {
|
| | | if (o.initial)
|
| | | convert(t, {node : t.getBody(), set : 1});
|
| | | });
|
| | | }
|
| | | },
|
| | |
| | |
|
| | | if (i != -1) {
|
| | | dom.setAttrib(f, 'size', '' + (i + 1 || 1));
|
| | | f.style.fontSize = '';
|
| | | //f.style.fontSize = '';
|
| | | }
|
| | | } else if (cl) {
|
| | | i = inArray(cl, dom.getAttrib(n, 'class'));
|
| | |
| | | },
|
| | |
|
| | | mceInsertLink : function(u, v) {
|
| | | var ed = this.editor, e = ed.dom.getParent(ed.selection.getNode(), 'A');
|
| | | var ed = this.editor, s = ed.selection, e = ed.dom.getParent(s.getNode(), 'A');
|
| | |
|
| | | if (tinymce.is(v, 'string'))
|
| | | v = {href : v};
|
| | |
| | | t.RemoveFormat();
|
| | | } else
|
| | | ed.getDoc().execCommand('FontName', false, v);
|
| | | },
|
| | |
|
| | | FontSize : function(u, v) {
|
| | | var ed = this.editor, s = ed.settings, fz = tinymce.explode(s.font_size_style_values), fzc = tinymce.explode(s.font_size_classes), h, bm;
|
| | |
|
| | | // Remove style sizes
|
| | | each(ed.dom.select('font'), function(e) {
|
| | | e.style.fontSize = '';
|
| | | });
|
| | |
|
| | | // Let the browser add new size it will remove unneded ones in some browsers
|
| | | ed.getDoc().execCommand('FontSize', false, v);
|
| | |
|
| | | // Add style values
|
| | | if (s.inline_styles) {
|
| | | each(ed.dom.select('font'), function(e) {
|
| | | // Try remove redundant font elements
|
| | | if (e.parentNode.nodeName == 'FONT' && e.size == e.parentNode.size) {
|
| | | if (!bm)
|
| | | bm = ed.selection.getBookmark();
|
| | |
|
| | | ed.dom.remove(e, 1);
|
| | | return;
|
| | | }
|
| | |
|
| | | // Setup font size based on font size value
|
| | | if (v = e.size) {
|
| | | if (fzc && fzc.length > 0)
|
| | | ed.dom.setAttrib(e, 'class', fzc[parseInt(v) - 1]);
|
| | | else
|
| | | ed.dom.setStyle(e, 'fontSize', fz[parseInt(v) - 1]);
|
| | | }
|
| | | });
|
| | | }
|
| | |
|
| | | ed.selection.moveToBookmark(bm);
|
| | | },
|
| | |
|
| | | queryCommandValue : function(c) {
|
| | |
| | | },
|
| | |
|
| | | FormatBlock : function(ui, val) {
|
| | | var t = this, ed = t.editor;
|
| | | var t = this, ed = t.editor, s = ed.selection, dom = ed.dom, bl, nb, b;
|
| | |
|
| | | function isBlock(n) {
|
| | | return /^(P|DIV|H[1-6]|ADDRESS|BLOCKQUOTE|PRE)$/.test(n.nodeName);
|
| | | };
|
| | |
|
| | | bl = dom.getParent(s.getNode(), function(n) {
|
| | | return isBlock(n);
|
| | | });
|
| | |
|
| | | // IE has an issue where it removes the parent div if you change format on the paragrah in <div><p>Content</p></div>
|
| | | // FF and Opera doesn't change parent DIV elements if you switch format
|
| | | if (bl) {
|
| | | if ((isIE && isBlock(bl.parentNode)) || bl.nodeName == 'DIV') {
|
| | | // Rename block element
|
| | | nb = ed.dom.create(val);
|
| | |
|
| | | each(dom.getAttribs(bl), function(v) {
|
| | | dom.setAttrib(nb, v.nodeName, dom.getAttrib(bl, v.nodeName));
|
| | | });
|
| | |
|
| | | b = s.getBookmark();
|
| | | dom.replace(nb, bl, 1);
|
| | | s.moveToBookmark(b);
|
| | | ed.nodeChanged();
|
| | | return;
|
| | | }
|
| | | }
|
| | |
|
| | | val = ed.settings.forced_root_block ? (val || '<p>') : val;
|
| | |
|
| | | if (/^(P|DIV|H[1-6]|ADDRESS|BLOCKQUOTE|PRE)$/.test(ed.selection.getNode().nodeName))
|
| | | t.mceRemoveNode();
|
| | |
|
| | | if (val.indexOf('<') == -1)
|
| | | val = '<' + val + '>';
|
| | |
| | | },
|
| | |
|
| | | queryStateUnderline : function() {
|
| | | var ed = this.editor, n;
|
| | | var ed = this.editor, n = ed.selection.getNode();
|
| | |
|
| | | if (n && n.nodeName == 'A')
|
| | | return false;
|
| | |
| | |
|
| | | // Add undo level if needed
|
| | | l.content = l.content.replace(/^\s*|\s*$/g, '');
|
| | | la = t.data[t.index > 0 ? t.index - 1 : 0];
|
| | | la = t.data[t.index > 0 && (t.index == 0 || t.index == t.data.length) ? t.index - 1 : t.index];
|
| | | if (!l.initial && la && l.content == la.content)
|
| | | return null;
|
| | |
|
| | |
| | | if (s.custom_undo_redo_restore_selection && !l.initial)
|
| | | l.bookmark = b = l.bookmark || ed.selection.getBookmark();
|
| | |
|
| | | if (t.index < t.data.length && t.data[t.index].initial)
|
| | | if (t.index < t.data.length)
|
| | | t.index++;
|
| | |
|
| | | // Only initial marked undo levels should be allowed as first item
|
| | | // This to workaround a bug with Firefox and the blur event
|
| | | if (t.data.length === 0 && !l.initial)
|
| | | return null;
|
| | |
|
| | | // Add level
|
| | | t.data.length = t.index + 1;
|
| | |
| | | // Store selection
|
| | | if (si == -2 && r) {
|
| | | if (!isIE) {
|
| | | so = r.startOffset;
|
| | | eo = r.endOffset;
|
| | | si = t.find(b, 0, r.startContainer);
|
| | | ei = t.find(b, 0, r.endContainer);
|
| | | // If element is inside body, might not be the case in contentEdiable mode
|
| | | if (ed.dom.getParent(r.startContainer, function(e) {return e === b;})) {
|
| | | so = r.startOffset;
|
| | | eo = r.endOffset;
|
| | | si = t.find(b, 0, r.startContainer);
|
| | | ei = t.find(b, 0, r.endContainer);
|
| | | }
|
| | | } else {
|
| | | tr = d.body.createTextRange();
|
| | | tr.moveToElementText(b);
|
| | |
| | | // Restore selection
|
| | | if (si != -2) {
|
| | | if (!isIE) {
|
| | | bl = d.getElementsByTagName(ed.settings.element)[0];
|
| | | bl = b.getElementsByTagName(ed.settings.element)[0];
|
| | | r = d.createRange();
|
| | |
|
| | | // Select last location or generated block
|
| | |
| | | },
|
| | |
|
| | | insertPara : function(e) {
|
| | | var t = this, ed = t.editor, d = ed.getDoc(), se = ed.settings, s = ed.selection.getSel(), r = s.getRangeAt(0), b = d.body;
|
| | | var rb, ra, dir, sn, so, en, eo, sb, eb, bn, bef, aft, sc, ec, n, vp = ed.dom.getViewPort(ed.getWin()), y, ch;
|
| | | var t = this, ed = t.editor, dom = ed.dom, d = ed.getDoc(), se = ed.settings, s = ed.selection.getSel(), r = s.getRangeAt(0), b = d.body;
|
| | | var rb, ra, dir, sn, so, en, eo, sb, eb, bn, bef, aft, sc, ec, n, vp = dom.getViewPort(ed.getWin()), y, ch;
|
| | |
|
| | | function isEmpty(n) {
|
| | | n = n.innerHTML;
|
| | |
| | | so = dir ? s.anchorOffset : s.focusOffset;
|
| | | en = dir ? s.focusNode : s.anchorNode;
|
| | | eo = dir ? s.focusOffset : s.anchorOffset;
|
| | |
|
| | | // If selection is in empty table cell
|
| | | if (sn === en && /^(TD|TH)$/.test(sn.nodeName)) {
|
| | | dom.remove(sn.firstChild); // Remove BR
|
| | |
|
| | | // Create two new block elements
|
| | | ed.dom.add(sn, se.element, null, '<br />');
|
| | | aft = ed.dom.add(sn, se.element, null, '<br />');
|
| | |
|
| | | // Move caret into the last one
|
| | | r = d.createRange();
|
| | | r.selectNodeContents(aft);
|
| | | r.collapse(1);
|
| | | ed.selection.setRng(r);
|
| | |
|
| | | return false;
|
| | | }
|
| | |
|
| | | // If the caret is in an invalid location in FF we need to move it into the first block
|
| | | if (sn == b && en == b && b.firstChild && ed.dom.isBlock(b.firstChild)) {
|
| | |
| | | if (isEmpty(aft))
|
| | | aft.innerHTML = isOpera ? ' ' : '<br />'; // Extra space for Opera so that the caret can move there
|
| | |
|
| | | // Opera needs this one backwards
|
| | | if (isOpera) {
|
| | | // Opera needs this one backwards for older versions
|
| | | if (isOpera && parseFloat(opera.version()) < 9.5) {
|
| | | r.insertNode(bef);
|
| | | r.insertNode(aft);
|
| | | } else {
|
| | |
| | | aft.normalize();
|
| | | bef.normalize();
|
| | |
|
| | | function first(n) {
|
| | | return d.createTreeWalker(n, NodeFilter.SHOW_TEXT, null, false).nextNode() || n;
|
| | | };
|
| | |
|
| | | // Move cursor and scroll into view
|
| | | r = d.createRange();
|
| | | r.selectNodeContents(aft);
|
| | | r.selectNodeContents(isGecko ? first(aft) : aft);
|
| | | r.collapse(1);
|
| | | s.removeAllRanges();
|
| | | s.addRange(r);
|
| | |
| | | // Fix for bug #1897785, #1898007
|
| | | if (tinymce.isIE) {
|
| | | c.onShowMenu.add(function() {
|
| | | var s = ed.selection, n = s.getNode();
|
| | |
|
| | | if (n.nodeName == 'IMG')
|
| | | bm = s.getBookmark();
|
| | | else
|
| | | bm = 0;
|
| | | bm = ed.selection.getBookmark(1);
|
| | | });
|
| | |
|
| | | c.onHideMenu.add(function() {
|
| | |
| | | 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) {
|
| | |
| | | },
|
| | |
|
| | | createColorSplitButton : function(id, s, cc) {
|
| | | var t = this, ed = t.editor, cmd, c, cls;
|
| | | var t = this, ed = t.editor, cmd, c, cls, bm;
|
| | |
|
| | | if (t.get(id))
|
| | | return null;
|
| | |
| | | ed.onRemove.add(function() {
|
| | | c.destroy();
|
| | | });
|
| | |
|
| | | // Fix for bug #1897785, #1898007
|
| | | if (tinymce.isIE) {
|
| | | c.onShowMenu.add(function() {
|
| | | bm = ed.selection.getBookmark(1);
|
| | | });
|
| | |
|
| | | c.onHideMenu.add(function() {
|
| | | if (bm) {
|
| | | ed.selection.moveToBookmark(bm);
|
| | | bm = 0;
|
| | | }
|
| | | });
|
| | | }
|
| | |
|
| | | return t.add(c);
|
| | | },
|
| | |
| | | s.dialogWidth = s.width + 'px';
|
| | | s.dialogHeight = s.height + 'px';
|
| | | s.scroll = s.scrollbars || false;
|
| | | } else
|
| | | s.modal = s.alwaysRaised = s.dialog = s.centerscreen = s.dependent = true;
|
| | | }
|
| | | }
|
| | |
|
| | | // Build features string
|
| | |
| | | if (tinymce.relaxedDomain)
|
| | | u += (u.indexOf('?') == -1 ? '?' : '&') + 'mce_rdomain=' + tinymce.relaxedDomain;
|
| | |
|
| | | u = tinymce._addVer(u);
|
| | |
|
| | | try {
|
| | | if (isIE && mo) {
|
| | | w = 1;
|
| | | window.showModalDialog(s.url || s.file, window, f);
|
| | | window.showModalDialog(u, window, f);
|
| | | } else
|
| | | w = window.open(u, s.name, f);
|
| | | } catch (ex) {
|