Working with Google Maps Javascript API V3

Google Maps Javascript API V3 is an awesome API provided by Google. Today I will give you a little flavor about this API. Later I will write about some advance features.

Here is a simple tool, created using this API. Click on the marker, the Latitude and Longitude position will be displayed in a window and also in the textbox. If you set a Latitude, Longitude point in the textbox and click on the button, that point will be shown in the map with a marker.

Latitude

Longitude


Now I'm going to show you, how you can make this tool..

First load the Google Maps Javascript API and the latest jQuery version . Then design the user interface.

 
<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?sensor=false"></script>
<script type="text/javascript" src="http://zmodal.googlecode.com/files/jquery-1.6.1.min.js"></script>

<div style="float:left; width:200px; border:1px solid #CCCCCC;">
        Latitude <input type="text" id="tbLattitude"/><br/>
        Longitude <input type="text" id="tbLongitude"/><br/>
        <input type="button" name="btCal" value="Show in Map" onclick="return showInMap();" />
    </div>
    <div id="map_canvas" style="float:left;width: 400px; height: 400px; border: 2px solid #999;margin-left:10px;">
    </div>

The DIV element with id 'map_canvas' will be the container of the Map. This id will be required when you create the map object to display in this div.

Now come to the Javascript part..

Set the window onLoad callback method and in that method, call the LoadMap method with initial latitude,longitude.

 
google.maps.event.addDomListener(window, 'load', initializeMap);
function initializeMap() {
  LoadMap(23.70992, 90.40714);
}

In the LoadMap method first create a LatLng object using the lat, long parameter

 
function LoadMap(lat, longitude) {
var latlng = new google.maps.LatLng(lat, longitude);
Create a Map object using map options and the container ID
 
var myOptions = {
  zoom: 12,
  center: latlng, // previously created LatLng object
  mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);

For the information window first create the content of the window then create a InfoWindow object using the content. This object will be later used in the onClick event of the Marker.

var contentString = '
' + 'Latitude : '+lat+'
Longitude : ' + longitude + '' '
'; var infowindow = new google.maps.InfoWindow({ content: contentString });

Now create the Marker object using the LatLng and Map object.

var marker = new google.maps.Marker({
  position: latlng,
  map: map,
  title: 'Location',
  draggable: true,
  animation: google.maps.Animation.DROP
});

Finally add an event listener for the Marker object. First open the InfoWindow object then call the method which set LatLng value to the textbox.

  google.maps.event.addListener(marker, 'click', function (event) {
    infowindow.open(map, marker);
    setLatLongToTextBox(event.latLng);
  });

}
Here is the setLatLongToTextBox and showInMap method
function setLatLongToTextBox(latlong) {
  var latstr = latlong + '';
  var value = latstr.slice(1, latstr.length - 1);
  var latlongs = value.split(",");
  $("#tbLattitude").attr("value", latlongs[0]);
  $("#tbLongitude").attr("value", latlongs[1]);
}

//this method is used as the onclick method of the button 
function showInMap() {
  var lat = $("#tbLattitude").attr("value");
  var longitude = $("#tbLongitude").attr("value");
  LoadMap(lat, longitude);
  return false;
}

Working with Google Chart Tools : Create a Geochart

Geochart can be a handy tool if you want to represent the demographic behavior of your service. In my recent project for Bangladesh Post Office I used this tool to represent the usage of their service in each Division of Bangladesh. Another big example is the Google Analytics where you can view the location based visitor information of your site. Here I am going to show you how you can use this in your project.

First load the Google's Javascript API
<script src="https://www.google.com/jsapi" type="text/javascript">  
</script> 

Now create a DIV element and give it an ID. This id will be required when you create the chart object to display in this div.

<div id="map">
    </div>

In your Javascript code first load the geomap package and set the onLoadCallback method name.

<script type="text/javascript">
 google.load('visualization', '1', { 'packages': ['geomap'] });
 google.setOnLoadCallback(drawGeoChart);

