You are viewing limited content. For full access, please sign in.

Question

Question

jQuery Classic Designer Traversing the DOM troubles

asked on August 20 Show version history

For some reason this is giving me a hard time and I could use a hand here. 

 

My starting element is this text field:
 $('.eachTravColl').on('change', '.progCode input', function(){

 

For some reason I can't seem to traverse up to the .totalAmt field:



I'm trying to get the value of .totalAmt. Easy, right? Not sure why this is not working.

Things I have tried:

 

    var TotalAmt1 = $(this).parents('li').prevAll('.totalAmt').find('div input').val();
    var TotalAmt_1 = $(this).parents('li').prevAll('li').filter(function(){
    	return $(this).attr('class')==='totalAmt';
    }).find('div input').val();
console.log('totalAmt val: '+TotalAmt_1); 

I've tried parents(), siblings() and closest() to traverse up. I can return the correct id for the field I need but, it will not return the value for some reason. 

Thank so much in advance. I know about 10 of you all that will make short work of this :)

EDIT: this seems to be working, but seems like overkill for this type of thing..

    var TotalAmtAttr1 = $(this).parents('li').prevAll('.totalAmt').attr('attr');
    var TotalAmt_1 = $(this).parents('li').prevAll('li').filter(function(){
    	return $(this).attr('attr')===TotalAmtAttr1;
    }).find('div input').val();
console.log('totalAmt val: '+TotalAmt_1); 

 

0 0

Replies

replied on August 21

I would use .closest() instead of .parents()

$(this).closest('li').prevAll('li.totalAmt').find('.cf-field input').val();

The code above seemed to work for me

1 0
replied on August 21 Show version history

Thanks so much for your reply. I tried that actually. The problem I think is that it is in a collection with other .totalAmt fields so I need the closest (up 2 elements) one's value. I tried your code and it returned the wrong value.

      var answers = $(this).closest('li').prevAll('li.totalAmt').find('.cf-field input').val();
console.log('answers: '+answers); 




it's a tricky one ha ha

0 0
replied on August 21 Show version history

You might want to check that $(this) is returning the expected value and that all your classes are entered correctly.

I tested the following code with a Collection and it still worked.

  $('.myCollection').on('change','.test1 select',function(){
    $(this).closest('li').prevAll('li.test2').find('input').val($(this).val());
  });

Each row/set in a collection is grouped within a parent with the rpx class so you shouldn't be running into other total amount fields with prevAll.

In the following screenshot, the code is applying the dropdown selection value to the associated Single line. I put it before the source field and added another field as a spacer so it would be the same basic setup as yours.

1 0
replied on August 21

I did return the id of the target field to confirm it was correct. I could even get the id of the child .cf-field element. I just couldn't go one level down to the input for some reason. 

I got creative and returned the attr of the target .totalAmt field and then filtered the prevAll to return that. I put that in the original post description. That is working like a charm.

0 0
replied on August 21 Show version history

I still think there's some other factor at play here because the example I sent works when I test it, and the DOM structure is the same.

Also, you're already navigating up to retrieve the rpx parent for the following:

var travRow1 = $(this).parents('.rpx').find('.inst input').val();

So you might be better off just grabbing the parent once, assigning it to a variable, then referencing that to get both of the values.

let set = $(this).closest('.rpx');
let totalAmt = set.find('.totalAmt input').val();
let travRow1 = set.find('.inst input').val();

Also, be careful using .parents() since that keeps going up to the root of the DOM and can return more than you expect.

For example, if you use .parents() in the following example, it would return both the parent li AND the li parent of the collection. Even if the first result is the right one and it doesn't "break" anything, it is still doing unnecessary work.

0 0
replied on August 21

By going up to the parent 'li' your only going this far before you try searching children again for the totalAmt which is in an adjacent 'li'

So try going higher, to the parent of all the fields in the set, which is a 'ul'

From there you can use .find because your other fields within the set will all be child objects

 

1 0
replied on August 21

Thanks for your reply! There are other .totalAmt fields, so I need the one up 2 elements specifically. So I can't go to the top .rpx and then find back down, unfortunately. 

 

0 0
replied on August 21

There are other total amount field in the same set? The ul only takes you to the set, not the whole collection.

1 0
replied on August 21

yes, multiple totalAmt in the collection set, so I need the closest one, which in this case is up 2 li elements. 

0 0
replied on August 21

I think there's something else going on that we haven't quite figured out yet since it seems to work as expected when I tested with a collection.

.prevAll() looks for sibling elements, so navigating up to the parent li should still get you where you need to go even with a collection.

.closest() instead of .parents() would ensure it stops at that first li since .parents() grabs matching ancestors all the way up to the root.

1 0
replied on August 21 Show version history

yes, multiple totalAmt in the collection set, so I need the closest one, which in this case is up 2 li elements. 

It is not up 2 li elements, it is adjacent to the li element your going up to. The method find() goes down the layer to descendants, not over.

All these li objects are on the same margin

So go up to the ul element and now your in the right spot to stay within your collection set.

Now from here you have multiple fields with the same class name, so get them all and "for each" through them finding the one you want to work with by whatever makes it distinct, it's label, a second class name, it's index. Whatever differentiates it that makes it the one you want to work with.

1 0
replied on August 21

Got it. Explaining how the are adjacent is super helpful. 

0 0
replied on August 20 Show version history

Here is the entire block for reference:

//#1 .eachTravColl on change to .progCode. Adds/update row to .progCodeDataTbl with mi data only when 4 digits
  $('.eachTravColl').on('change', '.progCode input', function(){
    var travTypeClass = $(this).parents('li').next().attr('class').split(' ');
    var cNm = [travTypeClass];
    var cNmLen = $(cNm)[0].length;
    var travTypeNm = '';
    if ($(cNm)[0][cNmLen -1]=='form-q'){
      travTypeNm = $(cNm)[0][cNmLen -2]
    }
    else{
      travTypeNm = $(cNm)[0][cNmLen -1]
    }  
    var ppssVal = $(this).val();
    var ppssVal_len = $(this).val().length;
    var TotalAmt1 = $(this).parents('li').prevAll('.totalAmt').find('div input').val();
    var TotalAmt_1 = $(this).parents('li').prevAll('li').filter(function(){
    	return $(this).attr('class')==='totalAmt';
    }).find('div input').val();    
    
    var travRow1 = $(this).parents('.rpx').find('.inst input').val();
    if (ppssVal_len === 4){
       $('.progCodeDataTbl tr').find('.Row input[value='+travRow1+']').each(function(){
           var pcdType = $(this).parents('tr').find('.Type_1 input').val();
           if (pcdType==travTypeNm){
           	 $(this).parents('tr').find('.form-del-field').click();          
           }	
       });
      $('.progCodeDataTbl .cf-table-add-row').click().change();
      $('.progCodeDataTbl tr:last .PPSS_1 input').val(ppssVal).change();
      $('.progCodeDataTbl tr:last .Amt input').val(TotalAmt1).change();
      $('.progCodeDataTbl tr:last .Type_1 input').val(travTypeNm).change();
      $('.progCodeDataTbl tr:last .Row input').val(travRow1).change();
         
    }  
  });//end on change

 

0 0
You are not allowed to follow up in this post.

Sign in to reply to this post.