I created a very easy javascript line to change the image on hover, https://designordering.com/wink/ however, I would like to make this hover effect on the entire container instead just on the image that has the image and the "Say Hi" text. Which is actually working now because I added it directly on the HTML tag.
<div class="sayHi" onhover="contact" onmouseover="document.getElementById('myImage').src='./img/face-wink.png'" onmouseout="document.getElementById('myImage').src='./img/face.png'">
<span style="font-size:1.5rem; font-family:Roboto, sans-serif; font-weight:600; padding-right: 15px;">Say Hi</span>
<img class="face" id="myImage" src="./img/face.png" alt="face" height="80px">
</div>
However, I want to move this script to an external JS file and I have a hard time finding the solution for it.
Can you help me, please?
I am trying to target the container div instead of the image tag. Or to find a solution how can I move this to an external JS file
onmouseover="document.getElementById('myImage').src='./img/face-wink.png'" onmouseout="document.getElementById('myImage').src='./img/face.png'"
You could do this by referring to the div element in the javascript code
const sayHiDiv = document.querySelector(".sayHi");
const myImage = document.getElementById("myImage");
sayHiDiv.addEventListener("mouseover", e => myImage.src = "./img/face-wink.png");
sayHiDiv.addEventListener("mouseout", e => myImage.src = "./img/face.png");
Edit
If a more modular approach is needed (if you can't access the element in the javascript) then you can define a function instead
function changeImage (div, src)
{
div.querySelector("img").src = src;
}
The function can then be used to simplify the HTML
<div class="sayHi" onmouseover="changeImage(this, '.img/face-wink.png');" onmouseout="changeImage(this, '.img/face.png');" >
<!-- span and img -->
</div>
Related
I have a page that show lots of photos which can be opened with lightgallery.js
I've already made some custom HTML caption which works fine. But now I want to add a label to the image itself. How can I do that?
I will show an example of what my photos page looks like:
When you open an image this is what it looks like:
The left part is a custom HTML caption which I linked with this attribute: data-sub-html.
Example code of my looped code:
$photomasonry .= '
<div class="tile scale-anm noselect">
<a href="https://studio.website.nl/'.$getphotos['preview'].'" data-sub-html="#caption'.$imgcount.'" class="item masonrytile" data-src="https://studio.website.nl/'.$getphotos['preview'].'">
<img src="https://studio.website.nl/'.$getphotos['preview'].'"/>
<span class="idlabel">'.$getphotos['id'].'</span>
<span class="sizelabel">'.$size.'</span>
</a>
</div>';
$photomasonry .= '
<div id="caption'.$imgcount.'" style="display:none">
<img src="https://studio.website.nl/images/logo.png">
<h4 class="subhtmlh4">Maak iets moois met deze foto</h4>
<div class="gallerypopupbtns">
<button class="btnstyle purplebtn" type="button" name="button">Maak iets moois</button>
</div>
</div>';
$imgcount++;
But now I want this purple size icon (L, XL, XX) as a label on the image when lightgallery is opened. How can I do this? The html of the lightgallery is only generated after the page is loaded.
I want to add an element inside this part:
<div class="lg-img-wrap">
<img class="lg-object lg-image" src="https://studio.website.nl/images/photos/previews/preview-bb58317c8d05e29b32963e7a295a5b9f.jpg">
</div>
But not just that, the content is dynamic, so display the correct size for the correct image. I already created this for the photo overview page but not when clicking a photo.
According to the lightgallery docs, you can use the event lgAfterOpen to execute code once the gallery is opened. However, lightgallery makes this slightly difficult as you can't access the image clicked on from this event, but you can access it from the event lgBeforeOpen. With this in mind, I'd accomplish this by doing two things.
Firstly, add the size as a data attribute of each image:
<img src="https://studio.website.nl/'.$getphotos['preview'].'" data-size="'.$size.'"/>
Secondly, add the following functions when initialising lightgallery:
// example gallery definition
const lg = document.getElementById('custom-events-demo');
// add the following functions
lg.addEventListener('lgBeforeOpen', (event) => {
//add datasize property to target so it can be accessed in the afterOpen function
event.target.dataset.size = event.explicitOriginalTarget.dataset.size;
});
lg.addEventListener('lgAfterOpen', (event) => {
// get size from data attribute
var size = event.target.dataset.size;
// get the .lg-img-wrap div to append size to
var imgWrap = document.querySelector(".lg-container.lg-show .lg-img-wrap");
// create and append span
var sizeSpan = document.createElement("span");
sizeSpan.classList.add("sizelabel");
sizeSpan.innerHTML = size;
imgWrap.appendChild(sizeSpan);
});
//initialise lightgallery
lightGallery(lg);
You may be using a different version of lightgallery, but when I tested this the .lg-img-wrap element was a picture element not a div, so I replaced the last line of the event listener function with the following to get the size to show:
imgWrap.parentElement.appendChild(sizeSpan);
You might need a bit of extra CSS to position the size span as you wish, but just to get it to show all you need is:
.sizelabel {
position: relative;
}
Note: I don't think this will work if you navigate to a different image from within lightgallery as it won't update the size, and in fact the size might just get removed. To fix this you'd probably need to do something using the lgAfterSlide event and the index of the image, but from your screenshot it looks like you don't expect the user to scroll through images within lightgallery anyway so this may not be an issue.
so I'm currently working in the development of site and I'm wanting to replace text in divs with images, I've seen a few examples on here however they don't repeat for multiple strings of the same text or the javascript loads before the PHP and doesn't change the text.
<div class="text">text1</div>
<div class="text">text2</div>
<div class="text">text1</div>
I'm needing text1 to replace with image1 and text2 to replace with image2 etc etc. What would the best way to do this ?
I forgot to include that it's a CMS so I don't have access to the PHP directly, just the HTML templates it uses.
This snippet loops over the .text elements and gets the text# value from each element. Then extracts the number of each text and uses it to create a new image. Whenever the image has been loaded with the correct src it will remove the text and replace it with the image.
const textElements = document.querySelectorAll('.text');
for (const textElement of textElements) {
let text = textElement.textContent;
let numberOfText = text.split('text').pop();
const image = new Image();
image.addEventListener('load', event => {
textElement.removeChild(textElement.firstChild);
textElement.append(image);
});
image.src = `/image${numberOfText}`;
}
<div class="text">text1</div>
<div class="text">text2</div>
<div class="text">text1</div>
I have a page where the following pattern happens quite often:
<a href="path/to/image.jpg">
<img src="path/to/image.jpg">
</a>
In order to avoid typos, I'd prefer to only have to enter the image and path once.
Is there a way (preferably using only native HTML/JS/CSS) to avoid that duplication?
Only recent browsers need to be supported.
Edited to add: there's one location in the page that has a similar but possibly conflicting pattern:
<a href="https://a.web.site/">
<img src="image.jpg">
</a>
I could get rid of it if needed.
But maybe a more robust solution would be to start from something like:
<a href="path/to/image.jpg">
IMG_LINK_TO_CREATE
</a>
and to replace a predefined pattern with the img tag, rather than the other way around.
To fit my answer to your question, I'll only use Vanilla JavaScript. Also, since it's not clear for me if you are trying to create an img from an anchor or viceversa, I am doing both for you. I'll put first the one that appears in you question title.
Identify your elements:
If you want this to work, you need to give at least a class or unique id attribute to your anchor tag in order to properly modify it later on when they are loaded into the DOM.
Generate anchor tag for an image tag
For this case, since you probably will be using multiple anchors and you'll have to do the same for every anchor you want, a class attribute with "create-link" would be enough for you to easily modify these elements directly from the DOM. Something like this would help:
<img class="create-link" src="path/to/image.jpg">
With this said, you can create a function called generateImages() which will do all the work.
function generateImages(){
let images = document.querySelectorAll(".create-link");
images.forEach(image=>{
let link = document.createElement('a'),
parent = image.parentNode,
childImage = new Image();
link.href = image.src;
link.classList.add('generated-link');
childImage.src = image.src;
link.append(childImage);
image.parentNode.removeChild(image);
parent.append(link);
});
}
And that should do it. You can now just execute it whenever you want or in the window load event.
window.onload = generateImages;
Here is a fiddle to help you visualize the overall of this method.
https://jsfiddle.net/m90b6vc5/1/
Generate image from anchor tag:
Same thing as the other one, identify your elements that you will need to use in JavaScript in the future.
The code would be a little bit easier to this, just need to retrieve the link from the anchor tag and append it to a new image element:
function generateImages(){
let a = document.querySelectorAll(".create-link");
a.forEach(element=>{
let image = new Image();
image.src = element.href;
element.append(image);
});
}
https://jsfiddle.net/m90b6vc5
You can do this. But note that this only adds the img after the page is loaded. which means the users view can be re-rendered after the page loads. You can control it to some extent by defining the expected img with-height or ratio in the .img-link class using css
$(document).ready(function(){
$('.img-link').each(function(){
$(this).append($('<img src="' + $(this).attr('href') + '" />'));
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<a href="custom-link">
<img src="custom-image.jpg" />
</a>
javascript function
function createImageStructure(number, imageArray){ var structure = "";
for(var i = 0; i < number; i++){
structure += ' <img src="'+imageArray[i]+'"> ';
} console.log(structure); }
var imageArray = [];
imageArray.push("https://pay.google.com/about/static/images/social/knowledge_graph_logo.png");
imageArray.push("https://pay.google.com/about/static/images/social/knowledge_graph_logo.png");
createImageStructure(2, imageArray);
output
<img src="https://pay.google.com/about/static/images/social/knowledge_graph_logo.png"> <img src="https://s23527.pcdn.co/wp-content/uploads/2018/05/google-photos.png">
basically, create a function, create an array, to have image paths, this will help to create HTML structure with multiple images.
if need more help please let me know, i will fix this, if you want just one image source path for all img tags
While I really don't want to encourage you to do this with client-side code, I will at least suggest you use code that generates links instead of code that generates images. This way, the website still shows images if the JS doesn't run.
The simplest way to do this is to add a class to all images which you want to automatically wrap in a link, such as "auto-link", and then run this code:
for (const img of document.querySelectorAll(".auto-link")) {
const link = document.createElement("a");
link.href = img.src;
img.parentElement.replaceChild(link, img);
link.appendChild(img);
}
You can put this in an "domready" or "load" event listener, or just in a script tag at the end of the page.
Note that pretty much all browsers have a "view image" option in their context menu, so there's no reason to do this. You shouldn't introduce a dependency on JavaScript, which slows down execution and wont work if you disable JS or use a screen reader. Instead, features like these ought to be done server-side or as a compilation step.
A good way to encapsulate your html and reuse it elsewhere is React.
function AImg({ href, src }) {
return <a href={ href || src }>
<img src={ src }/>
</a>;
}
ReactDOM.render(
<div>
<AImg src="https://placecage.com/./200/200" />
<AImg src="https://placecage.com/c/200/200" href="https://placecage.com"/>
<AImg src="https://placecage.com/g/200/200" />
</div>,
document.getElementById('aimg_container')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="aimg_container"></div>
React.js is good way to go. If you want to still use ES6 only you can use also backticks. Add links to images and links in an array and in a for of loop create links with image. Something like:
const urls = ['1', '2', '3'];
const images = ['a','b','c'];
let links = [];
for (let index of urls.keys()) {
links.push(`
<img src="${images[index]}" />
`);
}
Adding elements to the DOM can be expensive. I would not be adding a tags via javascript. Keep your HTML mostly as is, but leave the href attribute empty for the links you want to populate.
I've also given you the option of populating the image source based on the href. This is not as good as the image has to be loaded after the page is rendered.
//Wait for everything to be loaded
document.addEventListener("DOMContentLoaded", function(){
//Find a tags with empty hrefs
let emptyAs = document.querySelectorAll("a[href='']");
emptyAs.forEach((a) => {
//Update href based on image src
a.href = a.querySelector("img").src;
});
//Alternatively Find images with empty src
let emptyImgs = document.querySelectorAll("img[src='']");
emptyImgs.forEach((img) => {
img.src = img.parentNode.href;
});
});
<a href="">
<img src="https://fillmurray.com/200/200" />
</a>
<a href="">
<img src="https://fillmurray.com/100/100" />
</a>
<a href="https://fillmurray.com/300/300">
<img src="" />
</a>
<a href="http://www.google.com">
<img src="https://fillmurray.com/400/400" />
</a>
Note forEach has no IE support for a node list: https://developer.mozilla.org/en-US/docs/Web/API/NodeList/forEach
I'm replacing one image with another in javascript, then adding a link to it, but it doesn't seem to be working. Any suggestions?? Please and thank you!!
function showImage2(){
document.getElementById("tbc").src = "images/s2.jpg";
var elem = document.getElementById("Slideshow");
elem.style.display = "none";
document.getElementById('tbc').style.display='block';
document.getElementById('tbc').style.usemap='ss2Map';
var link = document.createElement('a'); // create the link
link.setAttribute('href', 'wastewater.html'); // set link path
link.appendChild("images/s2.jpg"); // append to link
}
link.appendChild("images/s2.jpg"); // append to link
This line won't do anything. You can only append an element, not a text string. You need to append document.getElementById("tbc") instead if I understand your markup correctly.
If that's not what you're trying to append, you can use var el = document.createElement('img') to create an img tag and then set the src attribute using el.setAttribute('src','images/s2.jpg')
After this, the above line would become link.appendChild(el); which would work.
I think all you really need is to have one image with a link and one image without the link. Onload, the image without the link is shown and the other image with the link is hidden. Once click on a button or something, then hide the image without the link and show the image with the link correct?
<img id="image1" src="http://us.123rf.com/400wm/400/400/tonygers/tonygers1108/tonygers110800022/10200687-manipulated-nasa-photographs-of-the-earth-and-moon-isolated-together-on-a-black-background.jpg" />
<a style="display:none;" id="image2" href="http://www.google.com" target="_blank"><img src="http://d1jqu7g1y74ds1.cloudfront.net/wp-content/uploads/2011/08/us-astronaut-bruce-mccandless-space-walk.jpg" /></a>
Click Me
<script>
function showImage2(){
var imageOne = document.getElementById('image1');
var imageTwo = document.getElementById('image2');
imageTwo.style.display = 'block';
imageOne.style.display = 'none';
}
</script>
You can see the working code here. http://jsfiddle.net/QbbJU/1/
appendChild() can only take a DOM node, not a string.
To set the text of an element, you can either set innerHTML or textContent, or append a text node (from document.createTextNode())
You also probably want to put the link somewhere in your page.
In my function I would like to take an image add a dynamically created caption then wrap it all neatly in a div.
Before:
<img src="whatever" />
After:
<div class="imageBlock">
<img src="whatever" />
<span class="caption">The Caption</span>
</div>
This is what I currently have:
var imageCaption = '<span class="caption">'+array[1]+'</span>'
$(this).after(imageCaption).wrap('<div class="imageBlock '+array[0]+'" />');
This is working BUT is placing the span outside of the closing div tag.
You have to pay attention to what this actually refers to.
To get what you want just reverse the order,
var imageCaption = '<span class="caption">'+array[1]+'</span>'
$(this).wrap('<div class="imageBlock '+array[0]+'" />').after(imageCaption);
This is because your object that is being passed is the original image tag. Originally you call after on your tag so it does that correctly, but what gets returned from that call is still just the original image element, not both. So when you call wrap, you are only calling it on the original image tag. By wrapping first, the image tag becomes the child of the wrapped element, then after will insert it in the correct location.
This might be clearer,
var myImage = $(this);
myImage.after(imageCaption);
myImage.wrap('<div class="imageBlock '+array[0]+'" />');
See the problem?
try
$(document).ready(function() {
$('#x').wrap('<div class="imageBlock">');
$('<span class="caption">The Caption</span>').insertAfter($('#x'));
});
'x' is the ID attribute value of <img src="whatever"> element
Here is a fiddle to start you off:
http://jsfiddle.net/c3nxe/