0

I want to add some own methods via Object.prototype to work easier with my DOM objects.

I found this on SO:

:

So I tried some code like this...

js code (not working):

Object.defineProperty(Object.prototype, 'getSiblings', {
    value: (filteredByClassName) => {
        let siblings = [];
        let sibling = this.closest(filteredByClassName).firstChild;
        while (sibling) {
            if (sibling.nodeType === 1 && sibling !== this && ((filteredByClassName)?(sibling.classList.contains(filteredByClassName)):true)) {
                siblings.push(sibling);
            }
            sibling = sibling.nextSibling
        }
        return siblings;
    },
    writable: true,
    configurable: true
});

let activeCultureName = document.querySelector('.page .cultures.active p.name'); //important: source is not the ".culture" div element itself, it's a children (e.g. <p class="name">) of
let inactiveCultureSiblings = activeCulture.getSiblings('.culture'); //get all ".culture" div elements, instead of the active.

:

Problem (this is undefined):

I can't access to the given object (via this), it's undefined. So I can't use the closest() method.

:

html code (for example):

<div class="page">
    <div class="culture">
        <p class="name"> de-DE </p>
    </div>
    <div class="culture">
        <p class="name"> en-GB </p>
    </div>
    <div class="culture active">
        <p class="name"> en-US </p>
    </div>
    <div class="culture">
        <p class="name"> pl-PL </p>
    </div>
</div>

:

What I'm looking for:

I simply want to ask: let mySiblings = domObject.getSiblings(); or with a filter-query-param like: let mySiblings = domObject.getSiblings('.classname');. So what I'm looking for is a way to add own methods/functions via prototype to my dom objects.> I need some simple helper methods (like filter, siblings, toggle ...) for my dom objects. The best way will be a

:

About me:

I'm a C#.NET Core developer, so usually I'm using extension methods (like string extensions or what ever). In JS I've a little bit problems with that mixed types.

Froschkoenig84
  • 470
  • 3
  • 12

2 Answers2

1

Define your function with a regular function instead of an arrow function.

Object.defineProperty(Object.prototype, 'getSiblings', {
  value(filteredByClassName) {
    let siblings = [];

    // Now `this` will work
    let sibling = this.closest(filteredByClassName).firstChild;
    while (sibling) {
      if (sibling.nodeType === 1 && sibling !== this && ((filteredByClassName)?(sibling.classList.contains(filteredByClassName)):true)) {
        siblings.push(sibling);
      }
      sibling = sibling.nextSibling
    }
    return siblings;
  },
  writable: true,
  configurable: true
});

Otherwise, this is bound to the lexical scope no matter what you do.

Jacob
  • 72,750
  • 22
  • 137
  • 214
0

Thanks to Jakob for giving the advice to relinquish the arrow function and set the "value" proberty as a function.

I also fixed the sibling finder method by className. It's only an example.
I think it may be more convenient to use a query statement (string) instead of a className (string) as filter parameter (method parameter).

So here's the full working code...

:

js code:

Object.defineProperty(Object.prototype, 'getSiblings', {
    value(filteredByClassName) {
        let closest = this.closest('.'+filteredByClassName);
        let siblings = [];
        let sibling = closest.parentElement.firstChild;
        while (sibling) {
            if (sibling.nodeType === 1 && sibling !== this && ((filteredByClassName)?(sibling.classList && closest.classList!==sibling.classList && sibling.classList.contains(filteredByClassName)):true)) { //} && ((filteredByClassName)?(sibling.classList.contains(filteredByClassName)):true)) {
                siblings.push(sibling);
            }
            sibling = sibling.nextSibling
        }
        alert('siblings.length: '+siblings.length);
        return siblings;
    },
    writable: true,
    configurable: true
});

let activeCultureName = document.querySelector('.page .cultures.active p.name');
let inactiveCultureSiblings = activeCulture.getSiblings('.culture');

:

html code (for example):

<div class="page">
    <div class="culture">
        <p class="name"> de-DE </p>
    </div>
    <div class="culture">
        <p class="name"> en-GB </p>
    </div>
    <div class="culture active">
        <p class="name"> en-US </p>
    </div>
    <div class="culture">
        <p class="name"> pl-PL </p>
    </div>
</div>
Froschkoenig84
  • 470
  • 3
  • 12