Powerful Chat System – Lesson 5

Date: 05th Mar 2012 Author: admin 1 Comment
Posted in: AJAX, HTML/CSS, HTML5, JavaScript, jQuery, MySQL, PHP |Tags: , , , ,

Powerful Chat System

Powerful Chat System – Lesson 5

Today we continue a series of articles on the creation of powerful chat system. Our fifth lesson will contain next elements: avatars (which will be reduced with GD library) and some customization (custom background for profile pages). As for color picker, I have decided to use modified version of our Paint Program.

Today I will publish updated sources of our growing project (I have created new folder, several files was modified, several – new, plus I have expanded structure of our database). All project is well structured: system classes is in ‘classes’ folder, all javascript files in ‘js’ folder, stylesheets in ‘css’ folder, images in ‘images’ folder, template files in ‘templates’ folder, and – new folder ‘data’ for avatar images (don’t forget to set proper permission to this folder.

Live Demo
download in package

Now – download the source files and lets start coding !


Step 1. SQL

I have added new field into table of profiles where we will store its custom color for background. So, please execute next SQL:

ALTER TABLE `cs_profiles` ADD `color` varchar(6) NOT NULL AFTER `date_reg`;

Step 2. HTML

I have updated template of our main page. As you can see – I have added new {avatar} key here:

templates/main_page.html

<!DOCTYPE html>
<html lang="en" >
<head>
    <title>Powerful Chat System - Lesson 5</title>
    <link href="css/main.css" rel="stylesheet" type="text/css" />
    <script src="http://code.jquery.com/jquery-latest.min.js"></script>
</head>
<body>
    <header>
        <h2>Powerful Chat System - Lesson 5</h2>
        <a href="http://script-tutorials.com/powerful-chat-system-lesson-5/" class="stuts">Back to original tutorial on <span>Script Tutorials</span></a>
    </header>
    <div class="container">
        {form}
        {avatar}
    </div>
    <div class="container">
        <h2>Main Chat Block</h2>
        <div class="chat_messages">
            {chat}
        </div>
        {input}
    </div>
    <div class="container">
        <h2>Profiles Block</h2>
        {profiles}
        <script>
            $(document).ready(function() { // align profiles on the center
                var iAll = $('.profiles div').size();
                var iWU = $('.profiles div:first').outerWidth({'margin':true});
                var iWC = $('.profiles').width();
                var iPerRow = parseInt(iWC/iWU);
                var iLeft = (iWC - (iAll > iPerRow ? iPerRow * iWU : iAll * iWU)) / 2;
                $('.profiles').css('padding-left', iLeft);
            });
        </script>
    </div>
</body>
</html>

Next affected file is profile view template:

templates/profile_page.html

<!DOCTYPE html>
<html lang="en" >
<head>
    <title>Powerful Chat System - Lesson 5</title>
    <link href="css/main.css" rel="stylesheet" type="text/css" />
    <script src="http://code.jquery.com/jquery-latest.min.js"></script>
    <script src="js/customizer.js"></script>
    <style>
        .container {
            {custom_styles}
        }
    </style>
</head>
<body>
    <header>
        <h2>Powerful Chat System - Lesson 5</h2>
        <a href="http://script-tutorials.com/powerful-chat-system-lesson-5/" class="stuts">Back to original tutorial on <span>Script Tutorials</span></a>
    </header>
    <div class="container">
        <div class="column">
            <h3>Name: {name}</h3>
            <h3>First name: {fname}</h3>
            <h3>Last name: {lname}</h3>
            <h3>About: {about}</h3>
            <h3>Date Reg: {datereg}</h3>
            <h3>Role: {role}</h3>
            <h3>Avatar: <img src="{avatar}" style="vertical-align:middle" /></h3>
        </div>
        <div class="column">
            <p><a href="index.php">Back to chat</a></p>
        </div>
    </div>
    <div class="container">
        <h2>You can customize your profile page</h2>
        <div class="column">
            <canvas id="color_canvas" width="370" height="60"></canvas>
        </div>
        <div class="column">
            <div class="customizer_buttons">
                <div id="preview"></div>
            </div>

            <form action="profile.php" method="GET" target="change_color_result">
                <input type="hidden" value="{id}" name="id">
                <input type="hidden" value="color" name="color" id="color">
                <input type="hidden" value="change_color" name="action">
                <input id="submit" type="submit" name="submit" value="Apply">
            </form>
            <iframe class="avatar_iframe" name="change_color_result">

        </div>
    </div>
</body>
</html>

It contain several new things: avatar image and possibility to customize appearance (background color). The next prepared template file:

templates/avatar.html

<div class="clear"></div>
<hr />
<h2>My avatar</h2>
<div class="column">
    <div class="profiles">
        <div title="{name}">
            <a href="profile.php?id={id}">
                <img alt="{name}" src="{image}" />
                <p>{name}</p>
            </a>
        </div>
    </div>
</div>
<div class="column">
    <form id="wrapper" target="upload_result" method="POST" action="index.php" enctype="multipart/form-data">
        <input id="avatar" type="file" name="avatar">
        <input type="hidden" name="action" value="add_avatar">
        <input id="submit" type="submit" value="Upload" name="submit">
    </form>
    <iframe name="upload_result" class="avatar_iframe">
    </iframe>
</div>

This template we will use at our index page (only for logged members) to upload an image as our avatar.

Step 3. CSS

This file has been updated:

css/main.css

/* page layout */
*{
    margin:0;
    padding:0;
}
body {
    background-color:#eee;
    color:#fff;
    font:14px/1.3 Arial,sans-serif;
}
header {
    background-color:#212121;
    box-shadow: 0 -1px 2px #111111;
    display:block;
    height:70px;
    position:relative;
    width:100%;
    z-index:100;
}
header h2{
    font-size:22px;
    font-weight:normal;
    left:50%;
    margin-left:-400px;
    padding:22px 0;
    position:absolute;
    width:540px;
}
header a.stuts,a.stuts:visited{
    border:none;
    text-decoration:none;
    color:#fcfcfc;
    font-size:14px;
    left:50%;
    line-height:31px;
    margin:23px 0 0 110px;
    position:absolute;
    top:0;
}
header .stuts span {
    font-size:22px;
    font-weight:bold;
    margin-left:5px;
}

/* main styles */
a {
    color: #fff;
    outline: none;
    text-decoration: none;
}
a:hover,a:active {
    outline: 0;
    text-decoration: none;
}
.container {
    background-color: #222;
    color: #bbb;
    margin: 20px auto;
    overflow: hidden;
    padding: 20px;
    position: relative;
    width: 800px;
}
.container h2 {
    color: #fff;
    margin-bottom: 10px;
}
.column {
    float: left;
    width: 48%;
}
.column:first-child {
    margin-right: 4%;
}
.column > * {
    color: #ddd;
    margin-bottom: 10px;
}
.clear {
    clear: both;
    font-size: 1px;
}

/* tabs section */
.tabs_container {
    margin: 0;
}
.tabs {
    overflow: hidden;
}
.tabs li {
    float: left;
    list-style: none;
}
.tabs li h3:first-child {
    margin-left: 10px
}
.tabs li h3 {
    border: 1px solid #ddd;
    border-bottom-width: 0;
    display: block;
    margin: 0 2px 0 0;
    padding: 6px 10px 4px
}
.tabs li.active h3 {
    background-color: #555;
    border: 1px solid #ddd;
    border-bottom-width: 0;

    -moz-border-radius: 4px 4px 0 0;
    -ms-border-radius: 4px 4px 0 0;
    -o-border-radius: 4px 4px 0 0;
    -webkit-border-radius: 4px 4px 0 0;
    border-radius: 4px 4px 0 0;
}
.tabs li h3:hover {
    background-color: #666;
    cursor: pointer;
}
.tabs li.active h3:hover {
    background-color: #555;
    cursor: normal;
}
.nav_container form {
    background-color: #555;
    display: block;
    padding: 15px;
}
.column h3 {
    color: #fff;
}
.login_form input,.login_form label,
.join_form input,.join_form label {
    display: block;
    margin-bottom: 10px;
}
input[type=text], input[type=password], input[type=submit] {
    -moz-border-radius: 5px;
    -ms-border-radius: 5px;
    -o-border-radius: 5px;
    -webkit-border-radius: 5px;
    border-radius: 5px;
}
input[type=text], input[type=password] {
    font-size: 16px;
    height: 25px;
    margin-right: 10px;
    width: 200px;
}
input[type=submit],
input[type=file]{
    cursor: pointer;
    font-size: 16px;
    font-weight: bold;
    height: 35px;
    padding: 5px;
}
.avatar_iframe {
    border: 2px dashed #FFFFFF;
    margin-top: 25px;
    width: 330px;
}

/* chat block */
.chat_messages {
    border: 1px solid #888;
    box-shadow: 0 0 5px #AAA;
    color: #000;
    padding: 10px;
}
.chat_messages a {
    color: #000;
}
.chat_messages a img {
    margin-right: 10px;
    vertical-align: middle;
    width: 22px;
}
.chat_messages h2 {
    color: #fff;
}
.chat_messages .message {
    background-color: #fff;
    margin: 5px;
    padding: 5px;

    -moz-border-radius: 5px;
    -ms-border-radius: 5px;
    -o-border-radius: 5px;
    -webkit-border-radius: 5px;
    border-radius: 5px;
}
.chat_messages .message span {
    color: #444;
    font-size: 10px;
    margin-left: 10px;
}
.chat_submit_form {
    margin: 10px 0px;
}
.chat_submit_form div {
    float: left;
    width: 49%;
}
.chat_submit_form .error, .chat_submit_form .success, .chat_submit_form .protect {
    display: none;
}
.chat_submit_form .error {
    color: #f55;
}
.chat_submit_form .success {
    color: #5f5;
}
.chat_submit_form .protect {
    color: #55f;
}

/* profiles */
.profiles {
    overflow: hidden;
}
.profiles a {
    display: block;
}
.profiles div {
    float: left;
    height: 100px;
    margin: 5px;
    overflow: hidden;
    padding: 5px;
    text-align: center;
    width: 70px;
}
.profiles div p {
    font-size: 12px;
}

/* customize profile page */
.customizer_buttons #preview, .customizer_buttons #pick {
    border: 1px solid #888;
    border-radius: 3px 3px 3px 3px;
    box-shadow: 2px 3px 3px #888;
    height: 40px;
    margin-bottom: 10px;
    width: 80px;
}

