Jump to content

PHP AJAX Get Viewport Width If X then A if Y then B if Z then Z.


bigignoramus

Recommended Posts

New here and huge thanks to w3schools.com for teaching me what I know about web programming!
I have a site for internal use only and so mobile, tablet, and desktop versions required. I know that people can be adamant about using CSS media queries and never serving different content depending on viewport, but the situation here is special; mobile users do not need tablet content, and only a few people need the full content of a desktop or laptop. The content for each viewport is different.
The simplest way is simply to serve the content each for three different viewports. The fact that the desktop version will change to the tablet version and then to the mobile version on further scrunching is quite acceptable.
The other requirement is the avoidance of frameworks. Six months of testing them convinces me that they are useless for the present purpose. I have also tried jquery, but it seems to be unneeded baggage for the saidpurpose.
So, the object is to detect the viewport (HTMLInner Width) in Ajax, and convey that width to a PHP variable to go into a PHP conditional statement that includes one of each of the three sites.
One could do the whole thing in AJAX and then call the includes as PHP files, but a PHP session seems smoother.
I have been able to find the viewport live on scrunching and expanding, and present it either on the page or in the URL. I have been able to pass a static variable from AJAX to PHP.
BUT I have not been able to use the PHP to fire the conditional statement.
Here is what works.
Code for finding live viewport and presenting it on the page. The snag here is that the page will loop infinitely, perhaps because of onresize and onload conflicting?

<script type="text/javascript">
window.location = "' . $_SERVER['PHP_SELF'] . '?width="+window.width
window.onresize = findWindowSize;
window.onload = findWindowSize;
function findWindowSize()
{
viewportWidth = window.innerWidth;
document.getElementById("dimensions").innerHTML = "This Browser's Width Is "+ viewportWidth + " Pixels.";
};
</script>

The Code for simply finding the width without presenting it is the same, but eliminate document.getElementbyId and so on.
The Code for passing the variable to PHP is

 

<?php
if (isset($_POST['width']))
$widthr = $_POST['width'];
else
$width = "<br />width is not set!";

/* width is the javascript variable, and $width is the PHP variable.*/
echo $width;
?>

 

The width echoes, and changes as the width of the browser is changed. POST is used to eliminate caching.

 

The next step is to take the PHP variable, $width, and put it into the following conditional.

 

if

($width > 900 px)

include ("large.php")

elseif

($width >=600 && <= 900 px)

include ("middle.php")

else

($width < 600 px)

include ("small.php")

 

And then the next snag is to be able to put any one of the three on the same page (index.php), having, of course, sandwiched the AJAX into the selfame index.php. The whole point of using AJAX is to enable this to be done continuously by dialogue with the server.

 

I don't claim to know AJAX very well and understanding its quirky syntax defies my lack of intelligence.

 

Many people on the web seem to ask this question, but there is no full answer to be found. Abuse seems to be hurled at anybody who dares to ask this question, but this present forum seems to be much more civilised. So, a comprehensive answer would benefit many people.

 

Any ideas would be most appreciated.

Link to comment
Share on other sites

The reason your code is constantly redirecting is because assigning to window.location forces a redirect.

 

In summary, this is what I understood: You want to display different content for different screen sizes.

 

There are many way to do this. I believe the easiest solution is actually to use media queries to set the content you don't need to "display: none".

 

If you're opposed to that, you can have Javascript detect the screen size and load different content. You should read the AJAX tutorial to learn to do AJAX requests.

// onload and onresize are events on the window object
// The functions assigned to them get called when the window first loads and when it is resized, respectively.
window.onload = changeContent;
window.onresize = changeContent;

// I'm storing useful numbers inside "constants"
// (Javascript doesn't have real constants, so uppercase variable names will do)
var MOBILE = 767;
var TABLET = 1024

