0

したがって、私のPHP Webisteは、次のようなDHTML出力を生成します。

<div class="toggle-ctrl" onclick="toggleMenu();">
    click me to toggle menu
</div>
<div id="site-menu">
    <ul>
        <li>opt 1</li>
        <li>opt 2</li>
    </ul>
</div>
<p><a href="#">Link to Myself</a></p>

そしてもちろん、クリックすると、最初のdivはJavaScriptを呼び出し、JavaScriptの表示を切り替えます。site-menu

function toggleMenu() {
    var navigation_pane  = document.getElementById('site-menu').style;
    if ( navigation_pane.display == 'none' )
        navigation_pane.display = 'block';
    else
        navigation_pane.display = 'none';
}

これはすべて正常に機能します。今気になっているリンクをクリックしています。それをクリックすると(もちろん)新しいhttpリクエストが作成され、私のPHPエンジンはページを再生成します。

この問題は、の可視性がである場合に発生しsite-menuます'none'。PHPエンジンはメニューが非表示になっていることを認識しないため、同じhtmlを再度生成し、ブラウザーはメニューを驚いたユーザーの前に戻します。

site-menuしたがって、問題は、ページを再生成する前に、PHPに可視性のステータスをどのように通知するか(またはPHPがどのようにチェックできるか)です。

4

5 に答える 5

2

メニュー状態をPHPスクリプトに送信する以外に、少なくとも2つのオプションがあります。

  1. AJAXを使用して、ページの一部だけをロードします。メニューをリロードしない場合は、スタイルを再初期化する必要はありません。この道を進む前に、AJAXが適切かどうかを調べてください。このソリューションを実装する場合は、ブラウザの機能を壊さないでください。
  2. 最新のブラウザはストレージメカニズムをサポートしています。メニューの状態がlocalStorage変更されたときに保存し、ページが読み込まれたときにメニューの状態を設定します。古いブラウザをサポートするために、利用可能な場合はWebストレージを使用し、利用できない場合はCookieを使用するAPIを作成できます(jQuery.Storageがこれを行います)。

    Menu.js:

    /* implementation of Storage, Class and addEventListenerTo left as 
       an exercise for the reader.
    */
    var Menu = {
        init: function(id, toggleId) {
            if (! toggleId) {
                toggleId = id + '-toggle';
            }
            var toggler = document.getElementById(toggleId),
                menu = document.getElementById(id);
            menu.toggler = toggler;
            /* addEventListenerTo should call the browser-supplied event subscriber 
               method (e.g. addEventListener or attachEvent)
            */
            addEventListenerTo(toggler, 'click', 
                function(evt) {
                    Menu.toggle(id);
                });
    
            if (! Storage.exists(id+'-open')) {
                Storage.set(id+'-open', true);
            }
    
            if (Storage.get(id+'-open')) {
                Menu.open(id);
            } else {
                Menu.close(id);
            }
        },
        toggle: function(id) {
            var menu = document.getElementById(id);
            Class.toggle(menu, 'open closed');
            if (Class.has(menu, 'open')) {
                menu.toggler.firstChild.nodeValue = 'close menu';
                Storage.set(id + '-open', true);
            } else {
                menu.toggler.firstChild.nodeValue = 'open menu';
                Storage.set(id + '-open', false);
            }
        },
        setState: function (id, toAdd, toRemove) {
            var menu = document.getElementById(id);
            Class.remove(menu, toRemove);
            Class.add(menu, toAdd);
        },
        open: function(id) {
            this.setState(id, 'open', 'closed');
        },
        close: function(id) {
            this.setState(id, 'closed', 'open');
        }
    };
    

    いくつかのCSSファイル:

    .closed { display: none; }
    

    ページ:

    <div id="site-menu-toggle" class="toggle-ctrl">close menu</div>
    <div id="site-menu" class="open">
        <ul>
            <li>opt 1</li>
            <li>opt 2</li>
        </ul>
    </div>
    <p><a href="#">Link to Myself</a></p>
    
    <script type="text/javascript">
    Menu.init('site-menu');
    </script>
    

    jsFiddleでMenu.jsアプローチのライブバージョンで遊ぶことができます。jQueryを使用すると、Menu.jsを廃止でき、より簡潔な実装になります。

    <script type="text/javascript">
    $('#site-menu-toggle').click(function (evt) {
            var $menu = $('#site-menu');
            $menu.toggleClass('open close');
            $.Storage.set('site-menu-state', $menu.attr('class'));
            if ($menu.hasClass('open')) {
                $('#site-menu-toggle').text('close menu');
            } else {
                $('#site-menu-toggle').text('open menu');
            }
        });
    $(function() {
        var state = $.Storage.get('site-menu-state');
        if (! state) {
            $.Storage.set('site-menu-state', $('#site-menu').attr('class'));
        } else {
            $('#site-menu').attr('class', state);
        }
    });
    </script>
    

    jQueryメニューの状態を実装するためのjFiddleがあります。

