Hi everyone

I have developed a PHP page which uses a few JavaScript functions and other JavaScript code to initially display today's date (and plus other data as well!). At the top of the PHP script is a PHP include file which determines whether or not today is BST - it creates a variable set to 1 if it is and 0 if it isn't. Pretty straight forward and it works as well.

This variable is used in the JavaScript to control what is output, depending whether or not BST is operating.

At the bottom of the PHP script is a bit of HTML which produces two buttons, with links to JavaScript functions. These buttons are named Yesterday and Tomorrow, and it shouldn't be too difficult to work out what they are used for.

These two JavaScript functions perform identically but with data for Yesterday or Tomorrow.

And this is the problem. When the script is first run, the BST test works as expected. But if a user clicks on either of the buttons mentioned above, the BST code is ignored because the variable originated from PHP and it has already been parsed.

So my question to all you clever JavaScript gurus is this....

Is there a simple, or complicated, JavaScript code that will determine whether or not BST is currently in force, and output a similar 1 for yes and 0 for no?

Thanks in advance
Terry

Part of the JavaScript code

Terry,

... the BST code is ignored because the variable originated from PHP and it has already been parsed.

I don't quite follow this. The variable should remain available to any statement/function within scope. If in doubt, create the variable in the global scope, then it is available to everything until changed or destroyed.

There may be a 100% javascript solution, depending on exactly what you are trying to do with your Yesterday/Tomorrow buttons and whether or not is is actually important to know GMT/BST.

Airshow

Hi Airshow

At the moment, the summertime variable is created within PHP. It uses "today's" date to decide. The result, 1 or 0, is then passed to a JavaScript routine which uses that information to display a set of times for today, depending on whether it is BST or not.

Then the user can click on the Yesterday or Tomorrow button which then adds or subtracts 1 day from today. This is also done with JavaScript, and a range of times is again calculated. But the day used will either be Yesterday or Tomorrow, so the PHP summertime variable is no longer valid, and I don't see or maybe don't know how it can be changed. JavaScript is obviously running locally while PHP runs on the server and that has already happened.

I suppose that begs another question? Can I re-run the PHP include file again? And if so, how?

Thanks
Terry

Terry,

Aha, that's much clearer now.

You certainly can re-run your PHP include or more likely another .php script that includes it. The script should echo a single character "1" or "0" - no !doctype, no <html> or <body> tags.

In order to avoid needing to reload the whole page, we use AJAX (Asynchronous Javascript And Xml). Forget about XML, data can be passed back in any String format. XML, HTML, JSON and plain text are the most commonly used.

With AJAX, javascript puts in place a response handler (a javascript funtion that you wrote), makes an HTTP request (to a URL string hardcoded or composed by you in javascript) then runs the response handler when the response is received. The whole thing is "asynchronous" because the response handler fires in response to an "event" (the reposnse arriving), not simply as the next line(s) in a block of code.

AJAX is actually quite simple, though the code looks a bit strange to start with. There are many formulations. Below is one.

First we put in place a general puspose AJAX namespace - which is just a container for reusable AJAX code :

var AJAX = function(){//NAMESPACE pattern
	//Private members
	var httpErrors = {//necessary if you want meaningful http error messages
		2: 'Failure on trying to send request',
		100: 'Continue',
		101: 'Switching Protocols',
		102: 'Processing',
		200: 'OK',
		201: 'Created',
		202: 'Accepted',
		203: 'Non-Authoritative Information',
		204: 'No Content',
		205: 'Reset Content',
		206: 'Partial Content',
		300: 'Multiple Choices',
		301: 'Moved Permanently',
		302: 'Found',
		303: 'See Other',
		304: 'Not Modified',
		305: 'Use Proxy',
		306: '(Unused)',
		307: 'Temporary Redirect',
		400: 'Bad Request',
		401: 'Unauthorized',
		402: 'Payment Required',
		403: 'Forbidden',
		404: 'Not Found',
		405: 'Method Not Allowed',
		406: 'Not Acceptable',
		407: 'Proxy Authentication Required',
		408: 'Request Timeout',
		409: 'Conflict',
		410: 'Gone',
		411: 'Length Required',
		412: 'Precondition Failed',
		413: 'Request Entity Too Large',
		414: 'Request-URI Too Long',
		415: 'Unsupported Media Type',
		416: 'Requested Range Not Satisfiable',
		417: 'Expectation Failed',
		500: 'Internal Server Error',
		501: 'Not Implemented',
		502: 'Bad Gateway',
		503: 'Service Unavailable',
		504: 'Gateway Timeout',
		505: 'HTTP Version Not Supported',
		12007: 'Loss of internet connection',
		12029: 'The attempt to connect to the server failed',
		12030: 'The connection with the server has been terminated'
	};
	var makeRequest = function(){//generate XMLHttpRequest object for known browsers.
		var ajaxRequest = false;
		try { ajaxRequest = new XMLHttpRequest(); }
		catch(e) {
			try { ajaxRequest = new ActiveXObject("Msxml2.XMLHTTP"); }
			catch(e) {
				try { ajaxRequest = new ActiveXObject("Microsoft.XMLHTTP"); }
				catch(e) { return false; }
			}
		}
		return ajaxRequest;
	};
	var readystatechangeHandler = function(ajaxRequest, successHandler, errorHandler, timeout) {
		if (ajaxRequest.readyState == 4) {
			clearTimeout(timeout);
			if (ajaxRequest.status == 200) { successHandler(ajaxRequest.responseText); }
			else { errorHandler(ajaxRequest.status, httpErrors[ajaxRequest.status]); }
		}
	};
	var get = function(url, successHandler, errorHandler, timeoutDuration){//general purpose ajax caller
		if(!url || !successHandler) { return; }
		errorHandler = (!errorHandler) ? (new Function()) : errorHandler;
		timeoutDuration = (!timeoutDuration) ? 0 : timeoutDuration;
		var timeout;
		var ajaxRequest = new makeRequest();
		if(!ajaxRequest) {
			errorHandler(-1, "Sorry, ajax not available in this browser");//optional
			return false;
		}
		if(timeoutDuration){
			timeout = setTimeout(function() {
				var h = errorHandler;
				errorHandler = function(){ h(ajaxRequest.status, "Timeout"); }
				ajaxRequest.abort();
			}, timeoutDuration);
		}
		ajaxRequest.open('GET', url, true);
		ajaxRequest.onreadystatechange = function() { readystatechangeHandler(ajaxRequest, successHandler, errorHandler, timeout); }
		try { ajaxRequest.send(null); }
		catch(e) { errorHandler(-2, httpErrors[2]); } //Necessary for FF but can cause IE to double-report.
	};
	//Here we could define functions for making other types of http request eg. "POST" or "HEAD"

	//Declare the following members Public
	return {
		get: get
	};
}();