function changeContent() {

  // We compare the window's width to the width it had before so that we only
  // do something if we're changing views, not just every time the screen is
  // resized.
  if(!window.previousWidth) {
    // Use -1 for the previous width if we've never assigned anything to it before
    window.previousWidth = -1;
  }

  // Shorten the variable names to make the code more readable
  var pw = window.previousWidth;
  var w = window.innerWidth; // window.innerWidth is provided to us by the browser telling us the width of the page

  // It's considered switching to desktop if the current width is larger than
  // tablet size and the previous width was equal to or smaller than a tablet size
  var switchToDesktop = w > TABLET && pw <= TABLET;

  // It's considered switching to tablet if the current width is larger than a
  // mobile screen but smaller or equal to a tablet screen and the previous width
  // was either mobile size or larger than desktop size.
  var switchToTablet = w > MOBILE && w <= TABLET && (pw <= MOBILE || pw > TABLET);

  // We consider that it's switching to mobile when the current width is the size of
  // a mobile screen and the previous width was larger than a mobile screen or was
  // not set.
  var switchToMobile = w <= MOBILE && (pw > MOBILE || pw == -1);

  // The window's current width will be the previous width next time this function is called
  window.previousWidth = window.innerWidth;

  if(switchToDesktop) {
    // Load desktop.php page with AJAX
  } else if(switchToTablet) {
    // Load tablet.php with AJAX
  } else if(switchToMobile) {
    // Load mobile.php with AJAX
  }
}

When you load the content with AJAX you need to put it into an element, you could do that with document.body.innerHTML = [data from response]

The files you're loading with AJAX should only be what goes between the <body> tags and not include <html> or <head> tags.

Edited by Ingolme
Added comments to the code
Link to comment
Share on other sites

Huge thanks. I am amazed by the speed, thoughtfulness, and detail of your kind reply! I much appreciate your directly addressing my question. After six months of hunting and testing, you have brightened my day!

As you surmise, I am not keen on media queries because of their limitations for content as opposed to style. And many thanks for not giving me the usual lecture about it!

I really like your clean, intelligible, coherent, and detailed code, which lets one see what is going on. There are people bashing w3schools on the web, and their code is a reflexion of their haughty attitude, reflecting their lack of ability. w3schools are tops and any sensible person should know it!

I greatly like the lack of need for Jquery and any other baggage, too.

I have done the Javascript and Ajax tutorials thrice each, as well as Jquery, and I must apologise that I, who am more used to and prefer procedural C-style programming, remain baffled by the syntax. I know that masses of C++ underlie the web, and that all of the web languages are higher-level scripts built on that underlying code, but I wonder if I shall ever understand Javascript and Ajax without seeing what that underlying C++ is. I don't know how anybody could clarify the presentation of Javascript and Ajax more than w3schools have already done, and I have looked at every book on the subject in the bookshops, even the ones for children; still, I cannot grasp it. My next method is simply to stare at the lessons and do the exercises six dozen times each, perhaps.

So, I have taken your code and read it over many times. It is almost self-explanatory - please be complimented - and vastly increases my understanding of Ajax, but your skill is so great that I am still baffled by some of the objects and variables that you introduce. I have nowhere seen these before.

 

You are quite right about the placing of the matter pulled in; to keep the page the same, I plan to use VARY HEADER, and draw in only pieces of the page in the usual php fashion.

Meanwhile, I have put the code in a single html page, with internal CSS, for a test, but a few questions remain, which I ask as comments. This code follows. I have named the file "w3index.html" in honour of w3schools.com.

If you will be so kind as to look it over, I shall be most grateful.

 

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Ajax to Determine Viewport Size</title>
<script>
window.onload = changeContent;
window.onresize = changeContent;

var MOBILE = 767;
var TABLET = 1024

