Rectangle 27 3

Using instead of bypassing Knockout (event handling)

I might miss something as I've no time right now to test it completely, but yes you're missing something. You're trying to update your viewModel through the DOM with jQuery in the live functions, thus bypassing the Knockout MVVM logic.

In fact Knockout also has an options binding which is designed specifically for this kind of task. Adapted example from the docs:

<select data-bind="options: myOptionsList,
                       optionsText: 'countryName',
                       value: myValueBinding,
                       optionsCaption: 'Choose...'"></select>

The value binding keeps track of the selected option if you have a myValueBinding observable in your viewmodel. The options binding is an observableArray in your view model, from which the value binding will be updated.

The arrayFirst utility function returns the first match for which the function evaluates true. In your snippet this is impossible: in your toggleSelected functions you only pass an array and no id, so it will never evaluate to true (id = undefined).

var credential = ko.utils.arrayFirst(array, function (credential) {
        var stringToInt = parseInt(id);
        return credential.Id === stringToInt;
    });

Instead of passing this.value to toggleSelected (which has no meaning for Knockout, unless you intend to use the DOM as data communication layer instead of your viewModel. So you should access the option's bound data with ko.dataFor(), eg

$("#selectedCredentials").live('dblclick', function (e) {
   var id = ko.dataFor(this).ID, array = ko.contextFor(this).$root.AllCredentials;
   // if you have properly stored your arrays and properties, this will work:
   toggleselected(array,id);
});

If you bound this live on your select it would have been even easier:

<select data-bind="event: { dblclick: toggleSelected }"></select>

You don't even need to pass parameters in the view, because event and data are automatically passed as parameter. In your toggleSelected function you'd have:

TestNWJS.QualificationList.ViewModel.toggleSelected = function(data, e) {
   var id = data.ID, array = TestNWJS.QualificationList.ViewModel.AllCredentials;
   // if you have properly stored your arrays and properties, this will work:
   toggleselected(array,id);
});

I'm a little confused about how to implement your answer. Are you saying that I should include all 3 of those, or just either the 1st or 2nd and 3rd?

@John these are not different approaches to the same issue; they are guidelines for correct usage of Knockout on the different aspects your question presented. The ko.utils is really just the same as a for loop, so that doesn't matter. The select binding takes an observableArray as list, so instead of binding if to each option, you move the option from 1 array (sel==false) to the other (sel==true). As for the event handling, it is absolutely required that you pass the KO data, and when possible, binding on the view is preferred (with data-bind).

knockout.js - Knockout array and binding issues - Stack Overflow

knockout.js
Rectangle 27 487

So this is way late, but I've discovered an answer, in case it becomes useful to anyone who comes across this thread.

Changes in value to hidden elements don't automatically fire the .change() event. So, wherever it is that you're setting that value, you also have to tell jQuery to trigger it.

function setUserID(myValue) {
     $('#userid').val(myValue)
                 .trigger('change');
}
$('#userid').change(function(){
      //fire your ajax call  
})

should work as expected.

.trigger()
change()

It works, but it seems like it triggers the change event twice!. Is like if I put this code, it treggers it twice, if I remove the code, no triggers w/e.!!

change
setUserID()
if ($('#userid').val() != myVaule) { // set val() and trigger change }

This is especially useful if you are are trying to catch a "change" event that as being changed via javascript, otherwise the changes made by javascript cannot be caught by the .change(handler) or .on("change", handler)

so If I don't have control on the function that changes the value of the hidden field (i.e. can't fire the trigger), this solution wont work , right ?

event handling - jQuery - Detect value change on hidden input field - ...

jquery event-handling field onchange hidden
Rectangle 27 485

So this is way late, but I've discovered an answer, in case it becomes useful to anyone who comes across this thread.

Changes in value to hidden elements don't automatically fire the .change() event. So, wherever it is that you're setting that value, you also have to tell jQuery to trigger it.

