Open Source Software Technical Articles

Want the Best of the Wazi Blogs Delivered Directly to your Inbox?

Subscribe to Wazi by Email

Your email:

Connect with Us!

Current Articles | RSS Feed RSS Feed

Creating a Mashup Dojo Widget

  
  
  

Dojo is a powerful user interface toolkit that lets developers build interactive web applications. In a previous article, I explained the steps you can take to create a custom Dojo component. While that article covered how to create the component structure, template, class, style, and how to test the component, the example I created was pretty simple. In this article, I will show how to create a more meaningful component that interacts with third-party APIs.



As you may remember from the previous article, the component template defines the HTML representation of the component, while the component class represents the component data and behavior. The elements of the component template can be referenced and used in the component class using the Dojo attach points.



Let's create a location viewer component that calls the Google Maps APIs to display the location of any valid address in the world on a map, and also states the latitude and longitude of the address. The component lets us configure the map zoom value, width, and height, and allows users to refresh a map by changing the address using the provided API.



We can declare the component within a page's HTML with the following syntax:




<div dojoType="custom.locationViewerWidget"
id="viewer1"
address="Cairo, Egypt"
zoom="5"
showLabel="true"
containerWidth="500px"
containerHeight="500px"/>


This declaration means that the component should display the location of the passed address ("Cairo, Egypt") on the map. The map has a zoom value equal to "5". The map width and height should be 500 pixels. Setting "showLabel" to true asks the LocationViewer component to show the address and its corresponding latitude and longitude above the map.



The Widget Template



Let's start creating the LocationViewer component by creating the component template. The LocationViewer template has two main HTML elements under the root div element. The span element displays the address information and the div element displays the address location on the map.




<div>
<span dojoAttachPoint="labelNode" class="locationWidgetLabel"></span>
<div dojoAttachPoint="mapNode"
style="width:${containerWidth}; height:${containerHeight}">
</div>
</div>


"labelNode" is used for referencing the span element, and "mapNode" is used for referencing the div element. The width and the height of the second div element are determined by the containerWidth and the containerHeight attributes, which as we'll see in a moment are defined in the widget class. The span element can be customized by modifying the "locationWidgetLabel" CSS class.



The Widget Class



As I explained in the previous article, the dijit._Widget class is the base class for all of the dijit widgets, while the dijit._Templated class is responsible for reading HTML templates and creating the widget's DOM tree. The locationViewer widget class inherits from both the dijit._Widget and the dijit._Templated classes using the dojo.declare API. The next code listing shows the complete code of the widget class:




dojo.provide("custom.locationViewerWidget");

dojo.require("dijit._Templated");
dojo.require("dijit._Widget");
dojo.require("dijit.Tooltip");

dojo.declare("custom.locationViewerWidget", [ dijit._Widget, dijit._Templated ],
{
templatePath: dojo.moduleUrl("custom","templates/locationViewerWidget.html"),
address: "",
showLabel: false,
zoom: 6,
containerWidth: "300px",
containerHeight: "300px",

constructor: function() {
},

postCreate: function() {
var address = this.address;

this.refreshMap(address);
},

refreshMap: function(address) {
if (address == "") {
return;
}

var geocoder = new google.maps.Geocoder();

var localZoom = this.zoom;
var localShowLabel = this.showLabel;
var localLabelNode = this.labelNode;

var mapOptions = {
zoom: localZoom,
mapTypeId: google.maps.MapTypeId.HYBRID
};

var map = new google.maps.Map(this.mapNode, mapOptions);

geocoder.geocode({'address': address}, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
map.setCenter(results[0].geometry.location);

var infoWindow = new google.maps.InfoWindow({
content: address
});

var marker = new google.maps.Marker({
map: map,
position: results[0].geometry.location
});

infoWindow.open(map, marker);

if (localShowLabel) {
localLabelNode.innerHTML = "\"" + address + "\" has the following coordinates: " + results[0].geometry.location;
}

} else {
alert("Error: " + status);
}
});
}
});


As you can see, the component attributes are defined near the top in the dojo.declare statement. The postCreate method calls refreshMap, the main method provided by the locationViewerWidget class, passing the address attribute value to it as a parameter. The refreshMap API uses the Google Maps v3 APIs for rendering the map and for resolving the address to get the latitude and longitude corresponding to the address.



The google.maps.Map object creates a map. Its constructor takes two parameters: the DOM object (div) to generate the map content on, and the map options object. The DOM object is referenced by the mapNode Dojo attach point, while the map options object is populated with the map zoom value and the map type.



