Cross browser SVG Masking – Supports IE8, IE9, IE10, Firefox, Chrome

In one of my recent projects I  ran into performance issues with the usage of multiple  png images(each image up to 1mb). So I started to research on the masking and clipping concepts over the web but nothing was close to what I wanted to achieve.  I want the code to be simple, maintainable and mostly work on all commonly used browsers.

I’ve come up with a cross-browser solution which supports Firefox, chrome, safari, IE v9 and above. Thankfully  IE v9 and above have support for basic SVG, masking and clipping. Here are some examples from the microsoft site: http://msdn.microsoft.com/en-us/library/ie/bg124134(v=vs.85).aspx on simple masking and clipping.

For IE v8: You can use the chromakey filter technique found in this wonderful tutorial: thenittygritty.co/css-masking

Here is the code / some steps involved:

You don’t need to create complex vector code or .SVG files for this solution. I made made the required mask shape as mask.png and applied it on top of the sample.jpg using SVN Mask code as shown below:

    <div class="svgMask">
        <svg width="400" height="300" baseProfile="full" version="1.2">
            <defs>
                <mask id="svgmask2" maskUnits="userSpaceOnUse" maskContentUnits="userSpaceOnUse" transform="scale(1)">
                    <image width="100%" height="100%" xlink:href="mask.png"/>
                </mask>
            </defs>
            <image mask="url(#svgmask2)" width="100%" height="100%" y="0" x="0" xlink:href="sample.jpg"/>
        </svg>
    </div>

Here is the demo on JSFiddle: http://jsfiddle.net/giri_jeedigunta/Z2J34/

The important thing with SVG is the height attribute. If you don’t mention proper height nothing will be visible.

DOM Manipulation: Please refer the createlementNS on MDN : https://developer.mozilla.org/en-US/docs/Web/API/document.createElementNS

Mobile Support: This worked perfectly fine on iPhone, iPad, Chrome on Android Phones but the native browser on the samsung s3 did not render this code.

Even though most of the online resources like http://caniuse.com/svg said that there is support for android, it failed to render on the native browser. You can use -webkit-mask as a fallback option for scenarios like this.

Advertisements

Custom infowindow with jQuery UI Tabs using infobox, Google Maps API v3

Note:
[Edited on June 2017]: To use the Google Maps JavaScript API Versions 3.27 and above, you must generate your own API key and add a list of  domains you intend to use this API. More details – https://developers.google.com/maps/documentation/javascript/get-api-key

————————————————————————————————–

Recently, I started using Google Maps API v3 and one of the things I wanted to achieve is to customize the default infowindow, re-skin it and add some tabbed content into it.

After some R&D I found infobox JS which allows you to customize the default infowindow. You can add styles and any HTML content. In a way it actually replaces the default infowindow functionality.

So in this tutorial I’m going to explain how I’ve used Google Maps API v3, jQuery UI Tabs and Infobox JS to achieve the below:

Prerequisites: Knowledge on XHTML / HTML5, CSS, JSON, Good understanding of JS and jQuery is required.

More Tutorials on Google Maps API V3: I’ve recently put up a tutorial on Get Directions and Custom Directions Panel.

HTML5 Mark-up:

<!DOCTYPE html>
<html>
  <head>

    <title>Google Maps API V3: Custom Infowindow using Infobox</title>
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no" />

    <link rel="stylesheet" href="jquery-ui-1.9.0.custom/css/ui-lightness/jquery-ui-1.9.0.custom.min.css" type="text/css" media="all" />

    http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js    
    http://jquery-ui-1.9.0.custom/js/jquery-ui-1.9.0.custom.min.js

    http://maps.googleapis.com/maps/api/js?key=&sensor=false
    http://infobox.js

    <style type="text/css">
    	body {margin: 0; padding: 0; width:100%; height: 1000px; overflow: hidden}
    	#map_canvas {margin:0 auto; width: 100%; height: 90%}
		#tabs {font-size: x-small; width: 255px; height: 150px}
		#tabs .ui-tabs-nav {height: 25px}
		p {font-size: x-small; marign: 0; padding: 0}
    </style>

  </head>
  <body>

http://sample.js </body> </html>

Google Maps API v3 Basics:

Reference Javascript script:

