PHP & Ajax

Summary

The next step of PHP self-teaching after PHP Basics. Learned to use Ajax by using PHP to receive information of an XML file, catalog.xml, and to instruct the display of data onto the original file.

Also added a cookie component so the visitors would not lose their place. Note: the cookie in this experiment expires very quickly so that the experiment can start over without manual deletion of the cookies from the browser.

Example

Projects List

Project Pieces List

This is where the text/image should load.

Date Created

17 Sept–5 Oct 2008.

Help

  1. w3schools.com
  2. php.net — Dictionary of PHP. Sometimes hard to find things but what you're looking for is probably there.
  3. PHP array length size count — Learned the count method to check the number of items in an array. A JavaScript version of .length.
  4. Passing Data from Javascript to PHP [Archive] - WebDeveloper.com — Learned to transfer values from JS to PHP without sending and requesting, just in case I needed it in the future.
  5. [Javascript] JavaScript to PHP variable transfer — While this thread shows how a JS value can be transfered to PHP, I figured out that I could get a PHP value and transfer it to JS.
  6. How to get Id of Div - JavaScript/SHTML/AJAX — Learned a new/overlooked property in JS Objects: .id.

Process

Really simple, follow-the-instructions from w3schools.com to practice writing it myself instead of copy and paste.

  1. Background prep. Set up an xml file, create reusable JS file for Ajax.
  2. Create unordered list frames and an area for php and ajax to take place.
  3. Generate a list (Projects) from the xml (No Ajax).
  4. Loads a second (Pieces) list when an item of the list is clicked. Also used Ajax.
  5. Make the Pieces list load on page load, without needing to be clicked first.
  6. Link the Pieces list items to the screen where the images will be displayed. Show the URI of the images.
  7. Show the images when a piece item is clicked.
  8. Make it so that when a diff. project is clicked, the first image in that project is displayed.
  9. Add a cookie aspect. This cookie only sets to the first project on page load, but at least the cookie is set.
  10. Make is so that when a project is clicked, the cookie is set so on page load, the cookie is retrieved and the last project viewed is shown.
  11. Make it so that when a piece is clicked, the cookies set both the project and the piece so when the cookies are retrieved, the last piece of last project viewed is shown.

The Code

Here’s the code. Please link back here if you’re using it.

Place this PHP in the body tag, before other PHP code.


//open the xml file (this is php 4.* and not 5.*)
$xmlDoc = domxml_open_file("catalog.xml");
//get the ARRAY of project nodes
$project = $xmlDoc->get_elements_by_tagname("project");
            

Place this HTML after the previous PHP code.


<h3>Projects List</h3>
<ul id='projectsList' style='background-color:#FFFF00;width:500px;min-height:20px;' >
    

Place this PHP inside the HTML.


//run through the project nodes
for ($i=0;$i<count($project);$i++){
    //get the name node of each project node
    $projectNameNode=$project[$i]->get_elements_by_tagname("name");
    //get the text of each name node
    $projectName=$projectNameNode[0]->get_content();
    //replace the spaces from the names with "%20" so CSS can take them as ID's
    $pNameContract=str_replace(" ","%20",$projectName);
    //create a list item with each project by using the project names as the links
    echo "<li id='projLi-".$pNameContract."'><a onclick='showPieces(\"".$pNameContract."\")' href='#' title='".$projectName."'>".$projectName."</a></li>\n";
    //temporary disables the href value
    //echo "<li id='projLi-".$pNameContract."'><a href='portfolio.php?project=".$pNameContract."' title='".$projectName."'>".$projectName."</a></li>\n";
    }
        

</ul>
<h3>Project Pieces List</h3>
<ul id='piecesList' style='background-color:#66FFCC;width:500px;min-height:100px;' >
</ul>
<div id='screen' style='width:400px;height:200px;border:1px solid black;' >
    This is where the text/image should load.
</div>
            

Put this JavaScript after all the objects are created.


//Define the variable for the piece list
//Do it here so I could refer to it in the function that goes with a project being clicked
var piecesList=document.getElementById("piecesList");

