Need advice on what's the best solution to this.
I'm doing a RWD Photo Gallery page. Basically, i'm using pretty photo if accessed through a desktop and photoswipe when accessed in mobile devices.
What i did is this:
<img src="sample_image" />
<img src="sample_image" />
I hide (display:none) one of them depending of the screen size using media queries.
Is this a right approach, i read that using display:none will not reduce the load time. I have hundreds of photos in my gallery and i'm worried this might greatly affect the load time. Is there any good solution to this?
Why do you need two tags for this?
<img src="sample_image" />
<img src="sample_image" />
You can achieve the same with a single tag.
<img src="sample_image" />
Now with media query you can have the same desktop_and_mobile class on both media query and define the css property accordingly in each.
This has the advantage that you will be loading only one image, instead of two.
I think that what you want is to have the anchor tag to call the correct lightbox when clicked, because styling the sample_img with responsive css will work as expected, no need for fancy stuff, but if i'm correct then you have 3 choices in my opinion, you can do it like you said and hide the .desktop links using media queries, since the images are exactly the same the user wont have to load again that image, and being set to display:none the user browser won't render that element, so the only downside is that you will have a cluttered html and it will feel muddy, but no other concern in my opinion.
Another option is to use a js code like this one, but since usually lightbox codes will have a method to add event handlers to every link they find with (with the proper formating, lets say its rel), you will have to manually trigger that event after you changed the links rel attr, or execute adaptLinks() before that happens, in that case, on windows resize it won't work, unless you do what i said before. For that you can check how to do it on the lightbox page, they propably have that method listed.
Here is the code
var adaptLinks = (function(){
var $winHeight = $(window).height();
var $lightBoxLinks = $('a.lightBox');
return function() {
var isPrettyPhoto = false;
if($winHeight < 1000){
$lightBoxLinks
.removeClass('desktop')
.addClass('mobile')
.attr('rel','external');
} else {
$lightBoxLinks
.removeClass('mobile')
.addClass('desktop')
.attr('rel','prettyPhoto');
isPrettyPhoto = true;
}
// Call the link processing method of the lightbox
if(isPrettyPhoto) {
$lightBoxLinks.prettyPhoto();
} else {
// photoSwipe method
}
}
})();
$(window).resize(adaptLinks());
And the thir option, is use a lightbox that works both for desktop and mobiles, i think that is the right way to do it.
Good luck.
Related
Quick Intro:
I'm using jQuery.elevateZoom-3.0.8 as to show zoomed picture.
SRC attribute is path to smaller/normal image
DATA-ZOOM-IMAGE attribute is path to bigger image that serves as a zoom.
HTML Code Below:
<section id="designer-single" class="col-md-7" >
<div class="magnifier-thumb-wrapper mc">
<img class="front-magnify"
src="../../public/img/burn/purple-front.png"
data-zoom-image="../../public/img/burn/purple-front-lg.png">
</div>
</section>
<button class='back-image'>Click me</button>
Now I want image to change when user presses a button. Smaller image will change (SRC attribute), but bigger one will not refresh (data-zoom-image attribute) even though i change it with jQuery.
$('.back-image').on('click', function(){
$('.front-magnify').attr('src', 'public/img/burn/purple-back.png');
$('.front-magnify').attr('data-zoom-image', 'public/img/burn/purple-back-lg.png');
});
Question is: how do I update state of custom attribute "data-zoom-image" in elevateZoom.js so that it updates on DOM?
https://i.stack.imgur.com/hFvG7.png => without clicking
https://i.stack.imgur.com/r0tUw.png => when changing
Example on Codepen:
https://codepen.io/kenanbalija/pen/MojOEp
What seems likely to be the problem is that you're changing the attribute successfully, but the code in elevateZoom.js is initing based on the original value and isn't watching for changes.
Based on your comment below and a quick look at the plugin source code, my earlier guesses (reinstantiate the plugin by calling .elevateZoom again, or use the responsive option) won't work. This is a one-shot plugin, it's really not designed to be controllable after it's instantiated, so your options are pretty limited.
You could go brute-force and destroy the existing plugin (by removing the whole DOM element) before replacing it with a new one and reinstantiating the plugin.
Or, since you appear to be toggling between two different zoomable images, it may be simpler to instantiate them both separately and hide / reveal each as necessary, something along the lines of
$('.image').on('click', function(){
$('.front-magnify, .back-magnify').toggleClass('hidden');
})
That'd be a tradeoff between bandwidth and code complexity, of course.
I give up... All of your answers were just different ways of targeting the local element.
If you bothered to actually read what I was saying you would realise that it was not a problem with the code I already had, just that the code DID NOT work on IMG tags.
While faffing around trying to demonstrate my problem (and that none of your solutions did anything different to what was already happening) I found that I can achieve exactly what I want by applying a Grayscale filter to a DIV element placed over each image. The mouseover event then triggers an opacity change in the DIV element.
It is a little heavier that I wanted but it answered my ACTUAL question. The answer being:
Yes, there probably is a way to toggle class of IMG tags. But no, I am probably not going to find it here without causing arguments or being told i'm using "bad code". So yes, it IS easier and more efficient to target DIV elements.
By the way, page load times are about how large data packages are. Larger data packages (images, html/css/js documents, etc) take longer to download and so the page takes longer to load. The website I am trying to create proves this thesis, I have an almost complete and (almost) fully functional website with loads of 'clever' little effects all under 20mb, about 15mb of which is images. This website is clean and simple, is hosted on my Samsung Galaxy Tab 4 (using Papaya) and loads almost instantly.
THIS is what I meant by "I want this to be VERY lite". Thank you all for your attempts to help, it's just a shame that I couldn't get anyone to understand what was going on.
If you add onClick to image element you don't need to pass anything, you will receive MouseEvent which contains all information. You need target from event.
I suggest to not use onClick on element as it is not scalable, you have to add it to all elements. Better to add listener to wrapping/container element and then filter target by some attribute e.g data-something Please check fiddle
So you have wrapping element and you images:
<div class="images-container">
<img src="https://placeholdit.imgix.net/~text?txtsize=33&txt=350%C3%97150&w=350&h=150" data-toggleable class="thumb-gray thumb-color" />
<img src="https://placeholdit.imgix.net/~text?txtsize=33&txt=350%C3%97150&w=350&h=150" data-toggleable class="thumb-gray" />
<img src="https://placeholdit.imgix.net/~text?txtsize=33&txt=350%C3%97150&w=350&h=150" data-toggleable class="thumb-gray" />
</div>
and you attach listener to you wrapping element. It is best practice as you don't attach listeners to each element and same time you are able easily scale your solution
var imagesContainerEl = document.querySelector('.images-container');
imagesContainerEl.addEventListener('click', function(event) {
var element = event.target;
if (element.hasAttribute('data-toggleable')) {
element.classList.toggle('thumb-color');
}
});
The same code can be extended to support mouseover and mouseout. Check fiddle2. One function to rule them all and in the darkness bind them..
var imagesContainerEl = document.querySelector('.images-container');
imagesContainerEl.addEventListener('mouseover', onToggleImage);
imagesContainerEl.addEventListener('mouseout', onToggleImage);
function onToggleImage(event) {
var element = event.target;
if (element.hasAttribute('data-toggleable')) {
element.classList.toggle('thumb-color');
}
}
Also updated fiddle which shows how to make image grayscale/color
Is what you refer to in your question as
onClick="colorFunction(image1)"
an inline javascript event listener?
If so, try replacing it with:
onClick="colorFunction(this)"
and rewrite colorFunction() as:
function colorFunction(image) {
image.classList.toggle('thumb-color');
}
I have a javascript function which animates images like a slide show. What I'd like is to just have the images being displayed one after another from left to right.
I can't seem to find where in the code the images is getting replaced.
var realoffset = d.offset % d.total;
$(this)
.html(d.titles[realoffset])
.attr('action','article:'+(realoffset+1))
.fadeIn(600);
$(this)
.siblings('img')
.attr('src',function(i,attr){
return attr.replace(
/.+(\/large\/[a-zA-Z\.-_]+)$/,
d.locations[realoffset]+'$1'
)
})
.attr('action','article:'+(realoffset+1))
.fadeIn(600);
.attr('src',function(i,attr){
return attr.replace(
/.+(\/large\/[a-zA-Z\.-_]+)$/,
d.locations[realoffset]+'$1'
)
})
This code is replacing the src of the img tag. You're going to want to be inserting new img tags to show them side by side, not replacing the current tag's src.
Did you write that jQuery snippet yourself? I'm guessing not. Anyway, there are a lot of factors involved in creating a "slideshow" with JavaScript. It sounds like you just need some general knowledge about the subject.
First, let's get your vision straight. Based on your code, you seem to want to fade images into view as they are cycled in the slideshow. For that, study this example:
http://jsfiddle.net/Y6fnx/1/
Now, your code does stuff with d.titles; purely by inference I'm guessing that this displays the image and also a caption for the image? For that, study my updated fiddle:
http://jsfiddle.net/ESP9S/1/
There are countless ways to create a slideshow! You can implement auto-play by taking advantage of JavaScript's setTimeout. You can load your captions from somewhere else. You can get your images from a external script (like Barbara mentioned). You can slide your images instead of fading them by playing with jQuery animate. It never ends!
I want the browser (mobile webkit especially) to NOT download images that are inside display:none divs. Right now, they get downloaded and not rendered.
Is there a jquery plugin to do this?
you can use data-* attributes. that way, you can have jQuery load them on demand:
<img data-source="image_path">
//this one gets all images and loads them
$('img').each(function(){
//loads the source from data-source
this.src = this.getAttribute('data-source');
});
<img data-source="image_path" class="foo">
<img data-source="image_path" class="foo">
//this one gets all images that have class foo and loads them
$('img.foo').each(function(){
//loads the source from data-source
this.src = this.getAttribute('data-source');
});
ofcourse you need to wrap this in a function so that you can call which images on demand. like:
function loadImg(selector){
$(selector).each(function(){
this.src = this.getAttribute('data-source');
});
}
//load images with class foo:
loadImg('.foo');
I don't think so. To be sure, you would need your original HTML DOM to exclude the hidden images, which you could do with server-side programming based on user agent sniffing (although that is not recommended). Modifying the DOM after document.ready or document.load will mean that the browser has already had a chance to request assets from the server even if they might not be displayed.
It would be unusual but if you still want to use jQuery you could follow #Pointy's advice and make all images placeholders in your markup. Then replace the :visible placeholders with the images you want using an attribute as the data source. No plugin is needed, just use something like replaceWith() or attr() to swap out the placeholder node for the image you want downloaded or change the src attribute.
I would use a 1x1 transparent gif as the placeholder with the correct height and width attributes rather than no source <img> for a placeholder. That way the page flow will be determined correctly when the page renders so it won't jump around as your images lazily load.
So, I've been using this JavaScript Snippet through out a fairly large website for rollovers:
<img src="img/vendorbuttons/bn_off.gif" name=bn_off border=0>
Which has worked great, and effortlessly, until now - I have a couple pages that will use the same rollover images for Buy Buttons across the pages, they will be the same aside from a different link being implemented. -Once I began using that JS, with using the same images more then once, all of the JS rollovers stopped work and don't render the 'off state'.
Ultimately - apparently, I can't have multiple JS rollovers using the same images more then once with this code? Any suggestions?
Are you sure nothing was changed? Images or code?
Since there isn't any clue here in the html (because you say it worked earlier), I can only suggest the following:
href="http://www.barnesandnoble.com" , name="bn_off" and border="0" <- these attribute values are missing double-quotes in your code.
Also try adding id="bn_off" (You already have name="bn_off", keep that too).
EDIT:
I think I know why. Because you are copying and pasting this to use in multiple locations, you get multiple links with the SAME name bn_off, and that is why it stops working.
It could have been WAY more easier with jQuery and/or CSS but here's what you can do with what you have:
Add these two functions inside a script block in the HEAD section of your html:
function OnMouseOver(link)
{
if (document.images)
{
var imageElements = link.getElementsByTagName("img");
imageElements[0].src = 'img/vendorbuttons/bn_on.gif';
}
}
function OnMouseOut(link)
{
if (document.images)
{
var imageElements = link.getElementsByTagName("img");
imageElements[0].src = 'img/vendorbuttons/bn_off.gif';
}
}
Change your html for the links like this:
<a href="http://www.barnesandnoble.com" onMouseOver= "OnMouseOver(this);" onMouseOut= "OnMouseOut(this);">
<img src="img/vendorbuttons/bn_off.gif" name="bn_off" border="0">
</a>
Now you can copy and paste the links as much as you want, the javascript won't depend on the name.
If I was you, I would use jQuery and CSS to simplify things.
Hope this helps.
this is how to fix your existing script. However, Guganeshan's solution is much cleaner.
<img src="img/vendorbuttons/bn_off.gif" border=0>