Getting jquery to view elements created on page load [duplicate] - javascript

This question already has answers here:
Jquery each(): variable in callback always has last value?
(3 answers)
Closed 1 year ago.
I have a block of code that reads json data, then constructs 50 divs with contest related information in it. I am working with Gleam.io so people can enter the contest. Each contest is it's own day and has a unique URL.
Currently I have it rendering all my boxes fine, putting in the correct data for each div. What I can't figure out for the life of me is when I click on a box, for it to find and pull the correct URL to put into the modal.
When I do it, the onclick will always just pull the last box's information and display that.
<script>
// FETCHING DATA FROM JSON FILE
$.getJSON("https://cdn.shopify.com/s/files/1/2660/5202/files/data.json?v=1624391152",
function (data) {
var modal = '';
var prizeState = '';
var prizeURL = '';
var card = '';
// ITERATING THROUGH OBJECTS
var cardwrapper = document.getElementById('cardWrapper');
$.each(data, function (key, value) {
var prize = '';
var prizeState = value.prizeState;
prizeURL = value.entryForm;
// DATA FROM JSON OBJECT
var card = document.createElement('div');
card.setAttribute('data-modal', value.prizeDay);
card.classList.add('card');
prize += '<div class="entry-form" onclick="modalPop(' + value.entryForm + ')"><span class="entry-url">' + value.entryForm + '</span></div>' +
' <div class=" ' + value.prizeState + '">' +
'<div class="prizeDay">Day ' + value.prizeDay + '</div>' +
/* '<div class="prizeDate"> ' + value.prizeDate + '</div>' + */
'<div class="prizePhoto"> <img src="' + value.prizePhoto + '" /></div>' +
'<div class="prizeTitle"> ' + value.prizeTitle + '</div>' +
'<div class="prizeWinner">' + value.prizeWinner + ' ' + value.prizeCity + '</div>' +
'<span class="button btn btn-default prizeEnterButton">Enter Contest</span>'
prize += '</div>';
card.innerHTML = prize;
card.addEventListener('click', function(){
modalPop(prizeURL);
console.log(prizeURL, ' from onclick');
});
cardwrapper.appendChild(card);
console.log(prizeURL);
});
});
// Get the modal
var modal = document.getElementById("myModal");
// Get the button that opens the modal
var btn = document.getElementById("myBtn");
function modalPop(prizeURL) {
console.log(prizeURL);
var popupContent = '<h4>' + prizeURL + '</h4>' +
'<span id="modalClose" class="close">×</span>' +
'<span id="widget-code">' +
'<iframe src="' + prizeURL + '" frameBorder="0" allowfullscreen></iframe>' +
'</span>'
$('#myModal #modalReplace').empty().html(popupContent);
$('#myModal').fadeIn(200).addClass('modal-active');
}
// When the user clicks anywhere outside of the modal, close it
window.onclick = function(event) {
if (event.target == modal) {
$('#myModal').fadeOut(200);
}
}
</script>

The problem with modalPop(prizeURL) is that, when you click the card, this click function should trigger correctly, but it has no idea what prizeURL is. This variable is defined in the function (key, value) function, not in the onclick function. I guess it just logs undefined.
It's just a blind guess, but a neat trick could be to attach each prizeURL to each card, like this :
card.prizeURL = prizeURL;
card.addEventListener('click', function(){
modalPop(this.prizeURL);
console.log(this.prizeURL, ' from onclick');
});

Store the prizeURL as an attribute of the card
...
prizeURL = value.entryForm;
// DATA FROM JSON OBJECT
var card = document.createElement('div');
card.setAttribute('data-prizeurl', prizeURL);
card.setAttribute('data-modal', value.prizeDay);
...
Move your click function out of the loop and delegate it
$(document).on('click', '[data-modal]', function(){
modalPop($(this).data('prizeurl'));
console.log(prizeURL, ' from onclick');
});
// When the user clicks anywhere outside of the modal, close it
window.onclick = function(event) {
if (event.target == modal) {
$('#myModal').fadeOut(200);
}
}

