Skip to content

Commit

Permalink
Update version
Browse files Browse the repository at this point in the history
  • Loading branch information
Tim committed Jan 22, 2015
1 parent b084158 commit 01b312b
Show file tree
Hide file tree
Showing 12 changed files with 160 additions and 120 deletions.
162 changes: 101 additions & 61 deletions rangy-classapplier.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
*
* Depends on Rangy core.
*
* Copyright 2014, Tim Down
* Copyright 2015, Tim Down
* Licensed under the MIT license.
* Version: 1.3.0-alpha.20140921
* Build date: 21 September 2014
* Version: 1.3.0-alpha.20150122
* Build date: 22 January 2015
*/
(function(factory, root) {
if (typeof define == "function" && define.amd) {
Expand Down Expand Up @@ -43,36 +43,51 @@
}
return true;
}

function trim(str) {
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(" ");
Expand Down Expand Up @@ -106,7 +121,7 @@
position.node = newNode;
position.offset = newOffset;
}

function movePositionWhenRemovingNode(position, parentNode, index) {
if (position.node == parentNode && position.offset > index) {
--position.offset;
Expand All @@ -133,7 +148,7 @@
newParent.insertBefore(node, newParent.childNodes[newIndex]);
}
}

function removePreservingPositions(node, positionsToPreserve) {

var oldParent = node.parentNode;
Expand Down Expand Up @@ -174,9 +189,9 @@

function getEffectiveTextNodes(range) {
var nodes = range.getNodes([3]);

// Optimization as per issue 145

// Remove non-intersecting text nodes from the start of the range
var start = 0, node;
while ( (node = nodes[start]) && !rangeSelectsAnyText(range, node) ) {
Expand All @@ -188,7 +203,7 @@
while ( (node = nodes[end]) && !rangeSelectsAnyText(range, node) ) {
--end;
}

return nodes.slice(start, end + 1);
}

Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -490,6 +493,9 @@

// Initialize from options object
if (typeof options == "object" && options !== null) {
if (typeof options.elementTagName !== "undefined") {
options.elementTagName = options.elementTagName.toLowerCase();
}
tagNames = options.tagNames;
elementPropertiesFromOptions = options.elementProperties;
elementAttributes = options.elementAttributes;
Expand Down Expand Up @@ -517,7 +523,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;
Expand Down Expand Up @@ -567,7 +573,7 @@
addClass(el, this.className);
el[p] = sortClassName(el[p]);
if (createCopy) {
elProps[p] = el[p];
elProps[p] = propValue;
}
}

Expand All @@ -578,9 +584,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);
Expand All @@ -603,7 +611,7 @@

return createCopy ? elProps : "";
},

copyAttributesToElement: function(attrs, el) {
for (var attrName in attrs) {
if (attrs.hasOwnProperty(attrName)) {
Expand All @@ -614,7 +622,7 @@

hasClass: function(node) {
return node.nodeType == 1 &&
contains(this.tagNames, node.tagName.toLowerCase()) &&
(this.applyToAnyTagName || contains(this.tagNames, node.tagName.toLowerCase())) &&
hasClass(node, this.className);
},

Expand Down Expand Up @@ -704,13 +712,28 @@
return el;
},

elementHasProperties: function(el, props) {
var applier = this;
return each(props, function(p, propValue) {
if (p == "className") {
return sortClassName(el.className) == applier.elementSortedClassName;
} 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 {
Expand All @@ -724,7 +747,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);
},
Expand All @@ -735,16 +758,16 @@
this.isRemovable(el) &&
(childNodeCount == 0 || (childNodeCount == 1 && this.isEmptyContainer(el.firstChild)));
},

removeEmptyContainers: function(range) {
var applier = this;
var nodesToRemove = range.getNodes([1], function(el) {
return applier.isEmptyContainer(el);
});

var rangesToPreserve = [range];
var positionsToPreserve = getRangeBoundaries(rangesToPreserve);

for (var i = 0, node; node = nodesToRemove[i++]; ) {
removePreservingPositions(node, positionsToPreserve);
}
Expand All @@ -767,6 +790,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 {
Expand All @@ -779,10 +818,10 @@

// Create an array of range boundaries to preserve
var positionsToPreserve = getRangeBoundaries(rangesToPreserve || []);

range.splitBoundariesPreservingPositions(positionsToPreserve);

// Tidy up the DOM by removing empty containers
// Tidy up the DOM by removing empty containers
if (this.removeEmptyElements) {
this.removeEmptyContainers(range);
}
Expand Down Expand Up @@ -831,7 +870,7 @@

range.splitBoundariesPreservingPositions(positionsToPreserve);

// Tidy up the DOM by removing empty containers
// Tidy up the DOM by removing empty containers
if (this.removeEmptyElements) {
this.removeEmptyContainers(range, positionsToPreserve);
}
Expand All @@ -841,16 +880,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) {
Expand Down Expand Up @@ -952,7 +992,7 @@
this.applyToSelection(win);
}
},

getElementsWithClassIntersectingRange: function(range) {
var elements = [];
var applier = this;
Expand Down Expand Up @@ -1007,4 +1047,4 @@
api.createCssClassApplier = api.createClassApplier = createClassApplier;
});

}, this);
}, this);
Loading

0 comments on commit 01b312b

Please sign in to comment.