Load new video src on link / video click html5 [duplicate] - html

This question already has answers here:
Can I use javascript to dynamically change a video's source?
(10 answers)
Closed 3 years ago.
I have a html5 video loaded on my page which looks like this:
'
<div class="row">
<video controls class="vid-center" poster="<?php echo get_template_directory_uri(); ?>/img/video-bg.png" id="video-id">
<div class="video-overlay">logo and play bitton here logo and play bitton here </div>
<source src="http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_1mb.mp4" type="video/mp4">
<source src="movie.ogg" type="video/ogg">
Your browser does not support the video tag. </video>
</div>
<div class="video-cont"></div>
</section>
<div class="row">
<div class="large-3 small-4 columns">
<img src="<?php echo get_template_directory_uri(); ?>/img/thumb-vid1.png" alt=""/>
<h4>Video name 1</h4>
<p>Lorum ipsum neg reyo sum tomenyen</p>
</div>
<div class="large-3 small-4 columns">
<img src="<?php echo get_template_directory_uri(); ?>/img/thumb-vid2.png" alt=""/>
<h4>Video name 1</h4>
<p>Lorum ipsum neg reyo sum tomenyen</p>
</div>
<div class="large-3 small-4 columns">
<img src="<?php echo get_template_directory_uri(); ?>/img/thumb-vid3.png" alt=""/>
<h4>Video name 1</h4>
<p>Lorum ipsum neg reyo sum tomenyen</p>
</div>
<div class="large-3 hide-for-small-only columns">
<img src="<?php echo get_template_directory_uri(); ?>/img/thumb-vid4.png" alt=""/>
<h4>Video name 1</h4>
<p>Lorum ipsum neg reyo sum tomenyen</p>
</div>
</div>
'
I am trying to create a basic gallery so when a user selects / clicks / presses one of the thumbnail images it will load a new video into the video player i.e change the video source depending on which img / div is clicked. If thumbnail clicked then load the string src into the player and autoplay.
Is this possible to do in JavaScript to change the current video src?
Any help would be greatly appreciated.