In the callback method first create a DataTable object add two columns. Just give a suitable name as per your requirement.

 function drawGeoChart() {
            var data = new google.visualization.DataTable();
            data.addRows(6);
            data.addColumn('string', 'Country');
            data.addColumn('number', 'Visit');

Now set some value to the DataTable. The first column can be an Address, country name, region name locations, or US metropolitan area codes. For country and region name follow this ISO-3166 code or text equivalent to the code. The second column will be the value of the area.

            data.setValue(0, 0, 'Germany');
            data.setValue(0, 1, 600);
            data.setValue(1, 0, 'United States');
            data.setValue(1, 1, 500);
            data.setValue(2, 0, 'Bangladesh');
            data.setValue(2, 1, 400);
            data.setValue(3, 0, 'Canada');
            data.setValue(3, 1, 200);
            data.setValue(4, 0, 'France');
            data.setValue(4, 1, 200);
            data.setValue(5, 0, 'RU');
            data.setValue(5, 1, 300);
Finally configure some property of the chart and draw it using the data previously set.
  var regionOptions = {};
  regionOptions['width'] = '400';
  regionOptions['height'] = '250';
  // Look the div id is used here to create the chart object 
  var regionChart = new  google.visualization.GeoMap(document.getElementById('map'));
  regionChart.draw(data, regionOptions);
        
}
</script>
And here is the outcome. On mouse over you can view the data of the area



You can load the chart data by a webservice call. For C# see my previous blog. Visit this link to know more about Geochart.

Working with Google Chart Tools in C# .NET : Create a Simple Pie Chart

If you want to load a chart asynchronously in C# . NET, Google Chart Tools will be the perfect choice for you. It is easy to use and enough flexible to customize. Suppose you want to show how many students in your class like Pizza, Burger, Hotdog, and Fried Chicken in a Pie chart. Here I will show you how to load the students' data from server side using WebService and show it in a chart asynchronously.

First create a new WebService file suppose GoogleChart.asmx . In this file create a Public Class named FoodLikingCount

    public class FoodLikingCount
    {
        public int PizzaCount { get; set; }
        public int BurgerCount { get; set; }
        public int HotdogCount { get; set; }
        public int FriedChickenCount { get; set; }
    }

After the class declaration add the following line

[System.Web.Script.Services.GenerateScriptType(typeof(FoodLikingCount))]

It will enable you to use the FoodLikingCount object in your Javascript code.

Create a new WebMethod in the WebService class named GetFoodLikingCountData

[WebMethod]
public FoodLikingCount GetFoodLikingCountData()
{
       FoodLikingCount countModel = new FoodLikingCount 
       {
           PizzaCount = 12,
           BurgerCount = 16,
           HotdogCount = 8,
           FriedChickenCount = 4,
       };
       // you can also load data from your database here

       return countModel ;
}

Now come to client side code. Create an aspx file named GoogleChartToolTest.aspx and add this line between head tag.

 <script src="https://www.google.com/jsapi" type="text/javascript">
 </script> 

Create a DIV element and give it an ID. This id will be required when you create the chart object to display in this div. Also add a ScriptManager to call your webservice method.

    <form id="form1" runat="server">
        <asp:ScriptManager ID="sm1" runat="server">
            <Services>
                 <asp:ServiceReference Path="~/[your_package]/GoogleChart.asmx" />
            </Services>
        </asp:ScriptManager>
    </form>
    <div id="pie_chart">
    </div>

Here is the Javascript code which you require to load data through the webservice call, create, and show chart in the div.

<script type="text/javascript">

//load the corechart package, the pie chart is in this package
google.load('visualization', '1', { packages: ['corechart'] });

//provide the method name which you want to call as onload callback
google.setOnLoadCallback(loadFoodLikingChart);

