0

1000 questions like this out there but I can't find what I am looking for; I will try and be as precise as possible. I've got a fair amount of experience with JS/JQuery but I get lost on this sort of thing.

So I am dynamically creating inputs that are then moved into a div to be used. I want to attached an event handler to those inputs so as they are changed something happens, which is reliant on know which input has been changed. The HTML in its basic form looks like this:

<div class='inputBucket' hidden>
    <input><input> <!-- etc -->
</div>
<div class='inputBox'></div>

The JS I'm using looks like this:

$('body').on(
        "input", 
        '.inputBox input[type!="radio"][type!="checkbox"]', 
        function(){
            $action($(this));
        }
);

$action is a function that is meant to do all the heavy lifting.

The problem I am getting is that "this" isn't the element I am expecting. It returns the first input that was used, even if it has since moved back to the .inputBucket div. The trigger always fires when expected, but with the first input used once the page has load, as opposed to the input that was actually changed.

Looking for any ways to make the desired functionality work, not sure what is going wrong to know what to change! This is also a stripped down version of what I am actually trying to create, if this should work I will provide more info.

Explanation round 2

So, the inputs inside the .inputBucket have been dragged there, using the JQueryUI draggable function. These are then sortable (.inputBucket has had the sortable JQueryUI function applied, the inputs are hidden but they are within divs which obviously are visible for this to work). The final step is for when one of the divs in .inputBucket is clicked it sends its input div to .inputBox, where they are changed and I get my problem

And some more... Thought this might be another reason for not working. I wanted to create one function to handle all the oddities from events, if this is correct it may be useful to others as well! I've updated this function so it now works

$.fn.onInput = function ($selector, $actionOrMod, $action) {
    if (arguments.length == 2){
        $mod = "";
        $action = $actionOrMod;
    }else if(arguments.length == 3){
        $mod = $actionOrMod;
    }else{
        console.error('Incorrect number of arguments');
        return;
    }

    $(this).on(
        "input", 
        $selector + ' textarea' + $mod, 
        $.debounce(function(evt){$action($(evt.target))}, 250)
    );
    $(this).on(
        "input", 
        $selector + ' input[type!="radio"][type!="checkbox"]' + $mod, 
        $.debounce(function(evt){$action($(evt.target))}, 250)
    );

    $(this).on(
        "submit", 
        $selector + ' input[type!="radio"][type!="checkbox"]' + $mod, 
        function(evt){$action($(evt.target))}
    );

     $(this).on(
         "change submit", 
         $selector + ' input[type="radio"]' + $mod + ', ' + $selector + ' input[type="checkbox"]' + $mod + ', ' + $selector + ' select' + $mod, 
         function(evt){$action($(evt.target))}
    );
}

I've tried simply passing $action as the on parameter, or writing a little function to pass "this" into action, both ways show this problem. Any errors in here? $.debounce is a JQuery plugin I know and use often, shouldn't be the issue.

9
  • You might need to explain a little more about how and when DIVs are moved, from where and to when. So they're being picked up from and relocated within the DOM? Commented Aug 3, 2017 at 10:32
  • Can you reproduce this? eg with a minimal reproducible example in a snippet? I tried with a simple jsfiddle and it works as expected. Might be because it's dynamically loaded, but I doubt it. Commented Aug 3, 2017 at 10:32
  • If you move your input out of .inputBox then the event won't fire for that input as you're using event delegation. If it is, then something else is happening. Commented Aug 3, 2017 at 10:36
  • Thanks guys, going to add another explanation.... Commented Aug 3, 2017 at 10:40
  • 1
    okay instead of this can you try function(evt){ $action(evt.target){..}} and see what happens? Commented Aug 3, 2017 at 11:02

2 Answers 2

1

instead of this can you try function(evt){ $action(evt.target){..}} and see what happens?

based on my basic understanding the this in jquery is manipulated so it is bound to the object/element that the event happened on (otherwise it would be referring to the window object) but since you are delegating the event you are not getting the expected element, event.target ensures that you get the element that received the event just as if you said

$('body').on('click', 'li', function(evt){ console.log(evt.target)}); you will get the precise li element which received the click

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

Comments

0

Am not sure about your requirement, but if am not wrong you can do by adding a common class to all the dynamically added input, and with below-given code, event get attached all those elements

$(body).on('input', '.myCommonClass', function () {
    var self=$(this);
    // so on.....
});

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.