The google.maps.Geocoder object is responsible for resolving the address by using the geocode API. This API takes two parameters: a JavaScript object that contains the address attribute, and a delegate function that is called once the geocoding operation is completed. The delegate function itself has two parameters that are filled when the operation is completed: the results object, which contains the latitude and the longitude of the location, and the status object, which represents the status code of the operation.



The google.maps.Marker object creates a marker on the map. Its constructor takes two parameters: the map object and the position of the marker (latitude and longitude).



The google.maps.InfoWindow object creates the Information window. Its constructor takes an object that contains the content attribute to be displayed. The information window is displayed when the open API is called.



Finally, if the showLabel attribute is set to true, the labelNode attach point HTML content is updated with the location and its information (latitude and longitude).


19a98812-f823-48dc-841e-bf029c63c6d7

The Widget Style



The widget style, defined in the custom.css file, applies to the labelNode span element. In our example it is a simple style class:




.locationWidgetLabel {
font: bold 17px serif;
}


Testing the Widget



To test the widget, you must register the locationViewerWidget module path in the HTML page using the dojo.registerModulePath statement, load the locationViewerWidget module using the dojo.require("custom.locationViewerWidget") directive, and include the custom.css style and the Google Maps API library script, as shown in the listing below:




<script src="dojo/dojo/dojo.js" djConfig="parseOnLoad: true">
</script>
<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?sensor=false">
</script>

<link href="dojo/custom/css/custom.css" rel="stylesheet" type="text/css"/>

<script type="text/javascript">
dojo.registerModulePath("locationViewerWidget", "custom/locationViewerWidget");

dojo.require("dojo.parser");
dojo.require("dijit.form.Button");
dojo.require("custom.locationViewerWidget");
</script>


Continuing with the HTML code for our example page, we create the LocationViewer widget via a div element whose Dojo type is custom.locationViewerWidget, with initial values for the address and the zoom attributes:




<div dojoType="custom.locationViewerWidget"
id="viewer1"
address="Cairo, Egypt"
zoom="5"
showLabel="true"
containerWidth="500px" containerHeight="500px"/>


Because the LocationViewer widget is a valid dijit widget, it can be retrieved at execution time using the dijit.byId function. The code listing below shows how to call the refreshMap API after retrieving its instance using the dijit.byId:




<script type="text/javascript">
function changeAddress() {
var viewer1 = dijit.byId("viewer1");
viewer1.refreshMap(document.getElementById("addressInput").value);
}
</script>

...
<label for="addressInput">Enter the address: </label>
<input id="addressInput" type="input"/>
<button id="changeLocationButton" dojoType="dijit.form.Button" onclick="javascript:changeAddress();">
Change location
</button>


When a user clicks the changeLocationButton button, the browser executes the changeAddress function, which itself calls the refreshMap API of the widget, passing the user's entered address to it.



The listing below shows the complete testing code of the LocationViewer widget:




<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<script src="dojo/dojo/dojo.js" djConfig="parseOnLoad: true">
</script>
<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?sensor=false">
</script>

<link href="dojo/custom/css/custom.css" rel="stylesheet" type="text/css"/>

<script type="text/javascript">
dojo.registerModulePath("locationViewerWidget","custom/locationViewerWidget");

dojo.require("dojo.parser");
dojo.require("dijit.form.Button");
dojo.require("custom.locationViewerWidget");
</script>

<link rel="stylesheet" type="text/css" href="dojo/dijit/themes/tundra/tundra.css"/>

<script type="text/javascript">
function changeAddress() {
var viewer1 = dijit.byId("viewer1");

viewer1.refreshMap(document.getElementById("addressInput").value);
}
</script>

</head>

<body class="tundra">
<label for="addressInput">Enter the address: </label>
<input id="addressInput" type="input"/>
<button dojoType="dijit.form.Button" onclick="javascript:changeAddress();">
Change location
</button>

<br/>

<div dojoType="custom.locationViewerWidget"
id="viewer1"
address="Cairo, Egypt"
zoom="5"
showLabel="true"
containerWidth="500px" containerHeight="500px"/>
</body>

</html>


When you display the testing HTML page, you should see a page that looks like this:





For reference, you can download the complete component source.



Conclusion



I hope this article illustrates how custom Dojo components can not only help speed up development of rich Web 2.0 applications, but also help you maintain the applications, as Dojo centralizes the related presentation and logic code in one place (the component).




This work is licensed under a Creative Commons Attribution 3.0 Unported License
Creative Commons License.


This work is licensed under a Creative Commons Attribution 3.0 Unported License
Creative Commons License.