This can be tucked away in an ajax.js file if you want, then included on the page with <script src="ajax.js"> or similar.

Then, you need to "front-end" your existing yesterday_tomorrow function, like this :

function goToDay(relDate, reportErrors) {//relDate is -1 for yesterday or 1 for tomorrow (ie. number of days relative to today).
	var url = "http://xxx.mydomain.com/bst_script.php?relDate=" + relDate;//adjust a necessary to be compatible with your php script
	AJAX.get(url,
		function(responseText) {//success handler
			var offsetHours = Number(responseText);//convert (String) '0'/'1' to (Number) 0/1.
			yesterday_tomorrow(offsetHours);//here, call your existing yesterday/tomorrow function (maybe with slight modification to accept offsetHours).
		},
		function(statusCode, errorMessage) {//error handler
			if(reportErrors) {
				//here do whatever is necessary if the call to bst_script.php fails
				//for example ...
				var msg = document.getElementById('msg');
				var div = document.createElement('div');
				div.innerHTML = "AJAX error : (" + statusCode + ') ' + errorMessage;
				msg.appendChild(div);
			}
	    },
		3000//timeout, 10 seconds in millisecods
	);
}

Then, all you need is something to initialise the page and put handlers in place for your yesterday/today/tomorrow buttons.

onload = function(){
	var relDate = 0;//keep track of cumulative "previous" and "next".
	errorMode = 1;//1 for debugging. Can be set to false for deployed code or leave true to allow users to see error messages.
	goToDay(relDate, errorMode);//initialises the page to today's data (no need to build the entire page server-side).
	var pButton = document.getElementById('pButton');//previous day button
	var tButton = document.getElementById('tButton');//today
	var nButton = document.getElementById('nButton');//next day button

	//For unconstrained previous/next day ...
	pButton.onclick = function() {
		goToDay(--relDate, errorMode);
	};
	tButton.onclick = function() {
		relDate = 0;
		goToDay(relDate, errorMode);
	};
	nButton.onclick = function() {
		goToDay(++relDate, errorMode);
	};
	//or, to constrain to yesterday/tomorrow ...
	pButton.onclick = function() {
		relDate = Math.max(relDate-1, -1);
		goToDay(relDate, errorMode);
	};
	tButton.onclick = function() {
		relDate = 0;
		goToDay(relDate, errorMode);
	};
	nButton.onclick = function() {
		relDate = Math.min(relDate+1, 1);
		goToDay(relDate, errorMode);
	};
};

Make sure your button ids are compatible with the code above and remove any onclick handlers or javascript urls currently in the buttons' HTML.

I have tested as much as I can (it's based on something I wrote ages ago) but may still need debugging.

You would need less lines of code if you use a lib like jQuery, but it would be much harder to follow/adapt.

Standing by for questions.

Airshow

Hi again Airshow

Whew! It all sounds a bit complicated just to determine whether or not BST is in force or not>

But I'll give it a try and see what happens. And then I'll get back to you with a result or a few questions. Whichever comes first?

Thanks
Terry

Terry,

I don't think there's a Javascript-only solution given that it must be reliable when executed from client computers anywhere in the world.

As already said, the code would be much more concise with a lib (jQuery, Prototype etc) but it would be tricky to follow (for quite some time), plus there's a 65k+ lib behind it. My whole test page with all that code and HTML and the draft of the text above is only 8k ... and it will run more efficiently than the lib code.

You should be able to install my code (after backing up your page and reading my text through 5 times!) in about 15 minutes. Then another 15 to write/amend the HTML for the buttons.

The hardest bit is probably creating/amending the php - 30 minutes for me but I'm slow in php. I'm sure you will be quicker.

Airshow

If your variable is set by your PHP, why not put some PHP in your <head> section to set the variable in javascript as well? It would be really simple and wouldn't require AJAX calls or massive JS framework libraries. For example:

<script type="text/javascript"><!--

var BSTflag = <?php echo( $BSTflag ); ?>;

//--></script>

Then that variable would be available to your javascript. Or am I missing something obvious that make this unsuitable for your needs?

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.