Indian Railways exports these beautiful coaches!

Business-Cars, Lifestyle-City

Established in 1986, Rail Coach Factory (RCF), a manufacturing unit of Indian Railways has manufactured around 16,000 passenger coaches of 51 different types including self propelled passenger vehicles which constitute over 35% of the total coaches in the Indian Railways.

RCF is equipped with CAD centre to design and manufacture bogies, (both with stainless steel and corten steel).

RCF has also manufactured coaches for both Rajdhani Express and Shatabdi Express. RCF exports coaches manufactured at its plant in Kapurthala.

World’s oldest Ferrari worth $8 m unveiled

Business-Cars

The world’s oldest Ferrari, which won the 1947 Turin Grand Prix, has been unveiled for the first time after restoration and is now believed to be worth $8 million.

The 166 Spyder Corsa built by manufacturer Enzo Ferrari just after the World War II is believed to be world’s oldest Ferrari and was restored for $5,00,000 by its owner Jim Glickenhaus from California, the Daily Mail reported.

Capable of speeds of up to 160 kilometres per hour, which was enough to win the model the 1947 Turin Grand Prix, this 12-cylinder classic car is a one-of-a-kind. “I bought the car at an auction in 2004 for around $770,000,” Glickenhaus said.The motor — numbered 002 — was the first sold by Enzo Ferrari in December 1947, after his first build crashed.

In 2006 the owner of a Ferrari marked 001C came forward claiming his vehicle was the world’s oldest. This was actually a number two car built before Glickenhaus’ 1947, which could contain a proportion of parts from the first crashed 01C Ferrari.However this vehicle lacked the original engine and used Ford motor parts.”My Ferrari still has the original chassis, engine, gearbox and most of the mechanical pieces,” Glickenhaus was quoted by the paper as saying.

Glickenhaus believes the car could now fetch up to $8 million.”I took it to the original home of Ferrari, Marenello in northern Italy. There you will find the mechanics that have preserved the heritage of this machine. They had all the photographs, parts and knowledge to deliver an authentic restoration,” Glickenhaus added.

Day 6: Torch Relay visits Gloucester Cathedral and Severn Valley Railway

Sports

Day 6 of the Olympic Torch Relay will see the Flame pass a number of iconic landmarks including Gloucester Cathedral.

It will also travel along the Severn Valley Railway, carried on the train from Bewdley to Kidderminster by 43-year-old Christopher Stokes from Kidderminster.

Among the day’s other Torchbearers will be Olympian Sharron Davies, carrying the Flame in Leominster in recognition of her swimming career.

Stuart Woodburn, 30, a teacher from Worcestershire will also carry the Flame. A Torchbearer through Ledbury, Stuart was nominated through the LOCOG campaign for the way he supports and inspires everyone at the school, especially in sport.

The Evening Celebration will take place at Worcester County Cricket Ground from 4pm. The event will feature a variety of entertainment staged by LOCOG and the three Presenting Partners of the London 2012 Olympic Torch Relay – Coca-Cola, Lloyds TSB and Samsung.

Towards the end of the two-hour show, the last Torchbearer of the day – Sally Flood, from Bromsgrove who was nominated for her charity work – will light a celebration cauldron on stage at the event which will enable the Olympic Flame to be seen by the audience.

On Day 6 the Flame will be carried through the following communities:
Gloucester, Maisemore, Hartpury, Corse and Staunton, Ledbury, Bartestree, Lugwardine, Hereford, Leominster, Ludlow, Clee Hill, Cleobury Mortimer, Far Forest, Callow Hill, Bewdley, Kidderminster, Droitwitch Spa, Fernhill Heath and Worcester.

Toyota begins Etios exports

Business-Cars

Automobile major Toyota, through its joint venture with the Kirloskar group, on Wednesday, began exporting Etios cars, manufactured at the Bangalore plant, to South Africa.

The first batch, of 247 Etios, were loaded on to m.v.Antares Leader, a roll-on-roll-off vessel, at the Ennore port in the presence of two Karnataka Ministers, R. Ashoka and Murugesh R. Nirani, and senior executives of the joint venture, Toyota Kirloskar Motor Private Ltd (TKM), including its Vice-Chairman Vikram Kirloskar.

Addressing presspersons after the function, TKM Managing Director Hiroshi Nakagawa said the company was looking to export 20,000 Etios to South Africa annually. In a release, he said with the export of Etios “we have been successful in completing our vision of making Toyota Indian operations a strategic hub for both the domestic and global markets.”

Toyota SA Motors (PTY) Ltd Senior Vice-President (Sales and Marketing) Calvyn Hamman said that Etios was expected to help the South African company improve its market share, which it lost, with a presence in the growing small car segment. The demand for smaller vehicles was on the rise in South Africa, he said, adding that Etios would be promoted as an entry-level car for middle class households. The entry-level Etios would be priced at 116,000 Rands (about Rs.7.60 lakh), including the service plan.

The export model of Etios is built on the same platform as Etios and Etios Liva, manufactured and sold in India. However, it would be customised to suit the local requirements. The company will export only the petrol variants.

Mr. Hamman said the modification included tyres to withstand higher speed. While the average speed on highways in South Africa is 120 kmph, motorists tend to go up to 160 kmph. The size of the automobile market (all vehicles, including trucks) is 5.90 lakh and the share of Toyota SA Motors in it is 18.5 per cent.

TKM Deputy Managing Director (Marketing) Sandeep Singh said the company was doing well after the launch of Etios and was focussed on expanding in to semi-urban and rural markets.

Levi and Ojha architect MI’s 8-wicket win

Sports

Levi and Ojha architect MI’s eight-wicket victory over CSK in IPL-V opener

 

Pragyan Ojha, the former Deccan Chargers bowler, took two wickets in his first two overs to spin new side Mumbai Indians to a dominating 8-wicket victory over Chennai Super Kings in Game 1 of Indian Premier League V here at Chepauk on 4th April 2012.

IPL title holders Chennai were coasting at 69-2, thanks to a thriving partnership between Suresh Raina (36) and Dwayne Bravo (19), when Ojha was introduced in the 10th over – a move that turned the tide in the visitors’ favor.