function loadFoodLikingChart()
{
       [your_package].GoogleChart.GetFoodLikingCountData(
            function (ws_rsp) {
              var foodLikingData= new google.visualization.DataTable();
              foodLikingData.addColumn('string', 'Food');
              foodLikingData.addColumn('number', 'Count');
              foodLikingData.addRows(4);
              
              foodLikingData.setValue(0, 0, "Pizza");
              foodLikingData.setValue(0, 1, ws_rsp.PizzaCount );
              foodLikingData.setValue(1, 0, "Burger");
              foodLikingData.setValue(1, 1, ws_rsp.BurgerCount );
              foodLikingData.setValue(2, 0, "Hotdog");
              foodLikingData.setValue(2, 1, ws_rsp.HotdogCount );
              foodLikingData.setValue(3, 0, "Fried Chicken");
              foodLikingData.setValue(3, 1, ws_rsp.FriedChickenCount );

              var options = {};
              options ['width'] = '400';
              options ['height'] = '250';
              options ['chartArea'] = { left: 20, top: 20, width: '95%', height: '90%' };

              // Look the div id is used here to create the chart object
              var chart = new google.visualization.PieChart(document.getElementById('pie_chart'));
              chart.draw(foodLikingData,options);
            },
            function (e) {
               alert("Error");
           }
      );
}
</script>

The result will be like this.

Visualize the DataTable as a two dimensional array. It will help you to understand the above code. Here is the Google Chart Gallery. You will get a lot of example there.

zModal, An Easy to Use jQuery Modal Plugin



There are lots of jQuery modal plugin available in the web. For my current project I need one which, I can easily customize. I realized creating a modal by myself is the best way for gaining maximum freedom.

It is very simple and easy to use and customizable. You can give it a try. Here I will describe how to use it.

First download all the required files from here and include in the page.

Create a DIV and give it an id and set the display property 'none'.

<div id="modalContent" style="width:400px; display:none;">
</div>
You can insert any content between the DIV tag.

Now place a button, the onclick event of which will show the modal
<input type="button" name="name2" value="Show Modal" 
onclick="$('#modalContent').showModal();" />
Here is an example. Click on the button and a modal will pop up.


<div id="modalContent" style="width:400px; height: 150px; display: none;">
<p style="padding-left:20px;">
modalContent:
Click the close button to hide the modal
You can also press ESCAPE button to hide the modal
</p>
</div>
<input type="button" name="name2" value="Show Modal" 
onclick="$('#modalContent').showModal();" />

There are some configurable options for the modal.
setModalButtonCss : Set True if you want to display all buttons contained in the modal in a zModal style.
hideDefaultClose : Set True if you want to hide the default close button.
opacity : You can control the opacity of the background with this parameter.
bgColor : You can change the background color with this parameter.

Here is an example with all the options are set.
<div id="modalContent2" style="width:400px; display:none;">
<p>
User Name:<br />
<input id="tbUname" type="text" name="uName">
</p>
<p>
Password:<br />
<input id="tbPass" type="text" name="pass">
</p>
<p>
<input type="button" name="login" value="Login" onclick="$('#modalContent2').hideModal()" />
</p>
</div>
<input type="button" name="name" value="Show Modal 1" 
onclick="$('#modalContent2').showModal({'setModalButtonCss': 'True', 
'hideDefaultClose' : 'True', 
'opacity' : '.2', 
'bgColor' : '#7FCFF9' });" />
Click on the button to view the example

If you want to hide your modal like the onclick event of the Login button write this code
$('#divID').hideModal();

Remember Old School OO Principle While Using RegularExpressionValidator

I'm sure all of you are frequently using RegularExpressionValidator in your project. But are sure you are not repeating same expression in multiple pages? Is your code impervious to Change? If you are a bit careful while writing code, you can avoid this. And your friend will be 'Inheritance'.

Suppose you are using a RegularExpressionValidator to validate phone number. You may possibly going to write following code block

