Monday, 2 September 2013

jQuery form validation using jquery.validate.min.js

<html>
<head>
<style type="text/css">

.error, .notice, .success{padding:.1em; margin-bottom:1em; border:2px solid
#ddd}
.error{background:#FBE3E4; color:#8a1f11; border-color:#FBC2C4}
.notice{background:#FFF6BF; color:#orange; border-color:#FFD324}
.success{background:#E6EFC2; color:#264409; border-color:#C6D880}

</style>
<script src="jquery.js"></script>
<script src="jquery.validate.min.js" type="text/javascript"></script>
<script type="text/javascript">

$(document).ready(function()
{
    $("#contact-form").validate({
       rules:{
              username:"required",
              userid:"required",
              useremailid:{required:true,email:true},
              usermobile:{required:true,digits:true,rangelength:[10,10]},
              userage:{required:true,digits:true,min:18,max:100},
              userpass:{required:true,rangelength:[6,10]},
              confpass:{required:true,equalTo:'#userpass'},
              country:{required:true,countrylist:["India"]},
              city:{required:true,citylist:["Kolkata","Chennai","Mumbai","New Delhi"]},
              langs:{required:true,langcount:[2]},
              ambition:{rangelength:[10,20]},
              vcode:{required:true,verify:true},
               
        }, //end rules
         messages:{
                usermobile:{required:"Please enter your mobile number",digits:"Please enter a valid mobile number",rangelength:"The mobile number must have exactly 10 digits"},
                confpass:{required:"Please enter the password again",equalTo:"The passwords do not match"},
                langs:{required:"Tick the languages you know"},
                ambition:{rangelength:"Should be 10 to 20 characters"},
                vcode:{required:"Please enter verification code"},
            },//end messages
           
       errorPlacement:function(error, element)
                      {
           if ( element.is(":radio") || element.is(":checkbox")) 
              {
                 error.appendTo( element.parent());
              } else 
                 {
                  error.insertAfter(element);
                 }
                     }//end errorPlacement
        });
       
        $.validator.addMethod("countrylist",function(value,element,params)
        {
           return this.optional(element)||   

                   value.toLowerCase()== params[0].toLowerCase();
        },"You must be an Indian citizen");
       
        $.validator.addMethod("citylist",function(value,element,params)
        {
            return this.optional(element) || 
            value.toLowerCase()==params[0].toLowerCase() ||
            value.toLowerCase()==params[1].toLowerCase() ||
            value.toLowerCase()==params[2].toLowerCase() ||
            value.toLowerCase()==params[3].toLowerCase() ;
        },$.format("You must stay in one of {0},{1},{2} or {3}"));
       
        $.validator.addMethod("langcount",function(value,element,params)
        {
            $langcount=$("form input:checkbox:checked").length;
           
            return this.optional(element) || $langcount>=params[0];
        },$.format("You must know at least {0} languages"));
       
        $.validator.addMethod("verify",function(value,element,params)
        {
            var total=parseInt($('#no1').val()) + parseInt($('#no2').val());
           
            return this.optional(element) || parseInt(value)==total;
        },$.format("Verification failed..please try again"));
       
        $('input:radio[name=pmtmeth]').change(function(){
       
            if($(this).val()=='cheque')
            {
                $('#chequeno').attr('readonly',false);
                $('#chequeno').rules('add',"required digits");
                $('#chequeno').rules('add',{messages:        {required: "Please enter cheque number",digits:"Invalid Cheque number. Should be digits only"}});               
            }
            else
            {
                $('#chequeno').attr('readonly',true);
                $('#chequeno').rules('remove',"required digits");
                $('#chequeno').val('');
                $('#chequeno').removeClass('error');
                $('label[for=chequeno]').remove();
               
            }
           
        });
       
});

</script>
</head>
<body>
<form id="contact-form">
Name<br />
<input type="text" name="username" value="" />
<br />UserId<br />
<input type="text" name="userid" value="" />
<br />EmailId<br />
<input type="text" name="useremailid" value="" />
<br />Mobile No<br />
<input type="text" name="usermobile" value="" />
<br />Age (must be between 18 and 100)<br />
<input type="text" name="userage" value="" />
<br />Country<br />
<input type="text" name="country" value="" />
<br />City<br />
<input type="text" name="city" value="" />
<br />Password (6 to 10 characters)<br />
<input type="password" id="userpass" name="userpass" value="" />
<br />Confirm Password<br />
<input type="password" name="confpass" value="" />
<br /><br />Languages Known
<div>
<input type="checkbox" name="langs" value="Bengali">English
<input type="checkbox" name="langs" value="English">Spanish
<input type="checkbox" name="langs" value="Hindi">French
</div>
<br />Your Ambition<br />
<textarea name="ambition"></textarea>
<br /><br />Payment Method
<input type="radio" name="pmtmeth" value="cash" checked="checked">Cash</input>
<input type="radio" name="pmtmeth" value="cheque">Cheque</input>
<br />Cheque No<input type="text" name="chequeno" id='chequeno' value="" readonly="true"/>
<br /><br />Enter Verification Code
<input type="text" name="no1" id="no1" value="5" size="2"/> + <input type="text" name="no2" id="no2" value="7" size="2"/> = <input type="text" name="vcode" value="" size="2"/>
<br /><br />
<input type="submit" name="btnSubmit" value="SAVE" />
</form>
</body>
</html>

Friday, 16 August 2013

Variable scope in JavaScript

In JavaScript, variables can be declared in two ways, implicit declaration and explicit declaration.

var x;

This was an explicit declaration. The keyword var indicates the next symbol is a new identifier in the current scope.

x = 100;

This was an implicit declaration. There is no need to always explicitly define a variable before using it. A variable can be implicitly defined by simply referring to it without using the var keyword.

The second piece of code assigns the variable to the global scope, meaning it will be accessible by all blocks,  functions, and statements. In general, it is better to avoid implicit variables.

Now, let us come to Variable Scope. The scope of a variable refers to the portions of the program where it can be directly accessed. 

When variables are defined explicitly, they are accessible by all parts of the program, so they have global  scope . If a variable’s scope is limited to its function, it has local scope . The scope to which a variable  belongs is called its context.

<script type="text/javascript">
var os = "Windows";

function myOs()
{
  var os = "Linux";
  document.write(os + "<br />");
}

myOs();
document.write(os + "<br />");
</script>


The output of the above code is:

Linux
Windows

The output above is a matter of variable scoping. When the function myOs() is called, the interpreter first checks whether there is a variable 'os' defined in the local scope (the function context). If it doesn’t find it, it moves up the hierarchy of scopes until it reaches the global scope (the window object in a browser), checking along the way. If instead it actually does find this variable declared in the local scope, it uses that one instead of any others of the same name that might appear higher up in the scope chain.

In the above example, since a variable 'os' is declared within the function, it is used and the global variable 'os' remains untouched.

<script type="text/javascript">
var os = "Windows";

function myOs()
{
  os = "Linux";  //no var here
  document.write(os + "<br />");
}

myOs();
document.write(os + "<br />");
</script>


The output of the above code is:

Linux
Linux

In the last code snippet, the variable 'os' inside the function myOs() is not declared explicitly in the local scope. So, the global scope is used thus reassigning the global variable 'os'.


Wednesday, 17 July 2013

Convert a JSON text into a JavaScript object

To convert a JSON text (i.e. a string formatted as JSON) into a JavaScript object, use  the eval() function.

Approach 1:


In this approach you should surround the JSON with parentheses. The reason for the parentheses is so the eval statement treats the text as an object initializer, rather than some other type of code.

var jsonstr='{"name":"Adis","age":25,married:false}';
var jsobj=eval("(" + jsonstr + ")");


OR

Approach 2:

The second approach is to include the variable assignment as the left side of the expression and the JSON as the right, within the eval method:

var jsonstr='{"name":"Adis","age":25,married:false}';
eval("var jsobj=" + jsonstr);

Monday, 24 June 2013

Dynamic image resize function maintaining aspect ratio

$img-width = Image width
$img-height = Image height
$cont-width = Width of the display container
$cont-height = height of the display container



function  calculate($img-width,$img-height,$cont-width,$cont-height)
{
    $adjusted=array($img-width,$img-height);
    $ratio=$img-width/$img-height;

    if($img-width>$cont-width || $img-height>$cont-height)
    {
        $adjusted[0]=$cont-width;
        $adjusted[1]=$adjusted[0]/$ratio;
       
        if($adjusted[1] > $cont-height)
        {
            $adjusted[1]=$cont-height;
            $adjusted[0]=$adjusted[1]*$ratio;
        }
    }
    return $adjusted; // adjusted[0]=required width, adjusted[1]=required height
}



If image width and image height are both less than those of the container then we need no resizing. But resizing is required if any one or both of image width and image height exceeds those of the container.

So, adjustment begins if:

if($img-width>$cont-width || $img-height>$cont-height)

Within the if condition we don't know which one exceeds. Might be width, or might be height or both of them. Whatever may be the case, we have to reduce the image size to fit into the container, but at the same time maintaining aspect ratio. That's why we have calculated the ratio as :


$ratio=$img-width/$img-height;

During reduction, a time will come when an exceeded dimension becomes equal to that of the container. Let's assume that this is the width. So,

$adjusted[0]=$cont-width; // $adjusted[0] is the required width

Hence, at this time, maintaining aspect ratio the image width should be:

$adjusted[1]=$adjusted[0]/$ratio; // $adjusted[1] is the required height

But, at this point we are not sure whether the calculated height fits in the height of the container. So, check by: 

if($adjusted[1] > $cont-height)

If the above is true, then our adjustment was incorrect. We must adjust the height first and then the width:

$adjusted[1]=$cont-height;
$adjusted[0]=$adjusted[1]*$ratio; // to maintain the ratio

Wednesday, 9 May 2012

Implementing polymorphism using the Strategy Design Pattern in PHP

The Strategy pattern is used to separate an object from its algorithms. The core idea of the pattern is the OOP principal of polymorphism. More explicitly, a Strategy pattern is a group of algorithms encapsulated inside classes that are made interchangeable so the algorithm can vary depending on the class used. Strategies are useful when you would like to decide at run time when to implement each algorithm. They can be used to vary each algorithm’s usage by its context.
The Strategy pattern has three main components: the Strategy, the Concrete Strategy, and the Context. The strategy is a common interface that ties together all supported algorithms. Usually this class is abstract. The concrete strategy is the implementation class where the logic for each different algorithm lives in the group. The context is the object that ties a concrete strategy to a particular code flow.


Advantage of the strategy pattern
As mentioned earlier, the motive behind the strategy pattern is to separate an object from its algorithms. Removing the algorithms from the host class and putting them in a separate class, enables the host to concentrate on its own job. Otherwise, the host will get messy with all the algorithms in itself with lot of if-else or switch-case statements.
Here’s an example.
Suppose a car renting service charges its customers differently at different situations – sometimes based on kilometers travelled, sometimes on hours of travel, and sometimes on a combination of both, depending on festive seasons, off-seasons etc.
There’s a billing class in the application which prepares the bill for the customer. Now the payable amount part needs a lot of calculations based on the type of charge, distance and hours of travel resulting in a lot of if-else or case statements. Addition of more billing algorithms results in inclusion of more if-else statements. To make the situation better, we simply encapsulate each faring algorithm in a separate class and depending on the context at runtime, we decide which algorithm to choose. Addition of another faring algorithm is done by simply adding another class i.e. extending the abstract class FareStrategy.

<?php
abstract class FareStrategy
{
    abstract function calculateFare($kms, $hrs);
}

class HourlyFareStrategy extends FareStrategy
{
    private $normalHours=8;
    private $normalHourRate=250;
    private $additionalHourRate=200;
   
    function calculateFare($kms, $hrs)
    {
        if($hrs > $this->normalHours)
        {
            $fare=($this->normalHours*$this->normalHourRate)+(($hrs-$this->normalHours)*$this->additionalHourRate);
            return $fare;
        }
        else
        {
            $fare=$hrs*$this->normalHourRate;
            return $fare;
        }       
    }
} //end class HourlyFareStrategy

class KmsFareStrategy extends FareStrategy
{
    private $normalKms=100;
    private $normalKmRate=15;
    private $additionalKmRate=13;
   
    function calculateFare($kms, $hrs)
    {
        if($kms>$this->normalKms)
        {
            $fare=($this->normalKms*$this->normalKmRate)+(($kms-$this->normalKms)*$this->additionalKmRate);
            return $fare;
        }
        else
        {
            $fare=$kms*$this->normalKmRate;
            return $fare;
        }
    }
}//end class KmsFareStrategy

class FaringContext
{
    private $_fareStrategy;
   
    public function __construct(FareStrategy $fareStrategy)
    {
        $this->_fareStrategy=$fareStrategy;
    }
   
    public function getFare($kms,$hrs)
    {
        return $this->_fareStrategy->calculateFare($kms,$hrs);
    }
} //end class FaringContext

//main program

$context=new FaringContext(new HourlyFareStrategy());
$fare=$context->getFare(120,6);
echo $fare;

echo '<br />';

$context=new FaringContext(new KmsFareStrategy());
$fare=$context->getFare(120,6);
echo $fare;

?>

Wednesday, 18 April 2012

Simple pagination class in PHP

File: paginator.php
 
<?php
require_once 'DB.php';

class Paginator
{
    private $queryStr;
    private $pageSize;
    private $currentPage=1;
    private $conn;
    private $totalRecords;
    private $totalPages;
   
    public function __construct($queryStr,$pageSize,$totalRecords)
    {
        $this->conn=DB::db_connect();
        $this->queryStr=$queryStr;
        if(isset($_REQUEST['showpage']))
        $this->currentPage=$_REQUEST['showpage'];
        $this->pageSize=$pageSize;
        $this->totalRecords=$totalRecords;
        $this->totalPages=ceil(($this->totalRecords)/($this->pageSize));
    }
   
    public function getPage()
    {
        $offset=($this->currentPage-1)*($this->pageSize);
        $queryStr="$this->queryStr limit $offset,$this->pageSize";   
        $result=$this->conn->query($queryStr);
        return $result;               
    }
   
    public function showNavigationLinks()
    {
        echo "<div id='nav'>";
       
        if($this->currentPage>1)
        {
            echo "<a href=index.php?showpage=".($this->currentPage-1).">Prev</a>";
        }
       
        echo "&nbsp";
       
        for($i=1;$i<=$this->totalPages;$i++)
        {
            echo "<a href=index.php?showpage=".$i.">".$i."</a>&nbsp";
        }
       
        echo "&nbsp";
       
        if(($this->totalRecords)>($this->currentPage)*($this->pageSize))
        {
            echo "<a href=index.php?showpage=".($this->currentPage+1).">Next</a>";
        }
       
        echo "</div>";
       
    }
   
}

?>

File: DB.php

<?php

class DB
{
    public static function db_connect()
    {
       $result = new mysqli('localhost', 'root', '', 'test');
       if (!$result)
          return false;
       return $result;
    }   

}

?>

File: index.php

<?php

require_once 'paginator.php';
require_once 'DB.php';

//I have a table 'countries' having two fields id, name

$mainquery='Select * from countries';
$countquery='Select count(id) as rec_count from countries';
$conn=DB::db_connect();
$result=$conn->query($countquery);
$row=$result->fetch_object();
$totalRecords=$row->rec_count;



$pg=new Paginator($mainquery,6,$totalRecords);
$pageData=$pg->getPage();

while($row=$pageData->fetch_object())
{
    echo '<br />'.$row->id.'-'.$row->name;   
}
echo '<br />';
$pg->showNavigationLinks();

?>

Monday, 16 April 2012

Using bitwise operators to assign permission levels of users

Bitwise operators if tactfully used can be very efficient in storing permission levels of users in an application. Notice there is something special about the numbers 1, 2, 4, 8 and 16. In each of these values the left- most 1 - bit advances a placeholder. These are powers of 2 (20=1, 21 =2, 22 =4, 23 =8, 24 =16 and so forth). This is the reason why they can be used as the integer values for the permission constants.

For eg., let the permissions be

1 = 0000 0001 for READ,
2 = 0000 0010 for CREATE,
4 = 0000 0100 for UPDATE,
8 = 0000 1000 for DELETE

This means, permissions of READ and UPDATE both would be specified by turning the 1st and 3rd bits on from the right, i.e., 0000 0101, which we can get by applying bitwise ‘or’ on 1 and 4.
1 |4 = 5 = 0000 0101.

<?php

class User
{
 //Permission levels
   const READ=1;
   const CREATE=2;
   const UPDATE=4;
   const DELETE=8;
     
   public $name;
   public $permission;
     
   public function addPermission($perm)
   {
     $this->permission=$perm;
   }
     
   public function removePermission($perm)
   {
     $this->permission = ~$perm & $this->permission;
   }
     
   public function showDetails()
   {
     echo '<br />';
     echo $this->name;
     echo ($this->permission & self::READ)? '<br />READ - YES':'<br />READ - NO';
     echo ($this->permission & self::CREATE)? '<br />CREATE - YES':'<br />CREATE - NO';
     echo ($this->permission & self::UPDATE)? '<br />UPDATE - YES':'<br />UPDATE - NO';
     echo ($this->permission & self::DELETE)? '<br />DELETE - YES':'<br />DELETE - NO';
    }
     
}

$user=new User();
$user->name='Barun Samanta';

$user->addPermission(User::READ|User::CREATE);
$user->showDetails();

$user->removePermission(User::CREATE);
$user->showDetails();

?>

In the code, to see if the user has been granted a particular permission, just mask out the value you are looking for with bitwise-and.

$this->permission & self::CREATE

Since in the CREATE permission all bits are zeros except the 2nd one from the right, therefore the result of the operation ($this->permission & self::CREATE) would evaluate to true if the 2nd bit from right in $this->permission
is 1 and false if the same bit is 0.

To remove a permission we apply ~$perm & $this->permission.
This means, if the permission we want to remove be UPDATE (0000 0100) from the permission set 0000 0101 (READ, UPDATE) we apply a bitwise AND of ~0000 0100 = 1111 1011 on 0000 0101. We get 0000 0001 as result. In the number 1111 1011, since all the bits are 1 except the 3rd from the right, the bitwise-and operation simply turns-off the bit for UPDATE keeping all other bits in the permission-set 0000 0101 unchanged.



Note: To store the permission in the MySQL database, simply use a column of type int(10) unsigned.

document.write() overwrites the entire page

document.write is a function which basically outputs whatever is given to it. But sometimes, improper usage may overwrite the entire page d...