Below you'll see examples of some of the code that I've either written myself or contributed to. If you have any questions, please feel free to contact me and don't forget to peruse my portfolio at http://www.brucegust.com/portfolio.
Please click on the Verizon logo displayed to the right to see what I contributed during my contract position with Verizon...
Thanks! Kind Words... In short, Bruce proved to be a professional model in every sense of the word. His skills were at the top of his peers and he maintained them through disciplined study, earning him the nickname "hard charger". As an instructional leader, he set standards of professionalism, discipline, and integrity that were beyond reproach. As a team member, he was consistently focused on the goals of leadership and never failed to deliver. As a team leader, he set an example for all to admire, including myself. As a result, many people Bruce touched during his service, attribute him to much of their success. He was indeed an inspirational leader. ...I give Bruce the highest marks in professionalism, leadership and integrity. Knowing his breadth of abilities, his dedication, and his proven success, I would hire him for nearly any position in my organization knowing he'll find a way to win regardless of the obstacles. Ray Dunaway, PMP, CWI Corporate Vice President of Technology Bapcock Power, Louisville, KY (click here to view the entire text)
I've had the pleasure of working with Bruce over the past six months. Bruce is hard-working, dependable and unafraid of a challenge. I hired Bruce to work on a legacy platform as we moved to a new system...Bruce single-handedly maintained three portals for us. He kept the call center portal up and running throughout the six months he was with us. He also made a few much needed enhancements to our client facing portal. The clients were thrilled with the functionality and ease of use...He will be a value add to any organization lucky enough to have him join the team. Kristi Hatchell Director of Operations Patient Focus (click here to view the entire text)
Bruce Gust has worked under my employ for over a year in the position of software development contractor. In that time he has proven himself to be a valuable resource to the team...Bruce is a pleasure to work with due to his personality and all around positive attitude. He interacted directly with internal customers and they were always pleased with the results. Bruce was a remote employee and was always easy to manage. He was responsive to emails and phone calls and I was never concerned about output even though we were at separate locations... I would not hesitate to work with him again. Donald Meador Senior Manager South Area Development at Verizon Wireless (refer to linkedin.com for the full text)
The following is a portion of an email I received after having remedied a dilemma that had been left unresolved for two years. I was asked to take a look at it and see if I couldn't come up with a solution. The problem was a broken link resulting from a number of factors, not the least of which were some security issues that prohibited some docs from being viewed using an http protocol. I was able to create a workaround and here is the response from the Stephanie Horton, Senior Manager of Member and Client Engagement ... I think you deserve a medal for this one, many minds have come and gone and given up! This definitely has the smell of success...Seriously Huge Thank You for working and succeeding! Stephanie Horton Sr. Manager, Member and Client Engagement Applied Health Analytics (refer to linkedin.com for the full text / screenshot)
click here to view more testimonials from both supervisors and clients...
Object Oriented Programming Most of my work is done in an OOP enviornment. With Verizon, I was asked to code within an original framework that further grouped the various classes beneath the banners of "Model," "View" and "Controller." Very clever, actually. With Patient Focus, again, OOP was the approach, but this time it was constructed within the Code Igniter framework and the syntax was more complicated / verbose. Symbion was primarily procedural PHP, but what made that paradigm unique is that the database was T-SQL and everything was written in PHP, including the Javascript. It was "echo-ed," rather than written as straight Javascript. I didn't include any samples of that work, although I do have that experience documented in the context of some Stored Procedures I wrote in MSSQL Studio. Feel free to look at the samples below. PDF Generator Using JQuery "GET" Upload and Insert of Document & Attachments w/ Email Alert Multi-Dimensional / Associative Arrays and the Scope Resolution Operator (::) GANT Calendar (PDO and Javascript) Verizon Calendar (Procedural and Javascript) Responsive Website Thornhill Landscaping Media Queries Symbion Healthcare Basic Functionality iPhone The Starting Line
 PHP | Object Oriented Programming
