Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

fix(jqLite) - toggleClass & removeClass reflect documentation #12852

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 48 additions & 16 deletions src/jqLite.js
Original file line number Diff line number Diff line change
Expand Up @@ -381,15 +381,26 @@ function jqLiteHasClass(element, selector) {
indexOf(" " + selector + " ") > -1);
}

function jqLiteRemoveClass(element, cssClasses) {
if (cssClasses && element.setAttribute) {
forEach(cssClasses.split(' '), function(cssClass) {
element.setAttribute('class', trim(
(" " + (element.getAttribute('class') || '') + " ")
.replace(/[\n\t]/g, " ")
.replace(" " + trim(cssClass) + " ", " "))
);
});
function jqLiteRemoveClass(element, cssClassesOrFunc) {
if (element.setAttribute) {
if (cssClassesOrFunc) {
if (typeof cssClassesOrFunc === 'function') {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can use isFunction

forEach(element.className.split(/\s+/), function(className, index) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is doing the right thing. jquery docs say:

A function returning one or more space-separated class names to be added to the existing class name(s). Receives the index position of the element in the set and the existing class name(s) as arguments. Within the function, this refers to the current element in the set.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Narretz
I will look into this, thank you.

cssClassesOrFunc(index, className);
});
} else {
forEach(cssClassesOrFunc.split(' '), function(cssClass) {
element.setAttribute('class', trim(
(" " + (element.getAttribute('class') || '') + " ")
.replace(/[\n\t]/g, " ")
.replace(" " + trim(cssClass) + " ", " "))
);
});
}
} else {
// if no class names are specified in the parameter, all classes will be removed
element.setAttribute('class', '');
}
}
}

Expand Down Expand Up @@ -935,14 +946,35 @@ forEach({
removeClass: jqLiteRemoveClass,

toggleClass: function(element, selector, condition) {

if (selector) {
forEach(selector.split(' '), function(className) {
var classCondition = condition;
if (isUndefined(classCondition)) {
classCondition = !jqLiteHasClass(element, className);
}
(classCondition ? jqLiteAddClass : jqLiteRemoveClass)(element, className);
});

// the class name to be toggled can be determined by passing in a function.
if (typeof selector === 'function') {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-> isFunction


forEach(element.className.split(/\s+/), function(className, index) {
if (Array.isArray(condition) && condition.length >= index) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-> isArray

selector(index, className, condition[index]);
} else {
selector(index, className);
}
});

// if has the class, then it is removed; if does not have the class, then it is added.
} else {

forEach(selector.split(' '), function(className) {
var classCondition = condition;
if (isUndefined(classCondition)) {
classCondition = !jqLiteHasClass(element, className);
}
(classCondition ? jqLiteAddClass : jqLiteRemoveClass)(element, className);
});
}

// if no arguments are passed all class names on the element will be toggled.
} else {
jqLiteRemoveClass(element);
}
},

Expand Down
85 changes: 85 additions & 0 deletions test/jqLiteSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -839,6 +839,65 @@ describe('jqLite', function() {
expect(jqLite(b).hasClass('cde')).toBe(false);
});

it('should allow function to be passed with conditions', function() {
var selector = jqLite([a, b]);
selector.addClass('abc');
selector.addClass('cde');
selector.addClass('fgh');
selector.addClass('ijk');

expect(selector.toggleClass(function(index, className, state) {
selector.toggleClass(className, state);
}, [true, true, false, false])).toBe(selector);

expect(jqLite(a).hasClass('abc')).toBe(true);
expect(jqLite(a).hasClass('cde')).toBe(true);
expect(jqLite(a).hasClass('fgh')).toBe(false);
expect(jqLite(a).hasClass('ijk')).toBe(false);

expect(jqLite(b).hasClass('abc')).toBe(true);
expect(jqLite(b).hasClass('cde')).toBe(true);
expect(jqLite(b).hasClass('fgh')).toBe(false);
expect(jqLite(b).hasClass('ijk')).toBe(false);
});

it('should allow function to be passed without condition', function() {
var selector = jqLite([a, b]);
selector.addClass('abc');
selector.addClass('cde');
selector.addClass('fgh');
selector.addClass('ijk');

expect(selector.toggleClass(function(index, className) {
if (className === 'abc' || className === 'cde') {
selector.removeClass(className);
}
})).toBe(selector);

expect(jqLite(a).hasClass('abc')).toBe(false);
expect(jqLite(a).hasClass('cde')).toBe(false);
expect(jqLite(a).hasClass('fgh')).toBe(true);
expect(jqLite(a).hasClass('ijk')).toBe(true);

expect(jqLite(b).hasClass('abc')).toBe(false);
expect(jqLite(b).hasClass('cde')).toBe(false);
expect(jqLite(b).hasClass('fgh')).toBe(true);
expect(jqLite(b).hasClass('ijk')).toBe(true);
});

it('should toggle all classes if no selector is passed', function() {
var selector = jqLite([a, b]);
selector.addClass('abc');
selector.addClass('cde');

expect(selector.toggleClass()).toBe(selector);

expect(jqLite(a).hasClass('abc')).toBe(false);
expect(jqLite(a).hasClass('cde')).toBe(false);
expect(jqLite(b).hasClass('abc')).toBe(false);
expect(jqLite(b).hasClass('cde')).toBe(false);
});

it('should not break for null / undefined selectors', function() {
var selector = jqLite([a, b]);
expect(selector.toggleClass(null)).toBe(selector);
Expand Down Expand Up @@ -869,6 +928,32 @@ describe('jqLite', function() {
});


it('should remove all classes if no class is specified', function() {
var element = jqLite('<div class="foo bar baz"></div>');

expect(element.removeClass()).toEqual(element);

expect(element.hasClass('foo')).toBe(false);
expect(element.hasClass('bar')).toBe(false);
expect(element.hasClass('baz')).toBe(false);
});


it('should allow a function as a paramater', function() {
var element = jqLite('<div class="foo bar baz"></div>');

expect(element.removeClass(function(index, className) {
if (className === 'foo' || className === 'bar') {
element.removeClass(className);
}
})).toEqual(element);

expect(element.hasClass('foo')).toBe(false);
expect(element.hasClass('bar')).toBe(false);
expect(element.hasClass('baz')).toBe(true);
});


it('should remove multiple classes specified as one string', function() {
var jqA = jqLite(a);

Expand Down