Comments

ralph polo outlet, michael kors outlet, louis vuitton online, juicy couture outlet, jordan 3, Ralph lauren Polo, iphone cases for 5S, louis vuitton online outlet, ralph lauren outlet, toms online, air jordan shoes, Tiffany co Bracelets, north face outlet, wholesale nfl, north face outlet, louis vuitton online store, ralph lauren outlet, ralph lauren polo outlet, toms outlet store, new york, Ralph lauren men, north face outlet, ralph lauren coupon, cheap nfl jersey, cheap toms, north face outlet, louis vuitton outlet online, louis vuitton outlet, toms on sale, wholesale jerseys nfl, ralph lauren outlets, north face outlet, ralph lauren clothes, toms outlet online, polo shirts for women, iphone cases for 5, abercrombie outlet, Hollister Online Shop, jordan 11, ralph lauren polo women, Cheap North Face, Hollister Jeans, tiffany wedding rings, mens ralph lauren, tiffany rings, tiffany lamps, outlet polo ralph lauren, toms outlet, ralph lauren for code, Ralph Polo, Seattle Seahawks outlet, Seattle Seahawks jersey, gucci outlet store, ralph lauren pony, polo shirts ralph lauren, gucci outlet, north face outlet, tiffany alvord, hollister california, michael kors outlet, louis vuitton outlet store, north face outlet, toms promo code, iphone cases for 5C, ralph lauren promo code, louis vuitton online, wholesale toms shoes, jordan outlet, north face outlet, ralph lauren outlet, north face denali, toms outlet, gucci outlet online, ralph lauren outlet online, iphone 5C cases, cheap ralph lauren polo, ralph lauren outlet, louis vuitton Mini, ralph lauren coupon, iphone cases 5, ralph outlet, nfl store, north face outlet, toms shoes online, polo sale, nfl shop, toms outlet, ugg outlet, ralph lauren t shirt, wedding jewelry, iphone cases, iphone cases, shop Ralph lauren, toms outlet, ralph outlet, north face outlet, ralph lauren cheap, toms on sale, nfl jersey, toms outlet, iphone cases 5, ralph outlet, toms shoes outlet, north face outlet, north face outlet, toms outlet, louis vuitton Damier, ralph lauren shop, north face sale, women polo shirts, uggs outlet, north face outlet, iphone cases 5S, toms coupon codes, Hollister Outlet, Tiffany co Bangles, jordan 4, ralph lauren black, nfl outlet, michael kors store, michael kors outlet, polo lauren outlet, michael kors outlet, tiffany outlet, iphone cases 5C, wholesale toms, iphone 4 cases, the north face outlet, toms wholesale, iphone 5 cases, tiffany outlet, clothing ralph lauren, ralph lauren outlet, louis vuitton Monogram, polo shirts for men, ralph lauren factory store, north face outlet, ralph lauren online, north face outlet, louis vuitton outlet, polo ralph lauren store, Ralph Lauren Outlet, polo online, north face outlet, louis vuitton Monogram, cheap ralph polo, tiffany engagement rings, michael kors online, polo shirts men, ralph lauren store, louis vuitton outlet online, north face for sale, nfl jersey sale, juicy couture outlet, tiffany jewelry, polo ralph lauren outlet, Ralph lauren women, ralph lauren for cheap, iphone cases 5S, iphone 5S cases, silver jewelry, ralph polo, louis vuitton Leather bags, polo outlet, ralph lauren outlet, iphone 5 cases, tiffany outlet, iphone 5 cases, gucci outlet, jordan 6, polo store, juicy couture outlet, polo lauren, uggs on sale, ralph lauren coupon code, Ralph Lauren Outlet, north face outlet, polo ralph lauren men, ralph polo, nfl jerseys, ralph lauren polo shirts, north face sale, iphone 5C cases, Hollister Clothing, ralph lauren home, iphone 5S cases, iphone cases for 5C, ralph lauren outlet, tiffany outlet, polo outlet online, louis vuitton store, Seattle Seahawks sale, buy nfl jersey, the north face outlet, north face outlet, iphone cases for 5, ugg boots on sale, Seattle Seahawks online, blue ralph lauren, toms online store, iphone cases 5C, iphone cases for 5S, north face outlet, north face outlet, wholesale nfl jerseys, toms outlet, tiffany necklace
Posted @ Wednesday, October 15, 2014 12:28 AM by FASF
Post Comment
Name
 *
Email
 *
Website (optional)
Comment
 *

Allowed tags: <a> link, <b> bold, <i> italics