This demo is twofold:
The top half features four divs, which upon loading will dynamically have a video each.
The bottom half has one video and a playlist. The video element will play whatever is clicked on the playlist.
What they have in common is that they are sharing the same video and image files. Basically, this demonstration shows 2 ways to go about having multiple videos on a page.
The top example starts of as 4 normal divs.
loadPlayers() is called on pageload. It will:
Collect the 4 divs into a NodeList.
Convert the NodeList into an array.
Array.prototype.map.call() will also call an anonymous function that will gather each of the divs ids and the pass them into the next function...
struct(ID) is responsible for building the video elements.
The ids from loadPlayers() is now processed into strings that will define values for src for each video.
The video and source elements are made with createElement()
The attributes are added by setAttribute()
Finally, each video is added into it's corresponding div with appendChild().
The bottom example dynamically creates a playlist from an array of strings provided by the developer (this can be modified so the user can interact with creating a playlist.)
generateList(arr, str) requires an array of strings and an element to add playlist items into. The first argument, arr is an array, each string representing the file name of a video/image (sans extension). The second argument is a string that must be syntactically like a selector. ex:
<div id="vid3"></div> = "#vid3"
<nav></nav> = "nav"
<main class="box"></main> = ".box"
<input type="number"/> = "input[type='number']"
Although this argument can be any element, it's suggested that a ul, ol, dl, or nav are better suited to host the playlist items.
Using array.map() to apply the function eachItem() to each array element, it is then returned as a complete playlist; each item is an anchor with a clipped background image.
When each item is clicked, the eventListener will trigger the function playSelect()
PLUNKER
README.md
Snippet
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Video Gallery</title>
<style>
html,
body {
width: 100%;
height: 100%;
font: 400 16px/1.45 'Verdana';
}
body {
position: relative;
background: #111;
color: #EEE;
}
.gallery {
display: flex;
flex-flow: row wrap;
justify-content: space-between;
width: 100vw;
height: 50vh;
}
#sec2 {
justify-content: center;
}
.vid {
width: 240px;
flex 0 2 auto;
}
.solo {
width: 480px;
flex: 0 2 auto;
}
video {
width: 100%;
height: auto;
}
.list {
border: 3px inset #fc3;
margin: 0 10px;
}
.list a {
text-decoration: none;
cursor: pointer;
display: block;
width: 75px;
height: 75px;
background-repeat: no-repeat;
background-size: cover;
color: #00f;
font-size: 1rem;
border-bottom: 1px solid #fc0;
}
.list a:hover {
color: #0ff;
}
#media screen and (max-width: 768px) {
#sec1 {
justify-content: flex-start;
}
#sec2 {
justify-content: flex-end;
}
.vid {
flex: 0 2 auto;
width: 160px;
}
.solo {
flex: 0 2 auto;
width: 320px;
}
}
</style>
</head>
<body>
<section id="sec1" class="gallery">
<div id="vid1" class="vid"></div>
<div id="vid2" class="vid"></div>
<div id="vid3" class="vid"></div>
<div id="vid4" class="vid"></div>
</section>
<section id="sec2" class="gallery">
<div id="vid5" class="solo">
<video id="vid5v" poster="https://glpjt.s3.amazonaws.com/so/av/vid5.png" controls=true>
<source src="https://glpjt.s3.amazonaws.com/so/av/vid5.mp4" type="video/mp4">
</video>
</div>
<nav id="vNav5" class="list"></nav>
</section>
<script>
var vNav5 = document.getElementById('vNav5');
var playlist = ['vid1', 'vid2', 'vid3', 'vid4'];
function loadPlayers() {
var divs = document.querySelectorAll('.vid');
var ids = Array.prototype.map.call(divs, function(obj) {
var ID = obj.id;
return vStruct(ID);
});
}
function vStruct(id) {
var vTag = document.createElement('video');
var vSrc = document.createElement('source');
var vDiv = document.getElementById(id);
var vIDv = id.toString();
vTag.id = vIDv + 'v';
var vUrl = 'https://glpjt.s3.amazonaws.com/so/av/';
var vPng = vUrl + id + '.png';
var vMp4 = vUrl + id + '.mp4';
vTag.setAttribute('poster', vPng);
vTag.setAttribute('controls', true);
vSrc.setAttribute('src', vMp4);
vSrc.setAttribute('type', 'video/mp4');
vDiv.appendChild(vTag);
vTag.appendChild(vSrc);
}
function generateList(vArr, vStr) {
var vTgt = document.querySelector(vStr);
var lArr = vArr.map(eachLink);
lArr.forEach(function(obj) {
vTgt.appendChild(obj);
});
}
function eachLink(id) {
var ID = id.toString();
var vUrl = 'https://glpjt.s3.amazonaws.com/so/av/';
var vLink = document.createElement('a');
vLink.setAttribute('href', vUrl + ID + '.mp4');
vLink.textContent = ID;
vLink.style.backgroundImage = "url('" + vUrl + ID + ".png')";
return vLink;
}
vNav5.addEventListener('click', playSelect, false);
function playSelect(e) {
e.preventDefault();
if (e.currentTarget !== e.target) {
var choice = e.target.href;
var parent = e.target.parentElement;
var uncle = parent.previousElementSibling;
var vid = uncle.querySelector('video');
if (vid.playing) {
vid.pause();
}
vid.src = "";
vid.src = choice;
vid.load();
vid.play();
e.stopPropagation();
}
}
loadPlayers();
generateList(playlist, '#vNav5');
</script>
</body>
</html>

Related

How to stack divs by click on image