<asp:RegularExpressionValidator ID="revPhoneNumber" Display="Dynamic" ErrorMessage="Valid phone no required." ControlToValidate="tbPhoneNumber" ValidationExpression="^\d{8,}$" runat="server">*</asp:RegularExpressionValidator>

If you need this Validator in more than one page, then writing the same code block in every page obviously produces code duplication. Moreover if your project manager asks you to allow '+' at the beginning of the phone number then you have to change the regular expression in all pages. That will be surely a painful task for you. You can make your life easy by following approach.

Create your own validator by inheriting RegularExpressionValidator. Assign a regular expression to the ValidationExpression property

namespace TestValidator.Validators
{
    public class PhoneNumberValidator : RegularExpressionValidator
    {
        public PhoneNumberValidator()
        {
            ValidationExpression = "^\\d{8,}$";
        }
    }
}

To use your own PhoneNumberValidator first add this in the Registry
<%@ Register Assembly="TestValidator(Project Name)" Namespace="TestValidator.Validators" TagPrefix="myvalidators" %>

Then use this in the following way

<myvalidators:PhoneNumberValidator ID="revPhoneNumber" Display="Dynamic" ErrorMessage="Valid phone no required." ControlToValidate="tbPhoneNumber" runat="server">*</myvalidators:PhoneNumberValidator>

Now it is a matter of seconds to accomplish what your project manager wants.

Working With GXT (Ext GWT) Grid : Add Filter Functionality

Yesterday I was looking for something new (new widgets, new functionality) in the latest GXT version (2.2.1) and found that, it is now providing grid filtering support. You can add MS Excel like filtering option in your application through this. I think it was the most demanded and expected feature from the GXT developers which can be highly utilized in Enterprise Reporting. I am going to describe how to add this functionality in GXT Grid.

Create a new project named GxtFilterGrid and add GXT library in the project. As like my previous blogs about GXT Grid I have used the same Employee model and TestData class for generating data. You will find the code of these classes here. Go to the onModuleLoad method of GxtFilterGrid class and remove all the auto generated code of this method.

First create a list of ColumnConfig and a ColumnModel from this list.

List<ColumnConfig> configs = new ArrayList<ColumnConfig>();

  ColumnConfig column = new ColumnConfig();
  column.setId("name");
  column.setHeader("Employee Name");
  column.setWidth(200);
  configs.add(column);

  column = new ColumnConfig("department", "Department", 150);
  column.setAlignment(HorizontalAlignment.LEFT);
  configs.add(column);

  column = new ColumnConfig("designation", "Designation", 150);
  column.setAlignment(HorizontalAlignment.LEFT);
  configs.add(column);

  column = new ColumnConfig("salary", "Slary", 100);
  column.setAlignment(HorizontalAlignment.RIGHT);
  final NumberFormat number = NumberFormat.getFormat("0.00");
  GridCellRenderer<Employee> checkSalary = new GridCellRenderer<Employee>() {
   @Override
   public Object render(Employee model, String property,
     com.extjs.gxt.ui.client.widget.grid.ColumnData config,
     int rowIndex, int colIndex, ListStore<Employee> store,
     Grid<Employee> grid) {
    double val = (Double) model.get(property);
    String style = val < 70000 ? "red" : "green";
    return ""
      + number.format(val) + "";

   }
  };
  column.setRenderer(checkSalary);
  configs.add(column);

  column = new ColumnConfig("joiningdate", "Joining Date", 100);
  column.setAlignment(HorizontalAlignment.RIGHT);
  column.setDateTimeFormat(DateTimeFormat.getShortDateFormat());
  configs.add(column);

  ColumnModel cm = new ColumnModel(configs);

Now create different types of filters like Numeric, String, Date, etc. Constructor of these filter classes takes the column name to bind the specific filter with a specific column.

NumericFilter numericFilter = new NumericFilter("salary");
StringFilter nameFilter = new StringFilter("name");
StringFilter designationFilter = new StringFilter("designation");
DateFilter dateFilter = new DateFilter("joiningdate"); 

