/BlogEngine/BlogEngine.NET/editors/tiny_mce_3_4_3_1/tiny_mce_src.js
JavaScript | 2488 lines | 2193 code | 222 blank | 73 comment | 196 complexity | 2c6c96b9d0b46ee7053301c941d3da97 MD5 | raw file
Possible License(s): LGPL-2.1, Apache-2.0, BSD-3-Clause
- (function(win) {
- var whiteSpaceRe = /^\s*|\s*$/g,
- undefined, isRegExpBroken = 'B'.replace(/A(.)|B/, '$1') === '$1';
-
- var tinymce = {
- majorVersion : '3',
-
- minorVersion : '4.3.1',
-
- releaseDate : '2011-06-16',
-
- _init : function() {
- var t = this, d = document, na = navigator, ua = na.userAgent, i, nl, n, base, p, v;
-
- 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.isIE6 = t.isIE && /MSIE [56]/.test(ua);
-
- t.isGecko = !t.isWebKit && /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<nl.length; i++) {
- 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(|_gzip|_jquery|_prototype|_full)(_dev|_src)?.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('/'));
-
- // If path to script is relative and a base href was found add that one infront
- // the src property will always be an absolute one on non IE browsers and IE 8
- // so this logic will basically only be executed on older IE versions
- if (base && t.baseURL.indexOf('://') == -1 && t.baseURL.indexOf('/') !== 0)
- t.baseURL = base + t.baseURL;
-
- return t.baseURL;
- }
-
- return null;
- };
-
- // Check document
- nl = d.getElementsByTagName('script');
- for (i=0; i<nl.length; i++) {
- if (getBase(nl[i]))
- return;
- }
-
- // Check head
- n = d.getElementsByTagName('head')[0];
- if (n) {
- nl = n.getElementsByTagName('script');
- for (i=0; i<nl.length; i++) {
- if (getBase(nl[i]))
- return;
- }
- }
-
- return;
- },
-
- is : function(o, t) {
- if (!t)
- return o !== undefined;
-
- if (t == 'array' && (o.hasOwnProperty && o instanceof Array))
- return true;
-
- return typeof(o) == t;
- },
-
- makeMap : function(items, delim, map) {
- var i;
-
- items = items || [];
- delim = delim || ',';
-
- if (typeof(items) == "string")
- items = items.split(delim);
-
- map = map || {};
-
- i = items.length;
- while (i--)
- map[items[i]] = {};
-
- return map;
- },
-
- each : function(o, cb, s) {
- var n, l;
-
- if (!o)
- return 0;
-
- s = s || o;
-
- if (o.length !== undefined) {
- // Indexed arrays, needed for Safari
- for (n=0, l = o.length; n < l; n++) {
- if (cb.call(s, o[n], n, o) === false)
- return 0;
- }
- } else {
- // Hashtables
- for (n in o) {
- if (o.hasOwnProperty(n)) {
- if (cb.call(s, o[n], n, o) === false)
- return 0;
- }
- }
- }
-
- return 1;
- },
-
-
- map : function(a, f) {
- var o = [];
-
- tinymce.each(a, function(v) {
- o.push(f(v));
- });
-
- return o;
- },
-
- grep : function(a, f) {
- var o = [];
-
- tinymce.each(a, function(v) {
- if (!f || f(v))
- o.push(v);
- });
-
- return o;
- },
-
- inArray : function(a, v) {
- var i, l;
-
- if (a) {
- for (i = 0, l = a.length; i < l; i++) {
- if (a[i] === v)
- return i;
- }
- }
-
- return -1;
- },
-
- extend : function(o, e) {
- var i, l, a = arguments;
-
- for (i = 1, l = a.length; i < l; i++) {
- e = a[i];
-
- tinymce.each(e, function(v, n) {
- if (v !== undefined)
- o[n] = v;
- });
- }
-
- return o;
- },
-
-
- trim : function(s) {
- return (s ? '' + s : '').replace(whiteSpaceRe, '');
- },
-
- create : function(s, p, root) {
- var t = this, sp, ns, cn, scn, c, de = 0;
-
- // Parse : <prefix> <class>:<super class>
- 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<n.length; i++) {
- v = n[i];
-
- if (!o[v])
- o[v] = {};
-
- o = o[v];
- }
-
- return o;
- },
-
- resolve : function(n, o) {
- var i, l;
-
- o = o || win;
-
- n = n.split('.');
- for (i = 0, l = n.length; i < l; i++) {
- o = o[n[i]];
-
- if (!o)
- break;
- }
-
- return o;
- },
-
- addUnload : function(f, s) {
- var t = this;
-
- f = {func : f, scope : s || this};
-
- if (!t.unloads) {
- function unload() {
- var li = t.unloads, o, 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
- }
-
- // Detach unload function
- if (win.detachEvent) {
- win.detachEvent('onbeforeunload', fakeUnload);
- win.detachEvent('onunload', unload);
- } else if (win.removeEventListener)
- win.removeEventListener('unload', unload, false);
-
- // Destroy references
- t.unloads = o = li = w = unload = 0;
-
- // Run garbarge collector on IE
- if (win.CollectGarbage)
- CollectGarbage();
- }
- };
-
- function fakeUnload() {
- var d = document;
-
- // Is there things still loading, then do some magic
- if (d.readyState == 'interactive') {
- function stop() {
- // Prevent memory leak
- d.detachEvent('onstop', stop);
-
- // Call unload handler
- if (unload)
- unload();
-
- d = 0;
- };
-
- // Fire unload when the currently loading page is stopped
- if (d)
- 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
- win.setTimeout(function() {
- if (d)
- d.detachEvent('onstop', stop);
- }, 0);
- }
- };
-
- // Attach unload handler
- if (win.attachEvent) {
- win.attachEvent('onunload', unload);
- win.attachEvent('onbeforeunload', fakeUnload);
- } else if (win.addEventListener)
- win.addEventListener('unload', unload, false);
-
- // Setup initial unload handler array
- t.unloads = [f];
- } else
- t.unloads.push(f);
-
- return f;
- },
-
- removeUnload : function(f) {
- var u = this.unloads, r = null;
-
- tinymce.each(u, function(o, i) {
- if (o && o.func == f) {
- u.splice(i, 1);
- r = f;
- return false;
- }
- });
-
- return r;
- },
-
- explode : function(s, d) {
- 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 + '#');
- },
-
- // Fix function for IE 9 where regexps isn't working correctly
- // Todo: remove me once MS fixes the bug
- _replace : function(find, replace, str) {
- // On IE9 we have to fake $x replacement
- if (isRegExpBroken) {
- return str.replace(find, function() {
- var val = replace, args = arguments, i;
-
- for (i = 0; i < args.length - 2; i++) {
- if (args[i] === undefined) {
- val = val.replace(new RegExp('\\$' + i, 'g'), '');
- } else {
- val = val.replace(new RegExp('\\$' + i, 'g'), args[i]);
- }
- }
-
- return val;
- });
- }
-
- return str.replace(find, replace);
- }
-
- };
-
- // Initialize the API
- tinymce._init();
-
- // Expose tinymce namespace to the global namespace (window)
- win.tinymce = win.tinyMCE = tinymce;
-
- // Describe the different namespaces
-
- })(window);
-
-
-
- tinymce.create('tinymce.util.Dispatcher', {
- scope : null,
- listeners : null,
-
- Dispatcher : function(s) {
- this.scope = s || this;
- this.listeners = [];
- },
-
- add : function(cb, s) {
- this.listeners.push({cb : cb, scope : s || this.scope});
-
- return cb;
- },
-
- addToTop : function(cb, s) {
- this.listeners.unshift({cb : cb, scope : s || this.scope});
-
- return cb;
- },
-
- remove : function(cb) {
- var l = this.listeners, o = null;
-
- tinymce.each(l, function(c, i) {
- if (cb == c.cb) {
- o = cb;
- l.splice(i, 1);
- return false;
- }
- });
-
- return o;
- },
-
- dispatch : function() {
- var s, a = arguments, i, li = this.listeners, c;
-
- // Needs to be a real loop since the listener count might change while looping
- // And this is also more efficient
- for (i = 0; i<li.length; i++) {
- c = li[i];
- s = c.cb.apply(c.scope, a);
-
- if (s === false)
- break;
- }
-
- return s;
- }
-
- });
-
- (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 or local anchor
- if (/^(mailto|tel|news|javascript|about|data):/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;
- });
-
- if (b = s.base_uri) {
- 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();
-
- 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) {
- var 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(n, p) {
- var d = new Date();
-
- d.setTime(d.getTime() - 1000);
-
- this.set(n, '', d, p, d);
- }
- });
- })();
-
- (function() {
- function serialize(o, quote) {
- var i, v, t;
-
- 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 && o instanceof Array) {
- for (i=0, v = '['; i<o.length; i++)
- v += (i > 0 ? ',' : '') + serialize(o[i], quote);
-
- return v + ']';
- }
-
- v = '{';
-
- for (i in o)
- v += typeof o[i] != 'function' ? (v.length > 1 ? ',' + quote : quote) + i + quote +':' + serialize(o[i], 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;
-
- // 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);
-
- 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);
- };
-
- // 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) {
- var namedEntities, baseEntities, reverseEntities,
- attrsCharsRegExp = /[&<>\"\u007E-\uD7FF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,
- textCharsRegExp = /[<>&\u007E-\uD7FF]|[\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 = {
- '"' : '"',
- "'" : ''',
- '<' : '<',
- '>' : '>',
- '&' : '&'
- };
-
- // 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;
-
- // 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 _<num>
- function encode(str) {
- isEncoded = true;
-
- return encodingLookup[str];
- };
-
- // Decodes the specified string by replacing all _<num> 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;
- }
-
- 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, function(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, "\\'") + "')";
- });
-
- 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 transitional = {}, boolAttrMap, blockElementsMap, shortEndedElementsMap, nonEmptyElementsMap, customElementsMap = {},
- whiteSpaceElementsMap, selfClosingElementsMap, 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;
- };
-
- // Build a lookup table for block elements both lowercase and uppercase
- blockElementsMap = 'h1,h2,h3,h4,h5,h6,hr,p,div,address,pre,form,table,tbody,thead,tfoot,' +
- 'th,tr,td,li,ol,ul,caption,blockquote,center,dl,dt,dd,dir,fieldset,' +
- 'noscript,menu,isindex,samp,header,footer,article,section,hgroup';
- blockElementsMap = makeMap(blockElementsMap, ',', makeMap(blockElementsMap.toUpperCase()));
-
- // This is the XHTML 1.0 transitional elements with it's attributes and children packed to reduce it's size
- transitional = 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]'
- );
-
- boolAttrMap = makeMap('checked,compact,declare,defer,disabled,ismap,multiple,nohref,noresize,noshade,nowrap,readonly,selected,preload,autoplay,loop,controls');
- shortEndedElementsMap = makeMap('area,base,basefont,br,col,frame,hr,img,input,isindex,link,meta,param,embed,source');
- nonEmptyElementsMap = tinymce.extend(makeMap('td,th,iframe,video,object'), shortEndedElementsMap);
- whiteSpaceElementsMap = makeMap('pre,script,style');
- selfClosingElementsMap = makeMap('colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr');
-
- tinymce.html.Schema = function(settings) {
- var self = this, elements = {}, children = {}, patternElements = [], validStyles;
-
- settings = settings || {};
-
- // 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);
- });
- }
-
- // 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(transitional, 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] = {};
-
- // 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] = {};
- });
- }
- });
- }
- }
-
- if (!settings.valid_elements) {
- // No valid elements defined then clone the elements from the transitional spec
- each(transitional, function(element, name) {
- elements[name] = {
- attributes : element.attributes,
- attributesOrder : element.attributesOrder
- };
-
- children[name] = element.children;
- });
-
- // Switch these
- 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'), function(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];
- });
- }
-
- self.children = children;
-
- self.styles = validStyles;
-
- self.getBoolAttrs = function() {
- return boolAttrMap;
- };
-
- self.getBlockElements = function() {
- return blockElementsMap;
- };
-
- 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.getElementRule = function(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;
- }
- };
-
- self.getCustomElements = function() {
- return customElementsMap;
- };
-
- self.addValidElements = addValidElements;
-
- self.setValidElements = setValidElements;
-
- self.addCustomElements = addCustomElements;
-
- self.addValidChildren = addValidChildren;
- };
-
- // Expose boolMap and blockElementMap as static properties for usage in DOMUtils
- tinymce.html.Schema.boolAttrMap = boolAttrMap;
- tinymce.html.Schema.blockElementsMap = blockElementsMap;
- })(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,
- shortEndedElements, fillAttrsMap, isShortEnded, validate, elementRule, isValidElement, attr, attribsValue,
- validAttributesMap, validAttributePatterns, attributesRequired, attributesDefault, attributesForced, selfClosing,
- tokenRegExp, attrRegExp, specialElements, attrValue, idCount = 0, decode = tinymce.html.Entities.decode, fixSelfClosing;
-
- 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;
- }
- };
-
- // 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
- '(?:([^\\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 = schema.getSelfClosingElements();
- fillAttrsMap = schema.getBoolAttrs();
- validate = settings.validate;
- fixSelfClosing = settings.fix_self_closing;
-
- 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
- processEndTag(value.toLowerCase());
- } else if (value = matches[7]) { // Start element
- value = value.toLowerCase();
- isShortEnded = value in shortEndedElements;
-
- // Is self closing tag for example an <li> after an open <li>
- 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]) {
- attrList = [];
- attrList.map = {};
-
- attribsValue.replace(attrRegExp, function(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 && 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
- });
- });
- } else {
- attrList = [];
- attrList.map = {};
- }
-
- // Process attributes if validation is enabled
- if (validate) {
- 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