Javascript Show/Hide DIV on click/toggle - php

I list a lot of users on my page and I use a php function to pass the user's id and return a div pop up that displays their online status, avatar, stats etc. The problem is that the code is currently set to show the layer onmouseover and hide the layer onmouseout. I would like the code to be onclick show, and second click (either toggle on the same link or click anywhere else on the page) hide the layer but I'm not sure how to accomplish that.
The current code I'm using I got from Dynamic Drive. (sorry my tab key won't work in this text box, not sure how to fix that. feel free to edit)
SKIP TO BOTTOM
Original Method:
Javascript part
<div id="dhtmltooltip"></div>
<script type="text/javascript">
/***********************************************
* Cool DHTML tooltip script- Dynamic Drive DHTML code library (www.dynamicdrive.com)
* This notice MUST stay intact for legal use
* Visit Dynamic Drive at http://www.dynamicdrive.com/ for full source code
***********************************************/
var offsetxpoint=-60 //Customize x offset of tooltip
var offsetypoint=20 //Customize y offset of tooltip
var ie=document.all
var ns6=document.getElementById && !document.all
var enabletip=false
if (ie||ns6)
var tipobj=document.all? document.all["dhtmltooltip"] : document.getElementById? document.getElementById("dhtmltooltip") : ""
function ietruebody(){
return (document.compatMode && document.compatMode!="BackCompat")? document.documentElement : document.body
}
function ddrivetip(thetext, thecolor, thewidth){
if (ns6||ie){
if (typeof thewidth!="undefined") tipobj.style.width=thewidth+"px"
if (typeof thecolor!="undefined" && thecolor!="") tipobj.style.backgroundColor=thecolor
tipobj.innerHTML=thetext
enabletip=true
return false
}
}
function positiontip(e){
if (enabletip){
var curX=(ns6)?e.pageX : event.clientX+ietruebody().scrollLeft;
var curY=(ns6)?e.pageY : event.clientY+ietruebody().scrollTop;
//Find out how close the mouse is to the corner of the window
var rightedge=ie&&!window.opera? ietruebody().clientWidth-event.clientX-offsetxpoint : window.innerWidth-e.clientX-offsetxpoint-20
var bottomedge=ie&&!window.opera? ietruebody().clientHeight-event.clientY-offsetypoint : window.innerHeight-e.clientY-offsetypoint-20
var leftedge=(offsetxpoint<0)? offsetxpoint*(-1) : -1000
//if the horizontal distance isn't enough to accomodate the width of the context menu
if (rightedge<tipobj.offsetWidth)
//move the horizontal position of the menu to the left by it's width
tipobj.style.left=ie? ietruebody().scrollLeft+event.clientX-tipobj.offsetWidth+"px" : window.pageXOffset+e.clientX-tipobj.offsetWidth+"px"
else if (curX<leftedge)
tipobj.style.left="5px"
else
//position the horizontal position of the menu where the mouse is positioned
tipobj.style.left=curX+offsetxpoint+"px"
//same concept with the vertical position
if (bottomedge<tipobj.offsetHeight)
tipobj.style.top=ie? ietruebody().scrollTop+event.clientY-tipobj.offsetHeight-offsetypoint+"px" : window.pageYOffset+e.clientY-tipobj.offsetHeight-offsetypoint+"px"
else
tipobj.style.top=curY+offsetypoint+"px"
tipobj.style.visibility="visible"
}
}
function hideddrivetip(){
if (ns6||ie){
enabletip=false
tipobj.style.visibility="hidden"
tipobj.style.left="-1000px"
tipobj.style.backgroundColor=''
tipobj.style.width=''
}
}
document.onmousemove=positiontip
</script>
PHP part
$username = "<a onMouseover=\"ddrivetip('<Center><font class=f2>$username</font><BR>$avatarl</center>
<table align=center><Tr><Td><b>Points:</b> <font class=alttext>$user_points</font>
<BR><B>Posts:</b> <font class=alttext>$user_posts</font><BR>$user_status</td></tr></table>
<BR><img src=$icons/add-user.png height=12> <a href=$cs_url/friends/add/$user>Send Friend Request</a>
<BR><img src=$icons/user_message2.png height=12> <a href=$cs_url/messages/compose/$user>Send Message</a>
<BR><img src=$icons/user_im2.png height=12> Instant Message')\"
onMouseout=\"hideddrivetip()\">$username</a>";
My primary reason for wanting the toggle/blur as opposed to mouseout is so that users have the chance to actually click the links inside of the div layer.
The reason why I am trying to stick to this script as opposed to other ones out there I've found is because it doesn't rely on unique ids or alot of css styles. With other scripts, when I click on one username, they all of the hidden divs on the page pop up, or at least all of them for that user. This seemed to be the best for showing just one at a time.
I decided to scrap the method above. I have a script that I also got elsewhere that I use to toggle a twitter-like login in. I was wondering how I could use it to toggle the user information layer.
Second Method:
Javascript
$(".users").click(function(e) {
e.preventDefault();
$("fieldset#users_menu").toggle();
$(".users").toggleClass("menu-open");
});
$("fieldset#users_menu").mouseup(function() {
return false
});
$(document).mouseup(function(e) {
if($(e.target).parent("a.users").length==0) {
$(".users").removeClass("menu-open");
$("fieldset#users_menu").hide();
}
});
PHP part
<div id='container' class='users_container'>
<div id='usersnav' class='usersnav'> <a href='<?php echo $cs_url; ?>/users/all' class='users'><span>Fans</span></a> </div>
<fieldset id='users_menu'>
content
</fieldset>
</div>
The problem with this method as I mentioned before is that when I click on the username link, ALL of the layers for ALL of the users display on the page appear. How can I make it so that only the child layer of the parent link is displayed? Also, is there a way to toggle the layer hidden when anywhere else on the page is clicked?

