R
E
S
O
U
R
C
E
S
       Home      Products & Services      Contact Us      Links


WebHatchers will design & develop your site for you.
_______________________

Website Menu Heaven: menus, buttons, etc.
_______________________

Send us your questions.
_______________________

site search by freefind
_______________________

HOME
SEO, Google, Privacy
   and Anonymity
Browser Insanity
JavaScript
Popups and Tooltips
Free Website Search
HTML Form Creator
Animation
Buttons and Menus
Counters
Captchas
Image Uploading
CSS and HTML
PHP
AJAX
XPATH
Website Poll
IM and Texting
Databases—MySQL
   or Not MySQL
Personal Status Boards
Content Management
   Systems
Article Content
   Management Systems
Website Directory
   CMS Systems
Photo Gallery CMS
Forum CMS
Blog CMS
Customer Records
   Management CMS
Address Book CMS
Private Messaging CMS
Chat Room CMS
JavaScript Charts
   and Graphs




Free Personal Status Boards (PSB™)

Free Standard Free PSB

Free PSB Pro Version

Free Social PSB

Free Social PSB Plus (with Email)

Free Business PSB

Free Business PSB Plus (with Email)

PSB demo

Social PSB demo

Business PSB demo

So what's all this PSB stuff about?

Chart comparing business status boards

PSB hosting diagram

PSB Licence Agreement



Copyright © 2002 -
MCS Investments, Inc. sitemap

PSBs, social networking, social evolution, microcommunities, personal status boards
PSBs, social networking, business personal status boards
website design, ecommerce solutions
website menus, buttons, image rotators
Ez-Architect, home design software
the magic carpet and the cement wall, children's adventure book
the squirrel valley railroad, model railroad videos, model train dvds
the deep rock railroad, model railroad videos, model train dvds

More PHP Info for the Standard Personal Status Board (PSB™)

The Standard Personal Status Board (PSB™), which is mostly a PHP file called test-db-WORKS-GOOD.php, requires some cool PHP and JavaScript routines

Let's start with JavaScript functions and arrays:

<html><head>
<script language="javascript">
var sub_title=new Array("Alone","Nurturing","P.E.T. or Other Authoritative Parenting Activity","Talk or Play","Coordinate MC Activities","Coordinate Outside Activities","I Am Out","Want Ride","Study or Projects","Custom Codes or Mobile");
var member=-1;Status="";Comment="";
var memstatus=new Array();
var fname=new Array();

mactest=(navigator.userAgent.indexOf("Mac")!=-1) //My browser sniffers
is_chrome = navigator.userAgent.toLowerCase().indexOf('chrome') > -1
Netscape=(navigator.appName.indexOf("Netscape") != -1)
msafari=(navigator.userAgent.indexOf("Safari")!= -1)
wsafari=0; if(!mactest&&msafari){wsafari=1;msafari=0}
is_opera = 0; if(window.opera){is_opera=1}
is_ie_mac = 0; is_ie=0;if(document.all){is_ie=1}
if(is_ie&&mactest){is_ie_mac=1}

function newstatus(){
  document.PSBform.status.value=memstatus[member];
  document.PSBform.ID.value=member+1;//IDs start at 1; arrays start at 0
  document.getElementById('newstatus').innerHTML = fname[member]+" ";}