function setUserID(myValue) {
     $('#userid').val(myValue)
                 .trigger('change');
}
$('#userid').change(function(){
      //fire your ajax call  
})

should work as expected.

.trigger()
change()

It works, but it seems like it triggers the change event twice!. Is like if I put this code, it treggers it twice, if I remove the code, no triggers w/e.!!

change
setUserID()
if ($('#userid').val() != myVaule) { // set val() and trigger change }

This is especially useful if you are are trying to catch a "change" event that as being changed via javascript, otherwise the changes made by javascript cannot be caught by the .change(handler) or .on("change", handler)

so If I don't have control on the function that changes the value of the hidden field (i.e. can't fire the trigger), this solution wont work , right ?

event handling - jQuery - Detect value change on hidden input field - ...

jquery event-handling field onchange hidden
Rectangle 27 5

Events bubble "up" the DOM tree, so if you've got handlers for an element and its parent, the child element handler will be called first.

If you register more than one handler for an event on a single DOM element (like, more than one "click" handler for a single button), then the handlers are called in the order that they were attached to the element.

Your handlers can do a few things to change what happens after they're done:

  • With the passed-in event parameter, call event.preventDefault() to keep any "native" action from happening
  • call event.stopPropagation() to keep the event from bubbling up the DOM tree
  • return false from the handler, to both stop propagation and prevent default

Note that for some input elements (checkboxes, radio buttons), the handling is a little weird. When your handler is called, the browser will have already set the checkbox "checked" value to the opposite of its former value. That is, if you have a checkbox that is not checked, then a "click" handler will notice that the "checked" attribute will be set to "true" when it is called (after the user clicks). However, if the handler returns false, the checkbox value will actually NOT be changed by the click, and it will remain un-checked. So it's like the browser does half of the "native" action (toggling the element "checked" attribute) before calling the handler, but then only really updates the element if the handler does not return false (or call "preventDefault()" on the event object).

will be called the parent handler or no?

The parent handler is called unless the child handler prevents that from happening - see my (edited) answer

javascript - Event Handling order - Stack Overflow

javascript jquery javascript-events event-bubbling
Rectangle 27 170

$('#myform :checkbox').change(function() {
    // this will contain a reference to the checkbox   
    if (this.checked) {
        // the checkbox is now checked 
    } else {
        // the checkbox is now no longer checked
    }
});

this is already set to the checkbox's DOM element so this.checked is sufficient. You won't need to create another jQuery object for it unless you plan on manipulating it.

Just a small tip. You will get a performance boost by using input:checkbox in your selector instead of just :checkbox since the latter is translated to the universal selector *:checkbox.

Click is not anywhere close to any check event.

This is no way the best answer. If you have a corresponding label for your input (like <label for='myInput'>Checkbox:</label><input id='myInput' name='myInput' type='checkbox'/> ) and you click the label, the checkbox will be checked, but this function would NOT be called. You should use the .change() event

This answer does not fully provide the answer - please see Anurag's answer below, which is a MUCH more complete (and accurate) answer. This answer is partly correct of course, but as stated, it is not the best answer.

html - jQuery checkbox event handling - Stack Overflow

jquery html checkbox
Rectangle 27 24

Handling the response client side

What server-side language are you using? In my app I can easily download a file from an AJAX call by setting the correct headers in PHP's response:

header("HTTP/1.1 200 OK");
header("Pragma: public");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");

// The optional second 'replace' parameter indicates whether the header
// should replace a previous similar header, or add a second header of
// the same type. By default it will replace, but if you pass in FALSE
// as the second argument you can force multiple headers of the same type.
header("Cache-Control: private", false);

header("Content-type: " . $mimeType);

// $strFileName is, of course, the filename of the file being downloaded. 
// This won't have to be the same name as the actual file.
header("Content-Disposition: attachment; filename=\"{$strFileName}\""); 

header("Content-Transfer-Encoding: binary");
header("Content-Length: " . mb_strlen($strFile));

// $strFile is a binary representation of the file that is being downloaded.
echo $strFile;

