En la misma página tengo varias secciones.
Se mostrará una section y esto sucederá usando una class active .
En la misma página tengo los botones li 1, 2 y 3 y cuando hago clic en uno de ellos aparece la section relacionada con él y desaparece la anterior. Para ese propósito estoy usando Javascript.
También en la misma página tengo un botón siguiente y anterior. Cuando hago clic en el siguiente botón, debería aparecer la siguiente section y la anterior debería desaparecer.
Y también el li relacionado a la sección debe tener la class active , lo mismo para el anterior: cuando hago clic en él debe ir a la section antigua y el actual debe desaparecer y la class li debe estar active .
Cuando estoy en la primera section el botón anterior debería desaparecer y cuando estoy en la última sección, el botón siguiente debería desaparecer.
¿Cómo puedo implementar este comportamiento para los botones siguiente y anterior de esta manera usando Javascript?
¿Alguna ayuda por favor?
let tab = document.querySelector(".nav li"); let tabs = document.querySelectorAll(".nav li"); let tabsArray = Array.from(tabs); let section = document.querySelectorAll(".section"); let sectionArray = Array.from(section); let nextButton = document.querySelector(".next"); let prevButton = document.querySelector(".previous"); let current = 0; tabsArray.forEach((ele) => { ele.addEventListener("click", function (e) { tabsArray.forEach((ele) => { ele.classList.remove("active"); }); e.currentTarget.classList.add("active"); sectionArray.forEach((sec) => { sec.classList.remove("active"); }); if(e.currentTarget.dataset.cont =='r1'){ prevButton.classList.add("disable"); }else{ prevButton.classList.remove("disable"); } if ( document.querySelector("#" + e.currentTarget.dataset.cont) == sectionArray[sectionArray.length - 1] ) { nextButton.classList.add("disable"); } else { nextButton.classList.remove("disable"); } document.querySelector('#' + e.currentTarget.dataset.cont).classList.add("active"); }); }); .section { display: none; } .section.active{ display: block; } ul { list-style: none; margin:0; padding: 0; display: flex; align-items: center; } ul li { background: #ccc; padding: 10px 15px; margin-left: 6px; border-radius: 50%; cursor: pointer; opacity: .5; } ul li.active{ opacity: 1 !important; } .next, .previous { padding: 15px 10px; border-radius: 6px; background: deepskyblue; color: white; border:0; outline: none; cursor: pointer; width: 100px; } .next.disable, .previous.disable{ cursor: none; opacity: .5; } <ul class="nav"> <li class="active" data-cont="r1">1</li> <li data-cont="r2">2</li> <li data-cont="r3">3</li> </ul> <section id="r1" class="section section-one active"> <h2>section 1</h2> </section> <section id="r2" class="section section-two"> <h2>section 2</h2> </section> <section id="r3" class="section section-three"> <h2>section 3</h2> </section> <button class="previous disable" id="previous">Previous</button> <button class="next" id="next">Next</button>tabsArray.forEach((ele) => { ele.addEventListener("click", function (e) { tabsArray.forEach((ele) => { ele.classList.remove("active"); }); e.currentTarget.classList.add("active"); sectionArray.forEach((sec) => { sec.classList.remove("active"); }); // get the current click section // if the current section is 3 // Then next button should be disabled // else if the current section is 1 // Then prev button should be disabled document.querySelector('#' + e.currentTarget.dataset.cont).classList.add("active"); }); });Lo siento, no soy bueno en Javascript simple, pero para una fácil visualización, ese debería ser el proceso
Puede identificar la sección actual obteniendo el atributo data-cont . Usando jQuery, el código será $(ele).attr('data-cont') que devolverá cualquier r1 , r2 o r3
// Get the current data-cont value in li attribute var currSection = $(ele).attr('data-cont') // Disable previous button when currSection is r1 $('button.previous').prop('disabled', currSection == 'r1') // Disable next button when currSection is r3 $('button.next').prop('disabled', currSection == 'r3')Espero haber entendido bien su pregunta y la solución a continuación ayude.
Se divide en pequeñas funciones, con el objetivo de que una función haga una cosa.
let tabs = document.querySelectorAll(".nav li"); let sections = document.querySelectorAll(".section"); let nextButton = document.querySelector("#nextBtn"); let prevButton = document.querySelector("#prevBtn"); let current = 0; const toggleTabs = () => { tabs.forEach(function(tab) { tab.classList.remove('active'); }); tabs[current].classList.add("active"); //console.log(current); } const toggleSections = () => { sections.forEach(function(section) { section.classList.remove('active'); }); sections[current].classList.add("active"); } const togglePrev = () => { const method = current == 0 ? 'add' : 'remove'; prevButton.classList[method]("disable"); } const toggleNext = () => { const method = current == tabs.length - 1 ? 'add' : 'remove'; nextButton.classList[method]("disable"); } const goNext = () => { if (current < tabs.length - 1) { current++ } toggleTabs(); toggleSections(); toggleNext(); togglePrev(); } const goPrev = () => { if (current > 0) { current-- } toggleTabs(); toggleSections(); toggleNext(); togglePrev(); } .section { display: none; } .section.active { display: block; } ul { list-style: none; margin: 0; padding: 0; display: flex; align-items: center; } ul li { background: #ccc; padding: 10px 15px; margin-left: 6px; border-radius: 50%; cursor: pointer; opacity: .5; } ul li.active { opacity: 1 !important; } .next, .previous { padding: 15px 10px; border-radius: 6px; background: deepskyblue; color: white; border: 0; outline: none; cursor: pointer; width: 100px; } .next.disable, .previous.disable { cursor: none; opacity: .5; } <ul class="nav"> <li class="active">1</li> <li>2</li> <li>3</li> </ul> <section class="section section-one active"> <h2>section 1</h2> </section> <section class="section section-two"> <h2>section 2</h2> </section> <section class="section section-three"> <h2>section 3</h2> </section> <button class="previous disable" id="prevBtn" onclick="goPrev()">Previous</button> <button class="next" id="nextBtn" onclick="goNext()">Next</button>Aquí hay una solución basada en clases con algunos cambios de CSS para centrar el contenido:
class TabbedContent { constructor() { this.tabs = document.querySelectorAll(".nav li"); this.sections = document.querySelectorAll(".section"); this.nextButton = document.querySelector("#nextBtn"); this.prevButton = document.querySelector("#prevBtn"); this.current = 0; } toggleTabs() { this.tabs.forEach(function(tab) { tab.classList.remove('active'); }); this.tabs[this.current].classList.add("active"); } toggleSections() { this.sections.forEach(function(section) { section.classList.remove('active'); }); this.sections[this.current].classList.add("active"); } togglePrev() { const method = this.current == 0 ? 'add' : 'remove'; this.prevButton.classList[method]("disable"); } toggleNext() { const method = this.current == this.tabs.length - 1 ? 'add' : 'remove'; this.nextButton.classList[method]("disable"); } goNext() { if (this.current < this.tabs.length - 1) { this.current++ } this.toggleTabs(); this.toggleSections(); this.toggleNext(); this.togglePrev(); } goPrev() { if (this.current > 0) { this.current-- } this.toggleTabs(); this.toggleSections(); this.toggleNext(); this.togglePrev(); } } const tabbedContent = new TabbedContent(); .container { max-width: 600px; margin: 0 auto; text-align: center; } .section { display: none; } .section.active { display: block; } ul { list-style: none; margin: 0; padding: 0; display: flex; justify-content: center; } ul li { background: #ccc; padding: 10px 15px; margin-left: 6px; border-radius: 50%; cursor: pointer; opacity: .5; } ul li.active { opacity: 1 !important; } .next, .previous { padding: 15px 10px; border-radius: 6px; background: deepskyblue; color: white; border: 0; outline: none; cursor: pointer; width: 100px; } .next.disable, .previous.disable { cursor: none; opacity: .5; } <div class="container"> <ul class="nav"> <li class="active">1</li> <li>2</li> <li>3</li> </ul> <section class="section section-one active"> <h2>section 1</h2> </section> <section class="section section-two"> <h2>section 2</h2> </section> <section class="section section-three"> <h2>section 3</h2> </section> <button class="previous disable" id="prevBtn" onclick="tabbedContent.goPrev()">Previous</button> <button class="next" id="nextBtn" onclick="tabbedContent.goNext()">Next</button> </div>Es recomendable tener una colección de botones y otra de secciones, conectando ambas a través del índice, del que también hay que hacer un seguimiento. Si tenemos todo esto, ir a continuación es aumentar el índice, mientras que ir al anterior es disminuir el índice. No estoy haciendo que el anterior y el siguiente desaparezcan, aunque la pregunta me lo pide. En su lugar, estoy usando la clase de disable . Si queremos que aparezcan/desaparezcan, entonces podemos usar la class invisible en su lugar.
let currentSection = 0; let sections = document.querySelectorAll(".section"); let sectionButtons = document.querySelectorAll(".nav > li"); let nextButton = document.querySelector(".next"); let previousButton = document.querySelector(".previous"); for (let i = 0; i < sectionButtons.length; i++) { sectionButtons[i].addEventListener("click", function() { sections[currentSection].classList.remove("active"); sectionButtons[currentSection].classList.remove("active"); sections[currentSection = i].classList.add("active"); sectionButtons[currentSection].classList.add("active"); if (i === 0) { if (previousButton.className.split(" ").indexOf("disable") < 0) { previousButton.classList.add("disable"); } } else { if (previousButton.className.split(" ").indexOf("disable") >= 0) { previousButton.classList.remove("disable"); } } if (i === sectionButtons.length - 1) { if (nextButton.className.split(" ").indexOf("disable") < 0) { nextButton.classList.add("disable"); } } else { if (nextButton.className.split(" ").indexOf("disable") >= 0) { nextButton.classList.remove("disable"); } } }); } nextButton.addEventListener("click", function() { if (currentSection < sectionButtons.length - 1) { sectionButtons[currentSection + 1].click(); } }); previousButton.addEventListener("click", function() { if (currentSection > 0) { sectionButtons[currentSection - 1].click(); } }); .section { display: none; } .section.active{ display: block; } .invisible { display: none; } ul { list-style: none; margin:0; padding: 0; display: flex; align-items: center; } ul li { background: #ccc; padding: 10px 15px; margin-left: 6px; border-radius: 50%; cursor: pointer; opacity: .5; } ul li.active{ opacity: 1 !important; } .next, .previous { padding: 15px 10px; border-radius: 6px; background: deepskyblue; color: white; border:0; outline: none; cursor: pointer; width: 100px; } .next.disable, .previous.disable{ cursor: none; opacity: .5; } <ul class="nav"> <li class="active" data-cont="r1">1</li> <li data-cont="r2">2</li> <li data-cont="r3">3</li> </ul> <section id="r1" class="section section-one active"> <h2>section 1</h2> </section> <section id="r2" class="section section-two"> <h2>section 2</h2> </section> <section id="r3" class="section section-three"> <h2>section 3</h2> </section> <button class="previous disable" id="previous">Previous</button> <button class="next" id="next">Next</button>Desacople los datos estructurales detrás del funcionamiento del diseño de pestañas de la interfaz de usuario. Primero conceptualice el problema del diseño de pestañas en términos de datos.
En mi código, el diseño de pestañas se almacena en una matriz llamada sections . El resto del código solo lee los datos de la matriz y se los muestra al usuario en función de active_section_index .
La función add_sections() solo lee los datos de la matriz de sections y se los muestra al usuario usando el css necesario.
La función handle_nav_buttons() actualiza el estado de los botones de navegación después de cada navegación
go_to(index) se usa para navegar usando active_section_index
la clase active se usa para mostrar la sección en consecuencia
Si desea que el botón "anterior"/"siguiente" desaparezca sin cambiar el diseño, puede configurar esos botones en "visibility:hidden;" por defecto en CSS y cámbielo a "visibility:visible;" cuando se activa el evento relevante.
También puede usar la etiqueta "botón" en lugar de la etiqueta "li" para la barra de navegación superior.
A continuación se muestra mi código:
const sectionContent = ["r1", "r2", "r3"]; let currentSection = sectionContent[0]; const displayContent = (q, area) => { document.getElementById(q).classList.add("active"); document.getElementById(q + "-button").classList.add("button-active"); currentSection = sectionContent[area.indexOf(q)]; const toNone = area.filter(e => e !== q); for (i in toNone) { document.getElementById(toNone[i]).classList.remove("active"); document.getElementById(toNone[i] + "-button").classList.remove("button-active"); } if (sectionContent.indexOf(q) == 0) { document.getElementById("previous").classList.remove("button-active"); document.getElementById("next").classList.add("button-active"); } else if (sectionContent.indexOf(q) == sectionContent.length - 1) { document.getElementById("previous").classList.add("button-active"); document.getElementById("next").classList.remove("button-active"); } else { document.getElementById("previous").classList.add("button-active"); document.getElementById("next").classList.add("button-active"); } } const displayR1 = () => displayContent("r1", sectionContent); const displayR2 = () => displayContent("r2", sectionContent); const displayR3 = () => displayContent("r3", sectionContent); const displayNext = () => displayContent(sectionContent[sectionContent.indexOf(currentSection) + 1], sectionContent); const displayPrevious = () => displayContent(sectionContent[sectionContent.indexOf(currentSection) - 1], sectionContent); .container { display: grid; place-items: center; } .section { display: none; } .section.active { display: block; } .nav { list-style: none; margin:0; padding: 0; display: flex; align-items: center; } .nav button { background: #ccc; padding: 10px 15px; margin-left: 6px; border-radius: 50%; cursor: pointer; opacity: .5; border: none; } .next, .previous { padding: 15px 10px; border-radius: 6px; background: deepskyblue; color: white; border:0; outline: none; cursor: pointer; width: 100px; visibility: hidden; } .button-active { opacity: 1 !important; visibility: visible; } <div class="container"> <nav class="nav"> <button class="button-active" id="r1-button" onclick="displayR1()">1</button> <button id="r2-button" onclick="displayR2()">2</button> <button id="r3-button" onclick="displayR3()">3</button> </nav> <section id="r1" class="section active"> <h2>section 1</h2> </section> <section id="r2" class="section"> <h2>section 2</h2> </section> <section id="r3" class="section"> <h2>section 3</h2> </section> <nav> <button class="previous" id="previous" onclick="displayPrevious()">Previous</button> <button class="next button-active" id="next" onclick="displayNext()">Next</button> </nav> </div>