メニューの状態の違いは、概念的にはリソースの違いにはならないため、メニューを開いたり閉じたりすることがブックマーク可能であるか、履歴の影響を受けるかは関係ありません。

NB。「 clickme」というテキストは使用しないでください。冗長すぎて冗長です(他にどのようなアクションがありますか?アフォーダンスは暗黙的である必要があります)。代わりに、グラフィックを使用して開閉を示すか、単に「メニューを開く」/「メニューを閉じる」と言うことができます。

于 2012-04-25T19:18:37.223 に答える
2

したがって、問題は、ページを再生成する前に、サイトメニューの可視性のステータスをPHPに通知する方法(またはPHPがチェックする方法)です。

できません。HTMLがブラウザに配信されるまでに、PHPはもはや画像に含まれていません。PHPにこれを認識させる唯一の方法は、メニューが非表示であることを示すパラメータをURLで送信するか、Cookieを設定してCookieにオブジェクトの可視性を示すことです。次に、PHPはこの値の存在を確認し、レンダリング時にdivの可視性を設定できます。

これは、次のようなさまざまな方法で実現できます。

  • document.cookieを使用して、toggleMenu関数にCookieを設定します。
  • ajaxを使用してtoggleMenu関数でPHPに通知し、PHPにCookieまたはセッション値を設定させます
  • トグルメニュー関数からのメニューの可視性を示すフラグをリンクに追加します。
于 2012-04-25T18:43:41.320 に答える
1

実際、あなたの質問に対する答えにはいくつかの種類があります。

やりたいことをする方法はないように聞こえるかもしれませんが、実際には多くの方法があります。

クッキー

明らかです。クッキーは、PHPだけでなくJavaScriptからもアクセスできます。メニューがjavascriptで表示/非表示になるたびにCookieを変更するだけです(優れたjQuery cookieプラグインがあります)。

フォーム入力

フォームを送信する場合は、非表示の入力でメニューの可視性の値を維持するだけです。

<input type="hidden" name="menu-visibility" value="0"/>

繰り返しますが、この入力を最新の状態に保つにはjavascriptが必要です。

ページの関連部分を更新する

これがヒップ&リートの新しいトレンドです。ええと、実際、それは約6年ほどそこにありました。基本的に、何も送信したり、ページをリロードしたりしないでください。AJAXを使用して、実際に更新が必要なページの部分を更新します。

ローカルストレージ

@outisが述べたように、今日のブラウザにはCookieに似たものがありますが、それを自分で保持する点が異なります(したがってローカルで)。これはかなり新しい機能です。正直なところ、必要なことを達成するためのより良い方法があることを考えると、私はそれを信用しません。

于 2012-04-25T19:19:18.953 に答える
1

drew010の提案に加えて、たとえば、値がtoggleMenu()によって設定される「menu_status」という名前の非表示の入力要素を使用してフォームを作成することもできます。次に、リンクをクリックしたら、javascriptを使用してフォームをPOSTまたはGETします。次に、formメソッドに応じて、$_POST["menu_status"]またはのいずれかを使用してphpで値サーバー側を読み取ります。$_GET["menu_status"]