This will in fact 'redirect' the browser to this download page, but as @ahren alread said in his comment, it won't navigate away from the current page.

It's all about setting the correct headers so I'm sure you'll find a suitable solution for the server-side language you're using if it's not PHP.

Assuming you already know how to make an AJAX call, on the client side you execute an AJAX request to the server. The server then generates a link from where this file can be downloaded, e.g. the 'forward' URL where you want to point to. For example, the server responds with:

{
    status: 1, // ok
    // unique one-time download token, not required of course
    message: 'http://yourwebsite.com/getdownload/ska08912dsa'
}

When processing the response, you inject an iframe in your body and set the iframe's SRC to the URL you just received like this (using jQuery for the ease of this example):

$("body").append("<iframe src='" + data.message +
  "' style='display: none;' ></iframe>");

If you've set the correct headers as shown above, the iframe will force a download dialog without navigating the browser away from the current page.

Extra addition in relation to your question; I think it's best to always return JSON when requesting stuff with AJAX technology. After you've received the JSON response, you can then decide client-side what to do with it. Maybe, for example, later on you want the user to click a download link to the URL instead of forcing the download directly, in your current setup you would have to update both client and server-side to do so.

Can you please provide jquery code that performs the POST request? Typically you will provide a callback function that deals with the server response and then you parse and process this response according to the requirements of your app. How exactly would you make the browser show the download dialog once it receives the response you provide using the above server-side code?

Thanks, I see what you meant now. Interesting solution with the iframe, however it won't work in my scenario. As I stated in the question: "Response might be a JSON string or it might be a file (as an attachment)" Changing what the server returns is not an option. Thank you for your effort, though. It is a good solution, and might help someone with a similar issue. I'll upvote.

Too bad I couldn't help you with this solution. Is changing the request the only thing that you cannot do or can't you write any server-side code at all in this particular case? If you could write some server-side code yourself, you could write a proxy which requests the file and returns an URL instead.

@Robin van Baalen This was a great answer for me, thanks. I'm using entirely different frameworks but the principle is sound. Upvoted.

javascript - Handle file download from ajax post - Stack Overflow

javascript jquery ajax
Rectangle 27 170

$('#myform :checkbox').change(function() {
    // this will contain a reference to the checkbox   
    if (this.checked) {
        // the checkbox is now checked 
    } else {
        // the checkbox is now no longer checked
    }
});

this is already set to the checkbox's DOM element so this.checked is sufficient. You won't need to create another jQuery object for it unless you plan on manipulating it.

Just a small tip. You will get a performance boost by using input:checkbox in your selector instead of just :checkbox since the latter is translated to the universal selector *:checkbox.

Click is not anywhere close to any check event.

This is no way the best answer. If you have a corresponding label for your input (like <label for='myInput'>Checkbox:</label><input id='myInput' name='myInput' type='checkbox'/> ) and you click the label, the checkbox will be checked, but this function would NOT be called. You should use the .change() event

This answer does not fully provide the answer - please see Anurag's answer below, which is a MUCH more complete (and accurate) answer. This answer is partly correct of course, but as stated, it is not the best answer.

html - jQuery checkbox event handling - Stack Overflow

jquery html checkbox
Rectangle 27 167

$('#myform :checkbox').change(function() {
    // this will contain a reference to the checkbox   
    if (this.checked) {
        // the checkbox is now checked 
    } else {
        // the checkbox is now no longer checked
    }
});

this is already set to the checkbox's DOM element so this.checked is sufficient. You won't need to create another jQuery object for it unless you plan on manipulating it.

Just a small tip. You will get a performance boost by using input:checkbox in your selector instead of just :checkbox since the latter is translated to the universal selector *:checkbox.

Click is not anywhere close to any check event.

This is no way the best answer. If you have a corresponding label for your input (like <label for='myInput'>Checkbox:</label><input id='myInput' name='myInput' type='checkbox'/> ) and you click the label, the checkbox will be checked, but this function would NOT be called. You should use the .change() event