Is there any way to make a div appear stacked on top of another one, by clicking on a button/image?
The problem I have:
I want a poster to appear if I click on it in the selector. I want it to stay, once I click on another poster, which then will stack on top of the previous one. Is it possible to make this a loop, so no matter how often I click different objects the old divs will always stay below the newest one?
(See pictures attached)
first click:
second click:
and so on...
Thanks in advance!
I will cut down the explaination to some documentations such as how to create an element through JS. Teachign every single step would blow the scope of Stackoverflow.
If you know how to create an element through JS you need a variable such as counter in my code that is raised by every single time you run the script with: counter = counter + 1
You set a z-index through JS with element.style.zIndex = variableand thanks to the rising counter it will set the new element over the other element (z-axis-wise).
To rotate the element you can use transform: rotate() which I randomized by calling a variable: rotation = Math.round(Math.random() * 40 - 20); which will randomize a number between -20 and 20.
var preview = document.querySelector('.preview'),
counter = '1';
picture = ''
function addRed() {
picture = 'red';
addPicture();
}
function addGreen() {
picture = 'green';
addPicture();
}
function addBlue() {
picture = 'blue';
addPicture();
}
function addYellow() {
picture = 'yellow';
addPicture();
}
function addPicture() {
var img = document.createElement('img'),
rotation = Math.round(Math.random() * 40 - 20);
switch (picture) {
case 'red':
img.src = 'https://via.placeholder.com/350.jpg/FF0000';
break;
case 'green':
img.src = 'https://via.placeholder.com/350.jpg/00FF00';
break;
case 'blue':
img.src = 'https://via.placeholder.com/350.jpg/0000FF';
break;
case 'yellow':
img.src = 'https://via.placeholder.com/350.jpg/FFFF00';
break;
}
img.style.position = 'absolute';
img.style.top = '50%';
img.style.left = '50%';
img.style.transform = 'translate(-50%, -50%) rotate(' + rotation + 'deg)';
img.style.zIndex = counter;
preview.appendChild(img);
var counter = counter + 1;
}
.container {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-gap: 10px;
}
.preview {
grid-column: 1 / -1;
aspect-ratio: 1 / 1;
position: relative;
}
.selector {
padding: 10px;
}
.selector > img {
display: block;
object-fit: contain;
width: 100%;
}
<div class="container">
<div class="preview"></div>
<div class="selector"><img src="https://via.placeholder.com/100.jpg/FF0000" onclick="addRed()"></div>
<div class="selector"><img src="https://via.placeholder.com/100.jpg/00FF00" onclick="addGreen()"></div>
<div class="selector"><img src="https://via.placeholder.com/100.jpg/0000FF" onclick="addBlue()"></div>
<div class="selector"><img src="https://via.placeholder.com/100.jpg/FFFF00" onclick="addYellow()"></div>
</div>
Create a div called preview, and makes its position relative. This is necessary because this creates a new stacking context.
Create another container that will hold the list of images to choose from. I choose a section with an unordered list which will contain these images as list elements.
Set overflow-x auto, so a scrollbar appears once the amount of images exceed the container width.
In your stylesheet, select the images which are child of our preview div, and make their position absolute, with a top margin of 0. This makes sure that all images are stacked in the same x-y direction. This works because the preview div also has display: flex, with align-items: center as well as justify-content: center.
In your script file, select these list images - I called them posters.
const posters = document.querySelectorAll(".poster");
Create two variables called zIndex ( = 1) and rotated ( = true).
Attach an event listener to each of the poster image inside this list of images, using a for...of loop.
for (const poster of posters) {
poster.addEventListener("click", () => onPosterClicked(poster));
}
In this event handler, we select the preview div, and clone the clicked image using cloneNode() method. We also give it class of shown so, our styling for images inside preview work.
We then increment the z-index, and assign this incremented z-index to this cloned image's style.
cloned.style.zIndex = ++zIndex;
For decorational purposes, we switch between rotated and non-rotated transforms, so each image new image added is rotated differently to our previous image.
if (rotated) {
cloned.style.transform = "rotate(-5deg)";
}
rotated = !rotated;
Note: We can achieve this rotation directly through CSS, by using nth-child selectors.
Finally, we append this cloned image to our preview div.
preview.appendChild(cloned);
The complete code looks like this:
function onPosterClicked(poster) {
const preview = document.querySelector(".preview");
const cloned = poster.cloneNode();
cloned.classList = "shown";
cloned.style.zIndex = ++zIndex;
if (rotated) {
cloned.style.transform = "rotate(-5deg)";
}
rotated = !rotated;
preview.appendChild(cloned);
}
const posters = document.querySelectorAll(".poster");
let zIndex = 1;
let rotated = true;
for (const poster of posters) {
poster.addEventListener("click", () => onPosterClicked(poster));
}
*,
*::before,
*::after {
box-sizing: border-box;
padding: 0;
margin: 0;
}
body {
width: 100%;
min-height: 100vh;
display: flex;
flex-direction: column;
}
.preview {
width: 100%;
height: 70vh;
display: flex;
align-items: center;
justify-content: center;
position: relative;
}
.shown {
height: 100%;
position: absolute;
top: 0;
border: 2px solid black;
}
.list {
width: 100%;
padding: 4rem 2rem;
}
.list ul {
display: flex;
flex-flow: row nowrap;
gap: 5px;
overflow-x: auto;
list-style: none;
}
.poster {
max-height: 300px;
object-fit: cover;
}
<body>
<div class="preview">
<img class="shown" src="https://picsum.photos/seed/picsum/200/300" alt="test image" />
</div>
<section class="list">
<ul>
<li>
<img class="poster" src="https://picsum.photos/seed/picsum/200/300" alt="sample poster image" />
</li>
<li>
<img class="poster" src="https://picsum.photos/seed/picsum/200/300" alt="sample poster image" />
</li>
<li>
<img class="poster" src="https://picsum.photos/seed/picsum/200/300" alt="sample poster image" />
</li>
<li>
<img class="poster" src="https://picsum.photos/seed/picsum/200/300" alt="sample poster image" />
</li>
<li>
<img class="poster" src="https://picsum.photos/seed/picsum/200/300" alt="sample poster image" />
</li>
<li>
<img class="poster" src="https://picsum.photos/seed/picsum/200/300" alt="sample poster image" />
</li>
<li>
<img class="poster" src="https://picsum.photos/seed/picsum/200/300" alt="sample poster image" />
</li>
<li>
<img class="poster" src="https://picsum.photos/seed/picsum/200/300" alt="sample poster image" />
</li>
</ul>
</section>
<script async defer src="main.js"></script>
</body>