Ouch: Mumbai Indians batsman Sachin Tendulkar misses a shot while CSK captain MS Dhoni  looks on. Tendulkar retired hurt on 16

Ojha (2-17), Kieron Pollard (2-15) and Lasith Malinga (2-16) kept chipping away with wickets as Chennai were shot out for 112.

Later, Mumbai’s other debutant Richard Levi, who recently scored the fastest Twenty20 international century, blasted 50 off 35 balls to set the ball rolling for the visitors in their pursuit of 113 runs.

Super start: Mumbai Indians players celebrate the early dismissal of Chennai opener Francois Du Plessis at MA Chidambaram Stadium yesterday

Levi added 69 for the first wicket with Sachin Tendulkar before being caught in the deep but by then the Mumbai Indians were in a commanding position.

Tendulkar (16 retd hurt), despite playing second fiddle to Levi also entertained the crowd as he smashed Albie Morkel over extra cover for a huge six. But he left the field after hurting his finger thanks to a rising delivery from Bollinger.

KP Strikes: Kieron Pollard, Harbhajan Singh and Dinesh Karthik celebrate the dismissal of Chennai Super Kings all-rounder Albie Morkel

Rayudu consolidates
Ambati Rayudu (18) and James Franklin (25) remained unbeaten to ensure that victory was attained with 19 balls to spare after Sachin Tendulkar (16) left the field retired hurt, and Rohit Sharma (0) was snared without troubling the scorers. For Chennai, only Doug Bollinger (1-34) and Bravo (1-14) finished with a wicket apiece.

Classy trinidadian: Mumbai’s new ’keeper Dinesh Karthik  looks on as Dwayne Bravo hits one of his three boundaries during his 19-run knock

The newly-laid 22-yard strip which had some patches of grass on either side turned out to be a nightmare for the hosts’ batsmen after Harbhajan Singh won the toss and elected to bowl.

While MI bowlers put up a spirited performance, CSK batsmen helped their cause as three of them including skipper Mahendra Singh Dhoni were run-out.

Pollard and Malinga triggered Chennai’s lower-order collapse when the former dug one short into Albie Morkel’s (3) ribs and his lofted shot went straight to Ojha at deep square-leg. Malinga removed Ravindra Jadeja (3) and Bollinger (3) quickly to end Chennai’s innings.

Brief scores
CSK 112 in 19.4 overs (Raina 36, Pollard 2-15, Malinga 2-16, Ojha 2-17). MI 115 for 2 in 16.5 overs (Levi 50, Franklin 25 no, Tendulkar 16 retd hurt)

Resources

Google Maps API Tutorial

How GLayers Work

When you add GLayer()s to your map, the API creates something like a GTileLayerOverlay() onto the G_MAP_OVERLAY_LAYER_PANE (pane 1).

The images on the layer are not individual icons, they’re painted onto tiles. The tiles look like this:

and have URLs like:
http://mlt3.google.com/mapslt?lyrs=lmc:panoramio&x=2013&y=1318&z=12&w=256&h=256
http://mlt3.google.com/mapslt?lyrs=lmc:youtube&x=2013&y=1318&z=12&w=256&h=256
http://mlt3.google.com/mapslt?lyrs=lmc:wikipedia_en&x=2013&y=1318&z=12&w=256&h=256

If you have more than one GLayer() on your map, there’s still only one layer of tiles. The different types of content are all assembled onto the same set of tiles, like this:

with URLs like:
http://mlt1.google.com/mapslt?lyrs=lmc:panoramio,lmc:wikipedia_en,lmc:youtube&x=2013&y=1316&z=12&w=256&h=256

The order in which you addOverlay the GLayers onto the map controls the order in which the LMCs appear in the URL. The order of the LMCs within the URL controls the order in which the images overlap. In the above example, the panoramio images are on the bottom, then the wikipedia images, and the youtube images are on the top.

The tiles are normally palletized PNG files with 8 bits per pixel, if the beowser is MSIE they will be full colour PNG files with 32 bits per pixel. I guess that the API chooses the smaller 8-bit images if the browser environment supports it.

Clicks

GLayer()s reside below all other clickable overlays. Polygons and polylines reside on thge same pane, but at a higher z-index value. All other clickable overlays reside in higher panes.

If there’s a clickable overlay covering a particular point, then a click at that point will be grabbed by that overlay, and won’t reach the GLayer(). So, if you want the GLayer() to be clicked when below a semitransparent GPOlygon, you’ll need to make that GPolygon unclickable by using {clickable:false}

When the user clicks on a GLayer icon, the click does not trigger a map “click” event.

When the user right-clicks on the map while a GLayer() is present, the details returned by the “singlerightclick” event are those of the GLayer(), not those of the map.

As well as the images, the API receives information about the positions of the hot spots, which it uses for changing the cursor when you hover over a hot spot. This information is not accessible.

There doesn’t appear to be any way to programmatically trigger a click on a GLayer hot spot.

LMCs

All possible layers are identified by an LMC. The documented layers also have IDs. You can use either an ID or an LMC when you create your GLayer. E.g. GLayer(“lmc:panoramio/0”) is the same thing as GLayer(“com.panoramio.popular”). It’s a good idea to use the ID whenever you’re adding a documented layer, because Google just might change the details of undocumented features.

Resources

Google Maps API Tutorial

GEvents

Here’s a list of the accessible GEvent types.