This answer does not fully provide the answer - please see Anurag's answer below, which is a MUCH more complete (and accurate) answer. This answer is partly correct of course, but as stated, it is not the best answer.

html - jQuery checkbox event handling - Stack Overflow

jquery html checkbox
Rectangle 27 123

$('#myform :checkbox').change(function() {
    // this represents the checkbox that was checked
    // do something with it
});

If the checkbox is hidden, then a user won't be able to interact with it. Let me know if you meant something else.

$("input[name=check1]").prop('checked', true)

That is by design. Programmatically changing a DOM element's property does not trigger associated event handlers. You'll have to fire them manually.

This should be the selected answer, it covers clicking a checkbox's label

From jQuery documentation: "Because :checkbox is a jQuery extension and not part of the CSS specification, queries using :checkbox cannot take advantage of the performance boost provided by the native DOM querySelectorAll() method. For better performance in modern browsers, use [type="checkbox"] instead."

html - jQuery checkbox event handling - Stack Overflow

jquery html checkbox
Rectangle 27 123

$('#myform :checkbox').change(function() {
    // this represents the checkbox that was checked
    // do something with it
});

If the checkbox is hidden, then a user won't be able to interact with it. Let me know if you meant something else.

$("input[name=check1]").prop('checked', true)

That is by design. Programmatically changing a DOM element's property does not trigger associated event handlers. You'll have to fire them manually.

This should be the selected answer, it covers clicking a checkbox's label

From jQuery documentation: "Because :checkbox is a jQuery extension and not part of the CSS specification, queries using :checkbox cannot take advantage of the performance boost provided by the native DOM querySelectorAll() method. For better performance in modern browsers, use [type="checkbox"] instead."

html - jQuery checkbox event handling - Stack Overflow

jquery html checkbox
Rectangle 27 123

$('#myform :checkbox').change(function() {
    // this represents the checkbox that was checked
    // do something with it
});

If the checkbox is hidden, then a user won't be able to interact with it. Let me know if you meant something else.

$("input[name=check1]").prop('checked', true)

That is by design. Programmatically changing a DOM element's property does not trigger associated event handlers. You'll have to fire them manually.

This should be the selected answer, it covers clicking a checkbox's label

From jQuery documentation: "Because :checkbox is a jQuery extension and not part of the CSS specification, queries using :checkbox cannot take advantage of the performance boost provided by the native DOM querySelectorAll() method. For better performance in modern browsers, use [type="checkbox"] instead."

html - jQuery checkbox event handling - Stack Overflow

jquery html checkbox
Rectangle 27 31

There are several useful answers, but none seem to cover all the latest options. To that end all my examples also cater for the presence of matching label elements and also allow you to dynamically add checkboxes and see the results in a side-panel (by redirecting console.log).

$('#myform :checkbox').change(function () {
    if ($(this).is(':checked')) {
        console.log($(this).val() + ' is now checked');
    } else {
        console.log($(this).val() + ' is now unchecked');
    }
});
  • Uses the :checkbox selector, which is preferable to using input[type=checkbox]
  • This connects only to matching elements that exist at the time the event was registered.

Delegated event handlers are designed for situations where the elements may not yet exist (dynamically loaded or created) and is very useful. They delegate responsibility to an ancestor element (hence the term).

$('#myform').on('change', ':checkbox', function () {
    if ($(this).is(':checked')) {
        console.log($(this).val() + ' is now checked');
    } else {
        console.log($(this).val() + ' is now unchecked');
    }
});
change
#myform
  • It then applies the jQuery selector (':checkbox' in this case) to only the elements in the bubble chain.
  • It then applies the event handler function to only those matching elements that caused the event.
  • Use document as the default to connect the delegated event handler, if nothing else is closer/convenient.
  • Do not use body to attach delegated events as it has a bug (to do with styling) that can stop it getting mouse events.