Starting from your old code I assume you had something like:
elem.onmouseover = showCard;
elem.onmouseout = hideCard;
Well, from there you just need to do something along the lines of:
elem.isShown = false;
elem.onclick = function() {
if( elem.isShown) hideCard();
else showCard();
elem.isShown = !elem.isShown;
}

This ended up being the best solution though there is still one thing I wish was different about it.
This is built upon Dan's response. The reason why it wasn't working before Dan was because the user information was inside tags, I switcher username to span and the content display. The problem after that was when I clicked on one username the layer would popup but it would remain until I clicked on the same link again. So multiple layers would sometimes be on at once.
The following closes the layer when a user clicks on the layer, outside the layer or on the original link. The one little snag is that when clicking on the original link to close the layer you must click twice.
Javascript
<script type="text/javascript">
$(document).ready(function () {
$(".username").click(function () {
$(this).children().toggle();
$('.tooltip_container').hover(function(){
mouse_is_inside=true;
}, function(){
mouse_is_inside=false;
});
$(".username").click(function () {
$(this).children().toggle();
});
});
$("body").mouseup(function(){
if(! mouse_is_inside) $('.tooltip_container').hide();
});
});
</script>
PHP
<span class='username'>$username
<div class='tooltip_container'>
<div class='tooltip'>
Content goes here
</div>
</div>
</span>

Related

jquery effects not visible in php if "echo" is used for output

