js implementation tab

Posted by johnsiilver on Thu, 23 Sep 2021 13:01:10 +0200

Tabs are often used in web pages, so how to implement tabs?

In the current framework, dom operation is omitted, and developers only need to pay attention to data. Is it really unnecessary to operate dom? Yes, it is necessary, but the program has helped to do this, and pure data logic will make the front end more difficult.

Overall structure

<div class="app" id="app">
			<div class="key-left">
				<div class="tap">1</div>
				<div class="tap">2</div>
				<div class="tap">3</div>
				<div class="tap">4</div>
				<div class="tap">5</div>
			</div>
			<div class="key-value">
				<div class="value"></div>
				<div class="value"></div>
				<div class="value"></div>
				<div class="value"></div>A
				<div class="value"></div>
			</div>
		</div>
		<script>
			let app = document.getElementById("app");
			let tap = app.getElementsByClassName("tap");
			let value = app.getElementsByClassName("value");
			let color = ['red','green','blue','yellow','pink'];
			for(let i = 0;i<value.length;i++){
				value[i].style.backgroundColor = color[i];
			}

Implemented with native dom

Control css properties

1, Toggle tab

Through the none value of the display attribute, set the required to block and the unnecessary to none;

for(let i = 0;i<tap.length;i++){
				tap[i].key = i;
				
				tap[i].onclick = function(){
					var key = this.key;
					//The first way is through the display attribute
					for(var k = 0;k<value.length;k++){
						value[k].style.display = "none";
						if(key === k){
							value[k].style.display = "block";
						}
					}
					//The second method is realized by displacement
					
				}
			}

2, Displacement tab.

Through displacement, the elements to be displaced are set as absolute positioning, and the height of each element is obtained to position it in the visual area. The advantage of using this method is that by slightly changing the thinking and positioning the height of the scroll bar, you can automatically scroll to the specified position by clicking the option page on the left.
If the element height is known and ordered
You need to make a mark on the outermost layer

	let sign = 0; //The location of the tag is the first by default

Set it to absolute positioning and save some data

let heightArr = []; //Used to get the height of each element in the value part
			let temp = 0; //Temporary transit
			let sign = 0; //The location of the tag is the first by default
			for (var i = 0;i < value.length;i++){
				// temp = value[i].clientHeight;
				// //This is the case when all elements are equal height
				// value[i].style.top = temp*i + "px";
				//If unequal height
				if(i != 0){
					temp += value[i].clientHeight;
				}
				value[i].style.top = temp + "px";
				let obj = {
					"height": value[i].clientHeight,
					"top": value[i].clientTop,
					"number": i,
				}
				heightArr.push(obj);
			}
 if(sign === key) return;
 let sum = key - sign; //Get a positive or negative value
 //Now use the simplest method
 for(var index = 0;index < value.length;index++){
	  value[index].style.top = parseInt(value[index].style.top) - sum*500 + "px";	
}

What if the height of each element is uncertain
We need to get the specific height of each displacement and encapsulate a function;

function specific(){
						let temp = 0;
						if(sum>0){
							for(var j = sign;j < key;j++){
								temp += value[j].clientHeight;
							}
							return temp;
						}else{
							for(var j = key;j < sign;j++){
								temp += value[j].clientHeight;
							}
							return -temp;
						}
					} 

That is, it returns a positive or negative value. You can call it when you use it

for(var index = 0;index < value.length;index++){
					    value[index].style.top = parseInt(value[index].style.top) - specific() + "px";	
					}

The most critical step: update the marker position after each click

	sign = key;

3, Positioning tab

The left option bar is fixed and the right layout is adaptive. Click the left option to locate the content position on the right
First, the layout is implemented with css, and elastic boxes can be used

