jQuery function that will change image link - javascript

I've got the following code for my images using srcset. I'd prefer to get away from srcset altogether. I want this to process all images with a particular class.
<img src="images/Connect-Groups-600.jpg"
srcset="
images/Connect-Groups-600.jpg 600w,
images/Connect-Groups-1000.jpg 1000w,
images/Connect-Groups-1920.jpg 1920w,
images/Connect-Groups-2880.jpg 2880w
" alt=""/>
Does anyone know of a solution using jquery that will take the tag and change the location based on screen size. I need this to work on mobile devices too.
ex:
If screen is bigger than 1920w, it uses
images/2880/Connect-Groups.jpg
If screen is bigger than 1000w and
1920w or less, it will pull images/1920/Connect-Groups.jpg
If screen is between 601 and 1000 it will pull
images/1000/Connect-Groups.jpg
if screen is 600w or less, it pulls images/600/Connect-Groups.jpg
If the size detection fails, I want it to always pull the image in the tag.
I need this to work no matter what the image is...I have no clue what to even search for to find a solution to do this.
EDIT
At the end of this, I want to be able to put in on the page... the code will then pull the URL from the img tag, and append the correct size folder.
It will end up looking like on the end user side.

Please note, this method is not sustainable, I would not recommend using it for anything else, but it will help you solve this specific issue:
Given that your folder structure remains something like:
images/<size>/<filename.ext>
We can re-create a source based on this information:
function resize() {
// First, we'll grab all the images on the page that can be changed:
var img = document.querySelectorAll('img.resizable');
for(var i = 0; i < img.length; i++) {
// Grab the image extension
var src = img[i].src.split('/')
if (window.innerWidth > 1920) {
img[i].src = "/images/2880/" + src[src.length - 1]; // Add the file name and extension
}
else if (window.innerWidth > 1000 && window.innerWidth <= 1920) {
img[i].src = "/images/1920/" + src[src.length - 1]; // Add the file name and extension
}
else if (window.innerWidth > 601 && window.innerWidth <= 1000) {
img[i].src = "/images/1000/" + src[src.length - 1]; // Add the file name and extension
}
else if (window.innerWidth <= 600) {
img[i].src = "/images/600/" + src[src.length - 1]; // Add the file name and extension
}
}
}
resize(); // execute when document is loaded to insert manual images for the first time without resizing
And ofcourse, load the basic 600 width file as default.
Example in jQuery:
function resize() {
var img = $('img.resizable');
var width = $(window).innerWidth();
img.each(function(index, element) {
var name = element.src.split('/') // Split is a native javascript function, which 'splits' the string into an array with the components
if(width <= 600) {
$(element).attr('src', 'images/600/' + name[name.length - 1]) // This name[name.length -1] trick is being used to select the 'last value in the string' based on the length of the string.
}
else if(width <= 1000) {
$(element).attr('src', 'images/1000/' + name[name.length - 1])
}
else if(width <= 1920) {
$(element).attr('src', 'images/1920/' + name[name.length - 1])
}
else {
$(element).attr('src', 'images/2880/' + name[name.length - 1])
}
})
}
resize();

Pretty much identical to Muhammad's answer but in jQuery. If you wanted to do by class just remove the '#' and add a '.'
window.onresize = resize;
function resize() {
console.log($(window).innerWidth);
if ($(window).innerWidth > 1920) {
$("#imageid").src = "images/2880/Connect-Groups.jpg";
} else if ($(window).innerWidth > 1000 && $(window).innerWidth <= 1920) {
$("#imageid").src = "images/1920/Connect-Groups.jpg";
} else if ($(window).innerWidth > 601 && $(window).innerWidth <= 1000) {
$("#imageid").src = "images/1000/Connect-Groups.jpg";
} else if ($(window).innerWidth <= 600) {
$("#imageid").src = "images/600/Connect-Groups.jpg";
}
}
<img id="imageid">

