--- a/includes/clientside/tinymce/tiny_mce_src.js Thu Mar 06 20:45:46 2008 -0500
+++ b/includes/clientside/tinymce/tiny_mce_src.js Thu Mar 06 20:47:11 2008 -0500
@@ -3,8 +3,8 @@
var tinymce = {
majorVersion : '3',
- minorVersion : '0.1',
- releaseDate : '2008-02-21',
+ minorVersion : '0.3',
+ releaseDate : '2008-03-03',
_init : function() {
var t = this, ua = navigator.userAgent, i, nl, n, base;
@@ -1031,8 +1031,16 @@
},
get : function(e) {
- if (typeof(e) == 'string')
- return this.doc.getElementById(e);
+ var n;
+
+ if (typeof(e) == 'string') {
+ n = e;
+ e = this.doc.getElementById(e);
+
+ // IE and Opera returns meta elements when they match the specified input ID, but getElementsByName seems to do the trick
+ if (e && e.id !== n)
+ return this.doc.getElementsByName(n)[1];
+ }
return e;
},
@@ -1558,11 +1566,11 @@
r = n;
while (r) {
- // Opera 9.25 bug fix, fixed in 9.50
- if (!tinymce.isOpera || r.nodeName != 'TR') {
+ // Opera 9.25 bug fix, fixed in 9.50 seems to be fixed in Opera 9.26 too
+ /* if (!tinymce.isOpera || r.nodeName != 'TR') {
x -= r.scrollLeft || 0;
y -= r.scrollTop || 0;
- }
+ }*/
r = r.parentNode;
@@ -1789,14 +1797,21 @@
e.innerHTML = '<br />' + h;
e.removeChild(e.firstChild);
} catch (ex) {
- // IE sometimes produces an unknown runtime error on innerHTML
- // This seems to fix this issue, don't know why.
+ // IE sometimes produces an unknown runtime error on innerHTML if it's an block element within a block element for example a div inside a p
+ // This seems to fix this problem
+
+ // Remove all child nodes
+ while (e.firstChild)
+ e.firstChild.removeNode();
+
+ // Create new div with HTML contents and a BR infront to keep comments
x = t.create('div');
x.innerHTML = '<br />' + h;
+ // Add all children from div to target
each (x.childNodes, function(n, i) {
- // Skip the BR
- if (i > 1)
+ // Skip br element
+ if (i)
e.appendChild(n);
});
}
@@ -1985,11 +2000,18 @@
},
decode : function(s) {
- var e = document.createElement("div");
-
- e.innerHTML = s;
-
- return !e.firstChild ? s : e.firstChild.nodeValue;
+ var e;
+
+ // Look for entities to decode
+ if (/&[^;]+;/.test(s)) {
+ // Decode the entities using a div element not super efficient but less code
+ e = this.doc.createElement("div");
+ e.innerHTML = s;
+
+ return !e.firstChild ? s : e.firstChild.nodeValue;
+ }
+
+ return s;
},
encode : function(s) {
@@ -2781,7 +2803,7 @@
return d;
}
- p += n.nodeValue ? n.nodeValue.length : 0;
+ p += n.nodeValue ? tinymce.trim(n.nodeValue).length : 0;
}
return null;
@@ -2798,7 +2820,8 @@
start : e.start + s.anchorOffset,
end : e.end + s.focusOffset,
scrollX : sx,
- scrollY : sy
+ scrollY : sy,
+ beg : s.anchorOffset == 0
};
} else {
e = getPos(ro, r.startContainer, r.endContainer);
@@ -2810,7 +2833,8 @@
start : e.start + r.startOffset,
end : e.end + r.endOffset,
scrollX : sx,
- scrollY : sy
+ scrollY : sy,
+ beg : r.startOffset == 0
};
}
},
@@ -2819,20 +2843,25 @@
var t = this, r = t.getRng(), s = t.getSel(), ro = t.dom.getRoot(), sd;
function getPos(r, sp, ep) {
- var w = document.createTreeWalker(r, NodeFilter.SHOW_TEXT, null, false), n, p = 0, d = {};
+ var w = document.createTreeWalker(r, NodeFilter.SHOW_TEXT, null, false), n, p = 0, d = {}, o, v;
while ((n = w.nextNode()) != null) {
- p += n.nodeValue ? n.nodeValue.length : 0;
+ p += n.nodeValue ? tinymce.trim(n.nodeValue).length : 0;
if (p >= sp && !d.startNode) {
+ o = sp - (p - n.nodeValue.length);
+
+ // Fix for odd quirk in FF
+ if (b.beg && o >= n.nodeValue.length)
+ continue;
+
d.startNode = n;
- d.startOffset = sp - (p - n.nodeValue.length);
+ d.startOffset = o;
}
if (p >= ep) {
d.endNode = n;
d.endOffset = ep - (p - n.nodeValue.length);
-
return d;
}
}
@@ -2906,6 +2935,7 @@
if (is(b.start) && is(b.end)) {
try {
sd = getPos(ro, b.start, b.end);
+
if (sd) {
r = t.dom.doc.createRange();
r.setStart(sd.startNode, sd.startOffset);
@@ -3339,7 +3369,18 @@
t.key = 0;
t.onPreProcess = new Dispatcher(t);
t.onPostProcess = new Dispatcher(t);
- t.writer = tinymce.relaxedDomain && tinymce.isGecko ? new tinymce.dom.StringWriter() : new tinymce.dom.XMLWriter();
+
+ if (tinymce.relaxedDomain && tinymce.isGecko) {
+ // Gecko has a bug where we can't create a new XML document if domain relaxing is used
+ t.writer = new tinymce.dom.StringWriter();
+ } else {
+ try {
+ t.writer = new tinymce.dom.XMLWriter();
+ } catch (ex) {
+ // IE might throw exception if ActiveX is disabled so we then switch to the slightly slower StringWriter
+ t.writer = new tinymce.dom.StringWriter();
+ }
+ }
// Default settings
t.settings = s = extend({
@@ -3848,17 +3889,17 @@
if (s.remove_linebreaks) {
h = h.replace(/(<[^>]+>)\s+/g, '$1 ');
h = h.replace(/\s+(<\/[^>]+>)/g, ' $1');
- h = h.replace(/<(p|h[1-6]|hr|div|table|tbody|tr|td|body|head|html|title|meta|style|pre|script|link|object) ([^>]+)>\s+/g, '<$1 $2>'); // Trim block start
- h = h.replace(/<(p|h[1-6]|hr|div|table|tbody|tr|td|body|head|html|title|meta|style|pre|script|link|object)>\s+/g, '<$1>'); // Trim block start
- h = h.replace(/\s+<\/(p|h[1-6]|hr|div|table|tbody|tr|td|body|head|html|title|meta|style|pre|script|link|object)>/g, '</$1>'); // Trim block end
+ h = h.replace(/<(p|h[1-6]|blockquote|hr|div|table|tbody|tr|td|body|head|html|title|meta|style|pre|script|link|object) ([^>]+)>\s+/g, '<$1 $2>'); // Trim block start
+ h = h.replace(/<(p|h[1-6]|blockquote|hr|div|table|tbody|tr|td|body|head|html|title|meta|style|pre|script|link|object)>\s+/g, '<$1>'); // Trim block start
+ h = h.replace(/\s+<\/(p|h[1-6]|blockquote|hr|div|table|tbody|tr|td|body|head|html|title|meta|style|pre|script|link|object)>/g, '</$1>'); // Trim block end
}
// Simple indentation
if (s.apply_source_formatting && s.indent_mode == 'simple') {
// Add line breaks before and after block elements
h = h.replace(/<(\/?)(ul|hr|table|meta|link|tbody|tr|object|body|head|html|map)(|[^>]+)>\s*/g, '\n<$1$2$3>\n');
- h = h.replace(/\s*<(p|h[1-6]|div|title|style|pre|script|td|li|area)(|[^>]+)>/g, '\n<$1$2>');
- h = h.replace(/<\/(p|h[1-6]|div|title|style|pre|script|td|li)>\s*/g, '</$1>\n');
+ h = h.replace(/\s*<(p|h[1-6]|blockquote|div|title|style|pre|script|td|li|area)(|[^>]+)>/g, '\n<$1$2>');
+ h = h.replace(/<\/(p|h[1-6]|blockquote|div|title|style|pre|script|td|li)>\s*/g, '</$1>\n');
h = h.replace(/\n\n/g, '\n');
}
}
@@ -4030,18 +4071,22 @@
o.items = o.items || [];
function enc(s) {
- return s.replace(/[\r\n]/g, function(c) {
+ return s.replace(/[\r\n\\]/g, function(c) {
if (c === '\n')
return '\\n';
+ else if (c === '\\')
+ return '\\\\';
return '\\r';
});
};
function dec(s) {
- return s.replace(/\\[rn]/g, function(c) {
+ return s.replace(/\\[\\rn]/g, function(c) {
if (c === '\\n')
return '\n';
+ else if (c === '\\\\')
+ return '\\';
return '\r';
});
@@ -4133,7 +4178,7 @@
} else {
// Remove internal mceItemXX classes when content is extracted from editor
if (na == 'class' && this.processObj.get)
- v = v.replace(/\bmceItem\w+\b/g, '');
+ v = v.replace(/\s?mceItem\w+\s?/g, '');
}
if (v === '')
@@ -4158,6 +4203,10 @@
this.lookup = {};
},
+ isDone : function(u) {
+ return this.lookup[u] ? this.lookup[u].state == 2 : 0;
+ },
+
markDone : function(u) {
this.lookup[u] = {state : 2, url : u};
},
@@ -4648,12 +4697,15 @@
s.vp_offset_y = s.vp_offset_y || 0;
if (is(s.icons) && !s.icons)
- s['class'] += ' noIcons';
+ s['class'] += ' mceNoIcons';
this.parent(id, s);
this.onShowMenu = new tinymce.util.Dispatcher(this);
this.onHideMenu = new tinymce.util.Dispatcher(this);
this.classPrefix = 'mceMenu';
+
+ // Fix for odd IE bug: #1903622
+ this.fixIE = tinymce.isIE && window.top != window;
},
createMenu : function(s) {
@@ -4743,7 +4795,7 @@
t.element.update();
t.isMenuVisible = 1;
- t.mouseClickFunc = Event.add(co, 'click', function(e) {
+ t.mouseClickFunc = Event.add(co, t.fixIE ? 'mousedown' : 'click', function(e) {
var m;
e = e.target;
@@ -4805,7 +4857,7 @@
return;
Event.remove(co, 'mouseover', t.mouseOverFunc);
- Event.remove(co, 'click', t.mouseClickFunc);
+ Event.remove(co, t.fixIE ? 'mousedown' : 'click', t.mouseClickFunc);
DOM.hide(co);
t.isMenuVisible = 0;
@@ -4888,7 +4940,7 @@
DOM.add(ro, 'td', {'class' : 'mceMenuItemSeparator'});
if (n = ro.previousSibling)
- DOM.addClass(n, 'last');
+ DOM.addClass(n, 'mceLast');
return;
}
@@ -4899,25 +4951,25 @@
DOM.addClass(it, s['class']);
// n = DOM.add(n, 'span', {'class' : 'item'});
- DOM.add(n, 'span', {'class' : 'icon' + (s.icon ? ' ' + s.icon : '')});
- n = DOM.add(n, s.element || 'span', {'class' : 'text', title : o.settings.title}, o.settings.title);
+ DOM.add(n, 'span', {'class' : 'mceIcon' + (s.icon ? ' mce_' + s.icon : '')});
+ n = DOM.add(n, s.element || 'span', {'class' : 'mceText', title : o.settings.title}, o.settings.title);
if (o.settings.style)
DOM.setAttrib(n, 'style', o.settings.style);
if (tb.childNodes.length == 1)
- DOM.addClass(ro, 'first');
+ DOM.addClass(ro, 'mceFirst');
if ((n = ro.previousSibling) && DOM.hasClass(n, 'mceMenuItemSeparator'))
- DOM.addClass(ro, 'first');
+ DOM.addClass(ro, 'mceFirst');
if (o.collapse)
DOM.addClass(ro, 'mceMenuItemSub');
if (n = ro.previousSibling)
- DOM.removeClass(n, 'last');
-
- DOM.addClass(ro, 'last');
+ DOM.removeClass(n, 'mceLast');
+
+ DOM.addClass(ro, 'mceLast');
}
});
@@ -4937,9 +4989,9 @@
var s = this.settings, h = '<a id="' + this.id + '" href="javascript:;" class="mceButton mceButtonEnabled ' + s['class'] + '" onmousedown="return false;" onclick="return false;" title="' + DOM.encode(s.title) + '">';
if (s.image)
- h += '<img class="icon" src="' + s.image + '" /></a>';
+ h += '<img class="mceIcon" src="' + s.image + '" /></a>';
else
- h += '<span class="icon ' + s['class'] + '"></span></a>';
+ h += '<span class="mceIcon ' + s['class'] + '"></span></a>';
return h;
},
@@ -4994,11 +5046,11 @@
// If no item was found then present title
if (!fv) {
DOM.setHTML(e, DOM.encode(t.settings.title));
- DOM.addClass(e, 'title');
+ DOM.addClass(e, 'mceTitle');
e = 0;
return;
} else
- DOM.removeClass(e, 'title');
+ DOM.removeClass(e, 'mceTitle');
}
e = 0;
@@ -5025,8 +5077,8 @@
var h = '', t = this, s = t.settings;
h = '<table id="' + t.id + '" cellpadding="0" cellspacing="0" class="mceListBox mceListBoxEnabled' + (s['class'] ? (' ' + s['class']) : '') + '"><tbody><tr>';
- h += '<td>' + DOM.createHTML('a', {id : t.id + '_text', href : 'javascript:;', 'class' : 'text', onclick : "return false;", onmousedown : 'return false;'}, DOM.encode(t.settings.title)) + '</td>';
- h += '<td>' + DOM.createHTML('a', {id : t.id + '_open', href : 'javascript:;', 'class' : 'open', onclick : "return false;", onmousedown : 'return false;'}, '<span></span>') + '</td>';
+ h += '<td>' + DOM.createHTML('a', {id : t.id + '_text', href : 'javascript:;', 'class' : 'mceText', onclick : "return false;", onmousedown : 'return false;'}, DOM.encode(t.settings.title)) + '</td>';
+ h += '<td>' + DOM.createHTML('a', {id : t.id + '_open', href : 'javascript:;', 'class' : 'mceOpen', onclick : "return false;", onmousedown : 'return false;'}, '<span></span>') + '</td>';
h += '</tr></tbody></table>';
return h;
@@ -5084,7 +5136,7 @@
m = t.settings.control_manager.createDropMenu(t.id + '_menu', {
menu_line : 1,
- 'class' : 'mceListBoxMenu noIcons',
+ 'class' : 'mceListBoxMenu mceNoIcons',
max_width : 150,
max_height : 150
});
@@ -5337,14 +5389,14 @@
h = '<tbody><tr>';
if (s.image)
- h1 = DOM.createHTML('img ', {src : s.image, 'class' : 'action ' + s['class']});
+ h1 = DOM.createHTML('img ', {src : s.image, 'class' : 'mceAction ' + s['class']});
else
- h1 = DOM.createHTML('span', {'class' : 'action ' + s['class']});
-
- h += '<td>' + DOM.createHTML('a', {id : t.id + '_action', href : 'javascript:;', 'class' : 'action ' + s['class'], onclick : "return false;", onmousedown : 'return false;', title : s.title}, h1) + '</td>';
+ h1 = DOM.createHTML('span', {'class' : 'mceAction ' + s['class']});
+
+ h += '<td>' + DOM.createHTML('a', {id : t.id + '_action', href : 'javascript:;', 'class' : 'mceAction ' + s['class'], onclick : "return false;", onmousedown : 'return false;', title : s.title}, h1) + '</td>';
- h1 = DOM.createHTML('span', {'class' : 'open ' + s['class']});
- h += '<td>' + DOM.createHTML('a', {id : t.id + '_open', href : 'javascript:;', 'class' : 'open ' + s['class'], onclick : "return false;", onmousedown : 'return false;', title : s.title}, h1) + '</td>';
+ h1 = DOM.createHTML('span', {'class' : 'mceOpen ' + s['class']});
+ h += '<td>' + DOM.createHTML('a', {id : t.id + '_open', href : 'javascript:;', 'class' : 'mceOpen ' + s['class'], onclick : "return false;", onmousedown : 'return false;', title : s.title}, h1) + '</td>';
h += '</tr></tbody>';
@@ -5471,8 +5523,8 @@
if (s.more_colors_func) {
n = DOM.add(tb, 'tr');
- n = DOM.add(n, 'td', {colspan : s.grid_width, 'class' : 'morecolors'});
- n = DOM.add(n, 'a', {href : 'javascript:;', onclick : 'return false;', 'class' : 'morecolors'}, s.more_colors_title);
+ n = DOM.add(n, 'td', {colspan : s.grid_width, 'class' : 'mceMoreColors'});
+ n = DOM.add(n, 'a', {href : 'javascript:;', onclick : 'return false;', 'class' : 'mceMoreColors'}, s.more_colors_title);
Event.add(n, 'click', function(e) {
s.more_colors_func.call(s.more_colors_scope || this);
@@ -5699,23 +5751,26 @@
switch (s.mode) {
case "exact":
l = s.elements || '';
- each(l.split(','), function(v) {
- if (DOM.get(v))
- new tinymce.Editor(v, s).render(1);
- else {
- c = 0;
-
- each(document.forms, function(f) {
- each(f.elements, function(e) {
- if (e.name === v) {
- v = 'mce_editor_' + c;
- DOM.setAttrib(e, 'id', v);
- new tinymce.Editor(v, s).render(1);
- }
+
+ if(l.length > 0) {
+ each(l.split(','), function(v) {
+ if (DOM.get(v))
+ new tinymce.Editor(v, s).render(1);
+ else {
+ c = 0;
+
+ each(document.forms, function(f) {
+ each(f.elements, function(e) {
+ if (e.name === v) {
+ v = 'mce_editor_' + c;
+ DOM.setAttrib(e, 'id', v);
+ new tinymce.Editor(v, s).render(1);
+ }
+ });
});
- });
- }
- });
+ }
+ });
+ }
break;
case "textareas":
@@ -5894,8 +5949,8 @@
tinymce.baseURL = new tinymce.util.URI(tinymce.documentBaseURL).toAbsolute(tinymce.baseURL);
tinymce.EditorManager.baseURI = new tinymce.util.URI(tinymce.baseURL);
- if (tinymce.EditorManager.baseURI.host != document.domain)
- document.domain = tinymce.relaxedDomain = document.domain.replace(/.*\.(.+\..+)$/, '$1');
+ if (tinymce.EditorManager.baseURI.host != window.location.hostname)
+ document.domain = tinymce.relaxedDomain = window.location.hostname.replace(/.*\.(.+\..+)$/, '$1');
})();
// Short for editor manager window.tinyMCE is needed when TinyMCE gets loaded though a XHR call
@@ -6000,6 +6055,7 @@
padd_empty_editor : 1,
render_ui : 1,
init_theme : 1,
+ force_p_newlines : 1,
indentation : '30px'
}, s);
@@ -6016,6 +6072,14 @@
render : function(nst) {
var t = this, s = t.settings, id = t.id, sl = tinymce.ScriptLoader;
+ // Page is not loaded yet, wait for it
+ if (!Event.domLoaded) {
+ Event.add(document, 'init', function() {
+ t.render();
+ });
+ return;
+ }
+
// Force strict loading mode if render us called by user and not internally
if (!nst) {
s.strict_loading_mode = 1;
@@ -6138,7 +6202,7 @@
},
init : function() {
- var n, t = this, s = t.settings, w, h, e = t.getElement(), o, ti, u;
+ var n, t = this, s = t.settings, w, h, e = t.getElement(), o, ti, u, bi, bc, re;
EditorManager.add(t);
@@ -6202,8 +6266,9 @@
// Remove ghost selections on images and tables in Gecko
if (isGecko) {
- function repaint() {
- t.execCommand('mceRepaint');
+ function repaint(a, o) {
+ if (!o || !o.initial)
+ t.execCommand('mceRepaint');
};
t.onUndo.add(repaint);
@@ -6219,11 +6284,12 @@
w = s.width || e.style.width || e.clientWidth;
h = s.height || e.style.height || e.clientHeight;
t.orgDisplay = e.style.display;
-
- if (('' + w).indexOf('%') == -1)
+ re = new RegExp('%|px|auto', 'gi');
+
+ if (!re.test('' + w))
w = Math.max(parseInt(w) + (o.deltaWidth || 0), 100);
- if (('' + h).indexOf('%') == -1)
+ if (!re.test('' + h))
h = Math.max(parseInt(h) + (o.deltaHeight || 0), 100);
// Render UI
@@ -6255,20 +6321,32 @@
if (tinymce.relaxedDomain)
t.iframeHTML += '<script type="text/javascript">document.domain = "' + tinymce.relaxedDomain + '";</script>';
- t.iframeHTML += '</head><body id="tinymce" class="mceContentBody"></body></html>';
+ bi = s.body_id || 'tinymce';
+ if (bi.indexOf('=') != -1) {
+ bi = t.getParam('body_id', '', 'hash');
+ bi = bi[t.id] || bi;
+ }
+
+ bc = s.body_class || '';
+ if (bc.indexOf('=') != -1) {
+ bc = t.getParam('body_class', '', 'hash');
+ bc = bc[t.id] || '';
+ }
+
+ t.iframeHTML += '</head><body id="' + bi + '" class="mceContentBody ' + bc + '"></body></html>';
// Domain relaxing enabled, then set document domain
if (tinymce.relaxedDomain) {
// We need to write the contents here in IE since multiple writes messes up refresh button and back button
if (isIE)
- u = 'javascript:(function(){document.open();document.domain="' + document.domain + '";var ed = window.parent.tinyMCE.get("' + s.id + '");document.write(ed.iframeHTML);document.close();ed.setupIframe();})()';
+ u = 'javascript:(function(){document.open();document.domain="' + document.domain + '";var ed = window.parent.tinyMCE.get("' + t.id + '");document.write(ed.iframeHTML);document.close();ed.setupIframe();})()';
else if (tinymce.isOpera)
u = 'javascript:(function(){document.open();document.domain="' + document.domain + '";document.close();ed.setupIframe();})()';
}
// Create iframe
n = DOM.add(o.iframeContainer, 'iframe', {
- id : s.id + "_ifr",
+ id : t.id + "_ifr",
src : u || 'javascript:""', // Workaround for HTTPS warning in IE6/7
frameBorder : '0',
style : {
@@ -6279,7 +6357,7 @@
t.contentAreaContainer = o.iframeContainer;
DOM.get(o.editorContainer).style.display = t.orgDisplay;
- DOM.get(s.id).style.display = 'none';
+ DOM.get(t.id).style.display = 'none';
// Safari 2.x requires us to wait for the load event and load a real HTML doc
if (tinymce.isOldWebKit) {
@@ -6294,7 +6372,7 @@
},
setupIframe : function() {
- var t = this, s = t.settings, e = DOM.get(s.id), d = t.getDoc(), h;
+ var t = this, s = t.settings, e = DOM.get(t.id), d = t.getDoc(), h;
// Setup iframe body
if (!isIE || !tinymce.relaxedDomain) {
@@ -6638,8 +6716,28 @@
return EditorManager.i18n[this.settings.language + '.' + n] || (is(dv) ? dv : '{#' + n + '}');
},
- getParam : function(n, dv) {
- return is(this.settings[n]) ? this.settings[n] : dv;
+ getParam : function(n, dv, ty) {
+ var tr = tinymce.trim, v = is(this.settings[n]) ? this.settings[n] : dv, o;
+
+ if (ty === 'hash') {
+ o = {};
+
+ if (is(v, 'string')) {
+ each(v.split(/[;,]/), function(v) {
+ v = v.split('=');
+
+ if (v.length > 1)
+ o[tr(v[0])] = tr(v[1]);
+ else
+ o[tr(v[0])] = tr(v);
+ });
+ } else
+ o = v;
+
+ return o;
+ }
+
+ return v;
},
nodeChanged : function(o) {
@@ -6800,7 +6898,11 @@
return o;
// Browser commands
- return this.getDoc().queryCommandState(c);
+ try {
+ return this.getDoc().queryCommandState(c);
+ } catch (ex) {
+ // Fails sometimes see bug: 1896577
+ }
},
queryCommandValue : function(c) {
@@ -6820,7 +6922,11 @@
return o;
// Browser commands
- return this.getDoc().queryCommandValue(c);
+ try {
+ return this.getDoc().queryCommandValue(c);
+ } catch (ex) {
+ // Fails sometimes see bug: 1896577
+ }
},
show : function() {
@@ -6832,15 +6938,16 @@
},
hide : function() {
- var t = this, s = t.settings, d = t.getDoc();
+ var t = this, d = t.getDoc();
// Fixed bug where IE has a blinking cursor left from the editor
if (isIE && d)
d.execCommand('SelectAll');
+ // We must save before we hide so Safari doesn't crash
+ t.save();
DOM.hide(t.getContainer());
- DOM.setStyle(s.id, 'display', t.orgDisplay);
- t.save();
+ DOM.setStyle(t.id, 'display', t.orgDisplay);
},
isHidden : function() {
@@ -6863,6 +6970,9 @@
t.execCallback('remove_instance_callback', t);
t.onRemove.dispatch(t);
+ // Clear all execCommand listeners this is required to avoid errors if the editor was removed inside another command
+ t.onExecCommand.listeners = [];
+
EditorManager.remove(t);
},
@@ -7040,8 +7150,8 @@
if (s.urlconverter_callback)
return t.execCallback('urlconverter_callback', u, e, true, n);
- // Don't convert link href since thats the CSS files that gets loaded into the editor
- if (!s.convert_urls || (e && e.nodeName == 'LINK'))
+ // Don't convert link href since thats the CSS files that gets loaded into the editor also skip local file URLs
+ if (!s.convert_urls || (e && e.nodeName == 'LINK') || u.indexOf('file:') === 0)
return u;
// Convert to relative
@@ -7532,7 +7642,7 @@
},
_convertInlineElements : function() {
- var t = this, s = t.settings, dom = t.dom, v;
+ var t = this, s = t.settings, dom = t.dom, v, e, na, st, sp;
function convert(ed, o) {
if (!s.inline_styles)
@@ -7549,11 +7659,11 @@
break;
case 'U':
- dom.replace(dom.create('span', {style : 'text-decoration: underline;'}), n, 1);
- break;
-
case 'STRIKE':
- dom.replace(dom.create('span', {style : 'text-decoration: line-through;'}), n, 1);
+ sp = dom.create('span', {style : dom.getAttrib(n, 'style')});
+ sp.style.textDecoration = n.nodeName == 'U' ? 'underline' : 'line-through';
+ dom.setAttrib(sp, 'mce_style', '');
+ dom.replace(sp, n, 1);
break;
}
});
@@ -7565,9 +7675,22 @@
} else {
// Convert spans to elements
if (n.style.textDecoration == 'underline')
- dom.replace(dom.create('u'), n, 1);
+ na = 'u';
else if (n.style.textDecoration == 'line-through')
- dom.replace(dom.create('strike'), n, 1);
+ na = 'strike';
+ else
+ na = '';
+
+ if (na) {
+ n.style.textDecoration = '';
+ dom.setAttrib(n, 'mce_style', '');
+
+ e = dom.create(na, {
+ style : dom.getAttrib(n, 'style')
+ });
+
+ dom.replace(e, n, 1);
+ }
}
});
}
@@ -7583,7 +7706,7 @@
},
_convertFonts : function() {
- var t = this, s = t.settings, dom = t.dom, sl, cl, fz, fzn, v, i, st;
+ var t = this, s = t.settings, dom = t.dom, sl, cl, fz, fzn, v, i, st, x, nl, sp, f, n;
// No need
if (!s.inline_styles)
@@ -7604,8 +7727,11 @@
if (tinymce.isWebKit || !s.inline_styles)
return;
- each(t.dom.select('span', no), function(n) {
- var f = dom.create('font', {
+ nl = t.dom.select('span', no);
+ for (x = nl.length - 1; x >= 0; x--) {
+ n = nl[x];
+
+ f = dom.create('font', {
color : dom.toHex(dom.getStyle(n, 'color')),
face : dom.getStyle(n, 'fontFamily'),
style : dom.getAttrib(n, 'style')
@@ -7639,13 +7765,12 @@
dom.setAttrib(f, 'mce_style', '');
dom.replace(f, n, 1);
}
- });
+ }
};
// Run on setup
t.onSetContent.add(function(ed, o) {
- if (o.initial)
- convertToFonts(ed.getBody());
+ convertToFonts(ed.getBody());
});
// Run on cleanup
@@ -7655,8 +7780,11 @@
return;
if (o.get) {
- each(t.dom.select('font', o.node), function(n) {
- var sp = dom.create('span', {
+ nl = t.dom.select('font', o.node);
+ for (x = nl.length - 1; x >= 0; x--) {
+ n = nl[x];
+
+ sp = dom.create('span', {
style : dom.getAttrib(n, 'style')
});
@@ -7675,9 +7803,8 @@
dom.setAttrib(sp, 'mce_style', '');
dom.replace(sp, n, 1);
- });
- } else if (o.set)
- convertToFonts(o.node);
+ }
+ }
});
},
@@ -8467,6 +8594,133 @@
},
mceBlockQuote : function() {
+ var t = this, ed = t.editor, s = ed.selection, dom = ed.dom, sb, eb, n, bm, bq, r, bq2, i, nl;
+
+ function getBQ(e) {
+ return dom.getParent(e, function(n) {return n.nodeName === 'BLOCKQUOTE';});
+ };
+
+ // Get start/end block
+ sb = dom.getParent(s.getStart(), dom.isBlock);
+ eb = dom.getParent(s.getEnd(), dom.isBlock);
+
+ // Remove blockquote(s)
+ if (bq = getBQ(sb)) {
+ if (sb != eb || sb.childNodes.length > 1 || (sb.childNodes.length == 1 && sb.firstChild.nodeName != 'BR'))
+ bm = s.getBookmark();
+
+ // Move all elements after the end block into new bq
+ if (getBQ(eb)) {
+ bq2 = bq.cloneNode(false);
+
+ while (n = eb.nextSibling)
+ bq2.appendChild(n.parentNode.removeChild(n));
+ }
+
+ // Add new bq after
+ if (bq2)
+ dom.insertAfter(bq2, bq);
+
+ // Move all selected blocks after the current bq
+ nl = t._getSelectedBlocks(sb, eb);
+ for (i = nl.length - 1; i >= 0; i--) {
+ dom.insertAfter(nl[i], bq);
+ }
+
+ // Empty bq, then remove it
+ if (/^\s*$/.test(bq.innerHTML))
+ dom.remove(bq, 1); // Keep children so boomark restoration works correctly
+
+ // Empty bq, then remote it
+ if (bq2 && /^\s*$/.test(bq2.innerHTML))
+ dom.remove(bq2, 1); // Keep children so boomark restoration works correctly
+
+ if (!bm) {
+ // Move caret inside empty block element
+ if (!isIE) {
+ r = ed.getDoc().createRange();
+ r.setStart(sb, 0);
+ r.setEnd(sb, 0);
+ s.setRng(r);
+ } else {
+ s.select(sb);
+ s.collapse(0);
+
+ // IE misses the empty block some times element so we must move back the caret
+ if (dom.getParent(s.getStart(), dom.isBlock) != sb) {
+ r = s.getRng();
+ r.move('character', -1);
+ r.select();
+ }
+ }
+ } else
+ t.editor.selection.moveToBookmark(bm);
+
+ return;
+ }
+
+ // Since IE can start with a totally empty document we need to add the first bq and paragraph
+ if (isIE && !sb && !eb) {
+ t.editor.getDoc().execCommand('Indent');
+ n = getBQ(s.getNode());
+ n.style.margin = n.dir = ''; // IE adds margin and dir to bq
+ return;
+ }
+
+ if (!sb || !eb)
+ return;
+
+ // If empty paragraph node then do not use bookmark
+ if (sb != eb || sb.childNodes.length > 1 || (sb.childNodes.length == 1 && sb.firstChild.nodeName != 'BR'))
+ bm = s.getBookmark();
+
+ // Move selected block elements into a bq
+ each(t._getSelectedBlocks(getBQ(s.getStart()), getBQ(s.getEnd())), function(e) {
+ // Found existing BQ add to this one
+ if (e.nodeName == 'BLOCKQUOTE' && !bq) {
+ bq = e;
+ return;
+ }
+
+ // No BQ found, create one
+ if (!bq) {
+ bq = dom.create('blockquote');
+ e.parentNode.insertBefore(bq, e);
+ }
+
+ // Add children from existing BQ
+ if (e.nodeName == 'BLOCKQUOTE' && bq) {
+ n = e.firstChild;
+
+ while (n) {
+ bq.appendChild(n.cloneNode(true));
+ n = n.nextSibling;
+ }
+
+ dom.remove(e);
+ return;
+ }
+
+ // Add non BQ element to BQ
+ bq.appendChild(dom.remove(e));
+ });
+
+ if (!bm) {
+ // Move caret inside empty block element
+ if (!isIE) {
+ r = ed.getDoc().createRange();
+ r.setStart(sb, 0);
+ r.setEnd(sb, 0);
+ s.setRng(r);
+ } else {
+ s.select(sb);
+ s.collapse(1);
+ }
+ } else
+ s.moveToBookmark(bm);
+ },
+/*
+ _mceBlockQuote : function() {
var t = this, s = t.editor.selection, b = s.getBookmark(), bq, dom = t.editor.dom;
function findBQ(e) {
@@ -8520,7 +8774,7 @@
t.editor.selection.moveToBookmark(b);
},
-
+*/
_getSelectedBlocks : function(st, en) {
var ed = this.editor, dom = ed.dom, s = ed.selection, sb, eb, n, bl = [];
@@ -8588,7 +8842,7 @@
}
}
- if (s.custom_undo_redo_restore_selection)
+ if (s.custom_undo_redo_restore_selection && !l.initial)
l.bookmark = b = l.bookmark || ed.selection.getBookmark();
if (t.index < t.data.length && t.data[t.index].initial)
@@ -8690,17 +8944,10 @@
tinymce.create('tinymce.ForceBlocks', {
ForceBlocks : function(ed) {
- var t = this, s, elm;
+ var t = this, s = ed.settings, elm;
t.editor = ed;
t.dom = ed.dom;
-
- // Default settings
- t.settings = s = extend({
- forced_root_block : 'p',
- force_p_newlines : true
- }, ed.settings);
-
elm = (s.forced_root_block || 'p').toLowerCase();
s.element = elm.toUpperCase();
@@ -8738,7 +8985,7 @@
},
setup : function() {
- var t = this, ed = t.editor, s = t.settings;
+ var t = this, ed = t.editor, s = ed.settings;
// Force root blocks when typing and when getting output
if (s.forced_root_block) {
@@ -8897,7 +9144,7 @@
}
}
- bl = ed.dom.create(t.settings.forced_root_block);
+ bl = ed.dom.create(ed.settings.forced_root_block);
bl.appendChild(nx.cloneNode(1));
nx.parentNode.replaceChild(bl, nx);
}
@@ -8914,7 +9161,7 @@
// Restore selection
if (si != -2) {
if (!isIE) {
- bl = d.getElementsByTagName(t.settings.element)[0];
+ bl = d.getElementsByTagName(ed.settings.element)[0];
r = d.createRange();
// Select last location or generated block
@@ -8955,7 +9202,7 @@
},
insertPara : function(e) {
- var t = this, ed = t.editor, d = ed.getDoc(), se = t.settings, s = ed.selection.getSel(), r = s.getRangeAt(0), b = d.body;
+ var t = this, ed = t.editor, d = ed.getDoc(), se = ed.settings, s = ed.selection.getSel(), r = s.getRangeAt(0), b = d.body;
var rb, ra, dir, sn, so, en, eo, sb, eb, bn, bef, aft, sc, ec, n;
function isEmpty(n) {
@@ -9153,9 +9400,9 @@
if (sc && ed.dom.isBlock(sc) && bs) {
if (sc.childNodes.length == 1 && sc.firstChild.nodeName == 'BR') {
n = sc.previousSibling;
- if (n) {
+ if (n) {
ed.dom.remove(sc);
- se.select(n, 1);
+ se.select(n.firstChild);
se.collapse(0);
return Event.cancel(e);
}
@@ -9266,13 +9513,15 @@
},
createDropMenu : function(id, s) {
- var t = this, ed = t.editor, c, bm;
+ var t = this, ed = t.editor, c, bm, v;
s = extend({
'class' : 'mceDropDown'
}, s);
s['class'] = s['class'] + ' ' + ed.getParam('skin') + 'Skin';
+ if (v = ed.getParam('skin_variant'))
+ s['class'] += ' ' + ed.getParam('skin') + 'Skin' + v.substring(0, 1).toUpperCase() + v.substring(1);
id = t.prefix + id;
c = t.controls[id] = new tinymce.ui.DropMenu(id, s);
@@ -9329,7 +9578,7 @@
s = extend({
title : s.title,
- 'class' : id,
+ 'class' : 'mce_' + id,
scope : s.scope,
control_manager : t
}, s);
@@ -9382,7 +9631,7 @@
s = extend({
title : s.title,
- 'class' : id,
+ 'class' : 'mce_' + id,
unavailable_prefix : ed.getLang('unavailable', ''),
scope : s.scope,
control_manager : t
@@ -9429,7 +9678,7 @@
s = extend({
title : s.title,
- 'class' : id,
+ 'class' : 'mce_' + id,
scope : s.scope,
control_manager : t
}, s);
@@ -9464,7 +9713,7 @@
s = extend({
title : s.title,
- 'class' : id,
+ 'class' : 'mce_' + id,
'menu_class' : ed.getParam('skin') + 'Skin',
scope : s.scope,
more_colors_title : ed.getLang('more_colors')