Here's a sampling of some of what I've done in an OOP environment... PDF Generator Using JQuery "GET" The dilemma in this instance is that you had several PDFs being generated via several SELECT statements. Because each PDF was several pages long, if the incoming request was for several hundred reports, the system had a tendancy to timeout. The solution was to do things incrementally using some JQuery. The user begins by clicking on a link that triggers the initial SELECT while simultaneously opening up a little "alert" box. This is the class that's looking to see if the user has selected a "Prime" dynamic. If so, then the "print_orders" command is put into position: E) Implementation (back to top...) 1) showOrders.tpl / pap.class.php (back to top...) Your GUI is represented by "showOrders.tpl" which is called by the "pap.class.php" page. On line #5553 - #5558 of the "pap.class.php" page, you've got this: if (stristr($row['ordItemShort'],'prime')) { $laps=round($row['ordQty']/10)+1; // define the number of laps you're going to do based on the $ordQty value $out['printButton'] = "print_forms('".$row['empID']."', '".$row['hID']."', '".$row['ordItemShort']."', '', '".$row['ordID']."', '". $row['ordQty']."','0','".$laps."')"; } else if(stristr($row['ordItemShort'],'survey')) { $out['printButton'] = $printButtonGrowl." xajax_Production.init_genPSM('".$row['empID']."', '".$row['hID']."', '".$row['ordItemShort']."', '', '".$row['ordID']."', '". $row['ordQty']."')"; } What you're looking at is different from the original in that you have some reports that have both "prime" and "survey" in the title. The original code was looking for either "prime" or "survey" ( if (stristr($row['ordItemShort'],'survey') || stristr($row['ordItemShort'], 'prime')) {. With that logic, the "prime" dynamic wasn't being accurately identified. Also, in our prototype we were using a regular link. This is a button so you had to pass the variables in a little differently. In any event... It's putting together the "printButton" that shows up on "showOrders.tpl" which looks like this: {{ IF $printButton}} <div class="UnTip" onmouseover="Tip('Print Order')" style="width: 20px; height: 20px; float: left; cursor: pointer; background: url(../images/layout/icons_dashboard.png) no-repeat -20px -100px;" onclick="{{$printButton}}"></div> {{ ELSE }} <div style="float:left; height:20px; width:20px;"></div> {{ END IF }} Notice, there's either a print button or there's not. Everything is being determined by the "pap.class.php" page. The "print_forms" JQuery function, which is located on the "js.tpl" page (bIQ/common/templates/pap)" looks like this: function print_forms(empID, hID, itemSel, cpID, orderID, quantity, primeID, laps, reps) { $('.centered').show(); $.get('hello.php?empID='+empID+'&hID='+hID+'&item_sel='+itemSel+'&cpID='+cpID+'&orderID='+orderID+'&quantity='+quantity+'&PrimeID='+primeID+'&laps='+laps+'&reps=1', function(data) { $('#gear_text').html(data); }); } The "print_forms" function "shows" the "centered" div and then puts the info coming back from the "hello.php" page into the "gear_text" part of the little window. That HTML / CSS on the "showOrders.tpl" page looks like this:
<style> .centered { position: fixed; top: 50%; left: 50%; /* bring your own prefixes */ transform: translate(-50%, -50%); border:1px solid #cccccc; width:320px; height:175px; background-color:#ffffff; box-shadow:6px 6px 6px #656464; border-radius:10pt; padding:0; z-index:10; display:none; } .embossed { width:285px; height:135px; margin:auto; box-shadow:3px 3px 1px #ccc inset; border:1px solid #ccc; border-radius:10pt; margin-top:10px; padding:10px; } .gears { width:90%; margin:auto; height:90%; margin-top:7px; font-family:arial; } .gears table tr td { border:none; } </style> <div class="centered"> <div class="embossed"> <div class="gears"> <br> <table> <tr> <td style="padding-top:10px;"><img src="../images/loading_gears.gif"></td> <td style="font-size:9pt;" id="gear_text">Do not close this window. The system is currently creating your PDFs! <br><br>Stand by! </td> </tr> </table> </div> </div> </div>
2) hello.php / pap_print.class.php (back to top...) The "print_forms" command starts by knocking on the door of the "hello.php" page which is going to trigger the "$bob" command which is going to run the init_genPSP function that's housed on the "pap_print.class" page. That particular function is a bear in that it's generating the actual PDF, but here's the piece that was edited so it's only generating 10 documents at a time and is always looking for the PrimeID that's greater than the one being passed into the function. Here's the "hello.php" page:
  1. <?php
  2. require_once(WEBROOT.'lib/functions.php');
  3. require_once(WEBROOT.'xajax/xajax_core/xajax.inc.php');
  4. require_once(WEBROOT.'lib/class/session.class.php');
  5. require_once(WEBROOT.'lib/class/app.class.php');
  6. require_once(WEBROOT.'lib/class/hdap.class.php');
  7. require_once(WEBROOT.'lib/class/channel.class.php');
  8. require_once(WEBROOT.'lib/class/admin.class.php');
  9. require_once('pap.class_print.php');
  10. // init vars and settings
  11. $A = new Application($CN);
  12. $P = new PrintProduction($CN);
  13. $H = new HelpDesk($CN);
  14. $C = new Channel($CN);
  15. $M = new Admin($CN);
  16. $xajax = new xajax();
  17. $xajax->configure("javascript URI", 'xajax/');
  18. $xajax->register(XAJAX_CALLABLE_OBJECT, $A);
  19. $xajax->register(XAJAX_CALLABLE_OBJECT, $P);
  20. $xajax->register(XAJAX_CALLABLE_OBJECT, $H);
  21. $xajax->register(XAJAX_CALLABLE_OBJECT, $C);
  22. $xajax->register(XAJAX_CALLABLE_OBJECT, $M);
  23. $empID=$_GET['empID'];
  24. $hID=$_GET['hID'];
  25. $item_sel=$_GET['item_sel'];
  26. $cpID=$_GET['cpID'];
  27. $orderID=$_GET['orderID'];
  28. $quantity=$_GET['quantity'];
  29. $PrimeID=$_GET['PrimeID'];
  30. $laps=$_GET['laps']-1;
  31. $reps=$_GET['reps'];
  32. $attempt=new PrintProduction($CN);
  33. //usuallly $cpID is NULL by default. It's set to 0 in the context of the JQuery syntax to avoid it throwing an error. For the sake of the "init_genPSM" method, if it's 0, just leave that parameter blank
  34. if($cpID==0)
  35. {
  36. $bob=$attempt->init_genPSP($empID, $hID, $item_sel, '', $orderID, $quantity, $PrimeID, $reps);
  37. }
  38. else
  39. {
  40. $bob=$attempt->init_genPSP($empID, $hID, $item_sel, $cpID, $orderID, $quantity, $PrimeID, $reps);
  41. }
  42. if($laps>0)
  43. {
  44. echo "<script>
  45. $(document).ready(function() {
  46. $.get('hello_again.php?empID=$empID&hID=$hID&item_sel=$item_sel&cpID=$cpID&orderID=$orderID&quantity=$quantity&PrimeID=$bob&laps=$laps&reps=$reps', function(data) {
  47. $('.centered').show();
  48. $('#gear_text').html(data);
  49. });
  50. });
  51. </script>";
  52. }
  53. else
  54. {
  55. $printDate = date('m_d_Y');
  56. $linkPath = '/SecureFileZipper.php?zipLoc=internal/production/' . $printDate . '/primed/' . $orderID;
  57. echo "<script>
  58. $('.centered').show();
  59. $('#gear_text').html('You are all set! <br><br>To access the PDFs you just created, click <a href=\"$linkPath\" target=\"_blank\" style=\"font-size:9pt;\">here</a>.<br><br>Click <a id=\"close_print_window\" href=\"#\" style=\"font-size:9pt;\">here</a> to close this window!');
  60. $('#close_print_window').click(function() {
  61. $('.centered').hide();
  62. });
  63. </script>";
  64. }
  65. ?>
On lines #27 - #35, you're grabbing the values that are embedded in the URL coming from the "print_forms" function. The "$reps" value was hardcoded initially as "1" and the "$laps" value was calculated as part of the initial functionality on the "pap.class.php" page. Notice how we're subtracting "1" from the number of laps that have been done. The "$reps" value is for the sake of numbering the PDFs that are being generated as part of the "init_genPSM" function on the "pap_print.class" page. Here's that code:
  1. function init_genPSP($empID_sel=NULL,$hID_sel=NULL,$item_sel=NULL,$cpID_sel=NULL, $orderID=NULL, $quantity=500, $PrimeID, $reps) {
  2. global $S;
  3. global $A;
  4. //$R = new xajaxResponse();
  5. //$R->appendResponse(Application::InitializeClass());
  6. $boom=0;
  7. //$stmt = $this->cn->prepare('SELECT Top 10 PrimeID, rhID FROM Orders_hraResponseHeaders WHERE orderID = :orderID AND PrimeID>:PrimeID ORDER BY PrimeID');
  8. $stmt = $this->cn->prepare('SELECT Top 10 PrimeID, rhID FROM Orders_hraResponseHeaders WHERE orderID = ? AND PrimeID>? ORDER BY PrimeID');
  9. $stmt->execute(array($orderID, $PrimeID));
  10. if($table = $stmt->fetchall(PDO::FETCH_ASSOC))
  11. {
  12. $userTable = array();
  13. foreach($table as $value) {
  14. $lastPrimeID=$value['PrimeID'];
  15. $rhID = $value['rhID'];
  16. $stmt = $this->cn->prepare('SELECT cp.cpID, RIGHT(u.usrSSN, 4) as usrSSN_L4, u.*, r.rhID, e.empName, h.hPID, h.hID, h.hName, c.cmpLogoLrg, c.cmpLogoMed,
  17. c.cmpSignatureImg, c.cmpSignatoryName, c.cmpSignatoryTitle, c.cmpPHRLetter, c.cmpPostSurveyTxt, c.cmpSurveyLegalTxt, c.cmpBioSurveyLegalTxt, c.cmpSurveyLetter_sp,
  18. c.cmpSignatoryTitle_sp, c.cmpSurveyLetter
  19. FROM hraResponseHeaders r INNER JOIN
  20. hraUsers u ON r.usrID = u.usrID INNER JOIN
  21. Employers e ON u.empID = e.empID INNER JOIN
  22. ChannelPartners cp ON e.cpID = cp.cpID INNER JOIN
  23. hraHeaders h ON r.hID = h.hID INNER JOIN
  24. Components c ON cp.cmpID=c.cmpID
  25. WHERE (r.rhID= ?)');
  26. $stmt->execute(array($rhID));
  27. $userTable[]= $stmt->fetchall(PDO::FETCH_ASSOC);
  28. }
  29. //Date for PDF Folder
  30. $pDate = date('m_d_Y');
  31. // Loop through Prime Users and Generate a report.
  32. //Determine the number of orders
  33. $orderCount = sizeof($userTable);
  34. //get the character count for the number of orders so we can use it in padding
  35. $orderCountCharCount = strlen($orderCount);
  36. if($orderCount>0)
  37. {
  38. //you still have rows to process
  39. $new_count=$reps;
  40. for ($i=0; $i < $orderCount; $i++) {
  41. $incrFileName = $orderID.'_'.str_pad($new_count, $orderCountCharCount, '0', STR_PAD_LEFT).'_';
  42. $pdfPath = $this->exe_primeGenPSP($item_sel, $userTable[$i][0], $incrFileName, $orderID, $pDate);
  43. //$R->append('d4', 'innerHTML', '<iframe style="display: none" name="iframe" name="iframe" src="'.$fpath[$i].'"></iframe>');
  44. $new_count=$new_count+1;
  45. }
  46. //kill the connection in order to avoid the chance of timing out...
  47. $stmt=null;
  48. $this->cn=null;
  49. return $lastPrimeID;
  50. }
  51. else
  52. {
  53. //you've reached the end of the line and all of the docs have been processed
  54. }
  55. }
  56. else
  57. {
  58. echo "no";
  59. }
  60. //if there are still more rows to process,
  61. //return $R;
  62. }
On line #9, you've got the SELECT that we're now familiar with thanks to the change that we made on the "pap.class.php" page, as far as grabbing only 10 rows. The $PrimeID is being grabbed from the embedded value in the URL. We get all that information and then on line #50, we kick off the "exe_primeGenPSP" function which is what actually generates the PDFs. On line #46 you see the "$reps" value. We add 10 to that with each lap in order to prevent overwriting the PDFs that have already been completed. When everything is done, we return the "$lastPrimeID" which is the last ID of the row that was processed and we pass that into the "GET" command on line #55 of the "hello.php" page that now has the new $PrimeID in tow as well as the adusted number of $reps and we send that all that to the "hello_again.php" page. 3) hello_again.php (back to top...) The "hello_again.php" page really only has one purpose and that's to give the database connection an opportunity to time out. You'll notice on lines #57 - #58, we're shutting down the connection. This is what ensures that regardless of how many rows we have to process, we don't run the risk of timing things out. The "hello_again.php" page looks like this:
  1. <?php
  2. $empID=$_GET['empID'];
  3. $hID=$_GET['hID'];
  4. $item_sel=$_GET['item_sel'];
  5. $cpID=$_GET['cpID'];
  6. $orderID=$_GET['orderID'];
  7. $quantity=$_GET['quantity'];
  8. $PrimeID=$_GET['PrimeID'];
  9. $laps=$_GET['laps'];
  10. $reps=$_GET['reps']+10;
  11. if($laps>1)
  12. {
  13. echo "<br><br>Stand by! You've only got $laps more laps to go!";
  14. }
  15. else
  16. {
  17. echo "<br><br>Stand by! You've only got $laps more lap to go!";
  18. }
  19. echo "<script>
  20. $(document).ready(function() {
  21. setTimeout(function() {
  22. $.get('hello.php?empID=$empID&hID=$hID&item_sel=$item_sel&cpID=$cpID&orderID=$orderID&quantity=$quantity&PrimeID=$PrimeID&laps=$laps&reps=$reps', function(data) {
  23. $('#gear_text').html(data);
  24. });
  25. }, 3000);
  26. });
  27. </script>";
  28. ?>
You're grabbing the needed values on lines #3 - #11 and embedding them into your next "GET" which is going to bounce the process back to the "hello.php" page. You add 10 to the $reps value on line #10, you'll subtract from the $laps value when you get back to the "hello.php" page and you're giving the whole process a 3 second reprieve on line #29. When you get back to the "hello.php" page, you're repeating the process but it's dependent on the number of $laps you've got left which is line #51 of the "pap_print.class" page. Once you're at a point where there are no laps left, you give the user the link to the zip file and provide the function that allows the user to close the window. Upload and Insert of Document & Attachments w/ Email Alert This is a basic syntax that allowed an employee to submit a Project Request. They would fill out the form the form that you see to the right. When the user hit, "submit" they were routed to a page that began like this: <?php require_once('satellitepageclass.php'); require_once('model_class.php'); //where the ProjectAdmin class was kept require_once('view_class.php'); $page_title="South Area Network Project Insert Page"; $new_page= new SatellitePage; $new_article= new ProjectAdmin; $new_display = new viewProject; $insert=$new_article->project_insert(); // instantiating the project_insert method
  1. class Project Admin {
  2. public function project_insert(){
  3. global $mysqli;
  4. $user_name=$mysqli->real_escape_string(trim($_POST['user_name'])); $email=trim($_POST['email']); $priority=trim($_POST['priority']);
  5. $type=trim($_POST['type']); $department=$mysqli->real_escape_string(trim($_POST['department']));
  6. $description=$mysqli->real_escape_string(trim($_POST['description'])); $name=$mysqli->real_escape_string(trim($_POST['short_name']));
  7. $go_live_date = date('Y-m-d',strtotime($_POST['month'].' '.$_POST['day'].' '.$_POST['year'])); $today=date("Y-m-d");
  8. $attachment_count=0;
  9. $pref_count=0;
  10. $sql="insert into projects (name, email, department, priority, description, requested_by, app_type, date, go_live_date) values ('$name', '$email', '$department', '$priority', '$description', '$user_name', '$type', '$today', '$go_live_date')"; //echo $sql;
  11. if(!$query=$mysqli->query($sql))
  12. {
  13. $err = 'your page_insert query didn\'t work becasue:'
  14. .' ERRNO: '
  15. .$mysqli->errno
  16. .' ERROR: '
  17. .$mysqli->error
  18. .' for this query: '
  19. .$sql
  20. .PHP_EOL;
  21. trigger_error($err, E_USER_WARNING);
  22. }
  23. $novie_id = $mysqli->insert_id;
  24. //check to see if this user is already listed in preferences
  25. $sql_1 = "select id from preferences where email = '$email'";
  26. if(!$query=$mysqli->query($sql_1))
  27. {
  28. $err = 'your preferences query didn\'t work becasue:'
  29. .' ERRNO: '
  30. .$mysqli->errno
  31. .' ERROR: '
  32. .$mysqli->error
  33. .' for this query: '
  34. .$sql
  35. .PHP_EOL;
  36. trigger_error($err, E_USER_WARNING);
  37. }
  38. $pref_count = $query_1->num_rows;
  39. if($pref_count==0)
  40. {
  41. //add user to preferences table
  42. $sql_3 = "insert into preferences (email) VALUES ('$email')";
  43. if(!$query=$mysqli->query($sql))
  44. {
  45. $err = 'your preferences_insert query didn\'t work because:'
  46. .' ERRNO: '
  47. .$mysqli->errno
  48. .' ERROR: '
  49. .$mysqli->error
  50. .' for this query: '
  51. .$sql
  52. .PHP_EOL;
  53. trigger_error($err, E_USER_WARNING);
  54. }
  55. }
  56. $msgText=""; $msgText .= "height:800px; border: 1px solid #cccccc;\">
  57. style=\"font-family:Helvetica; font-size:12px; color:#ffffff; text-align:right; vertical-align:middle;
  58. font-weight:bold; width:370px;\">Project Request Form; $msgText .=date("l - F jS, Y");
  59. $msgText .="background-color:#8f9293;\">
  60. style=\"border-spacing: 0; border-collapse: collapse;\">
  61. font-size:32px; color:#ffffff;\"> South Area Network
  62. style=\"background-color:#000000;\">
  63. font-family:Helvetica; font-size:12px; color:#000000; height:674px; vertical-align:top;
  64. padding:10px;\"> A project request has been submitted. Below are some of the details. To view the entire
  65. Project Request, login to the South Arean Network Admin Page.Project Name: ";
  66. $msgText .=$_POST['short_name']; $msgText.="<br><hr><br>Requested By: ";
  67. $msgText .=$_POST['user_name']; $msgText.="<br><hr><br"; if($_POST['priority']==1) {
  68. $priority="urgent"; } elseif($_POST['priority']==2) { $priority=="high"; }
  69. elseif($_POST['priority']==3) { $priority="medium"; } elseif($_POST['priority']==4) { $priority="low"; }
  70. elseif($_POST['priority']==5) { $priority="very low"; } $msgText.="Priority: "; $msgText .=$priority;
  71. $msgText.="<br><hr><br>"; $msgText .="go live date: "; $msgText .=date("m/d/Y",
  72. strtotime($go_live_date)); $msgText .="<br><hr><br>"; $msgText .=nl2br($_POST['description']); $msgText
  73. .="
  74. style=\"font-family:Helvetica; font-size:9px; color:#000000; text-align:center;\">©Verizon Wireless |
  75. South Area | All Rights Reserved |
  76. href=\"http://southareanetwork.nss.vzwnet.com/page.php?page_id=8\" style=\"font-family:Helvetica; font-size:9px;/">Contact</a>";
  77. $toText="Donald.Meador@VerizonWireless.com";
  78. //$toText="bruce.gust@VerizonWireless.com"; $ccText="bruce.gust@VerizonWireless.com"; $fromText = $_POST['email'];
  79. $subjectText="new project request from "; $subjectText .=$fromText; $header = "From:
  80. ".$fromText."\r\n"; $header .= "Cc: ".$ccText."\n"; $header .= "Reply-To : ".$fromText."\r\n"; $header
  81. .= "Return-Path : ".$fromText."\r\n"; $header .= "X-Mailer: PHP\r\n"; $header .=
  82. "MIME-Version: 1.0\r\n"; $header .= "Content-Type: text/html; charset=ISO-8859-1\r\n"; //
  83. ini_set(sendmail_from,$fromText); $postoffice=mail($toText, $subjectText, $msgText, $header, '-f'.$fromText);
  84. return($novie_id); }
  85. }
Please feel free to click on the "paint bucket" to view a more legible version of the code!
  • lines 1-7 clean up the data
  • lines 10-22 insert the data
  • line 23 grabs the insert id that will be used to update the row we just entered if there's an attachment associated with it
  • line 25 looks to see if user is currently listed in the preferences table. The preferences table stored all user data pertaining to their favorite tools and the corresponding links along with any Project Requests that had on file
  • line 38 looks to see how many rows were returned by the previous SELECT statement and if none were registered, then the user was added to the preferences table
  • lines 57 - 84 send an email out to the Regional Manager, alerting them to a new Project in the project table that includes a link to the project itself
  • line 85 returns the INSERT ID which will be used to "link" any attachments that go along with this Project Request to the Request itself
The next step is to handle any attachments the user may have included in their request. First, you have the instantiation of the method depending on whether or not anything was sent via the form. if(isset($_FILES['attachment_1'])&& !empty($_FILES['attachment_1']['name'])) { $attachment_upload_1=$new_article->attachment_upload_1($insert); $attachment_count=1; } You can see the attachment_upload method below.
  1. public function attachment_upload_1($insert) {
  2. global $mysqli;
  3. $novie_id=$insert;
  4. if(isset($_FILES['attachment_1'])&&!empty($_FILES['attachment_1']['name']))
  5. {
  6. $pathinfo = pathinfo($_FILES['attachment_1']['name']);
  7. $new_name =$pathinfo['filename'].'_'.$novie_id.'.'.$pathinfo['extension']; $base_directory= "attachments/";
  8. $target = $base_directory.''.$new_name; $url =$new_name; $uploadOk=1; $fileParts = pathinfo( $url );
  9. $extension = $fileParts['extension'];
  10. if($extension=="jpg" OR $extension=="jpeg" OR $extension=="JPG" OR $extension=="GIF" OR $extension=="gif" OR $extension=="PNG" OR $extension=="png" OR $extension=="doc" OR $extension=="docx" or $extension=="pdf" OR $extension=="xls" OR $extension=="xlsx" OR $extension=="ppt" OR $extension=="pptx" OR $extension=="txt" OR $extension=="pub" OR $extension=="wps" or $extension=="bmp" OR $extension=="BMP" OR $extension=="csv")
  11. {
  12. $uploadOk = 1;
  13. }
  14. else
  15. {
  16. $uploadOk = 0;
  17. header("Location:project_badfile.php");
  18. exit();
  19. }
  20. if(!move_uploaded_file($_FILES['attachment_1']['tmp_name'], $target))
  21. {
  22. header("Location: http://southareanetwork.nss.vzwnet.com/project_no_upload.php");
  23. exit();
  24. }
  25. else
  26. {
  27. $sql_10 = "insert into attachments (project_id, url) values ('$novie_id', '$url')";
  28. if(!$query_10=$mysqli->query($sql_10))
  29. {
  30. $err_10='your attachments info didn\'t get uploaded becasue:'
  31. . 'ERRNO: '
  32. .$mysqli->errno
  33. . 'ERROR: '
  34. .$mysqli->error
  35. . 'and the query itself looks like this: '
  36. .$sql_10
  37. .PHP_EOL;
  38. trigger_error($err_2, E_USER_NOTICE);
  39. }
  40. }
Basically, you're just uploading the file and, if the upload was successful, you insert the file name along with its URL and its corresponding project_id into the "attachments" table. Multi-Dimensional / Associative Arrays and the Scope Resolution Operator (::) With this particular contract, I was asked to come in and troubleshoot some code. Below is an example of some syntax I worked with that illustrates my familiarity with multi-dimensional /associative arrays. In the code below, you're seeing a SQL SELECT statement arriving as an array that is then broken up using a "for" loop. The purpose of what you're seeing below was to run through an array and look for "groups" of data based on their dates. Everything that constitutued a group was "pushed" into a sub array. Take a look: Line #31:$timeline = AccountTimelines::getAccountTimeline($accountid); - Here's an example of the double colon, or "Scope Resolution Operator Line #35-36: $event = $timeline[$i]; - This is saying to PHP, "Take the value of $i and use it as an array index into the $timeline array. Get the contents of that array position and assign it to the $event variable. Do this over and over again until the value of $i is equal to the number of elements in the $timeline array." Line #41: array_push($txnGroup, $event); - Here's an example of a subarray being pushed into the empty $txnGroup array
  1. public function accounttimeline($accountid = null)
  2.     {
  3.         if (isset($_REQUEST['preview']) && $_REQUEST['preview']) {
  4.             return;
  5.         }
  6.         if (isset($_REQUEST['searchfor'])) {
  7.             $return['json'] = Accounts::timelinesearch($_REQUEST['searchfor']);
  8.             if ($return['json']) {
  9.                 $return['success'] = 1;
  10.                 if (count($return['json'])>1) {
  11.                     $return['body'] = $this->load->view('/app/templates/accounttimeline/searchresults', $return, true);
  12.                 } else {
  13.                     $return['body'] = "There should be a loaded account now";
  14.                     $return['loadAccount'] = $return['json'][0]['clientcode']
  15.                                            . '-' . $return['json'][0]['practicecode']
  16.                                            . '-' . $return['json'][0]['practicepatientid'];
  17.                 }
  18.             } else {
  19.                 $return['success'] = 1;
  20.                 $return['body'] = "There are no results to display. Please refine your search.";
  21.             }
  22.             echo json_encode($return);
  23.             return;
  24.         }
  25.         $ud=setUserData();
  26.         $data = pf::getAppData('/app/accounttimeline');
  27.         $accountid = isset($_REQUEST['accountkey']) ?Accounts::getAccountFromNewAccountID($_REQUEST['accountkey']):(isset($_REQUEST['accountid'])?$_REQUEST['accountid']:$accountid);
  28.         if ($accountid !== null) {
  29.             $data['badge'] = Accounts::getBadge($accountid);
  30.             $timeline = AccountTimelines::getAccountTimeline($accountid);
  31.             $data['timeline'] = array();
  32.             $txnGroup = array();
  33.             for ($i=0; $i < count($timeline); $i++) {
  34.                 $event = $timeline[$i];
  35.                 $event['demo'] = ($data['badge']['practiceid'] == '63'?$accountid : false);
  36.                 if ($event['eventtype']=='transaction') {
  37.                     $thisDate = Date('mdy', strToTime($event['eventdate']));
  38.                     $nextDate = (isset($timeline[$i+1])&&$timeline[$i+1]['eventtype']=='transaction')?Date('mdy', strToTime($timeline[$i+1]['eventdate'])):null;
  39.                     array_push($txnGroup, $event);
  40.                     if ($thisDate != $nextDate) {
  41.                         //add to data
  42.                         if (count($txnGroup)!=1) {
  43.                             array_push($data['timeline'], array(
  44.                                 'eventdate'=>Date('m/d/Y', strToTime($event['eventdate'])),
  45.                                 'eventtype'=>'transactions',
  46.                                 'runningbal'=>$event['runningbal'],
  47.                                 'transactions'=>$txnGroup
  48.                             ));
  49.                         } else {
  50.                             array_push($data['timeline'], $event);
  51.                         }
  52.                         $txnGroup = array();
  53.                     }
  54.                 } else {
  55.                     if ($event['eventtype'] == 'statement') {
  56.                         $event['dir'] = "/p/" . (ENVIRONMENT === 'production' ? 'prod' : 'dev') . "/statements/$event[exportid]/";
  57.                         $event['file'] = "$event[accountid]-$event[content].pdf";
  58.                     }
  59.                     array_push($data['timeline'], $event);
  60.                 }
  61.             }
  62.             $data['timeline'] = array_reverse($data['timeline']);
  63.         }
  64.         $ci =& get_instance();
  65.         $ci->template->app2Load('app/templates/accounttimeline/body', $data);
  66.     }
GANT Calendar The GANT Calendar project was assigned to me in order to visually display what projects were being assigned and how their various due dates and projected timeframes overlapped. It looked like what you see to the right (feel free to click on the image to get a larger view). Because the DEV team had within its ranks both PHP developers and .NET developers, the database that had to be interacted with was a T-SQL database. Hence, all the queries had to be Stored Procedures and the database connection was a PDO configuration. I worked with my counterpart to put the whole thing together. She crafted the Stored Procedures and I assembled and displayed the data. The first two elements are the sliding carousels that give the user the opportunity to focus in on either a specific day or month. This was facilitated using the Owl Carousel" JQuery Plugin. The calendar itself is a large table. Each column represents a period of seven days, with each day being a cell. In my header, I use today's date as my starting point and then work my way both to the left and the right to "fill in" the weeks that will be displayed. For the sake of brevity, here's the primary SELECT as it was facilitated using a PDO configuration in order to connect with the T-SQL database and then execute the Stored Procedures on the server: $query = "EXECUTE stp_Select_REPORT_DevelopeProjects_Gantt :DataDisplay_Start, :DataDisplay_End"; $stpro = $mssql_pdo->prepare($query); $stpro->bindParam(':DataDisplay_Start', $week_one, PDO::PARAM_STR); $stpro->bindParam(':DataDisplay_End', $week_twelve, PDO::PARAM_STR); // call the stored procedure $stpro->execute(); $results = $stpro->fetchALL(PDO::FETCH_ASSOC); If you would like to see more of the code in detail, click on the paint bucket... Verizon Calendar The Verizon Calendar - at one point I was asked to basically deconstruct the google calendar and create an interface where engineers could document events that had compromised Verizon's coverage. The resulting app was something I was kind of proud of. There were places I incorporated a procedural approach within an OOP dynamic which may be poisonous in the minds of some, but it was the most direct way in which I could solve some of the "logic" that needed to be addressed as far as how things were displayed etc. I've got some code samples documented below, but be sure to click on the graphic to the right which will connect you to a working model. There were several challenges to overcome when given the inital "specs." The actual calendar "scaffolding" was basic enough, but then to generate specific Javascript code based on the states and regions that were displayed was a little cumbersome - especially given the fact that you had to set the visibility of the regions to "hidden" when working with the states dynamic and vice versa when the user started working with the regions. Some of the code was static, but here's the function that generated the Javascript for the states...
  1. function javascript_commands($content, $number)
  2. {
  3. $page_display=func_get_arg(0);
  4. $the_number=(func_get_arg(1)-1);
  5. //echo $the_number;
  6. $the_count=1;
  7. $java_count=0;
  8. $java_state="";
  9. $briefcase="";
  10. $current_state="";
  11. $the_state="";
  12. $briefcase.="var queue={};\n";
  13. if(isset($_GET['state'])&&!$_GET['state']=="")
  14. {
  15. $briefcase.="queue.";
  16. if($_GET['state']=="North Carolina")
  17. {
  18. $briefcase.="North_Carolina";
  19. }
  20. elseif($_GET['state']=="South Carolina")
  21. {
  22. $briefcase.="South_Carolina";
  23. }
  24. else
  25. {
  26. $briefcase.=$_GET['state'];
  27. }
  28. $briefcase.="=true;";
  29. }
  30. foreach($page_display as $page)
  31. {
  32. if($current_state<>$page['state'])
  33. {
  34. $briefcase.="function ";
  35. if(stripslashes($page['state'])=="North Carolina")
  36. {
  37. $briefcase.="North_Carolina";
  38. }
  39. elseif(stripslashes($page['state'])=="South Carolina")
  40. {
  41. $briefcase.="South_Carolina";
  42. }
  43. else
  44. {
  45. $briefcase.=stripslashes($page['state']);
  46. }
  47. $briefcase.="()\n{\n";
  48. $briefcase.="if(Object.size(the_queue)>0)\n{\n";
  49. $briefcase.="delete the_queue.CATN;\n";
  50. $briefcase.="delete the_queue.CATN;\n";
  51. $briefcase.="delete the_queue.FL;\n";
  52. $briefcase.="delete the_queue.CTX;\n";
  53. $briefcase.="delete the_queue.HGC;\n";
  54. $briefcase.="delete the_queue.GAAL;\n";
  55. $briefcase.="delete the_queue.SCTL;\n";
  56. $briefcase.="delete the_queue.AREA;\n";
  57. $briefcase.="delete the_queue.ALU;\n";
  58. $briefcase.="delete the_queue.DEVICE;\n";
  59. $briefcase.="delete the_queue.CATN_long;\n";
  60. $briefcase.="delete the_queue.FL_long;\n";
  61. $briefcase.="delete the_queue.CTX_long;\n";
  62. $briefcase.="delete the_queue.HGC_long;\n";
  63. $briefcase.="delete the_queue.GAAL_long;\n";
  64. $briefcase.="delete the_queue.SCTL_long;\n";
  65. $briefcase.="delete the_queue.AREA_long;\n";
  66. $briefcase.="delete the_queue.ALU_long;\n";
  67. $briefcase.="delete the_queue.DEVICE_long;\n";
  68. $briefcase.="}\n";
  69. $briefcase.="$(\".CATN,.FL,.CTX,.HGC,.GAAL,.SCTL,.AREA,.ALU,.DEVICE, .CATN_long,.FL_long,.CTX_long,.HGC_long,.GAAL_long,.SCTL_long,.AREA_long,.ALU_long,.DEVICE_long\").show();\n";
  70. $briefcase.="queue.";
  71. if(stripslashes($page['state'])=="North Carolina")
  72. {
  73. $briefcase.="North_Carolina";
  74. }
  75. elseif(stripslashes($page['state'])=="South Carolina")
  76. {
  77. $briefcase.="South_Carolina";
  78. }
  79. else
  80. {
  81. $briefcase.=stripslashes($page['state']);
  82. }
  83. $briefcase.="=true;\n";
  84. //right here you're doing a little test to ensure that you've got more than one state. Otherwise, the Javascript breaks
  85. foreach($page_display as $display)
  86. {
  87. if($java_state<>$page['state'])
  88. {
  89. $java_count=$java_count+1;
  90. }
  91. }
  92. //echo $java_count;
  93. //java_count represents the number of states you've got on this month. You'll compose only a portion of the Javascript command below if you only have one state. Otherwise, you're going to get an error
  94. if($java_count>1)
  95. {
  96. $briefcase.="$(\"";
  97. foreach($page_display as $display)
  98. {
  99. if($the_state=="")
  100. {
  101. $the_state==$page['state'];
  102. }
  103. if($the_state<>$current_state)
  104. {
  105. $briefcase.=".";
  106. if(stripslashes($display['state'])=="North Carolina")
  107. {
  108. $briefcase.="North_Carolina";
  109. }
  110. elseif(stripslashes($display['state'])=="South Carolina")
  111. {
  112. $briefcase.="South_Carolina";
  113. }
  114. else
  115. {
  116. $briefcase.=stripslashes($display['state']);
  117. }
  118. if($the_count<$the_number)
  119. {
  120. $briefcase.=",";
  121. }
  122. else
  123. {
  124. $briefcase.="\").hide();";
  125. }
  126. $the_count=$the_count+1;
  127. }
  128. $the_state=$display['state'];
  129. }
  130. }
  131. $briefcase.="\n\n";
  132. $briefcase.="for( var state in queue)";
  133. $briefcase.="\n{\n$(\".\" + state).show();\n}\n";
  134. $briefcase.="return true;\n";
  135. $briefcase.="}\n";
  136. }
  137. $the_count=$count=1;
  138. $current_state=$page['state'];
  139. }
  140. return $briefcase;
  141. }
One of the bigger "brain-benders" for me was to figure out a way to display all of the events correctly as the user scanned any one week from left to right. I had to figure out which day had the greatest concentration of activity and then configure the rest of the week according to a "staircase" look. It makes more sense when you see it. But to get to that point, I wound up creating a separate table for each week, or each "row" of the calendar. Here's what the third week - or row - would look like: First, make sure you've got data:
  1. if($row_number==3 AND $table_row_three>0)
  2. {
  3. $current_event_2="";
  4. for($d=1; $d<=$table_row_three; $d++)
  5. {
  6. ?>
  7. <tr style="height:16px; width:auto;">
  8. <td>
  9. <?php
  10. $korbin="SELECT * FROM `calendar_sequence_third` WHERE end_date>= '$the_date' AND date<= '$the_date' and sequence='$d'";
  11. //echo $korbin;
  12. $korbin_query=mysqli_query($mysqli, $korbin);
  13. $korbin_count=mysqli_num_rows($korbin_query);
  14. if($korbin_count>0)
  15. {
  16. $korbin_row=mysqli_fetch_assoc($korbin_query);
  17. if($current_event_2<>$korbin_row['event_id'])
  18. {
  19. //in order to display the proper start date for events that span multiple days, you've got to find the first day of that sequence
  20. $kathy="select date from calendar where event_id='$korbin_row[event_id]' ORDER by date ASC LIMIT 1";
  21. $kathy_query=mysqli_query($mysqli, $kathy);
  22. $kathy_row=mysqli_fetch_assoc($kathy_query);
  23. $start_date_3=$kathy_row['date'];
  24. include('row_three_script_long.php');
  25. $current_event_2=$korbin_row['event_id'];
  26. }
  27. }
  28. $kevin="SELECT * FROM `calendar_sequence_third` WHERE date='$the_date' and end_date='0000-00-00' and sequence='$d'";
  29. //echo $kevin;
  30. $kevin_query=mysqli_query($mysqli, $kevin);
  31. $kevin_count=mysqli_num_rows($kevin_query);
  32. if($kevin_count>0)
  33. {
  34. //echo $kevin;
  35. $kevin_row=mysqli_fetch_assoc($kevin_query);
  36. include('row_three_script.php');
  37. }
  38. if($kevin_count==0 AND $korbin_count==0)
  39. {
  40. echo " ";
  41. }

Once that's established, the next thing is to set up the formatting and the overall aesthetics and this is how that looks. Again, feel free to click on the "paint bucket" to see an easier-to-read version of the code.
  1. <?php
  2. $briefcase_5="";
  3. $briefcase_5.="<div class=\"";
  4. //make sure that this isn't repeating an event that's already been listed
  5. if($korbin_row['date']<=$the_date)
  6. {
  7. if($korbin_row['region']=="ALU")
  8. {
  9. $briefcase_5.="ALU_long";
  10. }
  11. if($korbin_row['region']=="AREA")
  12. {
  13. $briefcase_5.="AREA_long";
  14. }
  15. if($korbin_row['region']=="CATN")
  16. {
  17. $briefcase_5.="CATN_long";
  18. }
  19. if($korbin_row['region']=="CTX")
  20. {
  21. $briefcase_5.="CTX_long";
  22. }
  23. if($korbin_row['region']=="DEVICE")
  24. {
  25. $briefcase_5.="DEVICE_long";
  26. }
  27. if($korbin_row['region']=="ERC")
  28. {
  29. $briefcase_5.="ERC_long";
  30. }
  31. if($korbin_row['region']=="FL")
  32. {
  33. $briefcase_5.="FL_long";
  34. }
  35. if($korbin_row['region']=="GAAL")
  36. {
  37. $briefcase_5.="GAAL_long";
  38. }
  39. if($korbin_row['region']=="HGC")
  40. {
  41. $briefcase_5.="HGC_long";
  42. }
  43. if($korbin_row['region']=="SCTL")
  44. {
  45. $briefcase_5.="SCTL_long";
  46. }
  47. }
  48. $briefcase_5.="\">";
  49. $briefcase_5 .="<div class=\"";
  50. if(stripslashes($korbin_row['state'])=="North Carolina")
  51. {
  52. $briefcase_5.="North_Carolina";
  53. }
  54. elseif(stripslashes($korbin_row['state'])=="South Carolina")
  55. {
  56. $briefcase_5.="South_Carolina";
  57. }
  58. else
  59. {
  60. $briefcase_5.=stripslashes($korbin_row['state']);
  61. }
  62. $briefcase_5.="\">";
  63. //$briefcase_5.=$korbin_row['event_id'].' - ' .$korbin_row['date'];
  64. $briefcase_5.=" <a href=\"#\" onclick=\"javascript:void window.open('event_description.php?id=";
  65. $briefcase_5.=$korbin_row['id'];
  66. $briefcase_5.="','1435862141298','width=610,height=560,toolbar=0,menubar=0,location=0,status=0,scrollbars=0,resizable=1,left=0,top=0');return false;\" class=\"";
  67. //here you've got to determine if this date is the initial date of a multi day event, or if it's part of a succession. If so, you don't want to display the text. The other thing you need to look at
  68. //is the day. If it's Sunday, you need to display the text and if it's the first day of the month, you need to display the text
  69. $day_of_week=date("l", strtotime($the_date));
  70. //$date_of_month=date("d", strtotime($korbin_row['date']));
  71. if($day_of_week=="Sunday" OR date("d", strtotime($the_date))==01 OR $korbin_row['date']==$the_date)
  72. {
  73. if($korbin_row['region']=="ALU")
  74. {
  75. $briefcase_5.="tooltip_date_ALU_long";
  76. $text_style="ALU";
  77. }
  78. if($korbin_row['region']=="AREA")
  79. {
  80. $briefcase_5.="tooltip_date_AREA_long";
  81. $text_style="AREA";
  82. }
  83. if($korbin_row['region']=="CATN")
  84. {
  85. $briefcase_5.="tooltip_date_CATN_long";
  86. $text_style="CATN";
  87. }
  88. if($korbin_row['region']=="CTX")
  89. {
  90. $briefcase_5.="tooltip_date_CTX_long";
  91. $text_style="CTX";
  92. }
  93. if($korbin_row['region']=="DEVICE")
  94. {
  95. $briefcase_5.="tooltip_date_DEVICE_long";
  96. $text_style="DEVICE";
  97. }
  98. if($korbin_row['region']=="ERC")
  99. {
  100. $briefcase_5.="tooltip_date_ERC_long";
  101. $text_style="ERC";
  102. }
  103. if($korbin_row['region']=="FL")
  104. {
  105. $briefcase_5.="tooltip_date_FL_long";
  106. $text_style="FL";
  107. }
  108. if($korbin_row['region']=="GAAL")
  109. {
  110. $briefcase_5.="tooltip_date_GAAL_long";
  111. $text_style="GAAL";
  112. }
  113. if($korbin_row['region']=="HGC")
  114. {
  115. $briefcase_5.="tooltip_date_HGC_long";
  116. $text_style="HGC";
  117. }
  118. if($korbin_row['region']=="SCTL")
  119. {
  120. $briefcase_5.="tooltip_date_SCTL_long";
  121. $text_style="SCTL";
  122. }
  123. }
  124. else
  125. {
  126. if($korbin_row['region']=="ALU")
  127. {
  128. $briefcase_5.="tooltip_date_ALU";
  129. $text_style="area";
  130. }
  131. if($korbin_row['region']=="AREA")
  132. {
  133. $briefcase_5.="tooltip_date_AREA";
  134. $text_style="AREA";
  135. }
  136. if($korbin_row['region']=="CATN")
  137. {
  138. $briefcase_5.="tooltip_date_CATN";
  139. $text_style="CATN";
  140. }
  141. if($korbin_row['region']=="CTX")
  142. {
  143. $briefcase_5.="tooltip_date_CTX";
  144. $text_style="CTX";
  145. }
  146. if($korbin_row['region']=="DEVICE")
  147. {
  148. $briefcase_5.="tooltip_date_DEVICE";
  149. $text_style="DEVICE";
  150. }
  151. if($korbin_row['region']=="ERC")
  152. {
  153. $briefcase_5.="tooltip_date_ERC";
  154. $text_style="ERC";
  155. }
  156. if($korbin_row['region']=="FL")
  157. {
  158. $briefcase_5.="tooltip_date_FL";
  159. $text_style="FL";
  160. }
  161. if($korbin_row['region']=="GAAL")
  162. {
  163. $briefcase_5.="tooltip_date_GAAL";
  164. $text_style="GAAL";
  165. }
  166. if($korbin_row['region']=="HGC")
  167. {
  168. $briefcase_5.="tooltip_date_HGC";
  169. $text_style="HGC";
  170. }
  171. if($korbin_row['region']=="SCTL")
  172. {
  173. $briefcase_5.="tooltip_date_SCTL";
  174. $text_style="SCTL";
  175. }
  176. }
  177. //right here you're going to put your search stylings...
  178. if(isset($_GET['search'])&&$_GET['search']==$korbin_row['event_id'])
  179. {
  180. $briefcase_5.="\" style=\"background-color:#ecfa05; color:#000000;\">";
  181. }
  182. else
  183. {
  184. $briefcase_5.="\">";
  185. }
  186. $position = 10;
  187. $message = $korbin_row['short_name'];
  188. $post = substr($message,$position,1);
  189. if($post !=" ") {
  190. $length = strlen( $message );
  191. while($post !=" " && $position < $length){
  192. $b =1;
  193. $position = $position+$b;
  194. $post = substr($message,$position,1);
  195. }
  196. }
  197. $post = substr($message,0,$position);
  198. if(strlen($post)>10)
  199. {
  200. $briefcase_5.=stripslashes($post).'...';
  201. }
  202. else
  203. {
  204. $briefcase_5.=stripslashes($post);
  205. }
  206. //$briefcase_5.=$korbin_row['id'];
  207. $briefcase_5.="<span><img class=\"callout_area\" src=\"images/callout.gif\" alt=\"callout\" /><b>";
  208. $briefcase_5.=date("n/j/Y", strtotime($start_date_3)).' - '.date("n/j/Y", strtotime($korbin_row['end_date']));
  209. $briefcase_5.="</b><div style=\"float:right;\"><div class=\"";
  210. $briefcase_5.=$text_style;
  211. $briefcase_5.="\">";
  212. $briefcase_5.=stripslashes($korbin_row['state']).' | '.stripslashes($korbin_row['region']);
  213. $briefcase_5.="</div></div><br><br><u>";
  214. $briefcase_5.=stripslashes($korbin_row['short_name']);
  215. $briefcase_5.="</u><br>";
  216. $position_1 = 100;
  217. $message_1 = $korbin_row['description'];
  218. $post_1 = substr($message_1,$position_1,1);
  219. if($post_1 !=" ") {
  220. $length_1 = strlen( $message_1 );
  221. while($post_1 !=" " && $position_1 < $length_1){
  222. $a =1;
  223. $position_1 = $position_1+$a;
  224. $post_1 = substr($message_1,$position_1,1);
  225. }
  226. }
  227. $post_1 = substr($message_1,0,$position_1);
  228. if(strlen($post_1)>10)
  229. {
  230. $briefcase_5.=stripslashes($post_1).'...';
  231. }
  232. else
  233. {
  234. $briefcase_5.=stripslashes($post_1);
  235. }
  236. $briefcase_5.="</span>
  237. </a><br></div>";
  238. $briefcase_5.="</div>";
  239. echo $briefcase_5;
  240. ?>
Responsive Website Click here to view the Bootstrap version of the Verizon website I built for their South Regional Territory.
 CSS
The big priority these days with CSS is to ensure that your site is responsive to the type of devices that are being potentially used by your users. If they're on their desktop with a large monitor, that will be one kind of "look." On the other hand, if they're on their phone, the CSS will need to accommodate that scenario and display graphics and navigation that's appropriate to that size. Thornhill Landscaping Here's an example of what I did for "Thornhill Landscaping:"
  1. body {
  2. font-family: Helvetica, Microsoft Sans Serif;
  3. font-size: 12px;
  4. color: #000000;
  5. vertical-align: top;
  6. padding: 0px;
  7. height: 100%;
  8. width:768px;
  9. margin:auto;
  10. background-color:#101214;
  11. }
  12. #main_menu {
  13. width:768px;
  14. height:1024px;
  15. margin:auto;
  16. text-align:center;
  17. background-image:url(images/menu_768.png);
  18. background-repeat:no-repeat;
  19. }
  20. #main_menu_about {
  21. position:absolute;
  22. margin-left:45px;
  23. margin-top:200px;
  24. width:683px;
  25. height:70px;
  26. background-image:url(images/spacer.gif);
  27. background-repeat:no-repeat;
  28. z-index:100px;
  29. }
  30. #main_menu_visitors {
  31. position:absolute;
  32. margin-left:45px;
  33. margin-top:300px;
  34. width:683px;
  35. height:70px;
  36. z-index:100px;
  37. }
  38. #main_menu_ministries {
  39. position:absolute;
  40. margin-left:45px;
  41. margin-top:410px;
  42. width:683px;
  43. height:70px;
  44. z-index:100px;
  45. }
  46. #main_menu_children {
  47. position:absolute;
  48. margin-left:45px;
  49. margin-top:510px;
  50. width:683px;
  51. height:70px;
  52. z-index:100px;
  53. }
  54. #main_menu_calendar {
  55. position:absolute;
  56. margin-left:45px;
  57. margin-top:610px;
  58. width:683px;
  59. height:70px;
  60. z-index:100px;
  61. }
  62. #main_menu_contact {
  63. position:absolute;
  64. margin-left:45px;
  65. margin-top:709px;
  66. width:683px;
  67. height:70px;
  68. z-index:100px;
  69. }
  70. #main_menu_email {
  71. position:absolute;
  72. margin-left:335px;
  73. margin-top:870px;
  74. width:253px;
  75. height:28px;
  76. z-index:100px;
  77. }
  78. #main_menu_signature {
  79. position:absolute;
  80. margin-left:295px;
  81. margin-top:945px;
  82. width:168px;
  83. height:65px;
  84. z-index:100px;
  85. }
  86. #main_social_facebook {
  87. position:absolute;
  88. margin-left:628px;
  89. margin-top:55px;
  90. width:16px;
  91. height:32px;
  92. z-index:100px;
  93. }
  94. #main_social_twitter {
  95. position:absolute;
  96. margin-left:660px;
  97. margin-top:55px;
  98. width:20px;
  99. height:32px;
  100. z-index:100px;
  101. }
  102. #main_social_email {
  103. position:absolute;
  104. margin-left:690px;
  105. margin-top:55px;
  106. width:35px;
  107. height:32px;
  108. z-index:100px;
  109. }
  110. #header_divider {
  111. width:100%;
  112. margin:auto;
  113. height:10px;
  114. background-color:#28368f;
  115. }
  116. #footer {
  117. width:480px;
  118. margin:auto;
  119. font-family: Helvetica, Microsoft Sans Serif;
  120. font-size: 10px;
  121. color: #ffffff;
  122. text-align:center;
  123. padding-top:5px;
  124. }
  125. #title {
  126. height:38px;
  127. }
  128. #contact_images {
  129. padding-top:7px;
  130. width:320px;
  131. margin:auto;
  132. }
