SitePoint Sponsor

User Tag List

Results 1 to 23 of 23
  1. #1
    SitePoint Member
    Join Date
    Jul 2010
    Posts
    19
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Auto div refresh and easy user changability

    Hi Guys,

    1st post .

    But im stuck, i need to make a website that will be used as a traffic light system. So i will have a page with loads of divs starting red, that will change to green when clicked once, and back to red if clicked again, so on, so on. These changes will need to be viewable live on another computer, so changes need to save and will also need to automatically refresh without distrubing the rest of the page.

    Many thanks,

    Stephen

  2. #2
    I meant that to happen silver trophybronze trophy Raffles's Avatar
    Join Date
    Sep 2005
    Location
    Tanzania
    Posts
    4,662
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    So... if I'm clicking these DIVs and you're looking at the same webpage at exactly the same time on a different computer, the DIVs need to change on your computer as I'm clicking them?

    A pretty tall order. And pretty weird too. What may I ask is the purpose of this?

  3. #3
    SitePoint Member
    Join Date
    Jul 2010
    Posts
    19
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Yes, i was looking into where to start for this and came across a few examples using ajax periodic refresh.

    Doesn't need to be DIVs, just boxes that toggle between red and green.

    This is basically for a register system for pupils, so a tutor will click the students names to change it from red to green if they are in. Somebody in head office will then be able to see who is not in. This is basically for a institution teaching expelled pupils and so many come in late and at various times.

  4. #4
    I meant that to happen silver trophybronze trophy Raffles's Avatar
    Join Date
    Sep 2005
    Location
    Tanzania
    Posts
    4,662
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    You need to store this information on the server, in a database. When you load the page, you pull the information from the database. Then you can keep refreshing the page, say, every 30 seconds, pulling the new record set from the database.

    You can submit the information to the database via Ajax or via a normal HTML form, but whatever you do, you have to store the register in a database of some kind.

  5. #5
    SitePoint Member
    Join Date
    Jul 2010
    Posts
    19
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Okay, so any idea where to start?

    All i need is a little helping hand to get started then i will be on my way, hopefully, i am still a noob when it comes to AJAX/DBs.

    Thanks for your help so far.

  6. #6
    SitePoint Member
    Join Date
    Jul 2010
    Posts
    19
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ok im getting somewhere, i have some php code which displays red or green depending if the database value is 1 or 0.

    Now how can i make it so clicking on these will change there value in the database?

  7. #7
    I meant that to happen silver trophybronze trophy Raffles's Avatar
    Join Date
    Sep 2005
    Location
    Tanzania
    Posts
    4,662
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    You need to decide what you want. Are you OK with each click refreshing the page? If so, it's a simple case of using a normal HTML form, and converting your coloured DIVs to form controls of some kind - BUTTON perhaps. This requires no javascript at all.

    If for some reason you don't want the page to refresh (this is not a bad thing at all), then you need to use JavaScript and XMLHttpRequests.

    In either case, you will need a very simple PHP script that accepts the input, processes it and stores the value in the database. This means you'll need to create a database table for the values. Most web servers offer MySQL, which is what I know a bit about, but you need to find out what your server has.

  8. #8
    SitePoint Member
    Join Date
    Jul 2010
    Posts
    19
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I want to use XMLHttpRequests to refresh the data every few seconds.

    Server has got mysql.

    I'm just not sure what php code i need to start.

  9. #9
    I meant that to happen silver trophybronze trophy Raffles's Avatar
    Join Date
    Sep 2005
    Location
    Tanzania
    Posts
    4,662
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Let's say you have a MySQL table with the columns "id" "name" and "present", where "id" is a unique identifier, "name" is the student's name and "present" is 1 or 0.

    You output this data with a simple PHP loop when the page is first loaded, and every 30 seconds:

    PHP Code:
    $res mysqli_query($link'SELECT * FROM register');
    echo 
    "<ul>\n";
    while (
    $row mysqli_fetch_array($res)) {
      echo 
    '<li id="student_' $row['id'] . '"';
      if (
    $row['present'] === 1) echo ' class="present"';
      echo 
    '>' $row['name'] . "</li>\n";

    In the CSS you can style the list items red by default, and style .present green.

    Now, let's suppose someone clicks one of your list items. You catch the click and submit your XMLHttpRequest by POST, passing the id. It doesn't matter whether the page currently shows the student as present or not, you're just toggling between present and absent, and the database is what controls this. Your PHP script processes it:

    PHP Code:
    $id array_pop(explode('_'$_POST['id']));
    if (
    is_numeric($id)) { // check it's a number
      
    $res mysqli_query($link"UPDATE register SET present= IF(present=1, 0, 1) WHERE id=$id");
      echo (int)(
    mysqli_affected_rows($link) > 0); // success with query

    The echo will give either 0 (that means for some reason the table was not updated) or 1 (the table was updated) in which case you change the colour of the LI in question.

    30 seconds later, of course, the entire page will be refreshed with the contents of the database.

    Now you just need to write the javascript for it. It should be very easy with jQuery if you want to go via that route, or it's simple enough without it too.

    In my example I used is_numeric to sanitise the POSTed data, but depending on what you have, you might want to do something else. But you must check you're getting the expected input.

  10. #10
    SitePoint Member
    Join Date
    Jul 2010
    Posts
    19
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Wow thank you, works beatifully.

    I will let you know how i get on with the javascript, but many many thanks.

  11. #11
    SitePoint Member
    Join Date
    Jul 2010
    Posts
    19
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ok i have hit another wall.

    I can output the database contents fine but how exactly would i allow the user to change the value? Would i need to change the list to buttons instead?

  12. #12
    I meant that to happen silver trophybronze trophy Raffles's Avatar
    Join Date
    Sep 2005
    Location
    Tanzania
    Posts
    4,662
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    That's where the AJAX request comes in. First you need to attach event listeners to your list items. Then you need a simple Ajax function to handle the click and communicate with the server:

    Code javascript:
    var lis = document.getElementsByTagName('li');
    for (var i = 0, j = lis.length; i < j; i++) {
      lis[i].onclick = function() {
        var li = this;
        ajax('id='+this.id, function(res) {
          if (res === '1') { // query was successful, so change the colour
            li.className = li.className === 'present' ? '' : 'present';
          }
        });
      }
    }
     
    function ajax(data, callback) {
        var url = 'registration.php'; // change this to your PHP script path
        if (window.XMLHttpRequest) req = new XMLHttpRequest();
        else if (window.ActiveXObject) {
          var msxml = ['Msxml2.XMLHTTP', 'Msxml3.XMLHTTP', 'Microsoft.XMLHTTP'];
          for (var i = 0; i < 3; i++) {
            try {req = new ActiveXObject(msxml[i])}
            catch (e) {continue;}
            break;
          }
        }
        req.open('POST', url, true);
        req.onreadystatechange = function(e) {
          if (callback && req.readyState === 4 && req.status === 200) callback(req.responseText);
        }
        req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
        req.send(data);
      }
    In your CSS you might want to do something like this to indicate they can be clicked:
    Code css:
    li {
      cursor:hand
    }

  13. #13
    SitePoint Member
    Join Date
    Jul 2010
    Posts
    19
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hmmm ok clicking the list items still doesn't do anything.

    I know im proberly missing something really basic, but here is my code.

    Like i said im a total noob at AJAX/PHP but do have a few books coming so i won't have this problem again.

    Code PHP:
    <script>
    onload = function(){
    var lis = document.getElementsByTagName('li');
    for (var i = 0, j = lis.length; i < j; i++) {
      lis[i].onclick = function() {
        var li = this;
        ajax('id='+this.id, function(res) {
          if (res == '1') { // query was successful, so change the colour
            li.className = li.className == 'present' ? '' : 'present';
          }
        });
      }
    }
     
    function ajax(data, callback) {
        var url = '1.php'; // change this to your PHP script path
        if (window.XMLHttpRequest) req = new XMLHttpRequest();
        else if (window.ActiveXObject) {
          var msxml = ['Msxml2.XMLHTTP', 'Msxml3.XMLHTTP', 'Microsoft.XMLHTTP'];
          for (var i = 0; i < 3; i++) {
            try {req = new ActiveXObject(msxml[i])}
            catch (e) {continue;}
            break;
          }
        }
        req.open('POST', url, true);
        req.onreadystatechange = function(e) {
          if (callback && req.readyState == 4 && req.status == 200) callback(req.responseText);
        }
        req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
        req.send(data);
      }
    }
    </script>
    <style type="text/css">
    li{
    list-style-type: none;
    color: #F00;
    margin: 10px auto 10px auto;
    cursor:pointer;
    }
    .present {
    color:green;	
    }
     
     
    </style>
    </head>
    <?php
    $link = mysqli_connect('localhost','test3','test3','test2');
    $res = mysqli_query($link, 'SELECT * FROM name');
    echo "<ul>\n";
    while ($row = mysqli_fetch_array($res)) {
      echo '<li id="student_' . $row['id'] . '"';
      if ($row['present'] == 1) echo ' class="present"';
      echo '>' . $row['name'] . "</li>\n";
    } 
    mysqli_close($link);
    ?>
    <?php
    $id = array_pop(explode('_', $_POST['id']));
    if (is_numeric($id)) { // check it's a number
      $res = mysqli_query($link, "UPDATE register SET present= IF(present=1, 0, 1) WHERE id=$id");
      echo (int)(mysqli_affected_rows($link) > 0); // success with query
    } 
    ?>

    I did have the php script at the bottom of the page in a different document as there is a link to it in the JS.

    Sorry if im totally off with this.

  14. #14
    I meant that to happen silver trophybronze trophy Raffles's Avatar
    Join Date
    Sep 2005
    Location
    Tanzania
    Posts
    4,662
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Have you got Firebug? Look at the console and you will see that when something is clicked, you get this error:
    Code:
    Access to restricted URI denied"  code: "1012"
    This is because you're testing it locally.

    If you test it on an actual webserver then you shouldn't get this problem. Give it a go and hopefully it'll work.

  15. #15
    SitePoint Member
    Join Date
    Jul 2010
    Posts
    19
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Oh right, ok i will test it on my server.

    Again many thanks.

  16. #16
    SitePoint Member
    Join Date
    Jul 2010
    Posts
    19
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ok now it works perfectly, but it doesn't refresh automatically every 30 seconds on another computer? How would i do this, so the changes will refresh on a different computer?

  17. #17
    I meant that to happen silver trophybronze trophy Raffles's Avatar
    Join Date
    Sep 2005
    Location
    Tanzania
    Posts
    4,662
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    What I would do is make a GET request to the script, including a query string. Like 'register.php?update=1'. That will allow your PHP script to know that it needs to output only the present status of each student. Output it as an object literal:

    Code:
    {
      '12434': 'p',
      '34435': 'a',
      '87631': 'p'
    }
    Where the 'XXXX' code is the student ID and p and a represent present and absent.

    The function called by setInterval simply loops through the list items and sets the class name.

    So, with a little change to the ajax function, your script becomes:

    Code javascript:
    var lis;
    function registerClicks() {
    lis = document.getElementsByTagName('li');
      for (var i = 0, j = lis.length; i < j; i++) {
        lis[i].onclick = function() {
          var li = this;
          ajax('register.php', 'id='+this.id, function(res) {
            if (res === '1') { // query was successful, so change the colour
              li.className = li.className === 'present' ? '' : 'present';
            }
          });
        }
      }
    }
     
    window.onload = registerClicks;
    window.setInterval(function() {
      ajax('register.php?update=1', null, function(res) {
        var students = eval(res), id;
        for (var i = 0, j = lis.length; i < j; i++) {
          id = lis[i].id.split('_')[1];
          if (students[id]) {
            lis[i].className = students[id] === 'p' ?  'present' : '';
          }
        }
      }, 'GET');
    }, 30000);
     
      function ajax(url, data, callback, method) {
        if (!method) method = 'POST';
        if (window.XMLHttpRequest) req = new XMLHttpRequest();
        else if (window.ActiveXObject) {
          var msxml = ['Msxml2.XMLHTTP', 'Msxml3.XMLHTTP', 'Microsoft.XMLHTTP'];
          for (var i = 0; i < 3; i++) {
            try {req = new ActiveXObject(msxml[i])}
            catch (e) {continue;}
            break;
          }
        }
        req.open(method, url, true);
        req.onreadystatechange = function(e) {
          if (callback && req.readyState === 4 && req.status === 200) callback(req.responseText);
        }
        req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
        req.send(data);
      }
    You might want to include a little check to ensure that the setInterval function is receiving the correct sort of string before doing the innerHTML. Look at the string methods.

  18. #18
    SitePoint Member
    Join Date
    Jul 2010
    Posts
    19
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ok thats working perfect, just 1 last small problem, it now only loads every 30 seconds and doesnt automatically change colour when clicked, any way around this or should i just set the timer to 3seconds-ish???

    And thank you so much for your help, again.

  19. #19
    I meant that to happen silver trophybronze trophy Raffles's Avatar
    Join Date
    Sep 2005
    Location
    Tanzania
    Posts
    4,662
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Well, no, because then all you will be doing is reloading the same page every three seconds.

    If it isn't changing colour onclick, you'll have to debug it yourself. Find out if the click is getting registered, and then if the ajax POST is working. This is best done with Firebug (use console.log for the onclick check and the Net panel to monitor the ajax POST).

  20. #20
    SitePoint Member
    Join Date
    Jul 2010
    Posts
    19
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ok fixed that but now i have

    Code JavaScript:
    missing ; before statement
     
    [Break on this error] for (var i = 0, j = lis.length; i < j; i++) {

    which is just after

    Code JavaScript:
    var students = eval(res),id;

    which is causing the problem.

    Any ideas?

  21. #21
    SitePoint Member
    Join Date
    Jul 2010
    Posts
    19
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ok i think the above post was my mistake, however fixing that seems to create another error

    students is undefined
    [Break on this error] if (students[id]) {

    I think its the way im handling the php code, i have the loop on the main index.php, and the php script in a seprate file which i put into the javascript (what you refer to as register.php)

  22. #22
    I meant that to happen silver trophybronze trophy Raffles's Avatar
    Join Date
    Sep 2005
    Location
    Tanzania
    Posts
    4,662
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    If "students" is undefined, then you're not outputting the data properly in response to the GET ajax request (or the ajax request is not working at all).

    This is what I mean about you being able to debug things yourself. Using firebug you can pinpoint exactly at what stage of the process things are going wrong.

    All your PHP code needs to look like is this:

    PHP Code:
    if ($_GET['update'] === '1') {
      
    $res mysqli_query($link'SELECT * FROM register');
      
    $buff '{';
      while (
    $row mysqli_fetch_array($res)) {
        
    $buff .= "'" $row['id'] . "': '";
        
    $buff .= $row['present'] === "'p'" "'a'";
        
    $buff .= ',';
      }
      echo 
    rtrim($buff',') . '}';


  23. #23
    SitePoint Member
    Join Date
    Jul 2010
    Posts
    19
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ok i have it all working finally, ran into 1 lost problem with an invalid label error but fixed that with var students = eval( "(" + res + ")" ), id;

    Many many thanks for your help, i hope to learn JS alot in the next few weeks and hopefully help people as much as you have me.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •