<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>ajgraham.com &#187; JavaScript</title>
	<atom:link href="http://www.ajgraham.com/tag/javascript/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.ajgraham.com</link>
	<description>web design, development and consultation in Prague</description>
	<lastBuildDate>Tue, 01 Nov 2011 22:16:56 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1</generator>
		<item>
		<title>JQuery: Open external links in new window</title>
		<link>http://www.ajgraham.com/2010/05/jquery-open-external-links-in-new-window/</link>
		<comments>http://www.ajgraham.com/2010/05/jquery-open-external-links-in-new-window/#comments</comments>
		<pubDate>Mon, 24 May 2010 18:00:29 +0000</pubDate>
		<dc:creator>alex</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[JQuery]]></category>
		<category><![CDATA[rel="external"]]></category>

		<guid isPermaLink="false">http://www.ajgraham.com/?p=396</guid>
		<description><![CDATA[Finally got round to writing a small bit of code to automatically force anchor links to open in new windows if they are for different domains: $(document).ready(function() { var myDomain = ["www.ajgraham.com", "testing.ajgraham.com", "lifestream.ajgraham.com"]; //do NOT include the http:// pls! $("a[href^='http://']").each(function() { var slicedHref = $(this).attr('href').slice(7); var slashPosition = slicedHref.indexOf("/"); [...]]]></description>
			<content:encoded><![CDATA[<p>Finally got round to writing a small bit of code to automatically force anchor links to open in new windows if they are for different domains:</p>
<pre><code>$(document).ready(function() {
	var myDomain = ["www.ajgraham.com", "testing.ajgraham.com", "lifestream.ajgraham.com"]; //do NOT include the http:// pls!
	$("a[href^='http://']").each(function() {
		var slicedHref = $(this).attr('href').slice(7);
		var slashPosition = slicedHref.indexOf("/");
		if (slashPosition != -1) {
			slicedHref = slicedHref.slice(0,(slashPosition));
		}
		var matchCounter = 0;
		for (i=0;i&lt;myDomain.length;i++) {
			if (slicedHref.indexOf(myDomain[i]) == -1) {
				matchCounter++;
			}
		}
		if (matchCounter == myDomain.length) {
			$(this).attr("target","_blank").attr("rel","external").append("&lt;img class='new-window-link' alt='new window' src='http://www.ajgraham.com/wp-content/themes/ajgrahampro/images/external.png' style='padding-left:2px' /&gt;");
		}
	});
});</code></pre>
<p><a target="_blank" href="http://www.ajgraham.com/codestore/linksinnewwindow/anchorlinkstest.html">See Demo</a></p>
<p><a href="http://www.ajgraham.com/codestore/linksinnewwindow/newWindowLinks.zip">Download basic example</a></p>
<p>Just remember to change
<pre><code>var myDomain = ["www.ajgraham.com", "testing.ajgraham.com", "lifestream.ajgraham.com"];</code></pre>
<p> to your internal domain(s). You can use as many as you like, just don&#8217;t include the http:// bit.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ajgraham.com/2010/05/jquery-open-external-links-in-new-window/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Simple but powerful JQuery Form Validation</title>
		<link>http://www.ajgraham.com/2010/05/simple-but-powerful-jquery-form-validation/</link>
		<comments>http://www.ajgraham.com/2010/05/simple-but-powerful-jquery-form-validation/#comments</comments>
		<pubDate>Thu, 20 May 2010 01:29:46 +0000</pubDate>
		<dc:creator>alex</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[Field]]></category>
		<category><![CDATA[Form]]></category>
		<category><![CDATA[Input]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[JQuery]]></category>
		<category><![CDATA[Validator]]></category>

		<guid isPermaLink="false">http://www.ajgraham.com/?p=363</guid>
		<description><![CDATA[I wrote a relatively simple and intuitive form validation script for a client, which they kindly allowed me to release into the open-source community. Contents The Objective The Basics Including The JavaScript Explaining The Code Core Functions Expanded Functions Options HTML Examples Download License To-Do&#8217;s Change-log The Objective The aim [...]]]></description>
			<content:encoded><![CDATA[<p>I wrote a relatively simple and intuitive form validation script for a client, which they kindly allowed me to release into the open-source community.</p>
<h2>Contents</h2>
<p><a href="#objective">The Objective</a><br />
<a href="#basics">The Basics</a><br />
<a href="#include-the-javascript">Including The JavaScript</a><br />
<a href="#explain-code">Explaining The Code</a><br />
<a href="#core-functions">Core Functions</a><br />
<a href="#expanded-functions">Expanded Functions</a><br />
<a href="#options">Options</a><br />
<a href="#html">HTML</a><br />
<a href="#examples">Examples</a><br />
<a href="#download">Download</a><br />
<a href="#license">License</a><br />
<a href="#to-dos">To-Do&#8217;s</a><br />
<a href="#change-log">Change-log</a></p>
<h2 id="objective">The Objective</h2>
<p>The aim was to develop a simple JavaScript form validator plugin to be:</p>
<ul>
<li>JQuery based</li>
<li>Fast and efficient</li>
<li>Automated (via CSS Classes)</li>
<li>Adjustable (via option settings)</li>
<li>Easily expandable</li>
</ul>
<h2 id="basics">The Basics</h2>
<p>From a simplistic overview, the plugin loops around any form with a submit button and validates input elements based on its CSS classes.<br />
The standard CSS classes it works on are:<br />
<strong>required</strong> &#8211; if an input is marked as &#8216;required&#8217; it simply makes sure the field is not empty.<br />
<strong>email</strong> &#8211; it does a simple regex check to ensure the format is correct.<br />
<strong>digit</strong> &#8211; it checks whether the field only contains numbers 0 to 9.<br />
<strong>alpha</strong> &#8211; checks if the field contains characters a to z and A to Z.</p>
<h2 id="include-the-javascript">Including the JavaScript</h2>
<p>First include JQuery, supports 1.3.2 &#8211; 1.4.2:</p>
<pre><code>&lt;script type=&quot;text/javascript&quot; src=&quot;http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js&quot;&gt;&lt;/script&gt;</code></pre>
<p>Then include our <a href="#download">script</a>:</p>
<pre><code>&lt;script type=&quot;text/javascript&quot; src=&quot;options.validate-form.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;validate-form.js&quot;&gt;&lt;/script&gt;</code></pre>
<h2 id="explain-code">Explaining the Code</h2>
<p>Attaching the code automatically to all Forms is carried out by:</p>
<pre><code>$().ready(function() {
	//attach plugin to all forms with a submit button (except for ignored forms)
	$('form:not('+ formsToIgnore() +')').submit(function() {
		var formId = $(this).attr('id');
		var matchingElements = $('form#'+ formId +' input[type=text], form#'+ formId +' textarea, form#'+ formId +' input[type=checkbox]');
		if (!matchingElements == &quot;&quot;) {
			var formError = validateForm(formId, matchingElements);
			if (formError == true) {
				return false
			} else {
				return true;
			}
		}
	});
});</code></pre>
<p>If you need eager validation (it annoys me, but some people seem to love it #shake-head), set the options variable <em>eagerValidation=true</em> (see script options or examples), or if you don&#8217;t need it, remove it.</p>
<pre><code>//check whether to eagerly validate each field
	if (eagerValidation == true) {
		$('form input[type=text], form textarea, form input[type=checkbox]').focusout(function() {
			var fieldId = $(this).attr('id');
			var formId = $('#'+fieldId).parents('form').attr('id');
			if (validateField(formId, fieldId) == false) {
				removeFieldError(formId, fieldId);
			}
			removeFormError(formId);
			addFormError(formId);
		});
	}</code></pre>
<h2 id="core-functions">Core Functions</h2>
<pre><code>function validateField(formId, fieldId) {
	if (fieldId) {
		removeFieldError(formId, fieldId);

		var element = buildElement(formId, fieldId);
		var fieldValue = jQuery.trim(jQuery(element).val());
		var fieldLength = fieldValue.length;
		var fieldErrorMessage = &quot;&quot;;

		if ($(element).hasClass('text')) {
			if ($(element).hasClass('alpha') &#038;&#038; fieldLength &gt; 0) { // from string start to end, only contains '-' &quot;whitespace&quot; or 'aA'-'zZ'
				if (validateAlpha(fieldValue) == false) {
					fieldErrorMessage = alphaFieldError;
				}
			} else if ($(element).hasClass('digit') &#038;&#038; fieldLength &gt; 0) {
				if (validateDigit(fieldValue) == false) {
					fieldErrorMessage = digitFieldError;
				}
			} else if ($(element).hasClass('email') &#038;&#038; fieldLength &gt; 0) {
				if (validateEmail(fieldValue) == false) {
					fieldErrorMessage = emailFieldError;
				}
			} else if ($(element).hasClass('required') &#038;&#038; fieldLength == 0) {
				fieldErrorMessage = requiredTextError;
			}
		} else if ($(element).is('.textarea.required') &#038;&#038; fieldLength == 0) {
			fieldErrorMessage = requiredTextareaError;
		} else if ($(element).is('.checkbox.required') &#038;&#038; !$(element).is(':checked')) {
			fieldErrorMessage = requiredCheckboxError;
		}

		if (!fieldErrorMessage) {
			return false;
		} else {
			if (customErrorSelectors.length &gt; 0) {
				for (i=0;i&lt;customErrorSelectors.length;i++) { //check for overrides
					if (customErrorSelectors[i] == element) {
						fieldErrorMessage = customErrorMessages[i];
					}
				}
			}
			addFieldError(formId, fieldId, fieldErrorMessage);
			return true;
		}
	}
}

function validateForm(formId, matchingElements) {
	removeAllErrors(formId);

	matchingElements.each(function(index) {
		var elementId = $(this).attr('id');
		var fieldErrorStatus = validateField(formId, elementId);
	});

	if (countFormErrors(formId) &gt; 0) {
		if (focusFirstError == true) {
			focusOnFirstError(formId);
		}
		if (errorSummary == true) {
			addFormError(formId);
		}
		return true;
	} else {
		if (errorSummary == true) {
			removeFormError(formId);
		}
		return false;
	}
}</code></pre>
<h2 id="expanded-functions">Expanded Functions</h2>
<pre><code>function buildElement(formId, fieldId) {
	var element = &quot;form#&quot;+formId+&quot; #&quot;+fieldId;
	return element;
}

function focusOnFirstError(formId) {
	$('form#'+formId+' input.'+inputErrorClass+':first').focus();
}

function formsToIgnore() { //check for forms to ignore
	var formIgnoreItems = &quot;&quot;;
	for (i=0;i&lt;ignoreForms.length;i++) {
		if (i&gt;0) {
			formIgnoreItems += &quot;, &quot;;
		}
		formIgnoreItems += ignoreForms[i];
	}
	return formIgnoreItems;
}

function countFormErrors(formId) {
	var errorCounter = $('form#'+formId+' '+inputWrapper+'.'+inputWrapperErrorClass).size();
	return errorCounter;
}

function addFormError(formId) {
	var formSelector = 'form#'+formId;
	var errorMessageSelector = formSelector+' p.error-summary';
	var errorCounter = countFormErrors(formId);
	if (errorCounter &gt; 0) {
		if ($(errorMessageSelector).length) {
			$(errorMessageSelector).html(errorCounter + ' field(s) are invalid.');
		} else {
			$(formSelector).prepend('&lt;p class=\&quot;error-summary\&quot;&gt;' + errorCounter + ' field(s) are invalid.&lt;/p&gt;');
		}
	}
}

function removeAllErrors(formId) {
	removeFormError(formId);
	removeAllFieldErrors(formId);
}

function removeFormError(formId) {
	$('form#'+formId+' p.error-summary').remove();
}

function removeAllFieldErrors(formId) {
	var formSelector = 'form#'+formId;
	$(formSelector+' '+inputWrapper).removeClass(inputWrapperErrorClass);
	$(formSelector+' input[type=text], '+formSelector+' textarea, '+formSelector+' input[type=checkbox]').removeClass(inputErrorClass);
	$(formSelector+' '+inputWrapper+' p.error-message').remove();
}

function addFieldError(formId, fieldId, fieldErrorMessage) {
	var element = buildElement(formId, fieldId);
	$(element).addClass(inputErrorClass)
			  .parents(inputWrapper).addClass(inputWrapperErrorClass)
									.append('&lt;p class=\&quot;error-message\&quot;&gt;&gt;' + fieldErrorMessage + '&lt;/p&gt;');
}

function removeFieldError(formId, fieldId) {
	var element = buildElement(formId, fieldId);
	$(element).removeClass(inputErrorClass)
			  .parents(inputWrapper).removeClass(inputWrapperErrorClass);
	$(element).parents(inputWrapper).children('p.error-message').remove();
}

function validateAlpha(alpha) {
	var regex = /^[-\sa-zA-Z]+$/
	return regex.test(alpha);
}

function validateDigit(digit) {
	var regex = /^[0-9]+$/
	return regex.test(digit);
}

function validateEmail(email) {
	var regex = /^(([^&lt;&gt;()[\]\\.,;:\s@\&quot;]+(\.[^&lt;&gt;()[\]\\.,;:\s@\&quot;]+)*)|(\&quot;.+\&quot;))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
	return regex.test(email);
}</code></pre>
<h2 id="options">Options</h2>
<pre><code>//Validator options
var eagerValidation = false; //true/false   if set to true, form will eagerly validate each field. False will validate only ever on form submission
var errorSummary = true; //true/false    if set to true will show error summary at the top of the form
var focusFirstError = true; //true/false    if set to true will refocus user input to first error field on form submission
var inputErrorClass = &quot;error&quot;;    //set the class name that will be appended to the form input/textarea when an error is detected
var inputWrapper = &quot;p&quot;;    //set the element type that is used to wrap the form input/textarea in your forms
var inputWrapperErrorClass = &quot;err&quot;;    //set the class name that will be appended to the wrapper of the input/textarea when an error is detected

//Error Messages
var requiredTextError = &quot;cannot be empty&quot;; //Textbox error
var requiredTextareaError = &quot;cannot be empty&quot;; //Textarea error
var requiredCheckboxError = &quot;needs to be ticked&quot;; //Checkbox error
var alphaFieldError = &quot;characters only, no numbers&quot;; //Alpha Textbox error
var digitFieldError = &quot;numbers only, no characters&quot;; //Numeric Textbox error
var emailFieldError = &quot;valid email address only&quot;; //email Textbox error

var ignoreForms = ['#search-form']; //add any forms you need want the form to ignore, e.g search forms, etc. This can be ignored as long as none of the form inputs have 'required' or other validation classes attached

var customErrorSelectors = ['form#testform #el_0','form#testform #el_2']; //include form Id and element Id!
var customErrorMessages = ['this is an error message override, as specified in the config options','this is another error message override']; //Relates directly to customErrorSelectors</code></pre>
<h2 id="html">HTML</h2>
<p>The script assumes an element wrapper is used, and must be included in the options under inputWrapper, the default is &lt;p&gt;. See the examples included for the structure of HTML compatible.</p>
<h2 id="examples">Examples</h2>
<p><a target="_blank" href="http://www.ajgraham.com/codestore/jqueryformvalidator/formvalidation-basic.html">Simple Example</a><br />
<a target="_blank" href="http://www.ajgraham.com/codestore/jqueryformvalidator/formvalidation-complex.html">More Complex Example</a></p>
<h2 id="download">Download</h2>
<p>Options script &#8211; <strong>required for validation script to work</strong></p>
<p><a href="http://www.ajgraham.com/codestore/jqueryformvalidator/jquery.form-validator.zip">Download everything in 1 zipped package</a></p>
<h2 id="license">License</h2>
<p>Released under <a href="http://www.ajgraham.com/codestore/jqueryformvalidator/MIT-LICENSE.txt">MIT License</a>.</p>
<h2 id="to-dos">To Do&#8217;s</h2>
<ul>
<li>Improve the efficiency of the code execution.</li>
<li>Add min-length class options for fields.</li>
</ul>
<h2 id="change-log">Change-log</h2>
<p>2010/05/20: v0.2 released</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ajgraham.com/2010/05/simple-but-powerful-jquery-form-validation/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>XHTML and JavaScript checkbox colour change</title>
		<link>http://www.ajgraham.com/2009/10/xhtml-and-javascript-checkbox-colour-change/</link>
		<comments>http://www.ajgraham.com/2009/10/xhtml-and-javascript-checkbox-colour-change/#comments</comments>
		<pubDate>Sun, 18 Oct 2009 22:48:09 +0000</pubDate>
		<dc:creator>alex</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[Checkbox]]></category>
		<category><![CDATA[Colour Change Switch]]></category>
		<category><![CDATA[Colour Hover]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[MouseOver]]></category>
		<category><![CDATA[Style]]></category>

		<guid isPermaLink="false">http://www.ajgraham.com/?p=109</guid>
		<description><![CDATA[I wrote a very simple little piece of JavaScript that changes the colour, background colour and font colour of a checkbox depending on the Mouse Event (onclick, onmouseover and onmouseout) and whether the checkbox is ticked or not. It can also reset it back to its previous settings too. XHTML: [...]]]></description>
			<content:encoded><![CDATA[<p>I wrote a very simple little piece of JavaScript that changes the colour, background colour and font colour of a checkbox depending on the Mouse Event (onclick, onmouseover and onmouseout) and whether the checkbox is ticked or not. It can also reset it back to its previous settings too.</p>
<h4>XHTML:</h4>
<pre>
<code>&lt;label for="cb1" id="lb1" onclick="mouseToggle('cb1', 'lb1', '#000', '#fff', '#cccccc', '#000000', true)" onmouseover="mouseToggle('cb1', 'lb1', '#000', '#fff', '#cccccc', '#000000', true)" onmouseout="mouseToggle('cb1','lb1','#000','#fff','#cccccc','#000000', false)"&gt;
&lt;input type="checkbox" name="test" value="Test Checkbox1" id="cb1"/&gt;Test Checkbox1&lt;/label&gt;</code>
</pre>
<h4>JavaScript:</h4>
<pre><code>function mouseToggle(checkbox,label,bgcolour,fontcolour,bgreset,fontreset,mouseIn){
	if(document.getElementById)
	{
		var cb = document.getElementById(checkbox);
		var label = document.getElementById(label);
		if(cb.checked == false)
		{
			if( mouseIn == true )
			{
				label.style.backgroundColor = bgcolour;
				label.style.color = fontcolour;
			}
			else
			{
				label.style.backgroundColor = bgreset;
				label.style.color = fontreset;
			}
		}
	}
}
</code></pre>
<h4>Example:</h4>
<p><a href="http://www.ajgraham.com/codestore/togglecheckbox/checkbox.html" target="_blank">Demo of functionality</a></p>
<p>Something similar was used for <a href="http://www.howdenparkcentre.co.uk" target="_blank">http://www.howdenparkcentre.co.uk</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.ajgraham.com/2009/10/xhtml-and-javascript-checkbox-colour-change/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The problem with using the Google Maps API for UK addresses</title>
		<link>http://www.ajgraham.com/2009/09/the-problem-with-using-the-google-maps-api-for-uk-addresses/</link>
		<comments>http://www.ajgraham.com/2009/09/the-problem-with-using-the-google-maps-api-for-uk-addresses/#comments</comments>
		<pubDate>Tue, 01 Sep 2009 16:59:23 +0000</pubDate>
		<dc:creator>alex</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[address]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[British]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[maps]]></category>
		<category><![CDATA[UK]]></category>

		<guid isPermaLink="false">http://ajgraham.com/?p=17</guid>
		<description><![CDATA[I love the Google Maps API. Except when using it for UK based addresses. There is a big problem with any app created using the Google Maps API &#8211; UK postcodes will NOT be processed, worse still, they return errors. To give some background on the issue, The Royal Mail [...]]]></description>
			<content:encoded><![CDATA[<p>I love the Google Maps API. Except when using it for UK based addresses. There is a big problem with any app created using the Google Maps API &#8211; UK postcodes will <em>NOT</em> be processed, worse still, they return errors.</p>
<p>To give some background on the issue, The Royal Mail own the copywrite for the <acronym title="Postcode Address Finder">PAF</acronym> (Postcode Address File) as its called and charge anyone who wants to access it. You&#8217;re probably thinking &#8220;but I&#8217;ve used postcodes on Google Maps lots of times before&#8230;.&#8221; and you&#8217;d be right. The problem emerges as Google refuses (in my opinion rightly so) to pay for its API to access the PAF (see <a href="http://www.guardian.co.uk/technology/2007/apr/26/freeourdata.guardianweeklytechnologysection">background information</a>), which means that anyone using the Google Maps API for UK purposes is severely handicapped by its limitations from a usability and functionality point of view. What really rubs salt into the wounds is that almost every other major country has there post/zipcode data available freely.</p>
<p>So until this ridiculous situation is fixed, API developers using the Maps API for UK purposes will have plenty of headaches.</p>
<p><strong>Update 9/12/2009</strong>: UK Postcode data will finally be free in April 2010, source: <a href="http://news.bbc.co.uk/1/hi/technology/8402327.stm">http://news.bbc.co.uk/1/hi/technology/8402327.stm</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.ajgraham.com/2009/09/the-problem-with-using-the-google-maps-api-for-uk-addresses/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>