Media Queries Here's the remainder of the stylesheet that accommodates the landscape and portrait views of a mobile phone...
  1. @media screen and (max-width:480px)
  2. {
  3. body {
  4. font-family: Helvetica, Microsoft Sans Serif;
  5. font-size: 12px;
  6. color: #000000;
  7. vertical-align: top;
  8. padding: 0px;
  9. height: 100%;
  10. width:320px;
  11. margin:auto;
  12. background-color:#101214;
  13. }
  14. #main_menu {
  15. width:768px;
  16. height:1024px;
  17. margin:auto;
  18. text-align:center;
  19. background-image:url(images/menu_320.png);
  20. background-repeat:no-repeat;
  21. }
  22. etc...
  23. }
  24. @media screen and (max-width:320px)
  25. {
  26. body {
  27. font-family: Helvetica, Microsoft Sans Serif;
  28. font-size: 12px;
  29. color: #000000;
  30. vertical-align: top;
  31. padding: 0px;
  32. height: 100%;
  33. width:320px;
  34. margin:auto;
  35. background-color:#101214;
  36. }
  37. #main_menu {
  38. width:768px;
  39. height:1024px;
  40. margin:auto;
  41. text-align:center;
  42. background-image:url(images/menu_320.png);
  43. background-repeat:no-repeat;
  44. }
  45. #main_menu_about {
  46. position:absolute;
  47. margin-left:15px;
  48. margin-top:123px;
  49. width:282px;
  50. height:27px;
  51. z-index:100px;
  52. }
