0

バージョン 1. 以下の編集バージョン

これは私が最初に持っていたものの非常に基本的な表現です。これより短くすることはできないようです。コードの負荷については申し訳ありません。問題がどこにあるのかコメントしました。

拡張フィドル: http://jsfiddle.net/BramVanroy/tKL8E/53/

ご覧のとおり、ホバーできるメニューがあります。通常のビュー (水平メニュー) では、リンクのタイトルを表すツールチップが表示されます (基本的に、変更されたツールチップ)。ウィンドウのサイズを 800 未満に変更すると、メニューが垂直になります (メディア クエリ)。問題は、if 関数内で呼び出された関数がまだ機能することです。変更されたツールチップは (標準のツールチップの代わりに) 表示され、アニメーション化され続け、矢印はまだ配置されています。

function triangleMenu() {
  var wW = $(window).width();
  if (wW > 800) {
    // Get rid of [title]'s and put them in data unless it has sub-items
    $("li:not(.has-sub-menu) > a[title]").each(function () {
      var $this = $(this);
      $this.data("title", $this.attr("title"));
      $this.removeAttr("title");
    });

    // tooltip positioning on hover and overlay fade on all li's
    $("nav li").hover(function () {
      // Bunch of vars

      if (
      ($this.parent("ul:not(.sub-menu)").length || ($this.parent("ul.sub-menu").length && $this.is(":last-child"))) && !$this.hasClass("has-sub-menu")) {

        tooltip.stop(true).css("right", "auto").text(title).animate({
          "left": posL - (tooltip.width() / 2),
            "top": posT + $this.offset().top + 20
        }, 300).fadeTo(200, 1);
      } else if (!$this.is(":last-child") && $this.parent("ul.sub-menu").length) {
        var condition = offL > ((wW / 2) - $this.width()),
          properties = {},
          cssProp = {};

        tooltip.stop(true).text(title);
        if (condition) {
          properties = {
            "left": (offL - tooltip.width() - 30)
          };
        } else {
          properties = {
            "left": (offL + $this.width() + 25)
          };
        }
        $.extend(properties, {
          "top": ($this.offset().top + (posT / 2) - (tooltip.height() / 2))
        });

        tooltip.animate(properties, 300).fadeTo(200, 1); // SO TOOLTIP ANIMATES, BUT ONLY WHEN WINDOW WIDTH EXCEEDS 800
      }
    },function () {
    });
  } else { // IF WINDOW IS TIGHTER THAN 800 PX
    // Put data back
    $("li:not(.has-sub-menu) > a").each(function () {
      var $this = $(this),
        title = $this.data("title");

      $this.attr("title", title);
    });
  }
}

triangleMenu();

$(window).resize(function () {
  triangleMenu();
});

繰り返しますが、この例が広範で申し訳ありませんが、動作しない機能を失わずに、これ以上削減することはまったく不可能です。


新機能: バージョン 2

いくつかの助けと多くのテストと砂糖の過剰な飲み物で、私は「メインメニュー」が機能するようになりました. ただし、サイズ変更された (モバイル/レスポンシブ) メニューは機能しません。

新しいフィドル

小さいメニューにサイズ変更する場合 (小さい、大きい、小さいの 2 回サイズ変更する必要がある場合があります)、サブ メニューを持つアイテムをクリックして開くことができるはずですが、これは機能しません。li をクリックすると、サブアイテムに一連のインライン スタイルが表示されますが、それらがどこから来たのかわかりません!

overflow: hidden; display: none; height: 159px; padding-top: 0px; margin-top: -2px; padding-bottom: 0px; margin-bottom: 0px;

メニューが表示されなくなったと思いますが、原因がわかりません。

4

2 に答える 2

1

NEW :バージョン2に基づく

あなたが見逃している重要なことは、$("nav li.has-sub-menu")サイズ変更中に同じクリック関数をバインドしすぎることです。

console.log(1)以下のようにクリックハンドラーにを追加します。

    $("nav li.has-sub-menu").click(function () {                                                                               
        var $this = $(this);
        console.log(1);
        $this.children("ul.sub-menu").stop(true).slideToggle("fast");
    }); 