更新:このようなもの:

<form name="session_form" action="" method="POST">
    <input type="hidden" name="menu_state" value="block">
</form>

<?php $menu_state = isset($_POST["menu_state"]) ? $_POST["menu_state"] : "block"; ?>

<div id="site-menu" style="display:<?php echo $menu_state; ?>">
<ul>
    <li>opt 1</li>
    <li>opt 2</li>
</ul>
</div>

<p><a href="#" onClick="document.forms.session_form.submit();return false;">Link to Myself</a></p>

function toggleMenu() {
    var navigation_pane  = document.getElementById('site-menu').style;
    if ( navigation_pane.display == 'none' )
        navigation_pane.display = 'block';
    else
        navigation_pane.display = 'none';
    document.forms.session_form.menu_state.value = navigation_pane.display;
}

編集:jQuery ajaxの使用には、次のようなものが含まれる可能性があります。

<div class="toggle-ctrl">click me to toggle menu</div>

<?php $menu_state = isset($_POST["menu_state"]) ? $_POST["menu_state"] : "block"; ?>

<div id="site-menu" style="display:<?php echo $menu_state; ?>">
<ul>
    <li>opt 1</li>
    <li>opt 2</li>
</ul>
</div>

<p><a href="#" id="go">Link to Myself</a></p>

$("div.toggle-ctrl").click(function(){
    $("#site-menu").toggle();
});

$("#go").click(function(e) {
    e.preventDefault();
    var menu_state = $("#site-menu").css("display");
    $.post("", {menu_state:menu_state}, function (response) {
        $("html").html(response);
    });
});

または、ajaxやフォームを使用せずに、リンクにパラメーターを追加し、PHPで$_POSTの代わりに$_GETを使用します。

$("#go").click(function(e) {
    e.preventDefault();
    var menu_state = $("#site-menu").css("display");
    document.location.href = "index.php?menu_state=" + menu_state;
});

これは私には最も簡単な解決策のようです。

于 2012-04-25T18:49:16.580 に答える
0

あなた自身の質問に答えるのはクールではないことを私は知っていますが、昨夜私に別の可能な解決策が起こりました、そしてそれは書かれるべき1行の新しいコード(一種)だけを必要とします。

ソリューションの最初の部分は、すでに多くの人から暗黙のうちに提案されています。JavaScriptを変更してCookieに書き込みます。

function toggleMenu() {
    var navigation_pane  = document.getElementById('site-menu').style;
    if ( navigation_pane.display == 'none' )
        navigation_pane.display = 'block';
    else
        navigation_pane.display = 'none';
    document.cookie = "menu_vis=" + navigation_pane.display; // +1 line of code
}

さて、あなたのCSSファイルがたまたま変装したPHPファイルである場合、どのような可能性がありますか? my_css.php次のようになります。

<?php
header("Content-type: text/css");
?>
#site-menu {
    display: <?php echo isset($_COOKIE['menu_vis']) ? $_COOKIE['menu_vis'] : 'block'; ?>;  /* line of code modified, but not added! */
}

今朝テストしました、そしてそれは働きます。

これは、PHPやHTMLのデザインをプレゼンテーションの問題に合わせて曲げる必要がないことを意味するため、優れたソリューションだと思います。

-私はそこにもっと「包括的な」解決策があることを感謝します。私がより優れたJavaScript開発者であれば(またはjQueryなどを利用して)、より複雑なクラスを作成して、他のHTML要素にさらに一般的に適用することができます。後でそのような解決策を調査す​​るために戻ってくるかもしれませんが、それは私のプロジェクトが現在ある場所ではありません。

みなさん、ありがとうございました。これらのアイデアを皆さんにバウンスさせずに、この解決策を見つけることはできなかったでしょう。

于 2012-04-26T09:21:04.537 に答える