I stuck when experimenting with blogger thumbnails. I don't want to use blogger default thumbnails since the size just 72px, it's very small. So, I found a method by rewriting the URL of the image source (the image hosted by google blogger service).
For example, I have an image in this URL http://4.bp.blogspot.com/-XfeUAQMRZnk/VBw8Gv0tZvI/AAAAAAAAAXM/DnmxYqUROVc/s1600/home%2Bthumbs.jpg, the image will loaded with max-width 1600px, indicated by the /s1600/ in the URL. I want to load the image at 300px width, then the URL will be http://4.bp.blogspot.com/-XfeUAQMRZnk/VBw8Gv0tZvI/AAAAAAAAAXM/DnmxYqUROVc/s300/home%2Bthumbs.jpg. Also, the image served in HTTP protocol by default, but it's possible to served in HTTPS just by adding https:// as the protocol.
This is my thumbnail markup:
<div class="thumbnail">
<a class="thumbTooltip" href="#" title="Flat Design Sample">
<img alt="Flat Design Sample" src="http://4.bp.blogspot.com/-XfeUAQMRZnk/VBw8Gv0tZvI/AAAAAAAAAXM/DnmxYqUROVc/s1600/home%2Bthumbs.jpg">
</a>
</div>
The question is, how I can rewrite the default image URL by using javascript method? I want to force the image served in HTTPS by rewriting http:// to https://, and served in 300px width by rewriting s1600 to s300. The final URL will look like this: https://4.bp.blogspot.com/-XfeUAQMRZnk/VBw8Gv0tZvI/AAAAAAAAAXM/DnmxYqUROVc/s300/home%2Bthumbs.jpg
The code is inside an window.onload to ensure that all elements are there. Then in the url-string the first replace() changes the protocol. The second uses a regular expression to find the segment where the size is defined and changes it to s300. It will work even when the images comes from another directory.
window.onload = function() {
var img = document.querySelector('.thumbnail img');
img.src = img.src.replace('http', 'https').replace(/\/s\d+(?=\/)/, '/s300');
};
Instead of the window.onload wrap you also can put the code in <script>-tags just before </body>.
Simple replacement of a token.
function getThumbnailUrl (element)
{
$url = element.href.split("/");
$url[7] = "s300";
return $url.join("/");
}
Related
My issue only arises when the loaded image was preloaded somewhere else. For example, when I somewhere use a <img>-tag with the src attribute.
Have a look at this code:
<canvas id="myCanvas" width="300" height="150" style="border:1px solid #d3d3d3;" ></canvas>
<img src="https://local-spaces.fra1.digitaloceanspaces.com/test.jpg" width="50"/>
<button onclick="show()">Load Canvas Picture</button>
<script>
function show() {
const c = document.getElementById("myCanvas");
const ctx = c.getContext("2d");
const img = new Image();
img.setAttribute('crossOrigin', 'anonymous');
img.onload = function(){
ctx.drawImage(img,0,0, 300, 150);
};
img.src = "https://local-spaces.fra1.digitaloceanspaces.com/test.jpg"
}
</script>
Note: If you are seeing the image in canvas correctly, please cache+hardreload your browser to see the error.
If you are clicking on the button and open your console, you will see that you are getting a CORS-error:
Access to image at
'https://local-spaces.fra1.digitaloceanspaces.com/test.jpg' from
origin 'null' has been blocked by CORS policy: No
'Access-Control-Allow-Origin' header is present on the requested
resource.
Now let's take the next example to see that it is working without preloading the image: https://jsfiddle.net/akzxp9vs/
Note: To make this example work, it's super important that you are deleting your cache + hard reload your browser.
Only then you see that the correct header response is giving back.
Any ideas what I can do?
The image is on the S3 Cloud of Digital Ocean, called Spaces. The image itself is set to public and the CORS setting are set to:
The browser needs to know to check for CORS permissions when the HTTP request is made (i.e. to include an Origin header etc).
When you create a new Image object, it uses the cached data from the <img> element.
Add a crossorigin attribute to the existing <img> element or remove that <img> element entirely.
I found a better solution to my problem. #Quentin's solution is principally right, but it's just not practicable. I tried to update all <img>-tags, however in my page I have dozens of packages that are using the <img>-tag as well.
For example Leaflet. It's like Google Maps, but with Open Street Maps. You just don't have the control over to set attributes like crossorigin in custom icons.
So there had to be another solution. It feels bad to use it, but it does the job.
const src = new URL(imgUrl);
src.searchParams.append('cors', Date.now());
return src.href;
This code appends to your URL a query parameter and forces Chrome to reload the image without being cached.
The following image: http://www.oscn.net/dockets/GetDocument.aspx?ct=tulsa&cn=SC-2011-361&bc=1014242988&fmt=tif
How would I go about downloading this image and displaying it in html using javascript?
Here you go..
If you need to modify any properties of the image (size/color enhancement/etc.) use new_elem.setAttribute('attribute', 'value'); Just like in HTML <img attribute="value" />
var element = document.getElementById('mytargetlocation');
var new_elem = document.createElement('img');
var locationtoimage = 'https://www.sourcecertain.com/img/Example.png';
/*
Note: if your site uses HTTPS, this file will need to be loaded
over HTTPS, if it doesn't, you could just use the original
URL without downloading the image at all
*/
new_elem.setAttribute('src', locationtoimage);
new_elem.setAttribute('alt', 'image not found at specified URL');
element.append(new_elem);
<div id="mytargetlocation"></div>
I want to asynchronously download image, so first user sees a low resolution image, and higher resolution version is downloaded in the background. I have tried the following.
<html>
<head>
<script>
window.addEventListener('load', function () {
var kuvaEl = document.getElementById('kuva');
var r_src = kuvaEl.getAttribute('r-src');
var a_src = kuvaEl.getAttribute('a-src');
kuvaEl.setAttribute('src', r_src);
kuvaEl.setAttribute('src', a_src);
});
</script>
</head>
<body>
<img id="kuva" src="http://www.viikonloppu.com/wp-content/uploads/2014/04/lotoflaughters.com_-619x428.jpg?c3bc1b"
a-src="https://www.manitowoccranes.com/~/media/Images/news/2014/Potain-China-hi-res.jpg"
r-src="http://fuzyll.com/images/2016/angel_oak_panorama.jpg" />
</body>
</html>
But the problem is r_src download is aborted when src is change second time. I want to download both of these images in parallel, and show the r_src first (only if it downloads faster than a_src), and when the *a_src *is ready, show the a_src.
Also, is it possible to download these a_src and r_src images to the browser cache before the src is actually changed? Ideally I would like the the src change to either retrieve the image from the cache or join the pending download for that url.
I can also use jQuery. IE7 must support the implementation.
You just need to use javascript or jquery and load two version of the same image. the first will be your low res, but you will download a high res inside an hidden img tag.
When the download is complete, you just hide / delete the low res image and show the high res.
This link show some test and few way to do it. And it should support ie7 Load a low-res background image first, then a high-res one
You can use interlaced progressive JPEG format.
This method is the preferred method for handling high quality images and has been implemented by so many websites.the idea is that the compression of the image is made in such away that the when you send the image the receiver gets the image in finer and finer detail has the sending of the data progressed.
if you dont want to use the abouve technique
Have the low quality image in the src of the image. once the whole page loaded successfully,change the low quality image with high quality image
<img id="target-image" src="low-quality.jpg" data-src="high-quality.jpg" />
$(window).load(function(){
var imgSrc = $('#target-image').data('src');
$('#target-image').attr('src',imgSrc);
});
You should put your low res as default src. Then use JS to download the high res version and on download completion, change image src.
Also, good practice is to use data-* for custom attributes
If your really want a parallel download, you should replace "load" event for the "DOMContentLoaded" event. However, this will extend the time your user has to wait until page is ready. Your should keep the load event to prioritize critical assets loading (scripts and stylesheets)
window.addEventListener('load', function() {
// get all images
let images = document.getElementsByClassName("toHighRes");
// for each images, do the background loading
for (let i = 0; i < images.length; i++) {
InitHighResLoading(images[i]);
}
});
function InitHighResLoading(image) {
let hrSrc = image.dataset["hr"];
let img = new Image();
img.onload = () => {
// callback when image is loaded
image.src = hrSrc;
}
// launch download
img.src = hrSrc;
}
img {
/* only for code snippet */
max-height: 300px;
}
<img class="toHighRes"
data-hr="https://www.manitowoccranes.com/~/media/Images/news/2014/Potain-China-hi-res.jpg"
src="http://fuzyll.com/images/2016/angel_oak_panorama.jpg" />
I'm a beginner front-ender considering the following scenario :
A certain HTML page should include a heavy image (e.g - animated gif) but I don't want to force the client to sluggishly wait for it to completely download before enjoying a pretty page, rather I would prefer to show him a lightweight image (e.g - the first frame of the gif) and when the former is readily downloaded by the client's browser, replace the light one with the heavy.
What should be the best approach for the matter - Am I looking for a technological solution or a methodological one?
Thanks!
You can embed the light-weight image using a data-URL. This will show that image immediately.
<img src="data:image/gif;base64,---Your-Base64-Encoded-Image-Here---" />
You can use this web site to convert an image file to a data-URL.
What you then need to do is to load the larger image in the background and, once loaded, make it replace the light-weight image.
<img src="data:image/gif;base64,---Your-Base64-Encoded-Image-Here---" />
<img class="heavy" src="http://server.com/path/to/heavy/weight/image.gif" />
The following CSS hides the heavy-weight image initially:
/* Don't show heavy-weight images until they're loaded */
img.heavy {
display: none;
}
The following jQuery-based javascript will hide the light-weight image and show the heavy-weight image once it is loaded:
$(function () {
// Register handler that will be invoked when a heavy-weight image is loaded
$("img.heavy").on("load", function () {
// Hide the light-weight image
// (we assume that it is the immediate previous 'img' sibling of the
// heavy-weight image)
$(this).prev("img").hide();
// Show the heavy-weight image
$(this).show();
});
});
Update (not using data-URL)
If you don't want to use data-URL for the light-weight image, you can use a similar approach where you don't start loading the heavy-weight image until the light-weight is loaded.
<img class="light" src="http://server.com/path/to/light.gif" />
<img class="heavy" data-src="http://server.com/path/to/heavy.gif" />
The heavy-weight image is not loaded initially because it does not have a src-attribute.
The following script will start loading heavy-weight images (by copying data-src to src) as soon as the light-weight image is loaded, and finally "replace" the light-weight image once the heavy-weight image is loaded.
$(function () {
// Register handler that will be invoked when a light-weight image is loaded
$("img.light").on("load", function () {
// Start loading heavy image (by assigning the src-attribute)
$(this).next("img.heavy").each(function () {
$(this).attr("src", $(this).attr("data-src"));
}).on("load", function () {
// Show the heavy-weight image and hide the light-weight image
$(this).show().prev("img.light").hide();
});
});
});
Update 2 (automatic creation of heavy-weight image element)
If you can derive heavy-weight URLs from light-weight URLs, then you can use another approach which might be easier to use and maintain.
<img class="light" src="img/light/image.gif" />
The following script will create a new heavy-weight image element for each light-weight image that is loaded. The heavy-weight image URL is copied from the light-weight image URL, but with the text light replaced by heavy.
$(function () {
// Register handler that will be invoked when a light-weight image is loaded
$("img.light").on("load", function () {
// Create heavy-weight image element after the light-weight image
// URL is computed from light weight image (by replacing 'light' with 'heavy')
// The element is initially hidden.
$("<img/>")
.attr("src", $(this).attr("src").replace("light", "heavy"))
.hide()
.on("load", function () {
// Show the heavy-weight image and remove the light-weight image
$(this).show().prev("img.light").remove();
})
.insertAfter(this);
});
});
This version also removes the light-weight image from the DOM once the heavy-weight image is loaded.
I may use another simple solution depend on a hidden iframe for the heavy image. It will replace the src of the light image when the iframe is loaded. The iframe src will be the src of the heavy image.
<html>
<head>
<script>
function replaceImg(imgId,ifrId){
ifr = document.getElementById(ifrId);
img = document.getElementById(imgId);
img.src = ifr.src;
}
</script>
</head>
<body>
<img id="img1" src="../img/initializing.png" />
<iframe id="ifr1" onload="replaceImg('img1','ifr1')" src="http://lorempixel.com/800/400" style="display:none"></iframe>
</body>
</html>
A live DEMO is found here. However, if you could not able to notice the light image, press RUN button again in the jsfiddle page.
Is there any way without AJAX of changing the loading order of images on a page? Or even a way to completely halt or pause loading of images already present?
The use case is simple - I have a long list of images down a page, and visitors will be landing on different spots of the page using URL anchors (/images#middle-of-page) that refer to actual containers for those images.
I'd like in the least to load the images inside the requested container FIRST, then continue loading the rest of the images.
The challenge is that there is no way to know the image paths of the requested container image before loading the page DOM.
I've tried getting the container img contents on load, then using the Javascript new Image() technique, but it doesn't change the fact that that image on the page will still be waiting for all previous images to load.
I've also tried immediately prepending a div in the body with a background image (CSS) of said img path, but this also does not prioritize the image load.
Any other ideas?
You need to have a DOM with empty img placeholders, i.e.
<img src="" mysrc="[real image url here]" />
Or you can make images to display "Loading..." image by default. You can even cache real image url in some custom tag, mysrc for example. Then once you know what exactly images you want to show (and in what order) you need to build a sequence of image loading
var images = [];//array of images to show from start and in proper order
function step(i){
var img = images[i++];
img.onload = function(){
step(i);
}
img.src = "[some url here]"
}
Hope this helps.
For interest, this is the function I ended up implementing based on the answers here (I made it an on-demand loading function for optimum speed):
function loadImage(img) { // NEED ALTERNATE METHOD FOR USERS w/o JAVASCRIPT! Otherwise, they won't see any images.
//var img = new Image(); // Use only if constructing new <img> element
var src = img.attr('alt'); // Find stored img path in 'alt' element
if(src != 'loaded') {
img
.load(function() {
$(this).css('visibility','visible').hide().fadeIn(200); // Hide image until loaded, then fade in
$(this).parents('div:first').css('background','none'); // Remove background ajax spinner
$(this).attr('alt', 'loaded'); // Skip this function next time
// alert('Done loading!');
})
.error(function() {
alert("Couldn't load image! Please contact an administrator.");
$(this).parents('div:first').find("a").prepend("<p>We couldn't find the image, but you can try clicking here to view the image(s).</p>");
$(this).parents('div:first').css('background','none');
})
.attr('src', src);
}
}
The img loading="lazy" attribute now provides a great way to implement this.
With it, images load automatically only when on the viewport. But you can also force them to load by setting in the JavaScript:
document.getElementById('myimg').loading = 'eager';
I have provided a full runnable example at: How do you make images load lazily only when they are in the viewport?
One really cool thing about this method is that it is fully SEO friendly, since the src= attribute contains the image source as usual, see also: Lazy image loading with semantic markup