function changeContent() {
if(!window.previousWidth) {
window.previousWidth = -1;
}
var pw = window.previousWidth;
var w = window.innerWidth;

var switchToDesktop = w > TABLET && pw <= TABLET;
var switchToTablet = w > MOBILE && w <= TABLET && (pw <= MOBILE || pw > TABLET);
var switchToMobile = w <= MOBILE && (pw > MOBILE || pw == -1);

window.previousWidth = window.innerWidth;

if(switchToDesktop) {
// Load desktop.php page with AJAX
//Shall I put the header.desktop.html here?
} else if(switchToTablet) {
// Load tablet.php with AJAX
//Shall I put the header.tablet.html here?
} else if(switchToMobile) {
// Load mobile.php with AJAX
//Shall I put the header.mobile.html here?
}
}
document.body.innerHTML = [data from response]
//Not sure what to put as data from response? Does this mean the window.previousWidth or window.innerWidth?
</script>
body, html,
{
margin: 0 0 0 0;
margin-bottom: 0;
padding: 0;
text-align: center;
font-weight: bold;
text-decoration: none;
}
*
{
box-sizing: border-box;
}
.divrow1
{
display: flex;
width: 100%;
height: 100%;
margin: 0 0 0 0;
padding: 0;
position: relative;
float: left;
background-color: #ffd700;
text-align: center;
}
</style>
</head>
<body>
<!--Put Content Here.
Content Is:-
From header.mobile.html
<div class="divrow1">
<p>
THIS IS A MOBILE PAGE.
</p>
</div>
</div>
From header.tablet.html
<div class="divrow1">
<p>
THIS IS A TABLET PAGE.
</p>
</div>
</div>
From header.desktop.html
<div class="divrow1">
<p>
THIS IS A DESKTOP PAGE.
</p>
</div>
</div>
-->
</body>
</html>

Link to comment
Share on other sites

I haven't included any AJAX in my previous post, but I will edit it to add comments explaining more clearly what I'm doing.

 

Here's how AJAX works:

// Create XMLHttpRequest object which the browser uses to make requests to the server
var request = new XMLHttpRequest();

// Prepare the connection
// 1. "GET" refers to the HTTP request type.
//    In HTTP, GET is used when we want get information from the server
//    POST would be used if we wanted to send information to the server
// 2. "desktop.php" is the path to the file we want to read.
// 3. "true"  refers to asynchronous requests, this should always be true.
//    If set to false the browser will freese until the request has completed.
request.open("GET", "desktop.php", true);

// The onreadystatechange property is an event listener, it gets called automatically while the request occurs
request.onreadystatechange = handleResponse;

// Send the request
request.send();

// This function is called when the ready state of the request changes.
// Ready state 4 means data has been returned from the request.
// An HTTP status code of "200" means that the request was successful.
function handleResponse() {
  if(request.readyState === 4 && request.status === 200) {
    // request.responseText contains the contents of the file we requested from the server.
    // console.log() shows information in the browser's Javascript console which you can access by pressing F12 in most browsers
    console.log(request.responseText);
  };
};

In short, we can condense all that into this useful little function:

// Requests data to the server and runs the function "callback" sending the data to it
// We could make it more fancy by handling errors, but this is just a simple function
function requestData(url, callback) {
  var request = new XMLHttpRequest();
  request.onreadystatechange = function() {
    if(request.readyState === 4 && request.status === 200) {
      callback(request.responseText);
    }
  }
}

Here's how to use the function we just created:

requestData("desktop.php", showOnPage);
function showOnPage(data) {
  document.getElementById("content").innerHTML = data;
}

You can use it in the previous code like this:

if(switchToDesktop) {
  requestData("header.desktop.html", updateContent);
} else if(switchToTablet) {
  requestData("header.tablet.html", updateContent);
} else if(switchToMobile) {
  requestData("header.mobile.html", updateContent);
}




/*  This goes outside of everything else */
function updateContent(data) {
  // Assuming you have <div id="content"></div> on your page
  // wherever you want the content to appear
  document.getElementById("content").innerHTML = data;
}
  • Like 1
Link to comment
Share on other sites

Many thanks again for your good work.

 

I think that I am beginning to see where I am becoming confused.

 

