vendor/assets/javascripts/wysihtml5x.js in wysihtml5x-rails-0.4.8 vs vendor/assets/javascripts/wysihtml5x.js in wysihtml5x-rails-0.4.9
- old
+ new
@@ -23,22 +23,22 @@
if(!Array.isArray) {
Array.isArray = function(arg) {
return Object.prototype.toString.call(arg) === '[object Array]';
};
};/**
- * @license wysihtml5x v0.4.8
+ * @license wysihtml5x v0.4.9
* https://github.com/Edicy/wysihtml5
*
* Author: Christopher Blum (https://github.com/tiff)
* Secondary author of extended features: Oliver Pulges (https://github.com/pulges)
*
* Copyright (C) 2012 XING AG
* Licensed under the MIT license (MIT)
*
*/
var wysihtml5 = {
- version: "0.4.8",
+ version: "0.4.9",
// namespaces
commands: {},
dom: {},
quirks: {},
@@ -5811,14 +5811,19 @@
wysihtml5.lang.object(currentRules).merge(defaultRules).merge(config.rules).get();
var context = config.context || elementOrHtml.ownerDocument || document,
fragment = context.createDocumentFragment(),
isString = typeof(elementOrHtml) === "string",
+ clearInternals = false,
element,
newNode,
firstChild;
+ if (config.clearInternals === true) {
+ clearInternals = true;
+ }
+
if (config.uneditableClass) {
uneditableClass = config.uneditableClass;
}
if (isString) {
@@ -5827,15 +5832,17 @@
element = elementOrHtml;
}
while (element.firstChild) {
firstChild = element.firstChild;
- newNode = _convert(firstChild, config.cleanUp);
- element.removeChild(firstChild);
+ newNode = _convert(firstChild, config.cleanUp, clearInternals);
if (newNode) {
fragment.appendChild(newNode);
}
+ if (firstChild !== newNode) {
+ element.removeChild(firstChild);
+ }
}
// Clear element contents
element.innerHTML = "";
@@ -5843,35 +5850,42 @@
element.appendChild(fragment);
return isString ? wysihtml5.quirks.getCorrectInnerHTML(element) : element;
}
- function _convert(oldNode, cleanUp) {
+ function _convert(oldNode, cleanUp, clearInternals) {
var oldNodeType = oldNode.nodeType,
oldChilds = oldNode.childNodes,
oldChildsLength = oldChilds.length,
method = NODE_TYPE_MAPPING[oldNodeType],
i = 0,
fragment,
newNode,
newChild;
+ // Passes directly elemets with uneditable class
if (uneditableClass && oldNodeType === 1 && wysihtml5.dom.hasClass(oldNode, uneditableClass)) {
return oldNode;
}
- newNode = method && method(oldNode);
+ newNode = method && method(oldNode, clearInternals);
+ // Remove or unwrap node in case of return value null or false
if (!newNode) {
if (newNode === false) {
// false defines that tag should be removed but contents should remain (unwrap)
fragment = oldNode.ownerDocument.createDocumentFragment();
for (i = oldChildsLength; i--;) {
- newChild = _convert(oldChilds[i], cleanUp);
- if (newChild) {
- fragment.insertBefore(newChild, fragment.firstChild);
+ if (oldChilds[i]) {
+ newChild = _convert(oldChilds[i], cleanUp, clearInternals);
+ if (newChild) {
+ if (oldChilds[i] === newChild) {
+ i--;
+ }
+ fragment.insertBefore(newChild, fragment.firstChild);
+ }
}
}
// TODO: try to minimize surplus spaces
if (wysihtml5.lang.array([
@@ -5891,26 +5905,33 @@
if (fragment.normalize) {
fragment.normalize();
}
return fragment;
} else {
- return null;
+ // Remove
+ return null;
}
}
+ // Converts all childnodes
for (i=0; i<oldChildsLength; i++) {
- newChild = _convert(oldChilds[i], cleanUp);
- if (newChild) {
- newNode.appendChild(newChild);
+ if (oldChilds[i]) {
+ newChild = _convert(oldChilds[i], cleanUp, clearInternals);
+ if (newChild) {
+ if (oldChilds[i] === newChild) {
+ i--;
+ }
+ newNode.appendChild(newChild);
+ }
}
}
// Cleanup senseless <span> elements
if (cleanUp &&
newNode.nodeName.toLowerCase() === DEFAULT_NODE_NAME &&
(!newNode.childNodes.length ||
- ((/^\s*$/gi).test(newNode.innerHTML) && oldNode.className !== "_wysihtml5-temp-placeholder" && oldNode.className !== "rangySelectionBoundary") ||
+ ((/^\s*$/gi).test(newNode.innerHTML) && (clearInternals || (oldNode.className !== "_wysihtml5-temp-placeholder" && oldNode.className !== "rangySelectionBoundary"))) ||
!newNode.attributes.length)
) {
fragment = newNode.ownerDocument.createDocumentFragment();
while (newNode.firstChild) {
fragment.appendChild(newNode.firstChild);
@@ -5925,11 +5946,11 @@
newNode.normalize();
}
return newNode;
}
- function _handleElement(oldNode) {
+ function _handleElement(oldNode, clearInternals) {
var rule,
newNode,
tagRules = currentRules.tags,
nodeName = oldNode.nodeName.toLowerCase(),
scopeName = oldNode.scopeName;
@@ -5983,28 +6004,28 @@
// Remove empty unknown elements
return null;
}
newNode = oldNode.ownerDocument.createElement(rule.rename_tag || nodeName);
- _handleAttributes(oldNode, newNode, rule);
+ _handleAttributes(oldNode, newNode, rule, clearInternals);
_handleStyles(oldNode, newNode, rule);
// tests if type condition is met or node should be removed/unwrapped
- if (rule.one_of_type && !_testTypes(oldNode, currentRules, rule.one_of_type)) {
+ if (rule.one_of_type && !_testTypes(oldNode, currentRules, rule.one_of_type, clearInternals)) {
return (rule.remove_action && rule.remove_action == "unwrap") ? false : null;
}
oldNode = null;
if (newNode.normalize) { newNode.normalize(); }
return newNode;
}
- function _testTypes(oldNode, rules, types) {
+ function _testTypes(oldNode, rules, types, clearInternals) {
var definition, type;
// do not interfere with placeholder span or pasting caret position is not maintained
- if (oldNode.nodeName === "SPAN" && (oldNode.className === "_wysihtml5-temp-placeholder" || oldNode.className === "rangySelectionBoundary")) {
+ if (oldNode.nodeName === "SPAN" && !clearInternals && (oldNode.className === "_wysihtml5-temp-placeholder" || oldNode.className === "rangySelectionBoundary")) {
return true;
}
for (type in types) {
if (types.hasOwnProperty(type) && rules.type_definitions && rules.type_definitions[type]) {
@@ -6110,11 +6131,12 @@
}
}
}
}
- function _handleAttributes(oldNode, newNode, rule) {
+ // TODO: refactor. Too long to read
+ function _handleAttributes(oldNode, newNode, rule, clearInternals) {
var attributes = {}, // fresh new set of attributes to set on newNode
setClass = rule.set_class, // classes to set
addClass = rule.add_class, // add classes based on existing attributes
addStyle = rule.add_style, // add styles based on existing attributes
setAttributes = rule.set_attributes, // attributes to set on the current node
@@ -6187,12 +6209,15 @@
if (typeof(allowedClasses) === "string" && allowedClasses === "any" && oldNode.getAttribute("class")) {
attributes["class"] = oldNode.getAttribute("class");
} else {
// make sure that wysihtml5 temp class doesn't get stripped out
- allowedClasses["_wysihtml5-temp-placeholder"] = 1;
- allowedClasses["_rangySelectionBoundary"] = 1;
+ if (!clearInternals) {
+ allowedClasses["_wysihtml5-temp-placeholder"] = 1;
+ allowedClasses["_rangySelectionBoundary"] = 1;
+ allowedClasses["wysiwyg-tmp-selected-cell"] = 1;
+ }
// add old classes last
oldClasses = oldNode.getAttribute("class");
if (oldClasses) {
classes = classes.concat(oldClasses.split(WHITE_SPACE_REG_EXP));
@@ -6208,10 +6233,18 @@
if (newClasses.length) {
attributes["class"] = wysihtml5.lang.array(newClasses).unique().join(" ");
}
}
+ // remove table selection class if present
+ if (attributes["class"] && clearInternals) {
+ attributes["class"] = attributes["class"].replace("wysiwyg-tmp-selected-cell", "");
+ if ((/^\s*$/g).test(attributes["class"])) {
+ delete attributes.class;
+ }
+ }
+
if (styles.length) {
attributes["style"] = wysihtml5.lang.array(styles).unique().join(" ");
}
// set attributes on newNode
@@ -10825,11 +10858,11 @@
state: function(composer, command) {
return wysihtml5.commands.insertList.state(composer, command, "UL");
}
};
-;wysihtml5.commands.insertList = (function() {
+;wysihtml5.commands.insertList = (function(wysihtml5) {
var isNode = function(node, name) {
if (node && node.nodeName) {
if (typeof name === 'string') {
name = [name];
@@ -10983,11 +11016,11 @@
return (list.el && !list.other) ? list.el : false;
}
};
-})();;wysihtml5.commands.italic = {
+})(wysihtml5);;wysihtml5.commands.italic = {
exec: function(composer, command) {
wysihtml5.commands.formatInline.execWithToggle(composer, command, "i");
},
state: function(composer, command) {
@@ -11449,11 +11482,11 @@
});
},
transact: function() {
var previousHtml = this.historyStr[this.position - 1],
- currentHtml = this.composer.getValue();
+ currentHtml = this.composer.getValue(false, false);
if (currentHtml === previousHtml) {
return;
}
@@ -11652,15 +11685,14 @@
clear: function() {
this.element.innerHTML = browser.displaysCaretInEmptyContentEditableCorrectly() ? "" : this.CARET_HACK;
},
- getValue: function(parse) {
+ getValue: function(parse, clearInternals) {
var value = this.isEmpty() ? "" : wysihtml5.quirks.getCorrectInnerHTML(this.element);
-
- if (parse) {
- value = this.parent.parse(value);
+ if (parse !== false) {
+ value = this.parent.parse(value, (clearInternals === false) ? false : true);
}
return value;
},
@@ -11793,11 +11825,11 @@
var that = this;
this.doc = this.sandbox.getDocument();
this.element = (this.config.contentEditableMode) ? this.sandbox.getContentEditable() : this.doc.body;
if (!this.config.noTextarea) {
this.textarea = this.parent.textarea;
- this.element.innerHTML = this.textarea.getValue(true);
+ this.element.innerHTML = this.textarea.getValue(true, false);
} else {
this.cleanUp(); // cleans contenteditable on initiation as it may contain html
}
// Make sure our selection handler is ready
@@ -12372,11 +12404,11 @@
composer.commands.exec("insertHTML", " ");
};
wysihtml5.views.Composer.prototype.observe = function() {
var that = this,
- state = this.getValue(),
+ state = this.getValue(false, false),
container = (this.sandbox.getIframe) ? this.sandbox.getIframe() : this.sandbox.getContentEditable(),
element = this.element,
focusBlurElement = (browser.supportsEventsInIframeCorrectly() || this.sandbox.getContentEditable) ? element : this.sandbox.getWindow(),
pasteEvents = ["drop", "paste"],
interactionEvents = ["drop", "paste", "mouseup", "focus", "keyup"];
@@ -12420,15 +12452,15 @@
dom.observe(focusBlurElement, "focus", function() {
that.parent.fire("focus").fire("focus:composer");
// Delay storing of state until all focus handler are fired
// especially the one which resets the placeholder
- setTimeout(function() { state = that.getValue(); }, 0);
+ setTimeout(function() { state = that.getValue(false, false); }, 0);
});
dom.observe(focusBlurElement, "blur", function() {
- if (state !== that.getValue()) {
+ if (state !== that.getValue(false, false)) {
that.parent.fire("change").fire("change:composer");
}
that.parent.fire("blur").fire("blur:composer");
});
@@ -12601,20 +12633,20 @@
* Sync html from composer to textarea
* Takes care of placeholders
* @param {Boolean} shouldParseHtml Whether the html should be sanitized before inserting it into the textarea
*/
fromComposerToTextarea: function(shouldParseHtml) {
- this.textarea.setValue(wysihtml5.lang.string(this.composer.getValue()).trim(), shouldParseHtml);
+ this.textarea.setValue(wysihtml5.lang.string(this.composer.getValue(false, false)).trim(), shouldParseHtml);
},
/**
* Sync value of textarea to composer
* Takes care of placeholders
* @param {Boolean} shouldParseHtml Whether the html should be sanitized before inserting it into the composer
*/
fromTextareaToComposer: function(shouldParseHtml) {
- var textareaValue = this.textarea.getValue();
+ var textareaValue = this.textarea.getValue(false, false);
if (textareaValue) {
this.composer.setValue(textareaValue, shouldParseHtml);
} else {
this.composer.clear();
this.editor.fire("set_placeholder");
@@ -12691,11 +12723,11 @@
this.element.value = "";
},
getValue: function(parse) {
var value = this.isEmpty() ? "" : this.element.value;
- if (parse) {
+ if (parse !== false) {
value = this.parent.parse(value);
}
return value;
},
@@ -12876,12 +12908,12 @@
clear: function() {
this.currentView.clear();
return this;
},
- getValue: function(parse) {
- return this.currentView.getValue(parse);
+ getValue: function(parse, clearInternals) {
+ return this.currentView.getValue(parse, clearInternals);
},
setValue: function(html, parse) {
this.fire("unset_placeholder");
@@ -12924,16 +12956,17 @@
hasPlaceholderSet: function() {
return this.currentView.hasPlaceholderSet();
},
- parse: function(htmlOrElement) {
- var parseContext = (this.config.contentEditableMode) ? document : this.composer.sandbox.getDocument();
+ parse: function(htmlOrElement, clearInternals) {
+ var parseContext = (this.config.contentEditableMode) ? document : ((this.composer) ? this.composer.sandbox.getDocument() : null);
var returnValue = this.config.parser(htmlOrElement, {
"rules": this.config.parserRules,
"cleanUp": this.config.cleanUp,
"context": parseContext,
- "uneditableClass": this.config.uneditableContainerClassname
+ "uneditableClass": this.config.uneditableContainerClassname,
+ "clearInternals" : clearInternals
});
if (typeof(htmlOrElement) === "object") {
wysihtml5.quirks.redraw(htmlOrElement);
}
return returnValue;