How to make div in loop clickable - javascript

I have the following function on a .JS file (that I later call on an HTML file):
function writeDiv(){
x = 1
myArray.forEach(item => {
htmlText += '<div class="divsArray">';
htmlText += '<h5> Value of X: </h5>' + x;
htmlText += '</div>';
x++;
});
$('body').append(htmlText);
}
This writes me one div, with the said value of X, per entry on my array (in this case 14). What I want to do is, everytime I click on a div it shows me, through a window alert, the value of X that has been assigned to it. I tried some things but I couldn't get it to work, thanks for the help in advance!

function writeDiv() {
var temp = [100,150,200,300,400,500];
var innerHtml = "";
temp.forEach((item, index)=> {
innerHtml += `<div class="divsArray">`;
innerHtml += '<h5> Value of X: </h5><span>' + item +'</span>';
innerHtml += '</div>';
});
document.getElementsByTagName('body')[0].innerHTML = innerHtml;
}
writeDiv();
$(function() {
$('.divsArray').click(function() {
let addMoreRoomClone = $(this).find('span').html();
alert(addMoreRoomClone);
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

As you're seem to use jQuery ($), I would recommend to register a live event handler.
$(document)
.on('click', '.divsArray', (event)=>{
console.log(event);
console.log(event.currentTarget.getAttribute('id'));
// do further stuff here
});

I don't know is it what you what, but here is it.
If you use some variable instead of index, it won't work, cuz when function of setTimeout works, the value of x will be same for every iteration. If you have some other questions type.
function writeDiv() {
const myArray = [15,5,5];
let htmlText = "";
myArray.forEach((item, index)=> {
htmlText += `<div id="${index}" class="divsArray">`;
htmlText += '<h5> Value of X: </h5>' + x;
htmlText += '</div>';
setTimeout(()=>{
document
.getElementById(index)
.addEventListener("click",()=>{
alert(index + 1);
})},0)
});
document.getElementsByTagName('body')[0].innerHTML = htmlText;
}
writeDiv();

Related

How to modularize code while creating HTML elements in JavaScript?

I am writing a piece of code to basically call in the top money earner and the top five money earners in a given data set. While writing the code, I realized that there were a couple of spots where I was rewriting the code, basically copying and pasting it. While that works, I wanted to throw the duplicate portion of the code and call it from a function. However, that is not working and I don't exactly know why. Here is the code that is duplicated:
for (let i = 0; i < len; i++) {
html +=
'<li class="top">' +
'<h2>' +
topSalaries[i][8] +
'</h2>' +
'<h3>' +
topSalaries[i][11] +
'</h3>';
}
container.innerHTML = '<ul id = "topSalaries">' + html + '</ul>';
Here is the function I made to be called. However, when I call it, it's not working as expected, where the information shows up on the webpage. I'm using VS Code and am running this on live server so when I save, the webpage automatically updates.
function createHtmlElements(len, html) {
for (i = 0; i < len; i++) {
html +=
'<li class="top">' +
'<h2>' +
topFiveSalaries[i][8] +
'</h2>' +
'<h3>' +
topFiveSalaries[i][11] +
'</h3>' +
'</li>';
}
return html
}
function getTopSalaries(boston, container) {
const people = boston.data;
const len = 5; // only want top five
let topFiveSalaries = sortPeople(people).slice(0,len);
// create the list elements
html = createHtmlElements(len, html);
container.innerHTML = '<ul id = topSalaries">' + html + '</ul>';
}
For one thing topFiveSalaries is going to be undefined in the function createHtmlElements you've created, you must pass it to the function
Ok. So, Thanks Dave for the help. It looks like I also was missing a piece in that I needed to pass the array into the function as well. This is what I wrote and how I called it.
function getTopSalaries(boston, container) {
const people = boston.data;
const len = 5; // only want top five
var topFiveSalaries = sortPeople(people).slice(0,len);
let html = '';
// create the list elements
html = createHtmlElements(len, html, topFiveSalaries);
container.innerHTML = '<ul id = topSalaries">' + html + '</ul>';
}
function getTopEarner(boston, container){
const people = boston.data;
const len = 1;
let highEarner = sortPeople(people).slice(0,len);
var html = '';
// create the list elements
createHtmlElements(len, html, highEarner);
container.innerHTML = '<ul id = topSalaries">' + html + '</ul>';
}
// sort people by income in descending order
function sortPeople(people) {
people.sort(function(a, b) {
return b[11] - a[11];
})
return people
}
function createHtmlElements(len, html, array) {
for (i = 0; i < len; i++) {
html +=
'<li class="top">' +
'<h2>' +
array[i][8] +
'</h2>' +
'<h3>' +
array[i][11] +
'</h3>' +
'</li>';
}
return html
}

How to get the variable value after the $getJSON?

In the code below, I have a function counter which counts element. I use the counter function in order to count the elements that I have in the JSON file. My question is how can I get the value of the counter after the $getJSON, and why when I console log the counter outside of the brackets I keep on getting undefined, why it does not remember the last value, while if I console log the counter inside the brackets I get the number of elements in the JSON file. I want to get the number of elements so afterwards I can use that number in the for loop below.
// global variables
var c = 0;
var a;
var b;
// counter function
function counter() {
return c++;
}
// document ready function
$(document).ready(function () {
$.getJSON("https://graph.facebook.com/v3.2/...", function (data) {
var items = [];
$.each(data.data, function (i, obj) {
//$('#target').append($('<div/>', { id: 'dummy' + i }))
var text = '<p class="review_text">' + obj.review_text + '</p>'
var date = '<p class="date">' + obj.created_time + '</p>'
a = counter();
$("#carousel").find("[data-index='" + i + "']").append(text, date)
console.log(a) //here I get the number of elements inside the JSON file
});
});
console.log(a) //but if I put the console log here, I get undefined instead of the number
var wrapper = document.getElementById("carousel");
var myHTML = '';
for (b = 0; b <= a; b++) { //here I want to use what the function returns, so if I have 10 elements in the JSON file I can create 10 div elements in the HTML, it works only if I put number instead of 'a' but I want to use 'a' so I do not have to count the elements as well, the elements will increase.
myHTML += '<div id="review" data-index=' + (b) + '></div>';
}
wrapper.innerHTML = myHTML
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Move the code inside the ajax call so that it executes AFTER the data is returned/processed:
$(document).ready(function () {
$.getJSON("https://graph.facebook.com/v3.2/...", function (data) {
var items = [];
$.each(data.data, function (i, obj) {
//$('#target').append($('<div/>', { id: 'dummy' + i }))
var text = '<p class="review_text">' + obj.review_text + '</p>'
var date = '<p class="date">' + obj.created_time + '</p>'
a = counter();
$("#carousel").find("[data-index='" + i + "']").append(text, date)
console.log(a) //here I get the number of elements inside the JSON file
});
console.log(a) //but if I put the console log here, I get undefined instead of the number
var wrapper = document.getElementById("carousel");
var myHTML = '';
for (b = 0; b <= a; b++) { //here I want to use what the function returns, so if I have 10 elements in the JSON file I can create 10 div elements in the HTML, it works only if I put number instead of 'a' but I want to use 'a' so I do not have to count the elements as well, the elements will increase.
myHTML += '<div id="review" data-index=' + (b) + '></div>';
}
wrapper.innerHTML = myHTML;
});
});

Why doesn't my simple routine to avoid generating two random numbers in a row work?

I'm doing the random quote generator Free Code Camp challenge, but don't want to have the same quote twice in a row. I came to the exact same conclusion as the person here did: https://codereview.stackexchange.com/questions/62018/prevent-repetitive-random-numbers
However, he says his works but mine still does not. My pen can be found here: http://codepen.io/thomasdean/pen/qZGQxK
And the code is:
$(document).ready(function() {
$("#getQuote").on("click", function() {
   $.getJSON("http://codepen.io/thomasdean/pen/Yqmgyx.js", function(json) {
var html = "";
var lastQuote = "";
var whichQuoteToChoose = "";
while (whichQuoteToChoose === lastQuote) {
whichQuoteToChoose = Math.floor(Math.random() * 12); // returns a number between 0 and 11
}
lastQuote = whichQuoteToChoose;
// this converts raw data into html
json = json.filter(function(val) {
return (val.id == whichQuoteToChoose);
});
json.forEach(function(val) {
html += "<div class = 'quote'>"
html += "<h2>\"" + val.Quotation + "\"</h2><h2>" + val.Quotee + "</h2>"
html += "</div>"
});
     $(".quote").html(html);
   });
});
});
With the while loop and the assignment immediately after it being what should, in theory, solve the problem.
Thanks for any and all help.
Just dont rewrite lastQuote and whichQuoteToChoose on each click event. so i moved those variables out of click event :)
$(document).ready(function() {
var lastQuote = "";
var whichQuoteToChoose = "";
$("#getQuote").on("click", function() {
   $.getJSON("http://codepen.io/thomasdean/pen/Yqmgyx.js", function(json) {
var html = "";
//alert(lastQuote)
while (whichQuoteToChoose === lastQuote) {
whichQuoteToChoose = Math.floor(Math.random() * 12); // returns a number between 0 and 11
}
lastQuote = whichQuoteToChoose;
// this converts raw data into html
json = json.filter(function(val) {
return (val.id == whichQuoteToChoose);
});
json.forEach(function(val) {
html += "<div class = 'quote'>"
html += "<h2>\"" + val.Quotation + "\"</h2><h2>" + val.Quotee + "</h2>"
html += "</div>"
});
     $(".quote").html(html);
   });
});
});

How to insert html as text using .html() in javascript?

In my javascript app, I insert a user message using the code:
var displayMessages = function(response, onBottom) {
var user = GLOBAL_DATA.user;
var acc = '';
for(var i=0; i<response.length; i+=1) {
var obj = response[i];
var acc_temp = "";
acc_temp += '<div class="message ' + (obj['user_id']==user['id'] ? 'message-right' : 'message-left') + '">';
acc_temp += '<div>' + Autolinker.link($(obj['message']).text()) + '</div>';
if (obj['user_id']!=user['id']) {
acc_temp += '<div class="message-details">' + obj['first_name'] + ' ' + obj['last_name'] + '</div>';
}
acc_temp += '<div class="message-details">' + obj['date_sent'] + '</div>';
acc_temp += '</div>';
acc = acc_temp + acc;
}
addMessage(acc, onBottom);
};
The problem is that, if obj['message'] = "<script>alert(1);</script>"; then what gets printed on the screen is "alert(1);" because I use .text(). How can I insert the string with the script tags, so that it looks exactly like that on the page? I don't want it to get executed.
Thanks
I use these helper functions.
function htmlEncode(value){
return $('<div/>').text(value).html();
}
function htmlDecode(value){
return $('<div/>').html(value).text();
}
I would escape the other variables as well if you are not sure that they will not have any executable code.
I solved it using this:
function escapeHTML(str) {
return $("<p></p>").text(str).html();
}
I think you'll need to wrap your object in a dummy tag, then you can retrieve the full html from that.
You'll have issues though, because you're using a script tag, which will be evaluated.
obj['message'] = "<script>alert(1);</script>";
>
$(obj['message']).text();
> "alert(1);"
$(obj['message']).html();
> "alert(1);"
$(obj['message']).wrapAll('<div>').text();
// alerts with 1
> "alert(1);"
Not using a script tag will work.
obj['message'] = "<span>alert(1);</span>";
>
$(obj['message']).wrapAll('<div>').text();
> "<span>alert(1);</span>"

Javascript ID groupings

I'm looking to create an exception which creates 2 groupds based on their .php ID numbers.
I currently have a form that fills a table of images, and want to split them into groups using javascript.
currently the script looks like this:
var currentResults;
function init() {
getProducts();}
function getProducts() {
$.ajax({
url:"php/products.php",
dataType: "json",
data: { public: true },
success:function(result){
processResults(result);
}
});}
function processResults(results) {
currentResults = null;
if (!results && !results.products)
return;
currentResults = results.products;
for (var i = 0; i < results.products.length; i++) {
processResult(results.products[i]);}
$(".galleryitem").click(handleThumbnailClick);}
function processResult(result) {
var newDiv = '<div id="galleryitem' + result.id + '" class="galleryitem">';
newDiv += '<div class="imageHover" style="background: ' + result.color + '"> </div>';
newDiv += '<img class="galleryImage" src="' + encodeImagePath(result.thumbnail) + '" />';
if (result.artist)
newDiv += '<div class="imageArtist">' + result.artist + '</div>';
newDiv += '</div>';
$('#gallery').append(newDiv);}
function handleThumbnailClick(e) {
if (!e || !e.currentTarget || !e.currentTarget.id)
return;
var id = e.currentTarget.id.substring(11);
window.location = 'product.php?id=' + id;}
function encodeImagePath(path) {
return path.replace(/#/g, '%23');}
I am looking for some simple advice on how to split this into multiple div's based on the product's ID number to do sections of 6 images at a time with different header text.
please advise!! thanks much!
Not sure if I got your idea right but something like this should solve your problem (in case you have a "parent" property in the products JSON you're getting from the server):
function processResult(result) {
if (typeof(result.parent) !== 'undefined') { // see if the element has a parent
var newDiv = 'markup goes here'; // if some of the markup would be reused you can create a new function for this
$('#galleryitem' + result.parent).append(newDiv); // just make sure the parent is already there
} else {
var newDiv = '<div id="galleryitem' + result.id + '" class="galleryitem">'; // default behavior that you alreay had
// code skipped for brevity
$('#gallery').append(newDiv);
}
}
P.S. You should work on your code formatting -- it can be much easier to read if formatted well.

Categories

Resources