将活动类逐个添加到元素中,使用基本的 JavaScript。

huangapple go评论65阅读模式
英文:

active class to elements one by one with basic js

问题

需要将“active”类逐个移动到这5个div元素中,但只能使用非常基本的JavaScript,因为我仍在学习基础知识。我找到了这个解决方案,它有效,但我想将其转化为一个for循环,是否可以在没有任何函数或forEach循环的情况下实现,只使用非常基本的内容?谢谢

这是我的解决方案:

next.addEventListener('click', function(){

    let current = document.querySelector('.active')

    if(current.classList.contains('active')){
        imgItems[1].classList.add('active')
        imgItems[0].classList.remove('active')
    }

    if (current.classList.contains('active')) {
        imgItems[1].classList.remove('active')
        imgItems[2].classList.add('active')
    }
    if (current.classList.contains('active')) {
        imgItems[2].classList.remove('active')
        imgItems[3].classList.add('active')
    }
    if (current.classList.contains('active')) {
        imgItems[3].classList.remove('active')
        imgItems[4].classList.add('active')
    }
    

})

我尝试了很多次,在线解决方案很好,但对我来说太高级了,我只学习了数组和循环。

英文:

i need to "move" active class one by one to this 5 div elements but with very basic js because still learning basics, i found this solution and it work but i want transform this in a for loop,it is possible without any function,foreach loop,only with very basics? thanks

this is my solution:

next.addEventListener('click', function(){

    let current = document.querySelector('.active')

    if(current.classList.contains('active')){
        imgItems[1].classList.add('active')
        imgItems[0].classList.remove('active')
    }

    if (current.classList.contains('active')) {
        imgItems[1].classList.remove('active')
        imgItems[2].classList.add('active')
    }
    if (current.classList.contains('active')) {
        imgItems[2].classList.remove('active')
        imgItems[3].classList.add('active')
    }
    if (current.classList.contains('active')) {
        imgItems[3].classList.remove('active')
        imgItems[4].classList.add('active')
    }
    

})

I try many times and online solutions is nice but too advanced for me,i have learning only array and cycle.

答案1

得分: 3

假设这些项目在DOM中是相邻的,您可以使用nextElementSibling来转到下一个项目。

const next = document.getElementById("next");

next.addEventListener("click", function() {
  let current = document.querySelector(".active");
  let nextItem = current.nextElementSibling;
  if (!nextItem) {
    // 返回到第一个项目
    nextItem = document.querySelector(".item");
  }
  current.classList.remove("active");
  nextItem.classList.add("active");
})
.active {
  color: red;
}
<div id="container">
  <div class="item active">Item 1</div>
  <div class="item">Item 2</div>
  <div class="item">Item 3</div>
  <div class="item">Item 4</div>
  <div class="item">Item 5</div>
</div>

<button id="next">Next</button>
英文:

Assuming the items are adjacent in the DOM, you can use nextElementSibling to go to the next item.

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

const next = document.getElementById(&quot;next&quot;);

next.addEventListener(&quot;click&quot;, function() {
  let current = document.querySelector(&quot;.active&quot;);
  let nextItem = current.nextElementSibling;
  if (!nextItem) {
    // Go back to the first item
    nextItem = document.querySelector(&quot;.item&quot;);
  }
  current.classList.remove(&quot;active&quot;);
  nextItem.classList.add(&quot;active&quot;);
})

<!-- language: lang-css -->

.active {
  color: red;
}

<!-- language: lang-html -->

&lt;div id=&quot;container&quot;&gt;
  &lt;div class=&quot;item active&quot;&gt;Item 1&lt;/div&gt;
  &lt;div class=&quot;item&quot;&gt;Item 2&lt;/div&gt;
  &lt;div class=&quot;item&quot;&gt;Item 3&lt;/div&gt;
  &lt;div class=&quot;item&quot;&gt;Item 4&lt;/div&gt;
  &lt;div class=&quot;item&quot;&gt;Item 5&lt;/div&gt;
&lt;/div&gt;

&lt;button id=&quot;next&quot;&gt;Next&lt;/button&gt;

<!-- end snippet -->

答案2

得分: 0

