diff --git a/lib/rangy-classapplier.js b/lib/rangy-classapplier.js index 926540ae..11383571 100644 --- a/lib/rangy-classapplier.js +++ b/lib/rangy-classapplier.js @@ -9,8 +9,8 @@ * * Copyright 2014, Tim Down * Licensed under the MIT license. - * Version: 1.3.0-alpha.20140921 - * Build date: 21 September 2014 + * Version: 1.3.0-peitschie.perf-master + * Build date: 2 October 2014 */ (function(factory, root) { if (typeof define == "function" && define.amd) { @@ -48,31 +48,46 @@ return str.replace(/^\s\s*/, "").replace(/\s\s*$/, ""); } - function hasClass(el, className) { - return el.className && new RegExp("(?:^|\\s)" + className + "(?:\\s|$)").test(el.className); - } + var hasClass, addClass, removeClass; + if (api.util.isHostObject(document.createElement("div"), "classList")) { + hasClass = function(el, className) { + return el.classList.contains(className); + }; - function addClass(el, className) { - if (el.className) { - if (!hasClass(el, className)) { - el.className += " " + className; - } - } else { - el.className = className; - } - } + addClass = function(el, className) { + return el.classList.add(className); + }; - var removeClass = (function() { - function replacer(matched, whiteSpaceBefore, whiteSpaceAfter) { - return (whiteSpaceBefore && whiteSpaceAfter) ? " " : ""; - } + removeClass = function(el, className) { + return el.classList.remove(className); + }; + } else { + hasClass = function(el, className) { + return el.className && new RegExp("(?:^|\\s)" + className + "(?:\\s|$)").test(el.className); + }; - return function(el, className) { + addClass = function(el, className) { if (el.className) { - el.className = el.className.replace(new RegExp("(^|\\s)" + className + "(\\s|$)"), replacer); + if (!hasClass(el, className)) { + el.className += " " + className; + } + } else { + el.className = className; } }; - })(); + + removeClass = (function() { + function replacer(matched, whiteSpaceBefore, whiteSpaceAfter) { + return (whiteSpaceBefore && whiteSpaceAfter) ? " " : ""; + } + + return function(el, className) { + if (el.className) { + el.className = el.className.replace(new RegExp("(^|\\s)" + className + "(\\s|$)"), replacer); + } + }; + })(); + } function sortClassName(className) { return className && className.split(/\s+/).sort().join(" "); @@ -217,18 +232,6 @@ return false; } - function elementHasProperties(el, props) { - return each(props, function(p, propValue) { - if (typeof propValue == "object") { - if (!elementHasProperties(el[p], propValue)) { - return false; - } - } else if (el[p] !== propValue) { - return false; - } - }); - } - var getComputedStyleProperty = dom.getComputedStyleProperty; var isEditableElement = (function() { var testEl = document.createElement("div"); @@ -517,7 +520,7 @@ applier.elementAttributes = elementAttributes; applier.elementSortedClassName = applier.elementProperties.hasOwnProperty("className") ? - applier.elementProperties.className : className; + sortClassName(applier.elementProperties.className + " " + className) : className; // Initialize tag names applier.applyToAnyTagName = false; @@ -567,7 +570,7 @@ addClass(el, this.className); el[p] = sortClassName(el[p]); if (createCopy) { - elProps[p] = el[p]; + elProps[p] = propValue; } } @@ -578,9 +581,11 @@ elProps[p] = elPropsStyle = {}; } for (s in props[p]) { - elStyle[s] = propValue[s]; - if (createCopy) { - elPropsStyle[s] = elStyle[s]; + if (props[p].hasOwnProperty(s)) { + elStyle[s] = propValue[s]; + if (createCopy) { + elPropsStyle[s] = elStyle[s]; + } } } this.attrExceptions.push(p); @@ -704,13 +709,28 @@ return el; }, + elementHasProperties: function(el, props) { + var applier = this; + return each(props, function(p, propValue) { + if (p == "className") { + return hasClass(el, propValue); + } else if (typeof propValue == "object") { + if (!applier.elementHasProperties(el[p], propValue)) { + return false; + } + } else if (el[p] !== propValue) { + return false; + } + }); + }, + applyToTextNode: function(textNode, positionsToPreserve) { var parent = textNode.parentNode; if (parent.childNodes.length == 1 && this.useExistingElements && isHtmlNamespace(parent) && contains(this.tagNames, parent.tagName.toLowerCase()) && - elementHasProperties(parent, this.elementProperties)) { + this.elementHasProperties(parent, this.elementProperties)) { addClass(parent, this.className); } else { @@ -724,7 +744,7 @@ return isHtmlNamespace(el) && el.tagName.toLowerCase() == this.elementTagName && getSortedClassName(el) == this.elementSortedClassName && - elementHasProperties(el, this.elementProperties) && + this.elementHasProperties(el, this.elementProperties) && !elementHasNonClassAttributes(el, this.attrExceptions) && this.isModifiable(el); }, @@ -767,6 +787,22 @@ ancestorWithClass = splitNodeAt(ancestorWithClass, range.startContainer, range.startOffset, positionsToPreserve); } } + + if (this.isRemovable(ancestorWithClass)) { + replaceWithOwnChildrenPreservingPositions(ancestorWithClass, positionsToPreserve); + } else { + removeClass(ancestorWithClass, this.className); + } + }, + + splitAncestorWithClass: function(container, offset, positionsToPreserve) { + var ancestorWithClass = this.getSelfOrAncestorWithClass(container); + if (ancestorWithClass) { + splitNodeAt(ancestorWithClass, container, offset, positionsToPreserve); + } + }, + + undoToAncestor: function(ancestorWithClass, positionsToPreserve) { if (this.isRemovable(ancestorWithClass)) { replaceWithOwnChildrenPreservingPositions(ancestorWithClass, positionsToPreserve); } else { @@ -841,16 +877,17 @@ var lastTextNode = textNodes[textNodes.length - 1]; if (textNodes.length) { + this.splitAncestorWithClass(range.endContainer, range.endOffset, positionsToPreserve); + this.splitAncestorWithClass(range.startContainer, range.startOffset, positionsToPreserve); for (var i = 0, len = textNodes.length; i < len; ++i) { textNode = textNodes[i]; ancestorWithClass = this.getSelfOrAncestorWithClass(textNode); if (ancestorWithClass && this.isModifiable(textNode)) { - this.undoToTextNode(textNode, range, ancestorWithClass, positionsToPreserve); + this.undoToAncestor(ancestorWithClass, positionsToPreserve); } - - // Ensure the range is still valid - range.setStartAndEnd(textNodes[0], 0, lastTextNode, lastTextNode.length); } + // Ensure the range is still valid + range.setStartAndEnd(textNodes[0], 0, lastTextNode, lastTextNode.length); if (this.normalize) { diff --git a/lib/rangy-core.js b/lib/rangy-core.js index 6468a05d..bb1b2fb7 100644 --- a/lib/rangy-core.js +++ b/lib/rangy-core.js @@ -4,8 +4,8 @@ * * Copyright 2014, Tim Down * Licensed under the MIT license. - * Version: 1.3.0-alpha.20140921 - * Build date: 21 September 2014 + * Version: 1.3.0-peitschie.perf-master + * Build date: 2 October 2014 */ (function(factory, root) { @@ -98,7 +98,7 @@ }; var api = { - version: "1.3.0-alpha.20140921", + version: "1.3.0-peitschie.perf-master", initialized: false, isBrowser: isBrowser, supported: true, diff --git a/lib/rangy-highlighter.js b/lib/rangy-highlighter.js index c54aa869..34e62815 100644 --- a/lib/rangy-highlighter.js +++ b/lib/rangy-highlighter.js @@ -6,8 +6,8 @@ * * Copyright 2014, Tim Down * Licensed under the MIT license. - * Version: 1.3.0-alpha.20140921 - * Build date: 21 September 2014 + * Version: 1.3.0-peitschie.perf-master + * Build date: 2 October 2014 */ (function(factory, root) { if (typeof define == "function" && define.amd) { diff --git a/lib/rangy-selectionsaverestore.js b/lib/rangy-selectionsaverestore.js index 4909eef5..d35e0567 100644 --- a/lib/rangy-selectionsaverestore.js +++ b/lib/rangy-selectionsaverestore.js @@ -9,8 +9,8 @@ * * Copyright 2014, Tim Down * Licensed under the MIT license. - * Version: 1.3.0-alpha.20140921 - * Build date: 21 September 2014 + * Version: 1.3.0-peitschie.perf-master + * Build date: 2 October 2014 */ (function(factory, root) { if (typeof define == "function" && define.amd) { diff --git a/lib/rangy-serializer.js b/lib/rangy-serializer.js index 0686eba1..1bc90445 100644 --- a/lib/rangy-serializer.js +++ b/lib/rangy-serializer.js @@ -10,8 +10,8 @@ * * Copyright 2014, Tim Down * Licensed under the MIT license. - * Version: 1.3.0-alpha.20140921 - * Build date: 21 September 2014 + * Version: 1.3.0-peitschie.perf-master + * Build date: 2 October 2014 */ (function(factory, root) { if (typeof define == "function" && define.amd) { diff --git a/lib/rangy-textrange.js b/lib/rangy-textrange.js index 58d7528b..eb6ad739 100644 --- a/lib/rangy-textrange.js +++ b/lib/rangy-textrange.js @@ -26,8 +26,8 @@ * * Copyright 2014, Tim Down * Licensed under the MIT license. - * Version: 1.3.0-alpha.20140921 - * Build date: 21 September 2014 + * Version: 1.3.0-peitschie.perf-master + * Build date: 2 October 2014 */ /**