jQuery 수평 아코디언 웹 키 버그
-
20-08-2019 - |
문제
나는 jQuery와 함께 수평 아코디언을 만들려고 노력하고 있습니다. Firefox에서 "OK"가 작동하는 것 같습니다. 그러나 WebKit (Safari 3 + 4 및 Chrome)에서는 숨은 기능 이후 하위 레벨 UL이 깜박입니다. 모든 도움은 대단히 감사하겠습니다. 작동하는 데모를 보려면 : http://abableobject.com/horaccordion1.html
내가 작업중 인 작업은 다음과 같습니다.
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"></script>
<title>untitled</title>
<style type="text/css">
#container {
display: table;
margin: 0 auto;
text-align: center; /* for IE */
}
ul{
list-style: none;
background-color: yellow;
margin: 0;
padding: 0;
float: left;
height: 20px; /* For testing */
}
ul li {
background-color: aqua;
float: left;
}
ul li ul {
background-color: blue;
display: none;
}
ul li ul li {
background-color: green;
}
a, a:link, a:hover, a:visited, a:active {
color: black;
text-decoration: none;
float: left;
}
</style>
<script type="text/javascript">
/* Care of Hunter Daley */
var $current = null;
$(document).ready(function(){
$("ul li ul").hide(); // hide submenus by default on load
$("ul li a").click(function(){
var $sub = $(this).next();
if ($sub.css("display") == "none")
{
if ($current != null)
$current.animate({ width: 'hide' }); // if you want to only show one sub at a time
$sub.animate({ width: 'show' });
$current = $sub;
}
else
{
$sub.animate({ width: 'hide' });
$current = null;
}
});
});
</script>
</head>
<body>
<div id="container">
<ul>
<li>
<a href="#">Top-level 1</a>
</li>
<li>
<a href="#">Top-level 2</a>
<ul>
<li><a href="#">Bottom Level A1</a></li>
<li><a href="#">Bottom Level A2</a></li>
<li><a href="#">Bottom Level A3</a></li>
<li><a href="#">Bottom Level A4</a></li>
</ul>
</li>
<li>
<a href="#">Top-level 3</a>
<ul>
<li><a href="#">Bottom Level B1</a></li>
<li><a href="#">Bottom Level B2</a></li>
</ul>
</li>
<li>
<a href="#">Top-level 4</a>
</li>
</ul>
</div>
</body>
해결책
이것은 WebKit과 함께 조금 전에 가지고 있었던 문제와 관련이있는 것 같습니다. 원소의 폭을 줄이는 애니메이션 후에 요소의 부모가 원래 크기로 되돌아가는 WebKit 버그가 있습니다. 애니메이션 후, 요소의 부모는 콘텐츠를 수용하기 위해 원래 크기로 돌아갑니다.
편집 : jqueryui에 대한 주석을 제거했습니다. 내가 왜 당신이 그것을 사용하고 있다고 생각했는지 잘 모르겠습니다.
버그가 논의되었습니다 여기, 해결 방법을 자세히 설명합니다.
나는 제출했다 버그 보고서 jQuery에도.
기본적으로 동시에 폭을 줄여야합니다. $sub
같은 금액으로 요소의 부모 $sub
감소하고 있습니다. 따라서 너비가 있다면 $sub
100px이고 별도가 있습니다 animate()
부모를 100px로 줄입니다.
나는 당신의 예를 가지고 이것을 테스트하지 않았지만 아마도 그것이 핵심이라고 생각합니다.
편집 2 :divs를 사용하는 새 버전
CSS :
.title {
list-style: none;
margin: 0;
padding: 0;
float: left;
height: 32px; /* For testing */
font-family: helvetica;
font-size: 18px;
clip: auto; overflow: hidden;
}
.menu {
height: 32px; /* For testing */
clip: auto; overflow: hidden;
float: left;
}
a, a:link, a:hover, a:visited, a:active {
color: black;
text-decoration: none;
padding: 12px;
font-weight: 700;
float: left;
color: #222;
}
.menu a, .menu a:link, .menu a:hover, .menu a:visited, .menu a:active {
color: black;
text-decoration: none;
padding: 12px;
font-weight: normal;
float: left;
}
자바 스크립트 :
// Prevents us from having to check for null.
var $current = $('#someFictionalElement');
var $previous = null;
$(document).ready(function(){
$(".menu").css({width: 0}); // hide submenus by default on load
$(".title").click(
function() {
$previous = $current;
$current = $(this);
var $currentMenu = $current.next();
$previous.next().animate({ width: 0 }, {duration: 1000, queue: false} );
// Make sure that if there's no menu text (like Top Level 1 and 4) that it does not animate.
// This is because of the pixels added for Firefox (see comment below)
if( $currentMenu.width() == 0 && $currentMenu.text() != '' ) {
// Expand the menu but keep it hidden so we can get its width
$currentMenu.css({visibility: 'hidden', width: ''});
// Store the width, and add a few pixels for Firefox
var currentWidth = $currentMenu.width() + 3;
// Make menu visible and set with to 0 in preparation for the animation
$currentMenu.css({visibility: 'visible', width: 0})
.animate({ width: currentWidth }, 1000);
}
});
$(".title a").hover(
function(){$(this).animate ({ opacity: 0.7 }, 200);},
function(){$(this).animate ({ opacity: 1 }, 600);}
);
});
HTML :
<body>
<div id="container">
<div class='title' id='level1'>
<a href="#">Top-level 1</a>
</div>
<div class='menu'></div>
<div class='title' id='level2'>
<a href="#">Top-level 2</a>
</div>
<div class='menu'>
<a href="#">Bottom Level A1</a>
<a href="#">Bottom Level A2</a>
<a href="#">Bottom Level A3</a>
<a href="#">Bottom Level A4</a>
</div>
<div class='title' id='level3'>
<a href="#">Top-level 3</a>
</div>
<div class='menu'>
<a href="#">Bottom Level B1</a>
<a href="#">Bottom Level B2</a>
</div>
<div class='title' id='level4'>
<a href="#">Top-level 4</a>
</div>
<div class='menu'></div>
</div>
</body>
다른 팁
이전에 유용한 것을 찾을 경우를 대비하여 이것을 별도의 답변으로 게시하고 있습니다.
다음에 참고하십시오.
- IE에서 이것을 테스트하지 않았습니다.
- 이것은 '중첩'버전으로 돌아가서 클래스와 변수 이름을 약간 변경했습니다.
- 표시 할 메뉴가 없을 때 빈 메뉴가 더 이상 필요하지 않습니다.
- 각 메뉴의 '컨테이너'의 너비는 이제 메뉴와 같은 양을 줄입니다. 이것이 WebKit의 임시 플래시 (원래 전략)를 제거하는 것입니다.
- 메뉴의 애니메이션 타이밍이 메뉴 컨테이너와 약간 다릅니다. 기본적으로 확장 할 때 컨테이너가 조금 앞서 나가고 줄일 때 메뉴가 조금 앞서 나가기를 원합니다. 타이밍이 동일하게 설정되면 메뉴의 플래시를 얻을 수 있습니다.
- 주석에 설명 된 바와 같이, 처음에, 각 메뉴는 'fullwidth'라는 이전에 존재하지 않는 속성을 설정하여 완전히 확장 될 때 폭우를 암기합니다. 그런 다음 필요할 때이 속성의 값을 검색합니다. 글로벌 변수 또는 jQuery의 Data () 함수를 쉽게 사용하여 정보를 저장할 수 있습니다. 요점은 각 메뉴가 확장 될 때 얼마나 넓은지를 알고 있으면 상황이 단순화된다는 것입니다.
그래서 여기 있습니다. 도움이되기를 바랍니다!
CSS
#container {
margin: 0 auto 0 auto;
text-align: center;
display: table;
}
.menuContainer {
margin: 0;
padding: 0;
float: left;
height: 32px; /* For testing */
font-family: helvetica;
font-size: 18px;
clip: auto; overflow: hidden;
}
.menu {
height: 32px; /* For testing */
clip: auto; overflow: hidden;
float: left;
}
a, a:link, a:hover, a:visited, a:active {
color: black;
text-decoration: none;
padding: 12px;
font-weight: 700;
float: left;
color: #222;
}
.menu a, .menu a:link, .menu a:hover, .menu a:visited, .menu a:active {
color: black;
text-decoration: none;
padding: 12px;
font-weight: normal;
float: left;
}
자바 스크립트
var $currentMenuContainer = $('#someFictionalElement');
var $previousMenuContainer = null;
$(document).ready(function() {
// Iterate through each .menu element, setting the full width of each menu to a 'custom'
// attribute called 'fullWidth'. Since the full width should never change, this
// makes it easy to recall it quickly. You could use global variables instead.
// After setting 'fullWidth', it then collapses each menu and title.
$(".menu").each(function() {
var $theMenu = $(this);
var $theMenuContainer = $theMenu.parent();
$theMenu.attr({fullWidth: ($theMenu.width() + 3)}); // Add a few pixels for firefox
var menuContainerWidth = $theMenuContainer.width() - $theMenu.attr('fullWidth') + 6; // Add DOUBLE the pixels here
$theMenu.css({width: 0});
$theMenuContainer.css({width: menuContainerWidth});
});
$(".menuContainer a").click(
function() {
// Set the current and previous elements properly
$previousMenuContainer = $currentMenuContainer;
$currentMenuContainer = $(this).parent();
var $previousMenu = $previousMenuContainer.find('.menu');
var $currentMenu = $currentMenuContainer.find('.menu');
// Collapse the previous menu
$previousMenu.animate({ width: 0 }, {duration: 480, queue: false} );
// Subtract the width of the previous menuContainer's menu from the menuContainer (only if its menu is displayed)
if($previousMenu.width() > 0) $previousMenuContainer.animate({width: ('-=' + $previousMenu.attr('fullWidth'))}, 500);
// Expand the current menu and its menuContainer if it's not showing
if($currentMenu.width() == 0) {
// Increase the menuContainer width by the full width of its menu
$currentMenuContainer.animate({width: ('+=' + $currentMenu.attr('fullWidth'))}, 480);
// Increase the menuContainer to its full width
$currentMenu.animate({ width: $currentMenu.attr('fullWidth') }, 500);
}
});
$(".menuContainer a").hover(
function(){$(this).animate ({ opacity: 0.7 }, 200);},
function(){$(this).animate ({ opacity: 1 }, 600);}
);
});
HTML
<div id="container">
<div class='menuContainer'>
<a href="#">Top-level 1</a>
</div>
<div class='menuContainer'>
<a href="#">Top-level 2</a>
<div class='menu'>
<a href="#">Bottom Level A1</a>
<a href="#">Bottom Level A2</a>
<a href="#">Bottom Level A3</a>
<a href="#">Bottom Level A4</a>
</div>
</div>
<div class='menuContainer'>
<a href="#">Top-level 3</a>
<div class='menu'>
<a href="#">Bottom Level B1</a>
<a href="#">Bottom Level B2</a>
</div>
</div>
<div class='menuContainer'>
<a href="#">Top-level 4</a>
</div>
</div>
편집하다: 페이지 상단에 다음 DTD를 추가하십시오.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">