1. By adding the Ajax code as below, which I hope that I did correctly, I did a test, and nothing happened. No errors, no freeze, and so on: simply no result. The called files are in the same directory. So, are Javascript and Ajax mutually exclusive? I didn't think so, but here we now have two conditional statement toi attain the same result. Do I eliminate all of the Javascript and keep only the Ajax?

 

2. Otherwise, do they operate together, and, if so, how?

 

3. I see that GET is used because we are "getting" the called files. I thought that we had to post the call for the external files after we had "got" the variable of the size of viewport. The reason for the Ajax is to make the resizing calls continuous on any resize; this will not matter on the mobile and tablet, but a scrunching of the desktop browser back and forth should constantly replace the existing external file with the appropriate other external file. Otherwise, no Ajax would be needed. Hence, no caching wanted. That is why I became confused about the GET and POST, because POST is said not to cache. But I think that I see your point because I believe that we are doing this on the client side, and hence are not needing to POST anything to the server. The POST would come later in the PHP, which issue does not neeed to be addressed until the AJAX be working. I prefer the idea of doing all of the detection and resizing on the CLIENT size in a .html file before any PHP be called. But this is a later issue. My original idea had been to capture the variable, pass them to PHP, and let PHP do the calling of the external files. At the present juncture, I don't care which method will do the task as long as it works.

 

4. If, for this purpose, one ought to use one or the other, then is it necessary to translate any of the Javascript into Ajax? There seem to be two conditionals, one in each script, working at the same time.

 

5. I altered your "content" to my "divrow1". This raises the question whether it is all right that the ultimate content be enclosed in a <p></p> in the called files, which are all very terse tests. The real pages will be a mass of "div class= x", but all of this will go into body, so <body></body> will be the ultimate class. If <body></body> be one level of DOM too high for this Ajax work, then everything will have to be enclosed in one massive div, which could cause erratic behaviour in the underlying divs; it will go three or four levels of divs deep, depending on the content. The real calls are actual headers (in the formatting, not the HTTP, sense) set to work with CSS flex, and they each work very well, together with other pieces that make up the page, such as sidebars, middle content, and a footer, all of which have to be called to suit in the usual method of php includes. Thus, we get the different content by the Ajax calls, but this "adaptive" approach of Ajax contains the "responsive" sub-approach in CSS flex that should adjust for minute differences in browsers. As I say, the flex works perfectly.

 