This is a portion of the stylesheet used with the brucegust.com page. Here you see an example of what is done when your magnificent, full screen dynamic is suddenly being accessed by a lap top and threatens to cram your gorgeous vista into a tiny little portal. By using @media screen and (min-width: 1000px), we keep the title graphic from looking like the designer made a tragic mistake.
  1. body {
  2. font-family: Helvetica, Microsoft Sans Serif;
  3. font-size: 14px;
  4. color: #000000;
  5. vertical-align: top;
  6. padding: 0px;
  7. height: 100%;
  8. width: 100%;
  9. margin: 0;
  10. background-color:#000000;
  11. }
  12. #top_graphics {
  13. height:227px;
  14. }
  15. #qr_container {
  16. width:320px;
  17. position:relative;
  18. margin-left:-5px;
  19. }
  20. table.qr_code {
  21. width:329px;
  22. }
  23. #phone_background {
  24. width:332px;
  25. height:500px;
  26. position:relative;
  27. background-image:url(images/phone_background.png);
  28. background-repeat:no-repeat;
  29. margin:auto;
  30. }
  31. @media screen and (min-width: 1000px)
  32. {
  33. #left-container {
  34. z-index:3;
  35. position:absolute;top:0;
  36. height:227px;
  37. width:295px;
  38. float:left;
  39. background-image:url(images/1000_header_01.gif);
  40. background-repeat:no-repeat;
  41. }
  42. #brucegust {
  43. position:absolute;top:0;
  44. height:227px;
  45. width:295px;
  46. float:left;
  47. }
  48. }
  49. #top_filler {
  50. height:227px;
  51. background-image:url(images/header_02.jpg);
  52. background-repeat: repeat-x;
  53. }