im having small image gallery that uses fancybox. So on each image there is a hover and popup effect. Below is my code
<div class="one-third column hover">
<a href="large/28crowview_ld.jpg" class="image-box">
<div class="photo">
<span class="text"><span class="anchor"></span></span>
</div>
<img src="large/28crowview_ld.jpg" height="170px" width="260px"/>
</a>
</div>
the above code works perfectly.
but im using a ajax controller that returns the above code using an echo
echo '<div class="one-third column hover">
<a href="large/28crowview_ld.jpg" class="image-box">
<div class="photo">
<span class="text"><span class="anchor"></span></span>
</div>
<img src="large/28crowview_ld.jpg" height="170px" width="260px"/>
</a>
</div>';
but when i use the echo tag the images are displayed but non of the hover effects are visible. it was very odd. and i also noticed the same issue on my social bar.
It works perfectly when i use it in a html view. But when i echo, i see the code in the source but the icons are not visible
echo '<div class="supersocialshare" data-networks="facebook,google,twitter,linkedin,pinterest" data-url="'.$share.'" data-orientation="line"></div>';
all the images are placed correctly, no js conflicts.
Below is the java script im using
<script type="text/javascript">
$(document).ready(function() {
var track_click = 0; //track user click on "load more" button, righ now it is 0 click
var total_pages = <?php echo $total_pages; ?>;
$('#results').load("<?php echo base_url() ?>fetch_pages", {'page':track_click}, function() {track_click++;}); //initial data to load
$(".load_more").click(function (e) { //user clicks on button
$(this).hide(); //hide load more button on click
$('.animation_image').show(); //show loading image
if(track_click <= total_pages) //make sure user clicks are still less than total pages
{
//post page number and load returned data into result element
$.post('<?php echo base_url() ?>fetch_pages',{'page': track_click}, function(data) {
$(".load_more").show(); //bring back load more button
$("#results").append(data); //append data received from server
//scroll page to button element
$("html, body").animate({scrollTop: $("#load_more_button").offset().top}, 500);
//hide loading image
$('.animation_image').hide(); //hide loading image once data is received
track_click++; //user click increment on load button
}).fail(function(xhr, ajaxOptions, thrownError) {
alert(thrownError); //alert any HTTP error
$(".load_more").show(); //bring back load more button
$('.animation_image').hide(); //hide loading image once data is received
});
if(track_click >= total_pages-1)
{
//reached end of the page yet? disable load button
$(".load_more").attr("disabled", "disabled");
}
}
});
});
</script>
inside fetch_pages
$page_number = filter_var($this->input->post('page'), FILTER_SANITIZE_NUMBER_INT, FILTER_FLAG_STRIP_HIGH);
//throw HTTP error if page number is not valid
if(!is_numeric($page_number)){
header('HTTP/1.1 500 Invalid page number!');
exit();
}
$item_per_page = 5;
//get current starting point of records
$position = ($page_number * $item_per_page);
$cottages = $this->properties->getstuff($sub_location,$position, $item_per_page);
foreach ($props as $cots):
echo'<div class="container section" id="'.$cots["id"].'">
<div class="one-third column hover">
<a href="'.$cots["image_url"].'" class="image-box">
<div class="photo">
<span class="text"><span class="anchor"></span></span>
</div>
<img src="'.$cots["image_url"].'" height="170px" width="260px"/>
</a>
</div>';
endforeach;
Im building this project using codeigniter, php and jquery. Any help will be appreciated.
You seem to have some serious problems understanding the overall architecture of a web application, what is happening on the browser of your client and what is happening on the server, what php does, and so on. You should read up on that.
However, your problem is most likely related to the fact that your hover and popup effects are being accomplished by something equivalent to this:
$(".hover").on("hover",function () {
// BLAH
});
If this is the case, then any elements with class hover loaded after the event handler has been attached (that is, through ajax) will not have that event handler attached to them, a simple fix would be to attach the event handler to the container and use a delegated event handler, something like this:
$(document).on("hover",".hover",function () {
// This handler is attached to the document but applies to any .hover elements inside it
});
Another fix would be to run whatever function attaches your "fancybox" functionality to an element after the element has been loaded through ajax. Hard to get it right without some reference code but i assume it would be something like:
$.get(url, function (data) {
var elem = $(data);
$("#container").append(elem);
elem.fancybox();
});
please provide you JavaScript code, I would like to throw my cent. I bet you are using hover method instead of live hover or on hover functions
just like the following :
jQuery('#div').click(...); // this will work fine if you place your code in page not posted back from ajax request or dynamically created
jQuery('#div').live('click',...); // this will work even if the element was created dynamically or from ajax request.
jQuery "live" link
jQuery "On" link
one more thing, be careful the live function is deprecated and removed from jQuery 1.9
According to anpsmn comment i had to re initialize the complete fancybox plugin within
$(window).load(function() {
it worked perfectly..

Code works in jsfiddle but doesn't work when I put all the code into my website

My goal is to have a button on each side of my iframe (which contains a calendar) which toggles back and forth between calendar #1 and calendar #2 in a single iframe.
Any suggestions?
|arrowLeft| |-----Iframe-------| |arrowRight|
The code works in jsfiddle but doesn't work when I put all the code into my website.
Why is that?
HTML:
<p id="toggle">
<span> Left </span>
<span> </span>
</p>
<div id="left"> <iframe>LEFT CONTENT</iframe> L</div>
<div id="right"> <iframe>RIGHT CONTENT</iframe>R </div>
<p id="toggle">
<span></span>
<span> Right </span></p>
CSS:
#right { display:none; }
Script:
$('#toggle > span').click(function() {
var ix = $(this).index();
$('#left').toggle( ix === 0 );
$('#right').toggle( ix === 1 );
});
Since you say you have loaded jquery..
Probably your onclick setter (the jquery code) is run before the document is loaded (and as such there are no elements in document.body at that moment to set).
In jsfiddle ('No-Library' pure JS) code is wrapped (by default) in:
window.onload=function(){
// your code here
};
That should already do the trick.
This is what jsfiddle does when you select the (default) option 'onLoad' in the options panel on the left, under "Frameworks & Extensions".
If you would select 'onDomready' then your code would (currently) be wrapped in a function called VanillaRunOnDomReady, like this:
var VanillaRunOnDomReady = function() {
// your code here
}
var alreadyrunflag = 0;
if (document.addEventListener)
document.addEventListener("DOMContentLoaded", function(){
alreadyrunflag=1;
VanillaRunOnDomReady();
}, false);
else if (document.all && !window.opera) {
document.write('<script type="text/javascript" id="contentloadtag" defer="defer" src="javascript:void(0)"><\/script>');
var contentloadtag = document.getElementById("contentloadtag")
contentloadtag.onreadystatechange=function(){
if (this.readyState=="complete"){
alreadyrunflag=1;
VanillaRunOnDomReady();
}
}
}
window.onload = function(){
setTimeout("if (!alreadyrunflag){VanillaRunOnDomReady}", 0);
}
Note that this eventually still ends up in a window.onload like the 'onLoad' option.
If you'd load library JQuery 1.9.1 then things change (a little).
The option 'onLoad' then wraps your code like this:
$(window).load(function(){
// your code here
});
Note that this is essentially still the the same as the first option in this answer, but then in the JQuery way.
If you'd select the option 'onDomready' (whilst the JQuery library is loaded in JSFiddle), then your code would be wrapped in:
$(function(){
// your code here
});
As ErikE pointed out in the comments below, since you already load and use JQuery you might also want to use yet another JQuery way:
$(document).ready(function() {
// your code here
});
Finally as ErikE also pointed out in his comment to your question (a serious problem I overlooked), id's are meant to be unique. Whereas you gave to both paragraphs the id "toggle".
You should instead give them the class "toggle" and select the elements by class to assign the onclick function.

Why is my $(this).prop('class') not working?

Here is what i want: I have multiple <h3> tags that are being uses as a link to reveal answers to FAQ's. Also I have added a form in case that the user did not see any question of interest on that page. The link for the form is at the bottom of the page. Now when the user click on the show form link I would like the window to scroll down to the bottom. I have done this, however when I click on any of the link the window also scrolls to the bottom. I want when the user clicks only on the show form link that the window scrolls.
here is what I have so far:
<body>
<?php
$array = array("link 1","link 2","link 3");
foreach($array as $link)
{
echo "<h3 class='link'>".$link."</h3>";
echo "<div>";
//information to be displayed
echo "</div>";
}
?>
<h3 class="forms">Show Form</h3>
//form information here
</body>
here is the javscript:
<script>
$(document).ready(function(){
$('h3').click('bind',function() {
$(this).toggleClass('open').next().slideToggle(500,function(){
var i = $(this).prop('class');
if(i == 'forms')
{
$("html, body").animate({scrollTop: $(document).height()}, "slow");
}
});
});
});
</script>
I have added an alert to verify my output and when I click on <h3 class="forms"> the alert is blank but when I click on the others the alert showed "link". Can someone help me figure out why the alert is showing blank when I click on the <h3 class="forms"> tag?
You are echoing your LI with the link class, instead of $link.
Also, use
if ($(this).hasClass("forms"))
.prop() should really only be used when accessing the DOM element's properties and not attributes (like class or style, width, etc.). If you want the class, use .attr('class') instead (or, as others have mentioned, you can use .hasClass() to test (with jQuery) if an element has a specific class aplied).
to follow-up on .prop vs .class:
Foo Bar link
var a = document.getElementById('foolink'),
$a = $(a);
$a.prop('href') // like directly calling a.href
$a.prop('id') // again, like directly calling a.id
$a.attr('class') // where as it's actually a.className

Jquery Edit text then save to DB using ajax

I have a page with text displayed in divs and spans. Next to each one I have an image that the user can click on.
When they click this image I need the text to change to a text area so the user can edit the text and then when they click of it it will need to call a php script to save to DB via ajax.
All divs and images have unique ID's so this should make it easier with the jquery selector.
Can anyone help? Everything I have tried so far is not really worked.
Thanks
You could make the div editable:
$(".ajax-div .on-img").on("click",function(ev) {
$(this).parent().find(".editable-text").attr("contenteditable", "true").after("<button onclick='saveEdits()'>Save</button>");
})
Your html structure would have to look like this
<div class="ajax-div" id="somediv">
<div class="editable-text">Editable text</div>
<img class="on-img" src="" alt="">
</div>
The saveEdits() function:
function saveEdits() {
$(".ajax-div").each(function() {
if(this.hasAttr("contenteditable") && this.attr("contenteditable")==true) {
id = $(this).attr("id");
//handle change
}
})
}
Let's say you have:
<div id='mydivparent'>
Some text here
<div>
<img src='images/mypic.jpg' id='mydiv' onclick='editr(this)' />
</div>
</div>
To do as your requirements suggest, an approach that would suffice is the below JS code.
<script>
function editr(obj)
{
var id = $(obj).attr('id');
var text = $('#mydiv'+parent).text();
$('#mydiv'+parent).empty();
$('#mydiv'+parent).append('<form action='form_processor.php' onsubmit="send_ajax($('textarea#'+id+').value)"><textarea id='+id+'>'+text+'</textarea><input type='submit' value='Save Text'></form>');
}
function send_ajax(txtValue){
$.ajax({
url: 'form_processor',
cache: false;
type: 'POST',
data: {'text': txtValue},
success: function(){
//Code to add the text to the div and delete the textarea returning it to a normal div
}
});
return false;
}
</script>
You should put in mind how to name the divs and images ids so that accessing a div's id from the image id is easy. You should use your own protocol so that if you have the image ID, you can get the asssociated div id, OR you can put the image inside the div so that it's as easy as selecting the PARENT.
After editing you can then set it up for ajax after the user.
The code is does not fully cover every situation for example if you click another imagebefore saving your first opened textarea but I believe that it will set you to the right road on the approach you should take.
I used jeditable plugin in the end to solve this one for anyone that finds this post

How can PHP access the 'style' properties of a div?

So my PHP webiste generates DHTML output that looks like the following:
<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>Link to Myself</p>
And of course, when clicked, the first div calls some JavaScript which toggles the visibility of the 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';
}
All this works fine. It's clicking on the link which is bothering me right now. Clicking it (of course) creates a new http request, and my PHP engine re-generates the page again.
The problem occurs when the visibility of the site-menu is 'none'. The PHP engine doesn't know that the menu is hidden, so it generates the same-html again, and the browser places the menu back in front of the surprised-looking user.
The question therefore, is how do I inform PHP (or how can PHP go to check) what the status of the site-menu's visibility is, before it goes to re-generate the page?
There are at least two options other than sending the menu state to the PHP script.
Use AJAX to load just part of the page. If you don't reload the menu, you don't need to re-initialize its style. Before going down this path, examine whether AJAX is suitable. If you implement this solution, don't break browser functionality.
Modern browsers support a storage mechanism. Store the menu state in localStorage when it changes, and set the menu state when the page loads. To support older browsers, you can create an API that uses web storage when available and cookies when not (jQuery.Storage does this).
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');
}
};
some CSS file:
.closed { display: none; }
page:
<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>Link to Myself</p>
<script type="text/javascript">
Menu.init('site-menu');
</script>
You can play with a live version of the Menu.js approach on jsFiddle. Using jQuery, you can do away with Menu.js, resulting in a much more succinct implementation:
<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>
There's a jFiddle for the jQuery menu state implementation that you can play with.
Since differences in the menu state don't conceptually make for different resources, it doesn't matter whether having the menu open or closed is bookmarkable or affected by history.
NB. don't use the text "click me", it's too verbose and redundant (what other action is there? Affordances should be implicit.). Instead, you can use a graphic to indicate open/close, or simply say "open menu"/"close menu".
The question therefore, is how do I inform PHP (or how can PHP go to
check) what the status of the site-menu's visibility is, before it
goes to re-generate the page?
It can't. By the time the HTML is delivered to the browser, PHP is no longer in the picture. The only way you could make PHP aware of this would be to send a parameter in the URL indicating the menu is hidden, or set a cookie and have the cookie indicate visibility of the object. Then PHP can check for the presence of this value and set the visibility of the div when it renders it.
You could accomplish this in a number of ways, for example:
Use document.cookie to set the cookie in your toggleMenu function.
Use ajax to notify PHP in the toggleMenu function and have PHP set a cookie or session value
Append a flag to the link indicating the visibility of the menu from the toggleMenu function.
Actually, there are several types of answers to your question.
While it may sound there's no way to do what you want, there are, in fact, many ways.
Cookies
The obvious. Cookies can be accessed by javascript as well as PHP. Just modify the cookie whenever the menu is shown/hidden through javascript (there's the excellent jQuery cookie plugin).
Form input
If you are submitting a form, simply have a hidden input keep the value of the menu's visibility:
<input type="hidden" name="menu-visibility" value="0"/>
Again, you need javascript to keep this input updated.
Update relevant parts of the page
This is the hip & leet new trend. Well, actually, it's been there for some 6 years or so. Basically, don't submit anything and don't reload the page. Update the parts of the page that actually need updating, through AJAX.
Local Storage
As #outis mentioned, today browsers have something similar to cookies, except they keep it for themselves (hence locally). It's a pretty new feature, to be honest, I wouldn't trust it considering there are better ways to accomplish what you need.
In addition to drew010's suggestions: You could also create a form with a hidden input element named, let's say, 'menu_status' whose value gets set by toggleMenu(). Then when you click on your link, use javascript to POST or GET the form. Then you read the value server-side with php using either $_POST["menu_status"] or $_GET["menu_status"], depending on the form method.
UPDATE: Something like this:
<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>Link to Myself</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;
}
EDIT: Using jQuery ajax could involve something like this:
<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>Link to Myself</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);
});
});
Or without using ajax or a form, just append a parameter to the link and use $_GET instead of $_POST in your php:
$("#go").click(function(e) {
e.preventDefault();
var menu_state = $("#site-menu").css("display");
document.location.href = "index.php?menu_state=" + menu_state;
});
This seems to me the simplest solution.
I know it's not cool to answer your own question, but another possible solution occurred to me last night, and it only requires 1 new line of code to be written (sort of).
The first part of the solution has already been implicitly suggested by many of you. Modify the JavaScript to write to a 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
}
Now, what are the possibilities if your CSS file just so happens to be a PHP file in disguise? my_css.php would look something like this:
<?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! */
}
Tested this morning, and it works.
I find it a neat solution, because it means that I don't have to bend my PHP or HTML design around any presentational concerns.
--
I appreciate that there are more "encompassing" solutions out there. If I was a better JavaScript developer, (or made use of jQuery or the like), I could build more complicated classes which could then be applied more generally to other HTML elements. I may come back to investigate such solutions later, but that's just not where my project is at the moment.
Thank you everyone for all your replies. I wouldn't have found this solution without bouncing these ideas off you guys.

Categories