Showing posts with label Liferay integration. Show all posts
Showing posts with label Liferay integration. Show all posts

Thursday, January 27, 2011

Liferay (s)mashup - Google Maps


In the previous blog, we saw how to fire events asynchronously on the client side. In this blog, we will see the integration of Google Maps in a portlet.
Showing Google Maps in a portlet is a breeze. For this, create a portlet called 'Visual View'. This portlet displays the Google Map for visual interaction. It receives the source and destination from the Plan Your Travel portlet and shows the road route in the map.

Using Google Maps API

Google Maps API is a collection of web services providing geographic data for creating maps applications. These web services use HTTP requests to specific URLs, passing URL parameters as arguments to the services. Generally, these services return data in the HTTP request as either JSON or XML for parsing and/or processing by an application.  Let's get straight to the code.

Code Listing

<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet"%>
<portlet:defineObjects />
<style type="text/css">
#map_canvas {
    height: 500px;
    width: 400px
}
</style>

<script type="text/javascript">
    var <portlet:namespace />map;
    var <portlet:namespace />geocoder;
    var <portlet:namespace />directionDisplay;
    var <portlet:namespace />directionsService;
    var <portlet:namespace />rendererOptions = {
        draggable : true //make the map points draggable
    };
    var <portlet:namespace />initialLocation;
    var <portlet:namespace />infowindow;

    function <portlet:namespace />initialize() {
        var myLatlng = new google.maps.LatLng(-34.397, 150.644);
        var myOptions = {
            zoom : 8,
            center : myLatlng,
            mapTypeId : google.maps.MapTypeId.ROADMAP
        };

        <portlet:namespace />map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
        <portlet:namespace />geocoder = new google.maps.Geocoder();
        <portlet:namespace />directionsService = new google.maps.DirectionsService();
        <portlet:namespace />directionsDisplay = new google.maps.DirectionsRenderer(
                                                    <portlet:namespace />rendererOptions);
        <portlet:namespace />directionsDisplay.setMap(<portlet:namespace />map);
        <portlet:namespace />infowindow = new google.maps.InfoWindow();

        //geo location
        // Try W3C Geolocation method (Preferred)
        if (navigator.geolocation) {
            browserSupportFlag = true;
            navigator.geolocation.getCurrentPosition(function(position) {
                <portlet:namespace />initialLocation = new google.maps.LatLng(
                        position.coords.latitude, position.coords.longitude);
                contentString = "Location found using W3C standard";
                <portlet:namespace />map
                        .setCenter(<portlet:namespace />initialLocation);
                var marker = new google.maps.Marker({
                    map : <portlet:namespace />map,
                    position : <portlet:namespace />initialLocation
                });
            }, function() {
                <portlet:namespace />handleNoGeolocation(browserSupportFlag);
            });
        } else if (google.gears) {
            // Try Google Gears Geolocation
            browserSupportFlag = true;

            var geo = google.gears.factory.create('beta.geolocation');
            geo.getCurrentPosition(function(position) {
                <portlet:namespace />initialLocation = new google.maps.LatLng(
                        position.latitude, position.longitude);
                contentString = "Location found using Google Gears";
                <portlet:namespace />map.setCenter(<portlet:namespace />initialLocation);
                <portlet:namespace />infowindow.setContent(contentString);
                <portlet:namespace />infowindow.setPosition(<portlet:namespace />initialLocation);
                <portlet:namespace />infowindow.open(<portlet:namespace />map);
            }, function() {
                <portlet:namespace />handleNoGeolocation(browserSupportFlag);
            });
        } else {
            // Browser doesn't support Geolocation
            browserSupportFlag = false;
            <portlet:namespace />handleNoGeolocation(browserSupportFlag);
        }

        //add listener for directions change
        google.maps.event.addListener(
            <portlet:namespace />directionsDisplay,
            'directions_changed',
            function() {
                var leg = <portlet:namespace />directionsDisplay.directions.routes[0].legs[0];
                Liferay.fire('directionsChanged', {
                        origin : leg.start_address,
                        destination : leg.end_address
                });
            });
    }

    function <portlet:namespace />handleNoGeolocation(errorFlag) {
        if (errorFlag == true) {
            <portlet:namespace />initialLocation = newyork;
            contentString = "Error: The Geolocation service failed.";
        } else {
            <portlet:namespace />initialLocation = siberia;
            contentString = "Error: Your browser doesn't support geolocation. Are you in Siberia?";
        }
        <portlet:namespace />map.setCenter(<portlet:namespace />initialLocation);
        <portlet:namespace />infowindow.setContent(contentString);
        <portlet:namespace />infowindow.setPosition(<portlet:namespace />initialLocation);
        <portlet:namespace />infowindow.open(<portlet:namespace />map);
    }
 
    function <portlet:namespace />loadScript() {
        var script = document.createElement("script");
        script.type = "text/javascript";
        script.src = "http://maps.google.com/maps/api/js?sensor=false&callback=<portlet:namespace />initialize";
        document.body.appendChild(script);
    }

    window.onload = <portlet:namespace />loadScript;

    function <portlet:namespace />showDirection(source, destination) {
        var request = {
            origin : source,
            destination : destination,
            travelMode : google.maps.DirectionsTravelMode.DRIVING
        };
        <portlet:namespace />directionsService.route(request, function(
                response, status) {
            if (status == google.maps.DirectionsStatus.OK) {
                <portlet:namespace />directionsDisplay.setDirections(response);
            }
        });
    }

    Liferay.on('planTravel', function(event) {
        <portlet:namespace />showDirection(event.origin, event.destination);
    });