Step 4. PHP

Now, lets review php sources. Our index.php file has been updated. I have added here avatar processing functional:

index.php

<?php

// set error reporting level
if (version_compare(phpversion(), '5.3.0', '>=') == 1)
  error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED);
else
  error_reporting(E_ALL & ~E_NOTICE);

require_once('classes/Services_JSON.php');
require_once('classes/CMySQL.php'); // including service class to work with database
require_once('classes/CLogin.php'); // including service class to work with login processing
require_once('classes/CProfiles.php'); // including service class to work with profiles

$sErrors = '';
// join processing
if (! isset($_SESSION['member_id']) && $_POST['Join'] == 'Join') {
    $GLOBALS['CProfiles']->registerProfile();
}

// login system init and generation code
$sLoginForm = $GLOBALS['CLogin']->getLoginBox();

$sChat = '<h2>You do not have rights to use chat</h2>';
$sInput = '';
if ($_SESSION['member_id'] && $_SESSION['member_status'] == 'active' && $_SESSION['member_role']) {
    require_once('classes/CChat.php'); // including service class to work with chat

    // get last messages
    $sChat = $GLOBALS['MainChat']->getMessages();
    if ($_GET['action'] == 'get_last_messages') { // regular updating of messages in chat
        $oJson = new Services_JSON();
        header('Content-type: application/json');
        echo $oJson->encode(array('messages' => $sChat));
        exit;
    }

    // add avatar
    if ($_POST['action'] == 'add_avatar') {
        $iAvRes = $GLOBALS['CProfiles']->addAvatar();
        header('Content-Type: text/html; charset=utf-8');
        echo ($iAvRes == 1) ? '<h1 style="color:#fff;text-align:center">New avatar has been accepted, refresh main window to see it</h1>' : '';
        exit;
    }

    // get input form
    $sInput = $GLOBALS['MainChat']->getInputForm();

    if ($_POST['message']) { // POST-ing of message
        $iRes = $GLOBALS['MainChat']->acceptMessage();

        $oJson = new Services_JSON();
        header('Content-type: application/json');
        echo $oJson->encode(array('result' => $iRes));
        exit;
    }
}

