所以我的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
的可见性状态是什么?
答案 0 :(得分:2)
因此,问题是如何通知PHP(或PHP如何通知 检查站点菜单可见性的状态,在它之前 去重新生成页面?
它不能。当HTML被传递到浏览器时,PHP就不再适用了。让PHP意识到这一点的唯一方法是在URL中发送一个参数,指示菜单被隐藏,或者设置一个cookie并让cookie指示对象的可见性。然后,PHP可以检查是否存在此值,并在呈现div时设置div的可见性。
您可以通过多种方式完成此任务,例如:
答案 1 :(得分:2)
除了将菜单状态发送到PHP脚本之外,至少有两个选项。
现代浏览器支持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。
由于菜单状态的差异在概念上并不适用于不同的资源,因此打开或关闭菜单是否可收藏或受历史影响无关紧要。
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元素。我可能会在稍后回来调查这些解决方案,但那不是我目前的项目所在。
感谢大家的所有回复。如果不将这些想法反驳给你们,我就不会找到这个解决方案。