Dynamically-generated table keeps multiplying even though it's being cleared - javascript

I have a variety of fields I'm appending to a table (#dvdCollectionBody) in my function loadDvdCollectionView().
The problem: if I click the tag that calls my displayDvd() function, then hit the 'Back' button, everything works as it should. If I click the tag, calling displayDvd() a second time, then click the 'Back' button again, the table will be duplicated, indicating that rows are being appended that aren't getting cleared.
I cannot for the life of me understand why the table keeps appending itself, but only after repeating the process of clicking a 'td' tag more than once.
$(document).ready(function () {
loadDvdCollectionView();
// create on a click
createDvd();
});
function loadDvdCollectionView(){
// hide errors
$('#errorDiv').hide();
// show this view
$('#viewingTable').show();
// empty table body of any preexisting data
$('#dvdCollectionBody').empty();
$.ajax({
type: "GET",
url: "http://localhost:8080/dvds",
success:
function (data, status) { $.each(data, function (index, dvd) {
// append DVD collection to table rows in #dvdCollectionBody
var dvdRow = '<tr><td onclick="displayDvd(' + dvd.dvdId + ')">' + .......
$('#dvdCollectionBody').append(dvdRow);
});
}
// called when <td> tag is clicked
function displayDvd(dvdId){
//hide viewingTable
$('#viewingTable').hide();
// empty preexisting data
$('#releaseYearDisplay, #directorDisplay, #ratingDisplay, #notesDisplay, #dvdTitleHeader').empty();
// show table
$('#dvdDetailsDisplay, #dvdTitleHeader').show();
$.ajax({
type: "GET",
url: "http://localhost:8080/dvd/" + dvdId,
success: function (data) {
$('#dvdTitleHeader').append('
<h3>' + data.title + '</h3>'); $('#releaseYearDisplay').append('
<h3>' + data.releaseYear + '</h3>'); $('#directorDisplay').append('
<h3>' + data.director + '</h3>'); $('#ratingDisplay').append('
<h3>' + data.rating + '</h3>'); $('#notesDisplay').append('
<h3>' + data.notes + '</h3>'); }
}
});
$('#backButton').click(function(){
// hide current display and header
$('#dvdDetailsDisplay, #dvdTitleHeader').hide();
// load main view again
loadDvdCollectionView();
});
}

The problem is that, this piece of code:
$('#backButton').click(function(){
// hide current display and header
$('#dvdDetailsDisplay, #dvdTitleHeader').hide();
// load main view again
loadDvdCollectionView();
});
is placed inside your displayDvd() function.
So when the first time your <td> is clicked, the displayDvd() is called and your #backButton callback is added.
Then you hit the #backButton, the callback function is called, everything should work fine here.
However, when you hit the <td> 2nd time, displayDvd() is called again and another click callback is added to #backButton again, also.
This is where the bug occurred. Now your #backButton have 2 same click callback functions attached. So when you click on it, 2 loadDvdCollectionView() are called simultaneously.
Simply move the piece of code into $(document).ready() callback should fix the problem.

You're hiding the DOM elements, but you're not removing them from the DOM. Try the following to remove the content from dvdDetailsDisplay and dvdTitleHeader:
$('#backButton').click(function(){
// hide current display and header
$('#dvdDetailsDisplay, #dvdTitleHeader').empty();
// load main view again
loadDvdCollectionView();
});

Related

AJAX call to display dynamic data with Tooltipster

I'm having an issue where my tooltip from Tooltipster is showing the same data everytime I hover a new element, instead of showing new dynamic data everytime I hover a new element.
How can I fix my code so that only one tooltip shows with new dynamic data each time I hover?
I hover an element that's supposed to activate it, creating this console message:
"Tooltipster: one or more tooltips are already attached to this element: ignoring. Use the "multiple" option to attach more tooltips."
Using the 'multiple' option works by generating new tooltips that shows the proper data, but this causes the tooltips to stack on top of each other instead of replacing itself.
function showAsynchronousTooltipForTopicWithName(name) {
var urlToSend = '/API/v1/topic?name='+encodeURIComponent(name.trim());
$.ajax({
type: "GET",
url: urlToSend,
success: function (result) {
showNotification("API Success", 'success');
showTopicsTooltips(result);
},
error: function (result) {
showNotification("Something went wrong", 'error')
}
});
}
function showTopicsTooltips(response) {
var topic = response;
console.log(topic['name']);
// create content based on experts_internal and experts_external properties
$('.tooltip-topics').tooltipster({
animation: 'fade',
theme: 'tooltipster-shadow',
trigger: 'hover',
viewportAware: true,
contentAsHTML: true,
multiple: true,
content: '<div>' +
'<p><b>Team Experts</b></p>' +
'<p>'+ topic['experts_internal'] + '</p>' +
'<p><b>External Experts</b></p>' +
'<p>'+ topic['experts_external'] + '</p>' +
'</div>'
});
}
I was expecting the tooltip to replace the data dynamically every time I hover a different element that has the tooltip, but right now without 'multiple' option it keeps showing the same data for each element, and with 'multiple' option it just generates a new tooltip everytime without removing the last so they end up stacking.

Preppend a new child div ahead of previous child div's jquery

I am trying to a do a simple media posting project. When new records are added to the database I use ajax to add a new child div to a parent div based on the info in the record. I have it working except for the order that children are added in. Doing a prepend does not place the new div as the first child of the parent div, it puts it as the last child of the specified parent. That's no good when I want new posts displayed on top. Here is the code for the file I'm working on. How do I prepend above previously added children?
$(document).ready(function (){
setInterval(function(){
$.ajax({
type: 'GET',
url: 'JSONFile.php',
data: { get_param: 'value' },
dataType: 'json',
success: function(retrieved){
//$("#MainContent").empty();
$.each(retrieved, function(index, i){
$('#MainContent').append('<br><div class="Post"><h2>' + i.UserName + '</h2><br><p>' + i.Content + '</p></div>');
});
}
});
},3000);
});
Instead of using .append, you can use .prepend, which was made for exactly this purpose:
Insert content, specified by the parameter, to the beginning of each element in the set of matched elements.
So, you can use the code:
$.each(retrieved, function(index, i){
$('#MainContent').prepend('<br><div class="Post"><h2>' + i.UserName + '</h2><br><p>' + i.Content + '</p></div>');
});

Update/Refresh Listbox based on Dropdown selection with trigger("chosen:updated")

I have a Listbox that I need refreshed after a user selects an option in DropdownList.
Image is self explanatory. If one selects Department -> load list of departmetns in Listbox, if one selects Vat Rate refresh/load list of vat rates into the listbox below. (Default department list is loaded on page load). I am currently attempting this with trigger("chosen:updated") and having no luck refreshing listbox. Here is my code for that functionality.
$(function () {
$("#SelectFilter").change(function () {
if (document.getElementById('SelectFilter').value == 1) //dropdownlist
{
//empty listbox
$('#SelectItems').empty();
//append new list to listbox
$.each(data.Departments, function (index, element) {
$('#SelectItems').append('<option value="' + element.Value + '">'
+ element.Text + '</option>');
});
//refresh
$('#SelectItems').trigger("chosen:updated");
}
if (document.getElementById('SelectFilter').value == 2)
{
$('#SelectItems').empty();
$.each(data.VatRates, function (index, element) {
$('#SelectItems').append('<option value="' + element.Value + '">'
+ element.Text + '</option>');
});
$('#SelectItems').trigger("chosen:updated");
}
});
});
Recognising the selected value from the dropdownlist isnt an issue, that works fine. Listbox is currently not getting updated/refresh with new selection. And I cannot figure out were I am going wrong with this.
Try to put all your code for creating the list into a function, and then bind an event on chosing one of the selected items to call this function which generates a new list instead of using .trigger(). If you provide the HTML part as well, I'll post example code soon.
It's not clear to me if you have a problem with recognizing the selected value, or with populating the secondary select tag, or with the initial loading of the data. So I am providing an example of the three steps.
First, to detect the selected value, you need to provide a .change() handler and extract the selected value with .val(). Something similar to this:
$("#SelectFilter").change( function() {
var v = $(this).val();
if (v=="value1") {
} else if (v=="value2") {
} else {
}
});
then each of the changes detected has to refresh the contents of the secondary select tag, something as simple as this...
$("#SelectItems").empty();
['first item','second item','troisième'].forEach( (v,i) =>
$("#SelectItems").append($("<option>").val("item"+i).text(v))
);
}
And finally triggering the initial load should be as simple as triggering a change event
$("#SelectFilter").change();
I have put all the steps together in this fiddle https://jsfiddle.net/mud9u8yL/6/

jquery what the best way to reset every positioning to default?

I have a few thumbnails upon clicked, it will display all the works of the user, for example user 1 have 1 work, user 2 have 6 works. By right i will be showing the div accordingly to how many works the user have. If i click on user 1, it show 1 work, i exit and click on user 2, instead of 6 works it show 1 only, because the function takes on what was set on user1, as i didn't reset.. So i wonder if there is a best practices for resetting the show/hide div back to default upon exit, the only solution i know of now is calling the .show each time the function activates, but doesn't seem to be a good way to do things. Please advise
Example
$(function() {
$(".img_thumb_holder").on('click', function() {
var index = $(this).index(); // get current index of clicked thumbnail, so i can call out the related name from captionArray via same index
// what i did to solve the reseting, forcing it to show out each time the function runs
$(".portfolio_thumbImg_holder").show();
$.ajax({
type: "POST",
dataType: "json",
data: ({id: idArray[index]}), // pass the name of clicked holder into php to query
url: "CMS/PHP/retrieveAuthorWorks.php",
success: function(data) {
console.log("Array consist of " + data)
$('.portfolio_thumbImg_holder img').removeAttr("src");
linksArray=[];
titleArray=[];
descArray=[];
$(".full_image_desc .title").html(data[0].title);
$(".full_image_desc .info").html(data[0].desc);
$('.portfolio_thumbImg_holder img').each(function(index, element) {
if (data[index]) {
linksArray.push("http://localhost/testdatabase/cms/" + data[index].links);
$(element).attr("src", linksArray[index]);
titleArray.push(data[index].title);
$(element).attr("title", titleArray[index]);
descArray.push(data[index].desc);
$(element).attr("desc", descArray[index]);
}
});
// check how many divs without the image data, and hide it
$(".portfolio_thumbImg_holder img:not([src])").parent().hide();
}
});
});
});

Jquery find+length/size returns 0

I have some divs created dynamically this way:
//here goes some loop, and everything works fine
$("#result_main_search").append('<div class="singleresult_main_search">
<a href="http://somesite.com/" class="linktosight">'
+ SightsList[i]+ '</a> – ' +
'<img src="/images/balloon.gif" rel="'+ i
+'" class="balloon_img_main_search" /></div>');
After that loop, I try to set href attribute for each link:
$('.singleresult_main_search').each(function() {
$.get("_ajax_get_sight_link.php", {'id':$("img", this).attr('rel')},
function(data) {
alert($(this).find('.linktosight').length);
$(this).find('a').attr('href', data);
alert(data);
});
})
_ajax_get_sight_data.php accepts id, returns link ( alert(data) works fine) .
But alert which tells how much .linktosight elements are in current div always gives 0 (by saying always I mean everytime it finds one of my generated divs). I've tried .size(), $(this).find('a') with the same result. So, how am I to set it to work?
this inside the callback will point to the jqXHR-object and not to the looped elements.
You may create a closure:
$('.singleresult_main_search').each(function() {
var $this=$(this);
//.....
});
..and use it inside the callback:
function(data) {
alert($this.find('.linktosight').length);
});
$.proxy() may also be an option like suggested by Jack Franklin

Categories

Resources