You can also add a ListStore as a filtering option with the help of ListFilter. For adding a list filter, create a ListStore of ModelData or your own BaseModel class and add this as the source of ListFilter.

ListStore<ModelData> departmentStore = new ListStore<ModelData>();
departmentStore.add(departement("General Administration"));
departmentStore.add(departement("Information Technology"));
departmentStore.add(departement("Marketing"));
departmentStore.add(departement("Accounts"));
 //department method is stated later
ListFilter listFilter = new ListFilter("department", departmentStore);
listFilter.setDisplayProperty("departmentname");

Display Property of the ListFilter will be the key name of your model data. Now create a GridFilters instance and add all the filters created above with this instance.

GridFilters filters = new GridFilters();
filters.setLocal(true);
filters.addFilter(numericFilter);
filters.addFilter(nameFilter);
filters.addFilter(designationFilter);
filters.addFilter(dateFilter);
filters.addFilter(listFilter);

Finally create a ListStore of Employee Model and, a Grid from this ListStore and ColumnModel. Add the GridFilters instance as the Plugin of the Grid.

ListStore<Employee> employeeList = new ListStore<Employee>();
employeeList.add(TestData.getEmployees());

Grid<Employee> grid = new Grid<Employee>(employeeList, cm);
grid.setStyleAttribute("borderTop", "none");
grid.setAutoExpandColumn("name");
grid.setBorders(true);
grid.setStripeRows(true);
grid.getView().setForceFit(true);
grid.setColumnLines(true);
grid.addPlugin(filters);

ContentPanel cp = new ContentPanel();  
cp.setBodyBorder(false);  
cp.setHeading("Employee List With Filtering Option");  
cp.setButtonAlign(HorizontalAlignment.CENTER);  
cp.setLayout(new FitLayout());  
cp.setSize(700, 300); 
cp.add(grid);  
RootPanel.get().add(cp);
Here is the code of department method which is used previously.
private ModelData departement(String departement) {
  ModelData model = new BaseModelData();
  model.set("departmentname", departement);
  return model;
}

That's all. Run the project and the output will be like this

Java Image Utility

Few days ago I did some image manipulation tasks like resizing, cropping, etc. java awt provides some useful functionality to do this type of tasks. Here I am going to share how I accomplish the tasks and finally and ImageUtility Class which you can use in your project.

Image Resizing
First read the image with the ImageIO which returns a BufferedImage. Then create another BufferedImage instance with the new width, height and image type.

BufferedImage originalImage = ImageIO.read(imageFile); 
BufferedImage scaledBI = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);

Now get the Graphics2D component of the new scaled image and draw it.

g.drawImage(originalImage, 0, 0, 100, 100, null);
g.dispose();

If you want to preserve the image quality, add following line of code before disposing the graphics component.

g.setComposite(AlphaComposite.Src);
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.setRenderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);

It's simple, is not it?

Image Croping

Read the image with ImageIO as stated previously and get the sub image of the original image.

BufferedImage originalImage = ImageIO.read(imageFile); 
originalImage .getSubimage(0,0, 100, 100);

First two parameter of the getSubimage method is the x,y coordinate, from where you want to begin cropping.


Get Byte Array of an Image

Sometimes you need this specially when you want to save an image in database in blob data type . We can get byte[] of an image with the help of ByteArrayOutputStream and ImageIO class.


BufferedImage originalImage = ImageIO.read(imageFile); 
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(originalImage , getImageExtension(), baos);
//getImageExtension method is stated later
baos.flush();
byte[] imageData = baos.toByteArray();
baos.close();

ImageUtility.java

All the above actions can be encapsulated into a simple ImageUtility class.

import java.awt.AlphaComposite;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import org.openide.util.Exceptions;

/**
 *
 * @author ratul
 */
public class ImageUtility
{
    private File imageFile;
    private BufferedImage image;
    public ImageUtility()
    {
    }

