How to open largest version of image in lightbox upon click - javascript

I have embedded images in text blocks on my Divi website. I'd like that when the user clicks on the image, the largest/original size of the image opens up in a lightbox (instead of the thumbnail size as stated in the src). I have hundreds of images and therefore would be too time consuming to change the src link on each to the original size url. Could anyone help me on how I can change the src link to point to the largest/original image size and then for it to open in a lightbox upon click? I'm not sure of the JQuery to go about this. I've included below the HTML structure I'm using for each embedded image in the text blocks. I've also included the JQuery snippet I'm currently using. The snippet opens the image in a lightbox but only the thumbnail version (not the largest size possible).
Here are a few examples of the URLs of the images on my site:
https://mydomain/wp-content/uploads/2023/01/myimage-235x300.jpg
https://mydomain/wp-content/uploads/2023/01/myimage.jpg
https://mydomain/wp-content/uploads/2023/01/myimage-1.jpg
HTML:
<div class="dmpro_timeline_item_description">
<img decoding="async" loading="lazy" src="https://mydomain/wp-content/uploads/2023/01/myimage-235x300.jpg" width="235" height="300" class="wp-image-2129 alignnone size-medium">
<br>
<em>Image caption</em>
</div>
JQuery:
<script>
if ( jQuery('.dmpro_timeline_item_description').length > 0 ) {
jQuery(".dmpro_timeline_item_description p img").each(function(i, e){
var img_src = jQuery(this).attr("src");
var img = jQuery(this).parent().html();
var new_elem = jQuery('<a style="color: inherit;" href="'+img_src+'">'+img+'</a>');
jQuery(this).parent().html(new_elem);
});
}
jQuery(document).ready(function($){
$(".dmpro_timeline_item_description p").magnificPopup({
delegate: 'a',
type: 'image',
closeOnContentClick: true,
closeBtnInside: false,
mainClass: 'mfp-no-margins mfp-with-zoom',
gallery:{
enabled:false,
},
zoom: {
enabled: true,
duration: 200
}
});
});
</script>

In the snippet below you can see that the width and the height attributes can be toggled.
function toggleLarge(context) {
if (!context.large) {
context.large = true;
context.formerWidth = context.width;
context.formerHeight = context.height;
context.removeAttribute("width");
context.removeAttribute("height");
} else {
context.large = false;
context.width = context.formerWidth;
context.height = context.formerHeight;
}
}
for (let img of document.querySelectorAll("img.size-medium")) {
img.addEventListener('click', function(event) {
toggleLarge(this);
});
}
<div class="dmpro_timeline_item_description">
<img decoding="async" loading="lazy" src="https://www.yourtango.com/sites/default/files/styles/header_slider/public/image_blog/lion-meaning.png?itok=-eB2XSyC" width="235" height="300" class="wp-image-2129 alignnone size-medium">
<br>
<em>Image caption</em>
</div>
If you also need to change the URLs, then you will need to proceed similarly. Since you have not given a sample of large URLs, it's impossible to tell you how to convert the URL to something you did not specify. However, if the "-235x300" part is the problematic, then you can do something like this:
function toggleSrc(context) {
if (context.large) {
context.src = context.src.replace(".", "-235x300.");
} else {
context.src = context.src.replace("-235x300", "");
}
}
and call this function in toggleLarge just before the if, passing context. If this is inappropriate to your problem, then you need to provide further information.
EDIT
Initially, for the sake of simplicity, the event listener was defined with the onclick attribute, but I have changed it to be an addEventListener as per Roko C. Buljan's suggestion.
EDIT2
As Roko C. Buljan explained, it's also possible to use forEach instead of a for loop. For those who prefer that syntax, there is another snippet below:
function toggleLarge(context) {
if (!context.large) {
context.large = true;
context.formerWidth = context.width;
context.formerHeight = context.height;
context.removeAttribute("width");
context.removeAttribute("height");
} else {
context.large = false;
context.width = context.formerWidth;
context.height = context.formerHeight;
}
}
document.querySelectorAll("img.size-medium").forEach(function(img) {
img.addEventListener('click', function(event) {
toggleLarge(this);
});
});
<div class="dmpro_timeline_item_description">
<img decoding="async" loading="lazy" src="https://www.yourtango.com/sites/default/files/styles/header_slider/public/image_blog/lion-meaning.png?itok=-eB2XSyC" width="235" height="300" class="wp-image-2129 alignnone size-medium">
<br>
<em>Image caption</em>
</div>
EDIT3
In the snippet below I have implemented the two functions you need based on the comment section's content:
/*
https://mydomain/wp-content/uploads/2023/01/myimage-235x300.jpg
https://mydomain/wp-content/uploads/2023/01/myimage.jpg
https://mydomain/wp-content/uploads/2023/01/myimage-1.jpg
*/
function thumbnailToLarge(input) {
return input.substring(0, input.lastIndexOf(".")).split("-").filter((item) => (
!/[0-9]+x.*[0-9]+/g.test(item)
)).join("-") + input.substring(input.lastIndexOf("."));
}
console.log("Thumbnail to large: " + thumbnailToLarge("https://mydomain/wp-content/uploads/2023/01/myimage-235x300.jpg"));
function largeToThumbnail(input) {
return input.substring(0, input.lastIndexOf(".")) + "-235x300" + input.substring(input.lastIndexOf("."))
}
console.log("Large to thumbnail " + largeToThumbnail("https://mydomain/wp-content/uploads/2023/01/myimage.jpg"));
console.log("Large to thumbnail " + largeToThumbnail("https://mydomain/wp-content/uploads/2023/01/myimage-1.jpg"));