Appending Text to Div Extends Div Beyond Initial CSS Grid

I've created a basic CSS Grid and had everything positioned where I wanted it. When I run my JS (appends info from an API call to a div), the div's dimension push beyond the borders of the viewport. Is there a way to prevent the overall body element from changing and just have the div dynamically increase height?
pics: https://imgur.com/a/wJAcW
I've tried so many different things and can't seem to figure this out. My fallback will be to just overwrite the div rather than append to it. Code is below.
//Set initial latitute and longitude variables, to be used later
var lat = 0;
var long = 0;
//Google Geocode API to find the latitude and longitude of the txtAddress
$("#submit").on("click", function() {
var userInput = $("#txtAddress").val();
//trim the user input to the form needed for the api
var userSearchTerm = userInput.split(' ').join('+');
//call the google geocode api
var queryURLGeocode = "https://maps.googleapis.com/maps/api/geocode/json?address=" + userSearchTerm + "&key=AIzaSyCSAYHZn9fz13c3bsl_RcS13HJu8wDJXCU"
$.ajax({
url: queryURLGeocode,
method: "GET"
})
.done(function(response) {
//Set latitude and longitude from the returned object
lat = response.results[0].geometry.location.lat;
//limit decimal points to 4 (xx.xxxx) - form needed for hiking api
lat = lat.toFixed(4);
long = response.results[0].geometry.location.lng;
long = long.toFixed(4);
//Call the hiking project api
var queryURL = "https://www.hikingproject.com/data/get-trails?lat=" + lat + "&lon=" + long + "&maxDistance=10&key=200206461-4fa8ac1aa85295888ce833cca1b5929f"
$.ajax({
url: queryURL,
method: "GET"
})
.done(function(response) {
// loop through the response trails and add info to the site
for (i = 0; i < response.trails.length; i++) {
var contentDivTitle = $("<div> class='newTrailTitle'");
var contentDivMain = $("<div> class='newTrailDescription'");
contentDivTitle.text("Name: " + response.trails[i].name + " Location: " + response.trails[i].location);
contentDivMain.text("Summary: " + response.trails[i].summary);
$("#search-results").append(contentDivTitle);
$("#search-results").append(contentDivMain);
}
});
});
});
html,
body {
background-color: black;
margin: 10px;
}
h1,
h3 {
color: white;
text-align: center;
padding: 5px;
line-height: 1px;
}
h1 {
/* automatically changes lowercase to uppercase text; */
text-transform: uppercase;
}
sub {
color: white;
text-align: center;
line-height: 1px;
font-size: 15px;
font-weight: lighter;
}
.container {
display: grid;
grid-template-columns: auto;
grid-template-rows: 800px 500px 200px 50px 100px;
grid-gap: 3px;
}
.container>div {
display: flex;
justify-content: center;
align-items: center;
font-size: 1em;
}
.container>div:nth-child(1n) {
background-color: black;
}
.container>div:nth-child(2n) {
background-color: blue;
}
.container>div:nth-child(3n) {
background-color: red;
}
.container>div:nth-child(4n) {
background-color: yellow;
}
.container>div:nth-child(5n) {
background-color: green;
}
label {
color: white;
}
#main {
background-image: url("assets/images/etienne-bosiger-367964.jpg");
background-size: cover;
background-repeat: no-repeat;
}
#au,
#cr {
display: block;
margin: auto;
}
#groupPic {
padding: 10px;
}
<html>
<head>
<link rel="stylesheet" href="test.css">
</head>
<body>
<div class="container">
<div id="main">
<div id="title">
<h1>kairns<sub>®</sub></h1>
<h3>"find your trail"</h3>
<div class="search-div">
<label for="txtAddress">Enter Address: </label>
<input type="text" name="txtAddress" id="txtAddress">
<button type="button" id="submit">Search</button>
</div>
</div>
</div>
<div class="search-results" id="search-results">2</div>
<div>
<p id="au">About Us</p>
<img id="groupPic" src="http://via.placeholder.com/150x150" alt="placeholder image">
<p id="cr">Copyright 2018.</p>
</div>
<div>4</div>
<div>
<p>Powered by
Google Maps,
Open Weather Map, and Hiking Project
</p>
</div>
</div>
<!-- JAVASCRIPT -->
<!-- jQuery -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<!-- custom javaScript -->
<script type='text/javascript' src='assets/javascript/logic.js'></script>
</body>
</html>
All in-flow children of the #search-results element will align vertically if you apply:
#search-results {
display: flex;
flex-direction: column;
}

Stop a youtube video in an iframe when the div it is in is display:none

I have a div, "c1" which is display:none except when div "p1" is hovered. In "c1" there is a YouTube video set to auto play. in chrome when the div is visible the video starts but when it disappears the video keeps playing. Is there a way to stop it with only HTML and CSS or do I need JS?
HTML:
<div class="p1 parent"></div>
<div class="c1 child"><iframe class="embededInChild" src="https://www.youtube.com/embed/VLrULbtD-oo?autoplay=1" frameborder="1"></iframe>
<p class="childDescription">enjoy beautiful downtown bethesda just X miles from campus!</p></div>
CSS:
.child {
display: none;
width:494px;
height:300px;
position:absolute;
background-color: #E3EBF1;
border-radius: 10px;
border: 1px solid #333333;
left:0px;
top:-320px;
}
.parent{
background-color: #7BB9E0;
width:110px;
height:110px;
border:2px solid black;
display: block;
border-radius:55px;
margin: 5px;
display: inline-block;
float:left;
}
.parent:hover{
background-color: #CCCCCC;
border-color: #93305D;
}
.embededInChild{
width:474px;
height:250px;
margin: 5px 10px 0px 10px;
}
p.childDescription{
line-height:12px;
margin:5px 5px 0px 5px;
padding:0px;
color: #333333;
text-align: center;
}
.p1:hover + .c1 {
display: block;
}
I adopted the script shared earlier in the comment and I have created an alternate version to play video on mouseenter on an element and stopping when moving out of the element.
http://jsfiddle.net/588vwkrw/6/
Code for your reference (But use the JSfiddle, as the external youtube script link is not working within the SO snippet widget )
var players = []; // an array where we stock each videos youtube instances class
$(function() {
var playvideo = function() {
var id = $(this).attr("href");
$(id).show();
var pid = id.replace("#", "")
players[pid].playVideo();
}
var stopvideo = function() {
var id = $(this).attr("href");
$(id).hide();
var pid = id.replace("#", "")
players[pid].stopVideo();
}
$(".playvid").mouseenter(playvideo).mouseleave(stopvideo);
});
function onYouTubeIframeAPIReady() {
var videos = $('iframe'), // the iframes elements
playingID = null; // stock the current playing video
for (var i = 0; i < videos.length; i++) // for each iframes
{
var currentIframeID = videos[i].id; // we get the iframe ID
//alert(currentIframeID);
players[currentIframeID] = new YT.Player(currentIframeID); // we stock in the array the instance
}
}
onYouTubeIframeAPIReady();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script async="false" type="text/javascript" src="https://www.youtube.com/player_api"></script>
<div>
Hover on the anchor links to play related videos</div>
<a class="playvid" href="#player"> Play video 1 </a>
<br/>
<br/>
<br/>
<a class="playvid" href="#player2"> Play Jquery video</a>
<br/>
<br/>
<br/>
<iframe style="display:none" id="player" width="385" height="230" src="https://www.youtube.com/embed/erDxb4IkgjM?rel=0&wmode=Opaque&enablejsapi=1;showinfo=0;controls=0" frameborder="0" allowfullscreen></iframe>
<iframe style="display:none" id="player2" width="385" height="230" src="https://www.youtube.com/embed/hMxGhHNOkCU?rel=0&wmode=Opaque&enablejsapi=1;showinfo=0;controls=0" frameborder="0" allowfullscreen></iframe>
All I did was replace the src attribute in the iframe with nothin':
$('.youtube_div .close').on('click', function() {
$('.youtube_div iframe').attr('src', '');
})
Seems to work.

