I am creating an image gallery of sorts and I want users to have a choice between small, medium, and large thumbnails and have it change without reloading the page. What would the Jaavascript be so that on a mouseclick of a button, all the images with a certain class get resized dynamically?
set up classes for your different sizes.
$('input#small').click( function()
{
$('img').removeClass('large medium').addClass('small');
}
$('input#medium').click( function()
{
$('img').removeClass('large small').addClass('medium');
}
$('input#large').click( function()
{
$('img').removeClass('medium small').addClass('large');
}
var allImgs = document.getElementsByTagName('img'),
allImgsLength = allImgs.length,
className = 'something';
for (var i = 0, i < allImgsLength; i++) {
var image = allImgs[i];
if (image.className.match(new RegExp('\b' + className + '\b')) {
// Set what sizes you need
image.style.width = '400px';
image.style.height = '200px';
}
}
With jQuery:
$('input#foobar').click(function()
{
var newHeight = 200;
$('img.foo').each(function()
{
if ($(this).height() > 200)
{
$(this).css('height', parseInt(newHeight * $(this).css('width') / $(this).css('height')) + 'px');
}
});
});
No guarantees that this will work perfectly, but you can at least build off of it to add different size increments, etc.
Related
I am using this code: EXAMPLE
Depending on if "image-ul" is fully above the bottom edge of the browser window or not, will make divs scroll at different speeds, as it should. But the problem that I am having is that the scrolling is not smooth when the slow scrolling divs get somewhere close to the top of the page. They seem to stall for a moment, and even scroll in the opposite direction sometimes.
//
// default speed ist the lowest valid scroll speed.
//
var default_speed = 1;
//
// speed increments defines the increase/decrease of the acceleration
// between current scroll speed and data-scroll-speed
//
var speed_increment = 0.01;
//
// maximum scroll speed of the elements
//
var data_scroll_speed_a = 3; // #sloganenglish
var data_scroll_speed_b = 5; // #image-ul
//
//
//
var increase_speed, decrease_speed, target_speed, current_speed, speed_increments;
$(document).ready(function() {
$(window).on('load resize scroll', function() {
var WindowScrollTop = $(this).scrollTop(),
Div_one_top = $('#image-ul').offset().top,
Div_one_height = $('#image-ul').outerHeight(true),
Window_height = $(this).outerHeight(true);
if (WindowScrollTop + Window_height >= (Div_one_top + Div_one_height)) {
$('#sloganenglish').attr('data-scroll-speed', data_scroll_speed_a).attr('data-current-scroll-speed', default_speed).attr('data-speed-increments', data_scroll_speed_a * speed_increment);
$('#image-ul').attr('data-scroll-speed', data_scroll_speed_b).attr('data-current-scroll-speed', default_speed).attr('data-speed-increments', data_scroll_speed_b * speed_increment);
$('.slogan-a-line').css('color', 'yellow');
increase_speed = true;
decrease_speed = false;
} else {
$('#sloganenglish').attr('data-scroll-speed', '1').attr('data-current-scroll-speed', default_speed);
$('#image-ul').attr('data-scroll-speed', '1').attr('data-current-scroll-speed', default_speed);
$('.slogan-a-line').css('color', 'red');
decrease_speed = true;
increase_speed = false;
}
}).scroll();
});
// data-scroll-speed script
$.fn.moveIt = function() {
var $window = $(window);
var instances = [];
$(this).each(function() {
instances.push(new moveItItem($(this)));
});
window.onscroll = function() {
var scrollTop = $window.scrollTop();
instances.forEach(function(inst) {
inst.update(scrollTop);
});
}
}
var moveItItem = function(el) {
this.el = $(el);
this.speed = parseInt(this.el.attr('data-scroll-speed'));
this.current_speed = 1.0;
};
moveItItem.prototype.update = function(scrollTop) {
target_speed = parseInt(this.el.attr('data-scroll-speed'));
current_speed = this.current_speed;
speed_increments = parseFloat(this.el.attr('data-speed-increments'));
if (increase_speed) {
if (current_speed < target_speed) {
current_speed += speed_increments;
} else {
current_speed = target_speed;
}
} else if (decrease_speed) {
if (current_speed > default_speed) {
current_speed -= speed_increments;
}
if ($(window).scrollTop() === 0) {
current_speed = default_speed;
}
}
this.current_speed = current_speed;
var pos = scrollTop / this.current_speed;
this.el.css('transform', 'translateY(' + -pos + 'px)');
};
// Initialization
$(function() {
$('[data-scroll-speed]').moveIt();
});
The sample code wasn't slow for me, so it may be specific to your machine or browser.
However, there are a few things you can do:
Don't use jQuery where you don't need it. jQuery is significantly slower than using native JS functions (e.g. document.getElementById).
Don't repeatedly use jQuery selectors. Every time you use a jQuery selector, you suffer a performance hit. So for example, instead of this:
function(){
var Div_one_top = $('#image-ul').offset().top,
Div_one_height = $('#image-ul').outerHeight(true);
}
Do this:
var imageUl = $('#image-ul');
function(){
imageUl.offset().top,
imageUl.outerHeight(true);
}
This example should increase performance quite a bit. You're doing multiple jQuery selectors every time the page scrolls for no reason.
The best choice for something performance intensive is to cut out jQuery completely and do it by hand.
I am wondering how I can use Javascript to get a windows size and then set (really clear) an HTML ID with it.
I am currently working on a site that has a "default" navigation ID of "access" which I want to blank out if the windows size is less than 800 px wide.
This is the page I am working on and if the ID is cleared I can then setup the mobile navigation to work with bootstrap.
`window.onload = function() {
var w = window.innerWidth;
if(w < 800) {
document.getElementById('access').removeAttribute('id');
}
}
window.onload = function() {
var w = window.innerWidth;
if(w < 800) {
document.getElementById('access').removeAttribute('id');
}
}
window.onresize = function() {
var w = window.innerWidth;
if(w < 800) {
document.getElementById('access').removeAttribute('id');
}
}
Use
var w = window.innerWidth;
to get the width of the page.
and then,
window.onload = function() {
if(w < 800) {
document.getElementById('access').removeAttribute('id');
}
}
You probably want to add this functionality in resize too.
EDIT: put the code in window.onload
Based on the comment,
window.onload = function() {
var accessElem = document.getElementById('access');
var updateAccess = function() {
var w = window.innerWidth;
if(w < 800) {
accessElem.removeAttribute('id');
}
else {
accessElem.setAttribute('id', 'access');
}
};
window.onresize = updateAccess; // call updateAccess on resize
updateAccess(); // call once on load to set it.
};
Also, in my opinion, adding/removing id is not a great idea.
So for one of my new projects, I decided to write a super simple parallax script for some background images on scroll. This is what I came up with:
$(document).ready(function(){
parallaxScroll();
$(window).bind('scroll', function() {
parallaxScroll();
});
});
function parallaxScroll() {
$(".parallax").each(function() {
if($(this).hasClass('reverse')) {
$(this).css("background-position","center " + (($(this).offset().top - $(window).scrollTop())/2) + "px");
} else {
$(this).css("background-position","center " + (($(this).offset().top - $(window).scrollTop())/-2) + "px");
}
});
}
My question is, is this efficient enough? If not, is there a better solution? I wasn't sure if using an .each() would be best for performance, but it seems to work fine. The reason I have the function run at document load is so when you scroll the page for the first time, the background image doesn't jump.
Instead of css which sets the value immediately, consider using animate instead. It defers setting values using timers/requestAnimationFrame, ensuring that your animation does not block the UI, is async (runs pseudo-parallel to other code), and ensures that the animation is smooth.
This is a plain JS solution, but you'll be able to port it to jQuery really easily:
var lastScrollY = 0;
var backgroundImageY = 0;
var requestAnimationFrame = window.requestAnimationFrame ||
window.msRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame;
window.addEventListener('load', processScrollEvent);
function processScrollEvent() {
var innerHeight = window.innerHeight;
var scrollHeight = document.body.scrollHeight;
var backgroundImage = document.querySelector('#background img');
lastScrollY = document.body.scrollTop;
var currBackgroundImageY = Math.round(((backgroundImage.scrollHeight - innerHeight) / 100) * ((lastScrollY / (innerHeight - scrollHeight)) * 100));
if(currBackgroundImageY != backgroundImageY) {
backgroundImageY = currBackgroundImageY;
requestAnimationFrame(processScrollAnimationFrame);
}
}
function processScrollAnimationFrame() {
var backgroundImage = document.querySelector('#background img');
var transforms = ['transform', 'oTransform', 'msTransform', 'mozTransform', 'webkitTransform'];
for(var i = 0; i < transforms.length; i++) {
backgroundImage.style[transforms[i]] = 'translate3d(0, ' + backgroundImageY + 'px, 0)';
}
}
I have multiple sections showing different backgrounds, each section has a basic parallax background image. As the backgrounds vary in height, I cannot seem to work out how to stop the background image position once the image bottom is reached.
Background position change begins if the section offset().top is equal to or greater than $(window).scrollTop().
It would seem that the btmOffset is incorrect but I can't see why.
Any help greatly appreciated.
Live example
http://demo.dwweb.co.uk
What I have so far
$window = $(window);
var winWid = $window.width();
$('.portfolioSection').each(function(){
var $bgobj = $(this);
var speed = 2.4;
var bg = $(this).css('background-image').replace('url("','').replace('")','');
var tmpImg = new Image();
tmpImg.src = bg;
var orgW = tmpImg.width;
var orgH = tmpImg.height;
var imgResizedRatio = winWid/orgW;
var resizedH = orgH * imgResizedRatio;
var btmOffset = (resizedH - $(this).height()) + $bgobj.offset().top;
$(window).scroll(function() {
if($(window).scrollTop() > $bgobj.offset().top && $(window).scrollTop() < btmOffset){
var yPos = -(($window.scrollTop()-$bgobj.offset().top) / speed);
var coords = '0 '+ yPos + 'px';
$bgobj.css({ backgroundPosition: coords });
} else if($(window).scrollTop() < $bgobj.offset().top) {
$bgobj.css({ backgroundPosition: '0 0' });
} else {
$bgobj.css({ backgroundPosition: '0 '+resizedH+'px' });
}
});
});
orgH and orgW will be 0 on execution, since you are creating a new Image asynchronously, while executing your code synchronously:
var tmpImg = new Image();
tmpImg.src = bg;
//...
This means, you would have to use the onload event (and maybe cover the onerror event too), like this:
tmpImg.onload = function(ev) {
var orgW = tmpImg.width;
var orgH = tmpImg.height;
//and the rest of your code...
}
This is very inefficient, since you are loading all these (big) images again.
I would add data-attributes to each .portfolioSection, like data-bgmaxscroll="1000" (which is the height of the image).
This would be a bit more hardcoded, but i think it's the easiest and the most performant way.
Is it possible to know whether or not an HTML element like image is viewable in current viewport or it will be visible on scroll?
If it is viewable completely or partially then how can I get the amount of portions is visible?
I am trying to explain it from the following image:
The two images at the bottom is partially visible within the viewport and these will be completely visible if one scroll down a little bit.
Now I want to get the the aforesaid information.
In the actual scenario I am trying to get the popup-zoom effect on hover of image in my album like google image search. Everything is fine, except if the images are placed in the described manner then the zoomed div also displaying in half.
Normal condition where image is completely in viewport:
And partially in viewport:
I really appreciate your help.
The code:
var albumDetailOnReady = function() {
$('.image').each(function(){
var photo = $(this);
var wrap = $(findParentByClassName(document.getElementById(photo.attr('id')), 'wrap'));
var row = $(findParentByClassName(document.getElementById(wrap.attr('id')), 'albumDetailRow'));
var visibleZone = $(wrap).find('.alDtlColumn');
var pictureBlock = $(visibleZone).find('.pictuteBlock');
var hiddenZone = $(wrap).find('.hiddenZone');
$(photo).load(function(){
if(177 > $(photo).width()){
var imgleft = ($(pictureBlock).width() - $(photo).width())/2 + 'px';
$(photo).css({'left': imgleft});
}
});
$(photo).hover(function(){
var y;
if($(photo).height() > $(photo).width()) {
y = ($(visibleZone).offset().top - 50) + 'px';
} else {
y = ($(visibleZone).offset().top + 50) + 'px';
}
var x;
if($(row).find('.wrap:first').attr('id') === $(wrap).attr('id')) {
x = ($(visibleZone).offset().left - 10) + 'px';
} else if($(row).find('.wrap:last').attr('id') === $(wrap).attr('id')) {
x = ($(visibleZone).offset().left - 50) + 'px';
} else {
x = ($(visibleZone).offset().left - 20) + 'px';
}
$(hiddenZone).css({
'top': y,
'left': x,
'position': 'absolute',
'z-index': '10'
});
$(hiddenZone).fadeIn('fast');
}, function(){
});
$(hiddenZone).hover(function(){},function(){
$(hiddenZone).hide().stop(true, true);
});
});
}
var findParentByClassName = function(element, clazz) {
while (element.parentNode) {
element = element.parentNode;
if (hasClass(element, clazz)) {
return element;
}
}
return null;
}
function hasClass(element, cls) {
var regex = new RegExp('\\b' + cls + '\\b');
return regex.test(element.className);
}
I am unable to show any HTML as I haven't have any, I am working in ADF framework.
But for an explanation:
I have two zone for each image: visible and hidden. Both of them are in a wrap. Now on hover an image I am showing the hidden div. The top and left of the hidden div is measured by the top and left of the visible div with some condition.
jQuery.Viewport
Very helpfull and lightweight jQuery plugin that makes an element as a handy viewport for displaying elements with absolute position. The plugin is hosted on GitHub. You can see it in action right there:
https://github.com/borbit/jquery.viewport