summaryrefslogtreecommitdiff
path: root/program/js/tiny_mce/tiny_mce_src.js
diff options
context:
space:
mode:
authorthomascube <thomas@roundcube.net>2011-04-20 09:57:35 +0000
committerthomascube <thomas@roundcube.net>2011-04-20 09:57:35 +0000
commit61517ce39da8d64b37328ee98d2d53a408351dd4 (patch)
treea80015b06b6be5e9016c114254dc1c98418d55bb /program/js/tiny_mce/tiny_mce_src.js
parentf6bd52054daaf2d41deead7fb86753d1bbbaf843 (diff)
Updated to TinyMCE 3.4.2 which is now compatible with IE9
Diffstat (limited to 'program/js/tiny_mce/tiny_mce_src.js')
-rw-r--r--program/js/tiny_mce/tiny_mce_src.js230
1 files changed, 145 insertions, 85 deletions
diff --git a/program/js/tiny_mce/tiny_mce_src.js b/program/js/tiny_mce/tiny_mce_src.js
index b28a65a07..c1d47fcb7 100644
--- a/program/js/tiny_mce/tiny_mce_src.js
+++ b/program/js/tiny_mce/tiny_mce_src.js
@@ -5,9 +5,9 @@
var tinymce = {
majorVersion : '3',
- minorVersion : '4.1',
+ minorVersion : '4.2',
- releaseDate : '2011-03-24',
+ releaseDate : '2011-04-07',
_init : function() {
var t = this, d = document, na = navigator, ua = na.userAgent, i, nl, n, base, p, v;
@@ -1407,7 +1407,7 @@ tinymce.html.Styles = function(settings, schema) {
name = styleList[i];
value = styles[name];
- if (value !== undef)
+ if (value !== undef && value.length > 0)
css += (css.length > 0 ? ' ' : '') + name + ': ' + value + ';';
}
}
@@ -1423,7 +1423,7 @@ tinymce.html.Styles = function(settings, schema) {
for (name in styles) {
value = styles[name];
- if (value !== undef)
+ if (value !== undef && value.length > 0)
css += (css.length > 0 ? ' ' : '') + name + ': ' + value + ';';
}
}
@@ -2483,11 +2483,12 @@ tinymce.html.Styles = function(settings, schema) {
},
isEmpty : function(elements) {
- var self = this, node = self.firstChild, i;
+ var self = this, node = self.firstChild, i, name;
if (node) {
do {
if (node.type === 1) {
+ // Ignore bogus elements
if (node.attributes.map['data-mce-bogus'])
continue;
@@ -2495,10 +2496,11 @@ tinymce.html.Styles = function(settings, schema) {
if (elements[node.name])
return false;
- // Keep elements with data attributes
+ // Keep elements with data attributes or name attribute like <a name="1"></a>
i = node.attributes.length;
while (i--) {
- if (node.attributes[i].name.indexOf('data-') === 0)
+ name = node.attributes[i].name;
+ if (name === "name" || name.indexOf('data-') === 0)
return false;
}
}
@@ -2540,6 +2542,7 @@ tinymce.html.Styles = function(settings, schema) {
var self = this, nodeFilters = {}, attributeFilters = [], matchedNodes = {}, matchedAttributes = {};
settings = settings || {};
+ settings.validate = "validate" in settings ? settings.validate : true;
settings.root_name = settings.root_name || 'body';
self.schema = schema = schema || new tinymce.html.Schema();
@@ -2690,16 +2693,17 @@ tinymce.html.Styles = function(settings, schema) {
};
self.parse = function(html, args) {
- var parser, rootNode, node, nodes, i, l, fi, fl, list, name,
+ var parser, rootNode, node, nodes, i, l, fi, fl, list, name, validate,
blockElements, startWhiteSpaceRegExp, invalidChildren = [],
endWhiteSpaceRegExp, allWhiteSpaceRegExp, whiteSpaceElements, children, nonEmptyElements;
args = args || {};
matchedNodes = {};
matchedAttributes = {};
- blockElements = tinymce.extend(tinymce.makeMap('script,style,head,title,meta,param'), schema.getBlockElements());
+ blockElements = tinymce.extend(tinymce.makeMap('script,style,head,html,body,title,meta,param'), schema.getBlockElements());
nonEmptyElements = schema.getNonEmptyElements();
children = schema.children;
+ validate = settings.validate;
whiteSpaceElements = schema.getWhiteSpaceElements();
startWhiteSpaceRegExp = /^[ \t\r\n]+/;
@@ -2721,9 +2725,26 @@ tinymce.html.Styles = function(settings, schema) {
return node;
};
+ function removeWhitespaceBefore(node) {
+ var textNode, textVal, sibling;
+
+ for (textNode = node.prev; textNode && textNode.type === 3; ) {
+ textVal = textNode.value.replace(endWhiteSpaceRegExp, '');
+
+ if (textVal.length > 0) {
+ textNode.value = textVal;
+ textNode = textNode.prev;
+ } else {
+ sibling = textNode.prev;
+ textNode.remove();
+ textNode = sibling;
+ }
+ }
+ };
+
parser = new tinymce.html.SaxParser({
- validate : settings.validate,
- fix_self_closing : false, // Let the DOM parser handle <li> in <li> or <p> in <p> for better results
+ validate : validate,
+ fix_self_closing : !validate, // Let the DOM parser handle <li> in <li> or <p> in <p> for better results
cdata: function(text) {
node.append(createNode('#cdata', 4)).value = text;
@@ -2754,16 +2775,21 @@ tinymce.html.Styles = function(settings, schema) {
pi: function(name, text) {
node.append(createNode(name, 7)).value = text;
+ removeWhitespaceBefore(node);
},
doctype: function(text) {
- node.append(createNode('#doctype', 10)).value = text;
+ var newNode;
+
+ newNode = node.append(createNode('#doctype', 10));
+ newNode.value = text;
+ removeWhitespaceBefore(node);
},
start: function(name, attrs, empty) {
var newNode, attrFiltersLen, elementRule, textNode, attrName, text, sibling, parent;
- elementRule = schema.getElementRule(name);
+ elementRule = validate ? schema.getElementRule(name) : {};
if (elementRule) {
newNode = createNode(elementRule.outputName || name, 1);
newNode.attributes = attrs;
@@ -2792,20 +2818,8 @@ tinymce.html.Styles = function(settings, schema) {
}
// Trim whitespace before block
- if (blockElements[name]) {
- for (textNode = newNode.prev; textNode && textNode.type === 3; ) {
- text = textNode.value.replace(endWhiteSpaceRegExp, '');
-
- if (text.length > 0) {
- textNode.value = text;
- textNode = textNode.prev;
- } else {
- sibling = textNode.prev;
- textNode.remove();
- textNode = sibling;
- }
- }
- }
+ if (blockElements[name])
+ removeWhitespaceBefore(newNode);
// Change current node if the element wasn't empty i.e not <br /> or <img />
if (!empty)
@@ -2816,7 +2830,7 @@ tinymce.html.Styles = function(settings, schema) {
end: function(name) {
var textNode, elementRule, text, sibling, tempNode;
- elementRule = schema.getElementRule(name);
+ elementRule = validate ? schema.getElementRule(name) : {};
if (elementRule) {
if (blockElements[name]) {
if (!whiteSpaceElements[node.name]) {
@@ -2887,7 +2901,8 @@ tinymce.html.Styles = function(settings, schema) {
parser.parse(html);
- fixInvalidChildren(invalidChildren);
+ if (validate)
+ fixInvalidChildren(invalidChildren);
// Run node filters
for (name in matchedNodes) {
@@ -3019,8 +3034,12 @@ tinymce.html.Writer = function(settings) {
else
html[html.length] = ' />';
- /*if (indent && indentAfter[name])
- html.push('\n');*/
+ if (empty && indent && indentAfter[name] && html.length > 0) {
+ value = html[html.length - 1];
+
+ if (value.length > 0 && value !== '\n')
+ html.push('\n');
+ }
},
end: function(name) {
@@ -3061,10 +3080,13 @@ tinymce.html.Writer = function(settings) {
html.push('<?', name, ' ', text, '?>');
else
html.push('<?', name, '?>');
+
+ if (indent)
+ html.push('\n');
},
doctype: function(text) {
- html.push('<!DOCTYPE', text, '>');
+ html.push('<!DOCTYPE', text, '>', indent ? '\n' : '');
},
reset: function() {
@@ -3201,7 +3223,8 @@ tinymce.html.Writer = function(settings) {
isIE = tinymce.isIE,
Entities = tinymce.html.Entities,
simpleSelectorRe = /^([a-z0-9],?)+$/i,
- blockElementsMap = tinymce.html.Schema.blockElementsMap;
+ blockElementsMap = tinymce.html.Schema.blockElementsMap,
+ whiteSpaceRegExp = /^[ \t\r\n]*$/;
tinymce.create('tinymce.dom.DOMUtils', {
doc : null,
@@ -3239,7 +3262,8 @@ tinymce.html.Writer = function(settings) {
keep_values : false,
hex_colors : 1
}, s);
-
+
+ t.schema = s.schema;
t.styles = new tinymce.html.Styles({
url_converter : s.url_converter,
url_converter_scope : s.url_converter_scope
@@ -3469,9 +3493,7 @@ tinymce.html.Writer = function(settings) {
remove : function(node, keep_children) {
return this.run(node, function(node) {
- var parent, child;
-
- parent = node.parentNode;
+ var child, parent = node.parentNode;
if (!parent)
return null;
@@ -3539,7 +3561,7 @@ tinymce.html.Writer = function(settings) {
n = this.get(n);
if (!n)
- return false;
+ return;
// Gecko
if (this.doc.defaultView && c) {
@@ -3568,7 +3590,7 @@ tinymce.html.Writer = function(settings) {
if (n.currentStyle && c)
return n.currentStyle[na];
- return n.style[na];
+ return n.style ? n.style[na] : undefined;
},
setStyles : function(e, o) {
@@ -3589,8 +3611,8 @@ tinymce.html.Writer = function(settings) {
removeAllAttribs: function(e) {
return this.run(e, function(e) {
- var attrs = e.attributes;
- for (var i = attrs.length - 1; i >= 0; i--) {
+ var i, attrs = e.attributes;
+ for (i = attrs.length - 1; i >= 0; i--) {
e.removeAttributeNode(attrs.item(i));
}
});
@@ -3645,7 +3667,7 @@ tinymce.html.Writer = function(settings) {
}
break;
-
+
case "shape":
e.setAttribute('data-mce-style', v);
break;
@@ -4257,6 +4279,45 @@ tinymce.html.Writer = function(settings) {
return n.attributes;
},
+ isEmpty : function(node, elements) {
+ var self = this, i, attributes, type, walker, name;
+
+ node = node.firstChild;
+ if (node) {
+ walker = new tinymce.dom.TreeWalker(node);
+ elements = elements || self.schema ? self.schema.getNonEmptyElements() : null;
+
+ do {
+ type = node.nodeType;
+
+ if (type === 1) {
+ // Ignore bogus elements
+ if (node.getAttribute('data-mce-bogus'))
+ continue;
+
+ // Keep empty elements like <img />
+ if (elements && elements[node.nodeName.toLowerCase()])
+ return false;
+
+ // Keep elements with data attributes or name attribute like <a name="1"></a>
+ attributes = self.getAttribs(node);
+ i = node.attributes.length;
+ while (i--) {
+ name = node.attributes[i].nodeName;
+ if (name === "name" || name.indexOf('data-') === 0)
+ return false;
+ }
+ }
+
+ // Keep non whitespace text nodes
+ if ((type === 3 && !whiteSpaceRegExp.test(node.nodeValue)))
+ return false;
+ } while (node = walker.next());
+ }
+
+ return true;
+ },
+
destroy : function(s) {
var t = this;
@@ -4312,23 +4373,21 @@ tinymce.html.Writer = function(settings) {
// this function will then trim of empty edges and produce:
// <p>text 1</p><b>CHOP</b><p>text 2</p>
function trim(node) {
- var i, children = node.childNodes;
+ var i, children = node.childNodes, type = node.nodeType;
- if (node.nodeType == 1 && node.getAttribute('data-mce-type') == 'bookmark')
+ if (type == 1 && node.getAttribute('data-mce-type') == 'bookmark')
return;
for (i = children.length - 1; i >= 0; i--)
trim(children[i]);
- if (node.nodeType != 9) {
+ if (type != 9) {
// Keep non whitespace text nodes
- if (node.nodeType == 3 && node.nodeValue.length > 0) {
+ if (type == 3 && node.nodeValue.length > 0) {
// If parent element isn't a block or there isn't any useful contents for example "<p> </p>"
if (!t.isBlock(node.parentNode) || tinymce.trim(node.nodeValue).length > 0)
return;
- }
-
- if (node.nodeType == 1) {
+ } else if (type == 1) {
// If the only child is a bookmark then move it up
children = node.childNodes;
if (children.length == 1 && children[0] && children[0].nodeType == 1 && children[0].getAttribute('data-mce-type') == 'bookmark')
@@ -7428,7 +7487,13 @@ window.tinymce.dom.Sizzle = Sizzle;
if (s) {
t.explicitRange = r;
- s.removeAllRanges();
+
+ try {
+ s.removeAllRanges();
+ } catch (ex) {
+ // IE9 might throw errors here don't know why
+ }
+
s.addRange(r);
t.selectedRange = s.getRangeAt(0);
}
@@ -7860,6 +7925,10 @@ window.tinymce.dom.Sizzle = Sizzle;
htmlParser.parse(args.getInner ? node.innerHTML : tinymce.trim(dom.getOuterHTML(node), args), args)
);
+ // Replace all BOM characters for now until we can find a better solution
+ if (!args.cleanup)
+ args.content = args.content.replace(/\uFEFF/g, '');
+
// Post process
if (!args.no_events)
onPostProcess.dispatch(self, args);
@@ -9762,21 +9831,20 @@ tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', {
hideMenu : function(e) {
var t = this;
- // Prevent double toogles by canceling the mouse click event to the button
- if (e && e.type == "mousedown" && DOM.getParent(e.target, function(e) {return e.id === t.id + '_open';}))
- return;
-
- if (!e || !DOM.getParent(e.target, '.mceSplitButtonMenu')) {
- DOM.removeClass(t.id, 'mceSplitButtonSelected');
- Event.remove(DOM.doc, 'mousedown', t.hideMenu, t);
- Event.remove(t.id + '_menu', 'keydown', t._keyHandler);
- DOM.hide(t.id + '_menu');
- }
+ if (t.isMenuVisible) {
+ // Prevent double toogles by canceling the mouse click event to the button
+ if (e && e.type == "mousedown" && DOM.getParent(e.target, function(e) {return e.id === t.id + '_open';}))
+ return;
- t.onHideMenu.dispatch(t);
+ if (!e || !DOM.getParent(e.target, '.mceSplitButtonMenu')) {
+ DOM.removeClass(t.id, 'mceSplitButtonSelected');
+ Event.remove(DOM.doc, 'mousedown', t.hideMenu, t);
+ Event.remove(t.id + '_menu', 'keydown', t._keyHandler);
+ DOM.hide(t.id + '_menu');
+ }
- t.isMenuVisible = 0;
- t.editor.focus();
+ t.isMenuVisible = 0;
+ }
},
renderMenu : function() {
@@ -9950,7 +10018,7 @@ tinymce.create('tinymce.ui.ToolbarGroup:tinymce.ui.Container', {
(function(tinymce) {
// Shorten class names
-var dom = tinymce.DOM, each = tinymce.each
+var dom = tinymce.DOM, each = tinymce.each;
tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
renderHTML : function() {
var t = this, h = '', c, co, s = t.settings, i, pr, nx, cl;
@@ -12622,14 +12690,17 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
mceInsertContent : function(command, ui, value) {
var caretNode, rng, rootNode, parent, node, rng, nodeRect, viewPortRect, args;
- function findSuitableCaretNode(start_node, root_node) {
- var node, walker = new tinymce.dom.TreeWalker(start_node, root_node);
+ function findSuitableCaretNode(node, root_node, next) {
+ var walker = new tinymce.dom.TreeWalker(next ? node.nextSibling : node.previousSibling, root_node);
while ((node = walker.current())) {
if ((node.nodeType == 3 && tinymce.trim(node.nodeValue).length) || node.nodeName == 'BR' || node.nodeName == 'IMG')
return node;
- walker.prev();
+ if (next)
+ walker.next();
+ else
+ walker.prev();
}
};
@@ -12650,7 +12721,7 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
// Move the caret into the last suitable location within the previous sibling if it's a block since the block might be split
if (caretNode.previousSibling && dom.isBlock(caretNode.previousSibling) || caretNode.parentNode == rootNode) {
- node = findSuitableCaretNode(caretNode.previousSibling, rootNode);
+ node = findSuitableCaretNode(caretNode, rootNode);
if (node) {
if (node.nodeName == 'BR')
node.parentNode.insertBefore(caretNode, node);
@@ -12666,9 +12737,7 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
// This will remove invalid elements/attributes and fix nesting issues
dom.setOuterHTML(parent,
new tinymce.html.Serializer({}, editor.schema).serialize(
- new tinymce.html.DomParser({
- remove_trailing_brs : true
- }, editor.schema).parse(dom.getOuterHTML(parent))
+ editor.parser.parse(dom.getOuterHTML(parent))
)
);
@@ -12682,7 +12751,7 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
// Find caret after cleanup and move selection to that location
caretNode = dom.select('#__mce')[0];
if (caretNode) {
- node = findSuitableCaretNode(caretNode.previousSibling, rootNode);
+ node = findSuitableCaretNode(caretNode, rootNode) || findSuitableCaretNode(caretNode, rootNode, true);
dom.remove(caretNode);
if (node) {
@@ -12791,7 +12860,7 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
},
mceReplaceContent : function(command, ui, value) {
- editor.execCommand('mceInsertContent', false, selection.setContent(value.replace(/\{\$selection\}/g, selection.getContent({format : 'text'}))));
+ editor.execCommand('mceInsertContent', false, value.replace(/\{\$selection\}/g, selection.getContent({format : 'text'})));
},
mceInsertLink : function(command, ui, value) {
@@ -13064,19 +13133,10 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
return rng2.cloneContents().textContent.length == 0;
};
- function isEmpty(n) {
- n = n.innerHTML;
-
- n = n.replace(/<(img|hr|table|input|select|textarea)[ \>]/gi, '-'); // Keep these convert them to - chars
- n = n.replace(/<[^>]+>/g, ''); // Remove all tags
-
- return n.replace(/[ \u00a0\t\r\n]+/g, '') == '';
- };
-
function splitList(selection, dom, li) {
var listBlock, block;
- if (isEmpty(li)) {
+ if (dom.isEmpty(li)) {
listBlock = dom.getParent(li, 'ul,ol');
if (!dom.getParent(listBlock.parentNode, 'ul,ol')) {
@@ -13607,7 +13667,7 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
aft.innerHTML = aft.firstChild.innerHTML;
// Padd empty blocks
- if (isEmpty(bef))
+ if (dom.isEmpty(bef))
bef.innerHTML = '<br />';
function appendStyles(e, en) {
@@ -13641,7 +13701,7 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
};
// Fill empty afterblook with current style
- if (isEmpty(aft))
+ if (dom.isEmpty(aft))
car = appendStyles(aft, en);
// Opera needs this one backwards for older versions