Appending data from a handler loaded after the script - javascript

I've made a site that displays a user's Facebook photos. The code below appends the photos to the div "facebook-images". This part works fine. The problem I have is that the images are being appended after the Javascript code below is loaded; so the handler "fb-image" is not created when the browser reads the click function code at the bottom, therefore it does not work.
I believe I need to use jQuery on(), but where? I've tried to put on() everywhere in the code below. I've tried to bind with append, I've tried live (which I know is deprecated but worth a shot). Nothing is working.
Any ideas?
<div class="target">
</div>
<div id="facebook-images">
</div>
<script>
$.when(window.deferredes.fbLoaded, window.deferredes.fbLoggedIn).then(function () {
$.getJSON('https://graph.facebook.com/me/photos?access_token=' + FB.getAccessToken(), function (data) {
$.each(data.data, function (i, face) {
$('#facebook-images').append("<div class='fb-image'><img src='" + face.source + "' ></div>");
});
});
});
$(".fb-image img").click(function () {
$(".target").append("<h1>hi</h1>");
});
</script>

The simplest way to fix this is to add the click handlers AFTER the images are inserted into the page.
<script>
$.when(window.deferredes.fbLoaded, window.deferredes.fbLoggedIn).then(function () {
$.getJSON('https://graph.facebook.com/me/photos?access_token=' + FB.getAccessToken(), function (data) {
$.each(data.data, function (i, face) {
$('#facebook-images').append("<div class='fb-image'><img src='" + face.source + "' ></div>");
});
$(".fb-image img").click(function () {
$(".target").append("<h1>hi</h1>");
});
});
});
</script>
You can also use delegated event handling if you want. To do that, you set the event handler on a common parent that does exist at the time you run the event handling code with .on() and you use the delegated form of .on() by passing it a selector like this:
<script>
$.when(window.deferredes.fbLoaded, window.deferredes.fbLoggedIn).then(function () {
$.getJSON('https://graph.facebook.com/me/photos?access_token=' + FB.getAccessToken(), function (data) {
$.each(data.data, function (i, face) {
$('#facebook-images').append("<div class='fb-image'><img src='" + face.source + "' ></div>");
});
});
});
$("#facebook-images").on('click', ".fb-image img", function () {
$(".target").append("<h1>hi</h1>");
});
</script>
The delegated form of .on() works like this:
$(selector of static parent).on(event, selector that matches dynamic object, fn);

Related

JQuery on() method not binding events but works in console

I'm writing some TS code to generate a button dinamically, the button appear on page, but all events on it not works.
I already read answers about delegation and I using it, but the problem is not solved.
The most strange thing is that if I call $("#myID").click() or .mouseover() or .mousedown() in console, all events works correctly.
EDIT AND CLOSE:
Sorry for waste of time, I just put to my background the z-index css attribute to -100, and I don't know why, but the button was impossible to be clicked cause, even if it was visible, it was behind the background div.
Hierarchical selectors can often be avoided simply by attaching the handler to a more appropriate point in the document. For example, instead of $( "body" ).on( "click", "#commentForm .addNew", addComment ) use $( "#commentForm" ).on( "click", ".addNew", addComment ).
https://api.jquery.com/on/
I suspect your delegation is too complex. Consider the following example.
$(function() {
$("#add").click(function(e) {
var item = $("<div>", {
id: "image-button-1",
class: "button"
}).appendTo("#container");
$("<img>", {
src: "https://i.imgur.com/9yMnjGx.png"
}).appendTo(item);
});
$("#container").on("click", "#image-button-1", function(e) {
console.log("Click");
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="add">Add</button>
<div id="container"></div>
Edit: Please don't refer to this, it is incorrect
Can you try this. Enclosing your logic in a function and passing it to jQuery ensures that it is called after the page is loaded completely.
When you are trying to bind event handlers to an element, you have to ensure that the element is actually present in the DOM.
this.htmlElement = "<div id='" + this.ID + "' class='" + this.cssClasses + "'>" + this.buttonImage + "</div>";
$("#" + this.idContainer).append(this.htmlElement);
$(function() {
if (this.enabled) {
$(document).on('mousedown', "#" + this.ID, function (event) {
console.log("down");
});
$(document).on("mouseup", "#" + this.ID, function () {
console.log("up");
});
$(document).on("click", "#" + this.ID, this.action);
}
});

Applying jQuery hover to multiple elements using jQuery each

I'm trying to get the following working so I can make certain elements of a page reveal others on hover using jQuery. I'm trying to use the data attribute of the hover element to pick the revealed element.
I just can't seem to get this working. Or is there a better way to do this?
function setUpServiceHover(){
$( ".poster-banners__poster" ).each(function(i) {
$(this).hover(
function () {
$("#service_" + ($(this).data('target')).addClass('intro__service--show'));
$("#service_" + ($(this).data('target')).removeClass('intro__service--hidden'));
},
function () {
$("#service_" + ($(this).data('target')).addClass('intro__service--hidden'));
$("#service_" + ($(this).data('target')).removeClass('intro__service--show'));
})
});
}
setUpServiceHover();
Appreciate the help.
Thanks.
you don't need to iterate for hover effect, just add hover event handler as shown below
NOTE: you need not to put this script inside setUpServiceHover() function and remove this function. You need to put it inside document.ready.. or $(function().. to ensure DOM loaded.
$(function(){
$(".poster-banners__poster").on("hover",
function () {
$("#service_" + ($(this).data('target')).addClass('intro__service--show'));
$("#service_" + ($(this).data('target')).removeClass('intro__service--hidden'));
},
function () {
$("#service_" + ($(this).data('target')).addClass('intro__service--hidden'));
$("#service_" + ($(this).data('target')).removeClass('intro__service--show'));
});
});

"$(...).find(...)" in onclick-eventhandler

I am using this code for the click handling on a button inside my page:
$(document).on("click", $('#' + GlobalVariables.currentUserType).find(".addDocumentToSection"), function (e) {
addItemToDocumentGrid();
$('#removeDocumentFromSection').disable(true).addClass("disabled");
$('#removeSelection').disable(true).addClass("disabled");
});
But the event fires as soon as I click anywhere in the page. Even if it is not the supposed button which I want to select with $('#' + GlobalVariables.currentUserType).find(".addDocumentToSection").
$('#' + GlobalVariables.currentUserType).find(".addDocumentToSection") returns one element which is actually the button which I want to be selected.
Why does it behave like that?
If you want to use event delegation, the second argument should be a selector, not a jQuery object.
$(document).on("click", '#' + GlobalVariables.currentUserType + " .addDocumentToSection", function (e) {
// ---------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
addItemToDocumentGrid();
$('#removeDocumentFromSection').disable(true).addClass("disabled");
$('#removeSelection').disable(true).addClass("disabled");
});
If you don't want to use event delegation, you need to call on on the element you want to hook the event on:
$('#' + GlobalVariables.currentUserType).find(".addDocumentToSection").on("click", function (e) {
addItemToDocumentGrid();
$('#removeDocumentFromSection').disable(true).addClass("disabled");
$('#removeSelection').disable(true).addClass("disabled");
});
This is all covered in the on documentation.
You are attaching onClick event to a document element. Try:
var button = $('#' + GlobalVariables.currentUserType).find(".addDocumentToSection");
button.on("click", function() {
addItemToDocumentGrid();
$('#removeDocumentFromSection').disable(true).addClass("disabled");
$('#removeSelection').disable(true).addClass("disabled");
});
$('#' + GlobalVariables.currentUserType).find(".addDocumentToSection").on("click", function(e){
});
jQuery can use selectors before the .on("click", this should work for you.

JQuery on click event not working inside dropdown menu with hyperlink?

I have an autocomplete dropdown using twitter-typeahead as follows:
$('#Data').typeahead(
{
displayKey: 'description',
source: myData.ttAdapter(),
templates: {
empty: [
'<div class="empty-message">',
<a class="js-not-found" href="#">No results found</a>,
'</div>'
].join('\n'),
suggestion: function (data) {
return '<span>' + data.description + '</span>';
}
}
}
);
When no results are found the dropdown display a link. I have wired this to a Jquery on click handler as below but when I click the link it just reloads the page?
$(".js-not-found").click(function (e) {
e.preventDefault();
// some stuff
});
The event handler works fine if I have a normal link outside of the dropdown as follows <a class="js-not-found" href="#">No results found</a>
The link is not inside the DOM when you attach the event. For dynamically generated elements you should use on.
Can you try :
$(document).on('click','.js-not-found', function (e) {
e.preventDefault();
// some stuff
});
For better performance it's recommanded to use the direct ancestor inside the DOM of the generated element :
$(".container").on('click','.js-not-found', function (e) {
e.preventDefault();
// some stuff
});
Using delegate() function you can click on dynamically generated HTML elements that are not in your DOM.
Example:
$(document).delegate('.js-not-found', 'click', function()
{
e.preventDefault();
//your code
});
or you can use on() as
$(document).on('click', '.js-not-found', function()
{
// your code
});

a href click not triggering in jquery

$(function() {
$.getJSON("companies.json", function(response) {
var html = '<table id="tbl">';
response.businesses.forEach(function(row) {
html += '<tr><td>' + row.id + '</td><td>' + row.name;
});
html += '</table>';
$("#tabledata").html(html);
});
$(".move").click(function() {
var $id = $(this).attr("idname");
$.getJSON("companies.json", function(response) {
$.map(response.businesses, function(obj) {
if (obj.id == $id)
console.log(obj);
return obj; // or return obj.name, whatever.
});
});
});
});
HTML:
<div id="tabledata" class='left'></div>
<div class="right"></div>
Please help?
As your .move element is added to your page dynamically, you have to make use of jQuery's on() method to delegate the event to an ancestor of the .move element which does exist when your JavaScript first loads.
$(document).on('click', '.move', function() { ... });
Event delegation allows us to attach a single event listener, to a parent element, that will fire for all descendants matching a selector, whether those descendants exist now or are added in the future.
You can read more about jQuery's event delegation here.
If you use event delegation, your problem goes away (and your app becomes more performant and less prone to memory leaks).
// Only do this once, when your page loads...
$(document.body).on('click', '.move', function (ev) {
// This is the link that was clicked.
var $targ = $(ev.target);
});
Try This
$('#tabledata').on('click', '.move', function(e) { ... });
The reason the event isn't being triggered is because the event is only added to elements that exist on the page when you call the .click() method.
Instead, you can use event delegation:
$(document.body).on('click', '.move', function (ev) {
var $targ = $(ev.target);
});
which really says: call the function when any element that matches .move that's inside document.body is clicked.
I know others have said this already but I wanted to make event delegation clearer.

Categories