そして、それは1あなた以外ではないと私が思う多くを印刷します。

そしてもっと重要なのは、電話の回数console.log(1);が常に均等であるということです。理由はよくわかりません。ただし、これは、サブメニューの表示/非表示を何度も繰り返し、最後に非表示にすることを意味します。)

そこで、次のコードを追加して、バインドする前にすべてのクリック関数のバインドを解除します。できます。ここを参照してください

$("nav li.has-sub-menu").unbind("click");

次に言いたいのは、関数triangleMenuでは、サイズ変更中にすべてのコードが何度も実行されるということです。

> 800したがって、ここにブール変数を追加して、現在またはに保存できると思います。したがって< 800、この変数が変更された場合にのみ、すべてのコードを実行できます。

そして、私はそれを以下のように実行します:

var is_mobile;

function triangleMenu(){
    var wW = $(window).width();
    if (wW > 800 && (is_mobile === undefined || is_mobile)) {
       console.log('change to pc');
       is_mobile=false;
       //your code here
    } else if(wW <=800 && !is_mobile) {
       console.log('change to mobile');
       is_mobile=true;
       //your code here
    }
}

これがjsfiddleです。

アップデート

クリックが複数回記録される理由を知っていますか?変なの?

ブラウザのサイズを変更している間、$(window).resize常に呼び出されるためです。console.log次のようにチェックするを追加できます。

$(window).resize(function () {
    console.log('resizing');                                                                                                       
    triangleMenu();
});

そして、is_mobile varについて説明していただけますか?

これについては、上記のコードを以下のように前のコードと比較できます。

function triangleMenu(){
    var wW = $(window).width();
    if (wW > 800 ) {
       console.log('change to pc');
       //your code here
    } else {
       console.log('change to mobile');
       //your code here
    }
}

実行回数が少なくなりますconsole.log。つまり、jsが同じことを繰り返し実行する必要がなくなります。

is_mobileつまり、現在wW>800サイズ変更中の幅がどれほど正確であっても、に設定is_mobileしたfalseので、initとbindを繰り返し実行する必要はありません。wWが最初の場合にのみ<=800、に設定is_mobiletrue、モバイルサイズに変更することをマークしてから、初期化してバインドします。これらの後で、である限り、initを実行してaginをバインドする必要はありませwW<=800。反対も同じです。

私の英語はあまり上手ではありません。はっきりと説明できるかどうかわかりません。

于 2013-01-23T08:47:51.407 に答える
1

私はこの問題の専門家ではありませんが、問題の解決策を見つけました。多くのテストの後、どういうわけか、if 状態の 1 つでトリガーされた関数の一部がバインドされたままになっていることがわかりました。私はそれを発見しました:

  1. $(window).resize()関数をトリガーしていました。
  2. 初期のウィンドウ サイズは期待どおりに機能しました。
  3. しかし、サイズを変更した後、機能は持続しているように見えました。

拘束力のある問題があるという結論に達し、これを試してみたところうまくいきました.elseステートメントで、この最初の行を追加しました$("nav li").unbind('hover');. これにより、要素にバインドされたままのホバー機能が取り除かれました。

しかし、その後、矢も持続していることに気付きました。これに対処するには、2 行のコードを追加する必要がありました。まず、else ステートメントに を追加しました $("ul:not(.sub-menu) > li, ul.sub-menu > li:last-child").removeClass("over-down");

しかし、それだけでは十分ではありませんでした。関数にも移動$("ul:not(.sub-menu) > li, ul.sub-menu > li:last-child").not(":has(ul.sub-menu)").addClass("over-down");して$("nav li").hover()、より単純なものに変換しました。

$(this).addClass("over-down");.

それが最もエレガントなソリューションかどうかはわかりませんが、うまくいくようです。専門家がこれをよりよく説明できることを願っています。

もっとバグが見つかるかもしれませんが、これはこの機能の他の問題を修正するのに役立つと思います. ロジックと手順の一部を変更すると、より堅牢なコードが実行される可能性があります。

PS: Chrome でウィンドウのサイズを変更すると、メニューの高さにまだ問題があります。

于 2013-01-18T21:06:57.650 に答える