The upshot of delegated handlers is that the matching elements only need to exist at event time and not when the event handler was registered. This allows for dynamically added content to generate the events.

A: So long as the events are at user-interaction speeds, you do not need to worry about the negligible difference in speed between a delegated event handler and a directly connected handler. The benefits of delegation far outweigh any minor downside. Delegated event handlers are actually faster to register as they typically connect to a single matching element.

This is actually by design. If it did fire the event you would easily get into a situation of endless updates. Instead, after changing the checked property, send a change event to the same element using trigger (not triggerHandler):

trigger

e.g. with trigger the normal change event is caught

$cb.prop('checked', !$cb.prop('checked')).trigger('change');
  • Do not use triggerHandler as was suggested by one user, as it will not bubble events to a delegated event handler.

Events triggered with .triggerHandler() do not bubble up the DOM hierarchy; if they are not handled by the target element directly, they do nothing.

html - jQuery checkbox event handling - Stack Overflow

jquery html checkbox
Rectangle 27 17

First solution is handling the ajax requests

There are two ways to do it,

There is a .ajaxComplete() function in jQuery which handles all ajax request on page.

var actualCode = '(' + function() {
    $(document).ajaxComplete(function() { 
      alert('content has just been changed, you should change href tag again');
      // chaging href tag code will be here      
    });
} + ')();';
var script = document.createElement('script');
script.textContent = actualCode;
(document.head||document.documentElement).appendChild(script);
script.parentNode.removeChild(script);
content script
$(document).bind("DOMSubtreeModified", function() {
    alert("something has been changed on page, you should update href tag");
});

You might use some different selector to restrict the elements that you're controling the changes.

$("body").bind("DOMSubtreeModified", function() {}); // just listen changes on body content

$("#mydiv").bind("DOMSubtreeModified", function() {}); // just listen changes on #mydiv content

Why do you do script.parentNode.removeChild(script); ? Won't this remove all existing scripts on the rendered pages?

I think it is just a clean-up step. The script is still there. Although you cannot debug using breakpoints, debuggers still got hit.

jquery - Chrome-extension Javascript to detect dynamically-loaded cont...

javascript jquery google-chrome-extension
Rectangle 27 31

There are several useful answers, but none seem to cover all the latest options. To that end all my examples also cater for the presence of matching label elements and also allow you to dynamically add checkboxes and see the results in a side-panel (by redirecting console.log).

$('#myform :checkbox').change(function () {
    if ($(this).is(':checked')) {
        console.log($(this).val() + ' is now checked');
    } else {
        console.log($(this).val() + ' is now unchecked');
    }
});
  • Uses the :checkbox selector, which is preferable to using input[type=checkbox]
  • This connects only to matching elements that exist at the time the event was registered.

Delegated event handlers are designed for situations where the elements may not yet exist (dynamically loaded or created) and is very useful. They delegate responsibility to an ancestor element (hence the term).

$('#myform').on('change', ':checkbox', function () {
    if ($(this).is(':checked')) {
        console.log($(this).val() + ' is now checked');
    } else {
        console.log($(this).val() + ' is now unchecked');
    }
});
change
#myform
  • It then applies the jQuery selector (':checkbox' in this case) to only the elements in the bubble chain.
  • It then applies the event handler function to only those matching elements that caused the event.
  • Use document as the default to connect the delegated event handler, if nothing else is closer/convenient.
  • Do not use body to attach delegated events as it has a bug (to do with styling) that can stop it getting mouse events.

The upshot of delegated handlers is that the matching elements only need to exist at event time and not when the event handler was registered. This allows for dynamically added content to generate the events.

A: So long as the events are at user-interaction speeds, you do not need to worry about the negligible difference in speed between a delegated event handler and a directly connected handler. The benefits of delegation far outweigh any minor downside. Delegated event handlers are actually faster to register as they typically connect to a single matching element.

This is actually by design. If it did fire the event you would easily get into a situation of endless updates. Instead, after changing the checked property, send a change event to the same element using trigger (not triggerHandler):