Related

Thumb rotator by IMG URL folder location in jQuery

How to get folder location from IMG URL example https://cdn1.example.com/thumbs/23432/0.jpg via jQuery and to allow to set max images can be found on the folder example Total = 5 ( Images can be found in the folder URL).
The script after to generate the images URLs from the IMG URL example
https://cdn1.example.com/thumbs/23432/0.jpg
https://cdn1.example.com/thumbs/23432/1.jpg
https://cdn1.example.com/thumbs/23432/2.jpg
https://cdn1.example.com/thumbs/23432/3.jpg
https://cdn1.example.com/thumbs/23432/4.jpg
When a person hovers the "a link" with the mouse the image rotator to start with IMG 0.jpg ( First image from the list ) and END with 4.jpg
When the person remove the mouse from the a href to show the original image from <img src="(original link)" />.
I try some scripts but most of them need to add the links manually I was hoping I can find a script to work this way, and I see some issue with most thumb rotators, when they start to rotate some images is not fully loaded, I was hoping if there's a way to load images first before start rotate them.
HTML example:
<img src="https://cdn1.example.com/thumbs/23432/2.jpg" />
var hoverstatus = false;
var imgArr = ["https://picsum.photos/200/300", "https://picsum.photos/id/237/200/300", "https://picsum.photos/seed/picsum/200/300"];
function imagehover() {
hoverstatus = true;
for (var i = 0; i < imgArr.length; i++) {
var time = 1000 * (i + 1);
changeImage(i, time);
}
}
function changeImage(i, time) {
if (hoverstatus == false) {
imagehoverout();
return;
}
setTimeout(function() {
console.log(i);
jQuery('.video img').attr('src', imgArr[i]);
}, time);
}
function imagehoverout() {
hoverstatus = false;
$('.video img').attr('src', 'https://picsum.photos/200/300.jpg');
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<img onmouseover="imagehover()" onmouseout="imagehoverout()" src="https://picsum.photos/200/300.jpg" />

Wait for image to load plugin not functioning

I'm using the plugin from https://github.com/alexanderdickson/waitForImages to detect when is the image loaded.
Below is my code:
$('.marquee').waitForImages(function() {
console.log('All images have loaded.');
setTimeout(startMarquee);
}, function(loaded, count, success) {
console.log(loaded + ' of ' + count +
' images has ' + (success ? 'loaded' : 'failed to load') + '.');
$(this).addClass('loaded');
});
I will start a marquee scrolling of images when the images is loaded complete.
My problem is, some images had not yet load but just show a small empty square box like this:
,
the plugin also consider it already load. Any idea how to fix it?
Does showing a small empty square box only is consider image loaded?
Just write your own.
<marquee id="marquee" style="visiblity:hidden">
<img src="image1.jpg" onload="countMe(this,1)" onerror="countMe(this,0)"/>
<img src="image1.jpg" onload="countMe(this,1)" onerror="countMe(this,0)"/>
<img src="image1.jpg" onload="countMe(this,1)" onerror="countMe(this,0)"/>
</marquee>
<script>
var imageCount = 0, nofImages=$("#marquee img");
function countMe(img,success) {
if (!success) $(img).hide();
imageCount++;
if (imageCount == nofImages) $("#marquee").show();
}
</script>
If you want to give the image a chance and not load the marquee if permanent error you can try
<marquee id="marquee" style="visiblity:hidden">
<img src="image1.jpg" onload="countMe(this)" onerror="reloadMe(this)"/>
<img src="image2.jpg" onload="countMe(this)" onerror="reloadMe(this)"/>
<img src="image3.jpg" onload="countMe(this)" onerror="reloadMe(this)"/>
</marquee>
<script>
var imageCount = 0, nofImages=$("#marquee img");
function countMe(img) {
imageCount++;
if (imageCount == nofImages) $("#marquee").show();
}
function reloadMe(img) {
var tries = img.getAttribute("tries")?parseInt(img.getAttribute("tries"),10):1;
if (tries) == 3) return; // stop it
tries++;
img.setAttribute("tries",tries);
img.src=img.src;
}
</script>
If you want to wait till all page images loaded before running your marquee code you can use:
$(window).on("load", function() {
// all page html and images loaded
});
More details can be found in this questions:
Official way to ask jQuery wait for all images to load before executing something

