PHP如何访问div的“样式”属性?

时间:2012-04-25 18:22:57

标签: php javascript dom dynamic dhtml

所以我的PHP网站生成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来切换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,浏览器将菜单放回到看起来很惊讶的用户面前。

因此,问题是,在重新生成页面之前,我如何通知PHP(或PHP如何检查)site-menu的可见性状态是什么?

5 个答案:

答案 0 :(得分:2)

  

因此,问题是如何通知PHP(或PHP如何通知   检查站点菜单可见性的状态,在它之前   去重新生成页面?

它不能。当HTML被传递到浏览器时,PHP就不再适用了。让PHP意识到这一点的唯一方法是在URL中发送一个参数,指示菜单被隐藏,或者设置一个cookie并让cookie指示对象的可见性。然后,PHP可以检查是否存在此值,并在呈现div时设置div的可见性。

您可以通过多种方式完成此任务,例如:

  • 使用document.cookie在toggleMenu函数中设置Cookie。
  • 使用ajax在toggleMenu函数中通知PHP并让PHP设置cookie或会话值
  • 在链接上附加一个标记,指示toggleMenu函数的菜单可见性。

答案 1 :(得分:2)

除了将菜单状态发送到PHP脚本之外,至少有两个选项。

  1. 使用AJAX加载页面的一部分。如果不重新加载菜单,则无需重新初始化其样式。在沿着这条路走下去,检查一下AJAX is suitable。如果您实施此解决方案,请不要break browser functionality
  2. 现代浏览器支持storage mechanism。更改时将菜单状态存储在localStorage中,并在页面加载时设置菜单状态。要支持旧版浏览器,您可以创建一个在可用时使用网络存储的API,而在不使用时创建Cookie(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 menu state实现的jFiddle。

  3. 由于菜单状态的差异在概念上并不适用于不同的资源,因此打开或关闭菜单是否可收藏或受历史影响无关紧要。

    NB。不要使用文本“click me”,它太冗长和冗余(还有哪些其他操作?Affordances应该是隐含的。)。相反,您可以使用图形来指示打开/关闭,或者只是说“打开菜单”/“关闭菜单”。

答案 2 :(得分:1)

除了drew010的建议之外:您还可以创建一个带有隐藏输入元素的表单,例如,'menu_status',其值由toggleMenu()设置。然后,当您单击链接时,使用javascript POST或获取表单。然后使用$_POST["menu_status"]$_GET["menu_status"]使用php读取值服务器端,具体取决于表单方法。

更新:这样的事情:

<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中使用$ _GET而不是$ _POST:

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

在我看来,这是最简单的解决方案。

答案 3 :(得分:1)

实际上,您的问题有几种类型的答案。

虽然可能听起来没有办法做你想做的事,但实际上有很多方法。

<强>缓存

显而易见。可以通过javascript和PHP访问Cookie。只要通过javascript显示/隐藏菜单,就可以修改cookie(这里有优秀的jQuery cookie插件)。

表单输入

如果您要提交表单,只需隐藏输入即可保持菜单可见性的值:

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

同样,您需要使用javascript来更新此输入。

更新页面的相关部分

这是时尚&amp;新的趋势。嗯,实际上,它已经存在了大约6年左右。基本上,不要提交任何内容,也不要重新加载页面。通过AJAX更新实际需要更新的页面部分。

本地存储

正如@outis所提到的,今天的浏览器有类似于cookie的东西,除了它们自己保存(因此在本地)。这是一个非常新的功能,说实话,考虑到有更好的方法可以满足你的需求,我不相信它。

答案 4 :(得分:0)

我知道回答你自己的问题并不是很酷,但是我昨晚发生了另一种可能的解决方案,它只需要编写一行新代码(等等)。

许多人已经隐含地提出了解决方案的第一部分。修改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元素。我可能会在稍后回来调查这些解决方案,但那不是我目前的项目所在。

感谢大家的所有回复。如果不将这些想法反驳给你们,我就不会找到这个解决方案。