</script>

<div id="map_canvas"></div>

The Google Maps API requires a single div element with an id in the html page to be rendered. Here, we have given the id as 'map_canvas'. The loadScript() method dynamically loads the maps script file. This speeds up the page display. The initialize() method loads the map view with pre-configured values. Also, latest versions of most browsers support geolocation. Geolocation allows tracking user's current location. This information is used to load the map with user's current location.
Note the listener for the directions changed event from the map in the initialize function. When the directions changed event occurs, we republish the event using Liferay's event manager to notify other portlets. Other portlets receives this event to update their display. We saw this in the search form in the first part of this blog series.
To use the two portlets that we have developed so far, type in the names of cities in the origin and destination and hit the Search button. The road rout between the two cities will be shown in the Google map. Now, try changing the cities by dragging the marker in the map. The cities' names are updated in the Plan Your Travel portlet. We will see interesting applications of this event model in the next few portlets.
For more details working on the Google Maps API, see this and this.

Monday, November 15, 2010

Integrating Coin Slider with Liferay with zero development

In this blog, I will show you how to integrate the Coin Slider library in a Liferay portlet without having to develop any portlet. Coin Slider is a jQuery based image slider with many effects for image transition.

Note: This solution is based on Liferay 6.0.5

Download and extract the latest version of the Coin Slider library from http://workshop.rs/projects/coin-slider/

Create a folder slideshow in the document library of the community where you want to use the slider. Add the files coin-slider-min.js, coin-slider-styles.css, jquery-1.4.2.min.js to the slideshow folder. Create a new file javascript.js file in filesystem. Add the following code to this file:

$(document).ready(function() {
    $("#coin-slider").coinslider({ hoverPause: false });
});
 

Upload the javascript.js file to the slideshow document library. The slideshow folder should now look like this:

Next upload few images that you want to display in the slider in the Image Gallery.

There are 3 images in the image gallery above.

Now create a new web content structure. Name it coin-slideshow. Add xml schema definition to the structure as shown below:
Click Save when done.

Create a new web content template and name it coin-slideshow-template. Select coin-slideshow as the structure for the new template. Click the Launch Editor button. In the dialog that appears, paste the following code:


<link href="$css.getData()" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="$jquery.getData()"></script>
<script type="text/javascript" src="$coinjs.getData()"></script>
<script type="text/javascript" src="$slidestart.getData()"></script>

<div id="coin-slider">
#foreach ($item in $slide.getSiblings())
   #foreach ( $itemData in $item.getChildren() )
        #if ( "$itemData.getName()" == "href" )
          #set ( $href = $itemData.getData() )
        #elseif ( "$itemData.getName()" == "img_src" )
          #set ( $img_src = $itemData.getData() )
        #elseif ( "$itemData.getName()" == "description" )
          #set ( $description = $itemData.getData() )
        #end
    #end
    <a href="$href"><br />
        <img src="$img_src" />
        <span>$description</span>
    </a>
#end
</div>



Click Update button when done. Click Save again in the main dialog.

Now is the time to add the slider in our page. Add Web Content Display portlet to the page where you want the slider. Click the Add Web Content link in the portlet to create content for the portlet. In the new dialog box, give a name to the content, say Slideshow. Change the structure of the web content by clicking the Choose button under the Structure section on the right. Select the structure coin-slideshow that we created earlier. This will automatically choose the template that we associated with the structure. Instead of the HTML editor, a web form with fields are shown.

In the css field, choose the coin-slider-styles.css from the document library. Similarly, choose jquery-1.4.2.min.js for jquery field, coin-slider-min.js for coinjs field and javascript.js for coinstart field. For the first slide, name it slide1. Select a image from the Image Gallery for the img_src field. Select target location when an image is clicked from the dropdown list for the href field. Type some text to be displayed for the image in the description field. Similarly, add more slides for each image that you want to be displayed.


Click Publish button to save the content and make it viewable.