You need to add the below reference Javascript script to your page. There is no need of API key to use Google Maps API v3. Sensor parameter is false by default. If your device have a GPS sensor make the sensor parameter true(sensor=true).

http://maps.googleapis.com/maps/api/js?key=&sensor=false

Creating a Map:

To initialize the Map, we need to call constructor of Map class. It takes 2 arguments one is reference of HTML element to insert map (

) and two is Map options object.

map = new google.maps.Map(mapCanvas, {
	zoom: 10,
	center: new google.maps.LatLng(-33.950198, 151.259302),
	mapTypeId: google.maps.MapTypeId.ROADMAP 
});

zoom: It is a number to set initial zoom level of the map
center: It sets center of the map by taking coordinates of latitude and longitude.
mapTypeId: It specifies initial type of map. It is an identifier of google.maps.MapTypeId class.

Before continuing further please go through the Google MAPS API v3 Tutorials and get familiarized with the default options and functionalities.

Customizing infowindow using infobox JS:

The objective of this JS is to access the JSON Data and setup the markers using the latitude and longitude on the Google Map and add the custom infobox with jQuery UI Tabs for each of the markers.

For this tutorial I’ve used a JSON file which contains the location data(latitude and longitude). I’ve used a Singleton JS pattern coding standard for the JS. You can read more about this pattern here: The Singleton Pattern – Addy Osmani

Below is the JS code:

var myCustomMaps = (function (jQuery) {
	var instance, 
		map,
		mapCanvas = jQuery('#map_canvas')[0], 
		init = function () {
			return {
				pageLoad: function () {
					this.invokeMyMaps();										
				},	
				invokeMyMaps: function() {	

					var	markers = [], infoBubbles = [], infoBubble, 
						contentString=['

‘,’

‘,’

‘,’

‘,’

‘,’

‘,’

Tab 1 content. You can customize it further and make this dynamic / JS Object

‘,’

‘,’

‘,’

Tab 2 content

‘,’

‘,’

‘,’

Tab 3 content

‘,’

‘,'</div>’].join(”); map = new google.maps.Map(mapCanvas, { zoom: 10, center: new google.maps.LatLng(-33.950198, 151.259302), mapTypeId: google.maps.MapTypeId.ROADMAP }); jQuery.ajax({ url: ‘Beach.json’, type: ‘GET’, dataType: ‘json’, success: function(D) { beachSpecs = D.beaches; jQuery.each(beachSpecs, function(k, v) { //console.log(v.beachName, v.latitude, v.longitude); // Creating / Initiating Markers: var marker = new google.maps.Marker({ position: new google.maps.LatLng(v.latitude, v.longitude), map: map, title: jQuery.trim(v.beachName) }); // Creating / Initiating Infobox infoBubble = new InfoBox({ content: contentString, // Tab content gets appended here. disableAutoPan: false, maxWidth: 0, pixelOffset: new google.maps.Size(-140, 0), zIndex: null, boxStyle: { //background: “url(‘tipbox.gif’) no-repeat”, opacity: 1, width: “280px” }, closeBoxMargin: “0px”, closeBoxURL: “http://www.google.com/intl/en_us/mapfiles/close.gif&#8221;, infoBoxClearance: new google.maps.Size(1, 1), isHidden: false, pane: “floatPane”, enableEventPropagation: true }); markers[k] = marker; infoBubbles[k] = infoBubble; // Binding Tab Functionality to infowindow google.maps.event.addListener(infoBubble, ‘domready’, function() { jQuery(“#tabs”).tabs(); }); // Marker Mouse events google.maps.event.addListener(marker, ‘mouseup’, function() { $.each(infoBubbles, function(ix, vx) { if(ix >; 0) { infoBubbles[ix].close(); } }); infoBubble.open(map, marker); }); }); }, // success error: function (xhr, textStatus, errorThrown) { alert(“Error: ” + (errorThrown ? errorThrown : xhr.status)); } // error }); //ajax } //invokeMyMaps }; }; return { load: function () { if (!instance) { instance = init(); } return instance; } }; })(jQuery); (function (jQuery) { var myMaps = myCustomMaps.load(); myMaps.pageLoad(); })(jQuery);


All the Map related functionality is wrapped in the invokeMyMaps function. The below code is required to initialize the Google Map API.

map = new google.maps.Map(mapCanvas, {
	zoom: 10,
	center: new google.maps.LatLng(-33.950198, 151.259302),
	mapTypeId: google.maps.MapTypeId.ROADMAP
});

My next steps are to access the JSON File using the jQuery Ajax Call. On Success I’m accessing the JSON data and doing the following:

Setting up the Markers:

The below JS code is for setting up the Markers on the map with the latitude and longitude data from the JSON Object.

// Creating / Initiating Markers:
var marker = new google.maps.Marker({
	position: new google.maps.LatLng(v.latitude, v.longitude),
	map: map, 
	title: jQuery.trim(v.beachName)
});

Read more about markers.

Creating the Infobox:

Infobox is basically an enhanced version of an Infowindow. The below code is for setting up the infobox with options.

// Creating / Initiating Infobox					
infoBubble = new InfoBox({
	content: contentString, // Tab content gets appended here.
	disableAutoPan: false, 
	maxWidth: 0, 
	pixelOffset: new google.maps.Size(-140, 0), 
	zIndex: null, 
	boxStyle: { 
		//background: "url('tipbox.gif') no-repeat", 
		opacity: 1, 
		width: "280px"
	}, 
	closeBoxMargin: "0px", 
	closeBoxURL: "http://www.google.com/intl/en_us/mapfiles/close.gif", 
	infoBoxClearance: new google.maps.Size(1, 1), 
	isHidden: false, 
	pane: "floatPane", 
	enableEventPropagation: true									
});

The content option is where you need to pass your custom HTML Content. I’m passing the jQuery UI Tads code using contentString variable and Infobox gives you a lot of options to play around and do maximum customization.

Read the detailed documentation on Infobox.

Since I have more than one location data I’m storing the marker details and the infobox details in the arrays:

markers[k] = marker;
infoBubbles[k] = infoBubble;

The Below functions are required to put everything together. The jQuery Tab event needs to be attached to the infobox on domready and infobox .open function is responsible for opening up the infowindow.

// Binding Tab Functionality to infowindow
google.maps.event.addListener(infoBubble, 'domready', function() {
	jQuery("#tabs").tabs();
});	

// Marker Mouse events
google.maps.event.addListener(marker, 'mouseup', function() {
	$.each(infoBubbles, function(ix, vx) {
		if(ix >; 0) {
			infoBubbles[ix].close();											
		}
	});
	infoBubble.open(map, marker);
});

This tutorial is still a work in progress. My intention is to just give a basic idea on how we can put things together. Any feedback is welcome. Please comment or email me for any questions.

Click Here to download the complete code.

More Tutorials on Google Maps API V3: I’ve recently put up a tutorial on Get Directions and Custom Directions Panel.

Good Luck!

JavaScript Create Element – Part 1

This is a simple tutorial helps you start with how to create html elements dynamically using createElement functionality.

XHTML Code

	<h1>JavaScript Create Element</h1>
	<h2>All the tags created dynamically will be added to "subMain" div.</h2>
	<div id="main">
		<form action="#" id="cEleForm" method="post">
			<label><strong>Enter a Tag:</strong><em>(Example:a, p, div, span...)</em></label>
			<input type="text" id="textBox" />
			<input type="button" value="Create" onclick="createEle()" />
			<input type="button" value="Clear Status" onclick="clrSts()" />
		</form>
		<div id="msg"> </div>
	</div>

	<div id="subMain"> </div>

Below is the JavaScript that uses document.createElement functionality to create html elements dynamically:

JavaScript

	function createEle () {
		var sm = document.getElementById('subMain');
		var sMsg = document.getElementById('msg');
		clrSts();
		if(sm) {
			sm.innerHTML +=	"";
			var getTag = document.getElementById('textBox').value;
			if (getTag != '')
			{
				var addNewTag = document.createElement(getTag);
				sm.appendChild(addNewTag);
				sMsg.innerHTML += "Status: "+getTag+" tag added Successfully!... Please check view source."; document.getElementById('textBox').value = ""; } else {alert ("Please enter a tag");} } }

Here is a bit of explanation on how this works:

Prerequisites: You should already be familiar with XHTML before reading further.

The JavaScript createElement and appendChild are the key functions which helps us to create html elements dynamically.

Let’s examine the below code:

document.createElement('p')

The createElement function takes html tag as parameter and creates the tag dynamically. Once the element is created it have to be added to the DOM to access it using appendChild function. Have a look at the below code:

sourceNode.appendChild()

The below example shows how to create a tag dynamically and add it to the “subMain” div.

var sm = document.getElementById('subMain');
var addNewTag = document.createElement('p');
sm.appendChild(addNewTag);

Few things to consider carefully: All the elements which are added dynamically will always be added at the end(In my example the p tag will be added as the last tag in div subMain). Withiout appendChild you will not be able to see the tag anywhere. The dynamically created tags are always empty.

Click here to download the complete code.

Good Luck!

Basic: Form Validation using JavaScript

This is a simple tutorial helps you start with form validation. In this tutorial we’ll build a simple XHTML form with JavaScript validation. You can then adapt this form to your own requirements.

XHTML Form

<form method="post" action="#nosend.php" onsubmit="return validate()" id="basicFormVal">
	<label for="Name">Name:</label>
	<input type="text" id="name" name="name"/>

	<label for="Phone">Phone:</label>
	<input type="text" id="phone" name="phone"/>

	<label for="E-Mail">E-Mail:</label>
	<input type="text" id="email" name="email"/>

	<label for="Country">Country:</label>
	<select id="country">
	        <option selected="selected">Please Select your Country</option>
		<option value="DZ">Algeria</option>
		<option value="AS">American Samoa</option>
		<option value="ZM">Zambia</option>
		<option value="ZW">Zimbabwe</option>
	</select>

	<label for="Feedback">Feedback:</label>
	<textarea id="feedback" rows="6" cols="40"></textarea>

	<input type="submit" value="Submit" id="submitBtn" />
	<input type="reset" value="Reset" id="resetBtn" />

	</form>


The below JavaScript checks if any fields are left empty. If the field is blank, an alert box alerts an error message, the function returns false, and the form will not be submitted:

JavaScript

function validate()
{
  var myForm  = document.getElementById("basicFormVal");
  if(myForm)
    {
      if (myForm.name.value == "" || myForm.phone.value == "" || myForm.email.value == "" || myForm.country.selectedIndex == 0 || myForm.feedback.value == "")
        {
          alert ("Please fill all the fields");
        }
        else
        {
          alert ("Good to submit");
          return true;
        }
    }
}

Here is a bit of explanation on how this works:

Prerequisites: You should already be familiar with XHTML before reading further.

The JavaScript function needs to be placed in the XHTML like below:

<form method="post" action="#nosend.php" onsubmit="return validate()" id="basicFormVal">

The function in the JavaScript is called when the form is submitted. JavaScript treats the XHTML as a tree structure which is called as Document Object Model(DOM). If you can picture this it will be much easier to understand how JavaScript works. Let’s examine the below:

var myForm = document.getElementById("basicFormVal");

The above statement is trying to find the element or the XHTML tag with an id “basicFormVal” with the help of document.getElementById(“basicFormVal”). Once it finds the tag it will store it in a variable myForm. Now myForm can be used as a reference point to read / manipulate the tags inside the <form> tag.

Let’s examine the next bits of code in the JavaScript

	
        myForm.name.value == ""
	myForm.phone.value == ""
	myForm.email.value == ""
	myForm.country.selectedIndex == 0 
	myForm.feedback.value == ""

Note: if you are not familiar with If…else or the conditional operators please go through these tutorials.

name, phone, email, country, feedback are the ids’ on the tags inside the <form> tag. Since we already have the <form> tag in myForm variable it is easy to reference / read the tags inside it using myForm.name which directly points me to the tag with id “name”.

Let’s examine myForm.name.value. The value here is the text object property (Read more about text object properties). Every tag have properties some common some are more specific to each tag. This property helps the JavaScript to read the value inputed by the user and finally checks it aganist empty charcter or null using ==”” and similarly does the same thing with all the specifed tags inside the form.

But when it comes to <select> tag the property is different as I’ve previously mentioned. Here the user cannot type anything he will have to choose form the options provided. So we don’t have the value property for <select> tag. All the options in the select tag are indexed starting from 0. This is the reason we check for selectedIndex == 0. If the index value is 0 it means that user didn’t select anything.

So the function checks all the conditions through if and returs true or false. When all the fields are filled it will return true and alows the form to submit or it will return false and alerts the user to re-fill all the fields.

Click here to download the complete code.

Good Luck!