next.addEventListener('click', function() {
    let current = document.querySelector('.active');
    for (let index = 0; index <= 3; index++) {
        if (current.classList.contains('active')) {
            imgItems[index].classList.remove('active');
            imgItems[index + 1].classList.add('active');
        }
    }
});

JavaScript没有foreach循环。它有for .. in循环、for .. of循环和普通的C风格循环。在这种情况下,我使用了后者,因为我们要使用索引。

看起来你打算将active类级联到某些imgItems集合的末尾,所以思路是从0到3循环一个index,每次检查current是否具有active类,然后从当前索引的实际元素中删除该类,并将该类添加到下一个元素。你也可以不使用循环,像这样:

let imgItems = [...document.querySelectorAll('div')];
document.getElementById("next").addEventListener('click', function() {
    let current = document.querySelector('.active');
    let index = imgItems.indexOf(current);
    if (index < imgItems.length - 1) {
        imgItems[index].classList.remove('active');
        imgItems[index + 1].classList.add('active');
    } else {
        alert('You are at the last item');
    }
});

基本上,我们使用展开运算符([...]部分)将类似数组的对象imgItems转换为数组,并在事件内部获取当前元素在数组中的索引,如果不是最后一个元素,就移除active类并将其添加到下一个元素。

英文:

Here you go

next.addEventListener(&#39;click&#39;, function() {
    let current = document.querySelector(&#39;.active&#39;);
    for (let index = 0; index &lt;= 3; index++) {
        if (current.classList.contains(&#39;active&#39;)) {
            imgItems[index].classList.remove(&#39;active&#39;);
            imgItems[index + 1].classList.add(&#39;active&#39;);
        }
    }
});

Javascript has no foreach loop. It has for .. in loop, for .. of loop and normal C-style loop. In this case I have used the latter because we are to work with indexes.

It seems that you intend to cascade the active class towards the end of some imgItems set, so the idea is to loop an index from 0 up to 3 and each time to check whether current has an active class, then remove that class from the actual element on the index we are currently on and add this class to the next. You can also do it without a loop, like this:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

let imgItems = [...document.querySelectorAll(&#39;div&#39;)];
document.getElementById(&quot;next&quot;).addEventListener(&#39;click&#39;, function() {
    let current = document.querySelector(&#39;.active&#39;);
    let index = imgItems.indexOf(current);
    if (index &lt; imgItems.length - 1) {
        imgItems[index].classList.remove(&#39;active&#39;);
        imgItems[index + 1].classList.add(&#39;active&#39;);
    } else {
        alert(&#39;You are at the last item&#39;);
    }
});

<!-- language: lang-css -->

div {
    width: 100px;
    height: 100px;
    border: 1px solid black;
    float: left;
}

div.active {
    background-color: green;
}

<!-- language: lang-html -->

&lt;div class=&quot;active&quot;&gt;&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;input type=&quot;button&quot; value=&quot;next&quot; id=&quot;next&quot;&gt;

<!-- end snippet -->

Basically we convert the array-like object called imgItems to an array using the spread operator (the [...] part) and inside the event, you get the index of current in the array and if it's not the very last one, you remove the active class and add it to the next.

答案3

得分: 0

以下是翻译好的部分:

这是一种稍微更为复杂的方法,一定是您请求的“非常基本”的方法,它允许按下<button>按钮来浏览元素列表;解释性评论包含在代码中,以便您和其他人可以从中学习:

// 定义一个命名函数 - navigation() - 接受一个参数,一个对此函数绑定的事件的引用;这是从后面使用EventTarget.addEventListener()自动传递的:
const navigation = function(evt) {
  // 在这里,我们使用解构赋值从evt对象中检索currentTarget属性,创建一个同名的变量;currentTarget是事件处理程序(此函数)绑定到的元素节点:
  let {
    currentTarget
  } = evt;
  // 我们从currentTarget元素导航到其最近的具有"data-active-class"属性的祖先元素,然后从该元素中使用HTMLElement.dataset API检索"data-active-class"属性的属性值,注意我们还使用了驼峰表示法:
  let activeClassName = currentTarget.closest("[data-active-class]").dataset.activeClass;
  // 从currentTarget元素检索"data-role"属性的属性值,并将该字符串转换为其小写等效形式:
  let direction = currentTarget.dataset.role.toLowerCase();
  // 与上面一样,我们从currentTarget导航到其具有"data-iterates"属性的最近祖先,然后检索属性值:
  let selector = currentTarget.closest("[data-iterates]").dataset.iterates;
  // 在这里,我们使用document.querySelectorAll()来查找文档中匹配之前检索到的选择器的所有元素,并使用Array.from()将NodeList转换为数组:
  let elements = Array.from(document.querySelectorAll(selector));
  // 使用Array.prototype.map()基于elements数组创建一个新数组:
  let currentState = elements.map(
    // 这些参数自动可用于Array方法;名称完全由用户定义,而相关的参数始终按照这个顺序:
    // 	el,对节点数组的当前节点的引用,
    //	index,数组中当前数组元素的索引,
    // all,对我们正在迭代的当前数组的引用:
    function(el, index, all) {
      // 从Array方法中返回一个对象(从当前节点数组的当前数组中创建一个对象数组):
      return {
        // 在这里,我们返回具名属性和属性值,形式为:
        // 		el: el,
        // 		index: index
        // 利用了缩写表示法:
        el,
        index,
        // 在这里,我们返回一个isActive属性,其值为true/false的布尔值,具体取决于当前元素节点是否具有与上面检索到的activeClassName值匹配的类名:
        isActive: el.classList.contains(activeClassName),
        // 返回一个'progress'属性,其值是另一个对象:
        progress: {
          // next: 使用条件(三元)运算符,如果评估结果是index + 1是否等于整个数组的长度 - 为真/真值
          // 我们返回第一个数组元素,否则我们返回下一个索引处的数组元素:
          next: (
            (index + 1) === all.length ? all.at(0) : all.at(index + 1)
          ),
          // 如果index - 1小于零,我们使用Array.prototype.at()和索引-1返回最后一个数组元素;否则我们返回前一个数组元素:
          previous: (
            (index - 1) < 0 ? all.at(-1) : all.at(index - 1)
          )
        }
      };
    });
  // 然后我们使用Array.prototype.find()
  let currentlyActive = currentState.find(
    // 再次,我们检索方法可用的参数,这在这种情况下是一个对象:
    // {...},使用解构赋值检索当前数组元素(对象)的命名属性(作为变量):
    ({
      isActive
      // 我们返回测试评估为布尔true/真值的数组元素;'isActive'属性本身是一个布尔值,因此实际上我们直接返回(使用箭头函数的隐式返回)true或false:
    }) => isActive);
  // 我们再次使用解构赋值,从currentlyActive对象中检索属性:
  let {
    // 在这里,我们检索具名属性('el')并将其分配给不同的变量名'currentElement',类似地,我们检索并'index'属性,并分配新的变量名'currentIndex',因此变量名暗示了其值是/代表什么:
    el: currentElement,
    index: currentIndex,
    progress
  } = currentlyActive;

  // 在这里,我们使用Element.classList API删除activeClassName变量中保存的类名:
  currentElement.classList.remove(activeClassName);
  // 在这里,我们使用方括号表示法检索进度对象的相关属性,然后再次使用Element.classList API将activeClassName添加到该元素中:
  progress[direction].classList.add(activeClassName);
};

// 使用document.querySelector查找具有"data-role"自定义属性的元素,该属性本身嵌套在具有"data-iterates"自定义属性的祖先元素内;然后,使用NodeList.forEach()迭代检索到的元素节点:
document.querySelectorAll("[data-iterates] [data-role]").forEach(
  // 并传入对NodeList的当前节点的引用,并使用EventTarget.addEventListener()绑定navigation()函数 - 注意故意省略了括号;我们希望绑定函数本身,而不是函数的返回属性 - 作为"click"事件的事件处理程序:
  (el) => el.addEventListener("click", navigation)
);

以上是JavaScript部分的翻译。如果您需要其他部分的翻译,请提出具体要求。

英文:

This is one approach that's a little more developed &ndash; and not necessarily the "very basic" approach you requested &ndash; which allows for presses of a &lt;button&gt; to navigate through a list of elements; explanatory comments are in the code in order that you, and others, might learn from it:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

// defining a named function - navigation() - that takes
// one argument, a reference to the Event to which this
// function is bound; this is passed automatically from
// the later use of EventTarget.addEventListener():
const navigation = function(evt) {
// here we use destructuring assignment to retrieve
// the currentTarget property from the evt Object,
// creating a variable of that same name; the
// currentTarget is the element node to which the
// event-handler (this function) is bound:
let {
currentTarget
} = evt;
// we navigate from the currentTarget element to its closest
// ancestor element that has a &quot;data-active-class&quot; attribute,
// and from that element we use the HTMLElement.dataset API
// to retrieve the attribute-value for the &quot;data-active-class&quot;
// attribute, note that we&#39;re also using camelCase notation:
let activeClassName = currentTarget.closest(&quot;[data-active-class]&quot;).dataset.activeClass;
// retrieve the attribute-value of the &quot;data-role&quot; attribute
// from the currentTarget element, and convert that string
// to its lower-case equivalent:
let direction = currentTarget.dataset.role.toLowerCase();
// as above, we navigate from the currentTarget to its closest
// ancestor with a &quot;data-iterates&quot; attribute, and then retrieving
// the attribute-value:
let selector = currentTarget.closest(&quot;[data-iterates]&quot;).dataset.iterates;
// here we use document.querySelectorAll() to find all elements
// within the document that match the supplied selector (retrieved
// previously), and convert that NodeList into an Array, using
// Array.from():
let elements = Array.from(document.querySelectorAll(selector));
// using Array.prototype.map() to create a new Array based
// on the elements Array:
let currentState = elements.map(
// these arguments are available automatically to the
// Array method; the names are entirely user-defined
// while the relevant arguments are always in this order:
// 	el, a reference to the current Node of the Array of Nodes,
//	index, the index of the current Array-element in the Array,
// all, a reference to the current Array over which we&#39;re iterating:
function(el, index, all) {
// from the Array method we return an Object (creating an
// Array of Objects derived from the current Array of Nodes):
return {
// here we return the named property, and property-values
// in the form of:
// 		el: el,
// 		index: index
// taking advantage of the shorthand notation:
el,
index,
// here we return an isActive property with its value
// a Boolean true/false, according to whether the current
// element node has a class-name matching the activeClassName
// value (retrieved above):
isActive: el.classList.contains(activeClassName),
// returning a &#39;progress&#39; property with its value another Object:
progress: {
// next: using a conditional (ternary) operator, if the assessment
// - is index + 1 equal to the length of the whole Array - is true/truthy
// we return first Array-element, otherwise we return the Array-element
// at the next index:
next: (
(index + 1) === all.length ? all.at(0) : all.at(index + 1)
),
// if index - 1 is less than zero, we return the last Array-element
// using Array.prototype.at() and an index of -1; otherwise we
// return the previous Array-element:
previous: (
(index - 1) &lt; 0 ? all.at(-1) : all.at(index - 1)
)
}
};
});
// we then use Array.prototype.find()
let currentlyActive = currentState.find(
// again, we&#39;re retrieving the arguments available to the
// method, which is an Object in this case:
// {...}, using destructuring assignment to retrieve the named
// properties (as variables) of the current Array-element (the Object):
({
isActive
// and we return the Array-element for which the test evaluates to
// a Boolean true/truthy value; the &#39;isActive&#39; property is itself
// a Boolean, and so effectively we&#39;re returning (using the implicit
// return of an Arrow function) either true or false directly:
}) =&gt; isActive);
// we use destructuring assignment again, to retrieve properties from
// the currentlyActive Object:
let {
// here we retrieve the named property (&#39;el&#39;) and assign it to
// a different variable name &#39;currentElement&#39;, simarly we retrieve
// and &#39;index&#39; property, and also assign a new variable name
// &#39;currentIndex&#39; so the variable-name implies what its value
// is/represents:
el: currentElement,
index: currentIndex,
progress
} = currentlyActive;
// here we use the Element.classList API to remove the class
// held in the activeClassName variable:
currentElement.classList.remove(activeClassName);
// and here we use bracket-notation to retrieve the
// relevant property of the progress Object, and again
// using the Element.classList API we add the
// activeClassName to that element:
progress[direction].classList.add(activeClassName);
};
// using document.querySelector to find elements with a &quot;data-role&quot; custom
// attribute that is itself nested within an ancestor with a &quot;data-iterates&quot;
// custom attribute; we then use NodeList.forEach() to iterate over the
// element ndoes that were retrieved:
document.querySelectorAll(&quot;[data-iterates] [data-role]&quot;).forEach(
// and pass in a reference to the current Node of the NodeList,
// and use EventTarget.addEventListener() to bind the
// navigation() function - note the deliberately omitted
// parentheses; we want to bind the function itself not the
// returned property of the function - as the event-handler
// for the &quot;click&quot; event:
(el) =&gt; el.addEventListener(&quot;click&quot;, navigation)
);

<!-- language: lang-css -->

:root {
--spacing: 1rem;
}
*,
::before,
::after {
box-sizing: border-box;
font: inherit;
margin: 0;
padding: 0;
}
body {
block-size: 100vh;
font-family: system-ui;
font-size: 16px;
font-weight: 400;
padding: var(--spacing);
}
menu,
ol,
ul,
li {
list-style-type: none;
}
main {
border: 1px solid currentColor;
inline-size: clamp(30rem, 80% + 5vmin, 1200px);
margin-inline: auto;
min-block-size: 100%;
padding: var(--spacing);
}
.controls {}
li a,
button {
padding-block: calc(var(--spacing)/2);
padding-inline: var(--spacing);
}
section {
border: 1px solid currentColor;
margin-block: var(--spacing);
padding: var(--spacing);
}
li a {
display: block;
}
.active {
background-image: linear-gradient(90deg, lime, transparent);
}

<!-- language: lang-html -->

&lt;main&gt;
&lt;!-- taking advantage of custom data-* attributes to allow the
user to customise the JavaScript functionality:
data-active-class: the attribute that defines the class-name
that will be considered the indicator of the &quot;active&quot; element,
data-iterates: the attribute that defines the CSS selector for
the elements over which the JavaScript will iterate.
--&gt;
&lt;div
class=&quot;controls&quot;
data-active-class=&quot;active&quot;
data-iterates=&quot;a&quot;&gt;
&lt;!-- using the data-role attribute to define the &quot;role&quot; of the
current element in the navigation through/over the
elements: --&gt;
&lt;button data-role=&quot;previous&quot;&gt;previous&lt;/button&gt;
&lt;button data-role=&quot;next&quot;&gt;next&lt;/button&gt;
&lt;/div&gt;
&lt;section&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#&quot; class=&quot;active&quot;&gt;Link element 01&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#&quot;&gt;Link element 02&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#&quot;&gt;Link element 03&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#&quot;&gt;Link element 04&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#&quot;&gt;Link element 05&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#&quot;&gt;Link element 06&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#&quot;&gt;Link element 07&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#&quot;&gt;Link element 08&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#&quot;&gt;Link element 09&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#&quot;&gt;Link element 10&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;/main&gt;

<!-- end snippet -->

JS Fiddle demo.

Note that in the above demo, there is no error-handling for a situation in which there is no element with a class-name matching the activeClassName, or multiple classes matching that class-name. If such is required you'd need to either implement that yourself, or ask a question about how it might/should be handled in the event that you're unable to write such code.

The demo below shows one use of the possible customisations (bear in mind the aesthetics are horrible, as this is merely a proof-of-concept):

<!-- begin snippet: js hide: true console: false babel: false -->

<!-- language: lang-js -->

// defining a named function - navigation() - that takes
// one argument, a reference to the Event to which this
// function is bound; this is passed automatically from
// the later use of EventTarget.addEventListener():
const navigation = function(evt) {
// here we use destructuring assignment to retrieve
// the currentTarget property from the evt Object,
// creating a variable of that same name; the
// currentTarget is the element node to which the
// event-handler (this function) is bound:
let {
currentTarget
} = evt;
// we navigate from the currentTarget element to its closest
// ancestor element that has a &quot;data-active-class&quot; attribute,
// and from that element we use the HTMLElement.dataset API
// to retrieve the attribute-value for the &quot;data-active-class&quot;
// attribute, note that we&#39;re also using camelCase notation:
let activeClassName = currentTarget.closest(&quot;[data-active-class]&quot;).dataset.activeClass;
// retrieve the attribute-value of the &quot;data-role&quot; attribute
// from the currentTarget element, and convert that string
// to its lower-case equivalent:
let direction = currentTarget.dataset.role.toLowerCase();
// as above, we navigate from the currentTarget to its closest
// ancestor with a &quot;data-iterates&quot; attribute, and then retrieving
// the attribute-value:
let selector = currentTarget.closest(&quot;[data-iterates]&quot;).dataset.iterates;
// here we use document.querySelectorAll() to find all elements
// within the document that match the supplied selector (retrieved
// previously), and convert that NodeList into an Array, using
// Array.from():
let elements = Array.from(document.querySelectorAll(selector));
// using Array.prototype.map() to create a new Array based
// on the elements Array:
let currentState = elements.map(
// these arguments are available automatically to the
// Array method; the names are entirely user-defined
// while the relevant arguments are always in this order:
// 	el, a reference to the current Node of the Array of Nodes,
//	index, the index of the current Array-element in the Array,
// all, a reference to the current Array over which we&#39;re iterating:
function(el, index, all) {
// from the Array method we return an Object (creating an
// Array of Objects derived from the current Array of Nodes):
return {
// here we return the named property, and property-values
// in the form of:
// 		el: el,
// 		index: index
// taking advantage of the shorthand notation:
el,
index,
// here we return an isActive property with its value
// a Boolean true/false, according to whether the current
// element node has a class-name matching the activeClassName
// value (retrieved above):
isActive: el.classList.contains(activeClassName),
// returning a &#39;progress&#39; property with its value another Object:
progress: {
// next: using a conditional (ternary) operator, if the assessment
// - is index + 1 equal to the length of the whole Array - is true/truthy
// we return first Array-element, otherwise we return the Array-element
// at the next index:
next: (
(index + 1) === all.length ? all.at(0) : all.at(index + 1)
),
// if index - 1 is less than zero, we return the last Array-element
// using Array.prototype.at() and an index of -1; otherwise we
// return the previous Array-element:
previous: (
(index - 1) &lt; 0 ? all.at(-1) : all.at(index - 1)
)
}
};
});
// we then use Array.prototype.find()
let currentlyActive = currentState.find(
// again, we&#39;re retrieving the arguments available to the
// method, which is an Object in this case:
// {...}, using destructuring assignment to retrieve the named
// properties (as variables) of the current Array-element (the Object):
({
isActive
// and we return the Array-element for which the test evaluates to
// a Boolean true/truthy value; the &#39;isActive&#39; property is itself
// a Boolean, and so effectively we&#39;re returning (using the implicit
// return of an Arrow function) either true or false directly:
}) =&gt; isActive);
// we use destructuring assignment again, to retrieve properties from
// the currentlyActive Object:
let {
// here we retrieve the named property (&#39;el&#39;) and assign it to
// a different variable name &#39;currentElement&#39;, simarly we retrieve
// and &#39;index&#39; property, and also assign a new variable name
// &#39;currentIndex&#39; so the variable-name implies what its value
// is/represents:
el: currentElement,
index: currentIndex,
progress
} = currentlyActive;
// here we use the Element.classList API to remove the class
// held in the activeClassName variable:
currentElement.classList.remove(activeClassName);
// and here we use bracket-notation to retrieve the
// relevant property of the progress Object, and again
// using the Element.classList API we add the
// activeClassName to that element:
progress[direction].classList.add(activeClassName);
};
// using document.querySelector to find elements with a &quot;data-role&quot; custom
// attribute that is itself nested within an ancestor with a &quot;data-iterates&quot;
// custom attribute; we then use NodeList.forEach() to iterate over the
// element ndoes that were retrieved:
document.querySelectorAll(&quot;[data-iterates] [data-role]&quot;).forEach(
// and pass in a reference to the current Node of the NodeList,
// and use EventTarget.addEventListener() to bind the
// navigation() function - note the deliberately omitted
// parentheses; we want to bind the function itself not the
// returned property of the function - as the event-handler
// for the &quot;click&quot; event:
(el) =&gt; el.addEventListener(&quot;click&quot;, navigation)
);
document.querySelectorAll(&#39;[data-iterates]&#39;).forEach(
(el) =&gt; [...el.children].forEach(
(k) =&gt; k.innerHTML += `: &lt;span&gt;${el.dataset.iterates}&lt;/span&gt;`
)
);

<!-- language: lang-css -->

:root {
--spacing: 1rem;
}
*,
::before,
::after {
box-sizing: border-box;
font: inherit;
margin: 0;
padding: 0;
}
body {
block-size: 100vh;
font-family: system-ui;
font-size: 16px;
font-weight: 400;
padding: var(--spacing);
}
menu,
ol,
ul,
li {
list-style-type: none;
}
main {
border: 1px solid currentColor;
inline-size: clamp(30rem, 80% + 5vmin, 1200px);
margin-inline: auto;
min-block-size: 100%;
padding: var(--spacing);
}
main *:not(button span) {
background-clip: padding-box;
border: 2px solid transparent;
border-radius: 0.5em;
padding-block: calc(var(--spacing)/2);
padding-inline: var(--spacing);
overflow: hidden;
}
.controls {
display: inline-block;
inline-size: 45%;
}
section {
border: 1px solid currentColor;
margin-block: var(--spacing);
padding: var(--spacing);
}
li {
display: flex;
gap: 1em;
}
li a {
display: block;
}
.active {
background-image: linear-gradient(90deg, lime, transparent);
background-repeat: no-repeat;
}
.special {
border-image: radial-gradient(at 0 0, purple, aqua) 9;
}
.extraSpecialActive {
border: 2px solid hsl(280deg 70% 50% / 1);
}

<!-- language: lang-html -->

&lt;main&gt;
&lt;div class=&quot;controls&quot; data-active-class=&quot;active&quot; data-iterates=&quot;a&quot;&gt;
&lt;button data-role=&quot;previous&quot;&gt;previous&lt;/button&gt;
&lt;button data-role=&quot;next&quot;&gt;next&lt;/button&gt;
&lt;/div&gt;
&lt;!-- all I&#39;ve done here is add an extra pair of &lt;button&gt; elements within
a parent element with relevant &quot;data-active-class&quot; and &quot;data-iterates&quot;
attributes, and values (though obviously I&#39;ve added the relevant class
-names to elements in the document) --&gt;
&lt;div class=&quot;controls&quot; data-active-class=&quot;extraSpecialActive&quot; data-iterates=&quot;.special&quot;&gt;
&lt;button data-role=&quot;previous&quot;&gt;previous&lt;/button&gt;
&lt;button data-role=&quot;next&quot;&gt;next&lt;/button&gt;
&lt;/div&gt;
&lt;section&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#&quot; class=&quot;special extraSpecialActive&quot;&gt;Link element 01&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#&quot;&gt;Link element 02&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#&quot;&gt;Link element 03&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;span&gt;span: 1&lt;/span&gt;
&lt;span&gt;span: 2&lt;/span&gt;
&lt;span class=&quot;special&quot;&gt;span: 3&lt;/span&gt;
&lt;span&gt;span: 4&lt;/span&gt;
&lt;span class=&quot;special&quot;&gt;span: 5&lt;/span&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#&quot;&gt;Link element 05&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#&quot; class=&quot;active&quot;&gt;Link element 06&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#&quot;&gt;Link element 07&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#&quot;&gt;Link element 08&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#&quot;&gt;Link element 09&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#&quot;&gt;Link element 10&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#&quot;&gt;Link element 11&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;article&gt;
&lt;h3 class=&quot;special&quot;&gt;Special heading&lt;/h3&gt;
&lt;/article&gt;
&lt;/main&gt;

<!-- end snippet -->

JS Fiddle demo.

References:

huangapple
  • 本文由 发表于 2023年6月18日 17:48:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/76499919.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定