show alternate image if img src is not found - knockout

I have this piece of code.
<img data-bind="attr: {src: 'imagePath'}, style: { 'background-image': 'url('imagePath')' }" class="img-responsive">
The problem is it is showing two images. One is the image coming from src and other one coming from background image. My goal was to enable the background image when the src image is not available.
What you can do is create a custom binding, let's call it safeSrc.
In this binding, you listen to the load and error events of your image - rendering your image if it's loaded successfully and rendering a fallback if it is not.
In practice, it could look like the following:
ko.bindingHandlers.safeSrc = {
update: function(element, valueAccessor) {
var options = valueAccessor();
var src = ko.unwrap(options.src);
$('<img />').attr('src', src).on('load', function() {
$(element).attr('src', src);
}).on('error', function() {
$(element).attr('src', ko.unwrap(options.fallback));
});
}
};
And then, you can apply the binding like this:
<img alt="Foo" data-bind="safeSrc: {src: imageObservable, fallback: 'https://example.com/fallback.png'}" />
Note that this presumes you're using jQuery - but you can easily rewrite the event listener.
Finally, I would also like to say that you should be rendering a different src instead of the background image - unless you have a specific reason to require one?
Either way, you can simply change the line $(element).attr('src', ko.unwrap(options.fallback)); to $(element).css('background-image', 'url(' + ko.unwrap(options.fallback) + ')');.
JS Fiddle Demo
Here, you can see it all in action: https://jsfiddle.net/13vkutkv/2/
(EDIT: I replaced the cheeky hotlink to the Knockout JS logo with Placehold.it)
P.S.: Depending on how you wish to interact with the element in future (interacting with/updating the binding), you may wish to use applyBindingsToNode (i.e. the Knockout-way), rather than manipulating the src attribute directly on the DOM element.
To show alternate image if img src is not found make alternate image link in your server logic and use only src: 'imagePath' in your front-end
Or if it is important to do it in front-end, you should look at this post:
Display alternate image
I always check my images with a deferred object to be sure they will load. This is using the jquery deferred method, but you could use any deferred library. I coded this from memory, so there may be some errors.
<img data-bind="attr: {src: $root.imagePath()}, style: { 'background-image': 'url('imagePath')' }" class="img-responsive">
var myController = function()
{
var self = this;
this.imagePath = ko.observable('myPath.png'); // Make the image url an observable
var getImagePath = function(path)
{
var imagePath = this.imagePath();
isLoaded(imagePath).done(function(result)
{
// The image will load fine, do nothing.
}).fail(function(e)
{
self.imagePath('defaultImageOnFail.png'); // replace the image if it fails to load
});
};
getImagePath();
};
var isLoaded = function(img)
{
var deferred = new $.Deferred();
var imgObj = $("<img src='"+img+"'/>");
if(imgObj.height > 0 || imgObj.width > 0)
{
deferred.resolve(true);
}
else
{
imgObj.on("load", function(e)
{
deferred.resolve(true);
});
imgObj.on("error", function(e)
{
console.info("VoteScreenController.isLoaded URL error");
deferred.reject();
});
}
return deferred.promise();
};

