I am working on API and this HTML code created dynamically
<li class="d-flex align-item-center movieId">
<a class=" d-flex w-100" data-mov="${res[i].id}">
<img src="https://image.tmdb.org/t/p/w500${res[i].poster_path}" class="img-fluid himg"
alt="${res[i].title}" style="width:60px; height:70px">
<p class=" p-3"> ${res[i].title}</p>
</a>
</li>
I want when I click on the <a> tag I get the data-mov attribute value... I did solve it but when I click on any elements inside the <a> like <img> and <p> the data-mov value did not get. However, these elements inside it.
this is what I am trying to do
$(".srearchResults ul").on("click", "a", function (event) {
let id = event.target.getAttribute("data-mov");
console.log(id);
//$(this).find("a").data("mov");
//$(this).find("a").attr("data-mov");
});
The two lines commented I used and get undefined. When clicking on <p> or <img> i get null what would be the solution for that?
Vanilla JavaScript solution:
const ulElement = document.querySelector("ul");
ulElement.addEventListener("click", function (e) {
let element = e.target;
let liElement;
while (element && element.nodename !== "UL") {
if (element.nodeName === "LI") {
liElement = element;
}
element = element.parentElement;
}
const anchor = liElement.querySelector('a');
console.log(anchor.dataset.mov);
});
<ul>
<li>
<a data-mov="data-mov-1">
<img src="https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png" width="100">
<p>1</p>
</a>
</li>
<li>
<a data-mov="data-mov-2">
<img src="https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png" width="100">
<p>2</p>
</a>
</li>
</ul>
When using event.target it'll select the element you click on not the a and while img and p doesn't have data-mov it will output null or undefined .. so you need to use let id = $(this).data("mov"); instead .. no need to use .find('a') because $(this) will select the a for you and no nested a inside the clicked a
This is how your code work [data-mov added to the img] so when you click on the img you'll get the data-mov of the img
let res = [
{
'id' : 1,
'poster_path' : 234,
'title' : 'anything'
},
]
$('ul').append(`<li class="d-flex align-item-center movieId">
<a class=" d-flex w-100" data-mov="${res[0].id}">
<img data-mov="image data mov" src="https://image.tmdb.org/t/p/w500${res[0].poster_path}" class="img-fluid himg"
alt="${res[0].title}" style="width:60px; height:70px">
<p class=" p-3"> ${res[0].title}</p>
</a>
</li>`);
$("ul").on("click", "a", function (event) {
let id = event.target.getAttribute("data-mov");
console.log(id);
//$(this).find("a").attr("data-mov");
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul></ul>
And this is how it should work
let res = [
{
'id' : 1,
'poster_path' : 234,
'title' : 'anything'
},
]
$('ul').append(`<li class="d-flex align-item-center movieId">
<a class=" d-flex w-100" data-mov="${res[0].id}">
<img data-mov="image data mov" src="https://image.tmdb.org/t/p/w500${res[0].poster_path}" class="img-fluid himg"
alt="${res[0].title}" style="width:60px; height:70px">
<p class=" p-3"> ${res[0].title}</p>
</a>
</li>`);
$("ul").on("click", "a", function (event) {
let id = $(this).data('mov');
console.log(id);
//$(this).find("a").attr("data-mov");
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul></ul>
Related
I have two html list. One containing text and the other containing images. They all have data attributes. What I want to do is when I click on the text the image will change based the text clicked.
html
<div class="toggle">
<div class="menu">
<ul>
<li class="menu-list t1" data-id="0">R1</li>
<li class="menu-list t2" data-id="1">R2</li>
<li class="menu-list" data-id="2">Shop</li>
<li class="menu-list" data-id="3">Fleet</li>
</ul>
</div>
images
<div class="menu-pictures">
<img class="default" src="default.jpg" alt="">
<img data-id="0" src="r1.jpg" class="p1" alt="">
<img data-id="1" class="p1" src="r1.jpg" alt="">
<img data-id="2" src="shop.jpg" alt="">
<img data-id="3" src="fleet.jpg" alt="">
</div>
</div>
The default class is the default images that shows when the page loads... so the idea is to change the image when the text is being clicked on.
javascript
const menuList = document.querySelectorAll(".menu-list");
let convertList = [...menuList];
const def = document.querySelectorAll(".menu-pictures img");
let convertPictures = [...def];
const images = [
{ name: "0", img: "r1.jpg" },
{ name: "1", img: "r1.jpg" },
{ name: "2", img: "shop.jpg" },
{ name: "3", img: "fleet.jpg" },
];
menuList.forEach((list, e) => {
e.target;
let t = list.getAttribute("data-id");
list.addEventListener("click", function () {
if (images.find((img) => img.name === t)) {
console.log(e)
def[t].src = images[t].img;
console.log("hey");
} else console.log("wrong");
});
});
The idea here is for it to loop through text and get the data attribute and then check if the attribute matches the index of the images, then it will get the scr of the image and replace it with the default image src. But I'm stuck with the implementation
I have 32 items in my array, all of them have these properties: id, word, image. User has to guess what's in all the images and write their guess in inputs (so 32 inputs in total). I need to check if the input equals my arrays property "word" and then when clicked a button (type submit, all my pic's and inputs are in a form) display some text for example "Oops! Guess again" if wrong and "Yay! You got it correctly" if right. The text should appear below every input. I displayed all the pictures and inputs with a forEach, and i'm using bulma framework for this page:
const wordBox = info.forEach((words) => {
mainColumns.innerHTML += `
<div class="column is-one-quarter">
<div class="card">
<div class="card-image">
<figure class="image is-4by3">
<img src=${words.image} alt="Placeholder image">
</figure>
</div>
<div class="card-content">
<div class="media">
<div class="media-content">
<input class="input" id="text" type="text" placeholder="Įvesk žodį">
</div>
</div>
<div class="content">
Content
</div>
</div>
</div>
</div>`;
});
Any ideas?
This is how it should look like (the result should appear in content place)
Something like this
I use change instead of a button click
const info = [
{word:"flower",image:"flower.gif"},
{word:"boat",image:"boat.gif"}
];
const mainColumns = document.getElementById("mainColumns");
mainColumns.innerHTML = info.map(({image,word}) =>
`<div class="column is-one-quarter">
<div class="card">
<div class="card-image">
<figure class="image is-4by3">
<img src=${image} alt="Placeholder image">
</figure>
</div>
<div class="card-content">
<div class="media">
<div class="media-content">
<input class="input" data-word="${word}" type="text" placeholder="Įvesk žodį">
<span class="correct hide">Yay</span>
<span class="wrong hide">NOO</span>
</div>
</div>
<div class="content">
Content
</div>
</div>
</div>
</div>`).join("");
mainColumns.addEventListener("change",function(e) {
const correct = [...mainColumns.querySelectorAll("[data-word]")].map(input => {
if (input.value) {
const correct = input.value === input.dataset.word;
parent = input.closest("div");
parent.querySelector(".correct").classList.toggle("hide",!correct)
parent.querySelector(".wrong").classList.toggle("hide",correct);
return correct ? 1 : 0;
}
else return 0;
}).reduce((a,b)=>a+b);
document.getElementById("correct").innerText = correct;
})
#mainColumns { display:flex; }
.hide { display: none; }
<div id="mainColumns"></div>
Correct: <span id="correct"></span>
What you can do is to filter the word array with word from the input value. Then check if the length is equal zero, No match, if the length is greater than one, then there is a match.
const status = wordBox.filter(item => item.word === inputWord)
I'd move towards keeping the objects and the HTML separate, binding the HTML to the object and vice versa. This means including a couple more properties to your array elements.
let info = [{
image: 'flower.png',
word: 'flower',
content: '',
guess: ''
}];
function bindWords() {
info.forEach((words) => {
mainColumns.innerHTML = `
<div class="column is-one-quarter">
<div class="card">
<div class="card-image">
<figure class="image is-4by3">
<img src=${words.image} alt="Placeholder image">
</figure>
</div>
<div class="card-content">
<div class="media">
<div class="media-content">
<input class="input" data-word="${words.word}" type="text" placeholder="Įvesk žodį" value="${words.guess}">
</div>
</div>
<div class="content">
${words.content}
</div>
</div>
</div>
</div>`;
});
}
bindWords();
check.addEventListener('click', () => {
info = Array.from(document.querySelectorAll('.card')).map(el => ({
image: el.querySelector('img').src,
word: el.querySelector('.input').dataset.word,
guess: el.querySelector('.input').value,
content: el.querySelector('.input').value === el.querySelector('.input').dataset.word ?
'Correct' : 'Incorrect'
}));
bindWords();
});
<div id="mainColumns"></div>
<button id="check">Check Answers</button>
There many items and I get object of the desired item. But I don't know how can I click on the child element in this object.
html:
<div class="item">
<div role="button" tabindex="-1">
<strong>ItemName2</strong>
</div>
<div class="d">
<div class="item-icon" role="button" tabindex="-1" style="display: none">
<i aria-label="icon: add" class="add"></i> <!-- I need to click on this Item -->
</div>
<div class="item-icon" role="button" tabindex="-1" style="display: none">
<i aria-label="icon: del" class="del"></i>
</div>
</div>
</div>
<div class="item"> ... </div>
<div class="item"> ... </div>
<div class="item"> ... </div>
js:
let fBtns = await driver.findElements(By.tagName('strong')); // Find all objects
let buttons = fBtns.map(elem => elem.getText());
const allButtons = await Promise.all(buttons);
console.log(allButtons); // All object names
let current = fBtns[fBtns.length - 1];
console.log(current); // This is desired object
await current.click(); // This is click on the object and operates as expected
// But I need to click on the <i aria-label="icon: add" class="add"> element
// How can I click on the desired element?
To click the element <i aria-label="icon: del" class="del"></i>, you can just use an XPath to query directly on the element:
await driver.findElement(By.xpath("//div[div/strong[text()='ItemName2']]/div/div/i[#class='del']")).click()
You can probably shorten this a bit to:
await driver.findElement(By.xpath("//div[div/strong[text()='ItemName2']]//i[#class='del']")).click()
Try invoking click by trigger method:
$('.item-icon .add').trigger("click");
In the below example, I scan the document for a dynamic xpath that finds the strong with string ItemName2 and then traverse back up one level (/../) before moving back down to the child element. This will act like a waitForElement that you can hopefully repurpose to trigger a click.
var MyDefaultTimeout = 1500;
var loaded = false;
do {
var icon = document.getElementsByClassName('//*[contains(#strong,\'ItemName2\')]/../div/div/i');
if(!icon.length == 0)
{
setTimeout(function() { loaded = false }, MyDefaultTimeout);
}
else
{
if(!document.readyState === 'complete')
{
setTimeout(function() { loaded = false }, MyDefaultTimeout);
}
else
{
loaded = true;
return document.readyState;
}
}
}
while(loaded === false);
So here is the JQuery I am using
jQuery(document).ready(function($) {
$('.ltwitch').each(function () {
var tnick = $(this).data('tnick');
var span = $(this).next();
$.getJSON("https://api.twitch.tv/kraken/streams/"+tnick+".json?callback=?", function(c) {
if (c.stream == null) {
span.html("Offline");
} else {
span.html("Online");
}
});
});
});
And the HTML that was with it when I found it
<a class="ltwitch" href="http://www.twitch.tv/ifstudios" data-tnick="IFStudios">IFStudios</a> (<span>...</span>)
RoosterTeeth (...)
Now what I want to do, I have HTML that looks like this
<a href="#portfolioModal3" class="portfolio-link" data-toggle="modal">
<div class="portfolio-hover">
<div class="portfolio-hover-content">
<i class="fa fa-plus fa-3x"></i>
</div>
</div>
<img src="img/portfolio/sweet.png" class="img-responsive" alt="">
</a>
Basically when a channel becomes live I want to switch the img src from the image I have it set to, to the same image with -online on the end. So I can have multiple pictures on the website, but I can have the images change dependent on who is live and who isn't.
So if I have
<a href="#portfolioModal3" class="portfolio-link" data-toggle="modal">
<div class="portfolio-hover">
<div class="portfolio-hover-content">
<i class="fa fa-plus fa-3x"></i>
</div>
</div>
<img src="img/portfolio/sweet.png" class="img-responsive" alt="">
</a>
When her channel goes live, it will turn to
<a href="#portfolioModal3" class="portfolio-link" data-toggle="modal">
<div class="portfolio-hover">
<div class="portfolio-hover-content">
<i class="fa fa-plus fa-3x"></i>
</div>
</div>
<img src="img/portfolio/sweet-online.png" class="img-responsive" alt="">
Or if it was
<img src="img/portfolio/carrot.png"
it would turn to
<img src="img/portfolio/carrot-online.png"
Any ideas?
Try the below code
jQuery(document).ready(function($) {
$('.ltwitch').each(function () {
var tnick = $(this).data('tnick');
var span = $(this).next();
$.getJSON("https://api.twitch.tv/kraken/streams/"+tnick+".json?callback=?", function(c) {
var img = $(img-selector);
var source = img.attr('src');
if (c.stream != null) {
// Online
if(source.indexOf('.png') != -1){
source = source.replace(".png", "-online.png");
img.attr('src',source);
}
}
else{
// Offline
source.replace("-online", "");
img.attr('src',source);
}
});
});
});
Note: You have to pass the correct image selector to $(img-selector). Also call the same function again for refreshing
I have the following html:
<div id="prog" class="downloads clearfix">
<div class="item">
<div class="image_container">
<img src="/img/downloads/company.png" width="168" height="238" alt="">
</div>
<div class="title">
pricelist: <label id="pr1"></label>
</div>
<div class="type">
pdf document
</div>
<div class="link">
<a id="pdfdocument" class="button" target="_blank" href="#">start Download </a>
</div>
</div>
</div>
I want build HTML which is inside the <div id="prog"> with Javascript:
<div id="prog" class="downloads clearfix"></div>
I'm trying to use this Javascript, but without success:
var tmpDocument, tmpAnchorTagPdf, tmpAnchorTagXls, parentContainer, i;
parentContainer = document.getElementById('prog');
for (i = 0; i < documents.length; i++) {
tmpDocument = documents[i];
tmpAnchorTagPdf = document.createElement('a id="pdfdocument" ');
tmpAnchorTagPdf.href = '/role?element=' + contentElement.id + '&handle=' + ope.handle;
tmpAnchorTagPdf.innerHTML = 'start Download';
tmpAnchorTagXls = document.createElement('a');
tmpAnchorTagXls.href = '/role?element=' + contentElement.id + '&handle=' + ope.handle;
tmpAnchorTagXls.innerHTML = 'start Download';
parentContainer.appendChild(tmpAnchorTagPdf);
parentContainer.appendChild(tmpAnchorTagXls);
}
If this is a section of code that you will be using more than once, you could take the following approach.
Here is the original div without the code you want to create:
<div id="prog" class="downloads clearfix">
</div>
Create a template in a hidden div like:
<div id="itemtemplate" style="display: none;">
<div class="item">
<div class="image_container">
<img src="/img/downloads/company.png" width="168" height="238" alt="">
</div>
<div class="title">
pricelist: <label></label>
</div>
<div class="type">
pdf document
</div>
<div class="link">
<a class="button" target="_blank" href="#">start Download </a>
</div>
</div>
</div>
Then duplicate it with jquery (OP originally had a jquery tag; see below for JS), update some HTML in the duplicated div, then add it to the document
function addItem() {
var item = $("#itemtemplate div.item").clone();
//then you can search inside the item
//let's set the id of the "a" back to what it was in your example
item.find("div.link a").attr("id", "pdfdocument");
//...the id of the label
item.find("div.title label").attr("id", "pr1");
//then add the objects to the #prog div
$("#prog").append(item);
}
update
Here is the same addItem() function for this example using pure Javascript:
function JSaddItem() {
//get the template
var template = document.getElementById("itemtemplate");
//get the starting item
var tempitem = template.firstChild;
while(tempitem != null && tempitem.nodeName != "DIV") {
tempitem = tempitem.nextSibling;
}
if (tempitem == null) return;
//clone the item
var item = tempitem.cloneNode(true);
//update the id of the link
var a = item.querySelector(".link > a");
a.id = "pdfdocument";
//update the id of the label
var l = item.querySelector(".title > label");
l.id = "pr1";
//get the prog div
var prog = document.getElementById("prog");
//append the new div
prog.appendChild(item);
}
I put together a JSFiddle with both approaches here.