How do I create several ifs and elses? - javascript

I'm new to javascript and I have this jQuery that replaces one image when the screen size is shrunk down to 480px. The thing is that I'd like to add a lot more images to do the same thing.
The only solution i got to work was to paste the code over and over again and replace the image values with new ones.
So how can I create several ifs and elses in the same script?
$(document).ready(function() {
function imageresize() {
var contentwidth = $('body').width();
if ((contentwidth) < '480'){
$('.spelguide').attr('src','bilder/480/spelguide.jpg');
} else {
$('.spelguide').attr('src','bilder/spelguide.jpg');
}
}
imageresize();//Triggers when document first loads
$(window).bind("resize", function(){//Adjusts image when browser resized
imageresize();
});
});

The usual pattern for chaining multiple if-else-ifs is doing something like
if (some_condition) {
// do stuff
} else if (some_other_condition) {
// do other stuff
} else if (another_condition) {
// do another thing
} else {
//default case
}
This is not just for Javascript. In most other programming languages with an if statement it will look similar to this.

You want If..Else If..Else ? If so http://www.w3schools.com/js/js_if_else.asp gives an example.

Here's what I would do (assuming I understand your question correctly). The short answer, I would say is to: Use a "for" loop.
First, I would give each image a UNIQUE id (instead of a class):
<img id="example_img_id1" src="..." />
In my JavaScript, I would create a JSON object that has a (key : value) pair storing the (id : image_name) of each image (see below).
Then, I would use a for/in loop that iterates over a JSON object.
In your JSON object, add each of your unique img ids as the key and the name of the image as the value. Do this for all of the images that you have.
// get the width of your body
var contentwidth = $('body').width();
// key: value -----> '#img_id': 'src'
var imgs = {
'#example_img_id1' : 'imgname1.jpg',
'#example_img_id2' : 'imgname2.jpg',
'#example_img_id3' : 'imgname3.jpg',
// ...
'#example_img_idn' : 'imgname4.jpg'
};
// iterate over each image and create its new src
for(var img in imgs) {
// set the value of your src string
var src = '';
if(contentwidth < 480) { // if the screen size is less than 480
src = '/bilder/480/' + imgs.img; // add the "/480/" directory
} else { // anything 480 and larger
src = '/bilder/' + imgs.img; // don't add "/480/"
}
// for every image in your JSON object (imgs),
// it will create a jQuery object - $(img) - and
// update its src attribute based on the screen width.
$(img).attr('src', src);
}
There's more than one way to skin a cat, and by no means is this the "best" or "most efficient" approach. Hopefully it at least points you in the right direction. Does this all make sense?

Forget doing all that with javascript, let CSS do most of the work.
Just set a determining class on the body with javascript.
Javascript:
$(window).bind("resize", function(){
var body = $('body');
var bodyWidth = body.width();
body.toggleClass('size-480', bodyWidth < 480);
});
HTML:
<img src="transparant.gif" class="img-spelguide" />
CSS:
img.img-spelguide {
width: 400px; /*adjust accordingly*/
height: 400px; /*adjust accordingly*/
background: url(bilder/spelguide.jpg) 50% 50% no-repeat;
}
.size-480 img.img-spelguide {
width: 200px; /*adjust accordingly*/
height: 200px; /*adjust accordingly*/
background: url(bilder/480/spelguide.jpg) 50% 50% no-repeat;
}
You could still replace a lot of images using purely javascript, but CSS is better suited.
Note. if you can use #media-queries, please do so, thats the best option, however if you need to support legacy browsers, media-queries are obviously out =(
Lets throw in the javascript solution as well for good measure.
HTML:
<img src="bilder/spelguide.jpg" data-small="bilder/480/spelguide.jpg" />
JAVASCRIPT:
$(window).bind("resize", function(){
var body = $('body');
var useSmall = body.width() < 480;
$('img[data-small]').each(function(){
var img = $(this);
var big = img.data( 'big') || img.attr('src');
var small = img.data('small');
// make sure we have the original (big) src stored.
img.data( 'big', big );
img.attr( 'src', useSmall ? small : big );
});
});
Still some room for optimisation.

Related

CSS attribute not always being grabbed by javascript correctly