    public ImageUtility(File imageFile)
    {
        try
        {
            this.imageFile = imageFile;
            image = ImageIO.read(imageFile);
        }
        catch (IOException ex)
        {
            Exceptions.printStackTrace(ex);
        }
    }

    public ImageUtility(File imageFile, BufferedImage image)
    {
        this.imageFile = imageFile;
        this.image = image;
    }


    public File getImageFile()
    {
        return imageFile;
    }

    public void setImageFile(File imageFile)
    {
        this.imageFile = imageFile;
    }

    public BufferedImage getImage()
    {
        return image;
    }

    public void setImage(BufferedImage image)
    {
        this.image = image;
    }
    
    public String getImageExtension()
    {
        String fName = imageFile.getName();
        return fName.substring(fName.indexOf(".")+1, fName.length());
    }
    public BufferedImage getResizedCopy(int scaledWidth, int scaledHeight, boolean preserveAlpha)
    {
        return getResizedCopyOfImage(image, scaledWidth, scaledHeight, preserveAlpha);
    }
    
    public byte[] getByte()
    {
        return getByteOfImage(image);
    }
    public ImageIcon getImageIcon()
    {
        return new ImageIcon(image);
    }
    public BufferedImage getCropedImage(int x, int y, int width, int height)
    {
        return getCropedImageOfImage(image, x, y, width, height);
    }
    public BufferedImage getCropedImageFromCenter(Dimension panelDimension,int clipedWidth, int clipedHeight)
    {
        return getCropedImageOfImageFromCenter(image, panelDimension, clipedWidth, clipedHeight);
    }

    public BufferedImage getResizedCopyOfImage(BufferedImage originalImage,int scaledWidth, int scaledHeight, boolean preserveAlpha)
    {
        int imageType = preserveAlpha ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
        BufferedImage scaledBI = new BufferedImage(scaledWidth, scaledHeight, imageType);
        Graphics2D g = scaledBI.createGraphics();
        if (preserveAlpha)
        {
                g.setComposite(AlphaComposite.Src);
        }
        g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
        RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        g.setRenderingHint(RenderingHints.KEY_RENDERING,
        RenderingHints.VALUE_RENDER_QUALITY);
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
        RenderingHints.VALUE_ANTIALIAS_ON);
        g.drawImage(originalImage, 0, 0, scaledWidth, scaledHeight, null);
        g.dispose();
        return scaledBI;
    }

    public byte[] getByteOfImage(BufferedImage sourceImage)
    {
        try
        {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ImageIO.write(sourceImage, getImageExtension(), baos);
            baos.flush();
            byte[] imageData = baos.toByteArray();
            baos.close();
            return imageData;
        }
        catch (IOException ex)
        {
            Exceptions.printStackTrace(ex);
            return null;
        }
    }

    public ImageIcon getImageIconFromImage(BufferedImage sourceImage)
    {
        return new ImageIcon(sourceImage);
    }

    public BufferedImage  getCropedImageOfImage(BufferedImage sourceImage, int x, int y, int width, int height)
    {
        return sourceImage.getSubimage(x, y, width, height);
    }
    public BufferedImage getCropedImageOfImageFromCenter(BufferedImage sourceImage, Dimension panelDimension,int clipedWidth, int clipedHeight)
    {
        Rectangle clip = new Rectangle(clipedWidth, clipedHeight);
        clip.x = (panelDimension.width - clip.width) / 2;
        clip.y = (panelDimension.height - clip.height) / 2;
        int x0 = (panelDimension.width - sourceImage.getWidth()) / 2;
        int y0 = (panelDimension.height - sourceImage.getHeight()) / 2;
        int x = clip.x - x0;
        int y = clip.y - y0;
        return sourceImage.getSubimage(x, y, clip.width, clip.height);
    }
}

Total Pageviews

Tags

Twitter Updates
    follow me on Twitter

    Followers