// get profiles list
$sProfiles = $GLOBALS['CProfiles']->getProfilesBlock();

// get profile avatar
$sAvatar = $GLOBALS['CProfiles']->getProfileAvatarBlock();

// draw common page
$aKeys = array(
    '{form}' => $sLoginForm . $sErrors,
    '{chat}' => $sChat,
    '{input}' => $sInput,
    '{profiles}' => $sProfiles,
    '{avatar}' => $sAvatar
);
echo strtr(file_get_contents('templates/main_page.html'), $aKeys);

Our next updated file is profile view file (where I have added code and for avatar and for background customization):

profile.php

<?php

// set error reporting level
if (version_compare(phpversion(), '5.3.0', '>=') == 1)
  error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED);
else
  error_reporting(E_ALL & ~E_NOTICE);

require_once('classes/CMySQL.php');
require_once('classes/CLogin.php');
require_once('classes/CProfiles.php');

$iPid = (int)$_GET['id'];

if ($_SESSION['member_id'] && $_SESSION['member_status'] == 'active' && $_SESSION['member_role']) {
    if ($_GET['action'] == 'change_color') {
        $iRes = $GLOBALS['CProfiles']->changeColor($_GET['color']);
        header('Content-Type: text/html; charset=utf-8');
        echo ($iRes == 1) ? '<h1 style="color:#fff;text-align:center">New color has been accepted, refresh main window to see it</h1>' : '';
        exit;
    }
}

