bgneal@45: var tinymce = {
bgneal@45: majorVersion : '3',
bgneal@45: minorVersion : '2.2.3',
bgneal@45: releaseDate : '2009-03-26',
bgneal@45:
bgneal@45: _init : function() {
bgneal@45: var t = this, d = document, w = window, na = navigator, ua = na.userAgent, i, nl, n, base, p, v;
bgneal@45:
bgneal@45: // Browser checks
bgneal@45: t.isOpera = w.opera && opera.buildNumber;
bgneal@45: t.isWebKit = /WebKit/.test(ua);
bgneal@45: t.isIE = !t.isWebKit && !t.isOpera && (/MSIE/gi).test(ua) && (/Explorer/gi).test(na.appName);
bgneal@45: t.isIE6 = t.isIE && /MSIE [56]/.test(ua);
bgneal@45: t.isGecko = !t.isWebKit && /Gecko/.test(ua);
bgneal@45: t.isMac = ua.indexOf('Mac') != -1;
bgneal@45: t.isAir = /adobeair/i.test(ua);
bgneal@45:
bgneal@45: // TinyMCE .NET webcontrol might be setting the values for TinyMCE
bgneal@45: if (w.tinyMCEPreInit) {
bgneal@45: t.suffix = tinyMCEPreInit.suffix;
bgneal@45: t.baseURL = tinyMCEPreInit.base;
bgneal@45: t.query = tinyMCEPreInit.query;
bgneal@45: return;
bgneal@45: }
bgneal@45:
bgneal@45: // Get suffix and base
bgneal@45: t.suffix = '';
bgneal@45:
bgneal@45: // If base element found, add that infront of baseURL
bgneal@45: nl = d.getElementsByTagName('base');
bgneal@45: for (i=0; i :
bgneal@45: s = /^((static) )?([\w.]+)(:([\w.]+))?/.exec(s);
bgneal@45: cn = s[3].match(/(^|\.)(\w+)$/i)[2]; // Class name
bgneal@45:
bgneal@45: // Create namespace for new class
bgneal@45: ns = t.createNS(s[3].replace(/\.\w+$/, ''));
bgneal@45:
bgneal@45: // Class already exists
bgneal@45: if (ns[cn])
bgneal@45: return;
bgneal@45:
bgneal@45: // Make pure static class
bgneal@45: if (s[2] == 'static') {
bgneal@45: ns[cn] = p;
bgneal@45:
bgneal@45: if (this.onCreate)
bgneal@45: this.onCreate(s[2], s[3], ns[cn]);
bgneal@45:
bgneal@45: return;
bgneal@45: }
bgneal@45:
bgneal@45: // Create default constructor
bgneal@45: if (!p[cn]) {
bgneal@45: p[cn] = function() {};
bgneal@45: de = 1;
bgneal@45: }
bgneal@45:
bgneal@45: // Add constructor and methods
bgneal@45: ns[cn] = p[cn];
bgneal@45: t.extend(ns[cn].prototype, p);
bgneal@45:
bgneal@45: // Extend
bgneal@45: if (s[5]) {
bgneal@45: sp = t.resolve(s[5]).prototype;
bgneal@45: scn = s[5].match(/\.(\w+)$/i)[1]; // Class name
bgneal@45:
bgneal@45: // Extend constructor
bgneal@45: c = ns[cn];
bgneal@45: if (de) {
bgneal@45: // Add passthrough constructor
bgneal@45: ns[cn] = function() {
bgneal@45: return sp[scn].apply(this, arguments);
bgneal@45: };
bgneal@45: } else {
bgneal@45: // Add inherit constructor
bgneal@45: ns[cn] = function() {
bgneal@45: this.parent = sp[scn];
bgneal@45: return c.apply(this, arguments);
bgneal@45: };
bgneal@45: }
bgneal@45: ns[cn].prototype[cn] = ns[cn];
bgneal@45:
bgneal@45: // Add super methods
bgneal@45: t.each(sp, function(f, n) {
bgneal@45: ns[cn].prototype[n] = sp[n];
bgneal@45: });
bgneal@45:
bgneal@45: // Add overridden methods
bgneal@45: t.each(p, function(f, n) {
bgneal@45: // Extend methods if needed
bgneal@45: if (sp[n]) {
bgneal@45: ns[cn].prototype[n] = function() {
bgneal@45: this.parent = sp[n];
bgneal@45: return f.apply(this, arguments);
bgneal@45: };
bgneal@45: } else {
bgneal@45: if (n != cn)
bgneal@45: ns[cn].prototype[n] = f;
bgneal@45: }
bgneal@45: });
bgneal@45: }
bgneal@45:
bgneal@45: // Add static methods
bgneal@45: t.each(p['static'], function(f, n) {
bgneal@45: ns[cn][n] = f;
bgneal@45: });
bgneal@45:
bgneal@45: if (this.onCreate)
bgneal@45: this.onCreate(s[2], s[3], ns[cn].prototype);
bgneal@45: },
bgneal@45:
bgneal@45: walk : function(o, f, n, s) {
bgneal@45: s = s || this;
bgneal@45:
bgneal@45: if (o) {
bgneal@45: if (n)
bgneal@45: o = o[n];
bgneal@45:
bgneal@45: tinymce.each(o, function(o, i) {
bgneal@45: if (f.call(s, o, i, n) === false)
bgneal@45: return false;
bgneal@45:
bgneal@45: tinymce.walk(o, f, n, s);
bgneal@45: });
bgneal@45: }
bgneal@45: },
bgneal@45:
bgneal@45: createNS : function(n, o) {
bgneal@45: var i, v;
bgneal@45:
bgneal@45: o = o || window;
bgneal@45:
bgneal@45: n = n.split('.');
bgneal@45: for (i=0; i= items.length) {
bgneal@45: for (i = 0, l = base.length; i < l; i++) {
bgneal@45: if (i >= items.length || base[i] != items[i]) {
bgneal@45: bp = i + 1;
bgneal@45: break;
bgneal@45: }
bgneal@45: }
bgneal@45: }
bgneal@45:
bgneal@45: if (base.length < items.length) {
bgneal@45: for (i = 0, l = items.length; i < l; i++) {
bgneal@45: if (i >= base.length || base[i] != items[i]) {
bgneal@45: bp = i + 1;
bgneal@45: break;
bgneal@45: }
bgneal@45: }
bgneal@45: }
bgneal@45:
bgneal@45: if (bp == 1)
bgneal@45: return path;
bgneal@45:
bgneal@45: for (i = 0, l = base.length - (bp - 1); i < l; i++)
bgneal@45: out += "../";
bgneal@45:
bgneal@45: for (i = bp - 1, l = items.length; i < l; i++) {
bgneal@45: if (i != bp - 1)
bgneal@45: out += "/" + items[i];
bgneal@45: else
bgneal@45: out += items[i];
bgneal@45: }
bgneal@45:
bgneal@45: return out;
bgneal@45: },
bgneal@45:
bgneal@45: toAbsPath : function(base, path) {
bgneal@45: var i, nb = 0, o = [], tr;
bgneal@45:
bgneal@45: // Split paths
bgneal@45: tr = /\/$/.test(path) ? '/' : '';
bgneal@45: base = base.split('/');
bgneal@45: path = path.split('/');
bgneal@45:
bgneal@45: // Remove empty chunks
bgneal@45: each(base, function(k) {
bgneal@45: if (k)
bgneal@45: o.push(k);
bgneal@45: });
bgneal@45:
bgneal@45: base = o;
bgneal@45:
bgneal@45: // Merge relURLParts chunks
bgneal@45: for (i = path.length - 1, o = []; i >= 0; i--) {
bgneal@45: // Ignore empty or .
bgneal@45: if (path[i].length == 0 || path[i] == ".")
bgneal@45: continue;
bgneal@45:
bgneal@45: // Is parent
bgneal@45: if (path[i] == '..') {
bgneal@45: nb++;
bgneal@45: continue;
bgneal@45: }
bgneal@45:
bgneal@45: // Move up
bgneal@45: if (nb > 0) {
bgneal@45: nb--;
bgneal@45: continue;
bgneal@45: }
bgneal@45:
bgneal@45: o.push(path[i]);
bgneal@45: }
bgneal@45:
bgneal@45: i = base.length - nb;
bgneal@45:
bgneal@45: // If /a/b/c or /
bgneal@45: if (i <= 0)
bgneal@45: return '/' + o.reverse().join('/') + tr;
bgneal@45:
bgneal@45: return '/' + base.slice(0, i).join('/') + '/' + o.reverse().join('/') + tr;
bgneal@45: },
bgneal@45:
bgneal@45: getURI : function(nh) {
bgneal@45: var s, t = this;
bgneal@45:
bgneal@45: // Rebuild source
bgneal@45: if (!t.source || nh) {
bgneal@45: s = '';
bgneal@45:
bgneal@45: if (!nh) {
bgneal@45: if (t.protocol)
bgneal@45: s += t.protocol + '://';
bgneal@45:
bgneal@45: if (t.userInfo)
bgneal@45: s += t.userInfo + '@';
bgneal@45:
bgneal@45: if (t.host)
bgneal@45: s += t.host;
bgneal@45:
bgneal@45: if (t.port)
bgneal@45: s += ':' + t.port;
bgneal@45: }
bgneal@45:
bgneal@45: if (t.path)
bgneal@45: s += t.path;
bgneal@45:
bgneal@45: if (t.query)
bgneal@45: s += '?' + t.query;
bgneal@45:
bgneal@45: if (t.anchor)
bgneal@45: s += '#' + t.anchor;
bgneal@45:
bgneal@45: t.source = s;
bgneal@45: }
bgneal@45:
bgneal@45: return t.source;
bgneal@45: }
bgneal@45:
bgneal@45: });
bgneal@45: })();
bgneal@45: (function() {
bgneal@45: var each = tinymce.each;
bgneal@45:
bgneal@45: tinymce.create('static tinymce.util.Cookie', {
bgneal@45: getHash : function(n) {
bgneal@45: var v = this.get(n), h;
bgneal@45:
bgneal@45: if (v) {
bgneal@45: each(v.split('&'), function(v) {
bgneal@45: v = v.split('=');
bgneal@45: h = h || {};
bgneal@45: h[unescape(v[0])] = unescape(v[1]);
bgneal@45: });
bgneal@45: }
bgneal@45:
bgneal@45: return h;
bgneal@45: },
bgneal@45:
bgneal@45: setHash : function(n, v, e, p, d, s) {
bgneal@45: var o = '';
bgneal@45:
bgneal@45: each(v, function(v, k) {
bgneal@45: o += (!o ? '' : '&') + escape(k) + '=' + escape(v);
bgneal@45: });
bgneal@45:
bgneal@45: this.set(n, o, e, p, d, s);
bgneal@45: },
bgneal@45:
bgneal@45: get : function(n) {
bgneal@45: var c = document.cookie, e, p = n + "=", b;
bgneal@45:
bgneal@45: // Strict mode
bgneal@45: if (!c)
bgneal@45: return;
bgneal@45:
bgneal@45: b = c.indexOf("; " + p);
bgneal@45:
bgneal@45: if (b == -1) {
bgneal@45: b = c.indexOf(p);
bgneal@45:
bgneal@45: if (b != 0)
bgneal@45: return null;
bgneal@45: } else
bgneal@45: b += 2;
bgneal@45:
bgneal@45: e = c.indexOf(";", b);
bgneal@45:
bgneal@45: if (e == -1)
bgneal@45: e = c.length;
bgneal@45:
bgneal@45: return unescape(c.substring(b + p.length, e));
bgneal@45: },
bgneal@45:
bgneal@45: set : function(n, v, e, p, d, s) {
bgneal@45: document.cookie = n + "=" + escape(v) +
bgneal@45: ((e) ? "; expires=" + e.toGMTString() : "") +
bgneal@45: ((p) ? "; path=" + escape(p) : "") +
bgneal@45: ((d) ? "; domain=" + d : "") +
bgneal@45: ((s) ? "; secure" : "");
bgneal@45: },
bgneal@45:
bgneal@45: remove : function(n, p) {
bgneal@45: var d = new Date();
bgneal@45:
bgneal@45: d.setTime(d.getTime() - 1000);
bgneal@45:
bgneal@45: this.set(n, '', d, p, d);
bgneal@45: }
bgneal@45:
bgneal@45: });
bgneal@45: })();
bgneal@45: tinymce.create('static tinymce.util.JSON', {
bgneal@45: serialize : function(o) {
bgneal@45: var i, v, s = tinymce.util.JSON.serialize, t;
bgneal@45:
bgneal@45: if (o == null)
bgneal@45: return 'null';
bgneal@45:
bgneal@45: t = typeof o;
bgneal@45:
bgneal@45: if (t == 'string') {
bgneal@45: v = '\bb\tt\nn\ff\rr\""\'\'\\\\';
bgneal@45:
bgneal@45: return '"' + o.replace(/([\u0080-\uFFFF\x00-\x1f\"])/g, function(a, b) {
bgneal@45: i = v.indexOf(b);
bgneal@45:
bgneal@45: if (i + 1)
bgneal@45: return '\\' + v.charAt(i + 1);
bgneal@45:
bgneal@45: a = b.charCodeAt().toString(16);
bgneal@45:
bgneal@45: return '\\u' + '0000'.substring(a.length) + a;
bgneal@45: }) + '"';
bgneal@45: }
bgneal@45:
bgneal@45: if (t == 'object') {
bgneal@45: if (o.hasOwnProperty && o instanceof Array) {
bgneal@45: for (i=0, v = '['; i 0 ? ',' : '') + s(o[i]);
bgneal@45:
bgneal@45: return v + ']';
bgneal@45: }
bgneal@45:
bgneal@45: v = '{';
bgneal@45:
bgneal@45: for (i in o)
bgneal@45: v += typeof o[i] != 'function' ? (v.length > 1 ? ',"' : '"') + i + '":' + s(o[i]) : '';
bgneal@45:
bgneal@45: return v + '}';
bgneal@45: }
bgneal@45:
bgneal@45: return '' + o;
bgneal@45: },
bgneal@45:
bgneal@45: parse : function(s) {
bgneal@45: try {
bgneal@45: return eval('(' + s + ')');
bgneal@45: } catch (ex) {
bgneal@45: // Ignore
bgneal@45: }
bgneal@45: }
bgneal@45:
bgneal@45: });
bgneal@45: tinymce.create('static tinymce.util.XHR', {
bgneal@45: send : function(o) {
bgneal@45: var x, t, w = window, c = 0;
bgneal@45:
bgneal@45: // Default settings
bgneal@45: o.scope = o.scope || this;
bgneal@45: o.success_scope = o.success_scope || o.scope;
bgneal@45: o.error_scope = o.error_scope || o.scope;
bgneal@45: o.async = o.async === false ? false : true;
bgneal@45: o.data = o.data || '';
bgneal@45:
bgneal@45: function get(s) {
bgneal@45: x = 0;
bgneal@45:
bgneal@45: try {
bgneal@45: x = new ActiveXObject(s);
bgneal@45: } catch (ex) {
bgneal@45: }
bgneal@45:
bgneal@45: return x;
bgneal@45: };
bgneal@45:
bgneal@45: x = w.XMLHttpRequest ? new XMLHttpRequest() : get('Microsoft.XMLHTTP') || get('Msxml2.XMLHTTP');
bgneal@45:
bgneal@45: if (x) {
bgneal@45: if (x.overrideMimeType)
bgneal@45: x.overrideMimeType(o.content_type);
bgneal@45:
bgneal@45: x.open(o.type || (o.data ? 'POST' : 'GET'), o.url, o.async);
bgneal@45:
bgneal@45: if (o.content_type)
bgneal@45: x.setRequestHeader('Content-Type', o.content_type);
bgneal@45:
bgneal@45: x.send(o.data);
bgneal@45:
bgneal@45: function ready() {
bgneal@45: if (!o.async || x.readyState == 4 || c++ > 10000) {
bgneal@45: if (o.success && c < 10000 && x.status == 200)
bgneal@45: o.success.call(o.success_scope, '' + x.responseText, x, o);
bgneal@45: else if (o.error)
bgneal@45: o.error.call(o.error_scope, c > 10000 ? 'TIMED_OUT' : 'GENERAL', x, o);
bgneal@45:
bgneal@45: x = null;
bgneal@45: } else
bgneal@45: w.setTimeout(ready, 10);
bgneal@45: };
bgneal@45:
bgneal@45: // Syncronous request
bgneal@45: if (!o.async)
bgneal@45: return ready();
bgneal@45:
bgneal@45: // Wait for response, onReadyStateChange can not be used since it leaks memory in IE
bgneal@45: t = w.setTimeout(ready, 10);
bgneal@45: }
bgneal@45:
bgneal@45: }
bgneal@45: });
bgneal@45: (function() {
bgneal@45: var extend = tinymce.extend, JSON = tinymce.util.JSON, XHR = tinymce.util.XHR;
bgneal@45:
bgneal@45: tinymce.create('tinymce.util.JSONRequest', {
bgneal@45: JSONRequest : function(s) {
bgneal@45: this.settings = extend({
bgneal@45: }, s);
bgneal@45: this.count = 0;
bgneal@45: },
bgneal@45:
bgneal@45: send : function(o) {
bgneal@45: var ecb = o.error, scb = o.success;
bgneal@45:
bgneal@45: o = extend(this.settings, o);
bgneal@45:
bgneal@45: o.success = function(c, x) {
bgneal@45: c = JSON.parse(c);
bgneal@45:
bgneal@45: if (typeof(c) == 'undefined') {
bgneal@45: c = {
bgneal@45: error : 'JSON Parse error.'
bgneal@45: };
bgneal@45: }
bgneal@45:
bgneal@45: if (c.error)
bgneal@45: ecb.call(o.error_scope || o.scope, c.error, x);
bgneal@45: else
bgneal@45: scb.call(o.success_scope || o.scope, c.result);
bgneal@45: };
bgneal@45:
bgneal@45: o.error = function(ty, x) {
bgneal@45: ecb.call(o.error_scope || o.scope, ty, x);
bgneal@45: };
bgneal@45:
bgneal@45: o.data = JSON.serialize({
bgneal@45: id : o.id || 'c' + (this.count++),
bgneal@45: method : o.method,
bgneal@45: params : o.params
bgneal@45: });
bgneal@45:
bgneal@45: // JSON content type for Ruby on rails. Bug: #1883287
bgneal@45: o.content_type = 'application/json';
bgneal@45:
bgneal@45: XHR.send(o);
bgneal@45: },
bgneal@45:
bgneal@45: 'static' : {
bgneal@45: sendRPC : function(o) {
bgneal@45: return new tinymce.util.JSONRequest().send(o);
bgneal@45: }
bgneal@45: }
bgneal@45:
bgneal@45: });
bgneal@45: }());(function(tinymce) {
bgneal@45: // Shorten names
bgneal@45: var each = tinymce.each, is = tinymce.is;
bgneal@45: var isWebKit = tinymce.isWebKit, isIE = tinymce.isIE;
bgneal@45:
bgneal@45: tinymce.create('tinymce.dom.DOMUtils', {
bgneal@45: doc : null,
bgneal@45: root : null,
bgneal@45: files : null,
bgneal@45: pixelStyles : /^(top|left|bottom|right|width|height|borderWidth)$/,
bgneal@45: props : {
bgneal@45: "for" : "htmlFor",
bgneal@45: "class" : "className",
bgneal@45: className : "className",
bgneal@45: checked : "checked",
bgneal@45: disabled : "disabled",
bgneal@45: maxlength : "maxLength",
bgneal@45: readonly : "readOnly",
bgneal@45: selected : "selected",
bgneal@45: value : "value",
bgneal@45: id : "id",
bgneal@45: name : "name",
bgneal@45: type : "type"
bgneal@45: },
bgneal@45:
bgneal@45: DOMUtils : function(d, s) {
bgneal@45: var t = this;
bgneal@45:
bgneal@45: t.doc = d;
bgneal@45: t.win = window;
bgneal@45: t.files = {};
bgneal@45: t.cssFlicker = false;
bgneal@45: t.counter = 0;
bgneal@45: t.boxModel = !tinymce.isIE || d.compatMode == "CSS1Compat";
bgneal@45: t.stdMode = d.documentMode === 8;
bgneal@45:
bgneal@45: this.settings = s = tinymce.extend({
bgneal@45: keep_values : false,
bgneal@45: hex_colors : 1,
bgneal@45: process_html : 1
bgneal@45: }, s);
bgneal@45:
bgneal@45: // Fix IE6SP2 flicker and check it failed for pre SP2
bgneal@45: if (tinymce.isIE6) {
bgneal@45: try {
bgneal@45: d.execCommand('BackgroundImageCache', false, true);
bgneal@45: } catch (e) {
bgneal@45: t.cssFlicker = true;
bgneal@45: }
bgneal@45: }
bgneal@45:
bgneal@45: tinymce.addUnload(t.destroy, t);
bgneal@45: },
bgneal@45:
bgneal@45: getRoot : function() {
bgneal@45: var t = this, s = t.settings;
bgneal@45:
bgneal@45: return (s && t.get(s.root_element)) || t.doc.body;
bgneal@45: },
bgneal@45:
bgneal@45: getViewPort : function(w) {
bgneal@45: var d, b;
bgneal@45:
bgneal@45: w = !w ? this.win : w;
bgneal@45: d = w.document;
bgneal@45: b = this.boxModel ? d.documentElement : d.body;
bgneal@45:
bgneal@45: // Returns viewport size excluding scrollbars
bgneal@45: return {
bgneal@45: x : w.pageXOffset || b.scrollLeft,
bgneal@45: y : w.pageYOffset || b.scrollTop,
bgneal@45: w : w.innerWidth || b.clientWidth,
bgneal@45: h : w.innerHeight || b.clientHeight
bgneal@45: };
bgneal@45: },
bgneal@45:
bgneal@45: getRect : function(e) {
bgneal@45: var p, t = this, sr;
bgneal@45:
bgneal@45: e = t.get(e);
bgneal@45: p = t.getPos(e);
bgneal@45: sr = t.getSize(e);
bgneal@45:
bgneal@45: return {
bgneal@45: x : p.x,
bgneal@45: y : p.y,
bgneal@45: w : sr.w,
bgneal@45: h : sr.h
bgneal@45: };
bgneal@45: },
bgneal@45:
bgneal@45: getSize : function(e) {
bgneal@45: var t = this, w, h;
bgneal@45:
bgneal@45: e = t.get(e);
bgneal@45: w = t.getStyle(e, 'width');
bgneal@45: h = t.getStyle(e, 'height');
bgneal@45:
bgneal@45: // Non pixel value, then force offset/clientWidth
bgneal@45: if (w.indexOf('px') === -1)
bgneal@45: w = 0;
bgneal@45:
bgneal@45: // Non pixel value, then force offset/clientWidth
bgneal@45: if (h.indexOf('px') === -1)
bgneal@45: h = 0;
bgneal@45:
bgneal@45: return {
bgneal@45: w : parseInt(w) || e.offsetWidth || e.clientWidth,
bgneal@45: h : parseInt(h) || e.offsetHeight || e.clientHeight
bgneal@45: };
bgneal@45: },
bgneal@45:
bgneal@45: is : function(n, patt) {
bgneal@45: return tinymce.dom.Sizzle.matches(patt, n.nodeType ? [n] : n).length > 0;
bgneal@45: },
bgneal@45:
bgneal@45: getParent : function(n, f, r) {
bgneal@45: return this.getParents(n, f, r, false);
bgneal@45: },
bgneal@45:
bgneal@45: getParents : function(n, f, r, c) {
bgneal@45: var t = this, na, se = t.settings, o = [];
bgneal@45:
bgneal@45: n = t.get(n);
bgneal@45: c = c === undefined;
bgneal@45:
bgneal@45: if (se.strict_root)
bgneal@45: r = r || t.getRoot();
bgneal@45:
bgneal@45: // Wrap node name as func
bgneal@45: if (is(f, 'string')) {
bgneal@45: na = f;
bgneal@45:
bgneal@45: if (f === '*') {
bgneal@45: f = function(n) {return n.nodeType == 1;};
bgneal@45: } else {
bgneal@45: f = function(n) {
bgneal@45: return t.is(n, na);
bgneal@45: };
bgneal@45: }
bgneal@45: }
bgneal@45:
bgneal@45: while (n) {
bgneal@45: if (n == r)
bgneal@45: break;
bgneal@45:
bgneal@45: if (!f || f(n)) {
bgneal@45: if (c)
bgneal@45: o.push(n);
bgneal@45: else
bgneal@45: return n;
bgneal@45: }
bgneal@45:
bgneal@45: n = n.parentNode;
bgneal@45: }
bgneal@45:
bgneal@45: return c ? o : null;
bgneal@45: },
bgneal@45:
bgneal@45: get : function(e) {
bgneal@45: var n;
bgneal@45:
bgneal@45: if (e && this.doc && typeof(e) == 'string') {
bgneal@45: n = e;
bgneal@45: e = this.doc.getElementById(e);
bgneal@45:
bgneal@45: // IE and Opera returns meta elements when they match the specified input ID, but getElementsByName seems to do the trick
bgneal@45: if (e && e.id !== n)
bgneal@45: return this.doc.getElementsByName(n)[1];
bgneal@45: }
bgneal@45:
bgneal@45: return e;
bgneal@45: },
bgneal@45:
bgneal@45:
bgneal@45: select : function(pa, s) {
bgneal@45: var t = this;
bgneal@45:
bgneal@45: return tinymce.dom.Sizzle(pa, t.get(s) || t.get(t.settings.root_element) || t.doc, []);
bgneal@45: },
bgneal@45:
bgneal@45:
bgneal@45: add : function(p, n, a, h, c) {
bgneal@45: var t = this;
bgneal@45:
bgneal@45: return this.run(p, function(p) {
bgneal@45: var e, k;
bgneal@45:
bgneal@45: e = is(n, 'string') ? t.doc.createElement(n) : n;
bgneal@45: t.setAttribs(e, a);
bgneal@45:
bgneal@45: if (h) {
bgneal@45: if (h.nodeType)
bgneal@45: e.appendChild(h);
bgneal@45: else
bgneal@45: t.setHTML(e, h);
bgneal@45: }
bgneal@45:
bgneal@45: return !c ? p.appendChild(e) : e;
bgneal@45: });
bgneal@45: },
bgneal@45:
bgneal@45: create : function(n, a, h) {
bgneal@45: return this.add(this.doc.createElement(n), n, a, h, 1);
bgneal@45: },
bgneal@45:
bgneal@45: createHTML : function(n, a, h) {
bgneal@45: var o = '', t = this, k;
bgneal@45:
bgneal@45: o += '<' + n;
bgneal@45:
bgneal@45: for (k in a) {
bgneal@45: if (a.hasOwnProperty(k))
bgneal@45: o += ' ' + k + '="' + t.encode(a[k]) + '"';
bgneal@45: }
bgneal@45:
bgneal@45: if (tinymce.is(h))
bgneal@45: return o + '>' + h + '' + n + '>';
bgneal@45:
bgneal@45: return o + ' />';
bgneal@45: },
bgneal@45:
bgneal@45: remove : function(n, k) {
bgneal@45: var t = this;
bgneal@45:
bgneal@45: return this.run(n, function(n) {
bgneal@45: var p, g, i;
bgneal@45:
bgneal@45: p = n.parentNode;
bgneal@45:
bgneal@45: if (!p)
bgneal@45: return null;
bgneal@45:
bgneal@45: if (k) {
bgneal@45: for (i = n.childNodes.length - 1; i >= 0; i--)
bgneal@45: t.insertAfter(n.childNodes[i], n);
bgneal@45:
bgneal@45: //each(n.childNodes, function(c) {
bgneal@45: // p.insertBefore(c.cloneNode(true), n);
bgneal@45: //});
bgneal@45: }
bgneal@45:
bgneal@45: // Fix IE psuedo leak
bgneal@45: if (t.fixPsuedoLeaks) {
bgneal@45: p = n.cloneNode(true);
bgneal@45: k = 'IELeakGarbageBin';
bgneal@45: g = t.get(k) || t.add(t.doc.body, 'div', {id : k, style : 'display:none'});
bgneal@45: g.appendChild(n);
bgneal@45: g.innerHTML = '';
bgneal@45:
bgneal@45: return p;
bgneal@45: }
bgneal@45:
bgneal@45: return p.removeChild(n);
bgneal@45: });
bgneal@45: },
bgneal@45:
bgneal@45:
bgneal@45: setStyle : function(n, na, v) {
bgneal@45: var t = this;
bgneal@45:
bgneal@45: return t.run(n, function(e) {
bgneal@45: var s, i;
bgneal@45:
bgneal@45: s = e.style;
bgneal@45:
bgneal@45: // Camelcase it, if needed
bgneal@45: na = na.replace(/-(\D)/g, function(a, b){
bgneal@45: return b.toUpperCase();
bgneal@45: });
bgneal@45:
bgneal@45: // Default px suffix on these
bgneal@45: if (t.pixelStyles.test(na) && (tinymce.is(v, 'number') || /^[\-0-9\.]+$/.test(v)))
bgneal@45: v += 'px';
bgneal@45:
bgneal@45: switch (na) {
bgneal@45: case 'opacity':
bgneal@45: // IE specific opacity
bgneal@45: if (isIE) {
bgneal@45: s.filter = v === '' ? '' : "alpha(opacity=" + (v * 100) + ")";
bgneal@45:
bgneal@45: if (!n.currentStyle || !n.currentStyle.hasLayout)
bgneal@45: s.display = 'inline-block';
bgneal@45: }
bgneal@45:
bgneal@45: // Fix for older browsers
bgneal@45: s[na] = s['-moz-opacity'] = s['-khtml-opacity'] = v || '';
bgneal@45: break;
bgneal@45:
bgneal@45: case 'float':
bgneal@45: isIE ? s.styleFloat = v : s.cssFloat = v;
bgneal@45: break;
bgneal@45:
bgneal@45: default:
bgneal@45: s[na] = v || '';
bgneal@45: }
bgneal@45:
bgneal@45: // Force update of the style data
bgneal@45: if (t.settings.update_styles)
bgneal@45: t.setAttrib(e, 'mce_style');
bgneal@45: });
bgneal@45: },
bgneal@45:
bgneal@45: getStyle : function(n, na, c) {
bgneal@45: n = this.get(n);
bgneal@45:
bgneal@45: if (!n)
bgneal@45: return false;
bgneal@45:
bgneal@45: // Gecko
bgneal@45: if (this.doc.defaultView && c) {
bgneal@45: // Remove camelcase
bgneal@45: na = na.replace(/[A-Z]/g, function(a){
bgneal@45: return '-' + a;
bgneal@45: });
bgneal@45:
bgneal@45: try {
bgneal@45: return this.doc.defaultView.getComputedStyle(n, null).getPropertyValue(na);
bgneal@45: } catch (ex) {
bgneal@45: // Old safari might fail
bgneal@45: return null;
bgneal@45: }
bgneal@45: }
bgneal@45:
bgneal@45: // Camelcase it, if needed
bgneal@45: na = na.replace(/-(\D)/g, function(a, b){
bgneal@45: return b.toUpperCase();
bgneal@45: });
bgneal@45:
bgneal@45: if (na == 'float')
bgneal@45: na = isIE ? 'styleFloat' : 'cssFloat';
bgneal@45:
bgneal@45: // IE & Opera
bgneal@45: if (n.currentStyle && c)
bgneal@45: return n.currentStyle[na];
bgneal@45:
bgneal@45: return n.style[na];
bgneal@45: },
bgneal@45:
bgneal@45: setStyles : function(e, o) {
bgneal@45: var t = this, s = t.settings, ol;
bgneal@45:
bgneal@45: ol = s.update_styles;
bgneal@45: s.update_styles = 0;
bgneal@45:
bgneal@45: each(o, function(v, n) {
bgneal@45: t.setStyle(e, n, v);
bgneal@45: });
bgneal@45:
bgneal@45: // Update style info
bgneal@45: s.update_styles = ol;
bgneal@45: if (s.update_styles)
bgneal@45: t.setAttrib(e, s.cssText);
bgneal@45: },
bgneal@45:
bgneal@45: setAttrib : function(e, n, v) {
bgneal@45: var t = this;
bgneal@45:
bgneal@45: // Whats the point
bgneal@45: if (!e || !n)
bgneal@45: return;
bgneal@45:
bgneal@45: // Strict XML mode
bgneal@45: if (t.settings.strict)
bgneal@45: n = n.toLowerCase();
bgneal@45:
bgneal@45: return this.run(e, function(e) {
bgneal@45: var s = t.settings;
bgneal@45:
bgneal@45: switch (n) {
bgneal@45: case "style":
bgneal@45: if (!is(v, 'string')) {
bgneal@45: each(v, function(v, n) {
bgneal@45: t.setStyle(e, n, v);
bgneal@45: });
bgneal@45:
bgneal@45: return;
bgneal@45: }
bgneal@45:
bgneal@45: // No mce_style for elements with these since they might get resized by the user
bgneal@45: if (s.keep_values) {
bgneal@45: if (v && !t._isRes(v))
bgneal@45: e.setAttribute('mce_style', v, 2);
bgneal@45: else
bgneal@45: e.removeAttribute('mce_style', 2);
bgneal@45: }
bgneal@45:
bgneal@45: e.style.cssText = v;
bgneal@45: break;
bgneal@45:
bgneal@45: case "class":
bgneal@45: e.className = v || ''; // Fix IE null bug
bgneal@45: break;
bgneal@45:
bgneal@45: case "src":
bgneal@45: case "href":
bgneal@45: if (s.keep_values) {
bgneal@45: if (s.url_converter)
bgneal@45: v = s.url_converter.call(s.url_converter_scope || t, v, n, e);
bgneal@45:
bgneal@45: t.setAttrib(e, 'mce_' + n, v, 2);
bgneal@45: }
bgneal@45:
bgneal@45: break;
bgneal@45:
bgneal@45: case "shape":
bgneal@45: e.setAttribute('mce_style', v);
bgneal@45: break;
bgneal@45: }
bgneal@45:
bgneal@45: if (is(v) && v !== null && v.length !== 0)
bgneal@45: e.setAttribute(n, '' + v, 2);
bgneal@45: else
bgneal@45: e.removeAttribute(n, 2);
bgneal@45: });
bgneal@45: },
bgneal@45:
bgneal@45: setAttribs : function(e, o) {
bgneal@45: var t = this;
bgneal@45:
bgneal@45: return this.run(e, function(e) {
bgneal@45: each(o, function(v, n) {
bgneal@45: t.setAttrib(e, n, v);
bgneal@45: });
bgneal@45: });
bgneal@45: },
bgneal@45:
bgneal@45:
bgneal@45: getAttrib : function(e, n, dv) {
bgneal@45: var v, t = this;
bgneal@45:
bgneal@45: e = t.get(e);
bgneal@45:
bgneal@45: if (!e || e.nodeType !== 1)
bgneal@45: return false;
bgneal@45:
bgneal@45: if (!is(dv))
bgneal@45: dv = '';
bgneal@45:
bgneal@45: // Try the mce variant for these
bgneal@45: if (/^(src|href|style|coords|shape)$/.test(n)) {
bgneal@45: v = e.getAttribute("mce_" + n);
bgneal@45:
bgneal@45: if (v)
bgneal@45: return v;
bgneal@45: }
bgneal@45:
bgneal@45: if (isIE && t.props[n]) {
bgneal@45: v = e[t.props[n]];
bgneal@45: v = v && v.nodeValue ? v.nodeValue : v;
bgneal@45: }
bgneal@45:
bgneal@45: if (!v)
bgneal@45: v = e.getAttribute(n, 2);
bgneal@45:
bgneal@45: if (n === 'style') {
bgneal@45: v = v || e.style.cssText;
bgneal@45:
bgneal@45: if (v) {
bgneal@45: v = t.serializeStyle(t.parseStyle(v));
bgneal@45:
bgneal@45: if (t.settings.keep_values && !t._isRes(v))
bgneal@45: e.setAttribute('mce_style', v);
bgneal@45: }
bgneal@45: }
bgneal@45:
bgneal@45: // Remove Apple and WebKit stuff
bgneal@45: if (isWebKit && n === "class" && v)
bgneal@45: v = v.replace(/(apple|webkit)\-[a-z\-]+/gi, '');
bgneal@45:
bgneal@45: // Handle IE issues
bgneal@45: if (isIE) {
bgneal@45: switch (n) {
bgneal@45: case 'rowspan':
bgneal@45: case 'colspan':
bgneal@45: // IE returns 1 as default value
bgneal@45: if (v === 1)
bgneal@45: v = '';
bgneal@45:
bgneal@45: break;
bgneal@45:
bgneal@45: case 'size':
bgneal@45: // IE returns +0 as default value for size
bgneal@45: if (v === '+0' || v === 20 || v === 0)
bgneal@45: v = '';
bgneal@45:
bgneal@45: break;
bgneal@45:
bgneal@45: case 'width':
bgneal@45: case 'height':
bgneal@45: case 'vspace':
bgneal@45: case 'checked':
bgneal@45: case 'disabled':
bgneal@45: case 'readonly':
bgneal@45: if (v === 0)
bgneal@45: v = '';
bgneal@45:
bgneal@45: break;
bgneal@45:
bgneal@45: case 'hspace':
bgneal@45: // IE returns -1 as default value
bgneal@45: if (v === -1)
bgneal@45: v = '';
bgneal@45:
bgneal@45: break;
bgneal@45:
bgneal@45: case 'maxlength':
bgneal@45: case 'tabindex':
bgneal@45: // IE returns default value
bgneal@45: if (v === 32768 || v === 2147483647 || v === '32768')
bgneal@45: v = '';
bgneal@45:
bgneal@45: break;
bgneal@45:
bgneal@45: case 'multiple':
bgneal@45: case 'compact':
bgneal@45: case 'noshade':
bgneal@45: case 'nowrap':
bgneal@45: if (v === 65535)
bgneal@45: return n;
bgneal@45:
bgneal@45: return dv;
bgneal@45:
bgneal@45: case 'shape':
bgneal@45: v = v.toLowerCase();
bgneal@45: break;
bgneal@45:
bgneal@45: default:
bgneal@45: // IE has odd anonymous function for event attributes
bgneal@45: if (n.indexOf('on') === 0 && v)
bgneal@45: v = ('' + v).replace(/^function\s+anonymous\(\)\s+\{\s+(.*)\s+\}$/, '$1');
bgneal@45: }
bgneal@45: }
bgneal@45:
bgneal@45: return (v !== undefined && v !== null && v !== '') ? '' + v : dv;
bgneal@45: },
bgneal@45:
bgneal@45: getPos : function(n) {
bgneal@45: var t = this, x = 0, y = 0, e, d = t.doc, r;
bgneal@45:
bgneal@45: n = t.get(n);
bgneal@45:
bgneal@45: // Use getBoundingClientRect on IE, Opera has it but it's not perfect
bgneal@45: if (n && isIE && !t.stdMode) {
bgneal@45: n = n.getBoundingClientRect();
bgneal@45: e = t.boxModel ? d.documentElement : d.body;
bgneal@45: x = t.getStyle(t.select('html')[0], 'borderWidth'); // Remove border
bgneal@45: x = (x == 'medium' || t.boxModel && !t.isIE6) && 2 || x;
bgneal@45: n.top += t.win.self != t.win.top ? 2 : 0; // IE adds some strange extra cord if used in a frameset
bgneal@45:
bgneal@45: return {x : n.left + e.scrollLeft - x, y : n.top + e.scrollTop - x};
bgneal@45: }
bgneal@45:
bgneal@45: r = n;
bgneal@45: while (r) {
bgneal@45: x += r.offsetLeft || 0;
bgneal@45: y += r.offsetTop || 0;
bgneal@45: r = r.offsetParent;
bgneal@45: }
bgneal@45:
bgneal@45: r = n;
bgneal@45: while (r) {
bgneal@45: // Opera 9.25 bug fix, fixed in 9.50
bgneal@45: if (!/^table-row|inline.*/i.test(t.getStyle(r, "display", 1))) {
bgneal@45: x -= r.scrollLeft || 0;
bgneal@45: y -= r.scrollTop || 0;
bgneal@45: }
bgneal@45:
bgneal@45: r = r.parentNode;
bgneal@45:
bgneal@45: // No node type or document type
bgneal@45: if (!r.nodeType || r.nodeType == 9 || r.nodeName.toLowerCase() == 'body')
bgneal@45: break;
bgneal@45: }
bgneal@45:
bgneal@45: return {x : x, y : y};
bgneal@45: },
bgneal@45:
bgneal@45: parseStyle : function(st) {
bgneal@45: var t = this, s = t.settings, o = {};
bgneal@45:
bgneal@45: if (!st)
bgneal@45: return o;
bgneal@45:
bgneal@45: function compress(p, s, ot) {
bgneal@45: var t, r, b, l;
bgneal@45:
bgneal@45: // Get values and check it it needs compressing
bgneal@45: t = o[p + '-top' + s];
bgneal@45: if (!t)
bgneal@45: return;
bgneal@45:
bgneal@45: r = o[p + '-right' + s];
bgneal@45: if (t != r)
bgneal@45: return;
bgneal@45:
bgneal@45: b = o[p + '-bottom' + s];
bgneal@45: if (r != b)
bgneal@45: return;
bgneal@45:
bgneal@45: l = o[p + '-left' + s];
bgneal@45: if (b != l)
bgneal@45: return;
bgneal@45:
bgneal@45: // Compress
bgneal@45: o[ot] = l;
bgneal@45: delete o[p + '-top' + s];
bgneal@45: delete o[p + '-right' + s];
bgneal@45: delete o[p + '-bottom' + s];
bgneal@45: delete o[p + '-left' + s];
bgneal@45: };
bgneal@45:
bgneal@45: function compress2(ta, a, b, c) {
bgneal@45: var t;
bgneal@45:
bgneal@45: t = o[a];
bgneal@45: if (!t)
bgneal@45: return;
bgneal@45:
bgneal@45: t = o[b];
bgneal@45: if (!t)
bgneal@45: return;
bgneal@45:
bgneal@45: t = o[c];
bgneal@45: if (!t)
bgneal@45: return;
bgneal@45:
bgneal@45: // Compress
bgneal@45: o[ta] = o[a] + ' ' + o[b] + ' ' + o[c];
bgneal@45: delete o[a];
bgneal@45: delete o[b];
bgneal@45: delete o[c];
bgneal@45: };
bgneal@45:
bgneal@45: st = st.replace(/&(#?[a-z0-9]+);/g, '&$1_MCE_SEMI_'); // Protect entities
bgneal@45:
bgneal@45: each(st.split(';'), function(v) {
bgneal@45: var sv, ur = [];
bgneal@45:
bgneal@45: if (v) {
bgneal@45: v = v.replace(/_MCE_SEMI_/g, ';'); // Restore entities
bgneal@45: v = v.replace(/url\([^\)]+\)/g, function(v) {ur.push(v);return 'url(' + ur.length + ')';});
bgneal@45: v = v.split(':');
bgneal@45: sv = tinymce.trim(v[1]);
bgneal@45: sv = sv.replace(/url\(([^\)]+)\)/g, function(a, b) {return ur[parseInt(b) - 1];});
bgneal@45:
bgneal@45: sv = sv.replace(/rgb\([^\)]+\)/g, function(v) {
bgneal@45: return t.toHex(v);
bgneal@45: });
bgneal@45:
bgneal@45: if (s.url_converter) {
bgneal@45: sv = sv.replace(/url\([\'\"]?([^\)\'\"]+)[\'\"]?\)/g, function(x, c) {
bgneal@45: return 'url(' + s.url_converter.call(s.url_converter_scope || t, t.decode(c), 'style', null) + ')';
bgneal@45: });
bgneal@45: }
bgneal@45:
bgneal@45: o[tinymce.trim(v[0]).toLowerCase()] = sv;
bgneal@45: }
bgneal@45: });
bgneal@45:
bgneal@45: compress("border", "", "border");
bgneal@45: compress("border", "-width", "border-width");
bgneal@45: compress("border", "-color", "border-color");
bgneal@45: compress("border", "-style", "border-style");
bgneal@45: compress("padding", "", "padding");
bgneal@45: compress("margin", "", "margin");
bgneal@45: compress2('border', 'border-width', 'border-style', 'border-color');
bgneal@45:
bgneal@45: if (isIE) {
bgneal@45: // Remove pointless border
bgneal@45: if (o.border == 'medium none')
bgneal@45: o.border = '';
bgneal@45: }
bgneal@45:
bgneal@45: return o;
bgneal@45: },
bgneal@45:
bgneal@45: serializeStyle : function(o) {
bgneal@45: var s = '';
bgneal@45:
bgneal@45: each(o, function(v, k) {
bgneal@45: if (k && v) {
bgneal@45: if (tinymce.isGecko && k.indexOf('-moz-') === 0)
bgneal@45: return;
bgneal@45:
bgneal@45: switch (k) {
bgneal@45: case 'color':
bgneal@45: case 'background-color':
bgneal@45: v = v.toLowerCase();
bgneal@45: break;
bgneal@45: }
bgneal@45:
bgneal@45: s += (s ? ' ' : '') + k + ': ' + v + ';';
bgneal@45: }
bgneal@45: });
bgneal@45:
bgneal@45: return s;
bgneal@45: },
bgneal@45:
bgneal@45: loadCSS : function(u) {
bgneal@45: var t = this, d = t.doc;
bgneal@45:
bgneal@45: if (!u)
bgneal@45: u = '';
bgneal@45:
bgneal@45: each(u.split(','), function(u) {
bgneal@45: if (t.files[u])
bgneal@45: return;
bgneal@45:
bgneal@45: t.files[u] = true;
bgneal@45: t.add(t.select('head')[0], 'link', {rel : 'stylesheet', href : tinymce._addVer(u)});
bgneal@45: });
bgneal@45: },
bgneal@45:
bgneal@45:
bgneal@45: addClass : function(e, c) {
bgneal@45: return this.run(e, function(e) {
bgneal@45: var o;
bgneal@45:
bgneal@45: if (!c)
bgneal@45: return 0;
bgneal@45:
bgneal@45: if (this.hasClass(e, c))
bgneal@45: return e.className;
bgneal@45:
bgneal@45: o = this.removeClass(e, c);
bgneal@45:
bgneal@45: return e.className = (o != '' ? (o + ' ') : '') + c;
bgneal@45: });
bgneal@45: },
bgneal@45:
bgneal@45: removeClass : function(e, c) {
bgneal@45: var t = this, re;
bgneal@45:
bgneal@45: return t.run(e, function(e) {
bgneal@45: var v;
bgneal@45:
bgneal@45: if (t.hasClass(e, c)) {
bgneal@45: if (!re)
bgneal@45: re = new RegExp("(^|\\s+)" + c + "(\\s+|$)", "g");
bgneal@45:
bgneal@45: v = e.className.replace(re, ' ');
bgneal@45:
bgneal@45: return e.className = tinymce.trim(v != ' ' ? v : '');
bgneal@45: }
bgneal@45:
bgneal@45: return e.className;
bgneal@45: });
bgneal@45: },
bgneal@45:
bgneal@45: hasClass : function(n, c) {
bgneal@45: n = this.get(n);
bgneal@45:
bgneal@45: if (!n || !c)
bgneal@45: return false;
bgneal@45:
bgneal@45: return (' ' + n.className + ' ').indexOf(' ' + c + ' ') !== -1;
bgneal@45: },
bgneal@45:
bgneal@45: show : function(e) {
bgneal@45: return this.setStyle(e, 'display', 'block');
bgneal@45: },
bgneal@45:
bgneal@45: hide : function(e) {
bgneal@45: return this.setStyle(e, 'display', 'none');
bgneal@45: },
bgneal@45:
bgneal@45: isHidden : function(e) {
bgneal@45: e = this.get(e);
bgneal@45:
bgneal@45: return !e || e.style.display == 'none' || this.getStyle(e, 'display') == 'none';
bgneal@45: },
bgneal@45:
bgneal@45:
bgneal@45: uniqueId : function(p) {
bgneal@45: return (!p ? 'mce_' : p) + (this.counter++);
bgneal@45: },
bgneal@45:
bgneal@45: setHTML : function(e, h) {
bgneal@45: var t = this;
bgneal@45:
bgneal@45: return this.run(e, function(e) {
bgneal@45: var x, i, nl, n, p, x;
bgneal@45:
bgneal@45: h = t.processHTML(h);
bgneal@45:
bgneal@45: if (isIE) {
bgneal@45: function set() {
bgneal@45: try {
bgneal@45: // IE will remove comments from the beginning
bgneal@45: // unless you padd the contents with something
bgneal@45: e.innerHTML = '
' + h;
bgneal@45: e.removeChild(e.firstChild);
bgneal@45: } catch (ex) {
bgneal@45: // IE sometimes produces an unknown runtime error on innerHTML if it's an block element within a block element for example a div inside a p
bgneal@45: // This seems to fix this problem
bgneal@45:
bgneal@45: // Remove all child nodes
bgneal@45: while (e.firstChild)
bgneal@45: e.firstChild.removeNode();
bgneal@45:
bgneal@45: // Create new div with HTML contents and a BR infront to keep comments
bgneal@45: x = t.create('div');
bgneal@45: x.innerHTML = '
' + h;
bgneal@45:
bgneal@45: // Add all children from div to target
bgneal@45: each (x.childNodes, function(n, i) {
bgneal@45: // Skip br element
bgneal@45: if (i)
bgneal@45: e.appendChild(n);
bgneal@45: });
bgneal@45: }
bgneal@45: };
bgneal@45:
bgneal@45: // IE has a serious bug when it comes to paragraphs it can produce an invalid
bgneal@45: // DOM tree if contents like this
is inserted
bgneal@45: // It seems to be that IE doesn't like a root block element placed inside another root block element
bgneal@45: if (t.settings.fix_ie_paragraphs)
bgneal@45: h = h.replace(/<\/p>|
]+)><\/p>|
/gi, '
');
bgneal@45:
bgneal@45: set();
bgneal@45:
bgneal@45: if (t.settings.fix_ie_paragraphs) {
bgneal@45: // Check for odd paragraphs this is a sign of a broken DOM
bgneal@45: nl = e.getElementsByTagName("p");
bgneal@45: for (i = nl.length - 1, x = 0; i >= 0; i--) {
bgneal@45: n = nl[i];
bgneal@45:
bgneal@45: if (!n.hasChildNodes()) {
bgneal@45: if (!n.mce_keep) {
bgneal@45: x = 1; // Is broken
bgneal@45: break;
bgneal@45: }
bgneal@45:
bgneal@45: n.removeAttribute('mce_keep');
bgneal@45: }
bgneal@45: }
bgneal@45: }
bgneal@45:
bgneal@45: // Time to fix the madness IE left us
bgneal@45: if (x) {
bgneal@45: // So if we replace the p elements with divs and mark them and then replace them back to paragraphs
bgneal@45: // after we use innerHTML we can fix the DOM tree
bgneal@45: h = h.replace(/]+)>|
/g, '
');
bgneal@45: h = h.replace(/<\/p>/g, '
');
bgneal@45:
bgneal@45: // Set the new HTML with DIVs
bgneal@45: set();
bgneal@45:
bgneal@45: // Replace all DIV elements with he mce_tmp attibute back to paragraphs
bgneal@45: // This is needed since IE has a annoying bug see above for details
bgneal@45: // This is a slow process but it has to be done. :(
bgneal@45: if (t.settings.fix_ie_paragraphs) {
bgneal@45: nl = e.getElementsByTagName("DIV");
bgneal@45: for (i = nl.length - 1; i >= 0; i--) {
bgneal@45: n = nl[i];
bgneal@45:
bgneal@45: // Is it a temp div
bgneal@45: if (n.mce_tmp) {
bgneal@45: // Create new paragraph
bgneal@45: p = t.doc.createElement('p');
bgneal@45:
bgneal@45: // Copy all attributes
bgneal@45: n.cloneNode(false).outerHTML.replace(/([a-z0-9\-_]+)=/gi, function(a, b) {
bgneal@45: var v;
bgneal@45:
bgneal@45: if (b !== 'mce_tmp') {
bgneal@45: v = n.getAttribute(b);
bgneal@45:
bgneal@45: if (!v && b === 'class')
bgneal@45: v = n.className;
bgneal@45:
bgneal@45: p.setAttribute(b, v);
bgneal@45: }
bgneal@45: });
bgneal@45:
bgneal@45: // Append all children to new paragraph
bgneal@45: for (x = 0; x|]+)>/gi, '<$1b$2>');
bgneal@45: h = h.replace(/<(\/?)em>|]+)>/gi, '<$1i$2>');
bgneal@45: } else if (isIE) {
bgneal@45: h = h.replace(/'/g, '''); // IE can't handle apos
bgneal@45: h = h.replace(/\s+(disabled|checked|readonly|selected)\s*=\s*[\"\']?(false|0)[\"\']?/gi, ''); // IE doesn't handle default values correct
bgneal@45: }
bgneal@45:
bgneal@45: // Fix some issues
bgneal@45: h = h.replace(/]+)\/>|/gi, ''); // Force open
bgneal@45:
bgneal@45: // Store away src and href in mce_src and mce_href since browsers mess them up
bgneal@45: if (s.keep_values) {
bgneal@45: // Wrap scripts and styles in comments for serialization purposes
bgneal@45: if (/');
bgneal@45: };
bgneal@45:
bgneal@45: if (!tinymce.is(u, 'string')) {
bgneal@45: each(u, function(u) {
bgneal@45: loadScript(u);
bgneal@45: });
bgneal@45:
bgneal@45: if (cb)
bgneal@45: cb.call(s || t);
bgneal@45: } else {
bgneal@45: loadScript(u);
bgneal@45:
bgneal@45: if (cb)
bgneal@45: cb.call(s || t);
bgneal@45: }
bgneal@45: },
bgneal@45:
bgneal@45: loadQueue : function(cb, s) {
bgneal@45: var t = this;
bgneal@45:
bgneal@45: if (!t.queueLoading) {
bgneal@45: t.queueLoading = 1;
bgneal@45: t.queueCallbacks = [];
bgneal@45:
bgneal@45: t.loadScripts(t.queue, function() {
bgneal@45: t.queueLoading = 0;
bgneal@45:
bgneal@45: if (cb)
bgneal@45: cb.call(s || t);
bgneal@45:
bgneal@45: each(t.queueCallbacks, function(o) {
bgneal@45: o.func.call(o.scope);
bgneal@45: });
bgneal@45: });
bgneal@45: } else if (cb)
bgneal@45: t.queueCallbacks.push({func : cb, scope : s || t});
bgneal@45: },
bgneal@45:
bgneal@45: eval : function(co) {
bgneal@45: var w = window;
bgneal@45:
bgneal@45: // Evaluate script
bgneal@45: if (!w.execScript) {
bgneal@45: try {
bgneal@45: eval.call(w, co);
bgneal@45: } catch (ex) {
bgneal@45: eval(co, w); // Firefox 3.0a8
bgneal@45: }
bgneal@45: } else
bgneal@45: w.execScript(co); // IE
bgneal@45: },
bgneal@45:
bgneal@45: loadScripts : function(sc, cb, s) {
bgneal@45: var t = this, lo = t.lookup;
bgneal@45:
bgneal@45: function done(o) {
bgneal@45: o.state = 2; // Has been loaded
bgneal@45:
bgneal@45: // Run callback
bgneal@45: if (o.func)
bgneal@45: o.func.call(o.scope || t);
bgneal@45: };
bgneal@45:
bgneal@45: function allDone() {
bgneal@45: var l;
bgneal@45:
bgneal@45: // Check if all files are loaded
bgneal@45: l = sc.length;
bgneal@45: each(sc, function(o) {
bgneal@45: o = lo[o.url];
bgneal@45:
bgneal@45: if (o.state === 2) {// It has finished loading
bgneal@45: done(o);
bgneal@45: l--;
bgneal@45: } else
bgneal@45: load(o);
bgneal@45: });
bgneal@45:
bgneal@45: // They are all loaded
bgneal@45: if (l === 0 && cb) {
bgneal@45: cb.call(s || t);
bgneal@45: cb = 0;
bgneal@45: }
bgneal@45: };
bgneal@45:
bgneal@45: function load(o) {
bgneal@45: if (o.state > 0)
bgneal@45: return;
bgneal@45:
bgneal@45: o.state = 1; // Is loading
bgneal@45:
bgneal@45: tinymce.dom.ScriptLoader.loadScript(o.url, function() {
bgneal@45: done(o);
bgneal@45: allDone();
bgneal@45: });
bgneal@45:
bgneal@45: /*
bgneal@45: tinymce.util.XHR.send({
bgneal@45: url : o.url,
bgneal@45: error : t.settings.error,
bgneal@45: success : function(co) {
bgneal@45: t.eval(co);
bgneal@45: done(o);
bgneal@45: allDone();
bgneal@45: }
bgneal@45: });
bgneal@45: */
bgneal@45: };
bgneal@45:
bgneal@45: each(sc, function(o) {
bgneal@45: var u = o.url;
bgneal@45:
bgneal@45: // Add to queue if needed
bgneal@45: if (!lo[u]) {
bgneal@45: lo[u] = o;
bgneal@45: t.queue.push(o);
bgneal@45: } else
bgneal@45: o = lo[u];
bgneal@45:
bgneal@45: // Is already loading or has been loaded
bgneal@45: if (o.state > 0)
bgneal@45: return;
bgneal@45:
bgneal@45: if (!Event.domLoaded && !t.settings.strict_mode) {
bgneal@45: var ix, ol = '';
bgneal@45:
bgneal@45: // Add onload events
bgneal@45: if (cb || o.func) {
bgneal@45: o.state = 1; // Is loading
bgneal@45:
bgneal@45: ix = tinymce.dom.ScriptLoader._addOnLoad(function() {
bgneal@45: done(o);
bgneal@45: allDone();
bgneal@45: });
bgneal@45:
bgneal@45: if (tinymce.isIE)
bgneal@45: ol = ' onreadystatechange="';
bgneal@45: else
bgneal@45: ol = ' onload="';
bgneal@45:
bgneal@45: ol += 'tinymce.dom.ScriptLoader._onLoad(this,\'' + u + '\',' + ix + ');"';
bgneal@45: }
bgneal@45:
bgneal@45: document.write('');
bgneal@45:
bgneal@45: if (!o.func)
bgneal@45: done(o);
bgneal@45: } else
bgneal@45: load(o);
bgneal@45: });
bgneal@45:
bgneal@45: allDone();
bgneal@45: },
bgneal@45:
bgneal@45: // Static methods
bgneal@45: 'static' : {
bgneal@45: _addOnLoad : function(f) {
bgneal@45: var t = this;
bgneal@45:
bgneal@45: t._funcs = t._funcs || [];
bgneal@45: t._funcs.push(f);
bgneal@45:
bgneal@45: return t._funcs.length - 1;
bgneal@45: },
bgneal@45:
bgneal@45: _onLoad : function(e, u, ix) {
bgneal@45: if (!tinymce.isIE || e.readyState == 'complete')
bgneal@45: this._funcs[ix].call(this);
bgneal@45: },
bgneal@45:
bgneal@45: loadScript : function(u, cb) {
bgneal@45: var id = tinymce.DOM.uniqueId(), e;
bgneal@45:
bgneal@45: function done() {
bgneal@45: Event.clear(id);
bgneal@45: tinymce.DOM.remove(id);
bgneal@45:
bgneal@45: if (cb) {
bgneal@45: cb.call(document, u);
bgneal@45: cb = 0;
bgneal@45: }
bgneal@45: };
bgneal@45:
bgneal@45: if (tinymce.isIE) {
bgneal@45: /* Event.add(e, 'readystatechange', function(e) {
bgneal@45: if (e.target && e.target.readyState == 'complete')
bgneal@45: done();
bgneal@45: });*/
bgneal@45:
bgneal@45: tinymce.util.XHR.send({
bgneal@45: url : tinymce._addVer(u),
bgneal@45: async : false,
bgneal@45: success : function(co) {
bgneal@45: window.execScript(co);
bgneal@45: done();
bgneal@45: }
bgneal@45: });
bgneal@45: } else {
bgneal@45: e = tinymce.DOM.create('script', {id : id, type : 'text/javascript', src : tinymce._addVer(u)});
bgneal@45: Event.add(e, 'load', done);
bgneal@45:
bgneal@45: // Check for head or body
bgneal@45: (document.getElementsByTagName('head')[0] || document.body).appendChild(e);
bgneal@45: }
bgneal@45: }
bgneal@45: }
bgneal@45:
bgneal@45: });
bgneal@45:
bgneal@45: // Global script loader
bgneal@45: tinymce.ScriptLoader = new tinymce.dom.ScriptLoader();
bgneal@45: })(tinymce);
bgneal@45: (function(tinymce) {
bgneal@45: // Shorten class names
bgneal@45: var DOM = tinymce.DOM, is = tinymce.is;
bgneal@45:
bgneal@45: tinymce.create('tinymce.ui.Control', {
bgneal@45: Control : function(id, s) {
bgneal@45: this.id = id;
bgneal@45: this.settings = s = s || {};
bgneal@45: this.rendered = false;
bgneal@45: this.onRender = new tinymce.util.Dispatcher(this);
bgneal@45: this.classPrefix = '';
bgneal@45: this.scope = s.scope || this;
bgneal@45: this.disabled = 0;
bgneal@45: this.active = 0;
bgneal@45: },
bgneal@45:
bgneal@45: setDisabled : function(s) {
bgneal@45: var e;
bgneal@45:
bgneal@45: if (s != this.disabled) {
bgneal@45: e = DOM.get(this.id);
bgneal@45:
bgneal@45: // Add accessibility title for unavailable actions
bgneal@45: if (e && this.settings.unavailable_prefix) {
bgneal@45: if (s) {
bgneal@45: this.prevTitle = e.title;
bgneal@45: e.title = this.settings.unavailable_prefix + ": " + e.title;
bgneal@45: } else
bgneal@45: e.title = this.prevTitle;
bgneal@45: }
bgneal@45:
bgneal@45: this.setState('Disabled', s);
bgneal@45: this.setState('Enabled', !s);
bgneal@45: this.disabled = s;
bgneal@45: }
bgneal@45: },
bgneal@45:
bgneal@45: isDisabled : function() {
bgneal@45: return this.disabled;
bgneal@45: },
bgneal@45:
bgneal@45: setActive : function(s) {
bgneal@45: if (s != this.active) {
bgneal@45: this.setState('Active', s);
bgneal@45: this.active = s;
bgneal@45: }
bgneal@45: },
bgneal@45:
bgneal@45: isActive : function() {
bgneal@45: return this.active;
bgneal@45: },
bgneal@45:
bgneal@45: setState : function(c, s) {
bgneal@45: var n = DOM.get(this.id);
bgneal@45:
bgneal@45: c = this.classPrefix + c;
bgneal@45:
bgneal@45: if (s)
bgneal@45: DOM.addClass(n, c);
bgneal@45: else
bgneal@45: DOM.removeClass(n, c);
bgneal@45: },
bgneal@45:
bgneal@45: isRendered : function() {
bgneal@45: return this.rendered;
bgneal@45: },
bgneal@45:
bgneal@45: renderHTML : function() {
bgneal@45: },
bgneal@45:
bgneal@45: renderTo : function(n) {
bgneal@45: DOM.setHTML(n, this.renderHTML());
bgneal@45: },
bgneal@45:
bgneal@45: postRender : function() {
bgneal@45: var t = this, b;
bgneal@45:
bgneal@45: // Set pending states
bgneal@45: if (is(t.disabled)) {
bgneal@45: b = t.disabled;
bgneal@45: t.disabled = -1;
bgneal@45: t.setDisabled(b);
bgneal@45: }
bgneal@45:
bgneal@45: if (is(t.active)) {
bgneal@45: b = t.active;
bgneal@45: t.active = -1;
bgneal@45: t.setActive(b);
bgneal@45: }
bgneal@45: },
bgneal@45:
bgneal@45: remove : function() {
bgneal@45: DOM.remove(this.id);
bgneal@45: this.destroy();
bgneal@45: },
bgneal@45:
bgneal@45: destroy : function() {
bgneal@45: tinymce.dom.Event.clear(this.id);
bgneal@45: }
bgneal@45:
bgneal@45: });
bgneal@45: })(tinymce);tinymce.create('tinymce.ui.Container:tinymce.ui.Control', {
bgneal@45: Container : function(id, s) {
bgneal@45: this.parent(id, s);
bgneal@45: this.controls = [];
bgneal@45: this.lookup = {};
bgneal@45: },
bgneal@45:
bgneal@45: add : function(c) {
bgneal@45: this.lookup[c.id] = c;
bgneal@45: this.controls.push(c);
bgneal@45:
bgneal@45: return c;
bgneal@45: },
bgneal@45:
bgneal@45: get : function(n) {
bgneal@45: return this.lookup[n];
bgneal@45: }
bgneal@45:
bgneal@45: });
bgneal@45:
bgneal@45: tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', {
bgneal@45: Separator : function(id, s) {
bgneal@45: this.parent(id, s);
bgneal@45: this.classPrefix = 'mceSeparator';
bgneal@45: },
bgneal@45:
bgneal@45: renderHTML : function() {
bgneal@45: return tinymce.DOM.createHTML('span', {'class' : this.classPrefix});
bgneal@45: }
bgneal@45:
bgneal@45: });
bgneal@45: (function(tinymce) {
bgneal@45: var is = tinymce.is, DOM = tinymce.DOM, each = tinymce.each, walk = tinymce.walk;
bgneal@45:
bgneal@45: tinymce.create('tinymce.ui.MenuItem:tinymce.ui.Control', {
bgneal@45: MenuItem : function(id, s) {
bgneal@45: this.parent(id, s);
bgneal@45: this.classPrefix = 'mceMenuItem';
bgneal@45: },
bgneal@45:
bgneal@45: setSelected : function(s) {
bgneal@45: this.setState('Selected', s);
bgneal@45: this.selected = s;
bgneal@45: },
bgneal@45:
bgneal@45: isSelected : function() {
bgneal@45: return this.selected;
bgneal@45: },
bgneal@45:
bgneal@45: postRender : function() {
bgneal@45: var t = this;
bgneal@45:
bgneal@45: t.parent();
bgneal@45:
bgneal@45: // Set pending state
bgneal@45: if (is(t.selected))
bgneal@45: t.setSelected(t.selected);
bgneal@45: }
bgneal@45:
bgneal@45: });
bgneal@45: })(tinymce);
bgneal@45: (function(tinymce) {
bgneal@45: var is = tinymce.is, DOM = tinymce.DOM, each = tinymce.each, walk = tinymce.walk;
bgneal@45:
bgneal@45: tinymce.create('tinymce.ui.Menu:tinymce.ui.MenuItem', {
bgneal@45: Menu : function(id, s) {
bgneal@45: var t = this;
bgneal@45:
bgneal@45: t.parent(id, s);
bgneal@45: t.items = {};
bgneal@45: t.collapsed = false;
bgneal@45: t.menuCount = 0;
bgneal@45: t.onAddItem = new tinymce.util.Dispatcher(this);
bgneal@45: },
bgneal@45:
bgneal@45: expand : function(d) {
bgneal@45: var t = this;
bgneal@45:
bgneal@45: if (d) {
bgneal@45: walk(t, function(o) {
bgneal@45: if (o.expand)
bgneal@45: o.expand();
bgneal@45: }, 'items', t);
bgneal@45: }
bgneal@45:
bgneal@45: t.collapsed = false;
bgneal@45: },
bgneal@45:
bgneal@45: collapse : function(d) {
bgneal@45: var t = this;
bgneal@45:
bgneal@45: if (d) {
bgneal@45: walk(t, function(o) {
bgneal@45: if (o.collapse)
bgneal@45: o.collapse();
bgneal@45: }, 'items', t);
bgneal@45: }
bgneal@45:
bgneal@45: t.collapsed = true;
bgneal@45: },
bgneal@45:
bgneal@45: isCollapsed : function() {
bgneal@45: return this.collapsed;
bgneal@45: },
bgneal@45:
bgneal@45: add : function(o) {
bgneal@45: if (!o.settings)
bgneal@45: o = new tinymce.ui.MenuItem(o.id || DOM.uniqueId(), o);
bgneal@45:
bgneal@45: this.onAddItem.dispatch(this, o);
bgneal@45:
bgneal@45: return this.items[o.id] = o;
bgneal@45: },
bgneal@45:
bgneal@45: addSeparator : function() {
bgneal@45: return this.add({separator : true});
bgneal@45: },
bgneal@45:
bgneal@45: addMenu : function(o) {
bgneal@45: if (!o.collapse)
bgneal@45: o = this.createMenu(o);
bgneal@45:
bgneal@45: this.menuCount++;
bgneal@45:
bgneal@45: return this.add(o);
bgneal@45: },
bgneal@45:
bgneal@45: hasMenus : function() {
bgneal@45: return this.menuCount !== 0;
bgneal@45: },
bgneal@45:
bgneal@45: remove : function(o) {
bgneal@45: delete this.items[o.id];
bgneal@45: },
bgneal@45:
bgneal@45: removeAll : function() {
bgneal@45: var t = this;
bgneal@45:
bgneal@45: walk(t, function(o) {
bgneal@45: if (o.removeAll)
bgneal@45: o.removeAll();
bgneal@45: else
bgneal@45: o.remove();
bgneal@45:
bgneal@45: o.destroy();
bgneal@45: }, 'items', t);
bgneal@45:
bgneal@45: t.items = {};
bgneal@45: },
bgneal@45:
bgneal@45: createMenu : function(o) {
bgneal@45: var m = new tinymce.ui.Menu(o.id || DOM.uniqueId(), o);
bgneal@45:
bgneal@45: m.onAddItem.add(this.onAddItem.dispatch, this.onAddItem);
bgneal@45:
bgneal@45: return m;
bgneal@45: }
bgneal@45:
bgneal@45: });
bgneal@45: })(tinymce);(function(tinymce) {
bgneal@45: var is = tinymce.is, DOM = tinymce.DOM, each = tinymce.each, Event = tinymce.dom.Event, Element = tinymce.dom.Element;
bgneal@45:
bgneal@45: tinymce.create('tinymce.ui.DropMenu:tinymce.ui.Menu', {
bgneal@45: DropMenu : function(id, s) {
bgneal@45: s = s || {};
bgneal@45: s.container = s.container || DOM.doc.body;
bgneal@45: s.offset_x = s.offset_x || 0;
bgneal@45: s.offset_y = s.offset_y || 0;
bgneal@45: s.vp_offset_x = s.vp_offset_x || 0;
bgneal@45: s.vp_offset_y = s.vp_offset_y || 0;
bgneal@45:
bgneal@45: if (is(s.icons) && !s.icons)
bgneal@45: s['class'] += ' mceNoIcons';
bgneal@45:
bgneal@45: this.parent(id, s);
bgneal@45: this.onShowMenu = new tinymce.util.Dispatcher(this);
bgneal@45: this.onHideMenu = new tinymce.util.Dispatcher(this);
bgneal@45: this.classPrefix = 'mceMenu';
bgneal@45: },
bgneal@45:
bgneal@45: createMenu : function(s) {
bgneal@45: var t = this, cs = t.settings, m;
bgneal@45:
bgneal@45: s.container = s.container || cs.container;
bgneal@45: s.parent = t;
bgneal@45: s.constrain = s.constrain || cs.constrain;
bgneal@45: s['class'] = s['class'] || cs['class'];
bgneal@45: s.vp_offset_x = s.vp_offset_x || cs.vp_offset_x;
bgneal@45: s.vp_offset_y = s.vp_offset_y || cs.vp_offset_y;
bgneal@45: m = new tinymce.ui.DropMenu(s.id || DOM.uniqueId(), s);
bgneal@45:
bgneal@45: m.onAddItem.add(t.onAddItem.dispatch, t.onAddItem);
bgneal@45:
bgneal@45: return m;
bgneal@45: },
bgneal@45:
bgneal@45: update : function() {
bgneal@45: var t = this, s = t.settings, tb = DOM.get('menu_' + t.id + '_tbl'), co = DOM.get('menu_' + t.id + '_co'), tw, th;
bgneal@45:
bgneal@45: tw = s.max_width ? Math.min(tb.clientWidth, s.max_width) : tb.clientWidth;
bgneal@45: th = s.max_height ? Math.min(tb.clientHeight, s.max_height) : tb.clientHeight;
bgneal@45:
bgneal@45: if (!DOM.boxModel)
bgneal@45: t.element.setStyles({width : tw + 2, height : th + 2});
bgneal@45: else
bgneal@45: t.element.setStyles({width : tw, height : th});
bgneal@45:
bgneal@45: if (s.max_width)
bgneal@45: DOM.setStyle(co, 'width', tw);
bgneal@45:
bgneal@45: if (s.max_height) {
bgneal@45: DOM.setStyle(co, 'height', th);
bgneal@45:
bgneal@45: if (tb.clientHeight < s.max_height)
bgneal@45: DOM.setStyle(co, 'overflow', 'hidden');
bgneal@45: }
bgneal@45: },
bgneal@45:
bgneal@45: showMenu : function(x, y, px) {
bgneal@45: var t = this, s = t.settings, co, vp = DOM.getViewPort(), w, h, mx, my, ot = 2, dm, tb, cp = t.classPrefix;
bgneal@45:
bgneal@45: t.collapse(1);
bgneal@45:
bgneal@45: if (t.isMenuVisible)
bgneal@45: return;
bgneal@45:
bgneal@45: if (!t.rendered) {
bgneal@45: co = DOM.add(t.settings.container, t.renderNode());
bgneal@45:
bgneal@45: each(t.items, function(o) {
bgneal@45: o.postRender();
bgneal@45: });
bgneal@45:
bgneal@45: t.element = new Element('menu_' + t.id, {blocker : 1, container : s.container});
bgneal@45: } else
bgneal@45: co = DOM.get('menu_' + t.id);
bgneal@45:
bgneal@45: // Move layer out of sight unless it's Opera since it scrolls to top of page due to an bug
bgneal@45: if (!tinymce.isOpera)
bgneal@45: DOM.setStyles(co, {left : -0xFFFF , top : -0xFFFF});
bgneal@45:
bgneal@45: DOM.show(co);
bgneal@45: t.update();
bgneal@45:
bgneal@45: x += s.offset_x || 0;
bgneal@45: y += s.offset_y || 0;
bgneal@45: vp.w -= 4;
bgneal@45: vp.h -= 4;
bgneal@45:
bgneal@45: // Move inside viewport if not submenu
bgneal@45: if (s.constrain) {
bgneal@45: w = co.clientWidth - ot;
bgneal@45: h = co.clientHeight - ot;
bgneal@45: mx = vp.x + vp.w;
bgneal@45: my = vp.y + vp.h;
bgneal@45:
bgneal@45: if ((x + s.vp_offset_x + w) > mx)
bgneal@45: x = px ? px - w : Math.max(0, (mx - s.vp_offset_x) - w);
bgneal@45:
bgneal@45: if ((y + s.vp_offset_y + h) > my)
bgneal@45: y = Math.max(0, (my - s.vp_offset_y) - h);
bgneal@45: }
bgneal@45:
bgneal@45: DOM.setStyles(co, {left : x , top : y});
bgneal@45: t.element.update();
bgneal@45:
bgneal@45: t.isMenuVisible = 1;
bgneal@45: t.mouseClickFunc = Event.add(co, 'click', function(e) {
bgneal@45: var m;
bgneal@45:
bgneal@45: e = e.target;
bgneal@45:
bgneal@45: if (e && (e = DOM.getParent(e, 'TR')) && !DOM.hasClass(e, cp + 'ItemSub')) {
bgneal@45: m = t.items[e.id];
bgneal@45:
bgneal@45: if (m.isDisabled())
bgneal@45: return;
bgneal@45:
bgneal@45: dm = t;
bgneal@45:
bgneal@45: while (dm) {
bgneal@45: if (dm.hideMenu)
bgneal@45: dm.hideMenu();
bgneal@45:
bgneal@45: dm = dm.settings.parent;
bgneal@45: }
bgneal@45:
bgneal@45: if (m.settings.onclick)
bgneal@45: m.settings.onclick(e);
bgneal@45:
bgneal@45: return Event.cancel(e); // Cancel to fix onbeforeunload problem
bgneal@45: }
bgneal@45: });
bgneal@45:
bgneal@45: if (t.hasMenus()) {
bgneal@45: t.mouseOverFunc = Event.add(co, 'mouseover', function(e) {
bgneal@45: var m, r, mi;
bgneal@45:
bgneal@45: e = e.target;
bgneal@45: if (e && (e = DOM.getParent(e, 'TR'))) {
bgneal@45: m = t.items[e.id];
bgneal@45:
bgneal@45: if (t.lastMenu)
bgneal@45: t.lastMenu.collapse(1);
bgneal@45:
bgneal@45: if (m.isDisabled())
bgneal@45: return;
bgneal@45:
bgneal@45: if (e && DOM.hasClass(e, cp + 'ItemSub')) {
bgneal@45: //p = DOM.getPos(s.container);
bgneal@45: r = DOM.getRect(e);
bgneal@45: m.showMenu((r.x + r.w - ot), r.y - ot, r.x);
bgneal@45: t.lastMenu = m;
bgneal@45: DOM.addClass(DOM.get(m.id).firstChild, cp + 'ItemActive');
bgneal@45: }
bgneal@45: }
bgneal@45: });
bgneal@45: }
bgneal@45:
bgneal@45: t.onShowMenu.dispatch(t);
bgneal@45:
bgneal@45: if (s.keyboard_focus) {
bgneal@45: Event.add(co, 'keydown', t._keyHandler, t);
bgneal@45: DOM.select('a', 'menu_' + t.id)[0].focus(); // Select first link
bgneal@45: t._focusIdx = 0;
bgneal@45: }
bgneal@45: },
bgneal@45:
bgneal@45: hideMenu : function(c) {
bgneal@45: var t = this, co = DOM.get('menu_' + t.id), e;
bgneal@45:
bgneal@45: if (!t.isMenuVisible)
bgneal@45: return;
bgneal@45:
bgneal@45: Event.remove(co, 'mouseover', t.mouseOverFunc);
bgneal@45: Event.remove(co, 'click', t.mouseClickFunc);
bgneal@45: Event.remove(co, 'keydown', t._keyHandler);
bgneal@45: DOM.hide(co);
bgneal@45: t.isMenuVisible = 0;
bgneal@45:
bgneal@45: if (!c)
bgneal@45: t.collapse(1);
bgneal@45:
bgneal@45: if (t.element)
bgneal@45: t.element.hide();
bgneal@45:
bgneal@45: if (e = DOM.get(t.id))
bgneal@45: DOM.removeClass(e.firstChild, t.classPrefix + 'ItemActive');
bgneal@45:
bgneal@45: t.onHideMenu.dispatch(t);
bgneal@45: },
bgneal@45:
bgneal@45: add : function(o) {
bgneal@45: var t = this, co;
bgneal@45:
bgneal@45: o = t.parent(o);
bgneal@45:
bgneal@45: if (t.isRendered && (co = DOM.get('menu_' + t.id)))
bgneal@45: t._add(DOM.select('tbody', co)[0], o);
bgneal@45:
bgneal@45: return o;
bgneal@45: },
bgneal@45:
bgneal@45: collapse : function(d) {
bgneal@45: this.parent(d);
bgneal@45: this.hideMenu(1);
bgneal@45: },
bgneal@45:
bgneal@45: remove : function(o) {
bgneal@45: DOM.remove(o.id);
bgneal@45: this.destroy();
bgneal@45:
bgneal@45: return this.parent(o);
bgneal@45: },
bgneal@45:
bgneal@45: destroy : function() {
bgneal@45: var t = this, co = DOM.get('menu_' + t.id);
bgneal@45:
bgneal@45: Event.remove(co, 'mouseover', t.mouseOverFunc);
bgneal@45: Event.remove(co, 'click', t.mouseClickFunc);
bgneal@45:
bgneal@45: if (t.element)
bgneal@45: t.element.remove();
bgneal@45:
bgneal@45: DOM.remove(co);
bgneal@45: },
bgneal@45:
bgneal@45: renderNode : function() {
bgneal@45: var t = this, s = t.settings, n, tb, co, w;
bgneal@45:
bgneal@45: w = DOM.create('div', {id : 'menu_' + t.id, 'class' : s['class'], 'style' : 'position:absolute;left:0;top:0;z-index:200000'});
bgneal@45: co = DOM.add(w, 'div', {id : 'menu_' + t.id + '_co', 'class' : t.classPrefix + (s['class'] ? ' ' + s['class'] : '')});
bgneal@45: t.element = new Element('menu_' + t.id, {blocker : 1, container : s.container});
bgneal@45:
bgneal@45: if (s.menu_line)
bgneal@45: DOM.add(co, 'span', {'class' : t.classPrefix + 'Line'});
bgneal@45:
bgneal@45: // n = DOM.add(co, 'div', {id : 'menu_' + t.id + '_co', 'class' : 'mceMenuContainer'});
bgneal@45: n = DOM.add(co, 'table', {id : 'menu_' + t.id + '_tbl', border : 0, cellPadding : 0, cellSpacing : 0});
bgneal@45: tb = DOM.add(n, 'tbody');
bgneal@45:
bgneal@45: each(t.items, function(o) {
bgneal@45: t._add(tb, o);
bgneal@45: });
bgneal@45:
bgneal@45: t.rendered = true;
bgneal@45:
bgneal@45: return w;
bgneal@45: },
bgneal@45:
bgneal@45: // Internal functions
bgneal@45:
bgneal@45: _keyHandler : function(e) {
bgneal@45: var t = this, kc = e.keyCode;
bgneal@45:
bgneal@45: function focus(d) {
bgneal@45: var i = t._focusIdx + d, e = DOM.select('a', 'menu_' + t.id)[i];
bgneal@45:
bgneal@45: if (e) {
bgneal@45: t._focusIdx = i;
bgneal@45: e.focus();
bgneal@45: }
bgneal@45: };
bgneal@45:
bgneal@45: switch (kc) {
bgneal@45: case 38:
bgneal@45: focus(-1); // Select first link
bgneal@45: return;
bgneal@45:
bgneal@45: case 40:
bgneal@45: focus(1);
bgneal@45: return;
bgneal@45:
bgneal@45: case 13:
bgneal@45: return;
bgneal@45:
bgneal@45: case 27:
bgneal@45: return this.hideMenu();
bgneal@45: }
bgneal@45: },
bgneal@45:
bgneal@45: _add : function(tb, o) {
bgneal@45: var n, s = o.settings, a, ro, it, cp = this.classPrefix, ic;
bgneal@45:
bgneal@45: if (s.separator) {
bgneal@45: ro = DOM.add(tb, 'tr', {id : o.id, 'class' : cp + 'ItemSeparator'});
bgneal@45: DOM.add(ro, 'td', {'class' : cp + 'ItemSeparator'});
bgneal@45:
bgneal@45: if (n = ro.previousSibling)
bgneal@45: DOM.addClass(n, 'mceLast');
bgneal@45:
bgneal@45: return;
bgneal@45: }
bgneal@45:
bgneal@45: n = ro = DOM.add(tb, 'tr', {id : o.id, 'class' : cp + 'Item ' + cp + 'ItemEnabled'});
bgneal@45: n = it = DOM.add(n, 'td');
bgneal@45: n = a = DOM.add(n, 'a', {href : 'javascript:;', onclick : "return false;", onmousedown : 'return false;'});
bgneal@45:
bgneal@45: DOM.addClass(it, s['class']);
bgneal@45: // n = DOM.add(n, 'span', {'class' : 'item'});
bgneal@45:
bgneal@45: ic = DOM.add(n, 'span', {'class' : 'mceIcon' + (s.icon ? ' mce_' + s.icon : '')});
bgneal@45:
bgneal@45: if (s.icon_src)
bgneal@45: DOM.add(ic, 'img', {src : s.icon_src});
bgneal@45:
bgneal@45: n = DOM.add(n, s.element || 'span', {'class' : 'mceText', title : o.settings.title}, o.settings.title);
bgneal@45:
bgneal@45: if (o.settings.style)
bgneal@45: DOM.setAttrib(n, 'style', o.settings.style);
bgneal@45:
bgneal@45: if (tb.childNodes.length == 1)
bgneal@45: DOM.addClass(ro, 'mceFirst');
bgneal@45:
bgneal@45: if ((n = ro.previousSibling) && DOM.hasClass(n, cp + 'ItemSeparator'))
bgneal@45: DOM.addClass(ro, 'mceFirst');
bgneal@45:
bgneal@45: if (o.collapse)
bgneal@45: DOM.addClass(ro, cp + 'ItemSub');
bgneal@45:
bgneal@45: if (n = ro.previousSibling)
bgneal@45: DOM.removeClass(n, 'mceLast');
bgneal@45:
bgneal@45: DOM.addClass(ro, 'mceLast');
bgneal@45: }
bgneal@45:
bgneal@45: });
bgneal@45: })(tinymce);(function(tinymce) {
bgneal@45: var DOM = tinymce.DOM;
bgneal@45:
bgneal@45: tinymce.create('tinymce.ui.Button:tinymce.ui.Control', {
bgneal@45: Button : function(id, s) {
bgneal@45: this.parent(id, s);
bgneal@45: this.classPrefix = 'mceButton';
bgneal@45: },
bgneal@45:
bgneal@45: renderHTML : function() {
bgneal@45: var cp = this.classPrefix, s = this.settings, h, l;
bgneal@45:
bgneal@45: l = DOM.encode(s.label || '');
bgneal@45: h = '';
bgneal@45:
bgneal@45: if (s.image)
bgneal@45: h += '' + l + '';
bgneal@45: else
bgneal@45: h += '' + (l ? '' + l + '' : '') + '';
bgneal@45:
bgneal@45: return h;
bgneal@45: },
bgneal@45:
bgneal@45: postRender : function() {
bgneal@45: var t = this, s = t.settings;
bgneal@45:
bgneal@45: tinymce.dom.Event.add(t.id, 'click', function(e) {
bgneal@45: if (!t.isDisabled())
bgneal@45: return s.onclick.call(s.scope, e);
bgneal@45: });
bgneal@45: }
bgneal@45:
bgneal@45: });
bgneal@45: })(tinymce);
bgneal@45: (function(tinymce) {
bgneal@45: var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each, Dispatcher = tinymce.util.Dispatcher;
bgneal@45:
bgneal@45: tinymce.create('tinymce.ui.ListBox:tinymce.ui.Control', {
bgneal@45: ListBox : function(id, s) {
bgneal@45: var t = this;
bgneal@45:
bgneal@45: t.parent(id, s);
bgneal@45: t.items = [];
bgneal@45: t.onChange = new Dispatcher(t);
bgneal@45: t.onPostRender = new Dispatcher(t);
bgneal@45: t.onAdd = new Dispatcher(t);
bgneal@45: t.onRenderMenu = new tinymce.util.Dispatcher(this);
bgneal@45: t.classPrefix = 'mceListBox';
bgneal@45: },
bgneal@45:
bgneal@45: select : function(va) {
bgneal@45: var t = this, fv, f;
bgneal@45:
bgneal@45: if (va == undefined)
bgneal@45: return t.selectByIndex(-1);
bgneal@45:
bgneal@45: // Is string or number make function selector
bgneal@45: if (va && va.call)
bgneal@45: f = va;
bgneal@45: else {
bgneal@45: f = function(v) {
bgneal@45: return v == va;
bgneal@45: };
bgneal@45: }
bgneal@45:
bgneal@45: // Do we need to do something?
bgneal@45: if (va != t.selectedValue) {
bgneal@45: // Find item
bgneal@45: each(t.items, function(o, i) {
bgneal@45: if (f(o.value)) {
bgneal@45: fv = 1;
bgneal@45: t.selectByIndex(i);
bgneal@45: return false;
bgneal@45: }
bgneal@45: });
bgneal@45:
bgneal@45: if (!fv)
bgneal@45: t.selectByIndex(-1);
bgneal@45: }
bgneal@45: },
bgneal@45:
bgneal@45: selectByIndex : function(idx) {
bgneal@45: var t = this, e, o;
bgneal@45:
bgneal@45: if (idx != t.selectedIndex) {
bgneal@45: e = DOM.get(t.id + '_text');
bgneal@45: o = t.items[idx];
bgneal@45:
bgneal@45: if (o) {
bgneal@45: t.selectedValue = o.value;
bgneal@45: t.selectedIndex = idx;
bgneal@45: DOM.setHTML(e, DOM.encode(o.title));
bgneal@45: DOM.removeClass(e, 'mceTitle');
bgneal@45: } else {
bgneal@45: DOM.setHTML(e, DOM.encode(t.settings.title));
bgneal@45: DOM.addClass(e, 'mceTitle');
bgneal@45: t.selectedValue = t.selectedIndex = null;
bgneal@45: }
bgneal@45:
bgneal@45: e = 0;
bgneal@45: }
bgneal@45: },
bgneal@45:
bgneal@45: add : function(n, v, o) {
bgneal@45: var t = this;
bgneal@45:
bgneal@45: o = o || {};
bgneal@45: o = tinymce.extend(o, {
bgneal@45: title : n,
bgneal@45: value : v
bgneal@45: });
bgneal@45:
bgneal@45: t.items.push(o);
bgneal@45: t.onAdd.dispatch(t, o);
bgneal@45: },
bgneal@45:
bgneal@45: getLength : function() {
bgneal@45: return this.items.length;
bgneal@45: },
bgneal@45:
bgneal@45: renderHTML : function() {
bgneal@45: var h = '', t = this, s = t.settings, cp = t.classPrefix;
bgneal@45:
bgneal@45: h = '';
bgneal@45: h += '' + DOM.createHTML('a', {id : t.id + '_text', href : 'javascript:;', 'class' : 'mceText', onclick : "return false;", onmousedown : 'return false;'}, DOM.encode(t.settings.title)) + ' | ';
bgneal@45: h += '' + DOM.createHTML('a', {id : t.id + '_open', tabindex : -1, href : 'javascript:;', 'class' : 'mceOpen', onclick : "return false;", onmousedown : 'return false;'}, '') + ' | ';
bgneal@45: h += '
';
bgneal@45:
bgneal@45: return h;
bgneal@45: },
bgneal@45:
bgneal@45: showMenu : function() {
bgneal@45: var t = this, p1, p2, e = DOM.get(this.id), m;
bgneal@45:
bgneal@45: if (t.isDisabled() || t.items.length == 0)
bgneal@45: return;
bgneal@45:
bgneal@45: if (t.menu && t.menu.isMenuVisible)
bgneal@45: return t.hideMenu();
bgneal@45:
bgneal@45: if (!t.isMenuRendered) {
bgneal@45: t.renderMenu();
bgneal@45: t.isMenuRendered = true;
bgneal@45: }
bgneal@45:
bgneal@45: p1 = DOM.getPos(this.settings.menu_container);
bgneal@45: p2 = DOM.getPos(e);
bgneal@45:
bgneal@45: m = t.menu;
bgneal@45: m.settings.offset_x = p2.x;
bgneal@45: m.settings.offset_y = p2.y;
bgneal@45: m.settings.keyboard_focus = !tinymce.isOpera; // Opera is buggy when it comes to auto focus
bgneal@45:
bgneal@45: // Select in menu
bgneal@45: if (t.oldID)
bgneal@45: m.items[t.oldID].setSelected(0);
bgneal@45:
bgneal@45: each(t.items, function(o) {
bgneal@45: if (o.value === t.selectedValue) {
bgneal@45: m.items[o.id].setSelected(1);
bgneal@45: t.oldID = o.id;
bgneal@45: }
bgneal@45: });
bgneal@45:
bgneal@45: m.showMenu(0, e.clientHeight);
bgneal@45:
bgneal@45: Event.add(DOM.doc, 'mousedown', t.hideMenu, t);
bgneal@45: DOM.addClass(t.id, t.classPrefix + 'Selected');
bgneal@45:
bgneal@45: //DOM.get(t.id + '_text').focus();
bgneal@45: },
bgneal@45:
bgneal@45: hideMenu : function(e) {
bgneal@45: var t = this;
bgneal@45:
bgneal@45: // Prevent double toogles by canceling the mouse click event to the button
bgneal@45: if (e && e.type == "mousedown" && (e.target.id == t.id + '_text' || e.target.id == t.id + '_open'))
bgneal@45: return;
bgneal@45:
bgneal@45: if (!e || !DOM.getParent(e.target, '.mceMenu')) {
bgneal@45: DOM.removeClass(t.id, t.classPrefix + 'Selected');
bgneal@45: Event.remove(DOM.doc, 'mousedown', t.hideMenu, t);
bgneal@45:
bgneal@45: if (t.menu)
bgneal@45: t.menu.hideMenu();
bgneal@45: }
bgneal@45: },
bgneal@45:
bgneal@45: renderMenu : function() {
bgneal@45: var t = this, m;
bgneal@45:
bgneal@45: m = t.settings.control_manager.createDropMenu(t.id + '_menu', {
bgneal@45: menu_line : 1,
bgneal@45: 'class' : t.classPrefix + 'Menu mceNoIcons',
bgneal@45: max_width : 150,
bgneal@45: max_height : 150
bgneal@45: });
bgneal@45:
bgneal@45: m.onHideMenu.add(t.hideMenu, t);
bgneal@45:
bgneal@45: m.add({
bgneal@45: title : t.settings.title,
bgneal@45: 'class' : 'mceMenuItemTitle',
bgneal@45: onclick : function() {
bgneal@45: if (t.settings.onselect('') !== false)
bgneal@45: t.select(''); // Must be runned after
bgneal@45: }
bgneal@45: });
bgneal@45:
bgneal@45: each(t.items, function(o) {
bgneal@45: o.id = DOM.uniqueId();
bgneal@45: o.onclick = function() {
bgneal@45: if (t.settings.onselect(o.value) !== false)
bgneal@45: t.select(o.value); // Must be runned after
bgneal@45: };
bgneal@45:
bgneal@45: m.add(o);
bgneal@45: });
bgneal@45:
bgneal@45: t.onRenderMenu.dispatch(t, m);
bgneal@45: t.menu = m;
bgneal@45: },
bgneal@45:
bgneal@45: postRender : function() {
bgneal@45: var t = this, cp = t.classPrefix;
bgneal@45:
bgneal@45: Event.add(t.id, 'click', t.showMenu, t);
bgneal@45: Event.add(t.id + '_text', 'focus', function(e) {
bgneal@45: if (!t._focused) {
bgneal@45: t.keyDownHandler = Event.add(t.id + '_text', 'keydown', function(e) {
bgneal@45: var idx = -1, v, kc = e.keyCode;
bgneal@45:
bgneal@45: // Find current index
bgneal@45: each(t.items, function(v, i) {
bgneal@45: if (t.selectedValue == v.value)
bgneal@45: idx = i;
bgneal@45: });
bgneal@45:
bgneal@45: // Move up/down
bgneal@45: if (kc == 38)
bgneal@45: v = t.items[idx - 1];
bgneal@45: else if (kc == 40)
bgneal@45: v = t.items[idx + 1];
bgneal@45: else if (kc == 13) {
bgneal@45: // Fake select on enter
bgneal@45: v = t.selectedValue;
bgneal@45: t.selectedValue = null; // Needs to be null to fake change
bgneal@45: t.settings.onselect(v);
bgneal@45: return Event.cancel(e);
bgneal@45: }
bgneal@45:
bgneal@45: if (v) {
bgneal@45: t.hideMenu();
bgneal@45: t.select(v.value);
bgneal@45: }
bgneal@45: });
bgneal@45: }
bgneal@45:
bgneal@45: t._focused = 1;
bgneal@45: });
bgneal@45: Event.add(t.id + '_text', 'blur', function() {Event.remove(t.id + '_text', 'keydown', t.keyDownHandler); t._focused = 0;});
bgneal@45:
bgneal@45: // Old IE doesn't have hover on all elements
bgneal@45: if (tinymce.isIE6 || !DOM.boxModel) {
bgneal@45: Event.add(t.id, 'mouseover', function() {
bgneal@45: if (!DOM.hasClass(t.id, cp + 'Disabled'))
bgneal@45: DOM.addClass(t.id, cp + 'Hover');
bgneal@45: });
bgneal@45:
bgneal@45: Event.add(t.id, 'mouseout', function() {
bgneal@45: if (!DOM.hasClass(t.id, cp + 'Disabled'))
bgneal@45: DOM.removeClass(t.id, cp + 'Hover');
bgneal@45: });
bgneal@45: }
bgneal@45:
bgneal@45: t.onPostRender.dispatch(t, DOM.get(t.id));
bgneal@45: },
bgneal@45:
bgneal@45: destroy : function() {
bgneal@45: this.parent();
bgneal@45:
bgneal@45: Event.clear(this.id + '_text');
bgneal@45: }
bgneal@45:
bgneal@45: });
bgneal@45: })(tinymce);(function(tinymce) {
bgneal@45: var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each, Dispatcher = tinymce.util.Dispatcher;
bgneal@45:
bgneal@45: tinymce.create('tinymce.ui.NativeListBox:tinymce.ui.ListBox', {
bgneal@45: NativeListBox : function(id, s) {
bgneal@45: this.parent(id, s);
bgneal@45: this.classPrefix = 'mceNativeListBox';
bgneal@45: },
bgneal@45:
bgneal@45: setDisabled : function(s) {
bgneal@45: DOM.get(this.id).disabled = s;
bgneal@45: },
bgneal@45:
bgneal@45: isDisabled : function() {
bgneal@45: return DOM.get(this.id).disabled;
bgneal@45: },
bgneal@45:
bgneal@45: select : function(va) {
bgneal@45: var t = this, fv, f;
bgneal@45:
bgneal@45: if (va == undefined)
bgneal@45: return t.selectByIndex(-1);
bgneal@45:
bgneal@45: // Is string or number make function selector
bgneal@45: if (va && va.call)
bgneal@45: f = va;
bgneal@45: else {
bgneal@45: f = function(v) {
bgneal@45: return v == va;
bgneal@45: };
bgneal@45: }
bgneal@45:
bgneal@45: // Do we need to do something?
bgneal@45: if (va != t.selectedValue) {
bgneal@45: // Find item
bgneal@45: each(t.items, function(o, i) {
bgneal@45: if (f(o.value)) {
bgneal@45: fv = 1;
bgneal@45: t.selectByIndex(i);
bgneal@45: return false;
bgneal@45: }
bgneal@45: });
bgneal@45:
bgneal@45: if (!fv)
bgneal@45: t.selectByIndex(-1);
bgneal@45: }
bgneal@45: },
bgneal@45:
bgneal@45: selectByIndex : function(idx) {
bgneal@45: DOM.get(this.id).selectedIndex = idx + 1;
bgneal@45: this.selectedValue = this.items[idx] ? this.items[idx].value : null;
bgneal@45: },
bgneal@45:
bgneal@45: add : function(n, v, a) {
bgneal@45: var o, t = this;
bgneal@45:
bgneal@45: a = a || {};
bgneal@45: a.value = v;
bgneal@45:
bgneal@45: if (t.isRendered())
bgneal@45: DOM.add(DOM.get(this.id), 'option', a, n);
bgneal@45:
bgneal@45: o = {
bgneal@45: title : n,
bgneal@45: value : v,
bgneal@45: attribs : a
bgneal@45: };
bgneal@45:
bgneal@45: t.items.push(o);
bgneal@45: t.onAdd.dispatch(t, o);
bgneal@45: },
bgneal@45:
bgneal@45: getLength : function() {
bgneal@45: return DOM.get(this.id).options.length - 1;
bgneal@45: },
bgneal@45:
bgneal@45: renderHTML : function() {
bgneal@45: var h, t = this;
bgneal@45:
bgneal@45: h = DOM.createHTML('option', {value : ''}, '-- ' + t.settings.title + ' --');
bgneal@45:
bgneal@45: each(t.items, function(it) {
bgneal@45: h += DOM.createHTML('option', {value : it.value}, it.title);
bgneal@45: });
bgneal@45:
bgneal@45: h = DOM.createHTML('select', {id : t.id, 'class' : 'mceNativeListBox'}, h);
bgneal@45:
bgneal@45: return h;
bgneal@45: },
bgneal@45:
bgneal@45: postRender : function() {
bgneal@45: var t = this, ch;
bgneal@45:
bgneal@45: t.rendered = true;
bgneal@45:
bgneal@45: function onChange(e) {
bgneal@45: var v = t.items[e.target.selectedIndex - 1];
bgneal@45:
bgneal@45: if (v && (v = v.value)) {
bgneal@45: t.onChange.dispatch(t, v);
bgneal@45:
bgneal@45: if (t.settings.onselect)
bgneal@45: t.settings.onselect(v);
bgneal@45: }
bgneal@45: };
bgneal@45:
bgneal@45: Event.add(t.id, 'change', onChange);
bgneal@45:
bgneal@45: // Accessibility keyhandler
bgneal@45: Event.add(t.id, 'keydown', function(e) {
bgneal@45: var bf;
bgneal@45:
bgneal@45: Event.remove(t.id, 'change', ch);
bgneal@45:
bgneal@45: bf = Event.add(t.id, 'blur', function() {
bgneal@45: Event.add(t.id, 'change', onChange);
bgneal@45: Event.remove(t.id, 'blur', bf);
bgneal@45: });
bgneal@45:
bgneal@45: if (e.keyCode == 13 || e.keyCode == 32) {
bgneal@45: onChange(e);
bgneal@45: return Event.cancel(e);
bgneal@45: }
bgneal@45: });
bgneal@45:
bgneal@45: t.onPostRender.dispatch(t, DOM.get(t.id));
bgneal@45: }
bgneal@45:
bgneal@45: });
bgneal@45: })(tinymce);(function(tinymce) {
bgneal@45: var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each;
bgneal@45:
bgneal@45: tinymce.create('tinymce.ui.MenuButton:tinymce.ui.Button', {
bgneal@45: MenuButton : function(id, s) {
bgneal@45: this.parent(id, s);
bgneal@45: this.onRenderMenu = new tinymce.util.Dispatcher(this);
bgneal@45: s.menu_container = s.menu_container || DOM.doc.body;
bgneal@45: },
bgneal@45:
bgneal@45: showMenu : function() {
bgneal@45: var t = this, p1, p2, e = DOM.get(t.id), m;
bgneal@45:
bgneal@45: if (t.isDisabled())
bgneal@45: return;
bgneal@45:
bgneal@45: if (!t.isMenuRendered) {
bgneal@45: t.renderMenu();
bgneal@45: t.isMenuRendered = true;
bgneal@45: }
bgneal@45:
bgneal@45: if (t.isMenuVisible)
bgneal@45: return t.hideMenu();
bgneal@45:
bgneal@45: p1 = DOM.getPos(t.settings.menu_container);
bgneal@45: p2 = DOM.getPos(e);
bgneal@45:
bgneal@45: m = t.menu;
bgneal@45: m.settings.offset_x = p2.x;
bgneal@45: m.settings.offset_y = p2.y;
bgneal@45: m.settings.vp_offset_x = p2.x;
bgneal@45: m.settings.vp_offset_y = p2.y;
bgneal@45: m.settings.keyboard_focus = t._focused;
bgneal@45: m.showMenu(0, e.clientHeight);
bgneal@45:
bgneal@45: Event.add(DOM.doc, 'mousedown', t.hideMenu, t);
bgneal@45: t.setState('Selected', 1);
bgneal@45:
bgneal@45: t.isMenuVisible = 1;
bgneal@45: },
bgneal@45:
bgneal@45: renderMenu : function() {
bgneal@45: var t = this, m;
bgneal@45:
bgneal@45: m = t.settings.control_manager.createDropMenu(t.id + '_menu', {
bgneal@45: menu_line : 1,
bgneal@45: 'class' : this.classPrefix + 'Menu',
bgneal@45: icons : t.settings.icons
bgneal@45: });
bgneal@45:
bgneal@45: m.onHideMenu.add(t.hideMenu, t);
bgneal@45:
bgneal@45: t.onRenderMenu.dispatch(t, m);
bgneal@45: t.menu = m;
bgneal@45: },
bgneal@45:
bgneal@45: hideMenu : function(e) {
bgneal@45: var t = this;
bgneal@45:
bgneal@45: // Prevent double toogles by canceling the mouse click event to the button
bgneal@45: if (e && e.type == "mousedown" && DOM.getParent(e.target, function(e) {return e.id === t.id || e.id === t.id + '_open';}))
bgneal@45: return;
bgneal@45:
bgneal@45: if (!e || !DOM.getParent(e.target, '.mceMenu')) {
bgneal@45: t.setState('Selected', 0);
bgneal@45: Event.remove(DOM.doc, 'mousedown', t.hideMenu, t);
bgneal@45: if (t.menu)
bgneal@45: t.menu.hideMenu();
bgneal@45: }
bgneal@45:
bgneal@45: t.isMenuVisible = 0;
bgneal@45: },
bgneal@45:
bgneal@45: postRender : function() {
bgneal@45: var t = this, s = t.settings;
bgneal@45:
bgneal@45: Event.add(t.id, 'click', function() {
bgneal@45: if (!t.isDisabled()) {
bgneal@45: if (s.onclick)
bgneal@45: s.onclick(t.value);
bgneal@45:
bgneal@45: t.showMenu();
bgneal@45: }
bgneal@45: });
bgneal@45: }
bgneal@45:
bgneal@45: });
bgneal@45: })(tinymce);
bgneal@45: (function(tinymce) {
bgneal@45: var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each;
bgneal@45:
bgneal@45: tinymce.create('tinymce.ui.SplitButton:tinymce.ui.MenuButton', {
bgneal@45: SplitButton : function(id, s) {
bgneal@45: this.parent(id, s);
bgneal@45: this.classPrefix = 'mceSplitButton';
bgneal@45: },
bgneal@45:
bgneal@45: renderHTML : function() {
bgneal@45: var h, t = this, s = t.settings, h1;
bgneal@45:
bgneal@45: h = '';
bgneal@45:
bgneal@45: if (s.image)
bgneal@45: h1 = DOM.createHTML('img ', {src : s.image, 'class' : 'mceAction ' + s['class']});
bgneal@45: else
bgneal@45: h1 = DOM.createHTML('span', {'class' : 'mceAction ' + s['class']}, '');
bgneal@45:
bgneal@45: h += '' + DOM.createHTML('a', {id : t.id + '_action', href : 'javascript:;', 'class' : 'mceAction ' + s['class'], onclick : "return false;", onmousedown : 'return false;', title : s.title}, h1) + ' | ';
bgneal@45:
bgneal@45: h1 = DOM.createHTML('span', {'class' : 'mceOpen ' + s['class']});
bgneal@45: h += '' + DOM.createHTML('a', {id : t.id + '_open', href : 'javascript:;', 'class' : 'mceOpen ' + s['class'], onclick : "return false;", onmousedown : 'return false;', title : s.title}, h1) + ' | ';
bgneal@45:
bgneal@45: h += '
';
bgneal@45:
bgneal@45: return DOM.createHTML('table', {id : t.id, 'class' : 'mceSplitButton mceSplitButtonEnabled ' + s['class'], cellpadding : '0', cellspacing : '0', onmousedown : 'return false;', title : s.title}, h);
bgneal@45: },
bgneal@45:
bgneal@45: postRender : function() {
bgneal@45: var t = this, s = t.settings;
bgneal@45:
bgneal@45: if (s.onclick) {
bgneal@45: Event.add(t.id + '_action', 'click', function() {
bgneal@45: if (!t.isDisabled())
bgneal@45: s.onclick(t.value);
bgneal@45: });
bgneal@45: }
bgneal@45:
bgneal@45: Event.add(t.id + '_open', 'click', t.showMenu, t);
bgneal@45: Event.add(t.id + '_open', 'focus', function() {t._focused = 1;});
bgneal@45: Event.add(t.id + '_open', 'blur', function() {t._focused = 0;});
bgneal@45:
bgneal@45: // Old IE doesn't have hover on all elements
bgneal@45: if (tinymce.isIE6 || !DOM.boxModel) {
bgneal@45: Event.add(t.id, 'mouseover', function() {
bgneal@45: if (!DOM.hasClass(t.id, 'mceSplitButtonDisabled'))
bgneal@45: DOM.addClass(t.id, 'mceSplitButtonHover');
bgneal@45: });
bgneal@45:
bgneal@45: Event.add(t.id, 'mouseout', function() {
bgneal@45: if (!DOM.hasClass(t.id, 'mceSplitButtonDisabled'))
bgneal@45: DOM.removeClass(t.id, 'mceSplitButtonHover');
bgneal@45: });
bgneal@45: }
bgneal@45: },
bgneal@45:
bgneal@45: destroy : function() {
bgneal@45: this.parent();
bgneal@45:
bgneal@45: Event.clear(this.id + '_action');
bgneal@45: Event.clear(this.id + '_open');
bgneal@45: }
bgneal@45:
bgneal@45: });
bgneal@45: })(tinymce);
bgneal@45: (function(tinymce) {
bgneal@45: var DOM = tinymce.DOM, Event = tinymce.dom.Event, is = tinymce.is, each = tinymce.each;
bgneal@45:
bgneal@45: tinymce.create('tinymce.ui.ColorSplitButton:tinymce.ui.SplitButton', {
bgneal@45: ColorSplitButton : function(id, s) {
bgneal@45: var t = this;
bgneal@45:
bgneal@45: t.parent(id, s);
bgneal@45:
bgneal@45: t.settings = s = tinymce.extend({
bgneal@45: colors : '000000,993300,333300,003300,003366,000080,333399,333333,800000,FF6600,808000,008000,008080,0000FF,666699,808080,FF0000,FF9900,99CC00,339966,33CCCC,3366FF,800080,999999,FF00FF,FFCC00,FFFF00,00FF00,00FFFF,00CCFF,993366,C0C0C0,FF99CC,FFCC99,FFFF99,CCFFCC,CCFFFF,99CCFF,CC99FF,FFFFFF',
bgneal@45: grid_width : 8,
bgneal@45: default_color : '#888888'
bgneal@45: }, t.settings);
bgneal@45:
bgneal@45: t.onShowMenu = new tinymce.util.Dispatcher(t);
bgneal@45: t.onHideMenu = new tinymce.util.Dispatcher(t);
bgneal@45:
bgneal@45: t.value = s.default_color;
bgneal@45: },
bgneal@45:
bgneal@45: showMenu : function() {
bgneal@45: var t = this, r, p, e, p2;
bgneal@45:
bgneal@45: if (t.isDisabled())
bgneal@45: return;
bgneal@45:
bgneal@45: if (!t.isMenuRendered) {
bgneal@45: t.renderMenu();
bgneal@45: t.isMenuRendered = true;
bgneal@45: }
bgneal@45:
bgneal@45: if (t.isMenuVisible)
bgneal@45: return t.hideMenu();
bgneal@45:
bgneal@45: e = DOM.get(t.id);
bgneal@45: DOM.show(t.id + '_menu');
bgneal@45: DOM.addClass(e, 'mceSplitButtonSelected');
bgneal@45: p2 = DOM.getPos(e);
bgneal@45: DOM.setStyles(t.id + '_menu', {
bgneal@45: left : p2.x,
bgneal@45: top : p2.y + e.clientHeight,
bgneal@45: zIndex : 200000
bgneal@45: });
bgneal@45: e = 0;
bgneal@45:
bgneal@45: Event.add(DOM.doc, 'mousedown', t.hideMenu, t);
bgneal@45:
bgneal@45: if (t._focused) {
bgneal@45: t._keyHandler = Event.add(t.id + '_menu', 'keydown', function(e) {
bgneal@45: if (e.keyCode == 27)
bgneal@45: t.hideMenu();
bgneal@45: });
bgneal@45:
bgneal@45: DOM.select('a', t.id + '_menu')[0].focus(); // Select first link
bgneal@45: }
bgneal@45:
bgneal@45: t.onShowMenu.dispatch(t);
bgneal@45:
bgneal@45: t.isMenuVisible = 1;
bgneal@45: },
bgneal@45:
bgneal@45: hideMenu : function(e) {
bgneal@45: var t = this;
bgneal@45:
bgneal@45: // Prevent double toogles by canceling the mouse click event to the button
bgneal@45: if (e && e.type == "mousedown" && DOM.getParent(e.target, function(e) {return e.id === t.id + '_open';}))
bgneal@45: return;
bgneal@45:
bgneal@45: if (!e || !DOM.getParent(e.target, '.mceSplitButtonMenu')) {
bgneal@45: DOM.removeClass(t.id, 'mceSplitButtonSelected');
bgneal@45: Event.remove(DOM.doc, 'mousedown', t.hideMenu, t);
bgneal@45: Event.remove(t.id + '_menu', 'keydown', t._keyHandler);
bgneal@45: DOM.hide(t.id + '_menu');
bgneal@45: }
bgneal@45:
bgneal@45: t.onHideMenu.dispatch(t);
bgneal@45:
bgneal@45: t.isMenuVisible = 0;
bgneal@45: },
bgneal@45:
bgneal@45: renderMenu : function() {
bgneal@45: var t = this, m, i = 0, s = t.settings, n, tb, tr, w;
bgneal@45:
bgneal@45: w = DOM.add(s.menu_container, 'div', {id : t.id + '_menu', 'class' : s['menu_class'] + ' ' + s['class'], style : 'position:absolute;left:0;top:-1000px;'});
bgneal@45: m = DOM.add(w, 'div', {'class' : s['class'] + ' mceSplitButtonMenu'});
bgneal@45: DOM.add(m, 'span', {'class' : 'mceMenuLine'});
bgneal@45:
bgneal@45: n = DOM.add(m, 'table', {'class' : 'mceColorSplitMenu'});
bgneal@45: tb = DOM.add(n, 'tbody');
bgneal@45:
bgneal@45: // Generate color grid
bgneal@45: i = 0;
bgneal@45: each(is(s.colors, 'array') ? s.colors : s.colors.split(','), function(c) {
bgneal@45: c = c.replace(/^#/, '');
bgneal@45:
bgneal@45: if (!i--) {
bgneal@45: tr = DOM.add(tb, 'tr');
bgneal@45: i = s.grid_width - 1;
bgneal@45: }
bgneal@45:
bgneal@45: n = DOM.add(tr, 'td');
bgneal@45:
bgneal@45: n = DOM.add(n, 'a', {
bgneal@45: href : 'javascript:;',
bgneal@45: style : {
bgneal@45: backgroundColor : '#' + c
bgneal@45: },
bgneal@45: mce_color : '#' + c
bgneal@45: });
bgneal@45: });
bgneal@45:
bgneal@45: if (s.more_colors_func) {
bgneal@45: n = DOM.add(tb, 'tr');
bgneal@45: n = DOM.add(n, 'td', {colspan : s.grid_width, 'class' : 'mceMoreColors'});
bgneal@45: n = DOM.add(n, 'a', {id : t.id + '_more', href : 'javascript:;', onclick : 'return false;', 'class' : 'mceMoreColors'}, s.more_colors_title);
bgneal@45:
bgneal@45: Event.add(n, 'click', function(e) {
bgneal@45: s.more_colors_func.call(s.more_colors_scope || this);
bgneal@45: return Event.cancel(e); // Cancel to fix onbeforeunload problem
bgneal@45: });
bgneal@45: }
bgneal@45:
bgneal@45: DOM.addClass(m, 'mceColorSplitMenu');
bgneal@45:
bgneal@45: Event.add(t.id + '_menu', 'click', function(e) {
bgneal@45: var c;
bgneal@45:
bgneal@45: e = e.target;
bgneal@45:
bgneal@45: if (e.nodeName == 'A' && (c = e.getAttribute('mce_color')))
bgneal@45: t.setColor(c);
bgneal@45:
bgneal@45: return Event.cancel(e); // Prevent IE auto save warning
bgneal@45: });
bgneal@45:
bgneal@45: return w;
bgneal@45: },
bgneal@45:
bgneal@45: setColor : function(c) {
bgneal@45: var t = this;
bgneal@45:
bgneal@45: DOM.setStyle(t.id + '_preview', 'backgroundColor', c);
bgneal@45:
bgneal@45: t.value = c;
bgneal@45: t.hideMenu();
bgneal@45: t.settings.onselect(c);
bgneal@45: },
bgneal@45:
bgneal@45: postRender : function() {
bgneal@45: var t = this, id = t.id;
bgneal@45:
bgneal@45: t.parent();
bgneal@45: DOM.add(id + '_action', 'div', {id : id + '_preview', 'class' : 'mceColorPreview'});
bgneal@45: DOM.setStyle(t.id + '_preview', 'backgroundColor', t.value);
bgneal@45: },
bgneal@45:
bgneal@45: destroy : function() {
bgneal@45: this.parent();
bgneal@45:
bgneal@45: Event.clear(this.id + '_menu');
bgneal@45: Event.clear(this.id + '_more');
bgneal@45: DOM.remove(this.id + '_menu');
bgneal@45: }
bgneal@45:
bgneal@45: });
bgneal@45: })(tinymce);
bgneal@45: tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
bgneal@45: renderHTML : function() {
bgneal@45: var t = this, h = '', c, co, dom = tinymce.DOM, s = t.settings, i, pr, nx, cl;
bgneal@45:
bgneal@45: cl = t.controls;
bgneal@45: for (i=0; i'));
bgneal@45: }
bgneal@45:
bgneal@45: // Add toolbar end before list box and after the previous button
bgneal@45: // This is to fix the o2k7 editor skins
bgneal@45: if (pr && co.ListBox) {
bgneal@45: if (pr.Button || pr.SplitButton)
bgneal@45: h += dom.createHTML('td', {'class' : 'mceToolbarEnd'}, dom.createHTML('span', null, ''));
bgneal@45: }
bgneal@45:
bgneal@45: // Render control HTML
bgneal@45:
bgneal@45: // IE 8 quick fix, needed to propertly generate a hit area for anchors
bgneal@45: if (dom.stdMode)
bgneal@45: h += '' + co.renderHTML() + ' | ';
bgneal@45: else
bgneal@45: h += '' + co.renderHTML() + ' | ';
bgneal@45:
bgneal@45: // Add toolbar start after list box and before the next button
bgneal@45: // This is to fix the o2k7 editor skins
bgneal@45: if (nx && co.ListBox) {
bgneal@45: if (nx.Button || nx.SplitButton)
bgneal@45: h += dom.createHTML('td', {'class' : 'mceToolbarStart'}, dom.createHTML('span', null, ''));
bgneal@45: }
bgneal@45: }
bgneal@45:
bgneal@45: c = 'mceToolbarEnd';
bgneal@45:
bgneal@45: if (co.Button)
bgneal@45: c += ' mceToolbarEndButton';
bgneal@45: else if (co.SplitButton)
bgneal@45: c += ' mceToolbarEndSplitButton';
bgneal@45: else if (co.ListBox)
bgneal@45: c += ' mceToolbarEndListBox';
bgneal@45:
bgneal@45: h += dom.createHTML('td', {'class' : c}, dom.createHTML('span', null, ''));
bgneal@45:
bgneal@45: return dom.createHTML('table', {id : t.id, 'class' : 'mceToolbar' + (s['class'] ? ' ' + s['class'] : ''), cellpadding : '0', cellspacing : '0', align : t.settings.align || ''}, '' + h + '
');
bgneal@45: }
bgneal@45:
bgneal@45: });
bgneal@45: (function(tinymce) {
bgneal@45: var Dispatcher = tinymce.util.Dispatcher, each = tinymce.each;
bgneal@45:
bgneal@45: tinymce.create('tinymce.AddOnManager', {
bgneal@45: items : [],
bgneal@45: urls : {},
bgneal@45: lookup : {},
bgneal@45: onAdd : new Dispatcher(this),
bgneal@45:
bgneal@45: get : function(n) {
bgneal@45: return this.lookup[n];
bgneal@45: },
bgneal@45:
bgneal@45: requireLangPack : function(n) {
bgneal@45: var u, s = tinymce.EditorManager.settings;
bgneal@45:
bgneal@45: if (s && s.language) {
bgneal@45: u = this.urls[n] + '/langs/' + s.language + '.js';
bgneal@45:
bgneal@45: if (!tinymce.dom.Event.domLoaded && !s.strict_mode)
bgneal@45: tinymce.ScriptLoader.load(u);
bgneal@45: else
bgneal@45: tinymce.ScriptLoader.add(u);
bgneal@45: }
bgneal@45: },
bgneal@45:
bgneal@45: add : function(id, o) {
bgneal@45: this.items.push(o);
bgneal@45: this.lookup[id] = o;
bgneal@45: this.onAdd.dispatch(this, id, o);
bgneal@45:
bgneal@45: return o;
bgneal@45: },
bgneal@45:
bgneal@45: load : function(n, u, cb, s) {
bgneal@45: var t = this;
bgneal@45:
bgneal@45: if (t.urls[n])
bgneal@45: return;
bgneal@45:
bgneal@45: if (u.indexOf('/') != 0 && u.indexOf('://') == -1)
bgneal@45: u = tinymce.baseURL + '/' + u;
bgneal@45:
bgneal@45: t.urls[n] = u.substring(0, u.lastIndexOf('/'));
bgneal@45: tinymce.ScriptLoader.add(u, cb, s);
bgneal@45: }
bgneal@45:
bgneal@45: });
bgneal@45:
bgneal@45: // Create plugin and theme managers
bgneal@45: tinymce.PluginManager = new tinymce.AddOnManager();
bgneal@45: tinymce.ThemeManager = new tinymce.AddOnManager();
bgneal@45: }(tinymce));(function(tinymce) {
bgneal@45: // Shorten names
bgneal@45: var each = tinymce.each, extend = tinymce.extend, DOM = tinymce.DOM, Event = tinymce.dom.Event, ThemeManager = tinymce.ThemeManager, PluginManager = tinymce.PluginManager, explode = tinymce.explode;
bgneal@45:
bgneal@45: tinymce.create('static tinymce.EditorManager', {
bgneal@45: editors : {},
bgneal@45: i18n : {},
bgneal@45: activeEditor : null,
bgneal@45:
bgneal@45: preInit : function() {
bgneal@45: var t = this, lo = window.location;
bgneal@45:
bgneal@45: // Setup some URLs where the editor API is located and where the document is
bgneal@45: tinymce.documentBaseURL = lo.href.replace(/[\?#].*$/, '').replace(/[\/\\][^\/]+$/, '');
bgneal@45: if (!/[\/\\]$/.test(tinymce.documentBaseURL))
bgneal@45: tinymce.documentBaseURL += '/';
bgneal@45:
bgneal@45: tinymce.baseURL = new tinymce.util.URI(tinymce.documentBaseURL).toAbsolute(tinymce.baseURL);
bgneal@45: tinymce.EditorManager.baseURI = new tinymce.util.URI(tinymce.baseURL);
bgneal@45:
bgneal@45: // User specified a document.domain value
bgneal@45: if (document.domain && lo.hostname != document.domain)
bgneal@45: tinymce.relaxedDomain = document.domain;
bgneal@45:
bgneal@45: // Add before unload listener
bgneal@45: // This was required since IE was leaking memory if you added and removed beforeunload listeners
bgneal@45: // with attachEvent/detatchEvent so this only adds one listener and instances can the attach to the onBeforeUnload event
bgneal@45: t.onBeforeUnload = new tinymce.util.Dispatcher(t);
bgneal@45:
bgneal@45: // Must be on window or IE will leak if the editor is placed in frame or iframe
bgneal@45: Event.add(window, 'beforeunload', function(e) {
bgneal@45: t.onBeforeUnload.dispatch(t, e);
bgneal@45: });
bgneal@45: },
bgneal@45:
bgneal@45: init : function(s) {
bgneal@45: var t = this, pl, sl = tinymce.ScriptLoader, c, e, el = [], ed;
bgneal@45:
bgneal@45: function execCallback(se, n, s) {
bgneal@45: var f = se[n];
bgneal@45:
bgneal@45: if (!f)
bgneal@45: return;
bgneal@45:
bgneal@45: if (tinymce.is(f, 'string')) {
bgneal@45: s = f.replace(/\.\w+$/, '');
bgneal@45: s = s ? tinymce.resolve(s) : 0;
bgneal@45: f = tinymce.resolve(f);
bgneal@45: }
bgneal@45:
bgneal@45: return f.apply(s || this, Array.prototype.slice.call(arguments, 2));
bgneal@45: };
bgneal@45:
bgneal@45: s = extend({
bgneal@45: theme : "simple",
bgneal@45: language : "en",
bgneal@45: strict_loading_mode : document.contentType == 'application/xhtml+xml'
bgneal@45: }, s);
bgneal@45:
bgneal@45: t.settings = s;
bgneal@45:
bgneal@45: // If page not loaded and strict mode isn't enabled then load them
bgneal@45: if (!Event.domLoaded && !s.strict_loading_mode) {
bgneal@45: // Load language
bgneal@45: if (s.language)
bgneal@45: sl.add(tinymce.baseURL + '/langs/' + s.language + '.js');
bgneal@45:
bgneal@45: // Load theme
bgneal@45: if (s.theme && s.theme.charAt(0) != '-' && !ThemeManager.urls[s.theme])
bgneal@45: ThemeManager.load(s.theme, 'themes/' + s.theme + '/editor_template' + tinymce.suffix + '.js');
bgneal@45:
bgneal@45: // Load plugins
bgneal@45: if (s.plugins) {
bgneal@45: pl = explode(s.plugins);
bgneal@45:
bgneal@45: // Load compat2x first
bgneal@45: if (tinymce.inArray(pl, 'compat2x') != -1)
bgneal@45: PluginManager.load('compat2x', 'plugins/compat2x/editor_plugin' + tinymce.suffix + '.js');
bgneal@45:
bgneal@45: // Load rest if plugins
bgneal@45: each(pl, function(v) {
bgneal@45: if (v && v.charAt(0) != '-' && !PluginManager.urls[v]) {
bgneal@45: // Skip safari plugin for other browsers
bgneal@45: if (!tinymce.isWebKit && v == 'safari')
bgneal@45: return;
bgneal@45:
bgneal@45: PluginManager.load(v, 'plugins/' + v + '/editor_plugin' + tinymce.suffix + '.js');
bgneal@45: }
bgneal@45: });
bgneal@45: }
bgneal@45:
bgneal@45: sl.loadQueue();
bgneal@45: }
bgneal@45:
bgneal@45: // Legacy call
bgneal@45: Event.add(document, 'init', function() {
bgneal@45: var l, co;
bgneal@45:
bgneal@45: execCallback(s, 'onpageload');
bgneal@45:
bgneal@45: // Verify that it's a valid browser
bgneal@45: if (s.browsers) {
bgneal@45: l = false;
bgneal@45:
bgneal@45: each(explode(s.browsers), function(v) {
bgneal@45: switch (v) {
bgneal@45: case 'ie':
bgneal@45: case 'msie':
bgneal@45: if (tinymce.isIE)
bgneal@45: l = true;
bgneal@45: break;
bgneal@45:
bgneal@45: case 'gecko':
bgneal@45: if (tinymce.isGecko)
bgneal@45: l = true;
bgneal@45: break;
bgneal@45:
bgneal@45: case 'safari':
bgneal@45: case 'webkit':
bgneal@45: if (tinymce.isWebKit)
bgneal@45: l = true;
bgneal@45: break;
bgneal@45:
bgneal@45: case 'opera':
bgneal@45: if (tinymce.isOpera)
bgneal@45: l = true;
bgneal@45:
bgneal@45: break;
bgneal@45: }
bgneal@45: });
bgneal@45:
bgneal@45: // Not a valid one
bgneal@45: if (!l)
bgneal@45: return;
bgneal@45: }
bgneal@45:
bgneal@45: switch (s.mode) {
bgneal@45: case "exact":
bgneal@45: l = s.elements || '';
bgneal@45:
bgneal@45: if(l.length > 0) {
bgneal@45: each(explode(l), function(v) {
bgneal@45: if (DOM.get(v)) {
bgneal@45: ed = new tinymce.Editor(v, s);
bgneal@45: el.push(ed);
bgneal@45: ed.render(1);
bgneal@45: } else {
bgneal@45: c = 0;
bgneal@45:
bgneal@45: each(document.forms, function(f) {
bgneal@45: each(f.elements, function(e) {
bgneal@45: if (e.name === v) {
bgneal@45: v = 'mce_editor_' + c;
bgneal@45: DOM.setAttrib(e, 'id', v);
bgneal@45:
bgneal@45: ed = new tinymce.Editor(v, s);
bgneal@45: el.push(ed);
bgneal@45: ed.render(1);
bgneal@45: }
bgneal@45: });
bgneal@45: });
bgneal@45: }
bgneal@45: });
bgneal@45: }
bgneal@45: break;
bgneal@45:
bgneal@45: case "textareas":
bgneal@45: case "specific_textareas":
bgneal@45: function hasClass(n, c) {
bgneal@45: return c.constructor === RegExp ? c.test(n.className) : DOM.hasClass(n, c);
bgneal@45: };
bgneal@45:
bgneal@45: each(DOM.select('textarea'), function(v) {
bgneal@45: if (s.editor_deselector && hasClass(v, s.editor_deselector))
bgneal@45: return;
bgneal@45:
bgneal@45: if (!s.editor_selector || hasClass(v, s.editor_selector)) {
bgneal@45: // Can we use the name
bgneal@45: e = DOM.get(v.name);
bgneal@45: if (!v.id && !e)
bgneal@45: v.id = v.name;
bgneal@45:
bgneal@45: // Generate unique name if missing or already exists
bgneal@45: if (!v.id || t.get(v.id))
bgneal@45: v.id = DOM.uniqueId();
bgneal@45:
bgneal@45: ed = new tinymce.Editor(v.id, s);
bgneal@45: el.push(ed);
bgneal@45: ed.render(1);
bgneal@45: }
bgneal@45: });
bgneal@45: break;
bgneal@45: }
bgneal@45:
bgneal@45: // Call onInit when all editors are initialized
bgneal@45: if (s.oninit) {
bgneal@45: l = co = 0;
bgneal@45:
bgneal@45: each (el, function(ed) {
bgneal@45: co++;
bgneal@45:
bgneal@45: if (!ed.initialized) {
bgneal@45: // Wait for it
bgneal@45: ed.onInit.add(function() {
bgneal@45: l++;
bgneal@45:
bgneal@45: // All done
bgneal@45: if (l == co)
bgneal@45: execCallback(s, 'oninit');
bgneal@45: });
bgneal@45: } else
bgneal@45: l++;
bgneal@45:
bgneal@45: // All done
bgneal@45: if (l == co)
bgneal@45: execCallback(s, 'oninit');
bgneal@45: });
bgneal@45: }
bgneal@45: });
bgneal@45: },
bgneal@45:
bgneal@45: get : function(id) {
bgneal@45: return this.editors[id];
bgneal@45: },
bgneal@45:
bgneal@45: getInstanceById : function(id) {
bgneal@45: return this.get(id);
bgneal@45: },
bgneal@45:
bgneal@45: add : function(e) {
bgneal@45: this.editors[e.id] = e;
bgneal@45: this._setActive(e);
bgneal@45:
bgneal@45: return e;
bgneal@45: },
bgneal@45:
bgneal@45: remove : function(e) {
bgneal@45: var t = this;
bgneal@45:
bgneal@45: // Not in the collection
bgneal@45: if (!t.editors[e.id])
bgneal@45: return null;
bgneal@45:
bgneal@45: delete t.editors[e.id];
bgneal@45:
bgneal@45: // Select another editor since the active one was removed
bgneal@45: if (t.activeEditor == e) {
bgneal@45: each(t.editors, function(e) {
bgneal@45: t._setActive(e);
bgneal@45: return false; // Break
bgneal@45: });
bgneal@45: }
bgneal@45:
bgneal@45: e.destroy();
bgneal@45:
bgneal@45: return e;
bgneal@45: },
bgneal@45:
bgneal@45: execCommand : function(c, u, v) {
bgneal@45: var t = this, ed = t.get(v), w;
bgneal@45:
bgneal@45: // Manager commands
bgneal@45: switch (c) {
bgneal@45: case "mceFocus":
bgneal@45: ed.focus();
bgneal@45: return true;
bgneal@45:
bgneal@45: case "mceAddEditor":
bgneal@45: case "mceAddControl":
bgneal@45: if (!t.get(v))
bgneal@45: new tinymce.Editor(v, t.settings).render();
bgneal@45:
bgneal@45: return true;
bgneal@45:
bgneal@45: case "mceAddFrameControl":
bgneal@45: w = v.window;
bgneal@45:
bgneal@45: // Add tinyMCE global instance and tinymce namespace to specified window
bgneal@45: w.tinyMCE = tinyMCE;
bgneal@45: w.tinymce = tinymce;
bgneal@45:
bgneal@45: tinymce.DOM.doc = w.document;
bgneal@45: tinymce.DOM.win = w;
bgneal@45:
bgneal@45: ed = new tinymce.Editor(v.element_id, v);
bgneal@45: ed.render();
bgneal@45:
bgneal@45: // Fix IE memory leaks
bgneal@45: if (tinymce.isIE) {
bgneal@45: function clr() {
bgneal@45: ed.destroy();
bgneal@45: w.detachEvent('onunload', clr);
bgneal@45: w = w.tinyMCE = w.tinymce = null; // IE leak
bgneal@45: };
bgneal@45:
bgneal@45: w.attachEvent('onunload', clr);
bgneal@45: }
bgneal@45:
bgneal@45: v.page_window = null;
bgneal@45:
bgneal@45: return true;
bgneal@45:
bgneal@45: case "mceRemoveEditor":
bgneal@45: case "mceRemoveControl":
bgneal@45: if (ed)
bgneal@45: ed.remove();
bgneal@45:
bgneal@45: return true;
bgneal@45:
bgneal@45: case 'mceToggleEditor':
bgneal@45: if (!ed) {
bgneal@45: t.execCommand('mceAddControl', 0, v);
bgneal@45: return true;
bgneal@45: }
bgneal@45:
bgneal@45: if (ed.isHidden())
bgneal@45: ed.show();
bgneal@45: else
bgneal@45: ed.hide();
bgneal@45:
bgneal@45: return true;
bgneal@45: }
bgneal@45:
bgneal@45: // Run command on active editor
bgneal@45: if (t.activeEditor)
bgneal@45: return t.activeEditor.execCommand(c, u, v);
bgneal@45:
bgneal@45: return false;
bgneal@45: },
bgneal@45:
bgneal@45: execInstanceCommand : function(id, c, u, v) {
bgneal@45: var ed = this.get(id);
bgneal@45:
bgneal@45: if (ed)
bgneal@45: return ed.execCommand(c, u, v);
bgneal@45:
bgneal@45: return false;
bgneal@45: },
bgneal@45:
bgneal@45: triggerSave : function() {
bgneal@45: each(this.editors, function(e) {
bgneal@45: e.save();
bgneal@45: });
bgneal@45: },
bgneal@45:
bgneal@45: addI18n : function(p, o) {
bgneal@45: var lo, i18n = this.i18n;
bgneal@45:
bgneal@45: if (!tinymce.is(p, 'string')) {
bgneal@45: each(p, function(o, lc) {
bgneal@45: each(o, function(o, g) {
bgneal@45: each(o, function(o, k) {
bgneal@45: if (g === 'common')
bgneal@45: i18n[lc + '.' + k] = o;
bgneal@45: else
bgneal@45: i18n[lc + '.' + g + '.' + k] = o;
bgneal@45: });
bgneal@45: });
bgneal@45: });
bgneal@45: } else {
bgneal@45: each(o, function(o, k) {
bgneal@45: i18n[p + '.' + k] = o;
bgneal@45: });
bgneal@45: }
bgneal@45: },
bgneal@45:
bgneal@45: // Private methods
bgneal@45:
bgneal@45: _setActive : function(e) {
bgneal@45: this.selectedInstance = this.activeEditor = e;
bgneal@45: }
bgneal@45:
bgneal@45: });
bgneal@45:
bgneal@45: tinymce.EditorManager.preInit();
bgneal@45: })(tinymce);
bgneal@45:
bgneal@45: // Short for editor manager window.tinyMCE is needed when TinyMCE gets loaded though a XHR call
bgneal@45: var tinyMCE = window.tinyMCE = tinymce.EditorManager;
bgneal@45: (function(tinymce) {
bgneal@45: var DOM = tinymce.DOM, Event = tinymce.dom.Event, extend = tinymce.extend, Dispatcher = tinymce.util.Dispatcher;
bgneal@45: var each = tinymce.each, isGecko = tinymce.isGecko, isIE = tinymce.isIE, isWebKit = tinymce.isWebKit;
bgneal@45: var is = tinymce.is, ThemeManager = tinymce.ThemeManager, PluginManager = tinymce.PluginManager, EditorManager = tinymce.EditorManager;
bgneal@45: var inArray = tinymce.inArray, grep = tinymce.grep, explode = tinymce.explode;
bgneal@45:
bgneal@45: tinymce.create('tinymce.Editor', {
bgneal@45: Editor : function(id, s) {
bgneal@45: var t = this;
bgneal@45:
bgneal@45: t.id = t.editorId = id;
bgneal@45: t.execCommands = {};
bgneal@45: t.queryStateCommands = {};
bgneal@45: t.queryValueCommands = {};
bgneal@45: t.plugins = {};
bgneal@45:
bgneal@45: // Add events to the editor
bgneal@45: each([
bgneal@45: 'onPreInit',
bgneal@45: 'onBeforeRenderUI',
bgneal@45: 'onPostRender',
bgneal@45: 'onInit',
bgneal@45: 'onRemove',
bgneal@45: 'onActivate',
bgneal@45: 'onDeactivate',
bgneal@45: 'onClick',
bgneal@45: 'onEvent',
bgneal@45: 'onMouseUp',
bgneal@45: 'onMouseDown',
bgneal@45: 'onDblClick',
bgneal@45: 'onKeyDown',
bgneal@45: 'onKeyUp',
bgneal@45: 'onKeyPress',
bgneal@45: 'onContextMenu',
bgneal@45: 'onSubmit',
bgneal@45: 'onReset',
bgneal@45: 'onPaste',
bgneal@45: 'onPreProcess',
bgneal@45: 'onPostProcess',
bgneal@45: 'onBeforeSetContent',
bgneal@45: 'onBeforeGetContent',
bgneal@45: 'onSetContent',
bgneal@45: 'onGetContent',
bgneal@45: 'onLoadContent',
bgneal@45: 'onSaveContent',
bgneal@45: 'onNodeChange',
bgneal@45: 'onChange',
bgneal@45: 'onBeforeExecCommand',
bgneal@45: 'onExecCommand',
bgneal@45: 'onUndo',
bgneal@45: 'onRedo',
bgneal@45: 'onVisualAid',
bgneal@45: 'onSetProgressState'
bgneal@45: ], function(e) {
bgneal@45: t[e] = new Dispatcher(t);
bgneal@45: });
bgneal@45:
bgneal@45: // Default editor config
bgneal@45: t.settings = s = extend({
bgneal@45: id : id,
bgneal@45: language : 'en',
bgneal@45: docs_language : 'en',
bgneal@45: theme : 'simple',
bgneal@45: skin : 'default',
bgneal@45: delta_width : 0,
bgneal@45: delta_height : 0,
bgneal@45: popup_css : '',
bgneal@45: plugins : '',
bgneal@45: document_base_url : tinymce.documentBaseURL,
bgneal@45: add_form_submit_trigger : 1,
bgneal@45: submit_patch : 1,
bgneal@45: add_unload_trigger : 1,
bgneal@45: convert_urls : 1,
bgneal@45: relative_urls : 1,
bgneal@45: remove_script_host : 1,
bgneal@45: table_inline_editing : 0,
bgneal@45: object_resizing : 1,
bgneal@45: cleanup : 1,
bgneal@45: accessibility_focus : 1,
bgneal@45: custom_shortcuts : 1,
bgneal@45: custom_undo_redo_keyboard_shortcuts : 1,
bgneal@45: custom_undo_redo_restore_selection : 1,
bgneal@45: custom_undo_redo : 1,
bgneal@45: doctype : '',
bgneal@45: visual_table_class : 'mceItemTable',
bgneal@45: visual : 1,
bgneal@45: inline_styles : true,
bgneal@45: convert_fonts_to_spans : true,
bgneal@45: font_size_style_values : 'xx-small,x-small,small,medium,large,x-large,xx-large',
bgneal@45: apply_source_formatting : 1,
bgneal@45: directionality : 'ltr',
bgneal@45: forced_root_block : 'p',
bgneal@45: valid_elements : '@[id|class|style|title|dir';
bgneal@45: t.iframeHTML += '';
bgneal@45:
bgneal@45: if (tinymce.relaxedDomain)
bgneal@45: t.iframeHTML += '';
bgneal@45:
bgneal@45: bi = s.body_id || 'tinymce';
bgneal@45: if (bi.indexOf('=') != -1) {
bgneal@45: bi = t.getParam('body_id', '', 'hash');
bgneal@45: bi = bi[t.id] || bi;
bgneal@45: }
bgneal@45:
bgneal@45: bc = s.body_class || '';
bgneal@45: if (bc.indexOf('=') != -1) {
bgneal@45: bc = t.getParam('body_class', '', 'hash');
bgneal@45: bc = bc[t.id] || '';
bgneal@45: }
bgneal@45:
bgneal@45: t.iframeHTML += '