The issue is that
card.addEventListener('click', function(){
modalPop(prizeURL);
});
needs a closure or a scope change (use let for example)
But this can all be avoided if you delegate and store the URL in a data attribute
const modalPop = prizeURL => {
console.log(prizeURL);
$('#modalReplace').html(`<h4>${prizeURL}</h4>
<span id="modalClose" class="close">×</span>
<span id="widget-code">' +
<iframe src="' + prizeURL + '" frameBorder="0" allowfullscreen></iframe>' +
</span>`)
$('#myModal').fadeIn(200).addClass('modal-active');
}
// When the user clicks anywhere outside of the modal, close it
$(window).on("click", event => {
if ($(event.target).closest("#myModal").length===0 && !$(event.target).hasClass('close')) {
$("#myModal").fadeOut(200);
}
})
$.getJSON("https://cdn.shopify.com/s/files/1/2660/5202/files/data.json?v=1624391152",
function(data) {
$('#cardWrapper').html(
data.map(item => `<div class="card" data-modal="${item.prizeDay}" data-url="${item.entryForm}">
<div class="entry-form" ><span class="entry-url">${item.entryForm}</span></div>
<div class="${item.prizeState}">
<div class="prizeDay">Day ${item.prizeDay}</div>
<div class="prizePhoto"> <img src="${item.prizePhoto}" /></div>
<div class="prizeTitle">${item.prizeTitle}</div>
<div class="prizeWinner">${item.prizeWinner} ${item.prizeCity}</div>
<span class="button btn btn-default prizeEnterButton">Enter Contest</span>
</div>
</div>`))
.on("click", ".prizeEnterButton", function(e) { // clicking enter contest
modalPop($(this).data("url"))
e.stopPropagation();
})
})
#myModal { display: none; position:absolute; top:200px; background-color:white}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="myModal"><h1>MODAL</h1><div id="modalReplace"></div></div>
<div id="cardWrapper"></div>

Related

How to get parent div of clicked dynamically bound anchor tag?