[Modified]
let this is your image tag
<img class="imageid" src="images/Connect-Groups-600.jpg">
then this is the js you are looking for hopefully
var images = document.getElementsByClassName("imageid");
var sizes = ["images/2880/Connect-Groups.jpg","images/1920/Connect-Groups.jpg","images/1000/Connect-Groups.jpg","images/600/Connect-Groups.jpg"];
window.onresize = resize;
function resize() {
console.log(window.innerWidth);
if (window.innerWidth > 1920) {
images[0].src = sizes[0];
} else if (window.innerWidth > 1000 && window.innerWidth <= 1920) {
images[0].src = sizes[1];
} else if (window.innerWidth > 601 && window.innerWidth <= 1000) {
images[0].src = sizes[2];
} else if (window.innerWidth <= 600) {
images[0].src = sizes[3];
}
}
<img id="imageid" src="images/Connect-Groups-600.jpg">

Related

Images Failing to Preload - Causing TypeErrors

I'm making a vanilla JS flappy bird game, but I'm getting a TypeError: Can't read property 'x' of undefined. for a pipeTop variable.
While the background image loads, I'm guessing the pipe image doesn't load before pipeTop[i].x is called.
I tried pre-loading all of the images, as well as include a window.onload for my draw function, but it doesn't seem to serve the images (or their properties) before the logic is implemented.
// draw images
window.onload = function draw() {
ctx.drawImage(bg,0,0);
for (var i = 0; i < pipe.length; i++){
ctx.drawImage(pipeTop, pipe[i].x, pipe[i].y);
ctx.drawImage(pipeBottom, pipe[i].x, pipe[i].y+constant);
pipe[i].x--;
if (pipe[i].x == 125){
pipe.push({
x : cvs.width,
y : Math.floor(Math.random()*pipeTop.height)-pipeTop.height
});
}
}
// Detect Collision
if (bX + bird.width >= pipe[i].x && bX <= pipe[i].x + pipeTop.width && (bY <= pipe[i].y + pipeTop.height || bY+bird.height >= pipe[i].y+constant || bY + bird.height >= cvs.height - fg.height)){
location.reload();
}
if (pipe[i].x == 5) {
score+= 5;
score.play();
}
Pre-loading I tried (now commented out) was:
// function preloadImage(url) {
// var img = new Image();
// img.src = url;
// }
// preloadImage(
// "images/pipeBottom.png",
// "images/pipeTop.png",
// "images/fg.png",
// "images/bg.png",
// "images/bird.png"
// )
The line that has the typeError is:
if (bX + bird.width >= pipe[i].x && bX <= pipe[i].x + pipeTop.width && (bY <= pipe[i].y + pipeTop.height || bY+bird.height >= pipe[i].y+constant || bY + bird.height >= cvs.height - fg.height)){....
Essentially, I'm trying to load the images before any game logic runs so that I avoid these Undefined and Type errors. Any help is appreciated.

Sticky Edge - getting the edge of a cell, inside a carousel

I am working on an application that has a custom carousel and there is a desirable to intuitively move the inner contents of an item so its always in view until the item is truly out of scope.
^ so as the .item is moved in the left position. What techniques would you use to detect the edge to dynamically position the .unit padding-left value? So the text inside that cell is always viewable, even if the item starts to move out of position.
//Latest Fiddle
https://jsfiddle.net/atg5m6ym/3124/
$(document).ready(function() {
//console.log("ready!");
function isElementInViewport (el) {
//special bonus for those using jQuery
if (typeof jQuery === "function" && el instanceof jQuery) {
el = el[0];
}
var rect = el.getBoundingClientRect();
return (
rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && /*or $(window).height() */
rect.right <= (window.innerWidth || document.documentElement.clientWidth) /*or $(window).width() */
);
}
var currentPadding = 0;
var newPadd = 0;
function compensatePadding() {
var itemLeft = Math.abs(parseInt($('.caroseul').offset().left));
console.log("itemLeft", itemLeft)
newPadd = Math.abs(itemLeft);
$('.stick .unit').css("padding-left", newPadd + "px");
}
var unitWidth = $('.unit').width();
console.log("unitWidth", unitWidth);
function onVisibilityChange(el, callback) {
var old_visible;
return function() {
var visible = isElementInViewport(el);
if (visible != old_visible) {
old_visible = visible;
if (typeof callback == 'function') {
callback();
}
}
}
}
function checkVisible() {
console.log("checkvisible");
var labelGroups = $('.caroseul .item .wraps');
var length = labelGroups.length;
for (i = 0; i < length; i++) {
var isItemLabelInView = isElementInViewport(labelGroups[i]);
if(!isItemLabelInView){
$(labelGroups[i]).closest(".item").addClass("stick");
}
else{
$(labelGroups[i]).closest(".item").removeClass("stick");
//reset moved items
$('.unit').css("padding-left", 0);
}
console.log(" labelGroups[i]", labelGroups[i]);
console.log("isItemLabelInView", isItemLabelInView);
}
compensatePadding();
}
$('.container').on('scroll', checkVisible);
});
I tweaked a bit of your code - instead of checking if label is in viewport or not I have checked if label is moving out of viewport from left.
if ($(labelGroups[i]).offset().left < 0) {
$(labelGroups[i]).closest(".item").addClass("stick");
} else {
$(labelGroups[i]).closest(".item").removeClass("stick");
Besides this I have added a few conditions and offset values in compensatePadding() function.
Please refer this fiddle.
Using jquery for this pains me a bit, as I think you'd be better off using requestAnimationFrame...but, to answer your specific question, you could use something like this (I've specifically left the two aggregate values as separate vars in order to explain the point):
$(document).ready(function() {
function animateMe(){
$(".item").animate({
left: "-=5"
}, 1000, function() {
amountMovedLeft += 5;
if(amountMovedLeft >= amountUntilUnitHitsLeft){
$(".unit").animate({
right: "+=5"
}
}
});
}
var amountMovedLeft = 0;
var unitWidthHalf = $('.unit').width()/2;
var itemWidthHalf = $('.item').width()/2;
var amountUntilUnitHitsLeft = itemWidthHalf - unitWidthHalf;
setInterval(function(){
animateMe();
}, 1000);
});

Hide custom navigation buttons if carousel has less items to show - Owl Carousel

I am using owl carousel on one of the pages and I am using following script from theme unify http://htmlstream.com/preview/unify-v1.7/shortcode_carousels.html
I want to hide the navigation buttons when the carousel has fewer items to show even in responsive mode something similar to what has been done in this example http://codepen.io/OwlFonk/pen/qhgjb?editors=101, in this codepen example button hide based on items visible in different screen sizes.
I tried to implement the same to the carousel but it is not working for me
fiddle http://codepen.io/anon/pen/gpYKvq
//Owl Slider v1
var owl = jQuery(".owl-slider").owlCarousel({
itemsDesktop : [1000,5],
itemsDesktopSmall : [900,4],
itemsTablet: [600,3],
itemsMobile : [479,2],
});
jQuery(".next-v1").click(function(){
owl.trigger('owl.next');
})
jQuery(".prev-v1").click(function(){
owl.trigger('owl.prev');
})
I don't know if you still need it, but (just in case) if it's just the buttons that you'd like to hide, you can check the window width (like #Mohamed-Yousef's example) and then just do a .hide(). This is how it should roughly look like:
var viewport = jQuery(window).width();
var itemCount = jQuery("#owl-demo div").length;
if(
(viewport >= 900 && itemCount > 5) //desktop
|| ((viewport >= 600 && viewport < 900) && itemCount > 4) //desktopsmall
|| ((viewport >= 479 && viewport < 600) && itemCount > 3) //tablet
|| (viewport < 479 && itemCount > 2) //mobile
)
{
jQuery('.next-v1, .prev-v1').hide();
}
else
{
jQuery('.next-v1, .prev-v1').show();
}
Make sure that this runs on document load and whatever other events would trigger changes in the carousel.
I'd also just like to mention that I made assumptions about how your code looks like via the code snippet you gave in your question above, and not from the fiddle you gave as the two are different from each other. The fiddle is what I think #Mohamed-Yousef was basing his answer from, as it looks like the default implementation of owl carousel (I didn't check it thoroughly though), while the one in your question looks like a manually implemented custom button that is set to trigger the owl.next/owl.prev events.
I know it's an old question, but also looked for a solution and found one in pure CSS, so maybe it will be useful for someone in future. To hide one dot we can use :only-child pseudo-class. The problem is that it's not supported well (only chrome), so better one is to use an alias of it ":first-child:last-child":
.owl-dot:first-child:last-child {
display: none;
}
you can simply check the number of Divs by using
$(document).ready(function () {
var carousel = $("#owl-demo");
if($("#owl-demo div").length + 1 > 5){
carousel.owlCarousel({
navigation:true,
navigationText: [
"<i class='icon-chevron-left icon-white'><</i>",
"<i class='icon-chevron-right icon-white'>></i>"
],
});
}
});
this check if more than 5 divs run owlCarousel and for responsive mode you need to check for $(window).width(); for example
if($(window).width() > 800 && $(window).width() < 1400){ // for desktop
if($("#owl-demo div").length + 1 > 5){
// run carousel....
}
}else if($(window).width() > 600 && $(window).width() < 800){ // for Tab
if($("#owl-demo div").length + 1 > 4){ // change it as your screen size
// run carousel....
}
}
and so on
var owl = jQuery(".owl-slider").owlCarousel({
itemsDesktop: [1000, 5],
itemsDesktopSmall: [900, 4],
itemsTablet: [600, 3],
itemsMobile: [479, 2],
afterInit: function() {
var viewport = jQuery(window).width();
var itemCount = jQuery(".owl-slider div").length;
if ((viewport >= 900 && itemCount > 5) //desktop
|| ((viewport >= 600 && viewport < 900) && itemCount > 4) //desktopsmall
|| ((viewport >= 479 && viewport < 600) && itemCount > 3) //tablet
|| (viewport < 479 && itemCount > 2) //mobile
) {
jQuery('.next-v1, .prev-v1').show();
} else {
jQuery('.next-v1, .prev-v1').hide();
}
},
afterUpdate: function() {
var viewport = jQuery(window).width();
var itemCount = jQuery("#owl-demo div").length;
if (
(viewport >= 900 && itemCount > 5) //desktop
|| ((viewport >= 600 && viewport < 900) && itemCount > 4) //desktopsmall
|| ((viewport >= 479 && viewport < 600) && itemCount > 3) //tablet
|| (viewport < 479 && itemCount > 2) //mobile
) {
jQuery('.next-v1, .prev-v1').show();
} else {
jQuery('.next-v1, .prev-v1').hide();
}
}
});
If you use Bootstrap 3, you can try my solution which is based on reponsive classes.
It doesnt need additional listener on resize or other events and is executed on initialize. Moreover its quite simple.
var $el = $('.my-carousel');
var breakpoints = {
0: {
items: 3
},
480: {
items: 4
},
769: {
items: 5
},
992: {
items: 4
},
1200: {
items: 5
}
};
var carousel = $el.owlCarousel({
loop: true,
margin: 10,
nav: false,
dots: false,
responsive: breakpoints
});
// get real items count
var items = $el.find('.owl-item:not(.cloned)').length;
// $nav = your navigation element, mine is custom
var $nav = $el.parent().find('.center-navigation');
// add responsive classes to hide navigation if needed
if(breakpoints[1200].items>=items) $nav.addClass('hidden-lg');
if(breakpoints[992].items>=items) $nav.addClass('hidden-md');
if(breakpoints[769].items>=items) $nav.addClass('hidden-sm');
if(breakpoints[480].items>=items) $nav.addClass('hidden-xs');
if(breakpoints[0].items>=items) $nav.addClass('hidden-xxs');
I tried this and it worked for me
function HideNavigationInCarousel(ContainerdivId,viewport)
{
var itemCount = jQuery("#" + ContainerdivId +" .owl-item").length;
// console.log(ContainerdivId + " " + viewport+ " "+itemCount);
if (viewport / itemCount > (jQuery("#" + ContainerdivId + " .owl-item").width()))
{
jQuery("#" + ContainerdivId + " .owl-prev,"+"#" + ContainerdivId +" .owl-next").hide();
}
else {
jQuery("#" + ContainerdivId + ".owl-prev,"+"#" + ContainerdivId +" .owl-next").show();
}
}
Instead of using responsive options, I suggest adding or removing a disabled class on prev/next button, when it's not active.
jQuery(".owl-slider")
.on('initialized.owl.carousel changed.owl.carousel refreshed.owl.carousel', function (event) {
if (!event.namespace) return;
var carousel = event.relatedTarget,
element = event.target,
current = carousel.current();
setTimeout(function() {
$('.owl-next', element).toggleClass('disabled', current === carousel.maximum());
$('.owl-prev', element).toggleClass('disabled', current === carousel.minimum());
}, 1);
})
.owlCarousel({
itemsDesktop : [1000,5],
itemsDesktopSmall : [900,4],
itemsTablet: [600,3],
itemsMobile : [479,2],
});
In CSS, you can either hide disabled element or change its style.
Here's my SASS code for disabled class CSS :
.owl-next,
.owl-prev {
opacity: 1;
transition: opacity 0.3s ease;
&.disabled {
opacity: 0;
}
}
This is an old question, but the simplest way I found to do it, is to use owlCarousel own vars:
function toggleArrows(){
var c = $('.carousel').data('owlCarousel');
if(c.options.items==c.itemsAmount){
$('.next, .prev').hide();
}else{
$('.next, .prev').show();
}
}
Owl carousel will update his internal var options.items based on the number of visible items.
You can run this on the window resize event, just be careful with the responsiveRefreshRate, which update the vars each 200ms (by default), so I run this code inside a timeout after window resize.
var tmtResize = false;
$(window).resize(function(){
if(tmtResize) clearTimeout(tmtResize);
tmtResize = setTimeout(function(){
toggleArrows();
}, 250);
});

Responsive javascript

Can anyone please help with a dodgy if statement, try as I might I can't see anything wrong with it, the code works when outside of the if statement:
var sizeBefore;
var sizeAfterResize;
var sizeBreakPoint;
var resizeTimer;
$(function() {
sizeBefore = $(window).width();
sizeBreakPoint = 500;
doneResizing();
});
function doneResizing(){
sizeAfterResize = $(window).width();
if ((sizeBefore < sizeBreakPoint) && (sizeAfterResize >= sizeBreakPoint)) {
alert('Before:' + sizeBefore);
alert('After:' + sizeAfterResize);
sizeBefore = sizeAfterResize;
// THIS RUNS WHEN OUTSIDE IF STATEMENT
}
}
$(window).resize(function() {
//doneResizing();
clearTimeout(resizeTimer);
resizeTimer = setTimeout(doneResizing, 100);
});
EDIT: This statement should only be true on both document ready or completion of resize when the window has been resized from smaller than sizeBreakPoint to larger than sizeBreakPoint - hope this clarifies
EDIT: SOLUTION
var sizeBefore;
var sizeAfterResize;
var sizeBreakPoint;
var resizeTimer;
$(function() {
sizeBefore = $(window).width();
sizeBreakPoint = 500;
doneResizing();
});
function doneResizing(){
sizeAfterResize = $(window).width();
if ((sizeBefore < sizeBreakPoint) && (sizeAfterResize >= sizeBreakPoint)) {
alert('Before:' + sizeBefore);
alert('After:' + sizeAfterResize);
}
sizeBefore = sizeAfterResize;
}
$(window).resize(function() {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(doneResizing, 100);
});
ok from looking and testing your if i can say:
if ((sizeBefore < sizeBreakPoint) && (sizeAfterResize >= sizeBreakPoint))
this is only true if your window starts with smaller then 500 and after you resize if it goes over 500. This because you never change you sizeBefore other then on page load.
Can you tell me what you really want to verify? Or if this what you really want.
** edit: suggested solution **
try to do something like this:
$(function() {
sizeBreakPointMin = 480;
sizeBreakPointMax = 520;
doneResizing();
});
function doneResizing(){
sizeAfterResize = $(window).width();
//this way you have a window where this is false and it's as you want to allow the window as in a fine size
//you can garantie that the window is always bigger then 480 and smaller then 520
if ((sizeAfterResize < sizeBreakPointMin) || (sizeAfterResize >= sizeBreakPointMax)) {
alert('Before:' + sizeBefore);
alert('After:' + sizeAfterResize);
// THIS RUNS WHEN OUTSIDE IF STATEMENT
}
}
from your code:
if ((sizeBefore < sizeBreakPoint) && (sizeAfterResize >= sizeBreakPoint)) {
...
sizeBefore = sizeAfterResize;
}
this two lines don't go well together because the first time this is true you just garantied that sizeAfterResize >= sizeBreakPoint making the next time you go check the if sizeBefore is will always be bigger then sizeBreakPoint making the if statement impossible to enter 2 times as it is (and if you don't change sizeBefore outside the if.
Hope this helps.
I think your problem lies within the if condition.
sizeBefore is whatever your screen width is at the document ready event, which if you have a fullscreen browser, will be bigger than 500 (which is your breakpoint value). But you're never updating the sizeBefore, so it will never be lower than the sizeBreakPoint, and so, this part of the if statement will never be true: (sizeBefore < sizeBreakPoint)
This is no direct answer to the question, just my own twist on a responsive JavaScript
// calculate viewport width so that we can load js conditionally
function responsive(){
var scaffolding = 'desktop';
var w = parseInt($(window).innerWidth(), 10);
if (w > 0 && w < 768) { scaffolding = 'phone'; }
if (w >= 768 && w <= 980) { scaffolding = 'tablet'; }
if (w > 980) { scaffolding = 'desktop'; }
return scaffolding;
}
if ( responsive() == phone ) {
// do stuff only on phones
}
if ( responsive() != phone ) {
// do stuff everywhere else but phones
}
You get to define what each breakpoint represents and what it is called, in a way that it still makes sense when you start using the condition later in the code.

Reload page when a certain width is passed

I want the page to reload only if the browser window goes above or below 768px.
This was my attempt which failed.
if ($(window.width() > "769") {
$(window).resize(function () {
if ($(window).width() < "769") {
location.reload();
}
});
}
elseif($(window.width() < "769") {
$(window).resize(function () {
if ($(window).width() > "769") {
location.reload();
}
});
}
Im sures theres a really simple way of doing this.
demo jsFiddle
The proof that the page is reloaded is (the wait icon in the tab :D ) the Math random that generates a random number (in the demo.)
var ww = $(window).width();
var limit = 769;
function refresh() {
ww = $(window).width();
var w = ww<limit ? (location.reload(true)) : ( ww>limit ? (location.reload(true)) : ww=limit );
}
var tOut;
$(window).resize(function() {
var resW = $(window).width();
clearTimeout(tOut);
if ( (ww>limit && resW<limit) || (ww<limit && resW>limit) ) {
tOut = setTimeout(refresh, 100);
}
});
The timeout function will help on window resize to wait 100ms before calling the refresh function.
You can increase the timeout value to improve usability.
There are probably other and much better ways of doing what you really need, but:
if ($(window.width() > "769"){
Should be:
if ($(window).width() > 769){
Full code:
var width = $(window).width();
$(window).resize(function() {
if (width > 769 && $(window).width() < 769) {
location.reload();
}
else if (width < 769 && $(window).width() > 769) {
location.reload();
}
});​
Live DEMO
It could be made with one if statement, but I preferred splitting it into two so it'll be easier to follow.

Categories