$aInfo = $GLOBALS['CProfiles']->getProfileInfo($iPid);

$sName = $aInfo['name'];
$sFName = $aInfo['first_name'];
$sLName = $aInfo['last_name'];
$sAbout = $aInfo['about'];
$sDate = $aInfo['date_reg'];
$sRole = $GLOBALS['CProfiles']->getRoleName($aInfo['role']);
$sAvatar = $GLOBALS['CProfiles']->getProfileAvatar($iPid);
$sCustomBG = ($aInfo['color']) ? 'background-color:#'.$aInfo['color'] : '';

// draw common page
$aKeys = array(
    '{id}' => $iPid,
    '{name}' => $sName,
    '{fname}' => $sFName,
    '{lname}' => $sLName,
    '{about}' => $sAbout,
    '{datereg}' => $sDate,
    '{role}' => $sRole,
    '{avatar}' => $sAvatar,
    '{custom_styles}' => $sCustomBG
);
echo strtr(file_get_contents('templates/profile_page.html'), $aKeys);

classes/CChat.php

I have made a little change in this file to display actual profile avatar. I have changed:

            $sWhen = date("H:i:s", $aMessage['when']);
            $sMessages .= '<div class="message" id="message_'.$aMessage['id'].'" '.$sExStyles.'><b><a href="profile.php?id='.$aMessage['pid'].'" target="_blank">' . $aMessage['name'] . ':</a></b> ' . $aMessage['message'] . '<span>(' . $sWhen . ')</span></div>' . $sExJS;

(at lines 56-57) to next code:

            $sWhen = date("H:i:s", $aMessage['when']);
            $sAvatar = $GLOBALS['CProfiles']->getProfileAvatar($aMessage['pid']);
            $sMessages .= '<div class="message" id="message_'.$aMessage['id'].'" '.$sExStyles.'><b><a href="profile.php?id='.$aMessage['pid'].'" target="_blank"><img src="'. $sAvatar .'">' . $aMessage['name'] . ':</a></b> ' . $aMessage['message'] . '<span>(' . $sWhen . ')</span></div>' . $sExJS;

The next file that I have updated is our profile class:

classes/CProfiles.php

<?php

// Profiles class
class CProfiles {

    // constructor
    function CProfiles() {
    }