trigger

e.g. with trigger the normal change event is caught

$cb.prop('checked', !$cb.prop('checked')).trigger('change');
  • Do not use triggerHandler as was suggested by one user, as it will not bubble events to a delegated event handler.

Events triggered with .triggerHandler() do not bubble up the DOM hierarchy; if they are not handled by the target element directly, they do nothing.

html - jQuery checkbox event handling - Stack Overflow

jquery html checkbox
Rectangle 27 31

There are several useful answers, but none seem to cover all the latest options. To that end all my examples also cater for the presence of matching label elements and also allow you to dynamically add checkboxes and see the results in a side-panel (by redirecting console.log).

$('#myform :checkbox').change(function () {
    if ($(this).is(':checked')) {
        console.log($(this).val() + ' is now checked');
    } else {
        console.log($(this).val() + ' is now unchecked');
    }
});
  • Uses the :checkbox selector, which is preferable to using input[type=checkbox]
  • This connects only to matching elements that exist at the time the event was registered.

Delegated event handlers are designed for situations where the elements may not yet exist (dynamically loaded or created) and is very useful. They delegate responsibility to an ancestor element (hence the term).

$('#myform').on('change', ':checkbox', function () {
    if ($(this).is(':checked')) {
        console.log($(this).val() + ' is now checked');
    } else {
        console.log($(this).val() + ' is now unchecked');
    }
});
change
#myform
  • It then applies the jQuery selector (':checkbox' in this case) to only the elements in the bubble chain.
  • It then applies the event handler function to only those matching elements that caused the event.
  • Use document as the default to connect the delegated event handler, if nothing else is closer/convenient.
  • Do not use body to attach delegated events as it has a bug (to do with styling) that can stop it getting mouse events.

The upshot of delegated handlers is that the matching elements only need to exist at event time and not when the event handler was registered. This allows for dynamically added content to generate the events.

A: So long as the events are at user-interaction speeds, you do not need to worry about the negligible difference in speed between a delegated event handler and a directly connected handler. The benefits of delegation far outweigh any minor downside. Delegated event handlers are actually faster to register as they typically connect to a single matching element.

This is actually by design. If it did fire the event you would easily get into a situation of endless updates. Instead, after changing the checked property, send a change event to the same element using trigger (not triggerHandler):

trigger

e.g. with trigger the normal change event is caught

$cb.prop('checked', !$cb.prop('checked')).trigger('change');
  • Do not use triggerHandler as was suggested by one user, as it will not bubble events to a delegated event handler.

Events triggered with .triggerHandler() do not bubble up the DOM hierarchy; if they are not handled by the target element directly, they do nothing.

html - jQuery checkbox event handling - Stack Overflow

jquery html checkbox
Rectangle 27 26

Using the new 'on' method in jQuery (1.7): http://api.jquery.com/on/

$('#myform').on('change', 'input[type=checkbox]', function(e) {
        console.log(this.name+' '+this.value+' '+this.checked);

    });
  • will capture if the checkbox was changed by keyboard, not just click
$("input[name=check1]").prop('checked', true)

Just add .triggerHandler('change'); after the .prop call. Then it will toggle the box AND call the event.

html - jQuery checkbox event handling - Stack Overflow

jquery html checkbox
Rectangle 27 26

Using the new 'on' method in jQuery (1.7): http://api.jquery.com/on/

$('#myform').on('change', 'input[type=checkbox]', function(e) {
        console.log(this.name+' '+this.value+' '+this.checked);

    });
  • will capture if the checkbox was changed by keyboard, not just click
$("input[name=check1]").prop('checked', true)

Just add .triggerHandler('change'); after the .prop call. Then it will toggle the box AND call the event.

html - jQuery checkbox event handling - Stack Overflow

jquery html checkbox
Rectangle 27 26

Using the new 'on' method in jQuery (1.7): http://api.jquery.com/on/