How to get parent div of clicked dynamically bound anchor tag?
I am binding multiple images with multiple delete anchor tags on file upload button click. like below
$('#images').on('change', function(e) {
var files = e.target.files;
$.each(files, function(i, file) {
fileCollection.push(file);
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function(e) {
var templated = '<div id="imgPreView' + i + '" class="col-md-2"> ' +
'<img class="img-responsive" id="targetImg' + i + '" src="' + e.target.result + '"/> ' +
'<div class="caption">' +
'<i class="fa fa-trash-o"></i>' +
'<span id="description"></span>' +
'</div>' +
'</div>';
$('#images-to-upload').append(templated);
but when I want to delete image in ClearPreview() function its deleting correct indexed div and image but when I supposed to upload some other images and trying to delete some indexed img but its deleting some other img...
function ClearPreview(i) {
$('#images' + i).val('');
$('#imgPreView' + i).remove();
}
so how to delete current anchor tag's clicked image and div?
$(this).parent(); statement to your ClearPreview() function will give you parent div for clicked element having class "caption" dynamically

jQuery add dynamic content from one element to another element

I'm adding livechat to a website, the problem I have is that it adds dynamic onclick to the page which gets blocked by my CSP policy.
I have managed to work around this by removing the dynamic code and adding my own.
What I cannot figure out is how to grab the link id which can either be
id="online-icon" or id="offline-icon" and also the span class lhc-text-status text
Client-side is not my strong point, so apologies if the code below is a mess, but can someone help with adding the above id into my code.
$(document).ready(function () {
$('body').on('click', '.status-icon', function () {
$(this).closest('#lhc_status_container').remove();
$('<div id="lhc_status_container">' +
'<a id="NEED TO ADD STATUS HERE" class="status-icon" href="#">' +
'<span class="lhc-text-status">AND HERE</span>' +
'</a>' +
'</div>').appendTo("#liveChatCase");
$("#online-icon").click(function () {
return window.lh_inst.lh_openchatWindow();
});
});
});
Below is an example of how the dynamic code is added to the page.
<div id="lhc_status_container">
<a id="online-icon" class="status-icon" href="#" onclick="return lh_inst.lh_openchatWindow()">
<span class="lhc-text-status">Live help is online...</span></a>
</div>
UPDATE I now have managed to get the value of id="NEED TO ADD STATUS HERE" but still working on lhc-text-status
Solved problem, the code is below and if anyone can improve on it it would be appreciated as I need to click the live chat div twice before it opens
$(document).ready(function () {
$('body').on('click', '.status-icon', function () {
var statusId = $(this).attr('id');
var textStatus = $(".lhc-text-status").text();
$(this).closest('#lhc_status_container').remove();
$('<div id="lhc_status_container">' +
'<a id="'+ statusId +'" class="status-icon" href="#">' +
'<span class="lhc-text-status">' + textStatus +'</span>' +
'</a>' +
'</div>').appendTo("#liveChatCase");
$(".status-icon").click(function () {
return window.lh_inst.lh_openchatWindow();
});
});
});
OK fixed the double click issue with amended code below
$(document).ready(function () {
$('body').on('click', '.status-icon', function () {
var statusId = $(this).attr('id');
var textStatus = $(".lhc-text-status").text();
// $(this).closest('#lhc_status_container').remove();
$('<div id="lhc_status_container">' +
'<a id="'+ statusId +'" class="status-icon" href="#">' +
'<span class="lhc-text-status">' + textStatus +'</span>' +
'</a>' +
'</div>').appendTo("body");
return window.lh_inst.lh_openchatWindow();
// $(".status-icon").click(function () {
// return window.lh_inst.lh_openchatWindow();
//});
});
});

Uncheck a checkbox on click of button

I have a box with multiple checkboxes. I am selecting checkboxes and with that select I am generating a <span> Value (x) </span> on a different div. Now i want to uncheck the checkbox on click of (x) of that particular checkbox.
Example:
On selecting and deselecting the checkboxes the <span> Value (x) </span> is coming and going. but the inverse is not happening.
.reportbox is the class of the tile(checkbox).
#compareSection is the area where buttons are kept.
Code i am using:
<script type="text/javascript">
$('.reportBox').click(function() {
var selected = $('input[type=checkbox]:checked').map(function(_, el) {
selectedCheckbox = el.id;
var element = "<p class='selectedReport'>"+ $(el).val() + "</p>" + "<span onclick='removeReport(this, selectedCheckbox)' class='badge badge-notify close-badge'>x</span>";
return "<span id='elementPack'>" + element + "</span>";
}).get();
$("#compareSection").html(selected);
})
// this code is for removing the URLs
function removeReport(sender, selectedCheckbox) {
document.getElementById(selectedCheckbox).checked = false;
var div = sender.parentNode;
div.parentNode.removeChild(div);
}
</script>
<script>
$(function() {
$('.reportBox').click(function() {
var selected = $('input[type=checkbox]:checked').map(function(_, el) {
selectedCheckbox = el.id;
var element = '<p class="selectedReport">'+ $(el).val() + '</p>' + '<span data-target-box="'+el.id+'" class="badge badge-notify close-badge">x</span>';
return '<span id="elementPack">' + element + '</span>';
}).get();
$("#compareSection").html(selected);
});
$(document).on('click', 'span[data-target-box]', function(e) {
$('#'+$(this).data('target-box')).prop('checked', false);
$(this).remove();
});
});
</script>
On the line
var element = "<p class='selectedReport'>"+ $(el).val() + "</p>" + "<span onclick='removeReport(this, selectedCheckbox)' class='badge badge-notify close-badge'>x</span>";
You are using selectedCheckbox as a string meaning it will look for the variable when you click it, however the variable was never defined outside the first scope. You probably want to change it to the following:
var element = "<p class='selectedReport'>"+ $(el).val() + "</p>" + "<span onclick='removeReport(this, \'"+selectedCheckbox+"\')' class='badge badge-notify close-badge'>x</span>";
So that it calls removeReport(this, 'id_of_element') with the id as a string which can then be used in document.getElementById().

JQuery "Attribute Starts With" Selector Undefined

I have a modal dialog (Bootstrap) that has a list-group with custom list-group-items inside of it (populated by loop using append after adding data from my server).
Inside each list-group-item, I have a Checkbox that will be used to "select" the result. As I populate the items, I hook up the JQuery click event to the respective Checkbox:
// Add to search results
$('#search-results').append(
'<a id="centroid-list-item-' + featureAttrs['ObjectID'] + '" href="\\#"' + 'class="list-group-item" style="outline: 0">' +
'<table style="background: transparent">' +
'<tr>' +
'<td>' +
'<input id="centroid-checkbox-' + featureAttrs['ObjectID'] + '" type="checkbox" value=""> ' +
'</td>' +
'<td>' +
'<h4 class="list-group-item-heading">' +
featureAttrs['UNIQUEID'] +
'</h4>' +
'<p id="centroid-item-text-' + featureAttrs['ObjectID'] + '"' + 'class="list-group-item-text">' +
featureAttrs['NAME'] +
'</p>' +
'</td>' +
'</tr>' +
'</table>' +
'</a>'
);
// When the DOM is ready, add event
$(document).ready(function () {
$('#centroid-checkbox-' + featureAttrs['ObjectID']).click(function (event) {
var objectId = $(this).attr('id').replace(/^\D+/g, '');
console.log(objectId + " was clicked");
if ($(this).is(':checked')) {
// Enable the 'Set Target' button
$('#btn-set-target').removeAttr('disabled');
// Disable all other choices
$('[id^="centroid-checkbox-"]').each(function (event) {
console.log("Picked up values for checkboxes");
if ($(this).attr('id') != ('centroid-checkbox-' + objectId)) {
$(this).attr('disabled', true);
}
});
}
else {
$('#btn-set-target').attr('disabled', 'disabled');
// Enable all text boxes
$('[id^="centroid-checkbox-"]').each(function () {
if (this.attr('id') !== ('centroid-checkbox-' + objectId)) {
this.removeAttr('disabled');
}
});
}
});
});
The problem I am having is that when I call $('[id^="centroid-checkbox-"]') it is returning undefined. However, at the time is gets called, there are about 30 "centroid-checkbox-XXXXX" checkboxes. What am I doing wrong here?
The $ function never returns undefined.
But this in the callback you pass to each is an element, not a jQuery object.
Which means you must use this.id instead of this.attr('id') and $(this).removeAttr('disabled') instead of this.removeAttr('disabled') (and you probably want this.disabled=false or $(this).prop('disabled', false)).
objectId never gets defined because you need to quote enclose the regular expression you're using for replace():
var objectId = $(this).attr('id').replace(/^\D+/g, '');
should be:
var objectId = $(this).attr('id').replace('/^\D+/g', '');
DEMO: http://jsfiddle.net/4fUvn/8/

Using HTML inside jQuery code to pull part of a url and reuse it elsewhere?

The foundation: I have a simple lightbox on my home page (code below). It works exactly as I want it to: when the trigger image is clicked, it grays out the rest of the page and adds HTML to create an iframe for the text-based page that I want to display.
The problem: I need to create a lightbox where the content is dynamically chosen depending on the image that is clicked. The URLs will correspond to each other -- for example, if the user clicks "/media/X.png," he/she will be presented with a lightbox containing the iframe of the page "/X.html."
How can I accomplish this? My first stab at it is below (after the original, static lightbox code). It's cobbled together from various things I've read online and other answers to similar questions on StackOverflow, but I'm super new to jQuery / basically known no Javascript and I suspect I'm misusing variable assignment and the "split" function.
Many thanks.
EDIT: Someone has helped me insert the variable into the HTML (below). However, I think I'm assigning the variables incorrectly (see the beginning of the second block of code). Here's what I'm trying to do with each variable:
1. pre_lightbox_trigger: grab the string "X.png" from the image that the user has clicked.
2. lightbox_trigger: grab "X" only (remove ".png").
3. lightbox_trigger_href: make X into "X.html", and make it a link.
Code:
Original, static lightbox:
$(document).ready(function($) {
$('.lightbox_trigger').click(function(e) {
e.preventDefault();
if ($('#lightbox').length > 0) {
$('#lightbox').show();
}
else {
var lightbox =
'<div id="lightbox">' +
'<div id="content">' +
'<iframe src="why.html" id="lightframe" frameborder="0" seamless>' +
'</iframe>' +
'</div>' +
'<p>Click outside to close</p>' +
'</div>';
$('body').append(lightbox);
}
$(document).on('click', '#lightbox', function() {
$('#lightbox').hide();
});
});
});
My attempt to create a dynamic link:
$(document).ready(function($) {
$('.lightbox_trigger').click(function(e) {
e.preventDefault();
var pre_lightbox_trigger = location.'.lightbox_trigger'.split('/').pop();
var lightbox_trigger = pre_lightbox_trigger.split('.').pop(1);
var lightbox_trigger_href = lightbox_trigger + ".html";
if ($('#lightbox').length > 0) {
$('#lightbox').show();
}
else {
var lightbox =
'<div id="lightbox">' +
'<div id="content">' +
'<iframe src=$lightbox_trigger_href id="lightframe" frameborder="0" seamless>' +
'</iframe>' +
'</div>' +
'<p>Click outside to close</p>' +
'</div>';
$('body').append(lightbox);
}
$(document).on('click', '#lightbox', function() {
$('#lightbox').hide();
});
});
});
EDIT #2: Currently my "static" version of the lightbox is only for "trigger_small.png." However, I want a lightbox to appear when other images are clicked as well (for example, "vio_mass.png"). See below for sample HTML:
<div id="trigger">
<a class="lightbox_trigger" href="media/trigger_small.png">
<img src="media/trigger_small.png">
</a>
</div>
<div class="cat" id="violence_cat">
<div class="cat_grid" id="vio_1">
</div>
<div class="cat_grid" id="vio_2">
<img src="media/vio_mass.png">
</div>
...etc.
Instead of
var lightbox =
'<div id="lightbox">' +
'<div id="content">' +
'<iframe src=$lightbox_trigger_href id="lightframe" frameborder="0" seamless>' +
'</iframe>' +
'</div>' +
'<p>Click outside to close</p>' +
'</div>';
You would do
var lightbox =
'<div id="lightbox">' +
'<div id="content">' +
'<iframe src=' + lightbox_trigger_href + ' id="lightframe" frameborder="0" seamless>' +
'</iframe>' +
'</div>' +
'<p>Click outside to close</p>' +
'</div>';

Categories

Resources