Event Object Parameters
“addmaptype” GMap2, GMap map type
“addoverlay” GMap2, GMap overlay
“clearoverlays” GMap2, GMap
“click” GMap2, GMap overly, latlng, overlaylatlng
“dblclick” GMap2, GMap the first parameter is always null
The second parameter is the GLatLng
“drag” GMap2, GMap
“dragend” GMap2, GMap
“dragstart” GMap2, GMap
“infowindowbeforeclose” GMap2, GMap
“infowindowclose” GMap2, GMap
“infowindowopen” GMap2, GMap
“load” GMap2, GMap
“maptypechanged” GMap2, GMap
“move” GMap2, GMap
“moveend” GMap2, GMap
“movestart” GMap2, GMap
“mousemove” GMap2, GMap GLatLng
“mouseout” GMap2, GMap GLatLng
“mouseover” GMap2, GMap GLatLng
“removemaptype” GMap2, GMap map type
“removeoverlay” GMap2, GMap overlay
“resize” GMap2, GMap
“singlerightclick” GMap2, GMap 1. GLatLng() identifying the pixel position of the mouse within the map div.
2. URL of tile (if over the base map)
3. Map container if over the base map. Reference to the Gmarker if over a marker.
“zoomend” GMap2, GMap old zoom level, new zoom level
“zooming” GMap2, GMap
“zoomstart” GMap2, GMap direction (+1 = zoom in, -1 = zoom out)
latlng pivot
bool recentering
Event Object Parameters
“zoom” GMap old zoom level, new zoom level (v1 syntax)
Event Object Parameters
“newcopyright” GMapType copyright
Event Object Parameters
“newcopyright” GTileLayer copyright
Event Object Parameters
“newcopyright” GCopyrightCollection copyright
Event Object Parameters
“click” GMarker latlng of marker
“changed” GMarker marker, previous position
“dblclick” GMarker latlng of marker
“drag” GMarker latlng
“dragend” GMarker latlng
“dragstart” GMarker latlng
“infowindowbeforeclose” GMarker marker
“infowindowclose” GMarker marker
“infowindowopen” GMarker marker
“infowindowprepareopen” GMarker marker
“mousedown” GMarker latlng of marker
“mouseover” GMarker latlng of marker
“mouseout” GMarker latlng of marker
“mouseup” GMarker latlng of marker
“remove” GMarker
“visibilitychanged” GMarker true if the marker is now visible, else false
Event Object Parameters
“changed” GMarkerManager GBounds indicating active region in units of 1024×1024 pixels, number of active markers
Event Object Parameters
“cancelline” GPolyline
“click” GPolyline GLatLng of clicked location
“endline” GPolyline
“lineupdated” GPolyline
“mouseout” GPolyline
“mouseover” GPolyline
“remove” GPolyline
“visibilitychanged” GPolyline true if the poly is now visible, else false
Event Object Parameters
“cancelline” GPolygon
“click” GPolygon GLatLng of clicked location
“endline” GPolygon
“lineupdated” GPolygon
“mouseout” GPolygon
“mouseover” GPolygon
“remove” GPolygon
“visibilitychanged” GPolygon true if the poly is now visible, else false
Event Object Parameters
“moveend” GKeyboardHandler
“movestart” GKeyboardHandler
Event Object Parameters
“animate” [GInfoWindow] proportion of the animation that has been performed
“closeclick” [GInfoWindow]
“maximizeclick” [GInfoWindow]
“maximizeend” [GInfoWindow]
“restoreclick” [GInfoWindow]
“restoreend” [GInfoWindow]
Event Object Parameters
“click” GDraggableObject browser-specific event object
“dblclick” GDraggableObject browser-specific event object
“drag” GDraggableObject browser-specific event object
“dragend” GDraggableObject browser-specific event object
“dragstart” GDraggableObject browser-specific event object
“mouseup” GDraggableObject browser-specific event object
“mousedown” GDraggableObject browser-specific event object
“move” GDraggableObject
Event Object Parameters
“visibilitychanged” GScreenOverlay true if the overlay is now visible, else false
Event Object Parameters
“visibilitychanged” GGroundOverlay true if the overlay is now visible, else false
Event Object Parameters
“load” GGeoXml
Event Object Parameters
“changed” GTrafficOverlay true if the viewport contains traffic data
Event Object Parameters
“error” GStreetViewPanorama error code
“initialized” GStreetViewPanorama location object
“pitchchanged” GStreetViewPanorama pitch
“yawchanged” GStreetViewPanorama yaw
“zoomchanged” GStreetViewPanorama zoom
Event Object Parameters
“changed” GStreetViewOverlay true if the viewport contains StreetView data

Notes

  1. Watch out for those parameters. The same event can have different parameters with different objects.
  2. The GInfoWindow class isn’t directly accessible, but you can use GEvent.addListener(map.getInfoWindow(),”closeclick” …).
  3. The “closeclick” event is only triggered when the user actually clicks on the info window close icon, not for anything else that closes the info window.
  4. Watch out for the difference between the “zoom” event (GMap() only) which returns zoom levels in APIv1 format and the “zoomend” event which returns zoom levels in APIv2 format.
  5. To differentiate the situation where the user moves the map rather than the map being moved by code, you can use drag* and dblclick events. The move* events are triggered by anything that moves the map, which can include calls made by your own Javascript code and the opening of an info window.

Custom Events

It’s also possible to use the GEvent system to pass messages between different parts of your own code with custom events. Simply use GEvent.addListener(marker, “myevent”) to listen for the event andGEvent.trigger(marker, “myevent”) to trigger it. You can pass up to two parameters.