html2canvas - no screenshot for iframe

I have a task where i need to load a URL (e.g www.yahoo.com) , on my webpage, and take screenshot. I am using html2canvas for screenshot and appending it to the body of the page.
The page specified by the URL is successfully loaded in an iframe inside a div element. But when i try to take screenshot of that, the iframe area comes blank.
Below is the code for previewURL and screenshot.
//to preview the URL content
function previewUrl(url,target){
//use timeout coz mousehover fires several times
clearTimeout(window.ht);
window.ht = setTimeout(function(){
var div = document.getElementById(target);
div.innerHTML = '<iframe style="width:100%;height:100%;" frameborder="0" src="' + url + '" />';
},20);
}
function pic() {
html2canvas(document.body, {
onrendered: function(canvas) {
document.body.appendChild(canvas);
}
});
};
And the HTML part goes here :
<body>
<input type="button" class="clear-button" onclick="pic();" value="Take Screenshot" >
Hover to load
<div id="div1"></div>
</body>
The screenshot looks something like this :
I am stuck and don't understand why is this happening. I want something similar to this which can load URL and then onclick can give me screenshot.
The problem here is that you are not pointing correctly to the part of the iframe that you want to take the screenshot, instead you are pointing directly to the document body.
you can try this:
var body = $(iframe).contents().find('body')[0];
html2canvas(body, {
onrendered: function( canvas ) {
$("#content").empty().append(canvas);
},
Hope this helps!
Seems like it's not possible:
The script doesn't render plugin content such as Flash or Java applets. It doesn't render iframe content either.
http://html2canvas.hertzen.com/documentation.html#limitations
This code worked 4 me:
setTimeout(() => {
html2canvas($('#'+idd2).contents().find('body')[0], {
allowTaint : true,
logging: true,
profile: true,
useCORS: true
}).then(function(canvas) {
document.getElementById('screen').appendChild(canvas);
}); }, 3000);

How to load image on demand

I have this simple image zoom jQuery. Here is a Demo example. It uses the elevateZoom jQuery.
The code behind is very simple:
<img id="zoom_05" src='small_image1.png' data-zoom-image="large_image1.jpg"/>
<script>
$vc("#zoom_05").elevateZoom({
zoomType : "inner",
cursor: "crosshair"
});
</script>
My question, is how can i make the large image load on demand, only when the mouse is over it. Please have a look at this demo example and let me know what i need to add in the code.
img element (id="zoom_05") above, would not load large_image1.jpg on its own.
Large image load happens because elevateZoom() looks into its data-zoom-image value and immediately loads it. One way around this behaviour is to defer elevateZoom() until user hover's over the small image for the first time. Quick example:
jQuery( function () {
var elevate_zoom_attached = false, $zoom_05 = $("#zoom_05") ;
$zoom_05.hover(
// hover IN
function () {
if ( ! elevate_zoom_attached ) {
$zoom_05.elevateZoom({
zoomType : "inner",
cursor : "crosshair"
});
elevate_zoom_attached = true ;
};
},
// hover OUT
function () {
if ( elevate_zoom_attached) { // no need for hover any more
$zoom_05.off("hover");
}
}
);
}) ;
Mind you this is an quick, on-top-of-my-head code, but should work ...
Also in this case elevateZoom() action might not be immediate while large image loading is going on.
I used this idea to initiate zoom on any number of images on the same page by adding a zoom class to the image. It works without any HOVER OUT
<img class="zoom" src="myimage.png" data-zoom-image="mybigimage.png"/>
$('.zoom').hover(
// hover IN
function () {
var currImg = $(this); //get the current image
if (!currImg.hasClass('zoomon')) { //if it hasn't been initialized
currImg.elevateZoom(); //initialize elevateZoom
currImg.addClass('zoomon'); //add the zoomon class to the img so it doesn't re-initialize
}
})

Categories

Resources