html5 подробный тег открыть одну за другой JavaScript-функцию, работающую странно
Я использую тег HTML5 для раздела часто задаваемых вопросов о компании. Проблема заключалась в том, что если пользователь открыл другой вопрос, другой вопрос не будет закрыт автоматически. Поэтому я искал в Интернете и нашел следующее решение:
function thisindex(elm){
var nodes = elm.parentNode.childNodes, node;
var i = 0, count = i;
while( (node=nodes.item(i++)) && node!=elm )
if( node.nodeType==1 ) count++;
return count;
}
function closeAll(index){
var len = document.getElementsByTagName("details").length;
for(var i=0; i<len; i++){
if(i != index){
document.getElementsByTagName("details")[i].removeAttribute("open");
}
}
}
В некотором смысле этот код работает правильно, но у него есть небольшие проблемы. Иногда он открывает два вопроса одновременно и работает забавно. Есть ли способ, чтобы он мог работать правильно? Это должно работать на рабочем столе, планшете и мобильном телефоне.
НЕ НУЖНЫЙ ЭФФЕКТ:
Я создал скрипку http://jsfiddle.net/877tm/ со всем кодом. Javascript делает свою работу там, если вы хотите увидеть его вживую, нажмите здесь.
5 ответов
Так как вы пометили jQuery, вы можете просто сделать это:
$('.info').on('click', 'details', function () {
$('details').removeAttr('open');
$(this).attr('open', '');
});
Все это делает, это удалить open
атрибут всего detail
теги при нажатии на любой detail
, а затем снова откройте тот, на который вы только что нажали.
Функция дырки thisindex глупа и может быть удалена. Вы можете просто передать элемент details в closeAll.
CloseAll довольно глупо, он также ищет детали в цикле for, вау.
// закрыть все
function closeAll (openDetails){
var details = document.getElementsByTagName("details");
var len = details.length;
for(var i=0; i<len; i++){
if(details[i] != openDetails){
details[i].removeAttribute("open");
}
}
}
В случае, если вы хотите написать чистый код.
- Вы должны использовать $.on или addEventlistener.
- Старайтесь быть в определенном контексте и манипулировать только деталями в этом контексте. (Что произойдет, если вы хотите иметь две области аккордеона. Или некоторые обычные детали на одном сайте, но не внутри группы.)
- Искать детали в группе, только если детали были открыты, а не закрыты.
- Придайте свойству boolen open некоторую любовь вместо использования атрибута content
Я сделал небольшую скрипку, которая пытается это сделать.
Чтобы сделать детали как тег аккордеона, вы можете использовать ниже JQuery.
$("#edit-container details summary").click(function(e) {
var clicked = $(this).attr('aria-controls');
closeAll(clicked);
});
function closeAll (openDetailid){
$("#edit-container details" ).each(function( index ) {
var detailid = $(this).attr('id');
var detailobj = document.getElementById(detailid);
if (openDetailid != detailid ) {
detailobj.open = false;
}
});
$('html, body').stop().animate({ scrollTop: $('#'+openDetailid).offset().top -100 }, 1000);
}
У меня возникла проблема с ответом @MattDiamant, когда Firefox удалял атрибут open, но не помещал атрибут open в выбранную деталь. Я внес небольшое изменение в его код, чтобы он ориентировался на идентификатор выбранного в данный момент элемента детали.
Теперь, когда я нажимаю на<details>
элемент, затем щелкните другой, он сворачивает первый элемент и отображает второй.
$('details').click(function(e){
$('details').removeAttr('open');
$(e.currentTarget.id).attr('open', '');
});
У меня есть решение с помощью jQuery
$('details').on('click', function(ev){ //on a '<details>' block click
ev.preventDefault(); //prevent the default behavior
var attr = $(this).attr('open');
if (typeof attr !== typeof undefined && attr !== false){ //if '<details>' block is open then close it
$(this).removeAttr('open');
}else{ // if '<details>' block is closed then open the one that you clicked and close all others
var $that = $(this); //save the clicked '<details>' block
$(this).attr('open','open'); //open the '<details>' block
$('details').each(function(){ //loop through all '<details>' blocks
if ($that.is($(this))){ //check if this is the one that you clicked on, if it is than open it or else close it
$(this).attr('open','open');
}else{
$(this).removeAttr("open");
}
});
}
});