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();
//});
});
});
Related
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>
Hi i m having one page with one textbox named search and one search button. When i'm searching anything for the first time it's showing me the right data but when i'm searching some other things for the next time then the elements which was listed before are also appended below of that new list. Suppose i'm searching state name by k it will give me right list of karnataka, kerala. But if i start to search again by g, it will show me in output as goa,gujrat,karnataka kerala. i tried using refresh option but it still not working. This is my js code
$.each(response.state, function (i, state) {
$('#statelist').append(
'<li>' +
'<a href="#">'
+
+'<b>'+ '<font color="green">'+'<h3>'+ state.Name +'</h3>'+'</font>' +'</b>'+
'</a>' +
'</li>'
);
});
$('li img').width(100);
$('.ui-li-icon li').click(function() {
var index = $(this).index();
text = $(this).text();
// alert('Index is: ' + index + ' and text is ' + text);
});
$("#statelist").listview("refresh");
and this is html
You are using .append() function. It appends whatever you append to the end of the list.
Check this link:
http://api.jquery.com/append/
Try using innerHTML property of the DOM model.
You could add
If(!('#statelist').html() == ""){
$(this).remove();
//execute rest of code that appends state list
}
Then do an else statement and execute your append code without removing()
UPDATE: a better option is to do this-
$.each(response.state, function (i, state) {
$('#statelist').html(
'<li>' +
'<a href="#">'
+
+'<b>'+ '<font color="green">'+'<h3>'+ state.Name +'</h3>'+'</font>' +'</b>'+
'</a>' +
'</li>'
);
});
$('li img').width(100);
$('.ui-li-icon li').click(function() {
var index = $(this).index();
text = $(this).text();
// alert('Index is: ' + index + ' and text is ' + text);
});
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/
I'm stumped with this one, I've been at it hours, trying to get jQuery autocomplete to go to another page on the site when an item is clicked in the suggestions list.
Anyone know how to do this? Here is my code :
$(':input[data-autocomplete]').autocomplete({
source: $(':input[data-autocomplete]').attr("data-autocomplete"),
delay: 0,
select: function (event, item) {
//window.location.replace("http://www.example.com/Profile/Details/1");// Works but totally unacceptable, browser history lost etc..
//alert("Item Clicked"); //Fires Ok
}
}).data("autocomplete")._renderItem = function (ul, item) {
var MyHtml = '<a id="ItemUrl" href="/Profile/Details/' + item.PartyId + '"' + ">" +
"<div class='ac' >" +
"<div class='ac_img_wrap' >" +
'<img src="../../uploads/' + item.imageUrl + '.jpg"' + 'width="40" height="40" />' +
"</div>" +
"<div class='ac_mid' >" +
"<div class='ac_name' >" + item.value + "</div>" +
"<div class='ac_info' >" + item.info + " PartyId :" + item.PartyId + "</div>" +
"</div>" +
"</div>" +
"</a>";
return $("<li></li>").data("item.autocomplete", item).append(MyHtml).appendTo(ul);
};
As you can see I have used custom HTML in the _renderItem event, my custom HTML creates an anchor tag with the id passed in from the source, this looks ok, the link is formed correctly in the browser bottom left corner (I'm using Chrome)
<a href='/Profile/Details/id' >some other divs & stuff</a>
The problem is that when I click the link nothing happens, I have tried using the select event but item is null so can't get item.PartyId to force a manual jump.
How can I get the click event working?
It might late to answer it, but I have done this with the following code:
$(document).ready(function() {
$('#txtSearch').autocomplete({
minLength: 3,
source: "handlers/SearchAutoComplete.ashx?loc=" + $('#hfLocation').val(),
select: function(event, ui) {
doSearch(ui.item.label, ui.item.city);
}
});
});
function doSearch(term, location) {
window.location.href = 'Search.aspx?q=' + term + '&loc=' + location;
}
After a few days of head banging (not moshing kind) I've come up with the following:
$(':input[data-autocomplete]').autocomplete({
source: $(':input[data-autocomplete]').attr("data-autocomplete"),
delay: 0,
select: function (event, ui) {
var q = ui.item.PartyId;
if (q != "") {
$('#hidPID').val(q);
$('#ac_submit').trigger('click');
}
}).data("autocomplete")._renderItem // -->>> the rest of the code same as above
The issue was (event, item) should have been (event, ui) and to get the value of the item you use ui.item.PartyId (in my case PartyId is declared in the source : above)
So on my original form I had two html inputs 1-hidden ID, 2-Submit & as you can see in the select : function above I set the ID & trigger the submit (so now the user just picks an item and off they go to the controller which performs the RedirectToView & NOT this code as it doesn't seem correct to use location in this instance)
I Hope this saves someone some time as the jQuery autocomplete docs dont make it too clear.
I'm working my way through a JQuery Solution and for the most part it works but I"m stumped on seemingly a small detail I know I'm overlooking. Heck, maybe my implementation/approach needs to be reconsidered.
Here's the flow of what works.
1. Click an anchor that adds to a table.
2. Add CSS Class.
3. Disable (Unbind) click on after preappend().
4. From the table of dynamically added record remove table based on ID.
5. delete class that was added in step 2.
6. Bind 'click'
However, although I can bind the click and alert on it. The expected functionality does not allow me to step through the above process again.
The code in question:
HTML SAMPLE:
link that starts the process:
table that holds new records after click of link
<table id="carrier-table"><tbody></tbody></table>
JQUERY and Custom Javascript Function
<script type="text/javascript" id="removeCarrier">
function removeCarrierFromList(obj) {
var i = obj.parentNode.parentNode.rowIndex;
document.getElementById('carrier-table').deleteRow(i);
$('a#' + obj.id).removeClass('delete-carrier-company');
//alert(obj.id); //.hasClass('add-carrier-company').tostring() ); //
$('a#' + obj.id).bind('click', function() {
//alert('User clicked on ' + obj.id);
});
}
</script>
<script type="text/javascript" id="carrierListJS">
$(function() {
// Link
// This adds a carrier to a list
$('.add-carrier-company').click(
function() {
var target = $(this).attr("id");
alert(target);
$("#carrier-table").prepend("<tr id='carrierRow_" + target + "'>" +
"<td><a href='#' id='" + target + "' class='delete' onclick='removeCarrierFromList(this)'> </a></td>" +
"<td class='carrier-list-text'>" + target + " " + $("#name_" + target).val() + "</td>" +
"</tr>");
return false;
});
$('.add-carrier-company').click(
function() { $(this).addClass('delete-carrier-company').unbind('click'); }
);
});
</script>
There were a few issues I noticed with the code. For one thing, as #RussellUresti mentioned, you create two tags with the same ID. For another thing, if you're using ID's in a selector in jQuery, don't include the tag name, just use the id (ie. use $('#id') not $('a#id')) it will be faster (it won't break your code though).
I have created a jsfiddle to answer your question (though I rewrote most of it). :) I think it's what you're looking for.
Here's the code:
Test HTML
aa
bb
cc
10002
10003
<table id="carrier-table" style="border:1px solid #000"><tbody></tbody></table>
JavaScript
function addCarrier() {
var target = $(this).attr("id");
$("#carrier-table").prepend("<tr id='carrierRow_" + target + "'>" + "<td><a href='#' id='a" + target + "' class='delete'> </a></td>" + "<td class='carrier-list-text'>" + target + " " + $("#name_" + target).val() + "</td>" + "</tr>");
$('#a' + target).click(removeCarrierFromList);
$(this).addClass('delete-carrier-company').unbind('click');
return false;
}
function removeCarrierFromList() {
var $this = $(this);
var id = $this.attr('id').replace("a","");
$this.closest('tr').remove();
$('#' + id).removeClass('delete-carrier-company').click(addCarrier);
}
$(function() {
// Link
// This adds a carrier to a list
$('.add-carrier-company').click(addCarrier);
});