I'm trying to make some basic image slider as a part of JS excersises, and I've noticed something weird when I ran this script.
The source of an image stored in array under the 0 index is changing when I'm trying to change source image in html code with 'setAttribute' method, so when I want to get back from fifth image to one, this proto-slider (nothing is sliding at the moment) is stuck at second image.
My files are named 0.jpg - 5.jpg.
I've preloaded the images to be displayed smoothly without flicker and I'm displaying one image after the page loads, and then I'm trying to change source of this image to source of next image in array of images. Is this the right way to do it?
Here's the code:
var images = new Array(5);
var i=0;
function addImages(){
for (var j=0;j<images.length;j++){
images[j] = new Image();
images[j].src = j+".jpg";
console.log(images[j].src);
}
var article = document.getElementById("article");
article.insertBefore(images[0], document.getElementById("nav"));
}
function next(){
if (i<images.length-1){
document.getElementsByTagName('img')[0].setAttribute('src',images[++i].src);
console.log(images[0].src);
}}
function prev(){
if (i>0){
document.getElementsByTagName('img')[0].setAttribute('src', images[--i].src);
console.log(images[0].src);
}
}
What is the best way to do such a this as dynamically changing image sources?
I've thought about this:
article.removeChild(document.getElementsByTagName("img")[0]);
article.insertBefore(images[++i], document.getElementById("nav"));
I want to know if this isn't considered as a bad practice and what are the other ways to do it in single line of code.
Thanks in advance and sorry for grammar mistakes.
You could just insert empty image
<img id="someid">
and then use document.getElementById("someid").src=images[0].src
If you'd like to be sure that images[0] is completely loaded, use onload function, like:
images[0].onload=function()
{
document.getElementById("someid").src=images[0].src;
}
Related
I have an assignment where I need to make a photo appear when I click on another photo. I need to put each image in an array and call on it to appear when I click on the corresponding photo. When I click on another photo, I need to remove the existing photo and replace it with another one. I need to do it with Javascript and the DOM. I'm unsure how exactly I would do this. Here's my code so far:
var photoDiv = getElementById("photos");
document.getElementById("0").addEventListener("click", function () {
var img = createElement("img");
photoDiv.appendChild(img);
})
I know it's completely wrong but I don't know what to do to fix it :(
You have to add the image source of your image.
After this line:
var img = document.createElement("img");
img.src = 'pathto/yourimg.png_or_jpg'; // You need this.
Also, it's always a good practice to use document.getElementById() (or putting the parent) instead of just getElementById().
Instead of creating a new image you can also replace only the src of the image element, something like this:
// get the image
var imgElement = document.getElementById("myImage");
// add the listener
imgElement.addEventListener("click",
function () {
// update the src of the image
imgElement.src = "https://www.w3schools.com/html/img_girl.jpg";
});
and that's all, you should not create a new element and append it to the DOM element.
I'm making an extension that grabs an image URL within the "uCW" div on an HTML page.
Currently, I have:
var uCW = jNode.closest("div._q7o");
var image = uCW[0].children[1].getElementsByTagName("img")[0].src;
console.log(image);
That finds the image by going into the div/children and pulling the image. Unfortunately, this method is problematic, since it stops working if the children change, which they regularly do.
Instead, I want to select the image by searching the div and all its children (there are a lot of them) for the first image/string that starts with "https://external" (all the images I want start this way, and that doesn't seem to change.)
This is what I tried:
var uCW = jNode.closest("div._q7o");
var image = $(uCW).find([name^="https://external"]).src;
console.log(image);
This doesn't work. The console just prints "undefined."
You could do it like this, if ucw is a classname (if it's an id, you would write $("#ucw") instead):
var image = $(".ucw").find('[src^="https://external"]').attr("src");
console.log(image);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="ucw">
<img src="https://external/1.jpg"/>
</div>
If your images have a name attribute with the source of the image as value, you can also adjust your attempt to fetch the images via their name attribute like you did:
var image = $(".ucw").find('[name^="https://external"]').attr("src");
I want to show a random picture with every refresh but I don't know why my code is not working... probably because I'm bad at javascript, haha.
I tried "3" instead of "imgs.length", but it's still not working - I too don't really want to give an exact number, because the image count may vary.. only for my example I use three images.
var imgs = ['img1','img2','img3'];
function getRandomImage(){
var rnd = Math.floor(Math.random()*imgs.length);
document.getElementById('pr_randImage').src = imgs[rnd];
}
</script>
<img id="pr_randImage">
Quellcode is just not showing any src at all for the img. What am I doing wrong? I'm thankful for every help.
change this
var imgs = ['img1','img2','img3'];
to something like this depending on extension of the image you are using
var imgs = ['img1.png','img2.png','img3.jpg'];
If that still doesn't work then you need to include the path of where the images are
Something like this
document.getElementById('pr_randImage').src = "/images/" + imgs[rnd];
I am creating a page which will contain a lot of large sized images, so naturally I want to make sure the page loads without too much trouble. I read this article here http://24ways.org/2010/speed-up-your-site-with-delayed-content
The method of deferring is as follows (pulled from page, don't mind the URL)
<div>
<h4>
<a href="http://allinthehead.com/" data-gravatar-hash="13734b0cb20708f79e730809c29c3c48">
Drew McLellan
</a>
</h4>
</div>
then later a snippet of js takes care of the image loading
$(window).load(function() {
$('a[data-gravatar-hash]').prepend(function(index){
var hash = $(this).attr('data-gravatar-hash')
return '<img width="100" height="100" alt="" src="http://www.gravatar.com/avatar.php?size=100&gravatar_id=' + hash + '">'
});
});
I don't plan on doing this for every image but definitely for some image which I don't need it to show up at page load time.
Is this the best way to go or are there better ways to achieve faster page load by deferring images?
Thanks
A little late, but in case it benefits others, there is a great article on this topic by Patrick Sexton
https://varvy.com/pagespeed/defer-images.html
He basically is suggesting the same thing, only by using tiny base 64 encoded images, he can place his image tags directly in the HTML which has the benefit of being able to control attributes like height, width, alt, etc individually. It will be a lot easier to maintain your HTML this way as opposed to creating the entire image tag in a script.
<img src="data:image/png;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=" data-src="image1.jpg" alt="image 1">
<img src="data:image/png;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=" data-src="image2.jpg" alt="image 2">
Then your script is simple and generic for all images
<script>
function init() {
var imgDefer = document.getElementsByTagName('img');
for (var i = 0; i < imgDefer.length; i++) {
if (imgDefer[i].getAttribute('data-src')) {
imgDefer[i].setAttribute('src',imgDefer[i].getAttribute('data-src'));
}
}
}
window.onload = init;
</script>
This seems to be pretty clean way of deferring images. The only potential problem is if images carry important information as "Data attributes are a new feature in HTML5".
Another option could be to put images to end of body and use CSS to position them. Personally I would stick to javascript.
Here's a version showcasing .querySelectorAll:
function swapSrcAttributes(source) {
return function(element) {
element.setAttribute('src', element.getAttribute(source));
}
}
function forEach(collection, partial) {
for (var i = 0; i < collection.length; i++) {
partial(collection[i]);
}
}
function initDeferImages() {
// for images
var deferImages = document.querySelectorAll('img[data-src]');
// or you could be less specific and remove the `img`
deferImages = document.querySelectorAll('[data-src]');
forEach(deferImages, swapSrcAttributes('data-src'));
}
window.onload = function() {
initDeferImages();
}
Here is the compatibility table for .querySelector and .querySelectorAll via https://caniuse.com/#feat=queryselector
Html
<img
width="1024"
src="https://placehold.it/64x48.jpg"
data-src-defer="https://images.unsplash.com/photo-1570280406792-bf58b7c59247?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1486&q=80"
alt="image 1"
/>
<img
width="1024"
src="https://placehold.it/64x48.jpg"
data-src-defer="https://images.unsplash.com/photo-1557053964-d42e8e29cb27?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1500&q=80"
alt="image 2"
/>
JS
function deferImgs() {
Array
.from(document.querySelectorAll("img[data-src-defer]"))
.forEach((element) => {
element.setAttribute("src", element.dataset.srcDefer);
});
}
window.addEventListener("load", deferImgs());
================================================================
I'm trying to comply with Farrukh's request with this edit.
I try to do my best, but English is unfortunately only the third language I speak. And I am not a language genius. :D
This js code snippet illustrates a delayed load of some big pictures.
This is not a practical implementation.
The size difference between the images is intentionally huge.
This is because the test must be illustrative.
You can monitor its operation through a browser development tool page.
F12 > Network tab > Speed settings dropdown
The ideal network speed for the test is between 1 - 3MB/s (Some slow network speed).
You may want to run the test several times, so you can see, that the order in which the images are loaded is not controlled in this case, but depends on the transmission.
Because it is not regulated, it is not possible to predict, which image will arrive first.
We load first a small image into a large placeholder.
(image: 64x48.jpg > placeholder width="1024").
The querySelectorAll() method returns a static nodelist. This list of nodes at first glance looks like an array, but it's not.
This is an array-like object:
document.querySelectorAll("img[data-src-defer]")
The Array.from() method can creates a new array instance from this object.
The forEach method can now be executed on this array.
The forEach() method executes a provided function once for each element of the array.
In this case, each element of the array is passed once to this function:
(element) => {
element.setAttribute("src", element.dataset.srcDefer);
}
and this function sets the value of the src="" attribute of the image tag, to the value of the dataset of the same image tag.
src="https://placehold.it/64x48.jpg";
data-src-defer="https://images.unsplash.com/photo-1570280406792-bf58b7c59247?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1486&q=80";
src = data-src-defer;
So finally:
src="https://images.unsplash.com/photo-1570280406792-bf58b7c59247?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1486&q=80";
You can do it as simple as the example below:
All images have data-src attribute where you put the file path. And src attribute with a fake transparent 1x1px png image. You can also add loading attribute setted to lazy, it tells modern browsers to avoid to load immediately the images that are out of viewport (visible site zone)
<img data-src="path/to/image.jpg" loading="lazy"
src="data:image/png;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=" />
Add this script to make all images get the src attribute once your site is loaded (you need jQuery to make it work)
$(function(){
$("img[data-src]").attr("src", function(){ return $(this).data("src"); });
});
I need a little help with (probably) something really simple.
I want to use a script which converts images from color to grayscale.
I got it working partially — the first image turns gray, but the second won’t.
I know this is because an id cannot be used multiple times:
var imgObj = document.getElementById('grayimage');
I tried this:
var imgObj = $(’.grayimage’)[0];
But it didn’t work. Changing it to getElementByClass also does not work. (Before people ask, I did change the id to class in the <img> tag.)
I really could use some help here. Thanks in advance!
$('.grayimage').each(function(idx,imgObj){
<do your code here>
});
$('.grayimage') gives you a list of all elements with grayimage as a class. If you add '[0]' you're accessing the first element, so any changes you make will apply to only the first image that it finds with this class.
You should loop through all elements:
var images = $('.grayimage');
for(i = 0; i < images.length; i++) {
var image = images[i];
// Do stuff
}