    // profile registration
    function registerProfile() {
        $sUsername = $GLOBALS['MySQL']->escape($_POST['username']);
        $sFirstname = $GLOBALS['MySQL']->escape($_POST['firstname']);
        $sLastname = $GLOBALS['MySQL']->escape($_POST['lastname']);
        $sEmail = $GLOBALS['MySQL']->escape($_POST['email']);
        $sPassword = $GLOBALS['MySQL']->escape($_POST['password']);

        if ($sUsername && $sEmail && $sPassword) {
            // check if already exist
            $aProfile = $GLOBALS['MySQL']->getRow("SELECT * FROM `cs_profiles` WHERE `email`='{$sEmail}'");
            if ($aProfile['id'] > 0) {
                $sErrors = '<h2>Another profile with same email already exist</h2>';
            } else {
                // generate Salt and Cached password
                $sSalt = $this->getRandCode();
                $sPass = sha1(md5($sPassword) . $sSalt);

                // add new member into database
                $sSQL = "
                    INSERT INTO `cs_profiles` SET
                    `name` = '{$sUsername}',
                    `first_name` = '{$sFirstname}',
                    `last_name` = '{$sLastname}',
                    `email` = '{$sEmail}',
                    `password` = '{$sPass}',
                    `salt` = '{$sSalt}',
                    `status` = 'active',
                    `role` = '1',
                    `date_reg` = NOW();
                ";
                $GLOBALS['MySQL']->res($sSQL);

                // autologin
                $GLOBALS['CLogin']->performLogin($sUsername, $sPassword);
            }
        }
    }

    // get random code (for salt)
    function getRandCode($iLen = 8) {
        $sRes = '';

        $sChars = "23456789abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ";
        for ($i = 0; $i < $iLen; $i++) {
            $z = rand(0, strlen($sChars) -1);
            $sRes .= $sChars[$z];
        }
        return $sRes;
    }

    // get profiles block
    function getProfilesBlock($iLim = 16) {
        $sSQL = "
            SELECT *
            FROM `cs_profiles`
            WHERE `status` = 'active'
            ORDER BY `date_reg` DESC
            LIMIT {$iLim}
        ";
        $aProfiles = $GLOBALS['MySQL']->getAll($sSQL);

        // create list of messages
        $sCode = '';
        foreach ($aProfiles as $i => $aProfile) {
            $sName = ($aProfile['first_name'] && $aProfile['last_name']) ? $aProfile['first_name'] . ' ' . $aProfile['last_name'] : $aProfile['name'];
            $sSName = (strlen($sName) > 32) ? mb_substr($sName, 0, 28) . '...' : $sName;
            $iPid = $aProfile['id'];
            $sAvatar = $this->getProfileAvatar($iPid);

            $sCode .= '<div id="'.$iPid.'" title="'.$sName.'"><a href="profile.php?id='.$iPid.'"><img src="'.$sAvatar.'" alt="'.$sName.'"><p>'.$sSName.'</p></a></div>';
        }

        return '<div class="profiles">' . $sCode . '</div>';
    }

    // get profile info
    function getProfileInfo($i) {
        $sSQL = "
            SELECT *
            FROM `cs_profiles`
            WHERE `id` = '{$i}'
        ";
        $aInfos = $GLOBALS['MySQL']->getAll($sSQL);
        return $aInfos[0];
    }

    // get role name
    function getRoleName($i) {
        $sRet = 'Ordinary member';
        switch ($i) {
            case 4:
                $sRet = 'Moderator';
                break;
            case 5:
                $sRet = 'Administrator';
                break;
        }
        return $sRet;
    }

    // get profile avatar block
    function getProfileAvatarBlock() {
        if ($_SESSION['member_id']) {
            $aInfo = $this->getProfileInfo((int)$_SESSION['member_id']);
            if (is_array($aInfo) && count($aInfo)) {
                $sName = ($aInfo['first_name'] && $aInfo['last_name']) ? $aInfo['first_name'] . ' ' . $aInfo['last_name'] : $aInfo['name'];

                $aKeys = array(
                    '{id}' => $aInfo['id'],
                    '{image}' => $this->getProfileAvatar($aInfo['id']),
                    '{name}' => $sName
                );
                return strtr(file_get_contents('templates/avatar.html'), $aKeys);
            }
        }
    }

