// Requires the 'SWFObject' JavaScript library
swfobject.embedSWF("Assets/Flash/Promotion.swf", "promotion", "627", "280", "9.0.0");

/**
 * The STORM global namespace object.
 * 
 * @class STORM
 * @static
 * @methods loaded, external, getElementsByClassName, slide, init
 */
var STORM = {
	/**
	 * Augment the STORM class so it includes a method
	 * which checks when the Document Object Model (DOM) has loaded
	 *
	 * @class STORM
	 * @param Function
	 * @return Function
	 */
	loaded: (function() 
	{
		// create event function stack
		var load_events = [], load_timer, script, done, exec, old_onload;
		
		var init = function () 
		{
			done = true;
	
			// kill the timer
			clearInterval(load_timer);
	
			// execute each function in the stack in the order they were added
			while ((exec = load_events.shift())) { 
				exec(); 
			}
	
			if (script) { 
				script.onreadystatechange = ''; 
			}
		};
		
		return function (func) 
		{
			// if the init function was already ran, just run this function now and stop
			if (done) { 
				return func(); 
			}
		
			if (!load_events[0]) {
				// W3C Standard Compliant Browsers
				if (document.addEventListener) { 
					document.addEventListener("DOMContentLoaded", init, false); 
				}
				
				// for Internet Explorer
				if (/MSIE/i.test(navigator.userAgent)) {
					document.write("<script id=__ie_onload defer src=//0><\/scr"+"ipt>");
					script = document.getElementById("__ie_onload");
					script.onreadystatechange = function() 
					{
						if (this.readyState == "complete") {
							init(); // call the onload handler
						}
					};
				}
		
				// for Safari
				if (/WebKit/i.test( navigator.userAgent )) {
					load_timer = setInterval(function() 
					{
						if (/loaded|complete/.test(document.readyState)) { 
							init(); // call the onload handler
						}
					}, 10);
				}
		
				// for other browsers set the window.onload, but also execute the old window.onload
				old_onload = window.onload;
				window.onload = function() 
				{
					console.log("waiting for window onload");
					init();
					if (old_onload) { 
						old_onload(); 
					}
				};
			}
		
			load_events.push(func);
		};
	})(),
	
	/**
	 * Augment the STORM class so it includes a method
	 * which finds all relevant links and sets them to open in a popup window
	 *
	 * @class STORM
	 */
	external: function() 
	{
		// first store all anchor elements in an array
		var a = document.getElementsByTagName('a');
		
		// store array length in variable
		var len = a.length;
		
		// loop through the array checking for any A elements with an "rel" attribute that equals "external"
		for (var i=0; i<len; i++) {
			if (a[i].getAttribute( 'rel' ) == 'external') {
				a[i].onclick = function() {
					popup( this.href, screen.availWidth, screen.availHeight, 1 ); return false; 
				};
			}
		}
		
		// private method for opening a popup window
		var popup = function() 
		{
			var url = arguments[0];
			var w = arguments[1];
			var h = arguments[2];
			var toggle = arguments[3];
			
			// set x and y positions of new window
			x = screen.width / 2 - ( w / 2 );
			y = screen.height / 2 - ( h / 2 );
			
			// open window to specific
			window.open( url, 'popup', 'location=yes, resizable=yes, width=' + w + ',height=' + h + ',scrollbars=' + toggle + ',left=' + x + ',top=' + y );
		};
	},
	
	/**
	 * Augment the STORM class so it includes a method
	 * which finds all relevant elements with a specific class name, including the ability to choose a HTML tag limit
	 *
	 * @class STORM
	 * @param String class_name name of class to search each element for
	 * @param String tag HTML tag to limit the search by e.g. 'DIV' only search for DIV elements with specified class name
	 * @return Array
	 */
	getElementsByClassName: function(class_name, tag)
	{
		// Create an empty Array that will store all the elements with the specified class name
		var classElements = [];
		
		// Check the 'tag' argument is not null or empty
		if (tag == null) { tag = '*'; }
		
		// Store all relevant elements
		var els = document.getElementsByTagName(tag);
		
		// Regular Expression for checking the 'class' attribute
		var pattern = new RegExp("(^|\\s)"+class_name+"(\\s|$)");
		
		for(i=0, j=0, len=els.length; i<len; i++) {
			if (pattern.test(els[i].className)) {
				classElements[j] = els[i];
				j++;
			}
		}
		
		return classElements;
	},
	
	slide: {
		/*
		Because I wanted the html to be as simple as possible and to work with any number of panels, 
		I did not add links with onclick handlers (e.g. <a href="#" onclick="toggle()">) 
		and I also didn't want to have to add IDs to panels. 
		 
		Therefore, I made the script 'smart' enough to discover the panels and add the onclick handlers by itself.
		*/
		PANEL_NORMAL_CLASS: 'panel',
		PANEL_COLLAPSED_CLASS: 'panelcollapsed',
		PANEL_HEADING_TAG: 'h3',
		PANEL_CONTENT_CLASS: 'category',
		PANEL_ANIMATION_DELAY: 20, // milliseconds
		PANEL_ANIMATION_STEPS: 8,
		
		init: function(tag)
		{
			// if an argument is provided then use it to change the CONSTANT variable for which HTML tag is searched for
			STORM.slide.PANEL_HEADING_TAG = tag || 'h3';
			
			// Get all H2 headings in the page and collect them into an array;
			var headingTags = document.getElementsByTagName(STORM.slide.PANEL_HEADING_TAG);
			
			for (var i=0, len=headingTags.length; i<len; i++) {
				var el = headingTags[i];
				
				// Regular Expression pattern which looks for whitespace
				var pattern = /\s/g;
				
				// check that the class attribute has no white space (which would suggest multiple class names applied)
				if ((el.parentNode.className).search(pattern) === -1) {
					// Ignore any H elements who aren't contained within an element set with the required class name
					if (el.parentNode.className != STORM.slide.PANEL_NORMAL_CLASS && el.parentNode.className != STORM.slide.PANEL_COLLAPSED_CLASS) {
						continue;
					}
				} else {
					// check if after the whitespace the class name is equal to 'close' if so then replace the class attribute
					// with the value 'panelcollapsed' as this will automatically hide the sub DIV element when the page loads
					if ((el.parentNode.className).substring((el.parentNode.className).search(pattern)+1) === 'close') {
						// I hide the drop down content this way so that if JavaScript is disabled then CSS wont be hiding the content from users
						el.parentNode.className = 'panelcollapsed';
					}
				}
				
				// Add click event to header
				el.onclick = function()
				{
					// Get the heading's parent, that's the panel itself
					var target = this.parentNode;
					
					// Get the heading text
					var name = this.firstChild.nodeValue;
					
					// See if the target element has a class name of 'STORM.slide.PANEL_COLLAPSED_CLASS' (returns true/false)
					var collapsed = (target.className == STORM.slide.PANEL_COLLAPSED_CLASS);
					
					STORM.slide.animateTogglePanel(target, collapsed);
				};
				
				// Apply mouse 'hand' cursor style so the headers appear more like a link
				el.style.cursor = 'pointer';
			}
		},
		
		/**
		 * Start the expand/collapse animation of the panel
		 *
		 * @param panel reference to the panel div
		 */
		animateTogglePanel: function(panel, expanding)
		{
			/*
			To keep things as flexible as possible, I wanted the script to work easily regardless of the panel height, 
			so when animating, we'll dynamically change the height of the panel content 
			(that's why it needs the overflow:hidden definition in CSS). 
			If you want all panels to have the same height, maybe with scrollable content, 
			I suggest adding another DIV in the panel content and setting its height and overflow.
			*/
			
			/*
			First, it finds the DIV that has the panelcontent class by collecting all descendant DIVs 
			and going through them until it finds the one that has the right class name. 
			This process could have been simplified a little by using getElementsByClassName, 
			but that function is not supported by IE.
			*/
			var elements = panel.getElementsByTagName("div");
			var panelContent = null;
			for (var i=0, len=elements.length; i<len; i++) {
				if (elements[i].className == STORM.slide.PANEL_CONTENT_CLASS) {
					panelContent = elements[i];
					break;
				}
			}
		 
			/*
			Then, we need to get the height of the panel content, 
			so we make sure it's displayed by setting its display propery to "block" 
			and read its height with offsetHeight property. offsetHeight return its total height, 
			meaning defined height + paddings + border widths, 
			so you should not define any paddings or borders in the panelcontent class, 
			or you'll get inaccurate results.
			*/
			panelContent.style.display = "block";
			
			// Get the height of the content
			var contentHeight = panelContent.offsetHeight;
		 
			// If the animation is for expanding, we need the content visible, but it has to start with a height of 0.
			if (expanding) {
				panelContent.style.height = "0px";
			}
			
			/*
			Calculate by how much the panel should expand or contract on each step 
			by dividing the total height by the number of steps, 
			and the direction is set to positive for expansion, and negative for contraction
			*/
			var stepHeight = contentHeight / STORM.slide.PANEL_ANIMATION_STEPS;
			var direction = (!expanding ? -1 : 1);
		 
			/*
			Set the timeout - here's a tricky thing: 
			we can't call animateStep function directly because we need to pass the reference to the panel content to it. 
			So we set an anonymous function, which in turn will call animateStep. 
			It's confusing, but it works - for more details, read about setInterval callback arguments on Mozilla Developer Center.
			*/
			setTimeout(function(){ STORM.slide.animateStep(panelContent,1,stepHeight,direction); }, STORM.slide.PANEL_ANIMATION_DELAY);
		},
		
		/**
		 * Change the height of the target
		 *
		 * @param panelContent	reference to the panel content to change height
		 * @param iteration		current iteration; animation will be stopped when iteration reaches STORM.slide.PANEL_ANIMATION_STEPS
		 * @param stepHeight		height increment to be added/substracted in one step
		 * @param direction		1 for expanding, -1 for collapsing
		 */
		animateStep: function(panelContent, iteration, stepHeight, direction)
		{
			/*
			This function is called every 20 miliseconds. 
			It receives a reference to the panel content, 
			the current step (iteration number), 
			the step height and direction.
			*/
			
			// If the current iteration is smaller than the total number of iterations...
			if (iteration < STORM.slide.PANEL_ANIMATION_STEPS) {
				/*
				...then change the panel content height to be equal to iteration number multiplied by step height; 
				reverse if it's a collapsing animation;
				
				for example, consider iteration 2 with a step height of 5px, expanding. 
				Panel content height becomes 2*5=10px; at iteration 3 it will be 3*5=15px and so on;
				
				for a collapsing animation, if the total number of steps is 10, 
				at iteration 2 we'd have (10-2)*5 =40px, iteration 3 is (10-3)*5=35px.
				*/
				panelContent.style.height = Math.round(((direction > 0) ? iteration : STORM.slide.PANEL_ANIMATION_STEPS - iteration) * stepHeight) +"px";
				iteration++;
				
				// Set the timeout to call animateStep function again after the specified delay.
				setTimeout(function(){ STORM.slide.animateStep(panelContent,iteration,stepHeight,direction); }, STORM.slide.PANEL_ANIMATION_DELAY);
			} else {
				// ...otherwise, switch the class name for the panel (panel content's parent).
				panelContent.parentNode.className = (direction < 0) ? STORM.slide.PANEL_COLLAPSED_CLASS : STORM.slide.PANEL_NORMAL_CLASS;
				
				// clear any inline styles we've set.
				panelContent.style.display = panelContent.style.height = "";
			}
		}
	},
	
	isIE: (function()
	{
		var pattern = /MSIE/i;
		return pattern.test(navigator.userAgent);
	})(),
	
	/**
	 * The init method checks the current page and calls the relevant methods to apply any required functionailty.
	 */
	init: function()
	{
		/**
		 * SHOULD ONLY RUN IF THERE IS A 'SEARCH' SIDE BAR
		 */
				// Check if this page has a 'search' side bar
				if (document.getElementById('filter') != null) {
					// If it does then initiate the slide method which is required for the search widget
					STORM.slide.init();
				}
				
		/**
		 * SHOULD ONLY RUN IF THIS IS THE 'ABOUT' / 'QUALITY' / 'FENSURE' / BLACKBERRY EXPRESS / FENRECORD PAGES
		 */
				// Check if this page is the 'services' page
				if (window.location.href.indexOf( "about-us" ) != -1 || window.location.href.indexOf( "quality-of-service" ) != -1 || window.location.href.indexOf( "fensure" ) != -1 || window.location.href.indexOf( "blackberry-express" ) != -1 || window.location.href.indexOf( "fenrecord" ) != -1) {
					// If it is then initiate the slide method rquired for this page
					STORM.slide.init('h2');
				}
		
		/**
		 * SHOULD ONLY RUN IF THIS IS THE 'SERVICES' PAGE
		 */
				// Check if this page is the 'services' page
				if ( window.location.href.indexOf( "services" ) != -1) {
					// If it is then initiate the slide method rquired for this page
					STORM.slide.init('h2');
					
					// Array of H2 arrays
					var headers = [
						"blackberry",
						"business_account_management",
						"remote_connectivity",
						"windows_mobile"
					];
					
					// Store the inital hash value so we can check against it in the polling function
					var lastHash = window.location.hash.toLowerCase();
					
					function loopArray(locationHash)
					{
						// Check location against our list of available hashes
						for (var i=0; i<4; i++) {
							// If there is a match found then expand the relevant section
							if ("#"+headers[i] === locationHash) {
								// Store reference to the element
								var elem = document.getElementById(headers[i]);
								
								// Get the heading's parent, that's the panel itself
								var target = elem.parentNode;
								
								// Get the heading text
								var name = elem.firstChild.nodeValue;
								
								// See if the target element has a class name of 'STORM.slide.PANEL_COLLAPSED_CLASS' (returns true/false)
								var collapsed = (target.className == STORM.slide.PANEL_COLLAPSED_CLASS);
								
								// Animate the relevant section open
								STORM.slide.animateTogglePanel(target, collapsed);
							}
						}
					}
					
					// Check if a hash value has been set initially
					// The double exclamation converts the variable into a Boolean
					// So if there is a hash value then the condition will equal 'true' and the statement run
					if (!!lastHash) {
						// Call a function which loops through the array of available element IDs
						loopArray(lastHash);
					}
				
					// There is no native event listener for location bar hash changes
					// so we have to use a simple polling method to check for differences.
					function pollHash() 
					{
						var locationHash = window.location.hash.toLowerCase();
						
						if (lastHash !== locationHash) 
						{
							lastHash = locationHash;
							
							// Call a function which loops through the array of available element IDs
							loopArray(locationHash);
						}
					}
					
					// Call polling method
					setInterval(pollHash, 100);
				}
		
		/**
		 * SHOULD ONLY RUN IF THERE IS A 'TABBED' ELEMENT
		 */
				var tabs = STORM.getElementsByClassName('tabber','div');
				
				// Check if this page has a 'tab' feature on it
				if (tabs.length > 0) {
					tabs[0].style.display = 'none';
					STORM.tabs.active = true; // window.onload will check this property and then redisplay the tabs if necessary
					STORM.tabs.object = tabs[0]; // pass in the relevant tabbed element
				}
		
		/**
		 * SHOULD ONLY RUN ON 'PRODUCT LISTING' PAGE
		 */
				// Store the Array of 'DIV' elements that have the specified class
				var results = STORM.getElementsByClassName('features','div');
				
				// Check that there are some elements returned before doing anything further
				if (results.length > 0) {
					/*
						SPECIFIC CODE FOR IE BROWSERS...
						In the HTML we have wrapped an A tag around a load of block elements, 
						which isn't valid but it made it easier to create one big link for a specific product section.
						
						But there is a problem with IE in that the A element also wraps around an IMG element,
						but if the user clicks on the section where the IMG element is found it doesn't trigger the A element.
						It's almost like the IMG is sitting outside the A element.
						
						So to sort this out I'm looping through all DIV elements that have a class value of "features" 
						and for each IMG found within the DIV I'm setting an onclick event listener which the handler then redirects the browser location to the relevant product URL
					*/
					if (STORM.isIE) {
						// Now loop through them one by one and apply the required style to them
						for (var i=0, len=results.length; i<len; i++) {
							results[i].getElementsByTagName("img")[0].onclick = function()
							{
								var prodLink;
								function Recursion(node)
								{
									if (node.nodeName !== "A") {
										arguments.callee(node.parentNode);
									} else {
										prodLink = node;
									}
								}
								
								Recursion(this);
								document.location.href = prodLink;
							};
						}
					}
					
					// Now loop through each DIV element (only those that have a class value of "features") 
					// and apply the required style to them so they show the product features list when the user rolls their mouse over the DIV
					for (var j=0, leng=results.length; j<leng; j++) {
						results[j].style.display ='block';
						results[j].className = 'features off';
						results[j].onmouseover = function()
						{
							this.className = 'features';
						};
						results[j].onmouseout = function()
						{
							this.className = 'features off';
						};
					}
				}
	},
	
	tabs: {
		active: false,
		object: null,
		displayObject: function()
		{
			this.object.style.display = 'block';
		}
	}
};

STORM.loaded(STORM.init);

// When the DOM loads the above init method checks if there is a tabbed element and hides it (this is incase it takes a while to load and apply the relevent tab styles)
// And so when the page has actually finished loading we check whether there is a tabbed element, and if so we set it to display.
window.onload = function(){
	if(STORM.tabs.active) {
		STORM.tabs.displayObject();
	}
};