Symbion Healthcare Working with the SQL Management Studio, here are some of the queries I wrote:
  1. USE
  2. [BIProd]
  3. GO
  4. /****** Object: StoredProcedure [dbo].[cer_CapXTempSave] Script Date: 5/29/2014 3:26:06 PM ******/
  5. SET
  6. ANSI_NULLS
  7. ON
  8. GO
  9. SET
  10. QUOTED_IDENTIFIER
  11. ON
  12. GO
  13. ALTER PROCEDURE [dbo].[cer_CapXTempSave]
  14. --Parms for stored procedure
  15. @capxtempid as int,
  16. @cermodelid as int,
  17. @capxid as int,
  18. @spmodelid as int,
  19. @assettypeid as int,
  20. @totalcost as int ,
  21. @description as varchar(150),
  22. @shortname as varchar(150),
  23. @allocatedamount as int,
  24. @userid as int
  25. AS
  26. BEGIN
  27. declare @key as int
  28. declare @ErrorMessage as varchar(300)
  29. declare @ErrorNo as int
  30. set @ErrorMessage = ''
  31. set @ErrorNo = 0
  32. declare @cer_itemcost int
  33. select @cer_itemcost = ISNULL(itemcost,0) from cer_Detail where cermodelid= @cermodelid
  34. declare @cer_itemshipping int
  35. select @cer_itemshipping = ISNULL(shipping,0) from cer_Detail where cermodelid= @cermodelid
  36. declare @cer_iteminstallation int
  37. select @cer_iteminstallation = ISNULL(installation,0) from cer_Detail where cermodelid = @cermodelid
  38. declare @cer_totalcost int
  39. select @cer_totalcost = @cer_itemcost + @cer_itemshipping + @cer_iteminstallation
  40. declare @capx_allocatedamount int
  41. if @allocatedamount >@cer_totalcost
  42. BEGIN
  43. select @capx_allocatedamount= @cer_totalcost
  44. END
  45. ELSE
  46. BEGIN
  47. select @capx_allocatedamount = @allocatedamount
  48. END
  49. insert into cer_CapX(cermodelid, capxid, spmodelid, assettypeid, totalcost, description, shortname,allocatedamount,updateuserid, updatedate )
  50. values(@cermodelid, @capxid, @spmodelid, @assettypeid, @totalcost, @description, @shortname,@capx_allocatedamount, @userid, getdate ())
  51. set @ErrorNo = @@Error
  52. if @ErrorNo <> 0
  53. BEGIN
  54. set @key = 0
  55. set @ErrorMessage = 'Failed to insert the record (' + cast(@ErrorNo as varchar) + '}'
  56. END
  57. select @key as ID, @ErrorMessage as
  58. ErrorMessage
  59. END

  1. USE [BIProd]
  2. GO
  3. /****** Object: StoredProcedure [dbo].[cer_ActiveInfo] Script Date: 5/29/2014 3:26:51 PM ******/
  4. SET ANSI_NULLS ON
  5. GO
  6. SET QUOTED_IDENTIFIER ON
  7. GO
  8. ALTER PROCEDURE [dbo].[cer_ActiveInfo]
  9. @workqueuestageid as int
  10. AS
  11. SET NOCOUNT ON;
  12. declare @beginning_cermodelid int
  13. select @beginning_cermodelid = (select TOP 1 ws.cermodelid from cer_WorkqueueStage ws where ws.cerworkqueuestageid=@workqueuestageid)
  14. declare @notes_text varchar(1000)
  15. select @notes_text = (select ws.notes from cer_WorkqueueStage ws where ws.cerworkqueuestageid = @workqueuestageid)
  16. declare @the_workqueueuserid int
  17. IF @notes_text IS NULL
  18. BEGIN
  19. select @the_workqueueuserid =(select TOP 1 ws.workqueueuserid from cer_WorkqueueStage ws where ws.cermodelid=@beginning_cermodelid and ws.notes IS NOT NULL
  20. and ws.cerworkqueuestageid <@workqueuestageid order by ws.updatedate DESC)
  21. END
  22. ELSE
  23. BEGIN
  24. select @the_workqueueuserid =(select ws.workqueueuserid from cer_WorkqueueStage ws where ws.cermodelid=@beginning_cermodelid and ws.notes IS NOT NULL
  25. and ws.cerworkqueuestageid =(@workqueuestageid+1))
  26. END
  27. If @the_workqueueuserid IS NULL
  28. Begin
  29. select @the_workqueueuserid =(select TOP 1 ws.workqueueuserid from cer_WorkqueueStage ws where ws.cermodelid=@beginning_cermodelid and ws.cerworkqueuestageid =(@workqueuestageid +1))
  30. End
  31. declare @the_username varchar(150)
  32. select @the_username =(select u.displayname from ptl_User u where u.userid =@the_workqueueuserid)
  33. select TOP 1 ws.cerworkqueuestageid, ws.notes, ws.workqueueuserid,u.displayname, @the_username as the_username
  34. from cer_WorkqueueStage ws INNER JOIN ptl_User u on u.userid=ws.workqueueuserid
  35. where ws.cerworkqueuestageid =@workqueuestageid
  36. AND ws.notes IS NOT NULL order by ws.updatedate DESC
  37. declare @the_entityid int
  38. select @the_entityid = (select wr.workqueueentityid FROM cer_WorkqueueUser wr WHERE wr.userid=@UserID AND (wr.workqueueroleid=12 OR wr.workqueueroleid=13 OR wr.workqueueroleid=14 ))
  39. SELECT t2.assetshortname, t2.entityshortname, t2.abbrevname, t2.statusshortname, t2.cermodelid, t2.assettypeid, t2.statusid, t2.createuserid, t2.entityid, t2.createdate, t2.workqueueuserid, t2.workqueuestatusid, t2.displayname, t2.description, t2.financingflag
  40. FROM (select DISTINCT ws.cermodelid from cer_WorkqueueStage ws where ws.workqueueentityid = @the_entityid) t1
  41. INNER JOIN
  42. (SELECT at.shortname as assetshortname, en.shortname as entityshortname, en.abbrevname, st.shortname as statusshortname, cer.cermodelid, cer.assettypeid,
  43. cer.statusid, cer.createuserid, cer.entityid, cer.createdate, wq.workqueueuserid, wq.statusid as workqueuestatusid,u.displayname,det.financingflag,
  44. description = case when Len( cer.description ) >= 25 then Left( cer.description, 25 - patindex('%[^0-9a-z]%', reverse(Left( cer.description, 25)))) + '...' else cer.description end
  45. FROM
  46. cer_Model cer INNER JOIN fin_AssetType at on at.assettypeid = cer. assettypeid
  47. INNER JOIN ptl_Entity en on en.entityid = cer.entityid INNER JOIN cer_Workqueue wq on cer.cermodelid= wq.cermodelid
  48. INNER JOIN ptl_Status st on st.statusid = wq.statusid
  49. INNER JOIN cer_Detail det on det.cermodelid=cer.cermodelid
  50. LEFT OUTER JOIN ptl_User u on wq.workqueueuserid=u.userid
  51. WHERE det.financingflag=1) t2
  52. ON t1.cermodelid = t2.cermodelid