// This function is for when the xmlHttp object's ready state changes.
// It checks when the object is completed the request, and then it
// returns the text from the file it was sent to.
//
//define what to do with the response from the php
function stateChanged(){
//if the request is complete:
if (xmlHttp.readyState==4 || xmlHttp.readyState=="complete"){
//define variable to hold make the response text
var responseText=xmlHttp.responseText;

//splitting the responseText
//find where the project reference in the responseText
var respProjIndex=responseText.indexOf("projectInUri=");
//isolate the project part
var projectInUri=responseText.substring(respProjIndex);
//isolate the part BEFORE the project part
var respList=responseText.substring(0,respProjIndex);

//output the piecesList with the responseText w/o the project part
piecesList.innerHTML=respList;

//define an ARRAY of the pieces list items
var piecesLi=piecesList.getElementsByTagName("li");

//start of "pieces" script borrowing
//taken from the "pieces" part of the script (at the bottom) b/c this will integrate
//the screen update when either the project or the piece list is clicked
for (var i=0;i<piecesLi.length;i++){
//when the piece list item is clicked
piecesLi[i].onclick=function(){
//run the pieces ajax function and take the projectInUri string with it
//so the php will know which project to look through
screenProcessLi(this,projectInUri);
}
}
//end bottom script "borrowing"

//update the screen when the PROJECT is clicked.
//(the above screenProcessLi is for when the PIECE is clicked)
//run some tests to see which function to run
if (getCookie("c_piece")==null){
//if there's no c_piece cookie, show the first piece image
screenProcessLi(piecesLi[0],projectInUri);
} else {
//if c_piece exists, get the value
var c_piece=getCookie("c_piece");
//split c_piece into two parts
//find the split
var c_pieceBreak=c_piece.indexOf("projectInUri=");
//get the first part of c_piece (the piece name)
var c_piecePiece=c_piece.substring(0,c_pieceBreak);
//get the second part of c_piece (the projectInUri)
var c_pieceProject=c_piece.substring(c_pieceBreak);

if(c_pieceProject!=projectInUri){
//if the c_piece DOES exist but is not the same as the project just loaded, also show the first piece image
screenProcessLi(piecesLi[0],projectInUri);
} else if(c_pieceProject==projectInUri){
//if the c_piece DOES exist and is the same as the project displayed, show whatever piece it is
//(this is where the cookie is supposed to work, showing the piece that was last seen and registered in the cookie
showScreen(c_piecePiece,c_pieceProject);
} else {
//this condition shouldn't occur because all the bases should have been covered.
alert("something is wrong");
}
}


} else {
//if the request is not complete, don't do anything.
return;
}
}

//a mid-way function to process the string being sent to showPieces()
function piecesProcessLi(li){
//gets the id of the project list item
var liId=li.id;
//cuts the prefix to the id, leaving only the project name
var liName=liId.substring(7);
//pass it through showPieces function
showPieces(liName);
}

//define variable for the projects list ul
var projectsList=document.getElementById("projectsList");
//define the ARRAY for the projects list items
var projectsLi=projectsList.getElementsByTagName("li");

//run a loop to change the anchor href of the list items if the browser supports javascript
//if browser doesn't support javascript, it's the old fashion individual php
for (var i=0;i<projectsLi.length;i++){
//create an ARRAY of all anchors in the projects list items
var projectsLiAnchor=projectsLi[i].getElementsByTagName("a");
//define all hrefs in the projects list item anchors as "#"
for (var j=0;j<projectsLiAnchor.length;j++){
projectsLiAnchor[j].href="#";
}
}

//the function that does the xml request
//occurs when the page loads or a link is clicked
function showPieces(str){

//call the xmlhttp object.
xmlHttp=GetXmlHttpObject();
if (xmlHttp==null){
alert ("Your browser does not support HTML Request.");
return;
}

//define a url and built upon it
var url="showPieces.php";
//add the query and the project name into the url
url=url+"?project="+str;
//create a random id so the cache is not repeated, or something
url=url+"&amp;sid="+Math.random();

//tells browswer what to do when the ajax is occuring
xmlHttp.onreadystatechange=stateChanged;
//standard ajax stuff that i don't quite get but don't question much right now
xmlHttp.open("GET",url,true);
xmlHttp.send(null);

setCookie("c_project",str,0.001);
}


for (var i=0;i<projectsLi.length;i++){
//var projectsLiId=projectsLi[i].id;
//var projectsLiName=projectsLiId.substring(7);
//alert("projectsLi["+i+"]="+projectsLiName);
projectsLi[i].onclick=function(){
piecesProcessLi(this);
}
}

// the above is for projects section's ajax only

// the below is for pieces section's ajax only

//define the screen area
var screenArea=document.getElementById("screen");

//define a similar function above, to let browser know what to do when php gives us a response
function screenStateChanged(){
//when the state is complete
if (xmlHttp.readyState==4 || xmlHttp.readyState=="complete"){
//define variable to hold the response
var responseText=xmlHttp.responseText;

//outputs the response to the screen
screenArea.innerHTML=responseText;

} else {
//if the state is not complete, don't do anything
return;
}
}

//a function to process the string when the piece is clicked
function screenProcessLi(li,projectInUri){
//get the piece list item's id
var liId=li.id;
//cuts off the prefix of the id, leaving just the piece name
var liName=liId.substring(8);
//runs through the showScreen function to ajax the data
showScreen(liName,projectInUri);
}

//the function that sets up and sends the data to be processed and updates the screen
function showScreen(str,projectInUri){

//adds the project title onto the piece name
var urlData=str+"~"+projectInUri;
//get an xml http object, standard ajx stuff
xmlHttp=GetXmlHttpObject();
if (xmlHttp==null){
alert ("Your browser does not support HTML Request.");
return;
}

//call for a php file that deals with updating the screen;
var url="showScreen.php";
//add the piece query into the url
url=url+"?piece="+urlData;
//add a random id number to avoid cache repeat or whatever
url=url+"&amp;sid="+Math.random();

//standard ajax stuff that i don't really understand
xmlHttp.onreadystatechange=screenStateChanged;
xmlHttp.open("GET",url,true);
xmlHttp.send(null);

//set the cookie with the value of "str", which is the piece name,
//and the projectInUri value
setCookie("c_piece",str+projectInUri,0.001);

}
            