I am nervous about playing too heavily with your code, and so dare not go any farther with the latest version, here.

 

 

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Ajax to Determine Viewport Size</title>
<script>
window.onload = changeContent;
window.onresize = changeContent;
var MOBILE = 767;
var TABLET = 1024
function changeContent() {
if(!window.previousWidth) {
window.previousWidth = -1;
}
var pw = window.previousWidth;
var w = window.innerWidth;
var switchToDesktop = w > TABLET && pw <= TABLET;
var switchToTablet = w > MOBILE && w <= TABLET && (pw <= MOBILE || pw > TABLET);
var switchToMobile = w <= MOBILE && (pw > MOBILE || pw == -1);
window.previousWidth = window.innerWidth;
if(switchToDesktop) {
requestData("header.desktop.html", updateContent);
} else if(switchToTablet) {
requestData("header.tablet.html", updateContent);
} else if(switchToMobile) {
requestData("header.mobile.html", updateContent);
}
// Requests data to the server and runs the function "callback" sending the data to it
// We could make it more fancy by handling errors, but this is just a simple function
function requestData(url, callback) {
var request = new XMLHttpRequest();
request.onreadystatechange = function() {
if(request.readyState === 4 && request.status === 200) {
callback(request.responseText);
}
}
}
/* This goes outside of everything else */
function updateContent(data) {
// Assuming you have <div id="content"></div> on your page
// wherever you want the content to appear
document.getElementById("divrow1").innerHTML = data;
}
</script>
<style>
body, html,
{
margin: 0 0 0 0;
margin-bottom: 0;
padding: 0;
text-align: center;
font-weight: bold;
text-decoration: none;
}
*
{
box-sizing: border-box;
}
.divrow1
{
display: flex;
width: 100%;
height: 100%;
margin: 0 0 0 0;
padding: 0;
position: relative;
float: left;
background-color: #ffd700;
text-align: center;
}
</style>
</head>
<body>
<!--Put Content Here.
Content Is:-
From header.mobile.html
<div class="divrow1">
<p>
THIS IS A MOBILE PAGE.
</p>
</div>
</div>
From header.tablet.html
<div class="divrow1">
<p>
THIS IS A TABLET PAGE.
</p>
</div>
</div>
From header.desktop.html
<div class="divrow1">
<p>
THIS IS A DESKTOP PAGE.
</p>
</div>
</div>
-->
</body>
</html>

Link to comment
Share on other sites

I presume that you have been away.

 

I have been westling with this since the above, and pulled out the style and the javascript.

 

It still doesn't work, though it gives no errors.

 

I am wondering if some of it ought to go within one of the functions, or if lines 8-14 and 16-27, the conditional statements and the request statements, duplicate one another, or if the code ought to go in <body> rather than </head>, or what. Are the statements in the correct order?

 

Here is the amended code:-

 

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Ajax to Determine Viewport Size</title>
<script>
if(switchToDesktop) {
requestData("header.desktop.html", updateContent);
} else if(switchToTablet) {
requestData("header.tablet.html", updateContent);
} else if(switchToMobile) {
requestData("header.mobile.html", updateContent);
}

requestData("header.desktop.html", showOnPage);
function showOnPage(data) {
document.getElementById("content").innerHTML = data;
}
requestData("header.tablet.html", showOnPage);
function showOnPage(data) {
document.getElementById("content").innerHTML = data;
}
requestData("header.mobile.html", showOnPage);
function showOnPage(data) {
document.getElementById("content").innerHTML = data;
}

// Requests data to the server and runs the function "callback" sending the data to it
// We could make it more fancy by handling errors, but this is just a simple function
function requestData(url, callback) {
var request = new XMLHttpRequest();
request.onreadystatechange = function() {
if(request.readyState === 4 && request.status === 200) {
callback(request.responseText);
}
}
}

/* This goes outside of everything else */
function updateContent(data) {
// Assuming you have <div id="content"></div> on your page
// wherever you want the content to appear
document.getElementById("content").innerHTML = data;
}
</script>
</head>
<body>
<div id="content">
</div>
</body>
</html>

Link to comment
Share on other sites

I think perhaps this task may be beyond your current capabilities and you need spend a bit longer learning Javascript with more basic tasks. There are many mistakes in your code that a proper understanding of how Javascript works would solve. You don't understand what the code is doing, but you're trying to put the pieces together anyway.

 

To make things easier, please put your code in a

Code block

so that it's readable.

 

It would be in your best interest to move all the CSS and Javascript to external files so all the code isn't jumbled up in one place.

 

One issue you might encounter is that some browsers block AJAX on the local computer, also requests done on the local computer have an HTTP status of 0 instead of 200. If you want to test on your local filesystem, use Firefox (which will not block the AJAX requests) and check for status 0 instead of 200 when the readystatechange event is fired.

 

I'll answer your questions, but I don't have the time to point out all the mistakes in your code and indicate how to solve each one individually.

  1. Javascript and AJAX are not mutually exclusive.because AJAX is a part of Javascript.
  2. A Javascript object, called XMLHttpRequest, sends a request to the server, when the server responds a "readystatechanged" event is fired. You can read more about events in the Javascript tutorial. When the event is fired, the responseText property of the XMLHttpRequest object contains what was given by the server.
  3. The code I was providing did the screen size detection and calculations on the client side, which is preferable. There's no reason why the server should have to do the calculations, if it did you would have to make an HTTP request for every resize event which could overload the server
  4. AJAX is just the technology that requests data from the server, it doesn't do anything else, everything else is either Javascript or PHP.
  5. You can add the content directly to the body element, you just have to set the innerHTML property of document.body
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...