$('#myform').on('change', 'input[type=checkbox]', function(e) {
        console.log(this.name+' '+this.value+' '+this.checked);

    });
  • will capture if the checkbox was changed by keyboard, not just click
$("input[name=check1]").prop('checked', true)

Just add .triggerHandler('change'); after the .prop call. Then it will toggle the box AND call the event.

html - jQuery checkbox event handling - Stack Overflow

jquery html checkbox
Rectangle 27 17

Behavior #2: Dynamic or Delegated Event Binding

My guess is that you're seeing a difference in behavior because some objects in your page are being dynamically added/removed and you need delegated event handling in order to automatically have events for newly added objects.

Among your various examples, there are two basic types of behaviors here:

$('button').click(function () {
    console.log(this) + " - 1";
});

$('button').on('click', function () {
    console.log(this) + " - 2";
});

$body.find('button').on('click', function () {
    console.log(this) + " - 5";
});

The above three all attach a click handler directly to each button object that exists in the page at the time the code is first run. These are basically identical. The .click() syntax is just a shortcut. The $body.find('button') is functionally equivalent to $('button') since both select all buttons in the body.

Note: these event handlers will only be attached to the button objects that exist when this code is first run. Any button objects that are subsequently added to the document will not have an event handler attached to them.

$(document).on('click', 'button', function () {
    console.log(this) + " - 3";
});

$(document.body).on('click', 'button', function () {
    console.log(this) + " - 4";
});

These two use delegated event handling to watch for clicks that bubble up to the document or body objects. These are likewise similar. These will handle any click event that originated on a button tag. Since the event handler is not attached directly to the button object, buttons can come and go in the page and all button objects that exist at any time will get this handler behavior.

It is generally NOT recommended to bind delegated methods bound to the document or body objects. In fact, this is why .live() has been deprecated because that's what it did and it can cause performance issues. The issue is that if you get lots of delegated events all bound to the same object, then every time an event occurs and it bubbles up to this object, jQuery has to compare the originating selector to a lot of different selectors to see which handler to call.

It is much better to bind delegated events to a parent object that is as close to the actual target objects as possible, but obviously you must pick a parent object that won't be added/removed (you need one that is constantly in the page).

In your more specific code example, assuming the bxRetrieveCustomer div is not created dynamically, you should change this:

$(document).on("click", ".tag-open", function (event) {
    // DO SOMETHING
});
$("#bxRetrieveCustomer").on("click", ".tag-open", function (event) {
    // DO SOMETHING
});

Which will still be delegated event handling, but will bind the event handler much closer to the actual object so it will work more efficiently.

If you have objects that are created after you run the event binding code that you want events bound to, then you will want to use delegated event handling on the closest ancestor object that is not dynamically created after-the-fact.

If you have a very large number of objects (even if they are static), then delegated event handling will install much more efficiently because it installs one event handler for all of them rather than thousands for each individual object.

If you have a medium or small number of static objects, then binding event handlers directly to them is the most efficient. It will take a tiny bit more time to initially bind an event handler to each object, but then be the most efficient at the time of the event.

JQuery Event Handlers - What's the "Best" method - Stack Overflow

jquery
Rectangle 27 15

Since hidden input does not trigger "change" event on change, I used MutationObserver to trigger this instead.

This does not work in IE10 and below

MutationObserver = window.MutationObserver || window.WebKitMutationObserver;

var trackChange = function(element) {
  var observer = new MutationObserver(function(mutations, observer) {
    if(mutations[0].attributeName == "value") {
        $(element).trigger("change");
    }
  });
  observer.observe(element, {
    attributes: true
  });
}

// Just pass an element to the function to start tracking
trackChange( $("input[name=foo]")[0] );

AFAIK the mutationobserver also does NOT get fired on a change inside a text field (no matter if hidden or not)

input[type=hidden]

I've used this in combination with a function that was using the map command of jquery to retrieve a collection of hidden input field values. Thanks so much @lulalala!

event handling - jQuery - Detect value change on hidden input field - ...

jquery event-handling field onchange hidden