Place this PHP at the end of the page, after all the JavaScript actions are read.


//sets the default item of the page so that on page load, the javascript can have something to process and display an image
//take the first project, and get the name node(s)
$defaultPNameNode=$project[0]->get_elements_by_tagname("name");
//take the first name node (which there is only one) and get the content (the text)
$defaultPName=$defaultPNameNode[0]->get_content();
//manipulate the name by substituting spaces with "%20" so the JS function can recognize it
$defaultPNameContract=str_replace(" ","%20",$defaultPName);
            
//run the javascript function with a cookie searcher
echo "<script type='text/javascript'>\n <!--\n";
        //if c_piece doesn't exist
echo " if(getCookie(\"c_piece\")==null){\n";
            //and if c_project doesn't exist
echo " if(getCookie(\"c_project\")==null){\n";
                //set c_project with the default project
echo " setCookie(\"c_project\",\"".$defaultPNameContract."\",0.001);\n";
                //and show that default project and the first piece in the project is shown by default also
echo " onload=showPieces(\"".$defaultPNameContract."\"); \n";
                //if c_piece doesn't exist BUT c_project exists (which shouldn't happen)
echo " } else {\n";
                //get c_project's value
echo " var c_project=getCookie(\"c_project\");\n";
                //and load the project
echo " onload=showPieces(c_project);\n";
echo " };\n";

            //else if c_piece DOES exist (that means c_project should exist too)
echo " } else {\n";
            //get c_project's values
echo " var c_project=getCookie(\"c_project\");\n";
            
echo " var c_piece=getCookie(\"c_piece\");\n";
echo " var c_pieceBreak=c_piece.indexOf(\"projectInUri=\");\n";
echo " var c_piecePiece=c_piece.substring(0,c_pieceBreak);\n";
echo " var c_pieceProject=c_piece.substring(c_pieceBreak);\n";
            //load the pieces list, which also puts out a "projectInUri" value
echo " showPieces(c_project);\n";
echo " };\n";
echo " //-->\n </script>";
            

Place this PHP in a separate file, named showPieces.php.


$projectInUri=$_GET["project"];

$xmlDoc = domxml_open_file("catalog.xml");
$project = $xmlDoc->get_elements_by_tagname("project");
            
for ($i=0;$i<count($project);$i++){
    $projectNameNode=$project[$i]->get_elements_by_tagname("name");
    $projectName=$projectNameNode[0]->get_content();
    if ($projectName==$projectInUri){
        $pieceNodes=$project[$i]->get_elements_by_tagname("piece");
        for ($j=0;$j<count($pieceNodes);$j++){
            $pieceTitle=$pieceNodes[$j]->get_elements_by_tagname("title");
            $pieceTitleContract=str_replace(" ","%20",$pieceTitle[0]->get_content());
            echo "<li id=\"pieceLi-".$pieceTitleContract."\"><a href=\"#\" title=\"".$pieceTitle[0]->get_content()."\">".$pieceTitle[0]->get_content()."</a></li>\n";
            
            }
        echo "projectInUri=".$projectInUri;
        return;
        }
    }
            

Place this PHP in a separate file, named showScreen.php.


$receiveStr=$_GET["piece"];

$projectInUriIndex=strpos($receiveStr,"~projectInUri=");
$projectInUriString=substr($receiveStr,($projectInUriIndex+1));
$projectInUri=substr($projectInUriString,13);
$pieceInUri=substr($receiveStr,0,$projectInUriIndex);

$xmlDoc = domxml_open_file("catalog.xml");
$project = $xmlDoc->get_elements_by_tagname("project");
            
for ($i=0;$i<count($project);$i++){
    $projectNameNode=$project[$i]->get_elements_by_tagname("name");
    $projectName=$projectNameNode[0]->get_content();
    if ($projectName==$projectInUri){
        $pieceNodes=$project[$i]->get_elements_by_tagname("piece");
        for ($j=0;$j<count($pieceNodes);$j++){
            $pieceTitleNode=$pieceNodes[$j]->get_elements_by_tagname("title");
            $pieceTitle=$pieceTitleNode[0]->get_content();
            if ($pieceTitle==$pieceInUri){
                $pieceImageUriNode=$pieceNodes[$j]->get_elements_by_tagname("image");
                $pieceImageUri=$pieceImageUriNode[0]->get_content();
                echo "<img src=\"".$pieceImageUri."\" alt=\"".$pieceTitle."\" id=\"".$pieceTitle."\" />";
                return;
                }
            }
        return;
        }
    }
            

Return to top