function validate(){
  if(member<0){alert("Please click a 'Change Status' button first.");return false}
  d=document.PSBform;
  Status=d.status.value;
  if (Status.length!=2 || isNaN(Status)) {alert("Please input any two digits for the personal status code.");return false}

  Comment=d.comment.value;
  Comment=Comment.replace(/--/g," -");
  Comment=Comment.replace(/--/g," -");
  Comment=Comment.replace(/[@#$%\^&\*\(\)\+\|\\=\{\}\[\]\/><]/g," ");
  d.comment.value=Comment;
  return true;}

function validatepassword(){

  var ck_password = /^[A-Za-z0-9!@#$%^&*()_]{4,20}$/;
  if (document.formpw.txtPassword.value.search(ck_password)==-1)
  {alert("Please only enter letters, numbers and these for password: !@#$%^&*()_");return false}

  var ck_username = /^[A-Za-z0-9_]{1,20}$/;
  if (document.formpw.txtUsername.value.search(ck_username)==-1)
  {alert("Please only enter letters, numbers and underline for user name.");return false}

  return true;}

</script>

<script src="psb.js" language="javascript"></script>

The sub_title array gives needed data—subtitles that are used in the status code meanings table. Except for the psb meanings array gotten from the psb.js file, most other data comes from the MySQL db this page reads and displays.

The browser sniffers are obvious—note that even Chrome is included. The PSB™ page works on all major Windows and Mac browsers.

There are Change Status buttons next to each member's comment. The newstatus() function gets the member number when a button is clicked, and uses it to update the input box status and member's first name, next to that input box. The validate() function makes sure the new status code input is a 2-digit numeric number ranging from 00 to 99, then it uses a regular expression to throw out all weird characters like @#$%^&*()+={[}]/><|\ from the comment input and replaces them with spaces. One very dangerous entity is 2 hyphens in a row. This got replaced twice with one space character and one hyphen. Why twice? Because an odd number of hyphens could still let "--" leak through. The function called validatepassword() makes sure the password has no unacceptable characters like " or ' or < or > or -- or + or =, but many other weird characters are OK. Then it makes sure only letters, numbers or underline are in the user name. The routine keeps asking for these inputs until acceptable entries happen, whereas with the comment inputting, unacceptable characters are simply replaced with safer alternatives without warning.

Below, we wrap the entire web page in a container with CSS styles: width:1024px;text-align:left;position:absolute;top:0px;left:50%; and margin-left:-502px. This has little effect on a 1024-pixel-wide screen, but on all wider screens, it centers the page content in the center in this 1024-wide div. The left:50% tries to stick the left edge of the div in the center of the screen, but then the margin-left:-502px takes half the width of the container div and brings the left edge of the div leftward by that much, which exactly centers the div. Well, we had to account for the width of the scrollbar by having margin-left: be 10 less than half the container div width.

The psb.js file is loaded into the browser with an array of all 100 meanings for the 100 possible status codes.

</head>
<body>


<div id='container'>

<div id='logo'><IMG SRC="PSB_.jpg" WIDTH=118 HEIGHT=47 BORDER=0></div>

<?php
$Entry=$_POST['entry'];
$FLAG=$_POST['flag'];
$U=$_POST['txtUsername'];
$P=$_POST['txtPassword'];
$UP=$U."+".$P;

Note: user names and password pairs are stored together in one long string with a + for the separator. If we were dealing with sensitive data, we would store hashes of entered passwords in the db and compare these db hashes with hashes made when users entered passwords and we ran the hash routine on it. But statuses are not that critical—and not even interesting to anyone but the users involved.

$o = array("your_user_name1+your_password1","your_user_name2+your_password2",
"your_user_name3+your_password3","your_user_name4+your_password4",
"your_user_name5+your_password5","your_user_name6+your_password6",
"your_user_name7+your_password7","your_user_name8+your_password8",
"your_user_name9+your_password9","your_user_name10+your_password10");

if ((!in_array($UP, $o))&&($FLAG==0)&&($Entry==1))
{echo '<script language="javascript">alert("Username/password pair is invalid. Please try again.")
</script>;';}

if ((!in_array($UP, $o))&&($FLAG==0)) { ?>

<h1>Personal Status Board (PSB™)</h1>

<div id='pw' style='position:absolute;top:410px;left:200px;width:300px'>
<table style="background-color:#8aa;border-color:#00f" border='6' cellspacing=0 cellpadding=6><tr><td>
<form id='formpw' name="formpw" method="post" action="test-db-WORKS-GOOD.php" onsubmit="return validatepassword()">
<label for="User Name"><b>User Name: </b><input type="text" name="txtUsername" size="20" maxlength="20" value=""></label>
<label for="Password"><b>Password:    </b><input type="password" name="txtPassword" size="20" maxlength="20" value=""></label>
<input type="hidden" name="flag" value="0">
<input type="hidden" name="entry" value="1">
<input type="submit" value="Submit">
<input type="reset" value="Reset"></form></td></tr></table>
</div>
<?php
} else {$FLAG=1;$Entry=0;
?>


Finishing up the head section, we encounter a PHP tag then POST some values into some PHP strings. The $Entry flag set to 1 indicates the login form was filled with data (the value 1 is submitted from a hidden field with the name "entry"). The login submit button sends this page to itself to evaluate the login values—checking them against the correct ones. The variables $U and $P get the username and password entries from the form POSTed to them, and then a + sign is concatenated between them and this is compared to the correct values pairs in the $o array. The PSB™ webmaster will have input the data in the host control panel's MySQL database and also entered the passwords and user names into the control panel. This same webmaster will have entered the correct MySQL db name, MySQL db table name, and username and password in both the update.php file and the above test-db-WORKS-GOOD.php file. The webmaster will have also replaced the generic username/password pairs above with ones that match what he entered into the control panel, not forgetting the + sign separator.

The in_array() function is a PHP function that searches an array for a specific value. This function returns TRUE if the value is found in the array, or FALSE otherwise. So, if (!in_array($UP, $o)) is saying "if the inputted password pair $UP is not (! = not) found in any of the $o array elements, then . . .

The $FLAG flag if set to 0 means the page refreshed because it sent itself login attempt data, and if set to 1 means the page refreshed because it sent was sent a signal that status code and comment was updated by the update.php page, so no login is needed—the PSB™ was simply updated. The value 0 is submitted from a hidden field with the name "flag" when the login happens since one must login before updating the PSB™.

if ((!in_array($UP, $o))&&($FLAG==0)&&($Entry==1))
{echo '<script language="javascript">alert("Username/password pair is invalid. Please try again.")</script>;';}

means that if they blew the login after trying it, they get an "invalid" message. Note the JavaScript statement in the middle of a PHP echo.

if ((!in_array($UP, $o))&&($FLAG==0)) { ?>
means that if they never updated the db or entered array values or logged in, it's time to login. Note the "end of PHP" tag that shows that the entire subsequent HTML login script can now be run as the PHP "if" statement's "then" clause. These languages sure don't seem to mind mixing it up!

<?php
} else {$FLAG=1;$Entry=0;
?>

This is the "else" clause for the above PHP "if" statement, and it follows the HTML login form. Note that PHP has to be re-declared just to say else and reset a couple of flags. The else turns out to be the whole rest of the page—mostly JavaScript document.write statements! Like we've said, mixing it up doesn't upset these languages at all. So what's at the very bottom of the page? The PHP clause closing bracket, all alone. Cool stuff! PHP plays well with others. Some examples of that are at the bottom of this JavaScript Object Notation page.

<?php
}
?>


Now, let's get data from the db:

<div id='s' style='position:absolute;top:53px;left:2px'>
<?php
// Make a MySQL Connection
mysql_connect("localhost", "your_user_name", "your_password") or die(mysql_error());
mysql_select_db("name_of_db") or die(mysql_error());

// Retrieve all data from the "name_of_db_table" table as a MySQL Resource
$result = mysql_query("SELECT * FROM name_of_db_table") or die(mysql_error());

echo "<table border='1' width='578'>";
echo "<tr><th width='116'>Name</th><th width='25'>ID</th><th width='25'>Status</th><th width='412'>Comment</th></tr>";
// keeps getting the next row until there are no more to get
while($row = mysql_fetch_array($result)) { // Print out each row
echo "<tr><td>";
echo htmlentities(stripslashes($row['Firstname']), ENT_QUOTES);
echo "</td><td>";
echo htmlentities(stripslashes($row['ID']), ENT_QUOTES);
echo "</td><td>";
echo htmlentities(stripslashes($row['Status']), ENT_QUOTES);
echo "</td><td>";
$C=$row['Comment'];
$a=explode("|", $C);
$C=htmlentities(stripslashes($a[0]), ENT_QUOTES);
$C=$C."<span style='font-size:11px;'> ".$a[1]."</span>";
echo $C;
echo "</td></tr>";
}
echo "</table>";
echo "<br />";

We connect to the host server, select a db, get all the data from a specific table in the db (there can be many), and print it out in an HTML table. Standard stuff. Even the use of htmlentities() and stripslashes() to first get the slashes out of the data that the mysql_real_escape_string() function in update.php put in for security before putting data in the db table is standard. Changing text data into HTML entities (like " = %22) keeps it safer for screen display. A bit less standard is to explode the Comment field into an array of 2 elements. We run the security functions on the first element (the data before the |). The second element was automatically created in JavaScript as the date and time and POSTed to update.php during form submission. So it's harmless. The 2 array elements are concatenated together with a span tag that has a style forcing a smaller font size for the date and time.

$number=mysql_num_rows($result);

$myArray=array();

$res = mysql_query("SELECT Firstname FROM name_of_db_table") or die(mysql_error());
while ($row = mysql_fetch_row($res)) {
array_push ($myArray, $row[0]);
}

$myArray2=array();

$res = mysql_query("SELECT Status FROM name_of_db_table") or die(mysql_error());
while ($row = mysql_fetch_row($res)) {
array_push ($myArray2, $row[0]);
}

mysql_close();

?>

</div>

We grab the number of rows from a MySQL function, then define a couple of arrays to dump rows of data into as arrays. For this, we use "while" loops to dump the Firstname and Status rows into waiting PHP arrays. The PHP array_push function is available for this.

<script language="javascript">

var ttt="";

function dateandtime(){
var currentTime = new Date();
var currentDate = new Date();
var day = currentDate.getDate();
var month = currentDate.getMonth()+1;
var hours = currentTime.getHours();
var minutes = currentTime.getMinutes();
var suffix = "am";
if (hours >= 12) {suffix = "pm";hours = hours - 12;}
if (hours == 0) {hours = 12;}
if (minutes < 10){minutes = "0" + minutes;}
ttt=month + "/" + day + " " + hours + ":" + minutes + suffix;}

var fname = <?php echo json_encode($myArray); ?>;

number_records_in_table = <?php echo $number; ?>;

var memstatus = <?php echo json_encode($myArray2); ?>;

Above, first we utilize the JavaScript Date() function to create date and time variables full of the current date and time. Then we stick this data together in a convenient, concise form (i.e., 11/21 9:42am) and put it into the variable ttt. It will end up at the end of every comment in the display table, as well as substituting for a comment in entries in which the PSB user chooses to make no comment.

Now we encode the PHP arrays into JavaScript arrays using JSON, or JavaScript Object Notation, which is available by default in PHP V5.2 and up, unless the host has them turned off, in which case you need to ask him nicely to turn them on. You don't have to do anything to have this available in your code—it's part of PHP now. You can see how trivial the encoding function is. The JavaScript arrays were both previously declared in the above code, at the start of this tutorial. The $number variable converted to JavaScript without JSON help, since the conversion method shown above works on small numbers, but NOT on strings or arrays, and if the number has over 16 digits in it, the number will get rounded off.

a='82px';b='25px';h='25px';n=572;if(is_ie_mac){a='82px';b='23px';h='23px';n=570;}
if(Netscape&&!mactest){a='83px';b='26px';h='25px';};
if(Netscape&&mactest){a='84px';b='25px';h='25.7px';n=585;};
if(msafari){a='80px';b='24px';h='24px';n=570;};
if(wsafari&&!is_chrome){n=583;};
if(is_chrome){n=583;};
if(is_opera){n=565;};

Above, we use our browser sniffer results to adjust some display-related values according to which browser is being used.

document.write("<div id='q' style='position:absolute;top:53px;left:582px'><table width=\"420\" border=\"1\" cellpadding=\"1\">");

document.write("<tr><th width='50' height='+h+'>Change</th><th width='375'>Meanings</th></tr>");

for (i=0;i<number_records_in_table;i++){document.write( "<tr><td>" + " " + "</td><td>" + psb[parseInt(memstatus[i],10)] + "</td></tr>");}

document.write ("</table></div>");

z=410;zz=360;zzz=340;zzzz=391;zzzzz=145;if (number_records_in_table>10){z=410+((number_records_in_table - 10)*30);zz=z-50;zzz=z-73;};if(Netscape||is_opera){zzzz=402;zzzzz=123;}

Above, we use a FOR loop to print .js data into a table. The cool detail here is psb[parseInt(memstatus[i],10)], which gets the correct PSB™ status code meaning (out of 100 possibles) for each of the members, and where meanings are based on the current status code of each of the members, and where i is member id (1 to whatever) and memstatus[i] is the current status per member. Then we adjust some display-related values according to how many records there are. The zzzzz variable is for displaying a sidebar with links in it, where some browsers require different "box models" due to adding padding to widths:

document.write("<div style='padding:10px;border:1px solid black;background-color:#ccc;position:absolute;width:"+zzzzz+"px;top:"+z+"px;left:857px;text-align:left'> . . . . blah blah . . . </div>");

document.write ("<div style='position:absolute;top:"+zzz+"px;left:"+n+"px'><i>Please cease typing when you get here</i><span class='arrow'><b>↓</b></span></div>");

document.write ("<form style='position:absolute;top:"+zz+"px;left:10px;width:989px;' id='status' name='PSBform' method='post' action='update.php' onsubmit='return validate()'><b id='newstatus'>Member </b><label for='status'><b>Status: </b><input type='text' name='status' size='2' maxlength='2' value=''></label><label for='comment' style='position:absolute;top:0px;left:370px;width:629px;'><b>Comment (optional): </b><input type='text' name='comment' size='44' maxlength='44' style='font:16px \'Times New Roman\''></label><input type='hidden' name='ttt' value=' '><input type='hidden' name='ID' value=
' '><input type='submit' value='Update PSB'></form>");

Above, we display a message to get them to avoid typing past the end of the input box (because wider characters will mess up the looks of the table if there are too many of them). Then we create a form on the fly. Note that its top positioning is zz, a calculated value depending on how many members there are. A few members would require that the form display higher on the screen, while more members puts it lower. The form action is 'update.php' because we use that file to actually update the db.

document.write("<div id='r' style='position:absolute;top:"+z+"px;left:288px'><table border=\"1\" cellpadding=\"1\">");

document.write("<tr><th>Status Code</th><th>Meaning</th></tr>");

f=0;u=" ";

for (i=0;i<100;i++){

u=i.toString();if (u.length<2){u="0"+u}

if(u.charAt(1)=="0"){document.write( "<tr><th colspan=2>" + sub_title[f] + "</th></tr>");f=f+1}

document.write( "<tr><td>" + u + "</td><td>" + psb[i] + "</td></tr>")}

document.write ("</table><br><br><br></div><br><br><br>");

Above, we use a loop to print out all the status codes and their meanings, complete with subtitles. Since all codes must have 2 digits, we converted the loop's i variable to u with a string type, then added a "0" character if the i value was 0 through 9. The 2-digit i values needed no processing. If the second character is "0", a subtitle is printed, since every 10 codes the status codes are in a different generic category.

document.write("<div id='g' style='position:absolute;top:"+a+";left:587px'><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\">");

if(!mactest){for (i=0;i<number_records_in_table;i++){document.write( "<tr><td style='height:"+h+";'><a HREF='#' onclick='member="+i+",newstatus(),document.PSBform.status.focus()'><div style='height:"+b+";'><IMG SRC='change.png' WIDTH=40 HEIGHT=22 BORDER=0></a></div></td></tr>");}
}else{
for (i=0;i<number_records_in_table;i++){document.write( "<tr><td style='height:"+h+";'><a HREF='#' onclick='member="+i+",newstatus(),document.PSBform.status.focus()'><div style='height:"+b+";'><IMG SRC='change-.png' WIDTH=40 HEIGHT=18 BORDER=0></a></div></td></tr>");}}

document.write ("</table></div>");

document.write ("<div style='color:white;font-size:18px;position:absolute;left:80%;top:10px'><b>Refresh often [F5]</b></div>");

Above, we put a column of buttons next to the Comment and Meaning columns, so users can choose whose status and comment to update. We coded it twice, with Mac computers getting one image and Windows computers getting another. This is because the Mac default table displaying procedures make skinnier rows. Note that an OnClick event not only sends the focus to the status input box, it also sets the value of the member variable and runs a function which sets the comment box value to nothing (so old comments do not linger in case you updated another member first), sets the status input box to its current value, and replaces the word "Member" with the actual name of the member. Note the </div> at the end of the script below—this is the far end of the container div that holds the entire page. Also note the "Refesh often" message that gets printed at the top right corner of the screen, above. This reminds users that other users might be updating statuses but such changes will not happen on their page unless they refresh the screen to pull the very latest data from the MySQL table.

</script>
<BR>

<?php
}
?>

</div>

</body></html>

We could have used action="test-db-WORKS-GOOD.php" in the form tag so the page's form would reload the page, and also have the content of update.php on this page, but this would have made the page's code needlessly complex. We could have used Ajax to relate to the update.php page, so no page reloads would happen. We didn't, and for the same reason. It isn't surprising to see a PHP file run as the form submission action of an HTML form—this is common. But if the action here was a PHP command to reload the current page, we would like to be able to use $_SERVER['PHP_SELF'], but it's not safe. It's best to use the page's own name or " " (which reloads the page if there's a submission) instead.