.app{
			    width: 800px;
				height: 500px;
				margin: 10px auto;
				position: relative;
				/* overflow-y: scroll;- */
				/* display: flex; */
				/* justify-content: space-between; */
			}
			.key-left{
				height: 500px;
				width: 100px;
				left:0;
				position: absolute;
			}
			.key-left .tap{
				width: 100px;
				height: 100px;
				display: flex;
				justify-content: center;
				align-items: center;
				font-size: 50px;
				color: #4169E1;
			}
			.key-left .tap:hover{
				 background-color: burlywood;
			}
			.key-value{
				position: absolute;
				right: 0;
				width: 700px;
				height: 500px;
				/* overflow: hidden; */
			}
			.key-value .value{
				width: 700px;
				height: 500px;
				font-size: 50px;
				text-align: center;
				line-height: 500px;
				color: aliceblue;
				position: absolute;
				transition: all 0.3s linear;
			}
			.key-value .value-box{
				position: relative;
				width: 700px;
				height: 500px;
				overflow-y: scroll;
				overflow-x: hidden;
				transition: all 0.3s linear;
			}

Gets the outer box of the content area

			let valueBox = app.getElementsByClassName("value-box")[0];

The implementation idea is to set the height of the scroll bar

let sum = function(){
						let temp = 0;
						for(var index = 0;index < key;index++){
							temp += value[index].clientHeight;
						}
						return temp;
					}
valueBox.scrollTop = sum();

The same method is reset every time
You can also add a selected state

for(var index = 0;index < tap.length;index++){
						if(index === key){
							this.style.backgroundColor = "yellow";
							value[index].innerText = "Currently selected";
						}else{
							tap[index].style.backgroundColor = "";
							value[index].innerText = "Not selected";
						}
					}

Set default initial state

tap[0].style.backgroundColor = "yellow";
			value[0].innerText = "Currently selected";

This implementation

Yes
Ugly is ugly. Cover your face for the purpose of realizing function.
The above is implemented in a process oriented manner. Now do it again with object-oriented ideas

Object oriented implementation positioning tab

The dom structure remains unchanged, and a new JS file Tap.js is created

function Tap(className){
	if(!className) return;
	console.log(className);
	this.app = document.getElementById(className);
	this.tap = this.app.getElementsByClassName("tap");
	this.value = this.app.getElementsByClassName("value");
	this.color = ['red','green','blue','yellow','pink'];
	this.valueBox = this.app.getElementsByClassName("value-box")[0];
	this.heightArr = []; //Used to get the height of each element in the value part
	this.sign = 0; //The location of the tag is the first by default
}
//Initial state.
Tap.prototype.init = function(defindex = 0){
	let temp = 0;
	for (var i = 0;i < this.value.length;i++){
		if(i != 0){
			temp += this.value[i].clientHeight;
		}
		this.value[i].style.top = temp + "px";
		let obj = {
			"height": this.value[i].clientHeight,
			"top": this.value[i].clientTop,
			"number": i,
		}
		this.heightArr.push(obj);
	}
	for(let i = 0;i<this.value.length;i++){
		this.value[i].style.backgroundColor = this.color[i];
	}
	for(var index = 0;index < this.tap.length;index++){
		if(index === defindex){
			this.tap[index].style.backgroundColor = "yellow";
			this.value[index].innerText = "Currently selected";
		}else{
			this.tap[index].style.backgroundColor = "";
			this.value[index].innerText = "Not selected";
		}
	}
	this.valueBox.scrollTop = this.heightSum(defindex);
	return this;
}
//Height of scroll bar to jump
Tap.prototype.heightSum = function(defindex = 0){
	let temp = 0;
	for(var index = 0;index < defindex;index++){
		temp += this.value[index].clientHeight;
	}
	return temp;
}
//Click function
Tap.prototype.click = function(){
	for(let i = 0;i<this.tap.length;i++){
		this.tap[i].key = i;
		let that = this;
		this.tap[i].onclick = function(){
			var key = this.key;
			that.init(key);
		}
	}	
	return this
}

It seems to be getting more complicated
Reference Tap.js

<script src="./Tab.js" type="text/javascript"></script>

Used in initialization

window.onload = function(){
				new Tap('app').init(2).click();
			}

That's it.

Topics: Javascript Front-end html css