0

I try to get height of the parent div of children elements.enter image description here

I have a Parent div with class="Parent" this have also n children element like <div data-elementid="el_ryz-E9a349" class="row">

Parent have a fix height: 220px and I need to know if children element (n) <div data-elementid="el_ryz-E9a349" class="row"> appear in parrent height if not execute scrollIntoView() to this children.

Important I can't delete this both elements, empty div and <div class="container" because affects my design.

...
const scrollToBottom = () => {
    const elementNode = document.querySelector(`[data-elementid='${action.payload.id}']`);
    const parentElementNode = elementNode.parentNode;
    const elementsHeight = parentElementNode.offsetHeight;
    const menuContainer = parentElementNode.parentNode.offsetHeight;

    if (elementsHeight > menuContainer) {
      elementNode.scrollIntoView({
        behavior: 'smooth',
        block: 'end',
      });
    }

 };
setTimeout(scrollToBottom, 200);
...

It's obvious if I've n children elements it's redundant to make elementNode.parentNode.parentNode.parentNode to access Parent node to get height property.

Ian
  • 7,480
  • 2
  • 47
  • 51
Alex Raţiu
  • 107
  • 1
  • 12

2 Answers2

3

Use this function to go up in your element parents and search for you parent classname:

const getParent = (element, cls) => {
    if (element && element.parentElement) {
        const parentClassName = element.parentElement.className;
        if (element.parentElement && parentClassName && parentClassName.match(new RegExp(cls, 'g'))) {
            return element.parentElement; // Found it
        }
        getParent(element.parentElement, cls);
    } else {
        return false; // No parent with such a className
    }
}

const scrollToBottom = () => {
    const elementNode = document.querySelector(`[data-elementid='${action.payload.id}']`);
    const parentElementNode = getParent(elementNode, 'parent'); // second arg is the parent classname you looking for.

    if (parentElementNode) {
        const elementsHeight = parentElementNode.offsetHeight;
        const menuContainer = parentElementNode.parentNode.offsetHeight;

        if (elementsHeight > menuContainer) {
            elementNode.scrollIntoView({
                behavior: 'smooth',
                block: 'end',
            });
        }
    }

    console.log('no parent found!')

};

setTimeout(scrollToBottom, 200);

Select with data-atttribute:

const getParentWithAttr = (element, attr) => {
    if (element && element.parentElement) {
        const parentElement = element.parentElement;
        if (parentElement && parentElement.getAttribute('data-attr') === attr) {
            return parentElement; // Found it
        }
        getParent(parentElement, attr);
    } else {
        return false; // No parent with such a className
    }
}

Use case should be like this:

<div id="..." class="..." data-attr="parent">// parrent
    ... // chilren
</div>


getParentWithAttr(document.querySelector('.element'), 'parent');
Spleen
  • 2,656
  • 1
  • 10
  • 16
  • Thanks for fast answer, I can't work with `classnames`, in development mode it works 100% but in production classNames are hashed. That's why I work with data-attributes and querySelector to get that node. I need to use this function in two place in my page and the children of parent is not in same order. – Alex Raţiu Oct 05 '18 at 17:40
  • 1
    Ok then, just replace the className with dataAttr and define that function in the global and just import it where you wanna use it. You'll be fine. – Spleen Oct 05 '18 at 18:26
  • 1
    I added an example with `data-attr` at the end of my answer. hope that will help you. – Spleen Oct 05 '18 at 18:35
0

Since the question's tag says React.js, I would instead refer to ReactJS how to scroll to an element. This uses React refs and makes your code much simpler. That being said, it looks like the question is actually using pure JavaScript on static HTML.

import React, { Component } from 'react';
import ReactDOM from 'react-dom';

class SampleComponent extends Component {
  scrollToDomRef = () => {
    const myDomNode = ReactDOM.findDOMNode(this.myRef.current)
    myDomNode.scrollIntoView()
  };

  render() {
    return <> // '<></>' is a React 16.3.0+ feature, use <div> if previous
      <button onClick={this.scrollToDomRef}>Click me</div>
      <div ref={ re => { this.myRef = re } }></div>
    </>
  }
}
Ross Sheppard
  • 850
  • 1
  • 6
  • 14