2009-06-28 14 views
0

私はJqueryで水平アコーディオンを構築しようとしています。それはFirefoxで "ok"で動作しているようです。しかしWebkit(Safari 3 + 4、およびChrome)では、Hideレベルの機能の後にサブレベルのULが点滅します。どんな助けでも大歓迎です。作業のデモを参照するには:ここではhttp://ableobject.com/horaccordion1.htmlJquery Horizo​​ntal Accordion Webkitバグ

は私が働いているものです:それは、私はWebKitのと少し前だった問題に関連しているよう

<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> 

答えて

1

これが聞こえます。エレメントの幅を減らすアニメーションの後に、エレメントの親を元のサイズに戻すWebkitバグがあります。アニメーションの後、その要素の親はその内容に適応するために元のサイズにジャンプします。

編集:jQueryUIに関するコメントが削除されました。なぜあなたがそれを使っていると思ったのか分かりません。

バグはhereで説明されていますが、これは回避策の詳細です。

私はをjQueryにも提出しました。

基本的には、$subと同じ量だけ要素の親の幅を同時に小さくする必要があります。したがって、$subの幅が100ピクセルの場合は、親を100ピクセル縮小する別のanimate()があります。

私はあなたの例でこれをテストしていませんが、おそらくキーと思われます。

編集2: 新しいバージョン使用のdiv

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; 

}

のjavascript:

// 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> 
+0

の先頭に次のDTDを追加します。まだ点滅しています。私はそれを把握して再投稿しようとします...しかし、現時点では解決策は私を逃れます。 多分: $ sub.parent()。css({width: ''}); $ current = $ sub; ? – stapler

+0

おかげさまでたくさんのpatrick – stapler

+0

'list'要素の使用はどれくらい重要ですか?最終的にそれらを切り捨ててdivを使用した後、私はWebkitで動作するかなり簡潔なアコーディオンを考え出しました。 – user113716

1

私はあなたがまだ前のものが便利念のために別の答えとしてこれを掲示しています。

は、次の点に注意してください

  • 私は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; 
} 

javascriptの

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> 

編集:は、私はhttp://ableobject.com/horaccordion2.htmlそれを試してみたが、私は、拡張トップレベル3それからトップレベル4からつもりだとき、あなたのPAGE-

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" 
"http://www.w3.org/TR/html4/strict.dtd"> 
+0

これはすごくうまくいきました。IEの中心にどのように配置すればいいのか分かりません:) – stapler

+0

Firefoxで奇妙なバグに遭遇しました...リンクサイズを16pxに変更しました。 ?私はもっ​​と多くの(そしてそれ以下の)ピクセルを追加しようとしました...そして、パディングをして遊んで...私はそれが表示されるように見えることができません。 – stapler

+0

つまり、センターのために、ページの最上部に以下を追加してください。 <!DOCTYPE HTML PUBLIC " -// W3C // DTD HTML 4.01 // EN" "http://www.w3.org/TR/html4/strict.dtd"> 私はFirefoxを理解することができるはずだと思います問題。おそらく月曜日にあなたに戻ってくるでしょう。 – user113716

関連する問題