You can pass these custom events on any object, these can be API objects, HTML elements, data structures, or any type of Object().

 GEvent.addListener(map, "myevent", ... GEvent.addListener(document.getElementById("message"), "thisevent", ... var fred = new Object(); GEvent.addListener(fred, "thatevent", ... 

GEvent.addDomListener

It’s also possible to use GEvent.addDomListener() to listen for Dom events on HTML Elements.

Writing GEvent.addDomListener(document.getElementById(“button”), “mouseover”, … has a similar effect to writing <input id=”button” onmouseover=”…”>, but there are one or two advantages to using the GEvent system:

  1. You may find it easier to add or remove GEvent listeners
  2. You can use GEvent.trigger on these events

You can use this system to handle any of the standard HTML Dom events: “blur”, “click”, “dblclick”, “focus”, “keydown”, “keypress”, “keyup”, “load”, “mousedown”, “mousemove”, “mouseout”, “mouseover”, “mouseup”.

When using this system, the full event details are passed in the first parameter. So for example you could write

GEvent.addDomListener(document.getElementById("map"), "click", function(e) {...

and then examine the details of the event “e” and behave differently if, say, the ALT or CTRL keys were pressed by testing if (e.altKey) or if (e.ctrlKey).

Note that if you write GEvent.addDomListener(map, “click” then you don’t get the Dom event because a GMap2() object isn’t a HTML element. You get the conventional “map click” event instead, with the parameters “overlay” and “latlng”.

Third Party Extensions

Google Maps API Tutorial

Using the EWindow extension

The EWindow extension provides some of the functionality of custom info windows.

Here’s an example with a single EWindow that behaves something like the Google info window.

Here’s a similar example but now the EWindow has a close icon.

Here’s an example with multiple info windows that are permanently open.

Here’s a rather messy example with tabbed EWindows.

The basic procedure for using EWindows is:

  1. Download the ewindow.zip file which contains all the components, unzip it an place the contents on your web site.
  2. Call the CSS file like this <link rel=”stylesheet” type=”text/css” href=”ewindow.css”>
  3. Load the Javascript code like this <script type=”text/javascript” src=”ewindow.js”></script>
  4. Create and addOverlay() one or more EWindows, e.g. ewindow = new EWindow(map, E_STYLE_1); map.addOverlay(ewindow);
  5. Open the EWindow with ewindow.openOnMarker(marker,html) orewindow.openOnMap(point, html, offset)

EWindow Constructor

The parameters for new EWindow() are:

map The map on which the EWindow is to appear.
EStyle Information about the style of the EWindow
A few EStyles are provided, E_STYLE_1, E_STYLE_2, etc. or you can design your own.

Opening an EWindow

There are two methods provided for opening an EWindow

ewindow.openOnMap

This opens the EWindow on the map that you specified in the EWindow constructor.

point A GLatLng() or GPoint() specifying the geographical location
html A string containing simple HTML.
EWindows won’t handle all the complicated HTML that a Google info window can cope with, and won’t auto wrap the text. You’ll need to use <br> wherever you want the text to break
offset (optional) A GPoint() specifying a pixel offset.

ewindow.openOnMarker

This opens the EWindow on the map that you specified in the EWindow constructor, with a location derived from the specified marker.

This call uses the infoWindowAnchor parameter of the icon that is being used by the marker.

marker The marker on which the EWindow is to be opened.
html A string containing simple HTML.
EWindows won’t handle all the complicated HTML that a Google info window can cope with, and won’t auto wrap the text. You’ll need to use <br> wherever you want the text to break

Multiple EWindows

You can have as many EWindows as you like on the same map. Use the EWindow constsuctor to construct them ewindow2 = new EWindow(map, E_STYLE_1); map.addOverlay(ewindow2);

Closing an EWindow

Use ewindow.hide()

There’s no close icon in an EWindow, so you might consider arranging for them to close when the user clicks on the map

      // ========== Close the EWindow if theres a map click ==========
      GEvent.addListener(map, "click", function(marker,point) {
        if (point) {
          ewindow.hide();
        }
      });

map.removeOverlay(ewindow) is provided because it’s a required part of the Custom Overlay interface, but I don’t recommend using it.

You can use ewindow.show() to unhide an EWindow.

EWindow.copy()

ewindow.copy() is provided because it’s a required part of the Custom Overlay interface, but the copy will not be visible uless you use .openOnMap() or .openOnMarker() on the copy. So, for example, the EWindow will not be visible in blowups.

Making your own EStyles

If you don’t like the EStyles that are provided, you can make your own.

Create a suitable image for the stem. To keep things reasonably simple, the anchor point is always the bottom left corner of the stem image.

Then use the EStyle constructor like this
myEStyle = new EStyle(stemImage, stemSize, boxClass, boxOffset);

The parameters are:

stemImage A string containing the URL of the image file
stemSize A GSize() containing the pixel size of the stemImage
boxClass A string containing a class name to be used for the CSS style
boxOffset A GPoint containing the pixel offset of the bottom of the box from the bottom of the stem image
Typically, for stems that touch the bottom of the box, the x value will be a small negative number, and the y value will be the height of the image minus the width of the box border from the CSS.
For stems that touch the left of the box (like E_STYLE_6) the x value will typically be the width of the image minus the border, and the y value will be a small positive number.

If you create some nice EStyles that other people could use, send me a copy and I’ll include them in the EWindow distribution.

Third Party Extensions

Google Maps API Tutorial

Draggable EInserts

EInserts supports the GDraggableObject() facility.

Here’s an example.

Unfortunately, GDraggableObject() doesn’t track position changes caused by changes of zoom level, so I disable EInsert draggability when you change the zoom level.

To activate draggability, call the new einsert.makeDraggable() method.

When the dragging is complete, an EInsert “dragend” event is triggered, which returns the new value of einsert.point. This allows you to use draggable EInserts on a development version of your map, position them accurately by dragging, then be notified of the final coordinates which you can then use for the live a with non-draggable EInserts .

Download EInserts from here einsert.js.

Third Party Extensions

Google Maps API Tutorial

Using Jef Poskanzer’s OverlayMessage

OverlayMessage allows you to place a semi-transparent message over the top of any HTML element. It’s not a true Google API Map extension, because it works equally well on things other than maps.

It can be useful for Google Maps that take a while to load. You can display the message before the map starts to load, and clear it in the <body onload> function, if you’re not using onload for anything else.

Here’s an example

Full details of how to use it are at http://www.acme.com/javascript/#OverlayMessage

Third Party Extensions

Google Maps API Tutorial

Jef Poskanzer’s Clusterer

If you happen to have thousands of points that you want to plot, you’ll find that the map becomes too slow to be usable. One way round this, without a server side database, is to use Jef Poskanzer’s excellent Clusterer.js.

See http://www.acme.com/javascript/#Clusterer

Here’s an example

Instead of displaying the markers directly, you tell the Clusterer about them, and it monitors the map movements and zoom level and determines when it is appropriate to display icons that indicate clusters, and when it is appropriate to display individual markers.

Jef has asked me not to describe how to use Clusterer, so I won’t.

Parameters

If you don’t like the default Clusterer settings, then you can set some parameters.

  • clusterer.icon
    can be set to the GIcon to be used to indicate a cluster, so you can use your own marker icon to match the rest of your page.
  • clusterer.maxVisibleMarkers
    sets the maximum number of icons that will be displayed at any one time. The default is 150.
  • clusterer.gridSize
    sets the size of the grid used for placing the clusters. The default value of 5 indicates that there can be 5 clusters from east to west across the map.
  • clusterer.minMarkersPerCluster
    sets the minimum number of markers that can be in a cluster. The default value is 5.
  • clusterer.maxLinesPerInfoBox
    sets the number of detail lines that will be displayed in the info window associated with a cluster. If you’ve got a small map, then you may need to reduce this to prevent the cluster info boxes being too large for your map. If there are more markers in a cluster than this value, then the info window adds a line that says “.. and XXX more”. The default value is 10.

You don’t have to set any of these parameters, the Clusterer works perfectly well with the default settings.

Custom Maps

Google Maps API Tutorial

Alternative Map Type Controls

New formats for the map type controls were introduced in v2.93 and v2.94. These new formats can be useful in situations where you have a large number of custom map types, causing the normal GMapTypeControl to become cumbersome.

The GMenuMapTypeControl() displays all the map types in a drop-down menu.
If the optional first parameter is true, then shortnames are used.
If the optional second parameter is true, then a border is drawn round the control.

The GHeirarchicalMapTypeControl() lists “child” map types below their “parent” map type if that parent is active.
If the optional parameter is true, then shortnames are used.

GHeirarchicalMapTypeControl() has three Methods for managing parent and child map type relationships:

GHierarchicalMapTypeControl.addRelationship(parent, child, name, isDefault) adds a parent/child map type relationship. The parameters are

        1.  parent GMapType
        2.  child GMapType
        3.  (optional) Name for child
        4.  (optional) isDefault boolean

GHierarchicalMapTypeControl.removeRelationship(child) removes a parent/child map type relationship. The parameter is the child GMapType.

GHierarchicalMapTypeControl.clearRelationships() removes all relationships.

Here’s an example of a map with seven map types showing all possible map type controls. Click the buttons to display the different controls.

Here’s an example that sets the map type controls to look exactly like the v2.94 maps.google.com controls. The Terrain map type is added. Hybrid is underneath Satellite and is selected by default when the Sattelite button is clicked.

More advanced stuff

Google Maps API Tutorial

UK Posctcodes

The Problem

Since I wrote this page, The Problem seems to have gone away making this page unnecessary

Unlike other countries, the geographical information associated with UK postcodes is strictly controlled. The copyright is owned by the Royal Mail, who make a lot of money selling licences to use it.

For example, I just bought a new TV. The guy at the shop didn’t ask for my address, but just asked for my postcode and house number, and used that to find my full street address. The shop presumably finds it worthwhile fo pay the annual £85 licence per workstation, or the annual £75,000 corporate licence for all the workstations operated by that chain of stores, or one of the intermediate licences. Since large numbers of UK high street shops do the same thing, that adds up to an awful lot of money that the Royal Mail receive from licensing that data. Therefore they’re not keen to allow Google to give the information away for free via the API geocoder.

The Royal Mail have allowed Google to buy a licence to use the data on its own websites, but not to redistribute the data to other people.

This results in it being possible to find the exact location of “FY2 0HH, UK” at maps.google.com, but if you try the same search with the API geocoder you get a point that’s nearly a mile away.

What actually happens

The API geocoding database contains the locations of places like “FY2 0” and “FY2 9”. I.e. the “outcode” part of the postcode plus the numeric part of the “incode”.

When you reverse geocode a point, it gives the correct one of those locations as the Locality.PostalCode.PostalCodeNumber

When you forward geocode a UK postcode, the geocoder is only allowed to look at the “outcode” part. It then returns an arbitrary one of the “FY2 ?” locations, not necessarily the correct one. Which one of those locations actually gets returned is influenced ny things like country bias. There is a suggestion that it might even be biassed by the location of the user who is calling your page.

Workrounds

Use the full address

You could always ask your user to input their full address. That generally works.

The terms of the licence require the geocoder to discard the “incode” part of the postcode, and effectively performs a search for [street address] near [outcode]. In some extreme cases, even that won’t work. An example near where I live is “10 Bispham Road FY6 7PE, UK”. There are three “Bispham Road”s that are near FY6. One at “FY3 7HJ”. One at “FY5 1DG” and the one that I asked for at “FY6 7PE”. The API geocoder returns all three, but the one I asked for is the second placemark.

Use a non-google geocoding service

I don’t know of any commercial on-line services, but I’m sure there are some.

Buy the data from the Royal Mail

Put it on your server and perform your own lookups. I reckon that you need to pay the annuall £3,850 fee for a System Licence to do that.

Use the Google Local Search API

I’ve no idea how the licensing of this works, but calls to the Google Local Search API do correctly geocode full UK postcodes.

A Google spokesman did once say that this might not always be the case, so if you do use this strategy don’t be surprised if it suddenly stops working.

It’s not a good idea to use Google Local Search as a general purpose geocoder. It’s slower than the API geocoder and can sometimes get confused between placenames and business names. So if there’s a possibility that your search string might not be a UK postcode, it’s a good idea to test it first, see below.

Use GDirections

I’ve no idea how the licensing of this works, but calls to GDirections do correctly geocode full UK postcodes. The locations are slightly different from the maps.google.com locations, since they will have been snapped to the nearest street.

The strategy is to request a route from the postcode to itself, like “from: FY2 0HH to: FY2 0HH”, wait for the reply, then use .getPolyline().getVertex(0) to obtain the location.

If you do use this strategy don’t be surprised if it suddenly stops working.

It’s not a good idea to use GDirections as a general purpose geocoder. It’s slower than the API geocoder, has a lower daily quota, and can only handle one request at a time. So if there’s a possibility that your search string might not be a UK postcode, it’s a good idea to test it first, see below.

There’s also considerable doubt about whether this strategy is legal. Read section 10.12 of the Terms for yourself before implementing this strategy.

Testing if a string is a UK postcode

To test if a string looks like a UK post code you can use this regexp
^[A-Z]{1,2}[0-9R][0-9A-Z]? [0-9][ABD-HJLNP-UW-Z]{2}$.

That expession assumes that the string is in upper case, has exactly one space between outcode and incode, has no leading or trailing whitespace and no punctuation. That’s a bit more severe than we need, since GDirections and Google Local Search will accept any case and any punctuation and whitespace, so you might want to tidy it up first before performing the test.

That expression should be sufficient to distinguish a full UK postcode from anything else, but if you want to be more exact, there’s a long form in the Wikipedia. Don’t use the very long expression from the Wikipedia article that includes BFPO postcodes, because BFPO postcodes don’t represent fixed geographical locations, but groups of British Overseas Forces which may well be mobile.

Example

Here’s an example that tests whether a search string is a UK postcode, and if so uses the GDirections trick rather than the GClientGeocoder to find the location.

More advanced stuff

Google Maps API Tutorial

Using <CANVAS>

It is possible to directly use <canvas> in conjunction with a map.

Here’s an example

Details of how to use <canvas> are available from the Mozilla Developer Centerdeveloper.mozilla.org/en/Canvas_tutorial

However there are a few drawbacks.

Browser Support

Not all browsers support <canvas>, and there is some variation between levels of support in the browsers the do support it. The HTML5 standard which defines <canvas> is still evolving.

In particular, MSIE does not currently support <canvas>.

There is an add on called ExplorerCanvas which can intercept <canvas> canvas commands and convert some of them into VML and Filter commands that MSIE does recognise, but many <canvas> features are not supported, the end result is extremely slow.

Therefore it’s a good idea to test for <canvas> support, and provide some sort of alternative when that support is absent. In the above example, I have a small test canvas which always exists outside the map. If that canvas doesn’t have a .getContext() Method, then I don’t create the active canvas, but create a simple marker instead.

Cryptic error messages

Firefox3 <canvas> error messages are seriously cryptic. They thow a couple of lines of complete gibberish, out of which the only bit that means anything to me is the line number on which the error occurred.

Click handling

<Canvas> elements don’t seem to accept attributes like “onclick” and “onmouseover”, etc.

In some circumstances they seem to eat such events, even in the transparent parts of the <canvas>, preventing them from dropping through to the map controls and overlays below them. In other cirsumstances the clicks do drop through. I don’t know what causes the change in behaviour.

Therefore, if you’re going to use <canvas> in such a way that it overlaps clickable objects, do perform a quick sanity test to see if the clicks are going to reach the underlying elements.

Placing <canvas> elements in a map

You could place your <canvas> elements directly onto one of the map panes, but then you’d have to manage the lat/lng handling yourself.

In the example, I use an ELabel as a container for the <canvas>. This gives the advantage of having all the standard methods like .hide(), .setPoint(), etc. built in.

You could place <canvas> elements inside other structures, such as info windows, or GControls.

You could appendChild a <canvas> element to the map container, but watch out for the click passing problem mentioned above.

<canvas> images and onload function

I don’t usually recommend using onload functions, but if you’re using images in <canvas> then it is necessary to ensure that the image has completely loaded before you attempt to use it in <canvas>. One way to do this is to load the image in the main inline code and launch the <canvas> from the onload event.

Rotating icons

The awkward thing with rotations in <canvas> is that they don’t rotate the object, they rotate the canvas axes around point (0,0), the top left corner of the canvas workspace. That’s not what we generally want. We usually want to rotate an element about its centre.

In other graphics systems, we would translate the object to (0,0), then rotate it, then perform the inverse translation to put it back where it came from.

That’s basically what we have to do in <canvas> but the inverse translation takes place in the rotated frame, so instead of it being (-x,-y) it becomes (x*sin(a)+y*cos(a),y*cos(a)-y*sin(a)). The whole rotate-about-centre operation looks like this:

      var cosa = Math.cos(angle);
      var sina = Math.sin(angle);
      canvas.clearRect(0,0,x*2,y*2);
      canvas.save();
      canvas.rotate(angle);
      canvas.translate(x*sina+y*cosa,x*cosa-y*sina);
      canvas.drawImage(img,-x,-y);
      canvas.restore();

The save() and restore() operations put the axes back where they originally came from.

More advanced stuff

Google Maps API Tutorial

GGeoXml with sidebar

GGeoXml doesn’t expose the content that it adds to your map, so you can’t directly obtain information on its markers from Javascript. However, in some circumstances, it is possible to intercept the addoverlay events which are generated when it adds the markers to the map.

Here’s an example

Warning: This trick relies on undocumented details of the GGeoXml behaviour. It may well fail to work in future releases.

Other, more stable, methods for creating a sidebar are EGeoXml and GeoXml

When GGeoXml adds overlays to a map, an “addoverlay” event is triggered. It’s possible to catch that event, extract information about that overlay, and build a sidebar.

This is possible because GGeoXml adds extra accessible properties to the overlays that it creates. These properties currently are:

  • name
  • description
  • snippet
  • hiddenInStream
  • id
  • parentFolderForCallbackOverlayAddTimeout
  • parentGeoXml

The property that we’re interested in for building the sidebar is “name”.

Problems

Overlay management

GGeoXml now performs some sort of crude overlay management on the overlays it creates. This causes the overlays to be removeOverlay()ed when they leave the viewport and addOverlay()ed again when they re-enter the viewport. We need to be careful not to add an extra side bar entry for the overlay each time it re-enters the viewport.

In my example, I add my own extra property to the overlay to remember that I already know about the overlay.

Sidebar order

GGeoXml adds the overlays in random order. If you need the overlays to appear in alphabetical order of name, then you have to sort them yourself.

Long Sidebar

There’s no indication of whether a particular overlay is the last one in the KML file. This means that the usual technique of building the sidebar HTML until the last entry has been processed won’t work. In my example, I add each sidebar entry one by one. If there are large numbers of overlays, this becomes inefficient, since the browser has to re-render the sidebar div after each entry has been added.

I can’t think of any nice way around this, unless you happen to know how many overlays your KML file contains.

Intercepting infowindow content

Another trick that you might want to perform with GGeoXml is to modify the content of the infowindows that it manages. For example you might want to add a “get directions” facility at the bottom, or you might want to have active content in the info window.

It turns out that modifying overlay.description doesn’t modify the contents of the infowindow. The data must be being stored somewhere else before the “addoverlay” event gets triggered.

What you can do is to listen for the undocumented map “infowindowprepareopen” event, and modify the content of the GInfoWindowTab that it passes as a parameter.

In my example I simply add an extra line of text at the bottom of the infowindow contents.

You could place deactivated content in a KML file, perhaps using [ and ] instead of < and >, so that GGeoXml will allow the text to pass through, and then replace those characters as the infowindow opens.

More advanced stuff

Google Maps API Tutorial

GoogleBar Options

The GoogleBar allows you to achieve similar functionality to what you would get by using the Google AJAX Search API to perform a Local Search, but provides a few advantages:

  1. If you just need the basic functionality, all you need is one extra command in your code: map.enableGoogleBar().
  2. You can use it without having agreed to the Google AJAX Search API Terms of Use, which seem to not allow you to modify the results.

The Maps API GoogleBar options provide facilities which you can use to:

  • Modify or replace the text, images, or other content of the Google Search Results
  • Changing the order in which the Google Search Results appear
  • Intermix Search Results from sources other than Google
  • Intermix other content such that it appears to be part of the Google Search Results
  • Modify, replace or otherwise disable the functioning of links

All of which would be prohibited if you were using the Google AJAX Search API.

Options

The possible entries in the googleBarOptions are:

property type purpose
showOnLoad bool If true, the Google Bar will be expanded when the map has loaded.
linkTarget string Use one of these string variables to control the link target pane G_GOOGLEBAR_LINK_TARGET_BLANK, G_GOOGLEBAR_LINK_TARGET_PARENT, G_GOOGLEBAR_LINK_TARGET_SELF, G_GOOGLEBAR_LINK_TARGET_TOP
resultList string Use one of these string variables to control result list suppression G_GOOGLEBAR_RESULT_LIST_INLINE, G_GOOGLEBAR_RESULT_LIST_SUPPRESS
suppressInitialResultSelection bool If true, the info window is not opened on the first result.
suppressZoomToBounds bool If true, the map does not zoom and pan to fit the results.
onIdleCallback function Function be be called when the GoogleBar finishes searching
onSearchCompleteCallback function Function to be called when the search is complete, before the reults are plotted
onMarkersSetCallback function Function to be called after the markers have been placed on the map.
onGenerateMarkerHtmlCallback function Function to be called when the info window is about to be opened on one of the results. Must return the (modified) html element object to be used for the info window contents.

The first six options are fairly straight forward, but the callback functions need a bit of explanation:

onIdleCallback

This function is called when the GoogleBar is opened for the first time, and called again whenever the previous results are cleared. It is not called if a second search is executed without the user explicitly clearing the previous results.

No parameters are passed.

onSearchCompleteCallback

This function is called when the search is complete, before the results are plotted.

There is one parameter, a reference to a GlocalSearch object, see Official Class reference

Of particular interest is the .results[] array, which is an array of GlocalResult() objects, see Official Class reference

You can read that information, but also, because it’s a reference, you can modify the contents of the .result[] array. The .html will have already been calculated, so changing things like the .results[i].city won’t affect what gets displayed in the info window.

If you want to change the info window contents at this point, then you need to change the .results[i].html.innerHTML.

onMarkersSetCallback

This function is called when the API has created markers corresponding to the search results.

There is one parameter, an array of anonymous Objects.
Each Object in the array has two properties, .result is a GlocalResult object and .marker is a GMarker.

onGenerateMarkerHtmlCallback

This function is called whenever an info window is about to be opened.

The parameters are:

  1. The GMarker
  2. The HTMLElement which is intended to become the info window contents
  3. The GlocalResult

The function must return a HTMLElement which will become the actual info window contents.

Simple result filtering example

This example uses onSearchCompleteCallback to filter the search results, reducing the number of results to no more than two.

Simple info window modification

This example uses onGenerateMarkerHtmlCallback to read information from the GMarker and from the GlocalResult to modify the contents of the info window at the time that the info window is opened.

Advanced example: add ELabels

This advanced example uses all the GoogleBar Options. It displays an Elabel alongside each marker, and in order to do that it uses the callback functions like this:

onIdleCallback uses map.clearOverlays() to remove the old ELabels

onSearchCompleteCallback uses map.clearOverlays() to remove the old ELabels

onMarkersSetCallback reads the location of each GMarker and the titleNoFormatting of each GlocalResult and uses that information to create an ELabel.

onGenerateMarkerHtmlCallback hides the ELabel corresponding to the marker on which the info window is opening.

More advanced stuff

Google Maps API Tutorial

Modularized Overlays and Controls

Version information:

  • Info Windows: Google moved the info window back into the main code from v2.135 to v2.183, so this technique is not necessary for those versions.
    Google moved the info window back into an exernal module in v2.184, so this technique is again necessary from v2.184 onwards.
  • GOverviewMapControl: The undocumented .getOverviewMap() does not work since v2.135. There is now no way to obtain a reference to the overview map oject.

Google have been moving some code out of the main API code and into external modules. This reduces the memory required to run the API, and the time taken to load the main code. The external modules are only loaded when you make the first call to code that they contain.

The loading of an external module is performed asynchronously. This can be a problem if you were intending to directly modify the contents of something created by that module. Modifying the overlay using API calls is OK. I guess API calls to a module that hasn’t finished loading are pipelined.

If you attempt to reference DOM elements of modularized overlays or controls, then you’ll find that those elements don’t exist for a few hundred milliseconds.

GOverviewMapControl

In v2.93, the code for the map controls was moved into a separate module.

In previous versions of the API you could write

      var overlayControl = new GOverviewMapControl();
      map.addControl(overlayControl);
      var overmap = overlayControl.getOverviewMap();
      var overmapdiv = document.getElementById('map_overview');

From v2.93, those undocumented features no longer work because the GOverviewMapControl doesn’t actually exist until a few hundred milliseconds later, after the code that handles it has been loaded. You have to wait for the module to be loaded before those features become accessible. Or, alternatively, you could stop using those undocumented features.

The internal event that is triggered when the code module has been loaded doesn’t appear to be accessible, and waiting for a fixed time period carries the risk that it might fail for a user with slower Internet connectivity or when the Google server is busy.

What you could do is wait for a short while, and check to see if the feature is active, and wait again if it isn’t. Like this:

      var overlayControl = new GOverviewMapControl();
      map.addControl(overlayControl);
      setTimeout("checkOverview()",100);
   ...
      function checkOverview() {
        overmap = overlayControl.getOverviewMap();
        if (overmap) {
          ...
        } else {
        setTimeout("checkOverview()",100);
      }
    }

This example logs the availability of .getOverviewMap() and “map_overview”.

This example performs the same tweaks as described here for the earlier versions of the API.

Info Window

In v2.123, the code for the info window was moved into a separate module.

In previous versions of the API you could write

     marker.openInfoWindowHtml('<div id="info"> ... </div>');

and immediately access document.getElementById(“info”).

You might want to do that if you’re displaying a mini-map or a StreetView panorama inside the info window.

From v2.123, that doesn’t work the first time you open the info window, because the content div doesn’t exist until a few hundred milliseconds later, after the code that handles it has been loaded.

If you’re opening the info window immediately when the page launches, then you’d have to wait for the module to load, just like the GOverviewMapControl above.

If, however, you only open the info window when the user clicks on a marker, a neater solution is to force the module to be loaded as the page opens, with the expectation that the module will be available by the time that the user clicks on a marker. This can be done like this:

     var map = new GMap2(document.getElementById("map"));
     map.getInfoWindow().show();

The .show() method doesn’t display anything, since the info window isn’t set up. Other commands that don’t display anything are implemented in main.js, and don’t cause the module to be loaded.

More advanced stuff

Google Maps API Tutorial

Custom Cursors

It is possible to use your own custom cursors for the map and for GDraggableObjects.

Here’s a simple example

The cursor is implemented as part of the operating system code, not in the browser itself, and the implementation varies considerably depending on the operating system and the browser.

MSIE

MSIE allows you to specify a list of CUR and ANI files and standard cursor keywords.
E.g. ‘url(mycursor.ani), url(mycursor.cur), pointer’
The “hot spot” must be specified in the CUR or ANI file itself, you can’t specify it in the cursor list.

If, for any reason, one cursor in the list cannot be used in the current environment, then the next one in the list will be used. However, if you attempt to use standard CSS3 syntax to specify the “hot spot” of any of the cursors, the whole list is ignored.

Gecko based browsers

Recent versions of Gecko-based browsers (Firefox, Mozilla, Netscape, Flick, etc.) allow you to specify a list of CUR, PNG, GIF, JPG, XBM and BMP files but require that the last element in the list be a standard cursor keyword.
They also allow the “hot spot” to be specified in the cursor list using standard CSS3 syntax.
E.g. ‘url(mycursor.png) 16 16, pointer’
If you don’t specify a “hot spot” in the list, then for XBM and CUR files the “hot spot” specified in the file will be used, and for other file types the tip left pixel (0,0) will be used.

Animated cursors are not currently supported in Gecko-based browsers. If you specify an animated GIF, then the first frame will be used.

If, for any reason, one cursor in the list cannot be used in the current environment, then the next one in the list will be used. However, if the last entry in the list is not a standard cursor keyword, then the whole list is ignored.

Webkit based browsers

I can’t find a list of rules for Safari or Chrome, but anything that works in Firefox seems to work.

Presto based browsers

I can’t find a list of rules for Opera, and can’t get anything to work. Any attempt at using a custom cursor list causes the whole list to be ignored. The standard cursor keywords work on their own, but not if there’s a “url()” in the list.

Windows versions

Translucent cursors are not supported in Windows versions prior to XP.

Cursors larger than 32*32 pixels are not supported in Windows versions prior to XP.

Mac Os X

Custom cursors don’t currently work on Mac Os X in Gecko based browsers.

Creating CUR files

Normal image processing applications won’t output CUR files. You’ll need a separate dedicated CUR file editor.

I happened to use ArtCursors from Aha-Soft www.aha-soft.com/artcursors. It costs $39.99 and comes with a 30 day trial period. There are several similar looking shareware programs at fairly similar prices.

Alternatively, you could try downloading ready-made cursors from one of the many “free cursor” sites. I recommend deactivating Javascript and other active content before you go searching for such sites. The active content on some of those sites is extremely annoying.

Custom cursors outside the map

You can use custom cursors on any HTML element by using the same type of cursor list in a CSS “cursor:” style setting.

Standard cursor keywords

Standard cursors are “auto”, “crosshair”, “default”, “help”, “move”, “pointer”, “text”, “wait”, and in some environments “hand”, “progress”, “not-allowed”, “no-drop”, “vertical-text” and “all-scroll”.

Changing cursors dynamically

You can change the cursors of a GDraggableObject at any time with .setDraggableCursor() and .setDraggingCursor(). With API versions up to v2.92 you can only set the map cursors with the {draggableCursor} and {draggingCursor} options at the time that you create the map.

It is possible to change the cursors of a map dynamically by using the .getDragObject() Method.

   map.getDragObject().setDraggableCursor("crosshair");

The map cursors are actually owned by the GDraggableObject that is used to control the dragging of the map and its contents.

More advanced stuff

Google Maps API Tutorial

Custom direction details

GDirections.load() doesn’t give you much control over the layout of the directions information. If you want to have the directions displayed slightly differently, you have to read through the GRoutes and GSteps and build up the whole thing yourself.

Here’s a page where I’ve already done that to produce a display that looks almost exactly like that produced by GDirections, but since it’s all done in exposed Javascript, you can take a copy and customise the code to make it look the way that you want it to.

The parameters of my “customPanel()” function are:

  1. The map object.
  2. A string containing the name of the global variable that points to your map.
  3. The GDirections() object.
  4. The div into which the directions are to be placed.

Potential Pitfalls

  1. Don’t forget to use {getSteps:true} otherwise there won’t be any GRoute or GStep information to process
  2. The GDirections “load” event seems to happen just before it centres the map. If you are relying on GDirections to perform the initial centering of the map, then you have to set a short timeout after the “load” before the direction details are processed.