I am trying to resize the side bars whenever the image changes.
I have my javascript trying grab the height of the image after it changes
var imgHeight = $('#mainImg').height();
var currImg = 0;
var imagesSet = ["1.jpg", "2.jpg", "3.jpg", "4.jpg", "5.jpg", "6.jpg"];
var imageLoc = "images/zalman/"
$('#bttnRight').click(function(){
nextImg();
imgHeight = $('#mainImg').height();
resizeBttn();
});
function nextImg(){
currImg++;
if(currImg>=imagesSet.length){
currImg=0;
}
$('#mainImg').attr("src",imageLoc + imagesSet[currImg]);
}
function resizeBttn() {
$(document).ready(function() {
$('#bttnLeft').css("height",imgHeight);
$('#bttnLeft').css("bottom",imgHeight/2-5);
});
$(document).ready(function() {
$('#bttnRight').css("height",imgHeight);
$('#bttnRight').css("bottom",imgHeight/2-5);
});
}
for some reason, it doesn't always grab the height at the correct time and the side bars will stay at the previous height.
Below I have a JSFiddle that should be working the way my setup is.
Please excuse any inconsistencies and inefficiencies, I am learning.
Just seems weird that it would sometimes grab the height and sometimes not.
I will also be attaching an image of what I see sometimes from the JSfiddle.
I will also attach an image of what I see on my site I am actually writing.
https://jsfiddle.net/6bewkuo5/6/
The issue is because your JavaScript accessing the height of the image before the image as actually been re-rendered in the DOM. Adding a slight delay after assigning the new image source may help things, but...
You actually don't need to use JavaScript to set the height of the buttons
You can achieve what you're after by placing the buttons and image inside of a container with css attribute display: flex.
Like this:
.container {
display: flex;
justify-content: center;
}
<div class="container">
<button class="prev"><</button>
<img src="https://www.avalonwinery.com/wp-content/uploads/2013/12/200x300.gif">
<button class="next">></button>
</div>
Elements within a flex container will automatically fill the height, this includes buttons. Because the images will automatically adjust the height of the container, the buttons will also automatically adjust their height to match.
Run the example below
const images = [
"https://www.avalonwinery.com/wp-content/uploads/2013/12/200x300.gif",
"https://images.sftcdn.net/images/t_app-logo-xl,f_auto/p/ce2ece60-9b32-11e6-95ab-00163ed833e7/1578981868/the-test-fun-for-friends-logo.png",
"https://hiveconnect.co.za/wp-content/uploads/2018/05/800x600.png",
"https://upload.wikimedia.org/wikipedia/commons/b/b5/800x600_Wallpaper_Blue_Sky.png"
]
const imageEl = document.querySelector('img')
let imageIndex = 0
document.querySelector('.prev').addEventListener('click', e => {
if (--imageIndex < 0) { imageIndex = images.length - 1 }
imageEl.src = images[imageIndex]
})
document.querySelector('.next').addEventListener('click', e => {
if (++imageIndex > images.length - 1) { imageIndex = 0 }
imageEl.src = images[imageIndex]
})
body {
background-color: #206a5d;
color: #ffffff;
text-align: center;
}
.container {
display: flex;
justify-content: center;
}
img {
max-width: 50%;
}
<h1>Zalman Build</h1>
<div class="container">
<button class="prev"><</button>
<img src="https://www.avalonwinery.com/wp-content/uploads/2013/12/200x300.gif">
<button class="next">></button>
</div>
The reason is because the resizeBttn code is firing before the image has actually finished downloading and loading into the DOM. I made these changes in your fiddle:
var imgHeight = $('#mainImg').height();
var currImg = 0;
var imagesSet = ["https://www.avalonwinery.com/wp-content/uploads/2013/12/200x300.gif","https://images.sftcdn.net/images/t_app-logo-xl,f_auto/p/ce2ece60-9b32-11e6-95ab-00163ed833e7/1578981868/the-test-fun-for-friends-logo.png", "https://hiveconnect.co.za/wp-content/uploads/2018/05/800x600.png", "https://upload.wikimedia.org/wikipedia/commons/b/b5/800x600_Wallpaper_Blue_Sky.png"];
var imageLoc = "images/zalman/"
$(document).ready(function() {
resizeBttn();
});
$( window ).resize(function() {
/* imgHeight = $('#mainImg').height() */; // commented out; we do this in resizeBttn now
resizeBttn();
});
$('#bttnLeft').click(function(){
prevImg();
/* imgHeight = $('#mainImg').height() */; // commented out; we do this in resizeBttn now
/* resizeBttn() */; // we do this as an `onload` to the image now
});
$('#bttnRight').click(function(){
nextImg();
/* imgHeight = $('#mainImg').height() */; // commented out; we do this in resizeBttn now
/* resizeBttn() */; // we do this as an `onload` to the image now
});
function nextImg(){
currImg++;
if(currImg>=imagesSet.length){
currImg=0;
}
$('#mainImg').attr("src",imagesSet[currImg]);
}
function prevImg(){
currImg--;
if(currImg<0){
currImg=imagesSet.length-1;
}
$('#mainImg').attr("src",imagesSet[currImg]);
}
function resizeBttn() {
imgHeight = $('#mainImg').height()
// removed superfluous doc.ready
$('#bttnLeft').css("height",imgHeight);
$('#bttnLeft').css("bottom",imgHeight/2-5);
$('#bttnRight').css("height",imgHeight);
$('#bttnRight').css("bottom",imgHeight/2-5);
}
And then rewrote your <img /> tag to call resizeBttn on onload:
<img id="mainImg" src="https://www.avalonwinery.com/wp-content/uploads/2013/12/200x300.gif" onload="resizeBttn()"/>
You can see this in action in this fiddle.
Also, a few additional notes on your code, at a glance:
You have some invalid HTML; you're going to want to run that through an HTML validator and fix it, because sometimes it is fine, but sometimes it can lead to all sorts of strange behavior.
You're playing fast and l0ose with global variables in your JS that get set in different functions; it might work OK while the script is small, but as things scale it can quickly become difficult to maintain
You should really avoid abusing the onclick to get link-like behavior from <li> elements; it can impact SEO as well as accessibility. I'd recommend simply using an anchor element inside or outside the <li>
I'd recommend taking a close look at this answer by user camaulay; he makes an excellent point that this may not require JS at all- if a more elegant solution exists w/ CSS it is probably going to be more performant and maintainable.

