javascript if class x contains z get link of class y - javascript

i'm no js expert but need to execute some js in my applescript. Don't know if this is possible as the html page contains several instances of this div class.
If nested div class ".product_card__title" contains "my search term"
Extract href link from nested class ".js-search-product-link"
From main div with the class ".product_card"
A ANLTERNATIVE VERSION TO THE ONE ACCEPTED HERE IN THIS THREAD.
My Html:
<div class="product_card powersearch__product_card">
<a href="/shop/XYZ" class="js-search-product-link">
<div class="product_card__image" style="background-image:url(https://image.jpg);"></div>
<div class="product_card__title">SEARCH FOR THIS TITLE</div>
<div class="product_card__meta">€14</div></a></div>
What i have so far is:
tell application "Safari"
open location "https://teespring.com/search?q=rocker"
delay 5
set theLinks to (do JavaScript "Array.prototype.slice.call(document.querySelectorAll('.product_card')).map(function(d,i){var title = d.querySelector('.product_card__title'),link = d.querySelector('a');if(title && link && /Rocker/gi.test(title.textContent)){return link.href}})")
end tell
return theLinks

Replace yourSearchTerm with whatever you want to search below:
Array.prototype.slice.call(document.querySelectorAll(".product_card"))
.map(function(d,i){
var title = d.querySelector(".product_card__title"),
link = d.querySelector("a");
if(title && link && /yourSerchTerm/gi.test(title.textContent)){
return link.href
}
})
For all your divs with class of "product_card" it will return an array containing the hrefs, for the ones it could find, otherwise undefined
FIDDLE:
https://jsfiddle.net/ibowankenobi/gc6r2h3v/1/
As apple returns the last global value it might help to change the part where you set the theLinks variable:
set theLinks to (do JavaScript "someGlobal = Array.prototype.slice.call(document.querySelectorAll('.product_card')).map(function(d,i){var title = d.querySelector('.product_card__title'),link = d.querySelector('a');if(title && link && /Rocker/gi.test(title.textContent)){return link.href}})")

Related

JS - jQuery Remove all bands that contains a class but keep the one with the ID that is in the URL