Basic Functionality This is coming from the project I referenced earlier where I was using a hybrid of PHP, T-SQL and Javascript. Here's some of the basic Javascript I worked with (for more verbose examples of Javascript, please refer to the "Verizon Calendar.": <td width='$column4' align='right' valign='middle' class='overline'> <span class='clickableLite' onmouseover=\"this.style.textDecoration='underline';\" onmouseout=\"this.style.textDecoration='none';\" this "onmouseover" code is a clever usage of Javascript that gives the user the look and feel of a link, when in fact, it's just a cue to execute a Javascript command. Now you've got your "onclick" command... onclick='loadlookup(dataform,\"specialty_lookup\",entityid,specialtyid,specialty,\"specialty\")'> Here's the actual Javascript function... function loadlookup(form, page, entityid, id, name, label) { lookuplabel.innerHTML = 'Click name to add: '+label; lookupentity = form.entityid.value; switch (label) { case "physician" : groupid = form.specialtyid.value; break; case "payer" : groupid = form.finclassid.value; break; default : groupid = ""; break; } if (form.showsql.value == 1) showsql = "&showsql=1"; else showsql = ""; eval ('window.lookup.location=\''+page+'.php?entityid='+lookupentity+'&id='+id+'&name='+name+'&group='+groupid+showsql+'\';'); } iPhone As part of the Showdown, I built an iPhone app. This was prior to a full fledged mobile version of the site so I used the iPhone app to display crucial portions of the online community and also built an app tha tyou actually paid for which gave you access to certain portions of the website that were otherwise off limits. It worked very well and well received at the time! // // showdown_plus.m // Intro // // Created by Bruce Gust on 1/1/13. // Copyright (c) 2013 Bruce Gust. All rights reserved. // #import "showdown_plus.h" @interface showdown_plus () @end @implementation showdown_plus - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // Custom initialization } return self; } - (IBAction)home_plus_button:(id)sender { [self dismissViewControllerAnimated:YES completion:nil]; } - (IBAction)plus_forward_button:(id)sender { [_showdown_plus_webview goForward]; } - (IBAction)showdown_plus_button:(id)sender { NSString *fullURL = @"http://www.countryshowdown.com/mobile/showdown_plus.php?paid=1"; NSURL *url = [NSURL URLWithString:fullURL]; NSURLRequest *requestObj = [NSURLRequest requestWithURL:url]; [_showdown_plus_webview loadRequest:requestObj]; } - (void)viewDidLoad { [self showdown_plus_button :self]; [super viewDidLoad]; // Do any additional setup after loading the view. } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (IBAction)showdown_plus_back_button:(id)sender { [_showdown_plus_webview goBack]; } @end The Starting Line Flash / ActionScript was one of my first languages that I dove into. If you head out to http://www.brucegust.com/StartingLine, you'll see some of my Flash ability in action. The pages have a bunch of animation going on. This chunk of code is a series of "if" statements that determine how things flow based on the user's selection. if (Downloads eq "Yes") { gotoAndPlay("Downloads", 20); } else if (Saying eq "Yes") { gotoAndPlay("Saying I", 20); } else if (Order eq "Yes") { gotoAndPlay("How to Order", 20); } else if (About eq "Yes") { gotoAndPlay("About the Author", 20); } else if (Home eq "Yes") { gotoAndPlay("Transition", 1); } else if (Back eq "Yes") { gotoAndPlay("Overview II", 20); } else { gotoAndPlay("Transition", 1); } Another piece of code that you can see in action on the Texaco Country Showdown on the rotating carousel is something saves a great deal of space on the timeline. Rather than a multitude of frames being eaten up while one slide is "paused" before a motion tween that segues into the next slide, this makes the slide in question "wait" according to a perscribed number of seconds before it moves on. var myInterval; function wait(howLong) { clearInterval(myInterval); stop(); myInterval = setInterval(function () { play(); }, howLong); } counter = 1; Finally, this is a button that I enjoyed making. Again, it was for the Showdown site. This is when they were sponsored by Colgate when mobile devices were not the priority that they are today. This is the script that goes along with one of the volume control buttons that turns when you hove over it and then connects the user to a specific link when they click on it. Click here to see it in action. onClipEvent(load){ //is the cursor over the movie clip previouslyOver=false; } onClipEvent(enterFrame){ currentlyOver=this.hitTest(_root._xmouse,_root._ymouse,true); //if there is a change, go to another frame if(!previouslyOver and currentlyOver){ previouslyOver=true; this.gotoAndPlay("on"); } else if (previouslyOver and !currentlyOver){ previouslyOver=false; this.gotoAndPlay("off"); } } on (release) { getURL("Search.php"); } Here's a list of some of the Flash-based pages I built: