Yuki.kuroshita
Yuki.kuroshita

Reputation: 779

Setting width of element using Javascript gives unexpected results

I am trying to make a javascript image carousel for a school project. I am in early stages of making it, however I am already running into problems.

Here is the code:

class Carousel{
		constructor(selector=".carousel"){
			const number = 5;
			const autoscroll = 'off';
			const width = "100%";
			const height  = "200px";
			this.selector = document.querySelector(selector);
			this.number = (this.selector.dataset.viewNumber==undefined)? number : this.selector.dataset.viewNumber;
			this.autoScroll = (this.selector.dataset.autoscroll==undefined)? autoscroll : this.selector.dataset.autoscroll;
			this.width = (this.selector.dataset.width==undefined)? width : this.selector.dataset.width;
			this.height = (this.selector.dataset.height==undefined)? height : this.selector.dataset.height;
		}
		makeCarousel(){

			let srcList=[];
			let str = "<div class='previous'><p>&larr;</p></div><div class='rotater'>";
			let src;
			for (let i of this.selector.children){
				src = i.getAttribute("src");
				srcList.push(src);
				str= `${str}<div class='carousel-img-holder'><img src=${src} class='carousel-img' /></div>`;
			}
			str=`${str}</div><div class='next'><p>&rarr;</p></div>`;
			this.selector.innerHTML = str;
			const styler = this.selector.style;
			styler.width = this.width;
			styler.height = this.height;
			styler.display = "flex";
			const rotate = this.selector.childNodes[1];
			rotate.style.display = "flex";
			rotate.style.height = "100%";
			rotate.style.width = "100%";
			rotate.style.overflow = "scroll";
			for (let i of this.selector.childNodes[1].childNodes){
				let height = this.selector.getBoundingClientRect().height+"px";
				let width = (this.selector.getBoundingClientRect().width/this.number)+"px";
				i.setAttribute('style',`height: ${height};width: ${width}`);
				i.childNodes[0].style.maxWidth = "100%";
				i.childNodes[0].style.maxWidth = "100%";
			}
		}

	}

	const carousel = new Carousel("#carousel");
	carousel.makeCarousel();
	console.log("Width from getBoundingClientRect: "+document.querySelector(".carousel-img-holder").getBoundingClientRect().width)
  console.log("Width from css style: "+document.querySelector(".carousel-img-holder").style.width)
<body style="background: #444">
	<div id="carousel" data-view-number=7 data-autoscroll="on" data-width="100%" data-height="200px">
		<img src="https://swachhcoin.com/img/001.png">
		<img src="https://swachhcoin.com/img/002.png">
		<img src="https://swachhcoin.com/img/003.png">
		<img src="https://swachhcoin.com/img/004.png">
		<img src="https://swachhcoin.com/img/006.png">
		<img src="https://swachhcoin.com/img/007.png">
		<img src="https://swachhcoin.com/img/009.png">
		<img src="https://swachhcoin.com/img/010.png">
		<img src="https://swachhcoin.com/img/011.png">
		<img src="https://swachhcoin.com/img/012.png">
		<img src="https://swachhcoin.com/img/013.png">
		<img src="https://swachhcoin.com/img/014.png">
		<img src="https://swachhcoin.com/img/015.png">
	</div>
</body>

I am trying to show only the number of images mentioned in the data-view-number attribute on one page at a time. So I am calculating the width of the outer div from getBoundingClientRect().width, dividing it by the data-view-number value and assigning it to the style attribute using setAttribute. However, it is not coming out as desired. So I checked the width of the object. In google dev tools, it is showing that the style is applied correctly. So I tried to get it by getBoundingClientRect() and it shows a different width altogether. Is it because I am using percentage widths on the parent? I tried changing it to pixel width but it did not work.

I printed out both the values of the width in the console. As you can see, these two widths are not coming out to be equal. I don't understand why. I can't understand what I am doing wrong. Any pointers are appreciated. I don't know if this would have been easier in jquery but I want to avoid it because our professor told us to avoid using jquery if possible.

Upvotes: 0

Views: 153

Answers (1)

Nandita Sharma
Nandita Sharma

Reputation: 13407

You are not taking into account the widths of next and prev divs. You should subtract that also from the width of carousel.

Basically the logic should be

widthOfImg = (Totalwidth - Width of previous div - Width of next div )/this.number

Also add the following style

body {
    margin :0;
}

Also changed this line

rotate.style.width = "calc(100% - 32px)";

Also instead of applying max-width to the image, apply the same width to the image that you are adding on carousel-img-holder div

i.childNodes[0].style.width= width ;

See the updated code below

class Carousel{
		constructor(selector="#carousel"){
			const number = 5;
			const autoscroll = 'off';
			const width = "100%";
			const height  = "200px";
			this.selector = document.querySelector(selector);
			this.number = (this.selector.dataset.viewNumber==undefined)? number : this.selector.dataset.viewNumber;
			this.autoScroll = (this.selector.dataset.autoscroll==undefined)? autoscroll : this.selector.dataset.autoscroll;
			this.width = (this.selector.dataset.width==undefined)? width : this.selector.dataset.width;
			this.height = (this.selector.dataset.height==undefined)? height : this.selector.dataset.height;
		}
		makeCarousel(){

			let srcList=[];
			let str = "<div class='previous'><p>&larr;</p></div><div class='rotater'>";
			let src;
			for (let i of this.selector.children){
				src = i.getAttribute("src");
				srcList.push(src);
				str= `${str}<div class='carousel-img-holder'><img src=${src} class='carousel-img' /></div>`;
			}
			str=`${str}</div><div class='next'><p>&rarr;</p></div>`;
			this.selector.innerHTML = str;
			const styler = this.selector.style;
			styler.width = this.width;
			styler.height = this.height;
			styler.display = "flex";
			const rotate = this.selector.childNodes[1];
			rotate.style.display = "flex";
			rotate.style.height = "100%";
			rotate.style.width = "calc(100% - 32px)";
			for (let i of this.selector.childNodes[1].childNodes){
				let height = this.selector.getBoundingClientRect().height+"px";
				let width = ( (this.selector.getBoundingClientRect().width - document.getElementsByClassName('next')[0].getBoundingClientRect().width - document.getElementsByClassName('previous')[0].getBoundingClientRect().width ) /this.number)+"px";

				i.setAttribute('style',`height: ${height};width: ${width}`);
				i.childNodes[0].style.width= width ;
				i.childNodes[0].style.width= width ;
			}
		}

	}

	const carousel = new Carousel("#carousel");
	carousel.makeCarousel();
<body style="background: #444;margin:0;">
	<div id="carousel" data-view-number=7 data-autoscroll="on" data-width="100%" data-height="200px">
		<img src="https://swachhcoin.com/img/001.png">
		<img src="https://swachhcoin.com/img/002.png">
		<img src="https://swachhcoin.com/img/003.png">
		<img src="https://swachhcoin.com/img/004.png">
		<img src="https://swachhcoin.com/img/006.png">
		<img src="https://swachhcoin.com/img/007.png">
		<img src="https://swachhcoin.com/img/009.png">
		<img src="https://swachhcoin.com/img/010.png">
		<img src="https://swachhcoin.com/img/011.png">
		<img src="https://swachhcoin.com/img/012.png">
		<img src="https://swachhcoin.com/img/013.png">
		<img src="https://swachhcoin.com/img/014.png">
		<img src="https://swachhcoin.com/img/015.png">
	</div>
</body>

Upvotes: 2

Related Questions