I need your help. I am new to Javascript and jQuery. I have something to do.
I have a list of divs with the same class but each div has a specific ID.
Let say I have this:
<div class="list" id="apples"></div>
<div class="list" id="bananas"></div>
<div class="list" id="pineapples"></div>
I have the URL https://johndoe.com/apples, https://johndoe.com/bananas and https://johndoe.com/pineapples.
All divs are displayed on the 3 pages but I want to have only the div with id apples displayed on the Apples page and the others to be entirely removed not hidden. I want the same for each page (bananas displayed on bananas' page...). So what I wrote is this. I thought that changing apples div's class to something else would avoid it to be deleted.
var fruitId = val['id'];
function displayDiv()
{
var selectedSection = document.getElementById(fruitId);
if (window.location.href.indexOf(fruitId) > 0)
{
selectedSection.setAttribute('class', 'selectedfruit');
$("div.list").remove();
}
}
Do not pay attention to fruitId it's 'apples', 'bananas' and 'pineapples' in the JSON file and I have the correct list.
Use filter(function) and check the id in the function
$("div.list").filter(function(){
return !window.location.href.includes(this.id)
}).remove();
This will remove only the ones where the id value is not in the href
I tried this and it works perfectly BUT I still have Uncaught TypeError: window.location.href.contains is not a function
$("div.list").filter(function(){
if (window.location.href.indexOf(this.id) > -1)
{
return !window.location.href.contains(this.id)
}
$("div.list").remove();
});
What can I do to remove the error? If I replace the "contains" with "indexOf" then I don't have any results.

Changing image src depending on which word is in the element

I want to change the image displayed depending on which word is in the element, which will change frequently. I have tried using the indexOf method, to try and seach for the keyword which will decide whether to show a specific image in element 1 or element 2, but without luck.
<div class="main>
<h1 id="nextGame" onLoad="nextGames()">Aug 25, 2019: Home against Genoa</h1>
<p id="homeTeam"><img src="" id="teamHome"> vs <img src="" id="teamAway"></p>
</div>
<script>
var nextGame1 = document.getElementById("nextGame").indexOf("Home");
if (nextGame1 !== -1); {
document.getElementById("homeTeam").src = "asroma2.png";
} else {
document.getElementById("teamAway").src = "asroma2.png";
}
</script>
I expected my code to be able to see if the element "nextGame" had the string "Home" in it. If so, the image source of "homeTeam" would be changed to my specified src, and if not "teamAway" would be assigned the src.
This was clearly not the case.
Does anyone know what I did wrong?
Using document.getElementById("nextGame") will result in complete HTML Tag instead of the text present in the tag. You can use document.getElementById("nextGame").innerText to get the text inside the tags and then you can use the indexOf operator to identify if "Home" is present in it or not. The complete code will be written as follows:
<div class="main>
<h1 id="nextGame" onLoad="nextGames()">Aug 25, 2019: Home against Genoa</h1>
<p id="homeTeam"><img src="" id="teamHome"> vs <img src="" id="teamAway"></p>
</div>
<script>
var nextGame1 = document.getElementById("nextGame").innerText.indexOf("Home");
if (nextGame1 !== -1) {
document.getElementById("homeTeam").src = "asroma2.png";
} else {
document.getElementById("teamAway").src = "asroma2.png";
}
</script>
You have also closed the if statement with a semicolon and also used an additional closing bracket at the end, both of which will throw a syntax error.
I think you want to use something like
var nextGame1 = document.getElementById("nextGame").innerText.indexOf("Home");

How can I define addEventListener('click' with an ancestoral node hierarchy

Introductory note:
It was suggested the question below was not clearly stated. I simply wish to define an addEventListener('click' trap that traverses three nodes. One of the two examples I present below runs through a (grand)parent id ('id="ArticleStyle"' in the article tag) -> traverses down node to its child 'h1' -> and then further down node to the h1 spawned child, 'a'. Which is, the 'a href' being clicked and listened for.
I have two js scripts properly working that serve my needs by luck alone; not by robust planning. Both I would like to contain and evaluate in a grandparent node/wrapper using that unique id as the defined starting point. It would be essential in the second script to do so since there would be over a hundred (and growing) unique ids needed; if it weren't for the fact I am succeeding by using 'h1'-'a'. Fortunately here, 'h1' is not yet used elsewhere.
The 'a' links in the first script (immediately below / and one of its two HTML blocks is included below that) are fortunately parented by just a total of four unique id allowing it to be functional without the attempted EVALUATION for HANDLING line commented out. Otherwise, if I used an 'a'-'img' (as I used 'hi'-'a' in the second script), there would be sucked in traffic on clicks to other page navigation icons based on their similar 'a'-'img' coding. I would hope to use the attempted line of code I commented out, code it correctly and have it create a container/wrapper/node representing a lineage of 'div class="flagLinkVIEW"'-'a'-'img' || 'div class="flagLinkVIEW"'-'a'-'span' as a filter where none else enter in.
<script>
//Toggles between Montage and Montage_VIEW based on, clicking the img icon.png or the span text below it
document.addEventListener('click', ({ target }) => {
//!!!!!!!!!!!!!!!! FIX 'IF' LINE COMMENTED OUT in second line below this !!!!!!!!!!!!!!!!!!!!!!!!
//Code incorrectly formatted in line under this comment
//if ((target.matches('.flagLinkVIEW a > img')) || (target.matches('.flagLinkVIEW a > span'))) {
if (target.parentElement.id === "VIEW_topIconOnOff0") {
sessionStorage.displayStateMontage = "idMontage_VIEW";
document.body.style.background = "white";
}
if (target.parentElement.id === "VIEW_topIconOnOff1") {
sessionStorage.displayStateMontage = "idMontage";
document.body.style.background = "rgb(225, 213, 191)";
}
if (target.parentElement.id === "VIEW_btmIconOnOff0") {
sessionStorage.displayStateMontage = "idMontage_VIEW";
document.body.style.background = "white";
}
if (target.parentElement.id === "VIEW_btmIconOnOff1") {
sessionStorage.displayStateMontage = "idMontage";
document.body.style.background = "rgb(225, 213, 191)";
}
//}
//!!!!!!!!!!!Above is the closing bracket of the FIX 'IF' LINE COMMENTED OUT !!!!!!!!!!!!!!!!
});
</script>
<div id="Icons-midNAV" class="IconOpacityControl-p5 LNKiconCOLORS">
<a href="#" onclick="window.open ('./Poetry%20-%20Montage%20of%20the%20Years_files/PDF%20-%20MASTER%20Montage%20of%20the%20Years.pdf', 'PDF Master',
'resizable=yes,scrollbars=yes,top=100,left=260,height=420,width=420'); return false;">
<img class="PDF-IconBC-Pv" src="./b-pdf_w.png" alt="PDF Master" />
<span class="BtmCtrIconTextStyle PDF-TextBC-Pv">MASTER</span></a>
<div class="flagLinkVIEW">
<!-- Instead of class, which would be nice, I could if must, use a unique id of
flagLinkVIEW_A here if necessary, and elsewhere in the second similar block, an
id of flagLinkVIEW_B. It would be instructive though, to solve with a class example. -->
<a id="VIEW_btmIconOnOff0" href="./Poetry%20-%20Montage%20of%20the%20Years.html">
<img class="VIEW-IconBC-pV" src="./binoculars-detail-2A.png" alt="Basic-VIEW" />
<span class="BtmCtrIconTextStyle VIEW-TextBC-pV">BasicVIEW</span></a>
<a id="VIEW_btmIconOnOff1" href="./Poetry%20-%20Montage%20of%20the%20Years.html">
<img class="VIEW-IconBC-pV" src="./binoculars-detail-2A.png" alt="Basic-VIEW" />
<span class="BtmCtrIconTextStyle VIEW-TextBC-pV">FullVIEW</span></a>
</div>
</div>
The solution I seek for the second script I believe is similar. Here I would wish use the unique id attached to the article node. I would hope to incorporate the incorrectly coded line now commented out, and fix it to contain a specified node lineage of 'article id="ArticleStyle"'-'h1'-'a' and use it as a filter where none else enter in. Again, the js script is immediately below with the HTML following it.
<script>
//Sets localStorage to transfer present sessionStorage to a new _blank tab/window being opened
document.addEventListener('click', ({ target }) => {
//!!!!!!!!!!!!!!! Change line below to a correctly syntaxed lineage of:
//if ((target.matches('#ArticleStyle h1 > a')) !!!!!!!!!!!!!!!!!!
if (target.matches('h1 a')) {
localStorage.previousMenu = sessionStorage.previousMenu;
localStorage.motherMenu = sessionStorage.motherMenu;
localStorage.rootMenu = sessionStorage.rootMenu;
}
});
</script>
<article id="ArticleStyle">
<h1 style="line-height:0; padding-top:1.8em">
<a href="./Poetry%20-%20Black%20Holes%20and%20When%20Time%20Stands%20Still.html" target="_blank">
Black Holes and When Time Stands Still</a></h1>
<!--multiple 'h1' child nodes, as above but with differing URLs -->
</article
<script>
//Sets localStorage to transfer present sessionStorage to a new _blank tab/window being opened
document.addEventListener('click', ({ target }) => {
//!!!!!!!!!!!!Change line below to: if ((target.matches('.ArticleStyle h1 > a'))
if (target.closest('.ArticleStyle h1 > a')) {
localStorage.previousMenu = sessionStorage.previousMenu;
localStorage.motherMenu = sessionStorage.motherMenu;
localStorage.rootMenu = sessionStorage.rootMenu;
}
});
</script>
Maybe your are looking for this https://developer.mozilla.org/en-US/docs/Web/API/Element/closest still i would try to have classes or ids on my layout and put different handlers instead of in body

Why is my javascript file not re-setting a div's attribute?

I have a script that is adding and removing a class to a couple divs when a link is clicked on. Each div has a set class that does not need to be removed. However, said class is being removed. How do I stop this from happening?
HTML
<div id="home" class="page pageShowing"></div>
<div id="portfolio" class="page"></div>
JS
let holder = document.getElementById("main");
let pageShowingClass = holder.getElementsByClassName("pageShowing");
let pages = holder.getElementsByClassName("page");
Navigation.Links.forEach(function(value){
let createNavLink = document.createElement("li");
let createNavText = document.createTextNode(value.title);
createNavLink.appendChild(createNavText);
createNavList.appendChild(createNavLink);
createNavLink.addEventListener("click", function(){
let link = createNavLink.innerHTML;
link = link.toLowerCase().replace(" ", "_");
let page = document.getElementById(link);
page.setAttribute("class", "page");
for(let i = 0; i < pageShowingClass.length; i++){
Here, the click handler should only be removing the pageShowing class
if it exists but is also removing the page class
if(pageShowingClass[i].getAttribute("class") == "pageShowing"){
pageShowingClass[i].removeAttribute("class");
}
}
Here, the click handler should be readding the page class when the
link is clicked on.
page.setAttribute("class", "page");
page.setAttribute("class", "pageShowing");
page.style.display = "block";
});
});
I know it's easier to do this in jQuery, but I don't want it to be in jQuery. I also already have it to where it will add and remove the pageShowing class dynamically, so that's not an issue.
As Siguza said in the reply, you're removing the class attribute, which is what you DON'T want to be doing in this case.
Let's put the element in question here for reference:
<div id="home" class="page pageShowing"></div>
class is an attribute of the element div. When you call removeAttribute('class'), it will do as it says:
<div id="home"></div>
If you check the element in chrome's dev tools or whatever you use, you'll be seeing the element as it says above.
You're probably looking for Element.className to modify your classes, so instead of
if(pageShowingClass[i].getAttribute("class") == "pageShowing"){
pageShowingClass[i].removeAttribute("class");
}
you'll want
if(pageShowingClass[i].getAttribute("class") == "pageShowing"){
pageShowingClass[i].className = "page";
}
and if you want to add the pageShowing class again, you'd just say pageShowingClass[i].className = "page pageShowing"
Element.setAttribute() adds a new attribute or changes the value of an existing attribute on the specified element.
Use Element.classList.add(String [, String]), adds specified class values. If these classes already exist in attribute of the element, then they are ignored.
page.classList.add('page', 'pageShowing')

Select only the root item of a html node

I have this html code.
<div class="breadcrumb">
Home
<a class="breadcrumb" href="#">About</a>
<a class="breadcrumb" href="#">History</a>
Message from our Founding Members
</div>
Using javascript I want to get the text from the div ".breadcrumb". The problem is the a tag under the div also has a class with the same name, when I run this code:
var names = document.querySelectorAll('.breadcrumb');
return [].map.call(names, function(name) {
return name.textContent;
});
My first element of the array gets the textContent of all the a elements and also the div.
How can I do to get the text of only the div. In this case I want to return only "Message from our Founding Members".
Is there a way to select only the root item of the html, when they have all the same class ?
Thanks
If you want to get the text from the <a> tags with the class="breadcrumb", you can do that by using more specific selectors that include the tag type like this:
var items = document.querySelectorAll("div.breadcrumb a.breadcrumb");
var text = [];
for (var i = 0; i < items.length; i++) {
text.push(items[i].textContent);
}
Working demo: http://jsfiddle.net/jfriend00/kVwH8/
If, what you're trying to do is to get the "Message from our Founding Members" text (I wasn't entirely clear from your original question), then you can do that like this::
var items = document.querySelectorAll("div.breadcrumb a.breadcrumb");
// get node after the last item (that should be the desired text node)
var txtNode = items[items.length - 1].nextSibling;
console.log(txtNode.nodeValue); // Message from our Founding Members
Working demo: http://jsfiddle.net/jfriend00/kynuE/
use div.breadcrumb because that will give you divs with class breadcrumb, not a tags.
You can do this:
var names = document.querySelectorAll('div.breadcrumb')[0].childNodes;
var text = Array.prototype.reduce.call(names,function(prev,node){
if(node.nodeType === 3) return (prev || '' + node.textContent.trim());
});
console.log(text);
There are a lot of ES5 stuff here like trim and reduce so better have those polyfills handy.

Categories