|
9 | 9 | * |
10 | 10 | * Copyright 2014, Tim Down |
11 | 11 | * Licensed under the MIT license. |
12 | | - * Version: 1.3.0-alpha.20140921 |
13 | | - * Build date: 21 September 2014 |
| 12 | + * Version: 1.3.0-peitschie.perf-master |
| 13 | + * Build date: 2 October 2014 |
14 | 14 | */ |
15 | 15 | (function(factory, root) { |
16 | 16 | if (typeof define == "function" && define.amd) { |
|
48 | 48 | return str.replace(/^\s\s*/, "").replace(/\s\s*$/, ""); |
49 | 49 | } |
50 | 50 |
|
51 | | - function hasClass(el, className) { |
52 | | - return el.className && new RegExp("(?:^|\\s)" + className + "(?:\\s|$)").test(el.className); |
53 | | - } |
| 51 | + var hasClass, addClass, removeClass; |
| 52 | + if (api.util.isHostObject(document.createElement("div"), "classList")) { |
| 53 | + hasClass = function(el, className) { |
| 54 | + return el.classList.contains(className); |
| 55 | + }; |
54 | 56 |
|
55 | | - function addClass(el, className) { |
56 | | - if (el.className) { |
57 | | - if (!hasClass(el, className)) { |
58 | | - el.className += " " + className; |
59 | | - } |
60 | | - } else { |
61 | | - el.className = className; |
62 | | - } |
63 | | - } |
| 57 | + addClass = function(el, className) { |
| 58 | + return el.classList.add(className); |
| 59 | + }; |
64 | 60 |
|
65 | | - var removeClass = (function() { |
66 | | - function replacer(matched, whiteSpaceBefore, whiteSpaceAfter) { |
67 | | - return (whiteSpaceBefore && whiteSpaceAfter) ? " " : ""; |
68 | | - } |
| 61 | + removeClass = function(el, className) { |
| 62 | + return el.classList.remove(className); |
| 63 | + }; |
| 64 | + } else { |
| 65 | + hasClass = function(el, className) { |
| 66 | + return el.className && new RegExp("(?:^|\\s)" + className + "(?:\\s|$)").test(el.className); |
| 67 | + }; |
69 | 68 |
|
70 | | - return function(el, className) { |
| 69 | + addClass = function(el, className) { |
71 | 70 | if (el.className) { |
72 | | - el.className = el.className.replace(new RegExp("(^|\\s)" + className + "(\\s|$)"), replacer); |
| 71 | + if (!hasClass(el, className)) { |
| 72 | + el.className += " " + className; |
| 73 | + } |
| 74 | + } else { |
| 75 | + el.className = className; |
73 | 76 | } |
74 | 77 | }; |
75 | | - })(); |
| 78 | + |
| 79 | + removeClass = (function() { |
| 80 | + function replacer(matched, whiteSpaceBefore, whiteSpaceAfter) { |
| 81 | + return (whiteSpaceBefore && whiteSpaceAfter) ? " " : ""; |
| 82 | + } |
| 83 | + |
| 84 | + return function(el, className) { |
| 85 | + if (el.className) { |
| 86 | + el.className = el.className.replace(new RegExp("(^|\\s)" + className + "(\\s|$)"), replacer); |
| 87 | + } |
| 88 | + }; |
| 89 | + })(); |
| 90 | + } |
76 | 91 |
|
77 | 92 | function sortClassName(className) { |
78 | 93 | return className && className.split(/\s+/).sort().join(" "); |
|
217 | 232 | return false; |
218 | 233 | } |
219 | 234 |
|
220 | | - function elementHasProperties(el, props) { |
221 | | - return each(props, function(p, propValue) { |
222 | | - if (typeof propValue == "object") { |
223 | | - if (!elementHasProperties(el[p], propValue)) { |
224 | | - return false; |
225 | | - } |
226 | | - } else if (el[p] !== propValue) { |
227 | | - return false; |
228 | | - } |
229 | | - }); |
230 | | - } |
231 | | - |
232 | 235 | var getComputedStyleProperty = dom.getComputedStyleProperty; |
233 | 236 | var isEditableElement = (function() { |
234 | 237 | var testEl = document.createElement("div"); |
|
517 | 520 | applier.elementAttributes = elementAttributes; |
518 | 521 |
|
519 | 522 | applier.elementSortedClassName = applier.elementProperties.hasOwnProperty("className") ? |
520 | | - applier.elementProperties.className : className; |
| 523 | + sortClassName(applier.elementProperties.className + " " + className) : className; |
521 | 524 |
|
522 | 525 | // Initialize tag names |
523 | 526 | applier.applyToAnyTagName = false; |
|
567 | 570 | addClass(el, this.className); |
568 | 571 | el[p] = sortClassName(el[p]); |
569 | 572 | if (createCopy) { |
570 | | - elProps[p] = el[p]; |
| 573 | + elProps[p] = propValue; |
571 | 574 | } |
572 | 575 | } |
573 | 576 |
|
|
578 | 581 | elProps[p] = elPropsStyle = {}; |
579 | 582 | } |
580 | 583 | for (s in props[p]) { |
581 | | - elStyle[s] = propValue[s]; |
582 | | - if (createCopy) { |
583 | | - elPropsStyle[s] = elStyle[s]; |
| 584 | + if (props[p].hasOwnProperty(s)) { |
| 585 | + elStyle[s] = propValue[s]; |
| 586 | + if (createCopy) { |
| 587 | + elPropsStyle[s] = elStyle[s]; |
| 588 | + } |
584 | 589 | } |
585 | 590 | } |
586 | 591 | this.attrExceptions.push(p); |
|
704 | 709 | return el; |
705 | 710 | }, |
706 | 711 |
|
| 712 | + elementHasProperties: function(el, props) { |
| 713 | + var applier = this; |
| 714 | + return each(props, function(p, propValue) { |
| 715 | + if (p == "className") { |
| 716 | + return hasClass(el, propValue); |
| 717 | + } else if (typeof propValue == "object") { |
| 718 | + if (!applier.elementHasProperties(el[p], propValue)) { |
| 719 | + return false; |
| 720 | + } |
| 721 | + } else if (el[p] !== propValue) { |
| 722 | + return false; |
| 723 | + } |
| 724 | + }); |
| 725 | + }, |
| 726 | + |
707 | 727 | applyToTextNode: function(textNode, positionsToPreserve) { |
708 | 728 | var parent = textNode.parentNode; |
709 | 729 | if (parent.childNodes.length == 1 && |
710 | 730 | this.useExistingElements && |
711 | 731 | isHtmlNamespace(parent) && |
712 | 732 | contains(this.tagNames, parent.tagName.toLowerCase()) && |
713 | | - elementHasProperties(parent, this.elementProperties)) { |
| 733 | + this.elementHasProperties(parent, this.elementProperties)) { |
714 | 734 |
|
715 | 735 | addClass(parent, this.className); |
716 | 736 | } else { |
|
724 | 744 | return isHtmlNamespace(el) && |
725 | 745 | el.tagName.toLowerCase() == this.elementTagName && |
726 | 746 | getSortedClassName(el) == this.elementSortedClassName && |
727 | | - elementHasProperties(el, this.elementProperties) && |
| 747 | + this.elementHasProperties(el, this.elementProperties) && |
728 | 748 | !elementHasNonClassAttributes(el, this.attrExceptions) && |
729 | 749 | this.isModifiable(el); |
730 | 750 | }, |
|
767 | 787 | ancestorWithClass = splitNodeAt(ancestorWithClass, range.startContainer, range.startOffset, positionsToPreserve); |
768 | 788 | } |
769 | 789 | } |
| 790 | + |
| 791 | + if (this.isRemovable(ancestorWithClass)) { |
| 792 | + replaceWithOwnChildrenPreservingPositions(ancestorWithClass, positionsToPreserve); |
| 793 | + } else { |
| 794 | + removeClass(ancestorWithClass, this.className); |
| 795 | + } |
| 796 | + }, |
| 797 | + |
| 798 | + splitAncestorWithClass: function(container, offset, positionsToPreserve) { |
| 799 | + var ancestorWithClass = this.getSelfOrAncestorWithClass(container); |
| 800 | + if (ancestorWithClass) { |
| 801 | + splitNodeAt(ancestorWithClass, container, offset, positionsToPreserve); |
| 802 | + } |
| 803 | + }, |
| 804 | + |
| 805 | + undoToAncestor: function(ancestorWithClass, positionsToPreserve) { |
770 | 806 | if (this.isRemovable(ancestorWithClass)) { |
771 | 807 | replaceWithOwnChildrenPreservingPositions(ancestorWithClass, positionsToPreserve); |
772 | 808 | } else { |
|
841 | 877 | var lastTextNode = textNodes[textNodes.length - 1]; |
842 | 878 |
|
843 | 879 | if (textNodes.length) { |
| 880 | + this.splitAncestorWithClass(range.endContainer, range.endOffset, positionsToPreserve); |
| 881 | + this.splitAncestorWithClass(range.startContainer, range.startOffset, positionsToPreserve); |
844 | 882 | for (var i = 0, len = textNodes.length; i < len; ++i) { |
845 | 883 | textNode = textNodes[i]; |
846 | 884 | ancestorWithClass = this.getSelfOrAncestorWithClass(textNode); |
847 | 885 | if (ancestorWithClass && this.isModifiable(textNode)) { |
848 | | - this.undoToTextNode(textNode, range, ancestorWithClass, positionsToPreserve); |
| 886 | + this.undoToAncestor(ancestorWithClass, positionsToPreserve); |
849 | 887 | } |
850 | | - |
851 | | - // Ensure the range is still valid |
852 | | - range.setStartAndEnd(textNodes[0], 0, lastTextNode, lastTextNode.length); |
853 | 888 | } |
| 889 | + // Ensure the range is still valid |
| 890 | + range.setStartAndEnd(textNodes[0], 0, lastTextNode, lastTextNode.length); |
854 | 891 |
|
855 | 892 |
|
856 | 893 | if (this.normalize) { |
|
0 commit comments