    function getProfileAvatar($i) {
        $sPath = 'data/' . $i . '.jpg';
        return (file_exists($sPath)) ? $sPath : 'images/member.png';
    }

    // add avatar (upload image)
    function addAvatar() {
        $iPid = (int)$_SESSION['member_id'];
        if ($iPid) {
            $sFileTmpName = $_FILES['avatar']['tmp_name'];
            $sDstFilename = 'data/' . $iPid . '.jpg';

            if (file_exists($sFileTmpName) && filesize($sFileTmpName) > 0) {
                $aSize = getimagesize($sFileTmpName);
                if (! $aSize) {
                    @unlink($sFileTmpName);
                    return;
                }

                $bGDInstalled = extension_loaded('gd');

                // resize if GD is installed
                if (! $bGDInstalled)
                    return;

                $iWidth = $iHeight = 48; // width and height for avatar image
                define('IMAGE_TYPE_GIF', 1);
                define('IMAGE_TYPE_JPG', 2);
                define('IMAGE_TYPE_PNG', 3);

                $gdInfoArray = gd_info();
                switch($aSize[2]) {
                    case IMAGE_TYPE_GIF:
                        if (! $gdInfoArray['GIF Read Support'] || ! $gdInfoArray['GIF Create Support'])
                            return;
                        $vSrcImage = @imagecreatefromgif($sFileTmpName);
                        break;
                    case IMAGE_TYPE_JPG:
                        if (! $gdInfoArray['JPEG Support'])
                            return;
                        $vSrcImage = @imagecreatefromjpeg($sFileTmpName);
                        break;
                    case IMAGE_TYPE_PNG:
                        if (! $gdInfoArray['PNG Support'])
                            return;
                        $vSrcImage = @imagecreatefrompng($sFileTmpName);
                        break;
                    default:
                        return;
                }
                if (! $vSrcImage)
                    return;

                // calculate destination rate and sizes
                $fSrcRate = (float)($aSize[0] / $aSize[1]);
                $fDstRate = (float)($iWidth / $iHeight);
                $fResizeRate = ($fSrcRate > $fDstRate) ? (float)($iWidth / $aSize[0]) : (float)($iHeight / $aSize[1]);
                $iDstWidth = (int)($fResizeRate * $aSize[0]);
                $iDstHeight = (int)($fResizeRate * $aSize[1]);

                if (function_exists('imagecreatetruecolor') && $aSize[2] != IMAGE_TYPE_GIF) {
                    // resize if need (if size is larger than needed)
                    if ($aSize[0] > $iWidth || $aSize[1] > $iHeight) {
                        $vDstImage = imagecreatetruecolor($iDstWidth, $iDstHeight);
                        $vConvRes = imagecopyresampled($vDstImage, $vSrcImage, 0, 0, 0, 0, $iDstWidth, $iDstHeight, $aSize[0], $aSize[1]);
                    } else {
                        $vDstImage = $vSrcImage;
                        $vConvRes = true;
                    }
                } else { // for old GD versions and for GIF images
                    if ($aSize[0] > $iWidth || $aSize[1] > $iHeight) {
                        $vDstImage = imagecreate( $iDstWidth, $iDstHeight );
                        $vConvRes = imagecopyresized($vDstImage, $vSrcImage, 0, 0, 0, 0, $iDstWidth, $iDstHeight, $aSize[0], $aSize[1]);
                    } else {
                        $vDstImage = $vSrcImage;
                        $vConvRes = true;
                    }
                }

                if (! $vConvRes)
                    return;

                $bRes = imagejpeg($vDstImage, $sDstFilename);

                // memory cleanup
                if ($vDstImage != $vSrcImage) {
                    imagedestroy($vSrcImage);
                    imagedestroy($vDstImage);
                } else {
                    imagedestroy($vSrcImage);
                }
                return ($bRes && file_exists($sDstFilename)) ? 1 : '';
            }
        }
    }

