在 CSS class 和 'n' 元素上的纯 javascript 之间切换
Toggling Between a CSS class with pure javascript on 'n' elements
致力于创建功能,当用户点击其中一个产品(每个元素都具有相同的分配 ID card-reveal
)时,它会向专门点击的容器添加一个 CSS class
(活动状态)显示该特定项目的信息,最后,当用户单击取消按钮时,CSS class 被删除(激活状态消失)。
不幸的是,我遇到了 运行 一些问题,当我点击第一个元素时,它会向该元素添加 class,但我点击的其他元素不会添加 class ,以及关闭按钮根本不起作用。我想在 Pure Javascript 中完成解决方案。此外,如果您看到一些 classie() 方法,我正在使用 Classie.js 来帮助 CSS class 切换。
任何帮助将不胜感激!谢谢!
Html
<a id="card-reveal" class="card-view" href="javascript:void(0)"><h3 class='hover-title'>View More</h3></a>
<div class="card-cover">
<span class="card-exit"></span>
<a class="card-follow" href="javascript:void(0)">Follow {{object.product_website_name}}.com</a>
<a class="card-buy" target="_blank" href="{{object.product_slug_url}}">Buy {{object.product_name }}</a>
<a id="card-close" class="card-info" href="javascript:void(0)"><span class="icon-indie_web-03"></span></a>
<ul class="card-social">
<label>Share</label>
<li><a href="#"><span class="icon-indie_web-04"></span></a></li>
<li><a href="#"><span class="icon-indie_web-05"></span></a></li>
</ul>
</div>
CSS
.card-cover {
width:100%;
height: 100%;
background: none repeat scroll 0% 0% rgba(255, 91, 36, 0.9);
color: #FFF;
display: block;
position: absolute;
opacity: 0;
z-index:200;
overflow: hidden;
-webkit-transform:translate3d(0, 400px, 0);
transform:translate3d(0, 400px, 0);
-webkit-backface-visibility:hidden;
backface-visibility: hidden;
-webkit-transition-property:opacity, transform;
transition-property:opacity, transform;
-webkit-transition-duration:0.2s;
transition-duration:0.2s;
-webkit-transition-timing-function:cubic-bezier(0.165, 0.84, 0.44, 1);
transition-timing-function:cubic-bezier(0.165, 0.84, 0.44, 1);
-webkit-transition-delay: 0s;
transition-delay: 0s;
}
.card-cover.card--active {
opacity: 1;
-webkit-transform:translate3d(0, 0, 0);
transform:translate3d(0, 0px, 0);
}
以下JS:
var cardContainer = document.querySelector('.card-cover'),
cardTargets = Array.prototype.slice.call( document.querySelectorAll( '#card-reveal' ) ),
eventType = mobilecheck() ? 'touchstart' : 'click',
cardClose = document.getElementById('card-close'),
resetMenu = function() {
classie.remove( cardContainer, 'card--active' );
},
resetMenuClick = function( ) {
cardCloseaddEventListener(globalMenuEventType, function() {
resetMenu();
document.removeEventListener(eventType, resetMenuClick);
}, false);
};
cardTargets.forEach(function (element, index) {
if( element.target ) {
element.addEventListener(eventType, function( event ) {
event.preventDefault();
event.stopPropagation();
classie.add(cardContainer, 'card--active');
document.addEventListener(eventType, resetMenuClick);
} ,false);
}
});
我可以想到两种简单的方法来做这样的事情。
首先,如果您不能为每张卡指定 ID(听起来您不能),您将不得不使用 class 名称。就像评论中提到的那样,您真的不想为多个元素使用相同的 ID。
部分原因是,正如您从我下面的示例中看到的那样,.getElementById() 方法仅适用于 return 一个元素,而其他方法如 .getElementsByClassName()将 return 一个元素数组。
我们试图解决的问题是您想要 display/hide 的子内容必须附加到您以某种方式单击的元素。由于我们没有使用 ID,并且您不能真正依赖 class 名称在元素之间是唯一的,因此我将 div 与信息放在一个容器中,该容器带有切换它的元素。
在容器 div 内,有两个 div 内容。一个是始终可见的主要内容,另一个是仅在单击主要内容时才可见的子内容(再次单击时变为不可见)。
此方法的好处是,由于无需担心 ID,您可以 copy/paste 卡片,它们每张都会显示相同的行为。
var maincontent = document.getElementsByClassName("main-content");
// Note: getElemenstByClassName will return an array of elements (even if there's only one).
for (var i = 0; i < maincontent.length; i++) {
//For each element in the maincontent array, add an onclick event.
maincontent[i].onclick = function(event) {
//What this does is gets the first item, from an array of elements that have the class 'sub-content', from the parent node of the element that was clicked:
var info = event.target.parentNode.getElementsByClassName("sub-content")[0];
if (info.className.indexOf("show") > -1) { // If the 'sub-content' also contains the class 'show', remove the class.
info.className = info.className.replace(/(?:^|\s)show(?!\S)/g, '');
} else { // Otherwise add the class.
info.className = info.className + " show";
}
}
}
.container {
border: 1px solid black;
width: 200px;
margin: 5px;
}
.main-content {
margin: 5px;
cursor: pointer;
}
.sub-content {
display: none;
margin: 5px;
}
.show {
/* The class to toggle */
display: block;
background: #ccc;
}
<div class="container">
<div class="main-content">Here is the main content that's always visible.</div>
<div class="sub-content">Here is the sub content that's only visible when the main content is clicked.</div>
</div>
<div class="container">
<div class="main-content">Here is the main content that's always visible.</div>
<div class="sub-content">Here is the sub content that's only visible when the main content is clicked.</div>
</div>
<div class="container">
<div class="main-content">Here is the main content that's always visible.</div>
<div class="sub-content">Here is the sub content that's only visible when the main content is clicked.</div>
</div>
第二种方法是对您想要 show/hide 的内容使用一个 div,单击一个元素将同时切换其可见性和内容。
我将使用前面的示例作为基础,但理想情况下,您会有某种 MVVM 框架,如 React、Knockout 或 angular 来帮助您填写内容。为了这个例子,我将使用子内容 div 中的文本。
var info = document.getElementById("Info");
var maincontent = document.getElementsByClassName("main-content");
for (var i = 0; i < maincontent.length; i++) { //getElemenstByClassName will return an array of elements (even if there's only one).
maincontent[i].onclick = function(event) { //For each element in the maincontent array, add an onclick event.
//This does the same as before, but I'm getting the text to insert into the info card.
var text = event.target.parentNode.getElementsByClassName("sub-content")[0].innerHTML;
info.innerHTML = text; // Set the text of the info card.
info.style.display = "block"; //Make the info card visible.
}
}
info.onclick = function(event) {
info.style.display = "none"; // If the info card is ever clicked, hide it.
}
.container {
border: 1px solid black;
width: 200px;
margin: 5px;
padding: 5px;
}
.main-content {
margin: 5px;
cursor: pointer;
}
.sub-content {
display: none;
margin: 5px;
}
#Info {
cursor: pointer;
display: none;
}
<div id="Info" class="container">Here is some test information.</div>
<div class="container">
<div class="main-content">Link 1.</div>
<div class="sub-content">You clicked link 1.</div>
</div>
<div class="container">
<div class="main-content">Link 2.</div>
<div class="sub-content">You clicked link 2.</div>
</div>
<div class="container">
<div class="main-content">Link 3.</div>
<div class="sub-content">You clicked link 3.</div>
</div>
致力于创建功能,当用户点击其中一个产品(每个元素都具有相同的分配 ID card-reveal
)时,它会向专门点击的容器添加一个 CSS class
(活动状态)显示该特定项目的信息,最后,当用户单击取消按钮时,CSS class 被删除(激活状态消失)。
不幸的是,我遇到了 运行 一些问题,当我点击第一个元素时,它会向该元素添加 class,但我点击的其他元素不会添加 class ,以及关闭按钮根本不起作用。我想在 Pure Javascript 中完成解决方案。此外,如果您看到一些 classie() 方法,我正在使用 Classie.js 来帮助 CSS class 切换。
任何帮助将不胜感激!谢谢!
Html
<a id="card-reveal" class="card-view" href="javascript:void(0)"><h3 class='hover-title'>View More</h3></a>
<div class="card-cover">
<span class="card-exit"></span>
<a class="card-follow" href="javascript:void(0)">Follow {{object.product_website_name}}.com</a>
<a class="card-buy" target="_blank" href="{{object.product_slug_url}}">Buy {{object.product_name }}</a>
<a id="card-close" class="card-info" href="javascript:void(0)"><span class="icon-indie_web-03"></span></a>
<ul class="card-social">
<label>Share</label>
<li><a href="#"><span class="icon-indie_web-04"></span></a></li>
<li><a href="#"><span class="icon-indie_web-05"></span></a></li>
</ul>
</div>
CSS
.card-cover {
width:100%;
height: 100%;
background: none repeat scroll 0% 0% rgba(255, 91, 36, 0.9);
color: #FFF;
display: block;
position: absolute;
opacity: 0;
z-index:200;
overflow: hidden;
-webkit-transform:translate3d(0, 400px, 0);
transform:translate3d(0, 400px, 0);
-webkit-backface-visibility:hidden;
backface-visibility: hidden;
-webkit-transition-property:opacity, transform;
transition-property:opacity, transform;
-webkit-transition-duration:0.2s;
transition-duration:0.2s;
-webkit-transition-timing-function:cubic-bezier(0.165, 0.84, 0.44, 1);
transition-timing-function:cubic-bezier(0.165, 0.84, 0.44, 1);
-webkit-transition-delay: 0s;
transition-delay: 0s;
}
.card-cover.card--active {
opacity: 1;
-webkit-transform:translate3d(0, 0, 0);
transform:translate3d(0, 0px, 0);
}
以下JS:
var cardContainer = document.querySelector('.card-cover'),
cardTargets = Array.prototype.slice.call( document.querySelectorAll( '#card-reveal' ) ),
eventType = mobilecheck() ? 'touchstart' : 'click',
cardClose = document.getElementById('card-close'),
resetMenu = function() {
classie.remove( cardContainer, 'card--active' );
},
resetMenuClick = function( ) {
cardCloseaddEventListener(globalMenuEventType, function() {
resetMenu();
document.removeEventListener(eventType, resetMenuClick);
}, false);
};
cardTargets.forEach(function (element, index) {
if( element.target ) {
element.addEventListener(eventType, function( event ) {
event.preventDefault();
event.stopPropagation();
classie.add(cardContainer, 'card--active');
document.addEventListener(eventType, resetMenuClick);
} ,false);
}
});
我可以想到两种简单的方法来做这样的事情。
首先,如果您不能为每张卡指定 ID(听起来您不能),您将不得不使用 class 名称。就像评论中提到的那样,您真的不想为多个元素使用相同的 ID。
部分原因是,正如您从我下面的示例中看到的那样,.getElementById() 方法仅适用于 return 一个元素,而其他方法如 .getElementsByClassName()将 return 一个元素数组。
我们试图解决的问题是您想要 display/hide 的子内容必须附加到您以某种方式单击的元素。由于我们没有使用 ID,并且您不能真正依赖 class 名称在元素之间是唯一的,因此我将 div 与信息放在一个容器中,该容器带有切换它的元素。
在容器 div 内,有两个 div 内容。一个是始终可见的主要内容,另一个是仅在单击主要内容时才可见的子内容(再次单击时变为不可见)。
此方法的好处是,由于无需担心 ID,您可以 copy/paste 卡片,它们每张都会显示相同的行为。
var maincontent = document.getElementsByClassName("main-content");
// Note: getElemenstByClassName will return an array of elements (even if there's only one).
for (var i = 0; i < maincontent.length; i++) {
//For each element in the maincontent array, add an onclick event.
maincontent[i].onclick = function(event) {
//What this does is gets the first item, from an array of elements that have the class 'sub-content', from the parent node of the element that was clicked:
var info = event.target.parentNode.getElementsByClassName("sub-content")[0];
if (info.className.indexOf("show") > -1) { // If the 'sub-content' also contains the class 'show', remove the class.
info.className = info.className.replace(/(?:^|\s)show(?!\S)/g, '');
} else { // Otherwise add the class.
info.className = info.className + " show";
}
}
}
.container {
border: 1px solid black;
width: 200px;
margin: 5px;
}
.main-content {
margin: 5px;
cursor: pointer;
}
.sub-content {
display: none;
margin: 5px;
}
.show {
/* The class to toggle */
display: block;
background: #ccc;
}
<div class="container">
<div class="main-content">Here is the main content that's always visible.</div>
<div class="sub-content">Here is the sub content that's only visible when the main content is clicked.</div>
</div>
<div class="container">
<div class="main-content">Here is the main content that's always visible.</div>
<div class="sub-content">Here is the sub content that's only visible when the main content is clicked.</div>
</div>
<div class="container">
<div class="main-content">Here is the main content that's always visible.</div>
<div class="sub-content">Here is the sub content that's only visible when the main content is clicked.</div>
</div>
第二种方法是对您想要 show/hide 的内容使用一个 div,单击一个元素将同时切换其可见性和内容。
我将使用前面的示例作为基础,但理想情况下,您会有某种 MVVM 框架,如 React、Knockout 或 angular 来帮助您填写内容。为了这个例子,我将使用子内容 div 中的文本。
var info = document.getElementById("Info");
var maincontent = document.getElementsByClassName("main-content");
for (var i = 0; i < maincontent.length; i++) { //getElemenstByClassName will return an array of elements (even if there's only one).
maincontent[i].onclick = function(event) { //For each element in the maincontent array, add an onclick event.
//This does the same as before, but I'm getting the text to insert into the info card.
var text = event.target.parentNode.getElementsByClassName("sub-content")[0].innerHTML;
info.innerHTML = text; // Set the text of the info card.
info.style.display = "block"; //Make the info card visible.
}
}
info.onclick = function(event) {
info.style.display = "none"; // If the info card is ever clicked, hide it.
}
.container {
border: 1px solid black;
width: 200px;
margin: 5px;
padding: 5px;
}
.main-content {
margin: 5px;
cursor: pointer;
}
.sub-content {
display: none;
margin: 5px;
}
#Info {
cursor: pointer;
display: none;
}
<div id="Info" class="container">Here is some test information.</div>
<div class="container">
<div class="main-content">Link 1.</div>
<div class="sub-content">You clicked link 1.</div>
</div>
<div class="container">
<div class="main-content">Link 2.</div>
<div class="sub-content">You clicked link 2.</div>
</div>
<div class="container">
<div class="main-content">Link 3.</div>
<div class="sub-content">You clicked link 3.</div>
</div>