How to include caption on web page for gallery using magnific popup?

I am trying to include a caption on the actual webpage under the image while using the magnificence popup gallery. Using a div and class caption or carousel-caption, I am unable to do so without the images in the gallery stacking vertically one by one. How can I do this?
<a href="img/base/ggg.PNG" title="HELLO" class="chicken">
<img src="img/base/pop.PNG" alt="remember your alt tag" />
</a>
$(document).ready(function() {
$('.chicken').magnificPopup({
type: 'image',
gallery:{enabled:true}
// other options here
// end each line (except the last) with a comma
});
});
js fiddle: https://jsfiddle.net/sb4btox7
Alright, have a look at this, I adjusted your function a bit:
$(document).ready(function() {
$('.chicken').magnificPopup({
type: 'image',
gallery: {
enabled: true
}
}).each(function() { // Here I chain a loop to each .chicken element
// Now we append the title inside the .chicken element
$(this).append('<div class="title">' + $(this).attr('title') + '</div>');
});
});
The CSS:
.chicken {
display: inline-block;
width: 20%;
margin: 10px;
}
.chicken img {
width: 100%; /* set it to 100% of it's parents width */
vertical-align: bottom;
}
.chicken .title {
text-align: center;
}
and here's the DEMO.
Now you can also just add the title directly to the html like this:
<a href="http://placehold.it/350x250" title="The Title A" class="chicken">
<img src="http://placehold.it/350x250" />
<div class="title">The Title A</div>
</a>

Can I do image orientation detection with html or css?

If I have an image on html page, can I use html or css do the following?
When width of the image is greater than height, set height to a fixed value and auto stretch width; when height is greater than width, set width and auto stretch height?
Thanks a lot!
No, this is not possible - conditional statements cannot be handled with HTML or CSS, but you have to do it with JS.
An example would be calculating (and perhaps storing for future use) the aspect ratio of an image to determine whether is it in landscape or portrait mode:
$(document).ready(function() {
$("img").each(function() {
// Calculate aspect ratio and store it in HTML data- attribute
var aspectRatio = $(this).width()/$(this).height();
$(this).data("aspect-ratio", aspectRatio);
// Conditional statement
if(aspectRatio > 1) {
// Image is landscape
$(this).css({
width: "100%",
height: "auto"
});
} else if (aspectRatio < 1) {
// Image is portrait
$(this).css({
maxWidth: "100%"
});
} else {
// Image is square
$(this).css({
maxWidth: "100%",
height: "auto"
});
}
});
});
See fiddle here - http://jsfiddle.net/teddyrised/PkgJG/
2019 update: As ES6 is becoming the defacto standard, the above jQuery code can be easily refactored into vanilla JS:
const images = document.querySelectorAll('img');
Array.from(images).forEach(image => {
image.addEventListener('load', () => fitImage(image));
if (image.complete && image.naturalWidth !== 0)
fitImage(image);
});
function fitImage(image) {
const aspectRatio = image.naturalWidth / image.naturalHeight;
// If image is landscape
if (aspectRatio > 1) {
image.style.width = '100%';
image.style.height = 'auto';
}
// If image is portrait
else if (aspectRatio < 1) {
image.style.width = 'auto';
image.style.maxHeight = '100%';
}
// Otherwise, image is square
else {
image.style.maxWidth = '100%';
image.style.height = 'auto';
}
}
div.wrapper {
background-color: #999;
border: 1px solid #333;
float: left;
margin: 10px;
width: 200px;
height: 250px;
}
<div class="wrapper">
<img src="http://placehold.it/500x350" />
</div>
<div class="wrapper">
<img src="http://placehold.it/350x500" />
</div>
<div class="wrapper">
<img src="http://placehold.it/500x500" />
</div>
However, if all you want is to ensure the image fits within an arbitrary sized container, using simple CSS will work:
div.wrapper {
background-color: #999;
border: 1px solid #333;
float: left;
margin: 10px;
width: 400px;
height: 400px;
}
div.wrapper img {
width: auto
height: auto;
max-width: 100%;
max-height: 100%;
}
<div class="wrapper">
<img src="http://placehold.it/500x350" />
</div>
<div class="wrapper">
<img src="http://placehold.it/350x500" />
</div>
<div class="wrapper">
<img src="http://placehold.it/500x500" />
</div>