How can I animate a recently created DOM element in the same function?

I'm working to create an image gallery where the images will be composed by progressively fading in layers one on top of the other to form the final image.
I have many such layers so instead of loading them into many different <img> elements all at once (which would slow load time) I want to start off with a single <img id="base"> and then progressively add image elements with the jQuery .after() method, assign them the relevant sources and fade them in with a delay.
The problem is that I can't attach animations to the newly created elements because (I'm assuming) they don't exist yet within the same function. Here is my code:
HTML
<div id="gallery">
<img id="base" src="image-1.jpg">
</div>
CSS
#base {
opacity: 0;
}
.layers {
position: absolute;
top: 0;
left: 0;
opacity: 0;
}
JavaScript
$(document).ready(function () {
$("#base").animate({opacity: 1}, 300); //fade in base
for (var i = 1; i <= numberOfLayers; i++, gap += 300) {
// create a new element
$("#base").after("<img class='layers' src='" + imgName + ".png'>");
// fade that new element in
$("#gallery").children().eq(i).delay(gap).animate({opacity: '1'}, 300);
}
}
Please note that I've altered my actual code to illustrate this better. I'm fairly new at JavaScript but I'm a quick learner so I'd appreciate if you could tell me what I'm doing wrong and what solution I should pursue.
EDIT: I've included my code inside your JSFiddle (all you need to do is add the library-X.jpg images) : http://jsfiddle.net/pgoevx03/
I've tried to replicate the intent of the code in a cleaner/more flexible way. Please let me know if I can do anything else to help.
I'm not saying this is the best way to do it, but it should be easy enough to understand and use.
The code is untested, but should work just fine. The comments should help you out if there's any compilation error.
Note that I removed the first image in the gallery (with ID "base") from the HTML file. It will be appended the same way as the rest.
// Array storing all the images to append to the gallery
var galleryImages = [
"image-1.jpg",
"image-2.jpg",
"image-3.jpg",
"image-4.jpg",
"image-5.jpg",
"image-6.jpg",
"image-7.jpg",
"image-8.jpg",
"image-9.jpg",
"image-10.jpg"
];
// Index of the image about to be appended
var imgIndex = -1;
var baseID = "base";
$(document).ready(function() {
// Start appending images
appendAllImages();
});
// Append the images, one at a time, at the end of the gallery
function appendAllImages() {
//Move to the next image
imgIndex++;
//We've reached the last image: stop appending
if (imgIndex >= galleryImages.length) return;
//Create image object
var img = $("<img>", {
src: galleryImages[imgIndex],
});
if (imgIndex === 0) { // It's the base!
//Give the base ID to the first image
img.attr("id", baseID);
//Append the image object
$("#gallery").append(img);
} else { // It's a layer!
//Give the base ID to the first image
img.attr("class", "layers");
//Append the image object
$("#" + baseID).after(img);
}
//Fade in the image appended; append the next image once it's done fading in
img.animate({
opacity: 1,
}, 300, appendAllImages);
}

jQuery image resizing issue

I've found this line of code somewhere using firebug and I know you need to put something where I've put the 3... behind parseFloat, but I have no idea what.
It works when I fill in a random number but the width is never the correct one and want to use it on several pages with photographs so it's always the correct size.
script type="text/javascript">
var badBrowser = (/MSIE ((5\.5)|6)/.test(navigator.userAgent) && navigator.platform == "Win32");
$(document).ready(function(){
var scaledwidth = ((parseFloat(...)*($(window).height()/4000))+50).toFixed(0);
if (badBrowser) {
$('#container img').css('height',$(window).height()+'px');
}
$('#container').css('width',scaledwidth+'px');
imageresize();
});
jQuery(window).resize(function() {
var scaledwidth = ((parseFloat(...)*($(window).height()/4000))+50).toFixed(0);
if (badBrowser) {
$('#container img').css('height',$(window).height()+'px');
}
$('#container').css('width',scaledwidth+'px');
imageresize();
});
function imageresize() {
var height = $(window).height();
if ((height) > 1340){
var quality='1440';
} else if((height) > 980) {
var quality='1080';
} else if((height) > 680) {
var quality='720';
} else if((height) > 480) {
var quality='640';
} else {
var quality='320';
}
}
</script>
Thanks in advance!
It looks to me like the value you need to put there depends on the sum of the widths of all the images; so you can't just pick a value that works for all pages.
On the other hand, it also seems like a bad solution to the problem of keeping the images next to each other. Why set the width of the container? If you just ensure white-space doesn't wrap then all the images should sit next to each other without worrying about the container's width.
#container
{
white-space: nowrap; /* keep images on the same line */
font-size: 0; /* removes whitespace between images */
}
http://jsfiddle.net/f8y4Z/
From the javascript, we now only need the imageresize() (provided we use it to set different quality source images), and trigger it on ready and resize; no magic numbers required.
(For backwards compatibility with browsers that don't or poorly support white-space, you could use <nobr></nobr>)

Scroll event background change

I am trying to add a scroll event which will change the background of a div which also acts as the window background (it has 100% width and height). This is as far as I get. I am not so good at jquery. I have seen tutorials with click event listeners. but applying the same concept , like, returning scroll event as false, gets me nowhere. also I saw a tutorial on SO where the person suggest use of array. but I get pretty confused using arrays (mostly due to syntax).
I know about plugins like waypoints.js and skrollr.js which can be used but I need to change around 50-60 (for the illusion of a video being played when scrolled) ... but it wont be feasible.
here is the code im using:-
*
{
border: 2px solid black;
}
#frame
{
background: url('1.jpg') no-repeat;
height: 1000px;
width: 100%;
}
</style>
<script>
$(function(){
for ( i=0; i = $.scrolltop; i++)
{
$("#frame").attr('src', ''+i+'.jpg');
}
});
</script>
<body>
<div id="frame"></div>
</body>
Inside your for loop, you are setting the src attribute of #frame but it is a div not an img.
So, instead of this:
$("#frame").attr('src', ''+i+'.jpg');
Try this:
$("#frame").css('background-image', 'url(' + i + '.jpg)');
To bind a scroll event to a target element with jQuery:
$('#target').scroll(function() {
//do stuff here
});
To bind a scroll event to the window with jQuery:
$(window).scroll(function () {
//do stuff here
});
Here is the documentation for jQuery .scroll().
UPDATE:
If I understand right, here is a working demo on jsFiddle of what you want to achieve.
CSS:
html, body {
min-height: 1200px; /* for testing the scroll bar */
}
div#frame {
display: block;
position: fixed; /* Set this to fixed to lock that element on the position */
width: 300px;
height: 300px;
z-index: -1; /* Keep the bg frame at the bottom of other elements. */
}
Javascript:
$(document).ready(function() {
switchImage();
});
$(window).scroll(function () {
switchImage();
});
//using images from dummyimages.com for demonstration (300px by 300px)
var images = ["http://dummyimage.com/300x300/000000/fff",
"http://dummyimage.com/300x300/ffcc00/000",
"http://dummyimage.com/300x300/ff0000/000",
"http://dummyimage.com/300x300/ff00cc/000",
"http://dummyimage.com/300x300/ccff00/000"
];
//Gets a valid index from the image array using the scroll-y value as a factor.
function switchImage()
{
var sTop = $(window).scrollTop();
var index = sTop > 0 ? $(document).height() / sTop : 0;
index = Math.round(index) % images.length;
//console.log(index);
$("#frame").css('background-image', 'url(' + images[index] + ')');
}
HTML:
<div id="frame"></div>
Further Suggestions:
I suggest you change the background-image of the body, instead of the div. But, if you have to use a div for this; then you better add a resize event-istener to the window and set/update the height of that div with every resize. The reason is; height:100% does not work as expected in any browser.
I've done this before myself and if I were you I wouldn't use the image as a background, instead use a normal "img" tag prepend it to the top of your page use some css to ensure it stays in the back under all of the other elements. This way you could manipulate the size of the image to fit screen width better. I ran into a lot of issues trying to get the background to size correctly.
Html markup:
<body>
<img src="1.jpg" id="img" />
</body>
Script code:
$(function(){
var topPage = 0, count = 0;
$(window).scroll( function() {
topPage = $(document).scrollTop();
if(topPage > 200) {
// function goes here
$('img').attr('src', ++count +'.jpg');
}
});
});
I'm not totally sure if this is what you're trying to do but basically, when the window is scrolled, you assign the value of the distance to the top of the page, then you can run an if statement to see if you are a certain point. After that just simply change run the function you would like to run.
If you want to supply a range you want the image to change from do something like this, so what will happen is this will allow you to run a function only between the specificied range between 200 and 400 which is the distance from the top of the page.
$(function(){
var topPage = 0, count = 0;
$(window).scroll( function() {
topPage = $(document).scrollTop();
if(topPage > 200 && topPage < 400) {
// function goes here
$('#img').attr('src', ++count +'.jpg');
}
});
});

Javascript - Browser skips back to top of page on image change

I have some simple code to replace an image src. It is working correctly but everytime the image is updated, the browser skips right back to the top of the page.
I have several image tags in my page. All of which hidden, except for the first one. The script just iterates through them and uses the src attribute to update the first image.
Here is the code I am using:
var j = jQuery.noConflict();
var count = 1;
var img;
function update_main_image()
{
count++;
if (j('#main_image_picture_'+count).length > 0)
{
img = j('#main_image_picture_'+count).attr('src');
}
else
{
count = 1;
img = j('#main_image_picture_'+count).attr('src');
}
j(".main_image_picture_auto").fadeOut(1500, function() {
j(this).fadeIn();
j(this).attr("src", img);
});
}
j(document).ready(function()
{
setInterval(update_main_image, 6000);
});
Any ideas what might be causing it?
Any advice appreciated.
Thanks.
Try to add DIV around your IMG.main_image_picture_auto with width and height style properties setted to maximum posible image size, for example:
<div style='width:400px; height:400px; border: 0px; background: transparent; '>
<img class='main_image_picture_auto' src=''/>
</div>
<!-- Where width:400px and height:400px is maximum allowed image size -->
And I think, that is better to use setTimeout instead of setInterval
function update_main_image() {
// ....
setTimeout(update_main_image, 6000);
}
j(document).ready(function() {
setTimeout(update_main_image, 6000);
});
http://jsfiddle.net/UBEWS/

Categories

Resources