I need to change the location.href of some URLs on my site. These are product cards and they do not contain "a" (which would make this a lot easier).
Here is the HTML:
<div class="product-card " onclick="location.href='https://www.google.com'">
I mean it is pretty simple, but I just cannot get it to work. Did not find any results from Google without this type of results, all of which contain the "a":
$("a[href='http://www.google.com/']").attr('href', 'http://www.live.com/')
Any ideas on how to get this to work with jQuery (or simple JS)?
I cannot change the code itself unfortunaltely, I can just manipulate it with jQuery and JS.
To change the onClick for all the class='product-card', you can do something like this:
// All the links
const links = document.getElementsByClassName('product-card');
// Loop over them
Array.prototype.forEach.call(links, function(el) {
// Set new onClick
el.setAttribute("onClick", "location.href = 'http://www.live.com/'" );
});
<div class="product-card " onclick="location.href='https://www.google.com'">Test</div>
Will produce the following DOM:
<div class="product-card " onclick="location.href = 'http://www.live.com/'">Test</div>
Another option, is to loop over each <div> and check if something like google.com is present in the onClick, if so, we can safely change it without altering any other divs with the same class like so:
// All the divs (or any other element)
const allDivs = document.getElementsByTagName('div');
// For each
Array.from(allDivs).forEach(function(div) {
// If the 'onClick' contains 'google.com', lets change
const oc = div.getAttributeNode('onclick');
if (oc && oc.nodeValue.includes('google.com')) {
// Change onClick
div.setAttribute("onClick", "location.href = 'http://www.live.com/'" );
}
});
<div class="product-card" onclick="location.href='https://www.google.com'">Change me</div>
<div class="product-card">Don't touch me!</div>
Related
I'm using Elementor Pro for my photography website and i want to set custom links for each image in the gallery. By default, i can only set a global link which is the same for each image so that's not great.
In fact, i want to set a custom link which will redirect the user to the shop page of the specific image.
I found some code online (thanks to elementhow !) and it's really close to what i want, but i still need to change some things. The thing is a have to manually write all the links in an array and it's not convenient (close to 100 files and growing, if i change the order, i have to reorder the links, etc).
Here's the code i currently use :
<style>.e-gallery-item{cursor: pointer;} </style>
<script>
document.addEventListener('DOMContentLoaded', function () {
var filteredImages = document.querySelectorAll('.e-gallery-item');
//Edit the links HERE
var links = [
'https://www.mywebsiteurl.com/product/product-name1/',
'https://www.mywebsiteurl.com/product/product-name2/',
'https://www.mywebsiteurl.com/product/product-name3/',
'https://www.mywebsiteurl.com/product/product-name4/',
];
var _loope = function _loope(i) {
filteredImages[i].addEventListener('click', function () {
location = links[i];
});
};
for (var i = 0; i < filteredImages.length; i++) {
_loope(i);
}
});
</script>
I would like to use an attribute value in the algorithm to generate the link automatically for each image. I have the process in my mind, but i don't know how to code this...
Here's the code of one image ,i can set what value i want in "alt".
<div class="e-gallery-image elementor-gallery-item__image e-gallery-image-loaded" data-thumbnail="......" data-width="1024" data-height="768" alt="product-name";"></div>
I would like to use the "alt" attribute to create a unique url for each file, with this format :
'https://www......com/product/product-name/'
"product-name' will take the value of the "alt" attribute of each image.
I tried to change this part of the code (replace "links[i]" by trying to get the attribute value using filteredImages[i].getAttributes) but without success...
var _loope = function _loope(i) {
filteredImages[i].addEventListener('click', function () {
location = links[i];
});
};
Can someone give me some tips about how to do that ? I spend 2 years without coding so i'm a bit rusty...
I think this does what you'd like it to, as you have already done you can cycle through each image link using a class.
You can get the value of alt using the .attr() function and then replace the href value of the link.
DEMO
// Cycle through each image using common class
$(".e-gallery-image").each( function() {
// Get value of 'alt' for clicked item
alt = $(this).attr("alt");
// Update href value
$(this).attr("href", "https://www.mywebsiteurl.com/product/" + alt );
});
// Prove that its worked
$(".e-gallery-image").click( function() {
// Confirm all is correct
console.log($(this).attr("href"));
// Assign url to window
location.href = $(this).attr("href");
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="e-gallery-image" href="test.com" alt="product1">Product 1</div>
<div class="e-gallery-image" href="test.com" alt="product2">Product 2</div>
<div class="e-gallery-image" href="test.com" alt="product3">Product 3</div>
<div class="e-gallery-image" href="test.com" alt="product4">Product 4</div>
<div class="e-gallery-image" href="test.com" alt="product5">Product 5</div>
In fact it was really simple. I tried to target a parent element and it worked ! If anyone is interested, here's the code i use :
document.addEventListener('DOMContentLoaded', function () {
var filteredImages = document.querySelectorAll('YOUR_SELECTOR');
var _loope = function _loope(i) {
filteredImages[i].addEventListener('click', function() {
location = "YOUR_WEBSITE_URL" + filteredImages[i].querySelector("YOUR_SELECTOR").getAttribute("alt");
});
};
for (var i = 0; i < filteredImages.length; i++) {
_loope(i);
}
});
I have a cshtml view file with the following code:
<ul id="ul1">
<li id="ul1li1"></li>
<li id="ul1li2"></li>
<li id="ul1li3"></li>
</ul>
And an action "x" which returns me html code with which is several divs one after the other.
something like :
<div class="xdiv"></div>
<div class="xdiv"></div>
<div class="xdiv"></div>
<div class="xdiv"></div>
<div class="xdiv"></div>
Id like to use javascript function in order to put the divs I get from the action "X", into the lis in a circular ascending order.
I couldn't find the right solution, and so far my javascript function is something like this :
function fillLis()
{
var i = 0;
divs = #Url.Action("X");
for(ind in divs){
div = divs[ind];
i = i%3 + 1;
var currentli = document.getElementById('ul1li'+i);
currentli.innterHTML += div.innerHTML;
}
};
Because of some bad html coding, I have to do it that way.
This isn't doing what you think:
divs = #Url.Action("X");
It's just going to resolve to a string (and a syntax error), such as:
divs = /Home/X;
What you want to do is make an AJAX request to that action. (Note: Since you're using ASP.NET, I'm assuming that jQuery is an option.) Something like this:
$.get('#Url.Action("X")', function (data) {
// update your UI
});
In that callback function, data will contain the response from the server. Which, in this case, should be the HTML. At this point it looks like you want to loop over the div elements. So you can probably wrap it in a jQuery object and loop over that. Something like this:
$.get('#Url.Action("X")', function (data) {
var divs = $('div', data);
// at this point "divs" is a list of div HTML elements in the response
});
Your existing code should work on the divs array, perhaps with some minor adjustments through debugging. But essentially that's how you'd get the HTML elements you're looking for from the server in order to use those elements in your client-side code.
Something like that?
Array.prototype.forEach.call(#Url.Action("X"), function(xdiv, i) {
document.getElementById("ul1li"+i).appendChild(xdiv);
});
If not then please update your question with more detailed informations about what you're trying to do.
Some quick notes about your code:
function fillLis()
{
var i = 0;
divs = #Url.Action("X");
for(ind in divs){
div = divs[ind];
// This will always be equal to 1
i = i%3 + 1;
// You say you want to "put the divs [...] into the list", but it seems like you're trying to transfer only the content of your divs
var currentli = document.getElementById('ul1li'+i);
currentli.innterHTML += div.innerHTML;
}
};
I'm trying to figure out the following.
I have following jQuery code:
var as = "";
var bPlay = 0;
audiojs.events.ready(function() {
as = audiojs.createAll();
$(".audiojs .play-pause").click(function() {
var e = $(this).parents(".audiojs").index(".audiojs");
$.each(as, function(t, n) {
if (t != e && as[t].playing) {
as[t].pause()
}
})
bPlay = !bPlay;
if (bPlay == 1) {
$(".bar").each(function(i) {
fluctuate($(this));
});
} else {
$(".bar").stop();
}
})
});
In a nutshell it preforms list of things when someone clicks particular .audiojs instance on a page. 1) checks if there is any other instance playing, if there is pauses it. And if it is playing applies fluctuate function to elements on a page that have class="bar". This is the issue! I don't want to apply it to all .bar's on a page, but only to a specific group that is associated with particular .audiojs instance (the one that is being clicked and is playing).
I thought of the following solution. Each .audiojs instance is inside a div tag that has id like "post-1", "post-2" etc.. where numerical value is post id from database. I can add this numerical id to bar, so it would be like bar-1, bar-2 etc... However after this I'm having issues.
For javascript to work I need to retrieve numerical value from "post-[id]" associated with audiojs instance that is being clicked and than store it somehow, so I can use it like this afterwards
bPlay = !bPlay;
if (bPlay == 1) {
$(".bar-[value retrieved from post-...]").each(function(i) {
fluctuate($(this));
});
} else {
$(".bar-[value retrieved from post...]").stop();
}
Could someone explain to me how it can be achieved?
Honestly, the easiest way would be to stick it in a custom data-* attribute on the <div id="post-X"> element, like so:
<div id="post-1" data-bar="bar-1">...</div>
Then, you said your .audiojs element is inside that <div>, so just go from this inside the event handler to that <div> element (using .closest()) and get the value of it:
var barId = $(this).closest('[id^="post-"]').attr('data-bar');
Then when you need to use it:
$("." + barId).each(function(i) {
fluctuate($(this));
});
Instead of embedding the value in a class or ID, use a data-* attribute:
<div class="audiojs" data-fluctuate-target="bar-1">
<button type="button" class="play-pause">
<!-- ... -->
</button>
</div>
<div class="bar-1">
<!-- ... -->
</div>
In your click event handler, use the following to fluctuate or stop the correct elements:
var fluctuateClass = $(this).closest('.audiojs').attr('data-fluctuate-target');
$('.' + fluctuateClass).each(function () {
if (bPlay == 1) {
fluctuate($(this));
} else {
$(this).stop();
}
});
I have this bit of HTML :
<li eventId="123">
<img src="image.jpeg"/>
<h3 id="eventName">Event Name</h3>
<p id="eventDescription"></p>
</li>
I want to be able to pull out the <h3> and <p> via jQuery so that I can update their values.
I have a delegate bound to the list items, and on click I'm trying to grab hold of <h3> and <p> using :
function eventIdClicked()
{
// This gets hold of "123" OK
theEvent.id = $(this).get(0).getAttribute('eventId');
// How to get the other 2 inner html?
var existingEventName = $(this).get(1).getAttribute('eventName');
var existingEventDesc = $(this).get(2).getAttribute('eventDescription');
$.mobile.changePage("home.html");
}
Am I able to do this?
Maybe something like $(this).find("h3").text() and $(this).find("p").text()?
Very simple jquery.
Also, while it isn't affecting the code in this case, ID's must be unique.
If the ID's aren't unique the elements might as well not have id's.
First off, in your case you should use classes instead of Id's if there are going to be multiple eventnames and eventdescriptions. As for the event handling try passing the event object into the function like so:
function eventIdClicked(evt){
// Now you get get the event target.
// In your case this is the li element.
var target = $(evt.target);
// Now you can pull out the children that you want.
var eventName = target.children(".eventName").text();
var eventDescription = target.children(".eventDescription").text();
// Do more stuff...
}
First, I take for granted that there are several of these <li> so you shouldn't use the id attribute as id have to be unique. I replaced these with a class name.
<li eventId="123">
<img src="image.jpeg"/>
<h3 class="name">Event Name</h3>
<p class="description"></p>
</li>
I cleaned up your syntax using cleaner jQuery methods. I also add the values to the object your are already referencing.
function eventIdClicked()
{
theEvent.id = $(this).attr('eventId');
theEvent.name = $('.name', this).text();
theEvent.description= $('.description', this).text();
$.mobile.changePage("home.html");
}
If you are using HTML5 this would be cleaner:
Replace <li eventId="123">
with <li data-event="{'id':123,'name':Event Name','description':'Event Description'}">
Replace
theEvent.id = $(this).attr('eventId');
theEvent.name = $('.name', this).text();
theEvent.description= $('.description', this).text();
with theEvent = $(this).data('event');
function eventIdClicked()
{
// This gets hold of "123" OK
theEvent.id = $(this).get(0).getAttribute('eventId');
// since you used an id for both tags, you could even ommit the context
var existingEventName = $("#eventName", this);
var existingEventDesc = $("#eventDescription", this);
existingEventName.text("a new event name");
existingEventDesc.text("a new description");
$.mobile.changePage("home.html");
}
Use children function:
var existingEventName = $(this).children('h3')
var existingEventDesc = $(this).children('p');
Now you can use text to grab or modify values. On the other hand those elements also have ids so you can access them using id selector.
If you want to change the innerHTML of the <h3> and <p>, you could use
$('#eventName').html(/*NEW HTML HERE*/);
$('#eventDescription').html(/*NEW HTML HERE*/);
This is assuming the ids are unique in your document
The following works to replace a div with a new div...
<div id = "div1" style="display:block" onclick = "replace()"><img src="1.jpg" /></div>
<div id = "div2" style="display:none"><img src="2.jpg" /></div>
<script type = "text/javascript">
function replace() {
document.getElementById("div1").style.display="none";
document.getElementById("div2").style.display="block";
}
</script>
What I can't figure out is how to make this work so when you click div2 it is replaced by div3 and so on.
In other words, I want to replace the div on each click more than just once. What's the best way to go about this? I'm a novice, so not sure if the above is a good start or not.
Thanks!
You could make a more generic function:
function replace( hide, show ) {
document.getElementById(hide).style.display="none";
document.getElementById(show).style.display="block";
}
Then you can create many divs and use the same function:
<div id = "div1" style="display:block" onclick = "replace('div1','div2')">...</div>
<div id = "div2" style="display:none" onclick = "replace('div2','div3')">..</div>
<div id = "div3" style="display:none" onclick = "replace('div3','div4')">..</div>
...
I will suggest you some best practices in this answer:
Use classes instead of the style property, it's way nicer for the browser.
Don't use inline event handler. See the example below.
It's not "replace" you're looking for, it's "toggling".
I suggest you use event bubbling. This way, you add a single event on the container of all your div, and you can work on this.
Alright, now for the example:
HTML:
<div id="container">
<div id="div1">..</div>
<div id="div2" class="hidden">..</div>
<div id="div3" class="hidden">..</div>
</div>
JS:
// Notice how I declare an onclick event in the javascript code
document.getElementById( 'container' ).onclick = function( e ) {
// First, get the clicked element
// We have to add these lines because IE is bad.
// If you don't work with legacy browsers, the following is enough:
// var target = e.target;
var evt = e || window.event,
target = evt.target || evt.srcElement;
// Then, check if the target is what we want clicked
// For example, we don't want to bother about inner tags
// of the "div1, div2" etc.
if ( target.id.substr( 0, 3 ) === 'div' ) {
// Hide the clicked element
target.className = 'hidden';
// Now you have two ways to do what you want:
// - Either you don't care about browser compatibility and you use
// nextElementSibling to show the next element
// - Or you care, so to work around this, you can "guess" the next
// element's id, since it remains consistent
// Here are the two ways:
// First way
target.nextElementSibling.className = '';
// Second way
// Strip off the number of the id (starting at index 3)
var nextElementId = 'div' + target.id.substr( 3 );
document.getElementById( nextElementId ).className = '';
}
};
And of course, the CSS:
.hidden {
display: none;
}
I highly suggest you read the comments in the javascript code.
If you read carefully, you'll see that in modern browsers, the JS code is a matter of 5 lines. No more. To support legacy browsers, it requires 7 lines.