1

If I have the following markup how can I check if each div inside each child does not have class hidden and if it has a data-access attribute that its value is equal to the value of the class in div with id=main

 <div id="main" class="agent">

   <div class="child">
     <div class="area hidden" >
        <div class="section">
           <div data-type="text" >
                 <input type="text" name="firstname">
             
           </div>
        </div>
      </div>
   </div>
   <div class="child">
     <div class="area" data-access="agent">
        <div class="section">
           <div data-type="text" >
                   <input type="text" name="lastname">
             
           </div>
        </div>
      </div>
   </div>
   <div class="child">
     <div class="area">
        <div class="section">
           <div data-type="text" >
                 <input type="text" name="refnumber">
           </div>
        </div>
      </div>
   </div>
   
   

I can do the following but that only check if the divs don't contain the hidden class.

 $('.child').each(function(index, element) {

       $(element).find('.area:not(.hidden) .section:not(.hidden) div[data-type]:not(.hidden)').each(function(index, ele) {


       }

}

Along with checking if the divs do not contain a hidden class I want to check if each of those divs also contains a data-access attribute and if it does then check if the value is equal to the value of the class in <div id="main" class="agent">

2
  • Can simplify this significantly but not clear what higher level objective is. What do you need to do with results? Commented Nov 28, 2020 at 17:57
  • @charlietfl need to retrieve values of form inputs which sit inside div with data-type attribute if the div was displayed. If it was hidden then it can be ignored. visibilty of the containers can be toggled at three levels i.e. the three divs so need to check if any of them were hidden. Commented Nov 28, 2020 at 18:06

4 Answers 4

1

You could first check if any child element has a class hidden with .not and :has and then also if any child element has data attribute data-access equal to class of element with id main.

$('#main .child')
  .not(':has(.hidden)')
  .has(`[data-access="${$('#main').attr('class')}"]`)
  .css('color', 'red')
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="main" class="agent">
  <div class="child">
    <div class="area hidden">
      <div class="section">
        <div data-type="text">1 </div>
      </div>
    </div>
  </div>
  <div class="child">
    <div class="area" data-access="agent">
      <div class="section">
        <div data-type="text">2</div>
      </div>
    </div>
  </div>
  <div class="child">
    <div class="area">
      <div class="section">
        <div data-type="text">3 </div>
      </div>
    </div>
  </div>
</div>

Sign up to request clarification or add additional context in comments.

Comments

1

Using a combination of not() , filter() and hasClass()

$('.child').not(':has(.hidden)')
      .find('[data-access]')
      .filter(function(){      
          return $('#main').hasClass($(this).data('access'))
      })
      .end()
      .find('[data-type="text"]')
      .text('Matches main').css('color','red')
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="main" class="agent">

   <div class="child">
     <div class="area hidden" >
        <div class="section">
           <div data-type="text" >Has hidden
           </div>
        </div>
      </div>
   </div>
   <div class="child">
     <div class="area" data-access="agent">
        <div class="section">
           <div data-type="text" >No hidden
           </div>
        </div>
      </div>
   </div>
   <div class="child">
     <div class="area">
        <div class="section">
           <div data-type="text" >No data access
           </div>
        </div>
      </div>
   </div>
   </div>

17 Comments

if the divs have no hidden class or if they don't have data access attribute or if it does have a data access attribute and its value matches agent then its visible
Not clear what implication of that comment is
@chalietfl if input field was displayed to user i want to retrieve the value - see updated markup. However the input fields visbility can be controlled by three parent divs. If the area div has a hidden class or a data-access attribute and the data-access attribute value does not match the value of the class in div with #main (in this case its agent) the input field was hidden so can be ignored. I need to check all three divs (area, section and data-type div to see if the input field was visible.
Ok, so what isn't working using my filter approach? Could probably also simplify to $('.child input').filter(function(){ return !$(this).closest('.hidden').length})
well for one your not checking all 3 parent divs of the input fields to see if any of them also contain a data-access attribute
|
0

So there is what is came up with hope it helps

$(document).ready(function(){
        let listOfDivs = $('.child').children().filter((index, el) => !el.getAttribute('hidden') && el.getAttribute('data-access'))
        // lets check the 0 index & compare it with the #main class name
        if($('#main')[0] && listOfDivs[0] && $('#main')[0].getAttribute('class') === listOfDivs[0].getAttribute('data-access')){
          console.log("Matched",listOfDivs[0])
        }
      });
<!DOCTYPE html>
<html lang="en">

  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
  </head>

  <body>
    <div id="main" class="agent">
    </div>
    <div class="child">
      <div class="area hidden">
        <div class="section">
          <div data-type="text">
          </div>
        </div>
      </div>
    </div>
    <div class="child">
      <div class="area" data-access="agent">
        <div class="section">
          <div data-type="text">
          </div>
        </div>
      </div>
    </div>
    <div class="child">
      <div class="area">
        <div class="section">
          <div data-type="text">
          </div>
        </div>
      </div>
    </div>

    <script src="https://code.jquery.com/jquery-3.5.1.min.js"
      integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
  </body>
</html>

if you want to check a list

$(document).ready(function(){
        let listOfDivs = $('.child').children().filter((index, el) => !el.getAttribute('hidden') && el.getAttribute('data-access'))
        let main = $('#main').length ? $('#main')[0] : null
        
        if(main){
          let mainClassValue = main.getAttribute('class')
          for(let i = 0; i < listOfDivs.length; i++ ){
            if(mainClassValue === listOfDivs[i].getAttribute('data-access')){
              console.log("Matched",listOfDivs[i])
            }
          }
        }
      });

2 Comments

OP is using class hidden, not attribute and the data-access can exist on children of your children also. And what happens when listOfDivs has length greater than one?
Nothing it will just check the first one but you want to check a whole list just wrap the if case inside a loop.
0

From your first description:

<script>
$(function () {
    function findDivs() {
        var $root = $('#main');
        var rootClass = $root.get(0).className;

        // each div inside each child does not have class hidden...
        return $('#main > .child > div:not(.hidden)').filter(function (idx, elem) {
            var access = elem.dataset.access;

            //  ...if it has a data-access attribute...
            if (access) {
                // ..its value is equal to the value
                // of the class in div with id=main
                return access === rootClass;
            }

            // if it does not have data-access
            // attribute, return
            return true;
        });
    }

    // add this to an event handler
    console.log(findDivs());
});
</script>

Output:

0: <div class="area" data-access="agent">​
1: <div class="area">

If you want just the leaf divs with [data-type] you can add a .find() operation:

<script>
$(function () {
    function findDivs() {
        var $root = $('#main');
        var rootClass = $root.get(0).className;

        return $('#main > .child > div:not(.hidden)')
            .filter(function (idx, elem) {
                var access = elem.dataset.access;

                if (access) {
                    return access === rootClass;
                }

                return true;
            })
            .find('[data-type]'); // ADDED
    }

    console.log(findDivs());
});
</script>

Output:

0: <div data-type="text">​
1: <div data-type="text">

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.