22

I need a function to trigger if the element recordplayerstick contains either the pinplace or pinsongplay class. The code I currently have returns a syntax error. What is the correct way to do this?

if (document.getElementById('recordplayerstick').classList.contains('pinplace pinsongplay')) {
    removepin();
}
user9951515
  • 265
  • 1
  • 2
  • 9
  • 2
    Also you can only check for one class at a time. – Pointy Jan 14 '19 at 23:40
  • @Pointy any suggestions for how to go about multiple classes? `if (document.getElementById('recordplayerstick').classList.contains('pinplace') || document.getElementById('recordplayerstick').classList.contains('pinsongplay'))` ? – user9951515 Jan 14 '19 at 23:41
  • Just check for it containing one or the other (two calls to `.contains()`). – Pointy Jan 14 '19 at 23:42
  • `const cl = document.getElementById('recordplayerstick').classList; if (cl.contains('pinplace') || cl.contains('pinsongplay')) ...` –  Jan 14 '19 at 23:46
  • 2
    `document.getElementById('recordplayerstick').matches(".pinplace,.pinsongplay")` – Keith Jan 14 '19 at 23:48
  • 1
    OP said OR and bunch of the comments are AND – epascarello Jan 14 '19 at 23:49
  • `querySelector('#recordplayerstick.pinplace, #recordplayerstick.pinsongplay')` would also only return the element if it had the id selector and at least one of the classes. Fixed as per epascarello's note – Taplar Jan 14 '19 at 23:51

5 Answers5

33

Since Element.classList.contains accepts only a single class name, you need to check each separately.

You could use Array.prototype.some() to avoid writing a bunch of or conditions

const el = document.getElementById('recordplayerstick')
const classNames = ['pinplace', 'pinsongplay']
if (classNames.some(className => el.classList.contains(className))) {
  removeping()
}
Phil
  • 157,677
  • 23
  • 242
  • 245
18

You are going to have to do two checks if you are going to use classList.

function removepin() {
  console.log("yep");
}
var cList = document.getElementById('recordplayerstick').classList;
if (
  cList.contains('pinplace') ||
  cList.contains('pinsongplay')) {
  removepin();
}
<div id="recordplayerstick" class="pinplace pinsongplay"></div>
epascarello
  • 204,599
  • 20
  • 195
  • 236
5

Use ... (Spread syntax)

Example

const element = document.getElementById("left-sidebar");
const has_some = ["left-sidebar", "js-pinned-left-sidebar"];
const result = [...element.classList].some(className => has_some.indexOf(className) !== -1);  
// has_some.some(className => [...element.classList].indexOf(className) !== -1);
// or example like @Phil
// has_some.some(className => element.classList.contains(className))

complete functions

/**
 * @description determine if an array contains one or more items from another array.
 * @param {array} haystack the array to search.
 * @param {array} arr the array providing items to check for in the haystack.
 * @return {boolean} true|false if haystack contains at least one item from arr.
 */
var findOne = function (haystack, arr) {
    return arr.some(function (v) {
        return haystack.indexOf(v) !== -1;
    });
};

/**
 * @description determine if element has one or more className.
 * @param {HTMLElement} element element where is going to search classNames.
 * @param {array} arrayClassNames Array of Strings, provide to search ClassName in the element
 * @return {boolean} true|false if element.classList contains at least one item from arrayClassNames.
 */
var checkElementHasSomeClassName = function (element, arrayClassNames) {
    // uncoment and use this return if you don't want the findOne function
    // return [...element.classList].some(className => arrayClassNames.indexOf(className) !== -1);
    return findOne([...element.classList], arrayClassNames);
};

Links extras:

Spread syntax - browser compatibility

Check if exist one item from array in another array

DarckBlezzer
  • 4,578
  • 1
  • 41
  • 51
  • 3
    this doesn't work it seems, it only searches for first element in array. Make the classlist an array instead e.g. `[...element.classlist].includes('a','b', etc)`? – Andy B Nov 20 '19 at 16:18
0

It is convenient to have a set of functions for different types.

$.fn.has1Class = function (arrayClasses)
{
    return this.length > 0 ? this[0].has1Class(arrayClasses) : false; 
}

HTMLElement.prototype.has1Class = function (arrayClasses)
{
    if (!this.classList)
        return false;
    if (!Array.isArray(arrayClasses)) {
        throw new Error("The classArray parameter must be an array");
    }
    return [...this.classList].some(cl => arrayClasses.contains(cl));
};

Array.prototype.contains = function (v) {
    for (let i = 0; i < this.length; i++) {
        if (this[i] === v) return true;
    }
    return false;
};

console.log( $('#myInput').has1Class(['c']));
console.log( $('#myInput').has1Class(['a','a','a2']));

let domElem = document.getElementById('myInput');
if(domElem)
    console.log( domElem.has1Class(['a','b','a1']));

https://jsfiddle.net/NickU/7afw5oec/95/

-1

As already stated in previous answers .classList.contains() can only pass one parameter. The following example features a function that will iterate through a given list of classNames° and returns true should any or all¹ of the classNames are assigned to the targeted DOM node².

° 3rd parameter ...classes
¹ 2nd parameter all
² 1st parameter DOMNode

Usage

findClasses(DOMNode, all, ...classes)
DOMNode.....: The reference to a single DOM element
              ex. const node = document.querySelector('.target'); 
all.........: Boolean to determine whether all classes listed in the 
              third parameter need to be present (true) or just one of
              them (false)
...classes..: ClassNames as a comma delimited list of strings
              ex. "bullseye", "miss"

Example

const node = document.querySelector('#recordplayerstick');

const findClasses = (node, all, ...classes) => {
  return all ?
    classes.every(cls => node.classList.contains(cls)) :
    classes.some(cls => node.classList.contains(cls));
};

// console.log(findClasses(node, false, 'pinplace', 'pinsongplay'));
// returns true

// console.log(findClasses(node, true, 'pinplace', 'pinsongplay'));
// returns false

const removePin = () => alert(`PIN REMOVED!`);

if (findClasses(node, false, 'pinplace', 'pinsongplay')) removePin();
<div id='recordplayerstick' class='pinplace'></div>
zer00ne
  • 41,936
  • 6
  • 41
  • 68