title: HTML5 webcam capture display picture
body: <p>So, I have this HTML5 chatting script which requires users to input their name and email to start chatting. The script grabs the users display picture from gavatar. I'm trying to change that to make it take a webcam snapshot from the users computer and set that as a display picture.</p>
  
  <p>I've seen a few examples of the usage of HTML5 to access the users webcam but I can't seem to figure out how to automatically take the snapshot and set it as the users display picture.</p>
  
  <p>Here's my current code.</p>
  
  <pre><code>$(document).ready(function(){
  
      // Run the init method on document ready:
      chat.init();
  
  });
  
  var chat = {
  
      // data holds variables for use in the class:
  
      data : {
          lastID      : 0,
          noActivity  : 0
      },
  
      // Init binds event listeners and sets up timers:
  
      init : function(){
  
          // Using the defaultText jQuery plugin, included at the bottom:
          $('#name').defaultText('Nickname');
          $('#email').defaultText('Email');
  
          // Converting the #chatLineHolder div into a jScrollPane,
          // and saving the plugin's API in chat.data:
  
          chat.data.jspAPI = $('#chatLineHolder').jScrollPane({
              verticalDragMinHeight: 12,
              verticalDragMaxHeight: 12
          }).data('jsp');
  
          // We use the working variable to prevent
          // multiple form submissions:
  
          var working = false;
  
          // Logging a person in the chat:
  
          $('#loginForm').submit(function(){
  
              if(working) return false;
              working = true;
  
              // Using our tzPOST wrapper function
              // (defined in the bottom):
  
              $.tzPOST('login',$(this).serialize(),function(r){
                  working = false;
  
                  if(r.error){
                      chat.displayError(r.error);
                  }
                  else chat.login(r.name,r.gravatar);
              });
  
              return false;
          });
  
          // Submitting a new chat entry:
  
          $('#submitForm').submit(function(){
  
              var text = $('#chatText').val();
  
              if(text.length == 0){
                  return false;
              }
  
              if(working) return false;
              working = true;
  
              // Assigning a temporary ID to the chat:
              var tempID = 't'+Math.round(Math.random()*1000000),
                  params = {
                      id          : tempID,
                      author      : chat.data.name,
                      gravatar    : chat.data.gravatar,
                      text        : text.replace(/&lt;/g,'&amp;lt;').replace(/&gt;/g,'&amp;gt;')
                  };
  
              // Using our addChatLine method to add the chat
              // to the screen immediately, without waiting for
              // the AJAX request to complete:
  
              chat.addChatLine($.extend({},params));
  
              // Using our tzPOST wrapper method to send the chat
              // via a POST AJAX request:
  
              $.tzPOST('submitChat',$(this).serialize(),function(r){
                  working = false;
  
                  $('#chatText').val('');
                  $('div.chat-'+tempID).remove();
  
                  params['id'] = r.insertID;
                  chat.addChatLine($.extend({},params));
              });
  
              return false;
          });
  
          // Logging the user out:
  
          $('a.logoutButton').live('click',function(){
  
              $('#chatTopBar &gt; span').fadeOut(function(){
                  $(this).remove();
              });
  
              $('#submitForm').fadeOut(function(){
                  $('#loginForm').fadeIn();
              });
  
              $.tzPOST('logout');
  
              return false;
          });
  
          // Checking whether the user is already logged (browser refresh)
  
          $.tzGET('checkLogged',function(r){
              if(r.logged){
                  chat.login(r.loggedAs.name,r.loggedAs.gravatar);
              }
          });
  
          // Self executing timeout functions
  
          (function getChatsTimeoutFunction(){
              chat.getChats(getChatsTimeoutFunction);
          })();
  
          (function getUsersTimeoutFunction(){
              chat.getUsers(getUsersTimeoutFunction);
          })();
  
      },
  
      // The login method hides displays the
      // user's login data and shows the submit form
  
      login : function(name,gravatar){
  
          chat.data.name = name;
          chat.data.gravatar = gravatar;
          $('#chatTopBar').html(chat.render('loginTopBar',chat.data));
  
          $('#loginForm').fadeOut(function(){
              $('#submitForm').fadeIn();
              $('#chatText').focus();
          });
  
      },
  
      // The render method generates the HTML markup 
      // that is needed by the other methods:
  
      render : function(template,params){
  
          var arr = [];
          switch(template){
              case 'loginTopBar':
                  arr = [
                  '&lt;span&gt;&lt;img src="',params.gravatar,'" width="23" height="23" /&gt;',
                  '&lt;span class="name"&gt;',params.name,
                  '&lt;/span&gt;&lt;a href="" class="logoutButton rounded"&gt;Logout&lt;/a&gt;&lt;/span&gt;'];
              break;
  
              case 'chatLine':
                  arr = [
                      '&lt;div class="chat chat-',params.id,' rounded"&gt;&lt;span class="gravatar"&gt;&lt;img src="',params.gravatar,
                      '" width="23" height="23" onload="this.style.visibility=\'visible\'" /&gt;','&lt;/span&gt;&lt;span class="author"&gt;',params.author,
                      ':&lt;/span&gt;&lt;span class="text"&gt;',params.text,'&lt;/span&gt;&lt;span class="time"&gt;',params.time,'&lt;/span&gt;&lt;/div&gt;'];
              break;
  
              case 'user':
                  arr = [
                      '&lt;div class="user" title="',params.name,'"&gt;&lt;img src="',
                      params.gravatar,'" width="30" height="30" onload="this.style.visibility=\'visible\'" /&gt;&lt;/div&gt;'
                  ];
              break;
          }
  
          // A single array join is faster than
          // multiple concatenations
  
          return arr.join('');
  
      },
  
      // The addChatLine method ads a chat entry to the page
  
      addChatLine : function(params){
  
          // All times are displayed in the user's timezone
  
          var d = new Date();
          if(params.time) {
  
              // PHP returns the time in UTC (GMT). We use it to feed the date
              // object and later output it in the user's timezone. JavaScript
              // internally converts it for us.
  
              d.setUTCHours(params.time.hours,params.time.minutes);
          }
  
          params.time = (d.getHours() &lt; 10 ? '0' : '' ) + d.getHours()+':'+
                        (d.getMinutes() &lt; 10 ? '0':'') + d.getMinutes();
  
          var markup = chat.render('chatLine',params),
              exists = $('#chatLineHolder .chat-'+params.id);
  
          if(exists.length){
              exists.remove();
          }
  
          if(!chat.data.lastID){
              // If this is the first chat, remove the
              // paragraph saying there aren't any:
  
              $('#chatLineHolder p').remove();
          }
  
          // If this isn't a temporary chat:
          if(params.id.toString().charAt(0) != 't'){
              var previous = $('#chatLineHolder .chat-'+(+params.id - 1));
              if(previous.length){
                  previous.after(markup);
              }
              else chat.data.jspAPI.getContentPane().append(markup);
          }
          else chat.data.jspAPI.getContentPane().append(markup);
  
          // As we added new content, we need to
          // reinitialise the jScrollPane plugin:
  
          chat.data.jspAPI.reinitialise();
          chat.data.jspAPI.scrollToBottom(true);
  
      },
  
      // This method requests the latest chats
      // (since lastID), and adds them to the page.
  
      getChats : function(callback){
          $.tzGET('getChats',{lastID: chat.data.lastID},function(r){
  
              for(var i=0;i&lt;r.chats.length;i++){
                  chat.addChatLine(r.chats[i]);
              }
  
              if(r.chats.length){
                  chat.data.noActivity = 0;
                  chat.data.lastID = r.chats[i-1].id;
              }
              else{
                  // If no chats were received, increment
                  // the noActivity counter.
  
                  chat.data.noActivity++;
              }
  
              if(!chat.data.lastID){
                  chat.data.jspAPI.getContentPane().html('&lt;p class="noChats"&gt;No chats yet&lt;/p&gt;');
              }
  
              // Setting a timeout for the next request,
              // depending on the chat activity:
  
              var nextRequest = 1000;
  
              // 2 seconds
              if(chat.data.noActivity &gt; 3){
                  nextRequest = 2000;
              }
  
              if(chat.data.noActivity &gt; 10){
                  nextRequest = 5000;
              }
  
              // 15 seconds
              if(chat.data.noActivity &gt; 20){
                  nextRequest = 15000;
              }
  
              setTimeout(callback,nextRequest);
          });
      },
  
      // Requesting a list with all the users.
  
      getUsers : function(callback){
          $.tzGET('getUsers',function(r){
  
              var users = [];
  
              for(var i=0; i&lt; r.users.length;i++){
                  if(r.users[i]){
                      users.push(chat.render('user',r.users[i]));
                  }
              }
  
              var message = '';
  
              if(r.total&lt;1){
                  message = 'No one is online';
              }
              else {
                  message = r.total+' '+(r.total == 1 ? 'person':'people')+' online';
              }
  
              users.push('&lt;p class="count"&gt;'+message+'&lt;/p&gt;');
  
              $('#chatUsers').html(users.join(''));
  
              setTimeout(callback,15000);
          });
      },
  
      // This method displays an error message on the top of the page:
  
      displayError : function(msg){
          var elem = $('&lt;div&gt;',{
              id      : 'chatErrorMessage',
              html    : msg
          });
  
          elem.click(function(){
              $(this).fadeOut(function(){
                  $(this).remove();
              });
          });
  
          setTimeout(function(){
              elem.click();
          },5000);
  
          elem.hide().appendTo('body').slideDown();
      }
  };
  
  // Custom GET &amp; POST wrappers:
  
  $.tzPOST = function(action,data,callback){
      $.post('php/ajax.php?action='+action,data,callback,'json');
  }
  
  $.tzGET = function(action,data,callback){
      $.get('php/ajax.php?action='+action,data,callback,'json');
  }
  
  // A custom jQuery method for placeholder text:
  
  $.fn.defaultText = function(value){
  
      var element = this.eq(0);
      element.data('defaultText',value);
  
      element.focus(function(){
          if(element.val() == value){
              element.val('').removeClass('defaultText');
          }
      }).blur(function(){
          if(element.val() == '' || element.val() == value){
              element.addClass('defaultText').val(value);
          }
      });
  
      return element.blur();
  }
  </code></pre>
  
  <p>And this is the PHP file for grabbing the users DP from gravatar.</p>
  
  <pre><code>&lt;?php
  
  class ChatUser extends ChatBase{
  
      protected $name = '', $gravatar = '';
  
      public function save(){
  
          DB::query("
              INSERT INTO webchat_users (name, gravatar)
              VALUES (
                  '".DB::esc($this-&gt;name)."',
                  '".DB::esc($this-&gt;gravatar)."'
          )");
  
          return DB::getMySQLiObject();
      }
  
      public function update(){
          DB::query("
              INSERT INTO webchat_users (name, gravatar)
              VALUES (
                  '".DB::esc($this-&gt;name)."',
                  '".DB::esc($this-&gt;gravatar)."'
              ) ON DUPLICATE KEY UPDATE last_activity = NOW()");
      }
  }
  
  ?&gt;
  </code></pre>
  
  <p>Also another bit of code.</p>
  
  <pre><code>&lt;?php
  
  /* The Chat class exploses public static methods, used by ajax.php */
  
  class Chat{
  
      public static function login($name,$email){
          if(!$name || !$email){
              throw new Exception('Fill in all the required fields.');
          }
  
          if(!filter_input(INPUT_POST,'email',FILTER_VALIDATE_EMAIL)){
              throw new Exception('Your email is invalid.');
          }
  
          // Preparing the gravatar hash:
          $gravatar = md5(strtolower(trim($email)));
  
          $user = new ChatUser(array(
              'name'      =&gt; $name,
              'gravatar'  =&gt; $gravatar
          ));
  
          // The save method returns a MySQLi object
          if($user-&gt;save()-&gt;affected_rows != 1){
              throw new Exception('This nick is in use.');
          }
  
          $_SESSION['user']   = array(
              'name'      =&gt; $name,
              'gravatar'  =&gt; $gravatar
          );
  
          return array(
              'status'    =&gt; 1,
              'name'      =&gt; $name,
              'gravatar'  =&gt; Chat::gravatarFromHash($gravatar)
          );
      }
  
      public static function checkLogged(){
          $response = array('logged' =&gt; false);
  
          if($_SESSION['user']['name']){
              $response['logged'] = true;
              $response['loggedAs'] = array(
                  'name'      =&gt; $_SESSION['user']['name'],
                  'gravatar'  =&gt; Chat::gravatarFromHash($_SESSION['user']['gravatar'])
              );
          }
  
          return $response;
      }
  
      public static function logout(){
          DB::query("DELETE FROM webchat_users WHERE name = '".DB::esc($_SESSION['user']['name'])."'");
  
          $_SESSION = array();
          unset($_SESSION);
  
          return array('status' =&gt; 1);
      }
  
      public static function submitChat($chatText){
          if(!$_SESSION['user']){
              throw new Exception('You are not logged in');
          }
  
          if(!$chatText){
              throw new Exception('You haven\' entered a chat message.');
          }
  
          $chat = new ChatLine(array(
              'author'    =&gt; $_SESSION['user']['name'],
              'gravatar'  =&gt; $_SESSION['user']['gravatar'],
              'text'      =&gt; $chatText
          ));
  
          // The save method returns a MySQLi object
          $insertID = $chat-&gt;save()-&gt;insert_id;
  
          return array(
              'status'    =&gt; 1,
              'insertID'  =&gt; $insertID
          );
      }
  
      public static function getUsers(){
          if($_SESSION['user']['name']){
              $user = new ChatUser(array('name' =&gt; $_SESSION['user']['name']));
              $user-&gt;update();
          }
  
          // Deleting chats older than 5 minutes and users inactive for 30 seconds
  
          DB::query("DELETE FROM webchat_lines WHERE ts &lt; SUBTIME(NOW(),'0:5:0')");
          DB::query("DELETE FROM webchat_users WHERE last_activity &lt; SUBTIME(NOW(),'0:0:30')");
  
          $result = DB::query('SELECT * FROM webchat_users ORDER BY name ASC LIMIT 18');
  
          $users = array();
          while($user = $result-&gt;fetch_object()){
              $user-&gt;gravatar = Chat::gravatarFromHash($user-&gt;gravatar,30);
              $users[] = $user;
          }
  
          return array(
              'users' =&gt; $users,
              'total' =&gt; DB::query('SELECT COUNT(*) as cnt FROM webchat_users')-&gt;fetch_object()-&gt;cnt
          );
      }
  
      public static function getChats($lastID){
          $lastID = (int)$lastID;
  
          $result = DB::query('SELECT * FROM webchat_lines WHERE id &gt; '.$lastID.' ORDER BY id ASC');
  
          $chats = array();
          while($chat = $result-&gt;fetch_object()){
  
              // Returning the GMT (UTC) time of the chat creation:
  
              $chat-&gt;time = array(
                  'hours'     =&gt; gmdate('H',strtotime($chat-&gt;ts)),
                  'minutes'   =&gt; gmdate('i',strtotime($chat-&gt;ts))
              );
  
              $chat-&gt;gravatar = Chat::gravatarFromHash($chat-&gt;gravatar);
  
              $chats[] = $chat;
          }
  
          return array('chats' =&gt; $chats);
      }
  
      public static function gravatarFromHash($hash, $size=23){
          return 'http://www.gravatar.com/avatar/'.$hash.'?size='.$size.'&amp;amp;default='.
                  urlencode('http://www.gravatar.com/avatar/ad516503a11cd5ca435acc9bb6523536?size='.$size);
      }
  }
  
  
  ?&gt;
  </code></pre>