jQuery updating elements added on the fly? - javascript

My code is not working, i think because elements are added on the fly:
var tooltip = $('<div/>').insertAfter('.trigger').addClass('tooltip');
var tname = $('<span/>').addClass('tname').text('(...)');
tooltip.html(tname.html()):
// Ajax call
success: function() {
tname.html('success'); // not working
$('.tooltip').find('.tname').html('success'); // not working
$('.tname').html('success'); // not working
}

This won't work because you are not inserting the tname element into the DOM. See this fix below:
var tooltip = $('<div/>').insertAfter('.trigger').addClass('tooltip');
var tname = $('<span/>').addClass('tname').text('(...)');
tooltip.html("");
tooltip.append(tname);
// Ajax call
success: function() {
tname.html('success'); // should work
$('.tooltip').find('.tname').html('success'); // should work
$('.tname').html('success'); // should work
}

You're not inserting the span into the DOM.
// append to some element
var tname = $('<span/>').addClass('tname').text('(...)').appendTo(tooltip);
Only then you can use selectors to find the element and do something with it.

Related

Remove dynamically added div on timer

I'd like a div to appear for a short duration of time and then go away.
So, I dynamically create the div on the click of a button, and then after some work is done, I'd like it to be removed from the DOM.
So, I set up a timer like so:
var contentJoinTab = $("#...");
var divIdSubscribePleaseWait = "div-subscribe-pleasewait";
btnSubscribe.on("click", function (event) {
displaySubscriptionWait();
postMailingListSubscription();
});
function displaySubscriptionWait() {
var s = `<div id = ${divIdSubscribePleaseWait} class = "${classMailingListPleaseWait}">Please wait...</div>`;
contentJoinTab.append(s);
};
function postMailingListSubscription() {
// fake for now
window.setTimeout(function() {
removeSubscriptionWait();
}, 4000);
};
function removeSubscriptionWait() {
contentJoinTab.parent(`${divIdSubscribePleaseWait}`).remove();
// I've even tried the following to no avail
// $(`${divIdSubscribePleaseWait}`).remove();
// contentJoinTab.find(`${divIdSubscribePleaseWait}`).remove();
};
However, even though there is no error in the call to the remove() method, the div I am trying to remove remains in the DOM and is visible.
I do understand event propagation but my understanding is that that's not relevant here. That would have been relevant if I wanted to attach an event to the click (or any other event) of the dynamically created div or any of its parent.
You may be missing # when calling removeSubscriptionWait And also need "" for id = ${divIdSubscribePleaseWait}.
Please see changes below in case it isn't clear:
function displaySubscriptionWait() {
var s = `<div id = "${divIdSubscribePleaseWait}" class = "${classMailingListPleaseWait}">Please wait...</div>`;
contentJoinTab.append(s);
};
function postMailingListSubscription() {
// fake for now
window.setTimeout(function() {
removeSubscriptionWait();
}, 4000);
};
function removeSubscriptionWait() {
contentJoinTab.parent(`#${divIdSubscribePleaseWait}`).remove();
// I've even tried the following to no avail
$(`#${divIdSubscribePleaseWait}`).remove();
};
You can do that by setting outerHTML of that div to null
function addDiv() {
let s = "<div id='tempDiv'>Temporary Div</div>"
let root = document.getElementById("root")
root.innerHTML += s;
}
function removeDiv() {
let theDiv = document.getElementById("tempDiv");
theDiv.outerHTML=""
}
addDiv()
setTimeout(removeDiv,2000)
<div id=root>
</div>
You have appended that div as a child of contentJoinTab but when you go to remove it you are looking for it as being parent of contentJoinTab
You also need to add the ID prefix in selector
try changing
contentJoinTab.parent(`${divIdSubscribePleaseWait}`).remove();
To
contentJoinTab.find(`#${divIdSubscribePleaseWait}`).remove();
update removeSubscriptionWait function :
function removeSubscriptionWait() {
contentJoinTab.find('#'+`${divIdSubscribePleaseWait}`).remove();
};

Jquery .change() event fires only once

So I'm fairly novice with jquery and js, so I apologise if this is a stupid error but after researching I can't figure it out.
So I have a list of data loaded initially in a template, one part of which is a dropdown box that lets you filter the data. My issue is that the filtering only works once? As in, the .change function inside $(document).ready() only fires the once.
There are two ways to reload the data, either click the logo and reload it all, or use the search bar. Doing either of these at any time also means the .change function never fires again. Not until you refresh the page.
var list_template, article_template, modal_template;
var current_article = list.heroes[0];
function showTemplate(template, data)
{
var html = template(data);
$("#content").html(html);
}
$(document).ready(function()
{
var source = $("#list-template").html();
list_template = Handlebars.compile(source);
source = $("#article-template").html();
article_template = Handlebars.compile(source);
source = $("#modal-template").html();
modal_template = Handlebars.compile(source);
showTemplate(list_template,list);
$(".articleButton").click(function()
{
var index = $(this).data("id");
current_article = list.heroes[index];
showTemplate(article_template,current_article);
$('.poseThumb').click(displayModal);
});
$("#classFilter").change(function()
{
console.log("WOW!");
var classToFilter = this.value;
var filteredData =
{
heroes: list.heroes.filter(function(d)
{
if (d.heroClass.search(classToFilter) > -1)
{
return true;
}
return false;
})
};
console.log(filteredData);
showTemplate(list_template,filteredData);
$(".articleButton").click(function()
{
var index = $(this).data("id");
current_article = filteredData.heroes[index];
showTemplate(article_template,current_article);
$('.poseThumb').click(displayModal);
});
});
$("#searchbox").keypress(function (e)
{
if(e.which == 13)
{
var rawSearchText = $('#searchbox').val();
var search_text = rawSearchText.toLowerCase();
var filteredData =
{
heroes: list.heroes.filter(function(d)
{
if (d.name.search(search_text) > -1)
{
return true;
}
return false;
})
};
console.log(filteredData);
showTemplate(list_template,filteredData);
$(".articleButton").click(function()
{
var index = $(this).data("id");
current_article = filteredData.heroes[index];
showTemplate(article_template,current_article);
$('.poseThumb').click(displayModal);
});
}
});
$("#logo").click(function()
{
showTemplate(list_template,list);
$(".articleButton").click(function()
{
var index = $(this).data("id");
current_article = list.heroes[index];
showTemplate(article_template,current_article);
$('.poseThumb').click(displayModal);
});
});
//$("#logo").click();
});
function displayModal(event)
{
var imageNumber = $(this).data("id");
console.log(imageNumber);
var html = modal_template(current_article.article[0].vicPose[imageNumber]);
$('#modal-container').html(html);
$("#imageModal").modal('show');
}
I should note two things: first, that the search bar works perfectly, and the anonymous function inside both of them is nearly identical, and like I said, the filtering works perfectly if you try it after the initial load. The second is that the same problem occurs replacing .change(anonymous function) with .on("change",anonymous function)
Any help or advice would be greatly appreciated. Thanks.
I agree with Fernando Urban's answer, but it doesn't actually explain what's going on.
You've created a handler attached to an HTML element (id="classFilter") which causes part of the HTML to be rewritten. I suspect that the handler overwrites the HTML which contains the element with the handler on it. So after this the user is clicking on a new HTML element, which looks like the old one but doesn't have a handler.
There are two ways round this. You could add code inside the handler which adds the handler to the new element which has just been created. In this case, that would mean making the handler a named function which refers to itself. Or (the easier way) you could do what Fernando did. If you do this, the event handler is attached to the body, but it only responds to clicks on the #classFilter element inside the body. In other words, when the user clicks anywhere on the body, jQuery checks whether the click happened on a body #classFilter element. This way, it doesn't matter whether the #classFilter existed when the handler was set. See "Direct and delegated events" in jQuery docs for .on method.
Try to use some reference like 'body' in the event listeners inside your DOM like:
$('body').on('click','.articleButton', function() {
//Do your stuff...
})
$('body').on('click','#classFilter', function() {
//Do your stuff...
})
$('body').on('keypress','#searchbox', function() {
//Do your stuff...
})
$('body').on('click','#logo', function() {
//Do your stuff...
})
This will work that you can fire it more than once.

Why is this jQuery submit event not triggering correctly?

I am trying to create a function that takes a user's input and uses it to search Wikipedia. Then, at least for now, show the first result by appending it to the element call "#list".
I have tested the API, the JSON syntax, the appendTo syntax all independently and confirmed that they are working fine. But the event does not execute.
$('form').submit(function(event)
{
var $input = $(event.target).find('input');
var search = $input.val();
$.getJSON("https://en.wikipedia.org/w/api.php?action=query&format=json&list=search&titles=Main+Page&srsearch="+search+"&srprop=wordcount%7Ctimestamp%7Csnippet%7Ctitlesnippet",
function(data)
{
var item = data.query.pages.search[0].titlesnippet;
var itemDesc = data.query.pages.search[0].snippet;
var html = $('<li>').html(item+"<br/>"+itemDesc);
html.prependTo('#list');
});
});

How to properly use appendChild

$(document).ready(function() {
$("a:last").on("click", function(event) {
event.preventDefault();
var url = $("a:last").attr("href");
var page = url.slice(-2).trim();
var newDiv = document.createElement("div");
$(newDiv).addClass("content");
$(newDiv).addClass(page);
$(newDiv).load(url);
document.getElementById("main").appendChild($(newDiv));
});
});
I want to create a new div and load some content into it, then append it to the "main" div, but I get a TypeError:
Argument 1 of Node.appendChild does not implement interface Node.
I already have a div with id="main", why can't I append my new div to it?
Basically appendChild() expects a node object as its parameter, but here you are passing a jquery object. You can fix it by passing a node object,
document.getElementById("main").appendChild(newDiv);
And since you are using jquery, you can use its own append() function,
$(document).ready(function() {
$("a:last").on("click", function(event) {
event.preventDefault();
var url = $("a:last").attr("href");
var page = url.slice(-2).trim();
var newDiv = $("<div>");
newDiv.addClass("content");
newDiv.addClass(page);
newDiv.load(url);
$("#main").append(newDiv);
});
});
The issue is because you're mixing up jQuery and plain old JS. The error itself is because you're proving a jQuery object to appendChild() when it's expecting a DOMElement. As you're using jQuery anyway you may as well use that to create your elements. Try this:
$("a:last").on("click", function(e) {
e.preventDefault();
var url = $("a:last").attr("href");
var page = url.slice(-2).trim();
$('<div />').addClass('content ' + page).appendTo('#main').load(url);
});
$(newDiv) is a jquery object, not the node. You need to pass the node in. This will work
$(document).ready(function() {
$("a:last").on("click", function(event) {
event.preventDefault();
var url = $("a:last").attr("href");
var page = url.slice(-2).trim();
var newDiv = document.createElement("div");
$(newDiv).addClass("content");
$(newDiv).addClass(page);
$(newDiv).load(url);
document.getElementById("main").appendChild(newDiv);
});
});

JS adding a number to a class (classname+number)

There's a problem somewhere in ".addClass('clicked'+'nb')
my css classes are named "clicked1" "clicked2" etc.
I tried 'clicked1' and 'clicked2' and they work, but I'd like it to work with the "nb" that is collected.
$(document).ready(function() {
$('.boxes').on('click', '.box', function() {
var data = $(this).data('nb');
var tekst = $('.wrapper');
tekst.addClass('clicked'+'nb');/*'clicked1' is a css class, same with clicked2,3...*/
});
});
https://jsfiddle.net/yujtvd66/2/
I've updated the JSFiddle with the code i think you're looking for.
$('.wrapper').removeClass()
.addClass('wrapper')
.addClass('clicked'+data);
Here you are getting the data of the element to the data variable.
var data = $(this).data('nb');
You need to use that variable wherever you want to use your data.
tekst.addClass('clicked' + data);
$(document).ready(function() {
$('.boxes').on('click', '.box', function() {
var data = $(this).attr('data-nb');
var tekst = $('.wrapper');
tekst.addClass('clicked'+data);
});
});
Fiddle

Categories

Resources