    function changeColor($sColor = '') {
        $iPid = (int)$_SESSION['member_id'];
        $sColor = $GLOBALS['MySQL']->escape($sColor);
        if ($iPid && $sColor) {
            if (strlen($sColor) == 4) {
                $sColor = '00' . $sColor;
            }
            $sSQL = "
                UPDATE `cs_profiles` SET
                `color` = '{$sColor}'
                WHERE `id` = '{$iPid}'
            ";
            $GLOBALS['MySQL']->res($sSQL);
            return 1;
        }
        return;
    }
}

$GLOBALS['CProfiles'] = new CProfiles();

I have modified ‘getProfilesBlock’ function (to display avatars of members), and then, have prepared next new functions: ‘getProfileAvatarBlock’ (to display block where we can assign new avatar image) , ‘getProfileAvatar’ (this function will return us avatar image path), ‘addAvatar’ (this function is made to accept and resize (with using GD library) uploaded avatar image) and ‘changeColor’ (to save new custom profile background color into DB). Also, please pay attention, that sometimes instead:

if (! $gdInfoArray['JPEG Support'])

we have to use:

if (! $gdInfoArray['JPG Support'])

Step 5. Javascript

js/customizer.js

This is new file (our new color picker) for our project:

var canvasColor;
var ctxColor;
var bMouseDown = false;

$(function(){

    // create canvas and context objects
    canvasColor = document.getElementById('color_canvas');
    ctxColor = canvasColor.getContext('2d');

    drawGradients(ctxColor);

    $('#color_canvas').mousemove(function(e) { // mouse move handler
        var canvasOffset = $(canvasColor).offset();
        var canvasX = Math.floor(e.pageX - canvasOffset.left);
        var canvasY = Math.floor(e.pageY - canvasOffset.top);

        var imageData = ctxColor.getImageData(canvasX, canvasY, 1, 1);
        var pixel = imageData.data;

        var pixelColor = "rgba("+pixel[0]+", "+pixel[1]+", "+pixel[2]+", "+pixel[3]+")";
        $('#preview').css('backgroundColor', pixelColor);
    });

    $('#color_canvas').click(function(e) { // mouse click handler
        var canvasOffset = $(canvasColor).offset();
        var canvasX = Math.floor(e.pageX - canvasOffset.left);
        var canvasY = Math.floor(e.pageY - canvasOffset.top);

        var imageData = ctxColor.getImageData(canvasX, canvasY, 1, 1);
        var pixel = imageData.data;

        var pixelColor = "rgba("+pixel[0]+", "+pixel[1]+", "+pixel[2]+", "+pixel[3]+")";
        $('.container').css('backgroundColor', pixelColor);

        var dColor = pixel[2] + 256 * pixel[1] + 65536 * pixel[0];
        $('#color').val(dColor.toString(16));
    }); 

    $('#panel').mousedown(function(e) { // mouse down handler
        bMouseDown = true;
    });
    $('#panel').mouseup(function(e) { // mouse up handler
        bMouseDown = false;
    });
});

function drawGradients() {
    var grad = ctxColor.createLinearGradient(20, 0, canvasColor.width - 20, 0);
    grad.addColorStop(0, 'red');
    grad.addColorStop(1 / 6, 'orange');
    grad.addColorStop(2 / 6, 'yellow');
    grad.addColorStop(3 / 6, 'green')
    grad.addColorStop(4 / 6, 'aqua');
    grad.addColorStop(5 / 6, 'blue');
    grad.addColorStop(1, 'purple');
    ctxColor.fillStyle=grad;
    ctxColor.fillRect(0, 0, canvasColor.width, canvasColor.height);
}

Live Demo
download in archive

Conclusion

I hope that our new series of articles of chat system creation is useful and interesting for you. If you want to share your ideas, or you noticed any weakness – don’t hesitate to contact us. Good luck and welcome back!

Enjoyed this Post?

If you enjoyed this article, feel free to share our tutorial with your friends.
    Tweet
   
   

Stay connected with us:

1 Comment

    • Gyang's Gravatar
    • Am inspired, you are doing a very good work, I can’t wait for the next lesson…

Leave a Reply

Your email address will not be published. Required fields are marked *

*

CAPTCHA Image
Refresh Image

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>