/*
 * TAU (Tizen Advanced UI)
 * Copyright (c) 2010 - 2014 Samsung Electronics Co., Ltd.
 * License : MIT License V2
 */

(function(window, document, undefined) {

var ns = window.tau = {},
nsConfig = window.tauConfig = window.tauConfig || {};
nsConfig.rootNamespace = 'tau';
nsConfig.fileName = 'tau';
ns.version = '0.9.31';
/*global window, console, define, ns, nsConfig */
/*jslint plusplus:true */
/* 
 * Copyright (c) 2010 - 2014 Samsung Electronics Co., Ltd.
 * License : MIT License V2
 */
/**
 * #Core namespace
 * Object contains main framework methods.
 * @class ns
 * @author Maciej Urbanski <m.urbanski@samsung.com>
 * @author Krzysztof Antoszek <k.antoszek@samsung.com>
 * @author Maciej Moczulski <m.moczulski@samsung.com>
 * @author Piotr Karny <p.karny@samsung.com>
 * @author Tomasz Lukawski <t.lukawski@samsung.com>
 */
(function (document, ns, nsConfig) {
	
			var idNumberCounter = 0,
			currentDate = +new Date(),
			slice = [].slice,
			rootNamespace = nsConfig.rootNamespace,
			fileName = nsConfig.fileName,
			infoForLog = function (args) {
				var dateNow = new Date();
				args.unshift('[' + rootNamespace + '][' + dateNow.toLocaleString() + ']');
			};

		/**
		* Return unique id
		* @method getUniqueId
		* @static
		* @return {string}
		* @member ns
		*/
		ns.getUniqueId = function () {
			return rootNamespace + "-" + ns.getNumberUniqueId() + "-" + currentDate;
		};

		/**
		* Return unique id
		* @method getNumberUniqueId
		* @static
		* @return {number}
		* @member ns
		*/
		ns.getNumberUniqueId = function () {
			return idNumberCounter++;
		};

		/**
		* logs supplied messages/arguments
		* @method log
		* @static
		* @param {...*} argument
		* @member ns
		*/
		ns.log = function () {
			var args = slice.call(arguments);
			infoForLog(args);
			if (console) {
				console.log.apply(console, args);
			}
		};

		/**
		* logs supplied messages/arguments ad marks it as warning
		* @method warn
		* @static
		* @param {...*} argument
		* @member ns
		*/
		ns.warn = function () {
			var args = slice.call(arguments);
			infoForLog(args);
			if (console) {
				console.warn.apply(console, args);
			}
		};

		/**
		* logs supplied messages/arguments and marks it as error
		* @method error
		* @static
		* @param {...*} argument
		* @member ns
		*/
		ns.error = function () {
			var args = slice.call(arguments);
			infoForLog(args);
			if (console) {
				console.error.apply(console, args);
			}
		};

		/**
		* get from nsConfig
		* @method getConfig
		* @param {string} key
		* @param {*} defaultValue
		* @return {*}
		* @static
		* @member ns
		*/
		ns.getConfig = function (key, defaultValue) {
			return nsConfig[key] === undefined ? defaultValue : nsConfig[key];
		};

		/**
		 * set in nsConfig
		 * @method setConfig
		 * @param {string} key
		 * @param {*} value
		 * @param {boolean} [asDefault=false] value should be treated as default (doesn't overwrites the config[key] if it already exists)
		 * @static
		 * @member ns
		*/
		ns.setConfig = function (key, value, asDefault) {
			if (!asDefault || (asDefault && nsConfig[key] === undefined)) {
				nsConfig[key] = value;
			}
		};

		/**
		 * Return path for framework script file.
		 * @method getFrameworkPath
		 * @returns {?string}
		 * @member ns
		 */
		ns.getFrameworkPath = function () {
			var scripts = document.getElementsByTagName('script'),
				countScripts = scripts.length,
				i,
				url,
				arrayUrl,
				count;
			for (i = 0; i < countScripts; i++) {
				url = scripts[i].src;
				arrayUrl = url.split('/');
				count = arrayUrl.length;
				if (arrayUrl[count - 1] === fileName + '.js' || arrayUrl[count - 1] === fileName + '.min.js') {
					return arrayUrl.slice(0, count - 1).join('/');
				}
			}
			return null;
		};

		}(window.document, ns, nsConfig));

/*global window, define, ns */
/* Copyright  2010 - 2014 Samsung Electronics Co., Ltd.
 * License : MIT License V2
 */
/*jslint plusplus: true, nomen: true */
//  * @TODO add support of $.mobile.buttonMarkup.hoverDelay
/*
 * Defaults settings object
 * @author Maciej Urbanski <m.urbanski@samsung.com>
 * @class ns.defaults
 */
(function (ns) {
	
	
			ns.defaults = {};

			Object.defineProperty(ns.defaults, "autoInitializePage", {
				 get: function(){
					 return ns.getConfig("autoInitializePage", true);
				 },
				 set: function(value){
					 return ns.setConfig("autoInitializePage", value);
				 }
			});

			Object.defineProperty(ns.defaults, "dynamicBaseEnabled", {
				 get: function(){
					 return ns.getConfig("dynamicBaseEnabled", true);
				 },
				 set: function(value){
					 return ns.setConfig("dynamicBaseEnabled", value);
				 }
			});

			Object.defineProperty(ns.defaults, "pageTransition", {
				 get: function(){
					 return ns.getConfig("pageTransition", "none");
				 },
				 set: function(value){
					 return ns.setConfig("pageTransition", value);
				 }
			});

			Object.defineProperty(ns.defaults, "popupTransition", {
				 get: function(){
					 return ns.getConfig("popupTransition", "none");
				 },
				 set: function(value){
					 return ns.setConfig("popupTransition", value);
				 }
			});

			}(ns));

/*global window, define*/
/*jslint bitwise: true */
/* 
 * Copyright (c) 2010 - 2014 Samsung Electronics Co., Ltd.
 * License : MIT License V2
 */
/*
 * @author Maciej Urbanski <m.urbanski@samsung.com>
 * @author Piotr Karny <p.karny@samsung.com>
 */
(function (ns) {
	
	
			// Default configuration properties
			ns.setConfig('rootDir', ns.getFrameworkPath(), true);
			ns.setConfig('version', '');
			ns.setConfig('allowCrossDomainPages', false, true);
			ns.setConfig('domCache', false, true);
			// .. other possible options
			// ns.setConfig('autoBuildOnPageChange', true);
			// ns.setConfig('autoInitializePage', true);
			// ns.setConfig('container', document.body); // for defining application container
			// ns.setConfig('pageContainer', document.body); // same as above, but for wearable version

			}(ns));

/*global window, define*/
/*
* Copyright  2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/*
 * @author Piotr Karny <p.karny@samsung.com>
 */
(function (ns) {
	
	
			// Default configuration properties for mobile
			ns.setConfig('autoBuildOnPageChange', true, true);

			}(ns));

/*global window, define*/
/*jslint bitwise: true */
/* 
 * Copyright (c) 2010 - 2014 Samsung Electronics Co., Ltd.
 * License : MIT License V2
 */
/**
 * #Support
 * Namespace with helpers function connected with browser properties
 * @class ns.support
 * @author Maciej Urbanski <m.urbanski@samsung.com>
 * @author Piotr Karny <p.karny@samsung.com>
 */
(function (window, document, ns) {
	

			/* $.mobile.media method: pass a CSS media type or query and get a bool return
			note: this feature relies on actual media query support for media queries, though types will work most anywhere
			examples:
				$.mobile.media('screen') // tests for screen media type
				$.mobile.media('screen and (min-width: 480px)') // tests for screen media type with window width > 480px
				$.mobile.media('\@media screen and (-webkit-min-device-pixel-ratio: 2)') // tests for webkit 2x pixel ratio (iPhone 4)
		*/
			// TODO: use window.matchMedia once at least one UA implements it
			var cacheMedia = {},
				testDiv = document.createElement("div"),
				fakeBody = document.createElement("body"),
				fakeBodyStyle = fakeBody.style,
				html = document.getElementsByTagName('html')[0],
				style,
				vendors = [ "Webkit", "Moz", "O" ],
				webos = window.palmGetResource, //only used to rule out scrollTop
				opera = window.opera,
				operamini = window.operamini && ({}).toString.call(window.operamini) === "[object OperaMini]",
				blackBerry,
				testDivStyle = testDiv.style;

			testDiv.id = 'jquery-mediatest';
			fakeBody.appendChild(testDiv);

			/**
			 * Method checks \@media "query" support
			 * @method media
			 * @param {string} query
			 * @return {boolean}
			 * @static
			 * @member ns.support
			 */
			function media(query) {
				var styleBlock = document.createElement("style"),
					cssrule = "@media " + query + " { #jquery-mediatest { position:absolute; } }";
				if (query.cacheMedia === undefined) {
					//must set type for IE!
					styleBlock.type = "text/css";

					if (styleBlock.styleSheet) {
						styleBlock.styleSheet.cssText = cssrule;
					} else {
						styleBlock.appendChild(document.createTextNode(cssrule));
					}

					if (html.firstChild) {
						html.insertBefore(fakeBody, html.firstChild);
					} else {
						html.appendChild(fakeBody);
					}
					html.insertBefore(styleBlock, fakeBody);
					style = window.getComputedStyle(testDiv);
					cacheMedia[query] = (style.position === "absolute");
					styleBlock.parentNode.removeChild(styleBlock);
					fakeBody.parentNode.removeChild(fakeBody);
				}
				return cacheMedia[query];
			}

			function validStyle(prop, value, check_vend) {
				var div = document.createElement('div'),
					uc = function (txt) {
						return txt.charAt(0).toUpperCase() + txt.substr(1);
					},
					vend_pref = function (vend) {
						return "-" + vend.charAt(0).toLowerCase() + vend.substr(1) + "-";
					},
					returnValue,
					check_style = function (vend) {
						var vend_prop = vend_pref(vend) + prop + ": " + value + ";",
							uc_vend = uc(vend),
							propStyle = uc_vend + uc(prop);

						div.setAttribute("style", vend_prop);

						if (!!div.style[propStyle]) {
							returnValue = true;
						}
					},
					checkVendors = check_vend ? [check_vend] : vendors,
					checkVendorsLength = checkVendors.length,
					i;

				for (i = 0; i < checkVendorsLength; i++) {
					check_style(checkVendors[i]);
				}
				return !!returnValue;
			}

			/**
			 *
			 * @param prop
			 * @returns {boolean}
			 */
			function propExists(prop) {
				var uc_prop = prop.charAt(0).toUpperCase() + prop.substr(1),
					props = (prop + " " + vendors.join(uc_prop + " ") + uc_prop).split(" "),
					key;

				for (key = 0; key < props.length; key++) {
					if (props.hasOwnProperty(key) && fakeBodyStyle[props[key]] !== undefined) {
						return true;
					}
				}
				return false;
			}

			function transform3dTest() {
				var prop = "transform-3d";
				return validStyle('perspective', '10px', 'moz') || media("(-" + vendors.join("-" + prop + "),(-") + "-" + prop + "),(" + prop + ")");
			}

			blackBerry = window.blackberry && !propExists("-webkit-transform");

			function baseTagTest() {
				var fauxBase = location.protocol + "//" + location.host + location.pathname + "ui-dir/",
					head = document.head,
					base = head.querySelector("base"),
					fauxEle = null,
					hadBase = false,
					href = "",
					link,
					rebase;

				if (base) {
					href = base.getAttribute("href");
					base.setAttribute("href", fauxBase);
					hadBase = true;
				} else {
					base = fauxEle = document.createElement('base');
					base.setAttribute("href", fauxBase);
					head.appendChild(base);
				}

				link = document.createElement('a');
				link.href = 'testurl';
				if (fakeBody.firstChild) {
					fakeBody.insertBefore(link, fakeBody.firstChild);
				} else {
					fakeBody.appendChild(link);
				}
				rebase = link.href;
				base.href = href || location.pathname;

				if (fauxEle) {
					head.removeChild(fauxEle);
				}

				// Restore previous base href if base had existed
				if (hadBase) {
					base.setAttribute("href", href);
				}

				// Tell jQuery not to append <base> in build mode
				if (location.hash === "#build") {
					return false;
				}

				return rebase.indexOf(fauxBase) === 0;
			}

			function cssPointerEventsTest() {
				var element = document.createElement('x'),
					documentElement = document.documentElement,
					getComputedStyle = window.getComputedStyle,
					supports,
					elementStyle = element.style;

				if (elementStyle.pointerEvents === undefined) {
					return false;
				}

				elementStyle.pointerEvents = 'auto';
				elementStyle.pointerEvents = 'x';
				documentElement.appendChild(element);
				supports = getComputedStyle && getComputedStyle(element, '').pointerEvents === 'auto';
				documentElement.removeChild(element);
				return !!supports;
			}

			function boundingRect() {
				var div = document.createElement("div");
				return div.getBoundingClientRect !== undefined;
			}

			ns.support = {
				media: media,
				/**
				 * Informs browser support transition
				 * @property {boolean} cssTransitions
				 * @member ns.support
				 * @static
				 */
				cssTransitions: (window.WebKitTransitionEvent !== undefined || validStyle('transition', 'height 100ms linear')) && !opera,
				/**
				 * Informs browser support history.pushStare method
				 * @property {boolean} pushState
				 * @member ns.support
				 * @static
				 */
				pushState: window.history.pushState && window.history.replaceState && true,
				/**
				 * Informs browser support media query "only all"
				 * @property {boolean} mediaquery
				 * @member ns.support
				 * @static
				 */
				mediaquery: media("only all"),
				/**
				 * Informs browser support content property on element
				 * @property {boolean} cssPseudoElement
				 * @member ns.support
				 * @static
				 */
				cssPseudoElement: !!propExists("content"),
				/**
				 * Informs browser support overflowScrolling property on element
				 * @property {boolean} touchOverflow
				 * @member ns.support
				 * @static
				 */
				touchOverflow: !!propExists("overflowScrolling"),
				/**
				 * Informs browser support CSS 3D transiotions
				 * @property {boolean} cssTransform3d
				 * @member ns.support
				 * @static
				 */
				cssTransform3d: transform3dTest(),
				/**
				 * Informs browser support boxShadow property on element
				 * @property {boolean} boxShadow
				 * @member ns.support
				 * @static
				 */
				boxShadow: !!propExists("boxShadow") && !blackBerry,
				/**
				 * Informs browser support scrollTop property
				 * @property {boolean} scrollTop
				 * @member ns.support
				 * @static
				 */
				scrollTop: ((window.pageXOffset || document.documentElement.scrollTop || fakeBody.scrollTop) !== undefined && !webos && !operamini) ? true : false,
				/**
				 * Informs browser support dynamic change base tag
				 * @property {boolean} dynamicBaseTag
				 * @member ns.support
				 * @static
				 */
				dynamicBaseTag: baseTagTest(),
				/**
				 * Informs browser support CSS pointer events
				 * @property {boolean} cssPointerEvents
				 * @member ns.support
				 * @static
				 */
				cssPointerEvents: cssPointerEventsTest(),
				/**
				 * Prefix for animations
				 * @property ("-webkit-"|"-moz-"|"-o-"|""} cssAnimationPrefix
				 * @member ns.support
				 * @static
				 */
				cssAnimationPrefix: testDivStyle.hasOwnProperty("webkitAnimation") ? "-webkit-" :
						testDivStyle.hasOwnProperty("mozAnimation") ? "-moz-" :
								testDivStyle.hasOwnProperty("oAnimation") ? "-o-" : "",
				/**
				 * Informs browser support getBoundingClientRect
				 * @property {boolean} boundingRect
				 * @member ns.support
				 * @static
				 */
				boundingRect: boundingRect(),
				/**
				 * Object with browser informations
				 * @property (Object} browser
				 * @property {boolean} browser.ie detects Internet Explorer
				 * @member ns.support
				 * @static
				 */
				browser: {
					ie: (function () {
						var v = 3,
							div = document.createElement("div"),
							a = div.all || [];
						do {
							div.innerHTML = "<!--[if gt IE " + (++v) + "]><br><![endif]-->";
						} while (a[0]);
						return v > 4 ? v : !v;
					}())
				},
				/**
				 * Informs that browser pass all tests for run framework
				 * @method gradeA
				 * @member ns.support
				 * @static
				 * @return {boolean}
				 */
				gradeA: function () {
					return ((this.mediaquery || (this.browser.ie && this.browser.ie >= 7)) &&
						(this.boundingRect || ((window.jQuery && window.jQuery.fn && window.jQuery.fn.jquery.match(/1\.[0-7+]\.[0-9+]?/)) !== null)));
				},
				/**
				 * Informs browser support touch events
				 * @property {boolean} touch
				 * @member ns.support
				 * @static
				 */
				touch: document.ontouchend !== undefined,
				/**
				 * Informs browser support orientation property
				 * @property {boolean} orientation
				 * @member ns.support
				 * @static
				 */
				orientation: window.orientation !== undefined && window.onorientationchange !== undefined
			};
			}(window, window.document, ns));

/*global window, define, XMLHttpRequest, console, Blob */
/*jslint nomen: true, browser: true, plusplus: true */
/* 
 * Copyright (c) 2010 - 2014 Samsung Electronics Co., Ltd.
 * License : MIT License V2
 */
/**
 * #Utilities
 *
 * The Tizen Advanced UI (TAU) framework provides utilities for easy-developing
 * and fully replaceable with jQuery method. When user using these DOM and
 * selector methods, it provide more light logic and it proves performance
 * of web app. The following table displays the utilities provided by the
 * TAU framework.
 *
 * @class ns.util
 * @author Maciej Urbanski <m.urbanski@samsung.com>
 * @author Krzysztof Antoszek <k.antoszek@samsung.com>
 */
(function (window, document, ns) {
	
				var currentFrame = null,
				/**
				 * requestAnimationFrame function
				 * @method requestAnimationFrame
				 * @static
				 * @member ns.util
				*/
				requestAnimationFrame = (window.requestAnimationFrame ||
					window.webkitRequestAnimationFrame ||
					window.mozRequestAnimationFrame ||
					window.oRequestAnimationFrame ||
					function (callback) {
						currentFrame = window.setTimeout(callback.bind(callback, +new Date()), 1000 / 60);
					}).bind(window),
				util = ns.util || {},
				slice = [].slice;

			/**
			 * fetchSync retrieves a text document synchronously, returns null on error
			 * @param {string} url
			 * @param {=string} [mime=""] Mime type of the resource
			 * @return {string|null}
			 * @static
			 * @member ns.util
			 */
			function fetchSync(url, mime) {
				var xhr = new XMLHttpRequest(),
					status;
				xhr.open("get", url, false);
				if (mime) {
					xhr.overrideMimeType(mime);
				}
				xhr.send();
				if (xhr.readyState === 4) {
					status = xhr.status;
					if (status === 200 || (status === 0 && xhr.responseText)) {
						return xhr.responseText;
					}
				}

				return null;
			}
			util.fetchSync = fetchSync;

			/**
			 * Removes all script tags with src attribute from document and returns them
			 * @param {HTMLElement} container
			 * @return {Array.<HTMLElement>}
			 * @private
			 * @static
			 * @member ns.util
			 */
			function removeExternalScripts(container) {
				var scripts = slice.call(container.querySelectorAll("script[src]")),
					i = scripts.length,
					script;

				while (--i >= 0) {
					script = scripts[i];
					script.parentNode.removeChild(script);
				}

				return scripts;
			}

			/**
			 * Evaluates code, reason for a function is for an atomic call to evaluate code
			 * since most browsers fail to optimize functions with try-catch blocks, so this
			 * minimizes the effect, returns the function to run
			 * @param {string} code
			 * @return {Function}
			 * @static
			 * @member ns.util
			 */
			function safeEvalWrap(code) {
				return function () {
					try {
						window.eval(code);
					} catch (e) {
						if (typeof console !== "undefined") {
							if (e.stack) {
								console.error(e.stack);
							} else if (e.name && e.message) {
								console.error(e.name, e.message);
							} else {
								console.error(e);
							}
						}
					}
				};
			}
			util.safeEvalWrap = safeEvalWrap;

			/**
			 * Calls functions in supplied queue (array)
			 * @param {Array.<Function>} functionQueue
			 * @static
			 * @member ns.util
			 */
			function batchCall(functionQueue) {
				var i,
					length = functionQueue.length;
				for (i = 0; i < length; ++i) {
					functionQueue[i].call(window);
				}
			}
			util.batchCall = batchCall;

			/**
			 * Creates new script elements for scripts gathered from a differnt document
			 * instance, blocks asynchronous evaluation (by renaming src attribute) and
			 * returns an array of functions to run to evalate those scripts
			 * @param {Array.<HTMLElement>} scripts
			 * @param {HTMLElement} container
			 * @return {Array.<Function>}
			 * @private
			 * @static
			 * @member ns.util
			 */
			function createScriptsSync(scripts, container) {
				var scriptElement,
					scriptBody,
					i,
					length,
					queue = [];

				// proper order of execution
				for (i = 0, length = scripts.length; i < length; ++i) {
					scriptBody = fetchSync(scripts[i].src, "text/plain");
					if (scriptBody) {
						scriptElement = document.adoptNode(scripts[i]);
						scriptElement.setAttribute("data-src", scripts[i].src);
						scriptElement.removeAttribute("src"); // block evaluation
						queue.push(safeEvalWrap(scriptBody));
						if (container) {
							container.appendChild(scriptElement);
						}
					}
				}

				return queue;
			}

			util.requestAnimationFrame = requestAnimationFrame;

			/**
			* cancelAnimationFrame function
			* @method cancelAnimationFrame
			* @return {Function}
			* @member ns.util
			* @static
			*/
			util.cancelAnimationFrame = (window.cancelAnimationFrame ||
					window.webkitCancelAnimationFrame ||
					window.mozCancelAnimationFrame ||
					window.oCancelAnimationFrame ||
					function () {
						// propably wont work if there is any more than 1
						// active animationFrame but we are trying anyway
					window.clearTimeout(currentFrame);
				}).bind(window);

			/**
			 * Method make asynchronous call of function
			 * @method async
			 * @inheritdoc #requestAnimationFrame
			 * @member ns.util
			 * @static
			 */
			util.async = requestAnimationFrame;

			/**
			 * Appends element from different document instance to current document in the
			 * container element and evaluates scripts (synchronously)
			 * @param {HTMLElement} element
			 * @param {HTMLElement} container
			 * @method importEvaluateAndAppendElement
			 * @member ns.util
			 * @static
			 */
			util.importEvaluateAndAppendElement = function (element, container) {
				var externalScriptsQueue = createScriptsSync(removeExternalScripts(element), element),
					newNode = document.importNode(element, true);

				container.appendChild(newNode); // append and eval inline
				batchCall(externalScriptsQueue);

				return newNode;
			};

			/**
			* Checks if specified string is a number or not
			* @method isNumber
			* @return {boolean}
			* @member ns.util
			* @static
			*/
			util.isNumber = function (query) {
				var parsed = parseFloat(query);
				return !isNaN(parsed) && isFinite(parsed);
			};

			/**
			 * Reappend script tags to DOM structure to correct run script
			 * @method runScript
			 * @param {string} baseUrl
			 * @param {HTMLScriptElement} script
			 * @member ns.util
			 * @deprecated 2.3
			 */
			util.runScript = function (baseUrl, script) {
				var newScript = document.createElement("script"),
					scriptData = null,
					i,
					scriptAttributes = slice.call(script.attributes),
					src = script.getAttribute("src"),
					path = util.path,
					request,
					attribute,
					status;

				// 'src' may become null when none src attribute is set
				if (src !== null) {
					src = path.makeUrlAbsolute(src, baseUrl);
				}

				//Copy script tag attributes
				i = scriptAttributes.length;
				while (--i >= 0) {
					attribute = scriptAttributes[i];
					if (attribute.name !== "src") {
						newScript.setAttribute(attribute.name, attribute.value);
					} else {
						newScript.setAttribute("data-src", attribute.value);
					}
				}

				if (src) {
					scriptData = fetchSync(src, "text/plain");
									} else {
					scriptData = script.textContent;
				}

				if (scriptData) {
					// add the returned content to a newly created script tag
					newScript.src = URL.createObjectURL(new Blob([scriptData], {type: "text/javascript"}));
					newScript.textContent = scriptData; // for compatibility with some libs ex. templating systems
				}
				script.parentNode.replaceChild(newScript, script);
			};

			ns.util = util;
			}(window, window.document, ns));

/*global window, define */
/* Copyright (c) 2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/**
 * #Array Utility
 * Utility helps work with arrays.
 * @class ns.util.array
 */
(function (window, document, ns) {
	
				/**
			 * Create an array containing the range of integers or characters
			 * from low to high (inclusive)
			 * @method range
			 * @param {number|string} low
			 * @param {number|string} high
			 * @param {number} step
			 * @static
			 * @return {Array} array containing continous elements
			 * @member ns.util.array
			 */
			function range(low, high, step) {
				// Create an array containing the range of integers or characters
				// from low to high (inclusive)
				//
				// version: 1107.2516
				// discuss at: http://phpjs.org/functions/range
				// +   original by: Waldo Malqui Silva
				// *	example 1: range ( 0, 12 );
				// *	returns 1: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
				// *	example 2: range( 0, 100, 10 );
				// *	returns 2: [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
				// *	example 3: range( 'a', 'i' );
				// *	returns 3: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']
				// *	example 4: range( 'c', 'a' );
				// *	returns 4: ['c', 'b', 'a']
				var matrix = [],
					inival,
					endval,
					plus,
					walker = step || 1,
					chars = false;

				if (!isNaN(low) && !isNaN(high)) {
					inival = low;
					endval = high;
				} else if (isNaN(low) && isNaN(high)) {
					chars = true;
					inival = low.charCodeAt(0);
					endval = high.charCodeAt(0);
				} else {
					inival = (isNaN(low) ? 0 : low);
					endval = (isNaN(high) ? 0 : high);
				}

				plus = inival <= endval;
				if (plus) {
					while (inival <= endval) {
						matrix.push((chars ? String.fromCharCode(inival) : inival));
						inival += walker;
					}
				} else {
					while (inival >= endval) {
						matrix.push((chars ? String.fromCharCode(inival) : inival));
						inival -= walker;
					}
				}

				return matrix;
			}

			/**
			 * Check object is arraylike (arraylike include array and
			 * collection)
			 * @method isArrayLike
			 * @param {Object} object
			 * @return {boolean} Whether arraylike object or not
			 * @member ns.util.array
			 * @static
			 */
			function isArrayLike(object) {
				var type = typeof object,
					length = object && object.length;

				// if object exists and is different from window
				// window object has length property
				if (object && object !== object.window) {
					// If length value is not number, object is not array and collection.
					// Collection type is not array but has length value.
					// e.g) Array.isArray(document.childNodes) ==> false
					return Array.isArray(object) || object instanceof NodeList || type === "function" &&
						(length === 0 || typeof length === "number" && length > 0 && (length - 1) in object);
				}
				return false;
			}

			ns.util.array = {
				range: range,
				isArrayLike: isArrayLike
			};
			}(window, window.document, ns));

/*global window, ns, define, CustomEvent */
/*jslint nomen: true */
/* 
 * Copyright (c) 2010 - 2014 Samsung Electronics Co., Ltd.
 * License : MIT License V2
 */
/**
 * #Events
 *
 * The Tizen Advanced UI (TAU) framework provides events optimized for the Tizen
 * Web application. The following table displays the events provided by the TAU
 * framework.
 * @class ns.event
 */
(function (window, ns) {
	
	
			/**
			* Checks if specified variable is a array or not
			* @method isArray
			* @return {boolean}
			* @member ns.event
			* @private
			* @static
			*/
		var isArray = Array.isArray,
			isArrayLike = ns.util.array.isArrayLike,
			/**
			 * @property {RegExp} SPLIT_BY_SPACES_REGEXP
			 */
			SPLIT_BY_SPACES_REGEXP = /\s+/g,

			/**
			 * Returns trimmed value
			 * @method trim
			 * @param {string} value
			 * @return {string} trimmed string
			 * @static
			 * @private
			 * @member ns.event
			 */
			trim = function (value) {
				return value.trim();
			},

			/**
			 * Split string to array
			 * @method getEventsListeners
			 * @param {string|Array|Object} names string with one name of event, many names of events divided by spaces, array with names of widgets or object in which keys are names of events and values are callbacks
			 * @param {Function} globalListener
			 * @return {Array}
			 * @static
			 * @private
			 * @member ns.event
			 */
			getEventsListeners = function (names, globalListener) {
				var name,
					result = [],
					i;

				if (typeof names === 'string') {
					names = names.split(SPLIT_BY_SPACES_REGEXP).map(trim);
				}

				if (isArray(names)) {
					for (i=0; i<names.length; i++) {
						result.push({type: names[i], callback: globalListener});
					}
				} else {
					for (name in names) {
						if (names.hasOwnProperty(name)) {
							result.push({type: name, callback: names[name]});
						}
					}
				}
				return result;
			};

			ns.event = {

				/**
				* Triggers custom event fastOn element
				* The return value is false, if at least one of the event
				* handlers which handled this event, called preventDefault.
				* Otherwise it returns true.
				* @method trigger
				* @param {HTMLElement} element
				* @param {string} type
				* @param {?*} [data=null]
				* @param {boolean=} [bubbles=true]
				* @param {boolean=} [cancelable=true]
				* @return {boolean=}
				* @member ns.event
				* @static
				*/
				trigger: function (element, type, data, bubbles, cancelable) {
					var evt = new CustomEvent(type, {
							"detail": data,
							//allow event to bubble up, required if we want to allow to listen fastOn document etc
							bubbles: typeof bubbles === "boolean" ? bubbles : true,
							cancelable: typeof cancelable === "boolean" ? cancelable : true
						});
										return element.dispatchEvent(evt);
				},

				/**
				 * Prevent default on original event
				 * @method preventDefault
				 * @param {CustomEvent} event
				 * @member ns.event
				 * @static
				 */
				preventDefault: function (event) {
					var originalEvent = event._originalEvent;
					// @todo this.isPropagationStopped = returnTrue;
					if (originalEvent && originalEvent.preventDefault) {
						originalEvent.preventDefault();
					}
					event.preventDefault();
				},

				/**
				* Stop event propagation
				* @method stopPropagation
				* @param {CustomEvent} event
				* @member ns.event
				* @static
				*/
				stopPropagation: function (event) {
					var originalEvent = event._originalEvent;
					// @todo this.isPropagationStopped = returnTrue;
					if (originalEvent && originalEvent.stopPropagation) {
						originalEvent.stopPropagation();
					}
					event.stopPropagation();
				},

				/**
				* Stop event propagation immediately
				* @method stopImmediatePropagation
				* @param {CustomEvent} event
				* @member ns.event
				* @static
				*/
				stopImmediatePropagation: function (event) {
					var originalEvent = event._originalEvent;
					// @todo this.isPropagationStopped = returnTrue;
					if (originalEvent && originalEvent.stopImmediatePropagation) {
						originalEvent.stopImmediatePropagation();
					}
					event.stopImmediatePropagation();
				},

				/**
				 * Return document relative cords for event
				 * @method documentRelativeCoordsFromEvent
				 * @param {Event} event
				 * @return {Object}
				 * @return {number} return.x
				 * @return {number} return.y
				 * @member ns.event
				 * @static
				 */
				documentRelativeCoordsFromEvent: function(event) {
					var _event = event ? event : window.event,
							client = {
								x: _event.clientX,
								y: _event.clientY
							},
							page = {
								x: _event.pageX,
								y: _event.pageY
							},
							posX = 0,
							posY = 0,
							touch0,
							body = document.body,
							documentElement = document.documentElement;

						if (event.type.match(/^touch/)) {
							touch0 = _event.targetTouches[0] || _event.originalEvent.targetTouches[0];
							page = {
								x: touch0.pageX,
								y: touch0.pageY
							};
							client = {
								x: touch0.clientX,
								y: touch0.clientY
							};
						}

						if (page.x || page.y) {
							posX = page.x;
							posY = page.y;
						}
						else if (client.x || client.y) {
							posX = client.x + body.scrollLeft + documentElement.scrollLeft;
							posY = client.y + body.scrollTop  + documentElement.scrollTop;
						}

						return { x: posX, y: posY };
				},

				/**
				 * Return target relative cords for event
				 * @method targetRelativeCoordsFromEvent
				 * @param {Event} event
				 * @return {Object}
				 * @return {number} return.x
				 * @return {number} return.y
				 * @member ns.event
				 * @static
				 */
				targetRelativeCoordsFromEvent: function(event) {
					var target = event.target,
						cords = {
							x: event.offsetX,
							y: event.offsetY
						};

					if (cords.x === undefined || isNaN(cords.x) ||
						cords.y === undefined || isNaN(cords.y)) {
						cords = ns.event.documentRelativeCoordsFromEvent(event);
						cords.x -= target.offsetLeft;
						cords.y -= target.offsetTop;
					}

					return cords;
				},

				/**
				 * Add event listener to element
				 * @method fastOn
				 * @param {HTMLElement} element
				 * @param {string} type
				 * @param {Function} listener
				 * @param {boolean} [useCapture=false]
				 * @member ns.event
				 * @static
				 */
				fastOn: function(element, type, listener, useCapture) {
					element.addEventListener(type, listener, useCapture || false);
				},

				/**
				 * Remove event listener to element
				 * @method fastOff
				 * @param {HTMLElement} element
				 * @param {string} type
				 * @param {Function} listener
				 * @param {boolean} [useCapture=false]
				 * @member ns.event
				 * @static
				 */
				fastOff: function(element, type, listener, useCapture) {
					element.removeEventListener(type, listener, useCapture || false);
				},

				/**
				 * Add event listener to element that can be added addEventListner
				 * @method on
				 * @param {HTMLElement|HTMLDocument|Window} element
				 * @param {string|Array|Object} type
				 * @param {Function} listener
				 * @param {boolean} [useCapture=false]
				 * @member ns.event
				 * @static
				 */
				on: function(element, type, listener, useCapture) {
					var i,
						j,
						elementsLength,
						typesLength,
						elements,
						listeners;

					if (isArrayLike(element)) {
						elements = element;
					} else {
						elements = [element];
					}
					elementsLength = elements.length;
					listeners = getEventsListeners(type, listener);
					typesLength = listeners.length;
					for (i = 0; i < elementsLength; i++) {
						if (typeof elements[i].addEventListener === "function") {
							for (j = 0; j < typesLength; j++) {
								ns.event.fastOn(elements[i], listeners[j].type, listeners[j].callback, useCapture);
							}
						}
					}
				},

				/**
				 * Remove event listener to element
				 * @method off
				 * @param {HTMLElement|HTMLDocument|Window} element
				 * @param {string|Array|Object} type
				 * @param {Function} listener
				 * @param {boolean} [useCapture=false]
				 * @member ns.event
				 * @static
				 */
				off: function(element, type, listener, useCapture) {
					var i,
						j,
						elementsLength,
						typesLength,
						elements,
						listeners;
					if (isArrayLike(element)) {
						elements = element;
					} else {
						elements = [element];
					}
					elementsLength = elements.length;
					listeners = getEventsListeners(type, listener);
					typesLength = listeners.length;
					for (i = 0; i < elementsLength; i++) {
						if (typeof elements[i].addEventListener === "function") {
							for (j = 0; j < typesLength; j++) {
								ns.event.fastOff(elements[i], listeners[j].type, listeners[j].callback, useCapture);
							}
						}
					}
				},

				/**
				 * Add event listener to element only for one trigger
				 * @method one
				 * @param {HTMLElement|HTMLDocument|window} element
				 * @param {string|Array|Object} type
				 * @param {Function} listener
				 * @param {boolean} [useCapture=false]
				 * @member ns.event
				 * @static
				 */
				one: function(element, type, listener, useCapture) {
					var arraySlice = [].slice,
						i,
						j,
						elementsLength,
						typesLength,
						elements,
						types,
						listeners,
						callbacks = [];
					if (isArrayLike(element)) {
						elements = arraySlice.call(element);
					} else {
						elements = [element];
					}
					elementsLength = elements.length;
					listeners = getEventsListeners(type, listener);
					typesLength = listeners.length;
					for (i = 0; i < elementsLength; i++) {
						if (typeof elements[i].addEventListener === "function") {
							callbacks[i] = [];
							for (j = 0; j < typesLength; j++) {
								callbacks[i][j] = (function(i, j) {
									var args = arraySlice.call(arguments);
									ns.event.fastOff(elements[i], listeners[j].type, callbacks[i][j], useCapture);
									args.shift(); // remove the first argument of binding function
									args.shift(); // remove the second argument of binding function
									listeners[j].callback.apply(this, args);
								}).bind(null, i, j);
								ns.event.fastOn(elements[i], listeners[j].type, callbacks[i][j], useCapture);
							}
						}
					}
				}

			};

			}(window, ns));

/*global define: true, window: true */
/* 
 * Copyright (c) 2010 - 2014 Samsung Electronics Co., Ltd.
 * License : MIT License V2
 */
/**
 * #Selectors Utility
 * Object contains functions to get HTML elements by different selectors.
 * @class ns.util.selectors
 * @author Maciej Urbanski <m.urbanski@samsung.com>
 * @author Krzysztof Antoszek <k.antoszek@samsung.com>
 * @author Jadwiga Sosnowska <j.sosnowska@partner.samsung.com>
 * @author Damian Osipiuk <d.osipiuk@samsung.com>
 */
(function (document, ns) {
	
				/**
			 * @method slice Alias for array slice method
			 * @member ns.util.selectors
			 * @private
			 * @static
			 */
			var slice = [].slice,
				/**
				 * @method matchesSelectorType
				 * @return {string|boolean}
				 * @member ns.util.selectors
				 * @private
				 * @static
				 */
				matchesSelectorType = (function () {
					var el = document.createElement("div");

					if (typeof el.webkitMatchesSelector === "function") {
						return "webkitMatchesSelector";
					}

					if (typeof el.mozMatchesSelector === "function") {
						return "mozMatchesSelector";
					}

					if (typeof el.msMatchesSelector === "function") {
						return "msMatchesSelector";
					}

					if (typeof el.matchesSelector === "function") {
						return "matchesSelector";
					}

					return false;
				}());

			/**
			 * Prefix selector with 'data-' and namespace if present
			 * @method getDataSelector
			 * @param {string} selector
			 * @return {string}
			 * @member ns.util.selectors
			 * @private
			 * @static
			 */
			function getDataSelector(selector) {
				var namespace = ns.getConfig('namespace');
				return '[data-' + (namespace ? namespace + '-' : '') + selector + ']';
			}

			/**
			 * Runs matches implementation of matchesSelector
			 * method on specified element
			 * @method matchesSelector
			 * @param {HTMLElement} element
			 * @param {string} selector
			 * @return {boolean}
			 * @static
			 * @member ns.util.selectors
			 */
			function matchesSelector(element, selector) {
				if (matchesSelectorType && element[matchesSelectorType]) {
					return element[matchesSelectorType](selector);
				}
				return false;
			}

			/**
			 * Return array with all parents of element.
			 * @method parents
			 * @param {HTMLElement} element
			 * @return {Array}
			 * @member ns.util.selectors
			 * @private
			 * @static
			 */
			function parents(element) {
				var items = [],
					current = element.parentNode;
				while (current && current !== document) {
					items.push(current);
					current = current.parentNode;
				}
				return items;
			}

			/**
			 * Checks if given element and its ancestors matches given function
			 * @method closest
			 * @param {HTMLElement} element
			 * @param {Function} testFunction
			 * @return {?HTMLElement}
			 * @member ns.util.selectors
			 * @static
			 * @private
			 */
			function closest(element, testFunction) {
				var current = element;
				while (current && current !== document) {
					if (testFunction(current)) {
						return current;
					}
					current = current.parentNode;
				}
				return null;
			}

			/**
			 * @method testSelector
			 * @param {string} selector
			 * @param {HTMLElement} node
			 * @return {boolean}
			 * @member ns.util.selectors
			 * @static
			 * @private
			 */
			function testSelector(selector, node) {
				return matchesSelector(node, selector);
			}

			/**
			 * @method testClass
			 * @param {string} className
			 * @param {HTMLElement} node
			 * @return {boolean}
			 * @member ns.util.selectors
			 * @static
			 * @private
			 */
			function testClass(className, node) {
				return node && node.classList && node.classList.contains(className);
			}

			/**
			 * @method testTag
			 * @param {string} tagName
			 * @param {HTMLElement} node
			 * @return {boolean}
			 * @member ns.util.selectors
			 * @static
			 * @private
			 */
			function testTag(tagName, node) {
				return node.tagName.toLowerCase() === tagName;
			}

			/**
			 * @class ns.util.selectors
			 */
			ns.util.selectors = {
				matchesSelector: matchesSelector,

				/**
				* Return array with children pass by given selector.
				* @method getChildrenBySelector
				* @param {HTMLElement} context
				* @param {string} selector
				* @return {Array}
				* @static
				* @member ns.util.selectors
				*/
				getChildrenBySelector: function (context, selector) {
					return slice.call(context.children).filter(testSelector.bind(null, selector));
				},

				/**
				* Return array with children pass by given data-namespace-selector.
				* @method getChildrenByDataNS
				* @param {HTMLElement} context
				* @param {string} dataSelector
				* @return {Array}
				* @static
				* @member ns.util.selectors
				*/
				getChildrenByDataNS: function (context, dataSelector) {
					return slice.call(context.children).filter(testSelector.bind(null, getDataSelector(dataSelector)));
				},

				/**
				* Return array with children with given class name.
				* @method getChildrenByClass
				* @param {HTMLElement} context
				* @param {string} className
				* @return {Array}
				* @static
				* @member ns.util.selectors
				*/
				getChildrenByClass: function (context, className) {
					return slice.call(context.children).filter(testClass.bind(null, className));
				},

				/**
				* Return array with children with given tag name.
				* @method getChildrenByTag
				* @param {HTMLElement} context
				* @param {string} tagName
				* @return {Array}
				* @static
				* @member ns.util.selectors
				*/
				getChildrenByTag: function (context, tagName) {
					return slice.call(context.children).filter(testTag.bind(null, tagName));
				},

				/**
				* Return array with all parents of element.
				* @method getParents
				* @param {HTMLElement} context
				* @param {string} selector
				* @return {Array}
				* @static
				* @member ns.util.selectors
				*/
				getParents: parents,

				/**
				* Return array with all parents of element pass by given selector.
				* @method getParentsBySelector
				* @param {HTMLElement} context
				* @param {string} selector
				* @return {Array}
				* @static
				* @member ns.util.selectors
				*/
				getParentsBySelector: function (context, selector) {
					return parents(context).filter(testSelector.bind(null, selector));
				},

				/**
				* Return array with all parents of element pass by given selector with namespace.
				* @method getParentsBySelectorNS
				* @param {HTMLElement} context
				* @param {string} selector
				* @return {Array}
				* @static
				* @member ns.util.selectors
				*/
				getParentsBySelectorNS: function (context, selector) {
					return parents(context).filter(testSelector.bind(null, getDataSelector(selector)));
				},

				/**
				* Return array with all parents of element with given class name.
				* @method getParentsByClass
				* @param {HTMLElement} context
				* @param {string} className
				* @return {Array}
				* @static
				* @member ns.util.selectors
				*/
				getParentsByClass: function (context, className) {
					return parents(context).filter(testClass.bind(null, className));
				},

				/**
				* Return array with all parents of element with given tag name.
				* @method getParentsByTag
				* @param {HTMLElement} context
				* @param {string} tagName
				* @return {Array}
				* @static
				* @member ns.util.selectors
				*/
				getParentsByTag: function (context, tagName) {
					return parents(context).filter(testTag.bind(null, tagName));
				},

				/**
				* Return first element from parents of element pass by selector.
				* @method getClosestBySelector
				* @param {HTMLElement} context
				* @param {string} selector
				* @return {HTMLElement}
				* @static
				* @member ns.util.selectors
				*/
				getClosestBySelector: function (context, selector) {
					return closest(context, testSelector.bind(null, selector));
				},

				/**
				* Return first element from parents of element pass by selector with namespace.
				* @method getClosestBySelectorNS
				* @param {HTMLElement} context
				* @param {string} selector
				* @return {HTMLElement}
				* @static
				* @member ns.util.selectors
				*/
				getClosestBySelectorNS: function (context, selector) {
					return closest(context, testSelector.bind(null, getDataSelector(selector)));
				},

				/**
				* Return first element from parents of element with given class name.
				* @method getClosestByClass
				* @param {HTMLElement} context
				* @param {string} selector
				* @return {HTMLElement}
				* @static
				* @member ns.util.selectors
				*/
				getClosestByClass: function (context, selector) {
					return closest(context, testClass.bind(null, selector));
				},

				/**
				* Return first element from parents of element with given tag name.
				* @method getClosestByTag
				* @param {HTMLElement} context
				* @param {string} selector
				* @return {HTMLElement}
				* @static
				* @member ns.util.selectors
				*/
				getClosestByTag: function (context, selector) {
					return closest(context, testTag.bind(null, selector));
				},

				/**
				* Return array of elements from context with given data-selector
				* @method getAllByDataNS
				* @param {HTMLElement} context
				* @param {string} dataSelector
				* @return {Array}
				* @static
				* @member ns.util.selectors
				*/
				getAllByDataNS: function (context, dataSelector) {
					return slice.call(context.querySelectorAll(getDataSelector(dataSelector)));
				}
			};
			}(window.document, ns));

/*global window, define, ns */
/* 
 * Copyright (c) 2010 - 2014 Samsung Electronics Co., Ltd.
 * License : MIT License V2
 */
/**
 * #Object Utility
 * Object contains functions help work with objects.
 * @class ns.util.object
 * @author Maciej Urbanski <m.urbanski@samsung.com>
 * @author Piotr Karny <p.karny@samsung.com>
 */
(function (ns) {
	
	
			var object = {
				/**
				* Copy object to new object
				* @method copy
				* @param {Object} orgObject
				* @return {Object}
				* @static
				* @member ns.util.object
				*/
				copy: function (orgObject) {
					return object.merge({}, orgObject);
				},

				/**
				* Attach fields from second object to first object.
				* @method fastMerge
				* @param {Object} newObject
				* @param {Object} orgObject
				* @return {Object}
				* @static
				* @member ns.util.object
				*/
				fastMerge: function (newObject, orgObject) {
					var key;
					for (key in orgObject) {
						if (orgObject.hasOwnProperty(key)) {
							newObject[key] = orgObject[key];
						}
					}
					return newObject;
				},

				/**
				* Attach fields from second and next object to first object.
				* @method merge
				* @param {Object} newObject
				* @param {...Object} orgObject
				* @param {?boolean} [override=true]
				* @return {Object}
				* @static
				* @member ns.util.object
				*/
				merge: function ( /* newObject, orgObject, override */ ) {
					var newObject, orgObject, override,
						key,
						args = [].slice.call(arguments),
						argsLength = args.length,
						i;
					newObject = args.shift();
					override = true;
					if (typeof arguments[argsLength-1] === "boolean") {
						override = arguments[argsLength-1];
						argsLength--;
					}
					for (i = 0; i < argsLength; i++) {
						orgObject = args.shift();
						if (orgObject !== null) {
							for (key in orgObject) {
								if (orgObject.hasOwnProperty(key) && ( override || newObject[key] === undefined )) {
									newObject[key] = orgObject[key];
								}
							}
						}
					}
					return newObject;
				},

				/**
				 * Function add to Constructor prototype Base object and add to prototype properties and methods from
				 * prototype object.
				 * @method inherit
				 * @param {Function} Constructor
				 * @param {Function} Base
				 * @param {Object} prototype
				 * @static
				 * @member ns.util.object
				 */
				/* jshint -W083 */
				inherit: function( Constructor, Base, prototype ) {
					var basePrototype = new Base(),
						property,
						value;
					for (property in prototype) {
						if (prototype.hasOwnProperty(property)) {
							value = prototype[property];
							if ( typeof value === "function" ) {
								basePrototype[property] = (function createFunctionWithSuper(Base, property, value) {
									var _super = function() {
										var superFunction = Base.prototype[property];
										if (superFunction) {
											return superFunction.apply(this, arguments);
										}
										return null;
									};
									return function() {
										var __super = this._super,
											returnValue;

										this._super = _super;
										returnValue = value.apply(this, arguments);
										this._super = __super;
										return returnValue;
									};
								}(Base, property, value));
							} else {
								basePrototype[property] = value;
							}
						}
					}

					Constructor.prototype = basePrototype;
					Constructor.prototype.constructor = Constructor;
				},

				/**
				 * Returns true if every property value corresponds value from 'value' argument
				 * @method hasPropertiesOfValue
				 * @param {Object} obj
				 * @param {*} [value=undefined]
				 * @return {boolean}
				 */
				hasPropertiesOfValue: function (obj, value) {
					var keys = Object.keys(obj),
						i = keys.length;

					// Empty array should return false
					if (i === 0) {
						return false;
					}

					while (--i >= 0) {
						if (obj[keys[i]] !== value) {
							return false;
						}
					}

					return true;
				},

				/**
				 * Remove properties from object.
				 * @method removeProperties
				 * @param {Object} object
				 * @param {Array} propertiesToRemove
				 * @return {Object}
				 */
				removeProperties: function (object, propertiesToRemove) {
					var length = propertiesToRemove.length,
						property,
						i;

					for (i = 0; i < length; i++) {
						property = propertiesToRemove[i];
						if (object.hasOwnProperty(property)) {
							delete object[property];
						}
					}
					return object;
				}
			};
			ns.util.object = object;
			}(ns));

/*global window, define, ns, Node, HTMLElement */
/*jslint nomen: true, plusplus: true, bitwise: false */
/* 
 * Copyright (c) 2010 - 2014 Samsung Electronics Co., Ltd.
 * License : MIT License V2
 */
/**
 * #Engine
 * Main class with engine of library which control communication
 * between parts of framework.
 * @class ns.engine
 * @author Maciej Urbanski <m.urbanski@samsung.com>
 * @author Krzysztof Antoszek <k.antoszek@samsung.com>
 * @author Michal Szepielak <m.szepielak@samsung.com>
 * @author Jadwiga Sosnowska <j.sosnowska@partner.samsung.com>
 * @author Maciej Moczulski <m.moczulski@samsung.com>
 * @author Piotr Karny <p.karny@samsung.com>
 * @author Tomasz Lukawski <t.lukawski@samsung.com>
 * @author Przemyslaw Ciezkowski <p.ciezkowski@samsung.com>
 */
(function (window, document, ns) {
	
				/**
			 * @method slice Array.slice
			 * @private
			 * @static
			 * @member ns.engine
			 */
			var slice = [].slice,
				/**
				 * @property {Object} eventUtils {@link ns.event}
				 * @private
				 * @static
				 * @member ns.engine
				 */
				eventUtils = ns.event,
				objectUtils = ns.util.object,
				selectors = ns.util.selectors,
				/**
				 * @property {Object} widgetDefs Object with widgets definitions
				 * @private
				 * @static
				 * @member ns.engine
				 */
				widgetDefs = {},
				/**
				 * @property {Object} widgetBindingMap Object with widgets bindings
				 * @private
				 * @static
				 * @member ns.engine
				 */
				widgetBindingMap = {},
				location = window.location,
				/**
				 * engine mode, if true then engine only builds widgets
				 * @property {boolean} justBuild
				 * @private
				 * @static
				 * @member ns.engine
				 */
				justBuild = location.hash === "#build",
				/**
				 * @property {string} [TYPE_STRING="string"] local cache of string type name
				 * @private
				 * @static
				 * @readonly
				 * @member ns.engine
				 */
				TYPE_STRING = "string",
				/**
				 * @property {string} [TYPE_FUNCTION="function"] local cache of function type name
				 * @private
				 * @static
				 * @readonly
				 * @member ns.engine
				 */
				TYPE_FUNCTION = "function",
				/**
				 * @property {string} [DATA_BUILT="data-tau-built"] attribute informs that widget id build
				 * @private
				 * @static
				 * @readonly
				 * @member ns.engine
				 */
				DATA_BUILT = "data-tau-built",
				/**
				 * @property {string} [DATA_NAME="data-tau-name"] attribute contains widget name
				 * @private
				 * @static
				 * @readonly
				 * @member ns.engine
				 */
				DATA_NAME = "data-tau-name",
				/**
				 * @property {string} [DATA_BOUND="data-tau-bound"] attribute informs that widget id bound
				 * @private
				 * @static
				 * @readonly
				 * @member ns.engine
				 */
				DATA_BOUND = "data-tau-bound",
				/**
				 * @property {string} NAMES_SEPARATOR
				 * @private
				 * @static
				 * @readonly
				 */
				NAMES_SEPARATOR = ",",
				/**
				 * @property {string} [querySelectorWidgets="*[data-tau-built][data-tau-name]:not([data-tau-bound])"] query selector for all widgets which are built but not bound
				 * @private
				 * @static
				 * @member ns.engine
				 */
					// @TODO this selector is not valid ...
				querySelectorWidgets = "*[" + DATA_BUILT + "][" + DATA_NAME + "]:not([" + DATA_BOUND + "])",
				/**
				 * @method excludeBuildAndBound
				 * @private
				 * @static
				 * @member ns.engine
				 * @return {string} :not([data-tau-built*='widgetName']):not([data-tau-bound*='widgetName'])
				 */
				excludeBuiltAndBound = function (widgetType) {
					return ":not([" + DATA_BUILT + "*='" + widgetType +"']):not([" + DATA_BOUND + "*='" + widgetType +"'])";
				},

				/**
				 * Engine event types
				 * @property {Object} eventType
				 * @property {string} eventType.INIT="tauinit" INIT of framework init event
				 * @property {string} eventType.WIDGET_BOUND="widgetbound" WIDGET_BOUND of widget bound event
				 * @property {string} eventType.WIDGET_DEFINED="widgetdefined" WIDGET_DEFINED of widget built event
				 * @property {string} eventType.WIDGET_BUILT="widgetbuilt" WIDGET_BUILT of widget built event
				 * @property {string} eventType.BOUND="bound" BOUND of bound event
				 * @static
				 * @readonly
				 * @member ns.engine
				 */
				eventType = {
					INIT: "tauinit",
					WIDGET_BOUND: "widgetbound",
					WIDGET_DEFINED: "widgetdefined",
					WIDGET_BUILT: "widgetbuilt",
					BOUND: "bound"
				},
				engine,
				/**
				 * @property {Object} router Router object
				 * @private
				 * @static
				 * @member ns.engine
				 */
				router;

			/**
			 * This function prepares selector for widget' definition
			 * @method selectorChange
			 * @param {string} selectorName
			 * @return {string} new selector
			 * @member ns.engine
			 * @static
			 */
			function selectorChange (selectorName) {
				if (selectorName.match(/\[data-role=/) && !selectorName.match(/:not\(\[data-role=/)) {
					return selectorName.trim();
				}
				return selectorName.trim() + ":not([data-role='none'])";
			}

			/**
			 * Function to define widget
			 * @method defineWidget
			 * @param {string} name
			 * @param {string} selector
			 * @param {Array} methods
			 * @param {Object} widgetClass
			 * @param {string} [namespace]
			 * @param {boolean} [redefine]
			 * @param {boolean} [widgetNameToLowercase = true]
			 * @return {boolean}
			 * @member ns.engine
			 * @static
			 */
			function defineWidget(name, selector, methods, widgetClass, namespace, redefine, widgetNameToLowercase) {
				var definition;
				// Widget name is absolutely required
				if (name) {
					if (!widgetDefs[name] || redefine) {
												methods = methods || [];
						methods.push("destroy", "disable", "enable", "option", "refresh", "value");
						definition = {
							name: name,
							methods: methods,
							selector: selector || "",
							selectors: selector ? selector.split(",").map(selectorChange) : [],
							widgetClass: widgetClass || null,
							namespace: namespace || "",
							widgetNameToLowercase: widgetNameToLowercase === undefined ? true : !!widgetNameToLowercase
						};

						widgetDefs[name] = definition;
						eventUtils.trigger(document, "widgetdefined", definition, false);
						return true;
					}
									} else {
					ns.error("Widget with selector [" + selector + "] defined without a name, aborting!");
				}
				return false;
			}

			/**
			 * Get binding for element
			 * @method getBinding
			 * @static
			 * @param {HTMLElement|string} element
			 * @param {string} type widget name
			 * @return {?Object}
			 * @member ns.engine
			 */
			function getBinding(element, type) {
				var id = !element || typeof element === TYPE_STRING ? element : element.id,
					binding,
					widgetInstance,
					bindingElement,
					storedWidgetNames;

				if (typeof element === TYPE_STRING) {
					element = document.getElementById(id);
				}

				// Fetch group of widget defined for this element
				binding = widgetBindingMap[id];

				if (binding && typeof binding === "object") {
					// If name is defined it's possible to fetch it instantly
					if (type) {
						widgetInstance = binding.instances[type];
					} else {
						storedWidgetNames = Object.keys(binding.instances);
						widgetInstance = binding.instances[storedWidgetNames[0]];
					}

					// Return only it instance of the proper widget exists
					if (widgetInstance) {
						
						// Check if widget instance has that same object referenced
						if (widgetInstance.element === element) {
							return widgetInstance;
						}
					}
				}

				return null;
			}

			/**
			 * Set binding of widget
			 * @method setBinding
			 * @param {ns.widget.BaseWidget} widgetInstance
			 * @static
			 * @member ns.engine
			 */
			function setBinding(widgetInstance) {
				var id = widgetInstance.element.id,
					type = widgetInstance.name,
					widgetBinding = widgetBindingMap[id];

				
				// If the HTMLElement never had a widget declared create an empty object
				if(!widgetBinding) {
					widgetBinding = {
						elementId: id,
						element: widgetInstance.element,
						instances: {}
					};
				}

				widgetBinding.instances[type] = widgetInstance;
				widgetBindingMap[id] = widgetBinding;
			}

			/**
			 * Returns all bindings for element or id gives as parameter
			 * @method getAllBindings
			 * @param {HTMLElement|string} element
			 * @return {?Object}
			 * @static
			 * @member ns.engine
			 */
			function getAllBindings(element) {
				var id = !element || typeof element === TYPE_STRING ? element : element.id;

				return (widgetBindingMap[id] && widgetBindingMap[id].instances) || null;
			}

			/**
			 * Removes given name from attributeValue string.
			 * Names should be separated with a NAMES_SEPARATOR
			 * @param {string} name
			 * @param {string} attributeValue
			 * @private
			 * @static
			 * @return {string}
			 */
			function _removeWidgetNameFromAttribute(name, attributeValue) {
				var widgetNames,
					searchResultIndex;

				// Split attribute value by separator
				widgetNames = attributeValue.split(NAMES_SEPARATOR);
				searchResultIndex = widgetNames.indexOf(name);

				if (searchResultIndex > -1) {
					widgetNames.splice(searchResultIndex, 1);
					attributeValue = widgetNames.join(NAMES_SEPARATOR);
				}

				return attributeValue;
			}

			function _removeAllBindingAttributes(element) {
				element.removeAttribute(DATA_BUILT);
				element.removeAttribute(DATA_BOUND);
				element.removeAttribute(DATA_NAME);
			}
			/**
			 * Remove binding data attributes for element.
			 * @method _removeBindingAttributes
			 * @param {HTMLElement} element
			 * @param {string} type widget type (name)
			 * @private
			 * @static
			 * @member ns.engine
			 */
			function _removeWidgetFromAttributes(element, type) {
				var dataBuilt,
					dataBound,
					dataName;

				// Most often case is that name is not defined
				if (!type) {
					_removeAllBindingAttributes(element);
				} else {
					dataBuilt = _removeWidgetNameFromAttribute(type, element.getAttribute(DATA_BUILT) || "");
					dataBound = _removeWidgetNameFromAttribute(type, element.getAttribute(DATA_BOUND) || "");
					dataName = _removeWidgetNameFromAttribute(type, element.getAttribute(DATA_NAME) || "");

					// Check if all attributes have at least one widget
					if (dataBuilt && dataBound && dataName) {
						element.setAttribute(DATA_BUILT, dataBuilt);
						element.setAttribute(DATA_BOUND, dataBound);
						element.setAttribute(DATA_NAME, dataName);
					} else {
						// If something is missing remove everything
						_removeAllBindingAttributes(element);
					}
				}
			}

			/**
			 * Method removes binding for single widget.
			 * @method _removeSingleBinding
			 * @param {Object} bindingGroup
			 * @param {string} type
			 * @return {boolean}
			 * @private
			 * @static
			 */
			function _removeSingleBinding(bindingGroup, type) {
				var widgetInstance = bindingGroup[type];

				if (widgetInstance){
					if (widgetInstance.element && typeof widgetInstance.element.setAttribute === TYPE_FUNCTION) {
						_removeWidgetFromAttributes(widgetInstance.element, type);
					}

					bindingGroup[type] = null;

					return true;
				}

				return false;
			}

			/**
			 * Remove binding for widget based on element.
			 * @method removeBinding
			 * @param {HTMLElement|string} element
			 * @param {string} type widget name
			 * @return {boolean}
			 * @static
			 * @member ns.engine
			 */
			function removeBinding(element, type) {
				var id = (typeof element === TYPE_STRING) ? element : element.id,
					binding = widgetBindingMap[id],
					bindingGroup,
					widgetName,
					partialSuccess,
					fullSuccess = false;

				// [NOTICE] Due to backward compatibility calling removeBinding
				// with one parameter should remove all bindings

				if (binding) {
					if (typeof element === TYPE_STRING) {
						// Search based on current document may return bad results,
						// use previously defined element if it exists
						element = binding.element;
					}

					if (element) {
						_removeWidgetFromAttributes(element, type);
					}

					bindingGroup = widgetBindingMap[id] && widgetBindingMap[id].instances;

					if (bindingGroup) {
						if (!type) {
							fullSuccess = true;

							// Iterate over group of created widgets
							for (widgetName in bindingGroup) {
								if (bindingGroup.hasOwnProperty(widgetName)) {
									partialSuccess = _removeSingleBinding(bindingGroup, widgetName);
									
									// As we iterate over keys we are sure we want to remove this element
									// NOTE: Removing property by delete is slower than assigning null value
									bindingGroup[widgetName] = null;

									fullSuccess = (fullSuccess && partialSuccess);
								}
							}

							// If the object bindingGroup is empty or every key has a null value
							if (objectUtils.hasPropertiesOfValue(bindingGroup, null)) {
								// NOTE: Removing property by delete is slower than assigning null value
								widgetBindingMap[id] = null;
							}

							return fullSuccess;
						}

						partialSuccess = _removeSingleBinding(bindingGroup, type);

						if (objectUtils.hasPropertiesOfValue(bindingGroup, null)) {
							widgetBindingMap[id] = null;
						}

						return partialSuccess;
					}
				}

				return false;
			}

			/**
			 * Removes all bindings of widgets.
			 * @method removeAllBindings
			 * @param {HTMLElement|string} element
			 * @return {boolean}
			 * @static
			 * @member ns.engine
			 */
			function removeAllBindings(element) {
				// @TODO this should be coded in the other way around, removeAll should loop through all bindings and inside call removeBinding
				// but due to backward compatibility that code should be more readable
				return removeBinding(element);
			}

			/**
			 * Load widget
			 * @method processWidget
			 * @param {HTMLElement} element base element of widget
			 * @param {Object} definition definition of widget
			 * @param {ns.widget.BaseWidget} definition.widgetClass
			 * @param {string} definition.name
			 * @param {Object} [options] options for widget
			 * @private
			 * @static
			 * @member ns.engine
			 */
			function processWidget(element, definition, options) {
				var widgetOptions = options || {},
					createFunction = widgetOptions.create,
					Widget = definition.widgetClass,
					/**
					 * @type {ns.widget.BaseWidget} widgetInstance
					 */
					widgetInstance = Widget ? new Widget(element) : false,
					buildAttribute,
					parentEnhance = selectors.getParentsBySelectorNS(element, 'enhance=false'),
					existingBinding;

				// While processing widgets queue other widget may built this one before
				// it reaches it's turn
				existingBinding = getBinding(element, definition.name);
				if (existingBinding && existingBinding.element === element) {
					return existingBinding.element;
				}

				if (widgetInstance && !parentEnhance.length) {
										widgetInstance.configure(definition, element, options);

					// Run .create method from widget options when a [widgetName]create event is triggered
					if (typeof createFunction === TYPE_FUNCTION) {
						eventUtils.one(element, definition.name.toLowerCase() + "create", createFunction);
					}

					if (element.id) {
						widgetInstance.id = element.id;
					}

					// Check if this type of widget was build for this element before
					buildAttribute = element.getAttribute(DATA_BUILT);
					if (!buildAttribute || (buildAttribute && buildAttribute.split(NAMES_SEPARATOR).indexOf(widgetInstance.name) === -1)) {
						element = widgetInstance.build(element);
					}

					if (element) {
						widgetInstance.element = element;

						setBinding(widgetInstance);

						widgetInstance.trigger(eventType.WIDGET_BUILT, widgetInstance, false);

						if (!justBuild) {
							widgetInstance.init(element);
						}

						widgetInstance.bindEvents(element, justBuild);

						eventUtils.trigger(element, eventType.WIDGET_BOUND, widgetInstance, false);
						eventUtils.trigger(document, eventType.WIDGET_BOUND, widgetInstance);
					} else {
											}
				}
				return widgetInstance.element;
			}

			/**
			 * Destroys widget of given 'type' for given HTMLElement.
			 * [NOTICE] This method won't destroy any children widgets.
			 * @method destroyWidget
			 * @param {HTMLElement|string} element
			 * @param {string} type
			 * @static
			 * @member ns.engine
			 */
			function destroyWidget(element, type) {
				var widgetInstance;

				if (typeof element === TYPE_STRING) {
					element = document.getElementById(element);
				}

				
				// If type is not defined all widgets should be removed
				// this is for backward compatibility
				widgetInstance = getBinding(element, type);

				if (widgetInstance) {
					//Destroy widget
					widgetInstance.destroy();
					widgetInstance.trigger("widgetdestroyed");

					removeBinding(element, type);
				}
			}

			/**
			 * Calls destroy on widget (or widgets) connected with given HTMLElement
			 * Removes child widgets as well.
			 * @method destroyAllWidgets
			 * @param {HTMLElement|string} element
			 * @param {boolean} [childOnly=false] destroy only widgets on children elements
			 * @static
			 * @member ns.engine
			 */
			function destroyAllWidgets(element, childOnly) {
				var widgetName,
					widgetInstance,
					widgetGroup,
					childWidgets,
					i;

				if (typeof element === TYPE_STRING) {
					element = document.getElementById(element);
				}

				
				if (!childOnly) {
					// If type is not defined all widgets should be removed
					// this is for backward compatibility
					widgetGroup = getAllBindings(element);
					for (widgetName in widgetGroup) {
						if (widgetGroup.hasOwnProperty(widgetName)) {
							widgetInstance = widgetGroup[widgetName];

							//Destroy widget
							widgetInstance.destroy();
							widgetInstance.trigger("widgetdestroyed");
						}
					}
				}

				//Destroy child widgets, if something left.
				childWidgets = slice.call(element.querySelectorAll("[" + DATA_BOUND + "]"));
				for (i = childWidgets.length - 1; i >= 0; i -= 1) {
					if (childWidgets[i]) {
						destroyAllWidgets(childWidgets[i], false);
					}
				}

				removeAllBindings(element);
			}

			/**
			 * Load widgets from data-* definition
			 * @method processHollowWidget
			 * @param {HTMLElement} element base element of widget
			 * @param {Object} definition widget definition
			 * @param {Object} [options] options for create widget
			 * @return {HTMLElement} base element of widget
			 * @private
			 * @static
			 * @member ns.engine
			 */
			function processHollowWidget(element, definition, options) {
				var name = element.getAttribute(DATA_NAME) || (definition && definition.name);
								definition = definition || (name && widgetDefs[name]) || {
					"name": name
				};
				return processWidget(element, definition, options);
			}

			/**
			 * Compare function for nodes on build queue
			 * @param {Object} nodeA
			 * @param {Object} nodeB
			 * @return {number}
			 * @private
			 * @static
			 */
			function compareByDepth(nodeA, nodeB) {
				var mask = Node.DOCUMENT_POSITION_CONTAINS | Node.DOCUMENT_POSITION_PRECEDING;

				if (nodeA.element.compareDocumentPosition(nodeB.element) & mask) {
					return 1;
				}

				return -1;
			}

			/**
			 * Processes one build queue item. Runs processHollowWidget
			 * underneath
			 * @method processBuildQueueItem
			 * @param {Object|HTMLElement} queueItem
			 * @private
			 * @static
			 */
			function processBuildQueueItem(queueItem) {
				// HTMLElement doesn't have .element property
				// widgetDefs will return undefined when called widgetDefs[undefined]
				processHollowWidget(queueItem.element || queueItem, widgetDefs[queueItem.widgetName]);
			}

			/**
			 * Build widgets on all children of context element
			 * @method createWidgets
			 * @static
			 * @param {HTMLElement} context base html for create children
			 * @member ns.engine
			 */
			function createWidgets(context) {
				var builtWithoutTemplates = slice.call(context.querySelectorAll(querySelectorWidgets)),
					normal = [],
					buildQueue = [],
					selectorKeys = Object.keys(widgetDefs),
					excludeSelector,
					i,
					j,
					len = selectorKeys.length,
					definition,
					widgetName,
					definitionSelectors;

				
				// @TODO EXPERIMENTAL WIDGETS WITHOUT TEMPLATE DEFINITION
				builtWithoutTemplates.forEach(processBuildQueueItem);

				/* NORMAL */
				for (i = 0; i < len; ++i) {
					widgetName = selectorKeys[i];
					definition = widgetDefs[widgetName];
					definitionSelectors = definition.selectors;
					if (definitionSelectors.length) {
						excludeSelector = excludeBuiltAndBound(widgetName);

						normal = slice.call(context.querySelectorAll(definitionSelectors.join(excludeSelector + ",") + excludeSelector));
						j = normal.length;

						while (--j >= 0) {
							buildQueue.push({
								element: normal[j],
								widgetName: widgetName
							});
						}
					}
				}

				// Sort queue by depth, on every DOM branch outer most element go first
				buildQueue.sort(compareByDepth);

				// Build all widgets from queue
				buildQueue.forEach(processBuildQueueItem);

				eventUtils.trigger(document, "built");
				eventUtils.trigger(document, eventType.BOUND);
							}

			/**
			 * Handler for event create
			 * @method createEventHandler
			 * @param {Event} event
			 * @static
			 * @member ns.engine
			 */
			function createEventHandler(event) {
				createWidgets(event.target);
			}

			function setViewport() {
				/**
				 * Sets viewport tag if not exists
				 */
				var documentHead = document.head,
					metaTagListLength,
					metaTagList,
					metaTag,
					i;

				metaTagList = documentHead.querySelectorAll('[name="viewport"]');
				metaTagListLength = metaTagList.length;

				if (metaTagListLength > 0) {
					// Leave the last viewport tag
					--metaTagListLength;

					// Remove duplicated tags
					for (i = 0; i < metaTagListLength; ++i) {
						// Remove meta tag from DOM
						documentHead.removeChild(metaTagList[i]);
					}
				} else {
					// Create new HTML Element
					metaTag = document.createElement('meta');

					// Set required attributes
					metaTag.setAttribute('name', 'viewport');
					metaTag.setAttribute('content', 'width=device-width, user-scalable=no');

					// Force that viewport tag will be first child of head
					if (documentHead.firstChild) {
						documentHead.insertBefore(metaTag, documentHead.firstChild);
					} else {
						documentHead.appendChild(metaTag);
					}
				}
			}

			/**
			 * Build first page
			 * @method build
			 * @static
			 * @member ns.engine
			 */
			function build() {
				if (router) {
					// @TODO: Consider passing viewport options via script tag arguments (web-ui-fw style).
					setViewport();

					eventUtils.trigger(document, "beforerouterinit", router, false);
					router.init(justBuild);
					eventUtils.trigger(document, "routerinit", router, false);
				}
			}

			/**
			 * Method to remove all listeners bound in run
			 * @method stop
			 * @static
			 * @member ns.engine
			 */
			function stop() {
				if (router) {
					router.destroy();
				}
			}
			/*
			 document.addEventListener(eventType.BOUND, function () {
			 //@TODO dump it to file for faster binding by ids
			 nsWidgetBindingMap = widgetBindingMap;
			 }, false);
			 */
			ns.widgetDefinitions = {};
			engine = {
				justBuild: location.hash === "#build",
				/**
				 * object with names of engine attributes
				 * @property {Object} dataTau
				 * @property {string} [dataTau.built="data-tau-built"] attribute inform that widget id build
				 * @property {string} [dataTau.name="data-tau-name"] attribute contains widget name
				 * @property {string} [dataTau.bound="data-tau-bound"] attribute inform that widget id bound
				 * @property {string} [dataTau.separator=","] separation string for widget names
				 * @static
				 * @member ns.engine
				 */
				dataTau: {
					built: DATA_BUILT,
					name: DATA_NAME,
					bound: DATA_BOUND,
					separator: NAMES_SEPARATOR
				},
				destroyWidget: destroyWidget,
				destroyAllWidgets: destroyAllWidgets,
				createWidgets: createWidgets,

				/**
				 * Method to get all definitions of widgets
				 * @method getDefinitions
				 * @return {Object}
				 * @static
				 * @member ns.engine
				 */
				getDefinitions: function () {
					return widgetDefs;
				},
				/**
				 * Returns definition of widget
				 * @method getWidgetDefinition
				 * @param {string} name
				 * @static
				 * @member ns.engine
				 * @returns {Object}
				 */
				getWidgetDefinition: function (name) {
					return widgetDefs[name];
				},
				defineWidget: defineWidget,
				getBinding: getBinding,
				getAllBindings: getAllBindings,
				setBinding: setBinding,
				// @TODO either rename or fix functionally because
				// this method does not only remove binding but
				// actually destroys widget
				removeBinding: removeBinding,
				removeAllBindings: removeAllBindings,

				/**
				 * Clear bindings of widgets
				 * @method _clearBindings
				 * @static
				 * @member ns.engine
				 */
				_clearBindings: function () {
					//clear and set references to the same object
					widgetBindingMap = {};
				},

				build: build,

				/**
				 * Run engine
				 * @method run
				 * @static
				 * @member ns.engine
				 */
				run: function () {
					stop();

					eventUtils.fastOn(document, "create", createEventHandler);

					eventUtils.trigger(document, eventType.INIT, {tau: ns});

					switch (document.readyState) {
					case "interactive":
					case "complete":
						build();
						break;
					default:
						eventUtils.fastOn(document, "DOMContentLoaded", build.bind(engine));
						break;
					}
				},

				/**
				 * Return router
				 * @method getRouter
				 * @return {Object}
				 * @static
				 * @member ns.engine
				 */
				getRouter: function () {
					return router;
				},

				/**
				 * Initialize router. This method should be call in file with router class definition.
				 * @method initRouter
				 * @param {Function} RouterClass Router class
				 * @static
				 * @member ns.engine
				 */
				initRouter: function (RouterClass) {
					router = new RouterClass();
				},

				/**
				 * Build instance of widget and binding events
				 * Returns error when empty element is passed
				 * @method instanceWidget
				 * @param {HTMLElement} element
				 * @param {string} name
				 * @param {Object} options
				 * @return {?Object}
				 * @static
				 * @member ns.engine
				 */
				instanceWidget: function (element, name, options) {
					var binding = getBinding(element, name),
						definition;

					if (!element) {
						ns.error("'element' cannot be empty");
						return null;
					}

					if (!binding && widgetDefs[name]) {
						definition = widgetDefs[name];
						element = processHollowWidget(element, definition, options);
						binding = getBinding(element, name);
					}
					return binding;
				},

				stop: stop,

				/**
				 * Method to change build mode
				 * @method setJustBuild
				 * @param {boolean} newJustBuild
				 * @static
				 * @member ns.engine
				 */
				setJustBuild: function (newJustBuild) {
					// Set location hash to have a consistent behavior
					if(newJustBuild){
						location.hash = "build";
					} else {
						location.hash = "";
					}

					justBuild = newJustBuild;
				},

				/**
				 * Method to get build mode
				 * @method getJustBuild
				 * @return {boolean}
				 * @static
				 * @member ns.engine
				 */
				getJustBuild: function () {
					return justBuild;
				},
				_createEventHandler : createEventHandler
			};

			engine.eventType = eventType;
			ns.engine = engine;
			}(window, window.document, ns));

/*global window, define */
/* 
 * Copyright (c) 2010 - 2014 Samsung Electronics Co., Ltd.
 * License : MIT License V2
 */
/**
 * #jQuery Mobile mapping namespace
 * Object maps all methods enabling jQuery Mobile API.
 * @class ns.jqm
 */
(function (ns, window) {
	
				ns.jqm = {
				/**
				 * jQuery object
				 * @property {Object} jQuery
				 * @member ns.jqm
				 */
				jQuery: ns.getConfig('jQuery') || window.jQuery
			};
			document.addEventListener(ns.engine.eventType.INIT, function () {
				// Tell the world that JQM is ready to serve Tau
				ns.event.trigger(document, 'mobileinit');
			}, false);
			}(ns, window));

/*global window, define */
/*jslint plusplus: true, nomen: true */
/* 
 * Copyright (c) 2010 - 2014 Samsung Electronics Co., Ltd.
 * License : MIT License V2
 */
/**
 * #jQuery Mobile mapping defaults
 * Object maps default values from TAU namespace to jQuery Mobile namespace.
 * @class ns.jqm.defaults
 */
(function (window, document, ns, $) {
	
				ns.jqm.defaults = {
				/**
				* Proxy colors library from ns namespace to jQM namespace
				* @method init
				* @member ns.jqm.defaults
				* @static
				*/
				init: function () {
					if ($) {

						$.mobile = $.mobile || {};
						// Version of the jQuery Mobile Framework
						//$.mobile.version: __version__;

						// Namespace used framework-wide for data-attrs. Default is no namespace
						$.mobile.ns = "";

						// Define the url parameter used for referencing widget-generated sub-pages.
						// Translates to to example.html&ui-page=subpageIdentifier
						// hash segment before &ui-page= is used to make Ajax request
						$.mobile.subPageUrlKey = "ui-page";

						// Class assigned to page currently in view; and during transitions
						$.mobile.activePageClass = "ui-page-active";

						// Class used for "active" button state; from CSS framework
						$.mobile.activeBtnClass = "ui-btn-active";

						// Class used for "focus" form element state; from CSS framework
						$.mobile.focusClass = "ui-focus";

						// Automatically handle clicks and form submissions through Ajax; when same-domain
						$.mobile.ajaxEnabled = true;

						// Automatically load and show pages based on location.hash
						$.mobile.hashListeningEnabled = true;

						// disable to prevent jquery from bothering with links
						$.mobile.linkBindingEnabled = true;

						// Set default page transition - 'none' for no transitions
						$.mobile.defaultPageTransition = "fade";

						// Set maximum window width for transitions to apply - 'false' for no limit
						$.mobile.maxTransitionWidth = false;

						// Minimum scroll distance that will be remembered when returning to a page
						$.mobile.minScrollBack = 250;

						// DEPRECATED = the following property is no longer in use; but defined until 2.0 to prevent conflicts
						$.mobile.touchOverflowEnabled = false;

						// Set default dialog transition - 'none' for no transitions
						$.mobile.defaultDialogTransition = "pop";

						// Error response message - appears when an Ajax page request fails
						$.mobile.pageLoadErrorMessage = "Error Loading Page";

						// For error messages; which theme does the box uses?
						$.mobile.pageLoadErrorMessageTheme = "e";

						// replace calls to window.history.back with phonegaps navigation helper
						// where it is provided on the window object
						$.mobile.phonegapNavigationEnabled = false;

						//automatically initialize the DOM when it's ready
						$.mobile.autoInitializePage = true;

						$.mobile.pushStateEnabled = true;

						// allows users to opt in to ignoring content by marking a parent element as
						// data-ignored
						$.mobile.ignoreContentEnabled = false;

						// turn of binding to the native orientationchange due to android orientation behavior
						$.mobile.orientationChangeEnabled = true;

						$.mobile.tizen = $.mobile.tizen || {};
						$.mobile.tizen.enableHWKeyHandler = true;
					}
				}
			};
			// Listen when framework is ready
			document.addEventListener(ns.engine.eventType.INIT, function () {
				ns.jqm.defaults.init();
			}, false);

			}(window, window.document, ns, ns.jqm.jQuery));

/*global window, define */
/*jslint plusplus: true */
/* 
 * Copyright (c) 2010 - 2014 Samsung Electronics Co., Ltd.
 * License : MIT License V2
 */
/**
 * #Utility DOM
 * Utility object with function to DOM manipulation, CSS properties support
 * and DOM attributes support.
 *
 * # How to replace jQuery methods  by ns methods
 * ## append vs appendNodes
 *
 * #### HTML code before manipulation
 *
 *     @example
 *     <div>
 *         <div id="first">Hello</div>
 *         <div id="second">And</div>
 *         <div id="third">Goodbye</div>
 *     </div>
 *
 * #### jQuery manipulation
 *
 *     @example
 *     $( "#second" ).append( "<span>Test</span>" );

 * #### ns manipulation
 *
 *     @example
 *     var context = document.getElementById("second"),
 *         element = document.createElement("span");
 *     element.innerHTML = "Test";
 *     ns.util.DOM.appendNodes(context, element);
 *
 * #### HTML code after manipulation
 *
 *     @example
 *     <div>
 *         <div id="first">Hello</div>
 *         <div id="second">And
 *             <span>Test</span>
 *         </div>
 *        <div id="third">Goodbye</div>
 *     </div>
 *
 * ## replaceWith vs replaceWithNodes
 *
 * #### HTML code before manipulation
 *
 *     @example
 *     <div>
 *         <div id="first">Hello</div>
 *         <div id="second">And</div>
 *         <div id="third">Goodbye</div>
 *     </div>
 *
 * #### jQuery manipulation
 *
 *     @example
 *     $('#second').replaceWith("<span>Test</span>");
 *
 * #### ns manipulation
 *
 *     @example
 *     var context = document.getElementById("second"),
 *         element = document.createElement("span");
 *     element.innerHTML = "Test";
 *     ns.util.DOM.replaceWithNodes(context, element);
 *
 * #### HTML code after manipulation
 *
 *     @example
 *     <div>
 *         <div id="first">Hello</div>
 *         <span>Test</span>
 *         <div id="third">Goodbye</div>
 *     </div>
 *
 * ## before vs insertNodesBefore
 *
 * #### HTML code before manipulation
 *
 *     @example
 *     <div>
 *         <div id="first">Hello</div>
 *         <div id="second">And</div>
 *         <div id="third">Goodbye</div>
 *     </div>
 *
 * #### jQuery manipulation
 *
 *     @example
 *     $( "#second" ).before( "<span>Test</span>" );
 *
 * #### ns manipulation
 *
 *     @example
 *     var context = document.getElementById("second"),
 *         element = document.createElement("span");
 *     element.innerHTML = "Test";
 *     ns.util.DOM.insertNodesBefore(context, element);
 *
 * #### HTML code after manipulation
 *
 *     @example
 *     <div>
 *         <div id="first">Hello</div>
 *         <span>Test</span>
 *         <div id="second">And</div>
 *         <div id="third">Goodbye</div>
 *     </div>
 *
 * ## wrapInner vs wrapInHTML
 *
 * #### HTML code before manipulation
 *
 *     @example
 *     <div>
 *         <div id="first">Hello</div>
 *         <div id="second">And</div>
 *         <div id="third">Goodbye</div>
 *     </div>
 *
 * #### jQuery manipulation
 *
 *     @example
 *     $( "#second" ).wrapInner( "<span class="new"></span>" );
 *
 * #### ns manipulation
 *
 *     @example
 *     var element = document.getElementById("second");
 *     ns.util.DOM.wrapInHTML(element, "<span class="new"></span>");
 *
 * #### HTML code after manipulation
 *
 *     @example
 *     <div>
 *         <div id="first">Hello</div>
 *         <div id="second">
 *             <span class="new">And</span>
 *         </div>
 *         <div id="third">Goodbye</div>
 *     </div>
 *
 * @class ns.util.DOM
 * @author Jadwiga Sosnowska <j.sosnowska@partner.samsung.com>
 * @author Krzysztof Antoszek <k.antoszek@samsung.com>
 * @author Maciej Moczulski <m.moczulski@samsung.com>
 * @author Piotr Karny <p.karny@samsung.com>
 */
(function (ns) {
	
				ns.util.DOM = ns.util.DOM || {};
			}(ns));

/*global window, define */
/*jslint plusplus: true */
/* Copyright (c) 2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/*
 * @author Jadwiga Sosnowska <j.sosnowska@partner.samsung.com>
 * @author Krzysztof Antoszek <k.antoszek@samsung.com>
 * @author Maciej Moczulski <m.moczulski@samsung.com>
 * @author Piotr Karny <p.karny@samsung.com>
 */
(function (window, document, ns) {
	
	

			var selectors = ns.util.selectors,
				DOM = ns.util.DOM,
				namespace = "namespace";

			/**
			 * Returns given attribute from element or the closest parent,
			 * which matches the selector.
			 * @method inheritAttr
			 * @member ns.util.DOM
			 * @param {HTMLElement} element
			 * @param {string} attr
			 * @param {string} selector
			 * @return {?string}
			 * @static
			 */
			DOM.inheritAttr = function (element, attr, selector) {
				var value = element.getAttribute(attr),
					parent;
				if (!value) {
					parent = selectors.getClosestBySelector(element, selector);
					if (parent) {
						return parent.getAttribute(attr);
					}
				}
				return value;
			};

			/**
			 * Returns Number from properties described in html tag
			 * @method getNumberFromAttribute
			 * @member ns.util.DOM
			 * @param {HTMLElement} element
			 * @param {string} attribute
			 * @param {string=} [type] auto type casting
			 * @param {number} [defaultValue] default returned value
			 * @static
			 * @return {number}
			 */
			DOM.getNumberFromAttribute = function (element, attribute, type, defaultValue) {
				var value = element.getAttribute(attribute),
					result = defaultValue;

				if (value) {
					if (type === "float") {
						value = parseFloat(value);
						if (value) {
							result = value;
						}
					} else {
						value = parseInt(value, 10);
						if (value) {
							result = value;
						}
					}
				}
				return result;
			};

			function getDataName(name) {
				var namespace = ns.getConfig(namespace);
				return "data-" + (namespace ? namespace + "-" : "") + name;
			}

			/**
			 * This function sets value of attribute data-{namespace}-{name} for element.
			 * If the namespace is empty, the attribute data-{name} is used.
			 * @method setNSData
			 * @param {HTMLElement} element Base element
			 * @param {string} name Name of attribute
			 * @param {string|number|boolean} value New value
			 * @member ns.util.DOM
			 * @static
			 */
			DOM.setNSData = function (element, name, value) {
				element.setAttribute(getDataName(name), value);
			};

			/**
			 * This function returns value of attribute data-{namespace}-{name} for element.
			 * If the namespace is empty, the attribute data-{name} is used.
			 * Method may return boolean in case of 'true' or 'false' strings as attribute value.
			 * @method getNSData
			 * @param {HTMLElement} element Base element
			 * @param {string} name Name of attribute
			 * @member ns.util.DOM
			 * @return {?string|boolean}
			 * @static
			 */
			DOM.getNSData = function (element, name) {
				var value = element.getAttribute(getDataName(name));

				if (value === "true") {
					return true;
				}

				if (value === "false") {
					return false;
				}

				return value;
			};

			/**
			 * This function returns true if attribute data-{namespace}-{name} for element is set
			 * or false in another case. If the namespace is empty, attribute data-{name} is used.
			 * @method hasNSData
			 * @param {HTMLElement} element Base element
			 * @param {string} name Name of attribute
			 * @member ns.util.DOM
			 * @return {boolean}
			 * @static
			 */
			DOM.hasNSData = function (element, name) {
				return element.hasAttribute(getDataName(name));
			};

			/**
			 * Get or set value on data attribute.
			 * @method nsData
			 * @param {HTMLElement} element
			 * @param {string} name
			 * @param {?Mixed} [value]
			 * @static
			 * @member ns.util.DOM
			 */
			DOM.nsData = function (element, name, value) {
				// @TODO add support for object in value
				if (value === undefined) {
					return DOM.getNSData(element, name);
				} else {
					return DOM.setNSData(element, name, value);
				}
			};

			/**
			 * This function removes attribute data-{namespace}-{name} from element.
			 * If the namespace is empty, attribute data-{name} is used.
			 * @method removeNSData
			 * @param {HTMLElement} element Base element
			 * @param {string} name Name of attribute
			 * @member ns.util.DOM
			 * @static
			 */
			DOM.removeNSData = function (element, name) {
				element.removeAttribute(getDataName(name));
			};

			/**
			 * Returns object with all data-* attributes of element
			 * @method getData
			 * @param {HTMLElement} element Base element
			 * @member ns.util.DOM
			 * @return {Object}
			 * @static
			 */
			DOM.getData = function (element) {
				var dataPrefix = "data-",
					data = {},
					attrs = element.attributes,
					attr,
					nodeName,
					value,
					i,
					length = attrs.length;

				for (i = 0; i < length; i++) {
					attr = attrs.item(i);
					nodeName = attr.nodeName;
					if (nodeName.indexOf(dataPrefix) > -1) {
						value = attr.value;
						data[nodeName.replace(dataPrefix, "")] = value.toLowerCase() === "true" ? true : value.toLowerCase() === "false" ? false : value;
					}
				}

				return data;
			};

			/**
			 * Special function to remove attribute and property in the same time
			 * @method removeAttribute
			 * @param {HTMLElement} element
			 * @param {string} name
			 * @member ns.util.DOM
			 * @static
			 */
			DOM.removeAttribute = function (element, name) {
				element.removeAttribute(name);
				element[name] = false;
			};

			/**
			 * Special function to set attribute and property in the same time
			 * @method setAttribute
			 * @param {HTMLElement} element
			 * @param {string} name
			 * @param {Mixed} value
			 * @member ns.util.DOM
			 * @static
			 */
			DOM.setAttribute = function (element, name, value) {
				element[name] = value;
				element.setAttribute(name, value);
			};
			}(window, window.document, ns));

/*global window, define */
/* 
 * Copyright (c) 2010 - 2014 Samsung Electronics Co., Ltd.
 * License : MIT License V2
 */
/**
 * #Namespace For Widgets
 * Namespace For Widgets
 * @author Krzysztof Antoszek <k.antoszek@samsung.com>
 * @class ns.widget
 */
(function (document, ns) {
	
				var engine = ns.engine,
				widget = {
					/**
					 * Get bound widget for element
					 * @method getInstance
					 * @static
					 * @param {HTMLElement|string} element
					 * @param {string} type widget name
					 * @return {?Object}
					 * @member ns.widget
					 */
					getInstance: engine.getBinding,
					/**
					 * Returns Get all bound widget for element or id gives as parameter
					 * @method getAllInstances
					 * @param {HTMLElement|string} element
					 * @return {?Object}
					 * @static
					 * @member ns.widget
					 */
					getAllInstances: engine.getAllBindings
				};

			function widgetConstructor(name, element, options) {
				return engine.instanceWidget(element, name, options);
			}

			document.addEventListener(engine.eventType.WIDGET_DEFINED, function (evt) {
				var definition = evt.detail,
					name = definition.name;

				 ns.widget[name] = widgetConstructor.bind(null, name);

			}, true);

			/** @namespace ns.widget */
			ns.widget = widget;
			}(window.document, ns));

/*global window, define */
/*jslint nomen: true */
/* 
 * Copyright (c) 2010 - 2014 Samsung Electronics Co., Ltd.
 * License : MIT License V2
 */
/*jslint nomen: true */
/*
 */
/**
 * #BaseWidget
 * Prototype class of widget
 *
 * ## How to invoke creation of widget from JavaScript
 *
 * To build and initialize widget in JavaScript you have to use method {@link ns.engine#instanceWidget} . First argument for method
 * is HTMLElement, which specifies the element of widget. Second parameter is name of widget to create.
 *
 * If you load jQuery before initializing tau library, you can use standard jQuery UI Widget notation.
 *
 * ### Examples
 * #### Build widget from JavaScript
 *
 *		@example
 *		var element = document.getElementById("id"),
 *			ns.engine.instanceWidget(element, "Button");
 *
 * #### Build widget from jQuery
 *
 *		@example
 *		var element = $("#id").button();
 *
 * ## How to create new widget
 *
 *		@example
 *		(function (ns) {
 *			
 *			 *					var BaseWidget = ns.widget.BaseWidget, // create alias to main objects
 *						...
 *						arrayOfElements, // example of private property, common for all instances of widget
 *						Button = function () { // create local object with widget
 *							...
 *						},
 *						prototype = new BaseWidget(); // add ns.widget.BaseWidget as prototype to widget's object, for better minification this should be assign to local variable and next variable should be assign to prototype of object
 *
 *					function closestEnabledButton(element) { // example of private method
 *						...
 *					}
 *					...
 *
 *					prototype.options = { //add default options to be read from data- attributes
 *						theme: "s",
 *						...
 *					};
 *
 *					prototype._build = function (template, element) { // method called when the widget is being built, should contain all HTML manipulation actions
 *						...
 *						return element;
 *					};
 *
 *					prototype._init = function (element) { // method called during initialization of widget, should contain all actions necessary fastOn application start
 *						...
 *						return element;
 *					};
 *
 *					prototype._bindEvents = function (element) { // method to bind all events, should contain all event bindings
 *						...
 *					};
 *
 *					prototype._enable = function (element) { // method called during invocation of enable() method
 *						...
 *					};
 *
 *					prototype._disable = function (element) { // method called during invocation of disable() method
 *						...
 *					};
 *
 *					prototype.refresh = function (element) { // example of public method
 *						...
 *					};
 *
 *					prototype._refresh = function () { // example of protected method
 *						...
 *					};
 *
 *					Button.prototype = prototype;
 *
 *					engine.defineWidget( // define widget
 *						"Button", //name of widget
 *						"[data-role='button'],button,[type='button'],[type='submit'],[type='reset']",  //widget's selector
 *						[ // public methods, here should be list all public method, without that method will not be available
 *							"enable",
 *							"disable",
 *							"refresh"
 *						],
 *						Button, // widget's object
 *						"mobile" // widget's namespace
 *					);
 *					ns.widget.Button = Button;
 *					 *		}(ns));
 * @author Jadwiga Sosnowska <j.sosnowska@samsung.com>
 * @author Krzysztof Antoszek <k.antoszek@samsung.com>
 * @author Tomasz Lukawski <t.lukawski@samsung.com>
 * @author Przemyslaw Ciezkowski <p.ciezkowski@samsung.com>
 * @author Maciej Urbanski <m.urbanski@samsung.com>
 * @author Piotr Karny <p.karny@samsung.com>
 * @author Michał Szepielak <m.szepielak@samsung.com>
 * @class ns.widget.BaseWidget
 */
(function (document, ns, undefined) {
	
				/**
			 * Alias to Array.slice function
			 * @method slice
			 * @member ns.widget.BaseWidget
			 * @private
			 * @static
			 */
			var slice = [].slice,
				/**
				 * Alias to ns.engine
				 * @property {ns.engine} engine
				 * @member ns.widget.BaseWidget
				 * @private
				 * @static
				 */
				engine = ns.engine,
				engineDataTau = engine.dataTau,
				util = ns.util,
				/**
				 * Alias to {@link ns.event}
				 * @property {Object} eventUtils
				 * @member ns.widget.BaseWidget
				 * @private
				 * @static
				 */
				eventUtils = ns.event,
				/**
				 * Alias to {@link ns.util.DOM}
				 * @property {Object} domUtils
				 * @private
				 * @static
				 */
				domUtils = util.DOM,
				/**
				 * Alias to {@link ns.util.object}
				 * @property {Object} objectUtils
				 * @private
				 * @static
				 */
				objectUtils = util.object,
				BaseWidget = function () {
					return this;
				},
				prototype = {},
				/**
				 * Property with string represent function type 
				 * (for better minification)
				 * @property {string} [TYPE_FUNCTION="function"]
				 * @private
				 * @static
				 * @readonly
				 */
				TYPE_FUNCTION = "function";

			/**
			 * Protected method configuring the widget
			 * @method _configure
			 * @member ns.widget.BaseWidget
			 * @protected
			 * @template
			 * @internal
			 */
			/**
			 * Configures widget object from definition.
			 *
			 * It calls such methods as #\_getCreateOptions and #\_configure.
			 * @method configure
			 * @param {Object} definition
			 * @param {string} definition.name Name of the widget
			 * @param {string} definition.selector Selector of the widget
			 * @param {HTMLElement} element Element of widget
			 * @param {Object} options Configure options
			 * @member ns.widget.BaseWidget
			 * @chainable
			 * @internal
			 */
			prototype.configure = function (definition, element, options) {
				var self = this,
					definitionName,
					definitionNamespace;
				/**
				 * Object with options for widget
				 * @property {Object} [options={}]
				 * @member ns.widget.BaseWidget
				 */
				self.options = self.options || {};
				/**
				 * Base element of widget
				 * @property {?HTMLElement} [element=null]
				 * @member ns.widget.BaseWidget
				 */
				self.element = self.element || null;
				if (definition) {
					definitionName = definition.name;
					definitionNamespace = definition.namespace;
					/**
					 * Name of the widget
					 * @property {string} name
					 * @member ns.widget.BaseWidget
					 */
					self.name = definitionName;

					/**
					 * Name of the widget (in lower case)
					 * @property {string} widgetName
					 * @member ns.widget.BaseWidget
					 */
					self.widgetName = definitionName;

					/**
					 * Namespace of widget events
					 * @property {string} widgetEventPrefix
					 * @member ns.widget.BaseWidget
					 */
					self.widgetEventPrefix = definitionName.toLowerCase();

					/**
					 * Namespace of the widget
					 * @property {string} namespace 
					 * @member ns.widget.BaseWidget
					 */
					self.namespace = definitionNamespace;

					/**
					 * Full name of the widget
					 * @property {string} widgetFullName
					 * @member ns.widget.BaseWidget
					 */
					self.widgetFullName = ((definitionNamespace ? definitionNamespace + "-" : "") + definitionName).toLowerCase();
					/**
					 * Id of widget instance
					 * @property {string} id
					 * @member ns.widget.BaseWidget
					 */
					self.id = ns.getUniqueId();

					/**
					 * Widget's selector
					 * @property {string} selector
					 * @member ns.widget.BaseWidget
					 */
					self.selector = definition.selector;
				}

				if (typeof self._configure === TYPE_FUNCTION) {
					self._configure(element);
				}

				self._getCreateOptions(element);

				objectUtils.fastMerge(self.options, options);
			};

			/**
			 * Reads data-* attributes and save to options object.
			 * @method _getCreateOptions
			 * @param {HTMLElement} element Base element of the widget
			 * @return {Object}
			 * @member ns.widget.BaseWidget
			 * @protected
			 */
			prototype._getCreateOptions = function (element) {
				var options = this.options,
					bigRegexp = /[A-Z]/g;
				if (options !== undefined) {
					Object.keys(options).forEach(function (option) {
						// Get value from data-{namespace}-{name} element's attribute
						// based on widget.options property keys
						var value = domUtils.getNSData(element, (option.replace(bigRegexp, function (c) {
							return "-" + c.toLowerCase();
						})));

						if (value !== null) {
							options[option] = value;
						}
					});
				}
				return options;
			};
			/**
			 * Protected method building the widget
			 * @method _build
			 * @param {HTMLElement} element
			 * @return {HTMLElement} widget's element
			 * @member ns.widget.BaseWidget
			 * @protected
			 * @template
			 */
			/**
			 * Builds widget.
			 *
			 * It calls method #\_build.
			 *
			 * Before starting building process, the event beforecreate with
			 * proper prefix defined in variable widgetEventPrefix is triggered.
			 * @method build
			 * @param {HTMLElement} element Element of widget before building process
			 * @return {HTMLElement} Element of widget after building process
			 * @member ns.widget.BaseWidget
			 * @internal
			 */
			prototype.build = function (element) {
				var self = this,
					id,
					node,
					dataBuilt = element.getAttribute(engineDataTau.built),
					dataName = element.getAttribute(engineDataTau.name);

				eventUtils.trigger(element, self.widgetEventPrefix + "beforecreate");

				id = element.id;
				if (id) {
					self.id = id;
				} else {
					element.id = self.id;
				}

				if (typeof self._build === TYPE_FUNCTION) {
					node = self._build(element);
				} else {
					node = element;
				}

				// Append current widget name to data-tau-built and data-tau-name attributes
				dataBuilt = !dataBuilt ? self.name : dataBuilt + engineDataTau.separator + self.name;
				dataName = !dataName ? self.name : dataName + engineDataTau.separator + self.name;

				element.setAttribute(engineDataTau.built, dataBuilt);
				element.setAttribute(engineDataTau.name, dataName);

				return node;
			};

			/**
			 * Protected method initializing the widget
			 * @method _init
			 * @param {HTMLElement} element
			 * @member ns.widget.BaseWidget
			 * @template
			 * @protected
			 */
			/**
			 * Initializes widget.
			 *
			 * It calls method #\_init.
			 * @method init
			 * @param {HTMLElement} element Element of widget before initialization
			 * @member ns.widget.BaseWidget
			 * @chainable
			 * @internal
			 */
			prototype.init = function (element) {
				var self = this;
				self.id = element.id;

				if (typeof self._init === TYPE_FUNCTION) {
					self._init(element);
				}

				if (element.getAttribute("disabled") || self.options.disabled === true) {
					self.disable();
				} else {
					self.enable();
				}

				return self;
			};

			/**
			 * Bind widget events attached in init mode
			 * @method _bindEvents
			 * @param {HTMLElement} element Base element of widget
			 * @member ns.widget.BaseWidget
			 * @template
			 * @protected
			 */
			/**
			 * Binds widget events.
			 *
			 * It calls such methods as #\_buildBindEvents and #\_bindEvents.
			 * At the end of binding process, the event "create" with proper
			 * prefix defined in variable widgetEventPrefix is triggered.
			 * @method bindEvents
			 * @param {HTMLElement} element Base element of the widget
			 * @param {boolean} onlyBuild Inform about the type of bindings: build/init
			 * @member ns.widget.BaseWidget
			 * @chainable
			 * @internal
			 */
			prototype.bindEvents = function (element, onlyBuild) {
				var self = this,
					dataBound = element.getAttribute(engineDataTau.bound);

				if (!onlyBuild) {
					dataBound = !dataBound ? self.name : dataBound + engineDataTau.separator + self.name;
					element.setAttribute(engineDataTau.bound, dataBound);
				}
				if (typeof self._buildBindEvents === TYPE_FUNCTION) {
					self._buildBindEvents(element);
				}
				if (!onlyBuild && typeof self._bindEvents === TYPE_FUNCTION) {
					self._bindEvents(element);
				}

				self.trigger(self.widgetEventPrefix + "create", self);

				return self;
			};

			/**
			 * Focus widget's element.
			 *
			 * This function calls function focus on element and if it is known
			 * the direction of event, the proper css classes are added/removed.
			 * @method focus
			 * @param {object} options The options of event.
			 * @param {"up"|"down"|"left"|"right"} direction
			 * For example, if this parameter has value "down", it means that the movement
			 * comes from the top (eg. down arrow was pressed on keyboard).
			 * @param {HTMLElement} previousElement Element to blur
			 * @member ns.widget.BaseWidget
			 */
			prototype.focus = function (options) {
				var self = this,
					element = self.element,
					blurElement,
					blurWidget;

				options = options || {};

				if (self.isDisabled()) {
					// widget is disabled, so we cannot set focus
					return false;
				}

				blurElement = options.previousElement;
				// we try to blur element, which has focus previously
				if (blurElement) {
					blurWidget = engine.getBinding(blurElement);
					// call blur function on widget
					if (blurWidget) {
						options = objectUtils.merge({}, options, {element: blurElement});
						blurWidget.blur(options);
					} else {
						// or on element, if widget does not exist
						blurElement.blur();
					}
				}

				options = objectUtils.merge({}, options, {element: element});

				// set focus on element
				eventUtils.trigger(document, "taufocus", options);
				element.focus();

				return true;
			};

			/**
			 * Blur widget's element.
			 *
			 * This function calls function blur on element and if it is known
			 * the direction of event, the proper css classes are added/removed.
			 * @method blur
			 * @param {object} options The options of event.
			 * @param {"up"|"down"|"left"|"right"} direction
			 * @member ns.widget.BaseWidget
			 */
			prototype.blur = function (options) {
				var self = this,
					element = self.element;

				if (self.isDisabled()) {
					// widget is disabled, so we cannot blur it
					return false;
				}

				options = objectUtils.merge({}, options, {element: element});

				// blur element
				eventUtils.trigger(document, "taublur", options);
				element.blur();
				return true;
			};

			/**
			 * Protected method destroying the widget
			 * @method _destroy
			 * @template
			 * @protected
			 * @member ns.widget.BaseWidget
			 */
			/**
			 * Destroys widget.
			 *
			 * It calls method #\_destroy.
			 *
			 * At the end of destroying process, the event "destroy" with proper
			 * prefix defined in variable widgetEventPrefix is triggered and
			 * the binding set in engine is removed.
			 * @method destroy
			 * @param {HTMLElement} element Base element of the widget
			 * @member ns.widget.BaseWidget
			 */
			prototype.destroy = function (element) {
				var self = this;
				element = element || self.element;
				if (typeof self._destroy === TYPE_FUNCTION) {
					self._destroy(element);
				}
				if (self.element) {
					self.trigger(self.widgetEventPrefix + "destroy");
				}
				if (element) {
					engine.removeBinding(element, self.name);
				}
			};

			/**
			 * Protected method disabling the widget
			 * @method _disable
			 * @protected
			 * @member ns.widget.BaseWidget
			 * @template
			 */
			/**
			 * Disables widget.
			 *
			 * It calls method #\_disable.
			 * @method disable
			 * @member ns.widget.BaseWidget
			 * @chainable
			 */
			prototype.disable = function () {
				var self = this,
					args = slice.call(arguments);

				if (typeof self._disable === TYPE_FUNCTION) {
					args.unshift(self.element);
					self._disable.apply(self, args);
				}
				return this;
			};

			/**
			 * Check if widget is disabled.
			 * @method isDisabled
			 * @member ns.widget.BaseWidget
			 * @return {boolean} Returns true if widget is disabled
			 */
			prototype.isDisabled = function () {
				var self = this;
				return self.element.getAttribute("disabled") || self.options.disabled === true;
			};

			/**
			 * Protected method enabling the widget
			 * @method _enable
			 * @protected
			 * @member ns.widget.BaseWidget
			 * @template
			 */
			/**
			 * Enables widget.
			 *
			 * It calls method #\_enable.
			 * @method enable
			 * @member ns.widget.BaseWidget
			 * @chainable
			 */
			prototype.enable = function () {
				var self = this,
					args = slice.call(arguments);

				if (typeof self._enable === TYPE_FUNCTION) {
					args.unshift(self.element);
					self._enable.apply(self, args);
				}
				return this;
			};

			/**
			 * Protected method causing the widget to refresh
			 * @method _refresh
			 * @protected
			 * @member ns.widget.BaseWidget
			 * @template
			 */
			/**
			 * Refreshes widget.
			 *
			 * It calls method #\_refresh.
			 * @method refresh
			 * @member ns.widget.BaseWidget
			 * @chainable
			 */
			prototype.refresh = function () {
				var self = this;
				if (typeof self._refresh === TYPE_FUNCTION) {
					self._refresh.apply(self, arguments);
				}
				return self;
			};


			/**
			 * Gets or sets options of the widget.
			 *
			 * This method can work in many context.
			 *
			 * If first argument is type of object them, method set values for options given in object. Keys of object are names of options and values from object are values to set.
			 *
			 * If you give only one string argument then method return value for given option.
			 *
			 * If you give two arguments and first argument will be a string then second argument will be intemperate as value to set.
			 *
			 * @method option
			 * @param {string|Object} [name] name of option
			 * @param {*} [value] value to set
			 * @member ns.widget.BaseWidget
			 * @return {*} return value of option or undefined if method is called in setter context
			 */
			prototype.option = function (/*name, value*/) {
				var self = this,
					args = slice.call(arguments),
					firstArgument = args.shift(),
					secondArgument = args.shift(),
					key,
					result,
					partResult,
					refresh = false;
				if (typeof firstArgument === "string") {
					result = self._oneOption(firstArgument, secondArgument);
					if (firstArgument !== undefined && secondArgument !== undefined) {
						refresh = result;
						result = undefined;
					}
				} else if (typeof firstArgument === "object") {
					for (key in firstArgument) {
						if (firstArgument.hasOwnProperty(key)) {
							partResult = self._oneOption(key, firstArgument[key]);
							if (key !== undefined && firstArgument[key] !== undefined) {
								refresh = refresh || partResult;
							}
						}
					}
				}
				if (refresh) {
					self.refresh();
				}
				return result;
			};

			/**
			 * Gets or sets one option of the widget.
			 *
			 * @method _oneOption
			 * @param {string} field
			 * @param {*} value
			 * @member ns.widget.BaseWidget
			 * @return {*}
			 * @protected
			 */
			prototype._oneOption = function (field, value) {
				var self = this,
					methodName,
					refresh = false;
				if (value === undefined) {
					methodName = "_get" + (field[0].toUpperCase() + field.slice(1));
					if (typeof self[methodName] === TYPE_FUNCTION) {
						return self[methodName]();
					}
					return self.options[field];
				}
				methodName = "_set" + (field[0].toUpperCase() + field.slice(1));
				if (typeof self[methodName] === TYPE_FUNCTION) {
					self[methodName](self.element, value);
				} else {
					self.options[field] = value;
					if (self.element) {
						self.element.setAttribute("data-" + (field.replace(/[A-Z]/g, function (c) {
							return "-" + c.toLowerCase();
						})), value);
						refresh = true;
					}
				}
				return refresh;
			};

			/**
			 * Returns true if widget has bounded events.
			 *
			 * This methods enables to check if the widget has bounded 
			 * events through the {@link ns.widget.BaseWidget#bindEvents} method.
			 * @method isBound
			 * @param {string} [type] Type of widget
			 * @member ns.widget.BaseWidget
			 * @internal
			 * @return {boolean} true if events are bounded
			 */
			prototype.isBound = function (type) {
				var element = this.element;
				type = type || this.name;
				return element && element.hasAttribute(engineDataTau.bound) && element.getAttribute(engineDataTau.bound).indexOf(type) > -1;
			};

			/**
			 * Returns true if widget is built.
			 *
			 * This methods enables to check if the widget was built 
			 * through the {@link ns.widget.BaseWidget#build} method.
			 * @method isBuilt
			 * @param {string} [type] Type of widget
			 * @member ns.widget.BaseWidget
			 * @internal
			 * @return {boolean} true if the widget was built
			 */
			prototype.isBuilt = function (type) {
				var element = this.element;
				type = type || this.name;
				return element && element.hasAttribute(engineDataTau.built) && element.getAttribute(engineDataTau.built).indexOf(type) > -1;
			};

			/**
			 * Protected method getting the value of widget
			 * @method _getValue
			 * @return {*}
			 * @member ns.widget.BaseWidget
			 * @template
			 * @protected
			 */
			/**
			 * Protected method setting the value of widget
			 * @method _setValue
			 * @param {*} value
			 * @return {*}
			 * @member ns.widget.BaseWidget
			 * @template
			 * @protected
			 */
			/**
			 * Gets or sets value of the widget.
			 *
			 * @method value
			 * @param {*} [value] New value of widget
			 * @member ns.widget.BaseWidget
			 * @return {*}
			 */
			prototype.value = function (value) {
				var self = this;
				if (value !== undefined) {
					if (typeof self._setValue === TYPE_FUNCTION) {
						return self._setValue(value);
					}
					return self;
				}
				if (typeof self._getValue === TYPE_FUNCTION) {
					return self._getValue();
				}
				return self;
			};

			/**
			 * Triggers an event on widget's element.
			 *
			 * @method trigger
			 * @param {string} eventName The name of event to trigger
			 * @param {?*} [data] additional Object to be carried with the event
			 * @param {boolean} [bubbles=true] Indicating whether the event
			 * bubbles up through the DOM or not
			 * @param {boolean} [cancelable=true] Indicating whether
			 * the event is cancelable
			 * @member ns.widget.BaseWidget
			 * @return {boolean} False, if any callback invoked preventDefault on event object
			 */
			prototype.trigger = function (eventName, data, bubbles, cancelable) {
				return eventUtils.trigger(this.element, eventName, data, bubbles, cancelable);
			};

			/**
			 * Adds event listener to widget's element.
			 * @method on
			 * @param {string} eventName The name of event
			 * @param {Function} listener Function called after event will be trigger
			 * @param {boolean} [useCapture=false] useCapture Parameter of addEventListener
			 * @member ns.widget.BaseWidget
			 */
			prototype.on = function (eventName, listener, useCapture) {
				eventUtils.on(this.element, eventName, listener, useCapture);
			};

			/**
			 * Removes event listener from  widget's element.
			 * @method off
			 * @param {string} eventName The name of event
			 * @param {Function} listener Function call after event will be trigger
			 * @param {boolean} [useCapture=false] useCapture Parameter of addEventListener
			 * @member ns.widget.BaseWidget
			 */
			prototype.off = function (eventName, listener, useCapture) {
				eventUtils.off(this.element, eventName, listener, useCapture);
			};

			BaseWidget.prototype = prototype;

			// definition
			ns.widget.BaseWidget = BaseWidget;

			}(window.document, ns));

/*global window, define */
/*jslint plusplus: true, nomen: true */
/*
 * Copyright (c) 2010 - 2014 Samsung Electronics Co., Ltd.
 * License : MIT License V2
 */
/**
 * #jQuery Mobile mapping widget
 * Object maps widgets from TAU namespace to jQuery Mobile namespace.
 * @class ns.jqm.widget
 */
(function (window, document, ns, $) {
	
				/**
			* Alias to Array.slice function
			* @method slice
			* @member ns.jqm.widget
			* @private
			* @static
			*/
			var slice = [].slice,
				/**
				 * Wrap function in closure and wrap first argument in jquery object
				 */
				wrapFn = function (fn) {
					return function (el) {
						return fn($(el));
					};
				},
				/**
				* Alias to ns.engine
				* @member ns.jqm
				* @private
				* @static
				*/
				engine = ns.engine,
				object = ns.util.object,
				jqmWidget = {
					/**
					* bind widget to jqm
					* @method init
					* @param {Object} engine ns.engine class
					* @param {Object} definition widget definition
					* @member ns.jqm.widget
					* @static
					*/
					init: function (engine, definition) {
						var name = (definition.widgetNameToLowercase) ?
								definition.name.toLowerCase() :
										definition.name;
						if ($) {
							document.addEventListener(name + 'create', function (event) {
								var element = event.target,
									instance = event.detail,
									data = $(element).data(name);
								if (instance) {
									instance.bindings = {};
									instance.hoverable = {};
									instance.focusable = {};
									instance.document = $(element.style ? element.ownerDocument : element.document || element);
									instance.window = $(instance.document[0].defaultView || instance.document[0].parentWindow);
									object.merge(instance, data);
									$(element).data(name, instance);
								}
							}, true);
							this.processDefinition(definition, engine);
						}
					},

					/**
					* bind widget to jqm
					* @method processDefinition
					* @param {Object} definition widget definition
					* @param {Object} engine ns.engine class
					* @member ns.jqm.widget
					* @static
					*/
					processDefinition: function (definition, engine) {
						/*
						* name of widget
						* type string
						*/
						var name = (definition.widgetNameToLowercase) ?
								definition.name.toLowerCase() :
										definition.name,
							/*
							* list of public methods
							* type Array
							*/
							methods = definition.methods;

						$.fn[name] = widgetConstructor(engine, name, methods, definition.name);
						if (definition.namespace) {
							$[definition.namespace] = $[definition.namespace] || {};
							$[definition.namespace][definition.name.toLowerCase()] = definition.widgetClass;
						}
						definition = null;
					}
				};


			function widgetConstructor(engine, name, methods, instanceWidgetName) {
				/*
				 * widget instance
				 * type Object
				 */
				var instance = null;
				return function () {
					/*
					 * function arguments
					 * type Array
					 */
					var args = slice.call(arguments),
					/*
					 * element of jQuery collection
					 * type HTMLElement
					 */
						element,
					/*
					 * is built?
					 * type Boolean
					 */
						built,
					/*
					 * name of method
					 * type string
					 */
						method,
					/*
					 * result value
					 * type mixed
					 */
						resultValue,
					/*
					 * first argument of function
					 * type mixed
					 */
						firstarg,
						i,
						options = {},
						argsLength,
						argument;

					/*
					 * NOTE:
					 * The loop below contains some fixes/hacks for TizenSlider, Listview with FastScroll and AutoDividers
					 * and also Popup, please be aware while refactoring.
					 */
					for (i = 0; i < this.length; i++) {
						element = this.get(i);
						switch(name){
							// FastScroll has not real instance defined because it's build as an extension
							case "fastscroll":
								instance = engine.getBinding(element, "Listview");
								break;
							case "slider":
								instance = engine.getBinding(element, "Slider") || engine.getBinding(element, "TizenSlider");
								break;
							default:
								instance = engine.getBinding(element, instanceWidgetName);
						}

						built = instance && instance.isBuilt();
						firstarg = args.shift();
						if (firstarg === undefined || typeof firstarg === 'object') {
							if (typeof firstarg === 'object') {
								options = firstarg;
							}
							if (!instance || !built) {
								engine.instanceWidget(element, instanceWidgetName, options);
							} else {
								instance.configure(null, element, options);
							}
						} else {
							if (instance === null) {
								return this;
							}
							method = firstarg;
							if (method === "destroy") {
								instance.destroy();
								return this;
							}
							if (methods.indexOf(method) < 0) {
								throw "Method " + method + " does not exist!";
							}
							if (name === 'listview' &&
								method === 'option' &&
								args[0] === "autodividersSelector" &&
								typeof args[1] === 'function') {
								// wrap first argument of callback method in JQuery object
								args[1] = wrapFn(args[1]);
							}
							if (name === "popup" && method === "open") {
								// window.event is used because in Winset we open context popup by
								// $("#pop_text_only").popup("open") after clicking on input
								args[1] = window.event;
							}
							// transform jQuery arguments to HTMLElement
							argsLength = args.length;
							for (i = 0; i < argsLength; i++) {
								argument = args[i];
								if (argument instanceof jQuery) {
									// convert jQuery object to array of HTMLElement
									argument = argument.makeArray();
									// if we have only one element we take only first element
									if (argument.length === 1) {
										argument = argument[0];
									}
								}
							}
							resultValue = instance[method].apply(instance, args);
							if (resultValue !== undefined) {
								if (resultValue !== instance) {
									return resultValue;
								}
							}
						}
					}
					return this;
				};
			}

			document.addEventListener(engine.eventType.WIDGET_DEFINED, function (evt) {
				jqmWidget.init(engine, evt.detail);
			}, false);

			document.addEventListener(engine.eventType.INIT, function () {
				engine.defineWidget(
					"FixedToolbar",
					"",
					[],
					ns.widget.Page,
					'mobile'
				);
				engine.defineWidget(
					"pagelayout",
					"",
					[],
					ns.widget.Page,
					'mobile'
				);
				engine.defineWidget(
					"popupwindow",
					"",
					[],
					ns.widget.Popup,
					'tizen'
				);
				engine.defineWidget(
					"ctxpopup",
					"",
					[],
					ns.widget.Popup,
					'tizen'
				);

			}, false);

			ns.jqm.widget = jqmWidget;
			}(window, window.document, ns, ns.jqm.jQuery));

/*!
 * Globalize
 *
 * http://github.com/jquery/globalize
 *
 * Copyright Software Freedom Conservancy, Inc.
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 */

(function( window, undefined ) {

	
var Globalize,
	// private variables
	regexHex,
	regexInfinity,
	regexParseFloat,
	regexTrim,
	// private JavaScript utility functions
	arrayIndexOf,
	endsWith,
	extend,
	isArray,
	isFunction,
	isObject,
	startsWith,
	trim,
	truncate,
	zeroPad,
	// private Globalization utility functions
	appendPreOrPostMatch,
	expandFormat,
	formatDate,
	formatNumber,
	getTokenRegExp,
	getEra,
	getEraYear,
	parseExact,
	parseNegativePattern;

// Global variable (Globalize) or CommonJS module (globalize)
Globalize = function( cultureSelector ) {
	return new Globalize.prototype.init( cultureSelector );
};

if ( typeof require !== "undefined"
	&& typeof exports !== "undefined"
	&& typeof module !== "undefined" ) {
	// Assume CommonJS
	module.exports = Globalize;
} else {
	// Export as global variable
	window.Globalize = Globalize;
}

Globalize.cultures = {};

Globalize.prototype = {
	constructor: Globalize,
	init: function( cultureSelector ) {
		this.cultures = Globalize.cultures;
		this.cultureSelector = cultureSelector;

		return this;
	}
};
Globalize.prototype.init.prototype = Globalize.prototype;

// 1.	 When defining a culture, all fields are required except the ones stated as optional.
// 2.	 Each culture should have a ".calendars" object with at least one calendar named "standard"
//		 which serves as the default calendar in use by that culture.
// 3.	 Each culture should have a ".calendar" object which is the current calendar being used,
//		 it may be dynamically changed at any time to one of the calendars in ".calendars".
Globalize.cultures[ "default" ] = {
	// A unique name for the culture in the form <language code>-<country/region code>
	name: "en",
	// the name of the culture in the english language
	englishName: "English",
	// the name of the culture in its own language
	nativeName: "English",
	// whether the culture uses right-to-left text
	isRTL: false,
	// "language" is used for so-called "specific" cultures.
	// For example, the culture "es-CL" means "Spanish, in Chili".
	// It represents the Spanish-speaking culture as it is in Chili,
	// which might have different formatting rules or even translations
	// than Spanish in Spain. A "neutral" culture is one that is not
	// specific to a region. For example, the culture "es" is the generic
	// Spanish culture, which may be a more generalized version of the language
	// that may or may not be what a specific culture expects.
	// For a specific culture like "es-CL", the "language" field refers to the
	// neutral, generic culture information for the language it is using.
	// This is not always a simple matter of the string before the dash.
	// For example, the "zh-Hans" culture is netural (Simplified Chinese).
	// And the "zh-SG" culture is Simplified Chinese in Singapore, whose lanugage
	// field is "zh-CHS", not "zh".
	// This field should be used to navigate from a specific culture to it's
	// more general, neutral culture. If a culture is already as general as it
	// can get, the language may refer to itself.
	language: "en",
	// numberFormat defines general number formatting rules, like the digits in
	// each grouping, the group separator, and how negative numbers are displayed.
	numberFormat: {
		// [negativePattern]
		// Note, numberFormat.pattern has no "positivePattern" unlike percent and currency,
		// but is still defined as an array for consistency with them.
		//   negativePattern: one of "(n)|-n|- n|n-|n -"
		pattern: [ "-n" ],
		// number of decimal places normally shown
		decimals: 2,
		// string that separates number groups, as in 1,000,000
		",": ",",
		// string that separates a number from the fractional portion, as in 1.99
		".": ".",
		// array of numbers indicating the size of each number group.
		// TODO: more detailed description and example
		groupSizes: [ 3 ],
		// symbol used for positive numbers
		"+": "+",
		// symbol used for negative numbers
		"-": "-",
		// symbol used for NaN (Not-A-Number)
		NaN: "NaN",
		// symbol used for Negative Infinity
		negativeInfinity: "-Infinity",
		// symbol used for Positive Infinity
		positiveInfinity: "Infinity",
		percent: {
			// [negativePattern, positivePattern]
			//   negativePattern: one of "-n %|-n%|-%n|%-n|%n-|n-%|n%-|-% n|n %-|% n-|% -n|n- %"
			//   positivePattern: one of "n %|n%|%n|% n"
			pattern: [ "-n %", "n %" ],
			// number of decimal places normally shown
			decimals: 2,
			// array of numbers indicating the size of each number group.
			// TODO: more detailed description and example
			groupSizes: [ 3 ],
			// string that separates number groups, as in 1,000,000
			",": ",",
			// string that separates a number from the fractional portion, as in 1.99
			".": ".",
			// symbol used to represent a percentage
			symbol: "%"
		},
		currency: {
			// [negativePattern, positivePattern]
			//   negativePattern: one of "($n)|-$n|$-n|$n-|(n$)|-n$|n-$|n$-|-n $|-$ n|n $-|$ n-|$ -n|n- $|($ n)|(n $)"
			//   positivePattern: one of "$n|n$|$ n|n $"
			pattern: [ "($n)", "$n" ],
			// number of decimal places normally shown
			decimals: 2,
			// array of numbers indicating the size of each number group.
			// TODO: more detailed description and example
			groupSizes: [ 3 ],
			// string that separates number groups, as in 1,000,000
			",": ",",
			// string that separates a number from the fractional portion, as in 1.99
			".": ".",
			// symbol used to represent currency
			symbol: "$"
		}
	},
	// calendars defines all the possible calendars used by this culture.
	// There should be at least one defined with name "standard", and is the default
	// calendar used by the culture.
	// A calendar contains information about how dates are formatted, information about
	// the calendar's eras, a standard set of the date formats,
	// translations for day and month names, and if the calendar is not based on the Gregorian
	// calendar, conversion functions to and from the Gregorian calendar.
	calendars: {
		standard: {
			// name that identifies the type of calendar this is
			name: "Gregorian_USEnglish",
			// separator of parts of a date (e.g. "/" in 11/05/1955)
			"/": "/",
			// separator of parts of a time (e.g. ":" in 05:44 PM)
			":": ":",
			// the first day of the week (0 = Sunday, 1 = Monday, etc)
			firstDay: 0,
			days: {
				// full day names
				names: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ],
				// abbreviated day names
				namesAbbr: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ],
				// shortest day names
				namesShort: [ "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa" ]
			},
			months: {
				// full month names (13 months for lunar calendards -- 13th month should be "" if not lunar)
				names: [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December", "" ],
				// abbreviated month names
				namesAbbr: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "" ]
			},
			// AM and PM designators in one of these forms:
			// The usual view, and the upper and lower case versions
			//   [ standard, lowercase, uppercase ]
			// The culture does not use AM or PM (likely all standard date formats use 24 hour time)
			//   null
			AM: [ "AM", "am", "AM" ],
			PM: [ "PM", "pm", "PM" ],
			eras: [
				// eras in reverse chronological order.
				// name: the name of the era in this culture (e.g. A.D., C.E.)
				// start: when the era starts in ticks (gregorian, gmt), null if it is the earliest supported era.
				// offset: offset in years from gregorian calendar
				{
					"name": "A.D.",
					"start": null,
					"offset": 0
				}
			],
			// when a two digit year is given, it will never be parsed as a four digit
			// year greater than this year (in the appropriate era for the culture)
			// Set it as a full year (e.g. 2029) or use an offset format starting from
			// the current year: "+19" would correspond to 2029 if the current year 2010.
			twoDigitYearMax: 2029,
			// set of predefined date and time patterns used by the culture
			// these represent the format someone in this culture would expect
			// to see given the portions of the date that are shown.
			patterns: {
				// short date pattern
				d: "M/d/yyyy",
				// long date pattern
				D: "dddd, MMMM dd, yyyy",
				// short time pattern
				t: "h:mm tt",
				// long time pattern
				T: "h:mm:ss tt",
				// long date, short time pattern
				f: "dddd, MMMM dd, yyyy h:mm tt",
				// long date, long time pattern
				F: "dddd, MMMM dd, yyyy h:mm:ss tt",
				// month/day pattern
				M: "MMMM dd",
				// month/year pattern
				Y: "yyyy MMMM",
				// S is a sortable format that does not vary by culture
				S: "yyyy\u0027-\u0027MM\u0027-\u0027dd\u0027T\u0027HH\u0027:\u0027mm\u0027:\u0027ss"
			}
			// optional fields for each calendar:
			/*
			monthsGenitive:
				Same as months but used when the day preceeds the month.
				Omit if the culture has no genitive distinction in month names.
				For an explaination of genitive months, see http://blogs.msdn.com/michkap/archive/2004/12/25/332259.aspx
			convert:
				Allows for the support of non-gregorian based calendars. This convert object is used to
				to convert a date to and from a gregorian calendar date to handle parsing and formatting.
				The two functions:
					fromGregorian( date )
						Given the date as a parameter, return an array with parts [ year, month, day ]
						corresponding to the non-gregorian based year, month, and day for the calendar.
					toGregorian( year, month, day )
						Given the non-gregorian year, month, and day, return a new Date() object
						set to the corresponding date in the gregorian calendar.
			*/
		}
	},
	// For localized strings
	messages: {}
};

Globalize.cultures[ "default" ].calendar = Globalize.cultures[ "default" ].calendars.standard;

Globalize.cultures[ "en" ] = Globalize.cultures[ "default" ];

Globalize.cultureSelector = "en";

//
// private variables
//

regexHex = /^0x[a-f0-9]+$/i;
regexInfinity = /^[+-]?infinity$/i;
regexParseFloat = /^[+-]?\d*\.?\d*(e[+-]?\d+)?$/;
regexTrim = /^\s+|\s+$/g;

//
// private JavaScript utility functions
//

arrayIndexOf = function( array, item ) {
	if ( array.indexOf ) {
		return array.indexOf( item );
	}
	for ( var i = 0, length = array.length; i < length; i++ ) {
		if ( array[i] === item ) {
			return i;
		}
	}
	return -1;
};

endsWith = function( value, pattern ) {
	return value.substr( value.length - pattern.length ) === pattern;
};

extend = function( deep ) {
	var options, name, src, copy, copyIsArray, clone,
		target = arguments[0] || {},
		i = 1,
		length = arguments.length,
		deep = false;

	// Handle a deep copy situation
	if ( typeof target === "boolean" ) {
		deep = target;
		target = arguments[1] || {};
		// skip the boolean and the target
		i = 2;
	}

	// Handle case when target is a string or something (possible in deep copy)
	if ( typeof target !== "object" && !isFunction(target) ) {
		target = {};
	}

	for ( ; i < length; i++ ) {
		// Only deal with non-null/undefined values
		if ( (options = arguments[ i ]) != null ) {
			// Extend the base object
			for ( name in options ) {
				src = target[ name ];
				copy = options[ name ];

				// Prevent never-ending loop
				if ( target === copy ) {
					continue;
				}

				// Recurse if we're merging plain objects or arrays
				if ( deep && copy && ( isObject(copy) || (copyIsArray = isArray(copy)) ) ) {
					if ( copyIsArray ) {
						copyIsArray = false;
						clone = src && isArray(src) ? src : [];

					} else {
						clone = src && isObject(src) ? src : {};
					}

					// Never move original objects, clone them
					target[ name ] = extend( deep, clone, copy );

				// Don't bring in undefined values
				} else if ( copy || copy === 0 ) {
					// N_SE-46759 : If overring culture value is 'undefined' or 'null'
					//              then not copy overring value that remain default value.
					target[ name ] = copy;
				}
			}
		}
	}

	// Return the modified object
	return target;
};

isArray = Array.isArray || function( obj ) {
	return Object.prototype.toString.call( obj ) === "[object Array]";
};

isFunction = function( obj ) {
	return Object.prototype.toString.call( obj ) === "[object Function]";
};

isObject = function( obj ) {
	return Object.prototype.toString.call( obj ) === "[object Object]";
};

startsWith = function( value, pattern ) {
	return value.indexOf( pattern ) === 0;
};

trim = function( value ) {
	return ( value + "" ).replace( regexTrim, "" );
};

truncate = function( value ) {
	if ( isNaN( value ) ) {
		return NaN;
	}
	return Math[ value < 0 ? "ceil" : "floor" ]( value );
};

zeroPad = function( str, count, left ) {
	var l;
	for ( l = str.length; l < count; l += 1 ) {
		str = ( left ? ("0" + str) : (str + "0") );
	}
	return str;
};

//
// private Globalization utility functions
//

appendPreOrPostMatch = function( preMatch, strings ) {
	// appends pre- and post- token match strings while removing escaped characters.
	// Returns a single quote count which is used to determine if the token occurs
	// in a string literal.
	var quoteCount = 0,
		escaped = false;
	for ( var i = 0, il = preMatch.length; i < il; i++ ) {
		var c = preMatch.charAt( i );
		switch ( c ) {
			case "\'":
				if ( escaped ) {
					strings.push( "\'" );
				}
				else {
					quoteCount++;
				}
				escaped = false;
				break;
			case "\\":
				if ( escaped ) {
					strings.push( "\\" );
				}
				escaped = !escaped;
				break;
			default:
				strings.push( c );
				escaped = false;
				break;
		}
	}
	return quoteCount;
};

expandFormat = function( cal, format ) {
	// expands unspecified or single character date formats into the full pattern.
	format = format || "F";
	var pattern,
		patterns = cal.patterns,
		len = format.length;
	if ( len === 1 ) {
		pattern = patterns[ format ];
		if ( !pattern ) {
			throw "Invalid date format string \'" + format + "\'.";
		}
		format = pattern;
	}
	else if ( len === 2 && format.charAt(0) === "%" ) {
		// %X escape format -- intended as a custom format string that is only one character, not a built-in format.
		format = format.charAt( 1 );
	}
	return format;
};

formatDate = function( value, format, culture ) {
	var cal = culture.calendar,
		convert = cal.convert;

	if ( !format || !format.length || format === "i" ) {
		var ret;
		if ( culture && culture.name.length ) {
			if ( convert ) {
				// non-gregorian calendar, so we cannot use built-in toLocaleString()
				ret = formatDate( value, cal.patterns.F, culture );
			}
			else {
				var eraDate = new Date( value.getTime() ),
					era = getEra( value, cal.eras );
				eraDate.setFullYear( getEraYear(value, cal, era) );
				ret = eraDate.toLocaleString();
			}
		}
		else {
			ret = value.toString();
		}
		return ret;
	}

	var eras = cal.eras,
		sortable = format === "s";
	format = expandFormat( cal, format );

	// Start with an empty string
	ret = [];
	var hour,
		zeros = [ "0", "00", "000" ],
		foundDay,
		checkedDay,
		dayPartRegExp = /([^d]|^)(d|dd)([^d]|$)/g,
		quoteCount = 0,
		tokenRegExp = getTokenRegExp(),
		converted;

	function padZeros( num, c ) {
		var r, s = num + "";
		if ( c > 1 && s.length < c ) {
			r = ( zeros[c - 2] + s);
			return r.substr( r.length - c, c );
		}
		else {
			r = s;
		}
		return r;
	}

	function hasDay() {
		if ( foundDay || checkedDay ) {
			return foundDay;
		}
		foundDay = dayPartRegExp.test( format );
		checkedDay = true;
		return foundDay;
	}

	function getPart( date, part ) {
		if ( converted ) {
			return converted[ part ];
		}
		switch ( part ) {
			case 0: return date.getFullYear();
			case 1: return date.getMonth();
			case 2: return date.getDate();
		}
	}

	if ( !sortable && convert ) {
		converted = convert.fromGregorian( value );
	}

	for ( ; ; ) {
		// Save the current index
		var index = tokenRegExp.lastIndex,
			// Look for the next pattern
			ar = tokenRegExp.exec( format );

		// Append the text before the pattern (or the end of the string if not found)
		var preMatch = format.slice( index, ar ? ar.index : format.length );
		quoteCount += appendPreOrPostMatch( preMatch, ret );

		if ( !ar ) {
			break;
		}

		// do not replace any matches that occur inside a string literal.
		if ( quoteCount % 2 ) {
			ret.push( ar[0] );
			continue;
		}

		var current = ar[ 0 ],
			clength = current.length;

		switch ( current ) {
			case "ddd":
				//Day of the week, as a three-letter abbreviation
			case "dddd":
				// Day of the week, using the full name
				var names = ( clength === 3 ) ? cal.days.namesAbbr : cal.days.names;
				ret.push( names[value.getDay()] );
				break;
			case "d":
				// Day of month, without leading zero for single-digit days
			case "dd":
				// Day of month, with leading zero for single-digit days
				foundDay = true;
				ret.push(
					padZeros( getPart(value, 2), clength )
				);
				break;
			case "MMM":
				// Month, as a three-letter abbreviation
			case "MMMM":
				// Month, using the full name
				var part = getPart( value, 1 );
				ret.push(
					( cal.monthsGenitive && hasDay() )
					?
					cal.monthsGenitive[ clength === 3 ? "namesAbbr" : "names" ][ part ]
					:
					cal.months[ clength === 3 ? "namesAbbr" : "names" ][ part ]
				);
				break;
			case "M":
				// Month, as digits, with no leading zero for single-digit months
			case "MM":
				// Month, as digits, with leading zero for single-digit months
				ret.push(
					padZeros( getPart(value, 1) + 1, clength )
				);
				break;
			case "y":
				// Year, as two digits, but with no leading zero for years less than 10
			case "yy":
				// Year, as two digits, with leading zero for years less than 10
			case "yyyy":
				// Year represented by four full digits
				part = converted ? converted[ 0 ] : getEraYear( value, cal, getEra(value, eras), sortable );
				if ( clength < 4 ) {
					part = part % 100;
				}
				ret.push(
					padZeros( part, clength )
				);
				break;
			case "h":
				// Hours with no leading zero for single-digit hours, using 12-hour clock
			case "hh":
				// Hours with leading zero for single-digit hours, using 12-hour clock
				hour = value.getHours() % 12;
				if ( hour === 0 ) hour = 12;
				ret.push(
					padZeros( hour, clength )
				);
				break;
			case "H":
				// Hours with no leading zero for single-digit hours, using 24-hour clock
			case "HH":
				// Hours with leading zero for single-digit hours, using 24-hour clock
				ret.push(
					padZeros( value.getHours(), clength )
				);
				break;
			case "m":
				// Minutes with no leading zero for single-digit minutes
			case "mm":
				// Minutes with leading zero for single-digit minutes
				ret.push(
					padZeros( value.getMinutes(), clength )
				);
				break;
			case "s":
				// Seconds with no leading zero for single-digit seconds
			case "ss":
				// Seconds with leading zero for single-digit seconds
				ret.push(
					padZeros( value.getSeconds(), clength )
				);
				break;
			case "t":
				// One character am/pm indicator ("a" or "p")
			case "tt":
				// Multicharacter am/pm indicator
				part = value.getHours() < 12 ? ( cal.AM ? cal.AM[0] : " " ) : ( cal.PM ? cal.PM[0] : " " );
				ret.push( clength === 1 ? part.charAt(0) : part );
				break;
			case "f":
				// Deciseconds
			case "ff":
				// Centiseconds
			case "fff":
				// Milliseconds
				ret.push(
					padZeros( value.getMilliseconds(), 3 ).substr( 0, clength )
				);
				break;
			case "z":
				// Time zone offset, no leading zero
			case "zz":
				// Time zone offset with leading zero
				hour = value.getTimezoneOffset() / 60;
				ret.push(
					( hour <= 0 ? "+" : "-" ) + padZeros( Math.floor(Math.abs(hour)), clength )
				);
				break;
			case "zzz":
				// Time zone offset with leading zero
				hour = value.getTimezoneOffset() / 60;
				ret.push(
					( hour <= 0 ? "+" : "-" ) + padZeros( Math.floor(Math.abs(hour)), 2 )
					// Hard coded ":" separator, rather than using cal.TimeSeparator
					// Repeated here for consistency, plus ":" was already assumed in date parsing.
					+ ":" + padZeros( Math.abs(value.getTimezoneOffset() % 60), 2 )
				);
				break;
			case "g":
			case "gg":
				if ( cal.eras ) {
					ret.push(
						cal.eras[ getEra(value, eras) ].name
					);
				}
				break;
		case "/":
			ret.push( cal["/"] );
			break;
		default:
			throw "Invalid date format pattern \'" + current + "\'.";
			break;
		}
	}
	return ret.join( "" );
};

// formatNumber
(function() {
	var expandNumber;

	expandNumber = function( number, precision, formatInfo ) {
		var groupSizes = formatInfo.groupSizes,
			curSize = groupSizes[ 0 ],
			curGroupIndex = 1,
			factor = Math.pow( 10, precision ),
			rounded = Math.round( number * factor ) / factor;

		if ( !isFinite(rounded) ) {
			rounded = number;
		}
		number = rounded;

		var numberString = number+"",
			right = "",
			split = numberString.split( /e/i ),
			exponent = split.length > 1 ? parseInt( split[1], 10 ) : 0;
		numberString = split[ 0 ];
		split = numberString.split( "." );
		numberString = split[ 0 ];
		right = split.length > 1 ? split[ 1 ] : "";

		var l;
		if ( exponent > 0 ) {
			right = zeroPad( right, exponent, false );
			numberString += right.slice( 0, exponent );
			right = right.substr( exponent );
		}
		else if ( exponent < 0 ) {
			exponent = -exponent;
			numberString = zeroPad( numberString, exponent + 1 );
			right = numberString.slice( -exponent, numberString.length ) + right;
			numberString = numberString.slice( 0, -exponent );
		}

		if ( precision > 0 ) {
			right = formatInfo[ "." ] +
				( (right.length > precision) ? right.slice(0, precision) : zeroPad(right, precision) );
		}
		else {
			right = "";
		}

		var stringIndex = numberString.length - 1,
			sep = formatInfo[ "," ],
			ret = "";

		while ( stringIndex >= 0 ) {
			if ( curSize === 0 || curSize > stringIndex ) {
				return numberString.slice( 0, stringIndex + 1 ) + ( ret.length ? (sep + ret + right) : right );
			}
			ret = numberString.slice( stringIndex - curSize + 1, stringIndex + 1 ) + ( ret.length ? (sep + ret) : "" );

			stringIndex -= curSize;

			if ( curGroupIndex < groupSizes.length ) {
				curSize = groupSizes[ curGroupIndex ];
				curGroupIndex++;
			}
		}

		return numberString.slice( 0, stringIndex + 1 ) + sep + ret + right;
	};

	formatNumber = function( value, format, culture ) {
		if ( !isFinite(value) ) {
			if ( value === Infinity ) {
				return culture.numberFormat.positiveInfinity;
			}
			if ( value === -Infinity ) {
				return culture.numberFormat.negativeInfinity;
			}
			return culture.numberFormat.NaN;
		}
		if ( !format || format === "i" ) {
			return culture.name.length ? value.toLocaleString() : value.toString();
		}
		format = format || "D";

		var nf = culture.numberFormat,
			number = Math.abs( value ),
			precision = -1,
			pattern;
		if ( format.length > 1 ) precision = parseInt( format.slice(1), 10 );

		var current = format.charAt( 0 ).toUpperCase(),
			formatInfo;

		switch ( current ) {
			case "D":
				pattern = "n";
				number = truncate( number );
				if ( precision !== -1 ) {
					number = zeroPad( "" + number, precision, true );
				}
				if ( value < 0 ) number = "-" + number;
				break;
			case "N":
				formatInfo = nf;
				// fall through
			case "C":
				formatInfo = formatInfo || nf.currency;
				// fall through
			case "P":
				formatInfo = formatInfo || nf.percent;
				pattern = value < 0 ? formatInfo.pattern[ 0 ] : ( formatInfo.pattern[1] || "n" );
				if ( precision === -1 ) precision = formatInfo.decimals;
				number = expandNumber( number * (current === "P" ? 100 : 1), precision, formatInfo );
				break;
			default:
				throw "Bad number format specifier: " + current;
		}

		var patternParts = /n|\$|-|%/g,
			ret = "";
		for ( ; ; ) {
			var index = patternParts.lastIndex,
				ar = patternParts.exec( pattern );

			ret += pattern.slice( index, ar ? ar.index : pattern.length );

			if ( !ar ) {
				break;
			}

			switch ( ar[0] ) {
				case "n":
					ret += number;
					break;
				case "$":
					ret += nf.currency.symbol;
					break;
				case "-":
					// don't make 0 negative
					if ( /[1-9]/.test(number) ) {
						ret += nf[ "-" ];
					}
					break;
				case "%":
					ret += nf.percent.symbol;
					break;
			}
		}

		return ret;
	};

}());

getTokenRegExp = function() {
	// regular expression for matching date and time tokens in format strings.
	return /\/|dddd|ddd|dd|d|MMMM|MMM|MM|M|yyyy|yy|y|hh|h|HH|H|mm|m|ss|s|tt|t|fff|ff|f|zzz|zz|z|gg|g/g;
};

getEra = function( date, eras ) {
	if ( !eras ) return 0;
	var start, ticks = date.getTime();
	for ( var i = 0, l = eras.length; i < l; i++ ) {
		start = eras[ i ].start;
		if ( start === null || ticks >= start ) {
			return i;
		}
	}
	return 0;
};

getEraYear = function( date, cal, era, sortable ) {
	var year = date.getFullYear();
	if ( !sortable && cal.eras ) {
		// convert normal gregorian year to era-shifted gregorian
		// year by subtracting the era offset
		year -= cal.eras[ era ].offset;
	}
	return year;
};

// parseExact
(function() {
	var expandYear,
		getDayIndex,
		getMonthIndex,
		getParseRegExp,
		outOfRange,
		toUpper,
		toUpperArray;

	expandYear = function( cal, year ) {
		// expands 2-digit year into 4 digits.
		if ( year < 100 ) {
			var now = new Date(),
				era = getEra( now ),
				curr = getEraYear( now, cal, era ),
				twoDigitYearMax = cal.twoDigitYearMax;
			twoDigitYearMax = typeof twoDigitYearMax === "string" ? new Date().getFullYear() % 100 + parseInt( twoDigitYearMax, 10 ) : twoDigitYearMax;
			year += curr - ( curr % 100 );
			if ( year > twoDigitYearMax ) {
				year -= 100;
			}
		}
		return year;
	};

	getDayIndex = function	( cal, value, abbr ) {
		var ret,
			days = cal.days,
			upperDays = cal._upperDays;
		if ( !upperDays ) {
			cal._upperDays = upperDays = [
				toUpperArray( days.names ),
				toUpperArray( days.namesAbbr ),
				toUpperArray( days.namesShort )
			];
		}
		value = toUpper( value );
		if ( abbr ) {
			ret = arrayIndexOf( upperDays[1], value );
			if ( ret === -1 ) {
				ret = arrayIndexOf( upperDays[2], value );
			}
		}
		else {
			ret = arrayIndexOf( upperDays[0], value );
		}
		return ret;
	};

	getMonthIndex = function( cal, value, abbr ) {
		var months = cal.months,
			monthsGen = cal.monthsGenitive || cal.months,
			upperMonths = cal._upperMonths,
			upperMonthsGen = cal._upperMonthsGen;
		if ( !upperMonths ) {
			cal._upperMonths = upperMonths = [
				toUpperArray( months.names ),
				toUpperArray( months.namesAbbr )
			];
			cal._upperMonthsGen = upperMonthsGen = [
				toUpperArray( monthsGen.names ),
				toUpperArray( monthsGen.namesAbbr )
			];
		}
		value = toUpper( value );
		var i = arrayIndexOf( abbr ? upperMonths[1] : upperMonths[0], value );
		if ( i < 0 ) {
			i = arrayIndexOf( abbr ? upperMonthsGen[1] : upperMonthsGen[0], value );
		}
		return i;
	};

	getParseRegExp = function( cal, format ) {
		// converts a format string into a regular expression with groups that
		// can be used to extract date fields from a date string.
		// check for a cached parse regex.
		var re = cal._parseRegExp;
		if ( !re ) {
			cal._parseRegExp = re = {};
		}
		else {
			var reFormat = re[ format ];
			if ( reFormat ) {
				return reFormat;
			}
		}

		// expand single digit formats, then escape regular expression characters.
		var expFormat = expandFormat( cal, format ).replace( /([\^\$\.\*\+\?\|\[\]\(\)\{\}])/g, "\\\\$1" ),
			regexp = [ "^" ],
			groups = [],
			index = 0,
			quoteCount = 0,
			tokenRegExp = getTokenRegExp(),
			match;

		// iterate through each date token found.
		while ( (match = tokenRegExp.exec(expFormat)) !== null ) {
			var preMatch = expFormat.slice( index, match.index );
			index = tokenRegExp.lastIndex;

			// don't replace any matches that occur inside a string literal.
			quoteCount += appendPreOrPostMatch( preMatch, regexp );
			if ( quoteCount % 2 ) {
				regexp.push( match[0] );
				continue;
			}

			// add a regex group for the token.
			var m = match[ 0 ],
				len = m.length,
				add;
			switch ( m ) {
				case "dddd": case "ddd":
				case "MMMM": case "MMM":
				case "gg": case "g":
					add = "(\\D+)";
					break;
				case "tt": case "t":
					add = "(\\D*)";
					break;
				case "yyyy":
				case "fff":
				case "ff":
				case "f":
					add = "(\\d{" + len + "})";
					break;
				case "dd": case "d":
				case "MM": case "M":
				case "yy": case "y":
				case "HH": case "H":
				case "hh": case "h":
				case "mm": case "m":
				case "ss": case "s":
					add = "(\\d\\d?)";
					break;
				case "zzz":
					add = "([+-]?\\d\\d?:\\d{2})";
					break;
				case "zz": case "z":
					add = "([+-]?\\d\\d?)";
					break;
				case "/":
					add = "(\\" + cal[ "/" ] + ")";
					break;
				default:
					throw "Invalid date format pattern \'" + m + "\'.";
					break;
			}
			if ( add ) {
				regexp.push( add );
			}
			groups.push( match[0] );
		}
		appendPreOrPostMatch( expFormat.slice(index), regexp );
		regexp.push( "$" );

		// allow whitespace to differ when matching formats.
		var regexpStr = regexp.join( "" ).replace( /\s+/g, "\\s+" ),
			parseRegExp = { "regExp": regexpStr, "groups": groups };

		// cache the regex for this format.
		return re[ format ] = parseRegExp;
	};

	outOfRange = function( value, low, high ) {
		return value < low || value > high;
	};

	toUpper = function( value ) {
		// "he-IL" has non-breaking space in weekday names.
		return value.split( "\u00A0" ).join( " " ).toUpperCase();
	};

	toUpperArray = function( arr ) {
		var results = [];
		for ( var i = 0, l = arr.length; i < l; i++ ) {
			results[ i ] = toUpper( arr[i] );
		}
		return results;
	};

	parseExact = function( value, format, culture ) {
		// try to parse the date string by matching against the format string
		// while using the specified culture for date field names.
		value = trim( value );
		var cal = culture.calendar,
			// convert date formats into regular expressions with groupings.
			// use the regexp to determine the input format and extract the date fields.
			parseInfo = getParseRegExp( cal, format ),
			match = new RegExp( parseInfo.regExp ).exec( value );
		if ( match === null ) {
			return null;
		}
		// found a date format that matches the input.
		var groups = parseInfo.groups,
			era = null, year = null, month = null, date = null, weekDay = null,
			hour = 0, hourOffset, min = 0, sec = 0, msec = 0, tzMinOffset = null,
			pmHour = false;
		// iterate the format groups to extract and set the date fields.
		for ( var j = 0, jl = groups.length; j < jl; j++ ) {
			var matchGroup = match[ j + 1 ];
			if ( matchGroup ) {
				var current = groups[ j ],
					clength = current.length,
					matchInt = parseInt( matchGroup, 10 );
				switch ( current ) {
					case "dd": case "d":
						// Day of month.
						date = matchInt;
						// check that date is generally in valid range, also checking overflow below.
						if ( outOfRange(date, 1, 31) ) return null;
						break;
					case "MMM": case "MMMM":
						month = getMonthIndex( cal, matchGroup, clength === 3 );
						if ( outOfRange(month, 0, 11) ) return null;
						break;
					case "M": case "MM":
						// Month.
						month = matchInt - 1;
						if ( outOfRange(month, 0, 11) ) return null;
						break;
					case "y": case "yy":
					case "yyyy":
						year = clength < 4 ? expandYear( cal, matchInt ) : matchInt;
						if ( outOfRange(year, 0, 9999) ) return null;
						break;
					case "h": case "hh":
						// Hours (12-hour clock).
						hour = matchInt;
						if ( hour === 12 ) hour = 0;
						if ( outOfRange(hour, 0, 11) ) return null;
						break;
					case "H": case "HH":
						// Hours (24-hour clock).
						hour = matchInt;
						if ( outOfRange(hour, 0, 23) ) return null;
						break;
					case "m": case "mm":
						// Minutes.
						min = matchInt;
						if ( outOfRange(min, 0, 59) ) return null;
						break;
					case "s": case "ss":
						// Seconds.
						sec = matchInt;
						if ( outOfRange(sec, 0, 59) ) return null;
						break;
					case "tt": case "t":
						// AM/PM designator.
						// see if it is standard, upper, or lower case PM. If not, ensure it is at least one of
						// the AM tokens. If not, fail the parse for this format.
						pmHour = cal.PM && ( matchGroup === cal.PM[0] || matchGroup === cal.PM[1] || matchGroup === cal.PM[2] );
						if (
							!pmHour && (
								!cal.AM || ( matchGroup !== cal.AM[0] && matchGroup !== cal.AM[1] && matchGroup !== cal.AM[2] )
							)
						) return null;
						break;
					case "f":
						// Deciseconds.
					case "ff":
						// Centiseconds.
					case "fff":
						// Milliseconds.
						msec = matchInt * Math.pow( 10, 3 - clength );
						if ( outOfRange(msec, 0, 999) ) return null;
						break;
					case "ddd":
						// Day of week.
					case "dddd":
						// Day of week.
						weekDay = getDayIndex( cal, matchGroup, clength === 3 );
						if ( outOfRange(weekDay, 0, 6) ) return null;
						break;
					case "zzz":
						// Time zone offset in +/- hours:min.
						var offsets = matchGroup.split( /:/ );
						if ( offsets.length !== 2 ) return null;
						hourOffset = parseInt( offsets[0], 10 );
						if ( outOfRange(hourOffset, -12, 13) ) return null;
						var minOffset = parseInt( offsets[1], 10 );
						if ( outOfRange(minOffset, 0, 59) ) return null;
						tzMinOffset = ( hourOffset * 60 ) + ( startsWith(matchGroup, "-") ? -minOffset : minOffset );
						break;
					case "z": case "zz":
						// Time zone offset in +/- hours.
						hourOffset = matchInt;
						if ( outOfRange(hourOffset, -12, 13) ) return null;
						tzMinOffset = hourOffset * 60;
						break;
					case "g": case "gg":
						var eraName = matchGroup;
						if ( !eraName || !cal.eras ) return null;
						eraName = trim( eraName.toLowerCase() );
						for ( var i = 0, l = cal.eras.length; i < l; i++ ) {
							if ( eraName === cal.eras[i].name.toLowerCase() ) {
								era = i;
								break;
							}
						}
						// could not find an era with that name
						if ( era === null ) return null;
						break;
				}
			}
		}
		var result = new Date(), defaultYear, convert = cal.convert;
		defaultYear = convert ? convert.fromGregorian( result )[ 0 ] : result.getFullYear();
		if ( year === null ) {
			year = defaultYear;
		}
		else if ( cal.eras ) {
			// year must be shifted to normal gregorian year
			// but not if year was not specified, its already normal gregorian
			// per the main if clause above.
			year += cal.eras[( era || 0 )].offset;
		}
		// set default day and month to 1 and January, so if unspecified, these are the defaults
		// instead of the current day/month.
		if ( month === null ) {
			month = 0;
		}
		if ( date === null ) {
			date = 1;
		}
		// now have year, month, and date, but in the culture's calendar.
		// convert to gregorian if necessary
		if ( convert ) {
			result = convert.toGregorian( year, month, date );
			// conversion failed, must be an invalid match
			if ( result === null ) return null;
		}
		else {
			// have to set year, month and date together to avoid overflow based on current date.
			result.setFullYear( year, month, date );
			// check to see if date overflowed for specified month (only checked 1-31 above).
			if ( result.getDate() !== date ) return null;
			// invalid day of week.
			if ( weekDay !== null && result.getDay() !== weekDay ) {
				return null;
			}
		}
		// if pm designator token was found make sure the hours fit the 24-hour clock.
		if ( pmHour && hour < 12 ) {
			hour += 12;
		}
		result.setHours( hour, min, sec, msec );
		if ( tzMinOffset !== null ) {
			// adjust timezone to utc before applying local offset.
			var adjustedMin = result.getMinutes() - ( tzMinOffset + result.getTimezoneOffset() );
			// Safari limits hours and minutes to the range of -127 to 127.	 We need to use setHours
			// to ensure both these fields will not exceed this range.	adjustedMin will range
			// somewhere between -1440 and 1500, so we only need to split this into hours.
			result.setHours( result.getHours() + parseInt(adjustedMin / 60, 10), adjustedMin % 60 );
		}
		return result;
	};
}());

parseNegativePattern = function( value, nf, negativePattern ) {
	var neg = nf[ "-" ],
		pos = nf[ "+" ],
		ret;
	switch ( negativePattern ) {
		case "n -":
			neg = " " + neg;
			pos = " " + pos;
			// fall through
		case "n-":
			if ( endsWith(value, neg) ) {
				ret = [ "-", value.substr(0, value.length - neg.length) ];
			}
			else if ( endsWith(value, pos) ) {
				ret = [ "+", value.substr(0, value.length - pos.length) ];
			}
			break;
		case "- n":
			neg += " ";
			pos += " ";
			// fall through
		case "-n":
			if ( startsWith(value, neg) ) {
				ret = [ "-", value.substr(neg.length) ];
			}
			else if ( startsWith(value, pos) ) {
				ret = [ "+", value.substr(pos.length) ];
			}
			break;
		case "(n)":
			if ( startsWith(value, "(") && endsWith(value, ")") ) {
				ret = [ "-", value.substr(1, value.length - 2) ];
			}
			break;
	}
	return ret || [ "", value ];
};

//
// public instance functions
//

Globalize.prototype.findClosestCulture = function( cultureSelector ) {
	return Globalize.findClosestCulture.call( this, cultureSelector );
};

Globalize.prototype.format = function( value, format, cultureSelector ) {
	return Globalize.format.call( this, value, format, cultureSelector );
};

Globalize.prototype.localize = function( key, cultureSelector ) {
	return Globalize.localize.call( this, key, cultureSelector );
};

Globalize.prototype.parseInt = function( value, radix, cultureSelector ) {
	return Globalize.parseInt.call( this, value, radix, cultureSelector );
};

Globalize.prototype.parseFloat = function( value, radix, cultureSelector ) {
	return Globalize.parseFloat.call( this, value, radix, cultureSelector );
};

Globalize.prototype.culture = function( cultureSelector ) {
	return Globalize.culture.call( this, cultureSelector );
};

//
// public singleton functions
//

Globalize.addCultureInfo = function( cultureName, baseCultureName, info ) {

	var base = {},
		isNew = false;

	if ( typeof cultureName !== "string" ) {
		// cultureName argument is optional string. If not specified, assume info is first
		// and only argument. Specified info deep-extends current culture.
		info = cultureName;
		cultureName = this.culture().name;
		base = this.cultures[ cultureName ];
	} else if ( typeof baseCultureName !== "string" ) {
		// baseCultureName argument is optional string. If not specified, assume info is second
		// argument. Specified info deep-extends specified culture.
		// If specified culture does not exist, create by deep-extending default
		info = baseCultureName;
		isNew = ( this.cultures[ cultureName ] == null );
		base = this.cultures[ cultureName ] || this.cultures[ "default" ];
	} else {
		// cultureName and baseCultureName specified. Assume a new culture is being created
		// by deep-extending an specified base culture
		isNew = true;
		base = this.cultures[ baseCultureName ];
	}

	this.cultures[ cultureName ] = extend(true, {},
		base,
		info
	);
	// Make the standard calendar the current culture if it's a new culture
	if ( isNew ) {
		this.cultures[ cultureName ].calendar = this.cultures[ cultureName ].calendars.standard;
	}
};

Globalize.findClosestCulture = function( name ) {
	var match;
	if ( !name ) {
		return this.findClosestCulture( this.cultureSelector ) || this.cultures[ "default" ];
	}
	if ( typeof name === "string" ) {
		name = name.split( "," );
	}
	if ( isArray(name) ) {
		var lang,
			cultures = this.cultures,
			list = name,
			i, l = list.length,
			prioritized = [];
		for ( i = 0; i < l; i++ ) {
			name = trim( list[i] );
			var pri, parts = name.split( ";" );
			lang = trim( parts[0] );
			if ( parts.length === 1 ) {
				pri = 1;
			}
			else {
				name = trim( parts[1] );
				if ( name.indexOf("q=") === 0 ) {
					name = name.substr( 2 );
					pri = parseFloat( name );
					pri = isNaN( pri ) ? 0 : pri;
				}
				else {
					pri = 1;
				}
			}
			prioritized.push({ lang: lang, pri: pri });
		}
		prioritized.sort(function( a, b ) {
			return a.pri < b.pri ? 1 : -1;
		});

		// exact match
		for ( i = 0; i < l; i++ ) {
			lang = prioritized[ i ].lang;
			match = cultures[ lang ];
			if ( match ) {
				return match;
			}
		}

		// neutral language match
		for ( i = 0; i < l; i++ ) {
			lang = prioritized[ i ].lang;
			do {
				var index = lang.lastIndexOf( "-" );
				if ( index === -1 ) {
					break;
				}
				// strip off the last part. e.g. en-US => en
				lang = lang.substr( 0, index );
				match = cultures[ lang ];
				if ( match ) {
					return match;
				}
			}
			while ( 1 );
		}

		// last resort: match first culture using that language
		for ( i = 0; i < l; i++ ) {
			lang = prioritized[ i ].lang;
			for ( var cultureKey in cultures ) {
				var culture = cultures[ cultureKey ];
				if ( culture.language == lang ) {
					return culture;
				}
			}
		}
	}
	else if ( typeof name === "object" ) {
		return name;
	}
	return match || null;
};

Globalize.format = function( value, format, cultureSelector ) {
	var culture = this.findClosestCulture( cultureSelector );
	if ( value instanceof Date ) {
		value = formatDate( value, format, culture );
	}
	else if ( typeof value === "number" ) {
		value = formatNumber( value, format, culture );
	}
	return value;
};

Globalize.localize = function( key, cultureSelector ) {
	return this.findClosestCulture( cultureSelector ).messages[ key ] ||
		this.cultures[ "default" ].messages[ key ];
};

Globalize.parseDate = function( value, formats, culture ) {
	culture = this.findClosestCulture( culture );

	var date, prop, patterns;
	if ( formats ) {
		if ( typeof formats === "string" ) {
			formats = [ formats ];
		}
		if ( formats.length ) {
			for ( var i = 0, l = formats.length; i < l; i++ ) {
				var format = formats[ i ];
				if ( format ) {
					date = parseExact( value, format, culture );
					if ( date ) {
						break;
					}
				}
			}
		}
	} else {
		patterns = culture.calendar.patterns;
		for ( prop in patterns ) {
			date = parseExact( value, patterns[prop], culture );
			if ( date ) {
				break;
			}
		}
	}

	return date || null;
};

Globalize.parseInt = function( value, radix, cultureSelector ) {
	return truncate( Globalize.parseFloat(value, radix, cultureSelector) );
};

Globalize.parseFloat = function( value, radix, cultureSelector ) {
	// radix argument is optional
	if ( typeof radix !== "number" ) {
		cultureSelector = radix;
		radix = 10;
	}

	var culture = this.findClosestCulture( cultureSelector );
	var ret = NaN,
		nf = culture.numberFormat;

	if ( value.indexOf(culture.numberFormat.currency.symbol) > -1 ) {
		// remove currency symbol
		value = value.replace( culture.numberFormat.currency.symbol, "" );
		// replace decimal seperator
		value = value.replace( culture.numberFormat.currency["."], culture.numberFormat["."] );
	}

	// trim leading and trailing whitespace
	value = trim( value );

	// allow infinity or hexidecimal
	if ( regexInfinity.test(value) ) {
		ret = parseFloat( value );
	}
	else if ( !radix && regexHex.test(value) ) {
		ret = parseInt( value, 16 );
	}
	else {

		// determine sign and number
		var signInfo = parseNegativePattern( value, nf, nf.pattern[0] ),
			sign = signInfo[ 0 ],
			num = signInfo[ 1 ];

		// #44 - try parsing as "(n)"
		if ( sign === "" && nf.pattern[0] !== "(n)" ) {
			signInfo = parseNegativePattern( value, nf, "(n)" );
			sign = signInfo[ 0 ];
			num = signInfo[ 1 ];
		}

		// try parsing as "-n"
		if ( sign === "" && nf.pattern[0] !== "-n" ) {
			signInfo = parseNegativePattern( value, nf, "-n" );
			sign = signInfo[ 0 ];
			num = signInfo[ 1 ];
		}

		sign = sign || "+";

		// determine exponent and number
		var exponent,
			intAndFraction,
			exponentPos = num.indexOf( "e" );
		if ( exponentPos < 0 ) exponentPos = num.indexOf( "E" );
		if ( exponentPos < 0 ) {
			intAndFraction = num;
			exponent = null;
		}
		else {
			intAndFraction = num.substr( 0, exponentPos );
			exponent = num.substr( exponentPos + 1 );
		}
		// determine decimal position
		var integer,
			fraction,
			decSep = nf[ "." ],
			decimalPos = intAndFraction.indexOf( decSep );
		if ( decimalPos < 0 ) {
			integer = intAndFraction;
			fraction = null;
		}
		else {
			integer = intAndFraction.substr( 0, decimalPos );
			fraction = intAndFraction.substr( decimalPos + decSep.length );
		}
		// handle groups (e.g. 1,000,000)
		var groupSep = nf[ "," ];
		integer = integer.split( groupSep ).join( "" );
		var altGroupSep = groupSep.replace( /\u00A0/g, " " );
		if ( groupSep !== altGroupSep ) {
			integer = integer.split( altGroupSep ).join( "" );
		}
		// build a natively parsable number string
		var p = sign + integer;
		if ( fraction !== null ) {
			p += "." + fraction;
		}
		if ( exponent !== null ) {
			// exponent itself may have a number patternd
			var expSignInfo = parseNegativePattern( exponent, nf, "-n" );
			p += "e" + ( expSignInfo[0] || "+" ) + expSignInfo[ 1 ];
		}
		if ( regexParseFloat.test(p) ) {
			ret = parseFloat( p );
		}
	}
	return ret;
};

Globalize.culture = function( cultureSelector ) {
	// setter
	if ( typeof cultureSelector !== "undefined" ) {
		this.cultureSelector = cultureSelector;
	}
	// getter
	return this.findClosestCulture( cultureSelector ) || this.culture[ "default" ];
};

window.Globalize = Globalize;


}( window ));

/*global window, define */
/* 
 * Copyright (c) 2010 - 2014 Samsung Electronics Co., Ltd.
 * License : MIT License V2
 */
/**
 * #Globalize Utility
 * Object supports globalize options.
 * @class ns.util.globalize
 */
(function (window, document, ns, Globalize) {
	
				var loadedCultures = {};

			/**
			 * Get Language code
			 * @method getLang
			 * @param {?string} language
			 * @return {string}
			 * @private
			 * @member ns.util.globalize
			 * @static
			 */
			function getLang(language) {
				var lang = language ||
						document.getElementsByTagName('html')[0].getAttribute('lang') ||
						window.navigator.language.split('.')[0] || // Webkit, Safari + workaround for Tizen
						'en',
					countryCode = null,
					countryCodeIdx = lang.lastIndexOf('-'),
					ignoreCodes = ['Cyrl', 'Latn', 'Mong'];	// Not country code!
				if (countryCodeIdx !== -1) {	// Found country code!
					countryCode = lang.substr(countryCodeIdx + 1);
					if (ignoreCodes.join('-').indexOf(countryCode) < 0) {
						// countryCode is not found from ignoreCodes.
						// Make countryCode to uppercase.
						lang = [lang.substr(0, countryCodeIdx), countryCode.toUpperCase()].join('-');
					}
				}
				// NOTE: 'en' to 'en-US', because globalize has no 'en' culture file.
				lang = (lang === 'en' ? 'en-US' : lang);
				return lang;
			}

			/**
			 * Get neutral language
			 * @method getNeutralLang
			 * @param {string} lang
			 * @return {string}
			 * @private
			 * @member ns.util.globalize
			 * @static
			 */
			function getNeutralLang(lang) {
				var neutralLangIdx = lang.lastIndexOf('-'),
					neutralLang;
				if (neutralLangIdx !== -1) {
					neutralLang = lang.substr(0, neutralLangIdx);
				}
				return neutralLang;
			}

			/**
			 * Get path to the culture file
			 * @method getCultureFilePath
			 * @param {string} lang
			 * @param {Array} cultureDictionary
			 * @return {string}
			 * @private
			 * @member ns.util.globalize
			 * @static
			 */
			function getCultureFilePath(lang, cultureDictionary) {
				var path = null,
					frameworkData = ns.frameworkData;
				if (typeof lang === "string") {
					if (cultureDictionary && cultureDictionary[lang]) {
						path = cultureDictionary[lang];
					} else {
						// Default Globalize culture file path
						path = [
							frameworkData.jsPath,
							//ns.getConfig('version'),
							'cultures',
							['globalize', 'culture', lang, 'js'].join('.')
						].join('/');
					}
				}
				return path;
			}

			/**
			 * Throw error when the file cannot be loaded
			 * @method printLoadError
			 * @param {string} path
			 * @private
			 * @member ns.util.globalize
			 * @static
			 */
			function printLoadError(path) {
							}

			/**
			 * Error handler
			 * @method _errCB
			 * @param {string} path
			 * @param {?Function} errCB
			 * @private
			 * @member ns.util.globalize
			 * @static
			 */
			function _errCB(path, errCB) {
				if (typeof errCB === 'function') {
					errCB(path);
				} else {
					printLoadError(path);
				}
			}

			/**
			 * Loads culture file
			 * @method loadCultureFile
			 * @param {string} path
			 * @private
			 * @member ns.util.globalize
			 * @static
			 */
			function loadCultureFile(path) {
				var script,
					xhrObj;
				if (path) {	// Invalid path -> Regard it as '404 Not Found' error.
					if (loadedCultures[path] === undefined) {
						try {
							script = document.createElement('script');
							// get some kind of XMLHttpRequest
							xhrObj = new XMLHttpRequest();
							// open and send a synchronous request
							xhrObj.open('GET', path, false);
							xhrObj.send('');
							// add the returned content to a newly created script tag
							script.type = "text/javascript";
							script.text = xhrObj.responseText;
							document.body.appendChild(script);
							loadedCultures[path] = true;
						} catch (ignore) {
						}
					}
				} else {
					_errCB(path);
				}
			}

			ns.util.globalize = {
				/**
				* Load Globalize culture file, and set default culture.
				* @method loadGlobalizeCulture
				* Language code. ex) en-US, en, ko-KR, ko, If language is not
				* given, read language from html 'lang' attribute,
				* or from system setting.
				* @param {string} language
				* Dictionary having language code->
				* @param {string[]} cultureDictionary
				* @member ns.util.globalize
				* @return {string}
				*/
				loadGlobalizeCulture: function (language, cultureDictionary) {
					var path,
						lang;
					lang = getLang(language);
					path = getCultureFilePath(lang, cultureDictionary);
					loadCultureFile(path,
						function () {
							var nLang,
								npath;
							nLang = getNeutralLang(lang);
							npath = getCultureFilePath(nLang, cultureDictionary);
							loadCultureFile(npath, null);
						}, function (lang) {
							Globalize.culture(lang);
						}, lang);
					return lang;
				},
				/**
				 * Set globalize object for default language.
				 * @method setGlobalize
				 * @member ns.util.globalize
				 * @return {?string}
				 */
				setGlobalize: function () {
					var lang,
						self = this;
					/*
					* Tizen has rule that language was set by region setting
					*/
					if (window.tizen) {
						window.tizen.systeminfo.getPropertyValue("LOCALE", function (locale) {
							var countryLang = locale.country;
							if (countryLang) {
								countryLang = countryLang.replace("_", "-");
							}
							countryLang = self.loadGlobalizeCulture(countryLang);
							return Globalize.culture(countryLang);
						});
					} else {
						lang = this.loadGlobalizeCulture();
						return Globalize.culture(lang);
					}
					return null;
				},
				/**
				* Load custom globalize culture file
				* Find current system language, and load appropriate culture
				* file from given culture file list.
				* @method loadCustomGlobalizeCulture
				* collection of 'language':'culture file path' key-val pair.
				* @param {string[]} cultureDictionary
				* @member ns.util.globalize
				* @example
				* var myCultures = {
				*	"en"	: "culture/en.js",
				*	"fr"	: "culture/fr.js",
				*	"ko-KR" : "culture/ko-KR.js"
				* };
				* loadCultomGlobalizeCulture( myCultures );
				*
				* ex) culture/fr.js
				* -------------------------------
				* Globalize.addCultureInfo( "fr", {
				*   messages: {
				*	"hello" : "bonjour",
				*	"translate" : "traduire"
				*   }
				* } );
				* -------------------------------
				*/
				loadCustomGlobalizeCulture: function (cultureDictionary) {
					this.loadGlobalizeCulture(null, cultureDictionary);
				},

				/**
				* return culture object from Globalize library
				* @method culture
				* @return {Object}
				* @member ns.util.globalize
				*/
				culture: function () {
					this.setGlobalize();
					return Globalize.culture();
				}
			};

			document.addEventListener("DOMContentLoaded", function () {
				var globalize = ns.util.globalize;
				globalize.setGlobalize();
			}, false);

			}(window, window.document, ns, window.Globalize));

/*global window, define */
/* 
 * Copyright (c) 2010 - 2014 Samsung Electronics Co., Ltd.
 * License : MIT License V2
 */
/**
 * #Zoom Utility
 * Object supports enabling and disabling zoom.
 * @class ns.util.zoom
 * @author Maciej Urbanski <m.urbanski@samsung.com>
 */
(function (window, document, ns) {
	
				var meta = document.querySelector("meta[name=viewport]"),
				initialContent = meta && meta.getAttribute("content"),
				disabledZoom = initialContent + ",maximum-scale=1, user-scalable=no",
				enabledZoom = initialContent + ",maximum-scale=10, user-scalable=yes",
				disabledInitially = /(user-scalable[\s]*=[\s]*no)|(maximum-scale[\s]*=[\s]*1)[$,\s]/.test(initialContent),
				zoom = {
					/**
					 * Status of zoom
					 * @property {boolean} enabled
					 * @static
					 * @member ns.util.zoom
					 */
					enabled: !disabledInitially,
					/**
					 * Flag shows actual locked/unlocked status
					 * @property {boolean} [locked=false]
					 * @static
					 * @member ns.util.zoom
					 */
					locked: false,
					/**
					 * Disable zoom
					 * @method disable
					 * @param {boolean} lock
					 * @static
					 * @member ns.util.zoom
					 */
					disable: function (lock) {
						if (!disabledInitially && !zoom.locked) {
							if (meta) {
								meta.setAttribute("content", disabledZoom);
							}
							zoom.enabled = false;
							zoom.locked = lock || false;
						}
					},
					/**
					 * Enable zoom
					 * @method enable
					 * @param {boolean} unlock
					 * @static
					 * @member ns.util.zoom
					 */
					enable: function (unlock) {
						if (!disabledInitially && (!zoom.locked || unlock === true)) {
							if (meta) {
								meta.setAttribute("content", enabledZoom);
							}
							zoom.enabled = true;
							zoom.locked = false;
						}
					},
					/**
					 * Restore zoom
					 * @method restore
					 * @static
					 * @member ns.util.zoom
					 */
					restore: function () {
						if (!disabledInitially) {
							if (meta) {
								meta.setAttribute("content", initialContent);
							}
							zoom.enabled = true;
						}
					}
				};
			ns.util.zoom = zoom;
			}(window, window.document, ns));

/*global window, define, XMLHttpRequest */
/* 
 * Copyright (c) 2010 - 2014 Samsung Electronics Co., Ltd.
 * License : MIT License V2
 */
/**
 * #Load Utility
 * Object contains function to load external resources.
 * @class ns.util.load
 */
(function (document, ns) {
	
	
			/**
			 * Local alias for document HEAD element
			 * @property {HTMLHeadElement} head
			 * @static
			 * @private
			 * @member ns.util.load
			 */
			var head = document.head,
				/**
				 * Local alias for document styleSheets element
				 * @property {HTMLStyleElement} styleSheets
				 * @static
				 * @private
				 * @member ns.util.load
				 */
				styleSheets = document.styleSheets,
				/**
				 * Local alias for ns.util.DOM
				 * @property {Object} utilsDOM Alias for {@link ns.util.DOM}
				 * @member ns.util.load
				 * @static
				 * @private
				 */
				utilDOM = ns.util.DOM,
				getNSData = utilDOM.getNSData,
				setNSData = utilDOM.setNSData,
				load = ns.util.load || {},
				/**
				 * Regular expression for extracting path to the image
				 * @property {RegExp} IMAGE_PATH_REGEXP
				 * @static
				 * @private
				 * @member ns.util.load
				 */
				IMAGE_PATH_REGEXP = /url\((\.\/)?images/gm,
				/**
				 * Regular expression for extracting path to the css
				 * @property {RegExp} CSS_FILE_REGEXP
				 * @static
				 * @private
				 * @member ns.util.load
				 */
				CSS_FILE_REGEXP = /[^/]+\.css$/;

			/**
			 * Load file
			 * (synchronous loading)
			 * @method loadFileSync
			 * @param {string} scriptPath
			 * @param {?Function} successCB
			 * @param {?Function} errorCB
			 * @static
			 * @private
			 * @member ns.util.load
			 */
			 function loadFileSync(scriptPath, successCB, errorCB) {
				var xhrObj = new XMLHttpRequest();

				// open and send a synchronous request
				xhrObj.open('GET', scriptPath, false);
				xhrObj.send();
				// add the returned content to a newly created script tag
				if (xhrObj.status === 200 || xhrObj.status === 0) {
					if (typeof successCB === 'function') {
						successCB(xhrObj, xhrObj.status);
					}
				} else {
					if (typeof errorCB === 'function') {
						errorCB(xhrObj, xhrObj.status, new Error(xhrObj.statusText));
					}
				}
			}

			/**
			 * Callback function on javascript load success
			 * @method scriptSyncSuccess
			 * @private
			 * @static
			 * @param {?Function} successCB
			 * @param {?Function} xhrObj
			 * @param {?string} status
			 * @member ns.util.load
			 */
			function scriptSyncSuccess(successCB, xhrObj, status) {
				var script = document.createElement('script');
				script.type = 'text/javascript';
				script.text = xhrObj.responseText;
				document.body.appendChild(script);
				if (typeof successCB === 'function') {
					successCB(xhrObj, status);
				}
			}


			/**
			 * Add script to document
			 * (synchronous loading)
			 * @method scriptSync
			 * @param {string} scriptPath
			 * @param {?Function} successCB
			 * @param {?Function} errorCB
			 * @static
			 * @member ns.util.load
			 */
			function scriptSync(scriptPath, successCB, errorCB) {
				loadFileSync(scriptPath, scriptSyncSuccess.bind(null, successCB), errorCB);
			}

			/**
			 * Callback function on css load success
			 * @method cssSyncSuccess
			 * @param {string} cssPath
			 * @param {?Function} successCB
			 * @param {?Function} xhrObj
			 * @member ns.util.load
			 * @static
			 * @private
			 */
			function cssSyncSuccess(cssPath, successCB, xhrObj) {
				var css = document.createElement('style');
				css.type = 'text/css';
				css.textContent = xhrObj.responseText.replace(
					IMAGE_PATH_REGEXP,
					'url(' + cssPath.replace(CSS_FILE_REGEXP, 'images')
				);
				if (typeof successCB === 'function') {
					successCB(css);
				}
			}

			/**
			 * Add css to document
			 * (synchronous loading)
			 * @method cssSync
			 * @param {string} cssPath
			 * @param {?Function} successCB
			 * @param {?Function} errorCB
			 * @static
			 * @private
			 * @member ns.util.load
			 */
			function cssSync(cssPath, successCB, errorCB) {
				loadFileSync(cssPath, cssSyncSuccess.bind(null, cssPath, successCB), errorCB);
			}

			/**
			 * Add element to head tag
			 * @method addElementToHead
			 * @param {HTMLElement} element
			 * @param {boolean} [asFirstChildElement=false]
			 * @member ns.util.load
			 * @static
			 */
			function addElementToHead(element, asFirstChildElement) {
				var firstElement;
				if (head) {
					if (asFirstChildElement) {
						firstElement = head.firstElementChild;
						if (firstElement) {
							head.insertBefore(element, firstElement);
							return;
						}
					}
					head.appendChild(element);
				}
			}

			/**
			 * Create HTML link element with href
			 * @method makeLink
			 * @param {string} href
			 * @returns {HTMLLinkElement}
			 * @member ns.util.load
			 * @static
			 */
			function makeLink(href) {
				var cssLink = document.createElement('link');
				cssLink.setAttribute('rel', 'stylesheet');
				cssLink.setAttribute('href', href);
				cssLink.setAttribute('name', 'tizen-theme');
				return cssLink;
			}

			/**
			 * Adds the given node to document head or replaces given 'replaceElement'.
			 * Additionally adds 'name' and 'theme-name' attribute
			 * @param {HTMLElement} node Element to be placed as theme link
			 * @param {string} themeName Theme name passed to the element
			 * @param {HTMLElement} [replaceElement=null] If replaceElement is given it gets replaced by node
			 */
			function addNodeAsTheme(node, themeName, replaceElement) {
				setNSData(node, 'name', 'tizen-theme');
				setNSData(node, 'theme-name', themeName);

				if (replaceElement) {
					replaceElement.parentNode.replaceChild(node, replaceElement);
				} else {
					addElementToHead(node, true);
				}
			}

			/**
			 * Add css link element to head if not exists
			 * @method themeCSS
			 * @param {string} path
			 * @param {string} themeName
			 * @param {boolean} [embed=false] Embeds the CSS content to the document
			 * @member ns.util.load
			 * @static
			 */
			function themeCSS(path, themeName, embed) {
				var i,
					styleSheetsLength = styleSheets.length,
					ownerNode,
					previousElement = null,
					linkElement;
				// Find css link or style elements
				for (i = 0; i < styleSheetsLength; i++) {
					ownerNode = styleSheets[i].ownerNode;

					// We try to find a style / link node that matches current style or is linked to
					// the proper theme. We cannot use ownerNode.href because this returns the absolute path
					if (getNSData(ownerNode, 'name') === 'tizen-theme' || ownerNode.getAttribute("href") === path) {
						if (getNSData(ownerNode, 'theme-name') === themeName) {
							// Nothing to change
							return;
						}
						previousElement = ownerNode;
						break;
					}
				}

				if (embed){
					// Load and replace old styles or append new styles
					cssSync(path, function onSuccess(styleElement) {
						addNodeAsTheme(styleElement, themeName, previousElement);
					}, function onFailure(xhrObj, xhrStatus, errorObj) {
						ns.warn("There was a problem when loading '" + themeName + "', status: " + xhrStatus);
					});
				} else {
					linkElement = makeLink(path);
					addNodeAsTheme(linkElement, themeName, previousElement);
				}
			}

			/**
			 * In debug mode add time to url to disable cache
			 * @property {string} cacheBust
			 * @member ns.util.load
			 * @static
			 */
			load.cacheBust = (document.location.href.match(/debug=true/)) ? '?cacheBust=' + (new Date()).getTime() : '';
			// the binding a local methods with the namespace
			load.scriptSync = scriptSync;
			load.addElementToHead = addElementToHead;
			load.makeLink = makeLink;
			load.themeCSS = themeCSS;

			ns.util.load = load;
			}(window.document, ns));

/*global window, define, ns*/
/*jslint bitwise: true */
/* 
 * Copyright (c) 2010 - 2014 Samsung Electronics Co., Ltd.
 * License : MIT License V2
 */
/**
 * #Framework Data Object
 * Object contains properties describing run time environment.
 * @class ns.frameworkData
 */
(function (document, ns) {
	

			var slice = Array.prototype.slice,
				FRAMEWORK_WEBUI = "tizen-web-ui-fw",
				FRAMEWORK_TAU = "tau",
				IS_TAU_REGEXP = /(^|[\\\/])(tau(\.min)?\.js)$/,
				LIB_FILENAME_REGEXP = /(^|[\\\/])((tau(\.min)?\.js)|(tizen-web-ui-fw)(\.custom|\.full)?(\.min)?\.js)$/,
				CSS_FILENAME_REGEXP = /(^|[\\\/])((tau(\.min)?\.css)|(tizen-web-ui-fw)(\.custom|\.full)?(\.min)?\.css)$/,
				TIZEN_THEMES_REGEXP = /^(white|black|default)$/i,
				MINIFIED_REGEXP = /\.min\.js$/,
				frameworkData = {
					/**
					 * The name of framework
					 * @property {string} frameworkName="tizen-web-ui-fw"
					 * @member ns.frameworkData
					 * @static
					 */
					frameworkName: FRAMEWORK_WEBUI,
					/**
					 * The root directory of framework on current device
					 * @property {string} rootDir="/usr/share/tizen-web-ui-fw"
					 * @member ns.frameworkData
					 * @static
					 */
					rootDir: "/usr/share/" + FRAMEWORK_WEBUI,
					/**
					 * The version of framework
					 * @property {string} version="latest"
					 * @member ns.frameworkData
					 * @static
					 */
					version: "latest",
					/**
					 * The theme of framework
					 * @property {string} theme="default"
					 * @member ns.frameworkData
					 * @static
					 */
					theme: "default",
					/**
					 * Tells if the theme that is set was already loaded
					 * @property {boolean} themeLoaded=false
					 * @member ns.frameworkData
					 * @static
					 */
					themeLoaded: false,
					/**
					 * The default width of viewport in framework.
					 * @property {number} defaultViewportWidth=360
					 * @member ns.frameworkData
					 * @static
					 */
					defaultViewportWidth: 360,
					/**
					 * The type of width of viewport in framework.
					 * @property {string} viewportWidth="device-width"
					 * @member ns.frameworkData
					 * @static
					 */
					viewportWidth: "device-width",
					/**
					 * Determines whether the viewport should be scaled
					 * @property {boolean} isMinified=false
					 * @member ns.frameworkData
					 * @static
					 */
					viewportScale: false,
					/**
					 * The default font size in framework.
					 * @property {number} defaultFontSize=22
					 * @member ns.frameworkData
					 * @static
					 */
					defaultFontSize: 22,
					/**
					 * Determines whether the framework is minified
					 * @property {boolean} minified=false
					 * @member ns.frameworkData
					 * @static
					 */
					minified: false,
					/**
					 * Determines the capability of device
					 * @property {Object} deviceCapa
					 * @property {boolean} deviceCapa.inputKeyBack=true
					 * Determines whether the back key is supported.
					 * @property {boolean} deviceCapa.inputKeyMenu=true
					 *  Determines whether the menu key is supported.
					 * @member ns.frameworkData
					 * @static
					 */
					deviceCapa: { inputKeyBack: true, inputKeyMenu: true },
					/**
					 * Determines whether the framework is loaded in debug profile.
					 * @property {boolean} debug=false
					 * @member ns.frameworkData
					 * @static
					 */
					debug: false,
					/**
					 * The version of framework's package
					 * @property {string} pkgVersion="0.2.83"
					 * @member ns.frameworkData
					 * @static
					 */
					pkgVersion: "0.2.83",
					/**
					 * The prefix of data used in framework
					 * @property {string} dataPrefix="data-framework-"
					 * @member ns.frameworkData
					 * @static
					 */
					dataPrefix: "data-framework-",
					/**
					 * The profile of framework
					 * @property {string} profile=""
					 * @member ns.frameworkData
					 * @static
					 */
					profile: ""
				};

			/**
			 * Get data-* params from <script> tag, and set tizen.frameworkData.* values
			 * Returns true if proper <script> tag is found, or false if not.
			 * @method getParams
			 * @return {boolean} Returns true if proper <script> tag is found, or false if not.
			 * @member ns.frameworkData
			 * @static
			 */
			frameworkData.getParams = function() {
				var self = this,
					dataPrefix = self.dataPrefix,
					scriptElements = slice.call(document.querySelectorAll("script[src]")),
					cssElements = slice.call(document.styleSheets),
					themeLoaded = false,
					theme;

				/**
				 * Following cases should be covered here (by recognizing on-page css files).
				 * The final theme and themePath values are determined after going through all script elements
				 *
				 * @TODO write unit tests for covering those cases
				 *
				 * none                                       -> theme: null
				 * <link href="theme.css" />                  -> theme: null
				 * <link href="default/theme.css" />          -> theme: null
				 * <link href="tau.css" />                    -> theme: null
				 * <link href="white/tau.min.css" />          -> theme: "white"
				 * <link href="other/path/black/tau.css" />   -> theme: "black"
				 * <link href="other/path/black/tau.css" />   -> theme: "black"
				 * <link href="other/path/black/other.css" /> -> theme: null
				 * <link href="other/path/black/other.css" data-theme-name="white" />     -> theme: "white"
				 * @method findThemeInLinks
				 * @param {CSSStyleSheet} styleSheet
				 */
				function findThemeInLinks(styleSheet) {
					var cssElement = styleSheet.ownerNode,
						dataThemeName = cssElement.getAttribute("data-theme-name"),
						// Attribute value is taken because href property gives different output
						href = cssElement.getAttribute("href"),
						hrefFragments  = href && href.split('/'),
						hrefDirPart;

					// If we have the theme name defined we can use it right away
					// without thinking about the naming convention
					if (dataThemeName) {
						theme = dataThemeName;
					} else if (href && CSS_FILENAME_REGEXP.test(href)) {
						// We try to find file matching library theme CSS
						// If we have the theme name defined we can use it right away
						if (dataThemeName && TIZEN_THEMES_REGEXP.test(dataThemeName)) {
							theme = dataThemeName;
						} else {
							// We can only determine the current theme using path based approach when the .css file
							// is located in at least one directory
							if (hrefFragments.length >= 2) {
								// When the second to last element matches known themes set the theme to that name
								hrefDirPart = hrefFragments.slice(-2)[0].match(TIZEN_THEMES_REGEXP);
								theme = hrefDirPart && hrefDirPart[0];
							}
						}
					}

					// In case a theme was found (here or in a previous stylesheet) this will be true
					themeLoaded = themeLoaded || !!theme;
				}

				/**
				 * Sets framework data based on found framework library
				 * @TODO write unit cases
				 * @param {HTMLElement} scriptElement
				 */
				function findFrameworkDataInScripts(scriptElement) {
					var src = scriptElement.getAttribute("src"),
						profileName = "",
						frameworkName = FRAMEWORK_TAU,
						themePath,
						jsPath;

					// Check if checked file is a known framework
					// no need to check if src exists because of the query selector
					if (LIB_FILENAME_REGEXP.test(src)) {

						// Priority:
						// 1. theme loaded with css
						// 2. theme from attribute
						// 3. default theme
						theme = theme || scriptElement.getAttribute(dataPrefix + "theme") || self.theme;

						theme = theme.toLowerCase();

						if (IS_TAU_REGEXP.test(src)) {
							frameworkName = FRAMEWORK_TAU;
							// Get profile name.
							// Profile may be defined from framework script or
							// it can be assumed, that profile name is second up directory name
							// e.g. pathToLib/profileName/js/tau.js
							profileName = scriptElement.getAttribute(dataPrefix + "profile") || src.split('/').slice(-3)[0];
							themePath = "/" + profileName + "/theme/" + theme;

							// TAU framework library link
							jsPath = "/" + profileName + "/js";
						} else {
							// tizen-web-ui framework
							frameworkName = FRAMEWORK_WEBUI;
							themePath = "/latest/themes/" + theme;
							jsPath = "/latest/js";
						}

						self.rootDir = scriptElement.getAttribute(dataPrefix + "root") ||
							// remove from src path jsPath and "/" sign
							src.substring(0, src.lastIndexOf(frameworkName) - jsPath.length - 1) ||
							self.rootDir;

						self.themePath = self.rootDir + themePath;
						self.jsPath = self.rootDir + jsPath;
						self.version = scriptElement.getAttribute(dataPrefix + "version") || self.version;
						self.theme = theme;
						self.themeLoaded = themeLoaded;
						self.frameworkName = frameworkName;
						self.minified = src.search(MINIFIED_REGEXP) > -1;
						self.profile = profileName;
					}
				}

				cssElements.forEach(findThemeInLinks);

				scriptElements.forEach(findFrameworkDataInScripts);

				cssElements = null;
				scriptElements = null;
			};

			ns.frameworkData = frameworkData;
			// self init
			ns.frameworkData.getParams();
			}(window.document, ns));

/*global window, define, console */
/*jslint plusplus: true, nomen: true */
/*
 * Copyright (c) 2010 - 2014 Samsung Electronics Co., Ltd.
 * License : MIT License V2
 */
/**
 * #jQuery Mobile mapping engine
 * Object maps engine object from TAU namespace to jQuery Mobile namespace.
 * @class ns.jqm.engine
 */
(function (window, document, ns, $) {
	
				/**
			* Alias to Array.slice function
			* @method slice
			* @member ns.jqm.engine
			* @private
			* @static
			*/
			var slice = [].slice,
				/**
				* @property {Object} nsNormalizeDict directory of data-* attributes normalized name
				* @member ns.jqm.engine
				* @private
				* @static
				*/
				nsNormalizeDict = {},
				util = ns.util,
				zoom = util.zoom,
				events = ns.event,
				load = util.load,
				utilsObject = util.object,
				engine = ns.engine;

			function widgetFunction(parentarguments, mapItem, engine, name) {
				var args = slice.call(parentarguments).map(mapItem);
				engine[name].apply(engine, args);
			}

			ns.jqm.engine = {
				/**
				* append ns functions to jQuery Mobile namespace
				* @method init
				* @param {Object} engine ns.engine class
				* @member ns.jqm.engine
				* @static
				*/
				init: function () {
					var keys = Object.keys(engine),
						i,
						len,
						name,
						/*
						* original jQuery find function
						* type function
						*/
						oldFind,
						/*
						* regular expression to find data-{namespace}-attribute
						*/
						jqmDataRE = /:jqmData\(([^)]*)\)/g, // @TODO fix, insecure (jslint)
						/*
						* string to detect exists jqmData selector
						*/
						jqmDataStr = ':jqmData',
						/*
						* map item to jQuery
						*/
						mapItem = function (item) {
							if (typeof item === "object" && item.selector && item.get) {
								return item.length === 1 ? item.get(0) : item.toArray();
							}

							return item;
						},
						tizen;

					if ($) {

						for (i = 0, len = keys.length; i < len; ++i) {
							name = keys[i];
							$[name] = widgetFunction.bind(null, arguments, mapItem, engine, name);
						}

						utilsObject.merge($.mobile, {
							/*
							* jQuery Mobile namespace
							*/
							ns: "",
							/**
							 *
							 * @param prop
							 * @returns {?string}
							 */
							nsNormalize: function (prop) {
								if (!prop) {
									return null;
								}
								nsNormalizeDict[prop] = nsNormalizeDict[prop] || $.camelCase($.mobile.ns + prop);
								return nsNormalizeDict[prop];
							},
							activeBtnClass : ns.widget.mobile.Button.classes.uiBtnActive,
							activePageClass : ns.widget.mobile.Page.classes.uiPageActive,
							focusClass : ns.widget.mobile.Button.classes.uiFocus,
							version: "1.2.0",
							getAttrFixed: function (element, key) {
								var value = element.getAttribute(key);

								return value === "true" ? true :
										value === "false" ? false :
												value === null ? undefined :
														value;
							},
							path: ns.util.path,
							back : window.history.back.bind(window.history),
							silentScroll: function ( ypos ) {
								if ( ypos === undefined ) {
									ypos = $.mobile.defaultHomeScroll;
								}

								// prevent scrollstart and scrollstop events
								// @TODO enable event control
								//ns.event.special.scrollstart.enabled = false;

								setTimeout( function() {
									window.scrollTo( 0, ypos );
									events.trigger(document, "silentscroll", { x: 0, y: ypos });
								}, 20 );

								setTimeout( function() {
									// @TODO enable event control
									//$.event.special.scrollstart.enabled = true;
								}, 150 );
							},
							nsNormalizeDict: nsNormalizeDict,
							getInheritedTheme : ns.theme.getInheritedTheme,
							closestPageData: function (target) {
								var page = ns.util.selectors.getClosestBySelector($(target)[0],
												"[data-" + ($.mobile.ns || "") + "role='page'], [data-" + ($.mobile.ns || "") + "role='dialog']");
								return ns.engine.instanceWidget(page, 'Page');
							},
							enhanceable: function ( $set ) {
								return this.haveParents( $set, "enhance" );
							},
							hijackable: function ( $set ) {
								return this.haveParents( $set, "ajax" );
							},
							haveParents: function ( $set, attr ) {
								if ( !$.mobile.ignoreContentEnabled ) {
									return $set;
								}

								var count = $set.length,
									$newSet = $(),
									e,
									$element,
									excluded,
									i,
									c;

								for (i = 0; i < count; i++ ) {
									$element = $set.eq( i );
									excluded = false;
									e = $set[ i ];

									while ( e ) {
										c = e.getAttribute ? e.getAttribute( "data-" + $.mobile.ns + attr ) : "";

										if ( c === "false" ) {
											excluded = true;
											break;
										}

										e = e.parentNode;
									}

									if ( !excluded ) {
										$newSet = $newSet.add( $element );
									}
								}

								return $newSet;
							},
							getScreenHeight: function () {
								// Native innerHeight returns more accurate value for this across platforms,
								// jQuery version is here as a normalized fallback for platforms like Symbian
								return window.innerHeight;
							},
							widget: function () {
								// @todo fill data
								return null;
							},
							media: ns.support.media,
							browser: {},
							gradeA: function () {
								// @todo fill data
								return null;
							},
							zoom: zoom,
							popupwindow: {}
						});
						$.mobile.buttonMarkup = $.mobile.buttonMarkup || ns.widget.mobile.Button;
						$.mobile.$window = $(window);
						$.mobile.$document = $(document);
						$.mobile.keyCode = {
							ALT: 18,
							BACKSPACE: 8,
							CAPS_LOCK: 20,
							COMMA: 188,
							COMMAND: 91,
							COMMAND_LEFT: 91, // COMMAND
							COMMAND_RIGHT: 93,
							CONTROL: 17,
							DELETE: 46,
							DOWN: 40,
							END: 35,
							ENTER: 13,
							ESCAPE: 27,
							HOME: 36,
							INSERT: 45,
							LEFT: 37,
							MENU: 93, // COMMAND_RIGHT
							NUMPAD_ADD: 107,
							NUMPAD_DECIMAL: 110,
							NUMPAD_DIVIDE: 111,
							NUMPAD_ENTER: 108,
							NUMPAD_MULTIPLY: 106,
							NUMPAD_SUBTRACT: 109,
							PAGE_DOWN: 34,
							PAGE_UP: 33,
							PERIOD: 190,
							RIGHT: 39,
							SHIFT: 16,
							SPACE: 32,
							TAB: 9,
							UP: 38,
							WINDOWS: 91 // COMMAND
						};
						$.tizen = $.tizen || {};
						tizen = $.tizen;
						tizen.loadCustomGlobalizeCulture = ns.util.globalize.loadCustomGlobalizeCulture.bind(ns.util.globalize);
						$.mobile.tizen = utilsObject.merge($.mobile.tizen, {
							_widgetPrototypes: {},
							disableSelection : function (elements) {
								$(elements).each(function () {
									ns.theme.enableSelection(this, 'none');
								});
							},
							enableSelection : function (elements, value) {
								$(elements).each(function () {
									ns.theme.enableSelection(this, value);
								});
							},
							enableContextMenu: function (elements) {
								$(elements).each(function () {
									ns.theme.enableContextMenu(this);
								});
							},
							disableContextMenu: function (elements) {
								$(elements).each(function () {
									ns.theme.disableContextMenu(this);
								});
							}
						});
						$.mobile.tizen.loadPrototype = null;

						/*
						* jqmData function from jQuery Mobile
						*/
						$.fn.jqmData = function (prop, value) {
							var result;
							if (prop !== undefined) {
								if (prop) {
									prop = $.mobile.nsNormalize(prop);
								}
								if (arguments.length < 2 || value === undefined) {
									result = this.data(prop);
								} else {
									result = this.data(prop, value);
								}
							}
							return result;
						};

						$.fn.jqmRemoveData = function (prop) {
							if (prop !== undefined) {
								if (prop) {
									prop = $.mobile.nsNormalize(prop);
								}
								this.removeData(prop);
							}
							return this;
						};

						$.jqmData = function (context, prop, value) {
							var result = $(context).jqmData(prop, value);
							return value || result;
						};

						$.jqmRemoveData = function (context, prop) {
							$(context).jqmRemoveData(prop);
						};

						$.fn.removeWithDependents = function() {
							$.removeWithDependents( this );
						};

						$.removeWithDependents = function( elem ) {
							var $elem = $( elem );

							( $elem.jqmData( 'dependents' ) || $() ).remove();
							$elem.remove();
						};

						$.fn.addDependents = function( newDependents ) {
							$.addDependents( $( this ), newDependents );
						};

						$.addDependents = function( elem, newDependents ) {
							var dependents = $( elem ).jqmData( 'dependents' ) || $();

							$( elem ).jqmData( 'dependents', $.merge( dependents, newDependents ) );
						};

						$.fn.getEncodedText = function() {
							return $( "<div/>" ).text( $( this ).text() ).html();
						};

						// fluent helper function for the mobile namespaced equivalent
						$.fn.jqmEnhanceable = function() {
							return $.mobile.enhanceable( this );
						};

						$.fn.jqmHijackable = function() {
							return $.mobile.hijackable( this );
						};

						/*
						* Add support of jqmData() in jQuery find
						*/
						oldFind = $.find;

						$.find = function (selector, context, ret, extra) {
							if (selector.indexOf(jqmDataStr) > -1) {
								selector = selector.replace(jqmDataRE, "[data-" + ($.mobile.ns || "") + "$1]");
							}
							return oldFind.call(this, selector, context, ret, extra);
						};

						$.extend($.find, oldFind);

						$.find.matches = function (expr, set) {
							return $.find(expr, null, null, set);
						};

						$.find.matchesSelector = function (node, expr) {
							return $.find(expr, null, null, [ node ]).length > 0;
						};

						/* @TODO
						 * find a better way of initializing constructos
						 * this is for jquery style extending (not jqm
						 * widget extending altough it should work to
						 * when we import $.extend function) by replacing
						 * old methods and using them inline
						 */
						document.addEventListener(ns.engine.eventType.WIDGET_BOUND, function (event) {
							var originalEvent = event.originalEvent || event,
								widget = originalEvent.detail,
								widgetName  = widget && widget.widgetName;
							widgetName = widgetName && widgetName.toLowerCase();
							if (widgetName && widget.element) {
								try {
																		$(widget.element)[widgetName]();
								} catch(e) {
									// suppress errors in not debug mode
																	}

							}
						}, true);

						/* support for global object $.mobile
						* @TODO this is temporary fix, we have to think about this function
						*/
						$(document).bind('create', ns.engine._createEventHandler);
						// support creating widgets by triggering pagecreate
						$(document).bind('pagecreate', function (event) {
							var originalEvent = event.originalEvent || event,
								isPage = originalEvent.detail instanceof ns.widget.mobile.Page,
								pageWidget;
							if (!isPage) { // trigger create when the pagecrate trigger is from outside
								pageWidget = engine.instanceWidget(originalEvent.target, "Page");
								pageWidget.refresh();
								ns.engine._createEventHandler(originalEvent);
							}
						});
						$(document).bind('activePopup', function (event) {
							$.mobile.popup.active = $.mobile.popupwindow.active = event.originalEvent.detail;
						});

						// @TODO fill this object proper data
						$.tizen.frameworkData = ns.frameworkData;

						$.tizen.__tizen__ = tizen;
						tizen.libFileName = "tizen-web-ui-fw(.custom|.full)?(.min)?.js";
						tizen.log = {
							debug : function (msg) {
								if ($.tizen.frameworkData.debug) {
									console.log(msg);
								}
							},
							warn : console.warn.bind(console),
							error : console.error.bind(console),
							alert : window.alert.bind(window)
						};
						tizen.util = {
							loadScriptSync: load.scriptSync,
							isMobileBrowser: ns.theme.isMobileBrowser.bind(ns.theme)
						};
						tizen.css = {
							cacheBust: load.cacheBust,
							addElementToHead : load.addElementToHead.bind(load),
							makeLink : load.makeLink.bind(load),
							load: load.themeCSS
						};
						tizen.loadTheme = ns.theme.loadTheme.bind(ns.theme);
						tizen.loadGlobalizeCulture = ns.util.globalize.loadGlobalizeCulture.bind(ns.util.globalize);
						tizen.setGlobalize = util.globalize.setGlobalize.bind(ns.util.globalize);
						tizen.setViewport = ns.theme.setViewport.bind(ns.theme);
						tizen.scaleBaseFontSize = ns.theme.scaleBaseFontSize.bind(ns.theme);
						tizen.setScaling = ns.theme.setScaling.bind(ns.theme);
						tizen.getParams = ns.frameworkData.getParams.bind(ns.frameworkData);

						ns.setConfig('enableHWKeyHandler', $.mobile.tizen.enableHWKeyHandler);
					}
				}
			};

			// Listen when framework is ready
			document.addEventListener(ns.engine.eventType.INIT, function () {
				ns.jqm.engine.init();
			}, false);

			}(window, window.document, ns, ns.jqm.jQuery));

/*global CustomEvent, define, window, ns */
/*jslint plusplus: true, nomen: true, bitwise: true */
/* Copyright (c) 2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/**
 * #Virtual Mouse Events
 * Reimplementation of jQuery Mobile virtual mouse events.
 *
 * ##Purpose
 * It will let for users to register callbacks to the standard events like bellow,
 * without knowing if device support touch or mouse events
 * @class ns.event.vmouse
 */
/**
 * Triggered after mouse-down or touch-started.
 * @event vmousedown
 * @member ns.event.vmouse
 */
/**
 * Triggered when mouse-click or touch-end when touch-move didn't occur
 * @event vclick
 * @member ns.event.vmouse
 */
/**
 * Triggered when mouse-up or touch-end
 * @event vmouseup
 * @member ns.event.vmouse
 */
/**
 * Triggered when mouse-move or touch-move
 * @event vmousemove
 * @member ns.event.vmouse
 */
/**
 * Triggered when mouse-over or touch-start if went over coordinates
 * @event vmouseover
 * @member ns.event.vmouse
 */
/**
 * Triggered when mouse-out or touch-end
 * @event vmouseout
 * @member ns.event.vmouse
 */
/**
 * Triggered when mouse-cancel or touch-cancel and when scroll occur during touchmove
 * @event vmousecancel
 * @member ns.event.vmouse
 */
(function (window, document, ns) {
	
					/**
				 * Object with default options
				 * @property {Object} vmouse
				 * @member ns.event.vmouse
				 * @static
				 * @private
				 **/
			var vmouse,
				/**
				 * @property {Object} eventProps Contains the properties which are copied from the original event to custom v-events
				 * @member ns.event.vmouse
				 * @static
				 * @private
				 **/
				eventProps,
				/**
				 * Indicates if the browser support touch events
				 * @property {boolean} touchSupport
				 * @member ns.event.vmouse
				 * @static
				 **/
				touchSupport = window.hasOwnProperty("ontouchstart"),
				/**
				 * @property {boolean} didScroll The flag tell us if the scroll event was triggered
				 * @member ns.event.vmouse
				 * @static
				 * @private
				 **/
				didScroll,
				/**
				 * @property {Number} [startX=0] Initial data for touchstart event
				 * @member ns.event.vmouse
				 * @static
				 * @private
				 **/
				startX = 0,
				/**
				 * @property {Number} [startY=0] Initial data for touchstart event
				 * @member ns.event.vmouse
				 * @private
				 * @static
				**/
				startY = 0,
				touchEventProps = ["clientX", "clientY", "pageX", "pageY", "screenX", "screenY"],
				KEY_CODES = {
					enter: 13
				};

			/**
			 * Extends objects with other objects
			 * @method copyProps
			 * @param {Object} from Sets the original event
			 * @param {Object} to Sets the new event
			 * @param {Object} properties Sets the special properties for position
			 * @param {Object} propertiesNames Describe parameters which will be copied from Original to To event
			 * @private
			 * @static
			 * @member ns.event.vmouse
			 */
			function copyProps(from, to, properties, propertiesNames) {
				var i,
					length,
					descriptor,
					property;

				for (i = 0, length = propertiesNames.length; i < length; ++i) {
					property = propertiesNames[i];
					if (isNaN(properties[property]) === false || isNaN(from[property]) === false) {
						descriptor = Object.getOwnPropertyDescriptor(to, property);
						if (!descriptor || descriptor.writable) {
							to[property] = properties[property] || from[property];
						}
					}
				}
			}

			/**
			 * Create custom event
			 * @method createEvent
			 * @param {string} newType gives a name for the new Type of event
			 * @param {Event} original Event which trigger the new event
			 * @param {Object} properties Sets the special properties for position
			 * @return {Event}
			 * @private
			 * @static
			 * @member ns.event.vmouse
			 */
			function createEvent(newType, original, properties) {
				var evt = new CustomEvent(newType, {
						"bubbles": original.bubbles,
						"cancelable": original.cancelable,
						"detail": original.detail
					}),
					orginalType = original.type,
					changeTouches,
					touch,
					j = 0,
					len,
					prop;

				copyProps(original, evt, properties, eventProps);
				evt._originalEvent = original;

				if (orginalType.indexOf("touch") !== -1) {
					orginalType = original.touches;
					changeTouches = original.changedTouches;

					if (orginalType && orginalType.length) {
						touch = orginalType[0];
					} else {
						touch = (changeTouches && changeTouches.length) ? changeTouches[0] : null;
					}

					if (touch) {
						for (len = touchEventProps.length; j < len; j++) {
							prop = touchEventProps[j];
							evt[prop] = touch[prop];
						}
					}
				}

				return evt;
			}

			/**
			 * Dispatch Events
			 * @method fireEvent
			 * @param {string} eventName event name
			 * @param {Event} evt original event
			 * @param {Object} properties Sets the special properties for position
			 * @return {boolean}
			 * @private
			 * @static
			 * @member ns.event.vmouse
			 */
			function fireEvent(eventName, evt, properties) {
				return evt.target.dispatchEvent(createEvent(eventName, evt, properties || {}));
			}

			eventProps = [
				"currentTarget",
				"detail",
				"button",
				"buttons",
				"clientX",
				"clientY",
				"offsetX",
				"offsetY",
				"pageX",
				"pageY",
				"screenX",
				"screenY",
				"toElement",
				"which"
			];

			vmouse = {
				/**
				 * Sets the distance of pixels after which the scroll event will be successful
				 * @property {number} [eventDistanceThreshold=10]
				 * @member ns.event.vmouse
				 * @static
				 */
				eventDistanceThreshold: 10,

				touchSupport: touchSupport
			};

			/**
			 * Handle click down
			 * @method handleDown
			 * @param {Event} evt
			 * @private
			 * @static
			 * @member ns.event.vmouse
			 */
			function handleDown(evt) {
				fireEvent("vmousedown", evt);
			}

			/**
			 * Prepare position of event for keyboard events.
			 * @method preparePositionForClick
			 * @param {Event} event
			 * @return {?Object} options
			 * @private
			 * @static
			 * @member ns.event.vmouse
			 */
			function preparePositionForClick(event) {
				var x = event.clientX,
					y = event.clientY;
				// event comes from keyboard
				if (!x && !y) {
					return preparePositionForEvent(event);
				}
			}

			/**
			 * Handle click
			 * @method handleClick
			 * @param {Event} evt
			 * @private
			 * @static
			 * @member ns.event.vmouse
			 */
			function handleClick(evt) {
				fireEvent("vclick", evt, preparePositionForClick(evt));
			}

			/**
			 * Handle click up
			 * @method handleUp
			 * @param {Event} evt
			 * @private
			 * @static
			 * @member ns.event.vmouse
			 */
			function handleUp(evt) {
				fireEvent("vmouseup", evt);
			}

			/**
			 * Handle click move
			 * @method handleMove
			 * @param {Event} evt
			 * @private
			 * @static
			 * @member ns.event.vmouse
			 */
			function handleMove(evt) {
				fireEvent("vmousemove", evt);
			}

			/**
			 * Handle click over
			 * @method handleOver
			 * @param {Event} evt
			 * @private
			 * @static
			 * @member ns.event.vmouse
			 */
			function handleOver(evt) {
				fireEvent("vmouseover", evt);
			}

			/**
			 * Handle click out
			 * @method handleOut
			 * @param {Event} evt
			 * @private
			 * @static
			 * @member ns.event.vmouse
			 */
			function handleOut(evt) {
				fireEvent("vmouseout", evt);
			}

			/**
			 * Handle touch start
			 * @method handleTouchStart
			 * @param {Event} evt
			 * @private
			 * @static
			 * @member ns.event.vmouse
			 */
			function handleTouchStart(evt) {
				var touches = evt.touches,
					firstTouch;
				//if touches are registered and we have only one touch
				if (touches && touches.length === 1) {
					didScroll = false;
					firstTouch = touches[0];
					startX = firstTouch.pageX;
					startY = firstTouch.pageY;
					fireEvent("vmouseover", evt);
					fireEvent("vmousedown", evt);
				}

			}

			/**
			 * Handle touch end
			 * @method handleTouchEnd
			 * @param {Event} evt
			 * @private
			 * @static
			 * @member ns.event.vmouse
			 */
			function handleTouchEnd(evt) {
				var touches = evt.touches;
				if (touches && touches.length === 0) {
					fireEvent("vmouseup", evt);
					fireEvent("vmouseout", evt);
				}
			}

			/**
			 * Handle touch move
			 * @method handleTouchMove
			 * @param {Event} evt
			 * @private
			 * @static
			 * @member ns.event.vmouse
			 */
			function handleTouchMove(evt) {
				var over,
					firstTouch = evt.touches && evt.touches[0],
					didCancel = didScroll,
					//sets the threshold, based on which we consider if it was the touch-move event
					moveThreshold = vmouse.eventDistanceThreshold;

				/**
				 * Ignore the touch which has identifier other than 0.
				 * Only first touch has control others are ignored.
				 * Patch for webkit behaviour where touchmove event
				 * is triggered between touchend events
				 * if there is multi touch.
				 */
				if (firstTouch.identifier > 0) {
					evt.preventDefault();
					evt.stopPropagation();
					return;
				}

				didScroll = didScroll ||
				//check in both axes X,Y if the touch-move event occur
					(Math.abs(firstTouch.pageX - startX) > moveThreshold ||
					Math.abs(firstTouch.pageY - startY) > moveThreshold);

				// detect over event
				// for compatibility with mouseover because "touchenter" fires only once
				over = document.elementFromPoint(evt.pageX, evt.pageY);
				if (over) {
					fireEvent("_touchover", evt);
				}

				//if didscroll occur and wasn't canceled then trigger touchend otherwise just touchmove
				if (didScroll && !didCancel) {
					fireEvent("vmousecancel", evt);
				}
				fireEvent("vmousemove", evt);
			}

			/**
			 * Handle Scroll
			 * @method handleScroll
			 * @param {Event} evt
			 * @private
			 * @static
			 * @member ns.event.vmouse
			 */
			function handleScroll(evt) {
				if (!didScroll) {
					fireEvent("vmousecancel", evt);
				}
				didScroll = true;
			}

			/**
			 * Handle touch cancel
			 * @method handleTouchCancel
			 * @param {Event} evt
			 * @private
			 * @static
			 * @member ns.event.vmouse
			 */
			function handleTouchCancel(evt) {
				fireEvent("vmousecancel", evt);
			}

			/**
			 * Handle touch cancel
			 * @method handleTouchOver
			 * @private
			 * @static
			 * @member ns.event.vmouse
			 */
			function handleTouchOver() {
				return false;
				// @TODO add callback with handleTouchOver,
			}

			/**
			 * Prepare position of event for keyboard events.
			 * @method preparePositionForEvent
			 * @param {Event} event
			 * @return {Object} properties
			 * @private
			 * @static
			 * @member ns.event.vmouse
			 */
			function preparePositionForEvent(event) {
				var targetRect = event.target && event.target.getBoundingClientRect(),
					properties = {};
				if (targetRect) {
					properties = {
						"clientX": targetRect.left + targetRect.width / 2,
						"clientY": targetRect.top + targetRect.height / 2,
						"which": 1
					};
				}
				return properties;
			}

			/**
			 * Handle key up
			 * @method handleKeyUp
			 * @param {Event} event
			 * @private
			 * @static
			 * @member ns.event.vmouse
			 */
			function handleKeyUp(event) {
				var properties;
				if (event.keyCode === KEY_CODES.enter) {
					properties = preparePositionForEvent(event);
					fireEvent("vmouseup", event, properties);
					fireEvent("vclick", event, properties);
				}
			}

			/**
			 * Handle key down
			 * @method handleKeyDown
			 * @param {Event} event
			 * @private
			 * @static
			 * @member ns.event.vmouse
			 */
			function handleKeyDown(event) {
				if (event.keyCode === KEY_CODES.enter) {
					fireEvent("vmousedown", event, preparePositionForEvent(event));
				}
			}

			/**
			 * Binds events common to mouse and touch to support virtual mouse.
			 * @method bindCommonEvents
			 * @static
			 * @member ns.event.vmouse
			 */
			vmouse.bindCommonEvents = function () {
				document.addEventListener("keyup", handleKeyUp, true);
				document.addEventListener("keydown", handleKeyDown, true);
				document.addEventListener("scroll", handleScroll, true);
				document.addEventListener("click", handleClick, true);
			}

			// @TODO delete touchSupport flag and attach touch and mouse listeners,
			// @TODO check if v-events are not duplicated if so then called only once

			/**
			 * Binds touch events to support virtual mouse.
			 * @method bindTouch
			 * @static
			 * @member ns.event.vmouse
			 */
			vmouse.bindTouch = function () {
				document.addEventListener("touchstart", handleTouchStart, true);
				document.addEventListener("touchend", handleTouchEnd, true);
				document.addEventListener("touchmove", handleTouchMove, true);

				// @TODO add callback with handleTouchOver,
				document.addEventListener("touchenter", handleTouchOver, true);
				// for compatibility with mouseover because "touchenter" fires only once
				// @TODO add callback with handleTouchOver,
				document.addEventListener("_touchover", handleTouchOver, true);
				// document.addEventListener("touchleave", callbacks.out, true);
				document.addEventListener("touchcancel", handleTouchCancel, true);
			};

			/**
			 * Binds mouse events to support virtual mouse.
			 * @method bindMouse
			 * @static
			 * @member ns.event.vmouse
			 */
			vmouse.bindMouse = function () {
				document.addEventListener("mousedown", handleDown, true);

				document.addEventListener("mouseup", handleUp, true);
				document.addEventListener("mousemove", handleMove, true);
				document.addEventListener("mouseover", handleOver, true);
				document.addEventListener("mouseout", handleOut, true);
			};

			ns.event.vmouse = vmouse;

			if (touchSupport) {
				vmouse.bindTouch();
			} else {
				vmouse.bindMouse();
			}
			vmouse.bindCommonEvents();

			}(window, window.document, ns));

/*global window, define */
/* Copyright (c) 2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/**
 * #Event orientationchange
 * Namespace to support orientationchange event
 * @class ns.event.orientationchange
 */
/**
 * Event orientationchange
 * @event orientationchange
 * @member ns.event.orientationchange
 */
(function (window, document, ns) {
	
				var body = document.body,
				orientation = null,
				eventUtils = ns.event,
				orientationchange = {
					/**
					 * Informs about support orientation change event.
					 * @property {boolean} supported
					 * @member ns.event.orientationchange
					 */
					supported: (window.orientation !== undefined) && (window.onorientationchange !== undefined),
					/**
					 * Returns current orientation.
					 * @method getOrientation
					 * @return {"landscape"|"portrait"}
					 * @member ns.event.orientationchange
					 * @static
					 */
					getOrientation: function () {
						return orientation;
					},
					/**
					 * Triggers event orientationchange on element
					 * @method trigger
					 * @param {HTMLElement} element
					 * @member ns.event.orientationchange
					 * @static
					 */
					trigger: function (element) {
						eventUtils.trigger(element, "orientationchange", {'orientation': orientation});
					},
					/**
					 * List of properties copied to event details object
					 * @property {Array} properties
					 * @member ns.event.orientationchange
					 * @static
					 */
					properties: ['orientation']
				},
				detectOrientationByDimensions = function (omitCustomEvent) {
					var width = window.innerWidth,
						height = window.innerHeight;
					if (window.screen) {
						width = window.screen.availWidth;
						height = window.screen.availHeight;
					}

					if (width > height) {
						orientation = "landscape";
					} else {
						orientation = "portrait";
					}

					if (!omitCustomEvent) {
						eventUtils.trigger(window, "orientationchange", {'orientation': orientation});
					}
				},
				checkReportedOrientation = function () {
					if (window.orientation) {
						switch (window.orientation) {
						case 90:
						case -90:
							orientation = "portrait";
							break;
						default:
							orientation = "landscape";
							break;
						}
					} else {
						detectOrientationByDimensions(true);
					}
				},
				matchMediaHandler = function (mediaQueryList) {
					if (mediaQueryList.matches) {
						orientation = "portrait";
					} else {
						orientation = "landscape";
					}
					eventUtils.trigger(window, "orientationchange", {'orientation': orientation});
				},
				portraitMatchMediaQueryList;

			if (orientationchange.supported) {
				window.addEventListener("orientationchange", checkReportedOrientation, false);
				checkReportedOrientation();
				// try media queries
			} else {
				if (window.matchMedia) {
					portraitMatchMediaQueryList = window.matchMedia("(orientation: portrait)");
					if (portraitMatchMediaQueryList.matches) {
						orientation = "portrait";
					} else {
						orientation = "landscape";
					}
					portraitMatchMediaQueryList.addListener(matchMediaHandler);
				} else {
					body.addEventListener("throttledresize", detectOrientationByDimensions);
					detectOrientationByDimensions();
				}
			}

			ns.event.orientationchange = orientationchange;

			}(window, window.document, ns));

/*global window, define */
/* Copyright (c) 2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/**
 * #Touch events
 * Reimplementation of jQuery Mobile virtual mouse events.
 * @class ns.event.touch
 */
/**
 * Short tap event
 * @event tap
 * @member ns.event.touch
 */
/**
 * Long tap event
 * @event taphold
 * @member ns.event.touch
 */
(function (window, document, ns) {
	
				var Touch = {
					/**
					 * tap support configuration
					 * @property {Object} tap
					 * @property {number} [tap.tapholdThreshold=750]
					 * @member ns.event.touch
					 * @static
					 */
					tap: {
						tapholdThreshold: 750
					},
					/**
					 * swipe support configuration
					 * @property {Object} swipe
					 * @property {number} [swipe.scrollSupressionThreshold=30]
					 * @property {number} [swipe.durationThreshold=1000]
					 * @property {number} [swipe.horizontalDistanceThreshold=30]
					 * @property {number} [swipe.verticalDistanceThreshold=75]
					 * @member ns.event.touch
					 * @static
					 */
					swipe : {
						scrollSupressionThreshold: 30, // More than this horizontal displacement, and we will suppress scrolling.
						durationThreshold: 1000, // More time than this, and it isn't a swipe.
						horizontalDistanceThreshold: 30,  // Swipe horizontal displacement must be more than this.
						verticalDistanceThreshold: 75  // Swipe vertical displacement must be less than this.
					}
				},
				timer,
				origTarget,
				eventUtils = ns.event,
				swipeStart = {},
				swipeStop = {},
				clickHandler;

			function clearTapTimer() {
				window.clearTimeout(timer);
			}

			function clearTapHandlers() {
				clearTapTimer();
				document.removeEventListener('vclick', clickHandler, false);
				document.removeEventListener('vmouseup', clearTapTimer, false);
				document.removeEventListener("vmousecancel", clearTapHandlers, false);
			}

			clickHandler = function (event) {
				clearTapHandlers();
				// ONLY trigger a 'tap' event if the start target is
				// the same as the stop target.
				if (origTarget === event.target) {
					eventUtils.trigger(event.target, 'tap');
				}
			};

			function tiemoutFunction() {
				eventUtils.trigger(origTarget, 'taphold');
			}

			function handleTap(event) {
				if (!event.which || event.which === 1) {
					origTarget = event.target;

					document.addEventListener('vclick', clickHandler, false);
					document.addEventListener('vmouseup', clearTapTimer, false);
					document.addEventListener("vmousecancel", clearTapHandlers, false);

					timer = window.setTimeout(tiemoutFunction, Touch.tap.tapholdThreshold);
				}
			}

			function handleSwipeMove(event) {
				swipeStop = {
					time: (new Date()).getTime(),
					coords: [event.pageX, event.pageY]
				};
				// prevent scrolling
				if (Math.abs(swipeStart.coords[0] - swipeStop.coords[0]) > Touch.swipe.scrollSupressionThreshold) {
					event.preventDefault();
				}
			}

			function handleSwipeUp() {
				document.removeEventListener("vmousemove", handleSwipeMove, false);
				document.removeEventListener("vmouseup", handleSwipeUp, false);

				if (swipeStart && swipeStop) {
					if (swipeStop.time - swipeStart.time < Touch.swipe.durationThreshold &&
							Math.abs(swipeStart.coords[0] - swipeStop.coords[0]) > Touch.swipe.horizontalDistanceThreshold &&
							Math.abs(swipeStart.coords[1] - swipeStop.coords[1]) < Touch.swipe.verticalDistanceThreshold) {
						eventUtils.trigger(swipeStart.origin, "swipe");
						eventUtils.trigger(swipeStart.origin, swipeStart.coords[0] > swipeStop.coords[0] ? "swipeleft" : "swiperight");
						swipeStart = swipeStop = {};
					}
				}
			}

			function handleSwipe(event) {
				swipeStart = {
					time: (new Date()).getTime(),
					coords: [event.pageX, event.pageY],
					origin: event.target
				};
				document.addEventListener("vmousemove", handleSwipeMove, false);
				document.addEventListener("vmouseup", handleSwipeUp, false);
			}

			document.addEventListener("vmousedown", handleTap, true);
			document.addEventListener("vmousedown", handleSwipe, true);

			ns.event.touch = Touch;
			}(window, window.document, ns));


/*global window, define */
/*jslint plusplus: true, nomen: true */
/* 
 * Copyright (c) 2010 - 2014 Samsung Electronics Co., Ltd.
 * License : MIT License V2
 */
/**
 * #jQuery Mobile mapping events
 * Object maps events from TAU namespace to jQuery Mobile namespace.
 * @class ns.jqm.event
 */
(function (window, document, ns, $) {
	
	
			var eventUtils = ns.event,
				orginalTrigger,
				orginalDispatch,
				eventType = {
					CLICK: "click",
					SUBMIT: "submit",
					KEYUP: "keyup",
					TOUCHSTART: "touchstart",
					TOUCHEND: "touchend",
					VCLICK: "vclick",
					MOUSEDOWN: "mousedown",
					MOUSEUP: "mouseup",
					BEFOREROUTERINIT: "beforerouterinit"
				},
				registerEventNames = ["touchstart", "touchmove", "touchend", "tap", "taphold", "swipeleft", "swiperight", "scrollstart", "scrollstop"];

			ns.jqm.event = {
				/**
				* Create method on jQuery object with name represent event.
				* @method proxyEventTriggerMethod
				* @param {string} name Name of event and new method
				* @param {Function} trigger Function called after invoke method
				* @member ns.jqm.event
				* @static
				*/
				proxyEventTriggerMethod: function (name, trigger) {
					$.fn[name] = function () {
						var $elements = this,
							elementsLength = $elements.length,
							i;

						for (i = 0; i < elementsLength; i++) {
							trigger($elements.get(i));
						}
					};
				},

				/**
				 * Adds proxy to jquery.trigger method
				 * @method proxyTrigger
				 * @param {string} type event type
				 * @param {Mixed} data event data
				 * @return {jQuery}
				 * @member ns.jqm.event
				 */
				proxyTrigger: function (type, data) {
					var $elements = this,
						elementsLength = $elements.length,
						i;

					if(!eventType[type.toUpperCase()]){
						orginalTrigger.call($elements, type, data);
					}

					for (i = 0; i < elementsLength; i++) {
						eventUtils.trigger($elements.get(i), type);
					}

					return this;
				},

				/**
				 * Method read additional data from event.detail and move these data as additional argument to jQuery.event.dispatch
				 * @method proxyDispatch
				 * @param {jQuery.Event} event event type
				 * @return {jQuery}
				 * @member ns.jqm.event
				 */
				proxyDispatch: function (event) {
					var data = (event.originalEvent && event.originalEvent.detail) || event.detail,
						args;
					args = [].slice.call(arguments);
					if (data) {
						args.push(data);
					}
					return orginalDispatch.apply(this, args);
				},

				/**
				 * Copy properties from originalEvent.detail.* to event Object.
				 * @method copyEventProperties
				 * @param {HTMLElement} root root element to catch all events window/document
				 * @param {string} name Name of event
				 * @param {Array.<string>} properties Array of properties to copy from originalEvent to jQuery Event
				 * @member ns.jqm.event
				 * @static
				 */
				copyEventProperties: function (root, name, properties) {
					$(root).on(name, function (event) {
						var i,
							property;
						for (i = 0; i < properties.length; i++) {
							property = properties[i];
							if (!event[property]) {
								if (root instanceof window.screen.constructor) {
									// In case of orientation change event the properties are set to window.screen object
									// that's why we check if root is Screen in the first place
									event[property] = event.originalEvent.detail && event.originalEvent.detail[property]
										|| event.target[property];
								} else {
									event[property] = event.originalEvent.detail && event.originalEvent.detail[property];
								}
							}
						}
					});
				},

				/**
				 * Proxy events from ns namespace to jQM namespace
				 * @method init
				 * @param {Object} events Alias to {@link ns.event}
				 * @member ns.jqm.event
				 * @static
				 */
				init: function () {
						var removeEvents = function (eventUtils) {
							eventUtils.stopPropagation();
							eventUtils.preventDefault();
							return false;
						},
						blockedEvents = [eventType.TOUCHSTART, eventType.TOUCHEND, eventType.VCLICK, eventType.MOUSEDOWN, eventType.MOUSEUP, eventType.CLICK],
						blockedEventsLength = blockedEvents.length,
						html = document.body.parentNode;

					if ($) {
						// setup new event shortcuts
						registerEventNames.forEach(function(name) {
							$.fn[name] = function(fn) {
								return fn ? this.bind(name, fn) : this.trigger(name);
							};
							// jQuery < 1.8
							if ($.attrFn) {
								$.attrFn[name] = true;
							}
						});

						this.copyEventProperties(window.screen, 'orientationchange', eventUtils.orientationchange.properties);
						this.proxyEventTriggerMethod('orientationchange', eventUtils.orientationchange.trigger);

						// Proxied jQuery's trigger method to fire swipe event
						if (orginalTrigger === undefined) {
							orginalTrigger = $.fn.trigger;
							$.fn.trigger = this.proxyTrigger;
						}

						if (!orginalDispatch) {
							orginalDispatch = $.event.dispatch;
							$.event.dispatch = this.proxyDispatch;
						}

						$.mobile = $.mobile || {};
						$.mobile.tizen = $.mobile.tizen || {};
						$.mobile.tizen.documentRelativeCoordsFromEvent = null;
						$.mobile.tizen.targetRelativeCoordsFromEvent = null;
						$.mobile.addEventBlocker = function () {
							var i;
							html.classList.add("ui-blocker");
							for (i = 0; i < blockedEventsLength; i++) {
								html.addEventListener(blockedEvents[i], removeEvents, true);
							}
						};
						$.mobile.removeEventBlocker = function () {
							var i;
							html.classList.remove("ui-blocker");
							for (i = 0; i < blockedEventsLength; i++) {
								html.removeEventListener(blockedEvents[i], removeEvents, true);
							}
						};
						$.mobile.tizen.documentRelativeCoordsFromEvent = eventUtils.documentRelativeCoordsFromEvent.bind(eventUtils);
						$.mobile.tizen.targetRelativeCoordsFromEvent = eventUtils.targetRelativeCoordsFromEvent.bind(eventUtils);
					}
				}
			};

			// Listen when framework is ready
			document.addEventListener(eventType.BEFOREROUTERINIT, function () {
				ns.jqm.event.init();
			}, false);
			}(window, window.document, ns, ns.jqm.jQuery));

/*global window, define, ns */
/*
* Copyright  2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/**
 * #Mobile Widget Reference
 *
 * The Tizen Web UI service provides rich Tizen widgets that are optimized for the Tizen Web browser. You can use the widgets for:
 *
 * - CSS animation
 * - Rendering
 *
 * The following table displays the widgets provided by the Tizen Web UI service.
 *
 * @class ns.widget.mobile
 * @seeMore https://developer.tizen.org/dev-guide/2.2.1/org.tizen.web.uiwidget.apireference/html/web_ui_framework.htm "Web UI Framework Reference"
 * @author Maciej Urbanski <m.urbanski@samsung.com>
 */
(function (window, ns) {
	
				ns.widget.mobile = ns.widget.mobile || {};
			}(window, ns));

/*global window, define, ns */
/*
* Copyright  2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/*jslint nomen: true */
/**
 * #BaseWidgetMobile
 * Extenstion of class BaseWidget for mobile profile.
 * This class has compability properties and methods with jQuery Mobile Widget.
 * @class ns.widget.mobile.BaseWidgetMobile
 * @extends ns.widget.BaseWidget
 */
(function (document, ns) {
	
	
			var BaseWidgetMobile = function () {
					this.options = {};
				},
				BaseWidget = ns.widget.BaseWidget,
				basePrototype = BaseWidget.prototype,
				parent_configure = basePrototype.configure,
				parent_disable = basePrototype.disable,
				parent_enable = basePrototype.enable,
				prototype = new BaseWidget(),
				disableClass = "ui-state-disabled",
				ariaDisabled = "aria-disabled",
				slice = [].slice;

			BaseWidgetMobile.classes = {
				disable: disableClass
			};

			/**
			 * Configures widget object from definition.
			 * @method configure
			 * @param {Object} definition
			 * @param {string} definition.name Name of widget
			 * @param {string} definition.selector Selector of widget
			 * @param {string} definition.binding Path to file with widget (without extension)
			 * @param {HTMLElement} element
			 * @param {Object} options Configure options
			 * @member ns.widget.mobile.BaseWidgetMobile
			 * @chainable
			 * @instance
			 */
			prototype.configure = function (definition, element, options) {
				var self = this,
					definitionName,
					widgetName;
				parent_configure.call(self, definition, element, options);
				if (definition) {
					definitionName = definition.name;
					widgetName = definitionName && definitionName.toLowerCase();
					/**
					 * @property {string} widgetName Widget base class
					 * @member ns.widget.mobile.BaseWidgetMobile
					 * @instance
					 */
					self.widgetName = widgetName;
					/**
					* @property {string} widgetBaseClass Widget base class
					* @member ns.widget.mobile.BaseWidgetMobile
					* @instance
					*/
					self.widgetBaseClass = self.namespace + '-' + widgetName;
					/**
					* @property {number} uuid Number id of widget instance
					* @member ns.widget.mobile.BaseWidgetMobile
					* @instance
					*/
					self.uuid = ns.getNumberUniqueId();

					/**
					 * @property {string} eventNamespace Namespace of widget events (suffix for events)
					 * @member ns.widget.mobile.BaseWidgetMobile
					 * @instance
					 */
					self.eventNamespace = '.' + widgetName + (self.uuid || '');

					/**
					 * @property {string} [defaultElement='<div>'] Default element for the widget
					 * @member ns.widget.mobile.BaseWidgetMobile
					 * @instance
					 */
					self.defaultElement = '<div>';
				}

				return this;
			};

			/**
			* Disables widget.
			* @method disable
			* @member ns.widget.mobile.BaseWidgetMobile
			* @instance
			*/
			prototype.disable = function () {
				var self = this,
					element = self.element,
					elementClasses = element.classList,
					args = slice.call(arguments);

				parent_disable.apply(self, args);
				elementClasses.add(self.widgetFullName + "-disabled");
				elementClasses.add(disableClass);
				element.setAttribute(ariaDisabled, true);
				// @TODO
				//this.hoverable.removeClass( "ui-state-hover" );
				//this.focusable.removeClass( "ui-state-focus" );
			};

			/**
			* Enables widget.
			* @method enable
			* @member ns.widget.mobile.BaseWidgetMobile
			* @instance
			*/
			prototype.enable = function () {
				var self = this,
					element = self.element,
					elementClasses = element.classList,
					args = slice.call(arguments);

				parent_enable.apply(self, args);
				elementClasses.remove(self.widgetFullName + "-disabled");
				elementClasses.remove(disableClass);
				element.setAttribute(ariaDisabled, false);
				// @TODO
				//this.hoverable.removeClass( "ui-state-hover" );
				//this.focusable.removeClass( "ui-state-focus" );
			};

			/**
			* Throws exception.
			* @method raise
			* @param {?string} msg Message of throw
			* @member ns.widget.mobile.BaseWidgetMobile
			* @instance
			*/
			prototype.raise = function (msg) {
				throw "Widget [" + this.widgetName + "]: " + msg;
			};

			/**
			 * Enhances all the children of all elements in the set of matched elements.
			 * @method enhanceWithin
			 * @member ns.widget.mobile.BaseWidgetMobile
			 * @instance
			 * @removed 2.3
			 */
			prototype.enhanceWithin = function () {
				ns.log('method enhanceWithin is deprecated');
			};

			/**
			 * Enhances all the children of all elements in the set of matched elements.
			 * @method enhance
			 * @member ns.widget.mobile.BaseWidgetMobile
			 * @instance
			 * @removed 2.3
			 */
			prototype.enhance = function () {
				ns.log('method enhance is deprecated');
			};
			

			/**
			* Returns element of widget.
			* @method widget
			* @member ns.widget.mobile.BaseWidgetMobile
			* @return {HTMLElement}
			* @instance
			*/
			prototype.widget = function () {
				return this.element;
			};

			BaseWidgetMobile.prototype = prototype;

			// definition
			ns.widget.mobile.BaseWidgetMobile = BaseWidgetMobile;

			}(window.document, ns));

/*global window, define */
/*
* Copyright  2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/*jslint nomen: true, plusplus: true */
/**
 * #Loader Widget
 * Widget displaying loader popup on page changes.
 *
 * ##HTML Examples
 * ###Create simple loader pending from div using data-role:
 *
 *		@example
 *			<div data-role="loader" id="ns-loader"></div>
 *
 * ###Create simple loader pending from div using class:
 *
 *		@example
 *			<div class="ui-loader" id="ns-loader"></div>
 *
 * ##Manual constructor
 * For manual creation of loader widget you can use constructor of widget:
 *
 *		@example
 *			<div id="ns-loader"></div>
 *			<script>
 *				var elementLoader = document.getElementById("ns-loader"),
 *				loader = tau.widget.Loader(elementLoader);
 *			</script>
 * If jQuery library is loaded, its method can be used:
 *
 *		@example
 *			<div id="ns-loader"></div>
 *			<script>
 *				$("#ns-loader").loader();
 *			</script>
 *
 * ##Options for Loader Widget
 *
 * Options for widget can be defined as _data-..._ attributes or given as
 * parameter in constructor.
 *
 * You can change option for widget using method **option**.
 *
 * ###Custom html
 * Adds custom html for the inner content of the loading messages
 *
 *		@example
 *			<div data-role="loader" id="ns-loader"
 *			data-html="<span>loading...</span>"></div>
 *
 * ###Custom text
 * Text to be displayed when the loader is shown
 *
 *		@example
 *			<div data-role="loader" id="ns-loader" data-text="loading...">
 *			</div>

 * ###Visibility of text
 * When the loader is shown and text is added, checks whether the text in the
 * loading message is shown;
 *
 *		@example
 *			<div data-role="loader" id="ns-loader" data-text="loading..."
 *			data-text-visible="true"></div>

 * ###Set theme
 * Sets the theme for the loading messages
 *
 *		@example
 *			<div data-role="loader" id="ns-loader" data-theme="a"></div>
 *
 *
 * ##Options for Loader Widget
 *
 * Options for widget can be get/set .
 *
 * ###You can change option for widget using method **option**.
 * Initialize the loader
 *
 *		@example
 *			<script>
 *				var elementLoader = document.getElementById("ns-loader"),
 *				loader = tau.widget.Loader(elementLoader);
 *			</script>
 *
 * ###Custom html
 * Get or set the html option, after initialization
 *
 *		@example
 *			<script>
 *				//getter
 *				loader.option( "html" );
 *
 *				//setter
 *				loader.option( "html", "<span>Loader</span>", );
 *			</script>
 *
 * ###Custom text
 * Get or set the text option, after initialization
 *
 *		@example
 *			<script>
 *				//getter
 *				loader.option( "text" );
 *
 *				//setter
 *				loader.option( "text", "Loader" );
 *			</script>
 *
 * ###Visibility of text
 * Get or set the textVisible option, after initialization
 *
 *		@example
 *			<script>
 *				//getter
 *				loader.option( "textVisible" );
 *
 *				//setter
 *				loader.option( "textVisible", "true" );
 *			</script>
 *
 * ###Set theme
 * Get or set the theme option, after initialization
 *
 *		@example
 *			<script>
 *				//getter
 *				loader.option( "theme" );
 *
 *				//setter
 *				loader.option( "theme", "b" );
 *			</script>
 *
 *
 * @extends ns.widget.mobile.BaseWidgetMobile
 * @class ns.widget.mobile.Loader
 * @author Maciej Moczulski <m.moczulski@samsung.com>
 * @author Maciej Urbanski <m.urbanski@samsung.com>
 * @author Piotr Karny <p.karny@samsung.com>
 * @author Piotr Kusztal <p.kusztal@samsung.com>
 */
(function (window, ns) {
	


			/**
			 * {Object} Widget Alias for {@link ns.widget.mobile.BaseWidgetMobile}
			 * @member ns.widget.mobile.Loader
			 * @private
			 */
			var BaseWidget = ns.widget.mobile.BaseWidgetMobile,
				/**
				 * @property {Object} engine Alias for class ns.engine
				 * @member ns.widget.mobile.Loader
				 * @private
				 */
				engine = ns.engine,
				object = ns.util.object,

				Loader = function () {
					var self = this;
					self.action = "";
					self.label = null;
					self.defaultHtml = "";
					self.options = object.copy(Loader.prototype.options);
				},
				classes = {
					uiLoader: "ui-loader",
					uiLoaderPrefix: "ui-loader-",
					uiBodyPrefix: "ui-body-",
					uiCorner: "ui-corner-all",
					uiIcon: "ui-icon",
					uiLoaderIcon: "ui-icon-loading",
					uiLoading: "ui-loading",
					uiTextOnly: "ui-loader-textonly"
				},
				properties = {
					pageLoadErrorMessageTheme: "e",
					pageLoadErrorMessage: "Error Loading Page"
				},
				prototype = new BaseWidget();

			/**
			 * Dictionary for loader related css
			 * @property {Object} classes
			 * @member ns.widget.mobile.Loader
			 * @static
			 */
			Loader.classes = classes;

			/**
			 * Dictionary for loader related properties such as messages and
			 * themes
			 * @property {Object} properties
			 * @member ns.widget.mobile.Loader
			 * @static
			 */
			Loader.properties = properties;

			/**
			 * Object with default options
			 * @property {Object} options
			 * @property {string} [options.theme="a"] the theme for the loading
			 * messages
			 * @property {boolean} [options.textVisible=false] whether the text
			 * in the loading message is shown
			 * @property {?string} [options.html=""] custom html for the inner
			 * content of the loading messages
			 * @property {string} [options.text="loading"] the text to be
			 * displayed when the loading is shown
			 * @member ns.widget.mobile.Loader
			 */
			prototype.options = {
				theme: "a",
				textVisible: false,
				html: "",
				text: "loading"
			};

			/**
			 * Build structure of loader widget
			 * @method _build
			 * @param {HTMLElement} element
			 * @return {HTMLElement}
			 * @protected
			 * @member ns.widget.mobile.Loader
			 */
			prototype._build = function (element) {
				var options = this.options,
					loaderElementSpan = document.createElement("span"),
					loaderElementTile = document.createElement("h1"),
					elementClassList = element.classList,
					spanClassList = loaderElementSpan.classList;

				loaderElementTile.textContent = options.text;
				spanClassList.add(classes.uiIcon);
				spanClassList.add(classes.uiLoaderIcon);

				element.appendChild(loaderElementSpan);
				element.appendChild(loaderElementTile);
				elementClassList.add(classes.uiLoader);
				elementClassList.add(classes.uiCorner);
				elementClassList.add(classes.uiBodyPrefix + options.theme);
				elementClassList.add(classes.uiLoaderPrefix + "default");

				this.defaultHtml = element.innerHTML;

				return element;
			};

			/**
			 * Init structure of loader widget
			 * @method _init
			 * @param {HTMLElement} element
			 * @return {HTMLElement}
			 * @protected
			 * @member ns.widget.mobile.Loader
			 */
			prototype._init = function (element) {
				this.defaultHtml = element.innerHTML;
				return element;
			};

			/**
			 * Reset HTML
			 *
			 * Method resets contained html of loader
			 *
			 *		@example
			 *			<script>
			 *				var loaderWidget = tau.widget.Loader(
			 *						document.getElementById("ns-loader")
			 *				);
			 *				loaderWidget.resetHtml();
			 *
			 *				//or
			 *
			 *				$( "#ns-loader" ).loader( "resetHtml" );
			 *			</script>
			 *
			 * @method resetHtml
			 * @param {HTMLElement} element
			 * @member ns.widget.mobile.Loader
			 */
			prototype.resetHtml = function (element) {
				element = element || this.element;
				element.innerHTML = this.defaultHtml;
			};

			/**
			 * Show loader
			 *
			 * Method shows loader on the page
			 *
			 *		@example
			 *			<script>
			 *				var loaderWidget = tau.widget.Loader(
			 *						document.getElementById("ns-loader")
			 *					);
			 *				loaderWidget.show();
			 *
			 *				// or
			 *
			 *				$( "#ns-loader" ).loader( "show" );
			 *
			 *				//or with parameters
			 *
			 *				$( "#ns-loader" ).loader( "show", {
			 *					text: "foo",
			 *					textVisible: true,
			 *					theme: "z",
			 *					html: ""
			 *				});
			 *			</script>
			 *
			 * @method show
			 * @param {string} theme
			 * @param {string} msgText
			 * @param {boolean} textonly
			 * @member ns.widget.mobile.Loader
			 */
			prototype.show = function (theme, msgText, textonly) {
				var classes = Loader.classes,
					self = this,
					element = self.element,
					elementClassList = element.classList,
					body = document.body,
					copySettings = {},
					loadSettings = {},
					textVisible,
					message;

				self.resetHtml(element);

				if (theme !== undefined && theme.constructor === Object) {
					copySettings = object.copy(self.options);
					loadSettings = object.merge(copySettings, theme);
					// @todo remove $.mobile.loadingMessageTheme
					theme = loadSettings.theme || $.mobile.loadingMessageTheme;
				} else {
					loadSettings = self.options;
					// @todo remove $.mobile.loadingMessageTheme
					theme = theme || $.mobile.loadingMessageTheme ||
						loadSettings.theme;
				}

				// @todo remove $.mobile.loadingMessage
				message = msgText || $.mobile.loadingMessage ||
					loadSettings.text;
				document.documentElement.classList.add(classes.uiLoading);

				// @todo remove $.mobile.loadingMessage
				if ($.mobile.loadingMessage === false && !loadSettings.html) {
					element.getElementsByTagName("h1")[0].innerHTML = "";
				} else {
					// @todo remove $.mobile.loadingMessageTextVisible
					if ($.mobile.loadingMessageTextVisible !== undefined) {
						textVisible = $.mobile.loadingMessageTextVisible;
					} else {
						textVisible = loadSettings.textVisible;
					}

					element.className = "";
					elementClassList.add(classes.uiLoader);
					elementClassList.add(classes.uiCorner);
					elementClassList.add(classes.uiBodyPrefix + theme);
					elementClassList.add(classes.uiLoaderPrefix +
						(textVisible || msgText ||
							theme.text ? "verbose" : "default"));

					if ((loadSettings.textonly !== undefined &&
						loadSettings.textonly) || textonly) {
						elementClassList.add(classes.uiTextOnly);
					}

					if (loadSettings.html) {
						element.innerHTML = loadSettings.html;
					} else {
						element.getElementsByTagName("h1")[0].textContent =
							message;
					}
				}

			};

			/**
			 * Hide loader
			 *
			 * Method hides loader on the page
			 *
			 *		@example
			 *			<script>
			 *				var loaderWidget = tau.widget.Loader(
			 *						document.getElementById("ns-loader")
			 *					);
			 *				loaderWidget.hide();
			 *
			 *				// or
			 *
			 *				$( "#ns-loader" ).loader( "hide" );
			 *			</script>
			 *
			 * @method hide
			 * @member ns.widget.mobile.Loader
			 */
			prototype.hide = function () {
				var classes = Loader.classes;
				document.documentElement.classList.remove(classes.uiLoading);
			};

			/**
			 * The function "value" is not supported in this widget.
			 *
			 * @method value
			 * @chainable
			 * @member ns.widget.mobile.Loader
			 */

			/**
			 * Disable the Loader
			 *
			 * Method adds disabled attribute on loader and changes look of
			 * loader to disabled state.
			 *
			 *		@example
			 *		<div data-role="loader" id="ns-loader"></div>
			 *
			 *		<script>
			 *			var elementLoader = tau.widget.Loader(
			 *					document.getElementById("ns-loader")
			 *				);
			 *			elementLoader.disable();
			 *		</script>
			 *
			 * If jQuery is loaded:
			 *
			 *		@example
			 *		<div data-role="loader" id="ns-loader"></div>
			 *
			 *		<script>
			 *			$("#ns-loader").loader("disable");
			 *		</script>
			 *
			 * @method disable
			 * @chainable
			 * @member ns.widget.mobile.Loader
			 */

			/**
			 * Enable the loader
			 *
			 * Method removes disabled attribute on loader and changes look of
			 * loader to enabled state.
			 *
			 *		@example
			 *		<div data-role="loader" id="ns-loader"></div>
			 *
			 *		<script>
			 *			var elementLoader = tau.widget.Loader(
			 *					document.getElementById("ns-loader")
			 *				);
			 *			elementLoader.enable();
			 *		</script>
			 *
			 * If jQuery is loaded:
			 *
			 *		@example
			 *		<div data-role="loader" id="ns-loader"></div>
			 *
			 *		<script>
			 *			$("#ns-loader").loader("enable");
			 *		</script>
			 *
			 * @method enable
			 * @chainable
			 * @member ns.widget.mobile.Loader
			 */

			/**
			 * Trigger an event on widget's element.
			 *
			 *		@example
			 *		<div data-role="loader" id="ns-loader"></div>
			 *
			 *		<script>
			 *			var elementLoader = tau.widget.Loader(
			 *					document.getElementById("ns-loader")
			 *				);
			 *			elementLoader.trigger("eventName");
			 *		</script>
			 *
			 * If jQuery is loaded:
			 *
			 *		@example
			 *		<div data-role="loader" id="ns-loader"></div>
			 *
			 *		<script>
			 *			$("#ns-loader").loader("trigger", "eventName");
			 *		</script>
			 *
			 * @method trigger
			 * @param {string} eventName the name of event to trigger
			 * @param {?*} [data] additional object to be carried with the event
			 * @param {boolean} [bubbles=true] indicating whether the event
			 * bubbles up through the DOM or not
			 * @param {boolean} [cancelable=true] indicating whether the event
			 * is cancelable
			 * @return {boolean} false, if any callback invoked preventDefault
			 * on event object
			 * @member ns.widget.mobile.Loader
			 */

			/**
			 * Add event listener to widget's element.
			 *
			 *		@example
			 *		<div data-role="loader" id="ns-loader"></div>
			 *
			 *		<script>
			 *			var elementLoader = tau.widget.Loader(
			 *					document.getElementById("ns-loader")
			 *				);
			 *			elementLoader.on("eventName", function () {
			 *				console.log("Event fires");
			 *			});
			 *		</script>
			 *
			 * If jQuery is loaded:S
			 *
			 *		@example
			 *		<div data-role="loader" id="ns-loader"></div>
			 *
			 *		<script>
			 *			$("#ns-loader").loader("on", "eventName", function () {
			 *				console.log("Event fires");
			 *			});
			 *		</script>
			 *
			 * @method on
			 * @param {string} eventName the name of event
			 * @param {Function} listener function call after event will be
			 * trigger
			 * @param {boolean} [useCapture=false] useCapture param tu
			 * addEventListener
			 * @member ns.widget.mobile.Loader
			 */

			/**
			 * Remove event listener to widget's element.
			 *
			 *		@example
			 *		<div data-role="loader" id="ns-loader"></div>
			 *
			 *		<script>
			 *			var elementLoader = tau.widget.Loader(
			 *					document.getElementById("ns-loader")
			 *				),
			 *				callback = function () {
			 *					console.log("Event fires");
			 *				};
			 *			// add callback on event "eventName"
			 *			elementLoader.on("eventName", callback);
			 *			// ...
			 *			// remove callback on event "eventName"
			 *			elementLoader.off("eventName", callback);
			 *		</script>
			 *
			 * If jQuery is loaded:
			 *
			 *		@example
			 *		<div data-role="loader" id="ns-loader"></div>
			 *
			 *		<script>
			 *			var callback = function () {
			 *					console.log("Event fires");
			 *				};
			 *			// add callback on event "eventName"
			 *			$("#ns-loader").loader("on", "eventName", callback);
			 *			// ...
			 *			// remove callback on event "eventName"
			 *			$("#ns-loader").loader("off", "eventName", callback);
			 *		</script>
			 * @method off
			 * @param {string} eventName the name of event
			 * @param {Function} listener function call after event will be
			 * trigger
			 * @param {boolean} [useCapture=false] useCapture param to
			 * addEventListener
			 * @member ns.widget.mobile.Loader
			 */

			/**
			 * Get/Set options of the widget.
			 *
			 * This method can work in many context.
			 *
			 * If first argument is type of object them, method set values for
			 * options given in object. Keys of object are names of options and
			 * values from object are values to set.
			 *
			 * If you give only one string argument then method return value
			 * for given option.
			 *
			 * If you give two arguments and first argument will be a string
			 * then second argument will be intemperate as value to set.
			 *
			 *		@example
			 *		<div data-role="loader" id="ns-loader"></div>
			 *
			 *			<script>
			 *				//getter
			 *				loader.option("text");
			 *
			 *				//setter
			 *				loader.option("text","Loader");
			 *			</script>
			 *
			 * If jQuery is loaded:
			 *
			 *		@example
			 *		<div data-role="loader" id="ns-loader"></div>
			 *
			 *		<script>
			 *			var value;
			 *
			 * 			// get value
			 *			value = $("#ns-loader").loader("option", "text");
			 *
			 *			// set value
			 *			$("#ns-loader").loader(
			 *				"option", "text", "Loader fires"
			 *			);
			 *		</script>
			 *
			 * @method option
			 * @param {string|Object} [name] name of option
			 * @param {*} value value to set
			 * @member ns.widget.mobile.Loader
			 * @return {*} return value of option or undefined if method is
			 * called in setter context
			 */
			// definition
			Loader.prototype = prototype;
			ns.widget.mobile.Loader = Loader;
			engine.defineWidget(
				"Loader",
				"[data-role='loader'], .ui-loader",
				[
					"show",
					"hide",
					"resetHtml"
				],
				Loader,
				"mobile"
			);

}(window.document, ns));

/*global window, define */
/*jslint plusplus: true, nomen: true */
/* 
 * Copyright (c) 2010 - 2014 Samsung Electronics Co., Ltd.
 * License : MIT License V2
 */
(function (window, document, ns, $) {
	
	
			var initLoader = function () {
				if ($) {
					$.mobile = $.mobile || {};

					// DEPRECATED Should the text be visble in the loading message?
					$.mobile.loadingMessageTextVisible = undefined;

					// DEPRECATED When the text is visible, what theme does the loading box use?
					$.mobile.loadingMessageTheme = undefined;

					// DEPRECATED default message setting
					$.mobile.loadingMessage = undefined;

					// DEPRECATED
					// Turn on/off page loading message. Theme doubles as an object argument
					// with the following shape: { theme: '', text: '', html: '', textVisible: '' }
					// NOTE that the $.mobile.loading* settings and params past the first are deprecated
					$.mobile.showPageLoadingMsg = function (theme, msgText, textonly) {
						$.mobile.loading('show', theme, msgText, textonly);
						return;
					};

					// DEPRECATED
					$.mobile.hidePageLoadingMsg = function () {
						$.mobile.loading('hide');
						return;
					};

					$.mobile.loading = function () {
						var args = Array.prototype.slice.call(arguments),
							method = args[0],
							theme = args[1],
							msgText = args[2],
							textonly = args[3],
							element = document.querySelector('[data-role=loader]') || document.createElement('div'),
							loader = ns.engine.instanceWidget(element, 'Loader');
						if (method === 'show') {
							loader.show(theme, msgText, textonly);
						} else if (method === 'hide') {
							loader.hide();
						}
						return;
					};
				}
			};

			// Listen when framework is ready
			document.addEventListener(ns.engine.eventType.INIT, initLoader, false);

			}(window, window.document, ns, ns.jqm.jQuery));

/*global window, define, RegExp */
/* 
 * Copyright (c) 2010 - 2014 Samsung Electronics Co., Ltd.
 * License : MIT License V2
 */
/**
 * #Path Utility
 * Object helps work with paths.
 * @class ns.util.path
 * @static
 * @author Tomasz Lukawski <t.lukawski@samsung.com>
 * @author Maciej Urbanski <m.urbanski@samsung.com>
 * @author Piotr Karny <p.karny@samsung.com>
 */
(function (window, document, ns) {
	
					/**
				* Local alias for ns.engine
				* @property {Object} engine Alias for {@link ns.engine}
				* @member ns.util.path
				* @static
				* @private
				*/
			var engine = ns.engine,
				/**
				* Local alias for ns.util.object
				* @property {Object} utilsObject Alias for {@link ns.util.object}
				* @member ns.util.path
				* @static
				* @private
				*/
				utilsObject = ns.util.object,
				/**
				* Local alias for ns.util.selectors
				* @property {Object} utilsSelectors Alias for {@link ns.util.selectors}
				* @member ns.util.path
				* @static
				* @private
				*/
				utilsSelectors = ns.util.selectors,
				/**
				* Local alias for ns.util.DOM
				* @property {Object} utilsDOM Alias for {@link ns.util.DOM}
				* @member ns.util.path
				* @static
				* @private
				*/
				utilsDOM = ns.util.DOM,
				/**
				* Cache for document base element
				* @member ns.util.path
				* @property {HTMLBaseElement} base
				* @static
				* @private
				*/
				base,
				/**
				 * location object
				 * @property {Object} location
				 * @static
				 * @private
				 * @member ns.util.path
				 */
				location = {},
				path = {
					/**
					 * href part for mark state
					 * @property {string} [uiStateKey="&ui-state"]
					 * @static
					 * @member ns.util.path
					 */
					uiStateKey: "&ui-state",

					// This scary looking regular expression parses an absolute URL or its relative
					// variants (protocol, site, document, query, and hash), into the various
					// components (protocol, host, path, query, fragment, etc that make up the
					// URL as well as some other commonly used sub-parts. When used with RegExp.exec()
					// or String.match, it parses the URL into a results array that looks like this:
					//
					//	[0]: http://jblas:password@mycompany.com:8080/mail/inbox?msg=1234&type=unread#msg-content?param1=true&param2=123
					//	[1]: http://jblas:password@mycompany.com:8080/mail/inbox?msg=1234&type=unread
					//	[2]: http://jblas:password@mycompany.com:8080/mail/inbox
					//	[3]: http://jblas:password@mycompany.com:8080
					//	[4]: http:
					//	[5]: //
					//	[6]: jblas:password@mycompany.com:8080
					//	[7]: jblas:password
					//	[8]: jblas
					//	[9]: password
					//	[10]: mycompany.com:8080
					//	[11]: mycompany.com
					//	[12]: 8080
					//	[13]: /mail/inbox
					//	[14]: /mail/
					//	[15]: inbox
					//	[16]: ?msg=1234&type=unread
					//	[17]: #msg-content?param1=true&param2=123
					//	[18]: #msg-content
					//	[19]: ?param1=true&param2=123
					//
					/**
					* @property {RegExp} urlParseRE Regular expression for parse URL
					* @member ns.util.path
					* @static
					*/
					urlParseRE: /^(((([^:\/#\?]+:)?(?:(\/\/)((?:(([^:@\/#\?]+)(?:\:([^:@\/#\?]+))?)@)?(([^:\/#\?\]\[]+|\[[^\/\]@#?]+\])(?:\:([0-9]+))?))?)?)?((\/?(?:[^\/\?#]+\/+)*)([^\?#]*)))?(\?[^#]+)?)((#[^\?]*)(\?.*)?)?/,

					/**
					* Abstraction to address xss (Issue #4787) by removing the authority in
					* browsers that auto decode it. All references to location.href should be
					* replaced with a call to this method so that it can be dealt with properly here
					* @method getLocation
					* @param {string|Object} url
					* @return {string}
					* @member ns.util.path
					*/
					getLocation: function (url) {
						var uri = this.parseUrl(url || window.location.href),
							hash = uri.hash;
						// mimic the browser with an empty string when the hash is empty
						hash = hash === "#" ? "" : hash;
						location = uri;
						// Make sure to parse the url or the location object for the hash because using location.hash
						// is autodecoded in firefox, the rest of the url should be from the object (location unless
						// we're testing) to avoid the inclusion of the authority
						return uri.protocol + "//" + uri.host + uri.pathname + uri.search + hash;
					},

					/**
					* Return the original document url
					* @method getDocumentUrl
					* @member ns.util.path
					* @param {boolean} [asParsedObject=false]
					* @return {string|Object}
					* @static
					*/
					getDocumentUrl: function (asParsedObject) {
						return asParsedObject ? utilsObject.copy(path.documentUrl) : path.documentUrl.href;
					},

					/**
					* Parse a location into a structure
					* @method parseLocation
					* @return {Object}
					* @member ns.util.path
					*/
					parseLocation: function () {
						return this.parseUrl(this.getLocation());
					},

					/**
					* Parse a URL into a structure that allows easy access to
					* all of the URL components by name.
					* If we're passed an object, we'll assume that it is
					* a parsed url object and just return it back to the caller.
					* @method parseUrl
					* @member ns.util.path
					* @param {string|Object} url
					* @return {Object} uri record
					* @return {string} return.href
					* @return {string} return.hrefNoHash
					* @return {string} return.hrefNoSearch
					* @return {string} return.domain
					* @return {string} return.protocol
					* @return {string} return.doubleSlash
					* @return {string} return.authority
					* @return {string} return.username
					* @return {string} return.password
					* @return {string} return.host
					* @return {string} return.hostname
					* @return {string} return.port
					* @return {string} return.pathname
					* @return {string} return.directory
					* @return {string} return.filename
					* @return {string} return.search
					* @return {string} return.hash
					* @return {string} return.hashSearch
					* @static
					*/
					parseUrl: function (url) {
						var matches;
						if (typeof url === "object") {
							return url;
						}
						matches = path.urlParseRE.exec(url || "") || [];

							// Create an object that allows the caller to access the sub-matches
							// by name. Note that IE returns an empty string instead of undefined,
							// like all other browsers do, so we normalize everything so its consistent
							// no matter what browser we're running on.
						return {
							href:		matches[0] || "",
							hrefNoHash:	matches[1] || "",
							hrefNoSearch:	matches[2] || "",
							domain:		matches[3] || "",
							protocol:	matches[4] || "",
							doubleSlash:	matches[5] || "",
							authority:	matches[6] || "",
							username:	matches[8] || "",
							password:	matches[9] || "",
							host:		matches[10] || "",
							hostname:	matches[11] || "",
							port:		matches[12] || "",
							pathname:	matches[13] || "",
							directory:	matches[14] || "",
							filename:	matches[15] || "",
							search:		matches[16] || "",
							hash:		matches[18] || "",
							hashSearch:	matches[19] || ""
						};
					},

					/**
					* Turn relPath into an absolute path. absPath is
					* an optional absolute path which describes what
					* relPath is relative to.
					* @method makePathAbsolute
					* @member ns.util.path
					* @param {string} relPath
					* @param {string} [absPath=""]
					* @return {string}
					* @static
					*/
					makePathAbsolute: function (relPath, absPath) {
						var absStack,
							relStack,
							directory,
							i;
						if (relPath && relPath.charAt(0) === "/") {
							return relPath;
						}

						relPath = relPath || "";
						absPath = absPath ? absPath.replace(/^\/|(\/[^\/]*|[^\/]+)$/g, "") : "";

						absStack = absPath ? absPath.split("/") : [];
						relStack = relPath.split("/");
						for (i = 0; i < relStack.length; i++) {
							directory = relStack[i];
							switch (directory) {
							case ".":
								break;
							case "..":
								if (absStack.length) {
									absStack.pop();
								}
								break;
							default:
								absStack.push(directory);
								break;
							}
						}
						return "/" + absStack.join("/");
					},

					/**
					* Returns true if both urls have the same domain.
					* @method isSameDomain
					* @member ns.util.path
					* @param {string|Object} absUrl1
					* @param {string|Object} absUrl2
					* @return {boolean}
					* @static
					*/
					isSameDomain: function (absUrl1, absUrl2) {
						return path.parseUrl(absUrl1).domain === path.parseUrl(absUrl2).domain;
					},

					/**
					* Returns true for any relative variant.
					* @method isRelativeUrl
					* @member ns.util.path
					* @param {string|Object} url
					* @return {boolean}
					* @static
					*/
					isRelativeUrl: function (url) {
						// All relative Url variants have one thing in common, no protocol.
						return path.parseUrl(url).protocol === "";
					},

					/**
					 * Returns true for an absolute url.
					 * @method isAbsoluteUrl
					 * @member ns.util.path
					 * @param {string} url
					 * @return {boolean}
					 * @static
					 */
					isAbsoluteUrl: function (url) {
						return path.parseUrl(url).protocol !== "";
					},

					/**
					* Turn the specified realtive URL into an absolute one. This function
					* can handle all relative variants (protocol, site, document, query, fragment).
					* @method makeUrlAbsolute
					* @member ns.util.path
					* @param {string} relUrl
					* @param {string} absUrl
					* @return {string}
					* @static
					*/
					makeUrlAbsolute: function (relUrl, absUrl) {
						if (!path.isRelativeUrl(relUrl)) {
							return relUrl;
						}

						var relObj = path.parseUrl(relUrl),
							absObj = path.parseUrl(absUrl),
							protocol = relObj.protocol || absObj.protocol,
							doubleSlash = relObj.protocol ? relObj.doubleSlash : (relObj.doubleSlash || absObj.doubleSlash),
							authority = relObj.authority || absObj.authority,
							hasPath = relObj.pathname !== "",
							pathname = path.makePathAbsolute(relObj.pathname || absObj.filename, absObj.pathname),
							search = relObj.search || (!hasPath && absObj.search) || "",
							hash = relObj.hash;

						return protocol + doubleSlash + authority + pathname + search + hash;
					},

					/**
					* Add search (aka query) params to the specified url.
					* If page is embedded page, search query will be added after
					* hash tag. It's allowed to add query content for both external
					* pages and embedded pages.
					* Examples:
					* http://domain/path/index.html#embedded?search=test
					* http://domain/path/external.html?s=query#embedded?s=test
					* @method addSearchParams
					* @member ns.util.path
					* @param {string|Object} url
					* @param {Object|string} params
					* @return {string}
					*/
					addSearchParams: function (url, params) {
						var urlObject = path.parseUrl(url),
							paramsString = (typeof params === "object") ? this.getAsURIParameters(params) : params,
							searchChar = '',
							urlObjectHash = urlObject.hash;

						if (path.isEmbedded(url) && paramsString.length > 0) {
							searchChar = urlObject.hashSearch || "?";
							return urlObject.hrefNoHash + (urlObjectHash || "") + searchChar + (searchChar.charAt(searchChar.length - 1) === "?" ? "" : "&") + paramsString ;
						}

						searchChar = urlObject.search || "?";
						return urlObject.hrefNoSearch + searchChar + (searchChar.charAt(searchChar.length - 1) === "?" ? "" : "&") + paramsString + (urlObjectHash || "");
					},

					/**
					 * Add search params to the specified url with hash
					 * @method addHashSearchParams
					 * @member ns.util.path
					 * @param {string|Object} url
					 * @param {Object|string} params
					 * @returns {string}
					 */
					addHashSearchParams: function (url, params) {
						var urlObject = path.parseUrl(url),
							paramsString = (typeof params === "object") ? path.getAsURIParameters(params) : params,
							hash = urlObject.hash,
							searchChar = hash ? (hash.indexOf("?") < 0 ? hash + "?" : hash + "&") : "#?";
						return urlObject.hrefNoHash + searchChar + (searchChar.charAt(searchChar.length - 1) === "?" ? "" : "&") + paramsString;
					},

					/**
					* Convert absolute Url to data Url
					* - for embedded pages strips parameters
					* - for the same domain as document base remove domain
					* otherwise returns decoded absolute Url
					* @method convertUrlToDataUrl
					* @member ns.util.path
					* @param {string} absUrl
					* @param {string} dialogHashKey
					* @param {Object} documentBase uri structure
					* @return {string}
					* @static
					*/
					convertUrlToDataUrl: function (absUrl, dialogHashKey, documentBase) {
						var urlObject = path.parseUrl(absUrl);

						if (path.isEmbeddedPage(urlObject, !!dialogHashKey)) {
							// Keep hash and search data for embedded page
							return path.getFilePath(urlObject.hash + urlObject.hashSearch, dialogHashKey);
						}
						documentBase = documentBase || path.documentBase;
						if (path.isSameDomain(urlObject, documentBase)) {
							return urlObject.hrefNoHash.replace(documentBase.domain, "");
						}

						return window.decodeURIComponent(absUrl);
					},

					/**
					* Get path from current hash, or from a file path
					* @method get
					* @member ns.util.path
					* @param {string} newPath
					* @return {string}
					*/
					get: function (newPath) {
						if (newPath === undefined) {
							newPath = this.parseLocation().hash;
						}
						return this.stripHash(newPath).replace(/[^\/]*\.[^\/*]+$/, '');
					},

					/**
					* Test if a given url (string) is a path
					* NOTE might be exceptionally naive
					* @method isPath
					* @member ns.util.path
					* @param {string} url
					* @return {boolean}
					* @static
					*/
					isPath: function (url) {
						return (/\//).test(url);
					},

					/**
					* Return a url path with the window's location protocol/hostname/pathname removed
					* @method clean
					* @member ns.util.path
					* @param {string} url
					* @param {Object} documentBase  uri structure
					* @return {string}
					* @static
					*/
					clean: function (url, documentBase) {
						return url.replace(documentBase.domain, "");
					},

					/**
					* Just return the url without an initial #
					* @method stripHash
					* @member ns.util.path
					* @param {string} url
					* @return {string}
					* @static
					*/
					stripHash: function (url) {
						return url.replace(/^#/, "");
					},

					/**
					* Return the url without an query params
					* @method stripQueryParams
					* @member ns.util.path
					* @param {string} url
					* @return {string}
					* @static
					*/
					stripQueryParams: function (url) {
						return url.replace(/\?.*$/, "");
					},

					/**
					* Validation proper hash
					* @method isHashValid
					* @member ns.util.path
					* @param {string} hash
					* @static
					*/
					isHashValid: function (hash) {
						return (/^#[^#]+$/).test(hash);
					},

					/**
					* Check whether a url is referencing the same domain, or an external domain or different protocol
					* could be mailto, etc
					* @method isExternal
					* @member ns.util.path
					* @param {string|Object} url
					* @param {Object} documentUrl uri object
					* @return {boolean}
					* @static
					*/
					isExternal: function (url, documentUrl) {
						var urlObject = path.parseUrl(url);
						return urlObject.protocol && urlObject.domain !== documentUrl.domain ? true : false;
					},

					/**
					* Check if the url has protocol
					* @method hasProtocol
					* @member ns.util.path
					* @param {string} url
					* @return {boolean}
					* @static
					*/
					hasProtocol: function (url) {
						return (/^(:?\w+:)/).test(url);
					},

					/**
					 * Check if the url refers to embedded content
					 * @method isEmbedded
					 * @member ns.util.path
					 * @param {string} url
					 * @returns {boolean}
					 * @static
					 */
					isEmbedded: function (url) {
						var urlObject = path.parseUrl(url);

						if (urlObject.protocol !== "") {
							return (!path.isPath(urlObject.hash) && !!urlObject.hash && (urlObject.hrefNoHash === path.parseLocation().hrefNoHash));
						}
						return (/\?.*#|^#/).test(urlObject.href);
					},

					/**
					* Get the url as it would look squashed on to the current resolution url
					* @method squash
					* @member ns.util.path
					* @param {string} url
					* @param {string} [resolutionUrl=undefined]
					* @return {string}
					*/
					squash: function (url, resolutionUrl) {
						var href,
							cleanedUrl,
							search,
							stateIndex,
							isPath = this.isPath(url),
							uri = this.parseUrl(url),
							preservedHash = uri.hash,
							uiState = "";

						// produce a url against which we can resole the provided path
						resolutionUrl = resolutionUrl || (path.isPath(url) ? path.getLocation() : path.getDocumentUrl());

						// If the url is anything but a simple string, remove any preceding hash
						// eg #foo/bar -> foo/bar
						//	#foo -> #foo
						cleanedUrl = isPath ? path.stripHash(url) : url;

						// If the url is a full url with a hash check if the parsed hash is a path
						// if it is, strip the #, and use it otherwise continue without change
						cleanedUrl = path.isPath(uri.hash) ? path.stripHash(uri.hash) : cleanedUrl;

						// Split the UI State keys off the href
						stateIndex = cleanedUrl.indexOf(this.uiStateKey);

						// store the ui state keys for use
						if (stateIndex > -1) {
							uiState = cleanedUrl.slice(stateIndex);
							cleanedUrl = cleanedUrl.slice(0, stateIndex);
						}

						// make the cleanedUrl absolute relative to the resolution url
						href = path.makeUrlAbsolute(cleanedUrl, resolutionUrl);

						// grab the search from the resolved url since parsing from
						// the passed url may not yield the correct result
						search = this.parseUrl(href).search;

						// @TODO all this crap is terrible, clean it up
						if (isPath) {
							// reject the hash if it's a path or it's just a dialog key
							if (path.isPath(preservedHash) || preservedHash.replace("#", "").indexOf(this.uiStateKey) === 0) {
								preservedHash = "";
							}

							// Append the UI State keys where it exists and it's been removed
							// from the url
							if (uiState && preservedHash.indexOf(this.uiStateKey) === -1) {
								preservedHash += uiState;
							}

							// make sure that pound is on the front of the hash
							if (preservedHash.indexOf("#") === -1 && preservedHash !== "") {
								preservedHash = "#" + preservedHash;
							}

							// reconstruct each of the pieces with the new search string and hash
							href = path.parseUrl(href);
							href = href.protocol + "//" + href.host + href.pathname + search + preservedHash;
						} else {
							href += href.indexOf("#") > -1 ? uiState : "#" + uiState;
						}

						return href;
					},

					/**
					* Check if the hash is preservable
					* @method isPreservableHash
					* @member ns.util.path
					* @param {string} hash
					* @return {boolean}
					*/
					isPreservableHash: function (hash) {
						return hash.replace("#", "").indexOf(this.uiStateKey) === 0;
					},

					/**
					* Escape weird characters in the hash if it is to be used as a selector
					* @method hashToSelector
					* @member ns.util.path
					* @param {string} hash
					* @return {string}
					* @static
					*/
					hashToSelector: function (hash) {
						var hasHash = (hash.substring(0, 1) === "#");
						if (hasHash) {
							hash = hash.substring(1);
						}
						return (hasHash ? "#" : "") + hash.replace(new RegExp('([!"#$%&\'()*+,./:;<=>?@[\\]^`{|}~])', 'g'), "\\$1");
					},

					/**
					* Check if the specified url refers to the first page in the main application document.
					* @method isFirstPageUrl
					* @member ns.util.path
					* @param {string} url
					* @param {Object} documentBase uri structure
					* @param {boolean} documentBaseDiffers
					* @param {Object} documentUrl uri structure
					* @return {boolean}
					* @static
					*/
					isFirstPageUrl: function (url, documentBase, documentBaseDiffers, documentUrl) {
						var urlStructure,
							samePath,
							firstPage,
							firstPageId,
							hash;

						documentBase = documentBase === undefined ? path.documentBase : documentBase;
						documentBaseDiffers = documentBaseDiffers === undefined ? path.documentBaseDiffers : documentBaseDiffers;
						documentUrl = documentUrl === undefined ? path.documentUrl : documentUrl;

						// We only deal with absolute paths.
						urlStructure = path.parseUrl(path.makeUrlAbsolute(url, documentBase));

						// Does the url have the same path as the document?
						samePath = urlStructure.hrefNoHash === documentUrl.hrefNoHash || (documentBaseDiffers && urlStructure.hrefNoHash === documentBase.hrefNoHash);

						// Get the first page element.
						firstPage = engine.getRouter().firstPage;

						// Get the id of the first page element if it has one.
						firstPageId = firstPage ? firstPage.id : undefined;
						hash = urlStructure.hash;

						// The url refers to the first page if the path matches the document and
						// it either has no hash value, or the hash is exactly equal to the id of the
						// first page element.
						return samePath && (!hash || hash === "#" || (firstPageId && hash.replace(/^#/, "") === firstPageId));
					},

					/**
					* Some embedded browsers, like the web view in Phone Gap, allow cross-domain XHR
					* requests if the document doing the request was loaded via the file:// protocol.
					* This is usually to allow the application to "phone home" and fetch app specific
					* data. We normally let the browser handle external/cross-domain urls, but if the
					* allowCrossDomainPages option is true, we will allow cross-domain http/https
					* requests to go through our page loading logic.
					* @method isPermittedCrossDomainRequest
					* @member ns.util.path
					* @param {Object} docUrl
					* @param {string} reqUrl
					* @return {boolean}
					* @static
					*/
					isPermittedCrossDomainRequest: function (docUrl, reqUrl) {
						return ns.getConfig('allowCrossDomainPages', false) &&
							docUrl.protocol === "file:" &&
							reqUrl.search(/^https?:/) !== -1;
					},

					/**
					* Convert a object data to URI parameters
					* @method getAsURIParameters
					* @member ns.util.path
					* @param {Object} data
					* @return {string}
					* @static
					*/
					getAsURIParameters: function (data) {
						var url = '',
							key;
						for (key in data) {
							if (data.hasOwnProperty(key)) {
								url += encodeURIComponent(key) + '=' + encodeURIComponent(data[key]) + '&';
							}
						}
						return url.substring(0, url.length - 1);
					},

					/**
					* Document Url
					* @member ns.util.path
					* @property {string|null} documentUrl
					*/
					documentUrl: null,

					/**
					* The document base differs
					* @member ns.util.path
					* @property {boolean} documentBaseDiffers
					*/
					documentBaseDiffers: false,

					/**
					* Set location hash to path
					* @method set
					* @member ns.util.path
					* @param {string} path
					* @static
					*/
					set: function (path) {
						location.hash = path;
					},

					/**
					* Return the substring of a file path before the sub-page key,
					* for making a server request
					* @method getFilePath
					* @member ns.util.path
					* @param {string} path
					* @param {string} dialogHashKey
					* @return {string}
					* @static
					*/
					getFilePath: function (path, dialogHashKey) {
						var splitkey = '&' + ns.getConfig('subPageUrlKey', '');
						return path && path.split(splitkey)[0].split(dialogHashKey)[0];
					},

					/**
					* Remove the preceding hash, any query params, and dialog notations
					* @method cleanHash
					* @member ns.util.path
					* @param {string} hash
					* @param {string} dialogHashKey
					* @return {string}
					* @static
					*/
					cleanHash: function (hash, dialogHashKey) {
						return path.stripHash(hash.replace(/\?.*$/, "").replace(dialogHashKey, ""));
					},

					/**
					* Check if url refers to the embedded page
					* @method isEmbeddedPage
					* @member ns.util.path
					* @param {string} url
					* @param {boolean} allowEmbeddedOnlyBaseDoc
					* @return {boolean}
					* @static
					*/
					isEmbeddedPage: function (url, allowEmbeddedOnlyBaseDoc) {
						var urlObject = path.parseUrl(url);

						//if the path is absolute, then we need to compare the url against
						//both the documentUrl and the documentBase. The main reason for this
						//is that links embedded within external documents will refer to the
						//application document, whereas links embedded within the application
						//document will be resolved against the document base.
						if (urlObject.protocol !== "") {
							return (urlObject.hash &&
									( allowEmbeddedOnlyBaseDoc ?
											urlObject.hrefNoHash === path.documentUrl.hrefNoHash :
											urlObject.hrefNoHash === path.parseLocation().hrefNoHash ));
						}
						return (/^#/).test(urlObject.href);
					}
				};

			path.documentUrl = path.parseLocation();

			base = document.querySelector('base');

			/**
			* The document base URL for the purposes of resolving relative URLs,
			* and the name of the default browsing context for the purposes of
			* following hyperlinks
			* @member ns.util.path
			* @property {Object} documentBase uri structure
			* @static
			*/
			path.documentBase = base ? path.parseUrl(path.makeUrlAbsolute(base.getAttribute("href"), path.documentUrl.href)) : path.documentUrl;

			path.documentBaseDiffers = (path.documentUrl.hrefNoHash !== path.documentBase.hrefNoHash);

			/**
			* Get document base
			* @method getDocumentBase
			* @member ns.util.path
			* @param {boolean} [asParsedObject=false]
			* @return {string|Object}
			* @static
			*/
			path.getDocumentBase = function (asParsedObject) {
				return asParsedObject ? utilsObject.copy(path.documentBase) : path.documentBase.href;
			};

			/**
			* Find the closest page and extract out its url
			* @method getClosestBaseUrl
			* @member ns.util.path
			* @param {HTMLElement} element
			* @param {string} selector
			* @return {string}
			* @static
			*/
			path.getClosestBaseUrl = function (element, selector) {
				// Find the closest page and extract out its url.
				var url = utilsDOM.getNSData(utilsSelectors.getClosestBySelector(element, selector), "url"),
					baseUrl = path.documentBase.hrefNoHash;

				if (!ns.getConfig('dynamicBaseEnabled', true) || !url || !path.isPath(url)) {
					url = baseUrl;
				}

				return path.makeUrlAbsolute(url, baseUrl);
			};

			ns.util.path = path;
			}(window, window.document, ns));

/*global window, define, ns */
/* 
 * Copyright (c) 2010 - 2014 Samsung Electronics Co., Ltd.
 * License : MIT License V2
 */
/**
 * #Router
 * Namespace for routers
 * @author Maciej Urbanski <m.urbanski@samsung.com>
 * @author Krzysztof Antoszek <k.antoszek@samsung.com>
 * @class ns.router
 */
(function (ns) {
	
				ns.router = ns.router || {};
			}(ns));

/*global define, ns */
/*
* Copyright  2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/**
 * #URL History Support For Router
 * Class manages history of changing pages in application.
 * @class ns.router.urlHistory
 * @singleton
 * @author Maciej Urbanski <m.urbanski@samsung.com>
 * @author Hyunkook Cho <hk0713.cho@samsung.com>
 * @author Junhyeon Lee <juneh.lee@samsung.com>
 */
(function (ns) {
	
				var urlHistory = {
				/**
				 * History stack
				 * @property {Array.<object>} stack
				 * @readonly
				 * @member ns.router.urlHistory
				 * @member ns.router.urlHistorydirect
				 */
				stack: [],
				/**
				 * Current active index in the history stack
				 * @property {number} [activeIndex=0]
				 * @readonly
				 * @member ns.router.urlHistory
				 */
				activeIndex: 0,
				/**
				 * Returns current active history element
				 * @return {object}
				 * @method getActive
				 * @member ns.router.urlHistory
				 */
				getActive: function () {
					return urlHistory.stack[urlHistory.activeIndex];
				},
				/**
				 * Returns previous history element
				 * @return {object}
				 * @method getPrev
				 * @member ns.router.urlHistory
				 */
				getPrev: function () {
					return urlHistory.stack[urlHistory.activeIndex - 1];
				},
				/**
				 * Returns next history element
				 * @return {object}
				 * @method getNext
				 * @member ns.router.urlHistory
				 */
				getNext: function () {
					return urlHistory.stack[urlHistory.activeIndex + 1];
				},
				/**
				 * Add new history element to stack
				 * @param {string} url
				 * @param {string} transition
				 * @param {string} title
				 * @param {string} pageUrl
				 * @param {string} role
				 * @method addNew
				 * @member ns.router.urlHistory
				 */
				addNew: function (url, transition, title, pageUrl, role) {
					//if there's forward history, wipe it
					if (urlHistory.getNext()) {
						urlHistory.clearForward();
					}

					urlHistory.stack.push({
						url : url,
						transition: transition,
						title: title,
						pageUrl: pageUrl,
						role: role
					});

					urlHistory.activeIndex = urlHistory.stack.length - 1;
				},
				/**
				 * Wipe all history elements ahead of active element
				 * @method clearForward
				 * @member ns.router.urlHistory
				 */
				clearForward: function () {
					urlHistory.stack = urlHistory.stack.slice(0, urlHistory.activeIndex + 1);
				},
				/**
				 * Changes hash in history.
				 * @param {Object} options
				 * @method directHashChange
				 * @member ns.router.urlHistory
				 */
				directHashChange: function (options) {
					var back,
						forward,
						newActiveIndex;

					// check if url is in history and if it's ahead or behind current page
					urlHistory.stack.forEach(function (historyEntry, index) {
						//if the url is in the stack, it's a forward or a back
						if (decodeURIComponent(options.currentUrl) === decodeURIComponent(historyEntry.url)) {
							//define back and forward by whether url is older or newer than current page
							back = index < urlHistory.activeIndex;
							forward = !back;
							newActiveIndex = index;
						}
					});

					// save new page index, null check to prevent false or 0 result
					this.activeIndex = newActiveIndex || this.activeIndex;

					if (back) {
						(options.either || options.isBack)(true);
					} else if (forward) {
						(options.either || options.isForward)(false);
					}
				},
				//disable hashchange event listener internally to ignore one change
				//toggled internally when location.hash is updated to match the url of a successful page load
				ignoreNextHashChange: false
			};

			ns.router.urlHistory = urlHistory;

			}(ns));

/*global window, define, HTMLElement */
/*jslint plusplus: true, nomen: true */
/*
 * Copyright (c) 2010 - 2014 Samsung Electronics Co., Ltd.
 * License : MIT License V2
 */
/**
 * #jQuery Mobile mapping router
 * Object maps router from TAU namespace to jQuery Mobile namespace.
 * @class ns.jqm.router
 */
(function (window, document, ns, $) {
	
	
			var engine = ns.engine;
			ns.jqm.router = {
				/**
				 * Enables support jQM before router init.
				 * @method beforeinit
				 * @member ns.jqm.router
				 */
				beforeinit: function () {
					var container,
						router = engine.getRouter();
					if ($) {
						if ($.mobile) {
							if ($.mobile.pageContainer) {
								container = $.mobile.pageContainer;
								if (container instanceof $) {
									container = container[0];
								}
								if (!container instanceof HTMLElement) {
									container = document.body;
								}
								ns.setConfig('container', container);
								$.mobile.pageContainer = $(container);
								router.setContainer(container);
							}
							if ($.mobile.autoInitializePage !== undefined) {
								ns.setConfig('autoInitializePage', $.mobile.autoInitializePage);
							}
							if ($.mobile._bindPageRemove !== undefined) {
								ns.setConfig('_bindPageRemove', $.mobile._bindPageRemove);
							}
							$.mobile.changePage = function (toPage, options) {
								var htmlElementToPage;
								if (toPage instanceof $) {
									htmlElementToPage = $(toPage).get(0);
									return router.open(htmlElementToPage, options);
								}
								return router.open(toPage, options);
							};
							document.addEventListener('pageshow', function (ev) {
								$.mobile.activePage = $(ev.target);
							}, true);
							$.mobile.activePage = $();
							$.mobile.firstPage = $(router.getFirstPage());
							$.mobile.pageContainer = $(router.getContainer());
							$.mobile.subPageUrlKey = ns.widget.mobile.Page.classes.uiPage;
							$.mobile.ajaxEnabled = true;
							$.mobile.hashListeningEnabled = true;
							$.mobile.linkBindingEnabled = true;
							$.mobile.maxTransitionWidth = false;
							$.mobile.minScrollBack = 250;
							$.mobile.touchOverflowEnabled = false;
							$.mobile.defaultDialogTransition = 'pop';
							$.mobile.pageLoadErrorMessage = "Error Loading Page";
							$.mobile.pageLoadErrorMessageTheme = 'e';
							$.mobile.phonegapNavigationEnabled = false;
							$.mobile.autoInitializePage = false;
							$.mobile.pushStateEnabled = true;
							$.mobile.ignoreContentEnabled = false;
							$.mobile.orientationChangeEnabled = true;
							$.mobile.ajaxBlacklist = false;
							$.mobile.defaultTransitionHandler = null;
							$.mobile.transitionHandlers = {};
							$.mobile.transitionFallbacks = {};
							$.mobile._maybeDegradeTransition = null;
							$.mobile.focusPage = null;
							$.mobile.urlHistory = ns.router.urlHistory;
							$.mobile.dialogHashKey = "&ui-state=dialog";
							$.mobile.allowCrossDomainPages = false;
							$.mobile.getDocumentUrl = ns.util.path.getDocumentUrl;
							$.mobile.getDocumentBase = ns.util.path.getDocumentBase;
							$.mobile._bindPageRemove = null;
							$.mobile.loadPage = router.loadPage === undefined ? ns.error.bind(null, 'router PageExternal is not loaded') : router.loadPage.bind(router);
							$.mobile.navreadyDeferred = router.navreadyDeferred;
							$.mobile.initializePage = null;
							$.mobile._handleHashChange = router._hashChangeHandler;
						} else {
							$.mobile = {};
						}
					}
				},
				/**
				 * Enables support jQM after router init.
				 * @method init
				 * @member ns.jqm.router
				 */
				init: function () {
					var transitions,
						name,
						container,
						router = engine.getRouter();
					if ($) {
						$.mobile.defaultPageTransition = "none";

						if (router.getTransitions) {
							transitions = router.getTransitions();
							for (name in transitions) {
								if (transitions.hasOwnProperty(name)) {
									if (transitions[name].fallback !== undefined) {
										$.mobile.transitionFallbacks[name] = transitions[name].fallback;
									}
									if (transitions[name].handler !== undefined) {
										$.mobile.transitionHandlers[name] = transitions[name].handler;
									}
								}
							}
							$.mobile.defaultTransitionHandler = transitions.sequential.handler;
							$.mobile._maybeDegradeTransition = router._maybeDegradeTransition.bind(router);
							$.mobile.getMaxScrollForTransition = router.getMaxScrollForTransition.bind(router);
						}

						$.mobile.focusPage = function (toPage) {
							var page = $(toPage)[0],
								pageWidget = engine.getBinding(page);
							pageWidget.focus();
						};

						$.mobile._bindPageRemove = $.mobile._bindPageRemove || (router._bindPageRemove && router._bindPageRemove.bind(router));
						$.mobile.initializePage = router.init.bind(router);
						container = router.getContainer();
						$.mobile.pageContainer = $(container);
					}
				}
			};
			document.addEventListener("routerinit", function (evt) {
				ns.jqm.router.init();
			}, false);
			document.addEventListener("beforerouterinit", function (evt) {
				ns.jqm.router.beforeinit();
			}, false);
			}(window, window.document, ns, ns.jqm.jQuery));

/*global window, define */
/*jslint plusplus: true, nomen: true */
/* 
 * Copyright (c) 2010 - 2014 Samsung Electronics Co., Ltd.
 * License : MIT License V2
 */
/**
 * #jQuery Mobile mapping support
 * Object maps support object from TAU namespace to jQuery Mobile namespace.
 * @class ns.jqm.support
 */
(function (window, document, ns, $) {
	
				var support = ns.support,
				object = ns.util.object;

			ns.jqm.support = {
				/**
				 * Touch support flag
				 * @property {boolean} touch
				 * @member ns.jqm.support
				 */
				touch: document.ontouchend !== undefined,
				/**
				 * Enables support in jQM after TAU init
				 * @method init
				 * @member ns.jqm.support
				 */
				init: function () {
					var router = ns.engine.getRouter();
					if ($) {
						object.merge($.support, support);
						ns.support = $.support;
						$.mobile = $.mobile || {};
						$.mobile.support = $.mobile.support || {};
						$.mobile.support.touch = support.touch;
						$.mobile.base = support.dynamicBaseTag ? {
							element: router.resetBase === undefined ? ns.error.bind(null, 'router PageExternal is not loaded') : router.resetBase(),
							set: router.setBase === undefined ? ns.error.bind(null, 'router PageExternal is not loaded') : router.setBase.bind(router),
							reset: router.resetBase === undefined ? ns.error.bind(null, 'router PageExternal is not loaded') : router.resetBase.bind(router)
						} : undefined;
						$.mobile.gradeA = ns.support.gradeA.bind(ns.support);
						$.mobile.browser = ns.support.browser;
					}
				}
			};

			// Listen when framework is ready
			document.addEventListener(ns.engine.eventType.INIT, function () {
				ns.jqm.support.init();
			}, false);
			}(window, window.document, ns, ns.jqm.jQuery));

/*global window, define */
/* 
 * Copyright (c) 2010 - 2014 Samsung Electronics Co., Ltd.
 * License : MIT License V2
 */
/**
 * #Colors Utility
 * Class supports converting between color formats
 * @class ns.util.colors
 */

(function (window, document, ns) {
	
				ns.util.colors = {
				/**
				 * Round to the nearest Integer
				 * @method nearestInt
				 * @param {number} val
				 * @return {number}
				 * @member ns.util.colors
				 * @static
				 */
				nearestInt: function (val) {
					var theFloor = Math.floor(val);
					return (((val - theFloor) > 0.5) ? (theFloor + 1) : theFloor);
				},

				/**
				 * Converts html color string to rgb array.
				 * @method HTMLToRGB
				 * @param {string} clr_str is of the form "#aabbcc"
				 * @return {number[]} Returns: [ r, g, b ], where
				 * r is in [0, 1]
				 * g is in [0, 1]
				 * b is in [0, 1]
				 * @member ns.util.colors
				 * @static
				 */
				HTMLToRGB: function (clr_str) {
					clr_str = (('#' === clr_str.charAt(0)) ? clr_str.substring(1) : clr_str);
					return ([
						clr_str.substring(0, 2),
						clr_str.substring(2, 4),
						clr_str.substring(4, 6)
					].map(function (val) {
						return parseInt(val, 16) / 255.0;
					}));
				},

				/**
				 * Converts rgb array to html color string.
				 * @method RGBToHTML
				 * @param {number[]} rgb Input: [ r, g, b ], where 
				 * r is in [0, 1]
				 * g is in [0, 1]
				 * b is in [0, 1]
				 * @return {string} Returns string of the form "#aabbcc"
				 * @member ns.util.colors
				 * @static
				 */
				RGBToHTML: function (rgb) {
					return ("#" +
						rgb.map(function (val) {
							var ret = val * 255,
								theFloor = Math.floor(ret);
							ret = ((ret - theFloor > 0.5) ? (theFloor + 1) : theFloor);
							ret = (((ret < 16) ? "0" : "") + (ret & 0xff).toString(16));
							return ret;
						})
					.join(""));
				},

				/**
				 * Converts hsl to rgb.
				 * @method HSLToRGB
				 * @param {number[]} hsl Input: [ h, s, l ], where 
				 * h is in [0, 360]
				 * s is in [0,   1]
				 * l is in [0,   1]
				 * @return {number[]} Returns: [ r, g, b ], where
				 * r is in [0, 1]
				 * g is in [0, 1]
				 * b is in [0, 1]
				 * @member ns.util.colors
				 * @static
				 */
				HSLToRGB: function (hsl) {
					var h = hsl[0] / 360.0,
						s = hsl[1],
						l = hsl[2],
						temp1,
						temp2,
						temp3,
						ret;

					if (0 === s) {
						ret =  [ l, l, l ];
					} else {
						temp2 = ((l < 0.5) ? l * (1.0 + s) : l + s - l * s);
						temp1 = 2.0 * l - temp2;
						temp3 = {
							r: h + 1.0 / 3.0,
							g: h,
							b: h - 1.0 / 3.0
						};

						temp3.r = ((temp3.r < 0) ? (temp3.r + 1.0) : ((temp3.r > 1) ? (temp3.r - 1.0) : temp3.r));
						temp3.g = ((temp3.g < 0) ? (temp3.g + 1.0) : ((temp3.g > 1) ? (temp3.g - 1.0) : temp3.g));
						temp3.b = ((temp3.b < 0) ? (temp3.b + 1.0) : ((temp3.b > 1) ? (temp3.b - 1.0) : temp3.b));

						ret = [
							(((6.0 * temp3.r) < 1) ? (temp1 + (temp2 - temp1) * 6.0 * temp3.r) :
									(((2.0 * temp3.r) < 1) ? temp2 :
											(((3.0 * temp3.r) < 2) ? (temp1 + (temp2 - temp1) * ((2.0 / 3.0) - temp3.r) * 6.0) :
													temp1))),
							(((6.0 * temp3.g) < 1) ? (temp1 + (temp2 - temp1) * 6.0 * temp3.g) :
									(((2.0 * temp3.g) < 1) ? temp2 :
											(((3.0 * temp3.g) < 2) ? (temp1 + (temp2 - temp1) * ((2.0 / 3.0) - temp3.g) * 6.0) :
													temp1))),
							(((6.0 * temp3.b) < 1) ? (temp1 + (temp2 - temp1) * 6.0 * temp3.b) :
									(((2.0 * temp3.b) < 1) ? temp2 :
											(((3.0 * temp3.b) < 2) ? (temp1 + (temp2 - temp1) * ((2.0 / 3.0) - temp3.b) * 6.0) :
													temp1)))
						];
					}

					return ret;
				},

				/**
				 * Converts hsv to rgb.
				 * @method HSVToRGB
				 * @param {number[]} hsv Input: [ h, s, v ], where 
				 * h is in [0, 360]
				 * s is in [0,   1]
				 * v is in [0,   1]
				 * @return {number[]} Returns: [ r, g, b ], where
				 * r is in [0, 1]
				 * g is in [0, 1]
				 * b is in [0, 1]
				 * @member ns.util.colors
				 */
				HSVToRGB: function (hsv) {
					return this.HSLToRGB(this.HSVToHSL(hsv));
				},

				/**
				 * Converts rgb to hsv.
				 * @method HSVToRGB
				 * @param {number[]} rgb Input: [ r, g, b ], where 
				 * r is in [0,   1]
				 * g is in [0,   1]
				 * b is in [0,   1]
				 * @return {number[]} Returns: [ h, s, v ], where
				 * h is in [0, 360]
				 * s is in [0,   1]
				 * v is in [0,   1]
				 * @member ns.util.colors
				 * @static
				 */
				RGBToHSV: function (rgb) {
					var min, max, delta, h, s, v, r = rgb[0], g = rgb[1], b = rgb[2];

					min = Math.min(r, Math.min(g, b));
					max = Math.max(r, Math.max(g, b));
					delta = max - min;

					h = 0;
					s = 0;
					v = max;

					if (delta > 0.00001) {
						s = delta / max;

						if (r === max) {
							h = (g - b) / delta;
						} else {
							if (g === max) {
								h = 2 + (b - r) / delta;
							} else {
								h = 4 + (r - g) / delta;
							}
						}

						h *= 60;

						if (h < 0) {
							h += 360;
						}
					}

					return [h, s, v];
				},

				/**
				 * Converts Converts hsv to hsl.
				 * @method HSVToHSL
				 * @param {number[]} rgb Input: [ h, s, v ], where 
				 * h is in [0, 360]
				 * s is in [0,   1]
				 * v is in [0,   1]
				 * @return {number[]} Returns: [ h, s, l ], where
				 * h is in [0, 360]
				 * s is in [0,   1]
				 * l is in [0,   1]
				 * @member ns.util.colors
				 * @static
				 */
				HSVToHSL: function (hsv) {
					var max = hsv[2],
						delta = hsv[1] * max,
						min = max - delta,
						sum = max + min,
						half_sum = sum / 2,
						s_divisor = ((half_sum < 0.5) ? sum : (2 - max - min));

					return [ hsv[0], ((0 === s_divisor) ? 0 : (delta / s_divisor)), half_sum ];
				},

				/**
				 * Converts rgb to hsl
				 * @method RGBToHSL
				 * @param {number[]} rgb Input: [ r, g, b ], where 
				 * r is in [0,   1]
				 * g is in [0,   1]
				 * b is in [0,   1]
				 * @return {number[]} Returns: [ h, s, l ], where
				 * h is in [0, 360]
				 * s is in [0,   1]
				 * l is in [0,   1]
				 * @member ns.util.colors
				 */
				RGBToHSL: function (rgb) {
					return this.HSVToHSL(this.RGBToHSV(rgb));
				}
			};
			}(window, window.document, ns));

/*global window, define */
/*jslint plusplus: true, nomen: true */
/* 
 * Copyright (c) 2010 - 2014 Samsung Electronics Co., Ltd.
 * License : MIT License V2
 */
/**
 * #jQuery Mobile mapping colors
 * Object maps color support object from TAU namespace to
 * jQuery Mobile namespace.
 * @class ns.jqm.colors
 */
(function (window, document, ns, $) {
	
				ns.jqm.colors = {
				/**
				* Proxy colors library from ns namespace to jQM namespace
				* @method init
				* @member ns.jqm.colors
				* @static
				*/
				init: function () {
					if ($) {
						$.mobile.tizen.clrlib = ns.util.colors;
					}
				}
			};
			// Listen when framework is ready
			document.addEventListener(ns.engine.eventType.INIT, function () {
				ns.jqm.colors.init();
			}, false);

			}(window, window.document, ns, ns.jqm.jQuery));

/*global define */
/*
 * Copyright (c) 2010 - 2014 Samsung Electronics Co., Ltd.
 * License : MIT License V2
 */

/*global window, define, Math, ns*/
/*jslint bitwise: true */
/* 
 * Copyright (c) 2010 - 2014 Samsung Electronics Co., Ltd.
 * License : MIT License V2
 */
/**
 * #Theme object
 * Class with functions to set theme of application.
 * @class ns.theme
 */
(function (window, document, ns) {
	
			/**
			 * Local alias for document HEAD element
			 * @property {HTMLHeadElement} head
			 * @static
			 * @private
			 * @member ns.theme
			 */
			var head = document.head,
				documentElement = document.documentElement,
				frameworkData = ns.frameworkData,
				util = ns.util,
				DOM = util.DOM,
				load = util.load,
				support = ns.support,

				stopEvent = function (event) {
					var element = event.target,
						tag = element.tagName.toLowerCase(),
						type = element.type;
					if ((tag !== "input" ||
							(type !== "text" && type !== "email" && type !== "url" && type !== "search" && type !== "tel")) &&
							tag !== "textarea") {
						event.stopPropagation();
						event.preventDefault();
					}
				},

				THEME_JS_FILE_NAME = "theme.js",
				THEME_CSS_FILE_NAME = "tau",

				themeRegex =  /ui-(bar|body|overlay)-([a-z])\b/,
				deviceWidthRegex = /.*width=(device-width|\d+)\s*,?.*$/gi;

			ns.theme = {
				/**
				 * Standard theme
				 * @property {string} theme="s"
				 * @member ns.theme
				 */
				theme: "s",

				_activeTheme: null,

				/**
				 * This function inits theme.
				 * @method init
				 * @param {HTMLElement} container
				 * @member ns.theme
				 */
				init: function (container) {
					var self = this,
						containerClassList = container.classList;

					frameworkData.getParams();

					if (support.gradeA()) {
						documentElement.classList.add("ui-mobile");
						containerClassList.add("ui-mobile-viewport");
					}

					self.loadTheme(frameworkData.theme);
				},

				/**
				 * This function scales font size.
				 * @method scaleBaseFontSize
				 * @param {number} themeDefaultFontSize Default font size
				 * @param {number} ratio Scaling ration
				 * @member ns.theme
				 */
				scaleBaseFontSize : function (themeDefaultFontSize, ratio) {
					var scaledFontSize = Math.max(themeDefaultFontSize * ratio | 0, 4);
					documentElement.style.fontSize = scaledFontSize + "px";
					document.body.style.fontSize = scaledFontSize + "px";
				},

				/**
				 * This function searches theme, which is inherited
				 * from parents by element.
				 * @method getInheritedTheme
				 * @param {HTMLElement} element Element for which theme is looking for.
				 * @param {string} defaultTheme Default theme.
				 * It is used if no theme, which can be inherited, is found.
				 * @return {string} Inherited theme
				 * @member ns.theme
				 */
				getInheritedTheme: function (element, defaultTheme) {
					var theme,
						parentElement = element.parentNode,
						parentClasses,
						parentTheme;

					theme = DOM.getNSData(element, "theme");

					if (!theme) {
						while (parentElement) {
							parentClasses = parentElement.className || "";
							parentTheme = themeRegex.exec(parentClasses);
							if (parentClasses && parentTheme && parentTheme.length > 2) {
								theme = parentTheme[2];
								break;
							}
							parentElement = parentElement.parentNode;
						}
					}
					return theme || defaultTheme;
				},

				/**
				 * This function sets selection behavior for the element.
				 * @method enableSelection
				 * @param {HTMLElement} element Element for which selection behavior is set.
				 * @param {"text"|"auto"|"none"} value="auto" Selection behavior.
				 * @return {HTMLElement} Element with set styles.
				 * @member ns.theme
				 */
				enableSelection: function (element, value) {
					var val,
						elementStyle;

					switch (value) {
					case "text":
					case "auto":
					case "none":
						val = value;
						break;
					default:
						val = "auto";
						break;
					}

					if (element === document) {
						element = document.body;
					}

					elementStyle = element.style;
					elementStyle.MozUserSelect = elementStyle.webkitUserSelect = elementStyle.userSelect = val;

					return element;
				},

				/**
				 * This function disables event "contextmenu".
				 * @method disableContextMenu
				 * @param {HTMLElement} element Element for which event "contextmenu"
				 * is disabled.
				 * @member ns.theme
				 */
				disableContextMenu: function (element) {
					element.addEventListener("contextmenu", stopEvent, true);
				},

				/**
				 * This function enables event "contextmenu".
				 * @method enableContextMenu
				 * @param {HTMLElement} element Element for which event "contextmenu"
				 * is enabled.
				 * @member ns.theme
				 */
				enableContextMenu: function (element) {
					element.removeEventListener("contextmenu", stopEvent, true);
				},

				/**
				 * This function loads files with proper theme.
				 * @method loadTheme
				 * @param {string} theme Choosen theme.
				 * @member ns.theme
				 */
				loadTheme: function(theme) {
					var self = this,
						themePath = frameworkData.themePath,
						themeName = THEME_CSS_FILE_NAME,
						cssPath,
						isMinified = frameworkData.minified,
						jsPath;

					// If the theme has been loaded do not repeat that process
					if (frameworkData.themeLoaded) {
												return;
					}

					if (frameworkData.frameworkName !== "tau") {
						themeName = "tizen-web-ui-fw-theme";
					}
					if (isMinified) {
						cssPath = themePath + "/" + themeName + ".min.css";
					} else {
						cssPath = themePath + "/" + themeName + ".css";
					}

					
					load.themeCSS(cssPath, theme);
					jsPath = themePath + "/" + THEME_JS_FILE_NAME;
										load.scriptSync(jsPath);

					if (support.gradeA()) {
						self.setScaling();
					}

					frameworkData.themeLoaded = true;
				},

				/**
				 * This function sets viewport.
				 * If custom viewport is found, its width will be returned.
				 * Otherwise, the new viewport will be created.
				 * @method setViewport
				 * @param {number|string} viewportWidth Width of the new viewport.
				 * If no viewport is found, the new viewport with this
				 * width is created.
				 * @return {string} Width of custom viewport.
				 * @member ns.theme
				 */
				setViewport: function(viewportWidth) {
					var metaViewport = document.querySelector("meta[name=viewport]"),
						content;

					if (metaViewport) {
						// Found custom viewport!
						content = metaViewport.getAttribute("content");
						viewportWidth = content.replace(deviceWidthRegex, "$1");
					} else {
						// Create a meta tag
						metaViewport = document.createElement("meta");
						metaViewport.name = "viewport";
						content = "width=" + viewportWidth + ", user-scalable=no";
						metaViewport.content = content;
						head.insertBefore(metaViewport, head.firstChild);
					}
					return viewportWidth;
				},

				/**
				 * This function checks if application is run
				 * in the mobile browser.
				 * @method isMobileBrowser
				 * @return {boolean} Returns true, if application
				 * is run in mobile browser. Otherwise, false is returned.
				 * @member ns.theme
				 */
				isMobileBrowser: function() {
					return window.navigator.appVersion.indexOf("Mobile") > -1;
				},

				/**
				 * This function sets scaling of viewport.
				 * @method setScaling
				 * @member ns.theme
				 */
				setScaling: function () {
					var self = this,
						viewportWidth = frameworkData.viewportWidth,
						themeDefaultFontSize = frameworkData.defaultFontSize, // comes from theme.js
						ratio = 1;

					// Keep original font size
					document.body.setAttribute("data-tizen-theme-default-font-size", themeDefaultFontSize);

					if (ns.theme.isMobileBrowser()) {
						// Legacy support: tizen.frameworkData.viewportScale
						if (frameworkData.viewportScale === true) {
							viewportWidth = "screen-width";
						}

						// screen-width support
						if ("screen-width" === viewportWidth) {
							if (window.self === window.top) {
								// Top frame: for target. Use window.outerWidth.
								viewportWidth = window.outerWidth;
							} else {
								// iframe: for web simulator. Use clientWidth.
								viewportWidth = document.documentElement.clientWidth;
							}
						}

						// set viewport meta tag
						// If custom viewport setting exists, get viewport width
						viewportWidth = self.setViewport(viewportWidth);

						if (viewportWidth !== "device-width") {
							ratio = parseFloat(viewportWidth / ns.frameworkData.defaultViewportWidth);
							self.scaleBaseFontSize(themeDefaultFontSize, ratio);
						}
					}
				}
			};

			document.addEventListener("themeinit", function (evt) {
				var router = evt.detail;
				if (router && ns.getConfig("autoInitializePage", true)) {
					ns.theme.init(router.getContainer());
				}
			}, false);

			}(window, window.document, ns));

/*global define, ns */
			var utilsObject = ns.util.object,
				nsTheme = ns.theme,
				ThemeCommon = function () {
					var self = this;
					self.enabled = false;
					self.backup = null;
				},
				protoThemeCommon = {};

			protoThemeCommon._enable = function () {
				var self = this;
				// disable it active theme
				if (nsTheme._activeTheme) {
					nsTheme._activeTheme.disable();
				}
				self.backup = {};
				self.backup.frameworkData = utilsObject.copy(ns.frameworkData);
				self.backup.widgetOptions = {};
				self.storeAllWidgetOptions();
				nsTheme._activeTheme = self;
				self.enabled = true;
			};

			protoThemeCommon._disable = function () {
				var self = this,
					prop,
					backupFrameworkData;
				self.restoreAllWidgetOptions();

				backupFrameworkData = self.backup.frameworkData;

				if (backupFrameworkData) {
					for(prop in backupFrameworkData) {
						if (backupFrameworkData.hasOwnProperty(prop)) {
							ns.frameworkData[prop] = backupFrameworkData[prop];
						}
					}

					self.backup.frameworkData = null;
				}
				nsTheme._activeTheme = null;
				self.enabled = false;
			};

			/**
			 * This function stores the options of widgets.
			 * It is used by scripts of a custom themes on its activation to remember
			 * the default options of widgets and be able to restore them later.
			 * @method storeAllWidgetOptions
			 * @member ns.theme.ThemeCommon
			 */
			protoThemeCommon.storeAllWidgetOptions = function () {
				var self = this,
					i,
					widgets = ns.engine.getDefinitions(),
					widgetClass;
				for (i in widgets) {
					if (widgets.hasOwnProperty(i)) {
						widgetClass = widgets[i].widgetClass;
						if (widgetClass) {
							self.backup.widgetOptions[i] = utilsObject.copy(widgetClass.prototype.options);
						}
					}
				}
			};

			/**
			 * This function restores the options of widgets.
			 * It is used by scripts of a custom themes on its deactivation
			 * to restore default options of widgets
			 * @method restoreAllWidgetOptions
			 * @member ns.theme.ThemeCommon
			 */
			protoThemeCommon.restoreAllWidgetOptions = function () {
				var self = this,
					i,
					widgets = ns.engine.getDefinitions(),
					backup = self.backup.widgetOptions;
				for (i in backup) {
					if (backup.hasOwnProperty(i)) {
						widgets[i].widgetClass.prototype.options = utilsObject.copy(backup[i]);
					}
				}
			};
			ThemeCommon.prototype = protoThemeCommon;
			nsTheme.ThemeCommon = ThemeCommon;
			
/*global window, define */
/* 
 * Copyright (c) 2010 - 2014 Samsung Electronics Co., Ltd.
 * License : MIT License V2
 */
/**
 * #Grid Utility
 * Object helps creating grids.
 * @class ns.util.grid
 */
(function (ns) {
	
				/**
			 * Local alias for ns.util.selectors
			 * @property {Object} selectors Alias for {@link ns.util.selectors}
			 * @member ns.util.grid
			 * @static
			 * @private
			 */
			var selectors = ns.util.selectors,
				/**
				 * Alias to Array.slice method
				 * @method slice
				 * @member ns.util.grid
				 * @private
				 * @static
				 */
				slice = [].slice,
				/**
				 * grid types
				 * @property {Array} gridTypes
				 * @member ns.util.grid
				 * @static
				 * @private
				*/
				gridTypes = [
					null,
					"solo", //1
					"a",	//2
					"b",	//3
					"c",	//4
					"d"	//5
				];

			/**
			 * Add classes on the matched elements
			 * @method setClassOnMatches
			 * @param {HTMLElementCollection} elements
			 * @param {string} selector
			 * @param {string} className
			 * @private
			 * @member ns.util.grid
			 * @static
			 */
			function setClassOnMatches(elements, selector, className) {
				elements.forEach(function (item) {
					if (selectors.matchesSelector(item, selector)) {
						item.classList.add(className);
					}
				});
			}
			ns.util.grid = {
				/**
				* make css grid
				* @method makeGrid
				* @param {HTMLElement} element
				* @param {?string} [gridType="a"]
				* @static
				* @member ns.util.grid
				*/
				makeGrid: function (element, gridType) {
					var gridClassList = element.classList,
						kids = slice.call(element.children),
						iterator;
					if (!gridType) {
						gridType = gridTypes[kids.length];
						if (!gridType) {
							//if gridType is not defined in gritTypes
							//make it grid type "a""
							gridType = "a";
							iterator = 2;
							gridClassList.add("ui-grid-duo");
						}
					}
					if (!iterator) {
						//jquery grid doesn't care if someone gives non-existing gridType
						iterator = gridTypes.indexOf(gridType);
					}

					gridClassList.add("ui-grid-" + gridType);

					setClassOnMatches(kids, ":nth-child(" + iterator + "n+1)", "ui-block-a");

					if (iterator > 1) {
						setClassOnMatches(kids, ":nth-child(" + iterator + "n+2)", "ui-block-b");
					}
					if (iterator > 2) {
						setClassOnMatches(kids, ":nth-child(" + iterator + "n+3)", "ui-block-c");
					}
					if (iterator > 3) {
						setClassOnMatches(kids, ":nth-child(" + iterator + "n+4)", "ui-block-d");
					}
					if (iterator > 4) {
						setClassOnMatches(kids, ":nth-child(" + iterator + "n+5)", "ui-block-e");
					}
				}
			};
			}(ns));

/*global window, define, Object, Element */
/* 
 * Copyright (c) 2010 - 2014 Samsung Electronics Co., Ltd.
 * License : MIT License V2
 */
/**
 * #Data Attributes Utility
 * Object menages data attributes
 * @class ns.util.data
 */
(function (window, document, ns) {
	
				var hashMap = {},
				eventUtils = ns.event,
				objectUtils = ns.util.object,
				body = document.body,
				/**
				 * Return hash for object
				 * @method fetchDom
				 * @param {HTMLElement} element
				 * @param {string} key
				 * @return {?Object}
				 * @member ns.util.data
				 * @static
				 * @private
				 */
				fetchDom = function (element, key) {
					var dataKey = 'data-' + key,
						data,
						result;
					if (element.hasAttribute(dataKey)) {
						data = element.getAttribute(dataKey);
						try {
							result = JSON.parse(data);
						} catch (ignore) {}
					}
					return result;
				},
				/**
				 * Remove attribute from element
				 * @method removeDom
				 * @param {HTMLElement} element
				 * @param {string} key
				 * @member ns.util.data
				 * @static
				 * @private
				 */
				removeDom = function (element, key) {
					var dataKey = 'data-' + key;
					if (element.hasAttribute(dataKey)) {
						element.removeAttribute(dataKey);
					}
				},
				/**
				 * Return hash for object
				 * @method hashObject
				 * @param {*} value
				 * @return {string}
				 * @member ns.util.data
				 * @static
				 * @private
				 */
				hashObject = function (value) {
					if (value === undefined ||
							value === null ||
							value === false) {
						throw "Hashed object/primitive can not be undefined, null or false";
					}

					if (value instanceof Element && value.hasAttribute("data-ns-hash")) {
						return value.getAttribute("data-ns-hash");
					}

					if (value instanceof Object) {
						value.__tau_hash = value.__tau_hash || ns.getUniqueId();
					}
					var h = (typeof value) + "-" + (value instanceof Object ?
								value.__tau_hash : value.toString());

					if (value instanceof Element) {
						value.setAttribute("data-ns-hash", h);
					}
					return h;
				};

			ns.util.data = {
				/**
				 * Set value for element
				 * @method set
				 * @param {HTMLElement} element
				 * @param {string} key
				 * @param {*} value
				 * @return {*}
				 * @member ns.util.data
				 * @static
				 */
				set: function (element, key, value) {
					var hash = hashObject(element);
					if (!hash) {
						return false;
					}

					if (!hashMap[hash]) {
						hashMap[hash] = {};
					}

					hashMap[hash][key] = value;

					if (element instanceof Element) {
						eventUtils.trigger(element, "setData", {"key": key, "value": value});
					}
					eventUtils.trigger(body, "globalSetData", {"element": element, "key": key, "value": value});

					return value;
				},

				/**
				 * Get value for element
				 * @method get
				 * @param {HTMLElement} element
				 * @param {string} key
				 * @param {?*} defaultValue
				 * @return {Mixed}
				 * @member ns.util.data
				 * @static
				 */
				get: function (element, key, defaultValue) {
					var hash = hashObject(element),
						value;
					if (hash) {
						if (hashMap[hash] && hashMap[hash][key] !== undefined) {
							value = hashMap[hash][key];
						}

						if (element instanceof Element) {
							if (value === undefined) {
								value = fetchDom(element, key);
								// pass it to memory HashMap
								hashMap[hash] = hashMap[hash] || {};
								hashMap[hash][key] = hashMap[hash][key] || value;
							}
							eventUtils.trigger(element, "getData", {"key": key, "value": value});
						}
						eventUtils.trigger(body, "globalGetData", {"element": element, "key": key, "value": value});

						return value;
					}

					return defaultValue;
				},

				/**
				 * remove value for element
				 * @method remove
				 * @param {HTMLElement} element
				 * @param {string} key
				 * @return {boolean}
				 * @member ns.util.data
				 * @static
				 */
				remove: function (element, key) {
					var hash = hashObject(element),
						value;

					if (hash && hashMap[hash] && hashMap[hash][key] !== undefined) {
						value = hashMap[hash][key];

						// Delete keyword has a performance impact on the execution, that's why we assign undefined
						hashMap[hash][key] = undefined;

						// If any property is defined we cannot clear the hashMap[hash]
						if (objectUtils.hasPropertiesOfValue(hashMap[hash], undefined)) {
							hashMap[hash] = undefined;
						}

						if (element instanceof Element) {
							removeDom(element, key);
							eventUtils.trigger(element, "removeData", {"key": key, "value": value});
						}
						eventUtils.trigger(body, "globalRemoveData", {"element": element, "key": key, "value": value});

						return true;
					}
					return false;
				}
			};
			}(window, window.document, ns));

/*global window, define, ns */
/* 
 * Copyright (c) 2010 - 2014 Samsung Electronics Co., Ltd.
 * License : MIT License V2
 */
/**
 * #Date Utility
 * Object supports work with date and time
 * @author Krzysztof Antoszek <k.antoszek@samsung.com>
 * @class ns.util.date
 */
(function (ns) {
	
				var timeRegex = /([\-0-9.]*)(ms|s)?/i,
				date = {
					/**
					 * Convert string time length to miliseconds
					 * Note: this was implemented only for animation package
					 * and the string input should be conforming to css <time>
					 * unit definition (ref: https://developer.mozilla.org/en-US/docs/Web/CSS/time)
					 * If a different format or more functionality needs to be implemented, please
					 * change this function and usage cases in animation pacakge accordingly
					 * @method convertToMiliseconds
					 * @param {string} string
					 * @return {number}
					 * @static
					 * @member ns.util.date
					 */
					convertToMiliseconds: function (string) {
						var parsed = string.match(timeRegex),
							miliseconds = 0,
							parsedNumber = 0;
						if (parsed.length === 3) {
							parsedNumber = parseFloat(parsed[1]) || 0;
							switch (parsed[2]) {
							case "ms":
								miliseconds = parsedNumber;
								break;
							case "s":
								miliseconds = parsedNumber * 1000;
								break;
							}
						}
						return miliseconds;
					}
				};
			ns.util.date = date;
			}(ns));

/*global window, define */
/* 
 * Copyright (c) 2010 - 2014 Samsung Electronics Co., Ltd.
 * License : MIT License V2
 */
/**
 * #Callback Utility
 * Class creates a callback list
 *
 * Create a callback list using the following parameters:
 *  options: an optional list of space-separated options that will change how
 *			the callback list behaves or a more traditional option object
 *
 * By default a callback list will act like an event callback list and can be
 * "fired" multiple times.
 *
 * Possible options:
 *
 *	once:			will ensure the callback list can only be fired once (like a Deferred)
 *
 *	memory:			will keep track of previous values and will call any callback added
 *					after the list has been fired right away with the latest "memorized"
 *					values (like a Deferred)
 *
 *	unique:			will ensure a callback can only be added once (no duplicate in the list)
 *
 *	stopOnFalse:	interrupt callings when a callback returns false
 * @class ns.util.callbacks
 */
(function (window, document, ns) {
	
				ns.util.callbacks = function (orgOptions) {

				var object = ns.util.object,
					options = object.copy(orgOptions),
					/**
					 * Alias to Array.slice function
					 * @method slice
					 * @member ns.util.callbacks
					 * @private
					 */
					slice = [].slice,
					/**
					 * Last fire value (for non-forgettable lists)
					 * @property {Object} memory
					 * @member ns.util.callbacks
					 * @private
					 */
					memory,
					/**
					 * Flag to know if list was already fired
					 * @property {boolean} fired
					 * @member ns.util.callbacks
					 * @private
					 */
					fired,
					/**
					 * Flag to know if list is currently firing
					 * @property {boolean} firing
					 * @member ns.util.callbacks
					 * @private
					 */
					firing,
					/**
					 * First callback to fire (used internally by add and fireWith)
					 * @property {number} [firingStart=0]
					 * @member ns.util.callbacks
					 * @private
					 */
					firingStart,
					/**
					 * End of the loop when firing
					 * @property {number} firingLength
					 * @member ns.util.callbacks
					 * @private
					 */
					firingLength,
					/**
					 * Index of currently firing callback (modified by remove if needed)
					 * @property {number} firingIndex
					 * @member ns.util.callbacks
					 * @private
					 */
					firingIndex,
					/**
					 * Actual callback list
					 * @property {Array} list
					 * @member ns.util.callbacks
					 * @private
					 */
					list = [],
					/**
					 * Stack of fire calls for repeatable lists
					 * @property {Array} stack
					 * @member ns.util.callbacks
					 * @private
					 */
					stack = !options.once && [],
					fire,
					add,
					self = {
						/**
						 * Add a callback or a collection of callbacks to the list
						 * @method add
						 * @param {..Function} list
						 * @return {ns.util.callbacks} self
						 * @chainable
						 * @member ns.util.callbacks
						 */
						add: function () {
							if (list) {
								// First, we save the current length
								var start = list.length;
								add(arguments);
								// Do we need to add the callbacks to the
								// current firing batch?
								if (firing) {
									firingLength = list.length;
								// With memory, if we're not firing then
								// we should call right away
								} else if (memory) {
									firingStart = start;
									fire(memory);
								}
							}
							return this;
						},
						/**
						 * Remove a callback from the list
						 * @method remove
						 * @param {..Function} list
						 * @return {ns.util.callbacks} self
						 * @chainable
						 * @member ns.util.callbacks
						 */
						remove: function () {
							if (list) {
								slice.call(arguments).forEach(function (arg) {
									var index = list.indexOf(arg);
									while (index > -1) {
										list.splice(index, 1);
										// Handle firing indexes
										if (firing) {
											if (index <= firingLength) {
												firingLength--;
											}
											if (index <= firingIndex) {
												firingIndex--;
											}
										}
										index = list.indexOf(arg, index);
									}
								});
							}
							return this;
						},
						/**
						 * Check if a given callback is in the list. 
						 * If no argument is given,
						 * return whether or not list has callbacks attached.
						 * @method has
						 * @param {Funciton} fn
						 * @return {boolean}
						 * @member ns.util.callbacks
						 */
						has: function (fn) {
							return fn ? !!list && list.indexOf(fn) > -1 : !!(list && list.length);
						},
						/**
						 * Remove all callbacks from the list
						 * @method empty
						 * @return {ns.util.callbacks} self
						 * @chainable
						 * @member ns.util.callbacks
						 */
						empty: function () {
							list = [];
							firingLength = 0;
							return this;
						},
						/**
						 * Have the list do nothing anymore
						 * @method disable
						 * @return {ns.util.callbacks} self
						 * @chainable
						 * @member ns.util.callbacks
						 */
						disable: function () {
							list = stack = memory = undefined;
							return this;
						},
						/**
						 * Is it disabled?
						 * @method disabled
						 * @return {boolean}
						 * @member ns.util.callbacks
						 */
						disabled: function () {
							return !list;
						},
						/**
						 * Lock the list in its current state
						 * @method lock
						 * @return {ns.util.callbacks} self
						 * @chainable
						 * @member ns.util.callbacks
						 */
						lock: function () {
							stack = undefined;
							if (!memory) {
								self.disable();
							}
							return this;
						},
						/**
						 * Is it locked?
						 * @method locked
						 * @return {boolean} stack
						 * @member ns.util.callbacks
						 */
						locked: function () {
							return !stack;
						},
						/**
						 * Call all callbacks with the given context and
						 * arguments
						 * @method fireWith
						 * @param {Object} context
						 * @param {Array} args
						 * @return {ns.util.callbacks} self
						 * @chainable
						 * @member ns.util.callbacks
						 */
						fireWith: function (context, args) {
							if (list && (!fired || stack)) {
								args = args || [];
								args = [context, args.slice ? args.slice() : args];
								if (firing) {
									stack.push(args);
								} else {
									fire(args);
								}
							}
							return this;
						},
						/**
						 * Call all the callbacks with the given arguments
						 * @method fire
						 * @param {...*} argument
						 * @return {ns.util.callbacks} self
						 * @chainable
						 * @member ns.util.callbacks
						 */
						fire: function () {
							self.fireWith(this, arguments);
							return this;
						},
						/**
						 * To know if the callbacks have already been called at
						 * least once
						 * @method fired
						 * @return {booblean}
						 * @chainable
						 * @member ns.util.callbacks
						 */
						fired: function () {
							return !!fired;
						}
					};
				/**
				 * Adds functions to the callback list
				 * @method add
				 * @param {...*} argument
				 * @member ns.util.bezierCurve
				 * @private
				 */
				add = function (args) {
					slice.call(args).forEach(function (arg) {
						var type = typeof arg;
						if (type === "function") {
							if (!options.unique || !self.has(arg)) {
								list.push(arg);
							}
						} else if (arg && arg.length && type !== "string") {
							// Inspect recursively
							add(arg);
						}
					});
				};
				/**
				 * Fire callbacks
				 * @method fire
				 * @param {Array} data
				 * @member ns.util.bezierCurve
				 * @private
				 */
				fire = function (data) {
					memory = options.memory && data;
					fired = true;
					firingIndex = firingStart || 0;
					firingStart = 0;
					firingLength = list.length;
					firing = true;
					while (list && firingIndex < firingLength) {
						if (list[firingIndex].apply(data[0], data[1]) === false && options.stopOnFalse) {
							memory = false; // To prevent further calls using add
							break;
						}
						firingIndex++;
					}
					firing = false;
					if (list) {
						if (stack) {
							if (stack.length) {
								fire(stack.shift());
							}
						} else if (memory) {
							list = [];
						} else {
							self.disable();
						}
					}
				};

				return self;
			};

			}(window, window.document, ns));

/*global window, define, RegExp */
/* 
 * Copyright (c) 2010 - 2014 Samsung Electronics Co., Ltd.
 * License : MIT License V2
 */
/**
 * #Deferred Utility
 * Class creates object which can call registered callback depend from
 * state of object..
 * @class ns.util.deferred
 * @author Tomasz Lukawski <t.lukawski@samsung.com>
 * @author Maciej Urbanski <m.urbanski@samsung.com>
 * @author Piotr Karny <p.karny@samsung.com>
 */(function (window, document, ns) {
	
	
			var Deferred = function (callback) {
				var callbacks = ns.util.callbacks,
					object = ns.util.object,
					/**
					 * Register additional action for deferred object
					 * @property {Array} tuples
					 * @member ns.util.deferred
					 * @private
					 */
					tuples = [
						// action, add listener, listener list, final state
						["resolve", "done", callbacks({once: true, memory: true}), "resolved"],
						["reject", "fail", callbacks({once: true, memory: true}), "rejected"],
						["notify", "progress", callbacks({memory: true})]
					],
					state = "pending",
					deferred = {},
					promise = {
						/**
						 * Determine the current state of a Deferred object.
						 * @method state
						 * @return {"pending" | "resolved" | "rejected"} representing the current state
						 * @member ns.util.deferred
						 */
						state: function () {
							return state;
						},
						/**
						 * Add handlers to be called when the Deferred object
						 * is either resolved or rejected.
						 * @method always
						 * @param {...Function}
						 * @return {ns.util.deferred} self
						 * @member ns.util.deferred
						 */
						always: function () {
							deferred.done(arguments).fail(arguments);
							return this;
						},
						/**
						 * Add handlers to be called when the Deferred object
						 * is resolved, rejected, or still in progress.
						 * @method then
						 * @param {?Function} callback assign when done
						 * @param {?Function} callback assign when fail
						 * @param {?Function} callback assign when progress
						 * @return {Object} returns a new promise
						 * @member ns.util.deferred
						 */
						then: function () {/* fnDone, fnFail, fnProgress */
							var functions = arguments;
							return new Deferred(function (newDefer) {
								tuples.forEach(function (tuple, i) {
									var fn = (typeof functions[i] === 'function') && functions[i];
									// deferred[ done | fail | progress ] for forwarding actions to newDefer
									deferred[tuple[1]](function () {
										var returned = fn && fn.apply(this, arguments);
										if (returned && (typeof returned.promise === 'function')) {
											returned.promise()
												.done(newDefer.resolve)
												.fail(newDefer.reject)
												.progress(newDefer.notify);
										} else {
											newDefer[tuple[0] + "With"](this === promise ? newDefer.promise() : this, fn ? [returned] : arguments);
										}
									});
								});
								functions = null;
							}).promise();
						},
						/**
						 * Get a promise for this deferred. If obj is provided,
						 * the promise aspect is added to the object
						 * @method promise
						 * @param {Object} obj
						 * @return {Object} return a Promise object
						 * @member ns.util.deferred
						 */
						promise: function (obj) {
							if (obj) {
								return object.merge(obj, promise);
							}
							return promise;
						}
					};

				/**
				 * alias for promise.then, Keep pipe for back-compat
				 * @method pipe
				 * @member ns.util.deferred
				 */
				promise.pipe = promise.then;

				// Add list-specific methods

				tuples.forEach(function (tuple, i) {
					var list = tuple[2],
						stateString = tuple[3];

					// promise[ done | fail | progress ] = list.add
					promise[tuple[1]] = list.add;

					// Handle state
					if (stateString) {
						list.add(function () {
							// state = [ resolved | rejected ]
							state = stateString;

						// [ reject_list | resolve_list ].disable; progress_list.lock
						}, tuples[i ^ 1][2].disable, tuples[2][2].lock);
					}

					// deferred[ resolve | reject | notify ]
					deferred[tuple[0]] = function () {
						deferred[tuple[0] + "With"](this === deferred ? promise : this, arguments);
						return this;
					};
					deferred[tuple[0] + "With"] = list.fireWith;
				});

				// Make the deferred a promise
				promise.promise(deferred);

				// Call given func if any
				if (callback) {
					callback.call(deferred, deferred);
				}

				// All done!
				return deferred;
			};
			ns.util.deferred = Deferred;
			}(window, window.document, ns));

/*global window, define */
/* 
 * Copyright (c) 2010 - 2014 Samsung Electronics Co., Ltd.
 * License : MIT License V2
 */
/**
 * #Deferred When Utility
 * Class groups many deferred object to one.
 * @class ns.util.deferredWhen
 */
(function (window, document, ns) {
	
				var when = function( subordinate /* , ..., subordinateN */ ) {
				var i = 0,
					resolveValues = [].slice.call( arguments ),
					length = resolveValues.length,

					/**
					 * The count of uncompleted subordinates
					 * @property {number} remaining
					 * @member ns.util.deferredWhen
					 * @private
					 */
					remaining = length !== 1 || (subordinate && (typeof subordinate.promise === "function")) ? length : 0,

					/**
					 * The master Deferred. If resolveValues consist of only
					 * a single Deferred, just use that.
					 * @property {ns.util.deferred} deferred
					 * @member ns.util.deferredWhen
					 * @private
					 */
					deferred = remaining === 1 ? subordinate : new ns.util.deferred(),

					/**
					 * Update function for both resolve and progress values
					 * @method updateFunc
					 * @param {number} i
					 * @param {Array} contexts
					 * @param {Array} values
					 * @return {Function} representing the current state
					 * "pending" | "resolved" | "rejected"
					 * @member ns.util.deferredWhen
					 * @private
					 */
					updateFunc = function( i, contexts, values ) {
						return function( value ) {
							contexts[ i ] = this;
							values[ i ] = arguments.length > 1 ? [].slice.call( arguments ) : value;
							if ( values === progressValues ) {
								deferred.notifyWith( contexts, values );

							} else if ( !(--remaining) ) {
								deferred.resolveWith( contexts, values );
							}
						};
					},

					progressValues,
					progressContexts,
					resolveContexts;

				// add listeners to Deferred subordinates; treat others as resolved
				if (length > 1) {
					progressValues = [];
					progressValues.length =  length;
					progressContexts = [];
					progressContexts.length = length;
					resolveContexts = [];
					resolveContexts.length = length;
					for ( ; i < length; i++ ) {
						if (resolveValues[i] && (typeof resolveValues[i].promise === "function")) {
							resolveValues[i].promise()
								.done(updateFunc(i, resolveContexts, resolveValues))
								.fail(deferred.reject)
								.progress(updateFunc(i, progressContexts, progressValues));
						} else {
							--remaining;
						}
					}
				}

				// if we're not waiting on anything, resolve the master
				if (!remaining) {
					deferred.resolveWith(resolveContexts, resolveValues);
				}

				return deferred.promise();
			};

			ns.util.deferredWhen = when;

			}(window, window.document, ns));

/*global window: false, define: false, Math: false */
/* 
 * Copyright (c) 2010 - 2014 Samsung Electronics Co., Ltd.
 * License : MIT License V2
 */
/**
 * #Bezier Curves Utility
 * Class supports calculating Bezier Curves.
 * @class ns.util.bezierCurve
 */
(function (ns) {
	
			/**
		 * Store constant value for half PI
		 * @property {number} HALF_PI
		 * @member ns.util.bezierCurve
		 * @private
		 * @static
		 */
		var HALF_PI = Math.PI / 2,
			/**
			 * Store constant value for DEFAULT_STEP
			 * @property {number} DEFAULT_STEP
			 * @member ns.util.bezierCurve
			 * @private
			 * @static
			 */
			DEFAULT_STEP = 0.001,
			BezierCurve,
			/**
			 * Calculates the arc length
			 * @method arcLength3d
			 * @param {Array} p0
			 * @param {Array} p1
			 * @return {number}
			 * @member ns.util.bezierCurve
			 * @private
			 * @static
			 */
			arcLength3d = function (p0, p1) {
				var d = [ p1[0] - p0[0], p1[1] - p0[1], p1[2] - p0[2] ];
				return Math.sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]);
			};
		BezierCurve = function () {
			return this;
		};
		BezierCurve.prototype = {
			points: [],
			step: DEFAULT_STEP,
			length: 0,
			levels: [],
			/**
			 * Init BezierCurve
			 * @method init
			 * @param {Object} data
			 * @return {ns.util.BezierCurve} self
			 * @chainable
			 * @member ns.util.bezierCurve
			 */
			init: function (data) {
				this.points = data.points;
				this.step = data.step || DEFAULT_STEP;
				this.length = this.calculateTotalLength();
				this.levels = this.calculateLevel(data.maxLevel) || [];
				return this;
			},
			/**
			 * Calculate levels
			 * @method calculateLevel
			 * @param {?number} [maxLevel=null]
			 * @return {?Array} levels
			 * @member ns.util.bezierCurve
			 */
			calculateLevel: function (maxLevel) {
				var totalLength = this.length,
					interval = totalLength / maxLevel,
					levels = [],
					i;

				if (!maxLevel) {
					return null;
				}

				for (i = 0; i < maxLevel; i += 1) {
					levels[maxLevel - i] = this.getPercent(0, interval * i);
				}

				return levels;
			},
			/**
			 * Calculate total length
			 * @method calculateTotalLength
			 * @return {number}
			 * @member ns.util.bezierCurve
			 */
			calculateTotalLength: function () {
				var step = this.step,
					current = this.getPosition(0),
					last = current,
					length = 0,
					percent;
				for (percent = step; percent <= 1; percent += step) {
					current = this.getPosition(percent);
					length += arcLength3d(last, current);
					last = current;
				}
				return length;
			},
			/**
			 * Get position
			 * @method getPosition
			 * @param {number} percent
			 * @return {Array}
			 * @member ns.util.bezierCurve
			 */
			getPosition: function (percent) {
				var points = this.points,
					getValue = function (p1, c1, c2, p2, t) {
						return Math.pow(1 - t, 3) * p1 +
							3 * t * Math.pow(1 - t, 2) * c1 +
							3 * Math.pow(t, 2) * (1 - t) * c2 +
							Math.pow(t, 3) * p2;
					},
					result = [
						getValue(points[0][0], points[1][0], points[2][0], points[3][0], percent),
						getValue(points[0][2], points[1][2], points[2][2], points[3][2], percent)
					];
				return [ result[0], 0, result[1] ];
			},
			/**
			 * Get percent
			 * @method getPercent
			 * @param {number} [start=0]
			 * @param {?number} interval
			 * @return {number}
			 * @member ns.util.bezierCurve
			 */
			getPercent: function (start, interval) {
				var step = this.step,
					current,
					last,
					targetLength,
					length = 0,
					percent;
				start = start || 0;
				current = this.getPosition(start);
				last = current;
				targetLength = start + interval;
				for (percent = start + step; percent <= 1; percent += step) {
					current = this.getPosition(percent);
					length += arcLength3d(last, current);
					if (length >= targetLength) {
						return percent;
					}
					last = current;
				}
				return 1;
			},
			/**
			 * Get angle
			 * @method getAngle
			 * @param {number} percent
			 * @return {number}
			 * @member ns.util.bezierCurve
			 */
			getAngle: function (percent) {
				var points = this.points,
					getTangent = function (p1, c1, c2, p2, t) {
						return 3 * t * t * (-p1 + 3 * c1 - 3 * c2 + p2) + 6 * t * (p1 - 2 * c1 + c2) + 3 * (-p1 + c1);
					},
					tx = getTangent(points[0][0], points[1][0], points[2][0], points[3][0], percent),
					ty = getTangent(points[0][2], points[1][2], points[2][2], points[3][2], percent);
				return Math.atan2(tx, ty) - HALF_PI;
			}
		};
		ns.util.bezierCurve =  new BezierCurve();

		}(ns));

/*global window, define, ns */
/* Copyright (c) 2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/**
 * #Animation namespace
 * Namespace for animation utilities
 * @author Krzysztof Antoszek <k.antoszek@samsung.com
 * @class ns.util.anim
 */
(function (ns) {
	
				ns.util.anim = ns.util.anim || {};
			}(ns));

/*global window, define, ns */
/*jslint nomen: true, plusplus: true */
/* Copyright (c) 2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/**
 * # Keyframes
 *
 * Keyframes class for easy keyframe css syntax creation and
 * managing. Each frame is specified as an element of an array 
 * with size 100.
 *
 * @example
 
 *		<div id="test"
 *				style="width: 10px; height: 10px; background: red;"></div>
 *
 *		<script>
 *		var frames = [{ "background-color": "red" }],
 *			anim,
 *			keys;
 *
 *		frames[100] = {"background-color": "blue"};
 *		keys = new tau.util.anim.Keyframes(frames);
 *		anim = new tau.util.anim.Animation({
 *				element: document.getElementById("test"),
 *				fillMode: "both",
 *				delay: "2s",
 *				duration: "5s",
 *				steps: keys,
 *				onEnd: function () {
 *					console.log("Yay, finished!");
 *				}
 *			});
 *		</script>
 *
 * @class ns.util.anim.Keyframes
 * @author Krzysztof Antoszek <k.antoszek@samsung.com>
 */
(function (document, ns) {
	
				/**
			 * Helper function for generating css string from
			 * @TODO the steps array could be propably be more
			 * optimized (most usages will use maybe up to 3-5
			 * array elements, when it has 100) but thats not
			 * important for the moment
			 * frames array
			 * @param {string} prefix
			 * @param {string} name
			 * @param {Array} steps
			 * @return {string}
			 * @private
			 * @static
			 * @method keyframesToString
			 * @member ns.utils.anim.Keyframes
			 */
			function keyframesToString(prefix, name, steps) {
				var buff = "@" + prefix + "keyframes " + name + " {",
					i,
					l,
					prop,
					step;
				for (i = 0, l = steps.length; i < l; ++i) {
					step = steps[i];
					if (!step) {
						continue;
					}
					buff += i + "% { ";
					for (prop in step) {
						if (step.hasOwnProperty(prop)) {
							buff += prop + ": " + step[prop] + "; ";
						}
					}
					buff += "} ";
				}
				buff += "} ";
				return buff;
			}
				// Reference to stylesheet
			var styleContainer = null,
				cssPropertyPrefix = ns.support.cssAnimationPrefix,
				Keyframes = function (steps) {
					var id = ns.getUniqueId(),
						element = null;
					if (!styleContainer) {
						element = document.createElement("style");
						// a text node hack, it forces the browser
						// to create a stylesheet object in the
						// HTMLStyleElement object, which we can 
						// then use
						element.appendChild(document.createTextNode(""));
						document.head.appendChild(element);
						styleContainer = element.sheet;
					}
					styleContainer.insertRule(keyframesToString(cssPropertyPrefix, id, steps),
							0);
					/**
					 * Keyframes rule reference
					 * @property {CSSRule} keyframes
					 * @readonly
					 */
					this.keyframes = styleContainer.rules[0];
					/**
					 * Keyframes name
					 * @property {string} id
					 * @readonly
					 */
					this.id = id;
				};

			/**
			 * Destroys keyframes and removes css references from stylesheet
			 * @method destroy
			 * @member ns.util.anim.Keyframes
			 */
			Keyframes.prototype.destroy = function () {
				var keyframes = this.keyframes,
					stylesheet = keyframes.parentStyleSheet,
					rules = stylesheet.rules,
					i,
					l;

				// no other way for removal than with index
				// and since it changes we have to search for it
				// :(
				for (i = 0, l = rules.length; i < l; ++i) {
					if (rules[i] === keyframes) {
						stylesheet.deleteRule(i);
						break;
					}
				}
			};

			ns.util.anim.Keyframes = Keyframes;
			}(window.document, ns));

/*global window, define */
/*jslint plusplus: true */
/*jshint -W069 */
/* Copyright (c) 2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/*
 * @author Jadwiga Sosnowska <j.sosnowska@partner.samsung.com>
 * @author Krzysztof Antoszek <k.antoszek@samsung.com>
 * @author Maciej Moczulski <m.moczulski@samsung.com>
 * @author Piotr Karny <p.karny@samsung.com>
 */
(function (window, document, ns) {
	
	
			var DOM = ns.util.DOM;

			/**
			 * Returns css property for element
			 * @method getCSSProperty
			 * @param {HTMLElement} element
			 * @param {string} property
			 * @param {string|number|null} [def=null] default returned value
			 * @param {"integer"|"float"|null} [type=null] auto type casting
			 * @return {string|number|null}
			 * @member ns.util.DOM
			 * @static
			 */
			function getCSSProperty(element, property, def, type) {
				var style = window.getComputedStyle(element),
					value = null,
					result = def;
				if (style) {
					value = style.getPropertyValue(property);
					if (value) {
						switch (type) {
						case "integer":
							value = parseInt(value, 10);
							if (!isNaN(value)) {
								result = value;
							}
							break;
						case "float":
							value = parseFloat(value);
							if (!isNaN(value)) {
								result = value;
							}
							break;
						default:
							result = value;
							break;
						}
					}
				}
				return result;
			}

			/**
			 * Extracts css properties from computed css for an element.
			 * The properties values are applied to the specified
			 * properties list (dictionary)
			 * @method extractCSSProperties
			 * @param {HTMLElement} element
			 * @param {Object} properties
			 * @param {?string} [pseudoSelector=null]
			 * @param {boolean} [noConversion=false]
			 * @member ns.util.DOM
			 * @static
			 */
			function extractCSSProperties (element, properties, pseudoSelector, noConversion) {
				var style = window.getComputedStyle(element, pseudoSelector),
					property,
					value = null,
					utils = ns.util;

				// @TODO extractCSSProperties should rather return raw values (with units)
				for (property in properties) {
					if (properties.hasOwnProperty(property)) {
						value = style.getPropertyValue(property);
						if (utils.isNumber(value) && !noConversion) {
							if (value.match(/\./gi)) {
								properties[property] = parseFloat(value);
							} else {
								properties[property] = parseInt(value, 10);
							}
						} else {
							properties[property] = value;
						}
					}
				}
			}

			/**
			 * Returns elements height from computed style
			 * @method getElementHeight
			 * @param {HTMLElement} element
			 * if null then the "inner" value is assigned
			 * @param {"outer"|null} [type=null]
			 * @param {boolean} [includeOffset=false]
			 * @param {boolean} [includeMargin=false]
			 * @param {?string} [pseudoSelector=null]
			 * @param {boolean} [force=false] check even if element is hidden
			 * @return {number}
			 * @member ns.util.DOM
			 * @static
			 */
			function getElementHeight(element, type, includeOffset, includeMargin, pseudoSelector, force) {
				var height = 0,
					style,
					value,
					originalDisplay = null,
					originalVisibility = null,
					originalPosition = null,
					outer = (type && type === "outer") || false,
					offsetHeight = 0,
					property,
					props = {
						"height": 0,
						"margin-top": 0,
						"margin-bottom": 0,
						"padding-top": 0,
						"padding-bottom": 0,
						"border-top-width": 0,
						"border-bottom-width": 0,
						"box-sizing": ""
					};
				if (element) {
					style = element.style;

					if (style.display !== "none") {
						extractCSSProperties(element, props, pseudoSelector, true);
						offsetHeight = element.offsetHeight;
					} else if (force) {
						originalDisplay = style.display;
						originalVisibility = style.visibility;
						originalPosition = style.position;

						style.display = "block";
						style.visibility = "hidden";
						style.position = "relative";

						extractCSSProperties(element, props, pseudoSelector, true);
						offsetHeight = element.offsetHeight;

						style.display = originalDisplay;
						style.visibility = originalVisibility;
						style.position = originalPosition;
					}

					// We are extracting raw values to be able to check the units
					if(typeof props["height"] === "string" && props["height"].indexOf("px") === -1){
						//ignore non px values such as auto or %
						props["height"] = 0;
					}

					for (property in props) {
						if (props.hasOwnProperty(property) && property !== "box-sizing"){
							value = parseFloat(props[property]);
							if (isNaN(value)) {
								value = 0;
							}
							props[property] = value;
						}
					}

					height += props["height"] + props["padding-top"] + props["padding-bottom"];

					if (includeOffset) {
						height = offsetHeight;
					} else if (outer && props["box-sizing"] !== 'border-box') {
						height += props["border-top-width"] + props["border-bottom-width"];
					}

					if (includeMargin) {
						height += Math.max(0, props["margin-top"]) + Math.max(0, props["margin-bottom"]);
					}
				}
				return height;
			}

			/**
			 * Returns elements width from computed style
			 * @method getElementWidth
			 * @param {HTMLElement} element
			 * if null then the "inner" value is assigned
			 * @param {"outer"|null} [type=null]
			 * @param {boolean} [includeOffset=false]
			 * @param {boolean} [includeMargin=false]
			 * @param {?string} [pseudoSelector=null]
			 * @param {boolean} [force=false] check even if element is hidden
			 * @return {number}
			 * @member ns.util.DOM
			 * @static
			 */
			function getElementWidth(element, type, includeOffset, includeMargin, pseudoSelector, force) {
				var width = 0,
					style,
					value,
					originalDisplay = null,
					originalVisibility = null,
					originalPosition = null,
					offsetWidth = 0,
					property,
					outer = (type && type === "outer") || false,
					props = {
						"width": 0,
						"margin-left": 0,
						"margin-right": 0,
						"padding-left": 0,
						"padding-right": 0,
						"border-left-width": 0,
						"border-right-width": 0,
						"box-sizing": ""
					};

				if (element) {
					style = element.style;

					if (style.display !== "none") {
						extractCSSProperties(element, props, pseudoSelector, true);
						offsetWidth = element.offsetWidth;
					} else if (force) {
						originalDisplay = style.display;
						originalVisibility = style.visibility;
						originalPosition = style.position;

						style.display = "block";
						style.visibility = "hidden";
						style.position = "relative";

						extractCSSProperties(element, props, pseudoSelector, true);

						style.display = originalDisplay;
						style.visibility = originalVisibility;
						style.position = originalPosition;
					}

					if(typeof props["width"] === 'string' && props["width"].indexOf("px") === -1) {
						//ignore non px values such as auto or %
						props["width"] = 0;
					}
					for (property in props) {
						if (props.hasOwnProperty(property) && property !== "box-sizing"){
							value = parseFloat(props[property]);
							if (isNaN(value)) {
								value = 0;
							}
							props[property] = value;
						}
					}

					width += props["width"] + props["padding-left"] + props["padding-right"];

					if (includeOffset) {
						width = offsetWidth;
					} else if (outer && props["box-sizing"] !== 'border-box') {
						width += props["border-left-width"] + props["border-right-width"];
					}

					if (includeMargin) {
						width += Math.max(0, props["margin-left"]) + Math.max(0, props["margin-right"]);
					}
				}
				return width;
			}

			/**
			 * Returns offset of element
			 * @method getElementOffset
			 * @param {HTMLElement} element
			 * @return {Object}
			 * @member ns.util.DOM
			 * @static
			 */
			function getElementOffset(element) {
				var left = 0,
					top = 0;
				do {
					top += element.offsetTop;
					left += element.offsetLeft;
					element = element.offsetParent;
				} while (element !== null);

				return {
					top: top,
					left: left
				};
			}

			/**
			 * Check if element occupies place at view
			 * @method isOccupiedPlace
			 * @param {HTMLElement} element
			 * @return {boolean}
			 * @member ns.util.DOM
			 * @static
			 */
			function isOccupiedPlace(element) {
				return !(element.offsetWidth <= 0 && element.offsetHeight <= 0);
			}

			// assign methods to namespace
			DOM.getCSSProperty = getCSSProperty;
			DOM.extractCSSProperties = extractCSSProperties;
			DOM.getElementHeight = getElementHeight;
			DOM.getElementWidth = getElementWidth;
			DOM.getElementOffset = getElementOffset;
			DOM.isOccupiedPlace = isOccupiedPlace;

			}(window, window.document, ns));

/*global window, define, ns */
/*jslint nomen: true, plusplus: true */
/* Copyright (c) 2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/**
 * # Animation
 *
 * Animation class for easy animations of elements. There can be
 * multiple animations on one element but in such case the usage
 * of tau.util.anim.Chain is preferred.
 *
 * ## Usage example
 *
 * @example
 *
 *		<div id="test"
 *				style="width: 10px; height: 10px; background: red;"></div>
 *
 *		<script>
 *			var a = new tau.util.anim.Animation({
 *				element: document.getElementById("test"),
 *				fillMode: "both",
 *				delay: "2s",
 *				duration: "5s",
 *				from: {
 *					"background-color": "red"
 *				},
 *				to: {
 *					"background-color": "blue"
 *				},
 *				onEnd: function () {
 *					console.log("Yay, finished!");
 *				}
 *			});
 *		</script>
 *
 * @class ns.util.anim.Animation
 * @author Krzysztof Antoszek <k.antoszek@samsung.com>
 */
(function (document, ns) {
	
	
			/**
			 * Simple helper for using trim in Array.map() function
			 * @param {string} string
			 * @return {string}
			 * @private
			 * @static
			 * @method trim
			 * @member ns.util.anim.Animation
			 */
			function trim(string) {
				return string.trim();
			}

			/**
			 * Helper for fetching animation index in animation list
			 * @param {string|string[]} props
			 * @param {string} name
			 * @return {string}
			 * @private
			 * @static
			 * @member ns.util.anim.Animation
			 */
			function getAnimationIndex(props, name) {
				if (typeof props === "string") {
					props = props.split(",").map(trim);
				}
				return props.indexOf(name);
			}

			var objectUtils = ns.util.object,
				Keyframes = ns.util.anim.Keyframes,
				CSSUtils = ns.util.DOM,
				dateUtils = ns.util.date,
				cssPropertyPrefix = ns.support.cssAnimationPrefix,
				eventPrefix = cssPropertyPrefix.replace(/\-/gi, ""),
				endEventName = eventPrefix.length > 0 ? eventPrefix +
						"AnimationEnd" : "animationEnd",
				// paused state flag
				PAUSED = 0,
				// playing state flag
				PLAYING = 1,
				// finished state flag
				FINISHED = 2,
				// alias for function string for typeof conditionals
				TYPE_FUNCTION = "function",
				/**
				 * Animation end handler
				 * @param {ns.util.anim.Animation} self
				 * @param {Event} event
				 * @private
				 * @static
				 * @member ns.util.anim.Animation
				 */
				handleEnd = function (self, event) {
					var options = self.options,
						element = options.element,
						onEnd = options.onEnd,
						onPause = options.onPause;
					if (event.animationName === self.keyframes.id) {
						switch (self.state) {
						case PLAYING:
							self.state = FINISHED;
							if (typeof onEnd === TYPE_FUNCTION) {
								onEnd(self, element, event);
							}
							break;
						case PAUSED:
							if (typeof onPause === TYPE_FUNCTION) {
								onPause(self, element, event);
							}
							break;
						}
					}
				},
				/**
				 * Helper for playing/pausing
				 * @param {ns.util.anim.Animation} self
				 * @param {string} state
				 * @return {ns.util.anim.Animation}
				 * @private
				 * @static
				 * @member ns.util.anim.Animation
				 */
				changeState = function (self, state) {
					if (!self._applied) { // !set before keyframe fetch
						self._apply();
					}

					var options = self.options,
						element = options.element,
						onPlay = options.onPlay,
						style = element.style,
						keyframes = self.keyframes,
						propString = style.getPropertyValue(cssPropertyPrefix +
								"animation-play-state"),
						propsArray = (propString && propString.split(",")
								.map(trim)) || [],
						index = keyframes ? getAnimationIndex(
							style.getPropertyValue(cssPropertyPrefix +
										"animation-name"),
							keyframes.id
						) : -1;

					if (index > -1) {
						propsArray[index] = state || "running";
						style.setProperty(cssPropertyPrefix +
								"animation-play-state", propsArray.join(","));
						self.state = PLAYING;
						if (typeof onPlay === TYPE_FUNCTION) {
							window.clearTimeout(self.playTimer);
							self.playTimer = window.setTimeout(function () {
								onPlay(self, element);
							}, dateUtils.convertToMiliseconds(options.delay));
						}
					}
					return self;
				},
				Animation = function (options) {
					var self = this,
						/**
						 * @property {Object} options
						 * @property {HTMLElement} options.element The animated element
						 * @property {Object|null} [options.from=null] The starting step, this
						 * 		can be defined later
						 * @property {Object|null} [options.to=null]  The finishing step, this
						 * 		can also be defined later
						 * @property {Object[]} [options.steps=Array(0)] Animation steps,
						 * 		when advanced keying is required, the array must have 100 elements,
						 * 		which are percentages of the timeline (anmation duration)
						 * @property {string} [options.duration="0"] The duration of the animation
						 * @property {string} [options.direction="normal"] The direction of the
						 * 		animation (for possible values, refer to CSS Animation spec)
						 * @property {string} [options.delay="0"] The delay of the animation.
						 * 		Please remember when using ns.util.anim.Chain with concurrent
						 * 		option to false, the of subsequent animations will be modified
						 * @property {string} [options.fillMode="none"] The fill mode of the
						 * 		animations (for possible values, refer to CSS Animation spec)
						 * @property {boolean} [options.preserve=false] Indicates if the last
						 * 		key frame props should be kept after animation is destroyed
						 * 		(not implemented!)
						 * @property {string} [options.timingFunction="ease"] Chooses the timing
						 * 		function for the css animation (for possible values, refer to CSS
						 * 		Animation spec)
						 * @property {boolean} [options.autoPlay=false] Defines if the animation
						 * 		will start after definition
						 */
						opts = objectUtils.merge({
							element: null,
							from: null,
							to: null,
							steps: [],
							duration: "0",
							direction: "normal",
							delay: "0",
							iterationCount: 1,
							infinite: false,
							fillMode: "none",
							preserve: false, //@TODO preserve props after animation destroy!
							onEnd: null,
							onPause: null,
							onPlay: null,
							timingFunction: "ease",
							autoPlay: false
						}, options || {}),
						steps = null,
						props,
						endCallback = handleEnd.bind(null, this),
						element = opts.element;

					if (opts.steps.length === 0) {
						steps = [];
						steps.length = 101;
						if (opts.to) {
							steps[100] = opts.to;
						}
						if (!opts.from) {
							if (opts.to && opts.element) {
								props = Object.keys(opts.to);
								CSSUtils.extractCSSProperties(opts.element, props);
								steps[0] = props;
							}
						} else {
							steps[0] = opts.from;
						}
					} else {
						steps = opts.steps;
					}

					self.options = opts;
					/**
					 * @property {Array.<Object>} steps Array of animation steps
					 * @readonly
					 */
					self.steps = steps;
					// indicates if the css props were applied
					self._applied = false;
					/**
					 * @property {ns.util.anim.Keyframes|null} keyframes Keyframes reference
					 * @readonly
					 */
					self.keyframes = null;
					/**
					 * @property {number} [state=0] Animation state
					 *		(ns.util.anim.Animation.states.*)
					 * @readonly
					 */
					self.state = PAUSED;
					// timer for onPlay callback (we need to simulate actuall event firing
					self.playTimer = null;
					this._endCallback = endCallback;

					if (element) {
						element.addEventListener(endEventName, endCallback, false);
						if (opts.autoPlay) {
							self.play();
						}
					}

				},
				proto = {};

			/**
			 * Applies css properties for the element
			 * @method _apply
			 * @protected
			 * @member ns.util.anim.Animation
			 */
			proto._apply = function () {
				var self = this,
					opts = self.options,
					element = opts.element,
					style = element.style,
					propString = style.getPropertyValue(cssPropertyPrefix + "animation"),
					propsArray = (propString && propString.split(",").map(trim)) || [],
					id = null;

				self.keyframes = new Keyframes(self.steps);
				id = self.keyframes.id;
				if (element) {
					propsArray.push(id + " " + opts.duration + " " + opts.timingFunction +
							" " + opts.delay + " " + opts.iterationCount + " " + opts.direction +
							" " + opts.fillMode);
					element.style.setProperty(cssPropertyPrefix + "animation",
							propsArray.join(","));
					self._applied = true;
				}
			};

			/**
			 * Adds step to animation
			 * Note: this will reset the whole animation, so do it only in paused state
			 * @param {number} timePoint A keyframe number between from 0 to 100
			 * @param {Object} stepOptions Css props to change in the keyframe
			 * @return {ns.util.anim.Animation}
			 * @method step
			 * @chainable
			 * @member ns.util.anim.Animation
			 */
			proto.step = function (timePoint, stepOptions) {
				var self = this;

				self.steps[timePoint] = stepOptions;
				return self.reset();
			};

			/**
			 * Resets the animation			
			 * @return {ns.util.anim.Animation}
			 * @method reset
			 * @chainable
			 * @member ns.util.anim.Animation
			 */
			proto.reset = function () {
				var self = this,
					keyframes = self.keyframes,
					style = self.options.element.style,
					propString = style.getPropertyValue(cssPropertyPrefix + "animation-name"),
					propsArray = (propString && propString.split(",").map(trim)) || [],
					index = keyframes ? propsArray.indexOf(keyframes.id) : -1;

				if (self.keyframes) {
					self.keyframes.destroy();
				}

				keyframes = new Keyframes(self.steps);
				if (index > -1) {
					propsArray[index] = keyframes.id;
					self.keyframes = keyframes;
					style.setProperty(cssPropertyPrefix + "animation-name",
							propsArray.join(","));
				}

				return self;
			};

			/**
			 * Starts playback
			 * @return {ns.util.anim.Animation}
			 * @method play
			 * @chainable
			 * @member ns.util.anim.Animation
			 */
			proto.play = function () {
				return changeState(this, "running");
			};

			/**
			 * Pauses playback
			 * @return {ns.util.anim.Animation}
			 * @method pause
			 * @chainable
			 * @member ns.util.anim.Animation
			 */
			proto.pause = function () {
				return changeState(this, "paused");
			};

			/**
			 * Destroys the animation
			 * Note: Please use "preserve" options to keep applied last animation props
			 * @return {ns.util.anim.Animation}
			 * @method destroy
			 * @member ns.util.anim.Animation
			 */
			proto.destroy = function () {
				var self = this,
					element = self.options.element,
					prop,
					style,
					keyframes = self.keyframes,
					endCallback = self._endCallback,
					propRegexp;
				if (element) {
					if (self._applied && keyframes) {
						style = element.style;
						prop = style.getPropertyValue(cssPropertyPrefix + "animation");
						if (prop) {
							propRegexp = new RegExp(",? ?" + keyframes.id + "[^,%]*,? ?", "i");
							style.removeProperty(cssPropertyPrefix + "animation",
									prop.replace(propRegexp, ""));
						}
						keyframes.destroy();
						self._applied = false;
					}
					if (endCallback) {
						element.removeEventListener(endEventName, endCallback, false);
					}
				}
				window.clearTimeout(self.playTimer);
			};

			/**
			 * @property {Object} statea animation state definitions
			 * @property {number} [states.PAUSED=0] paused state
			 * @property {number} [states.PLAYING=1] playing state
			 * @property {number} [states.FINISHED=2] finished state
			 * @static
			 * @readonly
			 * @member ns.util.anim.Animation
			 */
			Animation.states = {
				"PAUSED": PAUSED,
				"PLAYING": PLAYING,
				"FINISHED": FINISHED
			};
			Animation.prototype = proto;
			ns.util.anim.Animation = Animation;
			}(window.document, ns));

/*global window, define, ns */
/*jslint plusplus: true, nomen: true */
/* Copyright (c) 2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/**
 * # Chain
 *
 * Chain class for easy multiple animations managment. The chain
 * can be executed as is (animations are concurrent) or in order
 * of adding in which animations are delayed so that the execute
 * in turn
 *
 * ## Usage example
 *
 * @example
 *
 *		<div id="test"
 *				style="width: 10px; height: 10px; background: red; position: absolute;">
 *		</div>
 *
 *		<script>
 *			var element = document.getElementById("test"),
 *				chain = new tau.util.anim.Chain(
 *					{
 *						concurrent: false,
 *						onPlay: function () {
 *							console.log("chain started to play");
 *						},
 *						onPause: function () {
 *							console.log("chain paused");
 *						},
 *						onEnd: function () {
 *							console.log("chain finished");
 *						}
 *					},
 *					[
 *						{
 *							element: element,
 *							from: { "background-color": "red" },
 *							to: { "background-color": "blue"},
 *							duration: "3s",
 *							onPlay: function () {
 *								console.log("animation 1 started to play");
 *							},
 *							onPause: function () {
 *								console.log("animation 1 paused");
 *							},
 *							onEnd: function () {
 *								console.log("animation 1 finished");
 *							}
 *						},
 *						{
 *							element: element,
 *						from: { "-webkit-transform": "translate3d(0,0,0)" },
 *							to: { "-webkit-transform": "translate3d(100px, 100px, 0)"},
 *							duration: "3s",
 *							onPlay: function () {
 *								console.log("animation 2 started to play");
 *							},
 *							onPause: function () {
 *								console.log("animation 2 paused");
 *							},
 *							onEnd: function () {
 *								console.log("animation 2 finished");
 *							}
 *						}
 *					]
 *				);
 *			chain.play();
 *		</script>
 *
 * @class ns.util.anim.Chain
 * @author Krzysztof Antoszek <k.antoszek@samsung.com>
 */
(function (ns) {
	
				var Animation = ns.util.anim.Animation,
				objectUtils = ns.util.object,
				dateUtils = ns.util.date,
				// paused state flag
				PAUSED = 0,
				// playing state flag
				PLAYING = 1,
				// finished state flag
				FINISHED = 2,
				// function type for typeof comparisions
				TYPE_FUNCTION = "function",
				/**
				 * Animation end handler
				 * @param {ns.util.anim.Chain} self
				 * @param {ns.util.anim.Animation} animation
				 * @method handleEnd
				 * @member ns.util.anim.Chain
				 * @private
				 * @static
				 */
				handleEnd = function (self, animation) {
					var onEnd = self.options.onEnd,
						animations = self.animations,
						index = animations.indexOf(animation);
					self.current = index;
					if (index === animations.length - 1) {
						self.state = FINISHED;
						if (typeof onEnd === TYPE_FUNCTION) {
							onEnd(self);
						}
					}
				},
				Chain = function (options, animations) {
						/**
						 * @property {Object} options
						 * @property {boolean} [options.concurent='false'] Sets the type of the chain
						 * @property {function(ns.util.anim.Chain)} [options.onPlay=null] a callback for play start
						 * @property {function(ns.util.anim.Chain)} [options.onPause=null] a callback for play pause
						 * @property {function(ns.util.anim.Chain)} [options.onEnd=null] a callback for play end
						 */
					var opts = objectUtils.merge({
							conocurrent: true,
							onPlay: null,
							onPause: null,
							onEnd: null
						}, options || {}),
						self = this;
					/**
					 * @property {number} current Marks current animation
					 * @readonly
					 */
					self.current = null;
					/**
					 * @property {Array.<ns.util.anim.Animation>} animations The animations holder
					 * @readonly
					 */
					self.animations = [];
					/**
					 * @property {number} totalTime
					 * @readonly
					 */
					self.totalTime = 0;
					self.options = opts;
					/**
					 * @property {number} state=0 (ns.util.anim.Chain.states.*)
					 * @readonly
					 */
					self.state = PAUSED;

					if (animations && animations.length > 0) {
						self.addMultiple(animations);
					}
				},
				proto = {
					/**
					 * Adds animation to chain
					 * @param {ns.util.anim.Animation} animation
					 * @return {ns.util.anim.Chain}
					 * @chainable
					 * @method add
					 * @member ns.util.anim.Chain
					 */
					add: function (animation) {
						var animationInstance = animation instanceof Animation ?
								animation :
								new Animation(animation),
							animationOptions = animationInstance.options,
							time = dateUtils.convertToMiliseconds(animationOptions.duration),
							delay = dateUtils.convertToMiliseconds(animationOptions.delay),
							onEndCallback = animationOptions.onEnd,
							self = this;

						if (typeof onEndCallback  === TYPE_FUNCTION) {
							animationOptions.onEnd = function (_animation, element, event) {
								onEndCallback(_animation, element, event);
								handleEnd(self, _animation);
							};
						} else {
							animationOptions.onEnd = handleEnd.bind(null, self);
						}

						if (self.options.concurrent === false) {
							animationOptions.delay = (delay + self.totalTime) + "ms";
							self.totalTime += delay + time;
						}

						self.animations.push(animationInstance);
						if (!self.current) {
							self.current = 0;
						}
						return self;
					},

					/**
					 * Adds multiple animations to chain
					 * @param {Array.<ns.util.anim.Animation>} animations
					 * @return {ns.util.anim.Chain}
					 * @method addMultiple
					 * @chainable
					 * @member ns.util.anim.Chain
					 */
					addMultiple: function (animations) {
						var i,
							l;
						for (i = 0, l = animations.length; i < l; ++i) {
							this.add(animations[i]);
						}
						return this;
					},

					/**
					 * Starts playing animation chain
					 * @method play
					 * @chainable
					 * @member ns.util.anim.Chain
					 */
					play: function () {
						var i,
							l,
							self = this,
							onPlay = self.options.onPlay;
						for (i = self.current, l = self.animations.length; i < l; ++i) {
							self.animations[i].play();
						}
						self.state = PLAYING;
						if (typeof onPlay === TYPE_FUNCTION) {
							onPlay(self);
						}
						return self;
					},

					/**
					 * Pauses playback
					 * @method pause
					 * @chainable
					 * @member ns.util.anim.Chain
					 */
					pause: function () {
						var i,
							l,
							self = this,
							onPause = self.options.onPause;
						for (i = self.current, l = self.animations.length; i < l; ++i) {
							self.animations[i].pause();
						}
						self.state = PAUSED;
						if (typeof onPause === TYPE_FUNCTION) {
							onPause(self);
						}
						return self;
					},
					
					/**
					 * Destroys chain and animations
					 * @method destroy
					 * @member ns.util.anim.Chain
					 */
					destroy: function () {
						var i,
							l;
						for (i = 0, l = this.animations.length; i < l; ++i) {
							this.animations[i].destroy();
						}
					}
				};

			/**
			 * Animation chain states
			 * @property {Object} states
			 * @property {number} [states.PAUSED = 0]
			 * @property {number} [states.PLAYING = 1]
			 * @property {number} [states.FINISHED = 2]
			 * @readonly
			 * @static
			 * @member ns.util.anim.Chain
			 */
			Chain.states = {
				"PAUSED": PAUSED,
				"PLAYING": PLAYING,
				"FINISHED": FINISHED
			};
			Chain.prototype = proto;
			ns.util.anim.Chain = Chain;
			}(ns));

/*global window, define */
/* Copyright (c) 2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/**
 * #Event hwkey
 * Namespace to support tizenhwkey event
 * @class ns.event.hwkey
 */
(function (window, ns) {
	
				var popupClose = function (event) {
					var keyName = event.keyName,
						activePopup = ns.activePopup,
						container,
						containerClass,
						focused;
					// Check enableHWKeyHandler property
					if (ns.getConfig("enableHWKeyHandler", true) && activePopup) {
						container = activePopup._ui.container;
						containerClass = container && container.classList;
						if (keyName === "menu") {
							focused = activePopup.element.querySelector(".ui-focus");
							if (focused) {
								// NOTE: If a popup is opened and focused element exists in it,
								//       do not close that popup.
								//       'false' is returned here, hence popup close routine is not run.
								event.preventDefault();
								event.stopPropagation();
								return;
							}
						}
						if (keyName === "menu" || keyName === "back") {
							if (containerClass && (!containerClass.contains("ui-datetimepicker") || containerClass.contains("in"))) {
								activePopup.close();
								event.preventDefault();
								event.stopPropagation();
							}
						}
					}
				},
				selectMenuClose = function (event) {
					var keyName = event.keyName,
						elActiveSelectMenu,
						activeSelectMenu;
					if (ns.getConfig("enableHWKeyHandler", true) && (keyName === "menu" || keyName === "back")){
						elActiveSelectMenu = document.querySelector("div.ui-selectmenu-active select");
						if (elActiveSelectMenu) {
							activeSelectMenu = ns.widget.SelectMenu(elActiveSelectMenu);
							activeSelectMenu.close();
							event.preventDefault();
							event.stopPropagation();
						}
					}
				},
				hwkey = {
					/**
					 * Bind event tizenhwkey to support hardware keys.
					 * @method bind
					 * @static
					 * @member ns.event.hwkey
					 */
					bind: function () {
						document.addEventListener("tizenhwkey", popupClose, true);
						document.addEventListener("tizenhwkey", selectMenuClose, true);
					},

					/**
					 * Unbind event tizenhwkey to support hardware keys.
					 * @method unbind
					 * @static
					 * @member ns.event.hwkey
					 */
					unbind: function () {
						document.removeEventListener("tizenhwkey", popupClose, true);
						document.removeEventListener("tizenhwkey", selectMenuClose, true);
					}
				};

			ns.event.hwkey = hwkey;

			document.addEventListener(ns.engine.eventType.INIT, function() {
				hwkey.unbind();
				hwkey.bind();
			}, false);

			}(window, ns));

/*global window, define */
/* Copyright (c) 2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/**
 * #Event throttledresize
 * Object supports throttledresize event.
 * @class ns.event.throttledresize
 */
/**
 * Event throttledresize
 * @event throttledresize
 * @member ns.event.throttledresize
 */
(function (window, ns) {
	
				var throttledresize = {
					/**
					 * State of event support
					 * @property {boolean} [enabled=true]
					 * @static
					 * @member ns.event.throttledresize
					 */
					enabled: ns.getConfig("enableThrottleResize", true),
					/**
					 * Timeout of triggering event.
					 * @property {number} [ttl=250]
					 * @static
					 * @member ns.event.throttledresize
					 */
					ttl: 250
				},
				timerID,
				eventUtils = ns.event,
				resizeHandler = function () {
					if (timerID) {
						window.clearTimeout(timerID);
					}
					timerID = window.setTimeout(function () {
						eventUtils.trigger(window, "throttledresize");
					}, throttledresize.ttl);
				},
				/**
				 * Enables event support
				 * @method enable
				 * @static
				 * @member ns.event.throttledresize
				 */
				enable = function () {
					if (!throttledresize.enabled) {
						throttledresize.enabled = true;
					}
					window.addEventListener("resize", resizeHandler, true);
				};

			if (throttledresize.enabled) {
				enable();
			}

			throttledresize.enable = enable;

			ns.event.throttledresize = throttledresize;

			}(window, ns));

/*global window, define, NodeList, HTMLCollection */
/*jslint plusplus: true */
/* Copyright (c) 2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/*
 * @author Jadwiga Sosnowska <j.sosnowska@partner.samsung.com>
 * @author Krzysztof Antoszek <k.antoszek@samsung.com>
 * @author Maciej Moczulski <m.moczulski@samsung.com>
 * @author Piotr Karny <p.karny@samsung.com>
 */
(function (window, document, ns) {
	
	
			/**
			 * @property {DocumentFragment} fragment
			 * @member ns.util.DOM
			 * @private
			 * @static
			 */
			/*
			 * @todo maybe can be moved to function scope?
			 */
			var fragment = document.createDocumentFragment(),
				/**
				 * @property {DocumentFragment} fragment2
				 * @member ns.util.DOM
				 * @private
				 * @static
				 */
				/*
				 * @todo maybe can be moved to function scope?
				 */
				fragment2 = document.createDocumentFragment(),
				/**
				 * @property {number} [containerCounter=0]
				 * @member ns.util.DOM
				 * @private
				 * @static
				 */
				/*
				 * @todo maybe can be moved to function scope?
				 */
				containerCounter = 0,
				/**
				 * Alias to Array.slice method
				 * @method slice
				 * @member ns.util.DOM
				 * @private
				 * @static
				 */
				slice = [].slice,
				DOM = ns.util.DOM;

			/**
			 * Appends node or array-like node list array to context
			 * @method appendNodes
			 * @member ns.util.DOM
			 * @param {HTMLElement} context
			 * @param {HTMLElement|HTMLCollection|NodeList|Array} elements
			 * @return {HTMLElement|Array|null}
			 * @static
			 * @throws {string}
			 */
			DOM.appendNodes = function (context, elements) {
				var i,
					len;
				if (context) {
					if (elements instanceof Array || elements instanceof NodeList || elements instanceof HTMLCollection) {
						elements = slice.call(elements);
						for (i = 0, len = elements.length; i < len; ++i) {
							context.appendChild(elements[i]);
						}
					} else {
						context.appendChild(elements);
					}
					return elements;
				}

				throw "Context empty!";
			};

			/**
			 * Replaces context with node or array-like node list
			 * @method replaceWithNodes
			 * @member ns.util.DOM
			 * @param {HTMLElement} context
			 * @param {HTMLElement|HTMLCollection|NodeList|Array} elements
			 * @return {HTMLElement|Array|null}
			 * @static
			 */
			DOM.replaceWithNodes = function (context, elements) {
				if (elements instanceof Array || elements instanceof NodeList || elements instanceof HTMLCollection) {
					elements = this.insertNodesBefore(context, elements);
					context.parentNode.removeChild(context);
				} else {
					context.parentNode.replaceChild(elements, context);
				}
				return elements;
			};

			/**
			 * Remove all children
			 * @method removeAllChildren
			 * @member ns.util.DOM
			 * @param {HTMLElement} context
			 * @static
			 */
			DOM.removeAllChildren = function (context) {
				context.innerHTML = "";
			};

			/**
			 * Inserts node or array-like node list before context
			 * @method insertNodesBefore
			 * @member ns.util.DOM
			 * @param {HTMLElement} context
			 * @param {HTMLElement|HTMLCollection|NodeList|Array} elements
			 * @return {HTMLElement|Array|null}
			 * @static
			 * @throws {string}
			 */
			DOM.insertNodesBefore = function (context, elements) {
				var i,
					len,
					parent;
				if (context) {
					parent = context.parentNode;
					if (elements instanceof Array || elements instanceof NodeList || elements instanceof HTMLCollection) {
						elements = slice.call(elements);
						for (i = 0, len = elements.length; i < len; ++i) {
							parent.insertBefore(elements[i], context);
						}
					} else {
						parent.insertBefore(elements, context);
					}
					return elements;
				}

				throw "Context empty!";

			};

			/**
			 * Inserts node after context
			 * @method insertNodeAfter
			 * @member ns.util.DOM
			 * @param {HTMLElement} context
			 * @param {HTMLElement} element
			 * @return {HTMLElement}
			 * @static
			 * @throws {string}
			 */
			DOM.insertNodeAfter = function (context, element) {
				if (context) {
					context.parentNode.insertBefore(element, context.nextSibling);
					return element;
				}
				throw "Context empty!";
			};

			/**
			 * Wraps element or array-like node list in html markup
			 * @method wrapInHTML
			 * @param {HTMLElement|NodeList|HTMLCollection|Array} elements
			 * @param {string} html
			 * @return {HTMLElement|NodeList|Array} wrapped element
			 * @member ns.util.DOM
			 * @static
			 */
			DOM.wrapInHTML = function (elements, html) {
				var container = document.createElement("div"),
					contentFlag = false,
					elementsLen = elements.length,
					//if elements is nodeList, retrieve parentNode of first node
					originalParentNode = elementsLen ? elements[0].parentNode : elements.parentNode,
					next = elementsLen ? elements[elementsLen - 1].nextSibling : elements.nextSibling,
					innerContainer;

				fragment.appendChild(container);
				html = html.replace(/(\$\{content\})/gi, function () {
					contentFlag = true;
					return "<span id='temp-container-" + (++containerCounter) + "'></span>";
				});
				container.innerHTML = html;

				if (contentFlag === true) {
					innerContainer = container.querySelector("span#temp-container-" + containerCounter);
					elements = this.replaceWithNodes(innerContainer, elements);
				} else {
					innerContainer = container.children[0];
					elements = this.appendNodes(innerContainer || container, elements);
				}

				// move the nodes
				while (fragment.firstChild.firstChild) {
					fragment2.appendChild(fragment.firstChild.firstChild);
				}

				// clean up
				while (fragment.firstChild) {
					fragment.removeChild(fragment.firstChild);
				}

				if (originalParentNode) {
					if (next) {
						originalParentNode.insertBefore(fragment2, next);
					} else {
						originalParentNode.appendChild(fragment2);
					}
				} else {
					// clean up
					while (fragment2.firstChild) {
						fragment2.removeChild(fragment2.firstChild);
					}
				}
				return elements;
			};
			}(window, window.document, ns));

/*global window, define, ns, setTimeout, clearTimeout */
/*
* Copyright  2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/*jslint nomen: true, plusplus: true */
/**
 * # Button Widget
 * Button widget changes default browser buttons to special buttons with additional opportunities like icon, corners, shadow.
 *
 * ## Default selectors
 * In default all **BUTTON** tags and all **INPUT** tags with type equals _button_, _submit_ or _reset_ are change to Tizen WebUI buttons.
 * In addition all elements with _data-role=button_ and class _ui-button_ are changed to Tizen Web UI buttons.
 * To prevent auto enhance element to Tizen Web UI buttons you can use _data-role=none_ attribute on **BUTTON** or **INPUT** element.
 *
 * ###HTML Examples
 *
 * ####Create simple button from link using data-role
 *
 *		@example
 *		<a href="#page2" data-role="button">Link button</a>
 *
 * ####Create simple button from link using class selector
 *
 *		@example
 *		<a href="#page2" class="ui-button">Link button</a>
 *
 * ####Create simple button using button's tag
 *
 *		@example
 *		<button>Button element</button>
 *
 * ####Create simple button from input using type
 *
 *		@example
 *		<input type="button" value="Button" />
 *		<input type="submit" value="Submit Button" />
 *		<input type="reset" value="Reset Button" />
 *
 * ## Manual constructor
 * For manual creation of button widget you can use constructor of widget from **tau** namespace:
 *
 *		@example
 *		<div id="button"></div>
 *		<script>
 *			var buttonElement = document.getElementById('button'),
 *				button = tau.widget.Button(buttonElement, {mini: true});
 *		</script>
 *
 * Constructor has one require parameter **element** which are base **HTMLElement** to create widget. We recommend to get this element by method *document.getElementById*. Second parameter is **options** and it is a object with options for widget.
 *
 * If jQuery library is loaded, its method can be used:
 *
 *		@example
 *		<div id="button"></div>
 *		<script>
 *			$('#button').button({mini: true});
 *		</script>
 *
 * jQuery Mobile constructor has one optional parameter is **options** and it is a object with options for widget.
 *
 * ##Options for Button Widget
 *
 * Options for widget can be defined as _data-..._ attributes or give as parameter in constructor.
 *
 * You can change option for widget using method **option**.
 *
 * ###Mini version
 * For a more compact version that is useful in toolbars and tight spaces, add the data-mini="true" attribute to the button to create a mini version. This will produce a button that is not as tall as the standard version and has a smaller text size.
 *
 *		@example
 *		<a href="index.html" data-role="button" data-mini="true">Link button</a>
 *
 *
 * ###Inline buttons
 * By default, all buttons in the body content are styled as block-level elements so they fill the width of the screen. However, if you want a more compact button that is only as wide as the text and icons inside, add the data-inline="true" attribute to the button.
 *
 *		@example
 *		<a href="index.html" data-role="button" data-inline="true">Cancel</a>
 *
 * If you have multiple buttons that should sit side-by-side on the same line, add the data-inline="true" attribute to each button. This will style the buttons to be the width of their content and float the buttons so they sit on the same line.
 *
 *		@example
 *		<a href="index.html" data-role="button" data-inline="true">Cancel</a>
 *		<a href="index.html" data-role="button" data-inline="true" data-theme="b">Save</a>
 *
 * ###Icon positioning
 * By default, all icons in buttons are placed to the left of the button text. This default may be overridden using the data-iconpos attribute.
 *
 *		@example
 *		<a href="index.html" data-role="button" data-icon="delete" data-iconpos="right">Delete</a>
 *
 * Possible values of data-iconpos:<br>
 *
 *  - "left"  - creates the button with left-aligned icon<br>
 *  - "right"  - creates the button with right-aligned icon<br>
 *  - "top"  - creates the button with icon positioned above the text<br>
 *  - "bottom"  - creates the button with icon positioned below the text
 *
 * You can also create an icon-only button, by setting the data-iconpos attribute to notext. The button plugin will hide the text on-screen, but add it as a title attribute on the link to provide context for screen readers and devices that support tooltips.
 *
 *		@example
 *		<a href="index.html" data-role="button" data-icon="delete" data-iconpos="notext">Delete</a>
 *
 * ##Methods
 *
 * To call method on widget you can use one of existing API:
 *
 * First API is from tau namespace:
 *
 *		@example
 *		<div id="button" data-role="button"></div>
 *		<script>
 *			var buttonElement = document.getElementById('button'),
 *				button = tau.widget.Button(buttonElement);
 *
 *			// button.methodName(methodArgument1, methodArgument2, ...);
 *			// for example:
 *
 *			button.value("text");
 *		</script>
 *
 * Second API is jQuery Mobile API and for call _methodName_ you can use:
 *
 *		@example
 *	    <div id="button"></div>
 *		<script>
 *			// $("#button").button('methodName', argument1, argument2, ...);
 *			// for example:
 *		</script>
 *
 * @class ns.widget.mobile.Button
 * @extends ns.widget.BaseWidget
 * @author Grzegorz Osimowicz <g.osimowicz@samsung.com>
 * @author Jadwiga Sosnowska <j.sosnowska@samsung.com>
 * @author Krzysztof Antoszek <k.antoszek@samsung.com>
 * @author Maciej Moczulski <m.moczulski@samsung.com>
 * @author Maciej Urbanski <m.urbanski@samsung.com>
 * @author Marcin Jakuszko <m.jakuszko@samsung.com>
 * @author Piotr Gorny <p.gorny2@samsung.com>
 * @author Piotr Karny <p.karny@samsung.com>
 * @author Przemyslaw Ciezkowski <p.ciezkowski@samsung.com>
 * @author Sergiusz Struminski <s.struminski@samsung.com>
 * @author Tomasz Lukawski <t.lukawski@samsung.com>
 */
(function(document, ns) {
	
				var BaseWidget = ns.widget.mobile.BaseWidgetMobile,
				engine = ns.engine,
				selectorsUtils = ns.util.selectors,
				themes = ns.theme,
				Button = function Button() {
					var self = this;

					self.action = "";
					self.label = null;
					self.options = {};
					self.ui = {};
				},
				classes = {
					uiDisabled: "ui-disabled",
					uiBtn: "ui-btn",
					uiBtnUpThemePrefix: "ui-btn-up-",
					uiBtnHoverThemePrefix: "ui-btn-hover-",
					uiBtnDownThemePrefix: "ui-btn-down-",
					uiShadow: "ui-shadow",
					uiBtnCornerAll: "ui-btn-corner-all",
					uiBtnHidden: "ui-btn-hidden",
					uiBtnBoxThemePrefix: "ui-btn-box-",
					uiBtnTextPaddingPrefix: "ui-btn-text-padding-",
					uiBtnCornerCircle: "ui-btn-corner-circle",
					uiBtnHastxt: "ui-btn-hastxt",
					uiBtnIconNobg: "ui-btn-icon-nobg",
					uiBtnIconOnly: "ui-btn-icon_only",
					uiBtnIconOnlyInner: "ui-btn-icon-only",
					uiBtnRound: "ui-btn-round",
					uiMini: "ui-mini",
					uiBtnInline: "ui-btn-inline",
					uiBtnBlock: "ui-btn-block",
					uiIcon: "ui-icon",
					uiBtnIconPrefix: "ui-btn-icon-",
					uiIconPrefix: "ui-icon-",
					uiIconShadow: "ui-icon-shadow",
					uiBtnIconPositionPrefix: "ui-btn-icon-",
					uiLink: "ui-link",
					uiBtnInner: "ui-btn-inner",
					uiBtnText: "ui-btn-text",
					uiFocus: "ui-focus",
					uiBlur: "ui-blur",
					uiBtnEdit: "ui-btn-edit",
					uiBtnLeft: "ui-btn-left",
					uiBtnRight: "ui-btn-right",
					uiSubmit: "ui-submit",
					uiBtnActive: "ui-btn-active",
					uiBtnIconNotext: "ui-btn-icon-notext",
					uiBtnIconRight: 'ui-btn-icon-right'
				},
				eventsAdded = false,
				prototype = new BaseWidget();

			prototype.options = {
				theme: null,
				icon: null,
				iconpos: null,
				inline: null,
				shadow: true,
				iconshadow: true,
				corners: false,
				mini: null,
				bar: false,
				style: null,
				wrapperEls: "span"
			};

				Button.prototype = prototype;

			/**
			 * Dictionary for button related css class names
			 * @property {Object} classes
			 * @member ns.widget.mobile.Button
			 * @static
			 * @readonly
			 */
			Button.classes = classes;

			/**
			 * Delay of highlight on hover
			 * @property {number} [hoverDelay=0]
			 * @member ns.widget.mobile.Button
			 * @static
			 */
			Button.hoverDelay = 0;

			// Return not disabled button element which is the closest to element and has div container
			// @method closestEnabledButtonInDiv
			// @param {HTMLElement} element
			// @return {HTMLElement}
			// @private
			// @static
			// @member ns.widget.mobile.Button
			function closestEnabledButtonInDiv(element) {
				var div = selectorsUtils.getClosestBySelector(element, "." + classes.uiBtn + ":not(." + classes.uiDisabled + ")"),
					button;
				if (div) {
					button = selectorsUtils.getChildrenByClass(div, classes.uiBtnHidden);
					if (button.length) {
						div = button[0];
					}
				}
				return div;
			}

			// Return not disabled button element which is the closest to element
			// @method closestEnabledButton
			// @param {HTMLElement} element
			// @return {HTMLElement}
			// @private
			// @static
			// @member ns.widget.mobile.Button
			function closestEnabledButton(element) {
				return selectorsUtils.getClosestBySelector(element, "." + classes.uiBtn + ":not(." + classes.uiDisabled + ")");
			}

			/**
			 * Return instance of Button widget
			 * @method getInstance
			 * @param {Event} event
			 * @return {?ns.widget.mobile.Button}
			 * @private
			 * @static
			 * @member ns.widget.mobile.Button
			 */
			function getInstance(event) {
				var button = closestEnabledButtonInDiv(event.target),
					instance;
				if (button) {
					instance = engine.getBinding(button, "Button") || engine.getBinding(button, "buttonMarkup");
				}
				return instance;
			}

			/**
			 * Function removes button up theme class and adds button up
			 * @method changeClasses
			 * @param {ns.widget.mobile.Button} instance
			 * @param {string} addedClassPrefix
			 * @param {string} removedClassPrefix
			 * @private
			 * @static
			 * @member ns.widget.mobile.Button
			 */
			function changeClasses(instance, addedClassPrefix, removedClassPrefix) {
				var theme = instance.options.theme,
					buttonClassList = instance.ui.container.classList;
				buttonClassList.remove(removedClassPrefix + theme);
				buttonClassList.add(addedClassPrefix + theme);
			}

			// Add class ui-focus to target element of event
			// @method onFocus
			// @param {Event} event
			// @private
			// @static
			// @member ns.widget.mobile.Button
			function onFocus(event) {
				var button = closestEnabledButton(event.target);
				if (button) {
					button.classList.add(classes.uiFocus);
					button.classList.remove(classes.uiBlur);
				}
			}

			// Remove class ui-focus from target element of event
			// @method onBlur
			// @param {Event} event
			// @private
			// @static
			// @member ns.widget.mobile.Button
			function onBlur(event) {
				var button = closestEnabledButton(event.target);
				if (button) {
					button.classList.add(classes.uiBlur);
					button.classList.remove(classes.uiFocus);
				}
			}

			// Function fires on mouse down event
			// @method onMouseDown
			// @param {Event} event
			// @private
			// @static
			// @member ns.widget.mobile.Button
			function onMouseDown(event) {
				var instance = getInstance(event);

				if (instance) {
					if (Button.hoverDelay) {
						instance.timeout = setTimeout(changeClasses.bind(null, instance,
							classes.uiBtnDownThemePrefix, classes.uiBtnUpThemePrefix), Button.hoverDelay);
					} else {
						changeClasses(instance, classes.uiBtnDownThemePrefix, classes.uiBtnUpThemePrefix);
					}
				}
			}

			// Function fires on mouse up event
			// @method onMouseUp
			// @param {Event} event
			// @private
			// @static
			// @member ns.widget.mobile.Button
			function onMouseUp(event) {
				var instance = getInstance(event);

				if (instance) {
					if (instance.timeout) {
						clearTimeout(instance.timeout);
					}
					changeClasses(instance, classes.uiBtnUpThemePrefix, classes.uiBtnDownThemePrefix);
				}
			}

			// Function fires on mouse over event
			// @method onMouseOver
			// @param {Event} event
			// @private
			// @static
			// @member ns.widget.mobile.Button
			function onMouseOver(event) {
				var instance = getInstance(event);

				if (instance) {
					changeClasses(instance, classes.uiBtnHoverThemePrefix, classes.uiBtnUpThemePrefix);
				}
			}

			// Function fires on mouse out event
			// @method onMouseOut
			// @param {Event} event
			// @private
			// @static
			// @member ns.widget.mobile.Button
			function onMouseOut(event) {
				var instance = getInstance(event);

				if (instance) {
					changeClasses(instance, classes.uiBtnUpThemePrefix, classes.uiBtnHoverThemePrefix);
				}
			}

			// Add events to all buttons
			// @method addGlobalEvents
			// @private
			// @static
			// @member ns.widget.mobile.Button
			function addGlobalEvents() {
				if (!eventsAdded) {
					document.addEventListener("focus", onFocus, true);
					document.addEventListener("focusin", onFocus, true);
					document.addEventListener("blur", onBlur, true);
					document.addEventListener("focusout", onBlur, true);
					document.addEventListener("vmousedown", onMouseDown, true);
					document.addEventListener("vmouseup", onMouseUp, true);
					document.addEventListener("vmousecancel", onMouseUp, true);
					document.addEventListener("vmouseup", onMouseUp, true);
					document.addEventListener("touchend", onMouseUp, true);
					document.addEventListener("touchcancel", onMouseUp, true);
					document.addEventListener("vmouseover", onMouseOver, true);
					document.addEventListener("focus", onMouseOver, true);
					document.addEventListener("vmouseout", onMouseOut, true);
					document.addEventListener("blur", onMouseOut, true);
					document.addEventListener("scrollstart", onMouseOut, true);
					eventsAdded = true;
				}
			}

			// Removes disabled attributes and removes uiDisabled class
			// @method enableElement
			// @param {HTMLElement} element html element to enable
			// @param {HTMLElement} divElement html container of element to enable
			// @private
			// @static
			// @member ns.widget.mobile.Button
			function enableElement(element, divElement) {
				if (element) {
					divElement.removeAttribute("disabled");
					element.setAttribute("aria-disabled", false);
					element.classList.remove(classes.uiDisabled);
				}
			}

			// Adds disabled attributes and uiDisabled class
			// @method disableElement
			// @param {HTMLElement} element html element to disable
			// @param {HTMLElement} divElement html container of element to disable
			// @private
			// @static
			// @member ns.widget.mobile.Button
			function disableElement(element, divElement) {
				if (element) {
					divElement.setAttribute("disabled", "disabled");
					element.setAttribute("aria-disabled", true);
					element.classList.add(classes.uiDisabled);
				}
			}

			/**
			 * Configure button widget
			 * @method _configure
			 * @param {HTMLElement} element
			 * @protected
			 * @member ns.widget.mobile.Button
			 */
			prototype._configure = function (element) {
				var prototypeOptions = prototype.options,
					options;
				/**
				 * All possible widget options
				 * @property {Object} options
				 * @property {?string} [options.theme=null] theme of widget
				 * @property {?string} [options.icon=null] icon type
				 * @property {"left"|"right"|"top"|"bottom"|null} [options.iconpos=null] position of icon
				 * @property {?string} [options.inline=null] if value is "true" then button has css property display = "inline"
				 * @property {boolean} [options.shadow=true] shadow of button
				 * @property {boolean} [options.iconshadow=true] shadow of button's icon
				 * @property {boolean} [options.corners=false] corners of button
				 * @property {?boolean} [options.mini=null] size of button
				 * @property {boolean} [options.bar=false] if button is part of bar then you should set true
				 * @property {"circle"|"nobg"|null} [options.style=null] style of button
				 * @property {"span"|"div"} [options.wrapperEls="span"] wrapper tag name of button
				 * @member ns.widget.mobile.Button
				 */
				ns.util.object.merge(this.options, prototypeOptions);

				options = this.options;

				// Set theme
				options.theme = themes.getInheritedTheme(element, (prototypeOptions && prototypeOptions.theme) || "s");

			};

			/**
			 * Remove all classes started from given prefix
			 * @method removePrefixesClasses
			 * @param {DOMTokenList} classList
			 * @param {string} prefix
			 * @private
			 * @static
			 * @member ns.widget.mobile.Button
			 */
			function removePrefixesClasses(classList, prefix) {
				var classListLength = classList.length,
					className;
				while (classListLength-- > 0) {
					className = classList.item(classListLength);
					if (className.indexOf(prefix) === 0) {
						classList.remove(className);
					}
				}
			}

			/**
			 * Method clear all classes depends from options before set new options
			 * @method _clearClasses
			 * @param {HTMLElement} element
			 * @protected
			 * @member ns.widget.mobile.Button
			 */
			prototype._clearClasses = function (element) {
				var ui = this.ui,
					textClassList = ui.buttonText.classList,
					innerClassList = ui.inner.classList,
					elementClassList = element.classList;

				removePrefixesClasses(textClassList, classes.uiBtnTextPaddingPrefix);

				innerClassList.remove(classes.uiBtnIconOnlyInner);

				elementClassList.remove(classes.uiBtnIconOnly);
				removePrefixesClasses(elementClassList, classes.uiIconPositionPrefix);
			};

			/**
			 * Method to reset icon from button
			 * @method _resetIcon
			 * @protected
			 * @member ns.widget.mobile.Button
			 */
			prototype._resetIcon = function () {
				var ui = this.ui,
					iconElement = ui.icon;
				if (iconElement) {
					iconElement.parentElement.removeChild(iconElement);
					ui.icon = null;
				}
			};

			/**
			 * Set icon shadow classes
			 * @method _setIconShadow
			 * @protected
			 * @member ns.widget.mobile.Button
			 */
			prototype._setIconShadow = function () {
				if (this.options.iconshadow) {
					this.ui.icon.classList.add(classes.uiIconShadow);
				}
			};

			/**
			 * Set icon position classes
			 * @method _setIconPos
			 * @param {HTMLElement|HTMLInputElement|HTMLButtonElement} element
			 * @protected
			 * @member ns.widget.mobile.Button
			 */
			prototype._setIconPos = function (element) {
				var self = this,
					ui = self.ui,
					optionIconpos = self.options.iconpos || "left",
					innerText = element.value || element.textContent,
					innerTextLength = innerText.length;

				element.classList.add(classes.uiBtnIconPositionPrefix + optionIconpos);

				if (innerTextLength > 0) {
					ui.buttonText.classList.add(classes.uiBtnTextPaddingPrefix + optionIconpos);
				}
			};

			/**
			 * Set title for button without showing text
			 * @method _setTitleForIcon
			 * @param {HTMLElement|HTMLInputElement|HTMLButtonElement} element
			 * @protected
			 * @member ns.widget.mobile.Button
			 */
			prototype._setTitleForIcon = function (element) {
				var self = this,
					elementTagName = element.tagName.toLowerCase(),
					options = self.options,
					buttonText = self.ui.buttonText;
				// Add title to element if button not has text.
				if (options.iconpos === "notext" && !element.getAttribute("title")) {
					element.setAttribute("title", element.textContent);
				}
				if (!buttonText.innerHTML.length && elementTagName !== "label") {
					self._setValue(options.icon.replace("naviframe-", ""));
				}
			};

			/**
			 * Create icon element and set correct classes
			 * @method _createIcon
			 * @protected
			 * @member ns.widget.mobile.Button
			 */
			prototype._createIcon = function mobileButtonCreateIcon(element) {
				var iconElement = document.createElement("span"),
					iconElementClassList = iconElement.classList,
					ui = this.ui;

				// Due to visibility non-breaking space on button cancel
				// in SearchBar widget
				if (this.options.icon !== "cancel") {
					iconElement.innerHTML = "&#160;";
				}
				// Set icon classes
				iconElementClassList.add(classes.uiIcon);
				iconElementClassList.add(classes.uiIconPrefix + this.options.icon);

				//set icon information on container
				if (element) {
					element.classList.add(classes.uiBtnIconPrefix + this.options.icon);
				}

				// Add icon element to DOM
				ui.inner.appendChild(iconElement);
				ui.icon = iconElement;
			};

			/**
			 * Set text classes connected with icon
			 * @method _setIconTextOnly
			 * @param {HTMLElement|HTMLInputElement|HTMLButtonElement} element
			 * @protected
			 * @member ns.widget.mobile.Button
			 */
			prototype._setIconTextOnly = function (element) {
				var innerText = element.value || element.textContent,
					innerTextLength = innerText.length,
					elementClassList = element.classList,
					innerClassList = this.ui.inner.classList;

				if (!innerTextLength) {
					elementClassList.add(classes.uiBtnIconOnly);
					innerClassList.add(classes.uiBtnIconOnlyInner);
				}
			};

			/**
			 * Set class has text if is any text to show in button
			 * @method _setHasText
			 * @param {HTMLElement|HTMLInputElement|HTMLButtonElement} element
			 * @protected
			 * @member ns.widget.mobile.Button
			 */
			prototype._setHasText = function (element) {
				var innerText = element.value || element.textContent,
					innerTextLength = innerText.length,
					innerClassList = this.ui.inner.classList;
				if (innerTextLength > 0) {
					innerClassList.add(classes.uiBtnHastxt);
				}
			};

			/**
			 * Method to create/rebuild icon element in button
			 * @method _buildIcon
			 * @param {HTMLElement|HTMLInputElement|HTMLButtonElement} element
			 * @protected
			 * @member ns.widget.mobile.Button
			 */
			prototype._buildIcon = function (element) {
				var self = this;

				//Set icon options
				if (self.options.icon) {
					self._setIconPos(element);
					self._setIconTextOnly(element);
					self._createIcon(element);
					self._setIconShadow();
					self._setTitleForIcon(element);
				}
			};

			/**
			* Build structure of button widget
			* @method _build
			* @param {HTMLElement|HTMLInputElement} element
			* @return {HTMLElement}
			* @protected
			* @member ns.widget.mobile.Button
			*/
			prototype._build = function (element) {
				var self = this,
					ui = self.ui,
					attributes = {
						"disabled": element.getAttribute("disabled")
					},
					buttonInner,
					buttonText,
					buttonIcon,
					buttonStyle,
					buttonClassList,
					buttonClassArray = [],
					elementTagName,
					elementTypeName,
					innerClass = classes.uiBtnInner,
					textClass = classes.uiBtnText,
					options = this.options,
					buttonValue,
					buttonInnerHTML,
					container,
					innerTextLength,
					label,
					prototypeOptions = prototype.options,
					i;

				// Create default structure of button
				buttonInner = document.createElement(options.wrapperEls);
				buttonInner.id = element.id + "-div-inner";
				buttonText = document.createElement(options.wrapperEls);
				buttonText.id = element.id + "-div-text";

				this.ui.buttonText = buttonText;

				elementTagName = element.tagName.toLowerCase();
				elementTypeName = element.type;
				buttonClassList = element.classList;

				if (elementTagName === "input" && elementTypeName === "button") {
					options.corners = true;
				}
				buttonClassArray.push(classes.uiBtn, classes.uiBtnUpThemePrefix + options.theme);
				if (options.shadow) {
					buttonClassArray.push(classes.uiShadow);
				}
				if (options.corners) {
					buttonClassArray.push(classes.uiBtnCornerAll);
				}

				buttonInnerHTML = element.innerHTML;
				buttonValue = element.value;

				buttonStyle = options.style;

				if (elementTagName === "a") {
					container = element;
				} else {
					if (elementTagName === "button" || elementTagName === "input") {
						buttonClassList.add(classes.uiBtnHidden);
						container = document.createElement("div");
						container.setAttribute("id", element.id + "-div-container");

						if (buttonClassList.contains(classes.uiBtnRight)) {
							container.classList.add(classes.uiBtnRight);
						} else if (buttonClassList.contains(classes.uiBtnLeft)) {
							container.classList.add(classes.uiBtnLeft);
						}
						if (elementTypeName === "submit" || elementTypeName === "reset") {
							container.classList.add(classes.uiSubmit);
						}
					} else {
						container = element;
					}

					label = document.querySelector("label[for='" + element.id + "']");
					if (label) {
						label.classList.add(classes.uiSubmit);
					}
				}

				container.setAttribute("tabindex", 0);
				if ( (element.getAttribute("data-role") === "button" && !options.bar) ||
					(elementTagName === "input" && ((elementTypeName === "submit") || (elementTypeName === "reset") || (elementTypeName === "button")) ) ||
					(elementTagName === "button") ) {
					buttonClassArray.push(classes.uiBtnBoxThemePrefix + options.theme);
				}

				innerTextLength = element.textContent.length || (element.value ? element.value.length : 0);

				switch (buttonStyle) {
				case "circle":
					if (innerTextLength > 0) {
						buttonClassArray.push(classes.uiBtnRound);
					} else {
						buttonClassArray.push(classes.uiBtnCornerCircle, classes.uiBtnIconOnly);
						if (options.icon) {
							// Style: no text, Icon only
							innerClass += " " + classes.uiBtnCornerCircle;
						} else {
							buttonClassArray.push(classes.uiBtnRound);
						}
					}
					break;
				case "nobg":
					buttonClassArray.push(classes.uiBtnIconNobg, classes.uiBtnIconOnly);
					if (options.icon && innerTextLength <= 0) {
						// Style: no text, Icon only, no background
						innerClass += " " + classes.uiBtnIconNobg;
					}
					break;
				case "edit":
					buttonClassArray.push(classes.uiBtnEdit);
					break;
				case "round":
					buttonClassArray.push(classes.uiBtnRound);
					break;
					default:
				}

				// Used to control styling in headers/footers, where buttons default to `mini` style.
				if (options.mini) {
					buttonClassArray.push(classes.uiMini);
				}

				// Used to control styling in headers/footers, where buttons default to `inline` style.
				if (options.inline !== null) {
					buttonClassArray.push(options.inline ? classes.uiBtnInline : classes.uiBtnBlock);
				}

				// Default disable element
				if (attributes.disabled) {
					disableElement(element, container);
				} else {
					enableElement(element, container);
				}

				innerClass += options.corners ? " "  + classes.uiBtnCornerAll : "";

				// Copy classes of structure
				buttonClassList = container.classList;
				buttonClassList.remove(classes.uiLink);

				// Copy all classes from buttonClassArray to buttonClassList
				i = buttonClassArray.length;
				while (--i >= 0) {
					buttonClassList.add(buttonClassArray[i]);
				}

				buttonInner.className = innerClass;
				buttonText.className = textClass;
				buttonInner.appendChild(buttonText);

				// copy inner structure of button to new tag
				while (element.firstChild) {
					buttonText.appendChild(element.firstChild);
				}

				if (elementTagName === "button" || elementTagName === "input") {
					ns.util.DOM.replaceWithNodes(element, container);
					container.appendChild(buttonInner);
					container.appendChild(element);
					if (buttonInnerHTML) {
						container.firstChild.firstChild.innerHTML = buttonInnerHTML;
						element.innerHTML = buttonInnerHTML;
					} else {
						container.firstChild.firstChild.textContent = buttonValue;
						element.value = buttonValue;
					}
				} else {
					element.appendChild(buttonInner);
				}

				ui.container = container;
				ui.inner = buttonInner;

				self._setHasText(element);
				self._buildIcon(element);

				element.setAttribute("tabindex", 0);

				return element;
			};

			/**
			* Init widget
			* @method _init
			* @param {HTMLElement} element
			* @protected
			* @member ns.widget.mobile.Button
			*/
			prototype._init = function (element) {
				var container = document.getElementById(element.id + "-div-container");
				if (!container) {
					container = element;
				}
				this.ui.container = container;
				this.ui.buttonText = document.getElementById(element.id + "-div-text");
				this.ui.inner = document.getElementById(element.id + "-div-inner");
			};

			/**
			* Bind events to widget
			* @method _bindEvents
			* @protected
			* @member ns.widget.mobile.Button
			*/
			prototype._bindEvents = function () {
				addGlobalEvents();
			};

			/**
			 * Enable the button
			 *
			 * Method removes disabled attribute on button and changes look of button to enabled state.
			 *
			 *	@example
			 *	<div data-role="button" id="button"></div>
			 *	<script>
			 *		var element = document.getElementById("button"),
			 *			buttonWidget = tau.widget.Button(element);
			 *		buttonWidget.enable();
			 *
			 *	</script>
			 *
			 *	@example
			 *	<div data-role="button" id="button"></div>
			 *	<script>
			 *		$( "#button" ).button( "enable" );
			 *	</script>
			 *
			 * @method enable
			 * @chainable
			 * @member ns.widget.mobile.Button
			 */

			/**
			* Enable button
			* @method _enable
			* @param {HTMLElement} element
			* @protected
			* @member ns.widget.mobile.Button
			*/
			prototype._enable = function (element) {
				if (element) {
					enableElement(element, this.ui.container);
				}
			};

			/**
			 * Get or set value
			 *
			 * Return inner text of button or set text on button
			 *
			 *	@example
			 *	<div data-role="button" id="button"></div>
			 *	<script>
			 *		var element = document.getElementById("button"),
			 *			buttonWidget = tau.widget.Button(element),
			 *			// value contains inner text of button
			 *			value = buttonWidget.value();
			 *
			 *		buttonWidget.value( "New text" ); // "New text" will be text of button
			 *	</script>
			 *
			 *	@example
			 *	<div data-role="button" id="button"></div>
			 *	<script>
			 *		// value contains inner text of button
			 *		$( "#button" ).button( "value" );
			 *
			 * 		// "New text" will be text of button
			 *		$( "#button" ).button( "value", "New text" );
			 *	</script>
			 *
			 * @method value
			 * @param {string} [value] Value to set on button
			 * @return {string} In get mode return inner text of button.
			 * @since 2.3
			 * @member ns.widget.mobile.Button
			 */

			/**
			 * Get value of button
			 * @method _getValue
			 * @protected
			 * @member ns.widget.mobile.Button
			 */
			prototype._getValue = function () {
				return this.ui.buttonText.textContent;
			};

			/**
			 * Set value of button
			 * @method _setValue
			 * @param {HTMLElement} element
			 * @param {string} value
			 * @protected
			 * @member ns.widget.mobile.Button
			 */
			prototype._setValue = function (value) {
				var elementTagName,
					ui = this.ui,
					element = this.element || ui.container;

				elementTagName = element.tagName.toLowerCase();

				ui.buttonText.textContent = value;

				if (elementTagName === "button" || elementTagName === "input") {
					element.textContent = value;
					element.value = value;
				}
			};

			/**
			 * Disable the button
			 *
			 * Method sets disabled attribute on button and changes look of button to disabled state.
			 *
			 *	@example
			 *	<div data-role="button" id="button"></div>
			 *	<script>
			 *		var element = document.getElementById("button"),
			 *			buttonWidget = tau.widget.Button(element);
			 *		buttonWidget.disable();
			 *
			 *	</script>
			 *
			 *	@example
			 *	<div data-role="button" id="button"></div>
			 *	<script>
			 *		$( "#button" ).button( "disable" );
			 *	</script>
			 *
			 * @method disable
			 * @chainable
			 * @member ns.widget.mobile.Button
			 */

			/**
			* Disable button
			* @method _disable
			* @param {HTMLElement} element
			* @protected
			* @member ns.widget.mobile.Button
			*/
			prototype._disable = function (element) {
				if (element) {
					disableElement(element, this.ui.container);
				}
			};

			/**
			 * Refresh a button markup.
			 *
			 * This method will rebuild while DOM structure of widget.
			 *
			 * This method should be called after are manually change in HTML attributes of widget DOM structure.
			 *
			 * This method is called automatically after change any option of widget.
			 *
			 *	@example
			 *	<div data-role="button" id="button"></div>
			 *	<script>
			 *		var element = document.getElementById("button"),
			 *			buttonWidget = tau.widget.Button(element);
			 *		buttonWidget.refresh();
			 *
			 *		// also will be called after
			 *
			 *		buttonWidget.option("mini", true);
			 *	</script>
			 *
			 *	@example
			 *	<div data-role="button" id="button"></div>
			 *	<script>
			 *		$( "#button" ).button( "refresh" );
			 *	</script>
			 *
			 * @method refresh
			 * @chainable
			 * @member ns.widget.mobile.Button
			 */

			/**
			* Refresh button
			* @method _refresh
			* @protected
			* @member ns.widget.mobile.Button
			*/
			prototype._refresh = function () {
				var self = this,
					element = self.element,
					container = self.ui.container,
					tagName = element.tagName.toLowerCase();
				if (element) {
					if (element.getAttribute("disabled")) {
						self.disable(element);
					} else {
						self.enable(element);
					}
					if (tagName === "button" || tagName === "input") {
						if (element.innerHTML) {
							container.firstChild.firstChild.innerHTML = element.innerHTML;
						} else {
							container.firstChild.firstChild.textContent = element.value;
						}
					}
					self._clearClasses(element);
					self._resetIcon();
					self._setHasText(element);
					self._buildIcon(element);
				}
			};

			// definition
			//@todo bring back ui-btn selector and refactor _build method to make it more intelligent for checking if structure is build
			ns.widget.mobile.Button = Button;
			engine.defineWidget(
				"Button",
				"[data-role='button'], button, [type='button'], [type='submit'], [type='reset'], .ui-button",
				[],
				Button,
				"mobile"
			);
			// ButtonMarkup is alias for Button widget
			// required for backward compatibility with jQM
			engine.defineWidget(
				"buttonMarkup",
				"",
				[],
				Button,
				"mobile",
				false, // redefine: false
				false // change name of widget to lowercase: false
			);
			}(window.document, ns));


/*jslint nomen: true, plusplus: true */
/*
* Copyright  2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/**
 * #Page Widget
 * Page widget represents the screen of an application
 *
 * ## Default selectors
 * All elements which have a class _.ui-page or a _data-role=page
 * will become Page widgets
 *
 * ### HTML examples
 *
 * #### Create a page widget using the data-role attribute
 *
 *		@example
 *		<div data-role="page">
 *			<div data-role="content">
 *				page content
 *			</div>
 *		</div>
 *
 * #### Create page widget using data-role attribute with header and footer
 *
 *		@example
 *		<div data-role="page">
 *			<div data-role="header">
 *				My Page
 *			</div>
 *			<div data-role="content">
 *				page contents
 *			</div>
 *			<div data-role="footer">
 *				Status: OK
 *			</div>
 *		</div>
 *
 * #### Create a page widget using css classes
 *
 *		@example
 *		<div class="ui-page">
 *			<div class="ui-content">
 *				page content
 *			</div>
 *		</div>
 *
 * #### Create a page widget using css classes with header and footer
 *
 *		@example
 *		<div class="ui-page">
 *			<div class="ui-header">
 *				My Page
 *			</div>
 *			<div class="ui-content">
 *				page contents
 *			</div>
 *			<div class="ui-footer">
 *				Status: OK
 *			</div>
 *		</div>
 *
 * ### Manual constructor
 *
 * Thease examples show how to create a Page widget by hand using
 * JavaScript code
 *
 * #### Created using TAU api
 *
 *		@example
 *		<div id="myPage"></div>
 *		<script type="text/javascript">
 *			var page = tau.widget.Page(document.getElementById("myPage"));
 *		</script>
 *
 * #### Created using jQuery api
 *
 *		@example
 *		<div id="myPage"></div>
 *		<script type="text/javascript">
 *			var page = $("#myPage").page();
 *		</script>
 *
 * ## Options for Page widget
 *
 * Options can be set by using data-* attributes or by passing them
 * to the constructor.
 *
 * There is also a method **option** for changing them after widget
 * creation.
 *
 * jQuery mobile format is also supported.
 *
 * ### Fullscreen
 *
 * Determines if the page is shown fullscreen. The default value is
 * *false*.
 *
 * You can change this by all available methods for options setting.
 *
 * #### By data-fullscreen attribute
 *
 *		@example
 *		<div data-role="page" data-fullscreen="true"></div>
 *
 * #### By config object passed to constructor
 *
 *		@example
 *		<div id="myPage"></div>
 *		<script type="text/javascript">
 *			var page = tau.widget.Page(document.getElementById("myPage"), {"fullscreen": true});
 *		</script>
 *
 * #### By setting the option after widget creation
 *
 *		@example
 *		<div data-role="page"></div>
 *		<script type="text/javascript">
 *			var page = tau.widget.Page(document.getElementById("myPage"));
 *			page.option("fullscreen", true);
 *		</script>
 *
 * #### By using jQuery API
 *
 *		@example
 *		<div data-role="page"></div>
 *		<script type="text/javascript">
 *			$("#myPage").page({"fullscreen": true});
 *		</script>
 *
 * ### Themes
 *
 * By using theme options we can change the default theme of a Page
 *
 * Possible theme options are: *theme*, *contentTheme*, *footerTheme*
 * and *headerTheme*. The default value for all of them is *"a"*.
 *
 * #### Using data-* attributes
 *		@example
 *		<div data-role="page" data-theme="s" data-content-theme="s" data-footer-theme="s"></div>
 *
 * #### Using config object passed to constructor
 *
 *		@example
 *		<div id="myPage"></div>
 *		<script type="text/javascript">
 *			var page = tau.widget.Page(document.getElementById("myPage"), {
 *				"theme": "s",
 *				"footerTheme": "s",
 *				"contentTheme": "s"
 *			});
 *		</script>
 *
 * #### Using jQuery API
 *
 *		@example
 *		<div id="myPage"></div>
 *		<script type="text/javascript">
 *			var page = $("#myPage").page({
 *				"theme": "s",
 *				"footerTheme": "s",
 *				"contentTheme": "s"
 *			});
 *		</script>
 *
 * ## Methods
 *
 * Page methods can be can be accessed trough 2 APIs: TAU API and jQuery
 * API (jQuery Mobile-like API)
 *
 * **WARNING** Some methods are not accessible through jQuery API
 * since jQuery already supplies functionalities for them (ex. focus).
 *
 * @class ns.widget.mobile.Page
 * @extends ns.widget.mobile.BaseWidgetMobile
 *
 * @author Hyunkook Cho <hk0713.cho@samsung.com>
 * @author Junhyeon Lee <juneh.lee@samsung.com>
 * @author Damian Osipiuk <d.osipiuk@samsung.com>
 * @author Jadwiga Sosnowska <j.sosnowska@samsung.com>
 * @author Krzysztof Antoszek <k.antoszek@samsung.com>
 * @author Krzysztof Głodowski <k.glodowski@samsung.com>
 * @author Maciej Moczulski <m.moczulski@samsung.com>
 * @author Maciej Urbanski <m.urbanski@samsung.com>
 * @author Piotr Karny <p.karny@samsung.com>
 */

/**
 * Triggered before switching current page
 * @event pagebeforchange
 * @member ns.widget.mobile.Page
 */

/**
 * Triggered before the widget is created and initialized
 * @event pagebeforecreate
 * @member ns.widget.mobile.Page
 */

/**
 * Triggered before current page is about to be closed
 * @event pagebeforehide
 * @member ns.widget.mobile.Page
 */

/**
 * Triggered before external page will be loaded
 * @event pagebeforeload
 * @member ns.widget.mobile.Page
 */

/**
 * Triggered before page will be displayed
 * @event pagebeforeshow
 * @member ns.widget.mobile.Page
 */

/**
 * Triggered after switching current page
 * @event pagechange
 * @member ns.widget.mobile.Page
 *
 */

/**
 * Triggered when page switching failed
 * @event pagechangefailed
 * @member ns.widget.mobile.Page
 */

/**
 * Triggered after widget creation
 * @event pagecreate
 * @member ns.widget.mobile.Page
 */

/**
 * Triggered after the page is hidden
 * @event pagehide
 * @member ns.widget.mobile.Page
 */

/**
 * Triggered after widget initialization occurs
 * @event pageinit
 * @member ns.widget.mobile.Page
 */

/**
 * Triggered after an external page is loaded
 * @event pageload
 * @member ns.widget.mobile.Page
 */

/**
 * Triggered after the external page is removed from the DOM
 * @event pagremove
 * @member ns.widget.mobile.Page
 */

/**
 * Triggered after the page is displayed
 * @event pageshow
 * @member ns.widget.mobile.Page
 */

(function (ns) {
	
				var BaseWidget = ns.widget.mobile.BaseWidgetMobile,
				engine = ns.engine,
				selectors = ns.util.selectors,
				object = ns.util.object,
				utilsDOM = ns.util.DOM,
				slice = [].slice,
				Page = function () {
					/**
					 * @property {boolean} [pageSetHeight=false] The flag is indicates that height of the page  was set by framework
					 * @member ns.widget.mobile.Page
					 */
					this.pageSetHeight = false;
					this.contentFillCallback = null;
					this.contentFillAfterResizeCallback = null;
					this.destroyCallback = null;
					this.options = object.copy(Page.prototype.options);
				};

			/**
			 * Dictionary for page related css class names
			 * @property {Object} classes
			 * @property {string} [classes.uiPrefix='ui-'] Main ui prefix
			 * @property {string} [classes.uiBarPrefix='ui-bar-'] Ui bar prefix
			 * @property {string} [classes.uiBodyPrefix='ui-body-'] Ui body prefix
			 * @property {string} [classes.uiBtnBack='ui-btn-back'] Button class
			 * @property {string} [classes.uiTabbarMargin-back='ui-tabbar-margin-back'] Tabbar margin class
			 * @property {string} [classes.uiTitle='ui-title'] Title class
			 * @property {string} [classes.uiTitleTextStub='ui-title-text-stub'] Title stub class
			 * @property {string} [classes.uiTitleMultiline='ui-title-multiline'] Title multiline class
			 * @property {string} [classes.uiPage='ui-page'] Main page class
			 * @property {string} [classes.uiPageActive='ui-page-active'] Page active class
			 * @property {string} [classes.uiPageHeaderFullscreen='ui-page-header-fullscreen'] Page header fullscreen class
			 * @property {string} [classes.uiPageFooterFullscreen='ui-page-footer-fullscreen'] Page footer fullscreen class
			 * @property {string} [classes.uiPageHeaderFixed='ui-page-header-fixed'] Page header fixed class
			 * @property {string} [classes.uiPageFooterFixed='ui-page-footer-fixed'] Page footer fixed class
			 * @property {string} [classes.uiOverlayPrefix='ui-overlay-'] Ui overlay prefix
			 * @property {string} [classes.uBtnLeft='ui-btn-left'] Left button class
			 * @property {string} [classes.uiBtnRight='ui-btn-right'] Right button class
			 * @property {string} [classes.uiBtnRightPrefix='ui-btn-right-'] Right button prefix
			 * @property {string} [classes.fixedSuffix='-fixed'] Class fixed suffix
			 * @property {string} [classes.fullscreenSuffix='-fullscreen'] class fullscreen suffix
			 * @member ns.widget.mobile.Page
			 * @static
			 * @readonly
			 */
			Page.classes = {
				uiPrefix: "ui-",
				uiBarPrefix: "ui-bar-",
				uiBodyPrefix: "ui-body-",
				uiBtnBack: "ui-btn-back",
				uiTabbarMarginBack: "ui-tabbar-margin-back",
				uiTitle: "ui-title",
				uiTitleTextSub: "ui-title-text-sub",
				uiTitleMultiline: "ui-title-multiline",
				uiFooterBtn: "ui-footer-btn-",
				uiPage: "ui-page",
				uiPageActive: "ui-page-active",
				uiPageContent: "ui-content",
				uiPageHeader: "ui-header",
				uiPageFooter: "ui-footer",
				uiPageHeaderFullscreen: "ui-page-header-fullscreen",
				uiPageFooterFullscreen: "ui-page-footer-fullscreen",
				uiPageHeaderFixed: "ui-page-header-fixed",
				uiPageFooterFixed: "ui-page-footer-fixed",
				uiOverlayPrefix: "ui-overlay-",
				uiBtnLeft: "ui-btn-left",
				uiBtnRight: "ui-btn-right",
				uiBtnRightPrefix: "ui-btn-right-",
				fixedSuffix: "-fixed",
				fullscreenSuffix: "-fullscreen"
				// @todo put all used classes here
			};

			Page.prototype = new BaseWidget();

			/**
			 * Object with default options
			 * @property {Object} options
			 * @property {boolean} [options.fullscreen=false] Fullscreen page flag
			 * @property {string} [options.theme='a'] Page theme
			 * @property {boolean} [options.domCache=false] Use DOM cache
			 * @property {?string} [options.contentTheme=null] Page content theme
			 * @property {string} [options.headerTheme='a'] Page header theme. If headerTheme is empty `theme` will be used
			 * @property {string} [options.footerTheme='a'] Page footer theme. If footerTheme is empty `theme` will be used
			 * @member ns.widget.mobile.Page
			 */
			Page.prototype.options = {
				fullscreen: false,
				theme: "a",
				domCache: false,
				keepNativeDefault: ns.getConfig("keepNative"),
				contentTheme: null,
				headerTheme: "a",
				footerTheme: "a",
				// @removed
				addBackBtn: false,
				enhanced: false
			};

			/**
			 * Text of back button
			 * @property {string} [backBtnText='Back']
			 * @member ns.widget.mobile.Page
			 * @protected
			 * @deprecated 2.3
			 */
			Page.prototype.backBtnText = "Back";

			/**
			 * Theme of back button
			 * @property {string} [backBtnTheme=null]
			 * @member ns.widget.mobile.Page
			 * @deprecated 2.3
			 */
			Page.prototype.backBtnTheme = null;

			// Sets top-bottom css attributes for content element
			// to allow it to fill the page dynamically
			// @method contentFill
			// @param {ns.widget.mobile.Page} self
			function contentFill(self) {
				var content,
					contentStyle,
					element = self.element,
					header,
					headerDivider,
					headerBtn,
					headerBtnWidth = 0,
					pageClasses = Page.classes,
					top = 0,
					bottom = 0,
					i,
					footer,
					len;

				if (element && !self.pageSetHeight && element.classList.contains(Page.classes.uiPageActive)) {
					content = element.querySelector("[data-role=content],." + pageClasses.uiPageContent);
					if (content) {
												contentStyle = content.style;
						header = element.querySelector("[data-role=header],." + pageClasses.uiPageHeader);

						if (header) {
							headerDivider = header.getElementsByClassName("ui-header-divider");
							len = headerDivider.length;
							if (len) {
								headerBtn = header.getElementsByClassName("ui-btn");
								// Header divider exist
								for (i = 0; i < len; i++) {
									headerBtnWidth += headerBtn[i].offsetWidth;
									headerDivider[i].style.right = headerBtnWidth + "px";
								}
							}
							top = utilsDOM.getElementHeight(header);
						}

						footer = element.querySelector("[data-role=footer],." + pageClasses.uiPageFooter);
						bottom = utilsDOM.getElementHeight(footer);

						contentStyle.top = top + "px";
						contentStyle.bottom = bottom + "px";
						contentStyle.height = utilsDOM.getElementHeight(content.parentNode) - top - bottom + "px";
						self.pageSetHeight = true;
					}
				}
			}

			// Build header/footer/content
			// @method buildSections
			// @param {Object} options Object with options for widget
			// @param {HTMLElement} pageElement main element of widget
			// @param {string} pageTheme page theme name
			function buildSections(options, pageElement, pageTheme) {
				var pageClassList = pageElement.classList,
					pageClasses = Page.classes,
					fullscreen = options.fullscreen;

				if (fullscreen) {
					// "fullscreen" overlay positioning
					pageClassList.add(pageClasses.uiPageHeaderFullscreen);
					pageClassList.add(pageClasses.uiPageFooterFullscreen);
				} else {
					// If not fullscreen, add class to page to set top or bottom padding
					pageClassList.add(pageClasses.uiPageHeaderFixed);
					pageClassList.add(pageClasses.uiPageFooterFixed);
				}

				[].slice.call(pageElement.querySelectorAll("[data-role='header'],[data-role='content'],[data-role='footer'],." +
						pageClasses.uiPageHeader +
						",." + pageClasses.uiPageContent +
						",." + pageClasses.uiPageFooter))
					.forEach(function (section) {
						var role = section.getAttribute("data-role"),
							sectionTheme = section.getAttribute("data-theme"),
							currentTheme,
							sectionClassList = section.classList,
							transition,
							headerButtons,
							headerButtonsWidth = 0,
							headerAnchors,
							headerDivider,
							footerButtons,
							footerWidth,
							moreButton,
							leftButton,
							rightButton,
							previousElementOfHeaderButton;

						if (!role) {
							if (sectionClassList.contains(pageClasses.uiPageHeader)) {
								role = "header";
							} else if (sectionClassList.contains(pageClasses.uiPageContent)) {
								role = "content";
							} else {
								role = "footer";
							}

							section.setAttribute("data-role", role);
						}

						sectionClassList.add(pageClasses.uiPrefix + role);

						// Adding transition classes for all matched elements
						// @todo support transition form config
						transition = section.getAttribute("data-transition") || "";

						if (transition && transition !== "none") {
							if (transition === "slide") {
								transition = role === "header" ? "slidedown" : "slideup";
							}
							sectionClassList.add(transition);
						}

						if (role === "content") {
							section.setAttribute("role", "main");
							currentTheme = sectionTheme || options.contentTheme;
							if (currentTheme) {
								sectionClassList.add(pageClasses.uiBodyPrefix + currentTheme);
							}
						} else {
							currentTheme = sectionTheme || (role === "header" ? options.headerTheme : options.footerTheme) || pageTheme;
							sectionClassList.add(pageClasses.uiBarPrefix + currentTheme);

							// We always set the ui-[header|footer]-fixed class to match Tizen design needs
							sectionClassList.add(pageClasses.uiPrefix + role + pageClasses.fixedSuffix);

							if (fullscreen) {
								sectionClassList.add(pageClasses.uiPrefix + role + pageClasses.fullscreenSuffix);
							}

							section.setAttribute("role", role === "header" ? "banner" : "contentinfo");

							if (role === "header") {
								headerAnchors = selectors.getChildrenBySelector(section, "a, div.naviframe-button, button, [data-role=button]");
								headerAnchors.forEach(function (anchor) {
									var anchorClassList = anchor.classList;
									leftButton = anchorClassList.contains(pageClasses.uiBtnLeft);
									rightButton = anchorClassList.contains(pageClasses.uiBtnRight);
								});

								if (!leftButton && headerAnchors[0] && !headerAnchors[0].classList.contains(pageClasses.uiBtnRight)) {
									leftButton = headerAnchors[0];
									utilsDOM.setNSData(leftButton, "role", "button");
									leftButton.classList.add(pageClasses.uiBtnLeft);
								}

								if (!rightButton && headerAnchors[1]) {
									rightButton = headerAnchors[1];
									utilsDOM.setNSData(rightButton, "role", "button");
									rightButton.classList.add(pageClasses.uiBtnRight);
								}

								headerButtons = selectors.getChildrenBySelector(section, "a,[data-role='button']");
								if (headerButtons.length) {
									headerButtons.forEach(function (button) {
										engine.instanceWidget(button, "Button");
										previousElementOfHeaderButton = button.previousElementSibling;
										// @TODO move this calculation after page show
										headerButtonsWidth += 90;//utilsDOM.getElementWidth(button, true) + 2;

									});
								}
								if (section.querySelector("." + pageClasses.uiTitleTextSub)) {
									sectionClassList.add(pageClasses.uiTitleMultiline);
								}
							} else if (role === "footer") {
								footerButtons = selectors.getChildrenBySelector(section, "a,div.naviframe-button,[data-role='button'],button,[type='button'],[type='submit'],[type='reset']");
								if (footerButtons.length) {
									//TODO rethink this solution
									footerWidth = section.offsetWidth || window.innerWidth;
									moreButton = selectors.getChildrenBySelector(section, "[data-icon='naviframe-more']");
									if (moreButton.length) {
										footerWidth -= utilsDOM.getElementWidth(moreButton[0]);
									}
									footerButtons.forEach(function (button) {
										var buttonStyle = button.style;
										engine.instanceWidget(button, "Button", {
											role: "button"
										});
									});
									section.classList.add(pageClasses.uiFooterBtn + footerButtons.length);
								}
							}

							selectors.getChildrenBySelector(section, "h1, h2, h3, h4, h5, h6").forEach(function (title) {
								var headerImgsWidth = 0,
									headerSrcNum = 0,
									width,
									titleStyle = title.style;

								title.classList.add(pageClasses.uiTitle);
								title.setAttribute("role", "heading");
								title.setAttribute("aria-level", 1);
								title.setAttribute("aria-label", "title");
								width = window.innerWidth - headerButtonsWidth - headerImgsWidth * headerSrcNum * 4;

								titleStyle.width = width + "px";
							});
						}
					});
			}

			// Method builds widget.
			// @method buildStructure
			// @param {Object} options object with options for create page
			// @param {HTMLElement} element base element of page
			function buildStructure(options, element) {
				var pageTheme = options.theme,
					dataPageTitle = utilsDOM.getNSData(element, "title"),
					pageTitle = dataPageTitle,
					titleElement,
					classes = Page.classes;

				element.classList.add(classes.uiPage);
				element.classList.add(classes.uiBodyPrefix + pageTheme);

				if (!pageTitle) {
					titleElement = selectors.getChildrenByDataNS(element, "role=header")[0];
					if (titleElement) {
						titleElement = titleElement.getElementsByClassName(classes.uiTitle)[0];
						if (titleElement) {
							pageTitle = titleElement.innerText;
						}
					}
				}

				if (!dataPageTitle && pageTitle) {
					utilsDOM.setNSData(element, "title", pageTitle);
				}
				buildSections(options, element, pageTheme);
			}

			/**
			 * Build page
			 * @method _build
			 * @param {HTMLElement} element
			 * @return {HTMLElement}
			 * @protected
			 * @member ns.widget.mobile.Page
			 */
			Page.prototype._build = function (element) {
				buildStructure(this.options, element);
				return element;
			};

			/*Page.prototype._updatePadding = function (page) {
				var pageStyle = page.style;
				Array.prototype.slice.call(page.querySelectorAll("[data-role='header'],[data-role='content'],[data-role='footer']")).forEach(function (section) {
					var role = section.getAttribute("data-role"),
						dataposition = section.getAttribute("data-position"),
						sectionStyle = section.style;
					if (dataposition === "fixed") {
						sectionStyle.position = "fixed";
						if (role === "header") {
							pageStyle.paddingTop = section.offsetHeight + "px";
							sectionStyle.top = 0;
						} else if (role === "footer") {
							pageStyle.paddingBottom = section.offsetHeight + "px";
							sectionStyle.bottom = 0;
						}
					}
				});
			};*/

			/**
			 * Set page active / unactive
			 * Sets ui-overlay-... class on `body` depending on current theme
			 *
			 * !!!This method is only available through TAU API!!!
			 *
			 *		@example
			 *		<div id="myPage"></div>
			 *		<script type="text/javascript">
			 *			var page = tau.widget.page(document.getElementById("myPage"));
			 *			page.setActive(true, document.body);
			 *		</script>
			 *
			 * @TODO make params optional (default action should be make page active if
			 * its not in its own container)
			 * @method setActive
			 * @param {boolean} value if true then page will be active if false page will be unactive
			 * @param {HTMLElement} pageContainer
			 * @member ns.widget.mobile.Page
			 */
			Page.prototype.setActive = function (value, pageContainer) {
				var theme = this.options.theme,
					classes = Page.classes,
					themeClass = classes.uiOverlayPrefix + theme,
					bodyClassList = pageContainer.classList;

				if (value) {
					this.element.classList.add(classes.uiPageActive);
					this.focus();
					bodyClassList.add(themeClass);
				} else {
					this.element.classList.remove(classes.uiPageActive);
					this.blur();
					bodyClassList.remove(themeClass);
				}
			};

			/**
			 * GUI Builder only : redesign page when user drag&drop header, footer
			 *
			 * !!!This method is only available through TAU API!!!
			 *
			 *		@example
			 *		<div id="myPage"></div>
			 *		<script type="text/javascript">
			 *			var page = tau.widget.page(document.getElementById("myPage"));
			 *			page.setToolbar();
			 *		</script>
			 *
			 * @method setToolbar
			 * @member ns.widget.mobile.Page
			 */
			Page.prototype.setToolbar = function () {
				this.trigger("pagebeforeshow");
			};

			/**
			 * Removes background from the page containing element
			 *
			 * #### TAU API
			 *
			 *		@example
			 *		<div id="myPage"></div>
			 *		<script type="text/javascript">
			 *			var page = tau.widget.page(document.getElementById("myPage"));
			 *			page.removeContainerBackground();
			 *		</script>
			 *
			 *#### jQuery API
			 *
			 *		@example
			 *		<div id="myPage"></div>
			 *		<script type="text/javascript">
			 *			$("#myPage").page("removeContainerBackground");
			 *		</script>
			 *
			 * @method removeContainerBackground
			 * @member ns.widget.mobile.Page
			 */
			Page.prototype.removeContainerBackground = function () {
				engine.getRouter().getContainer().classList.remove("ui-overlay-" + engine.getTheme().getInheritedTheme(this.element.parentNode));
			};

			/**
			 *  Sets background for page containing element
			 *
			 * #### TAU API
			 *
			 *		@example
			 *		<div id="myPage"></div>
			 *		<script type="text/javascript">
			 *			var page = tau.widget.page(document.getElementById("myPage"));
			 *			page.setContainerBackground("s");
			 *		</script>
			 *
			 * #### jQuery API
			 *
			 *		@example
			 *		<div id="myPage"></div>
			 *		<script type="text/javascript">
			 *			$("#myPage").page("setContainerBackground", "s");
			 *		</script>
			 *
			 * @method setContainerBackground
			 * @param {string} [theme]
			 * @member ns.widget.mobile.Page
			 */
			Page.prototype.setContainerBackground = function (theme) {
				theme = theme || this.options.theme;
				engine.getRouter().getContainer().classList.add("ui-overlay-" + theme);
			};

			/**
			 * Add back button
			 * @method addBackBtn
			 * @deprecated 2.3
			 * @member ns.widget.mobile.Page
			 */
			Page.prototype.addBackBtn = function () {
				return null;
			};

			/**
			 * Returns native selector
			 *
			 * #### TAU API
			 *
			 *		@example
			 *		<div id="myPage"></div>
			 *		<script type="text/javascript">
			 *			var page = tau.widget.page(document.getElementById("myPage")),
			 *				s = page.keepNativeSelector();
			 *		</script>
			 *
			 * #### jQuery API
			 *
			 *		@example
			 *		<div id="myPage"></div>
			 *		<script type="text/javascript">
			 *			var s = $("#myPage").page("keepNativeSelector");
			 *		</script>
			 *
			 * @method keepNativeSelector
			 * @return {string}
			 * @member ns.widget.mobile.Page
			 */
			Page.prototype.keepNativeSelector = function () {
				var options = this.options,
					optionsKeepNative = options.keepNative,
					optionsKeepNativeDefault = options.keepNativeDefault,
					keepNativeDefined = optionsKeepNative && optionsKeepNative.trim();

				if (keepNativeDefined && optionsKeepNative !== optionsKeepNativeDefault) {
					return [optionsKeepNative, optionsKeepNativeDefault].join(", ");
				}

				return optionsKeepNativeDefault;
			};


			/**
			 * This will set the content element's top or bottom padding equal to the toolbar's height
			 *
			 * !!!This method is only available through TAU API!!!
			 *
			 *		@example
			 *		<div id="myPage"></div>
			 *		<script type="text/javascript">
			 *			var page = tau.widget.page(document.getElementById("myPage"));
			 *			page.updatePagePadding();
			 *		</script>
			 *
			 * @method updatePagePadding
			 * @member ns.widget.mobile.Page
			 */
			Page.prototype.updatePagePadding = function () {
				contentFill(this);
			};

			/**
			 * Calculate and update content height
			 *
			 * !!!This method is only available through TAU API!!!
			 *
			 *		@example
			 *		<div id="myPage"></div>
			 *		<script type="text/javascript">
			 *			var page = tau.widget.page(document.getElementById("myPage"));
			 *			page.updatePageLayout();
			 *		</script>
			 *
			 * @method updatePageLayout
			 * @member ns.widget.mobile.Page
			 */
			Page.prototype.updatePageLayout = function () {
				contentFill(this);
			};


			/**
			 * Sets the focus to page
			 *
			 * !!!This method is only available through TAU API!!
			 *
			 *		@example
			 *		<div id="myPage"></div>
			 *		<script type="text/javascript">
			 *			var page = tau.widget.page(document.getElementById("myPage"));
			 *			page.focus();
			 *		</script>
			 * @method focus
			 * @member ns.widget.mobile.Page
			 */
			Page.prototype.focus = function () {
				var autofocus = this.element.querySelector("[autofocus]");
				if (autofocus) {
					autofocus.focus();
					return;
				}
				this.element.focus();
			};

			/**
			 * Removes focus from page and all descendants
			 *
			 * !!!This method is only available through TAU API!!!
			 *
			 *		@example
			 *		<div id="myPage"></div>
			 *		<script type="text/javascript">
			 *			var page = tau.widget.page(document.getElementById("myPage"));
			 *			page.blur();
			 *		</script>
			 *
			 * @method blur
			 * @member ns.widget.mobile.Page
			 */
			Page.prototype.blur = function () {
				slice.call(this.element.querySelectorAll(":focus")).forEach(function (element) {
					element.blur();
				});
			};

			/**
			 * Bind events to widget
			 * @method _bindEvents
			 * @param {HTMLElement} element
			 * @protected
			 * @member ns.widget.mobile.Page
			 */
			Page.prototype._bindEvents = function (element) {
				var self = this;
				self.contentFillCallback = contentFill.bind(null, self);
				self.contentFillAfterResizeCallback = function () {
					self.pageSetHeight = false;
					contentFill(self);
				};
				self.destroyCallback = self.destroy.bind(self, element);
				/*
				* @TODO
				* mobile zoom and persistant toolbar
				element.addEventListener("pagebeforehide", function (e, ui) {
					var _updatePadding = this.getAttribute("data-update-page-padding") || true,
						disablePageZoom = this.getAttribute("data-disable-page-zoom") || true;
					if (disablePageZoom === true) {
						// @TODO $.mobile.zoom.enable( true );
					}
					var thisFooter = $( ".ui-footer-fixed:jqmData(id)", this ),
						thisHeader = $( ".ui-header-fixed:jqmData(id)", this ),
						nextFooter = thisFooter.length && ui.nextPage && $( ".ui-footer-fixed:jqmData(id='" + thisFooter.jqmData( "id" ) + "')", ui.nextPage ) || $(),
						nextHeader = thisHeader.length && ui.nextPage && $( ".ui-header-fixed:jqmData(id='" + thisHeader.jqmData( "id" ) + "')", ui.nextPage ) || $();
					if ( nextFooter.length || nextHeader.length ) {
						nextFooter.add( nextHeader ).appendTo( $.mobile.pageContainer );
						ui.nextPage.one( "pageshow", function () {
							nextFooter.add( nextHeader ).appendTo( this );
						});
					}
				}, false);
				*/
				window.addEventListener("throttledresize", self.contentFillAfterResizeCallback, false);
				element.addEventListener("updatelayout", self.contentFillAfterResizeCallback, false);
				element.addEventListener("pageshow", self.contentFillCallback, true);
				self.on("pageremove", self.destroyCallback);
			};

			/**
			 * Refresh widget structure
			 * @method _refresh
			 * @protected
			 * @member ns.widget.mobile.Page
			 */
			Page.prototype._refresh = function () {
				buildStructure(this.options, this.element);
				this.pageSetHeight = false;
				contentFill(this);
			};

			/**
			 * Destroy widget
			 * @method _destroy
			 * @protected
			 * @member ns.widget.mobile.Page
			 */
			Page.prototype._destroy = function () {
				var element = this.element;
				window.removeEventListener("throttledresize", this.contentFillAfterResizeCallback, false);
				this.off("pageremove", this.destroyCallback);
				if (element) {
					element.removeEventListener("pageshow", this.contentFillCallback, true);
				}
			};

			// definition
			ns.widget.mobile.Page = Page;
			engine.defineWidget(
				"Page",
				"[data-role='page'], .ui-page",
				[
					"keepNativeSelector",
					"setContainerBackground",
					"removeContainerBackground"
				],
				Page,
				"mobile"
			);
			}(ns));

/*global window, define */
/*jslint nomen: true, plusplus: true */
/* 
 * Copyright (c) 2010 - 2014 Samsung Electronics Co., Ltd.
 * License : MIT License V2
 */
/**
 * #Easing Utility
 * Utility calculates time function for animations.
 * @class ns.util.easing
 */

(function (ns) {
	
				ns.util.easing = {
				/**
				* Performs cubit out easing calcuclations based on time
				* @method cubicOut
				* @member ns.util.easing
				* @param {number} currentTime
				* @param {number} startValue
				* @param {number} changeInValue
				* @param {number} duration
				* @return {number}
				* @static
				*/
				cubicOut: function (currentTime, startValue, changeInValue, duration) {
					currentTime /= duration;
					currentTime--;
					return changeInValue * (currentTime * currentTime * currentTime + 1) + startValue;
				},

				/**
				 * Performs quad easing out calcuclations based on time
				 * @method easeOutQuad
				 * @member ns.util.easing
				 * @param {number} currentTime
				 * @param {number} startValue
				 * @param {number} changeInValue
				 * @param {number} duration
				 * @return {number}
				 * @static
				 */
				easeOutQuad: function (currentTime, startValue, changeInValue, duration) {
					return -changeInValue * (currentTime /= duration) * (currentTime - 2) + startValue;
				},

				/**
				* Performs out expo easing calcuclations based on time
				* @method easeOutExpo
				* @member ns.util.easing
				* @param {number} currentTime
				* @param {number} startValue
				* @param {number} changeInValue
				* @param {number} duration
				* @return {number}
				* @static
				*/
				easeOutExpo: function (currentTime, startValue, changeInValue, duration) {
					return (currentTime === duration) ?
							startValue + changeInValue :
								changeInValue * (-Math.pow(2, -10 * currentTime / duration) + 1) +
								startValue;
				},
				/**
				* Performs out linear calcuclations based on time
				* @method linear
				* @member ns.util.easing
				* @param {number} currentTime
				* @param {number} startValue
				* @param {number} changeInValue
				* @param {number} duration
				* @return {number}
				* @static
				*/
				linear: function (currentTime, startValue, changeInValue, duration) {
					return startValue + duration * currentTime;
				}
			};
			}(ns));

/*global window, define, ns*/
/*jslint nomen: true */
/*
* Copyright  2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/**
 * # ScrollView Widget
 * Widgets allows for creating scrollable panes, lists, etc.
 *
 * ## Default selectors
 * All elements with _data-role=content attribute or _.ui-scrollview
 * css class will be changed to ScrollView widgets, unless they specify
 * _data-scroll=none attribute.
 *
 * ### HTML Examples
 *
 * #### Data attribute
 *
 *		@example
 *		<div data-role="page">
 *			<div data-role="content"><!-- this will become scrollview //-->
 *				content data
 *			</div>
 *		</div>
 *
 * #### CSS Class
 *
 *		@example
 *		<div data-role="page">
 *			<div class="ui-content"><!-- this will become scrollview //-->
 *				content data
 *			</div>
 *		</div>
 *
 * ## Manual constructor
 *
 * To create the widget manually you can use 2 different APIs, the TAU
 * API or jQuery API.
 *
 * ### Create scrollview by TAU API
 *
 *		@example
 *		<div data-role="page" id="myPage">
 *			<div data-role="content">
 *				page content
 *			</div>
 *		</div>
 *		<script>
 *			var page = tau.widget.Page(document.getElementById("myPage")),
 *				scrollview = tau.widget.Scrollview(page.ui.content);
 *		</script>
 *
 * ### Create scrollview using jQuery API
 *
 *		@example
 *		<div data-role="page" id="myPage">
 *			<div data-role="content">
 *				page content
 *			</div>
 *		</div>
 *		<script>
 *			$("#myPage > div[data-role='content']").scrollview();
 *		</script>
 *
 * ## Options for Scrollview widget
 *
 * Options can be set using data-* attributes or by passing them to
 * the constructor.
 *
 * There is also a method **option** for changing them after widget
 * creation.
 *
 * jQuery mobile format is also supported.
 *
 * ## Scroll
 *
 * This options specifies of a content element should become Scrollview
 * widget.
 *
 * You can change this by all available methods for changing options.
 *
 * ### By data-scroll attribute
 *
 *		@example
 *		<div data-role="page">
 *			<div data-role="content" data-scroll="none">
 *				content
 *			</div>
 *		</div>
 *
 * ### By config passed to constructor
 *
 *		@example
 *		<div class="myPageClass" data-role="page">
 *			<div data-role="content">
 *				content
 *			</div>
 *		</div>
 *		<script>
 *			var contentElement = document.querySelector(".myPageClass > div[data-role=content]");
 *			tau.widget.Scrollview(contentElement, {
 *				"scroll": false
 *			});
 *		</script>
 *
 * ### By using jQuery API
 *
 *		@example
 *		<div class="myPageClass" data-role="page">
 *			<div data-role="content">
 *				content
 *			</div>
 *		</div>
 *		<script>
 *			$(".myPageClass > div[data-role='content']").scrollview({
 *				"scroll": false
 *			});
 *		</script>
 *
 * ## ScrollJumps
 *
 * Scroll jumps are small buttons which allow the user to quickly
 * scroll to top or left
 *
 * You can change this by all available methods for changing options.
 *
 * ### By data-scroll-jump
 *
 *		@example
 *		<div data-role="page">
 *			<div data-role="content" data-scroll-jump="true">
 *				content
 *			</div>
 *		</div>
 *
 * ### By config passed to constructor
 *
 *		@example
 *		<div class="myPageClass" data-role="page">
 *			<div data-role="content">
 *				content
 *			</div>
 *		</div>
 *		<script>
 *			var contentElement = document.querySelector(".myPageClass > div[data-role=content]");
 *			tau.widget.Scrollview(contentElement, {
 *				"scrollJump": true
 *			});
 *		</script>
 *
 * ### By using jQuery API
 *
 *		@example
 *		<div class="myPageClass" data-role="page">
 *			<div data-role="content">
 *				content
 *			</div>
 *		</div>
 *		<script>
 *			$(".myPageClass > div[data-role='content']").scrollview({
 *				"scrollJump": true
 *			});
 *		</script>
 *
 * ## Methods
 *
 * Page methods can be called trough 2 APIs: TAU API and jQuery API
 * (jQuery mobile-like API)
 *
 * @class ns.widget.mobile.Scrollview
 * @extends ns.widget.BaseWidget
 *
 * @author Krzysztof Antoszek <k.antoszek@samsung.com>
 * @author Maciej Urbanski <m.urbanski@samsung.com>
 * @author Grzegorz Osimowicz <g.osimowicz@samsung.com>
 * @author Jadwiga Sosnowska <j.sosnowska@samsung.com>
 * @author Maciej Moczulski <m.moczulski@samsung.com>
 * @author Hyunkook Cho <hk0713.cho@samsung.com>
 * @author Junhyeon Lee <juneh.lee@samsung.com>
 */
/**
 * Triggered when scrolling operation starts
 * @event scrollstart
 * @member ns.widget.mobile.Scrollview
 */
/**
 * Triggered when scroll is being updated
 * @event scrollupdate
 * @member ns.widget.mobile.Scrollview
 */
/**
 * Triggered when scrolling stops
 * @event scrollstop
 * @member ns.widget.mobile.Scrollview
 */
(function (window, document, ns) {
	
				var BaseWidget = ns.widget.mobile.BaseWidgetMobile,
				engine = ns.engine,
				util = ns.util,
				easingUtils = ns.util.easing,
				eventUtils = ns.event,
				DOMUtils = ns.util.DOM,
				selectors = ns.util.selectors,
				currentTransition = null,
				Page = ns.widget.mobile.Page,
				pageClass = Page.classes.uiPage,
				pageActiveClass = Page.classes.uiPageActive,
				Scrollview = function () {
					var self = this,
						ui;
					/**
					 * @property {Object} state Scrollview internal state object
					 * @property {Function} state.currentTransition Instance transition function
					 * @readonly
					 */
					self.state = {
						currentTransition: null
					};
					/**
					 * @property {number} scrollDuration The time length of the scroll animation
					 * @member ns.widget.mobile.Scrollview
					 */
					self.scrollDuration = 300;
					self.scrollviewSetHeight = false;
					/**
					 * Scrollview options
					 * @property {Object} options
					 * @property {string} [options.scroll='y'] Scroll direction
					 * @property {boolean} [options.scrollJump=false] Scroll jump buttons flag
					 * @member ns.widget.mobile.Scrollview
					 */
					self.options = {
						scroll: "y",
						scrollJump: false
					};
					/**
					 * Dictionary for holding internal DOM elements
					 * @property {Object} ui
					 * @property {HTMLElement} ui.view The main view element
					 * @property {HTMLElement} ui.page The main page element
					 * @property {HTMLElement} ui.jumpHorizontalButton Jump left button
					 * @property {HTMLElement} ui.jumpVerticalButton Jump top button
					 * @member ns.widget.mobile.Scrollview
					 * @readonly
					 */
					ui = self._ui || {};
					ui.view = null;
					ui.page = null;
					ui.jumpHorizontalButton = null;
					ui.jumpVerticalButton = null;
					self._ui = ui;
					/**
					 * Dictionary for holding internal listeners
					 * @property {Object} _callbacks
					 * @property {Function} _callbacks.repositionJumps Refresh jumps listener
					 * @property {Function} _callbacks.jumpTop Top jump button click callback
					 * @property {Function} _callbacks.jumpLeft Left jump button click callback
					 * @member ns.widget.mobile.Scrollview
					 * @protected
					 * @readonly
					 */
					self._callbacks = {
						repositionJumps: null,
						jumpTop: null,
						jumpBottom: null
					};
				},
				/**
				 * Dictionary for scrollview css classes
				 * @property {Object} classes
				 * @property {string} [classes.view='ui-scrollview-view'] View main class
				 * @property {string} [classes.clip='ui-scrollview-clip'] Clip main class
				 * @property {string} [classes.jumpTop='ui-scroll-jump-top-bg'] Jump top button background
				 * @property {string} [classes.jumpLeft='ui-scroll-jump-left-bg'] Jump bottom button background
				 * @member ns.widget.mobile.Scrollview
				 * @static
				 * @readonly
				 */
				classes =  {
					view: "ui-scrollview-view",
					clip: "ui-scrollview-clip",
					jumpTop: "ui-scroll-jump-top-bg",
					jumpLeft: "ui-scroll-jump-left-bg"
				};

			// Changes static position to relative
			// @param {HTMLElement} view
			function makePositioned(view) {
				if (DOMUtils.getCSSProperty(view, "position") === "static") {
					view.style.position = "relative";
				} else {
					view.style.position = "absolute";
				}
			}

			// Translation animation loop
			// @param {Object} state Scrollview instance state
			// @param {HTMLElement} element
			// @param {number} startTime
			// @param {number} startX
			// @param {number} startY
			// @param {number} translateX
			// @param {number} translateY
			// @param {number} endX
			// @param {number} endY
			// @param {number} duration
			function translateTransition(state, element, startTime, startX, startY, translateX, translateY, endX, endY, duration) {
				var timestamp = (new Date()).getTime() - startTime,
					newX = parseInt(easingUtils.cubicOut(timestamp, startX, translateX, duration), 10),
					newY = parseInt(easingUtils.cubicOut(timestamp, startY, translateY, duration), 10);
				if (element.scrollLeft !== endX) {
					element.scrollLeft = newX;
				}
				if (element.scrollTop !== endY) {
					element.scrollTop = newY;
				}

				if ((newX !== endX || newY !== endY) &&
						(newX >= 0 && newY >= 0) &&
						state.currentTransition) {
					util.requestAnimationFrame(state.currentTransition);
				} else {
					state.currentTransition = null;
				}
			}

			// Translates scroll posotion directly or with an animation
			// if duration is specified
			// @param {Object} state Scrollview instance state
			// @param {HTMLElement} element
			// @param {number} x
			// @param {number} y
			// @param {number=} [duration]
			function translate(state, element, x, y, duration) {
				if (duration) {
					state.currentTransition = translateTransition.bind(
						null,
						state,
						element,
						(new Date()).getTime(),
						element.scrollLeft,
						element.scrollTop,
						x,
						y,
						element.scrollLeft + x,
						element.scrollTop + y,
						duration
					);
					util.requestAnimationFrame(state.currentTransition);
				} else {
					if (x) {
						element.scrollLeft = element.scrollLeft + x;
					}
					if (y) {
						element.scrollTop = element.scrollTop + y;
					}
				}
			}

			// Refresh jumpTop jumpLeft buttons
			// @param {ns.widget.mobile.Scrollview} self
			function repositionJumps(self) {
				var ui = self._ui,
					horizontalJumpButton = ui.jumpHorizontalButton,
					verticalJumpButton = ui.jumpVerticalButton,
					offsets = horizontalJumpButton || verticalJumpButton ? DOMUtils.getElementOffset(self.element) : null; // dont calc when not used

				if (horizontalJumpButton) {
					horizontalJumpButton.style.left = offsets.left + "px";
				}

				if (verticalJumpButton) {
					verticalJumpButton.style.top = offsets.top + "px";
				}
			}

			Scrollview.classes = classes;

			Scrollview.prototype = new BaseWidget();

			/**
			 * Builds the widget
			 * @param {HTMLElement} element
			 * @return {HTMLElement}
			 * @method _build
			 * @protected
			 * @member ns.widget.mobile.Scrollview
			 */
			Scrollview.prototype._build = function (element) {
				//@TODO wrap element's content with external function
				var self = this,
					ui = self._ui,
					view = selectors.getChildrenByClass(element, classes.view)[0] || document.createElement("div"),
					clipStyle = element.style,
					node = null,
					child = element.firstChild,
					options = self.options,
					direction = options.scroll,
					jumpButton,
					jumpBackground;
				view.className = classes.view;

				while (child) {
					node = child;
					child = child.nextSibling;
					if (view !== node) {
						view.appendChild(node);
					}
				}

				if (view.parentNode !== element) {
					element.appendChild(view);
				}

				// setting view style
				makePositioned(view);

				element.classList.add(classes.clip);

				switch (direction) {
					case "x":
						clipStyle.overflowX = "scroll";
						break;
					case "xy":
						clipStyle.overflow = "scroll";
						break;
					default:
						clipStyle.overflowY = "scroll";
						break;
				}

				if (options.scrollJump) {
					if (direction.indexOf("x") > -1) {
						jumpBackground = document.createElement("div");
						jumpBackground.className = classes.jumpLeft;
						jumpButton = document.createElement("div");

						jumpBackground.appendChild(jumpButton);
						element.appendChild(jumpBackground);
						engine.instanceWidget(
							jumpButton,
							"Button",
							{
								"icon": "scrollleft",
								"style": "box"
							}
						);
						ui.jumpHorizontalButton = jumpBackground;
					}

					if (direction.indexOf("y") > -1) {
						jumpBackground = document.createElement("div");
						jumpBackground.className = classes.jumpTop;
						jumpButton = document.createElement("div");

						jumpBackground.appendChild(jumpButton);
						element.appendChild(jumpBackground);
						engine.instanceWidget(
							jumpButton,
							"Button",
							{
								"icon": "scrolltop",
								"style": "box"
							}
						);
						ui.jumpVerticalButton = jumpBackground;
					}
				}

				ui.view = view;
				// @TODO
				//this._addOverflowIndicator(element);
				return element;
			};

			/**
			 * Inits widget
			 * @method _init
			 * @param {HTMLElement} element
			 * @protected
			 * @member ns.widget.mobile.Scrollview
			 */
			Scrollview.prototype._init = function (element) {
				var ui = this._ui,
					page = ui.page;

				if (!ui.view) {
					ui.view = selectors.getChildrenByClass(element, classes.view)[0];
				}

				if (!page) {
					page = selectors.getClosestByClass(element, pageClass);
					if (page) {
						ui.page = page;
						if (page.classList.contains(pageActiveClass) && this.options.scrollJump) {
							repositionJumps(this);
						}
					}
				}
			};

			/**
			 * Adds overflow indicators
			 * @param {HTMLElement} clip
			 * @method _addOverflowIndicator
			 * @protected
			 * @member ns.widget.mobile.Scrollview
			 */
			Scrollview.prototype._addOverflowIndicator = function (clip) {
				if ((clip.getAttribute("data-overflow-enable") || "true") === "false") {
					return;
				}
				clip.insertAdjacentHTML("beforeend", '<div class="ui-overflow-indicator-top"></div><div class="ui-overflow-indicator-bottom"></div>');
			};

			/**
			 * Scrolls to specified position
			 *
			 * ### Example usage with TAU API
			 *
			 *		@example
			 *		<div class="myPageClass" data-role="page">
			 *			<div data-role="content" data-scroll="y">
			 *				content
			 *			</div>
			 *		</div>
			 *		<script>
			 *			var scrollview = tau.widget.Scrollview(document.querySelector(".myPageClass > div[data-role=content]"));
			 *			scrollview.scrollTo(0, 200, 1000); // scroll to 200px vertical with 1s animation
			 *		</script>
			 *
			 * ### Example usage with jQuery API
			 *
			 *		@example
			 *		<div class="myPageClass" data-role="page">
			 *			<div data-role="content" data-scroll="y">
			 *				content
			 *			</div>
			 *		</div>
			 *		<script>
			 *			var element = $(".myPageClass > div[data-role=content]"));
			 *			element.scrollview();
			 *			element.scrollview("scrollTo", 0, 200, 1000); // scroll to 200px vertical with 1s animation
			 *		</script>
			 *
			 * @param {number} x
			 * @param {number} y
			 * @param {number=} [duration]
			 * @method scrollTo
			 * @protected
			 * @member ns.widget.mobile.Scrollview
			 */
			Scrollview.prototype.scrollTo = function (x, y, duration) {
				var element = this.element;
				this.translateTo(x - element.scrollLeft, y - element.scrollTop, duration);
			};

			/**
			 * Translates the scroll to specified position
			 *
			 * ### Example usage with TAU API
			 *
			 *		@example
			 *		<div class="myPageClass" data-role="page">
			 *			<div data-role="content" data-scroll="y">
			 *				content
			 *			</div>
			 *		</div>
			 *		<script>
			 *			var scrollview = tau.widget.Scrollview(document.querySelector(".myPageClass > div[data-role=content]"));
			 *			scrollview.translateTo(0, 200, 1000); // scroll forward 200px in vertical direction with 1s animation
			 *		</script>
			 *
			 * ### Example usage with jQuery API
			 *
			 *		@example
			 *		<div class="myPageClass" data-role="page">
			 *			<div data-role="content" data-scroll="y">
			 *				content
			 *			</div>
			 *		</div>
			 *		<script>
			 *			var element = $(".myPageClass > div[data-role=content]"));
			 *			element.scrollview();
			 *			element.scrollview("translateTo", 0, 200, 1000); // scroll forward 200px in vertical direction with 1s animation
			 *		</script>
			 *
			 * @param {number} x
			 * @param {number} y
			 * @param {number=} [duration]
			 * @method translateTo
			 * @member ns.widget.mobile.Scrollview
			 */
			Scrollview.prototype.translateTo = function (x, y, duration) {
				translate(this.state, this.element, x, y, duration);
			};

			/**
			 * Ensures that specified element is visible in the
			 * clip area
			 *
			 * ### Example usage with TAU API
			 *
			 *		@example
			 *		<div class="myPageClass" data-role="page">
			 *			<div data-role="content" data-scroll="y">
			 *				content
			 *				<div class="testElementClass">somedata</div>
			 *			</div>
			 *		</div>
			 *		<script>
			 *			var scrollview = tau.widget.Scrollview(document.querySelector(".myPageClass > div[data-role=content]")),
			 *				testElement = document.querySelector(".testElementClass");
			 *			scrollview.ensureElementIsVisible(testelement);
			 *		</script>
			 *
			 * ### Example usage with jQuery API
			 *
			 *		@example
			 *		<div class="myPageClass" data-role="page">
			 *			<div data-role="content" data-scroll="y">
			 *				content
			 *				<div class="testElementClass">somedata</div>
			 *			</div>
			 *		</div>
			 *		<script>
			 *			var element = $(".myPageClass > div[data-role=content]")),
			 *				testElement = $(".testElementClass");
			 *			element.scrollview();
			 *			element.scrollview("ensureElementIsVisible", testElement);
			 *		</script>
			 *
			 * @param {HTMLElement} element
			 * @method ensureElementIsVisible
			 * @member ns.widget.mobile.Scrollview
			 */
			Scrollview.prototype.ensureElementIsVisible = function (element) {
				var clip = this.element,
					clipHeight = DOMUtils.getElementHeight(clip),
					clipWidth = DOMUtils.getElementWidth(clip),
					clipTop = 0,
					clipBottom = clipHeight,
					elementHeight = DOMUtils.getElementHeight(element),
					elementWidth = DOMUtils.getElementWidth(element),
					elementTop = 0,
					elementBottom,
					elementFits = clipHeight >= elementHeight && clipWidth >= elementWidth,
					anchor,
					anchorPositionX,
					anchorPositionY,
					parent,
					findPositionAnchor = function (input) {
						var id = input.getAttribute("id"),
							tagName = input.tagName.toLowerCase();
						if (id && ["input", "textarea", "button"].indexOf(tagName) > -1) {
							return input.parentNode.querySelector("label[for=" + id + "]");
						}
					},
					_true = true;

				parent = element.parentNode;
				while (parent && parent !== clip) {
					elementTop += parent.offsetTop;
					//elementLeft += parent.offsetLeft;
					parent = parent.parentNode;
				}
				elementBottom = elementTop + elementHeight;
				//elementRight = elementLeft + elementWidth;

				switch (_true) {
					case elementFits && clipTop < elementTop && clipBottom > elementBottom: // element fits in view is inside clip area
						// pass, element position is ok
						break;
					case elementFits && clipTop < elementTop && clipBottom < elementBottom: // element fits in view but its visible only at top
					case elementFits && clipTop > elementTop && clipBottom > elementBottom: // element fits in view but its visible only at bottom
					case elementFits: // element fits in view but is not visible
						this.centerToElement(element);
						break;
					case clipTop < elementTop && elementTop < clipBottom && clipBottom < elementBottom: // element visible only at top; eg. partly visible textarea
					case clipTop > elementTop && clipBottom > elementBottom: // element visible only at bottom
						// pass, we cant do anything, if we move the scroll
						// the user could lost view of something he scrolled to
						break;
					default: // element is not visible
						anchor = findPositionAnchor(element);
						if (!anchor) {
							anchor = element;
						}
						anchorPositionX = anchor.offsetLeft + DOMUtils.getCSSProperty(anchor, "margin-left", 0, "integer");
						anchorPositionY = anchor.offsetTop + DOMUtils.getCSSProperty(anchor, "margin-top", 0, "integer");
						parent = anchor.parentNode;
						while (parent && parent !== clip) {
							anchorPositionX += parent.offsetLeft;
							anchorPositionY += parent.offsetTop;
							parent = parent.parentNode;
						}
						this.scrollTo(anchorPositionX, anchorPositionY, this.scrollDuration);
						break;
				}
			};

			/**
			 * Centers specified element in the clip area
			 *
			 * ### Example usage with TAU API
			 *
			 *		@example
			 *		<div class="myPageClass" data-role="page">
			 *			<div data-role="content" data-scroll="y">
			 *				content
			 *				<div class="testElementClass">somedata</div>
			 *			</div>
			 *		</div>
			 *		<script>
			 *			var scrollview = tau.widget.Scrollview(document.querySelector(".myPageClass > div[data-role=content]")),
			 *				testElement = document.querySelector(".testElementClass");
			 *			scrollview.centerToElement(testelement);
			 *		</script>
			 *
			 * ### Example usage with jQuery API
			 *
			 *		@example
			 *		<div class="myPageClass" data-role="page">
			 *			<div data-role="content" data-scroll="y">
			 *				content
			 *				<div class="testElementClass">somedata</div>
			 *			</div>
			 *		</div>
			 *		<script>
			 *			var element = $(".myPageClass > div[data-role=content]")),
			 *				testElement = $(".testElementClass");
			 *			element.scrollview();
			 *			element.scrollview("centerToElement", testElement);
			 *		</script>
			 *
			 * @param {HTMLElement} element
			 * @method centerToElement
			 * @member ns.widget.mobile.Scrollview
			 */
			Scrollview.prototype.centerToElement = function (element) {
				var clip = this.element,
					deltaX = parseInt(DOMUtils.getElementWidth(clip) / 2 - DOMUtils.getElementWidth(element) / 2, 10),
					deltaY = parseInt(DOMUtils.getElementHeight(clip) / 2 - DOMUtils.getElementHeight(element) / 2, 10),
					elementPositionX = element.offsetLeft,
					elementPositionY = element.offsetTop,
					parent = element.parentNode;

				while (parent && parent !== clip) {
					elementPositionX += parent.offsetLeft + DOMUtils.getCSSProperty(parent, "margin-left", 0, "integer");
					elementPositionY += parent.offsetTop + DOMUtils.getCSSProperty(parent, "margin-top", 0, "integer");
					parent = parent.parentNode;
				}
				this.scrollTo(elementPositionX - deltaX, elementPositionY - deltaY, this.scrollDuration);
			};

			/**
			 * This is just for compatibility
			 * @method skipDragging
			 * @member ns.widget.mobile.Scrollview
			 * @deprecated 2.3
			 */
			Scrollview.prototype.skipDragging = function () {
				if (ns.warn) {
					ns.warn("ns.widget.mobile.Scrollview: skipDragging is deprecated");
				}
			}; // just for TWEBUIFW compat

			/**
			 * Returns scroll current position
			 *
			 *		@example
			 *		<div class="myPageClass" data-role="page">
			 *			<div data-role="content" data-scroll="y">
			 *				content
			 *			</div>
			 *		</div>
			 *		<script>
			 *			var scrollview = tau.widget.Scrollview(document.querySelector(".myPageClass > div[data-role=content]")),
			 *				currentPosition = scrollview.getScrollPosition();
			 *		</script>
			 *
			 * ### Example usage with jQuery API
			 *
			 *		@example
			 *		<div class="myPageClass" data-role="page">
			 *			<div data-role="content" data-scroll="y">
			 *				content
			 *			</div>
			 *		</div>
			 *		<script>
			 *			var element = $(".myPageClass > div[data-role=content]")),
			 *				position;
			 *			element.scrollview();
			 *			position = element.scrollview("getScrollPosition");
			 *		</script>
			 *
			 * @return {Object}
			 * @method getScrollPosition
			 * @member ns.widget.mobile.Scrollview
			 */
			Scrollview.prototype.getScrollPosition = function () {
				var element = this.element;
				return {
					"x": element.scrollLeft,
					"y": element.scrollTop
				};
			};

			/**
			 * Binds scrollview events
			 * @method _bindEvents
			 * @param {HTMLElement} element
			 * @protected
			 * @member ns.widget.mobile.Scrollview
			 */
			Scrollview.prototype._bindEvents = function (element) {
				var scrollTimer = null,
					view = element.children[0],
					lastClipHeight = DOMUtils.getElementHeight(element),
					lastClipWidth = DOMUtils.getElementWidth(element),
					notifyScrolled = function () {
						eventUtils.trigger(element, "scrollstop");
						window.clearTimeout(scrollTimer);
						scrollTimer = null;
					},
					self = this,
					//FIXME there should be some other way to get parent container
					ui = self._ui,
					page = ui.page,
					jumpTop = ui.jumpVerticalButton,
					jumpLeft = ui.jumpHorizontalButton,
					repositionJumpsCallback,
					jumpTopCallback,
					jumpLeftCallback,
					callbacks = self._callbacks;

				if (page) {
					if (this.options.scrollJump) {
						repositionJumpsCallback = repositionJumps.bind(null, this);
						jumpTopCallback = function () {
							self.scrollTo(element.scrollLeft, 0, 250);
						};
						jumpLeftCallback = function () {
							self.scrollTo(0, element.scrollTop, 250);
						};
						page.addEventListener("pageshow", repositionJumpsCallback, false);
						if (jumpTop) {
							jumpTop.firstChild.addEventListener("vclick", jumpTopCallback, false);
						}
						if (jumpLeft) {
							jumpLeft.firstChild.addEventListener("vclick", jumpLeftCallback, false);
						}

						callbacks.repositionJumps = repositionJumpsCallback;
						callbacks.jumpTop = jumpTopCallback;
						callbacks.jumpLeft = jumpLeftCallback;
					}

					element.addEventListener("scroll", function () {
						if (scrollTimer) {
							window.clearTimeout(scrollTimer);
						} else {
							eventUtils.trigger(element, "scrollstart");
						}
						scrollTimer = window.setTimeout(notifyScrolled, 100);
						eventUtils.trigger(element, "scrollupdate");
					}, false);


					window.addEventListener("throttledresize", function () {
						var focusedElement = view.querySelector(".ui-focus"),
							clipWidth,
							clipHeight;
						if (focusedElement) {
							self.ensureElementIsVisible(focusedElement);
						} else if (DOMUtils.isOccupiedPlace(element)) {
							clipHeight = DOMUtils.getElementHeight(element);
							clipWidth = DOMUtils.getElementWidth(element);
							self.translateTo(
								lastClipWidth - clipWidth,
								lastClipHeight - clipHeight,
								self.scrollDuration
							);
							lastClipHeight = clipHeight;
							lastClipWidth = clipWidth;
						}
					}, false);

					document.addEventListener("vmousedown", function () {
						if (currentTransition) {
							currentTransition = null;
						}
					}, false);

				}
			};

			Scrollview.prototype._destroy = function () {
				var ui = this._ui,
					page = ui.page,
					scrollJump = this.options.scrollJump,
					jumpTop = ui.jumpVerticalButton,
					jumpLeft = ui.jumpHorizontalButton,
					callbacks = this._callbacks,
					repositionJumpsCallback = callbacks.repositionJumps,
					jumpTopCallback = callbacks.jumpTop,
					jumpLeftCallback = callbacks.jumpLeft;

				if (scrollJump) {
					if (page && repositionJumpsCallback) {
						page.removeEventListener("pageshow", repositionJumpsCallback, false);
					}
					if (jumpTop && jumpTopCallback) {
						jumpTop.firstChild.removeEventListener("vclick", jumpTopCallback, false);
					}
					if (jumpLeft && jumpLeftCallback) {
						jumpLeft.firstChild.removeEventListener("vclick", jumpLeftCallback, false);
					}
				}

			};

			ns.widget.mobile.Scrollview = Scrollview;
			engine.defineWidget(
				"Scrollview",
				"[data-role='content']:not([data-scroll='none']):not([data-handler='true']):not(.ui-scrollview-clip):not(.ui-scrolllistview):not(.ui-scrollhandler)" +
						", [data-scroll]:not([data-scroll='none']):not([data-handler='true']):not(.ui-scrollhandler)" +
						", .ui-scrollview:not([data-scroll='none']):not([data-handler='true']):not(.ui-scrollhandler)",
				[
					"scrollTo",
					"ensureElementIsVisible",
					"centerToElement",
					"getScrollPosition",
					"skipDragging",
					"translateTo"
				],
				Scrollview,
				"tizen"
			);
			}(window, window.document, ns));

/*global window, define */
/*
* Copyright  2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/*jslint nomen: true, plusplus: true */
/**
 * #Circular View Widget
 * The circular view widget shows a special scroll box which can be scroll in circle.
 *
 * @class ns.widget.mobile.Circularview
 * @extend ns.widget.mobile.BaseWidgetMobile
 */
(function (document, ns) {
	
				var CircularView = function () {
					this.options = {
						"fps": 60,
						"scrollDuration": 2000,
						"moveThreshold": 10,
						"moveIntervalThreshold": 150,
						"startEventName": "scrollstart",
						"updateEventName": "scrollupdate",
						"stopEventName": "scrollstop",
						"eventType": ns.event.vmouse.touchSupport ? "touch" : "mouse",
						"delaydedClickSelector": "a, .ui-btn",
						"delayedClickEnabled": false,
						"list": "> *"
					};
					this._callbacks = {};
					this._view = null;
					this._list = null;
					this._items = null;
					this._listItems = null;
					this._moving = false;
					this._lastMouseX = 0;
					this._lastStepX = 0;
					this._transformation = null;
					this._itemWidth = 0;
					this._width = 0;
					this._lastGapSize = 0;

					this._positionX = 0;
					this._positionXOffset = 0;

					this._centerTo = true;
				},
				slice = [].slice,
				BaseWidget = ns.widget.mobile.BaseWidgetMobile,
				domutils = ns.util.DOM,
				selectors = ns.util.selectors,
				util = ns.util,
				eventUtils = ns.event,
				engine = ns.engine,
				easingUtils = ns.util.easing,
				dragEvents = {
					"mouse": {
						"start": "mousedown",
						"move": "mousemove",
						"end": "mouseup"
					},
					"touch": {
						"start": "touchstart",
						"move": "touchmove",
						"end": "touchend"
					}
				};

			CircularView.prototype = new BaseWidget();

			function applyLeftItems(circularview, gapSizeDiff) {
				var list = circularview._list,
					items = list.children,
					lastIndex = items.length - 1,
					i;
				for (i = 0; i < gapSizeDiff; i++) {
					list.insertBefore(items[lastIndex], items[0])
					;
				}
			}

			function applyRightItems(circularview, gapSizeDiff) {
				var list = circularview._list,
					items = list.children,
					i;
				for (i = 0; i < gapSizeDiff; i++) {
					list.appendChild(items[0]);
				}
			}

			function updateView(circularview) {
				var viewStyle = circularview._view.style,
					positionX = circularview._positionX,
					positionXOffset = - circularview._positionXOffset,
					lastStepX = circularview._lastStepX,
					translate,
					gapSize = Math.floor((positionX - positionXOffset) / circularview._itemWidth),
					itemWidth = circularview._itemWidth,
					translateX = positionX + positionXOffset - (itemWidth * gapSize),
					gapSizeDiff = Math.abs(gapSize - circularview._lastGapSize);

				if(circularview._centerTo) {
					if (gapSize > 0) { // show more on left side
						applyLeftItems(circularview, gapSizeDiff);
					} else { // show more on right side
						applyRightItems(circularview, gapSizeDiff);
					}
				} else {
					if (gapSizeDiff) {
						if (lastStepX > 0) { // show more on left side
							applyLeftItems(circularview, gapSizeDiff);
						} else { // show more on right side
							applyRightItems(circularview, gapSizeDiff);
						}
					}
				}
				translate =  "translate3d(" + translateX + "px, 0px, 0px)";
				viewStyle.transform = translate;
				viewStyle.webkitTransform = translate;
				circularview._lastGapSize = gapSize;
			}

			function moveTo(circularview, startTime, changeX, endX, duration) {
				var isCentring = circularview._centerTo,
					elapsed = +new Date() - startTime, // timestamp passed to requestAnimationFrame callback is not stable so we create our own
					timestamp = elapsed > duration ? duration : elapsed,
					easingVal = easingUtils.easeOutQuad(timestamp, 0, 1, duration),
					newPositionX = isCentring ? changeX * easingVal : changeX * (1 - easingVal),
					transformation = circularview._transformation,
					options = circularview.options,
					element = circularview.element;

				eventUtils.trigger(element, options.updateEventName);

				if (!duration || +new Date() > startTime + duration) {
					circularview._positionX = isCentring ? endX : circularview._positionX;
					updateView(circularview);
					transformation = null;
					circularview._centerTo = false;
					eventUtils.trigger(element, options.stopEventName);
				} else if (newPositionX !== endX && isNaN(newPositionX) === false && transformation !== null) { // used isNaN to prevent jslint error, hope that closure will change this to val === val for speedup
					circularview._positionX = isCentring ? newPositionX : circularview._positionX + newPositionX;
					updateView(circularview);
					util.requestAnimationFrame.call(window, transformation);
				} else {
					circularview._positionX = isCentring ? newPositionX : circularview._positionX + newPositionX;
					updateView(circularview);
					circularview._transformation = null;
					circularview._centerTo = false;
					eventUtils.trigger(element, options.stopEventName);
				}

			}

			function handleDragStart(circularview, event) {
				var lastMouseX = event.clientX,
					options = circularview.options,
					element = circularview.element;

				//event.preventDefault();
				//event.stopPropagation();

				if (circularview._moving === true || circularview._transformation !== null) {
					eventUtils.trigger(element, options.stopEventName);
				}

				circularview._moving = true;
				circularview._transformation = null;

				if (circularview.options.eventType === "touch") {
					lastMouseX = event.touches[0].clientX;
				}
				circularview._lastMouseX = lastMouseX;

				eventUtils.trigger(element, options.startEventName);
			}

			function handleDragMove(circularview, event) {
				var stepX = 0,
					mouseX = event.clientX;

				circularview._lastMoveTime = Date.now();

				if (circularview.options.eventType === "touch") {
					mouseX = event.touches[0].clientX;
				}

				if (circularview._moving) {
					stepX = mouseX - circularview._lastMouseX;
					if (stepX !== 0) {
						circularview._positionX += stepX;
						util.requestAnimationFrame.call(window, updateView.bind(null, circularview));
					}
					circularview._lastMouseX = mouseX;
					circularview._lastStepX = stepX;
				}
			}

			function handleDragEnd(circularview) {
				var lastStepX = circularview._lastStepX,
					lastMoveTime = circularview._lastMoveTime,
					position = circularview.getScrollPosition(),
					momentum = lastStepX,
					doScroll = lastMoveTime && (Date.now() - lastMoveTime) <= circularview.options.moveIntervalThreshold;

				circularview._moving = false;

				if (doScroll) {
					circularview._transformation = moveTo.bind(
						null,
						circularview,
						+new Date(),
						momentum,
						position.x + momentum,
						circularview.options.scrollDuration
					);
					util.requestAnimationFrame.call(window, circularview._transformation);
				} else {
					circularview._transformation = null;
					eventUtils.trigger(circularview.element, circularview.options.stopEventName);
				}
			}

			function applyViewItems(circularview) {
				var i,
					items = circularview._listItems,
					itemsLength = items.length,
					fragment = document.createDocumentFragment();

				for (i = 0; i < itemsLength; ++i) {
					fragment.appendChild(items[i]);
				}
				circularview._list.appendChild(fragment);
				updateView(circularview);
			}

			CircularView.classes = {
				"clip": "ui-scrollview-clip",
				"view": "ui-scrollview-view",
				"listCurrent": "current"
			};

			CircularView.prototype._build = function (element) {
				var view = document.createElement("div"),
					list = document.createElement("ul"),
					viewStyle = view.style,
					classes = CircularView.classes,
					sourceListSelector = this.options.list,
					sourceRefNodeIsElement = sourceListSelector.charAt(0) === ">",
					sourceRefNode = sourceRefNodeIsElement ? element : document;

				if (sourceRefNodeIsElement) {
					sourceListSelector = sourceListSelector.replace(/^>\s*/, '');
				}

				// rewrite source to our list
				slice.call(sourceRefNode.querySelectorAll(sourceListSelector)).forEach(function (item) {
					list.appendChild(item);
				});

				element.classList.add(classes.clip);
				view.classList.add(classes.view);

				viewStyle.overflow = "hidden";

				view.appendChild(list);
				element.innerHTML = "";
				element.appendChild(view);

				if (domutils.getCSSProperty(element, "position") === "static") {
					element.style.position = "relative";
				}

				return element;
			};

			CircularView.prototype._init = function (element) {
				var self = this,
					classes = CircularView.classes,
					view = selectors.getChildrenByClass(element, classes.view)[0],
					list = selectors.getChildrenByTag(view, "ul")[0],
					listItems = [];

				self._list = list;
				// add to array by copy not through children reference
				slice.call(list.children).forEach(function (child) {
					listItems.push(child);
				});
				self._items = listItems;
				self._view = view;

				self._refresh();
			};

			CircularView.prototype._bindEvents = function (element) {
				var self = this,
					callbacks = self._callbacks,
					eventType = self.options.eventType;
				callbacks.dragstart = handleDragStart.bind(null, this);
				callbacks.dragmove = handleDragMove.bind(null, this);
				callbacks.dragend = handleDragEnd.bind(null, this);

				element.addEventListener(dragEvents[eventType].start, callbacks.dragstart, false);
				element.addEventListener(dragEvents[eventType].move, callbacks.dragmove, false);
				element.addEventListener(dragEvents[eventType].end, callbacks.dragend, false);
			};

			CircularView.prototype.getScrollPosition = function () {
				return {
					"x": -this._positionX,
					"y": 0 // compatibility
				};
			};

			CircularView.prototype.scrollTo = function (x, y, duration) {
				var self = this,
					position = self.getScrollPosition(),
					stepX = Math.round(x), // we have to be sure that integers are supplied so we do Math.round on input
					time = +new Date();

				self._transformation = moveTo.bind(
					null,
					this,
					time,
					stepX - (-position.x),
					stepX,
					duration
				);
				util.requestAnimationFrame.call(window, self._transformation);
			};

			CircularView.prototype.centerTo = function (selector, duration) {
				var self = this,
					searched = self._view.querySelector(selector),
					sibling = null,
					siblings = 0,
					itemWidth = self._itemWidth,
					// We need to add a half of element to make it on the center, and
					// additionaly one more element due to positionXOffset which have
					// exactly one item width - this is why here we have itemWidth
					// multiplication by 1.5
					center = parseInt(self._width / 2 + (itemWidth * 1.5), 10);

				if (searched) {
					self._centerTo = true;
					sibling = searched.previousSibling;
					while (sibling) {
						++siblings;
						sibling = sibling.previousSibling;
					}
					self.scrollTo(-((siblings * itemWidth) - center), 0, duration);
				}
			};

			CircularView.prototype.reflow = function () {
				var self = this,
					position = this.getScrollPosition();
				self._refresh();
				self.scrollTo(position.x, position.y, self.options.scrollDuration);
			};

			CircularView.prototype.add = function (item) {
				this._items.push(item);
			};

			CircularView.prototype._refresh = function () {
				var self = this,
					element = self.element,
					width = domutils.getElementWidth(element),
					items = self._items,
					firstItem = items[0],
					filledList = [],
					viewStyle = self._view.style,
					itemWidth,
					itemHeight,
					itemsPerView,
					list = self._list,
					fill,
					fills,
					i,
					len;

				list.innerHTML = "";
				if (!firstItem) {
					return;
				}
				list.appendChild(firstItem);
				itemWidth = domutils.getElementWidth(items[0]);
				itemHeight = domutils.getElementHeight(items[0]);

				list.removeChild(firstItem);

				itemsPerView = parseInt(width / itemWidth, 10);

				// fill list
				for (fill = 0, fills = Math.ceil(itemsPerView / items.length) + 1; fill < fills; ++fill) {
					for (i = 0, len = items.length; i < len; ++i) {
						filledList.push(items[i].cloneNode(true));
					}
				}
				filledList.unshift(filledList.pop());

				viewStyle.height = itemHeight + "px";
				viewStyle.width = itemWidth * filledList.length + "px";

				self._listItems = filledList;
				self._itemWidth = itemWidth;
				self._width = width;
				self._itemsPerView = itemsPerView;
				self._positionXOffset = itemWidth;

				applyViewItems(self);
			};

			CircularView.prototype._destroy = function () {
				var self = this,
					element = self.element,
					callbacks = self._callbacks,
					eventType = self.options.eventType;
				if (element) {
					element.removeEventListener(dragEvents[eventType].start, callbacks.dragstart, false);
					element.removeEventListener(dragEvents[eventType].move, callbacks.dragmove, false);
					element.removeEventListener(dragEvents[eventType].end, callbacks.dragend, false);
				}
			};

			// definition
			ns.widget.mobile.Circularview = CircularView;
			engine.defineWidget(
				"Circularview",
				"[data-role='circularview'], .ui-circularview", //@TODO ???
				[
					"getScrollPosition",
					"scrollTo",
					"centerTo",
					"reflow",
					"add"
				],
				CircularView,
				'mobile'
			);
			}(window.document, ns));

/*global window, define */
/*
* Copyright  2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/*jslint nomen: true */
/**
 * #Collapsible Widget
 * This is a simple widget that allows you to expand or collapse content when
 * tapped.
 *
 * ## Default selectors
 * All elements with _data-role="collapsible"_ or class _.ui-collapsible_ are
 * changed to collapsible widget.
 *
 * ###HTML Examples
 *
 * ####Create collapsible div using data-role
 *
 *		@example
 *		<div id="collapsible" data-role="collapsible" data-inset="false">
 *			<h1>Collapsible head</h1>
 *			<div>Content</div>
 *		</div>
 *
 * ####Create collapsible list using data-role
 *
 *		@example
 *		<ul data-role="listview">
 *			<li data-role="collapsible" data-inset="false">
 *				<h2>Collapsible head</h2>
 *				<-- sub list -->
 *				<ul data-role="listview">
 *					<li>sub list item1</li>
 *					<li>sub list item2</li>
 *				</ul>
 *			</li>
 *		</ul>
 *
 * ####Create using class selector
 *
 *		@example
 *		<div id="collapsible" class="ui-collapsible" data-inset="false">
 *			<h1>Collapsible head</h1>
 *			<div>Content</div>
 *		</div>
 *
 * ## Manual constructor
 * For manual creation of collapsible widget you can use constructor of widget
 * from **tau** namespace:
 *
 *		@example
 *		<script>
 *			var collapsibleElement = document.getElementById("collapsible"),
 *				collapsible = tau.widget.Collapsible(collapsibleElement,
 *					{mini: true});
 *		</script>
 *
 * Constructor has one require parameter **element** which are base
 * **HTMLElement** to create widget. We recommend get this element by method
 * *document.getElementById*. Second parameter is **options** and it is
 * a object with options for widget.
 *
 * If jQuery library is loaded, its method can be used:
 *
 *		@example
 *		<script>
 *			var collapsible = $("#collapsible").collapsible({mini: true});
 *		</script>
 *
 * jQuery Mobile constructor has one optional parameter, which is **options**
 * and it is a object with options for widget.
 *
 * ##Options for Collapsible Widget
 *
 * Options for widget can be defined as _data-..._ attributes or give as
 * parameter in constructor.
 *
 * You can change option for widget using method **option**.
 *
 * ##Methods
 *
 * To call method on widget you can use one of existing API:
 *
 * First API is from tau namespace:
 *
 *		@example
 *		var collapsibleElement = document.getElementById("collapsible"),
 *			collapsible = tau.widget.Collapsible(collapsibleElement);
 *
 *		collapsible.methodName(methodArgument1, methodArgument2, ...);
 *
 * Second API is jQuery Mobile API and for call _methodName_ you can use:
 *
 *		@example
 *		$(".selector").collapsible("methodName", methodArgument1, ...);
 *
 *
 * @class ns.widget.mobile.Collapsible
 * @extends ns.widget.BaseWidget
 * @author Piotr Karny <p.karny@samsung.com>
 * @author Marcin Jakuszko <m.jakuszko@samsung.com>
 */
(function (document, ns) {
	
					/**
				 * @property {Object} BaseWidget alias variable
				 * @private
				 * @static
				 */
			var BaseWidget = ns.widget.mobile.BaseWidgetMobile,
				/**
				 * @property {Object} Button alias variable
				 * @private
				 * @static
				 */
				Button = ns.widget.mobile.Button,
				/**
				 * @property {Object} engine alias variable
				 * @private
				 * @static
				 */
				engine = ns.engine,
				/**
				 * @property {Object} selectors alias variable
				 * @private
				 * @static
				 */
				selectors = ns.util.selectors,
				/**
				 * @property {Object} events alias variable
				 * @private
				 * @static
				 */
				events = ns.event,
				/**
				 * Shortcut for slice method from Array.prototype
				 * @method slice
				 * @private
				 * @static
				 */
				slice = [].slice,
				/**
				 * @property {Object} domUtils alias variable
				 * @private
				 * @static
				 */
				domUtils = ns.util.DOM,
				/**
				 * @property {Object} themes alias variable
				 * @private
				 * @static
				 */
				themes = ns.theme,
				/**
				 * Local constructor function
				 * @method Collapsible
				 * @private
				 * @member ns.widget.mobile.Collapsible
				 */
				Collapsible = function () {
					/**
					 * Collapsible widget options.
					 * @property {Object} options
					 * @property {string} [options.expandCueText=" Expandable list, tap to open list"] This text is used to provide audible feedback that
					 * list is expanded for users with screen reader software.
					 * @property {string} [options.collapseCueText=" Expandable list, tap to close list"] This text is used to provide audible feedback that
					 * list is collapsed for users with screen reader software.
					 * @property {boolean} [options.collapsed=true] Determines if content should be collapsed on load
					 * @property {string} [options.heading="h1,h2,h3,h4,h5,h6,legend,li"] Within the collapsible container, the first immediate child element
					 * that matches this selector will be used as the header for the collapsible.
					 * @property {?string} [options.theme=null] Sets the color scheme (swatch) for the collapsible. `{@link ns.widget.mobile.Collapsible#defaultOptions}.theme`
					 * This value is used when .theme option isn't on element itself and on it's parents
					 * @property {?string} [options.contentTheme=null] widget content theme
					 * @property {?string} [options.collapsedIcon=null] Icon for collapsed widget, `{@link ns.widget.mobile.Collapsible#defaultOptions}.collapsedIcon`
					 * value is used when collapsible is not in a collapsible-set or option isn't set
					 * @property {?string} [options.expandedIcon=null] Icon for expanded widget, `{@link ns.widget.mobile.Collapsible#defaultOptions}.expandedIcon`
					 * value is used when collapsible is not in a collapsible-set or option isn't set
					 * @property {?string} [options.iconpos=null] Icon position, `{@link ns.widget.mobile.Collapsible#defaultOptions}.iconPos`
					 * value is used when collapsible is not in a collapsible-set or option isn't set
					 * @property {boolean} [options.inset=true] Determines if widget should be shown as inset
					 * @property {boolean} [options.mini=false] Sets widget to mini version
					 * @member ns.widget.mobile.Collapsible
					 */
					this.options = {
						expandCueText: " Expandable list, tap to open list",
						collapseCueText: " Expandable list, tap to close list",
						collapsed: true,
						heading: "h1,h2,h3,h4,h5,h6,legend,li",
						theme: null,
						contentTheme: null,
						collapsedIcon: null,
						expandedIcon: null,
						iconpos: null,
						inset: false,
						mini: false
					};
					// theme, collapsedIcon, expandedIcon, iconpos set as null
					// because they may be overriden with collapsible-set options

					this._eventHandlers = {};
				},
				/**
				 * Dictionary object containing commonly used wiget classes
				 * @property {Object} classes
				 * @readonly
				 * @static
				 * @member ns.widget.mobile.Collapsible
				 */
				classes = {
					uiCollapsible: "ui-collapsible",
					uiCollapsibleContent: "ui-collapsible-content",
					uiCollapsibleContentCollapsed: "ui-collapsible-content-collapsed",
					uiCollapsibleCollapsed: "ui-collapsible-collapsed",
					uiCollapsibleInset: "ui-collapsible-inset",
					uiCollapsibleHeading: "ui-collapsible-heading",
					uiCollapsibleHeadingCollapsed: "ui-collapsible-heading-collapsed",
					uiCollapsibleHeadingStatus: "ui-collapsible-heading-status",
					uiCollapsibleHeadingToggle: "ui-collapsible-heading-toggle",
					uiCornerTop: "ui-corner-top",
					uiCornerBottom: "ui-corner-bottom",
					uiIcon: "ui-icon",
					uiLiActive: "ui-li-active",
					// Prefixes
					uiBodyPrefix: "ui-body-",
					uiIconPrefix: "ui-icon-",
					uiDisabled: "ui-disabled"
				};


			Collapsible.prototype = new BaseWidget();

			/**
			 * Default options for settings of collapsible widget
			 * @property {Object} defaultOptions
			 * @property {string} defaultOptions.theme="s"
			 * @property {string} defaultOptions.collapsedIcon="arrow-u"
			 * @property {string} defaultOptions.expandedIcon="arrow-d"
			 * @property {string} defaultOptions.iconpos="right"
			 * @static
			 * @readonly
			 * @member ns.widget.mobile.Collapsible
			 */
			Collapsible.defaultOptions = {
				theme: "s",
				collapsedIcon: "arrow-u",
				expandedIcon: "arrow-d",
				iconpos: "right"
			};

			Collapsible.classes = classes;

			/**
			 * Build widget structure
			 * @method _build
			 * @protected
			 * @param {HTMLElement} element
			 * @return {HTMLElement}
			 * @member ns.widget.mobile.Collapsible
			 */
			Collapsible.prototype._build = function (element) {
				var defaults = Collapsible.defaultOptions,
					options = this.options,
					elementClassList = element.classList,
					header,
					headerLink,
					headerLinkClassList,
					headerStatus,
					content,
					alterHeader,
					parentCollapsibleSet = selectors.getClosestBySelector(element, "[data-role='collapsible-set']"),
					getDataFromParentSet = domUtils.getNSData.bind(null, parentCollapsibleSet);

				if ((element.parentNode.tagName.toLowerCase() === "ul") && (element.tagName.toLowerCase() === "div")) {
					ns.warn("Don't make the collapsible list using <div>. It violates standard of HTML rule. Instead of, please use <li>.");
				}
				elementClassList.add(classes.uiCollapsible);

				// First child matching selector is collapsible header
				header = selectors.getChildrenBySelector(element, options.heading)[0];
				if (!header) {
										header = document.createElement("h1");
					element.appendChild(header);
				}

				if (header.tagName.toLowerCase() === "legend") {
					alterHeader = document.createElement("div");
					alterHeader.setAttribute("role", "heading");
					alterHeader.innerHTML = header.innerHTML;

					element.replaceChild(alterHeader, header);
					header = alterHeader;
				}
				header.classList.add(classes.uiCollapsibleHeading);

				// Wrap all widget content
				domUtils.wrapInHTML(element.childNodes, "<div class='" + classes.uiCollapsibleContent + "'></div>");

				// Move header out
				header = element.insertBefore(header, element.firstChild);
				// .. and set reference to content
				content = header.nextElementSibling;

				if (parentCollapsibleSet) {
					// If set theme from parent set or closest element and if everything is empty set default
					if (!options.theme) {
						options.theme = getDataFromParentSet("theme") || themes.getInheritedTheme(element) || defaults.theme;
					}

					if (!options.contentTheme) {
						options.contentTheme = getDataFromParentSet("content-theme");
					}
					//Get the preference for collapsed icon in the set
					if (!options.collapsedIcon) {
						options.collapsedIcon = getDataFromParentSet("collapsed-icon");
					}
					// Get the preference for expanded icon in the set
					if (!options.expandedIcon) {
						options.expandedIcon = getDataFromParentSet("expanded-icon");
					}
					// Gets the preference icon position in the set
					if (!options.iconpos) {
						options.iconpos = getDataFromParentSet("iconpos");
					}
					// Inherit the preference for inset from collapsible-set
					if (getDataFromParentSet("inset") !== undefined) {
						options.inset = getDataFromParentSet("inset");
					}
					// Gets the preference for mini in the set
					if (!options.mini) {
						options.mini = getDataFromParentSet("mini");
					}
				} else {
					if (!options.theme) {
						options.theme = themes.getInheritedTheme(element) || defaults.theme;
					}
				}

				if (options.contentTheme) {
					content.classList.add(classes.uiBodyPrefix + options.contentTheme);
				}

				// Based on value from:
				// elements data-collapsed-icon or passed options
				// [-> collapsible-set data-collapsed-icon]
				// -> defaultValue
				options.collapsedIcon = options.collapsedIcon || defaults.collapsedIcon;
				// Based on value from:
				// elements data-expanded-icon or passed options
				// [-> collapsible-set data-collapsed-icon]
				// -> defaultValue
				options.expandedIcon = options.expandedIcon || defaults.expandedIcon;

				options.iconpos = options.iconpos || defaults.iconpos;

				headerStatus = document.createElement("span");
				headerStatus.classList.add(classes.uiCollapsibleHeadingStatus);

				header.appendChild(headerStatus);

				domUtils.wrapInHTML(header.childNodes, "<a class='" + classes.uiCollapsibleHeadingToggle + "'></a>");
				headerLink = header.firstElementChild;
				headerLinkClassList = headerLink.classList;

				headerLinkClassList.add(classes.uiIconPrefix + options.iconpos);
				headerLinkClassList.add(classes.uiIconPrefix + options.collapsedIcon);

				headerLink.removeAttribute("role");

				// Append everything to header
				header.appendChild(headerLink);

				if (options.inset) {
					elementClassList.add(classes.uiCollapsibleInset);
					header.classList.add(classes.uiCornerTop);
					header.classList.add(classes.uiCornerBottom);
				}

				Collapsible.prototype.options = options;

				return element;
			};

			// Handler function for expanding/collapsing widget
			// @method toggleCollapsibleHandler
			// @param {HTMLElement} element
			// @param {Object} options
			// @param {Event} event
			// @private
			function toggleCollapsibleHandler(element, options, event) {
				var elementClassList = element.classList,
					header = selectors.getChildrenByClass(element, classes.uiCollapsibleHeading)[0],
					headerClassList = header.classList,
					headerStatus = header.querySelector("." + classes.uiCollapsibleHeadingStatus),
					headerLink = header.firstElementChild,
					headerLinkClassList = headerLink.classList,
					content = selectors.getChildrenByClass(element, classes.uiCollapsibleContent)[0],
					parentCollapsibleSet = selectors.getClosestBySelector(element, "[data-role='collapsible-set']"),
					isCollapse = event.type === "collapse";

				if (event.defaultPrevented) {
					return;
				}

				event.preventDefault();

				// @TODO customEventHandler or max-height from WebUI
				// is defined inside of themes/tizen/tizen-white/theme.js and themes/tizen/tizen-black/theme.js
				// those handlers set max-height property
				//if (options.customEventHandler) {
				//	options.customEventHandler.call(element, isCollapse);
				//}

				//Toggle functions switched to if/else statement due to toggle bug on Tizen
				if (isCollapse) {
					headerClassList.add(classes.uiCollapsibleHeadingCollapsed);
					headerLinkClassList.remove(classes.uiIconPrefix + options.expandedIcon);
					headerLinkClassList.add(classes.uiIconPrefix + options.collapsedIcon);
					elementClassList.add(classes.uiCollapsibleCollapsed);
					content.classList.add(classes.uiCollapsibleContentCollapsed);
				} else {
					headerClassList.remove(classes.uiCollapsibleHeadingCollapsed);
					headerLinkClassList.add(classes.uiIconPrefix + options.expandedIcon);
					headerLinkClassList.remove(classes.uiIconPrefix + options.collapsedIcon);
					elementClassList.remove(classes.uiCollapsibleCollapsed);
					content.classList.remove(classes.uiCollapsibleContentCollapsed);
				}

				headerStatus.innerHTML = isCollapse ? options.expandCueText : options.collapseCueText;

				if(options.expandedIcon === options.collapsedIcon) {
					headerLinkClassList.add(classes.uiIconPrefix + options.collapsedIcon);
				}

				content.setAttribute("aria-hidden", isCollapse);

				if (options.contentTheme && options.inset && (!parentCollapsibleSet || domUtils.getNSData(element, "collapsible-last"))) {
					slice.call(header.querySelectorAll("." + classes.uiCollapsibleHeadingToggle)).forEach(function (value) {

						if (isCollapse) {
							value.classList.add(classes.uiCornerBottom);
						} else {
							value.classList.remove(classes.uiCornerBottom);
						}
					});

					if (isCollapse) {
						headerLink.classList.add(classes.uiCornerBottom);
						content.classList.remove(classes.uiCornerBottom);
					} else {
						headerLink.classList.remove(classes.uiCornerBottom);
						content.classList.add(classes.uiCornerBottom);
					}
				}

				// @TODO ?
				//content.trigger( "updatelayout" );
				events.trigger(element, isCollapse ? "collapsed" : "expanded");
			}

			/**
			 * Bind widget events
			 * @method _bindEvents
			 * @protected
			 * @param {HTMLElement} element
			 * @member ns.widget.mobile.Collapsible
			 */
			Collapsible.prototype._bindEvents = function (element) {
				var options = this.options,
					eventHandlers = this._eventHandlers,
					toggleHandler,
					removeActiveClass,
					header = selectors.getChildrenByClass(element, classes.uiCollapsibleHeading)[0],
					setActiveHeaderLinkClass = function (setClass) {
						var headerClassList = header.classList;

						if (setClass) {
							headerClassList.add(classes.uiLiActive);
						} else {
							headerClassList.remove(classes.uiLiActive);
						}
					};

				// Declare handlers with and assign them to local variables
				toggleHandler = eventHandlers.toggleHandler = toggleCollapsibleHandler.bind(null, element, options);
				removeActiveClass = eventHandlers.removeActiveClass = setActiveHeaderLinkClass.bind(null, false);
				eventHandlers.addActiveClass = setActiveHeaderLinkClass.bind(null, true);
				eventHandlers.toggleCollapsiness = function toggleCollapsiness(event) {
					var eventType = header.classList.contains(classes.uiCollapsibleHeadingCollapsed) ? "expand" : "collapse";

					events.trigger(element, eventType);

					event.preventDefault();
					events.stopPropagation(event);
				};

				// Handle "expand" and "collapse" events
				element.addEventListener("expand", toggleHandler, false);
				element.addEventListener("collapse", toggleHandler, false);

				// Handle "vmousedown" event (this event is triggered with "touchstart" too)
				header.addEventListener("vmousedown", eventHandlers.addActiveClass, false);

				// Handle "vmousemove", "vmousecancel" and "vmouseup" events
				header.addEventListener("vmousemove", removeActiveClass, false);
				header.addEventListener("vmousecancel", removeActiveClass, false);
				header.addEventListener("vmouseup", removeActiveClass, false);

				// Handle touching and clicking
				header.addEventListener("vclick", eventHandlers.toggleCollapsiness, false);

				events.trigger(element, options.collapsed ? "collapse" : "expand");
			};

			/**
			 * This method refreshes collapsible.
			 *
			 *		@example
			 *		<div id="collapsible" data-role="collapsible" data-inset="false">
			 *			<h6>Collapsible head</h6>
			 *			<div>Content</div>
			 *		</div>
			 *
			 *		<script>
			 *			var collapsibleWidget = tau.widget.Collapsible(document.getElementById("collapsible"));
			 *			collapsibleWidget.refresh();
			 *		</script>
			 *
			 * If jQuery is loaded:
			 *
			 *		@example
			 *		<div id="collapsible" data-role="collapsible" data-inset="false">
			 *			<h6>Collapsible head</h6>
			 *			<div>Content</div>
			 *		</div>
			 *
			 *		<script>
			 *			$("#collapsible").collapsible("refresh");
			 *		</script>
			 *
			 * @method refresh
			 * @chainable
			 * @member ns.widget.mobile.Collapsible
			 */

			/**
			* Refresh structure
			* @method _refresh
			* @protected
			* @member ns.widget.mobile.Collapsible
			*/
			Collapsible.prototype._refresh = function () {
				return;
			};

			/**
			 * Removes the collapsible functionality completely.
			 *
			 *		@example
			 *		<div id="collapsible" data-role="collapsible" data-inset="false">
			 *			<h6>Collapsible head</h6>
			 *			<div>Content</div>
			 *		</div>
			 *
			 *		<script>
			 *			var collapsibleWidget = tau.widget.Collapsible(document.getElementById("collapsible"));
			 *			collapsibleWidget.destroy();
			 *		</script>
			 *
			 * If jQuery is loaded:
			 *
			 *		@example
			 *		<div id="collapsible" data-role="collapsible" data-inset="false">
			 *			<h6>Collapsible head</h6>
			 *			<div>Content</div>
			 *		</div>
			 *
			 *		<script>
			 *			$("#collapsible").collapsible("destroy");
			 *		</script>
			 *
			 * @method destroy
			 * @member ns.widget.mobile.Collapsible
			 */

			/**
			 * Destroy widget
			 * @method _destroy
			 * @protected
			 * @member ns.widget.mobile.Collapsible
			 */
			Collapsible.prototype._destroy = function () {
				var element = this.element,
					header = selectors.getChildrenByClass(element, classes.uiCollapsibleHeading)[0],
					eventHandlers = this._eventHandlers,
					toggleHandler = eventHandlers.toggleHandler,
					removeActiveClassHandler = eventHandlers.removeActiveClass,
					parentNode = element.parentNode;

				// Remove "expand" and "collapse" listeners
				element.removeEventListener("expand", toggleHandler, false);
				element.removeEventListener("collapse", toggleHandler, false);

				// Remove "vmousedown" event (this event is triggered with "touchstart" too) listeners
				header.removeEventListener("vmousedown", eventHandlers.addActiveClass, false);

				// Remove "vmousemove", "vmousecancel" and "vmouseup" events listeners
				header.removeEventListener("vmousemove", removeActiveClassHandler, false);
				header.removeEventListener("vmousecancel", removeActiveClassHandler, false);
				header.removeEventListener("vmouseup", removeActiveClassHandler, false);

				// Remove touching and clicking event listeners
				header.removeEventListener("vclick", eventHandlers.toggleCollapsiness, false);

				// @TODO remove all operations performed on _build
				// maybe store base structure inside element's object property as string
				// instead of reversing all operations?

				events.trigger(document, "destroyed", {
					widget: "Collapsible",
					parent: parentNode
				});
			};

			/**
			 * Get/Set options of the widget.
			 *
			 * This method can work in many context.
			 *
			 * If first argument is type of object them, method set values for
			 * options given in object. Keys of object are names of options and
			 * values from object are values to set.
			 *
			 * If you give only one string argument then method return value
			 * for given option.
			 *
			 * If you give two arguments and first argument will be a string
			 * then second argument will be intemperate as value to set.
			 *
			 *		@example
			 *		<div id="collapsible" data-role="collapsible" data-inset="false">
			 *			<h6>Collapsible head</h6>
			 *			<div>Content</div>
			 *		</div>
			 *
			 *		<script>
			 *			var collapsibleWidget = tau.widget.Collapsible(document.getElementById("collapsible")),
			 *				value;
			 *
			 *			value = collapsibleWidget.option("mini"); // get value
			 *			collapsibleWidget.option("mini", true); // set value
			 *		</script>
			 *
			 * If jQuery is loaded:
			 *
			 *		@example
			 *		<div id="collapsible" data-role="collapsible" data-inset="false">
			 *			<h6>Collapsible head</h6>
			 *			<div>Content</div>
			 *		</div>
			 *
			 *		<script>
			 *			var value;
			 *
			 *			value = $("#collapsible").collapsible("option", "mini"); // get value
			 *			$("#collapsible").collapsible("option", "mini", true); // set value
			 *		</script>
			 *
			 * @method option
			 * @param {string|Object} [name] name of option
			 * @param {*} value value to set
			 * @member ns.widget.mobile.Collapsible
			 * @return {*} return value of option or undefined if method is called in setter context
			 */

			/**
			 * The function "value" is not supported in this widget.
			 *
			 * @method value
			 * @chainable
			 * @member ns.widget.mobile.FieldContain
			 */

			/**
			 * Disable the collapsible
			 *
			 * Method adds disabled attribute on collapsible and adds classes
			 * related with disabled state.
			 *
			 *		@example
			 *		<div id="collapsible" data-role="collapsible" data-inset="false">
			 *			<h6>Collapsible head</h6>
			 *			<div>Content</div>
			 *		</div>
			 *
			 *		<script>
			 *			var collapsibleWidget = tau.widget.Collapsible(document.getElementById("collapsible"));
			 *			collapsibleWidget.disable();
			 *		</script>
			 *
			 * If jQuery is loaded:
			 *
			 *		@example
			 *		<div id="collapsible" data-role="collapsible" data-inset="false">
			 *			<h6>Collapsible head</h6>
			 *			<div>Content</div>
			 *		</div>
			 *
			 *		<script>
			 *			$("#collapsible").collapsible("disable");
			 *		</script>
			 *
			 * @method disable
			 * @chainable
			 * @member ns.widget.mobile.Collapsible
			 */

			/**
			 * Enable the collapsible
			 *
			 * Method removes disabled attribute on collapsible and adds
			 * classes related with enabled state.
			 *
			 *		@example
			 *		<div id="collapsible" data-role="collapsible" data-inset="false">
			 *			<h6>Collapsible head</h6>
			 *			<div>Content</div>
			 *		</div>
			 *
			 *		<script>
			 *			var collapsibleWidget = tau.widget.Collapsible(document.getElementById("collapsible"));
			 *			collapsibleWidget.enable();
			 *		</script>
			 *
			 * If jQuery is loaded:
			 *
			 *		@example
			 *		<div id="collapsible" data-role="collapsible" data-inset="false">
			 *			<h6>Collapsible head</h6>
			 *			<div>Content</div>
			 *		</div>
			 *
			 *		<script>
			 *			$("#collapsible").collapsible("enable");
			 *		</script>
			 *
			 * @method enable
			 * @chainable
			 * @member ns.widget.mobile.Collapsible
			 */

			/*
			 * Trigger an event on widget's element.
			 *
			 *		@example
			 *		<div id="collapsible" data-role="collapsible" data-inset="false">
			 *			<h6>Collapsible head</h6>
			 *			<div>Content</div>
			 *		</div>
			 *
			 *		<script>
			 *			var collapsibleWidget = tau.widget.Collapsible(document.getElementById("collapsible"));
			 *			collapsibleWidget.trigger("eventName");
			 *		</script>
			 *
			 * If jQuery is loaded:
			 *
			 *		@example
			 *		<div id="collapsible" data-role="collapsible" data-inset="false">
			 *			<h6>Collapsible head</h6>
			 *			<div>Content</div>
			 *		</div>
			 *
			 *		<script>
			 *			$("#collapsible").collapsible("trigger", "eventName");
			 *		</script>
			 *
			 * @method trigger
			 * @param {string} eventName the name of event to trigger
			 * @param {?*} [data] additional object to be carried with the event
			 * @param {boolean} [bubbles=true] indicating whether the event bubbles up through the DOM or not
			 * @param {boolean} [cancelable=true] indicating whether the event is cancelable
			 * @return {boolean} false, if any callback invoked preventDefault on event object
			 * @member ns.widget.mobile.Collapsible
			 */

			/**
			 * Add event listener to widget's element.
			 *
			 *		@example
			 *		<div id="collapsible" data-role="collapsible" data-inset="false">
			 *			<h6>Collapsible head</h6>
			 *			<div>Content</div>
			 *		</div>
			 *
			 *		<script>
			 *			var collapsibleWidget = tau.widget.Collapsible(document.getElementById("collapsible"));
			 *			collapsibleWidget.on("eventName", function () {
			 *				console.log("Event fires");
			 *			});
			 *		</script>
			 *
			 * If jQuery is loaded:
			 *
			 *		@example
			 *		<div id="collapsible" data-role="collapsible" data-inset="false">
			 *			<h6>Collapsible head</h6>
			 *			<div>Content</div>
			 *		</div>
			 *
			 *		<script>
			 *			$("#collapsible").collapsible("on", "eventName", function () {
			 *				console.log("Event fires");
			 *			});
			 *		</script>
			 *
			 * @method on
			 * @param {string} eventName the name of event
			 * @param {Function} listener function call after event will be trigger
			 * @param {boolean} [useCapture=false] useCapture param tu addEventListener
			 * @member ns.widget.mobile.Collapsible
			 */

			/**
			 * Remove event listener to widget's element.
			 *
			 *		@example
			 *		<div id="collapsible" data-role="collapsible" data-inset="false">
			 *			<h6>Collapsible head</h6>
			 *			<div>Content</div>
			 *		</div>
			 *
			 *		<script>
			 *			var collapsibleWidget = tau.widget.Collapsible(document.getElementById("collapsible")),
			 *				callback = function () {
			 *					console.log("Event fires");
			 *				};
			 *			// add callback on event "eventName"
			 *			collapsibleWidget.on("eventName", callback);
			 *			// ...
			 *			// remove callback on event "eventName"
			 *			collapsibleWidget.off("eventName", callback);
			 *		</script>
			 *
			 * If jQuery is loaded:
			 *
			 *		@example
			 *		<div id="collapsible" data-role="collapsible" data-inset="false">
			 *			<h6>Collapsible head</h6>
			 *			<div>Content</div>
			 *		</div>
			 *
			 *		<script>
			 *			var callback = function () {
			 *					console.log("Event fires");
			 *				};
			 *			// add callback on event "eventName"
			 *			$("#collapsible").collapsible("on", "eventName", callback);
			 *			// ...
			 *			// remove callback on event "eventName"
			 *			$("#collapsible").collapsible("off", "eventName", callback);
			 *		</script>
			 * @method off
			 * @param {string} eventName the name of event
			 * @param {Function} listener function call after event will be trigger
			 * @param {boolean} [useCapture=false] useCapture param tu addEventListener
			 * @member ns.widget.mobile.Collapsible
			 */

			// definition
			ns.widget.mobile.Collapsible = Collapsible;
			engine.defineWidget(
				"Collapsible",
				"[data-role='collapsible'], .ui-collapsible",
				[],
				Collapsible,
				"mobile"
			);
			}(window.document, ns));

/*global window, define */
/*
* Copyright  2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/*jslint nomen: true */
/**
 * #Collapsible Set Widget
 * Collapsible Set Widget groups many Collapsible Widgets in one container.
 *
 * ##Default selectors
 * In default all elements with _data-role="collapsible-set"_ or class _.ui-collapsible-set_ are changed to collapsibleset widget.
 *
 * ##HTML Examples
 *
 * ###Create collapsibleset by data-role
 *
 *		@example
 *		<div data-role="collapsible-set" data-theme="c" data-content-theme="d">
 *			<div data-role="collapsible" data-inset="false">
 *				<h6>Collapsible head 1</h6>
 *				<div>Content</div>
 *			</div>
 *			<div data-role="collapsible" data-inset="false">
 *				<h6>Collapsible head 2</h6>
 *				<div>Content</div>
 *			</div>
 *		</div>
 *
 * ###Create collapsibleset by class
 *
 *		@example
 *		<div class="ui-collapsible-set" data-theme="c" data-content-theme="d">
 *			<div data-role="collapsible" data-inset="false">
 *				<h6>Collapsible head 1</h6>
 *				<div>Content</div>
 *			</div>
 *			<div data-role="collapsible" data-inset="false">
 *				<h6>Collapsible head 2</h6>
 *				<div>Content</div>
 *			</div>
 *		</div>
 *
 * ## Manual constructor
 * For manual creation of collapsibleset widget you can use constructor of widget:
 *
 *		@example
 *		<div id="collapsibleset" data-theme="c" data-content-theme="d">
 *			<div data-role="collapsible" data-inset="false">
 *				<h6>Collapsible head 1</h6>
 *				<div>Content</div>
 *			</div>
 *			<div data-role="collapsible" data-inset="false">
 *				<h6>Collapsible head 2</h6>
 *				<div>Content</div>
 *			</div>
 *		</div>
 *
 *		<script>
 *			var collapsibleset = tau.widget.CollapsibleSet(document.getElementById("collapsibleset"));
 *		</script>
 *
 * If jQuery library is loaded, its method can be used:
 *
 *		@example
 *		<div id="collapsibleset" data-theme="c" data-content-theme="d">
 *			<div data-role="collapsible" data-inset="false">
 *				<h6>Collapsible head 1</h6>
 *				<div>Content</div>
 *			</div>
 *			<div data-role="collapsible" data-inset="false">
 *				<h6>Collapsible head 2</h6>
 *				<div>Content</div>
 *			</div>
 *		</div>
 *
 *		<script>
 *			var collapsibleset = $("#collapsibleset").collapsibleset();
 *		</script>
 *
 *
 * @class ns.widget.mobile.CollapsibleSet
 * @extends ns.widget.BaseWidget
 * @author Marcin Jakuszko <m.jakuszko@samsung.com>
 */

(function (document, ns) {
	
	
				/**
				 * @property {ns.engine} engine alias variable
				 * @private
				 * @static
				 */
			var engine = ns.engine,
				/**
				 * @property {ns.widget} widget alias variable
				 * @private
				 * @static
				 */
				widget = ns.widget,
				/**
				 * @property {ns.event} events alias variable
				 * @private
				 * @static
				 */
				events = ns.event,
				/**
				 * @property {ns.util.selectors} selectors alias variable
				 * @private
				 * @static
				 */
				selectors = ns.util.selectors,
				/**
				 * @property {ns.util.DOM} domUtils alias variable
				 * @private
				 * @static
				 */
				domUtils = ns.util.DOM,
				/**
				 * @property {Object} BaseWidget alias variable
				 * @private
				 * @static
				 */
				BaseWidget = widget.mobile.BaseWidgetMobile,
				prototype = new BaseWidget(),

				CollapsibleSet = function () {
					/**
					 * CollapsibleSet widget options
					 * @property {Object} options
					 * @property {?string} [options.theme=null] Sets the color scheme (swatch) for the collapsible set.
					 * @property {?string} [options.contentTheme=null] Sets the color scheme (swatch) for the content of collapsible set.
					 * @property {boolean} [options.inset=true] Determines if widget should be shown as inset.
					 * @property {boolean} [options.mini=false] Sets the size of the collapsibles to a more compact, mini version.
					 * @property {boolean} [options.collapsed=true] Determines if content should be collapsed on load.
					 * @property {?string} [options.collapsedIcon=null] Sets the icon for the headers of the collapsible containers when in a collapsed state.
					 * @property {?string} [options.expandedIcon=null] Sets the icon for the headers of the collapsible containers when in an expanded state.
					 * @member ns.widget.mobile.CollapsibleSet
					 */
					this.options = {
						theme: null,
						contentTheme: null,
						inset: null,
						mini: null,
						collapsed: true,
						collapsedIcon: null,
						expandedIcon: null
					};

					this._eventHandlers = {};
				};

			/**
			 * Dictionary object containing commonly used wiget classes
			 * @property {Object} classes
			 * @static
			 * @readonly
			 * @member ns.widget.mobile.CollapsibleSet
			 */
			CollapsibleSet.classes = {
				uiCollapsible: "ui-collapsible",
				uiCollapsibleSet: "ui-collapsible-set",
				uiCollapsibleHeading: "ui-collapsible-heading",
				uiCornerTop: "ui-corner-top",
				uiCornerBottom: "ui-corner-bottom",
				uiCollapsibleContent : "ui-collapsible-content"
			};


			/**
			 * Dictionary object containing commonly used wiget attributes
			 * @property {Object} attributes
			 * @static
			 * @readonly
			 * @member ns.widget.mobile.CollapsibleSet
			 */
			CollapsibleSet.attributes = {
				last: "collapsible-last"
			};

			/**
			 * Build widget structure
			 * @method _build
			 * @param {HTMLElement} element
			 * @return {HTMLElement}
			 * @protected
			 * @member ns.widget.mobile.CollapsibleSet
			 */
			prototype._build = function (element) {
				element.classList.add(CollapsibleSet.classes.uiCollapsibleSet);
				return element;
			};


			// Set proper corners' style for elements inside widget
			// @method roundCollapsibleSetBoundaries
			// @param {Array} collapsiblesInSet
			// @private
			// @member ns.widget.mobile.CollapsibleSet
			function roundCollapsibleSetBoundaries(collapsiblesInSet) {
				if(collapsiblesInSet.length > 0) {

					var firstCollapsible = collapsiblesInSet[0],
						classes = CollapsibleSet.classes,
						dataAttributes = CollapsibleSet.attributes,
						firstCollapsibleHeading = selectors.getChildrenByClass(firstCollapsible, classes.uiCollapsibleHeading)[0],

						lastCollapsible = collapsiblesInSet[collapsiblesInSet.length-1],
						lastCollapsibleHeading = selectors.getChildrenByClass(lastCollapsible, classes.uiCollapsibleHeading)[0];

					//clean up borders
					collapsiblesInSet.forEach(function(collapsibleElement) {
						var heading = selectors.getChildrenByClass(collapsibleElement, classes.uiCollapsibleHeading)[0],
							headingClassList = heading.classList;

						domUtils.removeNSData(collapsibleElement, dataAttributes.last);
						headingClassList.remove(classes.uiCornerBottom);
						headingClassList.remove(classes.uiCornerTop);
					});

					firstCollapsibleHeading.classList.add(classes.uiCornerTop);

					lastCollapsibleHeading.classList.add(classes.uiCornerBottom);
					domUtils.setNSData(lastCollapsible, dataAttributes.last, true);
				}
				return collapsiblesInSet;
			}

			//Handler function for expanding/collapsing widget
			//@method expandCollapseHandler
			//@param {HTMLElement} element
			//@param {Object} options
			//@param {Event} event
			//@private
			//@member ns.widget.mobile.CollapsibleSet
			function expandCollapseHandler(element, options, event) {
				var collapsible = event.target,
					isCollapse = event.type === "collapse",
					classes = CollapsibleSet.classes,
					dataAttributes = CollapsibleSet.attributes,
					firstCollapsible = element.firstChild,
					collapsibleHeading = selectors.getChildrenByClass(collapsible, classes.uiCollapsibleHeading)[0],
					collapsibleHeadingClassList = collapsibleHeading.classList,
					collapsibleContent = selectors.getChildrenByClass(collapsible, classes.uiCollapsibleContent)[0],
					collapsibleContentClassList =  collapsibleContent.classList;

				if(domUtils.hasNSData(collapsible, dataAttributes.last) && !!options.inset) {
					if(isCollapse) {
						collapsibleHeadingClassList.add(classes.uiCornerBottom);
						collapsibleContentClassList.remove(classes.uiCornerBottom);
					} else {
						collapsibleHeadingClassList.remove(classes.uiCornerBottom);
						collapsibleContentClassList.add(classes.uiCornerBottom);
					}
				}

				if(!isCollapse) {
					while(firstCollapsible) {
						if (firstCollapsible.nodeType === 1 && firstCollapsible !== collapsible) {
							events.trigger(firstCollapsible, "collapse");
						}
						firstCollapsible = firstCollapsible.nextSibling;
					}
				}
			}

			/**
			 * Bind widget events
			 * @method _bindEvents
			 * @param {HTMLElement} element
			 * @protected
			 * @member ns.widget.mobile.CollapsibleSet
			 */
			prototype._bindEvents = function (element) {
				var eventHandler = this._eventHandlers.expandCollapseHandler = expandCollapseHandler.bind(null, element, this.options);

				element.addEventListener("expand", eventHandler, true);
				element.addEventListener("collapse", eventHandler, true);

				return element;
			};

			/**
			 * Init widget
			 * @method _init
			 * @param {HTMLElement} element
			 * @protected
			 * @member ns.widget.mobile.CollapsibleSet
			 */
			prototype._init = function (element) {
				var expanded = selectors.getChildrenBySelector(element, "[data-collapsed='false']"),
					expandedLength = expanded.length,
					i;

				this.refresh();

				for(i = 0; i < expandedLength; i++) {
					events.trigger(expanded[i], "expand");
				}

			};

			/**
			 * This method refreshes collapsibleset.
			 *
			 *		@example
			 *		<div id="collapsibleset" data-role="collapsible-set" data-theme="c" data-content-theme="d">
			 *			<div data-role="collapsible" data-inset="false">
			 *				<h6>Collapsible head 1</h6>
			 *				<div>Content</div>
			 *			</div>
			 *			<div data-role="collapsible" data-inset="false">
			 *				<h6>Collapsible head 2</h6>
			 *				<div>Content</div>
			 *			</div>
			 *		</div>
			 *
			 *		<script>
			 *			var collapsiblesetWidget = tau.widget.CollapsibleSet(document.getElementById("collapsibleset"));
			 *			collapsiblesetWidget.refresh();
			 *		</script>
			 *
			 * If jQuery is loaded:
			 *
			 *		@example
			 *		<div id="collapsibleset" data-role="collapsible-set" data-theme="c" data-content-theme="d">
			 *			<div data-role="collapsible" data-inset="false">
			 *				<h6>Collapsible head 1</h6>
			 *				<div>Content</div>
			 *			</div>
			 *			<div data-role="collapsible" data-inset="false">
			 *				<h6>Collapsible head 2</h6>
			 *				<div>Content</div>
			 *			</div>
			 *		</div>
			 *
			 *		<script>
			 *			$("#collapsibleset").collapsibleset("refresh");
			 *		</script>
			 *
			 * @method refresh
			 * @chainable
			 * @member ns.widget.mobile.CollapsibleSet
			 */

			/**
			 * Refresh structure
			 * @method _refresh
			 * @protected
			 * @member ns.widget.mobile.CollapsibleSet
			 */
			prototype._refresh = function () {
				var element = this.element,
					collapsiblesInSet = selectors.getChildrenBySelector(element, "[data-role='collapsible']"),
					bareCollapsibles = selectors.getChildrenBySelector(element, ":not(.ui-collapsible)"),
					bareCollapsiblesLength = bareCollapsibles.length,
					i;

				for(i=0; i < bareCollapsiblesLength; i++) {
					engine.instanceWidget(bareCollapsibles[i], "Collapsible");
				}

				roundCollapsibleSetBoundaries(collapsiblesInSet);

				return this;
			};

			/**
			 * Removes the collapsibleset functionality completely.
			 *
			 * This will return the element back to its pre-init state.
			 *
			 *		@example
			 *		<div id="collapsibleset" data-role="collapsible-set" data-theme="c" data-content-theme="d">
			 *			<div data-role="collapsible" data-inset="false">
			 *				<h6>Collapsible head 1</h6>
			 *				<div>Content</div>
			 *			</div>
			 *			<div data-role="collapsible" data-inset="false">
			 *				<h6>Collapsible head 2</h6>
			 *				<div>Content</div>
			 *			</div>
			 *		</div>
			 *
			 *		<script>
			 *			var collapsiblesetWidget = tau.widget.CollapsibleSet(document.getElementById("collapsibleset"));
			 *			collapsiblesetWidget.destroy();
			 *		</script>
			 *
			 * If jQuery is loaded:
			 *
			 *		@example
			 *		<div id="collapsibleset" data-role="collapsible-set" data-theme="c" data-content-theme="d">
			 *			<div data-role="collapsible" data-inset="false">
			 *				<h6>Collapsible head 1</h6>
			 *				<div>Content</div>
			 *			</div>
			 *			<div data-role="collapsible" data-inset="false">
			 *				<h6>Collapsible head 2</h6>
			 *				<div>Content</div>
			 *			</div>
			 *		</div>
			 *
			 *		<script>
			 *			$("#collapsibleset").collapsibleset("destroy");
			 *		</script>
			 *
			 * @method destroy
			 * @member ns.widget.mobile.CollapsibleSet
			 */

			/**
			 * Destroy widget
			 * @method _destroy
			 * @protected
			 * @member ns.widget.mobile.CollapsibleSet
			 */
			prototype._destroy = function () {
				var element = this.element,
					eventHandler = this._eventHandlers.expandCollapseHandler;

				element.removeEventListener("expand", eventHandler, true);
				element.removeEventListener("collapse", eventHandler, true);
			};

			/**
			 * Get/Set options of the widget.
			 *
			 * This method can work in many context.
			 *
			 * If first argument is type of object them, method set values for options given in object. Keys of object are names of options and values from object are values to set.
			 *
			 * If you give only one string argument then method return value for given option.
			 *
			 * If you give two arguments and first argument will be a string then second argument will be intemperate as value to set.
			 *
			 *		@example
			 *		<div id="collapsibleset" data-role="collapsible-set" data-theme="c" data-content-theme="d">
			 *			<div data-role="collapsible" data-inset="false">
			 *				<h6>Collapsible head 1</h6>
			 *				<div>Content</div>
			 *			</div>
			 *			<div data-role="collapsible" data-inset="false">
			 *				<h6>Collapsible head 2</h6>
			 *				<div>Content</div>
			 *			</div>
			 *		</div>
			 *
			 *		<script>
			 *			var collapsiblesetWidget = tau.widget.CollapsibleSet(document.getElementById("collapsibleset")),
			 *				value;
			 *
			 *			value = collapsiblesetWidget.option("mini"); // get value
			 *			collapsiblesetWidget.option("mini", true); // set value
			 *		</script>
			 *
			 * If jQuery is loaded:
			 *
			 *		@example
			 *		<div id="collapsibleset" data-role="collapsible-set" data-theme="c" data-content-theme="d">
			 *			<div data-role="collapsible" data-inset="false">
			 *				<h6>Collapsible head 1</h6>
			 *				<div>Content</div>
			 *			</div>
			 *			<div data-role="collapsible" data-inset="false">
			 *				<h6>Collapsible head 2</h6>
			 *				<div>Content</div>
			 *			</div>
			 *		</div>
			 *
			 *		<script>
			 *			var value;
			 *
			 *			value = $("#collapsibleset").collapsibleset("option", "mini"); // get value
			 *			$("#collapsibleset").collapsibleset("option", "mini", true); // set value
			 *		</script>
			 *
			 * @method option
			 * @param {string|Object} [name] name of option
			 * @param {*} value value to set
			 * @member ns.widget.mobile.CollapsibleSet
			 * @return {*} return value of option or undefined if method is called in setter context
			 */

			/**
			 * The function "value" is not supported in this widget.
			 *
			 * @method value
			 * @chainable
			 * @member ns.widget.mobile.CollapsibleSet
			 */

			/**
			 * Disable the collapsibleset
			 *
			 * Method adds disabled attribute on collapsibleset and changes look of collapsibleset to disabled state.
			 *
			 *		@example
			 *		<div id="collapsibleset" data-role="collapsible-set" data-theme="c" data-content-theme="d">
			 *			<div data-role="collapsible" data-inset="false">
			 *				<h6>Collapsible head 1</h6>
			 *				<div>Content</div>
			 *			</div>
			 *			<div data-role="collapsible" data-inset="false">
			 *				<h6>Collapsible head 2</h6>
			 *				<div>Content</div>
			 *			</div>
			 *		</div>
			 *
			 *		<script>
			 *			var collapsiblesetWidget = tau.widget.CollapsibleSet(document.getElementById("collapsibleset"));
			 *			collapsiblesetWidget.disable();
			 *		</script>
			 *
			 * If jQuery is loaded:
			 *
			 *		@example
			 *		<div id="collapsibleset" data-role="collapsible-set" data-theme="c" data-content-theme="d">
			 *			<div data-role="collapsible" data-inset="false">
			 *				<h6>Collapsible head 1</h6>
			 *				<div>Content</div>
			 *			</div>
			 *			<div data-role="collapsible" data-inset="false">
			 *				<h6>Collapsible head 2</h6>
			 *				<div>Content</div>
			 *			</div>
			 *		</div>
			 *
			 *		<script>
			 *			$("#collapsibleset").collapsibleset("disable");
			 *		</script>
			 *
			 * @method disable
			 * @chainable
			 * @member ns.widget.mobile.CollapsibleSet
			 */

			/**
			 * Enable the collapsibleset
			 *
			 * Method removes disabled attribute on collapsibleset and changes look of collapsibleset to enabled state.
			 *
			 *		@example
			 *		<div id="collapsibleset" data-role="collapsible-set" data-theme="c" data-content-theme="d">
			 *			<div data-role="collapsible" data-inset="false">
			 *				<h6>Collapsible head 1</h6>
			 *				<div>Content</div>
			 *			</div>
			 *			<div data-role="collapsible" data-inset="false">
			 *				<h6>Collapsible head 2</h6>
			 *				<div>Content</div>
			 *			</div>
			 *		</div>
			 *
			 *		<script>
			 *			var collapsiblesetWidget = tau.widget.CollapsibleSet(document.getElementById("collapsibleset"));
			 *			collapsiblesetWidget.enable();
			 *		</script>
			 *
			 * If jQuery is loaded:
			 *
			 *		@example
			 *		<div id="collapsibleset" data-role="collapsible-set" data-theme="c" data-content-theme="d">
			 *			<div data-role="collapsible" data-inset="false">
			 *				<h6>Collapsible head 1</h6>
			 *				<div>Content</div>
			 *			</div>
			 *			<div data-role="collapsible" data-inset="false">
			 *				<h6>Collapsible head 2</h6>
			 *				<div>Content</div>
			 *			</div>
			 *		</div>
			 *
			 *		<script>
			 *			$("#collapsibleset").collapsibleset("enable");
			 *		</script>
			 *
			 * @method enable
			 * @chainable
			 * @member ns.widget.mobile.CollapsibleSet
			 */

			/*
			 * Trigger an event on widget's element.
			 *
			 *		@example
			 *		<div id="collapsibleset" data-role="collapsible-set" data-theme="c" data-content-theme="d">
			 *			<div data-role="collapsible" data-inset="false">
			 *				<h6>Collapsible head 1</h6>
			 *				<div>Content</div>
			 *			</div>
			 *			<div data-role="collapsible" data-inset="false">
			 *				<h6>Collapsible head 2</h6>
			 *				<div>Content</div>
			 *			</div>
			 *		</div>
			 *
			 *		<script>
			 *			var collapsiblesetWidget = tau.widget.CollapsibleSet(document.getElementById("collapsibleset"));
			 *			collapsiblesetWidget.trigger("eventName");
			 *		</script>
			 *
			 * If jQuery is loaded:
			 *
			 *		@example
			 *		<div id="collapsibleset" data-role="collapsible-set" data-theme="c" data-content-theme="d">
			 *			<div data-role="collapsible" data-inset="false">
			 *				<h6>Collapsible head 1</h6>
			 *				<div>Content</div>
			 *			</div>
			 *			<div data-role="collapsible" data-inset="false">
			 *				<h6>Collapsible head 2</h6>
			 *				<div>Content</div>
			 *			</div>
			 *		</div>
			 *
			 *		<script>
			 *			$("#collapsibleset").collapsibleset("trigger", "eventName");
			 *		</script>
			 *
			 * @method trigger
			 * @param {string} eventName the name of event to trigger
			 * @param {?*} [data] additional object to be carried with the event
			 * @param {boolean} [bubbles=true] indicating whether the event bubbles up through the DOM or not
			 * @param {boolean} [cancelable=true] indicating whether the event is cancelable
			 * @return {boolean} false, if any callback invoked preventDefault on event object
			 * @member ns.widget.mobile.CollapsibleSet
			 */

			/**
			 * Add event listener to widget's element.
			 *
			 *		@example
			 *		<div id="collapsibleset" data-role="collapsible-set" data-theme="c" data-content-theme="d">
			 *			<div data-role="collapsible" data-inset="false">
			 *				<h6>Collapsible head 1</h6>
			 *				<div>Content</div>
			 *			</div>
			 *			<div data-role="collapsible" data-inset="false">
			 *				<h6>Collapsible head 2</h6>
			 *				<div>Content</div>
			 *			</div>
			 *		</div>
			 *
			 *		<script>
			 *			var collapsiblesetWidget = tau.widget.CollapsibleSet(document.getElementById("collapsibleset"));
			 *			collapsiblesetWidget.on("eventName", function () {
			 *				console.log("Event fires");
			 *			});
			 *		</script>
			 *
			 * If jQuery is loaded:
			 *
			 *		@example
			 *		<div id="collapsibleset" data-role="collapsible-set" data-theme="c" data-content-theme="d">
			 *			<div data-role="collapsible" data-inset="false">
			 *				<h6>Collapsible head 1</h6>
			 *				<div>Content</div>
			 *			</div>
			 *			<div data-role="collapsible" data-inset="false">
			 *				<h6>Collapsible head 2</h6>
			 *				<div>Content</div>
			 *			</div>
			 *		</div>
			 *
			 *		<script>
			 *			$("#collapsibleset").collapsibleset("on", "eventName", function () {
			 *				console.log("Event fires");
			 *			});
			 *		</script>
			 *
			 * @method on
			 * @param {string} eventName the name of event
			 * @param {Function} listener function call after event will be trigger
			 * @param {boolean} [useCapture=false] useCapture param tu addEventListener
			 * @member ns.widget.mobile.CollapsibleSet
			 */

			/**
			 * Remove event listener to widget's element.
			 *
			 *		@example
			 *		<div id="collapsibleset" data-role="collapsible-set" data-theme="c" data-content-theme="d">
			 *			<div data-role="collapsible" data-inset="false">
			 *				<h6>Collapsible head 1</h6>
			 *				<div>Content</div>
			 *			</div>
			 *			<div data-role="collapsible" data-inset="false">
			 *				<h6>Collapsible head 2</h6>
			 *				<div>Content</div>
			 *			</div>
			 *		</div>
			 *
			 *		<script>
			 *			var collapsiblesetWidget = tau.widget.CollapsibleSet(document.getElementById("collapsibleset")),
			 *				callback = function () {
			 *					console.log("Event fires");
			 *				};
			 *			// add callback on event "eventName"
			 *			collapsiblesetWidget.on("eventName", callback);
			 *			// ...
			 *			// remove callback on event "eventName"
			 *			collapsiblesetWidget.off("eventName", callback);
			 *		</script>
			 *
			 * If jQuery is loaded:
			 *
			 *		@example
			 *		<div id="collapsibleset" data-role="collapsible-set" data-theme="c" data-content-theme="d">
			 *			<div data-role="collapsible" data-inset="false">
			 *				<h6>Collapsible head 1</h6>
			 *				<div>Content</div>
			 *			</div>
			 *			<div data-role="collapsible" data-inset="false">
			 *				<h6>Collapsible head 2</h6>
			 *				<div>Content</div>
			 *			</div>
			 *		</div>
			 *
			 *		<script>
			 *			var callback = function () {
			 *					console.log("Event fires");
			 *				};
			 *			// add callback on event "eventName"
			 *			$("#collapsibleset").collapsibleset("on", "eventName", callback);
			 *			// ...
			 *			// remove callback on event "eventName"
			 *			$("#collapsibleset").collapsibleset("off", "eventName", callback);
			 *		</script>
			 * @method off
			 * @param {string} eventName the name of event
			 * @param {Function} listener function call after event will be trigger
			 * @param {boolean} [useCapture=false] useCapture param tu addEventListener
			 * @member ns.widget.mobile.CollapsibleSet
			 */

			CollapsibleSet.prototype = prototype;

			// definition
			widget.mobile.CollapsibleSet = CollapsibleSet;
			engine.defineWidget(
				"CollapsibleSet",
				"[data-role='collapsible-set'], .ui-collapsible-set",
				[],
				CollapsibleSet,
				"mobile"
			);
			}(window.document, ns));

/*global window, define */
/*
* Copyright  2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/*jslint nomen: true, plusplus: true */

/**
 * # Dialog Widget
 * Display div as a model dialog page with inset appearance.
 *
 * Any page can be presented as a modal dialog by adding the data-rel="dialog"
 * attribute to the page anchor link. When the "dialog" attribute is applied,
 * the framework adds styles to add rounded corners, margins around the page
 * and a dark background to make the "dialog" appear to be suspended above
 * the page.
 *
  * ## Default selectors
 * By default all elements with _data-role=dialog_ are changed to Tizen Web UI
 * Dialog.
 *
 * In additional all elements with class _ui-dialog_ are changed to Tizen Web UI
 * Dialog.
 *
 * #### Create simple dialog from div using data-role
 *
 *		@example
 *		<div data-role="page" id="page1">
 *			<div data-role="header">
 *				<h1>Page</h1>
 *			</div>
 *			<div data-role="content" class="ui-content">
 *				<a data-role="button" href="#dialogPage"
 *					data-rel="dialog">Open dialog</a>
 *			</div>
 *		</div>
 *
 *		<div data-role="dialog" id="dialogPage">
 *			<div data-role="header">
 *				<h2>Dialog</h2>
 *			</div>
 *			<div data-role="content" class="ui-content">
 *				<p>I am a dialog</p>
 *			</div>
 *		</div>
 *
 * #### Create simple dialog from div using class selector
 *
 *		@example
 *		<div data-role="page" id="page1">
 *			<div data-role="header">
 *				<h1>Page</h1>
 *			</div>
 *			<div data-role="content" class="ui-content">
 *				<a data-role="button" href="#dialogPage"
 *					data-rel="dialog">Open dialog</a>
 *			</div>
 *		</div>
 *
 *		<div data-role="dialog" id="dialogPage">
 *			<div data-role="header">
 *				<h2>Dialog</h2>
 *			</div>
 *			<div data-role="content" class="ui-content">
 *				<p>I am a dialog</p>
 *			</div>
 *		</div>
 *
 * ## Manual constructor
 *
 *		@example
 *		<div data-role="page" id="page1">
 *			<div data-role="header">
 *				<h1>Page</h1>
 *			</div>
 *			<div data-role="content" class="ui-content">
 *				<a data-role="button" id="btn-open" href="#">Open dialog</a>
 *			</div>
 *		</div>
 *
 *		<div id="dialogPage">
 *			<div data-role="header">
 *				<h2>Dialog</h2>
 *			</div>
 *			<div data-role="content" class="ui-content">
 *				<p>I am a dialog</p>
 *			</div>
 *		</div>
 *		<script>
 *			var element = document.getElementById("dialogPage"),
 *				dialogOpen = function () {
 *					var dialog = tau.widget.Dialog(element);
 *				};
 *			document.getElementById("btn-open")
 *				.addEventListener("vclick", dialogOpen);
 *		</script>
 *
 * ## Options for Dialog
 * Options for widget can be defined as _data-..._ attributes or given
 * as parameter in constructor.
 *
 * You can change option for widget using method **option**.
 *
 * ### closeBtn
 * _data-close-btn_ Position of the dialog close button
 * in the header
 *
 *		@example
 *		<div data-role="page" id="page1">
 *			<div data-role="header">
 *				<h1>Page</h1>
 *			</div>
 *			<div data-role="content" class="ui-content">
 *				<a data-role="button" href="#dialogPage"
 *					data-rel="dialog">Open dialog</a>
 *			</div>
 *		</div>
 *
 *		<div data-role="dialog" data-close-btn="left" id="dialogPage">
 *			<div data-role="header">
 *				<h2>Dialog</h2>
 *			</div>
 *			<div data-role="content" class="ui-content">
 *				<p>I am a dialog</p>
 *			</div>
 *		</div>
 *
 * ### closeBtnText
 * _data-close-btn-text_ Customize text of the close button,
 * by default close button is displayed as an icon-only so the text
 * isn't visible, but is read by screen readers
 *
 *		@example
 *		<div data-role="page" id="page1">
 *			<div data-role="header">
 *				<h1>Page</h1>
 *			</div>
 *			<div data-role="content" class="ui-content">
 *				<a data-role="button" href="#dialogPage"
 *					data-rel="dialog">Open dialog</a>
 *			</div>
 *		</div>
 *
 *		<div data-role="dialog" data-close-btn="left"
 *			data-close-btn-text="Click to close" id="dialogPage">
 *			<div data-role="header">
 *				<h2>Dialog</h2>
 *			</div>
 *			<div data-role="content" class="ui-content">
 *				<p>I am a dialog</p>
 *			</div>
 *		</div>
 *
 * ### overlayTheme
 * _data-overlay-theme_ Background under dialog content color
 *
 *		@example
 *		<div data-role="page" id="page1">
 *			<div data-role="header">
 *				<h1>Page</h1>
 *			</div>
 *			<div data-role="content" class="ui-content">
 *				<a data-role="button" href="#dialogPage"
 *					data-rel="dialog">Open dialog</a>
 *			</div>
 *		</div>
 *
 *		<div data-role="dialog" data-overlay-theme="s" id="dialogPage">
 *			<div data-role="header">
 *				<h2>Dialog</h2>
 *			</div>
 *			<div data-role="content" class="ui-content">
 *				<p>I am a dialog</p>
 *			</div>
 *		</div>
 *
 * ### corners
 * _data-corners_ Sets if dialog should be drawn with rounded corners
 *
 *		@example
 *		<div data-role="page" id="page1">
 *			<div data-role="header">
 *				<h1>Page</h1>
 *			</div>
 *			<div data-role="content" class="ui-content">
 *				<a data-role="button" href="#dialogPage"
 *					data-rel="dialog">Open dialog</a>
 *			</div>
 *		</div>
 *
 *		<div data-role="dialog" data-corners="false" id="dialogPage">
 *			<div data-role="header">
 *				<h2>Dialog</h2>
 *			</div>
 *			<div data-role="content" class="ui-content">
 *				<p>I am a dialog</p>
 *			</div>
 *		</div>
 *
 * @class ns.widget.mobile.Dialog
 * @extends ns.widget.BaseWidget
 */
(function (document, ns) {
	
				/**
			 * Widget Alias for {@link ns.widget.BaseWidget}
			 * @property {Object}
			 * @member ns.widget.mobile.Dialog
			 * @private
			 * @static
			 */
			var BaseWidget = ns.widget.mobile.BaseWidgetMobile,
				/**
				 * Alias for class {@link ns.engine}
				 * @property {Object} engine
				 * @member ns.widget.mobile.Dialog
				 * @private
				 * @static
				 */
				engine = ns.engine,
				/**
				 * Alias to {@link ns.util.selectors}
				 * @property {Object} selectors
				 * @member ns.widget.mobile.Dialog
				 * @private
				 * @static
				 */
				selectors = ns.util.selectors,
				/**
				 * Alias to {@link ns.util.DOM}
				 * @property {Object} dom
				 * @member ns.widget.mobile.Dialog
				 * @private
				 * @static
				 */
				doms = ns.util.DOM,
				/**
				 * Alias to {@link ns.event}
				 * @property {Object} events
				 * @private
				 * @static
				 */
				events = ns.event,
				/**
				 * Alias to {@link ns.widget.mobile.Button#classes}
				 * @property {Object} buttonClasses
				 * @member ns.widget.mobile.Dialog
				 * @private
				 * @static
				 */
				buttonClasses = ns.widget.mobile.Button.classes,

				/**
				 * Dictionary for dialog related css class names
				 * @property {Object} classes
				 * @member ns.widget.mobile.Dialog
				 * @static
				 * @readonly
				 * @property {string} classes.uiDialog Main Dialog class name
				 * @property {string} classes.uiDialogContain
				 * Dialog container class name
				 * @property {string} classes.uiOverlayShadow
				 * Dialog overlay shadow
				 * @property {string} classes.uiOverlayPrefix
				 * @property {string} classes.uiCornerAll
				 * Class for all Dialog corners
				 * @property {string} classes.uiHeader
				 * @property {string} classes.uiContent
				 * @property {string} classes.uiFooter
				 * @property {string} classes.uiBarPrefix
				 * @property {string} classes.uiBodyPrefix
				 * @property {string} classes.uiDialogHidden
				 */
				classes = {
					uiDialog: "ui-dialog",
					uiDialogContain: "ui-dialog-contain",
					uiOverlayShadow: "ui-overlay-shadow",
					uiOverlayPrefix: "ui-overlay-",
					uiCornerAll: "ui-corner-all",
					uiHeader: "ui-header",
					uiContent: "ui-content",
					uiFooter: "ui-footer",
					uiBarPrefix: "ui-bar-",
					uiBodyPrefix: "ui-body-",
					uiDialogHidden: "ui-dialog-hidden"
				},

				Dialog = function () {
					var self = this;
					/**

					 * Object with default options
					 * @property {Object} options
					 * @property {"left"|"right"|"none"} [options.closeBtn="left"] Position of the dialog close button in the header, accepts: left, right and none
					 * @property {string} [options.closeBtnText="Close"] Customize text of the close button, by default close button is displayed as an icon-only so the text isn't visible, but is read by screen readers
					 * @property {string} [options.closeLinkSelector="a[data-rel='back']"] Selector for buttons used to closing dialog
					 * @property {string} [options.overlayTheme="c"] Backgroudn under dialog content color
					 * @property {boolean} [options.corners=true] Sets if dialog should be drawn with rounded corners
					 * @property {string} [options.page=""] Sets if of related page
					 * @member ns.widget.mobile.Dialog
					 */
					self.options = {
						closeBtn : "left",
						closeBtnText : "Close",
						closeLinkSelector: "a[data-rel='back']",
						overlayTheme : "c",
						corners : true,
						page: ""
					};

					self._eventHandlers = {};
					self._ui = {
						page: null // page related with this dialog
					};

				};

			/**
			 * Dictionary for dialog related css class names
			 * @property {Object} classes
			 * @protected
			 */
			Dialog.classes = classes;

			Dialog.prototype = new BaseWidget();


			/**
			* Create close button.
			* @method createCloseButton
			* @param {HTMLElement} element
			* @param {"none"|"left"|"right"} location="none"
			* @param {string} text
			* @private
			* @static
			* @member ns.widget.mobile.Dialog
			*/
			function createCloseButton (element, location, text) {
				var button,
					header;

				if (location !== "left" && location !== "right") {
					location = "none";
				}

				// if location of closing button is set, button is created
				if (location !== "none") {
					button = document.createElement("a");
					button.setAttribute("data-rel", "back");
					button.className = buttonClasses.uiBtn + "-" + location;
					button.textContent = text || "";

					header = element.getElementsByClassName(classes.uiHeader)[0];
					if (header) {
						header.insertBefore(button, header.firstChild);
					}

					engine.instanceWidget(button, "Button", {
						iconpos: "notext",
						icon: "delete",
						inline: true,
						corners: true
					});
				}
			}

			/**
			 * Set page active / unactive
			 * @method setActive
			 * @param {boolean} value
			 * @member ns.widget.mobile.Dialog
			 * @protected
			 */
			Dialog.prototype.setActive = function (value) {
				var self = this,
					options = self.options,
					elementClassList = self.element.classList,
					dialogClasses = classes,
					pageClasses = ns.widget.mobile.Page.classes;
				if (value) {
					elementClassList.remove(dialogClasses.uiDialogHidden);
					elementClassList.add(pageClasses.uiPage);
					elementClassList.add(pageClasses.uiPageActive);
					elementClassList.add(dialogClasses.uiOverlayPrefix +
							options.overlayTheme);
				} else {
					elementClassList.remove(pageClasses.uiPage);
					elementClassList.remove(pageClasses.uiPageActive);
					elementClassList.remove(dialogClasses.uiOverlayPrefix +
							options.overlayTheme);
					elementClassList.add(dialogClasses.uiDialogHidden);
				}
			};

			/**
			 * Builds Dialog widget
			 * @method _build
			 * @param {HTMLElement} element
			 * @returns {HTMLElement}
			 * @protected
			 * @member ns.widget.mobile.Dialog
			 */
			Dialog.prototype._build = function (element) {
				var self = this,
					container = document.createElement("div"),
					childrenLength = element.children.length,
					getChildrenBySelector = selectors.getChildrenBySelector,
					headers = getChildrenBySelector(element, "[data-role='header']"),
					content = getChildrenBySelector(element, "[data-role='content']"),
					footers = getChildrenBySelector(element, "[data-role='footer']"),
					options = self.options,
					pageOptions = ns.widget.mobile.Page.prototype.options,
					containerClassList = container.classList,
					headersClassList,
					dataTheme,
					elementTheme,
					contentTheme,
					page,
					pageId,
					i,
					l;


				page = selectors.getClosestBySelector(element, "[data-role='page']");
				pageId = page ? page.id : "";
				doms.setNSData(element, "page", pageId);
				options.page = pageId;


				dataTheme = element.getAttribute("data-theme");
				elementTheme = dataTheme ? dataTheme : options.overlayTheme;
				contentTheme = dataTheme ? dataTheme : pageOptions.contentTheme;

				element.classList.add(classes.uiDialog);
				element.classList.add(classes.uiBodyPrefix +
						elementTheme);

				for (i = 0; i < childrenLength; i++) {
					container.appendChild(element.children[0]);
				}

				containerClassList.add(classes.uiDialogContain);
				containerClassList.add(classes.uiOverlayShadow);

				if (options.corners) {
					containerClassList.add(classes.uiCornerAll);
				}

				for (i = 0, l = headers.length; i < l; i++) {
					headersClassList = headers[i].classList;
					headersClassList.add(classes.uiHeader);
					headersClassList.add(classes.uiBarPrefix +
							pageOptions.headerTheme);
				}

				for (i = 0, l = content.length; i < l; i++) {
					content[i].classList.add(classes.uiContent);
					content[i].classList.add(classes.uiBodyPrefix +
							contentTheme);
				}

				for (i = 0, l = footers.length; i < l; i++) {
					footers[i].classList.add(classes.uiFooter);
					footers[i].classList.add(classes.uiBarPrefix +
							pageOptions.footerTheme);
				}

				element.appendChild(container);
				element.parentNode.removeChild(element);
				document.body.appendChild(element);

				createCloseButton(element, options.closeBtn, options.closeBtnText);

				return element;
			};

			/**
			 * This method inits Dialog widget.
			 * @method _init
			 * @param {HTMLElement} element
			 * @protected
			 * @member ns.widget.mobile.Dialog
			 */
			Dialog.prototype._init = function (element) {
				var pageId = this.options.page;

				if (pageId) {
					this._ui.page = document.getElementById(pageId);
				}
			};

			/**
			 * Close dialog.
			 * @method _close
			 * @param {Event} event
			 * @returns {boolean} false
			 * @protected
			 * @member ns.widget.mobile.Dialog
			 */

			Dialog.prototype._close = function (event) {
				event.preventDefault();
				this.close();
				return false;
			};


			/**
			 * Close dialog
			 *
			 *		@example
			 *		<div data-role="page" id="page1">
			 *			<div data-role="header">
			 *				<h1>Page</h1>
			 *			</div>
			 *			<div data-role="content" class="ui-content">
			 *				<a href="#dialogPage" data-role="button"
			 *					data-rel="dialog">Open dialog</a>
			 *			</div>
			 *		</div>
			 *
			 *		<div data-role="dialog" id="dialogPage">
			 *			<div data-role="header">
			 *				<h2>Dialog</h2>
			 *			</div>
			 *			<div data-role="content" class="ui-content">
			 *				<div data-role="button" id="button-close">
			 *					Close dialog
			 *				</div>
			 *			</div>
			 *		</div>
			 *		<script>
			 *			var element = document.getElementById("dialogPage"),
			 *				onClose = function () {
			 *					// gets the dialog instance and closes Dialog
			 *					tau.widget.Dialog(element).close();
			 *				};
			 *			document.getElementById("button-close")
			 *				.addEventListener("vclick", onClose, true);
			 *		</script>
			 *
			 *
			 * @method close
			 * @member ns.widget.mobile.Dialog
			 */
			Dialog.prototype.close = function () {
				window.history.back();
			};

			/**
			 * Handler function to add class on pagebeforeshow
			 * @method pageBeforeShowHandler
			 * @param {HTMLElement} element
			 * @param {Object} options
			 * @param {Object} classes
			 * @static
			 * @private
			 */
			function pageBeforeShowHandler(element, options, classes) {
				document.body.classList.add(classes.uiOverlayPrefix +
						options.overlayTheme);
			}

			/**
			 * Handler function to close the dialog on click.
			 * @method closeOnClick
			 * @param {ns.widget.mobile.Dialog} self
			 * @param {Event} event
			 * @static
			 * @private
			 */
			function closeOnClick(self, event) {
				var element = event.target;

				if (selectors.getClosestBySelector(element, self.options.closeLinkSelector)) {
					self.close();
				}
			}

			/**
			 * Bind widget events
			 * @method _bindEvents
			 * @protected
			 * @param {HTMLElement} element
			 * @member ns.widget.mobile.Dialog
			 */
			Dialog.prototype._bindEvents = function (element) {
				var self = this,
					options = self.options,
					eventHandlers = self._eventHandlers;

				eventHandlers.pageBeforeShow = pageBeforeShowHandler.bind(null, element, options, classes);
				eventHandlers.destroyOnEvent = self.destroy.bind(self, element);
				eventHandlers.closeOnClick = closeOnClick.bind(null, self);

				element.addEventListener("pagebeforeshow", eventHandlers.pageBeforeShow, true);
				element.addEventListener("vclick", eventHandlers.closeOnClick, true);

				if (self._ui.page) {
					self._ui.page.addEventListener("pagedestroy", eventHandlers.destroyOnEvent, true);
				}
			};

			/**
			 * Destroy Dialog widget
			 *
			 * The method removes event listeners.
			 *
			 *		@example
			 *		<div data-role="page" id="page1">
			 *			<div data-role="header">
			 *				<h1>Page</h1>
			 *			</div>
			 *			<div data-role="content" class="ui-content">
			 *				<a href="#dialogPage" data-role="button"
			 *					data-rel="dialog">Open dialog</a>
			 *			</div>
			 *		</div>
			 *
			 *		<div data-role="dialog" id="dialogPage">
			 *			<div data-role="header">
			 *				<h2>Dialog</h2>
			 *			</div>
			 *			<div data-role="content" class="ui-content">
			 *				<div data-role="button" id="button-close">
			 *					Close dialog
			 *				</div>
			 *			</div>
			 *		</div>
			 *		<script>
			 *			var element = document.getElementById("dialogPage"),
			 *				onClose = function () {
			 *					// gets the dialog instance, closes and destroy
			 *					// Dialog widget
			 *					tau.widget.Dialog(element)
			 *						.close()
			 *						.destroy();
			 *				};
			 *			document.getElementById("button-close")
			 *				.addEventListener("vclick", onClose, true);
			 *		</script>
			 *
			 * @method _destroy
			 * @member ns.widget.mobile.Dialog
			 * @protected
			 */
			Dialog.prototype._destroy = function () {
				var self = this,
					element = self.element,
					parentNode = element.parentNode,
					eventHandlers = self._eventHandlers;

				element.removeEventListener("pagebeforeshow", eventHandlers.pageBeforeShow, true);
				element.removeEventListener("vclick", eventHandlers.closeOnClick, true);

				if (self._ui.page) {
					self._ui.page.removeEventListener("pagedestroy", eventHandlers.destroyOnEvent, true);
				}

				events.trigger(document, "destroyed", {
					widget: "Dialog",
					parent: parentNode
				});
				parentNode.removeChild(element);
			};

			// definition
			ns.widget.mobile.Dialog = Dialog;
			engine.defineWidget(
				"Dialog",
				"[data-role='dialog'], .ui-dialog",
				["close"],
				Dialog,
				"mobile"
			);
			}(window.document, ns));

/*global window, define */
/*
* Copyright  2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/*jslint nomen: true, plusplus: true */
/**
 * #Checkbox-radio Widget
 * Checkboxradio widget changes default browser checkboxes and radios to form more adapted to mobile environment.
 *
 * ##Default selectors
 * By default all inputs with:
 *
 * - type "checkbox" and without class "ui-slider-switch-input"
 * - type "radio"
 * - class "ui-checkbox"
 *
 * are changed to Checkboxradio widget.
 *
 * ##Manual constructor - checkbox
 * For manual creation of Checkboxradio widget with checkbox content you can use constructor of widget:
 *
 *	@example
 *	<!-- Widget structure -->
 *	<input type="checkbox" id="checkbox-1"></input>
 *	<label for="checkbox-1">Label1</label>
 *	<input class="ui-checkbox" id="checkbox-2"></input>
 *	<label for="checkbox-2">Label2</label>
 *	<script>
 *	var checkbox = document.getElementById("checkbox-1"),
 *		widget = tau.widget.Checkboxradio(checkbox),
 *		checkbox2 = document.getElementById("checkbox-2"),
 *		widget2 = tau.widget.Checkboxradio(checkbox2);
 *	</script>
 *
 * ##Manual constructor - radio
 * For manual creation of Checkboxradio widget with radio content you can use constructor of widget:
 *
 *	@example
 *	<!-- Widget structure -->
 *	<input type="radio" id="radio-1"></input>
 *	<label for="radio-1">Label1</label>
 *	<script>
 *	var radio = document.getElementById("radio-1"),
 *		widget = tau.widget.Checkboxradio(radio);
 *	</script>
 *
 * ##HTML Examples
 *
 * ###Setting checkbox checked / unchecked
 *
 *	@example
 *	<!-- Widget structure -->
 *	<input type="checkbox" id="checkbox-1"></input>
 *	<label for="checkbox-1">Label1</label>
 *	<script>
 *	var checkbox = document.getElementById("checkbox-1");
 *	// Checked
 *	checkbox.checked = true;
 *	// Unchecked
 *	checkbox.checked = false;
 *	</script>
 *
 * ###Setting radio checked / unchecked
 *
 *	@example
 *	<!-- Widget structure -->
 *	<input type="radio" id="radio-1"></input>
 *	<label for="radio-1">Label1</label>
 *	<script>
 *	var radio = document.getElementById("radio-1");
 *	// Checked
 *	radio.checked = true;
 *	// Unchecked
 *	radio.checked = false;
 *	</script>
 *
 * ###Setting disabled
 *
 *	@example
 *	<!-- Widget structure -->
 *	<input type="checkbox" id="checkbox-1" disabled="disabled"></input>
 *	<label for="checkbox-1">Label1</label>
 *	<input type="radio" id="radio-1" disabled="disabled"></input>
 *	<label for="radio-1">Label2</label>
 *
 * @class ns.widget.mobile.Checkboxradio
 * @extends ns.widget.BaseWidget
 */
(function (document, ns) {
	
				var Checkboxradio = function () {
					/**
					* @property {Object} options Object with default options
					* @property {string} [options.theme='s'] Widget's theme
					* @member ns.widget.mobile.Checkboxradio
					* @instance
					*/
					this.options = {
						theme: 's'
					};

					this._onLabelClickBound = null;
					this._onInputClickBound = null;
				},
				/**
				* @property {Object} Widget Alias for {@link ns.widget.BaseWidget}
				* @member ns.widget.mobile.Checkboxradio
				* @private
				* @static
				*/
				BaseWidget = ns.widget.mobile.BaseWidgetMobile,
				/**
				* @property {Object} engine Alias for class ns.engine
				* @member ns.widget.mobile.Checkboxradio
				* @private
				* @static
				*/
				engine = ns.engine,
				/**
				* @property {Object} selectors Alias for class ns.util.selectors
				* @member ns.widget.mobile.Checkboxradio
				* @private
				* @static
				*/
				selectors = ns.util.selectors,
				/**
				* @property {Object} dom Alias for class ns.util.DOM
				* @member ns.widget.mobile.Checkboxradio
				* @private
				* @static
				*/
				dom = ns.util.DOM,
				/**
				* @property {Object} events Alias for class ns.event
				* @member ns.widget.mobile.Checkboxradio
				* @private
				* @static
				*/
				events = ns.event,
				/**
				 * {Object} List of classes which can be added to widget`s element
				 * @member ns.widget.mobile.Checkboxradio
				 * @private
				 * @static
				 */
				classes = {
					checkboxradioIconWrapper: "ui-icon-wrapper"
				},
				/**
				* @property {Function} slice Alias for function Array.slice
				* @member ns.widget.mobile.Checkboxradio
				* @private
				* @static
				*/
				slice = [].slice;

			Checkboxradio.prototype = new BaseWidget();

			/**
			 * Dictionary for slider related css class names
			 * @property {Object} classes
			 * @member ns.widget.mobile.Checkboxradio
			 * @static
			 * @readonly
			 */
			Checkboxradio.classes = classes;

			/**
			* Finds best matched label for given input: <br>
			* 1. Checks if one of parents is not a label<br>
			* 2. Checks label#for=input.id if input.id is set in parent form, fieldset, page<br>
			* 3. Creates label
			* @method getLabel
			* @param {HTMLElement} input
			* @return {HTMLElement}
			* @private
			* @static
			* @member ns.widget.mobile.Checkboxradio
			*/
			function getLabel(input) {
				var parent = selectors.getClosestByTag(input, "label"),
					label;
				if (parent) { //1
					parent.parentNode.replaceChild(parent.firstElementChild, parent);
					return parent;
				}
				if (input.id) { //2
					parent = selectors.getClosestBySelector(input,
						"form, fieldset, [data-role='page'], [data-role='dialog']");
					if (parent) {
						label = parent.querySelector("label[for='" + input.id + "']");
						if (label) {
							return label;
						}
					}
				}
				//3
				label = document.createElement("label");
				if (input.id) {
					label.setAttribute("for", input.id);
				}
				return label;
			}

			/**
			 * Function fires on label click event
			 * @method onLabelClick
			 * @param {ns.widget.mobile.Checkboxradio} self
			 * @param {Event} event
			 * @private
			 * @static
			 * @member ns.widget.mobile.Checkboxradio
			 */
			function onLabelClick(self, event) {
				var element = self.element;

				events.preventDefault(event);
				events.stopPropagation(event);
				events.stopImmediatePropagation(event);
				if (element.getAttribute("disabled")) {
					return;
				}

				// Always set checked to true for radios
				// for checkboxes toggle value
				element.checked = (element.type === 'checkbox') ? !element.checked : true;

				if (element.checked) {
					self._getInputSet().forEach(function (el) {
						if (element !== el) {
							el.checked = false;
						}
					});
				}

				self._updateAll();
				event.stopPropagation();
				event.preventDefault();
			}

			/**
			 * Function fires on input click event
			 * @method onInputClick
			 * @param {ns.widget.mobile.Checkboxradio} self
			 * @param {Event} event
			 * @private
			 * @static
			 * @member ns.widget.mobile.Checkboxradio
			 */
			function onInputClick(self, event) {
				var element = self.element;

				if (element.getAttribute("disabled")) {
					event.preventDefault();
					return;
				}

				element.checked = !element.checked;

				if (element.checked) {
					self._getInputSet().forEach(function (el) {
						if (element !== el) {
							el.checked = false;
						}
					});
				}

				self._updateAll();
			}

			/**
			* Check checkboxradio element
			* @method checkElement
			* @param {ns.widget.mobile.Checkboxradio} instance
			* @private
			* @member ns.widget.mobile.Checkboxradio
			* @new
			*/
			function checkElement(instance) {
				var labelClassList = instance.label.classList,
					iconClassList,
					element = instance.element;
				if (!element.getAttribute("disabled")) {
					if (instance.icon) {
						iconClassList = instance.icon.classList;
						iconClassList.add(instance.checkedicon);
						iconClassList.remove(instance.uncheckedicon);
					}
					labelClassList.add(instance.checkedClass);
					labelClassList.remove(instance.uncheckedClass);
					instance.wrapper.setAttribute(instance.ariaCheckedAttr, true);
				}
			}

			/**
			* Uncheck checkboxradio element
			* @method uncheckElement
			* @param {ns.widget.mobile.Checkboxradio} instance
			* @private
			* @member ns.widget.mobile.Checkboxradio
			* @new
			*/
			function uncheckElement(instance) {
				var labelClassList = instance.label.classList,
					iconClassList,
					element = instance.element;
				if (!element.getAttribute("disabled")) {
					if (instance.icon) {
						iconClassList = instance.icon.classList;
						iconClassList.add(instance.uncheckedicon);
						iconClassList.remove(instance.checkedicon);
					}
					labelClassList.add(instance.uncheckedClass);
					labelClassList.remove(instance.checkedClass);
					instance.wrapper.setAttribute(instance.ariaCheckedAttr, false);
				}
			}

			/**
			* Builds structure of checkboxradio widget
			* @method _build
			* @param {HTMLInputElement} element
			* @return {HTMLInputElement}
			* @protected
			* @member ns.widget.mobile.Checkboxradio
			* @instance
			*/
			Checkboxradio.prototype._build = function (element) {
				var inputtype = element.getAttribute('type'),
					options = this.options,
					label,
					labelClassList,
					wrapper,
					ariaCheckedAttr,
					icon,
					checkedState,
					checkedClass,
					uncheckedClass,
					uncheckedState,
					checkedicon,
					uncheckedicon,
					activeBtn,
					iconSpan,
					iconClassList,
					iconpos,
					mini,
					iconSpanParent,
					iconWrapper;

				//if created dynamically on wrong element, just return from here
				if (inputtype !== "checkbox" && inputtype !== "radio") {
					//_build should always return element
					return element;
				}
				ariaCheckedAttr = inputtype === 'radio' ? 'aria-selected' : 'aria-checked';
				checkedState = inputtype + "-on";
				uncheckedState = inputtype + "-off";
				icon = selectors.getParentsBySelector(element, "[data-type='horizontal']").length ? false : uncheckedState;
				if (!icon) {
					activeBtn = "ui-btn-active";
				}
				checkedClass = "ui-" + checkedState;
				uncheckedClass = "ui-" + uncheckedState;
				checkedicon = "ui-icon-" + checkedState;
				uncheckedicon = "ui-icon-" + uncheckedState;

				label = getLabel(element);
				labelClassList = label.classList;

				//@todo these options should not be passed via DOM element
				mini = dom.inheritAttr(element, "data-mini", "form,fieldset");
				if (mini) {
					label.setAttribute('data-mini', mini);
				}

				iconpos = dom.inheritAttr(element, "data-iconpos", "form,fieldset");
				if (iconpos) {
					label.setAttribute('data-iconpos', iconpos);
				}

				label.setAttribute('data-theme', options.theme);
				label.setAttribute('data-icon', icon);
				label.setAttribute('data-shadow', false);
				label.setAttribute('data-bar', true);
				engine.instanceWidget(label, "Button");
				iconSpan = label.getElementsByClassName('ui-icon')[0];
				iconSpanParent = iconSpan && iconSpan.parentElement;
				iconWrapper = document.createElement("span");

				if (iconSpan) {
					iconClassList = iconSpan.classList;
					iconWrapper.classList.add(classes.checkboxradioIconWrapper);
					iconWrapper.appendChild(iconSpan);
					iconSpanParent.appendChild(iconWrapper);
				}

				// Wrap the input + label in a div
				wrapper = '<div role="' + inputtype + '" class="ui-' + inputtype;
				if (element.classList.contains("favorite")) {
					wrapper += ' favorite';
				}
				wrapper += '"></div>';

				//make sure label is after input
				if (element.nextElementSibling) {
					element.parentNode.insertBefore(label, element.nextElementSibling);
				} else {
					element.parentNode.appendChild(label);
				}
				dom.wrapInHTML([element, label], wrapper);
				wrapper = element.parentNode;

				if (element.hasAttribute('checked')) {
					// quick fix to resolve problem in tests when sometimes attribute checked isn't proper interpreted to property in object
					element.checked = true;
				}
				if (element.checked) {
					labelClassList.add(checkedClass);
					if (!icon) {
						labelClassList.add(activeBtn);
					}
					labelClassList.remove(uncheckedClass);
					if (iconSpan) {
						iconClassList.add(checkedicon);
						iconClassList.remove(uncheckedicon);
					}
					wrapper.setAttribute(ariaCheckedAttr, true);
				} else {
					labelClassList.remove(checkedClass);
					if (!icon) {
						labelClassList.remove(activeBtn);
					}
					labelClassList.add(uncheckedClass);
					if (iconSpan) {
						iconClassList.add(uncheckedicon);
						iconClassList.remove(checkedicon);
					}
					wrapper.setAttribute(ariaCheckedAttr, false);
				}

				element.checked = element.getAttribute('checked') === 'checked';

				if (element.getAttribute("disabled")) {
					wrapper.classList.add('ui-disabled');
				} else {
					wrapper.classList.remove('ui-disabled');
				}
				return element;
			};

			/**
			* Inits widget
			* @method _init
			* @param {HTMLElement} element
			* @protected
			* @member ns.widget.mobile.Checkboxradio
			* @instance
			*/
			Checkboxradio.prototype._init = function (element) {
				this.label = getLabel(element);
				this.icon = this.label.getElementsByClassName('ui-icon')[0];
				this.wrapper = element.parentNode;
				this.inputtype = element.getAttribute('type');
				this.checkedClass = 'ui-' + this.inputtype + '-on';
				this.uncheckedClass = 'ui-' + this.inputtype + '-off';
				this.ariaCheckedAttr = this.inputtype === 'radio' ? 'aria-selected' : 'aria-checked';
				this.checkedicon = "ui-icon-" + this.inputtype + '-on';
				this.uncheckedicon = "ui-icon-" + this.inputtype + '-off';
			};

			/**
			* Binds events to widget
			* @method _bindEvents
			* @protected
			* @member ns.widget.mobile.Checkboxradio
			* @instance
			*/
			Checkboxradio.prototype._bindEvents = function () {
				this._onLabelClickBound = onLabelClick.bind(null, this);
				this._onInputClickBound = onInputClick.bind(null, this);
				this.label.addEventListener('vclick', this._onLabelClickBound, true);
				this.element.addEventListener('vclick', this._onInputClickBound, false);
			};

			/**
			* Returns either a set of radios with the same name attribute or a single checkbox
			* @method getInputSet
			* @return {Array}
			* @protected
			* @member ns.widget.mobile.Checkboxradio
			* @instance
			*/
			Checkboxradio.prototype._getInputSet = function () {
				var parent;

				if (this.inputtype === 'checkbox') {
					return [this.element];
				}

				parent = selectors.getClosestBySelector(this.element,
					"form, fieldset, [data-role='page'], [data-role='dialog']");

				if (parent) {
					return slice.call(parent.querySelectorAll(
						"input[name='" + this.element.name + "'][type='" + this.inputtype + "']"
					));
				}

				return [];
			};

			/**
			* Updates all others checkboxradio widgets with the same name attribute (only radios)
			* @method _updateAll
			* @protected
			* @member ns.widget.mobile.Checkboxradio
			* @instance
			*/
			Checkboxradio.prototype._updateAll = function () {
				this._getInputSet().forEach(function (el) {
					var widget = engine.getBinding(el);

					if (widget) {
						if (widget.element.checked || widget.element.type === "checkbox") {
							events.trigger(widget.element, "change");
						}
						widget.refresh();
					}
				});
			};

			/**
			* Refreshes widget
			* @method refresh
			* @member ns.widget.mobile.Checkboxradio
			* @instance
			*/

			Checkboxradio.prototype.refresh = function () {
				var element = this.element;

				if (element.checked) {
					checkElement(this);
				} else {
					uncheckElement(this);
				}

				if (element.getAttribute("disabled")) {
					this.disable();
				} else {
					this.enable();
				}
			};

			/**
			* Enables widget
			* @method _enable
			* @member ns.widget.mobile.Checkboxradio
			* @protected
			* @instance
			*/
			Checkboxradio.prototype._enable = function () {
				dom.removeAttribute(this.element, "disabled");
				this.wrapper.classList.remove('ui-disabled');
			};

			/**
			* Disables widget
			* @method _disable
			* @protected
			* @member ns.widget.mobile.Checkboxradio
			* @instance
			*/
			Checkboxradio.prototype._disable = function () {
				dom.setAttribute(this.element, "disabled", true);
				this.wrapper.classList.add('ui-disabled');
			};

			/**
			* Cleans widget's resources
			* @method _destroy
			* @protected
			* @member ns.widget.mobile.Checkboxradio
			* @instance
			*/
			Checkboxradio.prototype._destroy = function () {
				this.label.removeEventListener('vclick', this._onLabelClickBound, true);
				this.element.removeEventListener('vclick', this._onInputClickBound, false);
			};

			/**
			* Return checked checkboxradio element
			* @method getCheckedElement
			* @return {?HTMLElement}
			* @member ns.widget.mobile.Checkboxradio
			* @new
			*/
			Checkboxradio.prototype.getCheckedElement = function () {
				var radios = this._getInputSet(),
					i,
					max = radios.length;
				for (i = 0; i < max; i++) {
					if (radios[i].checked) {
						return radios[i];
					}
				}
				return null;
			};

			/**
			* Returns value of checkbox if it is checked or value of radios with the same name
			* @method _getValue
			* @member ns.widget.mobile.Checkboxradio
			* @return {?string}
			 * @protected
			* @instance
			* @new
			*/
			Checkboxradio.prototype._getValue = function () {
				var checkedElement = this.getCheckedElement();

				if (checkedElement) {
					return checkedElement.value;
				}

				return null;
			};

			/**
			* Check element with value
			* @method _setValue
			* @param {string} value
			* @member ns.widget.mobile.Checkboxradio
			* @chainable
			* @instance
			 * @protected
			* @new
			*/
			Checkboxradio.prototype._setValue = function (value) {
				var radios = this._getInputSet(),
					checkedElement,
					i,
					max = radios.length;

				for (i = 0; i < max; i++) {
					if (radios[i].value === value) {
						checkedElement = this.getCheckedElement();
						if (checkedElement) {
							uncheckElement(engine.getBinding(checkedElement));
						}
						checkElement(engine.getBinding(radios[i]));
						return this;
					}
				}
				return this;
			};

			// definition
			ns.widget.mobile.Checkboxradio = Checkboxradio;
			engine.defineWidget(
				"Checkboxradio",
				"input[type='checkbox']:not(.ui-slider-switch-input):not([data-role='toggleswitch']):not(.ui-toggleswitch)," +
				"input[type='radio']," +
				"input.ui-checkbox",
				[
					"enable",
					"disable",
					"refresh"
				],
				Checkboxradio,
				'mobile'
			);
			}(window.document, ns));

/*global window, define */
/*
* Copyright  2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/*jslint nomen: true, plusplus: true */
/**
 * # Listview Widget
 * The list widget is used to display, for example, navigation data, results,
 * and data entries.
 *
 * !!!When implementing the list widget:!!!
 *
 *	- A button widget (data-role="button") placed in the *a* tag is
 *	 not supported in the list widget. The button must be placed in a *div* tag.
 *	- If you implement the list widget differently than described in
 *	 the examples shown below, application customization (set element
 *	 positioning) is required.
 *
 *
 * ## Default selectors
 * By default UL or OL elements with _data-role=listview_ are changed to
 * Tizen Web UI Listview.
 *
 * Additionaly all UL or OL elements with class _ui-listview_ are changed to
 *  Tizen Web UI Listview.
 *
 *		@example
 *		<ul data-role="listview">
 *			<li>Anton</li>
 *			<li>Arabella</li>
 *			<li>Barry</li>
 *			<li>Bill</li>
 *		</ul>
 *
 * #### Create Listview widget using tau method:
 *
 *		@example
 *		<ul id="list">
 *			<li>Anton</li>
 *			<li>Arabella</li>
 *			<li>Barry</li>
 *			<li>Bill</li>
 *		</ul>
 *		<script>
 *			tau.widget.Listview(document.getElementById("list"));
 *		</script>
 *
 * #### Create FastScroll widget using jQueryMobile notation:
 *
 *		@example
 *		<ul id="list">
 *			<li>Anton</li>
 *			<li>Arabella</li>
 *			<li>Barry</li>
 *			<li>Bill</li>
 *		</ul>
 *		<script>
 *			$('#list').listview();
 *		</script>
 *
 * ## Options
 *
 * ### Inset
 * _data-inset_ If this option is set to **true** the listview is wrapped by
 * additionally layer
 *
 *		@example
 *		<ul data-role="listview" data-inset="true">
 *			<li>Anton</li>
 *			<li>Arabella</li>
 *			<li>Barry</li>
 *			<li>Bill</li>
 *		</ul>
 *
 * ### Theme
 * _data-theme_ Sets the theme of listview
 *
 *		@example
 *		<ul data-role="listview" data-theme="s">
 *			<li>Anton</li>
 *			<li>Arabella</li>
 *			<li>Barry</li>
 *			<li>Bill</li>
 *		</ul>
 *
 * ### Divider theme
 * _data-divider-theme_ Sets the divider theme of listview
 *
 *		@example
 *		<ul data-role="listview" data-divider-theme="s">
 *			<li>Anton</li>
 *			<li>Arabella</li>
 *			<li data-role="divider">B</li>
 *			<li>Barry</li>
 *			<li>Bill</li>
 *		</ul>
 *
 *
 * ## HTML example code
 *
 * ### Basic 1-line list item with anchor.
 *
 *		@example
 *		<ul data-role="listview">
 *			<li><a href="#">Anton</a></li>
 *			<li><a href="#">Barry</a></li>
 *			<li><a href="#">Bill</a></li>
 *		</ul>
 *
 * ### Basic 1-line list item without anchor.
 *
 *		@example
 *		<ul data-role="listview">
 *			<li>Anton</li>
 *			<li>Barry</li>
 *			<li>Bill</li>
 *		</ul>
 *
 * ### 1-line list item with a subtext.
 *
 *		@example
 *		<ul data-role="listview">
 *			<li><a href="#">
 *				Anton
 *				<span class="ui-li-text-sub">subtext</span>
 *				</a>
 *			</li>
 *			<li><a href="#">
 *				Barry
 *				<span class="ui-li-text-sub">subtext</span>
 *				</a>
 *			</li>
 *			<li><a href="#">
 *				Bill
 *				<span class="ui-li-text-sub">subtext</span>
 *				</a>
 *			</li>
 *		</ul>
 *
 * ### List with sub text below the main text.
 *
 * If this attribute is not used, the sub text position is right next to
 * the main text.
 *
 *		@example
 *		<ul data-role="listview">
 *			<li class="ui-li-multiline">Anton
 *				<span class="ui-li-text-sub">subtext</span>
 *			</li>
 *			<li class="ui-li-multiline">Barry
 *				<span class="ui-li-text-sub">subtext</span>
 *			</li>
 *			<li class="ui-li-multiline">Bill
 *				<span class="ui-li-text-sub">subtext</span>
 *			</li>
 *		</ul>
 *
 * ### List with thumbnail
 *
 *		@example
 *		<ul data-role="listview">
 *			<li><img src="a.jpg" class="ui-li-bigicon" />Anton</li>
 *			<li><img src="a.jpg" class="ui-li-bigicon" />Barry</li>
 *			<li><img src="a.jpg" class="ui-li-bigicon" />Bill</li>
 *		</ul>
 *
 * ### List with thumbnail to the right.
 *
 *		@example
 *		<ul data-role="listview">
 *			<li class="ui-li-thumbnail-right">
 *				<img src="a.jpg" class="ui-li-bigicon" />
 *				Anton
 *			</li>
 *			<li class="ui-li-thumbnail-right">
 *				<img src="a.jpg" class="ui-li-bigicon" />
 *				Barry
 *			</li>
 *			<li class="ui-li-thumbnail-right">
 *				<img src="a.jpg" class="ui-li-bigicon" />
 *				Bill
 *			</li>
 *		</ul>
 *
 * ### 1-line list item with a text button, or with a circle-shaped button.
 *
 *		@example
 *		<ul data-role="listview">
 *			<li><a href="#">
 *					Anton
 *					<div data-role="button" data-inline="true">Button</div>
 *				</a>
 *			</li>
 *			<li><a href="#">
 *					Barry
 *					<div data-role="button" data-inline="true" data-icon="plus"
 *						data-style="circle"></div>
 *				</a>
 *			</li>
 *		</ul>
 *
 * ### 1-line list item with a toggle switch.
 *
 *		@example
 *		<ul data-role="listview">
 *			<li>
 *				Anton
 *				<select name="flip-11" id="flip-11" data-role="slider">
 *					<option value="off"></option>
 *					<option value="on"></option>
 *				</select>
 *			</li>
 *			<li>
 *				Barry
 *				<select name="flip-12" id="flip-12" data-role="slider">
 *					<option value="off"></option>
 *					<option value="on"></option>
 *				</select>
 *			</li>
 *			<li>
 *				Bill
 *				<select name="flip-13" id="flip-13" data-role="slider">
 *					<option value="off"></option>
 *					<option value="on"></option>
 *				</select>
 *			</li>
 *		</ul>
 *
 * ### 1-line list item with thumbnail image
 * #### - and a subtext,
 * #### - and text button,
 * #### - and circle-shaped button
 * #### - and a toggle switch.
 *
 *		@example
 *		<ul data-role="listview">
 *			<li><a href="#">
 *					<img src="thumbnail.jpg" class="ui-li-bigicon" />
 *					Anton
 *				</a>
 *			</li>
 *			<li><a href="#">
 *					<img src="thumbnail.jpg" class="ui-li-bigicon" />
 *					Barry
 *					<span class="ui-li-text-sub">subtext</span>
 *				</a>
 *			</li>
 *			<li><a href="#">
 *					<img src="thumbnail.jpg" class="ui-li-bigicon" />
 *					Barry
 *					<div data-role="button" data-inline="true">Button</div>
 *				</a>
 *			</li>
 *			<li><a href="#">
 *					<img src="thumbnail.jpg" class="ui-li-bigicon" />
 *					Barry
 *					<div data-role="button" data-inline="true" data-icon="plus"
 *						data-style="circle"></div>
 *				</a>
 *			</li>
 *			<li>
 *				<img src="thumbnail.jpg" class="ui-li-bigicon" />
 *				Barry
 *				<select name="flip-13" id="flip-13" data-role="slider">
 *					<option value="off"></option>
 *					<option value="on"></option>
 *				</select>
 *			</li>
 *		</ul>
 *
 * ### 1-line list item with check box,
 * #### - and thumbnail,
 * #### - and thumbnail and circle-shaped button.
 *
 *		@example
 *		<ul data-role="listview">
 *			<li>
 *				<form><input type="checkbox" name="c1line-check1" /></form>
 *				Anton
 *			</li>
 *			<li>
 *				<form><input type="checkbox" /></form>
 *				Barry
 *				<img src="thumbnail.jpg" class="ui-li-bigicon" />
 *			</li>
 *			<li>
 *				<form><input type="checkbox" name="c1line-check4" /></form>
 *				<img src="thumbnail.jpg" class="ui-li-bigicon" />
 *				Barry
 *				<div data-role="button" data-inline="true" data-icon="plus"
 *					data-style="circle"></div>
 *			</li>
 *		</ul>
 *
 * ### 1-line list item with radio button,
 * #### - and thumbnail,
 * #### - and thumbnail and circle-shaped button.
 *
 *		@example
 *		<form>
 *		<ul data-role="listview">
 *			<li>
 *				<input type="radio" name="radio"/>
 *				Anton
 *			</li>
 *			<li>
 *				<input type="radio" name="radio"/>
 *				Barry
 *				<img src="thumbnail.jpg" class="ui-li-bigicon" />
 *			</li>
 *			<li>
 *				<input type="radio" name="radio"/>
 *				<img src="thumbnail.jpg" class="ui-li-bigicon" />
 *				Barry
 *				<div data-role="button" data-inline="true" data-icon="plus"
 *					data-style="circle"></div>
 *			</li>
 *		</ul>
 *		<form>
 *
 * ### Basic 2-line list item.
 *
 *		@example
 *		<ul data-role="listview">
 *			<li class="ui-li-has-multiline">
 *				<a href="#">
 *					Anton
 *					<span class="ui-li-text-sub">subtext</span>
 *				</a>
 *			</li>
 *			<li class="ui-li-has-multiline">
 *				<a href="#">
 *					Barry
 *					<span class="ui-li-text-sub">subtext</span>
 *				</a>
 *			</li>
 *			<li class="ui-li-has-multiline">
 *				<a href="#">
 *					Bill
 *					<span class="ui-li-text-sub">subtext</span>
 *				</a>
 *			</li>
 *		</ul>
 *
 * ### 2-line list item with 2 subtexts.
 *
 *		@example
 *		<ul data-role="listview">
 *			<li class="ui-li-has-multiline">
 *				<a href="#">
 *					Anton
 *					<span class="ui-li-text-sub">subtext</span>
 *					<span class="ui-li-text-sub2">subtext 2</span>
 *				</a>
 *			</li>
 *			<li class="ui-li-has-multiline">
 *				<a href="#">
 *					Barry
 *					<span class="ui-li-text-sub">subtext</span>
 *					<span class="ui-li-text-sub2">subtext 2</span>
 *				</a>
 *			</li>
 *			<li class="ui-li-has-multiline">
 *				<a href="#">
 *					Bill
 *					<span class="ui-li-text-sub">subtext</span>
 *					<span class="ui-li-text-sub2">subtext 2</span>
 *				</a>
 *			</li>
 *		</ul>
 *
 * ### 2-line list item with a text or circle-shaped button.
 *
 *		@example
 *		<ul data-role="listview">
 *			<li class="ui-li-has-multiline">
 *				<a href="#">
 *					Anton
 *					<span class="ui-li-text-sub">subtext</span>
 *					<div data-role="button" data-inline="true">button</div>
 *				</a>
 *			</li>
 *			<li class="ui-li-has-multiline">
 *				<a href="#">
 *					Barry
 *					<span class="ui-li-text-sub">subtext</span>
 *					<div data-role="button" data-inline="true" data-icon="call"
 *						data-style="circle"></div>
 *				</a>
 *			</li>
 *		</ul>
 *
 * ### 2-line list item with 2 subtexts
 * #### - and a star-shaped icon next to the first subtext
 * #### - and 1 subtext and 2 star-shaped icons
 *
 *		@example
 *		<ul data-role="listview">
 *			<li class="ui-li-has-multiline">
 *				<a href="#">
 *					Anton
 *					<span class="ui-li-text-sub">subtext</span>
 *					<span style="position:absolute; right:16px; top:80px">
 *						<img class= "ui-li-icon-sub-right"
 *							src="00_winset_icon_favorite_on.png" />
 *					</span>
 *					<span class="ui-li-text-sub2">subtext 2</span>
 *				</a>
 *			</li>
 *			<li class="ui-li-has-multiline">
 *				<a href="#">
 *					Barry
 *					<span class="ui-li-text-sub">
 *						<img class="ui-li-icon-sub"
 *							src="00_winset_icon_favorite_on.png" />
 *						subtext
 *					</span>
 *					<span>
 *						<img class="ui-li-icon-sub-right"
 *							src="00_winset_icon_favorite_on.png" />
 *					</span>
 *				</a>
 *			</li>
 *		</ul>
 *
 * ### 2-line setting list item,
 * #### - with optionally also a toggle switch
 * #### - or circle-shaped button.
 *
 *		@example
 *		<ul data-role="listview">
 *			<li class="ui-li-has-multiline">
 *				<a href="#">
 *					Anton
 *					<span class="ui-li-text-sub">subtext</span>
 *				</a>
 *			</li>
 *			<li class="ui-li-has-multiline">
 *				Barry
 *				<span class="ui-li-text-sub">subtext</span>
 *				<select name="flip-13" id="flip-13" data-role="slider">
 *					<option value="off"></option>
 *					<option value="on"></option>
 *				</select>
 *			</li>
 *			<li class="ui-li-has-multiline">
 *				<a href="#">
 *					Bill
 *					<span class="ui-li-text-sub">subtext</span>
 *					<div data-role="button" data-inline="true" data-icon="call"
 *						data-style="circle"></div>
 *				</a>
 *			</li>
 *		</ul>
 *
 * ### 2-line list item with a subtext,
 * #### - and also a star-shaped icon and a circle-shaped button,
 * #### - thumbnail and a second subtext,
 *
 *		@example
 *		<ul data-role="listview">
 *			<li class="ui-li-has-multiline">
 *				<a href="#">
 *					Anton
 *					<span class="ui-li-text-sub">
 *						subtext
 *						<img class="ui-li-icon-sub"
 *							src="00_winset_icon_favorite_on.png" />
 *					</span>
 *					<div data-role="button" data-inline="true" data-icon="call"
 *						data-style="circle"></div>
 *				</a>
 *			</li>
 *			<li class="ui-li-has-multiline">
 *				<a href="#">
 *					<img src="thumbnail.jpg" class="ui-li-bigicon" />
 *					Barry
 *					<span class="ui-li-text-sub">subtext 1</span>
 *					<span class="ui-li-text-sub2">subtext 2</span>
 *				</a>
 *			</li>
 *		</ul>
 *
 * ### 2-line list item with a subtext and check box
 * #### - and thumbnail
 * #### - and a circle-shaped button.
 *
 *		@example
 *		<ul data-role="listview">
 *			<li class="ui-li-has-multiline">
 *				<form><input type="checkbox" name="check1" /></form>
 *				Anton
 *				<span class="ui-li-text-sub">subtext</span>
 *			</li>
 *			<li class="ui-li-has-multiline">
 *				<form><input type="checkbox" name="check2" /></form>
 *				<img src="thumbnail.jpg" class="ui-li-bigicon" />
 *				Barry
 *				<span class="ui-li-text-sub">subtext</span>
 *			</li>
 *			<li class="ui-li-has-multiline">
 *				<form><input type="checkbox" name="check3" /></form>
 *				Bill
 *				<span class="ui-li-text-sub">subtext</span>
 *				<div data-role="button" data-inline="true" data-icon="call"
 *					data-style="circle"></div>
 *			</li>
 *		</ul>
 *
 * ### 2-line list item with a subtext and radio button,
 * #### - and thumbnail
 * #### - and a circle-shaped button.
 *
 *		@example
 *		<form>
 *		<ul data-role="listview">
 *			<li class="ui-li-has-multiline">
 *					<input type="radio" name="radio1" />
 *					Anton
 *					<span class="ui-li-text-sub">subtext</span>
 *			</li>
 *			<li class="ui-li-has-multiline">
 *					<input type="radio" name="radio1" />
 *					<img src="thumbnail.jpg" class="ui-li-bigicon" />
 *					Barry
 *					<span class="ui-li-text-sub">subtext</span>
 *			</li>
 *			<li class="ui-li-has-multiline">
 *					<input type="radio" name="radio1" />
 *					Barry
 *					<span class="ui-li-text-sub">subtext</span>
 *					<div data-role="button" data-inline="true" data-icon="call"
 *						data-style="circle"></div>
 *			</li>
 *		</ul>
 *		</form>
 *
 * ### 2-line list item with a color bar,
 * #### - subtext, text button and 3 star-shaped icons,
 * #### - thumbnail, subtext, text button, and 1 star-shaped icon,
 * #### - thumbnail, subtext, and circle-shaped button.
 *
 *		@example
 *		<ul data-role="listview">
 *			<li class="ui-li-has-multiline">
 *				<a href="#">
 *					<span class="ui-li-color-bar"
 *						style="background-color: red;"></span>
 *					Anton
 *					<span class="ui-li-text-sub">subtext
 *						<img src="00_winset_icon_favorite_on.png" />
 *						<img src="00_winset_icon_favorite_on.png" />
 *						<img src="00_winset_icon_favorite_on.png" />
 *					</span>
 *					<div data-role="button" data-inline="true">button</div>
 *				</a>
 *			</li>
 *			<li class="ui-li-has-multiline">
 *				<a href="#">
 *					<span class="ui-li-color-bar"
 *						style="background-color:rgba(72, 136, 42, 1);"></span>
 *					<img src="thumbnail.jpg" class="ui-li-bigicon" />
 *					Barry
 *					<span>
 *						<img class="ui-li-icon-sub"
 *							src="00_winset_icon_favorite_on.png" />
 *					</span>
 *					<span class="ui-li-text-sub">subtext</span>
 *					<div data-role="button" data-inline="true">button</div>
 *				</a>
 *			</li>
 *			<li class="ui-li-has-multiline">
 *				<a href="#">
 *					<span class="ui-li-color-bar"
 *						style="background-color: blue;"></span>
 *					Bill
 *					<span>
 *						<img class="ui-li-icon-sub"
 *							src="00_winset_icon_favorite_on.png" />
 *					</span>
 *					<span class="ui-li-text-sub">subtext</span>
 *					<div data-role="button" data-inline="true" data-icon="call"
 *						data-style="circle"></div>
 *				</a>
 *			</li>
 *		</ul>
 *
 * ### 2-line list item with a subtext and thumbnail at right
 * #### and 2 star-shaped icons
 * #### and a star-shaped icons, subtext, and thumbnail.
 *
 *		@example
 *		<ul data-role="listview">
 *			<li class="ui-li-has-multiline ui-li-thumbnail-right">
 *				<a href="#">
 *					Anton
 *					<span class="ui-li-text-sub">subtext</span>
 *					<img src="thumbnail.jpg" class="ui-li-bigicon">
 *				</a>
 *			</li>
 *			<li class="ui-li-has-multiline ui-li-thumbnail-right">
 *				<a href="#">
 *					Barry
 *					<span>
 *						<img class="ui-li-icon-sub"
 *							src="00_winset_icon_favorite_on.png" />
 *					</span>
 *					<span class="ui-li-text-sub">
 *						<img class="ui-li-icon-sub"
 *							src="00_winset_icon_favorite_on.png" />
 *						subtext
 *					</span>
 *					<img src="thumbnail.jpg" class="ui-li-bigicon" />
 *				</a>
 *			</li>
 *		</ul>
 *
 * ### 2-line list item with a subtext before the main text and a thumbnail.
 *
 *		@example
 *		<ul data-role="listview">
 *			<li class="ui-li-has-multiline ui-li-thumbnail-right">
 *				<a href="#">
 *					<span class="ui-li-text-sub">subtext</span>
 *					Anton
 *					<img src="thumbnail.jpg" class="ui-li-bigicon" />
 *				</a>
 *			</li>
 *			<li class="ui-li-has-multiline ui-li-thumbnail-right">
 *				<a href="#">
 *					<span class="ui-li-text-sub">subtext</span>
 *					Barry
 *					<img src="thumbnail.jpg" class="ui-li-bigicon" />
 *				</a>
 *			</li>
 *			<li class="ui-li-has-multiline ui-li-thumbnail-right">
 *				<a href="#">
 *					<span class="ui-li-text-sub">subtext</span>
 *					Bill
 *					<img src="thumbnail.jpg" class="ui-li-bigicon" />
 *				</a>
 *			</li>
 *		</ul>
 *
 * ### 2-line list item with a thumbnail and a progress bar.
 *
 *		@example
 *		<ul data-role="listview">
 *			<li class="ui-li-has-multiline">
 *				<a href="#">
 *					<img scr="thumbnail.jpg" class="ui-li-bigicon">
 *					Anton
 *					<span class="ui-li-text-sub">subtext</span>
 *					<div data-role="progressbar" id="progressbar"></div>
 *				</a>
 *			</li>
 *			<li class="ui-li-has-multiline">
 *				<a href="#">
 *					<img scr="thumbnail.jpg" class="ui-li-bigicon">
 *					Barry
 *					<span class="ui-li-text-sub">subtext</span>
 *					<div data-role="progressbar" id="progressbar"></div>
 *				</a>
 *			</li>
 *			<li class="ui-li-has-multiline">
 *				<a href="#">
 *					<img scr="thumbnail.jpg" class="ui-li-bigicon">
 *					Bill
 *					<span class="ui-li-text-sub">subtext</span>
 *					<div data-role="progressbar" id="progressbar"></div>
 *				</a>
 *			</li>
 *		</ul>
 *
 * ### 2-line list item with a check box, thumbnail, subtext
 * ### and circle-shaped button.
 *
 *		@example
 *		<ul data-role="listview">
 *			<li class="ui-li-has-multiline">
 *				<form><input type="checkbox" name="checkbox" /></form>
 *				<img src="thumbnail.jpg" class="ui-li-bigicon" />
 *				Anton
 *				<span class="ui-li-text-sub">subtext</span>
 *				<div data-role="button" data-inline="true" data-icon="call"
 *					data-style="circle"></div>
 *			</li>
 *			<li class="ui-li-has-multiline">
 *				<form><input type="checkbox" name="checkbox" /></form>
 *				<img src="thumbnail.jpg" class="ui-li-bigicon" />
 *				Barry
 *				<span class="ui-li-text-sub">subtext</span>
 *				<div data-role="button" data-inline="true" data-icon="call"
 *					data-style="circle"></div>
 *			</li>
 *			<li class="ui-li-has-multiline">
 *				<form><input type="checkbox" name="checkbox" /></form>
 *				<img src="thumbnail.jpg" class="ui-li-bigicon" />
 *				Bill
 *				<span class="ui-li-text-sub">subtext</span>
 *				<div data-role="button" data-inline="true" data-icon="call"
 *					data-style="circle"></div>
 *			</li>
 *		</ul>
 *
 * @class ns.widget.mobile.Listview
 * @extends ns.widget.mobile.BaseWidgetMobile
 */
/**
 * Triggered when the listview is before refresh items.
 * @event beforerefreshitems
 * @member ns.widget.mobile.Listview
 */
(function (window, document, ns) {
	
				var Listview = function () {
					var self = this;
					self._ui = {
						page: null
					};
					self._coloredListHandler = null;
					self._scrolledElement = null;
				},
				BaseWidget = ns.widget.mobile.BaseWidgetMobile,
				/**
				 * Alias for class {@link ns.engine}
				 * @property {Object} engine
				 * @member ns.widget.mobile.Listview
				 * @private
				 * @static
				 */
				engine = ns.engine,
				/**
				 * Alias for class {@link ns.util.DOM}
				 * @property {Object} DOM
				 * @member ns.widget.mobile.Listview
				 * @private
				 * @static
				 */
				DOM = ns.util.DOM,
				/**
				 * Alias for class ns.widget.mobile.Button
				 * @property {Function} Button
				 * @member ns.widget.mobile.Listview
				 * @static
				 * @private
				 */
				Button = ns.widget.mobile.Button,
				/**
				 * Alias for class ns.widget.mobile.Page
				 * @property {Function} Page
				 * @member ns.widget.mobile.Listview
				 * @static
				 * @private
				 */
				Page = ns.widget.mobile.Page,
				/**
				 * Alias for class {@link ns.util.color}
				 * @property {Function} Page
				 * @member ns.widget.mobile.Listview
				 * @static
				 * @private
				 */
				colorUtils = ns.util.colors,
				/**
				 * Alias for object ns.widget.mobile.Listview.classes
				 * @property {Object} classes
				 * @member ns.widget.mobile.Listview
				 * @static
				 * @private
				 * @readonly
				 * @property {string} classes.uiListview Main class of listview
				 * @property {string} classes.uiListviewInset class of listview as inset
				 * @property {string} classes.uiCornerAll class of corners all
				 * @property {string} classes.uiShadow class of shadow
				 * @property {string} classes.uiLi class of li element
				 * @property {string} classes.uiLiLast class of last li element
				 * @property {string} classes.uiCornerTop class of top corners
				 * @property {string} classes.uiCornerTr class of top right corner
				 * @property {string} classes.uiCornerTl class of top left corner
				 * @property {string} classes.uiCornerBottom class of bottom corners
				 * @property {string} classes.uiCornerBr class of bottom right corner
				 * @property {string} classes.uiCornerBl class of bottom left corner
				 * @property {string} classes.uiLink class of link on listview
				 * @property {string} classes.uiLiLinkAlt class of li element as link on listview
				 * @property {string} classes.uiLiHasArrow class of li element which has arrow
				 * @property {string} classes.uiLiHasAlt class of li element which has alt
				 * @property {string} classes.uiLinkInherit class inherit link on listview
				 * @property {string} classes.uiLiThumb class of thumb included in li element
				 * @property {string} classes.uiLiHasThumb class of li element which has thumb
				 * @property {string} classes.uiLiIcon class of icon included in li element
				 * @property {string} classes.uiLiHasIcon class of li element which has icon
				 * @property {string} classes.uiLiHasCheckbox class of li element which has checkbox
				 * @property {string} classes.uiLiHasRadio class of li element which has radio button
				 * @property {string} classes.uiLiHasRightCircleBtn class of li element which has circle button
				 * @property {string} classes.uiLiHasRightBtn class of li element which has button allign to right
				 * @property {string} classes.uiLiCount class of count included in li element
				 * @property {string} classes.uiLiHasCount class of li element which has count
				 * @property {string} classes.uiLiStatic class of li static element
				 * @property {string} classes.uiLiHeading class of li heading
				 */
				classes = {
					uiListview : "ui-listview",
					uiListviewInset: "ui-listview-inset",
					uiListviewColored: "ui-listview-colored",
					uiCornerAll: "ui-corner-all",
					uiShadow: "ui-shadow",
					uiLi: "ui-li",
					uiLiLast: "ui-li-last",
					uiCornerTop: "ui-corner-top",
					uiCornerTr: "ui-corner-tr",
					uiCornerTl: "ui-corner-tl",
					uiCornerBottom: "ui-corner-bottom",
					uiCornerBr: "ui-corner-br",
					uiCornerBl: "ui-corner-bl",
					uiLink: "ui-link",
					uiLiLinkAlt: "ui-li-link-alt",
					uiLiHasArrow: "ui-li-has-arrow",
					uiLiHasAlt: "ui-li-has-alt",
					uiLinkInherit: "ui-link-inherit",
					uiLiThumb: "ui-li-thumb",
					uiLiHasThumb: "ui-li-has-thumb",
					uiLiIcon: "ui-li-icon",
					uiLiHasIcon: "ui-li-has-icon",
					uiLiHasCheckbox: "ui-li-has-checkbox",
					uiLiHasRadio: "ui-li-has-radio",
					uiLiHasRightCircleBtn: "ui-li-has-right-circle-btn",
					uiLiHasRightBtn: "ui-li-has-right-btn",
					uiLiCount: "ui-li-count",
					uiLiHasCount: "ui-li-has-count",
					uiLiStatic: "ui-li-static",
					uiLiHeading: "ui-li-heading"
				},
				/**
				 * Alias for object ns.widget.mobile.Button.classes
				 * @property {Object} buttonClasses
				 * @member ns.widget.mobile.Listview
				 * @static
				 * @private
				 */
				buttonClasses = Button.classes,
				/**
				 * Alias to ns.util.selectors
				 * @property {Object} selectors
				 * @member ns.widget.mobile.Listview
				 * @private
				 * @static
				 */
				selectors = ns.util.selectors,
				/**
				 * Alias to ns.event
				 * @property {Object} eventUtils
				 * @member ns.widget.mobile.Listview
				 * @private
				 * @static
				 */
				eventUtils = ns.event,
				/**
				 * Alias to Array.slice
				 * @method slice
				 * @member ns.widget.mobile.Listview
				 * @private
				 */
				slice = [].slice;

			Listview.prototype = new BaseWidget();

			Listview.classes = classes;

			Listview.prototype._configure = function () {
				var self = this,
					ui = self._ui || {},
					/**
					 * Object with default options
					 * @property {Object} options
					 * @property {?string} [options.theme=null] theme of widget
					 * @property {?string} [options.dividerTheme="s"] theme of listview divider
					 * @property {boolean} [options.inset=false] inset option - listview is wrapped by additionally layer
					 * @member ns.widget.mobile.Listview
					 */
					options = self.options || {};

				options.theme = null;
				options.dividerTheme = "s";
				options.inset = false;
				options.coloredListNumber = 12;
				options.diffLightness = 3;

				self.options = options;
				ui.page = null;
			};

			/**
			 * Change links to button widget
			 * @method changeLinksToButton
			 * @param {HTMLElement} item
			 * @param {Array} links
			 * @param {string} itemTheme
			 * @private
			 * @static
			 * @member ns.widget.mobile.Listview
			 */
			function changeLinksToButton(item, links, itemTheme) {
				var icon = DOM.getNSData(item, "icon"),
					linkClassList = links[0].classList,
					linksLength = links.length,
					last = links[linksLength - 1],
					span;
				DOM.setNSData(item, "theme", itemTheme);
				engine.instanceWidget(
					item,
					"Button",
					{
						wrapperEls: "div",
						shadow: false,
						corners: false,
						iconpos: "right",
						icon: false
					}
				);

				if (linksLength === 1) {
					item.classList.add(classes.uiLiHasArrow);
					if (icon !== false) {
						item.classList.add(buttonClasses.uiBtnIconRight);
					}
				} else if (linksLength > 1) {
					item.classList.add(classes.uiLiHasAlt);
					item.appendChild(last);
					last.classList.add(classes.uiLiLinkAlt);
					last.setAttribute("title", last.innerText);
					last.innerText = "";
					engine.instanceWidget(
						last,
						"Button",
						{
							wrapperEls: "span",
							shadow: false,
							corners: false,
							iconpos: "right",
							icon: false
						}
					);
					last.classList.add(buttonClasses.uiBtnIconNotext);

					span = document.createElement("span");
					engine.instanceWidget(
						span,
						"Button",
						{
							wrapperEls: "span",
							shadow: true,
							corners: false,
							iconpos: "notext",
							icon: "arrow-r"
						}
					);
					last.querySelector("." + buttonClasses.uiBtnInner)
							.appendChild(span);
				}
				linkClassList.remove(classes.uiLink);
				linkClassList.add(classes.uiLinkInherit);

				selectors.getChildrenByClass(item, buttonClasses.uiBtnInner)
					.forEach(function (element) {
						element.classList.add(classes.uiLi);
					});
			}

			/**
			 * Add thumb classes img
			 * @method addThumbClassesToImg
			 * @param {HTMLElement} img
			 * @private
			 * @static
			 * @member ns.widget.mobile.Listview
			 */
			function addThumbClassesToImg(img) {
				var parentNode = selectors.getClosestByTag(img.parentNode, "li");
				img.classList.add(classes.uiLiThumb);
				if (parentNode) {
					parentNode.classList.add(
						img.classList.contains(classes.uiLiIcon) ?
							classes.uiLiHasIcon :
							classes.uiLiHasThumb
					);
				}
			}

			/**
			 * Add thumb classes to first img of container
			 * @method addThumbClasses
			 * @param {HTMLElement} container
			 * @private
			 * @static
			 * @member ns.widget.mobile.Listview
			 */
			function addThumbClasses(container) {
				var img;
				img = selectors.getChildrenByTag(container, "img");
				if (img.length) {
					addThumbClassesToImg(img[0]);
				}
			}

			/**
			 * Add checkbox classes to first input of container
			 * @method addCheckboxRadioClasses
			 * @param {HTMLElement} container HTML LI element.
			 * @private
			 * @static
			 * @member ns.widget.mobile.Listview
			 */
			function addCheckboxRadioClasses(container) {
				var inputAttr = container.querySelector("input"),
					typeOfInput,
					contenerClassList = container.classList;
				if (inputAttr) {
					typeOfInput = inputAttr.getAttribute("type");
					if (typeOfInput === "checkbox") {
						contenerClassList.add(classes.uiLiHasCheckbox);
					} else if (typeOfInput === "radio") {
						contenerClassList.add(classes.uiLiHasRadio);
					}
				}
			}

			/**
			 * Function add ui-li-heading class to all headings elemenets in list
			 * @method addHeadingClasses
			 * @param {HTMLElement} container HTML LI element.
			 * @private
			 * @static
			 * @member ns.widget.mobile.Listview
			 */
			function addHeadingClasses(container) {
				var headings = [].slice.call(container.querySelectorAll("h1, h2, h3, h4, h5, h6")),
					i = headings.length - 1;
				while (i >= 0) {
					headings[i].classList.add(classes.uiLiHeading);
					i--;
				}
			}

			/**
			 * Add right button classes to first button of container
			 * @method addRightBtnClasses
			 * @param {HTMLElement} container HTML LI element
			 * @private
			 * @static
			 * @member ns.widget.mobile.Listview
			 */
			function addRightBtnClasses(container) {
				var btnAttr = container.querySelector("[data-role='button'],input[type='button'],select[data-role='slider'],input[type='submit'],input[type='reset'],button");
				if (btnAttr) {
					if (DOM.getNSData(btnAttr, "style") === "circle") {
						container.classList.add(classes.uiLiHasRightCircleBtn);
					} else {
						container.classList.add(classes.uiLiHasRightBtn);
					}
				}
			}

			/**
			 * Build Listview widget
			 * @method _build
			 * @param {HTMLElement} element
			 * @return {HTMLElement}
			 * @protected
			 * @member ns.widget.mobile.Listview
			 */
			Listview.prototype._build = function (element) {
				var elementClassList = element.classList;
				elementClassList.add(classes.uiListview);
				if (this.options.inset) {
					elementClassList.add(classes.uiListviewInset);
					elementClassList.add(classes.uiCornerAll);
					elementClassList.add(classes.uiShadow);
				}
				//@todo check if this is ol list

				this._refreshItems(element, true);
				return element;
			};

			/**
			 * Initialize Listview widget
			 * @method _init
			 * @param {HTMLElement} element
			 * @protected
			 * @member ns.widget.mobile.Listview
			 */
			Listview.prototype._init = function (element) {
				var ui = this._ui,
					page = ui.page,
					popup = selectors.getClosestBySelector(element, "[data-role=popup]"),
					drawer = selectors.getClosestBySelector(element, "[data-role=drawer]"),
					elementType = element.tagName.toLowerCase();

				//for everything what is not a list based on ul set the following width
				if (!popup && elementType !== "ul" && !drawer) {
					element.style.width = window.innerWidth + "px";
				}

				if (!page) {
					page = selectors.getClosestByClass(element, Page.classes.uiPage);
					if (page) {
						this._ui.page = page;
					}
				}

				this._liElementOffsetTop = [];
				this._liElementOffsetHeight = [];
				this._dummyElement = document.createElement("div");
				this._liElements = element.getElementsByTagName("li");
				this._color = {
						hue: 0,
						saturation: 0,
						lightness: 0
				};
				this._scrollTop = 0;
				this._coloredListTop = 0;
				return element;
			};

			/**
			 * Make colored list widget
			 * @method _makecoloredList
			 * @param {HTMLElement} element
			 * @protected
			 * @member ns.widget.mobile.Listview
			 */
			Listview.prototype._makeColoredList = function (element) {
				var self = this,
					page = selectors.getClosestByClass(element, Page.classes.uiPage),
					pageStyle = window.getComputedStyle(page),
					pageColor = pageStyle.getPropertyCSSValue("background-color").getRGBColorValue(),
					color = self._color,
					dummyElement = self._dummyElement,
					len,
					parentElement,
					i;

				// Init color
				pageColor = colorUtils.RGBToHSL([parseInt(pageColor.red.cssText, 10) / 255, parseInt(pageColor.green.cssText, 10) / 255, parseInt(pageColor.blue.cssText, 10) / 255]);
				color.hue = parseInt(pageColor[0], 10);
				color.saturation = parseInt(pageColor[1] * 100, 10);
				color.lightness = parseInt(pageColor[2] * 100, 10);

				len = self._liElements.length;
				for (i = 0; i < len; i++){
					self._liElementOffsetTop[i] = self._liElements[i].offsetTop;
					self._liElementOffsetHeight[i] = self._liElements[i].offsetHeight;
				}

				dummyElement.classList.add("ui-listview-dummy");
				parentElement = selectors.getClosestByClass(element, "ui-scrollview-clip");
				self._scrolledElement = parentElement;
				self._coloredListHandler = self._scrollHandler.bind(self); // This variable will be used when event handler remove.
				if (parentElement){
					// List in scrollview
					parentElement.parentNode.appendChild(dummyElement);
					parentElement.addEventListener("scroll", self._coloredListHandler);
					if (self._scrollTop) {
						// It was scrolled before that means listview element made before and don't need to init more.
						return;
					}

					dummyElement.style.top = parentElement.offsetTop + "px";
				} else {
					parentElement = element.parentNode;
					parentElement.appendChild(dummyElement);
					parentElement.addEventListener("scroll", self._coloredListHandler);
					dummyElement.style.top = "0";
				}
				self._changeColoredPosition(0); // Init linear-gradient

				parentElement.style.backgroundColor = "transparent";

				dummyElement.style.width = element.offsetWidth + "px";
				dummyElement.style.height = parentElement.offsetHeight + "px";

			};

			Listview.prototype._scrollHandler = function (event) {
				var self = this,
					scrollTop = event.target.scrollTop,
					liElementOffsetTop = self._liElementOffsetTop,
					coloredListTop = self._coloredListTop,
					liElementOffsetHeight = self._liElementOffsetHeight;
				self._scrollTop = scrollTop;

				if (scrollTop > liElementOffsetTop[coloredListTop + 1]) {
					if (scrollTop > liElementOffsetTop[coloredListTop + 1] + liElementOffsetHeight[coloredListTop + 1]) {
						// scroll was moved by scrollTo.
						while(scrollTop > liElementOffsetTop[coloredListTop + 1] + liElementOffsetHeight[coloredListTop + 1]) {
							coloredListTop++;
						}
					}
					coloredListTop++;
				} else if (scrollTop < liElementOffsetTop[coloredListTop]) {
					if (scrollTop < liElementOffsetTop[coloredListTop - 1]) {
						// scroll was moved by scrollTo
						while(scrollTop < liElementOffsetTop[coloredListTop - 1]) {
							coloredListTop--;
						}
					}
					coloredListTop--;
				}

				self._coloredListTop = coloredListTop;
				if (scrollTop > liElementOffsetTop[coloredListTop]) {
					// move down
					self._changeColoredPosition(1);
				} else if (scrollTop > liElementOffsetTop[coloredListTop][1] && scrollTop < liElementOffsetTop[self._coloredListTop]) {
					self._changeColoredPosition(0);
				} else if (scrollTop === 0) {
					self._changeColoredPosition(0);
				}
			};

			Listview.prototype._changeColoredPosition = function (direction) {
				var self = this,
					listTopOffsetHeight = self._liElementOffsetHeight[self._coloredListTop],
					colorRatio = 4 / listTopOffsetHeight, // Each list has difference to lightness 4%
					hue = self._color.hue,
					saturation = self._color.saturation,
					lightness = self._color.lightness,
					top = self._coloredListTop,
					liElementOffsetTop = self._liElementOffsetTop,
					scrollTop = self._scrollTop,
					diffLightness = self.options.diffLightness,
					changedRed = 0,
					changedGreen = 0,
					changedBlue = 0,
					changedInterval = liElementOffsetTop[top] - scrollTop,
					adjustedColorValue = 0,
					adjustedTopValue = 0,
					changedColor = 0,
					validTop = top,
					liElementsLength = liElementOffsetTop.length - 1,
					validLength,
					colorHsl,
					nextColorHsl,
					validLightness,
					gradientValue,
					gradient;

				if (!direction) {
					// move up
					colorRatio = -colorRatio; // redRatio = -4 / listTopOffsetHeight
				}

				if (self._liElements[top].classList.contains("ui-li-divider")) {
					validTop = top + 1;
				} else {
					changedColor = colorRatio * -changedInterval;
				}

				validLength = validTop + self.options.coloredListNumber;
				for (top = validTop; top < validLength && top < liElementsLength ; top++) {
					adjustedColorValue = top - validTop;
					adjustedTopValue = liElementOffsetTop[top + 1] - scrollTop + 2; // Number 2 makes boundary between each element located more correctly.
					validLightness = lightness - (diffLightness * adjustedColorValue) + changedColor;
					colorHsl = "hsl( " + hue + ", " + saturation + "%, " + validLightness + "%)";
					nextColorHsl = "hsl( " + hue + ", " + saturation + "%, " + (validLightness - diffLightness) + "%)";
					if (adjustedColorValue === 0) {
						// First gradient value
						gradientValue = colorHsl + " " + (liElementOffsetTop[validTop] - scrollTop + 2) + "px";
					}
					gradientValue += ", " + colorHsl + " " + adjustedTopValue + "px";
					gradientValue += ", "  + nextColorHsl + " " + adjustedTopValue + "px";

				}

				gradientValue += ", "  + nextColorHsl + " " + (adjustedTopValue + self._liElementOffsetHeight[top]) + "px";
				gradient = "-webkit-linear-gradient(top," + gradientValue + ")";
				self._dummyElement.style["background"] = gradient;
			};

			Listview.prototype._destroyColoredList = function (element) {
				var self = this;
				if (self._dummyElement.parentNode){
					self._dummyElement.remove();
				}
				if (self._scrolledElement) {
					self._scrolledElement.removeEventListener("scroll",self._coloredListHandler);
				}
			};
			/**
			 * Change Checkbox/Radio state when list clicked
			 * @method _clickCheckboxRadio
			 * @param {HTMLElement} element
			 * @protected
			 * @member ns.widget.mobile.Listview
			 */
			Listview.prototype._clickCheckboxRadio = function (element) {
				var checkboxRadio = slice.call(element.querySelectorAll(".ui-checkbox label, .ui-radio label")),
					i = checkboxRadio.length;
				while (--i >= 0) {
					eventUtils.trigger(checkboxRadio[i], "vclick");
				}
			};

			/**
			 * Registers widget's event listeners
			 * @method _bindEvents
			 * @param {HTMLElement} element
			 * @protected
			 * @member ns.widget.mobile.Listview
			 */
			Listview.prototype._bindEvents = function (element) {
				var self = this,
					page = selectors.getClosestByClass(element, Page.classes.uiPage);

				element.addEventListener("vclick", function (event) {
					var target = event.target,
						parentTarget = target.parentNode;

					if (target.classList.contains(classes.uiLiHasCheckbox) || target.classList.contains(classes.uiLiHasRadio)) {
						self._clickCheckboxRadio(target);
					} else if (parentTarget.classList.contains(classes.uiLiHasCheckbox) || parentTarget.classList.contains(classes.uiLiHasRadio)) {
						self._clickCheckboxRadio(parentTarget);
					}
				}, false);

				if (element.getAttribute("data-type") !== "colored") {
					element.classList.add("ui-listview-default");
					return;
				} else {
					if (!element.classList.contains(classes.uiListviewColored)) {
						element.classList.add(classes.uiListviewColored);
					}
					eventUtils.on(page, "pageshow updatelayout", self._makeColoredList.bind(this, element));
					page.addEventListener("pagebeforehide", self._destroyColoredList.bind(this, element));
				}

			};

			/**
			 * Removes corners from one LI element
			 * @method removeCorners
			 * @param {HTMLElement} element HTML LI element
			 * @param {string} which which corners will be removed
			 * @static
			 * @private
			 * @member ns.widget.mobile.Listview
			 */
			function removeCorners(element, which) {
				var elementClassList = element.classList;
				switch (which) {
					case "top":
						elementClassList.remove(classes.uiCornerTop);
						elementClassList.remove(classes.uiCornerTr);
						elementClassList.remove(classes.uiCornerTl);
						break;
					case "bottom":
						elementClassList.remove(classes.uiCornerBottom);
						elementClassList.remove(classes.uiCornerBr);
						elementClassList.remove(classes.uiCornerBl);
						break;
				}
			}

			/**
			 * Removes corners
			 * @method _removeCorners
			 * @param {HTMLElement} li HTML LI element
			 * @param {string} which which corners will be removed
			 * @protected
			 * @member ns.widget.mobile.Listview
			 */
			Listview.prototype._removeCorners = function (li, which) {
				var additionlElements = slice.call(li.querySelectorAll(
					"." + buttonClasses.uiBtnInner + ", " +
						"." + classes.uiLiLinkAlt + ", " +
						"." + classes.uiLiThumb
				));

				if (which === "top" || which !== "bottom") {
					removeCorners(li, "top");
					additionlElements.forEach(function (item) {
						removeCorners(item, "top");
					});
				}
				if (which === "bottom" || which !== "top") {
					removeCorners(li, "bottom");
					additionlElements.forEach(function (item) {
						removeCorners(item, "bottom");
					});
				}
			};

			/**
			 * Adding top corners for list item
			 * @param {HTMLElement} item
			 * @member ns.widget.mobile.Listview
			 * @private
			 * @static
			 */
			function addTopCorners(item) {
				item.classList.add(classes.uiCornerTop);
				slice.call(item.querySelectorAll("." + buttonClasses.uiBtnInner + ":not(." + classes.uiLiLinkAlt + ")")).forEach(function (subitem) {
					subitem.classList.add(classes.uiCornerTop);
				});
				slice.call(item.querySelectorAll("." + buttonClasses.uiBtnInner + ":not(:first-child)")).forEach(function (subitem) {
					subitem.classList.add(classes.uiCornerTop);
				});
				slice.call(item.querySelectorAll("." + classes.uiLiLinkAlt + ", ." + classes.uiLiLinkAlt + " span:first-child")).forEach(function (subitem) {
					subitem.classList.add(classes.uiCornerTr);
				});
				slice.call(item.querySelectorAll("." + classes.uiLiThumb + ":not(." + classes.uiLiIcon + ")")).forEach(function (subitem) {
					subitem.classList.add(classes.uiCornerTl);
				});
			}

			/**
			 * Adding bottom corners for list item
			 * @param {HTMLElement} item
			 * @member ns.widget.mobile.Listview
			 * @private
			 * @static
			 */
			function addBottomCorners(item) {
				var itemClassList = item.classList;
				itemClassList.add(classes.uiCornerBottom);
				itemClassList.add(classes.uiLiLast);
				slice.call(item.querySelectorAll("." + classes.uiLiThumb)).forEach(function (subitem) {
					subitem.classList.add(classes.uiCornerBr);
				});
				slice.call(item.querySelectorAll("." + classes.uiLiThumb + ":not(." + classes.uiLiIcon + ")")).forEach(function (subitem) {
					subitem.classList.add(classes.uiCornerBl);
				});
			}

			/**
			 * Refresh corners
			 * @method _refreshCorners
			 * @param {HTMLElement} ul HTML UL element
			 * @param {boolean} create if set "true" then the "updatelayout" event will be triggered
			 * @protected
			 * @member ns.widget.mobile.Listview
			 */
			Listview.prototype._refreshCorners = function (ul, create) {
				var items,
					self = this,
					last;

				items = selectors.getChildrenByTag(ul, "li");
				if (items.length) {
					// clean previous corners
					items.forEach(function (item) {
						// ui-li-last is used for setting border-bottom on the last li
						item.classList.remove(classes.uiLiLast);
						self._removeCorners(item);
					});

					// filter element which occupied place on the view
					items = items.filter(DOM.isOccupiedPlace);

					if (items.length) {
						last = items.length - 1;
						if (self.options.inset) {
							addTopCorners(items[0]);
							addBottomCorners(items[last]);
						} else {
							items[last].classList.add(classes.uiLiLast);
						}
					}
				}
				if (!create) {
					eventUtils.trigger(ul, "updatelayout");
				}
			};

			/**
			 * Refresh items of list
			 * @method _refreshItems
			 * @param {HTMLElement} ul HTML UL element
			 * @param {boolean} create
			 * @protected
			 * @member ns.widget.mobile.Listview
			 */
			Listview.prototype._refreshItems = function (ul, create) {
				var items,
					options = this.options,
					theme,
					last,
					imgs,
					dividerTheme;

				eventUtils.trigger(ul, "beforerefreshitems");
				items = selectors.getChildrenByTag(ul, "li");
				theme = DOM.getNSData(ul, "theme") || options.theme || "s";
				dividerTheme = DOM.getNSData(ul, "divider-theme") || options.dividerTheme || theme;
				last = items.length - 1;

				//@todo filter only visible
				items.forEach(function (item, index) {
					var itemTheme,
						links,
						link,
						itemClassList = item.classList;
					if (create || !item.classList.contains(classes.uiLi)) {
						itemClassList.add(classes.uiLi);
						links = selectors.getChildrenByTag(item, "a");
						itemTheme = DOM.getNSData(item, "theme") || theme;

						if (!!item.querySelector("." + classes.uiLiCount)) {
							itemClassList.add(classes.uiLiHasCount);
						}

						//becasue ListDivider is attached later then Listview I cannot make reference to ListDivider classes
						if (selectors.matchesSelector(item, '[data-role="list-divider"],.ui-list-divider')) {
							DOM.setNSData(item, "theme", dividerTheme);
							engine.instanceWidget(item, "ListDivider");
						} else {
							if (links.length) {
								changeLinksToButton(item, links, itemTheme);
								link = links[0];
								addCheckboxRadioClasses(link);
								addThumbClasses(link);
								addRightBtnClasses(link);
							} else {
								itemClassList.add(classes.uiLiStatic);
								itemClassList.add(buttonClasses.uiBtnUpThemePrefix + itemTheme);
								item.setAttribute("tabindex", "0");
							}
							addHeadingClasses(item);
						}
					}
					addCheckboxRadioClasses(item);
					addThumbClasses(item);
					addRightBtnClasses(item);
					if (index === last) {
						itemClassList.add(classes.uiLiLast);
					} else {
						itemClassList.remove(classes.uiLiLast);
					}
				}, this);

				imgs = ul.querySelectorAll("." + classes.uiLinkInherit + " > img:first-child");
				if (imgs.length !== 0) {
					slice.call(imgs).forEach(function (img) {
						addThumbClassesToImg(img);
					});
				}
				this._refreshCorners(ul, create);
			};

			/**
			 * Refresh Listview widget
			 * @method refresh
			 * @protected
			 * @member ns.widget.mobile.Listview
			 */
			Listview.prototype.refresh = function () {
				this._refreshItems(this.element, false);
				eventUtils.trigger(this.element, this.name.toLowerCase() + "afterrefresh");
			};

			/**
			 * Adds item to widget and refreshes layout.
			 * @method addItem
			 * @param {HTMLElement} listItem new LI item
			 * @param {number} position position on list
			 * @member ns.widget.mobile.Listview
			 */
			Listview.prototype.addItem = function (listItem, position) {
				var element = this.element,
					childNodes = element.getElementsByTagName("li"),
					tempDiv = document.createElement("div"),
					liItem,
					liButtons,
					i;

				tempDiv.innerHTML = listItem;
				liItem = tempDiv.firstChild;
				liButtons = liItem.querySelectorAll("[data-role='button']");

				if (position) {
					element.insertBefore(liItem, childNodes[position]);
				} else {
					element.appendChild(liItem);
				}

				for (i = 0; i < liButtons.length; i++) {
					engine.instanceWidget(liButtons[i], "Button");
				}

				this.refresh();
			};

			/**
			 * Removes item from widget and refreshes layout.
			 * @method removeItem
			 * @param {number} position position on list
			 * @member ns.widget.mobile.Listview
			 */
			Listview.prototype.removeItem = function (position) {
				var element = this.element,
					childNodes = element.getElementsByTagName("li");

				element.removeChild(childNodes[position]);
				this.refresh();
			};

			ns.widget.mobile.Listview = Listview;
			engine.defineWidget(
				"Listview",
				"ul[data-role='listview'], ul.ui-listview, ol[data-role='listview'], ol.ui-listview",
				["addItem", "removeItem"],
				Listview,
				"mobile"
			);
			}(window, window.document, ns));

/*global window, define */
/*
* Copyright  2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/*jslint nomen: true */
/**
 * # List Divider Widget
 * List divider widget creates a list separator, which can be used for building grouping lists using.
 *
 *
 * ## Default selectors
 * In all elements with _data-role=listdivider_ are changed to Tizen Web UI ListDivider.
 *
 * In addition all elements with class _ui-listdivider_ are changed to Tizen Web UI ListDivider.
 *
 *		@example
 *		<ul data-role="listview">
 *			<li data-role="list-divider">Item styles</li>
 *			<li><a href="#">Normal lists</a></li>
 *			<li><a href="#">Normal lists</a></li>
 *			<li><a href="#">Normal lists</a></li>
 *		</ul>
 *
 * ## Manual constructor
 * For manual creation of listdivider widget you can use constructor of widget:
 *
 *		@example
 *		<ul data-role="listview">
 *			<li>Item</li>
 *			<li id="listdivider">Divider</li>
 *			<li>Item</li>
 *			<li>Item</li>
 *		</ul>
 *		<script>
 *			var listdivider = tau.widget.ListDivider(document.getElementById("listdivider"));
 *		</script>
 *
 * If jQuery library is loaded, its method can be used:
 *
 *		@example
 *		<ul data-role="listview">
 *			<li>Item</li>
 *			<li id="listdivider">Divider</li>
 *			<li>Item</li>
 *			<li>Item</li>
 *		</ul>
 *		<script>
 *			$("#listdivider").listdivider();
 *		</script>
 *
 * ## Options
 *
 * ### Style
 * _data-style_ string ["normal" | "checkbox" | "dialogue"] Option sets the style of the list divider.
 *
 * #### Checkbox
 *
 *		@example
 *		<ul data-role="listview">
 *			<li data-role="list-divider" data-style="checkbox">
 *				<form><input type="checkbox">Select All</form>
 *			</li>
 *			<li><form><input type="checkbox">Item</form></li>
 *			<li><form><input type="checkbox">Item</form></li>
 *			<li><form><input type="checkbox">Item</form></li>
 *		</ul>
 *
 * #### Dialogue
 *
 *		@example
 *		<ul data-role="listview">
 *			<li data-role="list-divider" data-style="dialogue">Items</li>
 *			<li>Item</li>
 *			<li>Item</li>
 *			<li>Item</li>
 *		</ul>
 *
 * ### Theme
 * _data-theme_ string Theme for list divider
 *
 *		@example
 *		<ul data-role="listview">
 *			<li data-role="list-divider" data-theme="c">Item styles</li>
 *			<li>Item</li>
 *			<li>Item</li>
 *			<li>Item</li>
 *		</ul>
 *
 * ### Folded
 * _data-folded_ string ["true" | "false"] Decide to show divider press effect or not
 *
 *		@example
 *		<ul data-role="listview">
 *			<li data-role="list-divider" data-folded="true">Item styles</li>
 *			<li>Item</li>
 *			<li>Item</li>
 *			<li>Item</li>
 *		</ul>
 *
 * ### Line
 * _data-line_ string ["true" | "false"] Decide to draw divider line or not
 *
 *		@example
 *		<ul data-role="listview">
 *			<li data-role="list-divider" data-line="false">Item styles</li>
 *			<li>Item</li>
 *			<li>Item</li>
 *			<li>Item</li>
 *		</ul>
 *
 * @class ns.widget.mobile.ListDivider
 * @extends ns.widget.BaseWidget
 */
(function (ns) {
	
				var BaseWidget = ns.widget.mobile.BaseWidgetMobile,
				/**
				 * Alias for class {@link ns.engine}
				 * @property {Object} engine
				 * @member ns.widget.mobile.ListDivider
				 * @private
				 * @static
				 */
				engine = ns.engine,
				/**
				 * Alias to ns.util.DOM
				 * @property {Object} dom
				 * @private
				 * @member ns.widget.mobile.ListDivider
				 * @static
				 */
				dom = ns.util.DOM,
				/**
				 * Alias to ns.util.selectors
				 * @property {Object} selectors
				 * @member ns.widget.mobile.ListDivider
				 * @private
				 * @static
				 */
				selectors = ns.util.selectors,
				/**
				 * Alias for class ns.widget.mobile.Button
				 * @property {Function} Button
				 * @member ns.widget.mobile.ListDivider
				 * @static
				 * @private
				 */
				Button = ns.widget.mobile.Button,

				ListDivider = function () {
					return this;
				};

			ListDivider.prototype = new BaseWidget();

			/**
			 * Dictionary for listdivider related css class names
			 * @property {Object} classes
			 * @member ns.widget.mobile.ListDivider
			 * @property {string} uiLiDivider Main calss of divider
			 * @property {string} uiBarThemePrefix Calss prefix of divider bar
			 * @property {string} uiDividerNormalLine Class of divider normal line
			 * @static
			 * @readonly
			 */
			ListDivider.classes = {
				uiBarThemePrefix: "ui-bar-",
				uiLiDivider: "ui-li-divider",
				uiDividerNormalLine: "ui-divider-normal-line"
			};

			/**
			 * Configure widget options
			 * @method _configure
			 * @member ns.widget.mobile.ListDivider
			 * @protected
			 */
			ListDivider.prototype._configure = function () {
				var options = this.options || {};
				/**
				 * Object with default options
				 * @property {Object} options
				 * @property {string} [options.theme="s"] Theme for list divider
				 * @property {"normal"|"checkbox"|"dialogue"} [options.style="normal"] Option sets the style of the list divider
				 * @property {boolean} [options.folded=false] Decide to show divider press effect or not
				 * @property {boolean} [options.line=true] Decide to draw divider line or not
				 * @member ns.widget.mobile.ListDivider
				 */
				this.options = options;
				options.theme = "s";
				options.style = "normal";
				options.folded = false;
				options.line = true;
			};

			/**
			 * Build widget
			 * @method _build
			 * @param {HTMLElement} element
			 * @return {HTMLElement}
			 * @member ns.widget.mobile.ListDivider
			 * @protected
			 */
			ListDivider.prototype._build = function (element) {
				var options = this.options,
					classes = ListDivider.classes,
					classList = element.classList,
					buttonClasses = Button.classes,
					elementWithLine;

				classList.add(classes.uiBarThemePrefix + options.theme);
				classList.add(classes.uiLiDivider);
				element.setAttribute("role", "heading");
				element.setAttribute("tabindex", "0");
				//@todo check if ol tag and reset counter

				if (!options.style || options.style === "normal" || options.style === "check") {
					if (options.folded === true) {
						/* buttonMarkup on element */
						engine.instanceWidget(element, "Button");
					} else {
						dom.wrapInHTML(
							element.childNodes,
							"<span class='" + buttonClasses.uiBtnText + "'></span>"
						);
					}

					if (options.line === true) {
						if (options.folded === true) {
							/*append to element.childrenBySelector("ui-btn-inner")*/
							elementWithLine = selectors.getChildrenByClass(element,
								buttonClasses.uiBtnInner)[0];
						} else {
							elementWithLine = element;
						}
						if (elementWithLine) {
							elementWithLine.insertAdjacentHTML(
								"beforeend",
								"<span class='" + classes.uiDividerNormalLine + "'></span>"
							);
						}
					}
				}
				return element;
			};

			// definition
			ns.widget.mobile.ListDivider = ListDivider;
			engine.defineWidget(
				"ListDivider",
				"[data-role='list-divider'], .ui-list-divider",
				[],
				ListDivider,
				"tizen"
			);

			}(ns));

/*global window, define */
/*
* Copyright  2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/*jslint nomen: true, plusplus: true */
/**
 * #Autodividers extension for ListView Widget
 * The Autodividers widget extension automatically creates dividers for a ListView Widget.
 *
 * ## Default selectors
 * A list can be configured to automatically generate dividers for its items. This is done by adding the **data-autodividers="true"** attribute to the ListView element. This is similar to jQueryMobile version 1.2.0.
 *
 * ###HTML Examples
 *
  * To add an autodividers widget to the application, use the following code:
 *
 *      @example
 *      <ul data-role="listview" data-autodividers="true" id="listview-with-autodividers">
 *          <li><a href="#">Amy</a></li>
 *          <li><a href="#">Arabella</a></li>
 *          <li><a href="#">Barry</a></li>
 *      </ul>
 *
 * Autodividers is not independent widget, this is extension for [ListView widget](ns_widget_mobile_Listview.htm).
 *
 * ##Methods
 *
 * Listview with autodividers has interface to call methods the same as ListView widget. To call method use:
 *
 *      @example
 *      $("#listview-with-autodividers").listview("methodname", methodArgument1, methodArgument2, ...);
 *
 * @author Tomasz Lukawski <t.lukawski@samsung.com>
 * @class ns.widget.mobile.Listview.Autodividers
 * @since Tizen 2.0
 * @override ns.widget.mobile.Listview
 */
(function (document, ns) {
	
				/**
			* Local alias for ns.util.selectors
			* @property {Object} selectors Alias for {@link ns.util.selectors}
			* @member ns.widget.mobile.Listview.Autodividers
			* @static
			* @private
			*/
			var selectors = ns.util.selectors,

				/**
				* Local alias for ns.engine
				* @property {Object} engine Alias for {@link ns.engine}
				* @member ns.widget.mobile.Listview.Autodividers
				* @static
				* @private
				*/
				engine = ns.engine,

				/**
				* Local alias for ns.util.DOM
				* @property {Object} doms Alias for {@link ns.util.DOM}
				* @member ns.widget.mobile.Listview.Autodividers
				* @static
				* @private
				*/
				doms = ns.util.DOM,

				/**
				* Object contains handlers for listeners of "beforeRefreshListItems" event,
				* Keys are [instance].id
				* @property {Object} onBeforeRefreshListItems description
				* @member ns.widget.mobile.Listview.Autodividers
				* @static
				* @private
				*/
				beforeRefreshListItemsHandlers = {},

				/**
				* Handler method for event "beforerefreshitems"
				* @method beforeRefreshListItems
				* @member ns.widget.mobile.Listview.Autodividers
				* @param {ns.widget.mobile.Listview} listview instance of Listview.
				* @param {HTMLUListElement|HTMLOListElement} element bound UList or OList HTMLElement
				* @static
				* @private
				*/
				beforeRefreshListItems = function beforeRefreshListItems(listview, element) {
					if (listview.options.autodividers) {
						listview._addAutodividers(element);
					}
				},

				/**
				* Method finding text in list element and return first letter
				* @method findFirstLetter
				* @member ns.widget.mobile.Listview.Autodividers
				* @param {HTMLUListElement|HTMLOListElement} listElement bound UList or OList HTMLElement
				* @return {null|string} return "null" if doesn't text found
				* @static
				* @private
				*/
				findFirstLetter = function (listElement) {
					// look for the text in the given element
					var text = listElement.textContent || null;
					if (!text) {
						return null;
					}
					// create the text for the divider (first uppercased letter)
					text = text.trim().slice(0, 1).toUpperCase();
					return text;
				},

				/**
				* Method removes list dividers from list.
				* @method removeDividers
				* @param {HTMLUListElement|HTMLOListElement} list bound UList or OList HTMLElement
				* @member ns.widget.mobile.Listview.Autodividers
				* @static
				* @private
				*/
				removeDividers = function removeDividers(list) {
					var liCollection = selectors.getChildrenBySelector(list, "li[data-role='list-divider']"),
						i,
						len = liCollection.length;
					for (i = 0; i < len; i++) {
						list.removeChild(liCollection[i]);
					}
				},

				/**
				* Insert list dividers into list.
				* @method insertAutodividers
				* @param {ns.widget.mobile.Listview} self
				* @param {HTMLUListElement|HTMLOListElement} list bound UList or OList HTMLElement
				* @member ns.widget.mobile.Listview.Autodividers
				* @static
				* @private
				*/
				insertAutodividers = function insertAutodividers(self, list) {
						/*
						* @property {NodeList} liCollection collection of HTMLLIElements
						*/
					var liCollection = selectors.getChildrenByTag(list, "li"),
						/*
						* @property {HTMLLIElement} li HTMLLIElement
						*/
						li,
						/*
						* @property {string|null} lastDividerText Text in last divider for comparison
						*/
						lastDividerText = null,
						/*
						* @property {string|null} dividerText Text found in LI element
						*/
						dividerText,
						/*
						* @property {ns.widget.listdivider} divider Instance of divider widget
						*/
						divider,
						/*
						* @property {Number} i Counter of loop
						*/
						i,
						/*
						* @property {Number} len Length of collection of HTMLLIElements
						*/
						len,
						optionFolded = doms.getNSData(list, "folded");

					for (i = 0, len = liCollection.length; i < len; i++) {
						li = liCollection[i];
						dividerText = self.options.autodividersSelector(li);
						if (dividerText && lastDividerText !== dividerText) {
							divider = document.createElement("li");
							divider.appendChild(document.createTextNode(dividerText));
							divider.setAttribute("data-role", "list-divider");
							li.parentNode.insertBefore(divider, li);
							engine.instanceWidget(divider, "ListDivider", {"folded": optionFolded});
						}
						lastDividerText = dividerText;
					}
				},

				/**
				* Major method of autodividers extension.
				* It removes old and inserts new dividers.
				* @method replaceDividers
				* @member ns.widget.mobile.Listview.Autodividers
				* @param {ns.widget.mobile.Listview} self
				* @param {HTMLUListElement|HTMLOListElement} list bound UList or OList HTMLElement.
				* @static
				* @private
				*/
				replaceDividers = function replaceDividers(self, list) {
					// remove dividers if exists;
					removeDividers(list);
					// insert new dividers;
					insertAutodividers(self, list);
				},

				/**
				* @property {Function} Listview Alias for class ns.widget.mobile.Listview
				* @member ns.widget.mobile.Listview.Autodividers
				* @static
				* @private
				*/
				Listview = ns.widget.mobile.Listview,

				/**
				* Backup of _build methods for replacing it
				* @method parent_build
				* @member ns.widget.mobile.Listview.Autodividers
				* @private
				*/
				parent_build = Listview.prototype._build,

				/**
				* Backup of _configure methods for replacing it
				* @method parent_configure
				* @member ns.widget.mobile.Listview.Autodividers
				* @private
				*/
				parent_configure = Listview.prototype._configure,

				/**
				* Backup of _init methods for replacing it
				* @method parent_init
				* @member ns.widget.mobile.Listview.Autodividers
				* @private
				*/
				parent_init = Listview.prototype._init,

				/**
				* Backup of _destroy methods for replacing it
				* @method parent_destroy
				* @member ns.widget.mobile.Listview.Autodividers
				* @private
				*/
				parent_destroy = Listview.prototype._destroy,

				/**
				* Initializing autodividers on Listview instance
				* @method initializeAutodividers
				* @member ns.widget.mobile.Listview.Autodividers
				* @param {ns.widget.mobile.Listview} self listview instance.
				* @param {HTMLUListElement|HTMLOListElement} element bound UList or OList HTMLElement.
				* @static
				* @private
				*/
				initializeAutodividers = function initializeAutodividers(self, element) {
					var onBeforeRefreshListItems = beforeRefreshListItems.bind(null, self, element);
					beforeRefreshListItemsHandlers[self.id] = onBeforeRefreshListItems;
					/**
					 * Options object
					 * @property {Object} options
					 * @property {boolean} [options.autodividers=false] This option enables creating autodividers on ListView
					 * @member ns.widget.mobile.Listview.Autodividers
					 */
					self.options.autodividers = false;
					self._getCreateOptions(element);
					element.addEventListener("beforerefreshitems",
						onBeforeRefreshListItems);
				};

			/**
			* Rebuilding html list element
			* @method _addAutodividers
			* @member ns.widget.mobile.Listview.Autodividers
			* @param {HTMLUListElement|HTMLOListElement} list bound UList or OList HTMLElement.
			 * @protected
			* @instance
			*/
			Listview.prototype._addAutodividers = function addAutodividers(list) {
				replaceDividers.call(null, this, list);
			};

			/**
			* @expose
			* @method _setAutodividers
			* @member ns.widget.mobile.Listview.Autodividers
			* @param {HTMLUListElement|HTMLOListElement} element bound UList or OList HTMLElement.
			* @param {boolean} enabled
			* @return {boolean}
			* @instance
			* @protected
			*/
			Listview.prototype._setAutodividers = function Listview_setAutodividers(element, enabled) {
				var options = this.options;
				if (options.autodividers === enabled) {
					return false;
				}
				// If autodividers option is changing from "true" to "false"
				// we need remove older dividers;
				if (options.autodividers && !enabled) {
					removeDividers(element);
				}
				options.autodividers = enabled;
				element.setAttribute("data-autodividers", enabled);
				if (enabled) {
					this.refresh();
				}
				return true;
			};

			/**
			* @method _configure
			* @member ns.widget.mobile.Listview.Autodividers
			* @instance
			* @protected
			*/
			Listview.prototype._configure = function Listview_configure() {
				var options;
				if (typeof parent_configure === "function") {
					parent_configure.call(this);
				}

				this.options = this.options || {};
				options = this.options;
				/** @expose */
				options.autodividers = false;
				/** @expose */
				options.autodividersSelector = findFirstLetter;
			};

			/**
			* Initialize autodividers features on Listview
			* Override method "_build" from Listview & call the protected "_build"
			* @method _build
			* @member ns.widget.mobile.Listview.Autodividers
			* @param {HTMLUListElement|HTMLOListElement} element bound UList or OList HTMLElement.
			* @return {HTMLUListElement|HTMLOListElement}
			* @instance
			* @protected
			*/
			Listview.prototype._build = function Listview_build(element) {
				initializeAutodividers(this, element);
				return parent_build.call(this, element);
			};

			/**
			* Initialize autodividers features on Listview
			* Override method "_init" from Listview & call the protected "_init" or "init"
			* @method _init
			* @member ns.widget.mobile.Listview.Autodividers
			* @param {HTMLUListElement|HTMLOListElement} element bound UList or OList HTMLElement.
			* @return {HTMLUListElement|HTMLOListElement}
			* @instance
			* @protected
			*/

			Listview.prototype._init = function Listview_init(element) {
				var autodividers = this.options.autodividers;
				if (autodividers === undefined || autodividers === null) {
					initializeAutodividers(this, element);
				}
				return (typeof parent_init === "function") ?
						parent_init.call(this, element) :
						element;
			};

			/**
			* Removing and cleaning autodividers extension
			* Override method "_destroy" from Listview & call the protected "_destroy"
			* @method _destroy
			* @member ns.widget.mobile.Listview.Autodividers
			* @instance
			* @protected
			*/
			Listview.prototype._destroy = function _destroy() {
				var element = this.element;
				element.removeEventListener("beforerefreshitems",
					beforeRefreshListItemsHandlers[this.id]);
				this.options.autodividers = null;
				// delete attribute
				element.removeAttribute("data-autodividers");
				// recovery previous version of protected methods;
				this._build = parent_build;
				this._init = parent_init;
				this._destroy = parent_destroy;
				// call protected method from Listview;
				if (typeof parent_destroy === "function") {
					parent_destroy.call(this);
				}
			};
			}(window.document, ns));

/*global window, define, ns */
/*
* Copyright  2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/*jslint nomen: true, plusplus: true */
/**
 * #Text Input Widget
 * Decorator for inputs elements.
 *
 * ## Default selectors
 * In default elements matches to :
 *
 *  - INPUT with type "text" or "number" or "password" or "email" or "url" or
 *    "tel" or "month" or "week" or "datetime-local" or "color" or without any
 *    type
 *  - TEXTAREA
 *  - HTML elements with class _ui-textinput_
 *
 * ###HTML Examples
 *
 * ####Create simple text input on INPUT element
 *
 *		@example
 *		<form>
 *			<label for="text-1">Text input:</label>
 *			<input type="text" name="text-1" id="text-1" value="">
 *		</form>
 *
 * ####Create simple text input on TEXTAREA element
 *
 *		@example
 *		<form>
 *			<label for="text-1">Text input:</label>
 *			<textarea name="text-1" id="text-1"></textarea>
 *		</form>
 *
 * ####Create simple text input on INPUT element with class ui-textinput
 *
 *		@example
 *		<form>
 *			<label for="text-1">Text input:</label>
 *			<input name="text-1" id="text-1" class="ui-textinput">
 *		</form>
 *
 * ## Manual constructor
 * For manual creation of TextInput widget you can use constructor of widget
 * from **tau** namespace:
 *
 *		@example
 *		<form>
 *			<label for="text-1">Text input:</label>
 *			<input type="search" name="text-1" id="text-1" value="">
 *		</form>
 *		<script>
 *			var inputElement = document.getElementById("text-1"),
 *				textInput = tau.widget.TextInput(inputElement);
 *		</script>
 *
 * Constructor has one require parameter **element** which are base
 * **HTMLElement** to create widget. We recommend get this element by method
 * *document.getElementById*. Second parameter is **options** and it is a object
 * with options for widget.
 *
 * If jQuery library is loaded, its method can be used:
 *
 *		@example
 *		<form>
 *			<label for="text-1">Text input:</label>
 *			<input type="text" name="text-1" id="text-1" value="">
 *		</form>
 *		<script>
 *			$("#text-1").textinput();
 *		</script>
 *
 * jQuery Mobile constructor has one optional parameter is **options** and it is
 * a object with options for widget.
 *
 * ##Options for widget
 *
 * Options for widget can be defined as _data-..._ attributes or give as
 * parameter in constructor.
 *
 * You can change option for widget using method **option**.
 *
 * ##Methods
 *
 * To call method on widget you can use one of existing API:
 *
 * First API is from tau namespace:
 *
 *		@example
 *		<input id="text-1" />
 *		<script>
 *			var inputElement = document.getElementById('text-1'),
 *				textInput = tau.widget.TextInput(inputElement);
 *		 	// textInput.methodName(argument1, argument2, ...);
 *			// for example:
 *			textInput.value("text");
 *		</script>
 *
 *
 * Second API is jQuery Mobile API and for call _methodName_ you can use:
 *
 *		@example
 *		<input id="text-1" />
 *		<script>
 *			// $("#text-1").textinput('methodName', argument1, argument2, ...);
 *			// for example
 *			$("#text-1").value("text");
 *		</script>
 *
 * @class ns.widget.mobile.TextInput
 * @extends ns.widget.BaseWidget
 * @author Maciej Urbanski <m.urbanski@samsung.com>
 * @author Jadwiga Sosnowska <j.sosnowska@samsung.com>
 * @author Piotr Karny <p.karny@samsung.com>
 * @author Piotr Kusztal <p.kusztal@samsung.com>
 * @author Maciej Moczulski <m.moczulski@samsung.com>
 * @author Krzysztof Antoszek <k.antoszek@samsung.com>
 * @author Hyunkook Cho <hk0713.cho@samsung.com>
 * @author Junhyeon Lee <juneh.lee@samsung.com>
 */
(function (document, ns) {
	
			var TextInput = function () {
					/**
					 * Object with default options
					 * @property {Object} options
					 * @property {string} [options.clearSearchButtonText="clear text"] Default text for search field clear text button
					 * @property {boolean} [options.disabled=false] disable widget
					 * @property {?boolean} [options.mini=null] set mini version
					 * @property {string} [options.theme='s'] theme of widget
					 * @property {string} [options.clearBtn=false] option indicates that the clear button will be shown
					 * @member ns.widget.mobile.TextInput
					 */
					this.options = {
						clearSearchButtonText: "clear text",
						disabled: false,
						mini: null,
						theme: 's',
						clearBtn: false
					};

					this._ui = {};
					this._handlers = {};
				},
				/**
				 * Alias for {ns.widget.BaseWidget}
				 * @property {Object} BaseWidget
				 * @member ns.widget.mobile.TextInput
				 * @static
				 * @private
				 */
				BaseWidget = ns.widget.mobile.BaseWidgetMobile,
				/**
				 * Alias for {ns.engine}
				 * @property {Object} engine
				 * @member ns.widget.mobile.TextInput
				 * @static
				 * @private
				 */
				engine = ns.engine,
				/**
				 * Alias for {ns.theme}
				 * @property {Object} theme
				 * @member ns.widget.mobile.TextInput
				 * @static
				 * @private
				 */
				themes = ns.theme,
				/**
				 * Flag with informations about events
				 * @property {boolean} eventsAdded
				 * @private
				 * @static
				 * @member ns.widget.mobile.TextInput
				 */
				eventsAdded = false,

				domUtils = ns.util.DOM,

				/**
				 * Dictionary for textinput related css class names
				 * @property {Object} classes
				 * @member ns.widget.mobile.TextInput
				 * @static
				 */
				classes = {
					uiBodyTheme: "ui-body-",
					uiMini: "ui-mini",
					uiInputText: "ui-input-text",
					clear: "ui-input-clear",
					clearHidden: "ui-input-clear-hidden",
					clearActive: "ui-input-clear-active",
					textLine: "ui-text-line",
					focus: "ui-focus"
				},
				/**
				 * Selector for clear button appended to textinput
				 * @property {string} CLEAR_BUTTON_SELECTOR
				 * @member ns.widget.mobile.TextInput
				 * @static
				 * @private
				 * @readonly
				 */
				CLEAR_BUTTON_SELECTOR = '.' + classes.clear,
				/**
				 * Alias for {ns.widget.mobile.Button.classes.uiDisabled}
				 * @property {string} CLASS_DISABLED
				 * @member ns.widget.mobile.TextInput
				 * @static
				 * @private
				 * @readonly
				 */
				CLASS_DISABLED = ns.widget.mobile.Button.classes.uiDisabled;

			TextInput.prototype = new BaseWidget();

			TextInput.classes = classes;

			/**
			 * Enables the textinput
			 *
			 * Method removes disabled attribute on input and changes look of
			 * input to enabled state.
			 *
			 *	@example
			 *	<input id="input" />
			 *	<script>
			 *		var inputElement = document.getElementById("input"),
			 *			textInputWidget = tau.widget.TextInput();
			 *
			 *		textInputWidget.enable();
			 *	</script>
			 *
			 *	@example
			 *	<input id="input" />
			 *	<script>
			 *		$( "#input" ).textinput( "enable" );
			 *	</script>
			 *
			 * @method enable
			 * @chainable
			 * @member ns.widget.mobile.TextInput
			 */

			/**
			 * Method enables TextInput.
			 * @method _enable
			 * @member ns.widget.mobile.TextInput
			 * @protected
			 */
			TextInput.prototype._enable = function () {
				var element = this.element;
				if (element) {
					element.classList.remove(CLASS_DISABLED);
				}
			};

			/**
			 * Disables the textinput
			 *
			 * Method adds disabled attribute on input and changes look of
			 * input to disable state.
			 *
			 *	@example
			 *	<input id="input" />
			 *	<script>
			 *		var inputElement = document.getElementById("input"),
			 *			textInputWidget = tau.widget.TextInput();
			 *
			 *		textInputWidget.disable();
			 *	</script>
			 *
			 *	@example
			 *	<input id="input" />
			 *	<script>
			 *		$( "#input" ).textinput( "disable" );
			 *	</script>
			 *
			 * @method disable
			 * @chainable
			 * @member ns.widget.mobile.TextInput
			 */

			/**
			 * Method disables TextInput
			 * @method _disable
			 * @member ns.widget.mobile.TextInput
			 * @protected
			 */
			TextInput.prototype._disable = function () {
				var element = this.element;
				if (element) {
					element.classList.add(CLASS_DISABLED);
				}
			};

			/**
			 * Resize textarea, called after text input
			 * @method _resize
			 * @private
			 * @param {HTMLElement} element
			 * @member ns.widget.mobile.TextInput
			 */
			function _resize(element){
				if (element.nodeName.toLowerCase() === "textarea") {
					if(element.clientHeight < element.scrollHeight){
						element.style.height = element.scrollHeight + "px";
					}
				}
			}

			/**
			 * Toggle visibility of the clear button
			 * @method toggleClearButton
			 * @param {HTMLElement} clearBtn
			 * @param {HTMLInputElement} inputElement
			 * @member ns.widget.mobile.TextInput
			 * @static
			 * @private
			 */
			function toggleClearButton(clearBtn, inputElement) {
				if (clearBtn) {
					// @TODO change to two-parameter toggle after it's implemenation is fixed on the platform
					if (inputElement.value === "") {
						clearBtn.classList.add(classes.clearHidden);
						inputElement.classList.remove(classes.clearActive);
					} else {
						clearBtn.classList.remove(classes.clearHidden);
						inputElement.classList.add(classes.clearActive);
					}
				}
			}

			/**
			 * Method finds label tag for element.
			 * @method findLabel
			 * @param {HTMLElement} element
			 * @member ns.widget.mobile.TextInput
			 * @return {HTMLElement}
			 * @static
			 * @private
			 */
			function findLabel(element) {
				return element.parentNode.querySelector('label[for="' + element.id + '"]');
			}

			/**
			 * Method returns not disabled TextInput element which is the closest
			 * to element.
			 * @method isEnabledTextInput
			 * @param {HTMLInputElement} element
			 * @return {boolean}
			 * @private
			 * @static
			 * @member ns.widget.mobile.TextInput
			 */
			function isEnabledTextInput(element) {
				return element && element.classList.contains(classes.uiInputText) &&
					!element.classList.contains(CLASS_DISABLED) && !element.disabled;
			}

			/**
			* The check whether the element is the enable "clear" button
			* @method isEnabledClearButton
			* @param {HTMLElement} buttonElement
			* @return {boolean}
			* @private
			* @static
			* @member ns.widget.mobile.TextInput
			*/
			function isEnabledClearButton(buttonElement) {
				var input;

				if (buttonElement && buttonElement.classList.contains(classes.clear)) {
					//input = element.previousElementSibling;
					input = buttonElement.parentElement.querySelector("." + classes.uiInputText);

					return isEnabledTextInput(input);
				}
				return false;
			}

			/**
			 * Method adds class ui-focus to target element of event.
			 * @method onFocus
			 * @param {Event} event
			 * @private
			 * @static
			 * @member ns.widget.mobile.TextInput
			 */
			function onFocus(event) {
				var element = event.target;
				if (isEnabledTextInput(element)) {
					element.classList.add(classes.focus);
				}
			}

			/**
			 * Method adds event for showing clear button and optional resizing textarea.
			 * @method onInput
			 * @param {Event} event
			 * @private
			 * @static
			 * @member ns.widget.mobile.TextInput
			 */
			function onInput(event) {
				var element = event.target,
					self;
				if (isEnabledTextInput(element)) {
					self = engine.getBinding(element, "TextInput");
					if (self) {
						toggleClearButton(self._ui.clearButton, element);
					}
					_resize(element);
				}
			}
			/**
			 * Method removes class ui-focus from target element of event.
			 * @method onBlur
			 * @param {Event} event
			 * @private
			 * @static
			 * @member ns.widget.mobile.TextInput
			 */
			function onBlur(event) {
				var element = event.target,
					self;
				if (isEnabledTextInput(element)) {
					element.classList.remove(classes.focus);
					self = engine.getBinding(element, "TextInput");
					if (self) {
						toggleClearButton(self._ui.clearButton, element);
					}
				}
			}
			/**
			* Handler for vclick events in clearButton
			* @method onCancel
			* @param {Event} event
			* @private
			* @static
			* @member ns.widget.mobile.TextInput
			*/
			function onCancel(event) {
				var clearButton = event.target,
					input;

				if (isEnabledClearButton(clearButton)) {
					input = clearButton.parentElement.querySelector("." + classes.uiInputText);
					input.value = "";
					toggleClearButton(clearButton, input);
					input.focus();
				}
			}

			/**
			 * add events to all TextInputs
			 * @method addGlobalEvents
			 * @private
			 * @static
			 * @member ns.widget.mobile.TextInput
			 */
			function addGlobalEvents() {
				if (!eventsAdded) {
					document.addEventListener('focus', onFocus, true);
					document.addEventListener('blur', onBlur, true);
					document.addEventListener('vclick', onCancel, true);
					eventsAdded = true;
				}
			}

			/**
			 * Removes global events related to checkboxes
			 * @method removeGlobalEvents
			 * @private
			 * @static
			 * @member ns.widget.mobile.TextInput
			 */
			function removeGlobalEvents() {
				document.removeEventListener('focus', onFocus, true);
				document.removeEventListener('blur', onBlur, true);
				document.removeEventListener('vclick', onCancel, true);
				eventsAdded = false;
			}

			/**
			* Configure TextInput Widget
			* @method _configure
			* @member ns.widget.mobile.TextInput
			* @protected
			*/
			TextInput.prototype._configure = function () {
				var self = this;

				self._ui = self._ui || {};
			};

			function setAria(element) {
				element.setAttribute("role", "textbox");
				element.setAttribute("aria-label", "Keyboard opened");
			}

			function createDecorationLine(element) {
				var decorationLine = element.nextElementSibling;

				if (!decorationLine || (decorationLine && !decorationLine.classList.contains(classes.textLine))) {

					decorationLine = document.createElement("span");
					decorationLine.classList.add(classes.textLine);

					domUtils.insertNodeAfter(element, decorationLine);
				}

				return decorationLine;
			}

			/**
			* build TextInput Widget
			* @method _build
			* @param {HTMLElement} element
			* @member ns.widget.mobile.TextInput
			* @return {HTMLElement}
			* @protected
			*/
			TextInput.prototype._build = function (element) {
				var self= this,
					elementClassList = element.classList,
					options = self.options,
					themeClass,
					labelFor = findLabel(element),
					clearButton,
					type = element.type,
					ui;

				ui = self._ui;

				options.theme = themes.getInheritedTheme(element) || options.theme;
				themeClass = classes.uiBodyTheme + options.theme;

				if (labelFor) {
					labelFor.classList.add(classes.uiInputText);
				}

				elementClassList.add(classes.uiInputText);
				elementClassList.add(themeClass);

				switch (type) {
				case "text":
				case "password":
				case "number":
				case "email":
				case "url":
				case "tel":
					setAria(element);
					// Adds decoration line for textbox-like elements and textarea
					// this is required only to match the UX Guides, no other
					// functionality is related to that element
					ui.textLine = createDecorationLine(element);
					break;
				default:
					if (element.tagName.toLowerCase() === "textarea") {
						setAria(element);
						ui.textLine = createDecorationLine(element);
					}
				}

				element.tabindex = 0;

				if (options.clearBtn) {
					clearButton = document.createElement("span");
					clearButton.classList.add(classes.clear);
					clearButton.tabindex = 0;

					element.parentNode.appendChild(clearButton);

					ui.clearButton = clearButton;
				}

				//Auto grow
				_resize(element);

				return element;
			};

			/**
			* Init TextInput Widget
			* @method _init
			* @param {HTMLElement} element
			* @member ns.widget.mobile.TextInput
			* @return {HTMLElement}
			* @protected
			*/
			TextInput.prototype._init = function (element) {
				var self = this,
					ui = self._ui,
					options = self.options;
				if (options.clearBtn) {
					ui.clearButton = element.parentNode.querySelector(CLEAR_BUTTON_SELECTOR);

					if (ui.clearButton) {
						toggleClearButton(ui.clearButton, element);
					}
				}

				switch (element.type) {
					case "text":
					case "password":
					case "number":
					case "email":
					case "url":
					case "tel":
						ui.textLine = element.nextElementSibling;
						break;
				}

				return element;
			};


			/**
			* Bind events to widget
			* @method _bindEvents
			* @param {HTMLElement} element
			* @protected
			* @member ns.widget.mobile.TextInput
			*/
			TextInput.prototype._bindEvents = function (element) {
				element.addEventListener('input', onInput , false);
				addGlobalEvents();
				// One time resize after page show
				document.addEventListener("pageshow", function _resizeWidgetsOnPageLoad() {
					document.removeEventListener("pageshow", _resizeWidgetsOnPageLoad);

					_resize(element);
				});
			};

			/**
			 * Destroys additional elements created by the widget,
			 * removes classes and event listeners
			 * @method _destroy
			 * @param {HTMLElement} element
			 * @protected
			 * @member ns.widget.mobile.TextInput
			 */
			TextInput.prototype._destroy = function (element) {
				var ui = this._ui,
					textLine = ui.textLine,
					clearButton = ui.clearButton,
					elementClassList = element.classList;

				if (textLine) {
					textLine.parentElement.removeChild(ui.textLine);
				}

				if (clearButton) {
					clearButton.parentElement.removeChild(ui.clearButton);
				}

				// Remove events
				element.removeEventListener('input', onInput , false);

				removeGlobalEvents();

				// Remove classes
				elementClassList.remove(classes.clearActive);
				elementClassList.remove(classes.uiInputText);
				elementClassList.remove(classes.uiBodyTheme + this.options.theme);
			};

			ns.widget.mobile.TextInput = TextInput;
			engine.defineWidget(
				"TextInput",
				"input[type='text']:not([data-role])" +
					", input[type='number']:not([data-role])" +
					", input[type='password']:not([data-role])" +
					", input[type='email']:not([data-role])" +
					", input[type='url']:not([data-role])" +
					", input[type='tel']:not([data-role])" +
					", input[type='month']:not([data-role])" +
					", input[type='week']:not([data-role])" +
					", input[type='datetime-local']:not([data-role])" +
					", input[type='color']:not([data-role])" +
					", input:not([type]):not([data-role]):not(.ui-checkbox):not(.ui-tizenslider)" +
					", textarea" +
					", .ui-textinput",
				[],
				TextInput,
				"mobile"
			);
}(window.document, ns));

/*global window, define, ns */
/*
* Copyright  2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/*jslint nomen: true, plusplus: true */
/**
 * # Search Bar Widget
 * The search filter bar widget is used to search for page content.
 *
 * This widget can be placed in the header or page content.
 *
 * ## Default selectors
 * In default elementch matches to :
 *
 *  - INPUT with type equals "search" or "tizen-search"
 *  - HTML elements with data-type="search" or data-type="tizen-search"
 *  - HTML elements with class ui-searchbar
 *
 * ###HTML Examples
 *
 * ####Create simple searchbar in header
 *
 *		@example
 * 		<div data-role="page" id="search-bar-page">
 *			<div data-role="header">
 *				<label for="search-bar">Search Input:</label>
 *				<input type="search" name="search" id="search-bar"/>
 *			</div>
 *			<div data-role="content" id="search-bar-content">
 *				<p>Hairston</p>
 *				<p>Hansbrough</p>
 *				<p>Allred</p>
 *				<p>Hanrahan</p>
 *				<p>Egan</p>
 *				<p>Dare</p>
 *				<p>Edmonson</p>
 *				<p>Calip</p>
 *				<p>Baker</p>
 *				<p>Fazekas</p>
 *				<p>Garrity</p>
 *			</div>
 *		</div>
 *		<script>
 *			(function (document) {
 *				var inputElement = document.getElementById("search-bar"),
 *					contentElement = document.getElementById("search-bar-content"),
 *					contentChildren = contentElement.getElementsByTagName("p"),
 *					contentChildrenLength = contentChildren.length;
 *
 *				function changeHandle(event) {
 *					var i,
 *						child,
 *						childText,
 *						value = inputElement.value;
 *
 *					for (i = 0; i < contentChildrenLength; i++) {
 *						child = contentChildren.item(i);
 *						childText = child.textContent.toLowerCase();
 *						if (!value || ~childText.indexOf(value)) {
 *							child.style.display = "block";
 *						} else {
 *							child.style.display = "none";
 *						}
 *					}
 *				}
 *
 *				inputElement.addEventListener("change", changeHandle);
 *				inputElement.addEventListener("keyup", changeHandle);
 *			}(document));
 *		</script>
 *
 * ## Manual constructor
 * For manual creation of search bar widget you can use constructor of widget from
 * **tau** namespace:
 *
 *		@example
 * 		<div data-role="page" id="search-bar-page">
 *			<div data-role="header">
 *				<label for="search-bar">Search Input:</label>
 *				<input name="search" id="search-bar"/>
 *			</div>
 *			<div data-role="content" id="search-bar-content">
 *				<p>Hairston</p>
 *				<p>Hansbrough</p>
 *				<p>Allred</p>
 *				<p>Hanrahan</p>
 *				<p>Egan</p>
 *				<p>Dare</p>
 *				<p>Edmonson</p>
 *				<p>Calip</p>
 *				<p>Baker</p>
 *				<p>Fazekas</p>
 *				<p>Garrity</p>
 *			</div>
 *		</div>
 *		<script>
 *			(function (document) {
 *				var inputElement = document.getElementById("search-bar"),
 *					contentElement = document.getElementById("search-bar-content"),
 *					contentChildren = contentElement.getElementsByTagName("p"),
 *					contentChildrenLength = contentChildren.length,
 *					pageElement = document.getElementById("search-bar-page"),
 *					searchBar;
 *
 *				function changeHandle(event) {
 *					var i,
 *						child,
 *						childText,
 *						value = searchBar.value();
 *
 *					for (i = 0; i < contentChildrenLength; i++) {
 *						child = contentChildren.item(i);
 *						childText = child.textContent.toLowerCase();
 *						if (!value || ~childText.indexOf(value)) {
 *							child.style.display = "block";
 *						} else {
 *							child.style.display = "none";
 *						}
 *					}
 *				}
 *
 *				function createPageHandle() {
 *					searchBar = tau.widget.SearchBar(inputElement, {
 *						icon: "call"
 *					});
 *					searchBar.on("change keyup", changeHandle);
 *				}
 *
 *				pageElement.addEventListener("pagecreate", createPageHandle);
 *			}(document));
 *		</script>
 *
 * Constructor has one require parameter **element** which are base
 * **HTMLElement** to create widget. We recommend get this element by method
 * *document.getElementById*. Second parameter is **options** and it is a object
 * with options for widget.
 *
 * If jQuery library is loaded, its method can be used:
 *
 *		@example
 *		<div data-role="page" id="search-bar-page">
 *			<div data-role="header">
 *				<label for="search-bar">Search Input:</label>
 *				<input name="search" id="search-bar"/>
 *			</div>
 *			<div data-role="content" id="search-bar-content">
 *				<p>Hairston</p>
 *				<p>Hansbrough</p>
 *				<p>Allred</p>
 *				<p>Hanrahan</p>
 *				<p>Egan</p>
 *				<p>Dare</p>
 *				<p>Edmonson</p>
 *				<p>Calip</p>
 *				<p>Baker</p>
 *				<p>Fazekas</p>
 *				<p>Garrity</p>
 *			</div>
 *		</div>
 *		<script>
 *			(function (document) {
 *				var inputElement = document.getElementById("search-bar"),
 *						contentElement = document.getElementById("search-bar-content"),
 *						contentChildren = contentElement.getElementsByTagName("p"),
 *						contentChildrenLength = contentChildren.length,
 *						pageElement = document.getElementById("search-bar-page");
 *
 *				function changeHandle(event) {
 *					var i,
 *						child,
 *						childText,
 *						value = inputElement.value;
 *
 *					for (i = 0; i < contentChildrenLength; i++) {
 *						child = contentChildren.item(i);
 *						childText = child.textContent.toLowerCase();
 *						if (!value || ~childText.indexOf(value)) {
 *							child.style.display = "block";
 *						} else {
 *							child.style.display = "none";
 *						}
 *					}
 *				}
 *
 *				function createPageHandle() {
 *					$("#search-bar").searchbar(inputElement, {
 *						icon: "call"
 *					}).on("change keyup", changeHandle);
 *				}
 *
 *				$("#search-bar-page").on("pagecreate", createPageHandle);
 *			}(document));
 *		</script>
 *
 * jQuery Mobile constructor has one optional parameter is **options** and it is
 * a object with options for widget.
 *
 * ##Options for search bar widget
 *
 * Options for widget can be defined as _data-..._ attributes or give as
 * parameter in constructor.
 *
 * You can change option for widget using method **option**.
 *
 * ##Methods
 *
 * To call method on widget you can use one of existing API:
 *
 * First API is from tau namespace:
 *
 *		@example
 *		<script>
 *		var searchBarElement = document.getElementById('search-bar'),
 *			searchBar = tau.widget.SearchBar(searchBarElement);
 *
 *		searchBar.methodName(methodArgument1, methodArgument2, ...);
 *		</script>
 *
 * Second API is jQuery Mobile API and for call _methodName_ you can use:
 *
 *		@example
 *		<script>
 *		$(".selector").searchbar('methodName', methodArgument1, methodArgument2, ...);
 *		</script>
 *
 * #Search Bar Widget
 * @class ns.widget.mobile.SearchBar
 * @extends ns.widget.BaseWidget
 */
(function (document, ns) {
	
			var SearchBar = function () {
					return this;
				},
				BaseWidget = ns.widget.mobile.BaseWidgetMobile,
				textInputClasses = ns.widget.mobile.TextInput.classes,
				engine = ns.engine,
				themes = ns.theme,
				DOM = ns.util.DOM,
				events = ns.event,
				classes = {
					uiInputText: "ui-input-text",
					uiInputSearch: "ui-input-search",
					uiShadowInset: "ui-shadow-inset",
					uiCornerAll: "ui-corner-all",
					uiBtnShadow: "ui-btn-shadow",
					themePrefix: "ui-body-",
					uiInputSearchDefault: "ui-input-search-default",
					uiSearchBarIcon: "ui-search-bar-icon",
					uiInputClear: "ui-input-clear",
					uiInputClearHidden: "ui-input-clear-hidden",
					inputSearchBar: "input-search-bar",
					uiInputCancel: "ui-input-cancel",
					uiInputDefaultText: "ui-input-default-text",
					uiBtnSearchFrontIcon: "ui-btn-search-front-icon",
					uiInputSearchWide: "ui-input-search-wide",
					uiBtnCancelHide: "ui-btn-cancel-hide",
					uiBtnCancelShow: "ui-btn-cancel-show",
					uiFocus: 'ui-focus',
					uiHeaderSearchBar: "ui-header-searchbar",
					clearActive: textInputClasses.clearActive,
					textLine: textInputClasses.textLine
				};

			SearchBar.prototype = new BaseWidget();

			/**
			 * Dictionary for SearchBar related css class names
			 * @property {Object} classes
			 * @member ns.widget.mobile.SearchBar
			 * @static
			 */
			SearchBar.classes = classes;

			SearchBar.prototype._configure = function () {
				/**
				 * @property {Object} options All possible widget options
				 * @property {?string} [options.theme=null] theme of widget
				 * @property {boolean} [options.cancelBtn=false] shows or not cancel button
				 * @property {?string} [options.icon=null] type of icon on action button, possible values are the same as in button widget. If opition is not set then action button isn't showing
				 * @member ns.widget.mobile.SearchBar
				 */
				this.options = this.options || {};
				this.options.theme = null;
				this.options.cancelBtn = false;
				this.options.icon = null;
			};

			/**
			 * Enable the search bar
			 *
			 * Method removes disabled attribute on search bar and changes look
			 * of search bar to enabled state.
			 *
			 *		@example
			 *		<script>
			 *		var element = document.getElementById("searchbar"),
			 *			searchBarWidget = tau.widget.SearchBar(element);
			 *		searchBarWidget.enable();
			 *
			 *		// or
			 *
			 *		$( "#searchbar" ).searchbar( "enable" );
			 *		</script>
			 *
			 * @method enable
			 * @chainable
			 * @member ns.widget.mobile.SearchBar
			 */
			/**
			* Enable SearchBar
			* @method _enable
			* @param {HTMLElement} element
			* @member ns.widget.mobile.SearchBar
			* @protected
			*/
			SearchBar.prototype._enable = function (element) {
				element = element || this.element;
				if (element) {
					element.removeAttribute("disabled");
					element.classList.remove("ui-disabled");
				}
			};

			/**
			 * Disable the search bar
			 *
			 * Method add disabled attribute on search bar and changes look
			 * of search bar to disabled state.
			 *
			 *		@example
			 *		<script>
			 *		var element = document.getElementById("searchbar"),
			 *			searchBarWidget = tau.widget.SearchBar(element);
			 *		searchBarWidget.disable();
			 *
			 *		// or
			 *
			 *		$( "#searchbar" ).searchbar( "disable" );
			 *		</script>
			 *
			 * @method disable
			 * @chainable
			 * @member ns.widget.mobile.SearchBar
			 */
			/**
			* Disable SearchBar
			* @method _disable
			* @param {HTMLElement} element
			* @member ns.widget.mobile.SearchBar
			* @protected
			*/
			SearchBar.prototype._disable = function (element) {
				element = element || this.element;
				if (element) {
					element.setAttribute("disabled", "disabled");
					element.classList.add("ui-disabled");
				}
			};

			/**
			 * Finds label for element in parent's element.
			 * @method findLabel
			 * @static
			 * @private
			 * @param {HTMLElement} element base element for finding label
			 * @returns {?HTMLElement}
			 * @member ns.widget.mobile.SearchBar
			 */
			function findLabel(element) {
				var elemParent = element.parentNode,
					label = elemParent.querySelector('label[for="' + element.id + '"]');
				return label;
			}

			function createDecorationLine(element) {
				var decorationLine = element.nextElementSibling;

				if (!decorationLine || (decorationLine && !decorationLine.classList.contains(classes.textLine))) {

					decorationLine = document.createElement("span");
					decorationLine.classList.add(classes.textLine);

					DOM.insertNodeAfter(element, decorationLine);
				}

				return decorationLine;
			}

			/**
			 * Build widget structure
			 * @param {HTMLElement} element
			 * @returns {HTMLElement}
			 * @protected
			 * @member ns.widget.mobile.SearchBar
			 */
			SearchBar.prototype._build = function (element) {
				var options = this.options,
					protoOptions = SearchBar.prototype.options,
					theme = options.theme || themes.getInheritedTheme(element, (protoOptions || protoOptions.theme) || 'c'),
					themeClass  = classes.themePrefix + theme,
					searchBox,
					clearButton,
					cancelButton,
					defaultText,
					labelDiv,
					frontIcon,
					label = findLabel(element),
					searchBoxClasses,
					inputSearchBar,
					inputClassList = element.classList,
					ui;

				this._ui = this._ui || {};
				ui = this._ui;

				if (label) {
					label.classList.add(classes.uiInputText);
				}

				if (element.parentNode.classList.contains("ui-header")) {
					// searchbar located header area
					element.parentNode.classList.add(classes.uiHeaderSearchBar);
				}

				if (element.autocorrect !== undefined) { // @todo && !$.support.touchOverflow ) {
					// Set the attribute instead of the property just in case there
					// is code that attempts to make modifications via HTML.
					element.setAttribute("autocorrect", "off");
					element.setAttribute("autocomplete", "off");
				}

				element.removeAttribute('type');

				inputClassList.add(classes.uiInputText);
				inputClassList.add(themeClass);

				searchBox = document.createElement('div');
				searchBoxClasses = searchBox.classList;
				searchBoxClasses.add(classes.uiInputSearch);
				searchBoxClasses.add(classes.uiShadowInset);
				searchBoxClasses.add(classes.uiCornerAll);
				searchBoxClasses.add(classes.uiBtnShadow);
				searchBoxClasses.add(themeClass);

				element.parentNode.replaceChild(searchBox, element);
				searchBox.appendChild(element);

				// Decoration
				ui.textLine = createDecorationLine(element);

				// @TODO use TextInput widget instead
				if (options.cancelBtn) {
					searchBoxClasses.add(classes.uiInputSearchDefault);
				}

				clearButton = document.createElement('a');
				clearButton.setAttribute('href', '#');
				clearButton.setAttribute('title', 'clear text');
				clearButton.classList.add(classes.uiInputClear);
				if (!element.value) {
					clearButton.classList.add(classes.uiInputClearHidden);
				}
				clearButton.setAttribute('id', this.id + '-clear-button');
				searchBox.appendChild(clearButton);
				engine.instanceWidget(clearButton, 'Button', {
					icon: "deleteSearch",
					iconpos: "notext",
					corners: true,
					shadow: true
				});

				// Give space from right
				element.classList.add(classes.clearActive);

				inputSearchBar = document.createElement('div');
				inputSearchBar.classList.add(classes.inputSearchBar);
				searchBox.parentNode.replaceChild(inputSearchBar, searchBox);
				inputSearchBar.appendChild(searchBox);

				if (options.icon) {
					searchBoxClasses.add(classes.uiSearchBarIcon);
					frontIcon = document.createElement('div');
					DOM.setNSData(frontIcon, 'role', 'button');
					inputSearchBar.appendChild(frontIcon);
					engine.instanceWidget(frontIcon, 'Button', {
						iconpos: "notext",
						icon: options.icon
					});
					frontIcon.classList.add(classes.uiBtnSearchFrontIcon);
				}

				// @TODO use TextInput widget instead
				if (options.cancelBtn) {
					cancelButton = document.createElement('div');
					DOM.setNSData(cancelButton, 'role', 'button');
					cancelButton.classList.add(classes.uiInputCancel);
					cancelButton.setAttribute('title', 'Clear text');
					cancelButton.textContent = 'Cancel';
					cancelButton.setAttribute('id', this.id + '-cancel-button');

					engine.instanceWidget(cancelButton, 'Button');

					inputSearchBar.appendChild(cancelButton);
				}

				// Default Text
				defaultText = DOM.getNSData(element, "default-text");

				if (defaultText !== null) {
					element.setAttribute("placeholder", defaultText);
				}

				if (!element.getAttribute("placeholder")) {
					element.setAttribute("placeholder", "Search");
				}

				ui.input = element;
				ui.clearButton = clearButton;
				if (cancelButton) {
					ui.cancelButton = cancelButton;
				}
				if (labelDiv) {
					ui.labelDiv = labelDiv;
					labelDiv.setAttribute('id', this.id + '-label-div');
				}
				ui.searchBox = searchBox;
				searchBox.setAttribute('id', this.id + '-search-box');

				return element;
			};

			/**
			 * Callback for click event on clear button
			 * @method clearButtonClick
			 * @param {ns.widget.mobile.SearchBar} self
			 * @param {Event} event
			 * @static
			 * @private
			 * @member ns.widget.mobile.SearchBar
			 */
			function clearButtonClick(self, event) {
				var input = self._ui.input;
				if (!input.getAttribute("disabled")) {
					input.value = '';
					events.trigger(input, 'change');
					input.focus();
					event.preventDefault();
				}
			}

			/**
			 * Callback for click event on cancel button
			 * @method cancelButtonClick
			 * @param {ns.widget.mobile.SearchBar} self
			 * @param {Event} event
			 * @static
			 * @private
			 * @member ns.widget.mobile.SearchBar
			 */
			function cancelButtonClick(self, event) {
				var input = self._ui.input,
					localClassList;
				if (!input.getAttribute("disabled")) {
					event.preventDefault();
					event.stopPropagation();

					input.value = '';
					events.trigger(input, 'change');
					input.blur();

					if (self.options.cancel) {
						localClassList = self._ui.searchBox.classList;
						localClassList.add(classes.uiInputSearchWide);
						localClassList.remove(classes.uiInputSearchDefault);

						localClassList = self._ui.cancelButton.classList;
						localClassList.add(classes.uiBtnCancelHide);
						localClassList.remove(classes.uiBtnCancelShow);
					}
				}
			}

			/**
			 * Callback for focus event on input
			 * @method inputFocus
			 * @param {ns.widget.mobile.SearchBar} self
			 * @static
			 * @private
			 * @member ns.widget.mobile.SearchBar
			 */
			function inputFocus(self) {
				var input = self._ui.input,
					localClassList;
				if (!input.getAttribute("disabled")) {
					localClassList = self._ui.searchBox.classList;
					localClassList.add(classes.uiFocus);
					if (self.options.cancel) {
						localClassList.remove(classes.uiInputSearchWide);
						localClassList.add(classes.uiInputSearchDefault);

						localClassList = self._ui.cancelButton.classList;
						localClassList.remove(classes.uiBtnCancelHide);
						localClassList.add(classes.uiBtnCancelShow);
					}
				}
				if (self._ui.labelDiv) {
					self._ui.labelDiv.classList.add(classes.uiInputDefaultHidden);
				}
			}

			/**
			 * Callback for blur event on input
			 * @method inputBlur
			 * @param {ns.widget.mobile.SearchBar} self
			 * @static
			 * @private
			 * @member ns.widget.mobile.SearchBar
			 */
			function inputBlur(self) {
				var inputedText = self._ui.input.value,
					classes = SearchBar.classes,
					ui = self._ui;
				ui.searchBox.classList.remove(classes.uiFocus);
				if (ui.labelDiv) {
					if (inputedText.length > 0) {
						ui.labelDiv.classList.add(classes.uiInputDefaultHidden);
					} else {
						ui.labelDiv.classList.remove(classes.uiInputDefaultHidden);
					}
				}
			}

			/**
			 * Callback for click event on label
			 * @method labelClick
			 * @param {ns.widget.mobile.SearchBar} self
			 * @static
			 * @private
			 * @member ns.widget.mobile.SearchBar
			 */
			function labelClick(self) {
				self._ui.input.blur();
				self._ui.input.focus();
			}

			/**
			 * Init widget on builded structure
			 * @method _init
			 * @param {HTMLElement} element
			 * @protected
			 * @member ns.widget.mobile.SearchBar
			 */
			SearchBar.prototype._init = function (element) {
				var ui;
				this._ui = this._ui || {};
				ui = this._ui;
				ui.input = element;
				ui.clearButton = document.getElementById(this.id + '-clear-button');
				ui.cancelButton = document.getElementById(this.id + '-cancel-button');
				ui.labelDiv = document.getElementById(this.id + '-label-div');
				ui.searchBox = document.getElementById(this.id + '-search-box');
			};

			/**
			* Bind events to widget
			* @method _bindEvents
			* @protected
			* @member ns.widget.mobile.SearchBar
			*/
			SearchBar.prototype._bindEvents = function () {
				var handlers,
					ui = this._ui,
					input = ui.input;
				this._handlers = this._handlers || {};
				handlers = this._handlers;
				handlers.clearClick = clearButtonClick.bind(null, this);
				handlers.cancelClick = cancelButtonClick.bind(null, this);
				handlers.inputFocus = inputFocus.bind(null, this);
				handlers.inputBlur = inputBlur.bind(null, this);
				handlers.labelClick = labelClick.bind(null, this);

				ui.clearButton.addEventListener("vclick", handlers.clearClick, false);
				if (ui.cancelButton) {
					ui.cancelButton.addEventListener("vclick", handlers.cancelClick, false);
				}
				input.addEventListener("focus", handlers.inputFocus, false);
				input.addEventListener("blur", handlers.inputBlur, false);
				if (ui.labelDiv) {
					ui.labelDiv.addEventListener("vclick", handlers.labelClick, false);
				}
			};

			/**
			 * Gets or sets value of input text.
			 *
			 * If you call with parameter then first argument will be set as new
			 * value of input text. Otherwise method return value of input.
			 *
			 *		@example
			 *		var searchBarElement = document.getElementById("searchbar"),
			 *			searchBarWidget = tau.widget.SearchBar(searchBarElement),
			 *			value = searchBarWidget.value();
			 *			// value contains inner text of button
			 *
			 *		buttonWidget.value( "New text" ); // "New text" will be text of button
			 *
			 *		// or
			 *
			 *		$( "#searchbar" ).searchbar( "value" );
			 *		// value contains inner text of button
			 *
			 *		$( "#searchbar" ).searchbar( "value", "New text" );
			 *		// "New text" will be value of input
			 *
			 * @method value
			 * @param {string} [value] Value to set on widget
			 * @return {string} In get mode return value of widget.
			 * @since 2.3
			 * @member ns.widget.mobile.SearchBar
			 */

			SearchBar.prototype.value = function (value) {
				if (value) {
					this._setValue(value);
					return;
				}
				return this._getValue();
			};

			/**
			 * Gets value for widget
			 * @method _getValue
			 * @protected
			 * @member ns.widget.mobile.SearchBar
			 */
			SearchBar.prototype._getValue = function () {
				return this.element.value;
			};

			/**
			 * Sets value for widget
			 * @param {HTMLElement} element base element of widget
			 * @param {string} value value to set
			 * @protected
			 * @member ns.widget.mobile.SearchBar
			 */
			SearchBar.prototype._setValue = function (value) {
				this.element.value = value;
			};

			/**
			 * Refresh method is not supported in this widget.
			 *
			 * @method refresh
			 * @chainable
			 * @member ns.widget.mobile.SearchBar
			 */

			/**
			 * Destroy method is not supported in this widget.
			 *
			 * @method refresh
			 * @chainable
			 * @member ns.widget.mobile.SearchBar
			 */
			ns.widget.mobile.SearchBar = SearchBar;
			engine.defineWidget(
				"SearchBar",
				"input[type='search'], [data-type='search'], [data-type='tizen-search'], .ui-searchbar",
				[
					"value"
				],
				SearchBar,
				"tizen"
			);
}(window.document, ns));

/*global window, define */
/*
* Copyright  2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/*jslint nomen: true, plusplus: true */
/**
 * #Filter Extension For ListView Widget
 * The filter widget extension adds possibility to filter elements on list.
 *
 * ## Default selectors
 * In default all ListView elements with _data-filter=true_ are changed to Tizen
 * Web UI Listview Filter.
 *
 *		@example
 *		<ul data-role="listview" data-filter="true">
 *			<li>Anton</li>
 *			<li>Arabella</li>
 *			<li>Barry</li>
 *			<li>Bily</li>
 *		</ul>
 *
 * #### Create Listview widget with filter using tau method:
 *
 *		@example
 *		<ul id="contacts" data-role="listview" data-filter="true">
 *			<li>Anton</li>
 *			<li>Arabella</li>
 *			<li>Barry</li>
 *			<li>Bily</li>
 *		</ul>
 *		<script>
 *			tau.widget.Listview(document.getElementById("contacts"), {
 *				filter: true
 *			});
 *		</script>
 *
 * ## Options
 *
 * ### Filter
 * _data-filter_ option set to true, creates a listview filter the HTML
 * unordered list (&lt;ul&gt;) element.
 *
 *		@example
 *		<ul id="contacts" data-role="listview" data-filter="true">
 *			<li>Anton</li>
 *			<li>Arabella</li>
 *			<li>Barry</li>
 *			<li>Bily</li>
 *		</ul>
 *
 * ### Filter Placeholder
 * _data-filter-placeholder_ option sets the placeholder for filter input field.
 *
 *		@example
 *		<ul id="contacts" data-role="listview" data-filter="true"
 *		data-placeholder="First name">
 *			<li>Anton</li>
 *			<li>Arabella</li>
 *			<li>Barry</li>
 *			<li>Bily</li>
 *		</ul>
 *
 * ### Filter Theme
 * _data-filter-theme_ option sets the search box theme
 *
 *		@example
 *		<ul id="contacts" data-role="listview" data-filter="true"
 *		data-filter-theme="s">
 *			<li>Anton</li>
 *			<li>Arabella</li>
 *			<li>Barry</li>
 *			<li>Bily</li>
 *		</ul>
 *
 * ### Filter Callback
 * This option allow to change the way in which list items are filtered
 *
 *		@example
 *		<ul id="contacts" data-role="listview">
 *			<li>Anton</li>
 *			<li>Arabella</li>
 *			<li>Barry</li>
 *			<li>Bily</li>
 *		</ul>
 *		<script>
 *			var element = document.getElementById("contacts"),
 *		  		listview = tau.widget.Listview(element, {filter: true});
 *
 *			function yourFilterFunction(text, searchValue, item) {
 *				return text.toString().toLowerCase().indexOf(searchValue) === -1;
 *			}
 *
 *			listview.option("filterCallback", yourFilterFunction);
 *		</script>
 *
 * ### Filter text
 * _data-filtertext_ To filter list items by values other than the text,
 * add a _data-filtertext_ attribute to the list item.
 * The value of this attribute will be passed as the first argument to the
 * filterCallback function instead of the text. Alternately you can use an
 * attribute of your choosing as defined on the list item itself.
 *
 *		@example
 *		<ul id="contacts" data-role="listview" data-filter="true">
 *			<li data-filtertext="Anton">Person</li>
 *			<li data-filtertext="Arabella">Person</li>
 *			<li>Barry</li>
 *			<li data-filtertext="Bily">Person</li>
 *		</ul>
 *
 * ## Events
 *
 * ### beforefilter
 * Triggered before the listview will be filtered.
 *
 *		@example
 *		<ul id="contacts" data-role="listview" data-filter="true">
 *			<li>Anton</li>
 *			<li>Arabella</li>
 *			<li>Barry</li>
 *			<li>Bily</li>
 *		</ul>
 *		<script>
 *			var element = document.getElementById("contacts"),
 *				list = tau.widget.Listview(element);
 *
 *			// add the event handler
 *			list.on("beforefilter", function (event) {
 *				// handle event
 *			});
 *		</script>
 *
 * Full list of available events is in [events list section](#events-list).
 *
 * ## Methods
 *
 * To call method on widget you can use tau API:
 *
 *		@example
 *		<ul id="contacts" data-role="listview" data-filter="true">
 *			<li>Anton</li>
 *			<li>Arabella</li>
 *			<li>Barry</li>
 *			<li>Bily</li>
 *		</ul>
 *		<script>
 *			var element = document.getElementById("contacts"),
 *				contacts = tau.widget.Listview(element);
 *
 *			// contacts.methodName(argument1, argument2, ...);
 *			// for example:
 *
 *			contacts.refresh();
 *
 *			// or JQueryMobile notation:
 *			// $(element).listview("methodName", argument1, argument2, ...);
 *			// for example:
 *
 *			$(element).listview("refresh");
 *		</script>
 *
 * @author Maciej Urbanski <m.urbanski@samsung.com>
 * @author Tomasz Lukawski <t.lukawski@samsung.com>
 * @class ns.widget.mobile.Listview.Filter
 * @override ns.widget.mobile.Listview
 */
(function (document, ns) {
	
				/**
			* Local alias for ns.event
			* @property {Object} events Alias for {@link ns.event}
			* @member ns.widget.mobile.Listview.Filter
			* @static
			* @private
			*/
			var events = ns.event,

				/**
				* Local alias for ns.engine
				* @property {Object} engine Alias for {@link ns.engine}
				* @member ns.widget.mobile.Listview.Filter
				* @static
				* @private
				*/
				engine = ns.engine,

				/**
				* Local alias for ns.util.DOM
				* @property {Object} DOM Alias for {@link ns.util.DOM}
				* @member ns.widget.mobile.Listview.Filter
				* @static
				* @private
				*/
				DOM = ns.util.DOM,

				/**
				* Local alias for ns.util.selectors
				* @property {Object} selectors Alias for {@link ns.util.selectors}
				* @member ns.widget.mobile.Listview.Filter
				* @static
				* @private
				*/
				selectors = ns.util.selectors,

				/**
				* @method defaultFilterCallback
				* @member ns.widget.mobile.Listview.Filter
				* @param {string} text
				* @param {string} searchValue
				* @return {boolean}
				* @static
				* @private
				*/
				defaultFilterCallback = function (text, searchValue) {
					return text.toString().toLowerCase().indexOf(searchValue) === -1;
				},

				/**
				* @property {Function} Listview Alias for class {@link ns.widget.mobile.Listview}
				* @member ns.widget.mobile.Listview.Filter
				* @static
				* @private
				*/
				Listview = ns.widget.mobile.Listview,

				/**
				* Backup of _build methods for replacing it
				* @method parent_build
				* @member ns.widget.mobile.Listview.Filter
				* @private
				*/
				parent_build = Listview.prototype._build,

				/**
				* Backup of _configure methods for replacing it
				* @method parent_configure
				* @member ns.widget.mobile.Listview.Filter
				* @private
				*/
				parent_configure = Listview.prototype._configure,

				/**
				* Backup of _init methods for replacing it
				* @method parent_init
				* @member ns.widget.mobile.Listview.Filter
				* @private
				*/
				parent_init = Listview.prototype._init,

				/**
				* Backup of _bindEvents methods for replacing it
				* @method parent_bindEvents
				* @member ns.widget.mobile.Listview.Filter
				* @private
				*/
				parent_bindEvents = Listview.prototype._bindEvents,

				/**
				* Backup of _destroy methods for replacing it
				* @method parent_destroy
				* @member ns.widget.mobile.Listview.Filter
				* @private
				*/
				parent_destroy = Listview.prototype._destroy,

				/**
				 * @property {Object} listviewClasses Alias for object ns.widget.mobile.Listview.classes
				 * @member ns.widget.mobile.Listview.Filter
				 * @static
				 * @private
				 * @property {string} uiListviewFilter Main class of listview filter
				 * @property {string} uiBarPrefix Class of bar prefix
				 * @property {string} uiListviewFilterInset Class of listview filter as inset
				 * @property {string} uiFilterHidequeue The working class for prepare items queue to hiding
				 */
				ListviewClasses = Listview.classes || {},

				/**
				 * @property {Object} eventType Listview event types
				 * @property {string} [eventType.DESTROYED="destroyed"] Event is triggering after _destroy method call.
				 * @static
				 * @readonly
				 * @member ns.widget.mobile.Listview.Filter
				 */
				eventType = Listview.eventType || {},

				/**
				 * @property {string} [TYPE_FUNCTION="function"] local cache of function type name
				 * @private
				 * @static
				 * @member ns.widget.mobile.Listview.Filter
				 */
				TYPE_FUNCTION = "function";

			/**
			 * Prepare default configuration of listview widget
			 * @method _configure
			 * @member ns.widget.mobile.Listview.Filter
			 * @protected
			 */
			Listview.prototype._configure = function Listview_configure() {
				var options;
				if (typeof parent_configure === TYPE_FUNCTION) {
					parent_configure.call(this);
				}

				/**
				 * @property {Object} options Object with default options
				 * @property {boolean} [options.filter=false] Sets if filter should be enabled.
				 * @property {string} [options.filterPlaceholder=""] Sets a place holder.
				 * @property {string} [options.filterTheme="c"] Sets a theme for listview filter.
				 * @property {Function} [options.filterCallback] Sets a custom filter method
				 * @member ns.widget.mobile.Listview.Filter
				 */
				this.options = this.options || {};
				options = this.options;

				options.filter = false;
				options.filterPlaceholder = "";
				options.filterTheme = "c";
				options.filterCallback = defaultFilterCallback;
			};

			// the extension of Listview events dictionary
			/*
			 * Event is triggering after _destroy method call
			 * @event beforefilter
			 * @member ns.widget.mobile.Listview.Filter
			 */
			eventType.BEFORE_FILTER = "beforefilter";

			// the extension of Listview classes
			ListviewClasses.uiListviewFilter = "ui-listview-filter";
			ListviewClasses.uiBarPrefix = "ui-bar-";
			ListviewClasses.uiListviewFilterInset = "ui-listview-filter-inset";
			ListviewClasses.uiFilterHidequeue = "ui-filter-hidequeue";

			/**
			* Initialize filter features on Listview
			* Override method "_build" from Listview & call the protected "_build"
			* @method _build
			* @member ns.widget.mobile.Listview.Filter
			* @param {HTMLUListElement|HTMLOListElement} element bound UList or OList HTMLElement.
			* @return {HTMLUListElement|HTMLOListElement}
			* @protected
			*/
			Listview.prototype._build = function Listview_build(element) {
				var wrapper,
					wrapperClass,
					search,
					options = this.options,
					classes = Listview.classes,
					id = this.id;

				parent_build.call(this, element);

				if (options.filter) {
					wrapper = document.createElement("form");

					wrapper.setAttribute("id", id + "-form");

					wrapperClass = wrapper.classList;
					wrapperClass.add(classes.uiListviewFilter);
					wrapperClass.add(classes.uiBarPrefix + options.filterTheme);

					if (options.inset) {
						wrapperClass.add(classes.uiListviewFilterInset);
					}

					search = document.createElement("input");
					search.setAttribute("placeholder", options.filterPlaceholder);
					search.setAttribute("type", "search");
					search.setAttribute("id", id + "-search");

					DOM.setNSData(search, "lastval", "");

					wrapper.appendChild(search);

					DOM.insertNodesBefore(element, wrapper);
					engine.instanceWidget(search, "SearchBar");
				}
				return element;
			};

			/**
			 * Handle method event for change of the filter input field
			 * @param {ns.widget.mobile.Listview} self instance of listview widget
			 * @param {Event} event triggered event
			 * @member ns.widget.mobile.Listview.Filter
			 * @static
			 * @private
			 */
			function inputChangeHandler(self, event) {
				var search = event.target,
					val = search.value.toLowerCase(),
					listItems = null,
					lastval = DOM.getNSData(search, "lastval") || "",
					childItems = false,
					itemtext = "",
					item,
					// Check if a custom filter callback applies
					isCustomFilterCallback = self.options.filterCallback !== defaultFilterCallback,
					list = self.element,
					classes = Listview.classes,
					i,
					slice = [].slice;

				events.trigger(list, eventType.BEFORE_FILTER, { input: search });

				// Change val as lastval for next execution
				DOM.setNSData(search, "lastval", val);
				if (val) {
					if (isCustomFilterCallback || val.length < lastval.length || val.indexOf(lastval) !== 0) {
						// Custom filter callback applies or removed chars or pasted something totally different, check all items
						listItems = slice.call(list.children);
					} else {
						// Only chars added, not removed, only use visible subset
						listItems = slice.call(selectors.getChildrenBySelector(list, ":not(.ui-screen-hidden)"));
					}
					// This handles hiding regular rows without the text we search for
					// and any list dividers without regular rows shown under it
					for (i = listItems.length - 1; i >= 0; i--) {
						item = listItems[i];

						itemtext =  DOM.getNSData(item, "filtertext") || item.innerText;

						if (DOM.getNSData(item, "role") === "list-divider") {
							if (childItems) {
								item.classList.remove(classes.uiFilterHidequeue);
							} else {
								item.classList.add(classes.uiFilterHidequeue);
							}
							// New bucket!
							childItems = false;
						} else if (self.options.filterCallback(itemtext, val, item)) {
							//mark to be hidden
							item.classList.add(classes.uiFilterHidequeue);
						} else {
							// There's a shown item in the bucket
							childItems = true;
						}
					}
					// Hide elements which marked to hide
					listItems.forEach(function (item) {
						var itemClassList = item.classList;
						if (itemClassList.contains(classes.uiFilterHidequeue)) {
							itemClassList.add("ui-screen-hidden");
							itemClassList.remove(classes.uiFilterHidequeue);
						} else {
							itemClassList.remove("ui-screen-hidden");
						}
					});
				} else {
					slice.call(list.children).forEach(function (item) {
						item.classList.remove("ui-screen-hidden");
					});
				}
				// @todo self._refreshCorners(); this trigger should move to refreshCorners
				events.trigger(self.element, "updatelayout");
			}

			/**
			 * @param {Event} event
			 * @method preventDefault
			 * @private
			 * @static
			 */
			function preventDefault(event) {
				events.preventDefault(event);
				events.stopPropagation(event);
			}

			/**
			 * Initialize properties of widget
			 * Override method "_init" from Listview & call the protected "_init"
			 * @method _init
			 * @param {HTMLUListElement|HTMLOListElement} element bound UList or OList HTMLElement.
			 * @return {HTMLUListElement|HTMLOListElement}
			 * @member ns.widget.mobile.Listview.Filter
			 * @protected
			 */
			Listview.prototype._init = function Listview_init(element) {
				var id = element.id;

				this._ui = this._ui || {};
				this._ui.form = document.getElementById(id + "-form");
				this._ui.search = document.getElementById(id + "-search");

				if (typeof parent_init === TYPE_FUNCTION) {
					parent_init.call(this, element);
				}

				return element;
			};

			/**
			 * Bind events to HTML elements
			 * Override method "_bindEvents" from Listview & call the protected "_bindEvents"
			 * @method _bindEvents
			 * @param {HTMLUListElement|HTMLOListElement} element bound UList or OList HTMLElement.
			 * @return {HTMLUListElement|HTMLOListElement}
			 * @member ns.widget.mobile.Listview.Filter
			 * @protected
			 */
			Listview.prototype._bindEvents = function Listview_bindEvents(element) {
				var search = this._ui.search;
				parent_bindEvents.call(this, element);

				if (search) {
					this._inputChangeHandler = inputChangeHandler.bind(null, this);
					search.addEventListener("keyup", this._inputChangeHandler, false);
					search.addEventListener("change", this._inputChangeHandler, false);
					document.addEventListener("submit", preventDefault, true);
				}
			};

			/**
			 * Removing and cleaning filter extension
			 * Override method "_destroy" from Listview & call the protected "_destroy"
			 * @method _destroy
			 * @member ns.widget.mobile.Listview.Filter
			 * @protected
			 */
			Listview.prototype._destroy = function Listview_destroy() {
				var search = this._ui.search;
				if (search) {
					search.removeEventListener("keyup", this._inputChangeHandler, false);
					search.removeEventListener("change", this._inputChangeHandler, false);
					document.removeEventListener("submit", preventDefault, true);
				}
				// call protected method from Listview;
				if (typeof parent_destroy === TYPE_FUNCTION) {
					parent_destroy.call(this);
				}
			};
			}(window.document, ns));

/*global window, define, ns, $ */
/*
* Copyright  2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/*jslint nomen: true, white: true, plusplus: true*/
/**
 * #Extendable List Widget
 * The Extendable List is used to display a list of data elements that can be extended.
 *
 * ## Default selectors
 * **UL** tags with _data-role=extendablelist_ attribute. However most of required options has to be passed as Java Script object.
 * Widget has to be created manually.
 *
 * ###HTML Examples
 *
 * ####Create basic Extendable List
 *
 *		@example
 *		<ul id="widgetIdSelector" data-role="extendablelist"></ul>
 *
 *		<script>
 *			var config = {
 *				// NOTE: JSON_DATA is an object which holds all records that you want to load
 *				// Declare total number of items
 *				dataLength: JSON_DATA.length,
 *
 *				// Set list item updater
 *				listItemUpdater: function (processedIndex, listItem) {
 *					var data = JSON_DATA[processedIndex];
 *					listItem.textContent = data.NAME;
 *				},
 *
 *				// Set list item loader
 *				listItemLoader: function (loaderContainer, numMoreItems) {
 *					// Get loader element
 *					loaderContainer.textContent= 'Load ' + numMoreItems + ' more items';
 *				}
 *			};
 *
 *			// Create widget using TAU notation ...
 *			tau.widget.ExtendableList(document.getElementById("widgetIdSelector"), config).create();
 *
 *			// ... or using jQM notation
 *			$( "#widgetIdSelector" ).extendablelist( config );
 *		</script>
 *
 * ####Create basic Extendable List with custom loader item
 * To set custom loader element add one **li** element to list markup. If no element will be provided, widget will create it automatically.
 * Loader element is always passed as first (**loaderContainer**) argument while calling **listItemLoader** function.
 *
 *		@example
 *		<ul id="widgetIdSelector" data-role="extendablelist">
 *			<!-- Declaration of custom loader item -->
 *			<li class="custom-class"></li>
 *		</ul>
 *
 *		<script>
 *			var config = {
 *				// NOTE: JSON_DATA is an object which holds all records that you want to load
 *				// Declare total number of items
 *				dataLength: JSON_DATA.length,
 *
 *				// Set list item updater
 *				listItemUpdater: function (processedIndex, listItem) {
 *					var data = JSON_DATA[processedIndex];
 *					listItem.textContent = data.NAME;
 *				},
 *
 *				// Set list item loader
 *				listItemLoader: function (loaderContainer, numMoreItems) {
 *					// Get loader element
 *					loaderContainer.textContent= 'Load ' + numMoreItems + ' more items';
 *				}
 *			};
 *
 *			// Create widget using TAU notation ...
 *			tau.widget.ExtendableList(document.getElementById("widgetIdSelector"), config)
 *				.create();
 *
 *			// ... or using jQM notation
 *			$( "#widgetIdSelector" ).extendablelist( "create", config );
 *		</script>
 *
 * ####Create Extendable List using jQuery Template
 * Extendable List supports jQuery Template, for further information about **jQuery.template plugin** you can find in jQuery documentation for jQuery.template plugin.
 * To switch widget in template mode _data-template_ attribute must be set or template option must be passed.
 * **NOTE:** This feature is available but not recommended due performance issue and abandoned library jQuery Template support. It will be probably replaced by more efficient template system.
 *
 *		@example
 *		<!-- Template for list item -->
 *		<script id="tmp-1line" type="text/x-jquery-tmpl">
 *			<li class="my-custom-class">${NAME}</li>
 *		</script>
 *
 *		<!-- Template for loader -->
 *		<script id="tmp_load_more" type="text/x-jquery-tmpl">
 *			<li class="my-custom-loader-class">
 *				Load ${NUM_MORE_ITEMS} more items
 *			</li>
 *		</script>
 *
 *		<ul id="widgetIdSelector" data-role="extendablelist" data-template="tmp-1line"></ul>
 *		<script>
 *			var config = {
 *				// You can use itemData property, which is equivalent to listItemUpdater,
 *				// but it's deprecated and kept only for compatibility with old Web UI Framework.
 *				// Set list item updater for jQ template
 *				listItemUpdater: function (idx) {
 *					return JSON_DATA[idx];
 *				},
 *				// JSON_DATA is an object which holds all records that you want to load
 *				// You can use numitemdata property, which is equivalent to dataLength,
 *				// but it's deprecated and kept only for compatibility with old Web UI Framework.
 *				// Declare total number of items
 *				dataLength: JSON_DATA.length
 *			};
 *
 *			// Create widget using TAU notation
 *			tau.widget.ExtendableList(document.getElementById("widgetIdSelector"), config)
 *				.create();
 *
 *			// ... or using jQM notation
 *			$( "#widgetIdSelector" ).extendablelist( "create", config );
 *		</script>
 *
 *
 * #### Setting listItemUpdater option
 * List item updater function is called for every processed list element. There are two types of updater function. If there is **not** used jQuery Template mode updater should takes two arguments (processed index, list item element). otherwise function should return object and takes only one argument(processed index). Please check example for details.
 *
 * ##### Setting listItemUpdater in normal mode
 * List item updater function should takes **two parameters** when using non jQuery Template mode:
 * - **processedIndex** {number} Index of processed data set (zero based),
 * - **element** {HTMLElement} Current processed list item.
 *
 *		@example
 *		<script>
 *			var myNewListItemUpdater = function (processedIndex, listItem) {
 *				// JSON_DATA is an object which holds all records that you want to load
 *				var data = JSON_DATA[processedIndex];
 *				// Do some crazy things with listItem
 *				listItem.textContent = data.NAME;
 *				if (Math.round(Math.random()) === 1) {
 *					listItem.classList.add('crazy-class');
 *				}
 *			}
 *			// Create widget using TAU notation ...
 *			tau.widget.ExtendableList(document.getElementById("widgetIdSelector"))
 *				.option("listItemUpdater", myNewListItemUpdater);
 *
 *			// ... or using jQM notation
 *			$( "#widgetIdSelector" ).extendablelist( "option", "listItemUpdater", myNewListItemUpdater );
 *		</script>
 *
 *
 * ##### Setting listItemUpdater in jQuery Template mode
 * Using **jQuery Template** mode list item updater function should takes **one parameter** and returns an Object:
 * - **processedIndex** {number} Index of processed data set (zero based).
 *
 *		@example
 *		<script>
 *			var myTemplateListItemUpdater = function (processedIndex) {
 *				// JSON_DATA is an object which holds all records that you want to load
 *				return JSON_DATA[processedIndex];
 *			}
 *			// Create widget using TAU notation ...
 *			tau.widget.ExtendableList(document.getElementById("templateWidgetIdSelector"))
 *				.option("listItemUpdater", myTemplateListItemUpdater);
 *
 *			// ... or using jQM notation
 *			$( "#templateWidgetIdSelector" ).extendablelist( "option", "listItemUpdater", myTemplateListItemUpdater );
 *		</script>
 *
 *
 * @class ns.widget.mobile.ExtendableList
 * @extends ns.widget.mobile.Listview
 * @author Michał Szepielak <m.szepielak@samsung.com>
*/
(function(document, ns) {
	
				/**
			 * @property {ns.widget.mobile.Listview} Listview alias variable
			 * @private
			 * @static
			 */
			var Listview = ns.widget.mobile.Listview,

				/**
				 * @property {Object} parent_build Shortcut for parent's {@link ns.widget.mobile.Listview#_build}
				 * method from prototype of {@link ns.widget.mobile.Listview}
				 * @private
				 * @static
				 * @member ns.widget.mobile.ExtendableList
				 */
				parent_build = Listview.prototype._build,

				/**
				 * @property {Object} engine Alias for class {@link ns.engine}
				 * @private
				 * @static
				 * @member ns.widget.mobile.ExtendableList
				 */
				engine = ns.engine,

				/**
				 * @property {Object} util Alias for class {@link ns.util}
				 * @private
				 * @static
				 * @member ns.widget.mobile.ExtendableList
				 */
				util = ns.util,

				ExtendableList = function() {
					var self = this;

					/**
					 * @property {number} _currentIndex Current zero-based index of data set.
					 * @member ns.widget.mobile.ExtendableList
					 * @protected
					 */
					self._currentIndex = 0;

					/**
					 * @property {Object} options ExtendableList widget options.
					 * @property {?number} [options.bufferSize=null] Maximum number of items which will be loaded on widget startup and after each extension.
					 * @property {?number} [options.extenditems=null] Alias for bufferSize to preserve compatibility with Web UI Framework (deprecated)
					 * @property {number} options.dataLength Total number of list items.
					 * @property {number} options.numitemdata Alias for dataLength to preserve compatibility with Web UI Framework (deprecated)
					 * @property {Function} options.listItemUpdater Holds reference to method which modifies list items depended at specified index from database. <br>Method <b>should be overridden</b> by developer using <a href="#_setListItemUpdater">_setListItemUpdater</a> method or defined as a config object. <br>Method takes two parameters:<br>  -  index {number} Index of processed data set (zero based)<br> -  element {HTMLElement} List item to be modified (only non jQuery Template mode)
					 * @property {?Function} [options.itemData=null] Alias for listItemUpdater to preserve compatibility with Web UI Framework (deprecated)
					 * @property {Function} options.listItemLoader Holds reference to method which modifies loader item. <br>Method <b>should be overridden</b> by developer using <a href="#setListItemLoader">setListItemLoader</a> method or defined as a config object. <br>Method takes two parameters:<br>  -  loaderContainer {HTMLElement} Loader container, list element that holds e.g. extend button. If all elements will be loaded, this element will be removed from list.<br>  -  numMoreItems {number} Number of items, that left to load.
					 * @property {string} [options.loadmore="tmp_load_more"] Load more container jQuery Template's ID
					 * @property {string} options.template List item jQuery Template's ID. If this option is not **null** widget will work in jQuery Template mode.
					 * @member ns.widget.mobile.ExtendableList
					 */
					self.options = {
						bufferSize: 50,
						extenditems: null,
						dataLength: 0,
						numitemdata: 0,
						listItemUpdater: null,
						itemData: null,
						listItemLoader: null,
						loadmore: 'tmp_load_more',
						template: null
					};

					//@TODO jQuery template, change to better template system
					self._jQueryTmpl = false;
					self.$tmpl = {};

					/**
					 * @property {Object} _listItemLoaderBound Binding for loader item to fire method {ns.widget.mobile.ExtendableList._buildList}.
					 * @member ns.widget.mobile.ExtendableList
					 * @protected
					 */
					self._listItemLoaderBound = null;
				},

				/**
				 * @property {Object} classes Dictionary object containing commonly used widget CSS classes
				 * @static
				 * @member ns.widget.mobile.ExtendableList
				 */
				classes = {
					CONTAINER: "ui-extendable-list-container",
					ACTIVE: "ui-listview-active"
				},
				// Cached prototype for better minification
				prototype = new Listview();

			/**
			 * Copy alias options from old Web UI notation
			 * @param {ns.widget.mobile.ExtendableList} self Widget instance
			 * @private
			 * @static
			 * @member ns.widget.mobile.ExtendableList
			 */
			function copyAliases(self, newOptions) {
				var options = self.options;

				if (newOptions === undefined) {
					newOptions = options;
				}

				if (newOptions.extenditems || options.extenditems) {
					options.bufferSize = parseInt(newOptions.extenditems, 10) || parseInt(options.extenditems, 10);
				}

				if (newOptions.numitemdata || options.numitemdata) {
					options.dataLength = parseInt(newOptions.numitemdata, 10) || parseInt(options.numitemdata, 10);
				}

				if (newOptions.itemData || options.itemData) {
					options.listItemUpdater = newOptions.itemData || options.itemData;
				}
			}

			/**
			 * Unbinds vclick event from loader element.
			 * @param {ns.widget.mobile.ExtendableList} self Widget instance
			 * @param {HTMLElement} loaderItem Loader element
			 * @private
			 * @static
			 * @member ns.widget.mobile.ExtendableList
			 */
			function _unbindLoader(self, loaderItem) {
				if (self._listItemLoaderBound !== null) {
					loaderItem.removeEventListener('vclick', self._listItemLoaderBound, false);
				}
				self._listItemLoaderBound = null;
			}

			/**
			 * Binds vclick event to loader element.
			 * @param {ns.widget.mobile.ExtendableList} self Widget instance
			 * @param {HTMLElement} loaderItem Loader element
			 * @private
			 * @static
			 * @member ns.widget.mobile.ExtendableList
			 */
			function _bindLoader(self, loaderItem) {
				if (loaderItem) {
					_unbindLoader(self, loaderItem);
					self._listItemLoaderBound = self._buildList.bind(self);
					loaderItem.addEventListener('vclick', self._listItemLoaderBound, false);
				}
			}

			/**
			 * Updates list item using user defined listItemUpdater function.
			 * @method _updateListItem
			 * @param {HTMLElement} element List element to update
			 * @param {number} index Data row index
			 * @member ns.widget.mobile.ExtendableList
			 * @protected
			 */
			prototype._updateListItem = function (element, index) {
				var self = this,
					listItemUpdater = self.options.listItemUpdater;

				//@TODO jQuery template, change for better template system
				if (self._jQueryTmpl === true) {
					// Call list item updater and set list item content
					element.outerHTML = self.$tmpl.item.tmpl(listItemUpdater(index))[0].outerHTML;
				} else {
					// Call list item updater
					listItemUpdater(index, element);
				}
			};

			/**
			 * Build widget structure
			 * @method _build
			 * @param {HTMLElement} element Widget's element
			 * @return {HTMLElement} Element on which built is widget
			 * @member ns.widget.mobile.ExtendableList
			 * @protected
			 */
			prototype._build = function (element) {
				var self = this;

				//Call parent's method
				parent_build.call(self, element);

				// Add necessary CSS Classes
				element.classList.add(classes.CONTAINER);

				return element;
			};

			/**
			 * Builds widget list structure. Creates all list items and updates it using updater method.
			 * @method _buildList
			 * @member ns.widget.mobile.ExtendableList
			 * @protected
			 */
			prototype._buildList = function() {
				var listItem,
					self = this,
					list = self.element,
					options = self.options,
					bufferSize = options.bufferSize,
					dataLength = options.dataLength - 1, // Indexes are 0 based
					numberOfItems,
					currentIndex = self._currentIndex,
					loaderItem = null,
					i;

				// Get loader item if exists or create new one
				loaderItem = list.lastElementChild || document.createElement("li");

				// Get number of items to load
				numberOfItems = currentIndex + bufferSize > dataLength ? dataLength - currentIndex : bufferSize;

				// Load additional items
				for (i = 0; i < numberOfItems; ++i) {
					listItem = document.createElement("li");
					// To copy all element's attributes we use outerHTML property,
					// that's why we should not be appended to document fragment,
					// due document fragment is not an element node
					list.appendChild(listItem);
					self._updateListItem(listItem, i + currentIndex);

				}

				// Update current Index
				currentIndex += numberOfItems;

				// Get number of items to load for next time
				numberOfItems = currentIndex + bufferSize > dataLength ? dataLength - currentIndex : bufferSize;

				if (numberOfItems > 0) {
					// Update loader
					//@TODO jQuery template, change for better template system
					if (self._jQueryTmpl === true) {
						// Remove current loader to swap with new one
						if (loaderItem.parentNode) {
							loaderItem.parentNode.removeChild(loaderItem);
						}

						loaderItem = self.$tmpl.more.tmpl({ "NUM_MORE_ITEMS" : numberOfItems })[0];
					} else {
						options.listItemLoader(loaderItem, numberOfItems);
					}
					_bindLoader(self, loaderItem);

					// Add loader item or move it on end of the list if it's already appended.
					list.appendChild(loaderItem);
				} else {
					// Remove loader item node
					if (loaderItem.parentElement) {
						loaderItem.parentElement.removeChild(loaderItem);
						_unbindLoader(self, loaderItem);
					}
					loaderItem = null;
				}

				self._currentIndex = currentIndex;

				// Refresh widget
				self._refresh();
			};

			/**
			 * Configure widget in normal mode - using user defined method for item update.
			 * @method _configureNormal
			 * @param {Object} config Configuration options {@link ns.widget.mobile.ExtendableList#options}
			 * @protected
			 * @member ns.widget.mobile.ExtendableList
			 */
			prototype._configureNormal = function (config) {
				var options = this.options;

				if (util.isNumber(config.dataLength)) {
					options.dataLength = config.dataLength;
				}

				if (util.isNumber(config.bufferSize)) {
					options.bufferSize = config.bufferSize;
				}

				if (typeof config.listItemLoader === 'function') {
					options.listItemLoader = config.listItemLoader;
				}

				if (typeof config.listItemUpdater === 'function') {
					options.listItemUpdater = config.listItemUpdater;
				}
			};

			//@TODO jQuery template, change for better template system
			/**
			 * Configure widget in jQuery Template mode and grab template.
			 * Probably this method will be deprecated in future
			 * due to change for better template system.
			 * @method _configureTemplate
			 * @param {Object} config Configuration options {@link ns.widget.mobile.ExtendableList#options}
			 * @protected
			 * @member ns.widget.mobile.ExtendableList
			 */
			prototype._configureTemplate = function (config) {
				var self = this,
					$tmpl = self.$tmpl,
					options = self.options;

				// Set jQueryTmpl mode
				//@TODO jQuery template, change to better template system
				self._jQueryTmpl = true;

				copyAliases(self, config);

				// Assign templates
				// NOTE: jQuery is used here!
				$tmpl.item = $('#' + options.template);
				$tmpl.more = $('#' + options.loadmore);

				self._configureNormal(config);
			};


			/**
			 * Creates Extendable List with provided options. For more information of usage please check HTML Examples section.
			 *
			 *	@example
			 *	<script>
			 *		var widget = tau.widget.ExtendableList(document.getElementById("widgetIdSelector")),
			 *			config = {
			 *				// Create with custom list item updater
			 *				listItemUpdater: function (processedIndex, listItem) {
			 *					var data = JSON_DATA[processedIndex];
			 *					listItem.textContent = data.NAME;
			 *				},
			 *				bufferSize: 20,
			 *				dataLength: 500
			 *			};
			 *
			 *		widget.create();
			 *
			 *		// or using jQuery Mobile
			 *
			 *		$( "#widgetIdSelector" ).extendablelist( "create", config );
			 *	</script>
			 *
			 * @method create
			 * @param  config Configuration options {@link ns.widget.mobile.ExtendableList#options}
			 * @member ns.widget.mobile.ExtendableList
			 */
			prototype.create = function(config) {
				var self = this,
					options = self.options;

				if (!config) {
					config = options;
				}

				self._destroy();

				//@TODO jQuery template, change for better template system
				if (config.template || options.template) {
					self._configureTemplate(config);
				} else {
					copyAliases(self);
					self._configureNormal(config);
				}

				// Make sure, that buffer size is not bigger than number of provided records
				if (options.dataLength < options.bufferSize) {
					options.bufferSize = options.dataLength - 1;
				}

				// Make sure that buffer size has at least one element
				if (options.bufferSize < 1) {
					options.bufferSize = 1;
				}

				// Build first part of list
				self._buildList();
			};

			/**
			 * Initialize widget on an element.
			 * @method _init
			 * @param {HTMLElement} element Widget's element
			 * @member ns.widget.mobile.ExtendableList
			 * @protected
			 */
			prototype._init = function(element) {
				var self = this;

				// Set current index to first element
				self._currentIndex = 0;

				// Assign variables to members
				self.element = element;
			};

			/**
			 * Refresh a ExtendableList list elements.
			 *
			 * This method should be called after are manually change in HTML attributes of widget DOM structure.
			 *
			 * This method is called automatically after extending list with new list positions.
			 *
			 *	@example
			 *	<script>
			 *		var widget = tau.widget.ExtendableList(document.getElementById("widgetIdSelector"));
			 *		widget.refresh();
			 *
			 *		// or
			 *
			 *		$( "#widgetIdSelector" ).extendablelist( "refresh" );
			 *	</script>
			 *
			 * @method refresh
			 * @param {boolean} [create=false] Sets create flag to refresh Listview in create mode. For more
			 * details check {@link ns.widget.mobile.Listview#refresh}.
			 * @chainable
			 * @member ns.widget.mobile.ExtendableList
			 */

			/**
			 * Refresh list
			 * @method _refresh
			 * @param {boolean} [create=false] Sets create flag to refresh Listview in create mode. For more
			 * details check {@link ns.widget.mobile.Listview#refresh}.
			 * @member ns.widget.mobile.ExtendableList
			 * @protected
			 */
			prototype._refresh = function(create) {
				// Create not built widgets
				engine.createWidgets(this.element);
				// Calling NOT overridden parent's method
				this._refreshItems(this.element, !!create);
			};

			/**
			 * Binds ExtendableList events
			 * @method _bindEvents
			 * @member ns.widget.mobile.ExtendableList
			 * @protected
			 */
			prototype._bindEvents = function() {
				var self = this;

				_bindLoader(self, self.element.lastElementChild);
			};

			/**
			 * Cleans widget's resources and removes all child elements.
			 *
			 *	@example
			 *	var widget = tau.widget.ExtendableList(document.getElementById("widgetIdSelector"));
			 *	widget.destroy();
			 *
			 *	// or using jQuery Mobile
			 *
			 *	$( "#widgetIdSelector" ).extendablelist( "destroy" );
			 * @method destroy
			 * @member ns.widget.mobile.ExtendableList
			 */

			/**
			 * @method _destroy
			 * @member ns.widget.mobile.ExtendableList
			 * @protected
			 */
			prototype._destroy = function() {
				var self = this,
					element = self.element,
					listItem,
					loaderItem = element.lastElementChild;

				_unbindLoader(self, loaderItem);

				//Remove li elements.
				while (element.firstElementChild) {
					listItem = element.firstElementChild;
					listItem = element.firstElementChild;
					element.removeChild(listItem);
				}
				self._currentIndex = 0;

			};

			/**
			 * Recreates widget with new data set and resets list item updater. This function is used only in jQuery Template mode.
			 * This function is still available to keep Web UI Framework compatibility and will be removed with new version of TAU
			 *
			 *	@example
			 *	<script>
			 *		var widget = tau.widget.ExtendableList(document.getElementById("widgetIdSelector")),
			 *		// loadData should return an array.
			 *		newDataSource = loadData() || [];
			 *
			 *		widget.recreate(newDataSource);
			 *
			 *		// or using jQuery Mobile
			 *
			 *		$( "#widgetIdSelector" ).extendablelist( "recreate", newDataSource );
			 *	</script>
			 *
			 * @method recreate
			 * @param {Array} newDataSource An array with new records for displayed list.
			 * @deprecated 2.3
			 * @member ns.widget.mobile.ExtendableList
			 */
			prototype.recreate = function(newDataSource){
				return this.create({
					itemData: function (idx) { return newDataSource[idx]; },
					numitemdata: newDataSource.length
				});
			};


			/**
			 * Sets list item updater function. List item updater function is called for every processed list element.
			 * There are two types of updater function. If there is **not** used jQuery Template mode updater should takes
			 * two arguments (processed index, list item element). otherwise function should return object and takes
			 * only one argument(processed index). Please check examples for details.
			 *
			 * @method _setListItemUpdater
			 * @param {HTMLElement} element Widget's HTML element
			 * @param {Function} updateFunction Function reference.
			 * @protected
			 * @member ns.widget.mobile.ExtendableList
			 */
			prototype._setListItemUpdater = function(element, updateFunction) {
				this.options.listItemUpdater = updateFunction;
			};

			/**
			 * Sets list item loader function. List item loader is always called after adding items process is finished. Please check examples for details.
			 * @method _setListItemLoader
			 * @param {HTMLElement} element Widget's HTML element
			 * @param {Function} updateFunction Function reference.
			 * @protected
			 * @member ns.widget.mobile.ExtendableList
			 */
			prototype._setListItemLoader = function(element, loadFunction) {
				this.options.listItemLoader = loadFunction;
			};

			ExtendableList.classes = classes;

			// Assign prototype
			ExtendableList.prototype = prototype;

			// definition
			ns.widget.mobile.ExtendableList = ExtendableList;

			engine.defineWidget(
				"ExtendableList",
				"[data-role='extendablelist'], .ui-extendablelist",
				["recreate", "create"],
				ExtendableList,
				"tizen"
			);


			}(window.document, ns));

/*global window, define */
/*
* Copyright  2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/*jslint nomen: true, plusplus: true */
/**
 * #Tab Bar Widget
 * The tabbar widget shows an unordered list of buttons on the screen wrapped
 * together in a single group.
 *
 * This widget can be placed in the header or footer of page.
 *
 * ## Default selectors
 * In default elements matches to :
 *
 *  - HTML elements with data-role="tabbar"
 *  - HTML elements with class ui-tabbar
 *
 * ###HTML Examples
 *
 * ####Create simple tab bar in header
 *
 *		@example
 *		<div data-role="page">
 *			<div data-role="header">
 *				<div data-role="tabbar">
 *					<ul>
 *						<li><a data-icon="naviframe-edit">Tabbar1</a></li>
 *						<li><a data-icon="naviframe-cancel">Tabbar2</a></li>
 *						<li><a data-icon="naviframe-call">Tabbar3</a></li>
 *					</ul>
 *				</div>
 *			</div>
 *			<div data-role="content">
 *				Content
 *			</div>
 *		</div>
 *
 * ####Create simple tab bar in footer
 *
 *		@example
 *		<div data-role="page">
 *			<div data-role="content">
 *			 	Content
 *			</div>
 *			<div data-role="footer">
 *				<div data-role="tabbar">
 *					<ul>
 *						<li><a data-icon="naviframe-edit">Tabbar1</a></li>
 *						<li><a data-icon="naviframe-cancel">Tabbar2</a></li>
 *						<li><a data-icon="naviframe-call">Tabbar3</a></li>
 *					</ul>
 *				</div>
 *			</div>
 *		</div>
 *
 * ## Manual constructor
 * For manual creation of search bar widget you can use constructor of widget from
 * **tau** namespace:
 *
 *		@example
 *		<div data-role="page" id="tab-bar-page">
 *			<div data-role="header">
 *				<div id="ready-for-tab-bar">
 *					<ul>
 *						<li><a data-icon="naviframe-edit">Tabbar1</a></li>
 *						<li><a data-icon="naviframe-cancel">Tabbar2</a></li>
 *						<li><a data-icon="naviframe-call">Tabbar3</a></li>
 *					</ul>
 *				</div>
 *			</div>
 *			<div data-role="content">
 *			 	Content
 *			</div>
 *		</div>
 *		<script>
 *			(function (document) {
 *				var pageElement = document.getElementById("tab-bar-page"),
 *					tabBarElement = document.getElementById("ready-for-tab-bar"),
 *					tabBar;
 *
 *				function createPageHandle() {
 *					tabBar = tau.widget.TabBar(tabBarElement);
 *				}
 *
 *				pageElement.addEventListener("pagecreate", createPageHandle);
 *			}(document));
 *		</script>
 *
 * Constructor has one require parameter **element** which are base
 * **HTMLElement** to create widget. We recommend get this element by method
 * *document.getElementById*. Second parameter is **options** and it is a object
 * with options for widget.
 *
 * If jQuery library is loaded, its method can be used:
 *
 *		@example
 *		<div data-role="page" id="tab-bar-page">
 *			<div data-role="header">
 *				<div id="ready-for-tab-bar">
 *					<ul>
 *						<li><a data-icon="naviframe-edit">Tabbar1</a></li>
 *						<li><a data-icon="naviframe-cancel">Tabbar2</a></li>
 *						<li><a data-icon="naviframe-call">Tabbar3</a></li>
 *					</ul>
 *				</div>
 *			</div>
 *			<div data-role="content">
 *			 	Content
 *			</div>
 *		</div>
 *		<script>
 *			(function (document) {
 *				function createPageHandle() {
 *					$("#ready-for-tab-bar").tabbar();
 *				}
 *
 *				$("#tab-bar-page").on("pagecreate", createPageHandle);
 *			}(document));
 *		</script>
 *
 * jQuery Mobile constructor has one optional parameter is **options** and it is
 * a object with options for widget.
 *
 * ##Options for tab bar widget
 *
 * Options for widget can be defined as _data-..._ attributes or give as
 * parameter in constructor.
 *
 * You can change option for widget using method **option**.
 *
 * ##Methods
 *
 * To call method on widget you can use one of existing API:
 *
 * First API is from tau namespace:
 *
 *		@example
 *		<script>
 *		var tabBarElement = document.getElementById('tab-bar'),
 *			tabBar = tau.widget.TabBar(TabBarElement);
 *
 *		tabBar.methodName(methodArgument1, methodArgument2, ...);
 *		</script>
 *
 * Second API is jQuery Mobile API and for call _methodName_ you can use:
 *
 *		@example
 *		<script>
 *		$(".selector").tabbar('methodName', methodArgument1, methodArgument2, ...);
 *		</script>
 *
 * @class ns.widget.mobile.TabBar
 * @extends ns.widget.BaseWidget
 */
(function (document, ns) {
	
				var ButtonClasses = ns.widget.mobile.Button.classes,
				BaseWidget = ns.widget.mobile.BaseWidgetMobile,
				engine = ns.engine,
				selectors = ns.util.selectors,
				grid = ns.util.grid,
				DOM = ns.util.DOM,
				slice = [].slice,
				TabBar = function () {
					this.vclickCallback = null;
					this._ui = {};
					this.options = {
						active: 0,
						autoChange: true
					};
				},
				/**
				 * Object with class dictionary
				 * @property {Object} classes
				 * @static
				 * @member ns.widget.mobile.TabBar
				 * @readonly
				 */
				classes = {
					tabbarScrollUl: "tabbar-scroll-ul",
					tabbarScrollLi: "tabbar-scroll-li",
					uiTabbarActive: "ui-tabbar-active",
					uiStatePersist: "ui-state-persist",
					uiHeader: "ui-header",
					uiScrollviewView: "ui-scrollview-view",
					uiScrollviewClip: "ui-scrollview-clip",
					uiNavbar: "ui-navbar",
					uiFooter: "ui-footer",
					uiTabBtnStyle: "ui-tab-btn-style",
					uiTitle: "ui-title",
					uiTitleTabbar: "ui-title-tabbar",
					uiTabbarNoicons: "ui-tabbar-noicons",
					uiTabbarNotext: "ui-tabbar-notext",
					uiTitleTabbarMultiline: "ui-title-tabbar-multiline",
					uiTabbarPersist: "ui-tabbar-persist",
					uiTabbar: "ui-tabbar",
					uiPortraitTabbar: "ui-portrait-tabbar",
					uiLandscapeTabbar: "ui-landscape-tabbar"
				};

			TabBar.prototype = new BaseWidget();

			/*
			* @todo move to options object
			*/

			/**
			 * Position of icon
			 * @property {string} [iconpos="top"]
			 * @member ns.widget.mobile.TabBar
			 */
			TabBar.prototype.iconpos = 'top';
			/**
			 * Grid type
			 * @property {string} [grid=null]
			 * @member ns.widget.mobile.TabBar
			 */
			TabBar.prototype.grid = null;

			TabBar.classes = classes;

			/**
			 * Returns true if one of elements has data-icon set to true
			 * @method hasIcon
			 * @param {Array} elements
			 * @member ns.widget.mobile.TabBar
			 * @static
			 * @private
			 * @return {boolean}
			 */
			function hasIcon(elements) {
				return !elements.every(function (element) {
					return !element.getAttribute('data-icon');
				});
			}

			function setActive(self, index) {
				var element = self.element,
					uls = element.getElementsByTagName("ul"),
					ul = uls[0],
					buttons = element.getElementsByTagName("a"),
					i = 0,
					max,
					hasClass = false,
					buttonClasses,
					btnActiveClass = ButtonClasses.uiBtnActive,
					classes = TabBar.classes,
					activatedButton = buttons.length > index ? buttons[index] : null;

				while (!hasClass && ul) {
					if (ul.classList.contains(classes.tabbarScrollUl)) {
						hasClass = true;
					}
					ul = uls[++i];
				}

				if (hasClass) {
					for (i = 0, max = buttons.length; i < max; i++) {
						buttons[i].classList.remove(classes.uiTabbarActive);
					}
					/*
					* In original file btnActiveClass is always added.
					* Here, if button is disabled, this class will not be added
					*/
					if (activatedButton) {
						activatedButton.classList.add(classes.uiTabbarActive);
						self.options.active = index;
					}
				} else {
					for (i = 0, max = buttons.length; i < max; i++) {
						buttonClasses = buttons[i].classList;
						if (!buttonClasses.contains(classes.uiStatePersist)) {
							buttonClasses.remove(btnActiveClass);
						}
					}
					/*
					* In original file btnActiveClass is always added.
					* Here, if button is disabled, this class will not be added
					*/
					if (activatedButton) {
						activatedButton.classList.add(btnActiveClass);
						self.options.active = index;
					}
				}
			}

			/**
			 * @method vclickEvent
			 * @param {ns.widget.mobile.TabBar} self
			 * @member ns.widget.mobile.TabBar
			 * @static
			 * @private
			 */
			function vclickEvent(self) {
				var element = self.element,
					buttons = element.getElementsByTagName("a"),
					i = 0,
					max,
					activatedButton = selectors.getClosestByTag(event.target, "a"),
					active = 0;

				for (i = 0, max = buttons.length; i < max; i++) {
					if (activatedButton === buttons[i]) {
						active = i;
						break;
					}
				}

				if (self.options.autoChange) {
					setActive(self, active);
				}
			}

			/**
			 * Sets tabbar elements disabled and aria-disabled attributes according
			 * to specified value
			 * @method setDisabled
			 * @private
			 * @static
			 * @param {HTMLElement} element
			 * @param {boolean} value
			 * @param {number} index the element index
			 * @member ns.widget.mobile.TabBar
			 */
			function setDisabled(element, value, index) {
				var liItems = selectors.getChildrenByTag(element.children[0], 'li')[index];

				DOM.setAttribute(liItems, 'disabled', value);
				DOM.setAttribute(liItems, 'aria-disabled', value);
				if (value) {
					liItems.classList.add(ButtonClasses.uiDisabled);
				} else {
					liItems.classList.remove(ButtonClasses.uiDisabled);
				}
			}

			/**
			 * Build method
			 * @method _build
			 * @param {HTMLElement} element
			 * @return {HTMLElement}
			 * @protected
			 * @member ns.widget.mobile.TabBar
			 */
			TabBar.prototype._build = function (element) {
				var classes = TabBar.classes,
					tabbarClassList = element.classList,
					links = slice.call(element.getElementsByTagName('a')),
					headers = selectors.getParentsByClass(element, classes.uiHeader),
					scrollview = selectors.getParentsByClass(element, classes.uiScrollviewView)[0],
					li = slice.call(element.getElementsByTagName("li")),
					iconpos,
					i,
					textpos,
					instanceButtonOptions,
					instanceButtonHeaderOptions = {
						shadow: false,
						corners: false,
						inline: false,
						bar: true
					},
					instanceButtonFooterOptions = {
						shadow: true,
						inline: false,
						corners: true,
						bar: false
					};

				if (links.length) {
					iconpos = hasIcon(links) ? this.iconpos : false;
					textpos = links[0].innerHTML.length ? true : false;
				}

				if (headers.length && scrollview) {
					li.forEach(function (item) {
						item.classList.add(classes.tabbarScrollLi);
					});
					slice.call(element.getElementsByTagName("ul")).forEach(function (item) {
						item.classList.add(classes.tabbarScrollUl);
					});

					/* add shadow divider */
					selectors.getParentsByClass(element, classes.uiScrollviewClip).forEach(function (item) {
						item.insertAdjacentHTML('beforeend', '<div class="ui-tabbar-divider ui-tabbar-divider-left" style="display:none"></div><div class="ui-tabbar-divider ui-tabbar-divider-right" style="display:none"></div>');
					});

				} else {
					if (li.length) {
						tabbarClassList.add(classes.uiNavbar);
						slice.call(element.getElementsByTagName("ul")).forEach(function (item) {
							/*
							* @todo delete getAttribute
							*/
							grid.makeGrid(item, element.getAttribute("data-grid") || this.grid);
						});
					}
				}

				if (selectors.getParentsByClass(element, classes.uiFooter).length) {
					li.forEach(function (item) {
						item.classList.add(classes.uiTabBtnStyle);
					});
				}

				/* title tabbar */
				if (selectors.getChildrenByClass(element.parentElement, classes.uiTitle).length) {
					headers.forEach(function (header) {
						header.classList.add(classes.uiTitleTabbar);
					});
				}
				/* scrollable tabbar */
				if (element.parentNode.classList.contains(classes.uiScrollviewView)){
					if (li.length > 4) {
						i = headers.length;
						while (i--) {
							headers[i].classList.add(classes.uiTitleTabbar);
						}

						// scroller was needed when li element has more than forth.
						scrollview.style.width = parseInt(li[0].style.width, 10) * li.length + "px";
						this._ui.scrollview = scrollview;
						this._ui.scrollviewClip = selectors.getParentsByClass(element, classes.uiScrollviewClip)[0];
					}

				}

				if (!iconpos) {
					tabbarClassList.add(classes.uiTabbarNoicons);
				}
				if (!textpos) {
					tabbarClassList.add(classes.uiTabbarNotext);
				}
				if (textpos && iconpos) {
					headers.forEach(function (header) {
						header.classList.add(classes.uiTitleTabbarMultiline);
					});
				}

				if (links.length) {
					if (headers.length) {
						instanceButtonOptions = instanceButtonHeaderOptions;
					} else {
						instanceButtonOptions = instanceButtonFooterOptions;
					}
					if (iconpos) {
						instanceButtonOptions.iconpos = iconpos;
					}
					links.forEach(function (item) {
						DOM.setNSData(item, "role", "button");
						engine.instanceWidget(item, "Button", instanceButtonOptions);
					});
				}

				if (element.getElementsByClassName(classes.uiStatePersist).length) {
					tabbarClassList.add(classes.uiTabbarPersist);
				}

				tabbarClassList.add(classes.uiTabbar);

				return element;
			};

			/**
			 * Init method
			 * @method _init
			 * @param {HTMLElement} element
			 * @member ns.widget.mobile.TabBar
			 * @protected
			 */
			TabBar.prototype._init = function (element) {
				var self = this,
					tabbarClassList = element.classList,
					li = slice.call(element.getElementsByTagName("li")),
					innerWidth = element.offsetWidth ? element.offsetWidth : window.innerWidth,
					innerHeight = element.offsetHeight ? element.offsetHeight : window.innerHeight,
					inHeaders = !!(selectors.getParentsByClass(element, classes.uiHeader).length),
					isLandscape = window.innerWidth > window.innerHeight,
					btnActiveClass = ButtonClasses.uiBtnActive,
					uiTabbarActive = classes.uiTabbarActive,
					links = slice.call(element.getElementsByTagName('a'));

				if (li.length > 4) {
					// tabbar elements should be showed maximum forth elements.
					this._setWidth(li, innerWidth / 4, inHeaders);
				} else {
					this._setWidth(li, innerWidth / li.length, inHeaders);
				}

				if (isLandscape) {
					tabbarClassList.remove(classes.uiPortraitTabbar);
					tabbarClassList.add(classes.uiLandscapeTabbar);
				} else {
					tabbarClassList.remove(classes.uiLandscapeTabbar);
					tabbarClassList.add(classes.uiPortraitTabbar);
				}

				[].forEach.call(links, function(element, index) {
					if (element.classList.contains(btnActiveClass) || element.classList.contains(uiTabbarActive)) {
						self.options.active = index;
					}
				});

				setActive(self, self.options.active);
			};

			/**
			 * Bind events for widget
			 * @method _bindEvents
			 * @protected
			 * @member ns.widget.mobile.TabBar
			 */
			TabBar.prototype._bindEvents = function () {
				this.vclickCallback = vclickEvent.bind(null, this);
				this.element.addEventListener("vclick", this.vclickCallback, false);
				if (this._ui.scrollviewClip) {
					this._ui.scrollviewClip.addEventListener("scrollstop", roundTabBarPositionX);
				}
			};

			/**
			 * Destroy the tab bar
			 *
			 *		@example
			 *		<script>
			 *		var element = document.getElementById("tabbar"),
			 *			tabBarWidget = tau.widget.TabBar(element);
			 *		tabBarWidget.destroy();
			 *
			 *		// or
			 *
			 *		$( "#tabbar" ).tabbar( "destroy" );
			 *		</script>
			 *
			 * @method destroy
			 * @chainable
			 * @member ns.widget.mobile.TabBar
			 */

			/**
			 * Destroy widget
			 * @method _destroy
			 * @protected
			 * @member ns.widget.mobile.TabBar
			 */
			TabBar.prototype._destroy = function () {
				this.element.removeEventListener("vclick", this.vclickCallback, false);
				if (this._ui.scrollviewClip) {
					this._ui.scrollviewClip.removeEventListener("scrollstop", roundTabBarPositionX);
				}
			};

			/**
			 * Set width method
			 * @method _setWidth
			 * @param {Array} elements
			 * @param {number} width
			 * @param {boolean} setOnLink
			 * @member ns.widget.mobile.TabBar
			 * @protected
			 */
			TabBar.prototype._setWidth = function (elements, width, setOnLink) {
				var i,
					length = elements.length,
					element,
					linkElement,
					elementWidth = width + "px",
					linkWidth = width + "px";
				for (i = 0; i < length; i++) {
					element = elements[i];
					element.style.width = elementWidth;
					linkElement = selectors.getChildrenByTag(element, "a")[0];
					if (linkElement && setOnLink) {
						linkElement.style.width = linkWidth;
					}
				}
			};

			/**
			 * Move scroll to position from left border of li element
			 * @method roundTabBarPositionX
			 * @param {Event} event
			 * @private
			 * @static
			 * @member ns.widget.mobile.TabBar
			 */
			function roundTabBarPositionX(event) {
				var element = event.target,
					lastX = element.scrollLeft,
					liWidth = parseInt(element.getElementsByTagName("li")[0].style.width),
					interval = lastX % liWidth,
					middle = liWidth / 2,
					scrollViewWidget = engine.instanceWidget(element, "Scrollview");

				if (interval !== 0) {
					if (interval <= middle) {
						scrollViewWidget.scrollTo(lastX - interval, 0, 500);
					} else {
						scrollViewWidget.scrollTo(lastX + (liWidth - interval), 0, 500);
					}
				}
			}

			/**
			 * Disables the tab bar
			 *
			 * Method add disabled attribute on tab bar and changes look
			 * of search bar to enabled state.
			 *
			 *		@example
			 *		<script>
			 *		var element = document.getElementById("tabbar"),
			 *			tabBarWidget = tau.widget.TabBar(element);
			 *		tabBarWidget.disable();
			 *
			 *		// or
			 *
			 *		$( "#tabbar" ).tabbar( "disable" );
			 *		</script>
			 *
			 * @method disable
			 * @chainable
			 * @member ns.widget.mobile.TabBar
			 */

			/**
			 * Disables specified element in tabbar
			 * @method _disable
			 * @param {HTMLElement} element
			 * @param {number} index the element index
			 * @protected
			 * @member ns.widget.mobile.TabBar
			 */
			TabBar.prototype._disable = function (element, index) {
				if (index !== undefined) {
					setDisabled(element, true, index);
				}
			};

			/**
			 * Enable the tab bar
			 *
			 * Method removes disabled attribute on tab bar and changes look
			 * of tab bar to enabled state.
			 *
			 *		@example
			 *		<script>
			 *		var element = document.getElementById("tabbar"),
			 *			tabBarWidget = tau.widget.TabBar(element);
			 *		tabBarWidget.enable();
			 *
			 *		// or
			 *
			 *		$( "#tabbar" ).tabbar( "enable" );
			 *		</script>
			 *
			 * @method enable
			 * @chainable
			 * @member ns.widget.mobile.TabBar
			 */

			/**
			 * Enables specified element in tabbar
			 * @method _enable
			 * @param {HTMLElement} element
			 * @param {number} index the element index
			 * @protected
			 * @member ns.widget.mobile.TabBar
			 */
			TabBar.prototype._enable = function (element, index) {
				if (index !== undefined) {
					setDisabled(element, false, index);
				}
			};

			/**
			 * Refresh Tabbar widget.
			 *
			 * @method refresh
			 * @chainable
			 * @member ns.widget.mobile.TabBar
			 */
			TabBar.prototype._refresh = function () {
				setActive(this, this.options.active);
			}

			/**
			 * Value method is not supported in this widget.
			 *
			 * @method value
			 * @chainable
			 * @member ns.widget.mobile.TabBar
			 */

			ns.widget.mobile.TabBar = TabBar;
			engine.defineWidget(
				"TabBar",
				"[data-role='tabbar'], .ui-tabbar",
				[],
				TabBar,
				'tizen'
			);
			}(window.document, ns));

/*global window, define */
/*
* Copyright  2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/*jslint nomen: true, plusplus: true */
/**
 * # Fast Scroll Widget
 * The fast scroll widget shows a shortcut list that is bound to its parent scroll bar and respective list view.
 *
 * The fast scroll is a scroll view controller, which binds a scroll view to a list of shortcuts. It jumps the scroll view to the selected list divider. If you move the mouse on the shortcut column, the scroll view is moved to the list divider matching the text currently under the mouse cursor. A pop-up with the text currently under the cursor is also displayed. To use the fast scroll widget, add the data-fastscroll="true" attribute to a list view. You can also call the shortcutscroll() method on an element. The closest element of the ui-scrollview-clip class is used as the scroll view to be controlled.
 *
 * !!! For the fast scroll widget to be visible, the parent list view must have multiple list dividers.!!!
 *
 * ## Default selectors
 * In default all ListView elements with _data-fastscroll=true_ are changed to Tizen Web UI Fast Scroll.
 *
 * In default all ListView elements with class _.ui-fastscroll_ are changed to Tizen Web UI Fast Scroll
 *
 *		@example
 *		<div data-role="page" id="main">
 *			<div data-role="content">
 *				<ul data-role="listview" data-fastscroll="true">
 *					<li data-role="list-divider">A</li>
 *					<li>Anton</li>
 *					<li>Arabella</li>
 *					<li data-role="list-divider">B</li>
 *					<li>Barry</li>
 *					<li>Bily</li>
 *				</ul>
 *			</div>
 *		</div>
 *
 * #### Create FastScroll widget using tau method:
 *
 *		@example
 *		<div data-role="page" id="main">
 *			<div data-role="content">
 *				<ul id="list" data-fastscroll="true">
 *					<li data-role="list-divider">A</li>
 *					<li>Anton</li>
 *					<li>Arabella</li>
 *					<li data-role="list-divider">B</li>
 *					<li>Barry</li>
 *					<li>Bily</li>
 *				</ul>
 *			</div>
 *		</div>
 *		<script>
 *			var fastscroll = tau.widget.FastScroll(document.getElementById("list"));
 *		</script>
 *
 * #### Create FastScroll widget using jQueryMobile notation:
 *
 *		@example
 *		<div data-role="page" id="main">
 *			<div data-role="content">
 *				<ul id="list" data-fastscroll="true">
 *					<li data-role="list-divider">A</li>
 *					<li>Anton</li>
 *					<li>Arabella</li>
 *					<li data-role="list-divider">B</li>
 *					<li>Barry</li>
 *					<li>Bily</li>
 *				</ul>
 *			</div>
 *		</div>
 *		<script>
 *			var fastscroll = $("#list").fastscroll();
 *		</script>
 *
 * ## Options
 *
 * ### Fastscroll
 * _data-fastscroll_ option set to true, creates a fast scroll using the HTML unordered list (&lt;ul&gt;) element.
 *
 *		@example
 *		<div data-role="page" id="main">
 *			<div data-role="content">
 *				<ul id="contacts" data-role="listview" data-fastscroll="true">
 *					<li data-role="list-divider">A</li>
 *					<li>Anton</li>
 *					<li>Arabella</li>
 *					<li data-role="list-divider">B</li>
 *					<li>Barry</li>
 *					<li>Bily</li>
 *				</ul>
 *			</div>
 *		</div>
 *
 * ## Methods
 *
 * To call method on widget you can use tau API:
 *
 *		@example
 *		<div data-role="page" id="main">
 *			<div data-role="content">
 *				<ul id="contacts">
 *					<li data-role="list-divider">A</li>
 *					<li>Anton</li>
 *					<li>Arabella</li>
 *					<li data-role="list-divider">B</li>
 *					<li>Barry</li>
 *					<li>Bily</li>
 *				</ul>
 *			</div>
 *		</div>
 *		<script>
 *			var element = document.getElementById("contacts"),
 *				contacts = tau.widget.FastScroll(element, {fastscroll: true});
 *
 *			contacts.methodName(methodArgument1, methodArgument2, ...);
 *
 *			// or JQueryMobile notation:
 *			$(element).contacts("methodName", methodArgument1, methodArgument2, ...);
 *		</script>
 *
 * @class ns.widget.mobile.FastScroll
 * @extends ns.widget.mobile.Listview
 * @since 2.0
 */
(function (document, ns) {
	
				/**
			 * @property {Object} selectors Alias to ns.util.selectors
			 * @member ns.widget.mobile.FastScroll
			 * @private
			 * @static
			 */
			var selectors = ns.util.selectors,

				/**
				 * @property {Function} Tabbar Alias for class ns.widget.mobile.Tabbar
				 * @member ns.widget.mobile.FastScroll
				 * @static
				 * @private
				 */
				Tabbar = ns.widget.mobile.TabBar,
				/**
				 * @property {Object} engine Alias for class {@link ns.engine}
				 * @member ns.widget.mobile.FastScroll
				 * @private
				 * @static
				 */
				engine = ns.engine,
				/**
				 * @property {Object} events alias variable
				 * @member ns.widget.mobile.FastScroll
				 * @static
				 * @private
				 */
				events = ns.event,
				/**
				 * @property {Function} Page Alias for class ns.widget.mobile.Page
				 * @member ns.widget.mobile.FastScroll
				 * @static
				 * @private
				 */
				Page = ns.widget.mobile.Page,
				/**
				 * @property {Object} DOMUtils Alias to ns.util.DOM
				 * @private
				 * @member ns.widget.mobile.FastScroll
				 * @static
				 */
				DOMUtils = ns.util.DOM,
				/**
				 * @property {Function} Listview Alias for class ns.widget.mobile.Listview
				 * @member ns.widget.mobile.FastScroll
				 * @static
				 * @private
				 */
				Listview = ns.widget.mobile.Listview,

				/**
				 * Backup of _build methods for replacing it
				 * @method parent_build
				 * @member ns.widget.mobile.FastScroll
				 * @private
				 */
				parent_build = Listview.prototype._build,

				/**
				 * Backup of _configure methods for replacing it
				 * @method parent_configure
				 * @member ns.widget.mobile.FastScroll
				 * @private
				 */
				parent_configure = Listview.prototype._configure,

				/**
				 * Backup of _init methods for replacing it
				 * @method parent_init
				 * @member ns.widget.mobile.FastScroll
				 * @private
				 */
				parent_init = Listview.prototype._init,

				/**
				 * Backup of _bindEvents methods for replacing it
				 * @method parent_bindEvents
				 * @member ns.widget.mobile.FastScroll
				 * @private
				 */
				parent_bindEvents = Listview.prototype._bindEvents,

				/**
				 * Backup of _destroy methods for replacing it
				 * @method parent_destroy
				 * @member ns.widget.mobile.FastScroll
				 * @private
				 */
				parent_destroy = Listview.prototype._destroy,

				/**
				 * Refresh FastScroll widget
				 *
				 * This method updates and redraws current widget.
				 *
				 *		@example
				 *		<div data-role="page" id="main">
				 *			<div data-role="content">
				 *				<ul id="list" data-role="listview" data-fastscroll="true">
				 *					<li data-role="list-divider">A</li>
				 *					<li>Anton</li>
				 *					<li>Arabella</li>
				 *					<li data-role="list-divider">B</li>
				 *					<li>Barry</li>
				 *					<li>Bily</li>
				 *				</ul>
				 *			</div>
				 *		</div>
				 *		<script>
				 *			var element = document.getElementById("list"),
				 *				fastscroll = tau.widget.FastScroll(element);
				 *
				 *			element.insertAdjacentHTML("afterend", "<li>Bruce</li>");
				 *			fastscroll.refresh();
				 *		</script>
				 *
				 * or JQueryMobile notation:
				 *
				 *		@example
				 *		<div data-role="page" id="main">
				 *			<div data-role="content">
				 *				<ul data-role="listview" data-fastscroll="true" id="fastscroll">
				 *					<li data-role="list-divider">A</li>
				 *					<li>Anton</li>
				 *					<li>Arabella</li>
				 *					<li data-role="list-divider">B</li>
				 *					<li>Barry</li>
				 *					<li>Bily</li>
				 *				</ul>
				 *			</div>
				 *		</div>
				 *		<script>
				 *			$("#list").append("<li>Bruno</li>");
				 *			$("#list").fastscroll("refresh");
				 *		</script>
				 *
				 * @method refresh
				 * @member ns.widget.mobile.FastScroll
				 */

				/**
				 * Backup of _refresh methods for replacing it
				 * @method parent_refresh
				 * @member ns.widget.mobile.FastScroll
				 * @private
				 */
				parent_refresh = Listview.prototype._refresh,

				/**
				 * Alias for object ns.widget.mobile.Listview.classes
				 * @property {Object} classes
				 * @member ns.widget.mobile.FastScroll
				 * @static
				 * @property {string} listviewClasses.uiFastscroll
				 * Main calss of fascscroll view
				 * @property {string} listviewClasses.uiFastscrollTarget
				 * Class of fascroll target (listview)
				 * @property {string} listviewClasses.uiFastscrollPopup
				 * Class of fastscroll popup
				 * @property {string} listviewClasses.uiScrollbar
				 * Class of scrollbar
				 * @property {string} listviewClasses.uiFastscrollHover
				 * Class of fastscroll item with fover
				 * @property {string} listviewClasses.uiFastscrollHoverFirstItem
				 * Class of first item in fastscroll with fover
				 * @property {string} listviewClasses.uiFastscrollHoverDown
				 * Class of presed fastscroll item with fover
				 */
				listviewClasses = Listview.classes,

				/**
				 * FastScroll event types
				 * @property {Object} eventType
				 * @property {string} [eventType.DESTROYED="destroyed"]
				 * Event is triggering after _destroy method call.
				 * @static
				 * @readonly
				 * @member ns.widget.mobile.FastScroll
				 */
				eventType = Listview.eventType || {},

				/**
				 * Local cache of function type name
				 * @property {string} [TYPE_FUNCTION="function"]
				 * @private
				 * @static
				 * @member ns.widget.mobile.FastScroll
				 */
				TYPE_FUNCTION = "function";

			// the extension of Listview events dictionary
			/*
			 * Event is triggering after _destroy method call
			 * @event destroyed
			 * @member ns.widget.mobile.FastScroll
			 */
			eventType.DESTROYED = "destroyed";

			// the extension of Listview classes
			listviewClasses.uiFastscroll = "ui-fastscroll";
			listviewClasses.uiFastscrollTarget = "ui-fastscroll-target";
			listviewClasses.uiFastscrollPopup = "ui-fastscroll-popup";
			listviewClasses.uiScrollbar = "ui-scrollbar";
			listviewClasses.uiFastscrollHover = "ui-fastscroll-hover";
			listviewClasses.uiFastscrollHoverFirstItem = "ui-fastscroll-hover-first-item";
			listviewClasses.uiFastscrollHoverDown = "ui-fastscroll-hover-down";

			/**
			 * Count what is max height of short cut on fastscroll list
			 * @method getMaxFastscrollItemHeight
			 * @param {ns.widget.mobile.FastScroll} self
			 * @param {HTMLElement} item
			 * @param {number} itemsCount
			 * @param {number} containerHeight
			 * @return {number}
			 * @private
			 * @static
			 * @member ns.widget.mobile.FastScroll
			 */
			function getMaxFastscrollItemHeight(self, item, itemsCount, containerHeight) {
				var style = window.getComputedStyle(item, null),
					marginHeight = self.marginHeight || parseInt(style.marginBottom.replace(/[^\d\.]/g, ""), 10),
					itemHeight = Math.floor(containerHeight / itemsCount);

				marginHeight = self.marginHeight || marginHeight + 2 * parseInt(style.borderBottomWidth.replace(/[^\d\.]/g, ""), 10);

				self.marginHeight = marginHeight;
				itemHeight -= marginHeight;

				return itemHeight;
			}

			/**
			 * Match char to divider
			 * @method matchToDivider
			 * @param {HTMLElement} divider
			 * @param {string} indexChar
			 * @param {Array} map
			 * @private
			 * @static
			 * @member ns.widget.mobile.FastScroll
			 */
			function matchToDivider(divider, indexChar, map) {
				if (indexChar === divider.innerText) {
					map[indexChar] = divider;
				}
			}

			/**
			 * Creates character set for divider
			 * @method makeCharacterSet
			 * @param {HTMLElement} divider
			 * @param {string} primaryCharacterSet
			 * @return {string}
			 * @private
			 * @static
			 * @member ns.widget.mobile.FastScroll
			 */
			function makeCharacterSet(divider, primaryCharacterSet) {
				return primaryCharacterSet + divider.innerText;
			}

			/**
			 * Function called whane pageshow event on fastscroll parent is called
			 * @method onPageshow
			 * @param {ns.widget.mobile.FastScroll} self
			 * @param {Event} event
			 * @private
			 * @static
			 * @member ns.widget.mobile.FastScroll
			 */
			function onPageshow(self, event) {
				event.target.removeEventListener("pageshow", self._onPageshowBound);
				self._refresh();
			}

			/**
			 * Function called on focus out on fast scroll item
			 * @method onShortcutsListMouseOut
			 * @param {ns.widget.mobile.FastScroll} self
			 * @private
			 * @static
			 * @member ns.widget.mobile.FastScroll
			 */
			function onShortcutsListMouseOut(self) {
				var items,
					itemsLength,
					i,
					ui = self._ui;

				ui._popup.style.display = "none";

				items = document.getElementsByClassName(listviewClasses.uiFastscrollHover);
				itemsLength = items.length;
				for (i = 0; i < itemsLength; i++) {
					items[0].classList.remove(listviewClasses.uiFastscrollHover);
				}

				items = document.getElementsByClassName(listviewClasses.uiFastscrollHoverDown);
				itemsLength = items.length;
				for (i = 0; i < itemsLength; i++) {
					items[i].classList.remove(listviewClasses.uiFastscrollHoverDown);
				}

				items = document.getElementsByClassName(listviewClasses.uiFastscrollHoverFirstItem);
				itemsLength = items.length;
				for (i = 0; i < itemsLength; i++) {
					items[i].classList.remove(listviewClasses.uiFastscrollHoverFirstItem);
				}

				ui._shortcutsContainer.classList.remove(listviewClasses.uiFastscrollHover);
			}

			/**
			 * Function called on focus in on fast scroll item
			 * @method onShortcutsListMouseOver
			 * @param {ns.widget.mobile.FastScroll} self
			 * @param {Event} event
			 * @private
			 * @static
			 * @member ns.widget.mobile.FastScroll
			 */
			function onShortcutsListMouseOver(self, event) {
				var coords = {
						x: event.pageX,
						y: event.pageY
					},
					ui = self._ui,
					shortcutsList = ui._shortcutsList,
					shortcutsContainer = ui._shortcutsContainer,
					shortcutsListOffset = {
						left: shortcutsList.offsetLeft,
						top: shortcutsList.offsetTop
					},
					shortcutsContainerTop = shortcutsContainer.offsetTop,
					shortcutsContainerLeft = shortcutsContainer.offsetLeft,
					target = event.target,
					shortcutsListItems,
					shortcutsListItemsLength,
					i,
					j,
					left,
					top,
					right,
					bottom,
					unit,
					baseTop,
					baseBottom,
					omitSet,
					listItem,
					omitSetLength,
					tagName = target.tagName.toLowerCase();

				shortcutsContainer.classList.add(listviewClasses.uiFastscrollHover);

				// If the element is a list item, get coordinates relative to the shortcuts list
				if (tagName === "li") {
					coords.x += shortcutsListOffset.left - shortcutsContainerLeft;
					coords.y += shortcutsListOffset.top - shortcutsContainerTop;
				}

				if (tagName === "span") {
					coords.x += target.parentElement.offsetLeft - shortcutsListOffset.left;
					coords.y += target.parentElement.offsetTop  - shortcutsListOffset.top;
				}

				shortcutsListItems = shortcutsList.getElementsByTagName("li");
				shortcutsListItemsLength = shortcutsListItems.length;
				for (i = 0; i < shortcutsListItemsLength; i++) {
					listItem = shortcutsListItems[i];
					listItem.classList.remove(listviewClasses.uiFastscrollHover);
					listItem.classList.remove(listviewClasses.uiFastscrollHoverDown);

					left = listItem.offsetLeft;
					top = listItem.offsetTop;
					right = left + Math.abs(listItem.offsetWidth);
					bottom = top + Math.abs(listItem.offsetHeight);

					if (coords.x >= left && coords.x <= right && coords.y >= top && coords.y <= bottom) {
						if (listItem.innerText === ".") {
							omitSet = DOMUtils.getNSData(listItem, "omitSet");
							omitSetLength = omitSet.length;
							unit = (bottom - top) / omitSetLength;
							for (j = 0; j < omitSetLength; j++) {
								baseTop = top + (j * unit);
								baseBottom = baseTop + unit;
								if (coords.y >= baseTop && coords.y <= baseBottom) {
									self._hitOmitItem(listItem, omitSet.charAt(i));
								}
							}
						} else {
							self._hitItem(listItem);
						}
					}
				}

				event.preventDefault();
				event.stopPropagation();
			}

			/**
			 * Refresh fastscroll list items
			 *
			 * Recount of fastscroll height, recount of fastscroll item height,
			 * refresh short cuts list.
			 *
			 * @method fastscrollRefresh
			 * @param {ns.widget.mobile.FastScroll} self
			 * @private
			 * @static
			 * @member ns.widget.mobile.FastScroll
			 */
			function fastscrollRefresh(self) {
				var element = self.element,
					ui = self._ui,
					scrollViewClip = selectors.getClosestByClass(
						element,
						Tabbar.classes.uiScrollviewClip
					),
					contentHeight = DOMUtils.getElementHeight(scrollViewClip),
					primaryCharacterSet = null,
					secondCharacterSet = null,
					popup = ui._popup,
					popupStyle,
					popupHeight,
					shortcutsList = ui._shortcutsList,
					shapItem,
					shapItemSpan1,
					shapItemSpan2,
					omitIndex = 0,
					containerHeight,
					shortcutsItems,
					shortcutItem,
					shortcutsTop,
					maxNumOfItems,
					numOfItems,
					minHeight,
					omitInfo,
					dividers,
					listItems,
					emptySize,
					indexChar,
					lastIndex,
					seconds,
					i,
					listItemsLength,
					dividersLength,
					secondsLength,
					shortcutsItemsLength,
					styles,
					item,
					headers,
					shortcutsContainer,
					headersLength,
					dividerClass = ns.widget.mobile.ListDivider.classes.uiLiDivider,
					itemHeight,
					maxHeight,
					primaryCharacterSetLength;

				if (typeof parent_refresh === TYPE_FUNCTION) {
					parent_refresh.call(self);
				}
				if (true !== self.options.fastscroll) {
					return;
				}

				if (shortcutsList) {
					self._createDividerMap();
					DOMUtils.removeAllChildren(shortcutsList);

					dividers = element.getElementsByClassName(dividerClass);
					listItems = selectors.getChildrenBySelector(element, "li:not(." + dividerClass + ")");

					listItemsLength = listItems.length;

					shortcutsList.style.display = "block";
					ui._lastListItem = listItemsLength > 0 ? listItems[listItemsLength - 1] : null;

					shapItem = document.createElement("li");
					shapItem.setAttribute("aria-label", "double to move Number list");
					shapItem.tabIndex = 0;
					shapItemSpan1 = document.createElement("span");
					shapItemSpan1.setAttribute("aria-hidden", "true");
					shapItemSpan1.innerText = "#";
					shapItem.appendChild(shapItemSpan1);
					shapItemSpan2 = document.createElement("span");
					shapItemSpan2.setAttribute("aria-label", "Number");
					shapItem.appendChild(shapItemSpan2);

					shortcutsList.appendChild(shapItem);
					self._focusItem(shapItem);

					dividersLength = dividers.length;

					if (primaryCharacterSet === null) {
						primaryCharacterSet = "";
						for (i = 0; i < dividersLength; i++) {
							primaryCharacterSet = makeCharacterSet(dividers[i], primaryCharacterSet);
						}
					}

					minHeight = shapItem.offsetHeight;
					maxNumOfItems = parseInt(contentHeight / minHeight - 1, 10);
					numOfItems = primaryCharacterSet.length;

					maxNumOfItems = secondCharacterSet ? maxNumOfItems - 2 : maxNumOfItems;

					if (maxNumOfItems < 3) {
						if (shapItem.parentElement) {
							shapItem.parentElement.removeChild(shapItem);
						}

						return;
					}

					omitInfo = self._omit(numOfItems, maxNumOfItems);

					for (i = 0, primaryCharacterSetLength = primaryCharacterSet.length; i < primaryCharacterSetLength; i++) {
						indexChar = primaryCharacterSet.charAt(i);
						shortcutItem = document.createElement("li");
						shortcutItem.setAttribute("aria-label", "double to move " + indexChar + " list");
						shortcutItem.setAttribute("tabindex", 0);
						shortcutItem.innerText = indexChar;

						self._focusItem(shortcutItem);

						if (omitInfo && omitInfo[omitIndex] > 1) {
							shortcutItem = document.createElement("li");
							shortcutItem.innerText = ".";
							DOMUtils.setNSData(shortcutItem, "omitSet", self._makeOmitSet(i, omitInfo[omitIndex], primaryCharacterSet));
							i += omitInfo[omitIndex] - 1;
						}

						shortcutsList.appendChild(shortcutItem);
						omitIndex++;
					}

					if (secondCharacterSet !== null) {
						lastIndex = secondCharacterSet.length - 1;
						seconds = [];

						seconds.push(secondCharacterSet.charAt(0));
						seconds.push(secondCharacterSet.charAt(lastIndex));

						for (i = 0, secondsLength = seconds.length; i < secondsLength; i++) {
							indexChar = seconds[i];
							shortcutItem = document.createElement("li");
							shortcutItem.tabIndex = 0;
							shortcutItem.setAttribute("aria-label", "double to move " + indexChar + " list");
							shortcutItem.innerText = indexChar;

							self._focusItem(shortcutItem);
							shortcutsList.append(shortcutItem);
						}
					}

					shortcutsContainer = ui._shortcutsContainer;
					maxHeight = contentHeight - element.offsetTop;
					shortcutsContainer.style.maxHeight = maxHeight + "px";

					containerHeight = shortcutsContainer.offsetHeight;
					emptySize = contentHeight - containerHeight;
					shortcutsItems = shortcutsList.children;
					shortcutsItemsLength = shortcutsItems.length;
					shortcutsTop = (dividersLength > 0) ? dividers[0].offsetTop : 0;

					if (emptySize > 0) {
						if (shortcutsItemsLength > 0) {
							item = shortcutsItems[0];
							itemHeight = getMaxFastscrollItemHeight(self, item, shortcutsItemsLength, maxHeight);
						}
						for (i = 0; i < shortcutsItemsLength; i++) {
							item = shortcutsItems[i];
							styles = item.style;
							styles.height = itemHeight + "px";
							styles.lineHeight =  styles.height;
						}
					}

					headers = shortcutsContainer.parentNode.getElementsByClassName(Tabbar.classes.uiHeader);

					for (i = 0, headersLength = headers.length; i < headersLength; i++) {
						shortcutsTop += headers[i].offsetHeight;
					}

					shortcutsTop += (maxHeight - shortcutsContainer.offsetHeight) / 2;

					ui._shortcutsContainer.style.top = shortcutsTop + "px";

					popupHeight = DOMUtils.getElementHeight(popup);
					popupStyle = popup.style;
					popupStyle.width = popupHeight + 'px';
					popupStyle.marginLeft = -parseInt(DOMUtils.getElementWidth(popup) / 2, 10) + 'px';
					popupStyle.marginTop = -parseInt(popupHeight / 2, 10) + 'px';
				}
			}

			/**
			 * Function called on mouse down on short cut
			 * @method onListItemVMouseDown
			 * @param {ns.widget.mobile.FastScroll} self
			 * @param {Event} event
			 * @private
			 * @static
			 * @member ns.widget.mobile.FastScroll
			 */
			function onListItemVMouseDown(self, event) {
				self._ui._shortcutsList.setAttribute("aria-hidden", false);
				self._hitItem(event.target);
			}

			/**
			 * Function called on mouse up on short cut
			 * @method onListItemVMouseUp
			 * @param {ns.widget.mobile.FastScroll} self
			 * @private
			 * @static
			 * @member ns.widget.mobile.FastScroll
			 */
			function onListItemVMouseUp(self) {
				var i,
					length,
					elements,
					ui = self._ui;

				ui._shortcutsList.setAttribute("aria-hidden", true);
				ui._popup.style.display = "none";

				elements = document.getElementsByClassName(listviewClasses.uiFastscrollHover);
				length = elements.length;
				for (i = 0; i < length; i++) {
					elements[0].classList.remove(listviewClasses.uiFastscrollHover);
				}

				elements = document.getElementsByClassName(listviewClasses.uiFastscrollHoverFirstItem);
				length = elements.length;
				for (i = 0; i < length; i++) {
					elements[0].classList.remove(listviewClasses.uiFastscrollHoverFirstItem);
				}

				elements = document.getElementsByClassName(listviewClasses.uiFastscrollHoverDown);
				length = elements.length;
				for (i = 0; i < length; i++) {
					elements[0].classList.remove(listviewClasses.uiFastscrollHoverDown);
				}
			}

			/**
			 * Prepare default configuration of fastscroll widget
			 * @method _configure
			 * @protected
			 * @member ns.widget.mobile.FastScroll
			 */
			Listview.prototype._configure = function () {
				if (typeof parent_configure === TYPE_FUNCTION) {
					parent_configure.call(this);
				}

				/**
				 * Object with default options
				 * @property {Object} options
				 * @property {boolean} [options.fastscroll=false] Sets if fastscroll should be enabled.
				 * @member ns.widget.mobile.FastScroll
				 */
				this.options = this.options || {};
				this.options.fastscroll = false;
			};

			/**
			 * Builds fasctroll
			 * @method _build
			 * @param {HTMLElement} element HTML element with fasctscroll enabled
			 * @return {HTMLElement}
			 * @protected
			 * @member ns.widget.mobile.FastScroll
			 */
			Listview.prototype._build = function (element) {
				var scrollView,
					shortcutsContainer,
					shortcutsList,
					fastscrollPopup,
					lastListItem,
					elementChildrens,
					elementChildrensLength,
					scrollBars = [],
					i,
					ui,
					scrollviewParent,
					scrollBarsLength,
					id = this.id;

				parent_build.call(this, element);

				// Make sure, that *this* has assigned correct element
				// It is required for this.isBuilt checking.
				this.element = element;

				// @TODO This is bad solution and need to be fixed
				// Since few widgets can be built on one html element
				// every Listview 'plugin' can be built more than one.
				// There is a problem with selectors and Listview
				// plugins management
				if (this.options.fastscroll === true
					&& !(
						this.isBuilt('FastScroll')
						|| this.isBuilt('Listview')
						|| this.isBuilt('ListviewFilter')
						|| this.isBuilt('ListviewAutodivider')
					)
					) {
					//FIXME Why class uiScrollviewClip is in Tabbar not in Scrollview?
					scrollView = selectors.getClosestByClass(element, Tabbar.classes.uiScrollviewClip);
					if (scrollView) {
						shortcutsContainer = document.createElement("div");
						shortcutsContainer.classList.add(listviewClasses.uiFastscroll);
						shortcutsContainer.setAttribute("aria-label", "Fast scrollbar, double tap to fast scroll mode");
						shortcutsContainer.setAttribute("tabindex", 0);
						shortcutsContainer.setAttribute("id", id + "-shortcutscontainer");
						shortcutsContainer.style.maxHeight = scrollView.offsetHeight + "px";

						shortcutsList = document.createElement("ul");
						shortcutsList.setAttribute("aria-hidden", "true");
						shortcutsList.setAttribute("id", id + "-shortcutslist");

						fastscrollPopup = document.createElement("div");
						fastscrollPopup.classList.add(listviewClasses.uiFastscrollPopup);
						fastscrollPopup.setAttribute("id", id + "-fastscrollpopup");

						shortcutsContainer.appendChild(shortcutsList);

						scrollviewParent = scrollView.parentNode;
						scrollviewParent.appendChild(shortcutsContainer);
						scrollviewParent.appendChild(fastscrollPopup);

						elementChildrens = element.children;
						elementChildrensLength = elementChildrens.length;

						if (elementChildrensLength > 0) {
							lastListItem = elementChildrens[elementChildrensLength - 1];
						}

						scrollBars = scrollView.getElementsByClassName(listviewClasses.uiScrollbar);
						for (i = 0, scrollBarsLength = scrollBars.length; i < scrollBarsLength; i++) {
							scrollBars[i].style.display = "none";
						}

						this._ui = this._ui || {};
						ui = this._ui;

						ui._scrollView = scrollView;
						ui._shortcutsContainer = shortcutsContainer;
						ui._shortcutsList = shortcutsList;
						ui._lastListItem = lastListItem;
						ui._popup = fastscrollPopup;
					}
				}
				return element;
			};

			/**
			 * Initialize fastscroll widget
			 * @method _init
			 * @param {HTMLElement} element
			 * @protected
			 * @member ns.widget.mobile.FastScroll
			 */
			Listview.prototype._init = function (element) {
				var ui,
					elementChildrens,
					elementChildrensLength,
					id = this.id;
				if (typeof parent_init === TYPE_FUNCTION) {
					parent_init.call(this, element);
				}

				if (this.options.fastscroll) {
					this._ui = this._ui || {};
					ui = this._ui;

					ui._scrollView = selectors.getClosestByClass(element, Tabbar.classes.uiScrollviewClip);
					ui._shortcutsContainer = document.getElementById(id + "-shortcutscontainer");
					ui._shortcutsList = document.getElementById(id + "-shortcutslist");
					ui._popup = document.getElementById(id + "-fastscrollpopup");

					elementChildrens = element.children;
					elementChildrensLength = elementChildrens.length;

					if (elementChildrensLength > 0) {
						ui._lastListItem = elementChildrens[elementChildrensLength - 1];
					}

					element.classList.add(listviewClasses.uiFastscrollTarget);
				}
			};

			/**
			 * Binds fastscroll widget events
			 * @method _bindEvents
			 * @param {HTMLElement} element
			 * @protected
			 * @member ns.widget.mobile.FastScroll
			 */
			Listview.prototype._bindEvents = function (element) {
				var pageParent = selectors.getParentsByClass(element, Page.classes.uiPage)[0],
					shortcutsList = this._ui._shortcutsList;

				this._uiPageParent = pageParent;

				if (typeof parent_bindEvents === TYPE_FUNCTION) {
					parent_bindEvents.call(this, element);
				}

				if (this.options.fastscroll !== true) {
					return;
				}

				this._onPageshowBound = onPageshow.bind(null, this);
				this._onRefreshBound = fastscrollRefresh.bind(null, this);
				this._onShortcutsListMouseOverBound = onShortcutsListMouseOver.bind(null, this);
				this._onShortcutsListMouseOutBound = onShortcutsListMouseOut.bind(null, this);

				if (pageParent) {
					pageParent.addEventListener("pageshow", this._onPageshowBound, true);
				}

				element.addEventListener("updatelayout", this._onRefreshBound, false);
				window.addEventListener("resize", this._onRefreshBound, false);
				window.addEventListener("orientationchange", this._onRefreshBound, false);

				if (shortcutsList) {
					shortcutsList.addEventListener("vmousedown", this._onShortcutsListMouseOverBound, false);
					shortcutsList.addEventListener("vmousemove", this._onShortcutsListMouseOverBound, false);
					shortcutsList.addEventListener("vmouseover", this._onShortcutsListMouseOverBound, false);

					shortcutsList.addEventListener("vmouseup", this._onShortcutsListMouseOutBound, false);
					shortcutsList.addEventListener("vmouseout", this._onShortcutsListMouseOutBound, false);
				}
			};

			/**
			 * Destroy FastScroll widget
			 *
			 * Destroy current widget.
			 *
			 *		@example
			 *		<div data-role="page" id="main">
			 *			<div data-role="content">
			 *				<ul id="list" data-role="listview" data-fastscroll="true">
			 *					<li data-role="list-divider">A</li>
			 *					<li>Anton</li>
			 *					<li>Arabella</li>
			 *					<li data-role="list-divider">B</li>
			 *					<li>Barry</li>
			 *					<li>Bily</li>
			 *				</ul>
			 *			</div>
			 *		</div>
			 *		<script>
			 *			var element = document.getElementById("list"),
			 *				fastscroll = tau.widget.FastScroll(element);
			 *			fastscroll.destroy();
			 *		</script>
			 *
			 * or JQueryMobile notation:
			 *
			 *		@example
			 *		<div data-role="page" id="main">
			 *			<div data-role="content">
			 *				<ul data-role="listview" data-fastscroll="true" id="fastscroll">
			 *					<li data-role="list-divider">A</li>
			 *					<li>Anton</li>
			 *					<li>Arabella</li>
			 *					<li data-role="list-divider">B</li>
			 *					<li>Barry</li>
			 *					<li>Bily</li>
			 *				</ul>
			 *			</div>
			 *		</div>
			 *		<script>
			 *			$("#list").fastscroll("destroy");
			 *		</script>
			 *
			 * @method destroy
			 * @member ns.widget.mobile.FastScroll
			 */

			/**
			 * Unbinds fastscroll widget events
			 * @method _destroy
			 * @protected
			 * @member ns.widget.mobile.FastScroll
			 */
			Listview.prototype._destroy = function () {
				var element = this.element,
					pageParent = this._uiPageParent,
					shortcutsList = this._ui._shortcutsList,
					shortcutsListItems,
					listItem,
					shortcutsListItemsLength,
					i;
				if (typeof parent_destroy === TYPE_FUNCTION) {
					parent_destroy.call(this);
				}

				if (pageParent) {
					pageParent.removeEventListener("pageshow", this._onPageshowBound);
				}

				element.removeEventListener("updatelayout", this._onRefreshBound);
				window.removeEventListener("resize", this._onRefreshBound);
				window.removeEventListener("orientationchange", this._onRefreshBound);

				if (shortcutsList) {
					shortcutsList.removeEventListener("vmousedown", this._onShortcutsListMouseOverBound);
					shortcutsList.removeEventListener("vmousemove", this._onShortcutsListMouseOverBound);
					shortcutsList.removeEventListener("vmouseover", this._onShortcutsListMouseOverBound);

					shortcutsList.removeEventListener("vmouseup", this._onShortcutsListMouseOutBound);
					shortcutsList.removeEventListener("vmouseout", this._onShortcutsListMouseOutBound);

					shortcutsListItems = shortcutsList.getElementsByTagName("li");

					for (i = 0, shortcutsListItemsLength = shortcutsListItems.length; i < shortcutsListItemsLength; i++) {
						listItem = shortcutsListItems[i];
						listItem.removeEventListener("vmousedown", this._onListItemVMouseDownBound);
						listItem.removeEventListener("vmouseup", this._onListItemVMouseUpBound);
					}
				}

				events.trigger(element, eventType.DESTROYED, {
					widget: "FastScroll",
					parent: pageParent
				});
			};

			/**
			 * Creates map of deviders
			 * @method _createDividerMap
			 * @protected
			 * @member ns.widget.mobile.FastScroll
			 */
			Listview.prototype._createDividerMap = function () {
				var primaryCharacterSet = null,
					secondCharacterSet = null,
					numberSet = "0123456789",
					dividers = this.element.getElementsByClassName(ns.widget.mobile.ListDivider.classes.uiLiDivider),
					map = {},
					indexChar,
					i,
					j,
					length,
					dividersLength = dividers.length;

				if (primaryCharacterSet === null) {
					primaryCharacterSet = "";
					for (i = 0; i < dividersLength; i++) {
						primaryCharacterSet = makeCharacterSet(dividers[i], primaryCharacterSet);
					}
				}

				for (i = 0, length = primaryCharacterSet.length; i < length; i++) {
					indexChar = primaryCharacterSet.charAt(i);
					for (j = 0; j < dividersLength; j++) {
						matchToDivider(dividers[j], indexChar, map);
					}
				}

				if (secondCharacterSet !== null) {
					for (i = 0, length = secondCharacterSet.length; i < length; i++) {
						indexChar = secondCharacterSet.charAt(i);
						for (j = 0; j < dividersLength; j++) {
							matchToDivider(dividers[j], indexChar, map);
						}
					}
				}

				for (i = 0; i < dividersLength; i++) {
					if (numberSet.search(dividers[i].innerText) !== -1) {
						map.number = dividers[i];
						break;
					}
				}

				this._dividerMap = map;
				this._charSet = primaryCharacterSet + secondCharacterSet;
			};

			/**
			 * Finds closes divider
			 * @method _findClosestDivider
			 * @param {string} targetChar
			 * @protected
			 * @member ns.widget.mobile.FastScroll
			 */
			Listview.prototype._findClosestDivider = function (targetChar) {
				var i,
					dividerMap = this._dividerMap,
					charSet = this._charSet,
					charSetLen = charSet.length,
					targetIdx = charSet.indexOf(targetChar),
					lastDivider,
					subDivider = null;

				for (i = 0; i < targetIdx; ++i) {
					lastDivider = dividerMap[charSet.charAt(i)];
					if (lastDivider !== undefined) {
						subDivider = lastDivider;
					}
				}
				if (!subDivider) {
					for (++i; i < charSetLen; ++i) {
						lastDivider = dividerMap[charSet.charAt(i)];
						if (lastDivider !== undefined) {
							subDivider = lastDivider;
							break;
						}
					}
				}
				return subDivider;
			};

			/**
			 * Scroll listview to asked divider
			 * @method _jumpToDivider
			 * @param {HTMLElement} divider
			 * @protected
			 * @member ns.widget.mobile.FastScroll
			 */
			Listview.prototype._jumpToDivider = function (divider) {
				var dividerY = divider.offsetTop,
					ui = this._ui,
					lastListItem = ui._lastListItem,
					bottomOffset = lastListItem.offsetHeight + lastListItem.offsetTop,
					scrollviewHeight = ui._scrollView.offsetHeight,
					maxScroll = bottomOffset - scrollviewHeight,
					scrollViewBinding = engine.getBinding(ui._scrollView);

				dividerY = (dividerY > maxScroll ? maxScroll : dividerY);

				dividerY = Math.max(dividerY, 0);

				scrollViewBinding.scrollTo(0, dividerY, scrollViewBinding.scrollDuration);
			};

			/**
			 * On fastscroll item pressed
			 * @method _hitItem
			 * @param {HTMLElement} listItem
			 * @protected
			 * @member ns.widget.mobile.FastScroll
			 */
			Listview.prototype._hitItem = function (listItem) {
				var popup = this._ui._popup,
					text = listItem.innerText,
					divider,
					listItemClassList = listItem.classList,
					nextElement = listItem.nextElementSibling,
					popupStyles = popup.style;


				if (text === "#") {
					divider = this._dividerMap.number;
				} else {
					divider = this._dividerMap[text] || this._findClosestDivider(text);
				}

				if (divider) {
					this._jumpToDivider(divider);
				}

				popup.innerText = text;
				popupStyles.display = "block";
				popupStyles.width = popup.offsetHeight + 'px';
				popupStyles.marginLeft = -parseInt(popup.offsetWidth / 2) + 'px';
				popupStyles.marginTop = -parseInt(popup.offsetHeight / 2) + 'px';

				listItemClassList.add(listviewClasses.uiFastscrollHover);
				if (!listItem.previousElementSibling) {
					listItemClassList.add(listviewClasses.uiFastscrollHoverFirstItem);
				}
				if (nextElement) {
					nextElement.classList.add(listviewClasses.uiFastscrollHoverDown);
				}
			};

			/**
			 * Add focus to shortcut item
			 * @method _focusItem
			 * @param {HTMLElement} listItem
			 * @protected
			 * @member ns.widget.mobile.FastScroll
			 */
			Listview.prototype._focusItem = function (listItem) {
				this._onListItemVMouseDownBound = this._onListItemVMouseDownBound || onListItemVMouseDown.bind(null, this);
				this._onListItemVMouseUpBound = this._onListItemVMouseUpBound || onListItemVMouseUp.bind(null, this);
				listItem.addEventListener("vmouseover", this._onListItemVMouseDownBound, false);
				listItem.addEventListener("vmouseout", this._onListItemVMouseUpBound, false);
			};

			/**
			 * If max number of items is greater then 3 return array with cout of omited items.
			 * @method _omit
			 * @param {number} numOfItems
			 * @param {number} maxNumOfItems
			 * @return {?Array}
			 * @protected
			 * @member ns.widget.mobile.FastScroll
			 */
			Listview.prototype._omit = function (numOfItems, maxNumOfItems) {
				var maxGroupNum = parseInt((maxNumOfItems - 1) / 2, 10),
					numOfExtraItems = numOfItems - maxNumOfItems,
					groupPos = [],
					omitInfo = [],
					groupPosLength,
					group,
					size,
					i;

				if ((maxNumOfItems < 3) || (numOfItems <= maxNumOfItems)) {
					return null;
				}

				if (numOfExtraItems >= maxGroupNum) {
					size = 2;
					group = 1;
					groupPosLength = maxGroupNum;
				} else {
					size = maxNumOfItems / (numOfExtraItems + 1);
					group = size;
					groupPosLength = numOfExtraItems;
				}

				for (i = 0; i < groupPosLength; i++) {
					groupPos.push(parseInt(group, 10));
					group += size;
				}

				for (i = 0; i < maxNumOfItems; i++) {
					omitInfo.push(1);
				}

				for (i = 0; i < numOfExtraItems; i++) {
					omitInfo[groupPos[i % maxGroupNum]]++;
				}

				return omitInfo;
			};

			/**
			 * Creates string containing omited elements. Omits items starting from index.
			 * Max number of omited elemets is given as length parameter
			 * @method _makeOmitSet
			 * @param {number} index
			 * @param {number} length
			 * @param {string} primaryCharacterSet
			 * @return {string}
			 * @protected
			 * @member ns.widget.mobile.FastScroll
			 */
			Listview.prototype._makeOmitSet = function (index, length, primaryCharacterSet) {
				var count,
					omitSet = "";

				for (count = 0; count < length; count++) {
					omitSet += primaryCharacterSet[index + count];
				}

				return omitSet;
			};

			/**
			 * Refresh Fast Scroll widget
			 * @method _refresh
			 * @protected
			 * @member ns.widget.mobile.FastScroll
			 */
			Listview.prototype._refresh = function () {
				this._onRefreshBound = this._onRefreshBound || fastscrollRefresh.bind(this);
				this._onRefreshBound();
			};

			/**
			 * Get or set index string:
			 *
			 * You can use the _indexString_ method with the fast scroll to manage string values to be used in shortcut items:
			 *
			 *		@example
			 *		<div data-role="page" id="main">
			 *			<div data-role="content">
			 *				<ul id="fastscroll">
			 *					<li data-role="list-divider">A</li>
			 *					<li>Anton</li>
			 *					<li>Arabella</li>
			 *					<li data-role="list-divider">B</li>
			 *					<li>Barry</li>
			 *					<li>Bily</li>
			 *				</ul>
			 *			</div>
			 *		</div>
			 *		<script>
			 *			// get index string
			 *			var element = document.getElementById("fastscroll"),
			 *				fastscroll = tau.widget.FastScroll(element, {fastscroll: true});
			 *			fastscroll.indexString();
			 *
			 *			// set index string
			 *			fastscroll.indexString("A,D,J,P,W,Z");
			 *		</script>
			 *
			 * or JQueryMobile notation:
			 *
			 *		@example
			 *		<div data-role="page" id="main">
			 *			<div data-role="content">
			 *				<ul data-role="listview" data-fastscroll="true" id="fastscroll">
			 *					<li data-role="list-divider">A</li>
			 *					<li>Anton</li>
			 *					<li>Arabella</li>
			 *					<li data-role="list-divider">B</li>
			 *					<li>Barry</li>
			 *					<li>Bily</li>
			 *				</ul>
			 *			</div>
			 *		</div>
			 *		<script>
			 *			$("#fastscroll").fastscroll("indexString", "A,D,J,P,W,Z");
			 *		</script>
			 *
			 * @method indexString
			 * @param {string} [indexAlphabet] values to be used in shortcut items
			 * @member ns.widget.mobile.FastScroll
			 * @since 2.1
			 * @return {?string} Primary and secondary language
			 */
			Listview.prototype.indexString = function (indexAlphabet) {
				var characterSet;

				if (undefined === indexAlphabet) {
					return this._primaryLanguage + ":" + this._secondLanguage;
				}

				characterSet = indexAlphabet.split(":");
				this._primaryLanguage = characterSet[0];
				if (2 === characterSet.length) {
					this._secondLanguage = characterSet[1];
				}
				return null;
			};

			// definition
			ns.widget.mobile.FastScroll = Listview;
			engine.defineWidget(
				"FastScroll",
				"",
				["indexString"],
				Listview,
				"tizen"
			);
			}(window.document, ns));

/*global window, define */
/*
* Copyright  2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/*jslint plusplus: true, nomen: true */
/**
 * #Field's Container Grouping Widget
 * FieldContain widget improves the styling of labels and form elements on wider screens. It aligns the input and associated label side-by-side and breaks to stacked block-level elements below ~480px. Moreover, it adds a thin bottom border to act as a field separator.
 *
 * ##Default selectors
 * In default all div or fieldset elements with _data-role=fieldcontain_ or class _.ui-fieldcontain_ are changed to fieldcontain widget.
 *
 * ##HTML Examples
 *
 * ###Create fieldcontain by data-role
 *
 *		@example
 *		<div data-role="fieldcontain">
 *			<label for="name">Text Input:</label>
 *			<input type="text" name="name" id="name" value="" />
 *		</div>
 *
 * ###Create fieldcontain by class
 *
 *		@example
 *		<div class="ui-fieldcontain">
 *			<label for="name">Text Input:</label>
 *			<input type="text" name="name" id="name" value="" />
 *		</div>
 *
 * ## Manual constructor
 * For manual creation of fieldcontain widget you can use constructor of widget:
 *
 *		@example
 *		<div id="fieldcontain">
 *			<label for="name">Text Input:</label>
 *			<input type="text" name="name" id="name" value="" />
 *		</div>
 *
 *		<script>
 *			var fieldcontain = tau.widget.FieldContain(document.getElementById("fieldcontain"));
 *		</script>
 *
 * If jQuery library is loaded, its method can be used:
 *
 *		@example
 *		<div id="fieldcontain">
 *			<label for="name">Text Input:</label>
 *			<input type="text" name="name" id="name" value="" />
 *		</div>
 *
 *		<script>
 *			var fieldcontain = $("#fieldcontain").fieldcontain();
 *		</script>
 *
 * ##Hiding labels accessibly
 * For the sake of accessibility, the framework requires that all form elements be paired with a meaningful label. To hide labels in a way that leaves them visible to assistive technologies — for example, when letting an element's placeholder attribute serve as a label — apply the helper class ui-hidden-accessible to the label itself:
 *
 *		@example
 *		<div data-role="fieldcontain">
 *			<label for="username" class="ui-hidden-accessible">Username:</label>
 *			<input type="text" name="username" id="username" value="" placeholder="Username"/>
 *		</div>
 *
 * To hide labels within a field container and adjust the layout accordingly, add the class ui-hide-label to the field container as in the following:
 *
 *		@example
 *		<div data-role="fieldcontain" class="ui-hide-label">
 *			<label for="username">Username:</label>
 *			<input type="text" name="username" id="username" value="" placeholder="Username"/>
 *		</div>
 *
 * While the label will no longer be visible, it will be available to assisitive technologies such as screen readers.
 *
 * Because radio and checkbox buttons use the label to display the button text you can't use ui-hidden-accessible in this case. However, the class ui-hide-label can be used to hide the legend element:
 *
 *		@example
 *		<div data-role="fieldcontain" class="ui-hide-label">
 *			<fieldset data-role="controlgroup">
 *				<legend>Agree to the terms:</legend>
 *				<input type="checkbox" name="checkbox-agree" id="checkbox-agree" class="custom" />
 *				<label for="checkbox-agree">I agree</label>
 *			</fieldset>
 *		</div>
 *
 * ##Methods
 *
 * To call method on widget you can use one of existing API:
 *
 * First API is from tau namespace:
 *
 *		@example
 *		var fieldcontainElement = document.getElementById("fieldcontain"),
 *			fieldcontain = tau.widget.FieldContain(fieldcontainElement);
 *
 *		fieldcontain.methodName(methodArgument1, methodArgument2, ...);
 *
 * Second API is jQuery Mobile API and for call _methodName_ you can use:
 *
 *		@example
 *		$("#fieldcontain").fieldcontain("methodName", methodArgument1, methodArgument2, ...);
 *
 *
 * @class ns.widget.mobile.FieldContain
 * @extends ns.widget.BaseWidget
 */
(function (document, ns) {
	
				var FieldContain = function () {
					return;
				},
				/**
				 * @property {Object} Widget Alias for {@link ns.widget.BaseWidget}
				 * @member ns.widget.mobile.FieldContain
				 * @private
				 * @static
				 */
				BaseWidget = ns.widget.mobile.BaseWidgetMobile,
				/**
				 * @property {Object} engine Alias for class ns.engine
				 * @member ns.widget.mobile.FieldContain
				 * @private
				 * @static
				 */
				engine = ns.engine;

			/**
			 * Dictionary for fieldcontain related css class names
			 * @property {Object} classes
			 * @member ns.widget.mobile.FieldContain
			 * @static
			 * @readonly
			 */
			FieldContain.classes = {
				uiFieldContain: "ui-field-contain",
				uiBody: "ui-body",
				uiBr: "ui-br"
			};

			FieldContain.prototype = new BaseWidget();

			/**
			 * Build structure of fieldcontain widget
			 * @method _build
			 * @param {HTMLElement} element
			 * @return {HTMLElement}
			 * @protected
			 * @member ns.widget.mobile.FieldContain
			 */
			FieldContain.prototype._build = function (element) {
				var childNodes = element.childNodes,
					classList = element.classList,
					i = childNodes.length,
					childNode,
					classes = FieldContain.classes;
				// adding right classes
				classList.add(classes.uiFieldContain);
				classList.add(classes.uiBody);
				classList.add(classes.uiBr);
				// removing whitespace between label and form element
				while (--i >= 0) {
					childNode = childNodes[i];
					if (childNode.nodeType === 3 && !/\S/.test(childNode.nodeValue)) {
						element.removeChild(childNode);
					}
				}
				return element;
			};

			/**
			 * Removes the widget.
			 *
			 * This will return the element's style back to its pre-init state.
			 *
			 *      @example
			 *      <div id="fieldcontain" data-role="fieldcontain" class="ui-hide-label">
			 *          <label for="username">Username:</label>
			 *          <input type="text" name="username" id="username" value="" placeholder="Username"/>
			 *      </div>
			 *
			 *      <script>
			 *          var fieldcontainWidget = tau.widget.FieldContain(document.getElementById("fieldcontain"));
			 *          fieldcontainWidget.destroy();
			 *      </script>
			 *
			 * If jQuery is loaded:
			 *
			 *      @example
			 *      <div id="fieldcontain" data-role="fieldcontain" class="ui-hide-label">
			 *          <label for="username">Username:</label>
			 *          <input type="text" name="username" id="username" value="" placeholder="Username"/>
			 *      </div>
			 *
			 *      <script>
			 *          $("#fieldcontain").fieldcontain("destroy");
			 *      </script>
			 *
			 * @method destroy
			 * @inherited
			 * @member ns.widget.mobile.FieldContain
			 */
			/**
			 * Remove structure of fieldcontain widget
			 * @method _destroy
			 * @param {HTMLElement} element
			 * @protected
			 * @member ns.widget.mobile.FieldContain
			 */
			FieldContain.prototype._destroy = function (element) {
				var classList = element.classList,
					classes = FieldContain.classes;
				// removing classes added during building
				classList.remove(classes.uiFieldContain);
				classList.remove(classes.uiBody);
				classList.remove(classes.uiBr);
			};

			/**
			 * The function "value" is not supported in this widget.
			 *
			 * @method value
			 * @inherited
			 * @chainable
			 * @member ns.widget.mobile.FieldContain
			 */

			/**
			 * Disable the fieldcontain
			 *
			 * Method adds disabled attribute on fieldcontain and changes look of fieldcontain to disabled state.
			 *
			 *      @example
			 *      <div id="fieldcontain" data-role="fieldcontain" class="ui-hide-label">
			 *          <label for="username">Username:</label>
			 *          <input type="text" name="username" id="username" value="" placeholder="Username"/>
			 *      </div>
			 *
			 *      <script>
			 *          var fieldcontainWidget = tau.widget.FieldContain(document.getElementById("fieldcontain"));
			 *          fieldcontainWidget.disable();
			 *      </script>
			 *
			 * If jQuery is loaded:
			 *
			 *      @example
			 *      <div id="fieldcontain" data-role="fieldcontain" class="ui-hide-label">
			 *          <label for="username">Username:</label>
			 *          <input type="text" name="username" id="username" value="" placeholder="Username"/>
			 *      </div>
			 *
			 *      <script>
			 *          $("#fieldcontain").fieldcontain("disable");
			 *      </script>
			 *
			 * @method disable
			 * @inherited
			 * @chainable
			 * @member ns.widget.mobile.FieldContain
			 */

			/**
			 * Enable the fieldcontain
			 *
			 * Method removes disabled attribute on fieldcontain and changes look of fieldcontain to enabled state.
			 *
			 *      @example
			 *      <div id="fieldcontain" data-role="fieldcontain" class="ui-hide-label">
			 *          <label for="username">Username:</label>
			 *          <input type="text" name="username" id="username" value="" placeholder="Username"/>
			 *      </div>
			 *
			 *      <script>
			 *          var fieldcontainWidget = tau.widget.FieldContain(document.getElementById("fieldcontain"));
			 *          fieldcontainWidget.enable();
			 *      </script>
			 *
			 * If jQuery is loaded:
			 *
			 *      @example
			 *      <div id="fieldcontain" data-role="fieldcontain" class="ui-hide-label">
			 *          <label for="username">Username:</label>
			 *          <input type="text" name="username" id="username" value="" placeholder="Username"/>
			 *      </div>
			 *
			 *      <script>
			 *          $("#fieldcontain").fieldcontain("enable");
			 *      </script>
			 *
			 * @method enable
			 * @inherited
			 * @chainable
			 * @member ns.widget.mobile.FieldContain
			 */

			/**
			 * The function "refresh" is not supported in this widget.
			 *
			 * @method refresh
			 * @inherited
			 * @chainable
			 * @member ns.widget.mobile.FieldContain
			 */

			/**
			 * The function "option" is not supported in this widget.
			 * This widget does not have any options.
			 *
			 * @method option
			 * @inherited
			 * @member ns.widget.mobile.FieldContain
			 */

			/**
			 * Trigger an event on widget's element.
			 *
			 *      @example
			 *      <div id="fieldcontain" data-role="fieldcontain" class="ui-hide-label">
			 *          <label for="username">Username:</label>
			 *          <input type="text" name="username" id="username" value="" placeholder="Username"/>
			 *      </div>
			 *
			 *      <script>
			 *          var fieldcontainWidget = tau.widget.FieldContain(document.getElementById("fieldcontain"));
			 *          fieldcontainWidget.trigger("eventName");
			 *      </script>
			 *
			 * If jQuery is loaded:
			 *
			 *      @example
			 *      <div id="fieldcontain" data-role="fieldcontain" class="ui-hide-label">
			 *          <label for="username">Username:</label>
			 *          <input type="text" name="username" id="username" value="" placeholder="Username"/>
			 *      </div>
			 *
			 *      <script>
			 *          $("#fieldcontain").fieldcontain("trigger", "eventName");
			 *      </script>
			 *
			 * @method trigger
			 * @inherited
			 * @param {string} eventName the name of event to trigger
			 * @param {?*} [data] additional object to be carried with the event
			 * @param {boolean} [bubbles=true] indicating whether the event bubbles up through the DOM or not
			 * @param {boolean} [cancelable=true] indicating whether the event is cancelable
			 * @return {boolean} false, if any callback invoked preventDefault on event object
			 * @member ns.widget.mobile.FieldContain
			 */

			/**
			 * Add event listener to widget's element.
			 *
			 *      @example
			 *      <div id="fieldcontain" data-role="fieldcontain" class="ui-hide-label">
			 *          <label for="username">Username:</label>
			 *          <input type="text" name="username" id="username" value="" placeholder="Username"/>
			 *      </div>
			 *
			 *      <script>
			 *          var fieldcontainWidget = tau.widget.FieldContain(document.getElementById("fieldcontain"));
			 *
			 *          fieldcontainWidget.on("eventName", function() {
			 *                console.log("event fires");
			 *          });
			 *      </script>
			 *
			 * If jQuery is loaded:
			 *
			 *      @example
			 *      <div id="fieldcontain" data-role="fieldcontain" class="ui-hide-label">
			 *          <label for="username">Username:</label>
			 *          <input type="text" name="username" id="username" value="" placeholder="Username"/>
			 *      </div>
			 *
			 *      <script>
			 *          $("#fieldcontain").fieldcontain("on", "eventName", function() {
			 *                console.log("event fires");
			 *          });
			 *      </script>
			 *
			 * @method on
			 * @inherited
			 * @param {string} eventName the name of event
			 * @param {Function} listener function call after event will be trigger
			 * @param {boolean} [useCapture=false] useCapture param tu addEventListener
			 * @member ns.widget.mobile.FieldContain
			 */

			/**
			 * Remove event listener to widget's element.
			 *
			 *      @example
			 *      <div id="fieldcontain" data-role="fieldcontain" class="ui-hide-label">
			 *          <label for="username">Username:</label>
			 *          <input type="text" name="username" id="username" value="" placeholder="Username"/>
			 *      </div>
			 *
			 *      <script>
			 *          var fieldcontainWidget = tau.widget.FieldContain(document.getElementById("fieldcontain")),
			 *              callback = function () {
			 *                  console.log("event fires");
			 *              });
			 *
			 *          // add callback on event "eventName"
			 *          fieldcontainWidget.on("eventName", callback);
			 *          // ...
			 *          // remove callback on event "eventName"
			 *          fieldcontainWidget.off("eventName", callback);
			 *      </script>
			 *
			 * If jQuery is loaded:
			 *
			 *      @example
			 *      <div id="fieldcontain" data-role="fieldcontain" class="ui-hide-label">
			 *          <label for="username">Username:</label>
			 *          <input type="text" name="username" id="username" value="" placeholder="Username"/>
			 *      </div>
			 *
			 *      <script>
			 *          // add callback on event "eventName"
			 *          $("#fieldcontain").fieldcontain("on", "eventName", callback);
			 *          // ...
			 *          // remove callback on event "eventName"
			 *          $("#fieldcontain").fieldcontain("off", "eventName", callback);
			 *      </script>
			 *
			 * @method off
			 * @inherited
			 * @param {string} eventName the name of event
			 * @param {Function} listener function call after event will be trigger
			 * @param {boolean} [useCapture=false] useCapture param tu addEventListener
			 * @member ns.widget.mobile.FieldContain
			 */

			// definition
			ns.widget.mobile.FieldContain = FieldContain;
			engine.defineWidget(
				"FieldContain",
				"[data-role='fieldcontain'], .ui-fieldcontain",
				[],
				FieldContain,
				"mobile"
			);
			}(window.document, ns));

/*global window, define */
/*
* Copyright  2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/*jslint nomen: true */
/**
 * #Control Group Widget
 * Controlgroup widget improves the styling of a group of buttons by grouping them to form a single block.
 *
 * ##Default selectors
 * In default all divs with _data-role=controlgroup_ are changed to Controlgroup widget.
 *
 * ##HTML Examples
 *
 * ### Create Controlgroup
 *
 *		@example
 *		<div data-role="controlgroup">
 *			<a href="#" data-role="button">Yes</a>
 *			<a href="#" data-role="button">No</a>
 *			<a href="#" data-role="button">Cancel</a>
 *		</div>
 *
 * @class ns.widget.mobile.Controlgroup
 * @extends ns.widget.BaseWidget
 */
(function (document, ns) {
	
				/**
			* Alias for class ns.widget.mobile.Controlgroup
			* @method Controlgroup
			* @member ns.widget.mobile.Controlgroup
			* @private
			* @static
			*/
			var Controlgroup = function () {
					/**
					 * Object with default options
					 * @property {Object} options
					 * @property {"vertical"|"horizontal"} [options.type="vertical"] Direction of widget
					 * @property {boolean} [options.shadow=false] Shadow of Controlgroup
					 * @property {boolean} [options.excludeInvisible=false] Flag specifying exclusion of invisible elements
					 * @property {boolean} [options.mini=false] Size of Controlgroup
					 * @member ns.widget.mobile.Controlgroup
					 */
					this.options = {
						type: 'vertical',
						shadow: false,
						excludeInvisible: false,
						mini: false
					};
				},
				/**
				* @property {Object} Widget Alias for {@link ns.widget.BaseWidget}
				* @member ns.widget.mobile.Controlgroup
				* @private
				* @static
				*/
				BaseWidget = ns.widget.mobile.BaseWidgetMobile,
				/**
				* @property {Object} engine Alias for class ns.engine
				* @member ns.widget.mobile.Controlgroup
				* @private
				* @static
				*/
				engine = ns.engine,
				/**
				* @property {Object} dom Alias for class ns.util.DOM
				* @member ns.widget.mobile.Controlgroup
				* @private
				* @static
				*/
				dom = ns.util.DOM,
				/**
				* @property {Object} selectors Alias for class ns.util.selectors
				* @private
				* @static
				*/
				selectors = ns.util.selectors,
				/**
				* @property {Function} slice Alias for function Array.slice
				* @private
				* @static
				*/
				slice = [].slice;

			Controlgroup.prototype = new BaseWidget();

			/**
			 * Dictionary for Controlgroup related css class names
			 * @property {Object} classes
			 * @member ns.widget.mobile.Controlgroup
			 * @static
			 */
			Controlgroup.classes = {
				cornerAll: 'ui-btn-corner-all',
				cornerTop: 'ui-corner-top',
				cornerBottom: 'ui-corner-bottom',
				cornerLeft: 'ui-corner-left',
				cornerRight: 'ui-corner-right',
				controlGroupLast: 'ui-controlgroup-last',
				shadow: 'ui-shadow',
				mini: 'ui-mini',
				controlGroup: 'ui-controlgroup',
				typePrefix: 'ui-controlgroup-',
				controlGroupLabel: 'ui-controlgroup-label',
				controlGroupControls: 'ui-controlgroup-controls',
				controlGroupCornerAll: 'ui-corner-all'
			};

			/**
			* Applies css styles to Controlgroup elements
			* @method flipClasses
			* @param {Array} elements Array of Controlgroup elements
			* @param {Array} cornersClasses Array of css styles for first and last element
			* @private
			* @static
			* @member ns.widget.mobile.Controlgroup
			*/
			function flipClasses(elements, cornersClasses) {
				var len = elements.length,
					lastElementClassList,
					classes = Controlgroup.classes;

				if (!len) {
					return;
				}

				elements.forEach(function (element) {
					var classList = element.classList;

					classList.remove(classes.cornerAll);
					classList.remove(classes.cornerTop);
					classList.remove(classes.cornerBottom);
					classList.remove(classes.cornerLeft);
					classList.remove(classes.cornerRight);
					classList.remove(classes.controlgroupLast);
					classList.remove(classes.shadow);
				});

				elements[0].classList.add(cornersClasses[0]);
				lastElementClassList = elements[len - 1].classList;
				lastElementClassList.add(cornersClasses[1]);
				lastElementClassList.add(classes.controlGroupLast);
			}

			/**
			* Builds structure of Controlgroup widget
			* @method _build
			* @param {HTMLElement} element
			* @return {HTMLElement}
			* @protected
			* @member ns.widget.mobile.Controlgroup
			* @instance
			*/
			Controlgroup.prototype._build = function (element) {
				var classes = Controlgroup.classes,
					elementClassList = element.classList,
					options = this.options,
					groupLegend = selectors.getChildrenByTag(element, 'legend'),
					groupHeading = selectors.getChildrenByClass(element, classes.controlGroupLabel),
					groupControls,
					cornersClasses,
					legend,
					content;

				/*
				* if (groupControls.length) {
				*   //@todo unwrap content
				* }
				*/

				dom.wrapInHTML(element.childNodes, "<div class='" + classes.controlGroupControls + "'></div>");
				groupControls = selectors.getChildrenByClass(element, classes.controlGroupControls)[0];


				if (groupLegend.length) {
					//existing label is replaced with stylable div
					legend = document.createElement('div');
					legend.classList.add(classes.controlGroupLabel);
					legend.innerHTML = groupLegend[0].innerHTML;
					dom.insertNodesBefore(element.childNodes[0], legend);
					groupLegend.forEach(function (item) {
						item.parentNode.removeChild(item);
					});
				} else if (groupHeading.length) {
					dom.insertNodesBefore(element.childNodes[0], groupHeading);
				}

				cornersClasses = options.type === 'horizontal' ?
						[classes.cornerLeft, classes.cornerRight] : [classes.cornerTop, classes.cornerBottom];

				elementClassList.add(classes.controlGroupCornerAll);
				elementClassList.add(classes.controlGroup);
				elementClassList.add(classes.typePrefix + options.type);

				//Make all the control group elements the same width
				if (groupControls) {
					this._setWidthForButtons(groupControls);
				}

				content = slice.call(element.querySelectorAll('.ui-btn')).filter(function (item) {
					//@todo filter visiblity when excludeInvisible option is set
					return !item.classList.contains('ui-slider-handle');
				});

				if (options.shadow) {
					elementClassList.add(classes.shadow);
				}

				if (options.mini) {
					elementClassList.add(classes.mini);
				}

				flipClasses(content, cornersClasses);
				flipClasses(slice.call(element.querySelectorAll('.ui-btn-inner')), cornersClasses);

				return element;
			};

			Controlgroup.prototype._setWidthForButtons = function (groupControls) {
				var controlElements,
					controlElementsLength,
					widthSize,
					i;
				controlElements = selectors.getChildrenByTag(groupControls, 'a');
				controlElementsLength = controlElements.length;
				widthSize = 100 / controlElementsLength;
				for(i = 0; i < controlElementsLength; i++) {
					engine.instanceWidget(controlElements[i], 'Button');
					controlElements[i].style.width = widthSize + '%';
				}
			};

			// definition
			ns.widget.mobile.Controlgroup = Controlgroup;
			engine.defineWidget(
				"Controlgroup",
				"[data-role='controlgroup'], .ui-controlgroup",
				[],
				Controlgroup,
				'mobile'
			);

			}(window.document, ns));

/*global window, define */
/*
* Copyright  2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/*jslint nomen: true, plusplus: true */
/**
 * #Popup Widget
 * Widget handles creating and managing popup windows.
 *
 * ##Default selectors
 * In default all elements with _data-role=popup_ or CSS class _.ui-popup_ are changed to Tizen WebUI popups.
 *
 * ##HTML Examples
 *
 * ###Create simple popup from div
 *
 *		@example
 *		<div id="popup" data-role="popup">
 *			<p>This is a completely basic popup, no options set.</p>
 *		</div>
 *		<!-- link related with popup-->
 *		<a href="#popup">Click to open popup</a>
 *
 * ###Create simple popup positioned to window
 *
 * Popup inherits value of option _positionTo_ from property _data-position-to_ set in link.
 *
 *		@example
 *		<!--definition of link, which opens popup and sets its position-->
 *		<a href="#center_info" data-position-to="window">Click to open popup</a>
 *		<!--definition of popup, which inherites property position from link-->
 *		<div id="center_info" data-role="popup" class="center_info">
 *			<div class="ui-popup-text">
 *				<p>Pop-up dialog box, a child window that blocks user interaction to the parent windows</p>
 *			</div>
 *		</div>
 *
 * ###Create popup with title and button
 *
 *		@example
 *		<a href="#center_title_1btn">Click to open popup</a>
 *		<!--definition of popup with a title and button-->
 *		<div id="center_title_1btn" data-role="popup" class="center_title_1btn">
 *			<div class="ui-popup-title">
 *				<h1>Popup title</h1>
 *			</div>
 *			<div class="ui-popup-text">
 *				Pop-up dialog box, a child window that blocks user interaction to the parent windows
 *			</div>
 *			<div class="ui-popup-button-bg">
 *				<a data-role="button" data-rel="back" data-inline="true">Button</a>
 *			</div>
 *		</div>
 *
 * ###Create popup with menu
 *
 * A menu can be created by placing listview inside a popup.
 *
 *		@example
 *		<a href="#center_liststyle_1btn">Click to open popup</a>
 *		<div id="center_liststyle_1btn" data-role="popup" class="center_liststyle_1btn">
 *			<div class="ui-popup-title">
 *				<h1>Popup title</h1>
 *			</div>
 *			<div class="ui-popup-scroller-bg" data-scroll="y">
 *				<ul data-role="listview" data-icon="1line-textonly">
 *					<li><a href="#">List item 1</a></li>
 *					<li><a href="#">List item 2</a></li>
 *				</ul>
 *			</div>
 *			<div class="ui-popup-button-bg">
 *				<a data-role="button" data-rel="back" data-inline="true">Cancel</a>
 *			</div>
 *		</div>
 *
 * ###Create popup with nested menu
 *
 * A nested menu can be created by placing collapsible-set widget with listview elements.
 *
 *		@example
 *		<a href="#popupNested">Click to open popup</a>
 *		<div id="popupNested" data-role="popup">
 *			<div data-role="collapsible-set" data-collapsed-icon="arrow-r" data-expanded-icon="arrow-d">
 *				<div data-role="collapsible">
 *					<h2>First menu</h2>
 *					<ul data-role="listview">
 *						<li><a href="#" >Item 1</a></li>
 *						<li><a href="#" >Item 2</a></li>
 *					</ul>
 *				</div>
 *				<div data-role="collapsible">
 *					<h2>Second menu</h2>
 *					<ul data-role="listview">
 *						<li><a href="#" >Item 1</a></li>
 *						<li><a href="#" >Item 2</a></li>
 *					</ul>
 *				</div>
 *			</div>
 *		</div>
 *
 * ###Create popup with form
 *
 * A form can be created by placing inputs elements inside popup.
 *
 *		@example
 *		<a href="#textbox_popup">Click to open popup</a>
 *		<div id="textbox_popup" data-role="popup" class="center_title_2btn">
 *			<div class="ui-popup-title">
 *				<h1>PopupTest<h1>
 *			</div>
 *			<div class="ui-popup-text">
 *				<input type="text" size="20" />
 *				<input type="text" size="20" />
 *			</div>
 *			<div class="ui-popup-button-bg">
 *				<a data-role="button" id="btn_textbox_popup_cancel" data-inline="true">Cancel</a>
 *				<a data-role="button" data-rel="back" data-inline="true">OK</a>
 *			</div>
 *		</div>
 *
 * ##Manual constructor
 * For manual creation of popup widget you can use constructor of widget:
 *
 *		@example
 *		<div id="popup">
 *			<p>This is a completely basic popup, no options set.</p>
 *		</div>
 *
 *		<script>
 *			var popupElement = document.getElementById("popup"),
 *				popup = tau.widget.Popup(popupElement);
 *			popup.open();
 *		</script>
 *
 * If jQuery library is loaded, its method can be used:
 *
 *		@example
 *		<div id="popup">
 *			<p>This is a completely basic popup, no options set.</p>
 *		</div>
 *
 *		<script>
 *			var popup = $("#popup").popup();
 *			popup.popup("open");
 *		</script>
 *
 * ##Context popup with arrow
 *
 * If property _id_ is set in link and option _positionTo="origin"_ in popup, the context popup will be opened after clicking.
 *
 *		@example
 *		<!-- definition of link, which opens popup with id popup in context style with arrow -->
 *		<a href="#popup" id="linkId" data-position-to="origin" data-role="button" data-inline="true">Click to open context popup</a>
 *		<div id="popup" data-role="popup">
 *			<p>This is a completely basic context popup, no options set.</p>
 *		</div>
 *
 * Be award that option _positionTo_ has value "origin" in popup by default. However, the property _positionTo_ is inherited from related link and this inherited value has higher priority during opening process and overwrites the previous value. So, if we do not change it in popup and do not set value of _data-position-to_ other than "origin" in link, popup connected with link will be always opened in context style.
 *
 * To be sure that popup will be opened in context style with arrow, we can set properties _data-position-to="origin"_ as well as _id_ in the related with popup link as in the example above.
 *
 * Moreover, the same resulte can be achieve by setting only _id_ and not setting _positionTo_ in link because popup has value "origin" for option _positionTo_ by default.
 *
 *		@example
 *		<!-- in link id is set -->
 *		<a href="#popup" id="linkId" data-role="button" data-inline="true">Click to open context popup</a>
 *		<div id="popup" data-role="popup">
 *			<p>This is a completely basic popup, no options set.</p>
 *		</div>
 *
 *
 * After building, the value of option _positionTo_ can be changed by using method _option_.
 *
 *		@example
 *		<a href="#popup" id="linkId" data-role="button" data-inline="true">Click to open context popup</a>
 *		<div id="popup" data-role="popup">
 *			<p>This is a completely basic popup, no options set.</p>
 *		</div>
 *
 *		<script>
 *			// changing value of option positionTo by method option
 *			var popupWidget = tau.widget.Popup(document.getElementById("popup"));
 *			popupWidget.option("positionTo", "origin");
 *		</script>
 *
 * If jQuery is loaded:
 *
 *		@example
 *		<a href="#popup" id="linkId" data-role="button" data-inline="true">Click to open context popup</a>
 *		<div id="popup" data-role="popup">
 *			<p>This is a completely basic popup, no options set.</p>
 *		</div>
 *
 *		<script>
 *			// changing value of option positionTo by method option
 *			$("#popup").popup("option", "positionTo", "origin");
 *		</script>
 *
 *
 * Context popup can be created also manually for elements different than link by pushing options such as _positionTo_ and _link to method _open_.
 *
 *		@example
 *		<!-- element with no properties - popup will be opened next to it in context style manually -->
 *		<div id="linkId">Click to open context popup</div>
 *		<div id="popup" data-role="popup">
 *			<p>This is a completely basic popup, no options set.</p>
 *		</div>
 *
 *		<script>
 *			// set opening popup on click event
 *			document.getElementById("linkId").addEventListener("click", function () {
 *				// open context popup
 *				var popupWidget = tau.widget.Popup(document.getElementById("popup"));
 *				// opening with options
 *				popupWidget.open({link: "linkId", positionTo: "origin"});
 *			});
 *		</script>
 *
 * If jQuery is loaded:
 *
 *		@example
 *		<!-- element with no properties - popup will be opened next to it in context style manually -->
 *		<div id="linkId">Click to open context popup</div>
 *		<div id="popup" data-role="popup">
 *			<p>This is a completely basic popup, no options set.</p>
 *		</div>
 *
 *		<script>
 *			// set opening popup on click event
 *			$("#linkId").on("click", function () {
 *				// opening with options
 *				$("#popup").popup("open", {link: "linkId", positionTo: "origin"});
 *			});
 *		</script>
 *
 * These options can be also set globally and then method _open_ can be called without options. However, this solution can be used only for TAU API.
 *
 *		@example
 *		<!-- element with no properties - popup will be opened next to it in context style manually -->
 *		<div id="linkId">Link for popup</div>
 *		<div id="popup" data-role="popup">
 *			<p>This is a completely basic popup, no options set.</p>
 *		</div>
 *
 *		<script>
 *			// set options
 *			var popupWidget = tau.widget.Popup(document.getElementById("popup"));
 *			popupWidget.option({positionTo: "origin", link: "linkId"}); // here we set positionTo and id of link, which sets placement of popup
 *
 *			// set opening popup on click event
 *			document.getElementById("linkId").addEventListener("click", function () {
 *				//if options are set, we can call method open without options
 *				popupWidget.open();
 *			});
 *		</script>
 *
 * For jQuery API, id of link has to be always added as a option:
 *
 *		@example
 *		<!-- element with no properties - popup will be opened next to it in context style manually -->
 *		<div id="linkId">Link for popup</div>
 *		<div id="popup" data-role="popup">
 *			<p>This is a completely basic popup, no options set.</p>
 *		</div>
 *
 *		<script>
 *			// set option positionTo
 *			$("#popup").popup("option", "positionTo", "origin");
 *
 *			// set opening popup on click event
 *			$("#linkId").on("click", function () {
 *				// for jQuery API, link has to be added as a option
 *				$("#popup").popup("open", {link: "linkId"});
 *			});
 *		</script>
 *
 *
 * ##Special classes
 *
 * There are some special CSS classes, which changes the style of popup:
 *
 *  - _center_info_ - basic pop-up message<br>
 *  - _center_title_ - pop-up message with a title<br>
 *  - _center_basic_1btn_ - pop-up message with 1 button<br>
 *  - _center_basic_2btn_ - pop-up message with 2 horizontal buttons<br>
 *  - _center_title_1btn_ - pop-up message with a title and 1 button<br>
 *  - _center_title_2btn_ - pop-up message with a title and 2 horizontal buttons<br>
 *  - _center_title_3btn_ - pop-up message with a title and 3 horizontal buttons<br>
 *  - _center_button_vertical_ - pop-up message with vertical buttons<br>
 *  - _center_checkbox_ - pop-up message with a check box<br>
 *  - _center_liststyle_1btn_ - pop-up message with a list and 1 button<br>
 *  - _center_liststyle_2btn_ - pop-up message with a list and 2 horizontal buttons<br>
 *  - _center_liststyle_3btn_ - pop-up message with a list and 3 horizontal buttons<br>
 *
 * ##Methods
 *
 * To call method on widget you can use one of existing API:
 *
 * First API is from tau namespace:
 *
 *		@example
 *		var popupElement = document.getElementById("popup"),
 *			popup = tau.widget.Popup(popupElement);
 *
 *		popup.methodName(methodArgument1, methodArgument2, ...);
 *
 * Second API is jQuery Mobile API and for call _methodName_ you can use:
 *
 *		@example
 *		$(".selector").popup("methodName", methodArgument1, methodArgument2, ...);
 *
 * ##Opening popup
 * There are two ways to open popup.
 *
 * ###Opening by clicking on link
 *
 * If link has _id_ of popup set as value of property _href_, then this popup will be opened after clicking on it.
 *
 *		@example
 *		<!--definition of link, which opens popup with id popup-->
 *		<a href="#popup">Click to open popup</a>
 *		<div id="popup" data-role="popup">
 *			<p>This is a completely basic popup, no options set.</p>
 *		</div>
 *
 * Be award that context popup with arrow will be opened if link has _id_ property set and _data-position-to="origin"_  as in this example:
 *
 *		@example
 *		<!--definition of link, which opens context popup with id popup-->
 *		<a href="#popup" id="linkId" data-position-to="origin" data-role="button" data-inline="true">Click to open context popup</a>
 *		<div id="popup" data-role="popup">
 *			<p>This is a completely basic popup, no options set.</p>
 *		</div>
 *
 * To open window popup, property _data-position-to="window"_ must be set in link or popup.
 *
 *		@example
 *		<!--definition of link, which opens window popup with id popup-->
 *		<a href="#popup" id="linkId" data-position-to="window">Click to open popup</a>
 *		<div id="popup" data-role="popup">
 *			<p>This is a completely basic popup, no options set.</p>
 *		</div>
 *
 * ###Opening manually
 *
 * To open popup with _id_ "popup", tau namespace can be used:
 *
 *		@example
 *		<div id="popup">
 *			<p>This is a completely basic popup, no options set.</p>
 *		</div>
 *
 *		<script>
 *			var popupElement = document.getElementById("popup"),
 *				popup = tau.widget.Popup(popupElement);
 *			popup.open();
 *		</script>
 *
 * If jQuery library is loaded, this method can be used:
 *
 *		@example
 *		<div id="popup" data-role="popup">
 *			<p>This is a completely basic popup, no options set.</p>
 *		</div>
 *
 *		<script>
 *			var popup = $("#popup").popup();
 *			popup.popup("open");
 *		</script>
 *
 *
 * ## Closing popup
 *
 * ###Closing by clicking on button inside
 *
 * If link inside popup has property _data-rel="back"_, then popup will be closed after clicking on it as in this example:
 *
 *		@example
 *		<a href="#center_title_1btn" data-position-to="window">Click to open popup</a>
 *		<!--definition of popup with a title and button-->
 *		<div id="center_title_1btn" data-role="popup" class="center_title_1btn">
 *			<div class="ui-popup-title">
 *				<h1>Popup title</h1>
 *			</div>
 *			<div class="ui-popup-text">
 *				Pop-up dialog box, a child window that blocks user interaction to the parent windows
 *			</div>
 *			<div class="ui-popup-button-bg">
 *				<a data-role="button" data-rel="back" data-inline="true">Button</a>
 *			</div>
 *		</div>
 *
 *
 * The selector, which causes closing on click, can be changed by setting option _closeLinkSelector_ in popup.
 *
 * ###Closing manually
 *
 * To close popup with _id_ "popup", tau namespace can be used:
 *
 *		@example
 *		<a href="#popup" data-position-to="window">Click to open popup</a>
 *		<div id="popup" data-role="popup">
 *			<p>This is a completely basic popup, no options set.</p>
 *		</div>
 *
 *		<script>
 *			var popupElement = document.getElementById("popup"),
 *				popup = tau.widget.Popup(popupElement);
 *			// close popup after opening
 *			popupElement.addEventListener("popupafteropen", function () {
 *				popup.close();
 *			});
 *		</script>
 *
 * If jQuery library is loaded, this method can be used:
 *
 *		@example
 *		<a href="#popup" data-position-to="window">Click to open popup</a>
 *		<div id="popup" data-role="popup">
 *			<p>This is a completely basic popup, no options set.</p>
 *		</div>
 *
 *		<script>
 *			$("#popup").on("popupafteropen", function () {
 *				$("#popup").popup("close");
 *			});
 *		</script>
 *
 * ## Handling Popup Events
 *
 * To use popup events, use the following code:
 *
 *		@example
 *		<!-- Popup html code -->
 *		<div id="popup" data-role="popup">
 *			<p>This is a completely basic popup, no options set.</p>
 *		</div>
 *
 *		<script>
 *			// Use popup events
 *			var popup = document.getElementById("popup");
 *			popup.addEventListener("popupafteropen", function() {
 *				// Implement code for popupafteropen event
 *			});
 *		</script>
 *
 * Full list of available events is in [events list section](#events-list).

 *
 * @class ns.widget.mobile.Popup
 * @extends ns.widget.BaseWidget
 * @author Jadwiga Sosnowska <j.sosnowska@samsung.com>
 * @author Maciej Urbanski <m.urbanski@samsung.com>
 * @author Piotr Karny <p.karny@samsung.com>
 * @author Michał Szepielak <m.szepielak@samsung.com>
 */

/**
 * Triggered when process of opening popup is completed.
 * The "popupafteropen" event is triggered when the popup has completely appeared on the screen and all associated animations have completed.
 * @event popupafteropen
 * @member ns.widget.mobile.Popup
 */
/**
 * Triggered when process of opening popup is completed.
 * The "popupshow" event is triggered when the popup has completely appeared on
 * the screen and all associated animations have completed. This event is
 * triggered in the same time as event "popupafteropen".
 * @event popupshow
 * @member ns.widget.mobile.Popup
 */
/**
 * Triggered before a popup computes the coordinates where it will appear.
 * The "beforeposition" event is triggered before the popup starts the opening animations and calculates the coordinates where it will appear on the screen. Handling this event gives an opportunity to modify the content of the popup before it appears on the screen.
 * @event beforeposition
 * @member ns.widget.mobile.Popup
 */

/**
 * Triggered when the process of closing popup is completed.
 * The "popupafterclose" event is triggered when the popup has completely disappeared from the screen and all associated animations have completed.
 * @event popupafterclose
 * @member ns.widget.mobile.Popup
 */
/**
 * Triggered when the process of closing popup is completed.
 * The "popuphide" event is triggered when the popup has completely disappeared
 * from the screen and all associated animations have completed. This event is
 * triggered at the same time as event "popupafterclose".
 * @event popuphide
 * @member ns.widget.mobile.Popup
 */
(function (window, document, ns) {
	
				var Popup = function () {
				var self = this;
					/**
					* @property {Object} options Object with default options
					* @property {string} [options.theme="s"] Sets the color scheme (swatch) for the popup contents.
					* @property {?string} [options.overlayTheme=""] Sets the color scheme (swatch) for the popup background, which covers the entire window.
					* @property {boolean} [options.shadow=true] Sets whether to draw a shadow around the popup.
					* @property {boolean} [options.corners=true] Sets whether to draw the popup with rounded corners.
					* @property {boolean} [options.noScreen=false] Set screen to be always hidden.
					* @property {string} [options.transition="none"] Sets the default transition for the popup.
					* @property {string} [options.positionTo="origin"] Sets the element relative to which the popup will be centered.
					* @property {Object} [options.tolerance={t: 10, r: 10, b: 10, l: 10}] Sets the minimum distance from the edge of the window for the corresponding edge of the popup.
					* @property {Array} [options.directionPriority=["bottom", "top", "right", "left"]] Sets directions of popup's placement by priority. First one has the highest priority, last the lowest.
					* @property {string} [options.closeLinkSelector="a[data-rel="back"]"] Sets selector for buttons in popup
					* @property {?string} [options.link=null] Sets id of element used as reference for relative popup placement
					* @property {boolean} [options.isHardwarePopup=false] Sets whether the popup is hardware one.
					* @property {?number} [options.positionX=null] Sets desired horizontal coordinate of the center point in popup in pixels.
					* @property {?number} [options.positionY=null] Sets desired vertical coordinate of the center point in popup in pixels.
					* @property {boolean} [options.history=false] Sets whether to alter the url when a popup is open to support the back button.
					* @property {string} [options.specialContainerClass=""] Sets CSS class which is added for popup's container.
					* @member ns.widget.mobile.Popup
					*/
					self.options = {
						theme: null,
						overlayTheme: null,
						shadow: true,
						corners: true,
						noScreen: false,
						transition: "pop",
						positionTo: "origin",
						tolerance: { t: 10, r: 10, b: 10, l: 10 },
						directionPriority: ["bottom", "top", "right", "left"],
						closeLinkSelector: "a[data-rel='back']",
						link: null,
						isHardwarePopup: false,
						positionX: null,
						positionY: null,
						history: false,
						specialContainerClass: ""
					};
					self.defaultOptions = {
						theme: "s"
					};
					// @property {Object} _ui Object with html elements connected with popup
					// @member ns.widget.mobile.Popup
					self._ui = {
						screen: null,
						placeholder: null,
						container: null,
						arrow: null
					};
					// @property {HTMLElement} _page Page element
					// @member ns.widget.mobile.Popup
					self._page = null;
					// @property {boolean} _isPreOpen Status of popup before animation
					// @member ns.widget.mobile.Popup
					self._isPreOpen = false;
					// @property {boolean} _isOpen Status of popup after animation
					// @member ns.widget.mobile.Popup
					self._isOpen = false;
					// @property {boolean} _isPreClose Status of popup before animation (popup starts to close)
					// @member ns.widget.mobile.Popup
					self._isPreClose = false;
					// animations
					self._prereqs = null;
					self._fallbackTransition = "";
					self._currentTransition = "none";
					// callbacks
					self._onClickBound = null;
					self._onResizeBound = null;
					self._onButtonClickBound = null;
					// @property {Function} _callback Callback for "resize" event, which sets position of widget.
					// This callback must return object with properties "x" and "y".
					// @member ns.widget.mobile.Popup
					self._callback = null;
				},
				/**
				* @property {Object} Widget Alias for {@link ns.widget.BaseWidget}
				* @member ns.widget.mobile.Popup
				* @private
				*/
				BaseWidget = ns.widget.mobile.BaseWidgetMobile,
				/**
				* @property {Object} engine Alias for class ns.engine
				* @member ns.widget.mobile.Popup
				* @private
				*/
				engine = ns.engine,
				/**
				* @property {Object} selectors Alias for class ns.selectors
				* @member ns.widget.mobile.Popup
				* @private
				*/
				selectors = ns.util.selectors,
				/**
				* @property {Object} doms Alias for class ns.util.DOM
				* @member ns.widget.mobile.Popup
				* @private
				*/
				doms = ns.util.DOM,
				/**
				* @property {Object} themes Alias for class ns.theme
				* @member ns.widget.mobile.Popup
				* @private
				*/
				themes = ns.theme,
				/**
				* @property {Object} events Alias for class ns.event
				* @member ns.widget.mobile.Popup
				* @private
				*/
				events = ns.event,
				scrollviewClipClass = ns.widget.mobile.Scrollview.classes.clip,
				pageActiveClass = ns.widget.mobile.Page.classes.uiPageActive,
				/**
				* @property {ns.util.deferred} UtilsDeferred Alias for class ns.util.deferred
				* @member ns.widget.mobile.Popup
				* @private
				*/
				UtilsDeferred = ns.util.deferred;

			// Return window coordinates
			// @method windowCoords
			// @return {Object}
			// @private
			// @static
			// @member ns.widget.mobile.Popup
			function windowCoords() {
				var body = window.body;

				return {
					x: body ? (body.scrollLeft || 0) : 0,
					y: body ? (body.scrollTop || 0) : 0,
					elementWidth: (window.innerWidth || window.width),
					elementHeight: (window.innerHeight || window.height)
				};
			}

			// Return size of segment
			// @method fitSegmentInsideSegment
			// @param {Number} winSize
			// @param {Number} segSize
			// @param {Number} offset
			// @param {Number} desired
			// @return {Number}
			// @private
			// @static
			// @member ns.widget.mobile.Popup
			function fitSegmentInsideSegment(winSize, segSize, offset, desired) {
				var ret = desired;

				if (winSize < segSize) {
					// Center segment if it's bigger than the window
					ret = offset + (winSize - segSize) / 2;
				} else {
					// Otherwise center it at the desired coordinate while keeping it completely inside the window
					ret = Math.min(Math.max(offset, desired - segSize / 2), offset + winSize - segSize);
				}

				return ret;
			}


			// Return element relative to which popup must be positioned
			// @method findPositionToElement
			// @param {string} elementSelector
			// @return {HTMLElement}
			// @private
			// @static
			// @member ns.widget.mobile.Popup
			function findPositionToElement(elementSelector) {
				var positionToElement = null;

				if (elementSelector) {
					if (elementSelector[0] === "#") {
						positionToElement = document.getElementById(elementSelector.slice(1));
					} else {
						positionToElement = document.querySelector(elementSelector);
					}
					// :visible - in jq (>=1.3.2) an element is visible if its browser-reported offsetWidth or offsetHeight is greater than 0
					if (positionToElement && positionToElement.offsetWidth <= 0 && positionToElement.offsetHeight <= 0) {
						positionToElement = null;
					}
				}

				return positionToElement;
			}

			// Return offset of element
			// @method getOffsetOfElement
			// @param {HTMLElement} element
			// @param {?string} link
			// @return {Object}
			// @private
			// @static
			// @member ns.widget.mobile.Popup
			function getOffsetOfElement(element, link) {
				var top = element.offsetTop,
					left = element.offsetLeft,
					scrollview;
				while (element.offsetParent) {
					top += element.offsetParent.offsetTop;
					left += element.offsetParent.offsetLeft;
					if (element.getAttribute("data-role") === "page") {
						break;
					}

					element = element.offsetParent;
				}
				if (link) {
					scrollview = selectors.getClosestByClass(document.getElementById(link), scrollviewClipClass);
					top -= scrollview ? scrollview.scrollTop : 0;
				}

				return {top: top, left: left};
			}

			// Function fires on window resizing
			// @method onResize
			// @private
			// @static
			// @member ns.widget.mobile.Popup
			function onResize(self) {
				var callback,
					options;
				if (!self._isOpen) {
					return;
				}
				if (self._callback) {
					callback = self._callback();
					self._setPosition(callback.x, callback.y);
				} else {
					options = self.options;
					self._setPosition(options.positionX, options.positionY);
				}
			}

			// Function fires on click
			// @method _eatEventAndClose
			// @private
			// @static
			// @member ns.widget.mobile.Popup
			function _eatEventAndClose(self, event) {
				event.preventDefault();
				events.stopPropagation(event);
				setTimeout(self.close.bind(self), 10);
				return false;
			}

			function removeProperties() {
				var page = document.getElementsByClassName(pageActiveClass)[0],
					tabindexElements = page ? page.querySelectorAll("[tabindex]") : null,
					hrefElements = page ? page.querySelectorAll("[href]") : null,
					value;

				if (tabindexElements) {
					tabindexElements = [].slice.call(tabindexElements);
					tabindexElements.forEach(function (tabindexElement) {
						if (selectors.getClosestBySelector(tabindexElement, "[data-role='popup']") === null) {
							value = tabindexElement.getAttribute("tabindex");
							doms.setNSData(tabindexElement, "tabindex", value);
							tabindexElement.removeAttribute("tabindex");
						}
					});
				}
				if (hrefElements) {
					hrefElements = [].slice.call(hrefElements);
					hrefElements.forEach(function (hrefElement) {
						if (selectors.getClosestBySelector(hrefElement, "[data-role='popup']") === null) {
							value = hrefElement.getAttribute("href");
							doms.setNSData(hrefElement, "href", value);
							hrefElement.removeAttribute("href");
						}
					});
				}
			}

			function restoreProperties() {
				var page = document.getElementsByClassName(ns.widget.mobile.Page.classes.uiPageActive)[0],
					tabindexElements = page ? selectors.getAllByDataNS(page, "tabindex") : null,
					hrefElements = page ? page.querySelectorAll("[href]") : null,
					value;

				if (tabindexElements) {
					selectors.getAllByDataNS(page, "tabindex").forEach(function (tabindexElement) {
						value = doms.getNSData(tabindexElement, "tabindex");
						tabindexElement.setAttribute("tabindex", value);
						doms.removeNSData(tabindexElement, "tabindex");
					});
				}
				if (hrefElements) {
					selectors.getAllByDataNS(page, "href").forEach(function (hrefElement) {
						value = doms.getNSData(hrefElement, "href");
						hrefElement.setAttribute("href", value);
						doms.removeNSData(hrefElement, "href");
					});
				}
			}

			function applyTheme(element, theme, prefix) {
				var classes = element.classList,
					classesLength = classes.length,
					currentTheme = null,
					matches,
					i,
					regex = new RegExp("^ui-" + prefix + "-([a-z]+)$");

				for (i = 0; i < classesLength; i++) {
					matches = regex.exec(classes[i]);
					if (matches && matches.length > 1) {
						currentTheme = matches[1];
						break;
					}
				}

				if (theme !== currentTheme) {
					element.classList.remove("ui-" + prefix + "-" + currentTheme);
					if (theme !== null && theme !== "none") {
						element.classList.add("ui-" + prefix + "-" + theme);
					}
				}
			}

			 // @method chooseDirectionByPriority
			 // @param {Array} directionPriority
			 // @param {Object} positionOffsets
			 // @param {Object} elementDimensions
			 // @param {Object} arrowBorderWidths
			 // @private
			 // @static
			 // @return {string}
			function chooseDirectionByPriority(directionPriority, positionOffsets, elementDimensions, arrowBorderWidths) {
				var direction,
					bestMatchingDirection,
					spaceOccupied,
					priorityQueue;

				if (typeof directionPriority === "string") {
					directionPriority = directionPriority.split(",");
				}
				// Copy array to queue
				priorityQueue = directionPriority.slice();
				do {
					// Get get first element
					direction = priorityQueue.shift();
					if (direction) {
						if (direction === "top" || direction === "bottom") {
							spaceOccupied = elementDimensions.height;
						} else {
							spaceOccupied = elementDimensions.width;
						}

						spaceOccupied += arrowBorderWidths[direction];

						// Check if popup fits into free space
						if (spaceOccupied <= positionOffsets[direction]) {
							bestMatchingDirection = direction;
						}
					}
				// Repeat until space is found or queue is empty
				} while (!bestMatchingDirection && priorityQueue.length > 0);

				// Last matching direction has the highest priority
				return bestMatchingDirection || "bottom";
			}

			// Set events connected with animation
			// @method animationComplete
			// @param {HTMLElement} element
			// @param {Function} callback
			// @private
			// @static
			// @member ns.widget.mobile.Popup
			function animationComplete(element, callback) {
				events.one(element, "webkitAnimationEnd", callback);
				events.one(element, "animationend", callback);
			}

			// This function starts opening popup by seting global property "activePopup"
			// and calling "_open" method
			// @method startOpeningPopup
			// @param {ns.widget.mobile.Popup} instance
			// @param {Object} options opening options
			// @param {Event} event
			// @private
			// @static
			// @memberOf ns.widget.Popup
			function startOpeningPopup(instance, options, event) {
				ns.activePopup = instance;
				events.trigger(document, "activePopup", instance);
				instance._open(options, event);
			}

			Popup.prototype = new BaseWidget();

			/**
			 * Dictionary for popup related css class names
			 * @property {Object} classes
			 * @member ns.widget.mobile.Popup
			 * @static
			 */
			Popup.classes = {
				IN: "in",
				OUT: "out",
				REVERSE: "reverse",
				SCREEN_HIDDEN: "ui-screen-hidden",
				uiPopupScreen: "ui-popup-screen",
				uiPopupContainer: "ui-popup-container",
				uiPopupWindow: "ui-popup-window",
				uiPopupWindowPadding: "ui-popupwindow-padding",
				uiCtxpopupScreen: "ui-ctxpopup-screen",
				uiCtxpopupContainer: "ui-ctxpopup-container",
				uiSelectmenuHidden: "ui-selectmenu-hidden",
				uiArrow: "ui-arrow",
				uiPopup: "ui-popup",
				top: "top",
				bottom: "bottom",
				right: "right",
				left: "left",
				uiPopupActive: "ui-popup-active",
				uiPopupOpen: "ui-popup-open",
				uiCtxpopup: "ui-ctxpopup",
				uiCornerAll: "ui-corner-all",
				uiOverlaryShadow: "ui-overlay-shadow",
				uiCtxpopupOptionmenu: "ui-ctxpopup-optionmenu",
				uiBodyPrefix: "ui-body-"
			};

			/**
			* Build structure of popup widget
			* @method _build
			* @param {HTMLElement} element
			* @return {HTMLElement}
			* @protected
			* @member ns.widget.mobile.Popup
			*/
			Popup.prototype._build = function (element) {
				var classes = Popup.classes,
					options = this.options,
					page = selectors.getParentsByClass(element, "ui-page")[0] || document.body,
					uiScreen = document.createElement("div"),
					uiScreenClasses = uiScreen.classList,
					uiPlaceholder = document.createElement("div"),
					uiContainer = document.createElement("div"),
					uiContainerClasses = uiContainer.classList,
					uiArrow = document.createElement("div"),
					myId = element.id,
					fragment = document.createDocumentFragment();

				// init ui elements
				uiScreenClasses.add(classes.SCREEN_HIDDEN);
				uiScreenClasses.add(classes.uiPopupScreen);
				uiPlaceholder.style.display = "none";
				uiContainerClasses.add(classes.uiPopupContainer);
				uiContainerClasses.add(classes.uiSelectmenuHidden);

				// this option specifies what CSS class is added for container of popup
				// it is used by Tizen Slider widget to distinguish popup related with
				// slider, because it has to have different style than a normal popup
				if (options.specialContainerClass) {
					uiContainerClasses.add(options.specialContainerClass);
				}
				uiArrow.classList.add(classes.uiArrow);

				// define the container for navigation event bindings
				// TODO this would be nice at the the mobile widget level
				//this.options.container = this.options.container || $.mobile.pageContainer;

				uiScreen.setAttribute("id", myId + "-screen");
				uiContainer.setAttribute("id", myId + "-popup");
				uiPlaceholder.setAttribute("id", myId + "-placeholder");
				uiPlaceholder.innerHTML = "<!-- placeholder for " + myId + " -->";
				uiArrow.setAttribute("id", myId + "-arrow");
				element.classList.add(classes.uiPopup);

				doms.insertNodeAfter(element, uiPlaceholder);
				uiContainer.appendChild(element);
				uiContainer.appendChild(uiArrow);
				fragment.appendChild(uiScreen);
				fragment.appendChild(uiContainer);
				page.appendChild(fragment);

				return element;
			};

			/**
			* Init widget
			* @method _init
			* @param {HTMLElement} element
			* @protected
			* @member ns.widget.mobile.Popup
			*/
			Popup.prototype._init = function (element) {
				var id = element.id,
					options = this.options,
					ui;

				// set options
				options.theme = options.theme || themes.getInheritedTheme(element, this.defaultOptions.theme);
				this._setTolerance(element, options.tolerance);

				// @todo define instance variables
				ui = {
					screen: document.getElementById(id + "-screen"),
					placeholder: document.getElementById(id + "-placeholder"),
					container: element.parentNode,
					arrow: document.getElementById(id + "-arrow")
				};
				// if page isn't built, we choose body as page
				this._page = selectors.getParentsByClass(element, "ui-page")[0] || document.body;
				this._ui = ui;
				this._isPreOpen = false;
				this._isOpen = false;
				this._isPreClose = false;
			};

			/**
			* Set tolerance for widget's position
			* @method _setTolerance
			* @param {HTMLElement} element
			* @param {string|Array} value
			* @protected
			* @member ns.widget.mobile.Popup
			*/
			Popup.prototype._setTolerance = function (element, value) {
				var options = this.options,
					tolerance = {};

				if (value && typeof value === "string") {
					value = value.split(",");
					value.forEach(function(val, index){
						value[index] = parseInt(val, 10);
					});
					switch (value.length) {
						// All values are to be the same
						case 1:
							if (!isNaN(value[0])) {
								tolerance.t = tolerance.r = tolerance.b = tolerance.l = value[0];
							}
							break;

						// The first value denotes top/bottom tolerance, and the second value denotes left/right tolerance
						case 2:
							if (!isNaN(value[0])) {
								tolerance.t = tolerance.b = value[0];
							}
							if (!isNaN(value[1])) {
								tolerance.l = tolerance.r = value[1];
							}
							break;

						// The array contains values in the order top, right, bottom, left
						case 4:
							if (!isNaN(value[0])) {
								tolerance.t = value[0];
							}
							if (!isNaN(value[1])) {
								tolerance.r = value[1];
							}
							if (!isNaN(value[2])) {
								tolerance.b = value[2];
							}
							if (!isNaN(value[3])) {
								tolerance.l = value[3];
							}
							break;

						default:
							break;
					}
					options.tolerance = tolerance;
				}
			};

			/**
			* Return desired coordinates of popup
			* @method _desiredCoords
			* @param {string|HTMLElement} positionTo
			* @param {Number} x
			* @param {Number} y
			* @return {Object}
			* @protected
			* @member ns.widget.mobile.Popup
			*/
			Popup.prototype._desiredCoords = function (positionTo, x, y) {
				var winCoords = windowCoords(),
					offset;

				if (positionTo === "window") {
					x = winCoords.elementWidth / 2 + winCoords.x;
					y = winCoords.elementHeight / 2 + winCoords.y;
				} else if (positionTo) {
					// In this case, positionTo is HTML element, to which popup is positioned
					offset = getOffsetOfElement(positionTo, this.options.link);
					x = offset.left + positionTo.offsetWidth / 2;
					y = offset.top + positionTo.offsetHeight / 2;
				}

				// Make sure x and y are valid numbers - center over the window
				if (typeof x !== "number" || isNaN(x)) {
					x = winCoords.elementWidth / 2 + winCoords.x;
				}
				if (typeof y !== "number" || isNaN(y)) {
					y = winCoords.elementHeight / 2 + winCoords.y;
				}

				return {x : x,
						y : y};
			};

			/**
			* Return placement of popup
			* @method _placementCoords
			* @param {Object} desired
			* @return {Object}
			* @protected
			* @member ns.widget.mobile.Popup
			*/
			Popup.prototype._placementCoords = function (desired) {
				// rectangle within which the popup must fit
				var uiContainer = this._ui.container,
					winCoords = windowCoords(),
					tolerance = this.options.tolerance,
					maxCoords = {
						x: tolerance.l,
						y: winCoords.y + tolerance.t,
						elementWidth: winCoords.elementWidth - tolerance.l - tolerance.r,
						elementHeight: winCoords.elementHeight - tolerance.t - tolerance.b
					},
					menuSize,
					finalCoords,
					docElement = document.documentElement,
					docBody = document.body,
					docHeight = Math.max(docElement.clientHeight, docBody.scrollHeight, docBody.offsetHeight, docElement.scrollHeight, docElement.offsetHeight);

				// Clamp the width of the menu before grabbing its size
				uiContainer.style.maxWidth = maxCoords.elementWidth;

				menuSize = {
					elementWidth: uiContainer.clientWidth,
					elementHeight: uiContainer.clientHeight
				};

				// Center the menu over the desired coordinates, while not going outside
				// the window tolerances. This will center wrt. the window if the popup is too large.
				finalCoords = {
					x: fitSegmentInsideSegment(maxCoords.elementWidth, menuSize.elementWidth, maxCoords.x, desired.x),
					y: fitSegmentInsideSegment(maxCoords.elementHeight, menuSize.elementHeight, maxCoords.y, desired.y)
				};

				// Make sure the top of the menu is visible
				finalCoords.y = Math.max(0, finalCoords.y);

				// If the height of the menu is smaller than the height of the document
				// align the bottom with the bottom of the document

				finalCoords.y -= Math.min(finalCoords.y, Math.max(0, finalCoords.y + menuSize.elementHeight - docHeight));

				if (this.options.isHardwarePopup) {
					return {
						left: tolerance.l,
						top: maxCoords.elementHeight - menuSize.elementHeight - tolerance.b,
						arrowleft: 0,
						arrowtop: 0
					};
				}
				return {left: finalCoords.x, top: finalCoords.y};
			};


			/**
			 * Set placement of arrow
			 * @method _setArrowPosition
			 * @param {number} type
			 * @param {HTMLElement} positionToElement
			 * @param {number} containerLeft container's left position
			 * @param {number} containerTop container's top position
			 * @param {Object} positionToElementOffset contains toElement offsets
			 * @return {Object}
			 * @protected
			 * @member ns.widget.mobile.Popup
			 */
			Popup.prototype._setArrowPosition = function (type, positionToElement, containerLeft, containerTop, positionToElementOffset) {
				var classes = Popup.classes,
					options = this.options,
					tolerance = options.tolerance,
					uiContainer = this._ui.container,
					uiContainerHeight = uiContainer.clientHeight,
					uiContainerWidth = uiContainer.clientWidth,
					popupMargin,
					arrow = this._ui.arrow,
					arrowClasses = arrow.classList,
					arrowStyle = arrow.style,
					// @TODO this will fail when not all arrow borders are the same
					arrowBorderWidth = parseFloat(doms.getCSSProperty(arrow, "border-" + type + "-width")) || 0,
					left = positionToElement ? getOffsetOfElement(positionToElement, options.link).left + positionToElement.clientWidth / 2 - arrowBorderWidth : 0,
					positionToElementHeight = positionToElement ? positionToElement.clientHeight : 0,
					positionToElementWidth = positionToElement ? positionToElement.clientWidth : 0,
					correctionValue = [0, 0],
					usedTolerance,
					arrowLeft;

				arrow.removeAttribute("class");
				arrowClasses.add(classes.uiArrow);
				arrowClasses.add(classes[type]);

				arrowLeft = left - containerLeft;

				uiContainer.classList.add(classes[type]);

				switch (type) {
				case "bottom":
					popupMargin = parseInt(doms.getCSSProperty(this.element, "margin-top"), 10) || 0;
					arrowClasses.add(classes.bottom);
					arrowStyle.top = -arrowBorderWidth + popupMargin + "px";
					// Developer can try to change position of popup using method *refresh*.
					// However, in case of context popup, arrow should be always placed
					// in the middle of element related with popup.
					// So we have to check if arrow is still in range of popup's container
					// and correct value of left position of popup if it is necessary.
					if (arrowLeft < 0) {
						// popup container is positioned too far to the right
						usedTolerance = tolerance.l;
						arrowStyle.left = usedTolerance + "px";
						correctionValue[0] = arrowLeft - usedTolerance;
					} else if (arrowLeft > uiContainerWidth) {
						// popup container is positioned too far to the left
						usedTolerance = tolerance.r;
						arrowStyle.left = uiContainerWidth - usedTolerance - arrowBorderWidth * 2 + "px";
						correctionValue[0] = arrowLeft - uiContainerWidth + usedTolerance + arrowBorderWidth * 2;
					} else {
						// popup container is positioned properly,
						// so correction value of left position remains zero
						arrowStyle.left = arrowLeft + "px";
					}
					// correction value of top position is always the same
					correctionValue[1] = positionToElementHeight + positionToElementOffset.top - containerTop
					break;
				case "right":
					// @todo
					arrowStyle.left = -arrowBorderWidth * 2 + 1 + "px";
					arrowStyle.top = uiContainerHeight / 2 - arrowBorderWidth + "px";
					correctionValue = [positionToElementWidth + positionToElementOffset.left - arrowBorderWidth, 0];
					break;
				case "top":
					popupMargin = parseInt(doms.getCSSProperty(this.element, "margin-bottom"), 10) || 0;
					arrowClasses.add(classes.top);
					arrowStyle.top = uiContainerHeight - popupMargin - arrowBorderWidth + "px";
					// @todo make one correction for *top* and *bottom* arrows
					if (arrowLeft < 0) {
						// popup container is set too far to the right
						usedTolerance = tolerance.l;
						arrowStyle.left = usedTolerance + "px";
						correctionValue[0] = arrowLeft - usedTolerance;
					} else if (arrowLeft > uiContainerWidth) {
						// popup container is set too far to the left
						usedTolerance = tolerance.r;
						arrowStyle.left = uiContainerWidth - usedTolerance - arrowBorderWidth * 2 + "px";
						correctionValue[0] = arrowLeft - uiContainerWidth + usedTolerance + arrowBorderWidth * 2;
					} else {
						arrowStyle.left = arrowLeft + "px";
					}
					correctionValue[1] = -(containerTop + uiContainerHeight - positionToElementOffset.top);
					break;
				case "left":
					// @todo
					arrowStyle.left = uiContainer.clientWidth + 3 + "px";
					arrowStyle.top = uiContainerHeight / 2 - arrowBorderWidth + "px";
					correctionValue = [positionToElementOffset.left - uiContainerWidth, 0];
					break;
				}

				return correctionValue;

				// @todo arrow's positions (in original file, it was in _placementCoords)
				// correctionValue = [0, (positionToElement.offsetTop + positionToElement.style.height - y)];
			};

			/**
			 * Set callback, which is called on "resize" event. This callback should return desired position of popup after resizing.
			 *
			 * This function is deprecated and function setPositionCallback should be used to set this callback.
			 *
			 *      @example
			 *      <div id="popup" data-role="popup">
			 *          <p>This is a completely basic popup, no options set.</p>
			 *      </div>
			 *
			 *      <script>
			 *          var popupWidget = tau.widget.Popup(document.getElementById("popup"));
			 *
			 *          popupWidget.setPositionCB(function() {
			 *                return {x: 10, y: 20};
			 *          });
			 *      </script>
			 *
			 * If jQuery is loaded:
			 *
			 *      @example
			 *      <div id="popup" data-role="popup">
			 *          <p>This is a completely basic popup, no options set.</p>
			 *      </div>
			 *
			 *      <script>
			 *          $("#popup").popup("setPositionCB", function() {
			 *                return {x: 10, y: 20};
			 *          });
			 *      </script>
			 *
			 * @method setPositionCB
			 * @param {Function} callback Function called on resizing. It should return desired position of popup as object with "x" and "y" properties.
			 * @member ns.widget.mobile.Popup
			 * @deprecated 2.3
			 */
			Popup.prototype.setPositionCB = function (callback) {
				this.setPositionCallback(callback);
			};

			/**
			 * Set callback, which is called on "resize" event. This callback should return desired position of popup after resizing.
			 *
			 * This function should be used instead of "setPositionCB".
			 *
			 *      @example
			 *      <div id="popup" data-role="popup">
			 *          <p>This is a completely basic popup, no options set.</p>
			 *      </div>
			 *
			 *      <script>
			 *          var popupWidget = tau.widget.Popup(document.getElementById("popup"));
			 *
			 *          popupWidget.setPositionCallback(function() {
			 *                return {x: 10, y: 20};
			 *         });
			 *      </script>
			 *
			 * If jQuery is loaded:
			 *
			 *      @example
			 *      <div id="popup" data-role="popup">
			 *          <p>This is a completely basic popup, no options set.</p>
			 *      </div>
			 *
			 *      <script>
			 *          $("#popup").popup("setPositionCallback", function() {
			 *                return {x: 10, y: 20};
			 *          });
			 *      </script>
			 *
			 * @method setPositionCallback
			 * @param {Function} callback Function called on resizing. It should return desired position of popup as object with "x" and "y" properties.
			 * @member ns.widget.mobile.Popup
			 * @new 2.3
			 */
			Popup.prototype.setPositionCallback = function (callback) {
				this._callback = callback;
			};

			/**
			* Set position of popup
			* @method _setPosition
			* @param {number} [left]
			* @param {number} [top]
			* @protected
			* @member ns.widget.mobile.Popup
			*/
			Popup.prototype._setPosition = function (left, top) {
				var ui = this._ui,
					uiArrow = ui.arrow,
					uiContainer = ui.container,
					uiContainerStyle = uiContainer.style,
					uiContainerWidth = uiContainer.offsetWidth,
					uiContainerHeight = uiContainer.offsetHeight,
					options = this.options,
					positionToOption = options.positionTo.toLowerCase(),
					positionToElement,
					positionToElementOffset,
					docElement = document.documentElement,
					desired,
					arrowType = "top",
					positionOffsets,
					correctionValue = [0, 0],
					arrowDimensions,
					arrowBorders = {
						"border-top-width": 0,
						"border-right-width": 0,
						"border-bottom-width": 0,
						"border-left-width": 0
					},
					elementDimensions;

				doms.extractCSSProperties(uiArrow, arrowBorders);

				if (typeof top === "number" && typeof left === "number") {
					desired = {
						x: left,
						y: top
					};
				}

				if (positionToOption === "window") {
					top = null;
					uiContainerStyle.bottom = "0";
				} else if (positionToOption === "origin") {
					// popup with arrow
					if (options.link) {
						positionToElement = findPositionToElement("#" + options.link);
					} else {
						positionToElement = null;
					}
					desired = this._placementCoords(desired || this._desiredCoords(positionToElement));
					top = desired.top;
					left = desired.left;

					if (positionToElement) {
						positionToElementOffset = getOffsetOfElement(positionToElement, options.link);
						positionOffsets = {
							"top": positionToElementOffset.top,
							"right": docElement.clientWidth - (positionToElementOffset.left + doms.getElementWidth(positionToElement)),
							"bottom": docElement.clientHeight - (positionToElementOffset.top + doms.getElementHeight(positionToElement)),
							"left": positionToElementOffset.left
						};
						elementDimensions = {
							width: uiContainerWidth,
							height: uiContainerHeight
						};
						arrowDimensions = {
							// For proper results arrow width and height are assumed to be "0"
							"top": arrowBorders["border-top-width"],
							"right": arrowBorders["border-right-width"],
							"bottom": arrowBorders["border-bottom-width"],
							"left": arrowBorders["border-left-width"]
						};
						arrowType = chooseDirectionByPriority(options.directionPriority, positionOffsets, elementDimensions, arrowDimensions);

						if (uiArrow.style.display !== "none") {
							correctionValue = this._setArrowPosition(arrowType, positionToElement, left, top, positionToElementOffset);
						}
					}
				} else {
					// position to element which matches to options.positionTo selector
					positionToElement = findPositionToElement(options.positionTo);
					desired = this._placementCoords(desired || this._desiredCoords(positionToElement));
					top = desired.top;
					left = desired.left;
				}

				if (top) {
					uiContainerStyle.left = left + correctionValue[0] + "px";
					uiContainerStyle.top = top + correctionValue[1] + "px";
				}
			};

			/**
			* Set context style of widget
			* @method _setContextStyle
			* @param {boolean} popupwindow
			* @protected
			* @member ns.widget.mobile.Popup
			*/
			Popup.prototype._setContextStyle = function (popupwindow) {
				var classes = Popup.classes,
					options = this.options,
					ui = this._ui,
					linkElement = options.link ? document.getElementById(options.link) : null,
					position = options.positionTo.toLowerCase(),
					containerList = ui.container.classList;

				if ((position !== "window" && linkElement && linkElement.getAttribute("data-position-to") !== "window") || options.isHardwarePopup) {
					this.element.classList.add(classes.uiCtxpopup);
					if (popupwindow) {
						containerList.add(classes.uiPopupWindow);
						this.element.classList.add(classes.uiPopupWindowPadding);
					} else {
						containerList.remove(classes.uiPopupContainer);
						containerList.add(classes.uiCtxpopupContainer);
					}
					if (position === "origin") {
						ui.arrow.style.display = "initial";
						ui.screen.classList.add(classes.uiCtxpopupScreen);
					} else {
						ui.arrow.style.display = "none";
					}
				} else {
					this._setOverlayTheme(this.element, "dim");
					ui.arrow.style.display = "none";
				}

				if (options.isHardwarePopup) {
					ui.arrow.style.display = "none";
				}
			};

			/**
			* Set overlay theme for screen
			* @method _setOverlayTheme
			* @param {HTMLElement} element
			* @param {string} value
			* @protected
			* @member ns.widget.mobile.Popup
			*/
			Popup.prototype._setOverlayTheme = function (element, value) {
				var classes = Popup.classes,
					screen = this._ui.screen;

				applyTheme(screen, value, "overlay");
				if (this._isOpen) {
					screen.classList.add(classes.IN);
				}
			};

			/**
			* Set type of corners
			* @method _setCorners
			* @param {boolean} value
			* @protected
			* @member ns.widget.mobile.Popup
			*/
			Popup.prototype._setCorners = function (value) {
				var classes = Popup.classes;
				if (value) {
					this.element.classList.add(classes.uiCornerAll);
				} else {
					this.element.classList.remove(classes.uiCornerAll);
				}
			};

			/**
			* Set transition
			* @method _applyTransition
			* @param {string} value
			* @protected
			* @member ns.widget.mobile.Popup
			*/
			Popup.prototype._applyTransition = function (value) {
				var self = this;

				if (self._fallbackTransition) {
					self._ui.container.classList.remove(self._fallbackTransition);
				}
				if (value && value !== "none") {
					// @todo
					// this._fallbackTransition = $.mobile._maybeDegradeTransition( value );
					self._fallbackTransition = value;
					self._ui.container.classList.add(self._fallbackTransition);
				}
			};

			/**
			* Prepare deferred objects for animation
			* @method _createPrereqs
			* @param {Function} screenPrereq
			* @param {Function} containerPrereq
			* @param {Function} whenDone
			* @protected
			* @member ns.widget.mobile.Popup
			*/
			Popup.prototype._createPrereqs = function (screenPrereq, containerPrereq, whenDone) {
				var self = this,
					prereqs;

				// It is important to maintain both the local variable prereqs and self._prereqs. The local variable remains in
				// the closure of the functions which call the callbacks passed in. The comparison between the local variable and
				// self._prereqs is necessary, because once a function has been passed to .animationComplete() it will be called
				// next time an animation completes, even if that's not the animation whose end the function was supposed to catch
				// (for example, if an abort happens during the opening animation, the .animationComplete handler is not called for
				// that animation anymore, but the handler remains attached, so it is called the next time the popup is opened
				// - making it stale. Comparing the local variable prereqs to the widget-level variable self._prereqs ensures that
				// callbacks triggered by a stale .animationComplete will be ignored.
				prereqs = {
					screen: new UtilsDeferred(),
					container: new UtilsDeferred()
				};

				prereqs.screen.then(function () {
					if (prereqs === self._prereqs) {
						screenPrereq();
					}
				});

				prereqs.container.then(function() {
					if (prereqs === self._prereqs) {
						containerPrereq();
					}
				});

				ns.util.deferredWhen(prereqs.screen, prereqs.container).done(function() {
					if ( prereqs === self._prereqs ) {
						self._prereqs = null;
						whenDone();
					}
				});

				self._prereqs = prereqs;
			};

			/**
			* Set animation
			* @method _animate
			* @param {Object} options
			* @param {boolean} [options.additionalCondition]
			* @param {string} [options.transition]
			* @param {Array|string} [options.classToRemove]
			* @param {Array|string} [options.screenClassToAdd]
			* @param {Array|string} [options.containerClassToAdd]
			* @param {boolean} [options.applyTransition]
			* @param {Object} [options.prereqs]
			* @protected
			* @member ns.widget.mobile.Popup
			*/
			Popup.prototype._animate = function (options) {
				var ui = this._ui,
					screenClasses = ui.screen.classList,
					container = ui.container,
					containerClasses = container.classList,
					transition = options.transition,
					classesToRemove = typeof options.classToRemove === "string" ? options.classToRemove.split(" ") : options.classToRemove,
					classesToRemoveLen = classesToRemove.length,
					classes,
					classesLen,
					i;

				for (i = 0; i < classesToRemoveLen; i++) {
					if (classesToRemove[i]) {
						screenClasses.remove(classesToRemove[i]);
					}
				}

				classes = typeof options.screenClassToAdd === "string" ? options.screenClassToAdd.split(" ") : options.screenClassToAdd;
				classesLen = classes.length;
				for (i = 0; i < classesLen; i++) {
					if (classes[i]) {
						screenClasses.add(classes[i]);
					}
				}

				options.prereqs.screen.resolve();

				if (transition && transition !== "none") {
					if (options.applyTransition) {
						this._applyTransition(transition);
					}
					animationComplete(container, options.prereqs.container.resolve);
					classes = typeof options.containerClassToAdd === "string" ? options.containerClassToAdd.split(" ") : options.containerClassToAdd;
					classesLen = classes.length;
					for (i = 0; i < classesLen; i++) {
						containerClasses.add(classes[i]);
					}
					for (i = 0; i < classesToRemoveLen; i++) {
						if (classesToRemove[i]) {
							containerClasses.remove(classesToRemove[i]);
						}
					}
				} else {
					for (i = 0; i < classesToRemoveLen; i++) {
						if (classesToRemove[i]) {
							containerClasses.remove(classesToRemove[i]);
						}
					}
					options.prereqs.container.resolve();
				}
			};

			/**
			* Animation's callback on completed opening
			* @method _openPrereqsComplete
			* @protected
			* @member ns.widget.mobile.Popup
			*/
			Popup.prototype._openPrereqsComplete = function() {
				var self = this,
					container = self._ui.container;

				container.classList.add(Popup.classes.uiPopupActive);
				self._isOpen = true;
				self._isPreOpen = false;

				// Android appears to trigger the animation complete before the popup
				// is visible. Allowing the stack to unwind before applying focus prevents
				// the "blue flash" of element focus in android 4.0
				setTimeout(function(){
					container.setAttribute("tabindex", "0");
					container.focus();
					events.trigger(self.element, "popupafteropen");
					events.trigger(self.element, "popupshow");
				});
			};

			/**
			* Set popup, which will be opened
			* @method _open
			* @param {Object} options
			* @protected
			* @member ns.widget.mobile.Popup
			*/
			Popup.prototype._open = function (options, event) {
				var element = this.element,
					position = doms.getNSData(element, "position-to"),
					classes = Popup.classes,
					savedOptions = this.options,
					elementTheme = savedOptions.theme,
					ui = this._ui,
					uiContainer = ui.container,
					uiContainerClasses = uiContainer.classList,
					linkElement,
					transition,
					top,
					left;

				this._isPreOpen = true;

				options = options || {};
				top = savedOptions.positionY = options.positionY;
				left = savedOptions.positionX = options.positionX;
				transition = options.transition || savedOptions.transition;
				options.noScreen = options.noScreen || savedOptions.noScreen;

				this._setTolerance(element, options.tolerance);

				// Give applications a chance to modify the contents of the container before it appears
				events.trigger(this.element, "beforeposition");

				if (options.link) {
					savedOptions.link = options.link;
					savedOptions.positionTo = options.positionTo || position || "origin";
				} else {
					if (event) {
						linkElement = selectors.getClosestBySelector(event.target, "[data-role='button'],input[type='button']");
						savedOptions.link =  linkElement ? linkElement.getAttribute("id") : null;
						savedOptions.positionTo = options.positionTo || position || "origin";
					}
				}

				if (element.classList.contains(classes.uiCtxpopupOptionmenu)) {
					savedOptions.isHardwarePopup = true;
				}

				this._setContextStyle(options.popupwindow || savedOptions.popupwindow);
				this._setPosition(left, top);
				this._setCorners(options.corners || savedOptions.corners);


				this._createPrereqs(function(){}, function(){}, this._openPrereqsComplete.bind(this));

				if (transition) {
					this._currentTransition = transition;
					this._applyTransition(transition);
				}

				if (elementTheme) {
					element.classList.add(classes.uiBodyPrefix + elementTheme);
				}

				if (!options.noScreen) {
					ui.screen.classList.remove(classes.SCREEN_HIDDEN);
				}
				uiContainerClasses.remove(classes.uiSelectmenuHidden);
				this._page.classList.add(classes.uiPopupOpen);

				this._animate({
					additionalCondition: true,
					transition: transition,
					classToRemove: "",
					screenClassToAdd: (options.noScreen) ? "" :  classes.IN,
					containerClassToAdd: classes.IN,
					applyTransition: false,
					prereqs: this._prereqs
				});

				// FIX: for tv profile
				if (typeof this._supportKeyboard !== "boolean") {
					// This fix problem with host keyboard
					// @todo keyboard support for mobile
					removeProperties();
				}
			};

			/**
			* Animation's callback on scren closing
			* @method _closePrereqScreen
			* @protected
			* @member ns.widget.mobile.Popup
			*/
			Popup.prototype._closePrereqScreen = function() {
				var classes = Popup.classes,
					screenClasses = this._ui.screen.classList;

				screenClasses.remove(classes.OUT);
				screenClasses.add(classes.SCREEN_HIDDEN);
			};

			/**
			* Animation's callback on container closing
			* @method _closePrereqContainer
			* @protected
			* @member ns.widget.mobile.Popup
			*/
			Popup.prototype._closePrereqContainer = function() {
				var classes = Popup.classes,
					container = this._ui.container,
					containerClasses = container.classList;

				containerClasses.remove(classes.REVERSE);
				containerClasses.remove(classes.OUT);
				containerClasses.add(classes.uiSelectmenuHidden);
				container.removeAttribute("style");
			};

			/**
			* Animation's callbacl on completed closing
			* @method _closePrereqsDone
			* @protected
			* @member ns.widget.mobile.Popup
			*/
			Popup.prototype._closePrereqsDone = function() {
				var self = this;

				self._ui.container.removeAttribute("tabindex");

				// @todo?
				// remove nav bindings if they are still present
				// var opts = self.options;
				//opts.container.unbind( opts.closeEvents );

				// @todo?
				// unbind click handlers added when history is disabled
				//self.element.undelegate( opts.closeLinkSelector, opts.closeLinkEvents );

				ns.activePopup = null;
				// Popup's closing phase is finished
				this._isPreClose = false;
				events.trigger(document, "activePopup", null);
				events.trigger(this.element, "popupafterclose");		// this event must be triggered after setting mobile.popup.active
				events.trigger(this.element, "popuphide");
			};

			/**
			* Set popup, which will be closed
			* @method _close
			* @return {void}
			* @protected
			* @member ns.widget.mobile.Popup
			*/
			Popup.prototype._close = function (immediate) {
				var classes = Popup.classes,
					ui = this._ui,
					uiContainer = ui.container,
					uiContainerClass = uiContainer.classList,
					element = this.element,
					inputs = [].slice.call(element.querySelectorAll("input"));

				uiContainerClass.remove(classes.uiPopupActive);
				this._page.classList.remove(classes.uiPopupOpen);

				this._isOpen = false;
				this._isPreOpen = false;
				// Popup is starting to close
				this._isPreClose = true;

				inputs.forEach(function(input){
					input.blur();
				});

				// Count down to triggering "popupafterclose" - we have two prerequisites:
				// 1. The popup window reverse animation completes (container())
				// 2. The screen opacity animation completes (screen())
				this._createPrereqs(
					this._closePrereqScreen.bind(this),
					this._closePrereqContainer.bind(this),
					this._closePrereqsDone.bind(this));

				this._animate( {
					additionalCondition: this._ui.screen.classList.contains("in"),
					transition: (immediate ? "none" : (this._currentTransition || this.options.transition)),
					classToRemove: classes.IN,
					screenClassToAdd: classes.OUT,
					containerClassToAdd: [classes.REVERSE, classes.OUT],
					applyTransition: true,
					prereqs: this._prereqs
				});

				// FIX: for tv profile
				if (typeof this._supportKeyboard !== "boolean") {
					// @todo keyboard support for mobile
					restoreProperties();
				}
			};

			/**
			 * This method opens popup.
			 *
			 *      @example
			 *      <div id="popup" data-role="popup">
			 *          <p>This is a completely basic popup, no options set.</p>
			 *      </div>
			 *
			 *      <script>
			 *          var popupWidget = tau.widget.Popup(document.getElementById("popup"));
			 *
			 *          popupWidget.open();
			 *      </script>
			 *
			 * If jQuery is loaded:
			 *
			 *     @example
			 *      <div id="popup" data-role="popup">
			 *          <p>This is a completely basic popup, no options set.</p>
			 *      </div>
			 *
			 *     <script>
			 *       $("#popup").open("open", {"noScreen" : true, "positionX" : 10});
			 *     </script>
			 *
			 * @method open
			 * @param {Object} [options]
			 * @param {boolean} [options.corners] Sets whether to draw the popup with rounded corners.
			 * @param {string} [options.positionTo="origin"] Sets the element relative to which the popup will be centered.
			 * @param {?string} [options.link=null] Sets id of element used as reference for relative popup placement.
			 * @param {Object} [options.tolerance] Sets the minimum distance from the edge of the window for the corresponding edge of the popup.
			 * @param {boolean} [options.noScreen] Set screen to be always hidden
			 * @param {string} [options.transition] Sets the default transition for the popup.
			 * @param {boolean} [options.popupwindow] Sets whether the popup has context style.
			 * @param {boolean} [options.isHardwarePopup] Sets whether the popup is hardware one.
			 * @param {?number} [options.positionX] Sets desired horizontal coordinate of the center point in popup in pixels.
			 * @param {?number} [options.positionY] Sets desired vertical coordinate of the center point in popup in pixels.
			 * @protected
			 * @member ns.widget.mobile.Popup
			 */
			Popup.prototype.open = function (options) {
				var activePopup = ns.activePopup,
					closePopup,
					event,
					startOpeningCallback;

				if (activePopup !== this) {
					if (!doms.isOccupiedPlace(this._page)) {
						ns.warn("The popup cannot be shown if page which contains the popup is invisible");
					} else {
						// If there is an active popup, wait until active popup will close
						event = arguments[1],
						startOpeningCallback = startOpeningPopup.bind(null, this, options, event);
						if (activePopup) {
							events.one(activePopup.element, "popupafterclose", startOpeningCallback);
							if (activePopup._isOpen) {
								activePopup.close();
							} else if (!activePopup._isPreClose) {
								// If popup is opening or is promised to be opened
								// close it just after opening
								closePopup = activePopup.close.bind(activePopup);
								events.one(activePopup.element, "popupafteropen", closePopup);
							}
						} else {
							startOpeningCallback();
						}
						ns.activePopup = this;
					}
				}
			};

			/**
			 * Close popup
			 *
			 *      @example
			 *      <div id="popup" data-role="popup">
			 *          <p>This is a completely basic popup, no options set.</p>
			 *      </div>
			 *
			 *      <script>
			 *          var popupWidget = tau.widget.Popup(document.getElementById("popup"));
			 *
			 *          popupWidget.close(true); // popup will be closed without animation
			 *      </script>
			 *
			 * If jQuery is loaded:
			 *
			 *      @example
			 *      <div id="popup" data-role="popup">
			 *          <p>This is a completely basic popup, no options set.</p>
			 *      </div>
			 *
			 *      <script>
			 *          $("#popup").popup("close");
			 *      </script>
			 *
			 * @method close
			 * @param {boolean} [immediate=false] defined if popup should be closed without animation
			 * @protected
			 * @member ns.widget.mobile.Popup
			 */
			Popup.prototype.close = function (immediate) {
				// @todo define mutex $.mobile.popup.active
				if (!ns.activePopup || !this._isOpen) {
					return;
				}

				this._close(immediate);
			};

			/**
			* Bind events to widget
			* @method _bindEvents
			* @protected
			* @member ns.widget.mobile.Popup
			*/
			Popup.prototype._bindEvents = function () {
				var self = this,
					buttons = self.element.querySelectorAll(self.options.closeLinkSelector),
					i,
					buttonsLen = buttons.length;
				self._onClickBound = _eatEventAndClose.bind(null, self);
				self._onResizeBound = onResize.bind(null, self);
				self._closeOnEvent = self.close.bind(self, true);
				self._destroyOnEvent = self.destroy.bind(self, self.element);

				self._ui.screen.addEventListener("vclick", self._onClickBound, true);
				window.addEventListener("throttledresize", self._onResizeBound, true);
				if (buttonsLen) {
					for (i = 0; i < buttonsLen; i++) {
						buttons[i].addEventListener("click", self._closeOnEvent, true);
					}
				}
				self._page.addEventListener("pagebeforehide", self._closeOnEvent, true);
				self._page.addEventListener("pagedestroy", self._destroyOnEvent, true);
				// @todo
				// - orientationchange
				// - resize
				// - keyup
			};

			/**
			 * Removes the popup functionality completely.
			 *
			 * This will return the element back to its pre-init state.
			 *
			 *      @example
			 *      <div id="popup" data-role="popup">
			 *          <p>This is a completely basic popup, no options set.</p>
			 *      </div>
			 *
			 *      <script>
			 *          var popupWidget = tau.widget.Popup(document.getElementById("popup"));
			 *          popupWidget.destroy();
			 *      <script>
			 *
			 * If jQuery is loaded:
			 *
			 *      @example
			 *      <div id="popup" data-role="popup">
			 *          <p>This is a completely basic popup, no options set.</p>
			 *      </div>
			 *
			 *      <script>
			 *          $("#popup").popup("destroy");
			 *      </script>
			 *
			 * @method destroy
			 * @member ns.widget.mobile.Popup
			 */

			/**
			* Destroy popup
			* @method _destroy
			* @protected
			* @member ns.widget.mobile.Popup
			*/
			Popup.prototype._destroy = function () {
				var self = this,
					classes = Popup.classes,
					ui = self._ui,
					uiScreen = ui.screen,
					uiPlaceholder = ui.placeholder,
					page = self._page,
					element = self.element,
					elementClasses = element.classList,
					buttons = element.querySelectorAll(self.options.closeLinkSelector),
					i,
					buttonsLen = buttons.length;

				// When we destroy widget, we close it without animation
				self.close(true);

				uiScreen.removeEventListener("vclick", self._onClickBound, true);
				window.removeEventListener("throttledresize", self._onResizeBound, true);
				if (buttonsLen) {
					for (i = 0; i < buttonsLen; i++) {
						buttons[i].removeEventListener("click", self._closeOnEvent, true);
					}
				}

				page.removeEventListener("pagebeforehide", self._closeOnEvent, true);
				page.removeEventListener("pagedestroy", self._destroyOnEvent, true);

				doms.insertNodesBefore(uiPlaceholder, element);
				elementClasses.remove(classes.uiPopup);
				elementClasses.remove(classes.uiOverlaryShadow);
				elementClasses.remove(classes.uiCornerAll);
				uiPlaceholder.parentNode.removeChild(uiPlaceholder);
				ui.arrow.parentNode.removeChild(ui.arrow);
				ui.container.parentNode.removeChild(ui.container);
				uiScreen.parentNode.removeChild(uiScreen);
			};

			/**
			 * This method refreshes position of opened popup.
			 *
			 * In case of context popup, position of arrow is not changed after calling this method.
			 * If the new position of popup's content causes disconnection from the arrow, the position of popup will be corrected automatically. Content of popup is always set so that the arrow is placed between left and right side of the popup's container with proper margin set in option.tolerance.
			 *
			 *      @example
			 *      <div id="popup" data-role="popup">
			 *          <p>This is a completely basic popup, no options set.</p>
			 *      </div>
			 *
			 *      <script>
			 *          var popupWidget = tau.widget.Popup(document.getElementById("popup"));
			 *
			 *          popupWidget.refresh(); // only refresh original position
			 *      </script>
			 *
			 * If jQuery is loaded:
			 *
			 *      @example
			 *      <div id="popup" data-role="popup">
			 *          <p>This is a completely basic popup, no options set.</p>
			 *      </div>
			 *
			 *      <script>
			 *          $("#popup").popup("refresh", {top: 10, left: 10}); // try to set new position for the center point of popup
			 *      </script>
			 *
			 * @method refresh
			 * @param {Object} [options] options
			 * @param {number} [options.positionX] desired horizontal coordinate of the center point in popup in pixels (it only works if both coordinates are set - top and left)
			 * @param {number} [options.positionY] desired vertical coordinate of the center point in popup in pixels (it only works if both coordinates are set - top and left)
			 * @chainable
			 * @member ns.widget.mobile.Popup
			 */

			/**
			* Refresh popup
			* @method _refresh
			* @protected
			* @member ns.widget.mobile.Popup
			*/
			Popup.prototype._refresh = function (options) {
				options = options || {};
				this._setPosition(options.positionX, options.positionY);
			};

			/**
			 * This method changes state of popup on enabled and removes CSS classes connected with state.
			 *
			 *      @example
			 *      <div id="popup" data-role="popup">
			 *          <p>This is a completely basic popup, no options set.</p>
			 *      </div>
			 *
			 *      <script>
			 *          var popupWidget = tau.widget.Popup(document.getElementById("popup"));
			 *          popupWidget.enable();
			 *      </script>
			 *
			 * If jQuery is loaded:
			 *
			 *      @example
			 *      <div id="popup" data-role="popup">
			 *          <p>This is a completely basic popup, no options set.</p>
			 *      </div>
			 *
			 *      <script>
			 *          $("#popup").popup("enable");
			 *      </script>
			 *
			 * @method enable
			 * @chainable
			 * @member ns.widget.mobile.Popup
			 */

			/**
			 * This method changes state of popup on disabled and adds CSS classes connected with state.
			 *
			 *      @example
			 *      <div id="popup" data-role="popup">
			 *          <p>This is a completely basic popup, no options set.</p>
			 *      </div>
			 *
			 *      <script>
			 *          var popupWidget = tau.widget.Popup(document.getElementById("popup"));
			 *          popupWidget.disable();
			 *      </script>
			 *
			 * If jQuery is loaded:
			 *
			 *      @example
			 *      <div id="popup" data-role="popup">
			 *          <p>This is a completely basic popup, no options set.</p>
			 *      </div>
			 *
			 *      <script>
			 *          $("#popup").popup("disable");
			 *      </script>
			 *
			 * @method disable
			 * @chainable
			 * @member ns.widget.mobile.Popup
			 */

			/**
			 * The function "value" is not supported in this widget.
			 *
			 * @method value
			 * @chainable
			 * @member ns.widget.mobile.Popup
			 */

			/**
			 * Get/Set options of the widget.
			 *
			 * This method can work in many context.
			 *
			 * If first argument is type of object them, method set values for options given in object. Keys of object are names of options and values from object are values to set.
			 *
			 * If you give only one string argument then method return value for given option.
			 *
			 * If you give two arguments and first argument will be a string then second argument will be intemperate as value to set.
			 *
			 *      @example
			 *      <div id="popup" data-role="popup">
			 *          <p>This is a completely basic popup, no options set.</p>
			 *      </div>
			 *
			 *      <script>
			 *          var popupWidget = tau.widget.Popup(document.getElementById("popup")),
			 *              optionValue;
			 *
			 *          optionValue = popupWidget.option("positionTo"); // read value of option positionTo
			 *          popupWidget.option("positionTo", "window") // set value
			 *      </script>
			 *
			 * If jQuery is loaded:
			 *
			 *      @example
			 *      <div id="popup" data-role="popup">
			 *          <p>This is a completely basic popup, no options set.</p>
			 *      </div>
			 *
			 *      <script>
			 *          optionValue = $("#popup").popup("option", "positionTo");
			 *          $("#popup").popup("option", "positionTo", "window");
			 *      </script>
			 *
			 * @method option
			 * @param {string|Object} [name] name of option
			 * @param {*} value value to set
			 * @member ns.widget.mobile.Popup
			 * @return {*} return value of option or undefined if method is called in setter context
			 */

			/**
			 * Trigger an event on widget's element.
			 *
			 *      @example
			 *      <div id="popup" data-role="popup">
			 *          <p>This is a completely basic popup, no options set.</p>
			 *      </div>
			 *
			 *      <script>
			 *          var popupWidget = tau.widget.Popup(document.getElementById("popup"));
			 *          popupWidget.trigger("eventName");
			 *      </script>
			 *
			 * If jQuery is loaded:
			 *
			 *      @example
			 *      <div id="popup" data-role="popup">
			 *          <p>This is a completely basic popup, no options set.</p>
			 *      </div>
			 *
			 *      <script>
			 *          $("#popup").popup("trigger", "eventName");
			 *      </script>
			 *
			 * @method trigger
			 * @param {string} eventName the name of event to trigger
			 * @param {?*} [data] additional object to be carried with the event
			 * @param {boolean} [bubbles=true] indicating whether the event bubbles up through the DOM or not
			 * @param {boolean} [cancelable=true] indicating whether the event is cancelable
			 * @return {boolean} false, if any callback invoked preventDefault on event object
			 * @member ns.widget.mobile.Popup
			*/

			/**
			 * Add event listener to widget's element.
			 *
			 *      @example
			 *      <div id="popup" data-role="popup">
			 *          <p>This is a completely basic popup, no options set.</p>
			 *      </div>
			 *
			 *      <script>
			 *          var popupWidget = tau.widget.Popup(document.getElementById("popup")),
			 *              callback = function () {
			 *                  console.log("event fires");
			 *              });
			 *
			 *          popupWidget.on("eventName", callback);
			 *      </script>
			 *
			 * If jQuery is loaded:
			 *
			 *      @example
			 *      <div id="popup" data-role="popup">
			 *          <p>This is a completely basic popup, no options set.</p>
			 *      </div>
			 *
			 *      <script>
			 *          $("#popup").popup("on", "eventName", callback);
			 *      </script>
			 *
			 * @method on
			 * @param {string} eventName the name of event
			 * @param {Function} listener function call after event will be trigger
			 * @param {boolean} [useCapture=false] useCapture param to addEventListener
			 * @member ns.widget.mobile.Popup
			 */

			/**
			 * Remove event listener to widget's element.
			 *
			 *      @example
			 *      <div id="popup" data-role="popup">
			 *          <p>This is a completely basic popup, no options set.</p>
			 *      </div>
			 *
			 *      <script>
			 *          var popupWidget = tau.widget.Popup(document.getElementById("popup")),
			 *              callback = function () {
			 *                  console.log("event fires");
			 *              });
			 *
			 *          // add callback on event "eventName"
			 *          popupWidget.on("eventName", callback);
			 *          // ...
			 *          // remove callback on event "eventName"
			 *          popupWidget.off("eventName", callback);
			 *      </script>
			 *
			 * If jQuery is loaded:
			 *
			 *      @example
			 *      <div id="popup" data-role="popup">
			 *          <p>This is a completely basic popup, no options set.</p>
			 *      </div>
			 *
			 *      <script>
			 *          // add callback on event "eventName"
			 *          $("#popup").popup("on", "eventName", callback);
			 *          // ...
			 *          // remove callback on event "eventName"
			 *          $("#popup").popup("off", "eventName", callback);
			 *      </script>
			 *
			 * @method off
			 * @param {string} eventName the name of event
			 * @param {Function} listener function call after event will be trigger
			 * @param {boolean} [useCapture=false] useCapture param to addEventListener
			 * @member ns.widget.mobile.Popup
			 */

			ns.widget.mobile.Popup = Popup;
			engine.defineWidget(
				"Popup",
				"[data-role='popup'], .ui-popup",
				[
					"open",
					"close",
					"setPositionCallback",
					"setPositionCB"
				],
				Popup,
				"mobile"
			);
			}(window, window.document, ns));

/*global window, define */
/*
* Copyright  2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/*jslint nomen: true, plusplus: true */
/**
 * #Date-time Picker Widget
 * The picker widget shows a control that you can use to enter date and time values.
 *
 * @class ns.widget.mobile.Datetimepicker
 * @extends ns.widget.mobile.BaseWidgetMobile
 */
(function (document, ns) {
	
				var Datetimepicker = function () {
					this.options = {
						type: null, // date, time, datetime applicable
						format: null,
						date: null
					};
				},
				BaseWidget = ns.widget.mobile.BaseWidgetMobile,
				engine = ns.engine,
				dom = ns.util.DOM,
				globalize = ns.util.globalize,
				eventUtils = ns.event,
				range = ns.util.array.range,
				daysInMonth = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ],
				parsePatternRegexp = /\/|\s|dd|d|MMMM|MMM|MM|M|yyyy|yy|y|hh|h|HH|H|mm|m|ss|s|tt|t|f|gg|g|'[\w\W]*'$|[\w\W]/g,
				fieldRegexp = /ui-datefield-([\w]*)/;

			Datetimepicker.prototype = new BaseWidget();

			Datetimepicker.classes = {
				uiBtnPicker: 'ui-btn-picker',
				uiDatefield: 'ui-datefield',
				uiDatefieldPrefix: 'ui-datefield-',
				uiDatefieldSelected: 'ui-datefield-selected',
				uiDatefieldPeriod: 'ui-datefield-period',
				uiLink: 'ui-link',
				uiDatetimepickerSelector: 'ui-datetimepicker-selector',
				uiDatetimepicker: 'ui-datetimepicker',
				uiInputText: 'ui-input-text',
				uiBodyPrefix: 'ui-body-',
				uiDivider1st: 'ui-divider-1st',
				uiDivider2nd: 'ui-divider-2nd',
				inClass: 'in',
				outClass: 'out',
				current: 'current'
			};

			function getCalendar() {
				return globalize.culture().calendars.standard;
			}

			function isLeapYear(year) {
				return year % 4 ? 0 : (year % 100 ? 1 : (year % 400 ? 0 : 1));
			}

			function makeTwoDigits(val) {
				var ret = val.toString(10);
				if (val < 10) {
					ret = "0" + ret;
				}
				return ret;
			}

			function createDateField(type, pat, container) {
				var span = document.createElement('span'),
					spanClassList = span.classList,
					classes = Datetimepicker.classes;
				if (type !== 'seperator' && type !== 'tab') {
					spanClassList.add(classes.uiBtnPicker);
					dom.setNSData(span, 'type', type);
				}
				spanClassList.add(classes.uiDatefieldPrefix + type);
				dom.setNSData(span, 'pat', pat);
				if (type !== 'seperator' && type !== 'tab') {
					dom.setNSData(span, 'role', "button");
					dom.setNSData(span, 'inline', "true");
					engine.instanceWidget(span, 'Button');
				}
				dom.appendNodes(container, span);
				return span;
			}

			function updateField(self, target, value) {
				var pat,
					hour,
					text,
					targetClassList,
					classes = Datetimepicker.classes;

				if (!target) {
					return;
				}

				if (value === 0) {
					value = "0";
				}

				pat = dom.getNSData(target, 'pat');
				targetClassList = target.classList;

				switch (pat) {
					case 'H':
					case 'HH':
					case 'h':
					case 'hh':
						hour = value;
						if (pat.charAt(0) === 'h') {
							if (hour > 12) {
								hour -= 12;
							} else if (hour === 0) {
								hour = 12;
							}
						}
						hour = makeTwoDigits(hour);
						text = hour;
						break;
					case 'm':
					case 'M':
					case 'd':
					case 's':
						text = value;
						break;
					case 'mm':
					case 'dd':
					case 'MM':
					case 'ss':
						text = makeTwoDigits(value);
						break;
					case 'MMM':
						text = getCalendar().months.namesAbbr[value - 1];
						break;
					case 'MMMM':
						text = getCalendar().months.names[value - 1];
						break;
					case 'yy':
						text = makeTwoDigits(value % 100);
						break;
					case 'yyyy':
						if (value < 10) {
							value = '000' + value;
						} else if (value < 100) {
							value = '00' + value;
						} else if (value < 1000) {
							value = '0' + value;
						}
						text = value;
						break;
					case 't':
					case 'tt':
						text = value;
						target = target.firstChild.firstChild;
						break;
				}

				// to avoid reflow where its value isn't out-dated
				if (target.innerText !== text) {
					if (targetClassList.contains(classes.uiDatefieldSelected)) {
						targetClassList.add(classes.outClass);
						self._new_value = text;
						/*
						* @todo animation
						target.animationComplete( function () {
						target.text( self._new_value);
						target.addClass("in")
						removeClass("out");

						target.animationComplete( function () {
						target.removeClass("in").
						removeClass("ui-datefield-selected");
						});
						});
						*/
						target.innerText = self._new_value;
						targetClassList.remove(classes.inClass);
						targetClassList.remove(classes.uiDatefieldSelected);
					} else {
						target.innerText = text;
					}
				}
			}

			Datetimepicker.prototype._setType = function (element, type) {
				var options = this.options;

				switch (type) {
					case 'datetime':
					case 'date':
					case 'time':
						options.type = type;
						break;
					default:
						options.type = 'datetime';
						break;
				}

				dom.setNSData(element, 'type', options.type);
				return this;
			};


			Datetimepicker.prototype._setDate = function (element, newdate) {
				var oldValue = this._getValue(),
					newValue,
					fields,
					type,
					val,
					field,
					i,
					fieldsLength;

				if (typeof newdate === "string") {
					newdate = new Date(newdate);
				}

				if (this._ui) {
					fields = this._ui.querySelectorAll('[data-type]');
					fieldsLength = fields.length;

					for (i = 0; i < fieldsLength; i++) {
						field = fields[i];
						type = dom.getNSData(field, 'type');
						if (!type) {
							type = "";
						}
						switch (type) {
							case 'hour':
								val = newdate.getHours();
								break;
							case 'min':
								val = newdate.getMinutes();
								break;
							case 'sec':
								val = newdate.getSeconds();
								break;
							case 'year':
								val = newdate.getFullYear();
								break;
							case 'month':
								val = newdate.getMonth() + 1;
								break;
							case 'day':
								val = newdate.getDate();
								break;
							case 'period':
								val = newdate.getHours() < 12 && getCalendar().AM ? getCalendar().AM[0] : getCalendar().PM[0];
								break;
							default:
								val = null;
								break;
						}
						if (val !== null) {
							updateField(this, field, val);
						}
					}
				}

				this.options.date = newdate;
				dom.setNSData(element, "date", newdate);

				newValue = this._getValue();

				eventUtils.trigger(element, 'change', {
					oldValue: oldValue,
					newValue: newValue
				});
				eventUtils.trigger(element, 'date-changed', newValue);
				return this;
			};

			Datetimepicker.prototype._getDate = function () {
				return new Date(this.options.date);
			};

			function switchAmPm(self, element) {
				var date,
					change;

				if (getCalendar().AM !== null) {
					date = new Date(self.options.date);
					change = 1000 * 60 * 60 * 12;

					if (date.getHours() > 11) {
						change = -change;
					}
					date.setTime(date.getTime() + change);
					self._setDate(element, date);
				}
			}

			function addButton(self, container, element, pat) {
				var button = document.createElement('a');

				dom.setNSData(button, 'role', 'button');
				dom.setNSData(button, 'pat', pat);
				dom.setNSData(button, 'type', 'period');
				button.innerText = 'period';
				button.classList.add(Datetimepicker.classes.uiDatefieldPeriod);

				engine.instanceWidget(button, 'Button', {
					inline: true
				});

				button.addEventListener('vclick', function () {
					switchAmPm(self, element);
				});
				dom.appendNodes(container, button);

				return button;
			}

			function parsePattern(pattern) {
				var matches = pattern.match(parsePatternRegexp),
					matchesLength = matches.length,
					i;
				for (i = 0; i < matchesLength; i++) {
					if (matches[i].charAt(0) === "'") {
						matches[i] = matches[i].substr(1, matches[i].length - 2);
					}
				}
				return matches;
			}

			function populateDataSelector(self, field, pat) {
				var date = new Date(self.options.date),
					values,
					numItems,
					current,
					data,
					yearlb,
					yearhb,
					day;

				switch (field) {
					case 'hour':
						if (pat === 'H' || pat === 'HH') {
							// twentyfour
							values = range(0, 23);
							data = range(0, 23);
							current = date.getHours();
						} else {
							values = range(1, 12);
							current = date.getHours() - 1;//11
							if (current >= 11) {
								current = current - 12;
								data = range(13, 23);
								data.push(12); // consider 12:00 am as 00:00
							} else {
								data = range(1, 11);
								data.push(0);
							}
							if (current < 0) {
								current = 11; // 12:00 or 00:00
							}
						}
						if (pat.length === 2) {
							// two digit
							values = values.map(makeTwoDigits);
						}
						numItems = values.length;
						break;
					case 'min':
					case 'sec':
						values = range(0, 59);
						if (pat.length === 2) {
							values = values.map(makeTwoDigits);
						}
						data = range(0, 59);
						current = (field === 'min' ? date.getMinutes() : date.getSeconds());
						numItems = values.length;
						break;
					case 'year':
						yearlb = 1900;
						yearhb = 2100;
						data = range(yearlb, yearhb);
						current = date.getFullYear() - yearlb;
						values = range(yearlb, yearhb);
						numItems = values.length;
						break;
					case 'month':
						switch (pat.length) {
							case 1:
								values = range(1, 12);
								break;
							case 2:
								values = range(1, 12).map(makeTwoDigits);
								break;
							case 3:
								values = getCalendar().months.namesAbbr.slice();
								break;
							case 4:
								values = getCalendar().months.names.slice();
								break;
						}
						if (values.length === 13) { // @TODO Lunar calendar support
							if (values[12] === "") { // to remove lunar calendar reserved space
								values.pop();
							}
						}
						data = range(1, values.length);
						current = date.getMonth();
						numItems = values.length;
						break;
					case 'day':
						day = daysInMonth[date.getMonth()];
						if (day === 28) {
							day += isLeapYear(date.getFullYear());
						}
						values = range(1, day);
						if (pat.length === 2) {
							values = values.map(makeTwoDigits);
						}
						data = range(1, day);
						current = date.getDate() - 1;
						numItems = day;
						break;
				}
				return {
					values: values,
					data: data,
					numItems: numItems,
					current: current
				};
			}

			function date_calibration(date) {
				date.setDate(1);
				date.setDate(date.getDate() - 1);
			}

			function updateHandler(self, field, val) {
				var date = new Date(self.options.date),
					month;

				switch (field[1]) {
					case 'min':
						date.setMinutes(val);
						break;
					case 'hour':
						date.setHours(val);
						break;
					case 'sec':
						date.setSeconds(val);
						break;
					case 'year':
						month = date.getMonth();
						date.setFullYear(val);
						if (date.getMonth() !== month) {
							date_calibration();
						}
						break;
					case 'month':
						date.setMonth(val - 1);
						if (date.getMonth() === val) {
							date_calibration();
						}
						break;
					case 'day':
						date.setDate(val);
						break;
				}
				self._setDate(self.element, date);
			}

			function liClickHandler(self, event) {
				var val,
					target = event.target,
					classes = Datetimepicker.classes;

				if (target.tagName === 'A') {
					target.parentNode.parentNode.querySelector('.' + classes.current).classList.remove(classes.current);
					target.parentNode.classList.add(classes.current);
					val = dom.getNSData(target, 'val');

					updateHandler(self, self._field, val);

					self._ctx.close();
				}
			}

			function closePopupHandler(self) {
				var ctxElement = self._ctx.element,
					targetClassList = self._target.classList,
					classes = Datetimepicker.classes;
				if (self._reflow) {
					window.removeEventListener("resize", self._reflow);
					self._reflow = null;
				}

				if (!(targetClassList.contains(classes.inClass) || targetClassList.contains(classes.outClass))) {
					targetClassList.remove(classes.uiDatefieldSelected);
				}

				ctxElement.removeEventListener('popupafterclose', self._closePopupHandler);
				self._circularview.element.removeEventListener('vclick', self.liClickHandler);
				self._ctx.destroy();
				ctxElement.parentNode.removeChild(ctxElement);
				self._popup_open = false;
			}

			function scrollEndHandler(self) {
				if (!self._reflow) {
					self._reflow = function () {
						self._circularview.reflow();
					};
					window.addEventListener("resize", self._reflow);
				}
			}

			/**
			 * Method shows data selector.
			 * @method showDataSelector
			 * @param self
			 * @param target
			 * @return {?Object}
			 */
			function showDataSelector(self, target) {
				var className = target.className,
					field = className ? className.match(fieldRegexp) : null,
					pat,
					data,
					values,
					valuesData,
					current,
					datans,
					ul,
					div,
					li,
					a,
					i,
					ctx,
					circularview,
					valuesLength,
					divCircularview,
					divCircularviewContainer,
					ctxElement,
					classes = Datetimepicker.classes;

				if (!field) {
					return null;
				}
				if (self._popup_open) {
					return null;
				}

				self._target = target;
				self._field = field;
				target.classList.add(classes.uiDatefieldSelected);

				pat = dom.getNSData(target, 'pat');
				data = populateDataSelector(self, field[1], pat);

				if (!target.id) {
					target.id = self.elememberOfment.id + '-' + pat;
				}

				values = data.values;
				valuesLength = values.length;
				valuesData = data.data;
				current = data.current;

				if (values) {
					datans = "data-val";
					ul = document.createElement('ul');
					for (i = 0; i < valuesLength; i++) {
						li = document.createElement('li');
						if (i === current) {
							li.classList.add(classes.current);
						}
						a = document.createElement('a');
						a.classList.add(classes.uiLink);
						a.setAttribute(datans, valuesData[i]);
						a.innerText = values[i];
						li.appendChild(a);
						ul.appendChild(li);
					}

					div = document.createElement('div');
					div.classList.add(classes.uiDatetimepickerSelector);
					div.setAttribute('data-transition', 'fade');
					div.setAttribute('data-fade', 'false');
					div.setAttribute('data-role', 'popup');
					div.setAttribute('data-corners', 'false');
					divCircularview = document.createElement('div');
					divCircularview.appendChild(ul);

					self._ui.appendChild(div);

					ctx = engine.instanceWidget(div, 'Popup');
					self._ctx = ctx;
					divCircularviewContainer = document.createElement('div');
					div.appendChild(divCircularviewContainer);
					divCircularviewContainer.appendChild(divCircularview);
					divCircularviewContainer.style.overflow = 'hidden';
					// @TODO quich fix, change to proper width
					divCircularviewContainer.style.width = window.innerWidth +"px";
					ctxElement = ctx.element;
					ctxElement.parentNode.classList.add(classes.uiDatetimepicker);
					divCircularview.setAttribute('data-list', ">li");
					divCircularview.setAttribute('data-role', "circularview");

					circularview = engine.instanceWidget(divCircularview, 'Circularview');
					self._circularview = circularview;
					if (!self._reflow) {
						self._reflow = function () {
							circularview.reflow();
							circularview.centerTo('.' + classes.current, 0);
						};
						window.addEventListener("resize", self._reflow);
					}
					ctx.open({
						link: target.id,
						popupwindow: true,
						tolerance: "10,0"
					});

					self.contextPopup = ctx;
					self._popup_open = true;

					self._closePopupHandler = closePopupHandler.bind(null, self);
					self._liClickHandler = liClickHandler.bind(null, self);
					self._scrollEndHandler = scrollEndHandler.bind(null, self);
					ctxElement.addEventListener('popupafterclose', self._closePopupHandler);
					divCircularview.addEventListener('vclick', self._liClickHandler, true);

					circularview.centerTo('.' + classes.current, 500);
					ctxElement.addEventListener('scrollend', self._scrollEndHandler);
				}
				return self._ui;
			}

			/**
			 *
			 * @param self
			 * @returns {boolean}
			 */
			function orientationHandler(self) {
				if (self._popup_open) {
					self._popup_open = false;
					self.contextPopup.close();
				}
				return false;
			}

			Datetimepicker.prototype._setFormat = function (element, format, create) {
				var options = this.options,
					token,
					div = document.createElement('div'),
					tabulatordiv,
					pat,
					span,
					classes = Datetimepicker.classes;
				if (format) {
					if (options.format === format) {
						return null;
					} else {
						options.format = format;
					}
				} else {
					if (!create) {
						return null;
					}
					format = options.format;
				}

				dom.removeAllChildren(this._ui);

				token = parsePattern(format);

				while (token.length > 0) {
					pat = token.shift();
					switch (pat) {
						case 'H': //0 1 2 3 ... 21 22 23
						case 'HH': //00 01 02 ... 21 22 23
						case 'h': //0 1 2 3 ... 11 12
						case 'hh': //00 01 02 ... 11 12
							span = createDateField('hour', pat, div);
							break;
						case 'mm': //00 01 ... 59
						case 'm': //0 1 2 ... 59
							if (options.type === 'date') {
								span = createDateField('month', pat, div);
							} else {
								span = createDateField('min', pat, div);
							}
							break;
						case 'ss':
						case 's':
							span = createDateField('sec', pat, div);
							break;
						case 'd': // day of month 5
						case 'dd': // day of month(leading zero) 05
							span = createDateField('day', pat, div);
							break;
						case 'M': // Month of year 9
						case 'MM': // Month of year(leading zero) 09
						case 'MMM':
						case 'MMMM':
							span = createDateField('month', pat, div);
							break;
						case 'yy':	// year two digit
						case 'yyyy': // year four digit
							span = createDateField('year', pat, div);
							break;
						case 't': //AM / PM indicator(first letter) A, P
						// add button
						case 'tt': //AM / PM indicator AM/PM
							// add button
							span = addButton(this, div, element, pat);
							break;
						case 'g':
						case 'gg':
							span = createDateField('era', pat, div);
							span.innerText = this._calendar().eras.name;
							break;
						case '\t':
							span = createDateField('tab', pat, div);
							tabulatordiv = document.createElement('div');
							tabulatordiv.classList.add(classes.uiDivider1st);
							tabulatordiv.innerHTML = '&nbsp;';
							span.appendChild(tabulatordiv);
							tabulatordiv = document.createElement('div');
							tabulatordiv.classList.add(classes.uiDivider2nd);
							tabulatordiv.innerHTML = '&nbsp;';
							span.appendChild(tabulatordiv);
							break;
						default: // string or any non-clickable object
							span = createDateField('seperator', pat, div);
							span.innerText = pat.replace(/[\-\/]/gi, '');
							break;
					}
				}

				dom.appendNodes(this._ui, div);
				if (options.date) {
					this._setDate(element, options.date);
				}

				element.setAttribute("data-format", options.format);
				return options.format;
			};

			/**
			 * @method _build
			 * @param {HTMLElement} element
			 * @return {HTMLElement}
			 * @private
			 * @member ns.widget.mobile.Datetimepicker
			 */
			Datetimepicker.prototype._build = function (element) {
				var ui,
					elementClassList = element.classList,
					tagName = element.tagName.toLowerCase(),
					classes = Datetimepicker.classes;

				// INFO: Since 2.3, we decided to use Webkit based date-time picker.
				ns.warn("TAU based Datetimepicker widget will be deprecated. It is decieded to be replaced <input> based date-time picker. Please use <input type='month|week|date|time|datetime-local'> for date-time picker");

				if (tagName === 'input') {
					element.style.display = 'none';
					/*
					 * @todo change to class object
					 */
					elementClassList.add(classes.uiInputText);
					elementClassList.add(classes.uiBodyPrefix + 's');
				}
				ui = document.createElement('div');
				ui.setAttribute('id', this.id + '-datetimepicker-ui');
				ui.classList.add(classes.uiDatefield);
				this._ui = ui;
				if (tagName === 'input') {
					dom.insertNodeAfter(element, ui);
				} else {
					element.appendNode(ui);
				}

				return element;
			};

			function datetimepicerClick(self, event) {
				showDataSelector(self, event.target);
				return false;
			}

			Datetimepicker.prototype._bindEvents = function () {
				this._orientationHandlerBound = orientationHandler.bind(null, this);
				this._datetimepicerClickBound = datetimepicerClick.bind(null, this);
				this._ui.addEventListener('vclick', this._datetimepicerClickBound, true);
				window.addEventListener('orientationchange', this._orientationHandlerBound, false);
			};

			/**
			 * @method _init
			 * @protected
			 * @member ns.widget.mobile.Datetimepicker
			 */
			Datetimepicker.prototype._init = function () {
				var options = this.options,
					element = this.element,
					value,
					tagName = element.tagName.toLowerCase(),
					classes = Datetimepicker.classes,
					type;
				if (!this._ui) {
					this._ui = document.getElementById(this.id + '-datetimepicker-ui');
				}
				if (!options.format) {
					switch (options.type) {
						case 'datetime':
							this._setFormat(getCalendar().patterns.d + "\t" + getCalendar().patterns.t);
							break;
						case 'date':
							this._setFormat(element, getCalendar().patterns.d);
							break;
						case 'time':
							this._setFormat(element, getCalendar().patterns.t);
							break;
					}
				}

				if (element && tagName === 'input') {
					value = element.getAttribute("value");
					if (value) {
						options.date = new Date(value);
					}
					type = element.getAttribute("type");
					this._setType(element, type);
					if (!options.format) {
						switch (type) {
							case 'datetime':
								this._setFormat(element, getCalendar().patterns.d + "\t" + getCalendar().patterns.t);
								break;
							case 'date':
								this._setFormat(element, getCalendar().patterns.d);
								break;
							case 'time':
								this._setFormat(element, getCalendar().patterns.t);
								break;
						}
					}
				}

				if (!options.date) {
					options.date = new Date();
				}
				this._setFormat(element, null, true);
				this._popup_open = false;
				this._popup_open = false;
			};

			Datetimepicker.prototype._destroy = function () {
				this._ui.removeEventListener('vclick', this._datetimepicerClickBound, true);
				window.removeEventListener('orientationchange', this._orientationHandlerBound, false);
			};

			Datetimepicker.prototype._setValue = function (value) {
				return this._setDate(this.element, value);
			};

			function timetoString(time) {
				return makeTwoDigits(time.getHours()) + ':' +
					makeTwoDigits(time.getMinutes()) + ':' +
					makeTwoDigits(time.getSeconds());
			}

			function dateToString(date) {
				return ((date.getFullYear() % 10000) + 10000).toString().substr(1) + '-' +
					makeTwoDigits(date.getMonth() + 1) + '-' +
					makeTwoDigits(date.getDate());
			}

			Datetimepicker.prototype._isLeapYear = function (year) {
				return isLeapYear(year);
			};

			Datetimepicker.prototype._switchAmPm = function () {
				return switchAmPm(this, this.element);
			};

			Datetimepicker.prototype._getValue = function () {
				var date = this._getDate(this.element),
					rvalue;
				switch (this.options.type) {
					case 'time':
						rvalue = timetoString(date);
						break;
					case 'date':
						rvalue = dateToString(date);
						break;
					default:
						rvalue = dateToString(date) + 'T' + timetoString(date);
						break;
				}
				return rvalue;
			};

			// definition
			ns.widget.mobile.Datetimepicker = Datetimepicker;
			engine.defineWidget(
				"Datetimepicker",
				// Datetimepicker UI changed in changeable UX.
				// New UX need to UX whole change so we decide datetimepicker reimplement lately
				//"input[type='date'], input[type='datetime'], input[type='time'], [date-role='datetimepicker'], .ui-datetimepicker",
				"[data-role='datetimepicker']",
				[],
				Datetimepicker,
				'tizen'
			);

			}(window.document, ns));

/*global window, define */
/*
* Copyright  2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/*jslint nomen: true, plusplus: true */
/**
 * #Flip Toggle Switch Widget
 * Toggle Switch widget is a common UI element on mobile devices that is used
 * for binary on/off or true/false data input. You can either drag the flip
 * handle like a slider or tap one side of the switch.
 *
 * ## Default selectors
 * all **SELECT** tags with _data-type=range_ or class _ui-slider_ are changed
 * to toggle switch.
 *
 * ###HTML Examples
 *
 * ####Create simple toggle switch from select using data-role
 *
 *		@example
 *		<select name="flip-11" id="flip-11" data-role="range">
 *			<option value="off"></option>
 *			<option value="on"></option>
 *		</select>
 *
 * ## Manual constructor
 * For manual creation of toggle switch widget you can use constructor of
 * widget from **tau** namespace:
 *
 *		@example
 *		<select id="toggle" name="flip-11" id="flip-11" data-role="range"
 *		data-mini="true">
 *			<option value="off"></option>
 *			<option value="on"></option>
 *		</select>
 *		<script>
 *			var toggleElement = document.getElementById("toggle"),
 *				toggle = tau.widget.Slider(toggleElement, {mini: true});
 *		</script>
 * Constructor has one require parameter **element** which are base
 * **HTMLElement** to create widget. We recommend get this element by method
 * *document.getElementById*. Second parameter is **options** and it is
 * a object with options for widget.
 *
 * ####If jQuery library is loaded, its method can be used:
 *
 *		@example
 *		<select id="toggle" name="flip-11" id="flip-11" data-role="range"
 *		data-mini="true">
 *			<option value="off"></option>
 *			<option value="on"></option>
 *		</select>
 *		<script>
 *			var toggle = $("#toggle").slider({mini: true});
 *		</script>
 * jQuery Mobile constructor has one optional parameter is **options** and it
 * is a object with options for widget.
 *
 * ##Options for toggle switch Widget
 *
 * Options for widget can be defined as _data-..._ attributes or give as
 * parameter in constructor.
 *
 * You can change option for widget using method **option**.
 *
 * ###Mini version
 * For a more compact version that is useful in toolbars and tight spaces,
 * add the data-mini="true" attribute to the toggle switch to create
 * a mini version. This will produce a slider that is not as tall
 * as the standard version and has a smaller text size.
 *
 *		@example
 *		<select name="flip-11" id="flip-11" data-role="range"
 *		data-mini="true">
 *			<option value="off"></option>
 *			<option value="on"></option>
 *		</select>
 *
 * ###Inline Slider
 * By default, all toggle switches in the body content are styled
 * as block-level elements so they fill the width of the screen. However,
 * if you want a more compact toggle switch that is only as wide as the text
 * and icons inside, add the data-inline="true" attribute to the slider.
 *
 *		@example
 *		<select name="flip-11" id="flip-11" data-role="range"
 *		data-inline="true">
 *			<option value="off"></option>
 *			<option value="on"></option>
 *		</select>
 *
 * ###Vertical Slider
 * To implement verticcal slider, add _vertical_ option to *input* element.
 * The value of vertical property is designed to set the height of vertical slider.
 * If the vertical value is set to simply "true", the height of vertical slider
 * is set to pixel value as 5 time of its max value by default. So, to change one value
 * in veritcal slider with "true" option, handle is needed to move 5px.
 * The below example would create a vertical slider with 300px of height.
 *
 * 		@example
 *		<input id="vSlider" name="vSlider" type="range"
 *			value="5" min="0" max="10" data-vertical="300" />
 *
 * ##Methods
 *
 * To call method on widget you can use one of existing API:
 *
 * First API is from tau namespace:
 *
 *		@example
 *		<select name="flip-11" id="toggle" data-role="range"
 *		data-mini="true">
 *			<option value="off"></option>
 *			<option value="on"></option>
 *		</select>
 *		<script>
 *			var toggleElement = document.getElementById("toggle"),
 *				toggle = tau.widget.Slider(toggleElement, "Slider");
 *
 *			// toggle.methodName(methodArgument1, methodArgument2, ...);
 *			// for example:
 *			toggle.value("on");
 *		</script>
 * Second API is jQuery Mobile API and for call _methodName_ you can use:
 *
 *		@example
 *		<select name="flip-11" id="toggle" data-role="range"
 *		data-mini="true">
 *			<option value="off"></option>
 *			<option value="on"></option>
 *		</select>
 *		<script>
 *			// $("#toggle").slider("methodName", argument1, argument2, ...);
 *			// for example:
 *
 *			$("#toggle").slider("value", "on");
 *		</script>
 *
 * @class ns.widget.mobile.Slider
 * @extends ns.widget.BaseWidget
 * @author Jadwiga Sosnowska <j.sosnowska@partner.samsung.com>
 * @author Krzysztof Antoszek <k.antoszek@samsung.com>
 * @author Maciej Moczulski <m.moczulski@samsung.com>
 * @author Maciej Urbanski <m.urbanski@samsung.com>
 * @author Piotr Karny <p.karny@samsung.com>
 */
(function (document, ns) {
	
				var Slider = function () {
				var self = this;
					/**
					 * All possible widget options
					 * @property {Object} options
					 * @property {?string} [options.trackTheme=null] sets
					 * the color scheme (swatch) for the slider's track
					 * @property {boolean} [options.disabled=false] start
					 * widget as enabled / disabled
					 * @property {?boolean} [options.mini=false] size
					 * of toggle switch
					 * @property {boolean} [options.highlight=true] if set
					 * then toggle switch can be highligted
					 * @property {?boolean} [options.inline=false] if value is
					 * "true" then toggle switch has css property
					 * display = "inline"
					 * @property {string} [options.theme=null] theme of widget
					 * @property {boolean | number} [options.vertical=false] sets
					 * height of vertical slider
					 * @member ns.widget.mobile.Slider
					 */
					self.options = {
						trackTheme: null,
						disabled: false,
						mini: null,
						highlight: true,
						inline: null,
						theme: null,
						vertical: false
					};
					self._ui = {};
					//container background
					self.valueBackGround = null;
					self.dragging = false;
					self.beforeStart = null;
					self.userModified = false;
					self.mouseMoved = false;
				},
				BaseWidget = ns.widget.mobile.BaseWidgetMobile,
				TextInput = ns.widget.mobile.TextInput,
				Button = ns.widget.mobile.Button,
				engine = ns.engine,
				events = ns.event,
				themes = ns.theme,
				selectors = ns.util.selectors,
				DOMutils = ns.util.DOM,
				classes = {
					theme: "ui-body-",
					mini: "ui-mini",
					sliderSnapping : "ui-slider-handle-snapping",
					sliderSwitch: "ui-slider-switch",
					sliderInline: "ui-slider-inline",
					sliderMini: "ui-slider-mini",
					slider: "ui-slider",
					sliderVertical: "ui-vertical-slider",
					sliderHandle: "ui-slider-handle",
					sliderBg: "ui-slider-bg",
					sliderBgVertical: "ui-vertical-slider-bg",
					sliderToggle: "ui-toggle-switch",
					sliderToggleOn: "ui-toggle-on",
					sliderToggleOff: "ui-toggle-off",
					sliderInneroffset: "ui-slider-inneroffset",
					sliderInput: "ui-slider-input",
					sliderLabel: "ui-slider-label",
					sliderLabelTheme: "ui-slider-label-",
					sliderContainer: "ui-slider-container",
					sliderContainerVertical: "ui-vertical-slider-container",
					sliderLabelA: "ui-slider-label-a",
					sliderStateActive: "ui-state-active"
				},
				keyCode = {
					HOME: 36,
					END: 35,
					PAGE_UP : 33,
					PAGE_DOWN: 34,
					UP: 38,
					RIGHT: 39,
					DOWN: 40,
					LEFT: 37
				};

			Slider.prototype = new BaseWidget();

			/**
			* Dictionary for slider related css class names
			* @property {Object} classes
			* @member ns.widget.mobile.Slider
			* @static
			* @readonly
			*/
			Slider.classes = classes;

			/**
			* Dictionary for keyboard codes
			* @property {Object} keyCode
			* @member ns.widget.mobile.Slider
			* @static
			* @readonly
			*/
			Slider.keyCode = keyCode;

			/**
			 * disable any action when TouchMove event appear
			 * @method onTouchMove
			 * @param {Event} event
			 * @private
			 * @static
			 * @member ns.widget.mobile.Slider
			 */
			function onTouchMove(event) {
				event.stopPropagation();
				event.preventDefault();
			}

			/**
			 * Finds the label tag for sended element
			 * @method findLabel
			 * @param {HTMLElement} element
			 * @return {HTMLElement}
			 * @private
			 * @static
			 * @member ns.widget.mobile.Slider
			 */
			function findLabel(element) {
				return element.parentNode.querySelector('label[for="' +
						element.id + '"]');
			}

			/**
			 * sets the width for labels which represents a value of widget
			 * @method refreshLabels
			 * @param {ns.widget.mobile.Slider} self
			 * @param {number} percent
			 * @private
			 * @static
			 * @member ns.widget.mobile.Slider
			 */
			function refreshLabels(self, percent) {
				var ui = self._ui,
					shandle = ui.handle,
					getElementWidth = DOMutils.getElementWidth.bind(DOMutils),
					handlePercent = getElementWidth(shandle, "outer") /
							getElementWidth(ui.slider, "outer") * 100,
					aPercent = percent && handlePercent + (100 - handlePercent)
							* percent / 100,
					bPercent = percent === 100 ? 0 : Math.min(handlePercent +
							100 - aPercent, 100),
					labels = ui.labels,
					i = labels.length,
					label;

				while (i--) {
					label = labels[i];
					label.style.width = 
							(label.classList.contains(classes.sliderLabelA)
									? aPercent : bPercent) + "%";
				}
			}

			/**
			 * returns default position of the slider, if the element is input
			 * @method getInitialValue
			 * @param {string} tag
			 * @param {HTMLElement} element
			 * @return {number}
			 * @private
			 * @static
			 * @member ns.widget.mobile.Slider
			 */
			function getInitialValue(tag, element) {
				return tag === "input" ? parseFloat(element.value) :
						element.selectedIndex;
			}

			/**
			 * creates background for Slider element
			 * @method createBackground
			 * @param {HTMLElement} domSlider
			 * @return {HTMLElement}
			 * @private
			 * @static
			 * @member ns.widget.mobile.Slider
			 */
			function createBackground(domSlider, self) {
				var background = document.createElement("div"),
					cList = background.classList,
					btnClasses = Button.classes;

				cList.add(self.options.vertical ? classes.sliderBgVertical :
					classes.sliderBg);

				cList.add(btnClasses.uiBtnActive);
				cList.add(btnClasses.uiBtnCornerAll);

				return domSlider.insertBefore(background,
						domSlider.firstChild);
			}

			/**
			 * refresh all the elements of Slider widget
			 * @method refresh
			 * @param {ns.widget.mobile.Slider} self
			 * @param {Object|number|null} val
			 * @param {boolean} isfromControl
			 * @param {boolean} preventInputUpdate
			 * @private
			 * @static
			 * @member ns.widget.mobile.Slider
			 */
			function refresh(self, val, isfromControl, preventInputUpdate) {
				var ui = self._ui,
					control = self.element,
					percent,
					centerPercent,
					halfPercent = 50,
					shandle = ui.handle,
					sliderBackground = ui.background,
					sliderBackgroundStyle,
					cType = control.nodeName.toLowerCase(),
					min = 0,
					max = control.querySelectorAll("option").length - 1,
					stepValue = DOMutils.getNumberFromAttribute(control,
							"step", "float", 0),
					step = (cType === "input" && stepValue > 0) ?
							stepValue : 1,
					data,
					touchThreshold,
					localClasses = shandle.classList,
					slider = ui.slider,
					isVertical = self.options.vertical,
					newval,
					valModStep,
					alignValue,
					valueChanged,
					newValueOption,
					sliderOffsetLeft,
					sliderOffsetTop;

				if (cType === "input") {
					min = DOMutils.getNumberFromAttribute(control,
							"min",  "float", min);
					max = DOMutils.getNumberFromAttribute(control,
							"max", "float", max);
				}

				if (isNaN(step)) {
					step = 0;
				}

				if (self.options.disabled) {
					self._disable();
				}

				// If changes came from event
				if (typeof val === "object") {
					data = val;
					// @TODO take parameter out to config
					touchThreshold = 8;
					isVertical ?
					sliderOffsetTop =
						DOMutils.getElementOffset(slider).top :
					sliderOffsetLeft =
						DOMutils.getElementOffset(slider).left;

					// If refreshing while not dragging
					// or movement was within threshold
					if (!self.dragging ||
						data.pageX < sliderOffsetLeft - touchThreshold ||
						data.pageX > sliderOffsetLeft +
						slider.offsetWidth + touchThreshold) {
						return;
					}

					// Calculate new left or top side percent
					if (isVertical) {
						percent = ((data.pageY - sliderOffsetTop +
							selectors.getClosestByClass(slider, "ui-content").scrollTop) /
							slider.offsetHeight) * 100;
					} else {
						percent = ((data.pageX - sliderOffsetLeft) /
							slider.offsetWidth) * 100;
					}
				} else {
					if (val === null) {
						val = (cType === "input") ? parseFloat(control.value) :
							control.selectedIndex;
					}
					if (isNaN(val)) {
						return;
					}
					// While dragging prevent jumping by assigning
					// last percentage value
					if (self.dragging && self._lastPercent) {
						percent = self._lastPercent;
					} else {
						percent = isVertical ?
						100 - ((parseFloat(val) - min) / (max - min) * 100) :
						(parseFloat(val) - min) / (max - min) * 100;
					}
				}
				// Make sure percent is a value between 0 - 100;
				percent = Math.max(0, Math.min(percent, 100));
				self._lastPercent = percent;
				centerPercent = halfPercent - percent;

				newval = (percent / 100) * (max - min) + min;
				//from jQuery UI slider, the following source will round
				// to the nearest step
				valModStep = (newval - min) % step;
				alignValue = newval - valModStep;

				if (Math.abs(valModStep) * 2 >= step) {
					alignValue += (valModStep > 0) ? step : (-step);
				}
				// Since JavaScript has problems with large floats, round
				// the final value to 5 digits after the decimal point
				// (see jQueryUI: #4124)
				newval = parseFloat(alignValue.toFixed(5));

				if (isVertical) {
					shandle.style.top = percent + "%";
					newval = max - Math.max(min, Math.min(newval, max));
				} else {
					shandle.style.left = percent + "%";
					newval = Math.max(min, Math.min(newval, max));
				}

				newValueOption = control.querySelectorAll("option")[newval];
				shandle.setAttribute("aria-valuenow", cType === "input" ?
						newval : newValueOption && newValueOption.value);
				shandle.setAttribute("aria-valuetext", cType === "input" ?
						newval : newValueOption && newValueOption.innerText);
				shandle.setAttribute("title", cType === "input" ?
						newval : newValueOption && newValueOption.innerText);

				if (percent === 100 &&
						localClasses.contains("ui-slider-handle-snapping")) {
					localClasses.remove("ui-toggle-off");
					localClasses.add("ui-toggle-on");
				} else if (percent === 0 &&
						localClasses.contains("ui-slider-handle-snapping")) {
					localClasses.remove("ui-toggle-on");
					localClasses.add("ui-toggle-off");
				}

				if (sliderBackground) {
					sliderBackgroundStyle = sliderBackground.style;
					if (self.options.center) {
						if (centerPercent >= 0) {
							if (isVertical) {
								sliderBackgroundStyle.top = "initial";
								sliderBackgroundStyle.bottom = "50%";
								sliderBackgroundStyle.height = centerPercent + "%";
							} else {
								sliderBackgroundStyle.right = "50%";
								sliderBackgroundStyle.left = "initial";
								sliderBackgroundStyle.width = centerPercent + "%";
							}
						} else {
							if (isVertical) {
								sliderBackgroundStyle.top = "50%";
								sliderBackgroundStyle.bottom = "initial";
								sliderBackgroundStyle.height =
									Math.abs(centerPercent) + "%";
							} else {
								sliderBackgroundStyle.right = "initial";
								sliderBackgroundStyle.left = "50%";
								sliderBackgroundStyle.width =
									Math.abs(centerPercent) + "%";
							}
						}
					} else {
						if (isVertical) {
							sliderBackgroundStyle.height = 100 - percent + "%";
							sliderBackgroundStyle.top = percent + "%";
						} else {
							sliderBackgroundStyle.width = percent + "%";
						}
					}
				}

				// drag the label widths
				if (ui.labels) {
					refreshLabels(self, percent);
				}

				if (!preventInputUpdate) {
					valueChanged = false;
					// update control"s value
					if (cType === "input") {
						valueChanged = control.value !== newval;
						control.value = newval;
					} else {
						valueChanged = control.selectedIndex !== newval;
						control.selectedIndex = newval;
					}
					if (!isfromControl && valueChanged) {
						// Trigger change event on the control element
						events.trigger(control, "change");
					}
				}
			}

			/**
			 * Function fires on mouse move event
			 * @method onVmouseMove
			 * @param {ns.widget.mobile.Slider} self
			 * @param {Event} event
			 * @private
			 * @static
			 * @member ns.widget.mobile.Slider
			 */
			function onVmouseMove(self, event) {
				var tagName = self.element.nodeName.toLowerCase(),
					handle = self._ui.handle;
				// NOTE: we don't do this in refresh because we still want to
				//	support programmatic alteration of disabled inputs
				if (self.dragging && !self.options.disabled) {

					// self.mouseMoved must be updated before refresh() 
					// because it will be used in the control "change" event
					self.mouseMoved = true;

					if (tagName === "select") {
						// make the handle move in sync with the mouse
						handle.classList.remove(classes.sliderSnapping);
					}

					refresh(self, event);
					// only after refresh() you can calculate self.userModified
					self.userModified = self.beforeStart !==
							self.element.selectedIndex;
					event.preventDefault();
				}
			}

			/**
			 * Function fires on mouse move event
			 * @method sliderMouseUp
			 * @param {ns.widget.mobile.Slider} self
			 * @private
			 * @static
			 * @member ns.widget.mobile.Slider
			 */
			function sliderMouseUp(self) {
				if (self.dragging) {
					self.dragging = false;

					if (self.element.nodeName.toLowerCase() === "select") {
						// make the handle move with a smooth transition
						self._ui.handle.classList.add(classes.sliderSnapping);

						if (self.mouseMoved) {
							// this is a drag, change the value only
							// if user dragged enough
							if (self.userModified) {
								refresh(self, self.beforeStart === 0 ? 1 : 0);
							} else {
								refresh(self, self.beforeStart);
							}
						} else {
							refresh(self, self.beforeStart === 0 ? 1 : 0);
						}
					}
					self.mouseMoved = false;
				}
			}

			/**
			 * Build structure of slider widget
			 * @method _build
			 * @param {HTMLElement|HTMLSelectElement} element
			 * @return {HTMLElement}
			 * @protected
			 * @member ns.widget.mobile.Slider
			 */
			Slider.prototype._build = function (element) {
				var options = this.options,
					protoOptions = Slider.prototype.options,
					/*TODO - add support disabled */
					parentTheme = themes.getInheritedTheme(element,
							(protoOptions && protoOptions.theme) || "s"),
					theme = options.theme = options.theme || parentTheme,
					trackTheme = options.trackTheme = options.trackTheme ||
							parentTheme,
					/*
					* tagName containing lowered tagname
					* type String
					*/

					tagName = element.nodeName.toLowerCase(),
					selectClass =
							tagName === "select" ? classes.sliderSwitch : "",

					/*
					* elementId get the id attribute
					* type String
					*/
					elementId = element.getAttribute("id"),
					labelFor = findLabel(element),
					labelID,

					/*TODO - assign in callbacks*/
					min = tagName === "input" ?
							parseFloat(element.getAttribute("min")) : 0,
					/*TODO - assign in callbacks*/
					max = tagName === "input" ?
							parseFloat(element.getAttribute("max")) :
									element.querySelectorAll("option").length -
											1,


					domHandle = document.createElement("a"),
					domSlider = document.createElement("div"),
					sliderContainer,
					domSliderClassList = domSlider.classList,
					i,
					wrapper = null,
					j,
					side,
					sliderTheme,
					sliderImg,
					length,
					optionsCount,
					domSliderChildNod = domSlider.childNodes,
					sliderImgClassL = null,
					elementClassList = null,
					initValue,
					sliderBtnDownTheme,
					elementsOption = element.querySelector("option"),
					btnClasses = Button.classes,
					isVertical = options.vertical;
				if (options.highlight && tagName !== "select") {
					this._ui.background = createBackground(domSlider, this);
				}
				if (isNaN(min)) {
					min = 0;
				}
				if (isNaN(max)) {
					max = 0;
				}

				sliderBtnDownTheme = btnClasses.uiBtnDownThemePrefix +
						trackTheme;
				if (labelFor) {
					labelID = labelFor.getAttribute("id") || elementId +
							"-label";
					labelFor.setAttribute("id", labelID);

					labelFor.classList.add(classes.slider);
				}

				domSlider.setAttribute("role", "application");
				domSlider.id = elementId + "-slider";

				if (isVertical) {
					domSliderClassList.add(classes.sliderVertical);
				} else {
					domSliderClassList.add(classes.slider);
				}

				if (selectClass) {
					domSliderClassList.add(selectClass);
				}

				domSliderClassList.add(sliderBtnDownTheme);
				domSliderClassList.add(btnClasses.uiBtnCornerAll);
				if (options.inline) {
					domSliderClassList.add(classes.sliderInline);
				}
				if (options.mini) {
					domSliderClassList.add(classes.sliderMini);
				}

				domHandle.className = classes.sliderHandle;

				if (elementsOption && elementsOption.innerText === "") {
					domSlider.classList.add(classes.sliderToggle);
				}

				initValue = getInitialValue(tagName, element);
				if (initValue !== 1) {
					domHandle.classList.add(classes.sliderToggleOff);
					if (isVertical) {
						domHandle.style.top = "0px";
					} else {
						domHandle.style.left = "0px";
					}
				}

				domSlider.appendChild(domHandle);

				//temporary way to send initial parameters
				//to the instanceWidget method
				domHandle.setAttribute("data-corners", "true");
				domHandle.setAttribute("data-theme", theme);
				domHandle.setAttribute("data-shadow", "true");

				domHandle.setAttribute("role", "range");
				domHandle.setAttribute("aria-valuemin", min);
				domHandle.setAttribute("aria-valuemax", max);
				domHandle.setAttribute("aria-valuenow", initValue);
				domHandle.setAttribute("aria-valuetext", initValue);
				domHandle.setAttribute("title", initValue);
				domHandle.setAttribute("aria-labelledby", "labelID");
				domHandle.setAttribute("data-role", "button");
				domHandle.setAttribute("inline", "false");
				domHandle.setAttribute("data-bar", "true");
				domHandle.setAttribute("id", elementId + "-handle");

				if (tagName === "select") {
					wrapper = document.createElement("div");
					wrapper.className = classes.sliderInneroffset;

					for (j = 0, length = domSliderChildNod.length;
							j < length; j++) {
						wrapper.appendChild(domSliderChildNod[j]);
					}

					domSlider.appendChild(wrapper);

					// make the handle move with a smooth transition
					domHandle.classList.add("ui-slider-handle-snapping");

					for (i = 0, optionsCount = element.length;
							i < optionsCount; i++) {
						side = i ? "a" : "b";
						sliderTheme = i ? btnClasses.uiBtnActive :
								sliderBtnDownTheme;
						/* TODO - check sliderlabel */
						sliderImg = document.createElement("span");
						sliderImgClassL = sliderImg.classList;
						sliderImgClassL.add(classes.sliderLabel);
						sliderImgClassL.add(classes.sliderLabelTheme + side);
						sliderImgClassL.add(sliderTheme);
						sliderImgClassL.add(btnClasses.uiBtnCornerAll);

						sliderImg.setAttribute("role", "img");
						sliderImg.appendChild(document.createTextNode(
								element[i].innerHTML));
						domSlider.insertBefore(
								sliderImg, domSlider.firstChild);
					}
					sliderContainer = domSlider;
				}

				if (tagName === "input") {
					sliderContainer = document.createElement("div");

					if (isVertical) {
						sliderContainer.classList.add(classes.sliderContainerVertical);
						if (isNaN(isVertical)) {
							ns.warn("data-vetical has inappropriate value.",
							"please use 'true' or proper 'number'.");
							isVertical = max * 5;
						}
						if (typeof isVertical === "boolean") {
							isVertical = max * 5;
						}

						sliderContainer.style.height = isVertical + "px";
					} else {
						sliderContainer.classList.add(classes.sliderContainer);
					}

					sliderContainer.appendChild(domSlider);
					sliderContainer.id = elementId + "-container";
					elementClassList = element.classList;
					elementClassList.add(TextInput.classes.uiInputText);
					elementClassList.add(classes.theme + theme);
					elementClassList.add(classes.sliderInput);
					element.style.display = "none";
				}
				else {
					element.classList.add(classes.sliderSwitch);
				}

				//before it was used in refresh which was called during init,
				//needs duplication in build in order to pass tests
				if (initValue === 1) {
					domHandle.classList.add(classes.sliderToggleOn);
					domHandle.style.left = "27px";
				}

				domHandle.style.right = "auto";

				element.parentNode.insertBefore(sliderContainer,
						element.nextSibling);

				engine.instanceWidget(domHandle, "Button");

				return element;
			};

			/**
			 * Init widget
			 * @method _init
			 * @param {HTMLElement} element
			 * @protected
			 * @member ns.widget.mobile.Slider
			 */
			Slider.prototype._init = function (element) {
				var elementId = element.id,
					self = this,
					ui = self._ui;

				self.element = element;
				ui.slider = document.getElementById(elementId + "-slider");
				ui.handle = document.getElementById(elementId + "-handle");
				ui.container = document.getElementById(elementId +
						"-container") || element;
				ui.background = ui.slider.querySelector(self.options.vertical ?
					"." + Slider.classes.sliderBgVertical :
					"." + Slider.classes.sliderBg);
				self._type = element.tagName.toLowerCase();
				ui.labels = selectors.getChildrenByClass(ui.slider,
						Slider.classes.sliderLabel);
				if ( self.options.center && ui.background )
					ui.background.classList.add(
							Slider.classes.sliderBgHasCenter);
				refresh(self, self._getValue());
			};

			/**
			 * Get or Set value of the widget
			 *
			 * Return element value or set the value
			 *
			 *		@example
			 *		<select id="slider" name="flip-11" data-role="slider">
			 *			<option value="off"></option>
			 *			<option value="on"></option>
			 *		</select>
			 *		<script>
			 *			var slider = document.getElementById("slider"),
			 *				sliderWidget = tau.widget.Slider(slider),
			 *			// value contains index of select tag
			 *			value = sliderWidget.value();
			 *			//sets the index for the toggle
			 *			sliderWidget.value("1");
			 *		</script>
			 *
			 * ####If jQuery library is loaded, its method can be used:
			 *
			 *		@example
			 *		<select id="slider" name="flip-11" data-role="slider">
			 *			<option value="off"></option>
			 *			<option value="on"></option>
			 *		</select>
			 *		<script>
			 *			// value contains index of select tag
			 *			$( "#slider" ).slider( "value" );
			 *			// sets the index for the toggle
			 *			$( "#slider" ).slider( "value", "1" );
			 *		</script>
			 *
			 * @method value
			 * @return {string} In get mode return element value or element
			 * selected index based on tag name.
			 * @since 2.3
			 * @member ns.widget.mobile.Slider
			 */

			/**
			 * Get value of toggle switch. If widget is based on input type
			 * tag otherwise it return index of the element
			 * @method _getValue
			 * @protected
			 * @member ns.widget.mobile.Slider
			 */
			Slider.prototype._getValue = function () {
				return this._type === "input" ?
						parseFloat(this.element.value) :
								this.element.selectedIndex;
			};

			/**
			 * Set value of toggle switch
			 * @method _setValue
			 * @param {string} value
			 * @protected
			 * @member ns.widget.mobile.Slider
			 */
			Slider.prototype._setValue = function (value) {
				var self = this,
					element;

				element = self.element;

				if (element.tagName.toLowerCase() === "input") {
					element.value = value;
				} else {
					element.selectedIndex = value;
				}
			};

			/**
			 * Refresh a slider markup.
			 *
			 * This method will rebuild while DOM structure of widget.
			 *
			 * This method should be called after are manually change in HTML
			 * attributes of widget DOM structure.
			 *
			 * This method is called automatically after change any option
			 * of widget.
			 *
			 *		@example
			 *		<select id="slider" name="flip-11" data-role="slider">
			 *			<option value="off"></option>
			 *			<option value="on"></option>
			 *		</select>
			 *		<script>
			 *			var slider = document.getElementById("slider"),
			 *				  sliderWidget = tau.widget.Slider(slider),
			 *			sliderWidget.refresh();
			 *		</script>
			 *
			 * ####If jQuery library is loaded, its method can be used:
			 *
			 *		@example
			 *		<select id="slider" name="flip-11" data-role="slider">
			 *			<option value="off"></option>
			 *			<option value="on"></option>
			 *		</select>
			 *		<script>
			 *			$( "#slider" ).slider( "refresh" );
			 *		</script>
			 *
			 * @method refresh
			 * @chainable
			 * @member ns.widget.mobile.Slider
			 */

			/**
			 * Refresh slider
			 * @method _refresh
			 * @protected
			 * @member ns.widget.mobile.Slider
			 */
			Slider.prototype._refresh = function () {
				var self = this;
				if (self.value !== self._getValue()) {
					refresh(self, self._getValue());
				}
			};

			/**
			 * Bind events to widget
			 * @method _bindEvents
			 * @protected
			 * @member ns.widget.mobile.Slider
			 */
			Slider.prototype._bindEvents = function (element) {
				var self = this,
					ui = self._ui,
					handle = ui.handle,
					tagName = element.nodeName.toLowerCase(),
					slider = ui.slider,
					step = parseFloat( self.element.getAttribute( "step" ) ||
							1 ),
					min = tagName === "input" ?
							parseFloat(element.getAttribute("min")) : 0,
					max = tagName === "input"
							? parseFloat(element.getAttribute("max")) :
									element.getElementsByTagName(
											"option").length - 1;

				element.addEventListener("change", function () {
					if (!self.mouseMoved) {
						refresh(self, self._getValue(), true);
					}
				}, false);

				element.addEventListener("keyup", function () {
					refresh(self, self._getValue(), true, true);
				}, false);

				element.addEventListener("blur", function () {
					refresh(self, self._getValue(), true);
				}, false);

				handle.addEventListener("vmousedown", function (event) {
					events.trigger(event.target, "focus");
				}, false);
				handle.addEventListener("vclick", function (event) {
					event.stopPropagation();
					event.preventDefault();
				}, false);
				handle.addEventListener("keydown", function (event) {
					var index = getInitialValue(tagName, element),
						keyCode = Slider.keyCode,
						classList = event.target.classList;

					if (self.options.disabled) {
						return;
					}

					// In all cases prevent the default and mark the handle
					// as active
					switch (event.keyCode) {
						case keyCode.HOME:
						case keyCode.END:
						case keyCode.PAGE_UP:
						case keyCode.PAGE_DOWN:
						case keyCode.UP:
						case keyCode.RIGHT:
						case keyCode.DOWN:
						case keyCode.LEFT:
							event.preventDefault();

							if (!self._keySliding) {
								self._keySliding = true;
								classList.add(classes.sliderStateActive);
							}
							break;
					}
					// move the slider according to the keypress
					switch (event.keyCode) {
						case keyCode.HOME:
							refresh(self, min);
							break;
						case keyCode.END:
							refresh(self, max);
							break;
						case keyCode.PAGE_UP:
						case keyCode.UP:
						case keyCode.RIGHT:
							refresh(self, index + step);
							break;
						case keyCode.PAGE_DOWN:
						case keyCode.DOWN:
						case keyCode.LEFT:
							//self.refresh(index - step);
							refresh(self, index - step);
							break;
					}


				}, false);
				handle.addEventListener("keyup", function () {
					if (self._keySliding) {
						self._keySliding = false;
						handle.classList.remove(classes.sliderStateActive);
					}
				}, false);
				slider.addEventListener("touchend", function () {
					self.dragging = false;
					handle.classList.add("ui-slider-handle-snapping");
					refresh(self, getInitialValue(tagName, element),
							true, true);
				}, false);

				slider.addEventListener("vmousedown", function (event) {
					if (self.options.disabled) {
						return false;
					}

					self.dragging = true;
					self.userModified = false;
					self.mouseMoved = false;

					if (tagName === "select") {
						self.beforeStart = element.selectedIndex;
					}
					refresh(self, event);
					return false;
				}, false);
				/*TODO - add vmousemove support*/

				this._onVmouseMove = onVmouseMove.bind(null, this);
				slider.addEventListener("vmousemove", this._onVmouseMove,
						false);

				slider.addEventListener("vclick", function (event) {
					event.stopPropagation();
					event.preventDefault();
				}, false);
				//prevent scrolling when slider is in use
				slider.addEventListener("touchmove", onTouchMove, false);

				this._sliderMouseUp = sliderMouseUp.bind(null, this);
				slider.addEventListener("vmouseup", this._sliderMouseUp,
						false);

			};

			/**
			 * Enable the slider
			 *
			 * Method removes disabled attribute on slider and changes look
			 * of slider to enabled state.
			 *
			 *		@example
			 *		<select id="slider" name="flip-11" data-role="slider">
			 *			<option value="off"></option>
			 *			<option value="on"></option>
			 *		</select>
			 *		<script>
			 *			var slider = document.getElementById("slider"),
			 *				  sliderWidget = tau.widget.Slider(slider),
			 *			sliderWidget.enable();
			 *		</script>
			 *
			 * ####If jQuery library is loaded, its method can be used:
			 *
			 *		@example
			 *		<select id="slider" name="flip-11" data-role="slider">
			 *			<option value="off"></option>
			 *			<option value="on"></option>
			 *		</select>
			 *		<script>
			 *			$( "#slider" ).slider( "enable" );
			 *		</script>
			 *
			 * @method enable
			 * @chainable
			 * @member ns.widget.mobile.Slider
			 */

			/**
			 * Enable slider
			 * @method _enable
			 * @param {HTMLElement} element
			 * @protected
			 * @member ns.widget.mobile.Slider
			 */
			Slider.prototype._enable = function (element) {
				var btnClasses = Button.classes,
					slider = this._ui.slider;

				element.removeAttribute("disabled");
				slider.classList.remove( btnClasses.uiDisabled );
				slider.setAttribute("aria-disabled", false);
				this.options.disabled = false;
			};

			/**
			 * Disable the slider
			 *
			 * Method sets disabled attribute on slider and changes look
			 * of slider to disabled state.
			 *
			 *		@example
			 *		<select id="slider" name="flip-11" data-role="slider">
			 *			<option value="off"></option>
			 *			<option value="on"></option>
			 *		</select>
			 *		<script>
			 *			var slider = document.getElementById("slider"),
			 *				sliderWidget = tau.widget.Slider(slider),
			 *			sliderWidget.disable();
			 *		</script>
			 *
			 * ####If jQuery library is loaded, its method can be used:
			 *
			 *		@example
			 *		<select id="slider" name="flip-11" data-role="slider">
			 *			<option value="off"></option>
			 *			<option value="on"></option>
			 *		</select>
			 *		<script>
			 *			$( "#slider" ).slider( "disable" );
			 *		</script>
			 *
			 * @method disable
			 * @chainable
			 * @member ns.widget.mobile.Slider
			 */

			/**
			 * Disable slider
			 * @method _disable
			 * @param {HTMLElement} element
			 * @protected
			 * @member ns.widget.mobile.Slider
			 */
			Slider.prototype._disable = function (element) {
				var btnClasses = Button.classes,
					slider = this._ui.slider;

				element.setAttribute("disabled", "disabled");
				slider.classList.add( btnClasses.uiDisabled );
				slider.setAttribute( "aria-disabled", true );
				this.options.disabled = true;
			};

			// @TODO add destroy() method

			ns.widget.mobile.Slider = Slider;
			engine.defineWidget(
				"Slider",
				"select[data-role='range'], select.ui-slider",
				[],
				Slider,
				"mobile"
			);
			}(window.document, ns));

/*global window, define */
/*
* Copyright  2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/*jslint nomen: true, plusplus: true */
/**
 * # Swipe Widget
 * Widget adds swiped covers to element.
 *
 * ## Default selectors
 * All elements which have a class _.ui-swipe_ or an attribute _data-role=swipe_
 * will become a Swipe widget.
 *
 * ### HTML examples
 *
 * #### Create a swipe widget using the data-role attribute with one covered item
 *
 *		@example
 *		<div id="swipe" data-role="swipe">
 *			<div data-role="swipe-item-cover">
 *				Cover - swipe to open
 *			</div>
 *			<div data-role="swipe-item">
 *				<div data-role="button" data-inline="true">First item</div>
 *			</div>
 *		</div>
 *
 * #### Create swipe widget using the class
 *
 *		@example
 *		<div id="swipe" class="ui-swipe">
 *			<div data-role="swipe-item-cover">
 *				Cover - swipe to open
 *			</div>
 *			<div data-role="swipe-item">
 *				<div data-role="button" data-inline="true">First item</div>
 *			</div>
 *		</div>
 *
 * ## Manual constructor
 * For manual creation of swipe widget you can use constructor of widget:
 *
 *		@example
 *		<div id="swipe">
 *			<div data-role="swipe-item-cover">
 *				Cover - swipe to open
 *			</div>
 *			<div data-role="swipe-item">
 *				<div data-role="button" data-inline="true">First item</div>
 *			</div>
 *		</div>
 *
 *		<script>
 *			var swipeElement = document.getElementById("swipe"),
 *				swipe = tau.widget.Swipe(swipeElement);
 *		</script>
 *
 *  If jQuery library is loaded, its method can be used:
 *
 *		@example
 *		<div id="swipe">
 *			<div data-role="swipe-item-cover">
 *				Cover - swipe to open
 *			</div>
 *			<div data-role="swipe-item">
 *				<div data-role="button" data-inline="true">First item</div>
 *			</div>
 *		</div>
 *
 *		<script>
 *			var swipe = $("#swipe").swipe();
 *		</script>
 *
 * ## Methods
 *
 * To call method on widget you can use one of existing API:
 *
 * First API is from tau namespace:
 *
 *		@example
 *		var swipeElement = document.getElementById("swipe"),
 *			swipe = tau.widget.Swipe(swipeElement);
 *
 *		swipe.methodName(methodArgument1, methodArgument2, ...);
 *
 * Second API is jQuery Mobile API and for call _methodName_ you can use:
 *
 *		@example
 *		$(".selector").swipe("methodName", methodArgument1, methodArgument2, ...);
 *
 *
 * ## Opening swipe
 * There are three ways to open swipe widget.
 *
 * ### Opening by swiping
 *
 * To uncover items of widget, you can swipe over an element.
 *
 *		@example
 *		<div id="swipe" data-role="swipe">
 *			<div data-role="swipe-item-cover">
 *				Cover - swipe to open
 *			</div>
 *			<div data-role="swipe-item">
 *				<div data-role="button" data-inline="true">First item</div>
 *			</div>
 *		</div>
 *
 * ### Opening manually by using method "open"
 *
 * To uncoer items of widget,the method "open" can be used.
 *
 *		@example
 *		<div id="swipe" data-role="swipe">
 *			<div data-role="swipe-item-cover">
 *				Cover - swipe to open
 *			</div>
 *			<div data-role="swipe-item">
 *				<div data-role="button" data-inline="true">First item</div>
 *			</div>
 *		</div>
 *
 *		<script>
 *			var swipeWidget = tau.widget.Swipe(document.getElementById("swipe"));
 *			swipeWidget.open();
 *		<script>
 *
 * If jQuery is loaded:
 *
 *		@example
 *		<div id="swipe" data-role="swipe">
 *			<div data-role="swipe-item-cover">
 *				Cover - swipe to open
 *			</div>
 *			<div data-role="swipe-item">
 *				<div data-role="button" data-inline="true">First item</div>
 *			</div>
 *		</div>
 *
 *		<script>
 *			$("#swipe").swipe("open");
 *		<script>
 *
 *
 * @class ns.widget.mobile.Swipe
 * @extends ns.widget.BaseWidget
 */
(function (document, ns) {
	
				var Swipe = function () {
					var self = this;

					/**
					 * Object with default options
					 * @property {Object} options
					 * @property {?string} [options.theme=null] Sets the color
					 * scheme for the swipe contents.
					 * @member ns.widget.mobile.Swipe
					*/
					self.options = {
						theme: null
					};
					self._isOpen = false;
					self.moveAnimation = null;
					self.opacityAnimation = null;
				},
				/**
				 * Alias for {@link ns.widget.BaseWidget}
				 * @property {Object} Widget
				 * @member ns.widget.mobile.Swipe
				 * @private
				 * @static
				 */
				BaseWidget = ns.widget.mobile.BaseWidgetMobile,
				/**
				 * Alias for class ns.engine
				 * @property {ns.engine} engine
				 * @member ns.widget.mobile.Swipe
				 * @private
				 * @static
				 */
				engine = ns.engine,
				/**
				 * Alias for class ns.event
				 * @property {Object} events
				 * @member ns.widget.mobile.Swipe
				 * @private
				 */
				events = ns.event,
				Animation = ns.util.anim.Animation,
				slice = [].slice,
				prototype,
				classPrefix = "ui-swipe",
				classes = {
					uiBodyPrefix: "ui-body-",
					uiSwipe: classPrefix,
					uiSwipeItem: classPrefix + "-item",
					uiSwipeItemCover: classPrefix + "-item-cover",
					uiSwipeItemCoverInner: classPrefix + "-item-cover-inner"
				},
				selectorRoleSwipe = "[data-role='swipe']",
				selectorRoleSwipeItemCover = "[data-role='swipe-item-cover']" +
					', .' + classes.uiSwipeItemCover,
				selectorRoleSwipeItem = "[data-role='swipe-item']" +
					', .' + classes.uiSwipeItem,
				classUiBtn = ".ui-btn",
				swipeLeftEvent = "swipeleft",
				swipeRightEvent = "swiperight";

			Swipe.prototype = new BaseWidget();

			prototype = Swipe.prototype;

			/**
			 * Dictionary for swipe related css class names
			 * @property {Object} classes
			 * @member ns.widget.mobile.Swipe
			 * @static
			 * @readonly
			 */
			prototype.classes = classes;

			/**
			 * This method cleans up DOM modification made during building process.
			 * It is called during refreshing and destroying.
			 * @method cleanupDom
			 * @param {ns.widget.mobile.Swipe} self Widget
			 * @param {HTMLElement} element Element of widget
			 * @private
			 * @static
			 * @member ns.widget.mobile.Swipe
			 */
			function cleanupDom(self, element) {
				var covers,
					item,
					itemHasThemeClass,
					defaultCoverTheme = classes.uiBodyPrefix + self.options.theme,
					coverTheme = defaultCoverTheme,
					wrapper,
					selfUi = self._ui;

				if (selfUi) {
					covers = selfUi.covers;
					item = selfUi.item;

					element.classList.remove(classes.uiSwipe);
					item.classList.remove(classes.uiSwipeItem);

					itemHasThemeClass = element.className.match(/ui\-body\-[a-z]|ui\-bar\-[a-z]/);
					if (itemHasThemeClass) {
						coverTheme = itemHasThemeClass[0];
					}

					covers.forEach(function (cover) {
						var coverClassList = cover.classList;
						coverClassList.remove(classes.uiSwipeItemCover);
						coverClassList.remove(coverTheme);

						wrapper = cover.querySelector("." + classes.uiSwipeItemCoverInner);
						while (wrapper.firstChild) {
							cover.appendChild(wrapper.firstChild);
						}
						wrapper.parentNode.removeChild(wrapper);
					});
				}
			}

			/**
			 * This is callback for the animation which is triggered
			 * when cover is moved or opacity is changed.
			 * @method handleAnimationEnd
			 * @param {ns.util.anim.Animation} animation Animation
			 * @param {HTMLElement} element Element of widget
			 * @private
			 * @static
			 * @member ns.widget.mobile.Swipe
			 */
			function handleAnimationEnd(animation, element) {
				var to = animation.options.to;

				if (to.opacity !== undefined) {
					//@TODO implement "preserve" option in ns.util.anim.Animation
					element.style.opacity = animation.options.to.opacity;
					animation.destroy();
				}
				if (to.left !== undefined) {
					//@TODO implement "preserve" option in ns.util.anim.Animation
					element.style.left = animation.options.to.left;
					animation.destroy();
					events.trigger(element, "swipeanimationend");
				}
			}

			/**
			 * This is callback for the animation which is triggered
			 * when cover is moved or opacity is changed.
			 * @method animateCover
			 * @param {ns.widget.mobile.Swipe} self Widget
			 * @param {HTMLElement} cover Cover element
			 * @param {number} leftPercentage Percentage of opening
			 * @param {HTMLElement} item Item of widget
			 * @private
			 * @static
			 * @member ns.widget.mobile.Swipe
			 */
			function animateCover(self, cover, leftPercentage, item) {
				var coverStyle = cover.style,
					itemStyle = item.style,
					moveAnimation,
					opacityAnimation,
					swipeWidget;

				slice.call(self.element.parentNode.querySelectorAll(selectorRoleSwipe)).forEach(function (swipe) {
					swipeWidget = engine.instanceWidget(swipe, "Swipe");
					if (self !== swipeWidget && swipeWidget.opened()) {
						swipeWidget.close();
					}
				});

				self._isOpen = leftPercentage === 110;

				//To pass tests the animation can be triggered only once.
				//Then I need to have a reference to previous animations,
				//in order to destroy it when new animations appear
				if(self.moveAnimation){
					self.moveAnimation.destroy();
					self.opacityAnimation.destroy();
				}

				//animations change the left value to uncover/ cover item element
				moveAnimation = new Animation({
					element: cover,
					duration: "400ms",
					from: {
						"left": coverStyle.left
					},
					to: {
						"left": leftPercentage + "%"
					},
					onEnd: handleAnimationEnd
				});
				self.moveAnimation = moveAnimation;
				moveAnimation.play();

				//animations change item opacity in order to show items under cover
				opacityAnimation = new Animation({
					element: item,
					duration: "400ms",
					from: {
						"opacity": itemStyle.opacity
					},
					to: {
						"opacity": (self.opened()) ? "1" : "0"
					},
					onEnd: handleAnimationEnd
				});
				self.opacityAnimation = opacityAnimation;
				opacityAnimation.play();
			}

			/**
			 * This method sets up widget's element.
			 * It is called during building and refreshing process.
			 * @method refresh
			 * @param {ns.widget.mobile.Swipe} self Widget
			 * @param {HTMLElement} element Element of widget
			 * @private
			 * @static
			 * @member ns.widget.mobile.Swipe
			 */
			function refresh(self, element) {
				cleanupDom(self, element);

				var defaultCoverTheme = classes.uiBodyPrefix + self.options.theme,
					covers = slice.call(element.querySelectorAll(selectorRoleSwipeItemCover)),
					coverTheme = defaultCoverTheme,
					item = element.querySelector(selectorRoleSwipeItem),
					itemHasThemeClass = element.className.match(/ui\-body\-[a-z]|ui\-bar\-[a-z]/),
					ui = self._ui || {};

				/*
				* @todo good support multicovers
				*/
				ui.covers = covers;
				ui.item = item;
				self._ui = ui;

				element.classList.add(classes.uiSwipe);
				item.classList.add(classes.uiSwipeItem);

				covers.forEach(function (cover) {
					var span,
						coverClassList = cover.classList;

					if (itemHasThemeClass) {
						coverTheme = itemHasThemeClass[0];
					}

					coverClassList.add(classes.uiSwipeItemCover);
					coverClassList.add(coverTheme);

					if (!cover.querySelector("." + classes.uiSwipeItemCoverInner)) {
						span = document.createElement("span");
						span.classList.add(classes.uiSwipeItemCoverInner);
						while (cover.firstChild) {
							span.appendChild(cover.firstChild);
						}
						cover.appendChild(span);
					}
				});
			}

			/**
			 * This method builds structure of swipe widget.
			 * @method _build
			 * @param {HTMLElement} element Element of widget
			 * @return {HTMLElement}
			 * @protected
			 * @member ns.widget.mobile.Swipe
			 */
			prototype._build = function (element) {
				var options = this.options,
					protoOptions = Swipe.prototype.options;
				options.theme = options.theme ||
						ns.theme.getInheritedTheme(
							element,
							(protoOptions && protoOptions.theme) || "s"
						);
				refresh(this, element);
				return element;
			};

			/**
			 * This method inits structure of swipe widget.
			 * @method _init
			 * @param {HTMLElement} element Element of widget
			 * @protected
			 * @member ns.widget.mobile.Swipe
			 */
			prototype._init = function (element) {
				/* @TODO what is swipeSelectors? */
				this._ui = this._ui || {
					covers: slice.call(element.querySelectorAll(selectorRoleSwipeItemCover)),
					item: element.querySelector(swipeSelectors.swipeItem)
				};
			};

			/**
			 * This method binds events to widget.
			 * @method addEvents
			 * @param {ns.widget.mobile.Swipe} self Widget
			 * @private
			 * @static
			 * @member ns.widget.mobile.Swipe
			 */
			function addEvents(self) {
				var ui = self._ui,
					covers = ui.covers,
					item = ui.item,
					buttonSelector = engine.getWidgetDefinition("Button").selector;

					/*
					* @todo good support multicovers
					*/

				covers.forEach(function (cover) {
					cover.swipeAnimateLeft = animateCover.bind(null, self, cover, 0, item);
					cover.swipeAnimateRight = animateCover.bind(null, self, cover, 110, item);

					item.addEventListener(swipeLeftEvent, cover.swipeAnimateLeft, false);
					cover.addEventListener(swipeRightEvent, cover.swipeAnimateRight, false);

					[].forEach.call(item.querySelectorAll(buttonSelector), function (button) {
						button.addEventListener("vclick", cover.swipeAnimateLeft, false);
					});
				});
			}

			/**
			 * This method unbinds events to widget.
			 * @method removeEvents
			 * @param {ns.widget.mobile.Swipe} self Widget
			 * @private
			 * @static
			 * @member ns.widget.mobile.Swipe
			 */
			function removeEvents(self) {
				var selfUI = self._ui,
					covers = selfUI.covers,
					item = selfUI.item;

					/*
					* @todo good support multicovers
					*/

				covers.forEach(function (cover) {
					item.removeEventListener(swipeLeftEvent, cover.swipeAnimateLeft, false);
					cover.removeEventListener(swipeRightEvent, cover.swipeAnimateRight, false);

					slice.call(item.querySelectorAll(classUiBtn)).forEach(function (button) {
						button.removeEventListener("vclick", cover.swipeAnimateLeft, false);
					});
				});
			}

			/**
			 * This method binds events to widget.
			 * @method _bindEvents
			 * @protected
			 * @member ns.widget.mobile.Swipe
			 */
			prototype._bindEvents = function () {
				addEvents(this);
			};

			/**
			 * This method refreshes swipe widget.
			 *
			 * It re-builds the whole widget.
			 *
			 *		@example
			 *		<div id="swipe" data-role="swipe">
			 *			<div data-role="swipe-item-cover">
			 *				Swipe
			 *			</div>
			 *			<div data-role="swipe-item">
			 *				<div data-role="button" data-inline="true">First item</div>
			 *				<div data-role="button" data-inline="true">Second item</div>
			 *			</div>
			 *		</div>
			 *
			 *		<script>
			 *			var swipeWidget = tau.widget.Swipe(document.getElementById("swipe"));
			 *			swipeWidget.refresh();
			 *		<script>
			 *
			 * If jQuery is loaded:
			 *
			 *		@example
			 *		<div  id="swipe" data-role="swipe">
			 *			<div data-role="swipe-item-cover">
			 *				Swipe
			 *			</div>
			 *			<div data-role="swipe-item">
			 *				<div data-role="button" data-inline="true">First item</div>
			 *				<div data-role="button" data-inline="true">Second item</div>
			 *			</div>
			 *		</div>
			 *
			 *		<script>
			 *			$("#swipe").swipe("refresh");
			 *		</script>
			 *
			 * @method refresh
			 * @member ns.widget.mobile.Swipe
			 */
			/**
			 * This method refreshes widget.
			 * @method _refresh
			 * @protected
			 * @member ns.widget.mobile.Swipe
			 */
			prototype._refresh = function () {
				refresh(this, this.element);
			};

			/**
			 * Removes the swipe functionality completely.
			 *
			 * This will return the element back to its pre-init state.
			 *
			 *		@example
			 *		<div id="swipe" data-role="swipe">
			 *			<div data-role="swipe-item-cover">
			 *				Swipe
			 *			</div>
			 *			<div data-role="swipe-item">
			 *				<div data-role="button" data-inline="true">First item</div>
			 *				<div data-role="button" data-inline="true">Second item</div>
			 *			</div>
			 *		</div>
			 *
			 *		<script>
			 *			var swipeWidget = tau.widget.Swipe(document.getElementById("swipe"));
			 *			swipeWidget.destroy();
			 *		<script>
			 *
			 * If jQuery is loaded:
			 *
			 *		@example
			 *		<div  id="swipe" data-role="swipe">
			 *			<div data-role="swipe-item-cover">
			 *				Swipe
			 *			</div>
			 *			<div data-role="swipe-item">
			 *				<div data-role="button" data-inline="true">First item</div>
			 *				<div data-role="button" data-inline="true">Second item</div>
			 *			</div>
			 *		</div>
			 *
			 *		<script>
			 *			$("#swipe").swipe("destroy");
			 *		</script>
			 *
			 * @method destroy
			 * @member ns.widget.mobile.Swipe
			 */
			/**
			 * This method destroys widget.
			 * @method _destroy
			 * @protected
			 * @member ns.widget.mobile.Swipe
			 */
			prototype._destroy = function () {
				var self = this;

				removeEvents(self);
				cleanupDom(self, self.element);
			};

			/**
			 * This method runs opening animations.
			 *
			 *		@example
			 *		<div id="swipe" data-role="swipe">
			 *			<div data-role="swipe-item-cover">
			 *				Swipe
			 *			</div>
			 *			<div data-role="swipe-item">
			 *				<div data-role="button" data-inline="true">First item</div>
			 *				<div data-role="button" data-inline="true">Second item</div>
			 *			</div>
			 *		</div>
			 *
			 *		<script>
			 *			var swipeWidget = tau.widget.Swipe(document.getElementById("swipe"));
			 *			swipeWidget.open();
			 *		<script>
			 *
			 * If jQuery is loaded:
			 *
			 *		@example
			 *		<div  id="swipe" data-role="swipe">
			 *			<div data-role="swipe-item-cover">
			 *				Swipe
			 *			</div>
			 *			<div data-role="swipe-item">
			 *				<div data-role="button" data-inline="true">First item</div>
			 *				<div data-role="button" data-inline="true">Second item</div>
			 *			</div>
			 *		</div>
			 *
			 *		<script>
			 *			$("#swipe").swipe("open");
			 *		</script>
			 *
			 * @method open
			 * @member ns.widget.mobile.Swipe
			 */
			prototype.open = function () {
				var self = this,
					ui =  self._ui;

				ui.covers.forEach(function (cover) {
					animateCover(self, cover, 110, ui.item);
				});
			};

			/**
			 * This method checks if swipe element is opened.
			 *
			 *		@example
			 *		<div id="swipe" data-role="swipe">
			 *			<div data-role="swipe-item-cover">
			 *				Swipe
			 *			</div>
			 *			<div data-role="swipe-item">
			 *				<div data-role="button" data-inline="true">First item</div>
			 *				<div data-role="button" data-inline="true">Second item</div>
			 *			</div>
			 *		</div>
			 *
			 *		<script>
			 *			var swipeWidget = tau.widget.Swipe(document.getElementById("swipe"));
			 *				isOpened = swipeWidget.opened();
			 *		<script>
			 *
			 * If jQuery is loaded:
			 *
			 *		@example
			 *		<div  id="swipe" data-role="swipe">
			 *			<div data-role="swipe-item-cover">
			 *				Swipe
			 *			</div>
			 *			<div data-role="swipe-item">
			 *				<div data-role="button" data-inline="true">First item</div>
			 *				<div data-role="button" data-inline="true">Second item</div>
			 *			</div>
			 *		</div>
			 *
			 *		<script>
			 *			var isOpened = $("#swipe").swipe("opened");
			 *		</script>
			 *
			 * @method opened
			 * @return {boolean} True, if swipe element is opened.
			 * Otherwise, it returns false.
			 * @member ns.widget.mobile.Swipe
			 */
			prototype.opened = function () {
				return this._isOpen;
			};

			/**
			 * This method runs closing animations.
			 *
			 *		@example
			 *		<div id="swipe" data-role="swipe">
			 *			<div data-role="swipe-item-cover">
			 *				Swipe
			 *			</div>
			 *			<div data-role="swipe-item">
			 *				<div data-role="button" data-inline="true">First item</div>
			 *				<div data-role="button" data-inline="true">Second item</div>
			 *			</div>
			 *		</div>
			 *
			 *		<script>
			 *			var swipeWidget = tau.widget.Swipe(document.getElementById("swipe"));
			 *			swipeWidget.close();
			 *		<script>
			 *
			 * If jQuery is loaded:
			 *
			 *		@example
			 *		<div  id="swipe" data-role="swipe">
			 *			<div data-role="swipe-item-cover">
			 *				Swipe
			 *			</div>
			 *			<div data-role="swipe-item">
			 *				<div data-role="button" data-inline="true">First item</div>
			 *				<div data-role="button" data-inline="true">Second item</div>
			 *			</div>
			 *		</div>
			 *
			 *		<script>
			 *			$("#swipe").swipe("close");
			 *		</script>
			 *
			 * @method close
			 * @member ns.widget.mobile.Swipe
			 */
			prototype.close = function () {
				var self = this,
					ui = self._ui;

				ui.covers.forEach(function (cover) {
					animateCover(self, cover, 0, ui.item);
				});
			};


			/**
			 * This method changes state of swipe on enabled and removes CSS classes connected with state.
			 *
			 *		@example
			 *		<div id="swipe" data-role="swipe">
			 *			<div data-role="swipe-item-cover">
			 *				Swipe
			 *			</div>
			 *			<div data-role="swipe-item">
			 *				<div data-role="button" data-inline="true">First item</div>
			 *				<div data-role="button" data-inline="true">Second item</div>
			 *			</div>
			 *		</div>
			 *
			 *		<script>
			 *			var swipeWidget = tau.widget.Swipe(document.getElementById("swipe"));
			 *			swipeWidget.enable();
			 *		</script>
			 *
			 * If jQuery is loaded:
			 *
			 *		@example
			 *		<div id="swipe" data-role="swipe">
			 *			<div data-role="swipe-item-cover">
			 *				Swipe
			 *			</div>
			 *			<div data-role="swipe-item">
			 *				<div data-role="button" data-inline="true">First item</div>
			 *				<div data-role="button" data-inline="true">Second item</div>
			 *			</div>
			 *		</div>
			 *
			 *		<script>
			 *			$("#swipe").swipe("enable");
			 *		</script>
			 *
			 * @method enable
			 * @chainable
			 * @member ns.widget.mobile.Swipe
			 */

			/**
			 * This method changes state of swipe on disabled and adds CSS classes connected with state.
			 *
			 *		@example
			 *		<div id="swipe" data-role="swipe">
			 *			<div data-role="swipe-item-cover">
			 *				Swipe
			 *			</div>
			 *			<div data-role="swipe-item">
			 *				<div data-role="button" data-inline="true">First item</div>
			 *				<div data-role="button" data-inline="true">Second item</div>
			 *			</div>
			 *		</div>
			 *
			 *		<script>
			 *			var swipeWidget = tau.widget.Swipe(document.getElementById("swipe"));
			 *			swipeWidget.disable();
			 *		</script>
			 *
			 * If jQuery is loaded:
			 *
			 *		@example
			 *		<div id="swipe" data-role="swipe">
			 *			<div data-role="swipe-item-cover">
			 *				Swipe
			 *			</div>
			 *			<div data-role="swipe-item">
			 *				<div data-role="button" data-inline="true">First item</div>
			 *				<div data-role="button" data-inline="true">Second item</div>
			 *			</div>
			 *		</div>
			 *
			 *		<script>
			 *			$("#swipe").swipe("disable");
			 *		</script>
			 *
			 * @method disable
			 * @chainable
			 * @member ns.widget.mobile.Swipe
			 */

			/**
			 * The function "value" is not supported in this widget.
			 *
			 * @method value
			 * @chainable
			 * @member ns.widget.mobile.Swipe
			 */

			/**
			 * Get/Set options of the widget.
			 *
			 * This method can work in many context.
			 *
			 * If first argument is type of object them, method set values for options given in object. Keys of object are names of options and values from object are values to set.
			 *
			 * If you give only one string argument then method return value for given option.
			 *
			 * If you give two arguments and first argument will be a string then second argument will be intemperate as value to set.
			 *
			 *		@example
			 *		<div id="swipe" data-role="swipe">
			 *			<div data-role="swipe-item-cover">
			 *				Swipe
			 *			</div>
			 *			<div data-role="swipe-item">
			 *				<div data-role="button" data-inline="true">First item</div>
			 *				<div data-role="button" data-inline="true">Second item</div>
			 *			</div>
			 *		</div>
			 *
			 *		<script>
			 *			var swipeWidget = tau.widget.Swipe(document.getElementById("swipe")),
			 *				optionValue;
			 *
			 *			optionValue = swipeWidget.option("theme"); // read value of option theme
			 *			swipeWidget.option("theme", "a") // set value
			 *		</script>
			 *
			 * If jQuery is loaded:
			 *
			 *		@example
			 *		<div id="swipe" data-role="swipe">
			 *			<div data-role="swipe-item-cover">
			 *				Swipe
			 *			</div>
			 *			<div data-role="swipe-item">
			 *				<div data-role="button" data-inline="true">First item</div>
			 *				<div data-role="button" data-inline="true">Second item</div>
			 *			</div>
			 *		</div>
			 *
			 *		<script>
			 *			optionValue = $("#swipe").swipe("option", "theme");
			 *			$("#swipe").swipe("option", "theme", "a");
			 *		</script>
			 *
			 * @method option
			 * @param {string|Object} [name] name of option
			 * @param {*} value value to set
			 * @member ns.widget.mobile.Swipe
			 * @return {*} return value of option or undefined if method is called in setter context
			 */

			/**
			 * Trigger an event on widget's element.
			 *
			 *		@example
			 *		<div id="swipe" data-role="swipe">
			 *			<div data-role="swipe-item-cover">
			 *				Swipe
			 *			</div>
			 *			<div data-role="swipe-item">
			 *				<div data-role="button" data-inline="true">First item</div>
			 *				<div data-role="button" data-inline="true">Second item</div>
			 *			</div>
			 *		</div>
			 *
			 *		<script>
			 *			var swipeWidget = tau.widget.Swipe(document.getElementById("swipe"));
			 *			swipeWidget.trigger("eventName");
			 *		</script>
			 *
			 * If jQuery is loaded:
			 *
			 *		@example
			 *		<div id="swipe" data-role="swipe">
			 *			<div data-role="swipe-item-cover">
			 *				Swipe
			 *			</div>
			 *			<div data-role="swipe-item">
			 *				<div data-role="button" data-inline="true">First item</div>
			 *				<div data-role="button" data-inline="true">Second item</div>
			 *			</div>
			 *		</div>
			 *
			 *		<script>
			 *			$("#swipe").swipe("trigger", "eventName");
			 *		</script>
			 *
			 * @method trigger
			 * @param {string} eventName the name of event to trigger
			 * @param {?*} [data] additional object to be carried with the event
			 * @param {boolean} [bubbles=true] indicating whether the event bubbles up through the DOM or not
			 * @param {boolean} [cancelable=true] indicating whether the event is cancelable
			 * @return {boolean} false, if any callback invoked preventDefault on event object
			 * @member ns.widget.mobile.Swipe
			*/

			/**
			 * Add event listener to widget's element.
			 *
			 *		@example
			 *		<div id="swipe" data-role="swipe">
			 *			<div data-role="swipe-item-cover">
			 *				Swipe
			 *			</div>
			 *			<div data-role="swipe-item">
			 *				<div data-role="button" data-inline="true">First item</div>
			 *				<div data-role="button" data-inline="true">Second item</div>
			 *			</div>
			 *		</div>
			 *
			 *		<script>
			 *			var swipeWidget = tau.widget.Swipe(document.getElementById("swipe")),
			 *				callback = function () {
			 *					console.log("event fires");
			 *				});
			 *
			 *			swipeWidget.on("eventName", callback);
			 *		</script>
			 *
			 * If jQuery is loaded:
			 *
			 *		@example
			 *		<div id="swipe" data-role="swipe">
			 *			<div data-role="swipe-item-cover">
			 *				Swipe
			 *			</div>
			 *			<div data-role="swipe-item">
			 *				<div data-role="button" data-inline="true">First item</div>
			 *				<div data-role="button" data-inline="true">Second item</div>
			 *			</div>
			 *		</div>
			 *
			 *		<script>
			 *			var callback = function () {
			 *					console.log("event fires");
			 *				});
			 *
			 *			$("#swipe").swipe("on", "eventName", callback);
			 *		</script>
			 *
			 * @method on
			 * @param {string} eventName the name of event
			 * @param {Function} listener function call after event will be trigger
			 * @param {boolean} [useCapture=false] useCapture param to addEventListener
			 * @member ns.widget.mobile.Swipe
			 */

			/**
			 * Remove event listener to widget's element.
			 *
			 *		@example
			 *		<div id="swipe" data-role="swipe">
			 *			<div data-role="swipe-item-cover">
			 *				Swipe
			 *			</div>
			 *			<div data-role="swipe-item">
			 *				<div data-role="button" data-inline="true">First item</div>
			 *				<div data-role="button" data-inline="true">Second item</div>
			 *			</div>
			 *		</div>
			 *
			 *		<script>
			 *			var swipeWidget = tau.widget.Swipe(document.getElementById("swipe")),
			 *				callback = function () {
			 *					console.log("event fires");
			 *				});
			 *
			 *			// add callback on event "eventName"
			 *			swipeWidget.on("eventName", callback);
			 *			// ...
			 *			// remove callback on event "eventName"
			 *			swipeWidget.off("eventName", callback);
			 *		</script>
			 *
			 * If jQuery is loaded:
			 *
			 *		@example
			 *		<div id="swipe" data-role="swipe">
			 *			<div data-role="swipe-item-cover">
			 *				Swipe
			 *			</div>
			 *			<div data-role="swipe-item">
			 *				<div data-role="button" data-inline="true">First item</div>
			 *				<div data-role="button" data-inline="true">Second item</div>
			 *			</div>
			 *		</div>
			 *
			 *		<script>
			 *			// add callback on event "eventName"
			 *			$("#swipe").swipe("on", "eventName", callback);
			 *			// ...
			 *			// remove callback on event "eventName"
			 *			$("#swipe").swipe("off", "eventName", callback);
			 *		</script>
			 *
			 * @method off
			 * @param {string} eventName the name of event
			 * @param {Function} listener function call after event will be trigger
			 * @param {boolean} [useCapture=false] useCapture param to addEventListener
			 * @member ns.widget.mobile.Swipe
			 */

			ns.widget.mobile.Swipe = Swipe;
			engine.defineWidget(
				"Swipe",
				selectorRoleSwipe + ", .ui-swipe",
				["open", "opened", "close"],
				Swipe,
				"tizen"
			);
			}(window.document, ns));

/*global window, define */
/*
* Copyright  2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/**
 * #SelectMenu Widget
 * SelectMenu widget provide creating SelectMenu widget in the form of dropdown list and managing its operation.
 *
 * ##Default selector
 * In default all select elements with _data-role=select_ or with class .ui-select-menu
 * are changed to Tizen WebUI SelectMenu. Additionally elements with
 * _data-native-menu=false_ will use custom popups for option selection
 *
 * ###  HTML Examples
 *
 * ####  Create SelectMenu
 * Default value of data-native-menu attribute is true and it makes native SelectMenu.
 * This widget also offers the possibility of having custom SelectMenu.
 *
 * 		@example
 *		<select data-native-menu="false">
 *			<option value="1">Item1</option>
 *			<option value="2">Item2</option>
 *			<option value="3">Item3</option>
 *			<option value="4">Item4</option>
 *		</select>
 *
 * ## Manual constructor
 * For manual creation of SelectMenu widget you can use constructor of widget.
 *
 * 		@example
 *		<select id="selectmenu" data-native-menu="false">
 *			<option value="1">Item1</option>
 *			<option value="2">Item2</option>
 *			<option value="3">Item3</option>
 *			<option value="4">Item4</option>
 *		</select>
 *		<script>
 *			var element = document.getElementById("selectmenu"),
 *				widget = tau.widget.SelectMenu(element);
 *		</script>
 *
 * ##Label type
 * You can declare to the type of SelectMenu manually.
 * If you set data-label attribute to true(Default is false.), SelectMenu has label type.
 * The size of label type is inherited its parent element.
 *
 * 		@example
 * 		<div style="width:300px; height:150px;">
 *			<select id="selectmenu" data-native-menu="false" data-label="true">
 *				<option value="1">Item1</option>
 *				<option value="2">Item2</option>
 *				<option value="3">Item3</option>
 *				<option value="4">Item4</option>
 *			</select>
 *		</div>
 *
 * ##Inline type
 * When data-inline attribute is set to true, width of the SelectMenu is determined by its text. (Default is false.)
 *
 *			@example
 * 			<select id="selectmenu" data-native-menu="false" data-inline="true">
 *				<option value="1">Item1</option>
 *				<option value="2">Item2</option>
 *				<option value="3">Item3</option>
 *				<option value="4">Item4</option>
 *			</select>
 *
 * ##Placeholder options
 * If you use <option> with data-placeholder="true" attribute, you can make a default placeholder.
 * Default value of data-hide-placeholder-menu-items attribute is true and data-placeholder option is hidden.
 * If you don't want that, you can use data-hide-placeholder-menu-items="false" attribute.
 *
 *		@example
 *		<select id="selectmenu" data-native-menu="false" data-hide-placeholder-menu-items="false">
 *			<option value="choose-one" data-placeholder="true">Choose an option</option>
 *			<option value="1">Item1</option>
 *			<option value="2">Item2</option>
 *			<option value="3">Item3</option>
 *			<option value="4">Item4</option>
 *		</select>
 *
 * ##Methods
 * To call method on widget you can use one of existing API:
 *
 * First API is from tau namespace: RECOMMEND
 *
 *		@example
 *		var element = document.getElementById("selectmenu"),
 *			widget = tau.widget.SelectMenu(element);
 *		widget.methodName(methodArgument1, methodArgument2, ...);
 *
 * Second API is jQuery Mobile API and for call _methodName_ you can use: Support for backward compatibility
 *
 *		@example
 *		$(".selector").selectmenu("methodName", methodArgument1, methodArgument2, ...);
 *
 * - "open" - SelectMenu open
 *
 * 		@example
 * 		var elSelectMenu = document.getElementById("selectmenu"),
 * 			widget = tau.widget.SelectMenu(elSelectMenu);
 * 		widget.open();
 *
 * - "close" - SelectMenu close
 *
 * 		@example
 * 		var elSelectMenu = document.getElementById("selectmenu"),
 * 			widget = tau.widget.SelectMenu(elSelectMenu);
 * 		widget.close();
 *
 * - "refresh" - This method refreshs the SelectMenu widget.
 *
 * 		@example
 * 		var elSelectMenu = document.getElementById("selectmenu"),
 * 			widget = tau.widget.SelectMenu(elSelectMenu);
 * 		widget.refresh();
 *
 * @class ns.widget.mobile.SelectMenu
 * @extends ns.widget.mobile.BaseWidgetMobile
 * @author Hagun Kim <hagun.kim@samsung.com>
 */
(function (document, ns) {
	
				var BaseWidget = ns.widget.mobile.BaseWidgetMobile,
				engine = ns.engine,
				domUtils = ns.util.DOM,
				eventUtils = ns.event,
				selectors = ns.util.selectors,
				slice = [].slice,
				indexOf = [].indexOf,
				SelectMenu = function () {
					var self = this;
					/**
					* @property {boolean} _isOpen Open/Close status of SelectMenu
					* @member ns.widget.mobile.SelectMenu
					*/
					self._isOpen = false;
					/**
					* @property {number} _selectedIndex Index of selected option in SelectMenu
					* @member ns.widget.mobile.SelectMenu
					*/
					self._selectedIndex = null;
					/**
					* @property {Object} _ui Object with html elements connected with SelectMenu
					* @member ns.widget.mobile.SelectMenu
					*/
					self._ui = {
						elSelectWrapper: null,
						elPlaceHolder: null,
						elSelect: null,
						screenFilter: null,
						elOptionContainer: null,
						elOptions: null,
						elPage: null,
						elContent: null,
						elDefaultOption: null
					};
					/**
					* @property {Object} options Object with default options
					* @property {boolean} [options.nativeMenu=true] Sets the SelectMenu widget as native/custom type.
					* @property {boolean} [options.inline=false] Sets the SelectMenu widget as inline/normal type.
					* @property {boolean} [options.label=false] Sets the SelectMenu widget as label/normal type.
					* @property {boolean} [options.hidePlaceholderMenuItems=true] Hide/Reveal the placeholder option in dropdown list of the SelectMenu.
					* @member ns.widget.mobile.SelectMenu
					*/
					self.options = {
						nativeMenu: true,
						inline: false,
						label: false,
						hidePlaceholderMenuItems: true
					};
				},
				/**
				 * Dictionary for SelectMenu related css class names
				 * @property {Object} classes
				 * @member ns.widget.mobile.SelectMenu
				 * @static
				 */
				classes = {
					selectWrapper : "ui-selectmenu",
					optionGroup : "ui-selectmenu-optiongroup",
					placeHolder : "ui-selectmenu-placeholder",
					optionList : "ui-selectmenu-options",
					selected : "ui-selectmenu-selected",
					active : "ui-selectmenu-active",
					filter : "ui-selectmenu-screen-filter",
					filterHidden : "ui-selectmenu-filter-hidden",
					label : "ui-selectmenu-label",
					disabled : "ui-selectmenu-disabled",
					widgetDisabled : "ui-disabled",
					inline : "ui-selectmenu-inline",
					native : "ui-select-native",
					top : "ui-selectmenu-option-top",
					bottom : "ui-selectmenu-option-bottom"
				},
				prototype = new BaseWidget();
			SelectMenu.prototype = prototype;
			SelectMenu.classes = classes;

			/**
			 * vclick to toggle menu event handler
			 * @method toggleMenu
			 * @private
			 * @static
			 * @param {ns.widget.mobile.SelectMenu} self
			 * @param {Event} event
			 * @member ns.widget.mobile.SelectMenu
			*/
			function toggleMenu(self, event) {
				self._toggleSelect();
				eventUtils.stopPropagation(event);
				eventUtils.preventDefault(event);
			}

			/**
			 * vclick to change option event handler
			 * @method changeOption
			 * @private
			 * @static
			 * @param {ns.widget.mobile.SelectMenu} self
			 * @param {Event} event
			 * @member ns.widget.mobile.SelectMenu
			*/
			function changeOption(self, event) {
				var target = event.target,
					tag = target.tagName,
					classList = target.classList;
				if (tag === "LI" && !classList.contains(classes.optionGroup) && !classList.contains(classes.disabled)) {
					self._selectedIndex = indexOf.call(self._ui.elOptions, target);
					self._changeOption();
					self._toggleSelect();
				}
				event.stopPropagation();
				event.preventDefault();
			}

			/**
			 * Change option in native selectmenu
			 * @method nativeChangeOption
			 * @private
			 * @static
			 * @param {ns.widget.mobile.SelectMenu} self
			 * @member ns.widget.mobile.SelectMenu
			*/
			function nativeChangeOption(self) {
				var ui = self._ui,
					selectedOption = ui.elSelect[ui.elSelect.selectedIndex];
				ui.elPlaceHolder.textContent = selectedOption.textContent;
			}

			/**
			 * Function fires on window resizing
			 * @method onResize
			 * @private
			 * @static
			 * @param {ns.widget.mobile.SelectMenu} self
			 * @param {Event} event
			 * @member ns.widget.mobile.SelectMenu
			*/
			function onResize(self, event) {
				self._isOpen = !self._isOpen;
				self._toggleSelect();
				event.stopPropagation();
				event.preventDefault();
			}

			/**
			 * Toggle enable/disable selectmenu
			 * @method setDisabledStatus
			 * @private
			 * @static
			 * @param {HTMLElement} element
			 * @param {Boolean} isDisabled
			 * @member ns.widget.mobile.SelectMenu
			*/
			function setDisabledStatus(element, isDisabled) {
				var classList = element.classList;
				if (isDisabled) {
					classList.add(classes.disabled);
					classList.add(classes.widgetDisabled);
				} else {
					classList.remove(classes.disabled);
					classList.remove(classes.widgetDisabled);
				}
			}

			/**
			 * Convert option tag to li element
			 * @method convertOptionToHTML
			 * @private
			 * @static
			 * @param {HTMLElement} option
			 * @param {Boolean} isDisabled
			 * @return {string}
			 * @member ns.widget.mobile.SelectMenu
			*/
			function convertOptionToHTML(option, isDisabled) {
				return "<li data-value='" + option.value + "'" + (isDisabled ? (" class='" + classes.disabled + "'") : "tabindex='0'" ) + ">" + option.textContent + "</li>";
			}

			/**
			 * Return offset of element
			 * @method getOffsetOfElement
			 * @private
			 * @static
			 * @param {HTMLElement} element
			 * @param {HTMLElement} container
			 * @return {Object}
			 * @member ns.widget.mobile.SelectMenu
			*/
			function getOffsetOfElement(element, container) {
				var top = element.offsetTop,
					left = element.offsetLeft,
					offsetParent;
				while (element.offsetParent) {
					offsetParent = element.offsetParent;
					top += offsetParent.offsetTop;
					left += offsetParent.offsetLeft;
					if (element === container) {
						break;
					}
					element = offsetParent;
				}
				return {top: top, left: left};
			}

			/**
			 * Construct element of option of selectmenu
			 * @method constructOption
			 * @private
			 * @static
			 * @param {HTMLElement} element
			 * @param {ns.widget.mobile.SelectMenu} self
			 * @return {string}
			 * @member ns.widget.mobile.SelectMenu
			*/
			function constructOption(self) {
				var i,
					j,
					forElement,
					tag,
					options = "",
					optionArray,
					optionCount,
					groupOptionArray,
					groupOptCount,
					isDisabled,
					widgetOptions = self.options,
					getData = domUtils.getNSData;

				optionArray = slice.call(self._ui.elSelect.children);

				// This part is for optgroup tag.
				for (i = 0, optionCount = optionArray.length; i < optionCount; i++) {
					forElement = optionArray[i];
					isDisabled = !!forElement.disabled;
					tag = forElement.tagName;
					// for <option> tag
					if (tag === "OPTION") {
						/* When data-hide-placeholder-menu-items is true,
						 * <option> with data-placeholder="true" is hidden in selectmenu.
						 * It means that the <option> doesn't have to be selectmenu element.
						 */
						if (widgetOptions.hidePlaceholderMenuItems && getData(forElement, "placeholder")) {
							continue;
						}
						// normal <option> tag will be selectmenu element.
						options += convertOptionToHTML(forElement, isDisabled);
					} else if (tag === "OPTGROUP"){
						// for <optgroup> tag
						options += "<li class='" + classes.optionGroup + (isDisabled ? (" " + classes.disabled + "'") : "'" ) + ">" + forElement.label + "</li>";
						groupOptionArray = slice.call(forElement.children);
						for (j = 0, groupOptCount = groupOptionArray.length; j < groupOptCount; j++) {
							// If <optgroup> is disabled, all child of the optgroup are also disabled.
							isDisabled = !!forElement.disabled || !!groupOptionArray[j].disabled;
							if (widgetOptions.hidePlaceholderMenuItems && getData(forElement, "placeholder")) {
								continue;
							}
							options += convertOptionToHTML(groupOptionArray[j], isDisabled);
						}
					}
				}
				return options;
			}

			/**
			 * Check whether the placeholder option exist or not
			 * @method findDataPlaceHolder
			 * @private
			 * @static
			 * @param {HTMLElement} element
			 * @return {HTMLElement}
			 * @member ns.widget.mobile.SelectMenu
			*/
			function findDataPlaceHolder(element) {
				return element.querySelector("option[data-placeholder='true']");
			}

			/**
			 * Check whether the type is label or not
			 * @method _checkLabel
			 * @protected
			 * @member ns.widget.mobile.SelectMenu
			 */
			prototype._checkLabel = function () {
				var self = this,
					ui = self._ui;
				if (self.options.label) {
					ui.elSelectWrapper.classList.add(classes.label);
				} else {
					ui.elSelectWrapper.classList.remove(classes.label);
				}
			};

			/**
			 * Check whether the type is Inline or not
			 * @method _checkInline
			 * @protected
			 * @member ns.widget.mobile.SelectMenu
			 */
			prototype._checkInline = function () {
				var self = this,
					ui = self._ui;
				if (self.options.inline) {
					ui.elSelectWrapper.classList.add(classes.inline);
					ui.elPlaceHolder.removeAttribute("style");
				} else {
					ui.elSelectWrapper.classList.remove(classes.inline);
				}
			};

			/**
			 * Build structure of SelectMenu widget
			 * @method _build
			 * @param {HTMLElement} element
			 * @return {HTMLElement}
			 * @protected
			 * @member ns.widget.mobile.SelectMenu
			 */
			prototype._build = function (element) {
				this._generate(element);
				return element;
			};

			/**
			 * Generate Placeholder and Options elements for SelectMenu
			 * @method _generate
			 * @param {HTMLElement} element
			 * @return {HTMLElement}
			 * @protected
			 * @member ns.widget.mobile.SelectMenu
			 */
			prototype._generate = function (element) {
				var self = this,
					isNewBuild = false,
					options = "",
					selectedOption,
					fragment,
					elementId = element.id,
					ui = self._ui,
					elSelect = element,
					elPlaceHolder,
					elSelectWrapper,
					elOptions,
					screenFilter,
					elOptionContainer;

				ui.elSelect = elSelect;
				ui.page = selectors.getParentsByClass(elSelect, "ui-page")[0] || document.body;
				ui.content = selectors.getParentsByClass(elSelect, "ui-content")[0];
				ui.elDefaultOption = findDataPlaceHolder(elSelect);
				if (!ui.elOptions) {
					self._selectedIndex = elSelect.selectedIndex;
				}
				selectedOption = ui.elDefaultOption || elSelect[self._selectedIndex];

				elSelectWrapper = document.getElementById(elementId + "-selectmenu");

				if (elSelectWrapper === null) {
					elSelectWrapper = document.createElement("div");
					elSelectWrapper.className = classes.selectWrapper;
					elSelectWrapper.id = elementId + "-selectmenu";
				}

				if (self.options.nativeMenu) {
					elPlaceHolder = document.getElementById(elementId + "-placeholder");
					if (elPlaceHolder === null) {
						elPlaceHolder = document.createElement("span");
						elPlaceHolder.id = elementId + "-placeholder";
						elPlaceHolder.className = classes.placeHolder;
						domUtils.insertNodesBefore(elSelect, elSelectWrapper);
						elSelectWrapper.appendChild(elPlaceHolder);
						elSelectWrapper.appendChild(elSelect);
						elSelectWrapper.classList.add(classes.native);
						elPlaceHolder.innerHTML = selectedOption.textContent;
					}
					elOptions = elSelect.querySelectorAll("option");
				} else {
					options = constructOption(self);

					elPlaceHolder = document.getElementById(elementId + "-placeholder");

					if (elPlaceHolder === null) {
						elPlaceHolder = document.createElement("span");
						elPlaceHolder.id = elementId + "-placeholder";
						elPlaceHolder.className = classes.placeHolder;
						domUtils.insertNodesBefore(elSelect, elSelectWrapper);
						elSelectWrapper.appendChild(elPlaceHolder);
						elSelectWrapper.appendChild(elSelect);

						screenFilter = document.createElement("div");
						screenFilter.className = classes.filterHidden;
						screenFilter.classList.add(classes.filter);
						screenFilter.id = elementId + "-screen";

						elOptionContainer = document.createElement("ul");
						elOptionContainer.className = classes.optionList;
						elOptionContainer.id = elementId + "-options";
						isNewBuild = true;
					} else {
						screenFilter = document.getElementById(elementId + "-screen");
						elOptionContainer = document.getElementById(elementId + "-options");
					}

					elPlaceHolder.innerHTML = selectedOption.textContent;
					elOptionContainer.innerHTML = options;

					/*****************************************************************************************************
					 * FIX ME : When scrollview is removed, elOptionContainer can be located around SelectTag.
					 *****************************************************************************************************/
					if (isNewBuild) {
						fragment = document.createDocumentFragment();
						fragment.appendChild(screenFilter);
						fragment.appendChild(elOptionContainer);
						ui.page.appendChild(fragment);
					}

					elOptions = elOptionContainer.querySelectorAll("li[data-value]");
					elOptions[self._selectedIndex].classList.add(classes.selected);
				}

				elSelectWrapper.setAttribute("tabindex", 0);

				ui.elSelectWrapper = elSelectWrapper;
				ui.elPlaceHolder = elPlaceHolder;
				ui.elOptions = elOptions;
				ui.screenFilter = screenFilter;
				ui.elOptionContainer = elOptionContainer;

				self._checkLabel();
				self._checkInline();

				return element;
			};

			/**
			 * Init of SelectMenu widget
			 * @method _init
			 * @param {HTMLElement} element
			 * @protected
			 * @member ns.widget.mobile.SelectMenu
			 */
			prototype._init = function (element) {
				var self = this,
					ui = self._ui,
					elementId = element.id;
				if (!ui.elSelectWrapper) {
					ui.elSelectWrapper = document.getElementById(elementId+"-selectmenu");
					ui.elPlaceHolder = document.getElementById(elementId+"-placeholder");
					ui.elSelect = element;
					if (!self.options.nativeMenu) {
						ui.screenFilter = document.getElementById(elementId+"-screen");
						ui.elOptionContainer = document.getElementById(elementId+"-options");
						ui.elOptions = ui.elOptionContainer.querySelectorAll("li[data-value]");
					}
				}
				if (element.disabled) {
					self._disable();
				}
			};

			/**
			 * Refresh of SelectMenu widget
			 * @method _refresh
			 * @protected
			 * @member ns.widget.mobile.SelectMenu
			 */
			prototype._refresh = function () {
				var self = this;
				self._generate(self._ui.elSelect);
			};

			/**
			* Enables widget
			* @method _enable
			*  @protected
			* @member ns.widget.mobile.SelectMenu
			*/
			prototype._enable = function () {
				setDisabledStatus(this._ui.elSelectWrapper, false);
				domUtils.removeAttribute(this.element, "disabled");
			};

			/**
			* Disables widget
			* @method _disable
			*  @protected
			* @member ns.widget.mobile.SelectMenu
			*/
			prototype._disable = function () {
				setDisabledStatus(this._ui.elSelectWrapper, true);
				domUtils.setAttribute(this.element, "disabled", true);
			};

			/**
			 * Open SelectMenu
			 * @method open
			 * @member ns.widget.mobile.SelectMenu
			 */
			prototype.open = function () {
				var self = this;
				if (self._isOpen === false) {
					self._toggleSelect();
				}
			};

			/**
			 * Close SelectMenu
			 * @method close
			 * @member ns.widget.mobile.SelectMenu
			 */
			prototype.close = function () {
				var self = this;
				if (self._isOpen === true) {
					self._toggleSelect();
				}
			};

			/**
			 * Bind events of SelectMenu widget
			 * @method _bindEvents
			 * @protected
			 * @member ns.widget.mobile.SelectMenu
			 */
			prototype._bindEvents = function () {
				var self = this,
					ui = self._ui;

				self._toggleMenuBound = toggleMenu.bind(null, self);
				self._changeOptionBound = changeOption.bind(null,self);
				self._onResizeBound = onResize.bind(null,self);
				self._nativeChangeOptionBound = nativeChangeOption.bind(null,self);
				if (!self.options.nativeMenu){
					ui.elSelectWrapper.addEventListener("vclick", self._toggleMenuBound);
					ui.elOptionContainer.addEventListener("vclick", self._changeOptionBound);
					ui.screenFilter.addEventListener("vclick", self._toggleMenuBound);
					window.addEventListener("throttledresize", self._onResizeBound, true);
				} else {
					ui.elSelect.addEventListener("change", self._nativeChangeOptionBound);
				}
			};

			/**
			 * Coordinate Option ul element
			 * @method _coordinateOption
			 * @return {String}
			 * @protected
			 * @member ns.widget.mobile.SelectMenu
			 */
			prototype._coordinateOption = function () {
				var self = this,
					offsetTop,
					offsetLeft,
					width,
					placeholderStyle = window.getComputedStyle(self._ui.elPlaceHolder, null),
					areaInfo,
					optionStyle,
					ui = self._ui,
					overLapValue,
					optionHeight = ui.elOptionContainer.offsetHeight,
					scrollTop = ui.elOptionContainer.parentNode.querySelector(".ui-scrollview-clip").scrollTop;

				self._offset = getOffsetOfElement(ui.elSelectWrapper, ui.page);
				areaInfo = self._chooseDirection();
				// the option list width is shorter than the placeholder.
				width = ui.elPlaceHolder.offsetWidth - (parseFloat(placeholderStyle.paddingLeft) * 2);
				// This part decides the location and direction of option list.
				offsetLeft = self._offset.left;
				overLapValue = areaInfo.overLapValue;
				optionStyle = "left: " + offsetLeft + "px; ";
				if (areaInfo.direction === "top") {
					offsetTop = 0;
					if (optionHeight < areaInfo.topArea) {
						offsetTop = self._offset.top - optionHeight + 1- scrollTop + overLapValue;
					}
					optionStyle += "top: " + offsetTop + "px; width: " + width + "px; max-height: " + (areaInfo.topArea + 1 + overLapValue) + "px;";
					ui.elOptionContainer.classList.add(classes.top);
					ui.elOptionContainer.classList.remove(classes.bottom);
				} else {
					offsetTop = self._offset.top + ui.elPlaceHolder.offsetHeight - 1 - scrollTop - overLapValue;
					optionStyle += "top: " + offsetTop + "px; width: " + width + "px; max-height: " + (areaInfo.belowArea + 1 + overLapValue) + "px;";
					ui.elOptionContainer.classList.add(classes.bottom);
					ui.elOptionContainer.classList.remove(classes.top);
				}
				return optionStyle;
			};

			/**
			 * Choose a spreading direction of option list and calculate area to display the option list
			 * @method _chooseDirection
			 * @return {Object}
			 * @protected
			 * @member ns.widget.mobile.SelectMenu
			 */
			prototype._chooseDirection = function () {
				var self = this,
					ui = self._ui,
					areaInfo = {
						belowArea : null,
						topArea : null,
						direction : null,
						overLapValue : null
					},
					currentOffset = self._offset;

				areaInfo.belowArea = ui.page.offsetHeight - currentOffset.top - ui.elPlaceHolder.offsetHeight + ui.content.scrollTop;
				areaInfo.topArea = currentOffset.top - ui.content.scrollTop;
				areaInfo.overLapValue = ui.elOptions[0].offsetHeight / 8;

				if ((areaInfo.belowArea < areaInfo.topArea) && (ui.elOptionContainer.offsetHeight > areaInfo.belowArea + areaInfo.overLapValue)) {
					areaInfo.direction = "top";
				} else {
					areaInfo.direction = "bottom";
				}
				return areaInfo;
			};

			/**
			 * Open and Close Option List
			 * @method _toggleSelect
			 * @protected
			 * @member ns.widget.mobile.SelectMenu
			 */
			prototype._toggleSelect = function () {
				var self = this,
					ui = self._ui,
					container = ui.elOptionContainer;

				if (self._isOpen) {
					ui.screenFilter.classList.add(classes.filterHidden);
					container.removeAttribute("style");
					ui.elSelectWrapper.classList.remove(classes.active);
					container.classList.remove(classes.active);
				} else {
					container.setAttribute("style", self._coordinateOption());
					ui.screenFilter.classList.remove(classes.filterHidden);
					ui.elSelectWrapper.classList.add(classes.active);
					container.classList.add(classes.active);
					container.setAttribute("tabindex", "0");
					container.focus();
				}
				self._isOpen = !self._isOpen;
			};

			/**
			 * Change Value of Select tag and Placeholder
			 * @method changeOption
			 * @protected
			 * @member ns.widget.mobile.SelectMenu
			 */
			prototype._changeOption = function () {
				var self = this,
					ui = self._ui,
					selectedOption = ui.elOptions[self._selectedIndex],
					previousOption = ui.elOptionContainer.querySelector("." + classes.selected),
					getData = domUtils.getNSData;

				if ((selectedOption !== previousOption) || (ui.elDefaultOption && (ui.elPlaceHolder.textContent === ui.elDefaultOption.textContent))) {
					ui.elPlaceHolder.textContent = selectedOption.textContent;
					ui.elSelect.value = getData(selectedOption, "value");
					if (ui.elSelect.value === "") {
						ui.elSelect.value = getData(previousOption, "value");
						ui.elPlaceHolder.textContent = previousOption.textContent;
						return;
					}
					eventUtils.trigger(ui.elSelect, "change");
					previousOption.classList.remove(classes.selected);
					selectedOption.classList.add(classes.selected);
				}
			};

			/**
			 * Destroy SelectMenu widget
			 * @method _destroy
			 * @protected
			 * @member ns.widget.mobile.SelectMenu
			 */
			prototype._destroy = function () {
				var self = this,
					ui = self._ui;
				if (!self.options.nativeMenu) {
					ui.elSelectWrapper.removeEventListener("vclick", self._toggleMenuBound);
					ui.elOptionContainer.removeEventListener("vclick", self._changeOptionBound);
					ui.screenFilter.removeEventListener("vclick", self._toggleMenuBound);
					window.removeEventListener("throttledresize", self._onResizeBound, true);
				} else{
					ui.elSelect.removeEventListener("change", self._nativeChangeOptionBound);
				}
			};

			ns.widget.mobile.SelectMenu = SelectMenu;
			engine.defineWidget(
				"SelectMenu",
				"select:not([data-role='slider']):not([data-role='range']):not([data-role='toggleswitch']):not(.ui-toggleswitch):not(.ui-slider)" +
				", select.ui-select-menu:not([data-role='slider']):not([data-role='range']):not([data-role='toggleswitch'])",
				["open", "close"],
				SelectMenu,
				"mobile"
			);

			}(window.document, ns));
/*global window, define, ns */
/*
* Copyright  2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/*jslint nomen: true, plusplus: true */

/**
 * #Progress Widget
 * The progress widget shows that an operation is in progress.
 *
 * ## Default selectors
 * In default elements matches to :
 *
 *  - HTML elements with data-role equal "progress"
 *  - HTML elements with class ui-progress
 *
 * ###HTML Examples
 *
 * ####Create simple text input on INPUT element
 *
 *		@example
 *		<div id="progress" data-role="progress"></div>
 *
 * ## Manual constructor
 * For manual creation of button widget you can use constructor of widget from
 * **tau** namespace:
 *
 *		@example
 *		<div id="progress"></div>
 *		<script>
 *			var element = document.getElementById("progress"),
 *				progress = tau.widget.Progress(element);
 *		</script>
 *
 * Constructor has one required parameter **element** which is base
 * **HTMLElement** to create widget. We recommend get this element by method
 * *document.getElementById*. Second parameter **options** and it is a object
 * with options for widget.
 *
 * If jQuery library is loaded, its method can be used:
 *
 *		@example
 *		<div id="progress"></div>
 *		<script>
 *			$("#progress").progress();
 *		</script>
 *
 * jQuery Mobile constructor has one optional parameter **options** and it is
 * a object with options for widget.
 *
 * ##Options for widget
 *
 * Options for widget can be defined as _data-..._ attributes or supplied as
 * parameter in constructor.
 *
 * You can change option for widget using method **option**.
 *
 * ##Methods
 *
 * To call method on widget you can use one of existing API:
 *
 * First API is from tau namespace:
 *
 *		@example
 *		<div id="progress"></div>
 *		<script>
 *			var element = document.getElementById("progress"),
 *				progress = tau.widget.Progress(element);
 *
 *			// progress.methodName(argument1, argument2, ...);
 *			// for example
 *			progress.value(2);
 *		</script>
 *
 * Second API is jQuery Mobile API and for call _methodName_ you can use:
 *
 *		@example
 *		<div id="progress"></div>
 *		<script>
 *			// $(".selector").progress("methodName", argument1, argument2, ...);
 *			// for example
 *			$("#progress").progress("value", 2);
 *		</script>
 *
 * @extends ns.widget.BaseWidget
 * @class ns.widget.mobile.Progress
 */

(function (document, ns) {
	


			/**
			 * {Object} Widget Alias for {@link ns.widget.BaseWidget}
			 * @member ns.widget.mobile.Progress
			 * @private
			 */
			var BaseWidget = ns.widget.mobile.BaseWidgetMobile,
				/**
				 * @property {ns.engine} engine Alias for class ns.engine
				 * @member ns.widget.mobile.Progress
				 * @private
				 * @static
				 */
				engine = ns.engine,
				classes = {
					uiProgressContainerCircle: "ui-progress-container-circle",
					uiProgressCircleRunning: "ui-progress-circle-running",
					uiProgressCircle: "ui-progress-circle",
					uiProgressCircleSmall: "ui-progress-circle-small",
					uiProgressCircleLarge: "ui-progress-circle-large",
					uiProgressbar: "ui-progressbar",
					uiProgressbarBg: "ui-progressbar-bg",
					uiProgressPending: "ui-progress-pending",
					uiProgressPendingRunning: "ui-progress-pending-running",
					uiProgressPrefix: ".ui-progress-"
				},

				Progress = function () {
					this.action = "";
					this.label = null;
					/**
					 * Object with default options
					 * @property {Object} options
					 * @property {"circle"|"pending"} [options.style="pending"]
					 * style of progress
					 * @property {boolean} [options.running=true] start running
					 * or not
					 * @property {"small"|"medium"|"large"} [options.size="medium"] The size
					 * for the circle style progress
					 * @member ns.widget.mobile.Progress
					 */
					this.options = {
						style: "pending",
						running: true,
						size: "medium"
					};
					/**
					 * witch information about css style animation element
					 * @property {string} runningClass
					 * @member ns.widget.mobile.Progress
					 */
					this.runningClass = classes.uiProgressCircleRunning;
					/**
					 * @property {HTMLElement} _uiProgress nn
					 * @protected
					 * @member ns.widget.mobile.Progress
					 */
					this._uiProgress = null;
				};

			Progress.prototype = new BaseWidget();

			/**
			 * Dictionary for progress related css class names
			 * @property {Object} classes
			 * @member ns.widget.mobile.Progress
			 * @static
			 */
			Progress.classes = classes;

			/**
			 * Build structure of progress widget
			 * @method _build
			 * @param {HTMLElement} element
			 * @return {HTMLElement}
			 * @protected
			 * @member ns.widget.mobile.Progress
			 */
			Progress.prototype._build = function (element) {
					/* cached options object
					* type Object
					*/
				var options = this.options,
					/*
					* created HTML element of progress container
					* type HTMLElement
					*/
					progressElement = document.createElement("div"),
					/*
					* created HTML element of progress container
					* type HTMLElement
					*/
					progressPendingElement,
					/*
					* cached classList of element
					* type DOMTokenList
					*/
					elementClasses = element.classList,
					progressClasses = progressElement.classList;

				/*
				 * Create structure for progress with style circle
				 */
				if (options.style === "circle") {
					elementClasses.add(classes.uiProgressContainerCircle);
					progressClasses.add(classes.uiProgressCircle);
					switch (options.size) {
					case "small":
						progressClasses.add(classes.uiProgressCircleSmall);
						break;
					case "large":
						progressClasses.add(classes.uiProgressCircleLarge);
						break;
					}
					this.runningClass = classes.uiProgressCircleRunning;

					/*
					 * Create structure for progress with style pending
					 */
				} else if (options.style === "pending") {
					elementClasses.add(classes.uiProgressbar);
					progressElement.classList.add(classes.uiProgressbarBg);
					progressPendingElement = document.createElement("div");
					progressPendingElement.classList.add(classes.uiProgressPending);
					progressElement.appendChild(progressPendingElement);
					this.runningClass = classes.uiProgressPendingRunning;
				}

				element.appendChild(progressElement);
				return element;
			};

			/**
			 * Init widget
			 * @method _init
			 * @param {HTMLElement} element
			 * @protected
			 * @member ns.widget.mobile.Progress
			 */
			Progress.prototype._init = function (element) {
				var self = this,
					options = self.options;
				if (self._uiProgress === null) {
					self._uiProgress = element.querySelector(classes.uiProgressPrefix +
							options.style);
				}
				self._setRunning(options.running);
			};


			/**
			 * Method starts or stops running the progress.
			 *
			 *	@example
			 *	<div id="progress"></div>
			 *	<script>
			 *		var element = document.getElementById("progress"),
			 *			progressWidget = tau.widget.Progress(element),
			 *			// return current state of running
			 *			value = progressWidget.running();
			 *
			 *		progressWidget.running( true ); // starts running
			 *
			 *		progressWidget.running( fasle ); // stops running
			 *	</script>
			 *
			 *	@example
			 *	<div id="progress"></div>
			 *	<script>
			 *		// return current state of running
			 *		$( "#progress" ).progress( "running" );
			 *
			 *		// starts running
			 *		$( "#progress" ).progress( "running", true );
			 *
			 *		// stops running
			 *		$( "#progress" ).progress( "running", fasle );
			 *	</script>
			 *
			 * @method running
			 * @param {boolean} flag if thrue then set mode to running if false
			 * the stop running mode
			 * @member ns.widget.mobile.Progress
			 * @returns {boolean}
			 */
			Progress.prototype.running = function (flag) {
				if (typeof flag === "boolean") {
					this._setRunning(flag);
				}
				return this.options.running;
			};

			/**
			 * Set running flag and refresh progress
			 * @method _setRunning
			 * @param {boolean} flag
			 * @protected
			 * @member ns.widget.mobile.Progress
			 */
			Progress.prototype._setRunning = function (flag) {
				if (typeof flag === "boolean") {
					this.options.running = flag;
					this._refresh();
				}
			};


			/**
			 * Start progress
			 * @method _start
			 * @protected
			 * @member ns.widget.mobile.Progress
			 */
			Progress.prototype._start = function () {
				this.show();
				this._uiProgress.classList.add(this.runningClass);
			};

			/**
			 * Stop progress
			 * @method _stop
			 * @protected
			 * @member ns.widget.mobile.Progress
			 */
			Progress.prototype._stop = function () {
				this._uiProgress.classList.remove(this.runningClass);
			};

			/**
			 * Method shows progress.
			 *
			 *	@example
			 *	<div id="progress"></div>
			 *	<script>
			 *		var element = document.getElementById("progress"),
			 *			progressWidget = tau.widget.Progress(element);
			 *
			 *		progressWidget.show();
			 *	</script>
			 *
			 *	@example
			 *	<div id="progress"></div>
			 *	<script>
			 *		$( "#progress" ).progress( "show" );
			 *	</script>
			 *
			 * @method show
			 * @member ns.widget.mobile.Progress
			 */
			Progress.prototype.show = function () {
				this.element.style.display = "";
			};

			/**
			 * Method hides progress
			 *
			 *	@example
			 *	<div id="progress"></div>
			 *	<script>
			 *		var element = document.getElementById("progress"),
			 *			progressWidget = tau.widget.Progress(element);
			 *		progressWidget.hide();
			 *	</script>
			 *
			 *	@example
			 *	<div id="progress"></div>
			 *	<script>
			 *		$( "#progress" ).progress( "hide" );
			 *	</script>
			 *
			 * @method hide
			 * @member ns.widget.mobile.Progress
			 */
			Progress.prototype.hide = function () {
				this.element.style.display = "none";
			};

			/**
			 * Method refreshes a progress.
			 *
			 * This method will rebuild while DOM structure of widget. Method
			 * should be called after all manually change in HTML attributes
			 * of widget DOM structure. Refresh is called automatically after
			 * change any option of widget.
			 *
			 *	@example
			 *	<div id="progress"></div>
			 *	<script>
			 *		var element = document.getElementById("progress"),
			 *			progressWidget = tau.widget.Progress(element);
			 *
			 *		progressWidget.refresh();
			 *
			 *		// also will be called after
			 *		progressWidget.option("running", true);
			 *	</script>
			 *
			 *	@example
			 *	<div id="progress"></div>
			 *	<script>
			 *		$( "#progress" ).progress( "refresh" );
			 *	</script>
			 *
			 * @method refresh
			 * @chainable
			 * @member ns.widget.mobile.Progress
			 */

			/**
			 * Refresh progress
			 * @method _refresh
			 * @member ns.widget.mobile.Progress
			 * @protected
			 */
			Progress.prototype._refresh = function () {
				if (this.options.running) {
					this._start();
				} else {
					this._stop();
				}
			};

			// definition
			ns.widget.mobile.Progress = Progress;
			engine.defineWidget(
				"Progress",
				"[data-role='progress'], .ui-progress",
				[
					"running",
					"show",
					"hide"
				],
				Progress,
				"tizen"
			);

}(window.document, ns));

/*global window, define, ns */
/*
* Copyright  2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/*jslint nomen: true, plusplus: true */

/**
 * #Progress Bar Widget
 * The progress bar widget shows a control that indicates the progress
 * percentage of an on-going operation.
 *
 * ## Default selectors
 * In default elements matches to :
 *
 *  - HTML elements with data-role equal "progressbar"
 *  - HTML elements with class ui-progressbar
 *
 * ###HTML Examples
 *
 * ####Create simple text input on INPUT element
 *
 *		@example
 *		<div id="progress-bar" data-role="progressbar"></div>
 *
 * ## Manual constructor
 * For manual creation of button widget you can use constructor of widget from
 * **tau** namespace:
 *
 *		@example
 *		<div id="progress-bar"></div>
 *		<script>
 *			var element = document.getElementById("progress-bar"),
 *				progressBar = tau.widget.ProgressBar(element);
 *		</script>
 *
 * Constructor has one required parameter **element** which is base
 * **HTMLElement** to create widget. We recommend fetching this element by
 * method *document.getElementById*. Second parameter is **options** and it is a
 * object with options for widget.
 *
 * If jQuery library is loaded, its method can be used:
 *
 *		@example
 *		<div id="progress-bar"></div>
 *		<script>
 *			$("#progress-bar").progressbar();
 *		</script>
 *
 * jQuery Mobile constructor has one optional parameter **options** and it is
 * a object with options for widget.
 *
 * ##Options for widget
 *
 * Options for widget can be defined as _data-..._ attributes or give as
 * parameter in constructor.
 *
 * You can change option for widget using method **option**.
 *
 * ##Methods
 *
 * To call method on widget you can use one of existing API:
 *
 * First API is from tau namespace:
 *
 *		@example
 *		<script>
 *			var element = document.getElementById("probress-bar"),
 *				progressBar = tau.widget.ProgressBar(element);
 *
 *			progressBar.methodName(argument1, argument2, ...);
 *		</script>
 *
 *
 * Second API is jQuery Mobile API and for call _methodName_ you can use:
 *
 *		@example
 *		$(".selector").progressbar("methodName", argument1, argument2, ...);
 *
 * @extends ns.widget.BaseWidget
 * @class ns.widget.mobile.ProgressBar
 */

(function (document, ns) {
	


			var BaseWidget = ns.widget.mobile.BaseWidgetMobile,


				events = ns.event,
				/**
				 * @property {ns.engine} engine Alias for class ns.engine
				 * @member ns.widget.mobile.ProgressBar
				 * @private
				 */
				engine = ns.engine,

				ProgressBar = function () {

					/**
					 * Object with default options
					 * @property {Object} options
					 * @property {number} [options.value=0] value of progress
					 * bar
					 * @property {number} [options.min=0] minimal value of
					 * progress bar
					 * @property {number} [options.max=100] maximal value of
					 * progress bar
					 * @member ns.widget.mobile.ProgressBar
					 */
					this.options = {
						value: 0,
						max: 100,
						min: 0
					};
				};

			/**
			 * Event is triggered when value of widget is changing.
			 * @event change
			 * @member ns.widget.mobile.ProgressBar
			 */

			/**
			 * Event is triggered when value of widget riches maximal value.
			 * @event complete
			 * @member ns.widget.mobile.ProgressBar
			 */

			ProgressBar.prototype = new BaseWidget();

			/**
			 * Dictionary for progress related css class names
			 * @property {Object} classes
			 * @static
			 * @member ns.widget.mobile.ProgressBar
			 * @readonly
			 */
			ProgressBar.classes = {
				uiProgressbar: "ui-progressbar",
				uiProgressbarBg: "ui-progressbar-bg",
				uiProgressbarValue: "ui-progressbar-value"
			};

			/**
			 * Build structure of progress widget
			 * @method _build
			 * @param {HTMLElement} element
			 * @return {HTMLElement}
			 * @protected
			 * @member ns.widget.mobile.ProgressBar
			 */
			ProgressBar.prototype._build = function (element) {
				/* cached ProgressBar.classes object
				* type Object
				*/
				var classes = ProgressBar.classes,
					self = this,
					options = self.options,
					progressBarBgElement,
					progressBarValueElement;

				progressBarBgElement = document.createElement("div");
				progressBarValueElement = document.createElement("div");

				element.classList.add(classes.uiProgressbar);
				progressBarBgElement.classList.add(classes.uiProgressbarBg);
				progressBarValueElement.classList.add(classes.uiProgressbarValue);

				progressBarValueElement.style.width = options.value + "%";

				progressBarValueElement.style.display = "none";

				element.setAttribute("role", "ProgressBar");
				element.setAttribute("aria-valuemin", options.min);
				element.setAttribute("aria-valuenow", options.value);
				element.setAttribute("aria-valuemax", options.max);

				progressBarBgElement.appendChild(progressBarValueElement);
				element.appendChild(progressBarBgElement);

				// fix for compare tests
				self.min = options.min;
				self.valueDiv = progressBarValueElement;
				self.oldValue = options.value;

				return element;
			};

			/**
			 * Get or set value
			 *
			 * Return inner text of button or set text on button
			 *
			 *	@example
			 *	<div id="progress-bar"></div>
			 *	<script>
			 *		var element = document.getElementById("progress-bar"),
			 *			progressBarWidget = tau.widget.ProgressBar(element),
			 *			// returns current value
			 *			value = progressBarWidget.value();
			 *
			 *		progressBarWidget.value( 30 ); // sets new value to 30
			 *	</script>
			 *
			 *	@example
			 *	<div id="progress-bar"></div>
			 *	<script>
			 *		// returns current value
			 *		$( "#progress-bar" ).progressbar( "value" );
			 *
			 *		// set new value to 30
			 *		$( "#progress-bar" ).progressbar( "value", 30 );
			 *	</script>
			 * @method value
			 * @param {number} [value] Value to set on progress bar
			 * @return {number} In get mode returns current value of progress
			 * bar
			 * @since 2.3
			 * @member ns.widget.mobile.ProgressBar
			 */

			/**
			 * Method sets ProgressBar value.
			 * @method _setValue
			 * @param {number} value
			 * @return {boolean}
			 * @protected
			 * @member ns.widget.mobile.ProgressBar
			 */
			ProgressBar.prototype._setValue = function (value) {
				var options = this.options;
				if (typeof value === "number") {
					value = Math.min(options.max, Math.max(options.min, value));
					if (value !== options.value) {
						events.trigger(this.element, "change");
						options.value = value;
					}
					if (value === options.max) {
						events.trigger(this.element, "complete");
					}
					this.refresh();
					return true;
				}
				return false;
			};

			/**
			 * Method gets ProgressBar value.
			 * @method _getValue
			 * @return {number}
			 * @protected
			 * @member ns.widget.mobile.ProgressBar
			 */
			ProgressBar.prototype._getValue = function () {
				return this.options.value;
			};

			/**
			 * Refresh a progres bar.
			 *
			 * This method will rebuild while DOM structure of widget. Method
			 * should be called after are manually change in HTML attributes of
			 * widget DOM structure. Refresh is called automatically after
			 * change any option of widget.
			 *
			 *	@example
			 *	<div id="progress-bar"></div>
			 *	<script>
			 *		var element = document.getElementById("progress-bar"),
			 *			progressBarWidget = tau.widget.ProgressBar(element),
			 *
			 *		progressBarWidget.refresh();
			 *	</script>
			 *
			 *	@example
			 *	<div id="progress-bar"></div>
			 *	<script>
			 *		$( "#progress-bar" ).progressbar( "refresh" );
			 *	</script>
			 *
			 * @method refresh
			 * @chainable
			 * @member ns.widget.mobile.ProgressBar
			 */

			/**
			 * Method refreshes ProgressBar.
			 * @method _refresh
			 * @member ns.widget.mobile.ProgressBar
			 * @protected
			 */
			ProgressBar.prototype._refresh = function () {
				var element = this.element,
					options = this.options,
					elementChild = element.firstElementChild.firstElementChild;

				element.setAttribute("aria-valuenow", options.value);
				elementChild.style.display = "";
				elementChild.style.width = options.value + "%";
			};

			// definition
			ns.widget.mobile.ProgressBar = ProgressBar;
			engine.defineWidget(
				"ProgressBar",
				"[data-role='progressbar'], .ui-progressbar",
				["value"],
				ProgressBar,
				"tizen"
			);

}(window.document, ns));

/*global window, define, ns */
/*
* Copyright  2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/*jslint nomen: true */
/**
* #Multimedia View widget
 * The multimedia view widget displays the audio and video player.
* @class ns.widget.mobile.MultimediaView
* @extends ns.widget.mobile.BaseWidgetMobile
* @author Maciej Urbanski <m.urbanski@samsung.com>
* @author Tomasz Lukawski <t.lukawski@samsung.com>
*/
(function (window, document, ns) {
	
					/**
				* Local alias for ns.widget.mobile.BaseWidgetMobile
				* @property {Function} BaseWidgetMobile Alias for {@link ns.widget.mobile.BaseWidgetMobile}
				* @member ns.widget.mobile.MultimediaView
				* @static
				* @private
				*/
			var BaseWidget = ns.widget.mobile.BaseWidgetMobile,
				/**
				* Local alias for ns.engine
				* @property {Object} engine Alias for {@link ns.engine}
				* @member ns.widget.mobile.MultimediaView
				* @static
				* @private
				*/
				engine = ns.engine,
				/**
				* Local alias for ns.event
				* @property {Object} engine Alias for {@link ns.event}
				* @member ns.widget.mobile.MultimediaView
				* @static
				* @private
				*/
				events = ns.event,
				/**
				* Local alias for ns.util
				* @property {Object} engine Alias for {@link ns.util}
				* @member ns.widget.mobile.MultimediaView
				* @static
				* @private
				*/
				util = ns.util,
				/**
				* Local alias for ns.utilsTheme
				* @property {Object} engine Alias for {@link ns.theme}
				* @member ns.widget.mobile.MultimediaView
				* @static
				* @private
				*/
				utilsTheme = ns.theme,
				/**
				* Local alias for ns.util.object
				* @property {Object} utilsDOM Alias for {@link ns.util.object}
				* @member ns.widget.mobile.MultimediaView
				* @static
				* @private
				*/
				utilsObject = ns.util.object,
				/**
				* Local alias for ns.util.DOM.manipulation & ns.util.DOM.css & ns.util.DOM.attributes
				* @property {Object} utilsDOM Alias for {@link ns.util.DOM.*}
				* @member ns.widget.mobile.MultimediaView
				* @static
				* @private
				*/
				utilsDOM = ns.util.DOM,
				/**
				* Local alias for ns.util.selectors
				* @property {Object} utilsSelectors Alias for {@link ns.util.selectors}
				* @member ns.widget.mobile.MultimediaView
				* @static
				* @private
				*/
				utilsSelectors = ns.util.selectors,
				/**
				 * Local alias for classes of Page widget
				 * @property {Object} Page Alias for {@link ns.widget.mobile.Page}
				 */
				pageClasses = ns.widget.mobile.Page.classes,
				/**
				 * Local alias for classes of Button widget
				 * @property {Object} Button Alias for {@link ns.widget.mobile.Button}
				 */
				buttonClasses = ns.widget.mobile.Button.classes,
				/**
				 * Local alias for classes of Scrollview widget
				 * @property {Object} Scrollview Alias for {@link ns.widget.mobile.Scrollview}
				 */
				scrollviewClasses = ns.widget.mobile.Scrollview.classes,
				/**
				 * Local alias for classes of Progressbar widget
				 * @property {Object} Progressbar Alias for {@link ns.widget.mobile.Progressbar}
				 */
				progressbarClasses = ns.widget.mobile.ProgressBar.classes,
				/**
				 * Local alias for classes of Progressbar widget
				 * @property {Object} Progressbar Alias for {@link ns.widget.mobile.Progressbar}
				 */
				sliderClasses = ns.widget.mobile.Slider.classes,
				/**
				* Alias to Array.slice
				* @method slice
				* @member ns.widget.mobile.MultimediaView
				* @static
				* @private
				*/
				slice = [].slice,

				POINTER_CLICK_EVENT = 'vclick',
				POINTER_MOVE_EVENT = 'vmousemove',
				POINTER_DOWN_EVENT = 'vmousedown',
				POINTER_UP_EVENT = 'vmouseup',
				MEDIA_POSITION_CHANGE_TIMEOUT = 200, //[ms]
				FULLSCREEN_DELAY = 300, //[]ms

				MultimediaView = function () {
					var self = this;
					/**
					* @property {Object} options
					* @property {Object} options.controls=true Sets the controls for the widget.
					* @property {Object} options.fullScreen=false Defines whether the widget opens in the fullscreen view mode.
					* @property {Object} [options.theme] Sets the widget theme. If the value is not set, the parent control's theme is used.
					*/
					self.options = {
						controls: true,
						fullScreen: false,
						theme: ''
					};
					self.role = null;
					self.controlTimer = null;
					self.isVolumeHide = true;
					self.backupView = null;
					self._reserveVolume = -1;
					self._isVideo = false;
					self.isVolumeHide = false;
					self._progressBarPressed = false;
					self._changeMediaPositionTimeout = null;
				},
				/**
				 * Local variable for MultimediaView prototype object
				 * @property {ns.widget.mobile.BaseWidgetMobile} MultimediaViewPrototype
				 * @member ns.widget.mobile.MultimediaView
				 * @private
				 * @static
				 */
				MultimediaViewPrototype = new BaseWidget(),
				/**
				 * Prefix of classes
				 * @property PREFIX
				 * @member ns.widget.mobile.MultimediaView
				 * @private
				 * @static
				 */
				PREFIX = 'ui-multimediaview',
				/**
				 * Directory with classes
				 * @property {Object} classes
				 * @static
				 * @readonly
				 * @member ns.widget.mobile.MultimediaView
				 */
				classes = {
					VIEW: PREFIX,
					VIDEO: PREFIX + '-video',
					WRAP: PREFIX + '-wrap',
					THEME_PREFIX: PREFIX + '-',
					BAR: PREFIX + '-bar',
					BAR_BACKGROUND: PREFIX + '-bar-bg',
					BAR_HIGHLIGHT: PREFIX + '-bar-highlight',
					// control bar
					CONTROL: PREFIX + '-control',
					PLAY_PAUSE: 'ui-playpausebutton',
					MUTE_ICON: 'ui-mute-icon',
					SEEK_BAR: 'ui-seekbar',
					DURATION_LABEL: 'ui-durationlabel',
					PLAY_ICON: 'ui-play-icon',
					PAUSE_ICON: 'ui-pause-icon',
					TIMESTAMP_LABEL: 'ui-timestamplabel',
					VOLUME_BAR: 'ui-volumebar',
					VOLUME_ICON: 'ui-volume-icon',
					VOLUME_BUTTON: 'ui-volumebutton',
					VOLUME_CONTROL: 'ui-volumecontrol',
					VOLUME_VALUE: 'ui-value',
					VOLUME_HANDLE: 'ui-handle',
					VOLUME_GUIDE: 'ui-guide',
					FULLSCREEN_BUTTON: 'ui-fullscreenbutton',
					FULLSCREEN_ON: 'ui-fullscreen-on',
					FULLSCREEN_OFF: 'ui-fullscreen-off',
					DURATION: 'ui-duration',
					CURRENT_TIME: 'ui-currenttime',
					BUTTON: 'ui-button',
					BUTTON_DOWN: 'ui-button-down',
					BUTTON_CORNER_ALL: buttonClasses.uiBtnCornerAll,
					BUTTON_CORNER_CIRCLE: buttonClasses.uiBtnCornerCircle,
					SHADOW: buttonClasses.uiShadow,
					PAGE_ACTIVE: pageClasses.uiPageActive,
					PAGE: pageClasses.uiPage
				},
				/**
				 * Selectors using in MultimediaView widget
				 * @property {Object} classes {@link ns.widget.mobile.MultimediaView#classes}
				 * @static
				 * @private
				 */
				selectors = {
					BUTTONS: '.' + classes.BUTTON,
					VOLUME_HANDLE: '.' + classes.VOLUME_CONTROL + ' .' + classes.VOLUME_HANDLE,
					WRAP: '.' + classes.WRAP,
					CONTROL: '.' + classes.CONTROL,
					SCROLLVIEW_CLIP: '.' + scrollviewClasses.clip,
					PROGRESS_BAR_BG: '.' + progressbarClasses.uiProgressbarBg,
					PROGRESS_BAR_VALUE: '.' + progressbarClasses.uiProgressbarValue,
					SLIDER_CONTAINER: '.' + sliderClasses.sliderContainer,
					SLIDER: '.' + sliderClasses.sliderContainer + ' .' + sliderClasses.slider
				},
				/**
				 * Name of video tag
				 * @property {string} VIDEO_TAG_NAME
				 */
				VIDEO_TAG_NAME = 'VIDEO',
				/**
				 * Tag for label of media duration
				 * @property {string} DURATION_LABEL_TAG_NAME
				 */
				DURATION_LABEL_TAG_NAME = 'p';

			/**
			* @property {Object} classes
			* @member ns.widget.mobile.MultimediaView
			* @static
			*/
			MultimediaView.classes = classes;

			/**
			* The method builds HTML structure of control panel
			* @method _createControl
			* @return {HTMLElement}
			* @member ns.widget.mobile.MultimediaView
			* @protected
			* @instance
			*/
			MultimediaViewPrototype._createControl = function () {
				var self = this,
					view = self.element,
					control = document.createElement('span'),
					playpauseButton = control.cloneNode(),
					seekBar = control.cloneNode(),
					timestampLabel = control.cloneNode(),
					durationLabel = control.cloneNode(),
					volumeButton = control.cloneNode(),
					volumeControl = control.cloneNode(),
					volumeBar = control.cloneNode(),
					fullscreenButton = control.cloneNode(),
					durationBar = control.cloneNode();

				volumeBar.innerHTML = '<input type="range" value="25" min="0" max="100" data-highlight="true" >';
				volumeBar = volumeBar.childNodes[0];

				self.ui = utilsObject.merge(self.ui, {
					control: control,
					playpauseButton: playpauseButton,
					seekBar: seekBar,
					timestampLabel: timestampLabel,
					durationLabel: durationLabel,
					volumeButton: volumeButton,
					volumeControl: volumeControl,
					volumeBar: volumeBar,
					fullscreenButton: fullscreenButton,
					durationBar: durationBar
				});

				timestampLabel.innerHTML = '<p>00:00:00</p>';
				durationLabel.innerHTML = '<p>00:00:00</p>';

				control.classList.add(classes.CONTROL, 'fade-out');

				durationLabel.classList.add(classes.DURATION_LABEL);
				playpauseButton.classList.add(classes.PLAY_PAUSE);
				playpauseButton.classList.add(classes.BUTTON);
				playpauseButton.classList.add(classes.PLAY_ICON);
				seekBar.classList.add(classes.SEEK_BAR);
				seekBar.classList.add(classes.BAR);
				timestampLabel.classList.add(classes.TIMESTAMP_LABEL);
				durationLabel.classList.add(classes.DURATION_LABEL);
				volumeButton.classList.add(classes.VOLUME_BUTTON);
				volumeButton.classList.add(classes.BUTTON);
				volumeControl.classList.add(classes.VOLUME_CONTROL);
				volumeBar.classList.add(classes.VOLUME_BAR);
				volumeBar.classList.add(classes.BAR);
				fullscreenButton.classList.add(classes.FULLSCREEN_BUTTON);
				fullscreenButton.classList.add(classes.BUTTON);
				durationBar.classList.add(classes.DURATION);

				seekBar.appendChild(durationBar);
				seekBar.appendChild(durationLabel);
				seekBar.appendChild(timestampLabel);

				volumeButton.classList.add(view.muted ? classes.MUTE_ICON : classes.VOLUME_ICON);

				volumeControl.appendChild(volumeBar);

				control.appendChild(playpauseButton);
				control.appendChild(seekBar);
				control.appendChild(volumeControl);
				control.appendChild(volumeButton);

				if (self._isVideo) {
					fullscreenButton.classList.add(classes.FULLSCREEN_ON);
					control.appendChild(fullscreenButton);
				}

				slice.call(control.querySelectorAll(selectors.BUTTONS), 0).forEach(function (element) {
					element.classList.add(classes.SHADOW);
					element.classList.add(classes.BUTTON_CORNER_ALL);
				});

				return control;
			};

			/**
			* The width method is used to get (if no value is defined)
			*  or set the multimedia view widget width
			* @method width
			* @param {number} [value=undefined]
			* @return {number|null} width Width value or null if fullScreen option is enabled
			* @member ns.widget.mobile.MultimediaView
			* @protected
			* @instance
			*/
			MultimediaViewPrototype.width = function (value) {
				var self = this,
					view,
					wrap;

				if (self.options.fullScreen) {
					return null;
				}

				view = self.element;
				wrap = self.ui.wrap;

				if (value === undefined) {
					return utilsDOM.getElementWidth(view);
				}

				if (!self._isVideo) {
					wrap.style.width = value + 'px';
				}

				view.style.width = value + 'px';
				self._resize();
			};

			/**
			* The height method is used to get (if no value is defined)
			*  or set the multimedia view widget height
			* @method height
			* @param {number} [value=undefined]
			* @return {number|null} height Height value or null if fullScreen option is enabled or element is not video
			* @member ns.widget.mobile.MultimediaView
			* @protected
			* @instance
			*/
			MultimediaViewPrototype.height = function (value) {
				var self = this,
					view = self.element;

				if (!self._isVideo || self.options.fullScreen) {
					return null;
				}

				if (value === undefined) {
					return view.getElementHeight();
				}

				view.style.height = value + 'px';
				self._resize();
			};

			/**
			* The fullScreen method is used to get (if no value is defined)
			*  or set the fullscreen mode of the multimedia view widget.
			* If the value is true, the fullscreen mode is used;
			*  otherwise the multimedia view widget runs in the normal mode
			* @method fullScreen
			* @param {boolean} value
			* @return {boolean}
			* @member ns.widget.mobile.MultimediaView
			* @instance
			*/
			MultimediaViewPrototype.fullScreen = function (value) {
				var self = this,
					control = self.ui.control,
					fbClasses = self.ui.fullscreenButton.classList;
				if (!self._isVideo) {
					return;
				}
				if (value === undefined) {
					return self.options.fullScreen;
				}
				// change icon class
				if (value) {
					fbClasses.remove(classes.FULLSCREEN_ON);
					fbClasses.add(classes.FULLSCREEN_OFF);
				} else {
					fbClasses.add(classes.FULLSCREEN_ON);
					fbClasses.remove(classes.FULLSCREEN_OFF);
				}
				if (self.options.fullScreen === value) {
					return;
				}
				self.options.fullScreen = value;
				if (value) {
					control.style.opacity = 0;
					setTimeout(function () {
						self.ui.wrap.webkitRequestFullScreen();
					}, FULLSCREEN_DELAY);
				} else {
					control.style.opacity = 1.0;
					setTimeout(function () {
						document.webkitCancelFullScreen();
					}, FULLSCREEN_DELAY);
				}
				self._resize();
			};

			/**
			* Resize view
			* @method fullScreen
			* @return {boolean}
			* @member ns.widget.mobile.MultimediaView
			* @instance
			* @protected
			*/
			MultimediaViewPrototype._resize = function () {
				this._resizeControl();
				this.trigger('updatelayout');
			};

			/**
			* The method builds HTML structure of widget
			* @method _build
			* @param {HTMLElement} element
			* @return {HTMLElement}
			* @member ns.widget.mobile.MultimediaView
			* @protected
			* @instance
			*/
			MultimediaViewPrototype._build = function (element) {
				var self = this,
					view = element || self.element,
					viewClasslist = view.classList,
					isVideo = (view.nodeName === VIDEO_TAG_NAME),
					options = self.options,
					parentTheme = utilsTheme.getInheritedTheme(view, utilsTheme.theme),
					theme = options.theme || parentTheme,
					wrap = null,
					control = null;

				// The creating of object that contains aliases for widget's HTML elements
				self.ui = {
					wrap: null,
					control: null
				};
				self.element = element;
				self._isVideo = isVideo;

				// INFO: since 2.3, we decided to use standard HTML <video> and <audio> tag.
				ns.warn("TAU based Multimediaview widget will be deprecated. Please use <video> / <audio> tag with standard HTML.");

				viewClasslist.add(classes.VIEW);

				control = self._createControl();
				// on build stage control panel is hidden,
				// control is showing on event "onLoadedMetadata"
				control.style.opacity = 0;
				self.ui.control = control;


				wrap = document.createElement('div');
				wrap.classList.add(classes.WRAP);
				wrap.classList.add(classes.THEME_PREFIX + theme);
				view.parentNode.replaceChild(wrap, view);
				wrap.appendChild(view);
				wrap.appendChild(control);
				self.ui.wrap = wrap;

				engine.instanceWidget(self.ui.volumeBar, 'Slider');
				engine.instanceWidget(self.ui.durationBar, 'ProgressBar');

				// customizing
				// progressBar
				self.ui.durationBar.classList.remove(progressbarClasses.uiProgressbar);
				//-- binding
				self.ui.progressBar = self.ui.durationBar.querySelector(selectors.PROGRESS_BAR_BG);

				if (isVideo) {
					control.classList.add(classes.VIDEO);
				} else {
					self.options.fullScreen = false;
				}

				if (options.controls && utilsDOM.getNSData(view, 'controls')) {
					utilsDOM.removeNSData(view, 'controls');
				}

				return element;
			};

			/**
			* The method initializing widget properties
			* @method _initControl
			* @member ns.widget.mobile.MultimediaView
			* @protected
			* @instance
			*/
			MultimediaViewPrototype._initControl = function () {
				var self = this,
					control = self.ui.control;
				// @todo: check binding;
				self.ui = utilsObject.merge(self.ui, {
					playpauseButton: control.querySelector('.' + classes.PLAY_PAUSE),
					seekBar: control.querySelector('.' + classes.SEEK_BAR),
					timestampLabel: control.querySelector('.' + classes.TIMESTAMP_LABEL),
					durationLabel: control.querySelector('.' + classes.DURATION_LABEL),
					volumeButton: control.querySelector('.' + classes.VOLUME_BUTTON),
					volumeControl: control.querySelector('.' + classes.VOLUME_CONTROL),
					volumeBar: control.querySelector('.' + classes.VOLUME_BAR),
					fullscreenButton: control.querySelector('.' + classes.FULLSCREEN_BUTTON),
					durationBar: control.querySelector('.' + classes.DURATION),
				});
				self.ui.progressBar = self.ui.durationBar.querySelector(selectors.PROGRESS_BAR_BG);
			};

			/**
			* The method initializing widget properties
			* @method _init
			* @param {HTMLElement} element
			* @return {HTMLElement}
			* @member ns.widget.mobile.MultimediaView
			* @protected
			* @instance
			*/
			MultimediaViewPrototype._init = function (element) {
				var self = this;
				if (self.ui === undefined) {
					self.element = element;
					self.ui = {};
					self.ui.wrap = utilsSelectors.getParentsBySelector(element, selectors.WRAP);
					self.ui.control = utilsSelectors.getParentsBySelector(element, selectors.CONTROL);
					self._isVideo = (element.nodeName === VIDEO_TAG_NAME);
					self.options.fullScreen = false;
				}

				return element;
			};

			/**
			* The method configuring base options of widget
			* @method _configure
			* @param {HTMLElement} element
			* @return {HTMLElement}
			* @member ns.widget.mobile.MultimediaView
			* @protected
			* @instance
			*/
			MultimediaViewPrototype._configure = function (element) {
				// @todo: make body of method;
				return element;
			};

			/**
			* The method destroy widget and unbinds event listeners
			* @method _destroy
			* @member ns.widget.mobile.MultimediaView
			* @protected
			* @instance
			*/
			MultimediaViewPrototype._destroy = function () {
				var self = this;
				self._unbindEvents();
			};

			/**
			* Resizing of controlBar
			* @method _resizeControl
			* @member ns.widget.mobile.MultimediaView
			* @protected
			* @instance
			 */
			MultimediaViewPrototype._resizeControl = function () {
				var self = this,
					view = self.element,
					isVideo = self._isVideo,
					wrap = self.ui.wrap,
					control = self.ui.control,
					buttons = slice.call(control.querySelectorAll(selectors.BUTTONS), 0),
					playpauseButton = self.ui.playpauseButton,
					seekBar = self.ui.seekBar,
					durationLabel = self.ui.durationLabel,
					timestampLabel = self.ui.timestampLabel,
					volumeControl = self.ui.volumeControl,
					volumeBar = self.ui.volumeBar,

					width = isVideo ? utilsDOM.getElementWidth(view) : utilsDOM.getElementWidth(wrap),
					offset = utilsDOM.getElementOffset(view),
					buttonWidth,
					availableWidth = 0;

				if (control) {
					if (isVideo) {
						control.style.left = offset.left + 'px';
					}
					control.style.width = width + 'px';
				}

				if (seekBar) {
					buttonWidth = utilsDOM.getElementWidth(buttons[0], 'outer', false, true);
					availableWidth = utilsDOM.getElementWidth(control) - (buttonWidth * buttons.length);
					if (!self.isVolumeHide) {
						availableWidth -= utilsDOM.getElementWidth(volumeControl, 'outer', false, true);
					}
					availableWidth -= utilsDOM.getCSSProperty(seekBar, 'margin-left', 0, "integer");
					seekBar.style.width = availableWidth + 'px';
				}

				if (durationLabel && !isNaN(view.duration)) {
					durationLabel.querySelector(DURATION_LABEL_TAG_NAME).innerHTML = convertTimeFormat(view.duration);
				}

				if (view.autoplay && view.paused === false) {
					playpauseButton.classList.remove(classes.PLAY_ICON);
					playpauseButton.classList.add(classes.PAUSE_ICON);
				}

				if (utilsDOM.getElementWidth(seekBar) < (utilsDOM.getElementWidth(volumeBar) + utilsDOM.getElementWidth(timestampLabel) + utilsDOM.getElementWidth(durationLabel))) {
					durationLabel.classList.add('hidden');
				} else {
					durationLabel.classList.remove('hidden');
				}
			};

			/**
			* Convert time format, from timestamp [s] to string
			* @method convertTimeFormat
			* @member ns.widget.mobile.MultimediaView
			* @param {number} systime
			* @return {string} time time as format HH:mm:ss
			* @private
			* @static
			 */
			function convertTimeFormat(systime) {
				if (!util.isNumber(systime)) {
					return "Playback Error";
				}

				var ss = parseInt(systime % 60, 10).toString(),
					mm = parseInt((systime / 60) % 60, 10).toString(),
					hh = parseInt(systime / 3600, 10).toString(),
					time = ((hh.length < 2) ? "0" + hh : hh) + ":" +
							((mm.length < 2) ? "0" + mm : mm) + ":" +
							((ss.length < 2) ? "0" + ss : ss);

				return time;
			}

			/**
			* Update the position of progress Bar
			* @method _updateSeekBar
			* @member ns.widget.mobile.MultimediaView
			* @protected
			* @instance
			 */
			MultimediaViewPrototype._updateSeekBar = function (currenttime) {
				var self = this,
					view = self.element,
					durationBarWidget = engine.getBinding(self.ui.durationBar),
					duration = view.duration,
					timestampLabel = self.ui.timestampLabel;

				if (currenttime === undefined) {
					currenttime = view.currentTime;
				}
				durationBarWidget.value(currenttime / duration * 100);
				timestampLabel.querySelector(DURATION_LABEL_TAG_NAME).innerHTML = convertTimeFormat(currenttime);
			};

			/**
			* Update the position of Volume Bar eg. after volume change on VIDEO element
			* @method _updateVolumeBarState
			* @member ns.widget.mobile.MultimediaView
			* @protected
			* @instance
			 */
			MultimediaViewPrototype._updateVolumeBarState = function () {
				var self = this,
					volume = engine.getBinding(self.ui.volumeBar);
				volume.element.value = self.element.volume * 100;
				volume.refresh();
			};

			/**
			 * Set volume
			 * @param {number} value
			 */
			MultimediaViewPrototype._setVolume = function (value) {
				if (value >= 0.0 && value <= 1.0) {
					this.element.volume = value;
				}
			};

			/**
			 * Toggle control panel visibility
			 */
			MultimediaViewPrototype._toggleControlPanel = function () {
				var controlStyle = this.ui.control.style;
				controlStyle.opacity = (parseFloat(controlStyle.opacity) | 0) === 0 ? 1.0: 0;
			};

			/**
			 * Called when metadata was loaded
			 * @param {ns.widget.mobile.MultimediaView} self
			 * @static
			 * @private
			 */
			function onLoadedMetadata(self) {
				var options = self.options,
					control = self.ui.control,
					durationLabel = self.ui.durationLabel,
					view = self.element;

				if (!isNaN(view.duration)) {
					durationLabel.querySelector(DURATION_LABEL_TAG_NAME).innerHTML = convertTimeFormat(view.duration);
				}
				// show control bar
				if (options.controls) {
					control.style.opacity = 1.0;
				}
				self._resize();
			}

			function onTimeUpdate(self) {
				var view = self.element;
				self._updateSeekBar();
				if (view.currentTime >= view.duration && !view.loop) {
					view.pause();
				}
			}

			function onPlay(self) {
				var playpauseButtonClassList = self.ui.playpauseButton.classList;
				playpauseButtonClassList.remove(classes.PLAY_ICON);
				playpauseButtonClassList.add(classes.PAUSE_ICON);
			}

			function onPause(self) {
				var playpauseButtonClassList = self.ui.playpauseButton.classList;
				playpauseButtonClassList.remove(classes.PAUSE_ICON);
				playpauseButtonClassList.add(classes.PLAY_ICON);
			}

			function onVolumeChange(self) {
				var view = self.element,
					volumeButtonClassList = self.ui.volumeButton.classList;
				if (view.muted && view.volume > 0.1) {
					volumeButtonClassList.remove(classes.VOLUME_ICON);
					volumeButtonClassList.add(classes.MUTE_ICON);
					self._reserveVolume = view.volume;
					view.volume = 0;
				} else if (self._reserveVolume !== -1 && !view.muted) {
					volumeButtonClassList.remove(classes.MUTE_ICON);
					volumeButtonClassList.add(classes.VOLUME_ICON);
					view.volume = self._reserveVolume;
					self._reserveVolume = -1;
				} else if (view.volume < 0.1) {
					volumeButtonClassList.remove(classes.VOLUME_ICON);
					volumeButtonClassList.add(classes.MUTE_ICON);
				} else {
					volumeButtonClassList.remove(classes.MUTE_ICON);
					volumeButtonClassList.add(classes.VOLUME_ICON);
				}

				self._updateVolumeBarState();
			}

			function onDurationChange(self) {
				var view = self.element,
					durationLabel = self.ui.durationLabel;
				if (!isNaN(view.duration)) {
					durationLabel.querySelector(DURATION_LABEL_TAG_NAME).innerHTML = convertTimeFormat(view.duration);
				}
				self._resize();
			}

			function onViewClick(self) {
				if (!self.options.controls) {
					return;
				}
				self._toggleControlPanel();
				self._resize();
			}

			function onViewInit(self) {
				self._resize();
			}

			function onPlayPauseButtonClick(self) {
				var view = self.element;

				if (view.paused) {
					view.play();
				} else {
					view.pause();
				}
			}

			function onFullScreenButton(self) {
				self.fullScreen(!self.options.fullScreen);
			}

			function onVolumeButtonClick(self) {
				var volumeStyle = self.ui.volumeControl.style;

				if (self.isVolumeHide) {
					self.isVolumeHide = false;
					// @todo: fadeIn
					volumeStyle.display = 'initial';
				} else {
					self.isVolumeHide = true;
					// @todo: fadeOut
					volumeStyle.display = 'none';
				}
				self._resize();
			}

			function onVolumeBarChange(self, event) {
				var volume = engine.getBinding(self.ui.volumeBar);
				self._setVolume(volume.element.value / 100);
			}

			function setViewPositionFromEvent(self, event) {
				var value =  getProgressByPointerEvent(event),
					progressBar = engine.getBinding(self.ui.durationBar);
				progressBar.value(value);
				//clearTimeout(self._changeMediaPositionTimeout);
				//self._changeMediaPositionTimeout = setTimeout(function () {
					setViewPositionByPercent(self, value);
				//}, MEDIA_POSITION_CHANGE_TIMEOUT);
			}

			function setViewPositionByPercent(self, percent) {
				var view = self.element;
				view.currentTime = view.duration * percent / 100;
			}

			function getProgressByPointerEvent(event) {
				var target = event.target;
				return (event.clientX - target.offsetLeft) / target.offsetWidth * 100;
			}
			function onProgressBarMove(self, event) {
				if (self._progressBarPressed) {
					setViewPositionFromEvent(self, event);
				}
			}
			function onProgressBarDown(self, event) {
				self._progressBarPressed = true;
				setViewPositionFromEvent(self, event);
			}
			function onProgressBarUp(self) {
				self._progressBarPressed = false;
			}
			function onButtonDown(button) {
				button.classList.add(classes.BUTTON_DOWN);
			}
			function onButtonUp(button) {
				button.classList.remove(classes.BUTTON_DOWN);
			}

			function onClick(self, event) {
				var view = self.element,
					playpauseButton = self.ui.playpauseButton,
					volumeButton = self.ui.volumeButton,
					fullscreenButton = self.ui.fullscreenButton;

				switch (event.target) {
					case playpauseButton:
						return onPlayPauseButtonClick(self, event);
					case volumeButton:
						return onVolumeButtonClick(self, event);
					case fullscreenButton:
						return onFullScreenButton(self, event);
					case view:
						return onViewClick(self, event);
				}
			}

			function onPointerMove(self, event) {
				var progressBarBackgruond = self.ui.progressBar;

				switch (event.target) {
					case progressBarBackgruond:
						return onProgressBarMove(self, event);
				}
			}
			function onPointerDown(self, event) {
				var progressBarBackgruond = self.ui.progressBar;

				switch (event.target) {
					case progressBarBackgruond:
						return onProgressBarDown(self, event);
					case self.ui.playpauseButton:
					case self.ui.fullscreenButton:
					case self.ui.volumeButton:
						return onButtonDown(event.target);
				}
			}
			function onPointerUp(self, event) {
				var progressBarBackgruond = self.ui.progressBar;

				switch (event.target) {
					case progressBarBackgruond:
						return onProgressBarUp(self, event);
					case self.ui.playpauseButton:
					case self.ui.fullscreenButton:
					case self.ui.volumeButton:
						return onButtonUp(event.target);
				}
			}
			function onChange(self, event) {
				var volumeBar = self.ui.volumeBar;

				switch (event.target) {
					case volumeBar:
						return onVolumeBarChange(self, event);
				}
			}
			function onResize(self, event) {
				switch (event.target) {
					case window:
						return self._resize();
				}
			}

			MultimediaViewPrototype.handleEvent = function (event) {
				var self = this;

				switch (event.type) {
					case 'loadedmetadata':
						return onLoadedMetadata(self, event);
					case 'timeupdate':
						return onTimeUpdate(self, event);
					case 'play':
						return onPlay(self, event);
					case 'pause':
						return onPause(self, event);
					case 'volumechange':
						return onVolumeChange(self, event);
					case 'change':
						return onChange(self, event);
					case 'durationchange':
						return onDurationChange(self, event);
					case POINTER_CLICK_EVENT:
						return onClick(self, event);
					case POINTER_MOVE_EVENT:
						return onPointerMove(self, event);
					case POINTER_DOWN_EVENT:
						return onPointerDown(self, event);
					case POINTER_UP_EVENT:
						return onPointerUp(self, event);
					case 'multimediaviewinit':
						return onViewInit(self, event);
					case 'resize':
						return onResize(self, event);
				}
			};

			/**
			* The method binding event handlers to widget
			* @method _bindEvents
			* @param {HTMLElement} element
			* @member ns.widget.mobile.MultimediaView
			* @protected
			* @instance
			*/
			MultimediaViewPrototype._bindEvents = function (element) {
				var self = this,
					view = self.element,
					control = self.ui.control,
					seekBar = self.ui.seekBar,
					volumeBar = self.ui.volumeBar,
					progressBarBackgruond = self.ui.progressBar;

				events.on(
					view,
					["loadedmetadata", "timeupdate", "play", "pause", "volumechange", "durationchange", POINTER_CLICK_EVENT, "multimediaviewinit"],
					self,
					true
				);
				events.on(
					progressBarBackgruond,
					[POINTER_MOVE_EVENT, POINTER_DOWN_EVENT, POINTER_UP_EVENT],
					self,
					true
				);
				events.on(
					control,
					[POINTER_CLICK_EVENT, POINTER_DOWN_EVENT, POINTER_UP_EVENT],
					self,
					true
				);
				seekBar.addEventListener(POINTER_CLICK_EVENT, self, true);
				volumeBar.addEventListener('change', self, true);
				window.addEventListener('resize', self, true);

				return element;
			};

			/**
			* The method unbinds event listeners
			* @method _unbindEvents
			* @member ns.widget.mobile.MultimediaView
			* @protected
			* @instance
			*/
			MultimediaViewPrototype._unbindEvents = function () {
				var self = this,
					view = self.element,
					control = self.ui.control,
					seekBar = self.ui.seekBar,
					volumeBar = self.ui.volumeBar,
					progressBarBackgruond = self.ui.progressBar;

				events.off(
					view,
					["loadedmetadata", "timeupdate", "play", "pause", "volumechange", "durationchange", POINTER_CLICK_EVENT, "multimediaviewinit"],
					self,
					true
				);
				events.off(
					progressBarBackgruond,
					[POINTER_MOVE_EVENT, POINTER_DOWN_EVENT, POINTER_UP_EVENT],
					self,
					true
				);
				events.off(
					control,
					[POINTER_CLICK_EVENT, POINTER_DOWN_EVENT, POINTER_UP_EVENT],
					self,
					true
				);
				seekBar.removeEventListener(POINTER_CLICK_EVENT, self, true);
				volumeBar.removeEventListener('change', self, true);

				window.addEventListener('resize', self, true);
			};

			MultimediaView.prototype = MultimediaViewPrototype;

			ns.widget.mobile.MultimediaView = MultimediaView;
			engine.defineWidget(
				'MultimediaView',
				// Multimediaview UX used native multimedia UX
				//'video, audio, .ui-multimediaview',
				'ui-multimediaview',
				['width', 'height', 'fullScreen'],
				MultimediaView,
				'tizen'
			);
			}(window, window.document, ns));

/*global window, define */
/*
* Copyright  2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/*jslint nomen: true, plusplus: true */

/* Added to classes:
 *   + ui-tokentextarea display flex
 *   + ui-tokentextarea-input added flex
 *   + ui-tokentextarea-span-block added flex
 *   + ui-tokentextarea-desclabel added padding
 *
 * Delete from class:
 *   + ui-tokentextarea-link-base deleted position
 *
 * Changed classes:
 *   + ui-tokentextarea div to ui-tokentextarea-span-block
 * Added class for hiding element:
 *   + span.ui-tokentextarea-invisible
 *
 * All was made for better responsivity and locations tokens.
 *
 */

/**
 * #TokenTextArea widget
 * The TokenTextArea widget changes a text item to a button. It can be
 * comprised of a number of button widgets. When a user types text and the text
 * gets a specific event to change from a text to a button, the input text is
 * changed to a TokenTextArea widget. A user can add the TokenTextArea widget
 * to a contact list, email list, or another list.
 *
 * The typical use of this
 * widget is composing a number of contacts or phone numbers in a specific area
 * of the screen. The TokenTextArea widget enables the user to enter text and
 * convert it to a button. Each button that is created from entered text as a
 * result of a change event forms a token text area widget. This widget is
 * useful in composing an e-mail or SMS message to a group of addresses,
 * each of which is a clickable item for more actions, such as copying,
 * editing, or removing the address.
 *
 * ##HTML Examples
 * ###Create simple Tokentextarea from div using data-role:
 *
 *		@example
 *			<div data-role="tokentextarea"></div>

 * ###Create simple Tokentextarea from div using class:
 *
 *		@example
 *			<div class="ui-tokentextarea"></div>
 *
 * ##Manual constructor
 * ###For manual creation of progressbar widget you can use constructor
 * of widget:
 *
 *		@example
 *			<div id="ns-tokentextarea"><div>
 *			 <script>
 *				var token = tau.widget.Tokentextarea(
 *					document.getElementById('ns-tokentextarea')
 *				);
 *			</script>
 *
 * If jQuery library is loaded, it's method can be used:
 *
 *		@example
 *			<div id="ns-tokentextarea"><div>
 *			 <script>
 *				$("#ns-tokentextarea").tokentextarea();
 *			</script>
 *
 *	##Options for Tokentextarea Widget
 *
 *	Options for widget can be defined as _data-..._ attributes or give as
 *	parameter in constructor.
 *
 * You can change option for widget using method **option**.
 *
 * ###data-label
 * Label for a user guide
 * Provide custom label for the user guide, for example, while composing
 * an sms message "Send to: " label is a user guide to enter phone number
 * or choose recipient from address book.
 *
 *		@example
 *			<div data-role="tokentextarea" data-label="Send to: "></div>
 *
 * ####data-link
 * Represents the id of the page or the URL of other HTML file.
 * The page contains data for the user, for example, an address book.
 * If the value is null, anchor button doesn't work. (Default : null)
 *
 *		@example
 *			<div data-role="tokentextarea" data-link="bar.html"></div>
 *
 * ###data-description
 * This attribute is managing message format.
 * This message is displayed when widget status was changed to 'focusout'.
 * (Default : '+ {0}')
 *
 *		@example
 *			<div data-role="tokentextarea" data-description="bar + {0}"></div>
 *
 *
 * ##Options for Tokentextarea Widget
 *
 * Options for widget can be get/set .
 *
 * ###You can change option for widget using method **option**.
 * Initialize the widget
 *
 *		@example
 *			<script>
 *				var elementToken = document.getElementById("ns-tokentextarea"),
 *				Tokentextarea = tau.widget.Tokentextarea(elementToken);
 *			</script>
 *
 * ### Custom Label
 * Get or set the label option, after initialization
 *
 *		@example
 *			<script>
 *				//getter
 *				Tokentextarea.option( "label" );
 *
 *				//setter
 *				Tokentextarea.option( "label", "e-mail To:" );
 *			</script>
 *
 * ### Custom Link
 * Get or set the link option, after initialization
 *
 *		@example
 *			<script>
 *				//getter
 *				Tokentextarea.option( "link" );
 *
 *				//setter
 *				Tokentextarea.option( "link", "favorites.html");
 *			</script>
 *
 * ### Custom description
 * Get or set the link option, after initialization
 *
 *		@example
 *			<script>
 *				//getter
 *				Tokentextarea.option( "description" );
 *
 *				//setter
 *				Tokentextarea.option( "description", "bar + {0}");
 *			</script>
 *
 * ##Methods
 *
 * To call method on widget you can use one of existing API:
 *
 * First API is from tau namespace:
 *
 *		@example
 *		var elementToken = document.getElementById("ns-tokentext"),
 *			tokentextarea = tau.widget.Tokentextarea(elementToken);
 *
 *		tokentextarea.methodName(methodArgument1, methodArgument2, ...);
 *
 * Second API is jQuery Mobile API and for call _methodName_ you can use:
 *
 *		@example
 *		$(".selector").tokentextarea("methodName", methodArgument1, ...);
 *
 * @author Kamil Stepczuk <k.stepczuk@samsung.com>
 * @class ns.widget.mobile.TokenTextarea
 * @extends ns.widget.BaseWidget
 */

(function (window, ns) {
	

			/**
			 * BaseWidget alias variable
			 * @property {Object} BaseWidget alias variable
			 * @private
			 * @static
			 */
			var BaseWidget = ns.widget.mobile.BaseWidgetMobile,

				/**
				 * Engine alias variable
				 * @property {ns.engine} engine alias variable
				 * @private
				 * @static
				 * @member ns.widget.mobile.Tokentextarea
				 */
				engine = ns.engine,

				/**
				 * Alias for class ns.selectors
				 * @property {Object} selectors
				 * @private
				 * @static
				 * @member ns.widget.mobile.Tokentextarea
				 */
				selectors = ns.util.selectors,

				/**
				 * Dictionary object containing commonly used widget classes
				 * @property {Object} classes
				 * @static
				 * @private
				 * @readonly
				 * @member ns.widget.mobile.TokenTextarea
				 */
				classes = {
					uiTokentextarea: "ui-tokentextarea",
					uiTokentextareaLabel: "ui-tokentextarea-label",
					uiTokentextareaInput: "ui-tokentextarea-input",
					uiTokentextareaInputVisible:
						"ui-tokentextarea-input-visible",
					uiTokentextareaInputInvisible:
						"ui-tokentextarea-input-invisible",
					uiinputText: "ui-input-text",
					uiBodyS: "ui-body-s",
					uiTokentextareaLinkBase: "ui-tokentextarea-link-base",
					uiBtnBoxS: "ui-btn-box-s",
					uiTokentextareaSblock: "ui-tokentextarea-sblock",
					uiTokentextareaBlock: "ui-tokentextarea-block",
					uiTokentextareaFocusout: "ui-tokentextarea-focusout",
					uiTokentextareaFocusin: "ui-tokentextarea-focusin",
					uiTokentextareaSpanBlock: "ui-tokentextarea-span-block",
					uiTokentextareaInputArea: "ui-tokentextarea-input-area",
					uiTokentextareaDesclabel: "ui-tokentextarea-desclabel",
					uiTokentextareaInvisible: "ui-tokentextarea-invisible"
				},

				/**
				 * Alias to Page.selector from widget definition
				 * @private
				 * @static
				 * @readonly
				 * @member ns.widget.mobile.Tokentextarea
				 */
				pageSelector = engine.getWidgetDefinition("Page").selector,

				/**
				 * Dictionary for keyboard codes
				 * @property {Object} keyCode
				 * @private
				 * @readonly
				 * @static
				 * @member ns.widget.mobile.Tokentextarea
				 */
				keyCode = {
					BACKSPACE: 8,
					ENTER: 13,
					SEMICOLON: 186,
					COMMA: 188
				},

				/**
				 * Local constructor function
				 * @method Tokentextarea
				 * @private
				 * @member ns.widget.mobile.TokenTextarea
				 */
				Tokentextarea = function () {
					/**
					 * Focus state
					 * @property {boolean} [_focusStatus=true]
					 * @member ns.widget.mobile.TokenTextarea
					 */
					this._focusStatus = true;
					/**
					 * Object with default options
					 * @property {Object} options
					 * @property {string} [options.label="To : "] Sets a label
					 * as a guide for the user
					 * @property {string} [link=""] Sets the ID of the page or
					 * the URL of other HTML file
					 * @property {string} [options.description="+ {0}"] Manages
					 * the message format
					 * @member ns.widget.mobile.TokenTextarea
					 */
					this.options = {
						label: "To : ",
						link: "",
						description: "+ {0}"
					};
					/**
					 *
					 * @property {?Function|null} [inputKeyUp=null]
					 * @private
					 * @member ns.widget.mobile.TokenTextarea
					 */
					this.inputKeyUp = null;
				};

			Tokentextarea.prototype = new BaseWidget();

			Tokentextarea.classes = classes;

			Tokentextarea.keyCode = keyCode;

			/**
			 * Object containing commonly used widget strings
			 * @property {Object} strings
			 * @property {string} strings.doubleTapToEdit Is used to set aria
			 * label for token text area button
			 * @property {string} strings.moreDoubleTapToEdit Is used to set
			 * aria label for grouped hidden tokens
			 * @property {string} strings.addRecipient Is used to add text to
			 * the button linked to external page or URL
			 * @static
			 * @member ns.widget.mobile.TokenTextarea
			 */
			Tokentextarea.strings = {
				doubleTapToEdit: "double tap to edit",
				moreDoubleTapToEdit: "more, double tap to edit",
				addRecipient: "Add recipient"
			};

			/**
			 * Function for select block
			 * @method _selectBlock
			 * @param {HTMLElement} block
			 * @private
			 * @static
			 * @member ns.widget.mobile.TokenTextarea
			 */
			function _selectBlock(block) {
				var blockClasses = block.classList;
				blockClasses.add(classes.uiTokentextareaSblock);
				blockClasses.remove(classes.uiTokentextareaBlock);
			}

			/**
			 * Function for unselect block
			 * @method _unselectBlock
			 * @param {HTMLElement} block
			 * @private
			 * @static
			 * @member ns.widget.mobile.TokenTextarea
			 */
			function _unselectBlock(block) {
				var blockClasses = block.classList;
				blockClasses.remove(classes.uiTokentextareaSblock);
				blockClasses.add(classes.uiTokentextareaBlock);
			}

			/**
			 * Function set max width for block element
			 * Function will be deleted when 'overflow: hidden' and
			 * 'text-overflow: ellipsis' will work with percent value max width.
			 * @method setMaxSizeBlock
			 * @param {HTMLElement} element
			 * @private
			 * @static
			 * @member ns.widget.mobile.TokenTextarea
			 */
			function setMaxSizeBlock(element) {
				var parent = element.parentNode,
					maxWidth;
				maxWidth = parent.offsetWidth / 2;
				element.style.maxWidth = maxWidth + "px";
			}

			/**
			 * Function remove text block from widget
			 * @method _removeTextBlock
			 * @param {HTMLElement} element
			 * @param {number} blockIndex
			 * @private
			 * @static
			 * @member ns.widget.mobile.TokenTextarea
			 */
			function _removeTextBlock(element, blockIndex) {
				var blockParent,
					block,
					blockLength,
					i;
				if (arguments.length === 1) {
					element.parentNode.removeChild(element);
				} else {
					block = element.getElementsByClassName(
						classes.uiTokentextareaSpanBlock
					);
					blockLength = block.length;
					if (blockLength === 0) {
						return;
					}
					blockParent = block[0].parentNode;
					if (blockIndex !== null && blockIndex < blockLength) {
						blockParent.removeChild(block[blockIndex]);
					} else {
						for (i = blockLength - 1; i >= 0; i--) {
							blockParent.removeChild(block[i]);
						}
					}
				}
			}

			/**
			 * Handler function for click to block
			 * @method blockClick
			 * @param {Event} event
			 * @private
			 * @static
			 * @member ns.widget.mobile.TokenTextarea
			 */
			function blockClick(event) {
				var element = event.target,
					parent = element.parentNode,
					widget = ns.engine.instanceWidget(parent),
					lockBlock;

				if (widget._focusStatus) {
					if (element.classList.contains(
						classes.uiTokentextareaSblock)) {
						_removeTextBlock(element);
					} else {
						lockBlock = parent.getElementsByClassName(
							classes.uiTokentextareaSblock)[0];
						if (lockBlock !== undefined) {
							_unselectBlock(lockBlock);
						}
						_selectBlock(element);
					}
				} else {
					widget.focusIn();
				}
			}

			/**
			 * Function bind event vclick for block
			 * @method _bindBlockEvents
			 * @param {HTMLElement} block
			 * @private
			 * @static
			 * @member ns.widget.mobile.TokenTextarea
			 */
			function _bindBlockEvents(block) {
				block.addEventListener("vclick", blockClick, false);
			}

			/**
			 * Function add block into widget
			 * @method _addTextBlock
			 * @param {HTMLElement} element
			 * @param {string} messages
			 * @param {number} blockIndex
			 * @private
			 * @static
			 * @member ns.widget.mobile.TokenTextarea
			 */
			function _addTextBlock(element, messages, blockIndex) {
				var strings = Tokentextarea.strings,
					textBlock,
					textBlockClasses,
					input,
					blocks;

				blocks = element.getElementsByClassName(
					classes.uiTokentextareaSpanBlock
				);
				textBlock = document.createElement("div");
				textBlock.textContent = messages;
				textBlockClasses = textBlock.classList;
				textBlockClasses.add(classes.uiTokentextareaBlock);
				textBlockClasses.add(classes.uiTokentextareaSpanBlock);
				textBlock.setAttribute("aria-label", strings.doubleTapToEdit);
				textBlock.tabIndex = 0;
				if (blockIndex !== null && blockIndex < blocks.length) {
					element.insertBefore(textBlock, blocks[blockIndex]);
				} else {
					input = element.childNodes[element.childNodes.length - 1];
					element.insertBefore(textBlock, input);
				}
				setMaxSizeBlock(textBlock);
				_bindBlockEvents(textBlock);
			}

			/**
			 * Changes maximum size each token text block
			 * @method setMaxSizeForAllBlocks
			 * @param {HTMLElement} element
			 * @private
			 * @static
			 * @member ns.widget.mobile.Tokentextarea
			 */
			function setMaxSizeForAllBlocks(element) {
				var blocks = element.getElementsByClassName(
					classes.uiTokentextareaSpanBlock
				),
				blocksLength = blocks.length,
				i;

				for (i = 0; i < blocksLength; i++) {
					setMaxSizeBlock(blocks[i]);
				}
			}

			/**
			 * Function validate last block
			 * @method _validateTargetBlock
			 * @param {HTMLElement} container
			 * @private
			 * @static
			 * @member ns.widget.mobile.TokenTextarea
			 */
			function _validateTargetBlock(container) {
				var block,
					lastBlock,
					lastBlockClasses;


				block = container.getElementsByClassName(
					classes.uiTokentextareaSpanBlock
				);
				lastBlock = block[block.length - 1];
				lastBlockClasses  = lastBlock.classList;

				if (lastBlockClasses.contains(classes.uiTokentextareaSblock)) {
					_removeTextBlock(lastBlock);
				} else {
					_selectBlock(lastBlock);
				}
			}

			/**
			 * Function unselect block in widget
			 * @method _unlockTextBlock
			 * @param {HTMLElement} element
			 * @private
			 * @static
			 * @member ns.widget.mobile.TokenTextarea
			 */
			function _unlockTextBlock(element) {
				var selectedBlock = element.getElementsByClassName(
						classes.uiTokentextareaSblock)[0];
				if (selectedBlock !== undefined) {
					_unselectBlock(selectedBlock);
				}
			}

			/**
			 * Handler function for event keyUp
			 * @method inputKeyUp
			 * @param {HTMLElement} element
			 * @param {Event} event
			 * @private
			 * @static
			 * @member ns.widget.mobile.TokenTextarea
			 */
			function inputKeyUp (element, event) {
				var keyValue = event.keyCode,
					input = element.getElementsByTagName("input")[0],
					inputValue = input.value,
					messages = [],
					messagesLength,
					i;

				if (keyValue === keyCode.BACKSPACE) {
					if (inputValue.length === 0) {
						_validateTargetBlock(element);
					}
				} else if (keyValue === keyCode.ENTER ||
					keyValue === keyCode.SEMICOLON ||
					keyValue === keyCode.COMMA) {
					if (inputValue.length !== 0) {
						messages = inputValue.split(/[,;]/);
						messagesLength = messages.length;
						for (i = 0; i < messagesLength; i++) {
							messages[i] = messages[i].trim();
							if (messages[i].length !== 0) {
								_addTextBlock(element, messages[i]);
							}
						}
					}
					input.value = "";
				} else {
					_unlockTextBlock(element);
				}
			}

			/**
			 * Build widget structure
			 * @method _build
			 * @protected
			 * @param {HTMLElement} element
			 * @return {HTMLElement}
			 * @member ns.widget.mobile.TokenTextarea
			 */
			Tokentextarea.prototype._build = function (element) {
				var strings = Tokentextarea.strings,
					option = this.options,
					moreBlockClasses,
					inputBox,
					inputBoxClasses,
					inputArea,
					labelTag,
					moreBlock;

				inputBox = document.createElement("input");
				labelTag = document.createElement("span");
				moreBlock = document.createElement("a");
				inputArea = document.createElement("div");

				inputBoxClasses = inputBox.classList;

				inputArea.classList.add(classes.uiTokentextareaInputArea);
				element.classList.add(classes.uiTokentextarea);

				inputBox.style.minWidth = 3 + "rem";
				inputBox.style.width    = 100 +"%";

				labelTag.textContent = option.label;
				labelTag.classList.add(classes.uiTokentextareaLabel);
				labelTag.tabIndex = 0;
				element.appendChild(labelTag);


				inputBoxClasses.add(classes.uiTokentextareaInput);
				inputBoxClasses.add(classes.uiTokentextareaInputVisible);
				inputBoxClasses.add(classes.uiinputText);
				inputBoxClasses.add(classes.uiBodyS);

				inputBox.setAttribute("role", "textbox");
				inputArea.appendChild(inputBox);
				engine.instanceWidget(moreBlock, "Button", {
					inline: true,
					icon: "plus",
					style: "circle"
				});

				moreBlockClasses = moreBlock.classList;

				moreBlock.href = option.link;
				moreBlock.tabIndex = 0;
				moreBlockClasses.add(classes.uiTokentextareaLinkBase);
				moreBlockClasses.add(classes.uiBtnBoxS);
				moreBlock.firstChild.firstChild.textContent =
					strings.addRecipient;
				inputArea.appendChild(moreBlock);
				element.appendChild(inputArea);
				return element;
			};

			/**
			 * Method add block
			 *
			 * Method adds new token text widget button with specified text
			 * in place of the index. If index isn't set the token will
			 * be inserted at the end.
			 *
			 *		@example
			 *			<div data-role="tokentextarea" id="ns-tokentext"></div>
			 *			<script>
			 *				var tokenWidget = tau.widget.Tokentextarea(
			 *						document.getElementById("ns-tokentext")
			 *				);
			 *				tokenWidget.add("foobar");
			 *
			 *				//or
			 *
			 *				$( "#ns-tokentext" ).tokentextarea("add", "foobar");
			 *			</script>
			 *
			 * @method add
			 * @param {string} messages
			 * @param {number} blockIndex
			 * @member ns.widget.mobile.TokenTextarea
			 */
			Tokentextarea.prototype.add = function (messages, blockIndex) {
				var focusStatus = this._focusStatus,
					element = this.element;
				if (focusStatus) {
					_addTextBlock(element, messages, blockIndex);
				}
			};

			/**
			 * Method delete token; delete all tokens without parameter
			 *
			 * The remove method is used to remove a token text area widget
			 * button at the specified index position. If the parameter
			 * is not defined, all the widget buttons are removed.
			 *
			 *		@example
			 *			<div 	data-role="tokentextarea"
			 *					data-label="Send to: "
			 *					id="ns-tokentext">
			 *			</div>
			 *			<script>
			 *				var tokenWidget = tau.widget.Tokentextarea(
			 *						document.getElementById("ns-tokentext")
			 *				);
			 *				tokenWidget.remove(1);
			 *
			 *				//or
			 *
			 *				$( "#ns-tokentext" ).tokentextarea("remove", "1" );
			 *			</script>
			 *
			 * @method remove
			 * @param {number} blockIndex
			 * @member ns.widget.mobile.TokenTextarea
			 */
			Tokentextarea.prototype.remove = function (blockIndex) {
				var focusStatus = this._focusStatus,
					element = this.element;
				if (focusStatus) {
					_removeTextBlock(element, blockIndex);
				}
			};

			/**
			 * Function return blocks count
			 *
			 * The length method is used to retrieve the number of buttons
			 * in the token text area widget:
			 *
			 *		@example
			 *			<div data-role="tokentextarea" id="ns-tokentext"></div>
			 *			<script>
			 *				var tokenWidget = tau.widget.Tokentextarea(
			 *						document.getElementById("ns-tokentext")
			 *				);
			 *				tokenWidget.lenght();
			 *
			 *				//if jQuery is loaded
			 *
			 *				$( "#ns-tokentext" ).tokentextarea( "length" );
			 *			</script>
			 *
			 * @method length
			 * @return {number}
			 * @member ns.widget.mobile.TokenTextarea
			 */
			Tokentextarea.prototype.length = function () {
				var element = this.element;
				return element.getElementsByClassName(
					classes.uiTokentextareaSpanBlock).length;
			};

			/**
			 * Method is used to manage the widget input box text.
			 *
			 * If no parameter is set, the method gets the input box text.
			 * If a parameter is set, the parameter text is set in
			 * the input box.
			 *
			 *		@example
			 *			<div data-role="tokentextarea" id="ns-tokentext"></div>
			 *			<script>
			 *				// !!!set text in the input box text!!!
			 *
			 *				var tokenWidget = tau.widget.Tokentextarea(
			 *						document.getElementById("ns-tokentext")
			 *				);
			 *				tokenWidget.inputText("foobar");
			 *
			 *				//if jQuery is loaded
			 *
			 *				$( "#ns-tokentext" ).tokentextarea(
			 *					"inputText" , "foobar");
			 *
			 *				// !!!get the input box text!!!
			 *
			 *				var tokenWidget = tau.widget.Tokentextarea(
			 *						document.getElementById("ns-tokentext")
			 *				);
			 *				tokenWidget.inputText();
			 *
			 *				//if jQuery is loaded
			 *
			 *				$( "#ns-tokentext" ).tokentextarea( "inputText" );
			 *			</script>
			 *
			 * @method inputText
			 * @param {string} text
			 * @return {string}
			 * @member ns.widget.mobile.TokenTextarea
			 */
			Tokentextarea.prototype.inputText = function (text) {
				var element = this.element,
					input = element.getElementsByTagName("input")[0];

				if (text !== undefined) {
					input.value = text;
				}
				return input.value;
			};

			/**
			 * The select method is used to select token text area button on its
			 * index value
			 * If a parameter is set, token text area button will be select
			 * the block which is matched with the argument.
			 * If some token text area button is selected and parameter isn't
			 * set method returns string of the selected button.
			 * If none is selected return null
			 *
			 *		@example
			 *			<div data-role="tokentextarea" id="ns-tokentext"></div>
			 *			<script>
			 *				// !!!select first block!!!
			 *
			 *				var tokenWidget = tau.widget.Tokentextarea(
			 *						document.getElementById("ns-tokentext")
			 *				);
			 *				tokenWidget.add("text 1");
			 *				tokenWidget.add("text 2");
			 *				tokenWidget.select(0);
			 *
			 *				//if jQuery is loaded
			 *
			 *				$( "#ns-tokentext" ).tokentextarea("select" , "0");
			 *
			 *				// !!!gets string from selected block!!!
			 *
			 *				tokenWidget.select();
			 *
			 *				//if jQuery is loaded
			 *
			 *				$( "#ns-tokentext" ).tokentextarea( "select" );
			 *			</script>
			 *
			 * @method select
			 * @param {number} blockIndex
			 * @return {?string}
			 * @public
			 * @member ns.widget.mobile.TokenTextarea
			 */
			Tokentextarea.prototype.select = function (blockIndex) {
				var focusStatus = this._focusStatus,
					element = this.element,
					block,
					sBlock;

				if (focusStatus) {
					block = element.getElementsByClassName(
						classes.uiTokentextareaSpanBlock);
					sBlock = element.getElementsByClassName(
						classes.uiTokentextareaSblock);

					if (blockIndex !== undefined && blockIndex < block.length) {
						if (sBlock.length === 1) {
							_unselectBlock(sBlock[0]);
						}
						_selectBlock(block[blockIndex]);
					} else if (block.length !== 0) {
						if (sBlock[0]) {
							return sBlock[0].textContent;
						}
					}
				}
				return null;
			};

			/**
			 * Function ungroup elements and set focus to input
			 *
			 *		@example
			 *			<div 	data-role="tokentextarea"
			 *					data-label="Send to: "
			 *					id="ns-tokentext">
			 *			</div>
			 *			<script>
			 *				var tokenWidget = tau.widget.Tokentextarea(
			 *						document.getElementById("ns-tokentext")
			 *				);
			 *				tokenWidget.focusIn(0);
			 *
			 *				//if jQuery is loaded
			 *
			 *				$( "#ns-tokentext" ).tokentextarea( "focusIn" );
			 *			</script>
			 *
			 * @method focusIn
			 * @public
			 * @member ns.widget.mobile.TokenTextarea
			 */
			Tokentextarea.prototype.focusIn = function () {
				var element = this.element,
					elementClasses,
					label,
					sBlock,
					sBlockClasses,
					input,
					inputClasses,
					button,
					hiddenBlocksCount,
					hiddenBlocks,
					hiddenBlocksLength,
					i;

				if (this._focusStatus) {
					return;
				}

				label = element.getElementsByClassName(
					classes.uiTokentextareaLabel)[0];
				hiddenBlocksCount = element.getElementsByClassName(
					classes.uiTokentextareaDesclabel)[0];
				if (hiddenBlocksCount) {
					element.removeChild(hiddenBlocksCount);
					hiddenBlocks = element.getElementsByClassName(
						classes.uiTokentextareaInvisible);
					hiddenBlocksLength = hiddenBlocks.length;
					for (i = hiddenBlocksLength - 1; i >= 0; i--) {
						hiddenBlocks[i].classList
							.remove(classes.uiTokentextareaInvisible);
					}
				}

				input = element.getElementsByTagName("input")[0];
				inputClasses = input.classList;
				button = element.getElementsByTagName("a")[0];
				elementClasses = element.classList;

				label.tabIndex = 0;
				label.style.display = "";


				sBlock = element
					.getElementsByClassName(classes.uiTokentextareaSblock)[0];
				if (sBlock !== undefined) {
					sBlockClasses = sBlock.classList;
					sBlockClasses.remove(classes.uiTokentextareaSblock);
					sBlockClasses.add(classes.uiTokentextareaBlock);
				}
				inputClasses.remove(classes.uiTokentextareaInputInvisible);
				inputClasses.add(classes.uiTokentextareaInputVisible);
				input.tabIndex = 0;
				button.tabIndex = 0;
				button.style.display = "";

				// change focus state.
				this._focusStatus = true;
				elementClasses.remove(classes.uiTokentextareaFocusout);
				elementClasses.add(classes.uiTokentextareaFocusin);
				element.removeAttribute("tabindex");
				input.focus();
			};

			/**
			 * function get width of element with margins
			 * @method _getElementWidth
			 * @param {HTMLElement} element
			 * @return {number}
			 * @private
			 * @static
			 * @member ns.widget.mobile.TokenTextarea
			 */
			function _getElementWidth(element) {
				var elementView;
				elementView =  document.defaultView
					.getComputedStyle(element);
				return parseInt(
					elementView.getPropertyValue("margin-left"), 10) +
					parseInt(elementView.getPropertyValue("margin-right"), 10) +
					element.offsetWidth;
			}

			/**
			 * Function group elements and hide input
			 *
			 *		@example
			 *			<div 	data-role="tokentextarea"
			 *					data-label="Send to: "
			 *					id="ns-tokentext">
			 *			</div>
			 *			<script>
			 *				var tokenWidget = tau.widget.Tokentextarea(
			 *						document.getElementById("ns-tokentext")
			 *				);
			 *				tokenWidget.focusOut(0);
			 *
			 *				//if jQuery is loaded
			 *
			 *				$( "#ns-tokentext" ).tokentextarea( "focusOut" );
			 *			</script>
			 *
			 * @method focusOut
			 * @public
			 * @member ns.widget.mobile.TokenTextarea
			 */
			Tokentextarea.prototype.focusOut = function () {
				var element = this.element,
					strings = Tokentextarea.strings,
					description = this.options.description,
					elementClasses,
					elementWidth,
					blockWidthSum = 0,
					label,
					input,
					inputClasses,
					button,
					blocks,
					blocksLenght,
					hiddenBlocksCount = 0,
					descLabel,
					descLabel1stChild,
					descLabel2ndChild,
					i;

				if (!this._focusStatus) {
					return;
				}

				blocks = element.getElementsByClassName(
					classes.uiTokentextareaSpanBlock
				);
				blocksLenght =  blocks.length;
				label = element
					.getElementsByClassName(classes.uiTokentextareaLabel)[0];
				input = element.getElementsByTagName("input")[0];
				inputClasses = input.classList;
				button = element.getElementsByTagName("a")[0];

				label.removeAttribute("tabindex");
				inputClasses.remove(classes.uiTokentextareaInputVisible);
				inputClasses.add(classes.uiTokentextareaInputInvisible);
				input.removeAttribute("tabindex");
				button.removeAttribute("tabindex");
				button.style.display = "none";

				elementWidth = element.offsetWidth;
				blockWidthSum += _getElementWidth(label);
				for (i = 0; i <=  blocksLenght - 1; i++) {
					blockWidthSum += _getElementWidth(blocks[i]);
					if (blockWidthSum >= elementWidth) {
						hiddenBlocksCount++;
						blocks[i].classList
							.add(classes.uiTokentextareaInvisible);
					}
				}

				this._focusStatus = false;
				elementClasses = element.classList;
				elementClasses.remove(classes.uiTokentextareaFocusin);
				elementClasses.add(classes.uiTokentextareaFocusout);
				element.tabIndex = 0;

				if (hiddenBlocksCount !== 0) {
					descLabel = document.createElement("div");
					descLabel1stChild = document.createElement("div");
					descLabel2ndChild = document.createElement("div");

					descLabel.classList.add(classes.uiTokentextareaDesclabel);
					descLabel.setAttribute("aria-label",
						strings.moreDoubleTapToEdit);
					descLabel.tabIndex = -1;

					descLabel1stChild.setAttribute("aria-hidden", "true");
					descLabel1stChild.textContent = description
						.replace("{0}", hiddenBlocksCount);

					descLabel2ndChild.setAttribute("aria-label", "and");
					descLabel2ndChild.style.visibility = "hidden";
					descLabel2ndChild.textContent = hiddenBlocksCount;

					descLabel.appendChild(descLabel1stChild);
					descLabel.appendChild(descLabel2ndChild);
					element.insertBefore(descLabel, input.parentNode);
				}
			};

			/**
			 * Bind widget events
			 * @method _bindEvents
			 * @param {HTMLElement} element
			 * @protected
			 * @member ns.widget.mobile.TokenTextarea
			 */
			Tokentextarea.prototype._bindEvents = function (element) {
				var self = this,
					parentPage = selectors.getClosestBySelector(
						element, pageSelector);

				self.inputKeyUp = inputKeyUp.bind(null, element);
				element.getElementsByTagName("input")[0]
					.addEventListener("keyup", self.inputKeyUp, false);
				self._setMaxSizeForAllBlocksBound =
					setMaxSizeForAllBlocks.bind(null, element);
				parentPage.addEventListener(
					"pageshow", self._setMaxSizeForAllBlocksBound , false);
			};

			/**
			 * Destroy widget
			 * @method _destroy
			 * @protected
			 * @member ns.widget.mobile.TokenTextarea
			 */
			Tokentextarea.prototype._destroy = function () {
				var element = this.element,
					elementCilds,
					elementCildsLength,
					input,
					block,
					blockLength,
					parentPage = selectors.getClosestBySelector(
						element, pageSelector),
					i;

				input = element.getElementsByTagName("input")[0];
				block = element.getElementsByClassName(
					classes.uiTokentextareaSpanBlock
				);
				blockLength = block.length;
				for (i = blockLength - 1; i >= 0; i--) {
					block[i].removeEventListener("vclick", blockClick, false);
				}
				input.removeEventListener("keyup", this.inputKeyUp, false);
				parentPage.removeEventListener("pageshow",
					this._setMaxSizeForAllBlocksBound, false);
				elementCilds = element.childNodes;
				elementCildsLength = elementCilds.length;
				for (i =  elementCildsLength - 1; i >= 0; i--) {
					element.removeChild(elementCilds[i]);
				}
				element.classList.remove(classes.uiTokentextarea);
				element.removeAttribute("data-ns-built");
				element.removeAttribute("data-ns-binding");
				element.removeAttribute("data-ns-name");
				element.removeAttribute("data-ns-selector");
				element.removeAttribute("aria-disabled");
				element.removeAttribute("data-ns-bound");
			};

			/**
			 * The function "value" is not supported in this widget.
			 *
			 * @method value
			 * @chainable
			 * @member ns.widget.mobile.TokenTextarea
			 */

			/**
			 * Disable the Tokentextarea
			 *
			 * Method adds disabled attribute on Tokentextarea widget and
			 * changes look to disabled state.
			 *
			 *		@example
			 *		<div data-role="tokentexarea" id="ns-tokentex"></div>
			 *
			 *		<script>
			 *			var elementToken = tau.widget.Tokentextarea(
			 *					document.getElementById("ns-tokentext")
			 *				);
			 *			elementToken.disable();
			 *		</script>
			 *
			 * If jQuery is loaded:
			 *
			 *		@example
			 *		<div data-role="tokentextarea" id="ns-tokentext"></div>
			 *
			 *		<script>
			 *			$("#ns-tokentext").tokentextarea("disable");
			 *		</script>
			 *
			 * @method disable
			 * @chainable
			 * @member ns.widget.mobile.TokenTextarea
			 */

			/**
			 * Enable the Tokentextarea
			 *
			 * Method removes disabled attribute on Tokentextarea widget and
			 * changes look to enabled state.
			 *
			 *		@example
			 *		<div data-role="tokentextarea" id="ns-tokentext"></div>
			 *
			 *		<script>
			 *			var elementToken = tau.widget.Tokentextarea(
			 *					document.getElementById("ns-tokentext")
			 *				);
			 *			elementToken.enable();
			 *		</script>
			 *
			 * If jQuery is loaded:
			 *
			 *		@example
			 *		<div data-role="tokentextarea" id="ns-tokentext"></div>
			 *
			 *		<script>
			 *			$("#ns-tokentext").tokentextarea("enable");
			 *		</script>
			 *
			 * @method enable
			 * @chainable
			 * @member ns.widget.mobile.TokenTextarea
			 */

			/**
			 * Trigger an event on widget's element.
			 *
			 *		@example
			 *		<div data-role="tokentextarea" id="ns-tokentext"></div>
			 *
			 *		<script>
			 *			var elementToken = tau.widget.Tokentextarea(
			 *					document.getElementById("ns-tokentext")
			 *				);
			 *			elementToken.trigger("eventName");
			 *		</script>
			 *
			 * If jQuery is loaded:
			 *
			 *		@example
			 *		<div data-role="tokentextarea" id="ns-tokentext"></div>
			 *
			 *		<script>
			 *			$("#ns-tokentext").tokentextarea("trigger", "eventName");
			 *		</script>
			 *
			 * @method trigger
			 * @param {string} eventName the name of event to trigger
			 * @param {?*} [data] additional object to be carried with the event
			 * @param {boolean} [bubbles=true] indicating whether the event
			 * bubbles up through the DOM or not
			 * @param {boolean} [cancelable=true] indicating whether the event
			 * is cancelable
			 * @return {boolean} false, if any callback invoked preventDefault
			 * on event object
			 * @member ns.widget.mobile.TokenTextarea
			 */

			/**
			 * Add event listener to widget's element.
			 *
			 *		@example
			 *		<div data-role="tokentextarea" id="ns-tokentext"></div>
			 *
			 *		<script>
			 *			var elementToken = tau.widget.Tokentextarea(
			 *					document.getElementById("ns-tokentext")
			 *				);
			 *			elementToken.on("eventName", function () {
			 *				console.log("Event fires");
			 *			});
			 *		</script>
			 *
			 * If jQuery is loaded:
			 *
			 *		@example
			 *		<div data-role="tokentextarea" id="ns-tokentext"></div>
			 *
			 *		<script>
			 *			$("#ns-tokentext").tokentextarea("on", "eventName",
			 *				function () { console.log("Event fires");
			 *			});
			 *		</script>
			 *
			 * @method on
			 * @param {string} eventName the name of event
			 * @param {Function} listener function call after event will be
			 * trigger
			 * @param {boolean} [useCapture=false] useCapture param tu
			 * addEventListener
			 * @member ns.widget.mobile.TokenTextarea
			 */

			/**
			 * Remove event listener to widget's element.
			 *
			 *		@example
			 *		<div data-role="tokentextarea" id="ns-tokentext"></div>
			 *
			 *		<script>
			 *			var elementToken = tau.widget.Tokentextarea(
			 *					document.getElementById("ns-tokentext")
			 *				),
			 *				callback = function () {
			 *					console.log("Event fires");
			 *				};
			 *			// add callback on event "eventName"
			 *			elementToken.on("eventName", callback);
			 *			// ...
			 *			// remove callback on event "eventName"
			 *			elementToken.off("eventName", callback);
			 *		</script>
			 *
			 * If jQuery is loaded:
			 *
			 *		@example
			 *		<div data-role="tokentextarea" id="ns-tokentext"></div>
			 *
			 *		<script>
			 *			var callback = function () {
			 *					console.log("Event fires");
			 *				};
			 *			// add callback on event "eventName"
			 *			$("#ns-tokentext").tokentextarea(
			 *				"on", "eventName", callback);
			 *			// ...
			 *			// remove callback on event "eventName"
			 *			$("#ns-tokentext").tokentextarea(
			 *				"off", "eventName", callback);
			 *		</script>
			 *
			 * @method off
			 * @param {string} eventName the name of event
			 * @param {Function} listener function call after event will be
			 * trigger
			 * @param {boolean} [useCapture=false] useCapture param to
			 * addEventListener
			 * @member ns.widget.mobile.TokenTextarea
			 */

			/**
			 * Get/Set options of the widget.
			 *
			 * This method can work in many context.
			 *
			 * If first argument is type of object them, method set values for
			 * options given in object. Keys of object are names of options and
			 * values from object are values to set.
			 *
			 * If you give only one string argument then method return value
			 * for given option.
			 *
			 * If you give two arguments and first argument will be a string
			 * then second argument will be intemperate as value to set.
			 *
			 *		@example
			 *		<div data-role="tokentextarea" id="ns-tokentext"></div>
			 *
			 * 			<script>
			 *				var tokenWidet = tau.widget.Tokentextarea(
			 *				document.getElementById("ns-tokentext")),
			 *					tokenValue;
			 *
			 * 				 //getter
			 *				tokentValue = tokenWidget.option("label");
			 *
			 *				//setter
			 *				tokenWidget.option("label","e-mail to: ");
			 *			</script>
			 *
			 * If jQuery is loaded:
			 *
			 *		@example
			 *			<div data-role="tokentextarea" id="ns-tokentext"></div>
			 *			<script>
			 *				var tokenValue;
			 *
			 * 				// get value
			 *				tokentValue = $("#ns-tokentext").tokentextarea(
			 *					"option", "label");
			 *
			 *				// set value
			 *				$("#ns-tokentext").tokentextarea(
			 *					"option", "label", "e-mail to: "
			 *				);
			 *			</script>
			 *
			 * @method option
			 * @param {string|Object} [name] name of option
			 * @param {*} value value to set
			 * @member ns.widget.mobile.TokenTextarea
			 * @return {*} return value of option or undefined if method is
			 * called in setter context
			 */
			// definition
			ns.widget.mobile.TokenTextarea = Tokentextarea;
			engine.defineWidget(
				"TokenTextarea",
				"[data-role='tokentextarea'], .ui-tokentextarea",
				[
					"add",
					"remove",
					"length",
					"inputText",
					"select",
					"focusIn",
					"focusOut"
				],
				Tokentextarea,
				"tizen"
			);

}(window.document, ns));

/*global window, define, ns */
/*
* Copyright  2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/*jslint nomen: true, plusplus: true */
/**
 * #Notification widget
 * The Notification widget shows a popup on the screen to provide notifications.
 *
 * ##Default selectors
 * In all elements with _data-role=notification_ or with _ui-notification_ CSS class. Use _p_ tag for messages and _img_ tag for icon.
 *
 * ##Manual constructor
 * For manual creation of notification widget you can use constructor of widget:
 *
 *		@example
 *		<!-- Widget structure -->
 *		<div data-role="notification" id="notification" data-type="smallpopup">
 *			<p>Line of message</p>
 *		</div>
 *		<script>
 *			var notification = tau.widget.Notification(document.getElementById("notification"));
 *		</script>
 *
 * If jQuery library is loaded, this method can be used:
 *
 *		@example
 *		<!-- Widget structure -->
 *		<div data-role="notification" id="notification" data-type="smallpopup">
 *			<p>Line of message</p>
 *		</div>
 *		<script>
 *			var notification = $("#notification").notification();
 *		</script>
 *
 * ##HTML Examples
 *
 * ###Create notification smallpopup
 * Smallpopup has only one line of message and is positioned to the bottom of the active page. It's default type of notification widget.
 *
 * Running example in pure JavaScript:
 *
 *		@example
 *		<!-- Widget structure -->
 *		<div data-role="notification" id="notification" data-type="smallpopup">
 *			<p>Line of message</p>
 *		</div>
 *		<script>
 *			// Get widget instance or create new instance if widget not exists.
 *			var notification = tau.widget.Notification(document.getElementById("notification"));
 *			// Open notification
 *			notification.open();
 *		</script>
 *
 * If jQuery library is loaded, this method can be used:
 *
 *		@example
 *		<!-- Widget structure -->
 *		<div data-role="notification" id="notification" data-type="smallpopup">
 *			<p>Line of message</p>
 *		</div>
 *		<script>
 *			// Open widget using jQuery notation
 *			$( "#notification" ).notification( "open" )
 *		</script>
 *
 * ###Create notification ticker
 * Notification ticker has maximum two lines of message, other messages will be hidden. Additionally you can set an icon. Notification ticker is default positioned to the top of the page.
 *
 * Running example in pure JavaScript:
 *
 *		@example
 *		<div data-role="notification" id="notification" data-type="ticker">
 *			<p>First line of message</p>
 *			<p>Second line of message</p>
 *		</div>
 *		<script>
 *			// Get widget instance or create new instance if widget not exists.
 *			var notification = tau.widget.Notification(document.getElementById("notification"));
 *			// Open notification
 *			notification.open();
 *		</script>
 *
 * If jQuery library is loaded, this method can be used:
 *
 *		@example
 *		<div data-role="notification" id="notification" data-type="ticker">
 *			<p>First line of message</p>
 *			<p>Second line of message</p>
 *		</div>
 *		<script>
 *			// Open widget using jQuery notation
 *			$( "#notification" ).notification( "open" )
 *		</script>
 *
 * ###Create notification wih interval
 * Interval defines time to showing notification widget, after this it will close automatically. Values of _data-interval_ is a positive **number of miliseconds**, e.g. _data-interval="2000"_ (sets to close widget after 2 seconds). Otherwise widget will show infinietely.
 *
 * Running example in pure JavaScript:
 *
 *		@example
 *		<div data-role="notification" id="notification" data-type="ticker" data-interval="4000">
 *			<img src="icon.png">
 *			<p>I will close in 4* seconds!</p>
 *			<p>* starts counting from widget opening</p>
 *		</div>
 *		<script>
 *			// Get widget instance or create new instance if widget not exists.
 *			var notification = tau.widget.Notification(document.getElementById("notification"));
 *			// Open notification
 *			notification.open();
 *		</script>
 *
 * If jQuery library is loaded, this method can be used:
 *
 *		@example
 *		<div data-role="notification" id="notification" data-type="ticker" data-interval="4000">
 *			<img src="icon.png">
 *			<p>I will close in 4* seconds!</p>
 *			<p>* starts counting from widget opening</p>
 *		</div>
 *		<script>
 *			// Open widget using jQuery notation
 *			$( "#notification" ).notification( "open" )
 *		</script>
 *
 * ###Create notification ticker with icon
 * !!!Icon is only supported with notification ticker.!!!
 *
 * Running example in pure JavaScript:
 *
 *		@example
 *		<div data-role="notification" id="notification" data-type="ticker">
 *			<img src="icon.png">
 *			<p>First line of message</p>
 *			<p>Second line of message</p>
 *		</div>
 *		<script>
 *			// Open notification
 *			notification.open();
 *		</script>
 *
 * If jQuery library is loaded, this method can be used:
 *
 *		@example
 *		<div data-role="notification" id="notification" data-type="ticker">
 *			<img src="icon.png">
 *			<p>First line of message</p>
 *			<p>Second line of message</p>
 *		</div>
 *		<script>
 *			// Open widget using jQuery notation
 *			$( "#notification" ).notification( "open" )
 *		</script>
 *
 * @class ns.widget.mobile.Notification
 * @extends ns.widget.mobile.BaseWidgetMobile
 */
(function (document, ns) {
	
				/**
			 * {Object} Widget Alias for {@link ns.widget.mobile.BaseWidgetMobile}
			 * @member ns.widget.mobile.Notification
			 * @private
			 */
			var BaseWidget = ns.widget.mobile.BaseWidgetMobile,
				/**
				 * {Object} Widget Alias for {@link ns.widget.mobile.Page}
				 * @member ns.widget.Notification
				 * @private
				 */
				Page = ns.widget.mobile.Page,
				/**
				 * @property {Object} engine Alias for class ns.engine
				 * @member ns.widget.mobile.Notification
				 * @private
				 */
				engine = ns.engine,
				/**
				 * @property {Object} selectors Alias for class ns.selectors
				 * @member ns.widget.mobile.Notification
				 * @private
				 */
				selectors = ns.util.selectors,
				doms = ns.util.DOM,
				/**
				 * @property {Object} themes Alias for class ns.theme
				 * @member ns.widget.mobile.Notification
				 * @private
				 */
				themes = ns.theme,

				/**
				 * Alias for class ns.widget.mobile.Notification
				 * @method Notification
				 * @member ns.widget.mobile.Notification
				 * @private
				 */
				Notification = function () {

					/**
					 * @property {boolean} _eventsAdded Flag that the widget was binded with events
					 * @member ns.widget.mobile.Notification
					 * @private
					 */
					this._eventsAdded = false;

					/**
					 * @property {Object} _ui Holds all needed UI HTMLElements
					 * @member ns.widget.mobile.Notification
					 * @protected
					 */
					this._ui = {
						/**
						 * @property {HTMLElement} _ui.wrapper Widgets content wrapper
						 * @member ns.widget.mobile.Notification
						 * @protected
						 */
						wrapper: null,

						/**
						 * @property {NodeList} _ui.iconImg Widgets icons
						 * @member ns.widget.mobile.Notification
						 * @protected
						 */
						iconImg: null,

						/**
						 * @property {NodeList} _ui.texts Widgets texts
						 * @member ns.widget.mobile.Notification
						 * @protected
						 */
						texts: []
					};

					/**
					 * @property {number} interval Widgets interval
					 * @member ns.widget.mobile.Notification
					 * @protected
					 */
					this.interval = null;

					/**
					 * @property {boolean} running Widget running status
					 * @member ns.widget.mobile.Notification
					 * @protected
					 */
					this.running = false;

					/**
					 * Widget options
					 * @property {Object} options
					 * @property {string} [options.theme="s"] theme Theme of widget
					 * @property {"smallpopup"|"ticker"} [options.type="smallpopup"] type of widget. Allowed types: <b>smallpopup</b> or <b>ticker</b>.
					 * @property {number} [interval=0] interval value in milliseconds of widget. 0 - show widget infinitely
					 * @member ns.widget.mobile.Notification
					 * @protected
					 */
					this.options = {
						theme: "s",
						type: "smallpopup",
						interval: 0
					};
				};

			Notification.prototype = new BaseWidget();

			/**
			 * Dictionary for notification related css class names
			 * @property {Object} classes
			 * @member ns.widget.mobile.Notification
			 * @static
			 */
			Notification.classes = {
				uiTicker : "ui-ticker",
				uiTickerText1Bg : "ui-ticker-text1-bg",
				uiTickerText2Bg : "ui-ticker-text2-bg",
				uiTickerIcon : "ui-ticker-icon",
				uiSmallpopup : "ui-smallpopup",
				uiSmallpopupTextBg : "ui-smallpopup-text-bg",
				uiTickerBtn : "ui-ticker-btn",
				uiNotificationFix: "fix",
				uiNotificationShow: "show",
				uiNotificationHide: "hide"
			};

			/**
			 * Build structure of notification widget
			 * @method _build
			 * @param {HTMLElement} element
			 * @return {HTMLElement}
			 * @protected
			 * @member ns.widget.mobile.Notification
			 */
			Notification.prototype._build = function (element) {
				var wrapperTag = "div",
					textTag = "p",
					options = this.options,
					classes = Notification.classes,
					uiElements = this._ui,
					notifyBtnWrapper,
					notifyWrapper,
					closeButton,
					nodeList,
					texts,
					i,
					l;

				//Set theme
				options.theme = themes.getInheritedTheme(element) || options.theme;

				//Wrap it!
				notifyWrapper = document.createElement(wrapperTag);
				uiElements.wrapper = notifyWrapper;

				nodeList = element.childNodes;
				while (nodeList.length > 0) {
					notifyWrapper.appendChild(nodeList[0]);
				}

				//Get texts
				texts = notifyWrapper.getElementsByTagName(textTag);

				//Add elements if is lower than 2
				l = texts.length;
				for (i = l; i < 2; i++) {
					notifyWrapper.appendChild(document.createElement(textTag));
				}

				//Hide not visible elements
				l = texts.length; //Update length
				for (i = 2; i < l; i++) {
					texts[i].style.display = "none";
				}

				if (options.type === "ticker") {
					//Create elements
					notifyBtnWrapper = document.createElement(wrapperTag);
					closeButton = document.createElement(wrapperTag);

					//Create skeleton
					notifyBtnWrapper.appendChild(closeButton);
					notifyWrapper.appendChild(notifyBtnWrapper);

					//Add classes
					notifyWrapper.className = classes.uiTicker;
					notifyBtnWrapper.className = classes.uiTickerBtn;

					//Instance Button widget
					closeButton.textContent = "Close";
					engine.instanceWidget(closeButton, "Button", {
						theme: options.theme,
						inline: true
					});

					//Add clases to elements
					texts[0].classList.add(classes.uiTickerText1Bg);
					texts[1].classList.add(classes.uiTickerText2Bg);

				} else {
					//Add classes
					notifyWrapper.className = classes.uiSmallpopup;

					//Add classes to element and hide second element
					texts[0].classList.add(classes.uiSmallpopupTextBg);
					texts[1].style.display = "none";
				}
				element.appendChild(notifyWrapper);
				uiElements.texts = texts;
				return element;
			};

			/**
			 * Init widget
			 * @method _init
			 * @param {HTMLElement} element
			 * @protected
			 * @member ns.widget.mobile.Notification
			 */
			Notification.prototype._init = function (element) {
				var options = this.options,
					classes = Notification.classes,
					uiElements = this._ui,
					iconImg,
					iconImgLength,
					wrapper,
					i;

				//Set widget wrapper
				uiElements.wrapper = element.firstElementChild;
				wrapper = uiElements.wrapper;

				//Set theme
				options.theme = themes.getInheritedTheme(element) || options.theme;

				//Set texts
				uiElements.texts[0] = wrapper.getElementsByClassName(classes.uiTickerText1Bg)[0];
				uiElements.texts[1] = wrapper.getElementsByClassName(classes.uiTickerText2Bg)[0];

				//Get icons
				iconImg = element.getElementsByTagName("img");
				iconImgLength = iconImg.length;
				for (i = 0; i < iconImgLength; i++) {
					iconImg[i].classList.add(classes.uiTickerIcon);
					//Hide unused icons
					if (i > 1) {
						iconImg[i].style.display = "none";
					}
				}
				uiElements.iconImg = iconImg;

				//fix for compare tests
				this.type = options.type;
			};

			/**
			 * Bind events to widget
			 * @method _bindEvents
			 * @param {HTMLElement} element
			 * @protected
			 * @member ns.widget.mobile.Notification
			 */
			Notification.prototype._bindEvents = function (element) {
				if (!this._eventsAdded) {
					// Is it needed, that closeButton should has click event binded with self.close() too?
					element.addEventListener("vmouseup", this.close.bind(this), true);
					this._eventsAdded = true;
				}
			};

			/**
			 * Enable to show notification on screen. This method removes __display: none__ style from notification element.
			 *
			 * #####Running example in pure JavaScript:
			 *
			 *	@example
			 *	<!-- Widget structure -->
			 *	<div data-role="notification" id="notification" data-type="smallpopup">
			 *		<p>Line of message</p>
			 *	</div>
			 *
			 *	<script>
			 *		// Get widget instance or create new instance if widget not exists.
			 *		var notification = tau.widget.Notification(document.getElementById("notification"));
			 *
			 *		// Make it enabled
			 *		notification.enable();
			 *	</script>
			 *
			 * #####If jQuery library is loaded, this method can be used:
			 *
			 *	@example
			 *	<!-- Widget structure -->
			 *	<div data-role="notification" id="notification" data-type="smallpopup">
			 *		<p>Line of message</p>
			 *	</div>
			 *
			 *	<script>
			 *		// Make it enabled
			 *		$( "#notification" ).notification( "enable" );
			 *	</script>
			 *
			 * @method enable
			 * @member ns.widget.mobile.Notification
			 */

			/**
			 * @method _enable
			 * @protected
			 * @member ns.widget.mobile.Notification
			 */
			Notification.prototype._enable = function () {
				this._ui.wrapper.style.display = "";
			};

			/**
			 * Disable notification. This method adds display:none style to notification element.
			 *
			 * #####Running example in pure JavaScript:
			 *
			 *	@example
			 *	<!-- Widget structure -->
			 *	<div data-role="notification" id="notification" data-type="smallpopup">
			 *		<p>Line of message</p>
			 *	</div>
			 *
			 *	<script>
			 *		// Get widget instance or create new instance if widget not exists.
			 *		var notification = tau.widget.Notification(document.getElementById("notification"));
			 *
			 *		// Make it disabled
			 *		notification.disable();
			 *	</script>
			 *
			 *
			 * #####If jQuery library is loaded, this method can be used:
			 *
			 *	@example
			 *	<!-- Widget structure -->
			 *	<div data-role="notification" id="notification" data-type="smallpopup">
			 *		<p>Line of message</p>
			 *	</div>
			 *
			 *	<script>
			 *		// Make it disabled
			 *		$( "#notification" ).notification( "disable" );
			 *	</script>
			 *
			 * @method disable
			 * @member ns.widget.mobile.Notification
			 *
			 */

			/**
			 * @method _disable
			 * @protected
			 * @member ns.widget.mobile.Notification
			 */
			Notification.prototype._disable = function () {
				this._ui.wrapper.style.display = "none";
			};

			/**
			 * Refresh a notification widget and resets interval if it was set before.
			 *
			 * #####Running example in pure JavaScript:
			 *
			 *	@example
			 *	<div data-role="notification" id="notificationSelector" data-type="smallpopup">
			 *		<p>Line of message</p>
			 *	</div>
			 *	<script>
			 *		var notification = tau.widget.Notification(document.getElementById("notificationSelector"));
			 *		notification.refresh();
			 *	</script>
			 *
			 * #####If jQuery library is loaded, this method can be used:
			 *
			 *	@example
			 *	<div data-role="notification" id="notificationSelector" data-type="smallpopup">
			 *		<p>Line of message</p>
			 *	</div>
			 *	<script>
			 *		$("#notificationSelector").notification("refresh");
			 *	</script>
			 *
			 * @method refresh
			 * @chainable
			 * @member ns.widget.mobile.Notification
			 */

			/**
			 * Refresh notification
			 * @method _refresh
			 * @protected
			 * @member ns.widget.mobile.Notification
			 */
			Notification.prototype._refresh = function () {
				var wrapperClassList = this._ui.wrapper.classList,
					classes = Notification.classes;
				wrapperClassList.add(classes.uiNotificationFix);
				wrapperClassList.remove(classes.uiNotificationHide);
				wrapperClassList.remove(classes.uiNotificationShow);
				this._setCloseInterval();
			};

			/**
			 * Set widget position.
			 * @method _positionWidget
			 * @protected
			 * @member ns.widget.mobile.Notification
			 */
			Notification.prototype._positionWidget = function () {
				var pages = document.body.getElementsByClassName(Page.classes.uiPageActive),
					footers,
					footerHeight = 0,
					pageWidth = 0,
					wrapper = this._ui.wrapper,
					wrapperStyle = wrapper.style,
					wrapperWidth = 0;

				if (typeof pages[0] === "object") {
					footers = selectors.getChildrenByClass(pages[0], "ui-footer");
					pageWidth = pages[0].offsetWidth;
					if (typeof footers[0] === "object") {
						footerHeight = footers[0].offsetHeight;
					}
				}
				wrapperWidth = doms.getCSSProperty(wrapper, "width", 0, "float") + doms.getCSSProperty(wrapper, "padding-left", 0, "float") + doms.getCSSProperty(wrapper, "padding-right", 0, "float");
				wrapperStyle.left = (pageWidth - wrapperWidth)/2 + "px";
				wrapperStyle.bottom = footerHeight + (footerHeight > 0 ? "px" : "");
			};

			/**
			 * Open widget to show notification.
			 *
			 * #####Running example in pure JavaScript:
			 *
			 *	@example
			 *	<div data-role="notification" id="notificationSelector" data-type="smallpopup">
			 *		<p>Line of message</p>
			 *	</div>
			 *	<script>
			 *		var notification = tau.widget.Notification(document.getElementById("notificationSelector"));
			 *		notification.open();
			 *	</script>
			 *
			 * #####If jQuery library is loaded, this method can be used:
			 *
			 *	@example
			 *	<div data-role="notification" id="notificationSelector" data-type="smallpopup">
			 *		<p>Line of message</p>
			 *	</div>
			 *	<script>
			 *		$("#notificationSelector").notification("open");
			 *	</script>
			 *
			 * @method open
			 * @member ns.widget.mobile.Notification
			 */
			Notification.prototype.open = function () {
				var wrapperClassList = this._ui.wrapper.classList,
					classes = Notification.classes;

				if (this.running === true) {
					this.refresh();
					return;
				}
				wrapperClassList.add(classes.uiNotificationShow);
				wrapperClassList.remove(classes.uiNotificationHide);
				wrapperClassList.remove(classes.uiNotificationFix);

				if (this.options.type !== "ticker") {
					this._positionWidget();
				}

				this._setCloseInterval();
				this.running = true;
			};

			/**
			 * Close opened widget to hide notification.
			 *
			 * #####Running example in pure JavaScript:
			 *
			 *	@example
			 *	<div data-role="notification" id="notificationSelector" data-type="ticker">
			 *		<p>Line of message</p>
			 *	</div>
			 *	<script>
			 *		var notification = tau.widget.Notification(document.getElementById("notificationSelector"));
			 *		notification.close();
			 *	</script>
			 *
			 * #####If jQuery library is loaded, this method can be used:
			 *
			 *	@example
			 *	<div data-role="notification" id="notificationSelector" data-type="ticker">
			 *		<p>Line of message</p>
			 *	</div>
			 *	<script>
			 *		// or using jQuery
			 *		$("#notificationSelector").notification("close");
			 *	</script>
			 *
			 * @method close
			 * @member ns.widget.mobile.Notification
			 */
			Notification.prototype.close = function () {
				var wrapperClassList = this._ui.wrapper.classList,
					classes = Notification.classes;

				if (this.running !== true) {
					return;
				}

				wrapperClassList.add(classes.uiNotificationHide);
				wrapperClassList.remove(classes.uiNotificationShow);
				wrapperClassList.remove(classes.uiNotificationFix);
				clearInterval(this.interval);
				this.running = false;
			};

			/**
			 * Creates icon or changes existing icon to new one. This method resets CSS classes on image element.
			 *
			 * #####Running example in pure JavaScript:
			 *
			 *	@example
			 *	<div data-role="notification" id="notificationSelector" data-type="smallpopup">
			 *		<p>Line of message</p>
			 *	</div>
			 *	<script>
			 *		var notification = tau.widget.Notification(document.getElementById("notificationSelector"));
			 *		notification.icon("some-image.png");
			 *
			 *		// or using jQuery
			 *		$( "#notificationSelector" ).notification( "icon", "some-image.png" );
			 *	</script>
			 *
			 * #####If jQuery library is loaded, this method can be used:
			 *
			 *	@example
			 *	<div data-role="notification" id="notificationSelector" data-type="smallpopup">
			 *		<p>Line of message</p>
			 *	</div>
			 *	<script>
			 *		$( "#notificationSelector" ).notification( "icon", "some-image.png" );
			 *	</script>
			 *
			 * @method icon
			 * @param {string} src icon source URL
			 * @member ns.widget.mobile.Notification
			 */
			Notification.prototype.icon = function (src) {
				var uiElements = this._ui,
					iconImg = uiElements.iconImg,
					classes = Notification.classes;

				if (src) {
					//Remove all elements from NodeList
					while (iconImg.length > 0 && iconImg[0].remove) {
						iconImg[0].remove();
					}

					iconImg[0] = document.createElement("img");
					iconImg[0].className = classes.uiTickerIcon;
					iconImg[0].setAttribute("src", src);

					//Append icon
					uiElements.wrapper.appendChild(iconImg[0]);
					uiElements.iconImg = iconImg;
				}
			};

			/**
			 * Set widget texts. If no text is given, method returns notification text as an array.
			 *
			 * Getting current text of notification
			 *
			 * #####Running example in pure JavaScript:
			 *
			 *	@example
			 *	<div data-role="notification" id="notificationSelector" data-type="ticker">
			 *		<p>Line of message</p>
			 *		<p>Second line of message</p>
			 *	</div>
			 *	<script>
			 *		var notification = tau.widget.Notification(document.getElementById("notificationSelector")),
			 *			widgetText;
			 *		widgetText = notification.text();
			 *
			 *		alert(widgetText);
			 *		// will alert "Line of message,Second line of message"
			 *	</script>
			 *
			 * #####If jQuery library is loaded, this method can be used:
			 *
			 *	@example
			 *	<div data-role="notification" id="notificationSelector" data-type="ticker">
			 *		<p>Line of message</p>
			 *		<p>Second line of message</p>
			 *	</div>
			 *	<script>
			 *		var widgetText;
			 *
			 *		// or using jQuery
			 *		widgetText = $("#notificationSelector").notification("text");
			 *
			 *		alert(widgetText);
			 *		// will alert "Line of message,Second line of message"
			 *	</script>
			 *
			 * Setting text of notification.
			 *
			 * #####Running example in pure JavaScript:
			 *
			 *	@example
			 *	<div data-role="notification" id="notificationSelector" data-type="ticker">
			 *		<p>Line of message</p>
			 *		<p>Second line of message</p>
			 *	</div>
			 *	<script>
			 *		var notification = tau.widget.Notification(document.getElementById("notificationSelector"));
			 *
			 *		notification.text("This is a new Notification!", "This is an example");
			 *	</script>
			 *
			 * #####If jQuery library is loaded, this method can be used:
			 *
			 *	@example
			 *	<div data-role="notification" id="notificationSelector" data-type="ticker">
			 *		<p>Line of message</p>
			 *	</div>
			 *	<script>
			 *		$( "#notificationSelector" ).notification( "text", "This is new Notification!", "This is an example" );
			 *	</script>
			 *
			 * @method text
			 * @param {string} text0 first line of text
			 * @param {string} text1 second line of text
			 * @member ns.widget.mobile.Notification
			 * @return {?Array} widget text if no param given
			 */
			Notification.prototype.text = function (text0, text1) {

				if (text0 === undefined && text1 === undefined) {
					return this._getText();
				}

				this._setText(text0, text1);
				return null;
			};

			/**
			 * Set widgets texts
			 * @method _setText
			 * @param {string} text0 first line of text
			 * @param {string} text1 second line of text
			 * @private
			 * @member ns.widget.mobile.Notification
			 */
			Notification.prototype._setText = function (text0, text1) {
				if (text0 !== undefined) {
					this._ui.texts[0].textContent = text0;
				}
				if (text1 !== undefined) {
					this._ui.texts[1].textContent = text1;
				}
			};

			/**
			 * Get widget texts
			 * @method _getText
			 * @protected
			 * @member ns.widget.mobile.Notification
			 * @return {Array} widget texts
			 */
			Notification.prototype._getText = function () {
				var ui = this._ui,
					texts = [null, null];

				if (this.options.type === "ticker") {
					texts[0] = ui.texts[0] && ui.texts[0].textContent;
					texts[1] = ui.texts[1] && ui.texts[1].textContent;
				} else {
					texts[0] = ui.texts[0] && ui.texts[0].textContent;
				}

				return texts;
			};

			/**
			 * Sets interval
			 * @method _setCloseInterval
			 * @protected
			 * @member ns.widget.mobile.Notification
			 */
			Notification.prototype._setCloseInterval = function () {
				//Clear current interval
				clearInterval(this.interval);

				if (this.options.interval > 0) {
					//Create new interval
					this.interval = setInterval(this.close.bind(this), this.options.interval);
				}
			};

			/**
			 * Removes notification.
			 * This will return the element back to its pre-init state.
			 *
			 * #####Running example in pure JavaScript:
			 *
			 *	@example
			 *	<script>
			 *		var notification = tau.widget.Notification(document.getElementById("notificationSelector")),
			 *		notification.destroy();
			 *	</script>
			 *
			 * #####If jQuery library is loaded, this method can be used:
			 *
			 *	@example
			 *	<script>
			 *		$( "#notificationSelector" ).notification( "destroy" );
			 *	</script>
			 *
			 * @method destroy
			 * @member ns.widget.mobile.Notification
			 */

			/**
			 * Destroy widget
			 * @method _destroy
			 * @param {?HTMLElement} element Base element for destroy widget
			 * @protected
			 * @member ns.widget.mobile.Notification
			 */
			Notification.prototype._destroy = function (element) {
				var wrapper = this._ui.wrapper,
					nodeList;
				if (element) {
					wrapper = element.firstChild;
				} else {
					element = this.element;
				}
				nodeList = wrapper.childNodes;
				while (nodeList.length > 0) {
					element.appendChild(nodeList[0]);
				}
				element.removeChild(wrapper);
			};

			// definition
			ns.widget.mobile.Notification = Notification;
			engine.defineWidget(
				"Notification",
				"[data-role='notification'], .ui-notification",
				["open", "close", "icon", "text"],
				Notification,
				"tizen"
			);
			}(window.document, ns));

/*global window, define */
/*
* Copyright  2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/*jslint nomen: true, plusplus: true */
/**
 * #Gallery Widget
 * The gallery widget shows images in a gallery on the screen.
 *
 * ##Default selectors
 * In default all elements with _data-role="gallery"_ or class _.ui-gallery_ are changed to gallery widget.
 *
 * @class ns.widget.mobile.Gallery
 * @extends ns.widget.BaseWidget
 */
(function (document, ns) {
	
				/**
			 * Alias for {@link ns.widget.BaseWidget}
			 * @property {Function} BaseWidget
			 * @member ns.widget.mobile.Gallery
			 * @private
			 */
			var BaseWidget = ns.widget.mobile.BaseWidgetMobile,
				/**
				 * Alias for class {@link ns.engine}
				 * @property {Object} engine
				 * @member ns.widget.mobile.Gallery
				 * @private
				 */
				engine = ns.engine,
				/**
				 * Alias for class {@link ns.util.selectors}
				 * @property {Object} selectors
				 * @member ns.widget.mobile.Gallery
				 * @private
				 */
				selectors = ns.util.selectors,
				/**
				 * Alias for class {@link ns.util.DOM}
				 * @property {Object} doms
				 * @member ns.widget.mobile.Gallery
				 * @private
				 */
				doms = ns.util.DOM,

				Gallery = function () {
					var self = this;

					/**
					 * Object with default options
					 * @property {Object} options All possible widget options
					 * @property {boolean} [options.flicking=false] This property
					 * enables swinging of the first and the last images.
					 * @property {number} [options.duration=500] This property
					 * determines how long the animation of switching images will run.
					 * @property {"top"|"middle"|"bottom"} [options.verticalAlign="top"]
					 * This property sets the vertical alignment of a widget.
					 * The alignment options are top, middle, and bottom.
					 * @property {number} [options.index=0] This property defines
					 * the index number of the first image in the gallery.
					 * @member ns.widget.mobile.Gallery
					 */
					self.options = {
						flicking: false,
						duration: 500,
						verticalAlign: "top",
						index: 0
					};

					self.dragging = false;
					self.moving = false;
					self.maxImageWidth = 0;
					self.maxImageHeight = 0;
					self.orgX = 0;
					self.orgTime = null;
					self.currentImage = null;
					self.previousImage = null;
					self.nextImage = null;
					self.images = [];
					self.imagesHold = [];
					self.direction = 1;
					self.container = null;

					// events' handlers
					self.pageShowHandler = null;
					self.throttledresizeHandler = null;
					self.vmousemoveHandler = null;
					self.vmousedownHandler = null;
					self.vmouseupHandler = null;
					self.vmouseoutHandler = null;
					self.orientationEventFire = false;
				};

			Gallery.prototype = new BaseWidget();

			/**
			 * This method returns the height of element.
			 * @method getHeight
			 * @param {HTMLElement} element Element of widget
			 * @return {number} Height of element
			 * @private
			 * @static
			 * @member ns.widget.mobile.Gallery
			 */
			function getHeight(element) {
				var page = selectors.getClosestBySelectorNS(element, "role=page"),
					content = selectors.getAllByDataNS(element, "role=content"),
					header = selectors.getAllByDataNS(page, "role=header"),
					footer = selectors.getAllByDataNS(page, "role=footer"),
					headerHeight = header.length ? doms.getElementHeight(header[0]) : 0,
					footerHeight = footer.length ? doms.getElementHeight(footer[0]) : 0,
					paddings = doms.getCSSProperty(content, "padding-top", 0, "integer") + doms.getCSSProperty(content, "padding-bottom", 0, "integer"),
					contentHeight = window.innerHeight - headerHeight - footerHeight - paddings;

				return contentHeight;
			}

			/**
			 * This method resizes the image.
			 * @method resizeImage
			 * @param {HTMLElement} image Element of image
			 * @param {number} maxHeight Maximum value of height
			 * @param {number} maxWidth Maximum value of width
			 * @private
			 * @static
			 * @member ns.widget.mobile.Gallery
			 */
			function resizeImage(image, maxHeight, maxWidth) {
				var width = image.clientWidth,
					height = image.clientHeight,
					ratio = height / width,
					imageStyle = image.style;

				if (maxWidth === 0 && isNaN(maxHeight)) {
					/*
					* Exception : When image max width and height has incorrect value.
					* This exception is occured when this.maxImageWidth value is 0 and this.maxImageHeight value is NaN when page transition like rotation.
					* This exception affect that image width and height values are 0.
					*/
					imageStyle.width = width;
					imageStyle.height = width * ratio;
				} else {
					if (width > maxWidth) {
						imageStyle.width = maxWidth + "px";
						imageStyle.height = maxWidth * ratio + "px";
					}
					height = image.clientHeight;
					if (height > maxHeight) {
						imageStyle.height = maxHeight + "px";
						imageStyle.width = maxHeight / ratio + "px";
					}
				}
			}

			/**
			 * This method resizes the image and its container.
			 * @method setTranslatePosition
			 * @param {HTMLElement} imageContainer Container of image
			 * @param {number} value The abscissa of the translating vector
			 * @private
			 * @static
			 * @member ns.widget.mobile.Gallery
			 */
			function setTranslatePosition(imageContainer, value) {
				var translate = "translate3d(" + value + ", 0px, 0px)",
					style = imageContainer.style;

				style.webkitTransform = translate;
				style.OTransform = translate;
				style.MozTransform = translate;
				style.transform = translate;

				return imageContainer;
			}

			/**
			 * This method is used as the listener for event "vmousemove".
			 * @method vmousemoveEvent
			 * @param {ns.widget.mobile.Gallery} self Widget
			 * @param {Event} event Event
			 * @private
			 * @static
			 * @member ns.widget.mobile.Gallery
			 */
			function vmousemoveEvent(self, event) {
				event.preventDefault();
				if (self.moving || !self.dragging) {
					event.stopPropagation();
					return;
				}
				self._drag(event.pageX);
			}

			/**
			 * This method is used as the listener for event "vmousedown".
			 * @method vmousedownEvent
			 * @param {ns.widget.mobile.Gallery} self Widget
			 * @param {Event} event Event
			 * @private
			 * @static
			 * @member ns.widget.mobile.Gallery
			 */
			function vmousedownEvent(self, event) {
				event.preventDefault();
				if (self.moving) {
					event.stopPropagation();
					return;
				}
				self.dragging = true;
				self.orgX = event.pageX;
				self.orgTime = Date.now();
			}

			/**
			 * This method is used as the listener for event "vmouseup".
			 * @method vmouseupEvent
			 * @param {ns.widget.mobile.Gallery} self Widget
			 * @param {Event} event Event
			 * @private
			 * @static
			 * @member ns.widget.mobile.Gallery
			 */
			function vmouseupEvent(self, event) {
				if (self.moving) {
					event.stopPropagation();
					return;
				}
				self.dragging = false;
				self._move(event.pageX);
			}

			/**
			 * This method is used as the listener for event "vmouseout".
			 * @method vmouseoutEvent
			 * @param {ns.widget.mobile.Gallery} self Widget
			 * @param {Event} event Event
			 * @private
			 * @static
			 * @member ns.widget.mobile.Gallery
			 */
			function vmouseoutEvent(self, event) {
				if (self.moving || !self.dragging) {
					return;
				}
				if ((event.pageX < 20) || (event.pageX > (self.maxImageWidth - 20))) {
					self._move(event.pageX);
					self.dragging = false;
				}
			}

			/**
			 * This method resizes the image and its container.
			 * @method loading
			 * @param {ns.widget.mobile.Gallery} self Widget
			 * @param {number} index Index of shown image
			 * @param {HTMLElement} container Container of image
			 * @private
			 * @static
			 * @member ns.widget.mobile.Gallery
			 */
			function loading(self, index, container) {
				var loadFunction = loading.bind(null, self, index, container);
				if (self.images[index] === undefined) {
					return;
				}
				if (!self.images[index].clientHeight) {
					setTimeout(loadFunction, 10);
					return;
				}
				resizeImage(self.images[index], self.maxImageHeight, self.maxImageWidth);
				self._align(index, container);
			}

			//function hideImage(image) {
			//	if (image) {
			//		image.style.visibility = "hidden";
			//	}
			//}

			/**
			 * Dictionary for gallery related css class names
			 * @property {Object} classes
			 * @member ns.widget.mobile.Gallery
			 * @static
			 * @readonly
			 */
			Gallery.classes = {
				uiGallery: "ui-gallery",
				uiGalleryContainer: "ui-gallery-container",
				uiGalleryBg: "ui-gallery-bg",
				uiContent: "ui-content",
				uiHeader: "ui-header",
				uiFooter: "ui-footer",
			};

			/**
			* Configure gallery widget
			* @method _configure
			* @protected
			* @member ns.widget.mobile.Gallery
			*/
			Gallery.prototype._configure = function () {
				var options = this.options;

				options.flicking = false;
				options.duration = 500;
				options.verticalAlign = "top";
				options.index = 0;
			};

			/**
			 * This method detaches all images from the containers.
			 * @method _detachAll
			 * @param {NodeList} images Images hold by widget
			 * @protected
			 * @member ns.widget.mobile.Gallery
			 */
			Gallery.prototype._detachAll = function (images) {
				var i = 0,
					length = images.length,
					image;
				while (i < length) {
					image = images[0];
					this.images[i] = image.parentNode.removeChild(image);
					i = i + 1;
				}
			};

			/**
			 * This method detaches the image from the container.
			 * @method _detach
			 * @param {number} index Index of widget
			 * @param {HTMLElement} container Container of image
			 * @protected
			 * @member ns.widget.mobile.Gallery
			 */
			Gallery.prototype._detach = function (index, container) {
				var images = this.images,
					image = images[index];
				if (container && index >= 0 && index < images.length && image.parentNode) {
					container.style.display = "none";
					images[index] = image.parentNode.removeChild(image);
				}
			};

			/**
			* Build structure of gallery widget
			* @method _build
			* @param {HTMLElement} element
			* @return {HTMLElement}
			* @protected
			* @member ns.widget.mobile.Gallery
			*/
			Gallery.prototype._build = function (element) {
				var classes = Gallery.classes,
					options = this.options,
					images,
					image,
					index,
					i,
					length;

				element.classList.add(classes.uiGallery);
				images = selectors.getChildrenByTag(element, "img");
				for (i = 0, length = images.length; i < length; i++) {
					image = images[i];
					doms.wrapInHTML(image, "<div class='" + classes.uiGalleryBg + "'></div>");
				}
				if (element.children.length) {
					doms.wrapInHTML(element.children, "<div class='" + classes.uiGalleryContainer + "'></div>");
				} else {
					element.innerHTML = "<div class='" + classes.uiGalleryContainer + "'></div>";
				}
				index = parseInt(options.index, 10);
				if (!index) {
					index = 0;
				}
				if (index < 0) {
					index = 0;
				}
				if (index >= length) {
					index = length - 1;
				}

				this.index = index;

				return element;
			};

			/**
			* Init widget
			* @method _init
			* @param {HTMLElement} element
			* @protected
			* @member ns.widget.mobile.Gallery
			*/
			Gallery.prototype._init = function (element) {
				var images = element.getElementsByTagName("img"),
					classes = Gallery.classes;
				this.container = selectors.getChildrenByClass(element, classes.uiGalleryContainer)[0];
				this._detachAll(images);

				// for "compare" test
				this.max_width = this.maxImageWidth;
				this.max_height = this.maxImageHeight;
				this.org_x = this.orgX;
				this.org_time = this.orgTime;
				this.prev_img = this.previousImage;
				this.cur_img = this.currentImage;
				this.next_img = this.nextImage;
				this.images_hold = this.imagesHold;
			};

			/**
			* Bind events to widget
			* @method _bindEvents
			* @param {HTMLElement} element
			* @protected
			* @member ns.widget.mobile.Gallery
			*/
			Gallery.prototype._bindEvents = function (element) {
				//todo
				//galleryorientationchanged

				var container = this.container,
					page = selectors.getClosestBySelectorNS(element, "role=page");

				this.vmousemoveHandler = vmousemoveEvent.bind(null, this);
				this.vmousedownHandler = vmousedownEvent.bind(null, this);
				this.vmouseupHandler =  vmouseupEvent.bind(null, this);
				this.vmouseoutHandler = vmouseoutEvent.bind(null, this);
				this.pageShowHandler = this.show.bind(this);
				this.throttledresizeHandler = this.refresh.bind(this);

				window.addEventListener("throttledresize", this.throttledresizeHandler, false);
				page.addEventListener("pageshow", this.pageShowHandler, false);

				container.addEventListener("vmousemove", this.vmousemoveHandler, false);
				container.addEventListener("vmousedown", this.vmousedownHandler, false);
				container.addEventListener("vmouseup", this.vmouseupHandler, false);
				container.addEventListener("vmouseout", this.vmouseoutHandler, false);
			};

			/**
			 * This method sets the value of CSS "top" property for container.
			 * @method _align
			 * @param {number} index Index of widget
			 * @param {HTMLElement} container Container of image
			 * @protected
			 * @member ns.widget.mobile.Gallery
			 */
			Gallery.prototype._align = function (index, container) {
				var image = this.images[index],
					imageTop = 0,
					align = this.options.verticalAlign;

				if (container) {
					if (align === "middle") {
						imageTop = (this.maxImageHeight - image.clientHeight) / 2;
					} else if (align === "bottom") {
						imageTop = this.maxImageHeight - image.clientHeight;
					} else {
						imageTop = 0;
					}
					container.style.top = imageTop + "px";
				}
			};

			/**
			 * This method sets the transformation of widget.
			 * @method _moveLeft
			 * @param {HTMLElement} imageContainer Container of image
			 * @param {string} value The abscissa of the translating vector
			 * @param {number} duration Duration of the animation
			 * @return {HTMLElement} Container of image
			 * @protected
			 * @member ns.widget.mobile.Gallery
			 */
			Gallery.prototype._moveLeft = function (imageContainer, value, duration) {
				var transition = "";

				if (imageContainer) {
					if (duration !== undefined) {
						transition =  "-webkit-transform " + (duration / 1000) + "s ease";
						imageContainer.style.webkitTransition = transition;
					}
					imageContainer = setTranslatePosition(imageContainer, value);
				}
				return imageContainer;
			};

			/**
			 * This method attaches image to container.
			 * @method _attach
			 * @param {number} index Index of shown image
			 * @param {HTMLElement} container Container of image
			 * @protected
			 * @member ns.widget.mobile.Gallery
			 */
			Gallery.prototype._attach = function (index, container) {
				if (container && index >= 0 && this.images.length && index < this.images.length) {
					container.style.display = "block";
					container.appendChild(this.images[index]);
					loading(this, index, container);
				}
			};

			/**
			 * The show method is used to display the gallery.
			 * This method is called on event "pageshow" and during refreshing.
			 *
			 *      @example
			 *      var galleryWidget = tau.widget.Gallery(document.getElementById("gallery"));
			 *
			 *      galleryWidget.show();
			 *
			 *      // or
			 *
			 *      $( "#gallery" ).gallery( "show" );
			 *
			 * @method show
			 * @member ns.widget.mobile.Gallery
			 */
			Gallery.prototype.show = function () {
				var classes = Gallery.classes,
					index = this.index,
					element = this.element,
					previousImage,
					nextImage,
					currentImage;
				/* resizing */

				if (this.images.length) {
					this.windowWidth = window.innerWidth;
					this.maxImageWidth = element.clientWidth;
					this.maxImageHeight = getHeight(element);
					this.container.style.height = this.maxImageHeight + "px";

					currentImage = this.currentImage = element.getElementsByClassName(classes.uiGalleryBg)[index];
					previousImage = this.previousImage = currentImage.previousSibling;
					nextImage = this.nextImage = currentImage.nextSibling;

					this._attach(index - 1, previousImage);
					this._attach(index, currentImage);
					this._attach(index + 1, nextImage);

					if (previousImage) {
						setTranslatePosition(previousImage, -this.windowWidth + "px");
					}

					this._moveLeft(currentImage, "0px");
					if (nextImage) {
						setTranslatePosition(nextImage, this.windowWidth + "px");
					}
				}
			};

			/**
			 * This method calculates the new position of gallery during moving.
			 * It is called on event vmousemove.
			 * @method _drag
			 * @param {number} x Position relative to the left edge of the document
			 * @protected
			 * @member ns.widget.mobile.Gallery
			 */
			Gallery.prototype._drag = function (x) {
				var delta,
					coordX,
					previousImage = this.previousImage,
					nextImage = this.nextImage,
					windowWidth = this.windowWidth;

				if (this.dragging) {
					if (this.options.flicking === false) {
						delta = this.orgX - x;

						// first image
						if (delta < 0 && !previousImage) {
							return;
						}
						// last image
						if (delta > 0 && !nextImage) {
							return;
						}
					}

					coordX = x - this.orgX;

					this._moveLeft(this.currentImage, coordX + "px");
					if (nextImage) {
						this._moveLeft(nextImage, coordX + windowWidth + "px");
					}
					if (previousImage) {
						this._moveLeft(previousImage, coordX - windowWidth + "px");
					}
				}
			};

			/**
			 * This method calculates the new position of gallery during moving.
			 * It is called on event vmouseup.
			 * @method _move
			 * @param {number} x Position relative to the left edge of the document
			 * @protected
			 * @member ns.widget.mobile.Gallery
			 */
			Gallery.prototype._move = function (x) {
				var delta = this.orgX - x,
					flip = 0,
					dragTime,
					sec,
					self,
					previousImage = this.previousImage,
					nextImage = this.nextImage;

				if (delta !== 0) {
					if (delta > 0) {
						flip = delta < (this.maxImageWidth * 0.45) ? 0 : 1;
					} else {
						flip = -delta < (this.maxImageWidth * 0.45) ? 0 : 1;
					}

					if (!flip) {
						dragTime = Date.now() - this.orgTime;

						if (Math.abs(delta) / dragTime > 1) {
							flip = 1;
						}
					}

					if (flip) {
						if (delta > 0 && nextImage) {
							/* next */
							this._detach(this.index - 1, previousImage);

							this.previousImage = this.currentImage;
							this.currentImage = nextImage;
							nextImage = this.nextImage = nextImage.nextSibling;

							this.index++;

							if (nextImage) {
								this._moveLeft(nextImage, this.windowWidth + "px");
								this._attach(this.index + 1, nextImage);
							}

							this.direction = 1;

						} else if (delta < 0 && previousImage) {
							/* prev */
							this._detach(this.index + 1, nextImage);

							this.nextImage = this.currentImage;
							this.currentImage = previousImage;
							previousImage = this.previousImage = this.previousImage.previousSibling;

							this.index--;

							if (previousImage) {
								this._moveLeft(previousImage, -this.windowWidth + "px");
								this._attach(this.index - 1, previousImage);
							}

							this.direction = -1;
						}
					}

					sec = this.options.duration;
					self = this;

					this.moving = true;

					setTimeout(function () {
						self.moving = false;
					}, sec - 25);

					this._moveLeft(this.currentImage, "0px", sec);
					if (this.nextImage) {
						this._moveLeft(this.nextImage, this.windowWidth + "px", sec);
					}
					if (this.previousImage) {
						this._moveLeft(this.previousImage, -this.windowWidth + "px", sec);
					}
				}
			};

			/**
			 * This method deletes all "vmouse" events' handlers.
			 * It is called by method "destroy".
			 * @method _deleteEvents
			 * @protected
			 * @member ns.widget.mobile.Gallery
			 */
			Gallery.prototype._deleteEvents = function () {
				var container = this.container;

				container.removeEventListener("vmousemove", this.vmousemoveHandler, false);
				container.removeEventListener("vmousedown", this.vmousedownHandler, false);
				container.removeEventListener("vmouseup", this.vmouseupHandler, false);
				container.removeEventListener("vmouseout", this.vmouseoutHandler, false);
			};

			/**
			 * The _unbind method is used to disable showing gallery on "pageshow" event
			 * and refreshing gallery on "throttledresize" event.
			 * @method _unbind
			 * @member ns.widget.mobile.Gallery
			 * @protected
			 */
			Gallery.prototype._unbind = function () {
				var page = selectors.getClosestBySelectorNS(this.element, "role=page");

				window.removeEventListener("throttledresize", this.throttledresizeHandler, false);
				page.removeEventListener("pageshow", this.pageShowHandler, false);
			};

			/**
			 * Removes the gallery functionality completely.
			 *
			 * This will return the element back to its pre-init state.
			 *
			 *      @example
			 *      var galleryWidget = tau.widget.Gallery(document.getElementById("gallery"));
			 *      galleryWidget.destroy();
			 *
			 *      // or
			 *
			 *      $( "#gallery" ).gallery( "destroy" );
			 *
			 * @method destroy
			 * @member ns.widget.mobile.Gallery
			 */

			/**
			 * This method destroys gallery.
			 * @method _destroy
			 * @protected
			 * @member ns.widget.mobile.Gallery
			 */
			Gallery.prototype._destroy = function () {
				this._unbind();
				this._deleteEvents();
				//@todo adding returning element back
			};

			/**
			 * The add method is used to add an image to the gallery. As a parameter, the file URL of image should be passed.
			 *
			 * The refresh method must be call after adding. Otherwise, the file will be added, but not displayed.
			 *
			 *      @example
			 *      var galleryWidget = tau.widget.Gallery(document.getElementById("gallery"));
			 *
			 *      galleryWidget.add( "./images/01.jpg" ); // image with attribute src="./images/01.jpg" will be added
			 *      galleryWidget.refresh( );
			 *
			 *      // or
			 *
			 *      $( "#gallery" ).gallery( "add", "./images/01.jpg" );
			 *      $( "#gallery" ).gallery( "add", "./images/02.jpg" );
			 *      $( "#gallery" ).gallery( "refresh" ); // to see changes, method "refresh" must be called
			 *
			 * @method add
			 * @param {string} file the image's file URL
			 * @member ns.widget.mobile.Gallery
			 */
			Gallery.prototype.add = function (file) {
				this.imagesHold.push(file);
			};

			/**
			 * The remove method is used to delete an image from the gallery.
			 * If parameter is defined, the selected image is deleted. Otherwise, the current image is deleted.
			 *
			 *      @example
			 *      var galleryWidget = tau.widget.Gallery(document.getElementById("gallery"));
			 *
			 *      galleryWidget.remove( 0 ); // the first image will be removed
			 *
			 *      // or
			 *
			 *      $( "#gallery" ).gallery( "remove", 0 );
			 *
			 * @method remove
			 * @param {number} [index] index of image, which should be deleted
			 * @member ns.widget.mobile.Gallery
			 */
			Gallery.prototype.remove = function (index) {
				var classes = Gallery.classes,
					images = this.images,
					currentIndex = this.index,
					container = this.container,
					previousImage,
					nextImage,
					tempImageContainer;

				if (index === undefined) {
					index = currentIndex;
				}

				if (index >= 0 && index < images.length) {
					if (index === currentIndex) {
						tempImageContainer = this.currentImage;
						if (currentIndex === 0) {
							this.direction = 1;
						} else if (currentIndex === images.length - 1) {
							this.direction = -1;
						}
						if (this.direction < 0) {
							previousImage = this.previousImage;
							this.currentImage = previousImage;
							this.previousImage = previousImage ? previousImage.previousSibling : null;
							if (this.previousImage) {
								this._moveLeft(this.previousImage, -this.windowWidth + "px");
								this._attach(index - 2, this.previousImage);
							}
							this.index--;
						} else {
							nextImage = this.nextImage;
							this.currentImage = nextImage;
							this.nextImage = nextImage ? nextImage.nextSibling : null;
							if (this.nextImage) {
								this._moveLeft(this.nextImage, this.windowWidth + "px");
								this._attach(index + 2, this.nextImage);
							}
						}
						this._moveLeft(this.currentImage, "0px", this.options.duration);
					} else if (index === currentIndex - 1) {
						tempImageContainer = this.previousImage;
						this.previousImage = this.previousImage.previousSibling;
						if (this.previousImage) {
							this._moveLeft(this.previousImage, -this.windowWidth + "px");
							this._attach(index - 1, this.previousImage);
						}
						this.index--;
					} else if (index === currentIndex + 1) {
						tempImageContainer = this.nextImage;
						this.nextImage = this.nextImage.nextSibling;
						if (this.nextImage) {
							this._moveLeft(this.nextImage, this.windowWidth + "px");
							this._attach(index + 1, this.nextImage);
						}
					} else {
						tempImageContainer = container.getElementsByClassName(classes.uiGalleryBg)[index];
					}

					container.removeChild(tempImageContainer);
					images.splice(index, 1);
				}

				return;
			};

			/**
			 * This method hides images.
			 * It is called by method "hide".
			 * @method _hide
			 * @protected
			 * @member ns.widget.mobile.Gallery
			 */
			Gallery.prototype._hide = function () {
				var index = this.index;

				this._detach(index - 1, this.previousImage);
				this._detach(index, this.currentImage);
				this._detach(index + 1, this.nextImage);
			};

			/**
			 * The hide method is used to hide the gallery. It makes all images invisible and also unbinds all touch events.
			 *
			 *       @example
			 *      var galleryWidget = tau.widget.Gallery(document.getElementById("gallery"));
			 *
			 *      galleryWidget.hide( ); // gallery will be hidden
			 *
			 *      // or
			 *
			 *      $( "#gallery" ).gallery( "hide" );
			 *
			 * @method hide
			 * @member ns.widget.mobile.Gallery
			 */
			Gallery.prototype.hide = function () {
				this._hide();
				this._deleteEvents();
			};

			/**
			 * This method updates the images hold by wigdet.
			 * It is called by method "refesh".
			 * @method _update
			 * @protected
			 * @member ns.widget.mobile.Gallery
			 */
			Gallery.prototype._update = function () {
				var self = this,
					galleryBgClass = Gallery.classes.uiGalleryBg,
					images = self.images,
					imagesHold = self.imagesHold,
					imagesHoldLen = imagesHold.length,
					container = self.container,
					image,
					wrapped,
					imageFile,
					i;

				for (i = 0; i < imagesHoldLen; i++) {
					imageFile = imagesHold.shift();
					image = document.createElement("img");
					image.src = imageFile;
					wrapped = document.createElement("div");
					wrapped.classList.add(galleryBgClass);
					container.appendChild(wrapped);
					images.push(image);
				}
			};

			/**
			 * The refresh method is used to refresh the gallery.
			 *
			 * This method must be called after adding images to the gallery.
			 *
			 * This method is called automatically after changing any option of widget and calling method value with not empty parameter.
			 *
			 *      @example
			 *      var galleryWidget = tau.widget.Gallery(document.getElementById("gallery"));
			 *      galleryWidget.refresh();
			 *
			 *      // or
			 *
			 *      $( "#gallery" ).gallery( "refresh" );
			 *
			 *      // also will be called automatically in during changing option (method "option") or setting value (method "value")
			 *
			 *      galleryWidget.option("flicking", true);
			 *      galleryWidget.value(0);
			 *
			 *
			 * @method refresh
			 * @param {number} [startIndex] index of the first image
			 * @return {?number} index of the first image, which will be displayed
			 * @member ns.widget.mobile.Gallery
			 */
			/**
			 * This method refreshes wigdet.
			 * It is called by method "refesh".
			 * @method _refresh
			 * @param {?number} startIndex
			 * @protected
			 * @member ns.widget.mobile.Gallery
			 */
			Gallery.prototype._refresh = function (startIndex) {
				this._update();

				this._hide();

				// if startIndex is undefined or it is not possible to convert value to integer, the old index is used
				startIndex = parseInt(startIndex, 10);

				if (isNaN(startIndex)){
					startIndex = this.index;
				}

				if (startIndex < 0) {
					startIndex = 0;
				}
				if (startIndex >= this.images.length) {
					startIndex = this.images.length - 1;
				}

				this.index = startIndex;

				this.show();

				return this.index;

			};

			/**
			 * The empty method is used to remove all of images from the gallery.
			 *
			 *      @example
			 *      var galleryWidget = tau.widget.Gallery(document.getElementById("gallery"));
			 *
			 *      galleryWidget.empty( ); // all images will be deleted
			 *
			 *      // or
			 *
			 *      $( "#gallery" ).gallery( "empty" );
			 *
			 * @method empty
			 * @member ns.widget.mobile.Gallery
			 */
			Gallery.prototype.empty = function () {
				this.container.innerHTML = "";
				this.images.length = 0;
			};

			/**
			 * The length method is used to get the number of images.
			 *
			 *      @example
			 *      var galleryWidget = tau.widget.Gallery(document.getElementById("gallery")),
			 *          imagesItems;
			 *
			 *      imagesLength = galleryWidget.length( ); // number of images
			 *
			 *      // or
			 *
			 *      imagesLength = $( "#gallery" ).gallery( "length" );
			 *
			 * @method length
			 * @return {number}
			 * @member ns.widget.mobile.Gallery
			 */
			Gallery.prototype.length = function () {
				return this.images.length;
			};

			/**
			 * The value method is used to get or set current index of gallery.
			 * If parameter is not defined, the current index is return. Otherwise, the index of the image is set and proper image is displayed. The index of images is counted from 0. If new index is less than 0 or greater than or equal length of images, then the index will not be changed.
			 *
			 *      @example
			 *      var galleryWidget = tau.widget.Gallery(document.getElementById("gallery")),
			 *          value = galleryWidget.value(); // value contains the index of current image
			 *
			 *      galleryWidget.value( 0 ); // the first image will be displayed
			 *
			 *      // or
			 *
			 *      value = $( "#gallery" ).gallery( "value" ); // value contains the index of current image
			 *
			 *      $( "#gallery" ).gallery( "value",  0 ); // the first image will be displayed
			 *
			 * @method value
			 * @param {?number} index of image, which should be displayed now
			 * @return {?number}
			 * @member ns.widget.mobile.Gallery
			 */

			/**
			 * This method sets value of index.
			 * It is called by method "value".
			 * @method _setValue
			 * @param {number} index New value of index
			 * @protected
			 * @member ns.widget.mobile.Gallery
			 */
			Gallery.prototype._setValue = function (index) {
				this.refresh(index);
				return null;
			};

			/**
			 * This method returns the value of index.
			 * It is called by method "value".
			 * @method _getValue
			 * @protected
			 * @member ns.widget.mobile.Gallery
			 */
			Gallery.prototype._getValue = function () {
				return this.index;
			};

			/**
			* This method changes state of gallery on enabled and removes CSS classes connected with state.
			*
			*      @example
			*      var galleryWidget = tau.widget.Gallery(document.getElementById("gallery"));
			*
			*      galleryWidget.enable();
			*
			*      // or
			*
			*      $( "#gallery" ).gallery( "enable" );
			*
			* @method enable
			* @chainable
			* @member ns.widget.mobile.Gallery
			*/

			/**
			* This method changes state of gallery on disabled and adds CSS classes connected with state.
			*
			*      @example
			*      var galleryWidget = tau.widget.Gallery(document.getElementById("gallery"));
			*
			*      galleryWidget.disable();
			*
			*      // or
			*
			*      $( "#gallery" ).gallery( "disable" );
			*
			* @method disable
			* @chainable
			* @member ns.widget.mobile.Gallery
			*/

			/**
			 * Get/Set options of the widget.
			 *
			 * This method can work in many context.
			 *
			 * If first argument is type of object them, method set values for options given in object. Keys of object are names of options and values from object are values to set.
			 *
			 * If you give only one string argument then method return value for given option.
			 *
			 * If you give two arguments and first argument will be a string then second argument will be intemperate as value to set.
			 *
			 * @method option
			 * @param {string|Object} [name] name of option
			 * @param {*} value value to set
			 * @member ns.widget.mobile.Gallery
			 * @return {*} return value of option or undefined if method is called in setter context
			 */

			/**
			 * Trigger an event on widget's element.
			 *
			 *      @example
			 *      var galleryWidget = tau.widget.Gallery(document.getElementById("gallery"));
			 *      galleryWidget.trigger("eventName");
			 *
			 *      // or
			 *
			 *      $("#gallery").gallery("trigger", "eventName");
			 *
			 * @method trigger
			 * @param {string} eventName the name of event to trigger
			 * @param {?*} [data] additional object to be carried with the event
			 * @param {boolean} [bubbles=true] indicating whether the event bubbles up through the DOM or not
			 * @param {boolean} [cancelable=true] indicating whether the event is cancelable
			 * @return {boolean} false, if any callback invoked preventDefault on event object
			 * @member ns.widget.mobile.Gallery
			*/

			/**
			 * Add event listener to widget's element.
			 *
			 *      @example
			 *      var galleryWidget = tau.widget.Gallery(document.getElementById("gallery")),
			 *          callback = function () {
			 *              console.log("event fires");
			 *          });
			 *
			 *      galleryWidget.on("eventName", callback);
			 *
			 *      // or
			 *
			 *      $("#gallery").gallery("on", callback);
			 *
			 * @method on
			 * @param {string} eventName the name of event
			 * @param {Function} listener function call after event will be trigger
			 * @param {boolean} [useCapture=false] useCapture param to addEventListener
			 * @member ns.widget.mobile.Gallery
			 */

			/**
			 * Remove event listener to widget's element.
			 *
			 *      @example
			 *      var galleryWidget = tau.widget.Gallery(document.getElementById("gallery")),
			 *          callback = function () {
			 *              console.log("event fires");
			 *          });
			 *
			 *      // add callback on event "eventName"
			 *      galleryWidget.on("eventName", callback);
			 *      // ...
			 *      // remove callback on event "eventName"
			 *      galleryWidget.off("eventName", callback);
			 *
			 *      // or
			 *
			 *      // add callback on event "eventName"
			 *      $("#gallery").gallery("on", callback);
			 *      // ...
			 *      // remove callback on event "eventName"
			 *      $("#gallery").gallery("off", "eventName", callback);
			 *
			 *
			 * @method off
			 * @param {string} eventName the name of event
			 * @param {Function} listener function call after event will be trigger
			 * @param {boolean} [useCapture=false] useCapture param to addEventListener
			 * @member ns.widget.mobile.Gallery
			 */

			// definition
			ns.widget.mobile.Gallery = Gallery;
			engine.defineWidget(
				"Gallery",
				"[data-role='gallery'], .ui-gallery",
				[
					"add",
					"remove",
					"empty",
					"length",
					"hide",
					"show"
				],
				Gallery,
				"tizen"
			);
			}(window.document, ns));

/*global window, define, $, ns */
/*
* Copyright  2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/*jslint nomen: true, plusplus: true */

/**
 * #Virtual List Widget
 * Widget creates special list which can contain big number of items.
 *
 * In the Web environment, it is challenging to display a large amount of data in a list, such as
 * displaying a contact list of over 1000 list items. It takes time to display the entire list in
 * HTML and the DOM manipulation is complex.
 *
 * The virtual list widget is used to display a list of unlimited data elements on the screen
 * for better performance. This widget provides easy access to databases to retrieve and display data.
 * It based on **result set** which is fixed size defined by developer by data-row attribute. Result
 * set should be **at least 3 times bigger** then size of clip (number of visible elements).
 *
 * For now Virtual Lists are based on the **jQuery.template plugin** as described in the jQuery documentation
 * for jQuery.template plugin - but it will change some day...
 *
 * ##Default selectors
 * In _ul_ elements with _data-role=virtuallistview_ or _data-role=virtuallist_.
 *
 * ##Make it work
 * To active and configure virtual list widget with application follow these steps:
 *
 * ####1. Create template and place widget element
 *
 *    @example
 *    <script id="tmp-3-2-7" type="text/x-jquery-tmpl">
 *            <li class="ui-li-3-2-7">
 *            <span class="ui-li-text-main">${NAME}</span>
 *                <img src="00_winset_icon_favorite_on.png" class="ui-li-icon-sub"/>
 *                <span class="ui-li-text-sub">${ACTIVE}</span>
 *                <span class="ui-li-text-sub2">${FROM}</span>
 *            </li>
 *        </script>
 *        <ul id="vlist" data-role="virtuallistview" data-template="tmp-3-2-7" data-row="100"></ul>
 *
 * **NOTE:** Tizen Web UI's data-dbtable attribute and functionality is not supported.
 *
 * ####2. Create template and place widget element
 * Run {@link ns.widget.mobile.VirtualListview#create .create} method to configure iteration function and
 * declare total number of items.
 *
 *    @example
 *    virtuallistview.create({
 *		//Configure iteration function
 *		itemData: function ( idx ) {
 *			return myDATA[idx];
 *		},
 *		//Declare total number of items
 *		numItemData: myDATA.length
 *	});
 *
 * ##Manual constructor
 * To construct VirtualListview widget manually you can use constructor of the widget:
 *
 *    @example
 *    var virtuallistview = ns.engine.instanceWidget(document.getElementById('virtuallistview'), 'VirtualListview');
 *
 * If jQuery library is loaded, its method can be used:
 *
 *    @example
 *    var virtuallistview = $('#virtuallistview').virtuallistview();
 *
 * **NOTE:** after construct of widget should be create method called with proper parameters.
 *
 *
 * @author Michał Szepielak <m.szepielak@samsung.com>
 * @author Mateusz Ciepliński <m.cieplinski@samsung.com> [add jQuery template functionality]
 * @author Piotr Karny <p.karny@samsung.com>
 * @class ns.widget.mobile.VirtualListview
 * @extends ns.widget.mobile.Listview
 */

/**
 * CSS MODIFICATION
 * creating this widget we modified CSS file.
 *
 * CHANGED:
 * .ui-virtual-list-container { position:relative; }
 *
 */

(function (window, document, ns) {
	
				/**
			 * @property {ns.widget.mobile.Listview} Listview alias variable
			 * @private
			 * @static
			 */
			var Listview = ns.widget.mobile.Listview,
				/**
				 * @property {ns.engine} engine alias variable
				 * @private
				 * @static
				 */
				engine = ns.engine,
				/**
				 * @property {ns.util.selectors} utilsSelectors alias variable
				 * @private
				 * @static
				 */
				utilsSelectors = ns.util.selectors,
				/**
				 * @property {ns.theme} themes alias variable
				 * @private
				 * @static
				 */
				themes = ns.theme,
				/**
				 * @property {ns.widget.mobile.Listview} listviewPrototype
				 * @private
				 */
				parentPrototype = Listview.prototype,
				/**
				 * Shortcut for parent's `{@link ns.widget.mobile.Listview#_build} ns.widget.mobile.Listview._build`
				 * method from `{@link ns.widget.mobile.Listview} ns.widget.mobile.Listview.prototype`
				 * @method
				 * @private
				 * @static
				 */
				parent_build = parentPrototype._build,

				/**
				 * @property {Object} parent_init Shortcut for parent's {@link ns.widget.mobile.Listview#_build}
				 * method from prototype of {@link ns.widget.mobile.Listview}
				 * @private
				 * @static
				 * @member ns.widget.mobile.ExtendableList
				 */
				parent_init = Listview.prototype._init,
				/**
				 * @property {Object} parent_bindEvent Shortcut for parent's {@link ns.widget.mobile.Listview#_build}
				 * method from prototype of {@link ns.widget.mobile.Listview}
				 * @private
				 * @static
				 * @member ns.widget.mobile.ExtendableList
				 */
				parent_bindEvents = Listview.prototype._bindEvents,
				// Constants definition
				/**
				 * @property {number} SCROLL_UP defines index of scroll \_scroll.direction
				 * to retrive if user is scrolling up
				 * @private
				 * @static
				 */
				SCROLL_UP = 0,
				/**
				 * @property {number} SCROLL_RIGHT defines index of scroll \_scroll.direction
				 * to retrive if user is scrolling right
				 * @private
				 * @static
				 */
				SCROLL_RIGHT = 1,
				/**
				 * @property {number} SCROLL_DOWN defines index of scroll \_scroll.direction
				 * to retrive if user is scrolling down
				 * @private
				 * @static
				 */
				SCROLL_DOWN = 2,
				/**
				 * @property {number} SCROLL_LEFT defines index of scroll \_scroll.direction
				 * to retrive if user is scrolling left
				 * @private
				 * @static
				 */
				SCROLL_LEFT = 3,
				/**
				 * @property {string} VERTICAL Defines vertical scrolling direction. It's default direction.
				 * @private
				 * @static
				 */
				VERTICAL = "y",
				/**
				 * @property {string} HORIZONTAL Defines horizontal scrolling direction.
				 * @private
				 * @static
				 */
				HORIZONTAL = "x",
				/**
				 * @property {boolean} blockEvent Determines that scroll event should not be taken into account if scroll event accurs.
				 * @private
				 * @static
				 */
				blockEvent = false,
				/**
				 * Local constructor function
				 * @method VirtualListview
				 * @private
				 * @member ns.widget.mobile.VirtualListview
				 */
				VirtualListview = function () {
					var self = this;

					/**
					* @property {Object} ui VirtualListview widget's properties associated with
					* User Interface
					* @property {?HTMLElement} [ui.scrollview=null] Reference to associated
					* {@link ns.widget.mobile.Scrollview Scrollview widget}
					* @property {number} [ui.itemSize=0] Size of list element in piksels. If scrolling is
					* vertically it's item width in other case it's height of item element
					* @member ns.widget.mobile.VirtualListview
					*/
					self._ui = {
						scrollview: null,
						itemSize: 0
					};

					/**
					* @property {Object} _scroll Holds information about scrolling state
					* @property {Array} [_scroll.direction=[0,0,0,0]] Holds current direction of scrolling.
					* Indexes suit to following order: [up, left, down, right]
					* @property {number} [_scroll.lastPositionX=0] Last scroll position from top in pixels.
					* @property {number} [_scroll.lastPositionY=0] Last scroll position from left in pixels.
					* @property {number} [_scroll.lastJumpX=0] Difference between last and current
					* position of horizontal scroll.
					* @property {number} [_scroll.lastJumpY=0] Difference between last and current
					* position of vertical scroll.
					* @property {number} [_scroll.clipWidth=0] Width of clip - visible area for user.
					* @property {number} [_scroll.clipHeight=0] Height of clip - visible area for user.
					* @member ns.widget.mobile.VirtualListview
					*/
					self._scroll = {
						direction: [0, 0, 0, 0],
						lastPositionX: 0,
						lastPositionY: 0,
						lastJumpX: 0,
						lastJumpY: 0,
						//@TODO: what if there is another element in scroll view? what size of clip should be?
						clipWidth: 0,
						clipHeight: 0
					};

					/**
					* @property {number} _currentIndex Current zero-based index of data set.
					* @member ns.widget.mobile.VirtualListview
					*/
					self._currentIndex = 0;

					/**
					 * Returns list item value at specified index from database.
					 *
					 * **Method should overrided by developer using {@link ns.widget.mobile.VirtualListview#create .create} method.**
					 * @method itemData
					 * @param {number} index Index of data set.
					 * @return {Object}
					 * @member ns.widget.mobile.VirtualListview
					 */
					self.itemData = function () {
						return null;
					};

					//Event function handler
					self._scrollEventBound = null;

					return self;
				},
				prototype = new Listview(),
				classes = {
					CONTAINER: "ui-virtual-list-container"
				};


			VirtualListview.prototype = prototype;

			/**
			 * Dictionary object containing commonly used widget classes
			 * @property {Object} classes
			 * @static
			 * @member ns.widget.mobile.VirtualListview
			 * @readonly
			 */
			VirtualListview.classes = classes;

			prototype._configure = function () {
				var self = this,
					options = self.options;

				// Call parent _configure
				parentPrototype._configure.apply(self, arguments);

				/**
				 * @property {Object} options VirtualListview widget options.
				 * @property {?Object} [options.template=null] Widget template engine.
				 * @property {?string} [options.theme=null] Widget theme
				 * value is used when .theme option isn't on element itself and on it's parents.
				 * @property {number} [options.row=100] Number of items of result set. The minimum
				 * value is 20 and the default value is 100. As the value gets higher, the loading
				 * time increases while the system performance improves. So you need to pick a value
				 * that provides the best performance without excessive loading time.
				 * @property {number} [options.numItemData=0] Total number of items.
				 * @property {boolean} [options.standalone=false] If true scrollview instance will be created inside of the widget
				 */
				options.template = null;
				options.theme = null;
				options.direction = VERTICAL;
				options.row = 50;
				options.numItemData = 0;
				options.standalone = false;
			};

			//@TODO: Maybe this information should by provided by Scrollview
			/**
			 * Updates scroll information about position, direction and jump size.
			 * @method _updateScrollInfo
			 * @private
			 */
			prototype._updateScrollInfo = function () {
				var self = this,
					scrollInfo = self._scroll,
					scrollDirection,
					scrollViewElement = self._ui.scrollview.element,
					scrollLastPositionX = scrollInfo.lastPositionX,
					scrollLastPositionY = scrollInfo.lastPositionY,
					// Fetch current scroll position
					scrollviewPosX = scrollViewElement.scrollLeft,
					scrollviewPosY = scrollViewElement.scrollTop;

				self._refreshScrollbar();
				//Reset scroll matrix
				scrollDirection = [0, 0, 0, 0];

				//Scrolling UP
				if (scrollviewPosY < scrollLastPositionY) {
					scrollDirection[SCROLL_UP] = 1;
				}

				//Scrolling RIGHT
				if (scrollviewPosX > scrollLastPositionX) {
					scrollDirection[SCROLL_RIGHT] = 1;
				}

				//Scrolling DOWN
				if (scrollviewPosY > scrollLastPositionY) {
					scrollDirection[SCROLL_DOWN] = 1;
				}

				//Scrolling LEFT
				if (scrollviewPosX < scrollLastPositionX) {
					scrollDirection[SCROLL_LEFT] = 1;
				}

				scrollInfo.lastJumpY = Math.abs(scrollviewPosY - scrollLastPositionY);
				scrollInfo.lastJumpX = Math.abs(scrollviewPosX - scrollLastPositionX);
				scrollInfo.lastPositionX = scrollviewPosX;
				scrollInfo.lastPositionY = scrollviewPosY;
				scrollInfo.direction = scrollDirection;
				scrollInfo.clipHeight = scrollViewElement.clientHeight;
				scrollInfo.clipWidth = scrollViewElement.clientWidth;
			};

			/**
			 * Computes list element size according to scrolling orientation
			 * @method _computeElementSize
			 * @param {HTMLElement} element Element whose size should be computed
			 * @param {string} orientation Scrolling orientation
			 * @return {number} Size of element in pixels
			 * @member ns.widget.wearable.VirtualListview
			 * @private
			 * @static
			 */
			function _computeElementSize(element, orientation) {
				// @TODO change to util method if it will work perfectly
				return parseInt(orientation === VERTICAL ? element.clientHeight : element.clientWidth, 10) + 1;
			}

			/**
			 * Scrolls and manipulates DOM element to destination index. Element at destination
			 * index is the first visible element on the screen. Destination index can
			 * be different from Virtual List's current index, because current index points
			 * to first element in the buffer.
			 * @member ns.widget.mobile.VirtualListview
			 * @param {ns.widget.mobile.VirtualListview} self VirtualListview widget reference
			 * @param {number} toIndex Destination index.
			 * @method _orderElementsByIndex
			 * @private
			 * @static
			 */
			function _orderElementsByIndex(self, toIndex) {
				var element = self.element,
					options = self.options,
					scrollInfo = self._scroll,
					resultsetSize = 0,
					dataLength = options.numItemData,
					indexCorrection = 0,
					bufferedElements = 0,
					avgListItemSize = 0,
					bufferSize = options.row,
					i,
					offset = 0,
					index;

				//Get size of scroll clip depended on scroll direction
				resultsetSize = options.direction === VERTICAL ? scrollInfo.clipHeight : scrollInfo.clipWidth;

				//resultsetSize = self._computeResultsetSize();
				//Compute average list item size
				avgListItemSize = self._computeAvgSize();

				//Compute average number of elements in each buffer (before and after clip)
				bufferedElements = Math.floor((bufferSize - Math.floor(resultsetSize / avgListItemSize)) / 2);

				if (toIndex - bufferedElements <= 0) {
					index = 0;
					indexCorrection = 0;
				} else {
					index = toIndex - bufferedElements;
				}

				if (index + bufferSize >= dataLength) {
					index = dataLength - bufferSize;
				}
				indexCorrection = toIndex - index;

				self._loadData(index);
				blockEvent = true;
				offset = index * avgListItemSize;
				if (options.direction === VERTICAL) {
					element.style.top = offset + "px";
				} else {
					element.style.left = offset + "px";
				}

				for (i = 0; i < indexCorrection; i += 1) {
					offset += _computeElementSize(element.children[i], options.direction);
				}

				if (options.direction === VERTICAL) {
					self.ui.scrollview.element.scrollTop = offset;
				} else {
					self.ui.scrollview.element.scrollLeft = offset;
				}
				blockEvent = false;
				self._currentIndex = index;
			}

			/**
			 * Orders elements. Controls resultset visibility and does DOM manipulation.
			 * @method _orderElements
			 * @param {ns.widget.mobile.VirtualListview} self VirtualListview widget reference
			 * @private
			 */
			function _orderElements(self) {
				var element = self.element,
					scrollInfo = self._scroll,
					options = self.options,
					elementStyle = element.style,
					//Current index of data, first element of resultset
					currentIndex = self._currentIndex,
					//Number of items in resultset
					bufferSize = parseInt(options.row, 10),
					//Total number of items
					dataLength = options.numItemData,
					//Array of scroll direction
					scrollDirection = scrollInfo.direction,
					scrolledVertically = (scrollDirection[SCROLL_UP] || scrollDirection[SCROLL_DOWN]),
					scrolledHorizontally = (scrollDirection[SCROLL_LEFT] || scrollDirection[SCROLL_RIGHT]),
					scrollClipWidth = scrollInfo.clipWidth,
					scrollClipHeight = scrollInfo.clipHeight,
					scrollLastPositionY = scrollInfo.lastPositionY,
					scrollLastPositionX = scrollInfo.lastPositionX,
					elementPositionTop = parseInt(elementStyle.top, 10) || 0,
					elementPositionLeft = parseInt(elementStyle.left, 10) || 0,
					elementsToLoad = 0,
					elementsLeftToLoad = 0,
					temporaryElement = null,
					avgListItemSize,
					resultsetSize,
					i,
					jump = 0,
					hiddenPart = 0,
					newPosition;

				resultsetSize = self._computeResultsetSize();
				avgListItemSize = self._computeAvgSize(resultsetSize);

				//Compute hidden part of result set and number of elements, that needed to be loaded, while user is scrolling DOWN
				if (scrollDirection[SCROLL_DOWN]) {
					hiddenPart = scrollLastPositionY - elementPositionTop;
					elementsLeftToLoad = dataLength - currentIndex - bufferSize;
				}

				//Compute hidden part of result set and number of elements, that needed to be loaded, while user is scrolling UP
				if (scrollDirection[SCROLL_UP]) {
					hiddenPart = (elementPositionTop + resultsetSize) - (scrollLastPositionY + scrollClipHeight);
					elementsLeftToLoad = currentIndex;
				}

				//Compute hidden part of result set and number of elements, that needed to be loaded, while user is scrolling RIGHT
				if (scrollDirection[SCROLL_RIGHT]) {
					hiddenPart = scrollLastPositionX - elementPositionLeft;
					elementsLeftToLoad = dataLength - currentIndex - bufferSize;
				}

				//Compute hidden part of result set and number of elements, that needed to be loaded, while user is scrolling LEFT
				if (scrollDirection[SCROLL_LEFT]) {
					hiddenPart = (elementPositionLeft + resultsetSize) - (scrollLastPositionX + scrollClipWidth);
					elementsLeftToLoad = currentIndex;
				}

				//manipulate DOM only, when at least 2/3 of result set is hidden
				//NOTE: Result Set should be at least 3x bigger then clip size
				if (hiddenPart > 0 && (resultsetSize / hiddenPart) <= 1.5) {

					//Left half of hidden elements still hidden/cached
					elementsToLoad = Math.floor(hiddenPart / avgListItemSize) - Math.floor((bufferSize - scrollClipHeight / avgListItemSize) / 2);
					elementsToLoad = elementsLeftToLoad < elementsToLoad ? elementsLeftToLoad : elementsToLoad;

					if (scrollDirection[SCROLL_DOWN] || scrollDirection[SCROLL_RIGHT]) {
						//Switch currentIndex to last
						currentIndex = currentIndex + bufferSize - 1;
					}

					for (i = elementsToLoad; i > 0; i -= 1) {
						if (scrollDirection[SCROLL_DOWN] || scrollDirection[SCROLL_RIGHT]) {
							temporaryElement = element.appendChild(element.firstElementChild);
							++currentIndex;

							//Updates list item using template
							self._updateListItem(temporaryElement, currentIndex);
							if (scrolledVertically) {
								jump += temporaryElement.offsetHeight;
							} else {
								jump += temporaryElement.offsetWidth;
							}
						}

						if (scrollDirection[SCROLL_UP] || scrollDirection[SCROLL_LEFT]) {
							temporaryElement = element.insertBefore(element.lastElementChild, element.firstElementChild);
							--currentIndex;

							//Updates list item using template
							self._updateListItem(temporaryElement, currentIndex);
							if (scrolledVertically) {
								jump -= temporaryElement.offsetHeight;
							} else {
								jump -= temporaryElement.offsetWidth;
							}
						}
					}
					if (scrolledVertically) {
						newPosition = elementPositionTop + jump;

						if (newPosition < 0 || currentIndex <= 0) {
							newPosition = 0;
							currentIndex = 0;
						}

						elementStyle.top = newPosition + "px";
					}

					if (scrolledHorizontally) {
						newPosition = elementPositionLeft + jump;

						if (newPosition < 0 || currentIndex <= 0) {
							newPosition = 0;
							currentIndex = 0;
						}

						elementStyle.left = newPosition + "px";
					}

					if (scrollDirection[SCROLL_DOWN] || scrollDirection[SCROLL_RIGHT]) {
						//Switch currentIndex to first
						currentIndex = currentIndex - bufferSize + 1;
					}
					//Save current index
					self._currentIndex = currentIndex;
				}
			}


			/**
			 * @method _updateListItem
			 * Updates list item using user defined listItemUpdater function.
			 * @param {HTMLElement} element List element to update
			 * @param {number} index Data row index
			 * @protected
			 */
			prototype._updateListItem = function (element, index) {
				var self = this,
					itemData = self.itemData,
					$jqTmpl = self._ui.$jqTmpl,
					templateElement;

				if (typeof self.options.listItemUpdater === "function") {
					self.options.listItemUpdater(element, index);
				} else {
					//@TODO THIS IS A JQUERY INCLUSION IN A TAU WIDGET!!!
					//@TODO FIX THIS!!!
					templateElement = $.tmpl($jqTmpl, itemData(index))[0];
					element.innerHTML = templateElement.innerHTML;
					if (templateElement.className) {
						//@TODO move this to utils
						window.DOMTokenList.prototype.add.apply(element.classList, templateElement.className.split(" "));
					}
					engine.createWidgets(element);
				}
			};

			/**
			 * Build widget structure
			 * @method _build
			 * @protected
			 * @param {string} template
			 * @param {HTMLElement} element
			 * @return {HTMLElement}
			 */
			VirtualListview.prototype._build = function (element) {
				var self = this,
					options = self.options,
					elementStyle = element.style,
					styleHeight = elementStyle.height,
					styleWidth = elementStyle.width,
					standaloneContainer;

				// Check if standalone must be forced
				// this is not placed inside _configure method because it could be overriden by a data- attribute
				// @TODO other properties could potentially work in this way too
				if (styleHeight !== "" && styleHeight !== "auto" && styleWidth !== "" && styleWidth !== "auto") {
					options.standalone = true;
				}

				// Prepare a parent container for VirtualList
				if (options.standalone) {
					standaloneContainer = document.createElement('div');

					// Standalone container must match sizes designed by developer
					standaloneContainer.style.width = styleWidth || "100%";
					standaloneContainer.style.height = styleHeight || "100%";

					// Remove style values
					// @TODO reassign those values on destroy
					elementStyle.height = "";
					elementStyle.width = "";

					// Add scrollview to content element
					// we must add it before creating instance because some operations inside build method
					// require presence inside DOM
					element.parentElement.appendChild(standaloneContainer);

					// Create a widget instance of it
					self._ui.scrollview = engine.instanceWidget(standaloneContainer, "Scrollview", {
						scroll: options.direction
					});

					// After creating scrollview widget apeend list as a child
					self._ui.scrollview._ui.view.appendChild(element);
				}

				//Call parent's method
				parent_build.call(self, element);

				options.theme = themes.getInheritedTheme(element) || options.theme;
				element.classList.add(classes.CONTAINER);

				//Prepare element
				elementStyle.position = "relative";

				return element;
			};

			/**
			 * Check if scrolling position is changed and updates list if it needed.
			 * @method _updateList
			 * @param {ns.widget.mobile.VirtualListview} self VirtualListview widget reference
			 * @member ns.widget.mobile.VirtualListview
			 * @private
			 * @static
			 */
			function _updateList(self) {
				var _scroll = self._scroll;

				self._updateScrollInfo();

				if (_scroll.lastJumpY > 0 || _scroll.lastJumpX > 0) {
					if (!blockEvent) {
						_orderElements(self);
					}
				}
			}

			/**
			 * Configures list. Sets data source and iterator behavior.
			 * @method _configureList
			 * @protected
			 * @param {Object} argumentsArray
			 * @member ns.widget.mobile.VirtualListview
			 */
			prototype._configureList = function (argumentsArray) {
				var self = this,
					options = self.options,
					args = argumentsArray[0] || {};

				if (typeof args.itemData === "function" && (typeof args.numItemData === "function" || typeof args.numItemData === "number")) {
					if (typeof args.numItemData === "function") {
						options.numItemData = args.numItemData();
					} else {
						options.numItemData = args.numItemData <= 0 ? 0 : args.numItemData;
					}
					self.itemData = args.itemData;
				}

				// @TODO set minimum set size depending on current screen size
				options.row = Math.max(20, options.row);

				self._buildList();

				//Update scroll info: scroll position etc... if options.standalone = true
				if (options.standalone) {
					self._updateScrollInfo();
				}
			};

			/**
			 * Sums current element set size depending on direction
			 * @return {number} current loaded set of elements size
			 * @protected
			 */
			prototype._computeResultsetSize = function () {
				var self = this,
					resultsetSize = 0,
					currentDirection = self.options.direction,
					childrenNodes = self.element.children,
					i;

				// Go through children and fetch their sizes
				for (i = childrenNodes.length - 1; i >= 0; i -= 1) {
					if (currentDirection === VERTICAL) {
						resultsetSize += childrenNodes[i].offsetHeight;
					} else {
						resultsetSize += childrenNodes[i].offsetWidth;
					}
				}

				return resultsetSize;
			};


			/**
			 * Calculates current set size depending on currently loaded elements
			 * @method _computeAvgSize
			 * @param {number} [resultsetSize] result size may be passed for saving computations
			 * @protected
			 * @return {number} Average size of result elements
			 */
			prototype._computeAvgSize = function (resultsetSize) {
				var self = this,
					size = resultsetSize || self._computeResultsetSize(),
					avgSize = Math.ceil(size / self.options.row);

				self._avgListItemSize = avgSize;

				return avgSize;
			};

			/**
			 * Initialize list on an element
			 * @method _init
			 * @protected
			 * @param {HTMLElement} element
			 * @member ns.widget.mobile.VirtualListview
			 */
			prototype._init = function (element) {
				var self = this,
					ui = self._ui,
					options = self.options,
					standalone = options.standalone,
					direction,
					scrollviewInstance;


				// scrollview may be set while widget is created with standalone option
				if (standalone && !ui.scrollview || !standalone) {
					//Get Scrollview widget instance
					// @TODO make this asynchrous, it's currently possible that a child widget will be built before scrollview (for example VirtualGrid)
					// @TODO this will fail also if data-scroll is set to none on target scrollable element
					scrollviewInstance = engine.getBinding(utilsSelectors.getClosestByClass(element, 'ui-scrollview-clip'));
					ui.scrollview = scrollviewInstance;
				} else {
					scrollviewInstance = ui.scrollview;
				}

				//@TODO JQUERY!
				ui.$jqTmpl = $(document.getElementById(self.options.template));

				options.row = parseInt(options.row, 10);

				//Set direction, default vertical scrolling is allowed
				direction = (options.direction.toLowerCase() === HORIZONTAL) ? HORIZONTAL : VERTICAL;
				options.direction = direction;

				// Prepare view
				if (standalone && options.direction === HORIZONTAL) {
					scrollviewInstance._ui.view.style.height = "100%";
				}

				parent_init.call(self, element);
			};

			/**
			 * Builds list items
			 * @method _buildList
			 * @protected
			 * @member ns.widget.mobile.VirtualListview
			 */
			prototype._buildList = function () {
				var self = this,
					listItem,
					list = self.element,
					childElementType = (list.tagName === "UL" || list.tagName === "OL") ? "li" : "div",
					numberOfItems = self.options.row,
					documentFragment = document.createDocumentFragment(),
					direction = self.options.direction,
					i;

				for (i = 0; i < numberOfItems; ++i) {
					listItem = document.createElement(childElementType);

					if (direction === HORIZONTAL) {
						// TODO: check if whiteSpace: nowrap is better for vertical listes
						// NOTE: after rebuild this condition check possible duplication from _init method
						listItem.style.float = 'left';
					}

					self._updateListItem(listItem, i);
					documentFragment.appendChild(listItem);
				}

				list.appendChild(documentFragment);
				self._refresh();
			};

			/**
			 * Refresh list
			 * @method _refresh
			 * @member ns.widget.mobile.VirtualListview
			 * @protected
			 * @instance
			 */
			prototype._refresh = function (create) {
				//Set default value of variable create
				create = create === undefined ? false : create;
				//Set default value of variable create
				this._refreshItems(this.element, create);
				this._refreshScrollbar();
			};

			/**
			 * Loads data from specefied index to result set size.
			 * @method _loadData
			 * @protected
			 * @param {number} index Index of first row
			 * @member ns.widget.mobile.VirtualListview
			 */
			prototype._loadData = function (index) {
				var self = this,
					children = self.element.firstElementChild;

				if (self._currentIndex !== index) {
					self._currentIndex = index;
					do {
						self._updateListItem(children, index);
						++index;
						children = children.nextElementSibling;
					} while (children);
				}
			};

			/**
			 * Sets proper scrollbar size: height (vertical), width (horizontal)
			 * @method _refreshScrollbar
			 * @protected
			 * @member ns.widget.mobile.VirtualListview
			 */
			prototype._refreshScrollbar = function () {
				var self = this,
					options = self.options,
					newViewSize = self._computeAvgSize() * options.numItemData,
					scrollviewInstance = self._ui.scrollview,
					// Get scrollview view element (child)
					// @TODO remove fetching first child after createing ui.view property inside Scrollview widget
					scrollviewView;

				if (scrollviewInstance) {
					scrollviewView = (scrollviewInstance.ui && scrollviewInstance.ui.view) || scrollviewInstance.element.firstElementChild;
					if (options.direction === VERTICAL) {
						scrollviewView.style.height = newViewSize + "px";
					} else {
						scrollviewView.style.width = newViewSize + "px";
					}
				}
			};

			/**
			 * Binds VirtualListview events
			 * @method _bindEvents
			 * @protected
			 * @member ns.widget.mobile.VirtualListview
			 */
			prototype._bindEvents = function () {
				var self = this,
					scrollEventBound = _updateList.bind(null, self),
					scrollviewClip = self._ui.scrollview && self._ui.scrollview.element;

				if (scrollviewClip) {
					scrollviewClip.addEventListener("scroll", scrollEventBound, false);
					self._scrollEventBound = scrollEventBound;
				}

				parent_bindEvents.call(self, self.element);
			};

			/**
			 * Cleans widget's resources
			 * @method _destroy
			 * @protected
			 * @member ns.widget.mobile.VirtualListview
			 */
			prototype._destroy = function () {
				var self = this,
					scrollview = self._ui.scrollview,
					scrollviewClip = scrollview && scrollview.element,
					scrollviewParent = scrollviewClip && scrollviewClip.parentElement,
					element = self.element,
					elementStyle = element.style,
					options = self.options,
					listItem;

				// Restore start position
				elementStyle.position = "static";
				if (options.direction === VERTICAL) {
					elementStyle.top = "";
				} else {
					elementStyle.left = "";
				}

				if (scrollviewClip) {
					scrollviewClip.removeEventListener("scroll", self._scrollEventBound, false);
				}

				// In case we have a standalone version move element to parent of scrollview
				// call destroy and remove it from DOM
				if (options.standalone) {
					scrollviewParent.appendChild(self.element);
					scrollview.destroy();

					scrollviewParent.removeChild(scrollviewClip);

					self._ui.scrollview = null;
				}

				//Remove li elements.
				// @TODO innerHTML = "" could be faster
				while (element.firstElementChild) {
					listItem = element.firstElementChild;
					element.removeChild(listItem);
				}
			};

			/**
			 * Scrolls list to defined index.
			 * @method scrollToIndex
			 * @param {number} index Scroll Destination index.
			 * @member ns.widget.mobile.VirtualListview
			 */
			prototype.scrollToIndex = function(index) {
				if (index < 0) {
					index = 0;
				}
				if (index >= this.options.numItemData) {
					index = this.options.numItemData - 1;
				}
				this._updateScrollInfo();
				_orderElementsByIndex(this, index);
			};

			/**
			 * Sets iterator function and total number of data based on users arguments.
			 * @method create
			 * @protected
			 * @member ns.widget.mobile.VirtualListview
			 */
			prototype.create = function () {
				this._configureList(arguments);
			};

			// definition
			ns.widget.mobile.VirtualListview = VirtualListview;

			engine.defineWidget(
				"VirtualListview",
				"[data-role='virtuallistview'],[data-role='virtuallist'], .ui-virtuallistview",
				["create", "scrollToIndex"],
				VirtualListview,
				'tizen'
			);
			}(window, window.document, ns));


/*global window, define, ns, console */
/*
* Copyright  2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/*jslint nomen: true */
/**
 * # Scroll Handler
 * Extension for Scroll View Widget, adds scroll handler.
 *
 * ## Default selectors
 * All scrollview selectors with have a class _.ui-scrollhandler_
 * or _data-handler=[DIRECTION]_ will become be enhanced
 *
 * ### HTML examples
 *
 * #### Enhanced scrollview using data-handler attribute
 *
 *		@example
 *		<div data-role="page">
 *			<div data-role="content" data-handler="true">
 *				page content
 *			</div>
 *		</div>
 *
 * #### Enhanced scrollview using css .ui-scrollhandler class
 *
 *		@example
 *		<div data-role="page">
 *			<div data-role="content" class="ui-scrollhandler">
 *				page content
 *			</div>
 *		</div>
 *
 * ## Manual constructor
 * To create the widget manually you can use 2 different APIs, the TAU
 * API or jQuery API
 *
 * ### Enhanced scrollview by using TAU API
 *
 *		@example
 *		<div data-role="page" id="myPage">
 *			<div data-role="content">
 *				pagecontent
 *			<div>
 *		</div>
 *		<script>
 *			var handlerElement = document.getElementById("myPage")
 *						.querySelector("[data-role=content]");
 *			tau.widget.ScrollHandler(handlerElement);
 *		</script>
 *
 * ### Enhanced scrollview by using jQuery API
 *
 *		@example
 *		<div data-role="page" id="myPage">
 *			<div data-role="content">
 *				pagecontent
 *			<div>
 *		</div>
 *		<script>
 *			$("#myPage > div[data-role=content]").scrollhandler();
 *		</script>
 *
 * ## Options for ScrollHandler
 *
 * Options can be set by using data-* attributes or by passing them to
 * the constructor.
 *
 * There is also a method **option** for changing them after widget
 * creation
 *
 * jQuery mobile API is also supported.
 *
 * ### Enable handler
 *
 * This option sets the handler status. The default value is true.
 *
 * You can change this option by all available methods for options
 * changing
 *
 * #### By data-handler attribute
 *
 *		@example
 *		<div data-role="page" id="myPage">
 *			<div data-role="content" data-handler="true">
 *				pagecontent
 *			<div>
 *		</div>
 *
 * #### By passing object to constructor
 *
 *		@example
 *		<div data-role="page" id="myPage">
 *			<div data-role="content">
 *				pagecontent
 *			<div>
 *		</div>
 *		<script>
 *			var handlerElement = document.getElementById("myPage")
 *						.querySelector("[data-role=content]");
 *			tau.widget.ScrollHandler(handlerElement, {
 *				"handler": true
 *			});
 *		</script>
 *
 * #### By using jQuery API
 *
 *		@example
 *		<div data-role="page" id="myPage">
 *			<div data-role="content">
 *				pagecontent
 *			<div>
 *		</div>
 *		<script>
 *			$("#myPage > div[data-role=content]").scrollhandler({
 *				"handler": "true"
 *			});
 *		</script>
 *
 * ### handlerTheme
 *
 * This option sets the handler theme. The default value is inherited
 * or "s" if none found.
 *
 * You can change this option by all available methods for options
 * changing
 *
 * #### By data-handler-theme attribute
 *
 *		@example
 *		<div data-role="page" id="myPage">
 *			<div data-role="content" data-handler-theme="s" handler="true">
 *				pagecontent
 *			<div>
 *		</div>
 *
 *
 * #### By passing object to constructor
 *
 *		@example
 *		<div data-role="page" id="myPage">
 *			<div data-role="content">
 *				pagecontent
 *			<div>
 *		</div>
 *		<script>
 *			var handlerElement = document.getElementById("myPage")
 *						.querySelector("[data-role=content]");
 *			tau.widget.ScrollHandler(handlerElement, {
 *				"handlerTheme": "s"
 *			});
 *		</script>
 *
 * #### By using jQuery API
 *
 *		@example
 *		<div data-role="page" id="myPage">
 *			<div data-role="content">
 *				pagecontent
 *			<div>
 *		</div>
 *		<script>
 *			$("#myPage > div[data-role=content]").scrollhandler({
 *				"handlerTheme": "s"
 *			});
 *		</script>
 *
 * ### direction
 *
 * This option sets the the direction of which the handler is presented.
 * The default value is "y" meaning vertical scroll button.
 *
 * You can change this option by all available methods for options
 * changing
 *
 * #### By data-handler-direction attribute
 *
 *		@example
 *		<div data-role="page" id="myPage">
 *			<div data-role="content" data-direction="y" handler="true">
 *				pagecontent
 *			<div>
 *		</div>
 *
 * #### By passing object to constructor
 *
 *		@example
 *		<div data-role="page" id="myPage">
 *			<div data-role="content">
 *				pagecontent
 *			<div>
 *		</div>
 *		<script>
 *			var handlerElement = document.getElementById("myPage")
 *						.querySelector("[data-role=content]"),
 *			tau.widget.ScrollHandler(handlerElement, {
 *				"scroll": "y"
 *			});
 *		</script>
 *
 * #### By using jQuery API
 *
 *		@example
 *		<div data-role="page" id="myPage">
 *			<div data-role="content">
 *				pagecontent
 *			<div>
 *		</div>
 *		<script>
 *			$("#myPage > div[data-role=content]").scrollhandler({
 *				"scroll": "y"
 *			});
 *		</script>
 *
 * ### scroll
 *
 * This option sets the the direction of which the handler is scrolling.
 * The default value is "y" which means vertical.
 *
 * You can change this option by all available methods for options
 * changing
 *
 * #### By data-handler-scroll attribute
 *
 *		@example
 *		<div data-role="page" id="myPage">
 *			<div data-role="content" data-scroll="x" handler="true">
 *				pagecontent
 *			<div>
 *		</div>
 *
 * #### By passing object to constructor
 *
 *		@example
 *		<div data-role="page" id="myPage">
 *			<div data-role="content">
 *				pagecontent
 *			<div>
 *		</div>
 *		<script>
 *			var handlerElement = document.getElementById("myPage")
 *						.querySelector("[data-role=content]"),
 *			tau.widget.ScrollHandler(handlerElement, {
 *				"scroll": "x"
 *			});
 *		</script>
 *
 * #### By using jQuery API
 *
 *		@example
 *		<div data-role="page" id="myPage">
 *			<div data-role="content">
 *				pagecontent
 *			<div>
 *		</div>
 *		<script>
 *			$("#myPage > div[data-role=content]").scrollhandler({
 *				"scroll": "x"
 *			});
 *		</script>
 *
 * ## Methods
 *
 * ScrollHandler methods can be called through 2 APIs: TAU API and jQuery
 * API (jQuery Mobile-like API). Since this widget extends Scrollview,
 * all the Scrollview methods can be called also.
 *
 * @class ns.widget.mobile.ScrollHandler
 * @extends ns.widget.mobile.Scrollview
 *
 * @author Krzysztof Antoszek <k.antoszek@samsung.com>
 * @author Piotr Karny <p.karny@samsung.com>
 * @author Hyunkook Cho <hk0713.cho@samsung.com>
 * @author Junhyeon Lee <juneh.lee@samsung.com>
 * @author Maciej Urbanski <m.urbanski@samsung.com>
 */
(function (window, document, ns) {
	
				var ScrollHandler = function () {
					var self = this;
					/**
					 * Widget options
					 * @property {Object} options
					 * @property {boolean} [options.handler=true] Enabled flag
					 * @property {string} [options.handlerTheme="s"] Handler theme
					 * @property {"x"|"y"} [options.direction="y"] The direction of the handler
					 * @property {"x"|"y"|"xy"} [options.scroll="y"] The direction of scrolling
					 * @member ns.widget.mobile.ScrollHandler
					 */
					self.options = {
						handler: true,
						handlerTheme: "s",
						direction: "y",
						scroll: "y"
					};
					/**
					 * A collection of handler UI elements
					 * @property {Object} ui
					 * @member ns.widget.mobile.ScrollHandler
					 * @instance
					 */
					self.ui = {
						handler: null,
						thumb: null,
						track: null,
						handle: null,
						page: null
					};
					/**
					 * Event listeners for various events
					 * @property {Object} _callbacks
					 * @property {Function} _callbacks.scrollstart Start handler
					 * @property {Function} _callbacks.scrollupdate Scrolling handler
					 * @property {Function} _callbacks.scrollend Scroll end handler
					 * @property {Function} _callbacks.touchstart Start handler
					 * @property {Function} _callbacks.touchmove Touch move  handler
					 * @property {Function} _callbacks.touchend Touch end handler
					 * @property {Function} _callbacks.resize Window resize handler
					 * @member ns.widget.mobile.ScrollHandler
					 * @protected
					 */
					self._callbacks = {
						scrolstart: null,
						scrollupdate: null,
						scrollend: null,
						touchstart: null,
						touchmove: null,
						touchend: null,
						resize: null
					};
					/**
					 * A drag indicator flag
					 * @property {boolean} [_dragging=false]
					 * @member ns.widget.mobile.ScrollHandler
					 * @protected
					 */
					self._dragging = false;
					/**
					 * Collection of scroll bounds params
					 * @property {Object} _offsets
					 * @member ns.widget.mobile.ScrollHandler
					 * @protected
					 */
					self._offsets = {
						x: 0,
						y: 0,
						maxX: 0,
						maxY: 0
					};
					/**
					 * Holds original pointer events state
					 * @property {string} [_lastPointerEvents=""]
					 * @member ns.widget.mobile.ScrollHandler
					 * @protected
					 */
					self._lastPointerEvents = "";
					/**
					 * Holds information about scrollviews available offset
					 * @property {number} [_availableOffsetX=0]
					 * @member ns.widget.mobile.ScrollHandler
					 * @protected
					 */
					self._availableOffsetX = 0;
					/**
					 * Holds information about scrollviews available offset
					 * @property {number} [_availableOffsetX=0]
					 * @member ns.widget.mobile.ScrollHandler
					 * @protected
					 */
					self._availableOffsetY = 0;
					/**
					 * @property {?number} [_hideTimer=null]
					 * Holds timer ID
					 * @member ns.widget.mobile.ScrollHandler
					 * @protected
					 */
					self._hideTimer = null;
					/**
					 * Holds last mouse position
					 * @property {Object} _lastMouse
					 * @member ns.widget.mobile.ScrollHandler
					 * @protected
					 */
					self._lastMouse = {
						x: 0,
						y: 0
					};
				},
				engine = ns.engine,
				CSSUtils = ns.util.DOM,
				selectors = ns.util.selectors,
				PageClasses = ns.widget.mobile.Page.classes,
				Scrollview = ns.widget.mobile.Scrollview,
				ScrollviewPrototype = Scrollview.prototype,
				ScrollviewBuild = ScrollviewPrototype._build,
				ScrollviewInit = ScrollviewPrototype._init,
				ScrollviewBindEvents = ScrollviewPrototype._bindEvents,
				ScrollviewDestroy = ScrollviewPrototype._destroy,
				max = Math.max,
				min = Math.min,
				floor = Math.floor,
				/**
				 * A collection of ScrollHandlers classes
				 * @property {Object} classes
				 * @property {string} [classes.handler="ui-handler"] Handler main class
				 * @property {string} [classes.directionPrefix="ui-handler-direction"] Direction class prefix
				 * @property {string} [classes.track="ui-handler-track"] Handler track class
				 * @property {string} [classes.thumb="ui-handler-thumb"] Handler thumb button prefix
				 * @property {string} [classes.themePrefix="ui-handller-"] Handler theme class prefix
				 * @property {string} [classes.scrollbarDisabled="scrollbar-disabled"] Scrollview scrollbar disabled class
				 * @property {string} [classes.disabled="disabled"] Disabled class
				 * @property {string} [classes.hideNativeScrollbar="ui-hide-scrollbar"] Hides native scrollbar in scrollview
				 * @member ns.widget.mobile.ScrollHandler
				 * @static
				 * @readonly
				 */
				classes = {
					handler: "ui-handler",
					directionPrefix: "ui-handler-direction-",
					track: "ui-handler-track",
					handle: "ui-handler-handle",
					thumb: "ui-handler-thumb",
					visible: "ui-handler-visible",
					themePrefix: "ui-handler-",
					scrollbarDisabled: "scrollbar-disabled",
					disabled: "disabled",
					hideNativeScrollbar: "ui-hide-scrollbar"
				},
				prototype = new Scrollview();

			ScrollHandler.classes = classes;

			/**
			 * Translates objects position to a new position
			 * @param {ns.widget.mobile.ScrollHandler} self
			 * @param {number} xOffset
			 * @param {number} yOffset
			 * @member ns.widget.mobile.ScrollHandler
			 * @private
			 * @static
			 */
			function translate(self, xOffset, yOffset) {
				var style = null,
					translateString = null;
				if (self.options.handler) {
					style = self.ui.handle.style;
					translateString = "translate3d(" + (xOffset || 0) + "px, " + (yOffset || 0) + "px, 0px)";

					style.webkitTransform = translateString;
					style.mozTransform = translateString;
					style.transform = translateString;
				}
			}

			/**
			 * Sets handler position according to scrollviews position
			 * @param {ns.widget.mobile.ScrollHandler} self
			 * @member ns.widget.mobile.ScrollHandler
			 * @private
			 * @static
			 */
			function syncHandleWithScroll(self) {
				var position = self.getScrollPosition(),
					offsets = self._offsets,
					direction = self.options.direction,
					x = floor(min(position.x, self._availableOffsetX) / self._availableOffsetX * offsets.maxX),
					y = floor(min(position.y, self._availableOffsetY) / self._availableOffsetY * offsets.maxY);

				if (isNaN(x) === true) {
					x = offsets.x;
				}

				if (isNaN(y) === true) {
					y = offsets.y;
				}

				translate(
					self,
						direction === "y" ? 0 : x,
						direction === "x" ? 0 : y
				);

				offsets.x = x;
				offsets.y = y;
			}

			/**
			 * Handles scroll start event
			 * @param {ns.widget.mobile.ScrollHandler} self
			 * @member ns.widget.mobile.ScrollHandler
			 * @private
			 * @static
			 */
			function handleScrollstart(self) {
				if (self._dragging === false) {
					syncHandleWithScroll(self);
					if (self._hideTimer) {
						window.clearTimeout(self._hideTimer);
					}
					self.ui.handler.classList.add(classes.visible);
				}
			}

			/**
			 * Handles scroll update event
			 * @param {ns.widget.mobile.ScrollHandler}
			 * @member ns.widget.mobile.ScrollHandler
			 * @private
			 * @static
			 */
			function handleScrollupdate(self) {
				if (self._dragging === false) {
					if (self._hideTimer) {
						window.clearTimeout(self._hideTimer);
					}
					syncHandleWithScroll(self);
				}
			}

			/**
			 * Handles scroll stop event
			 * @param {ns.widget.mobile.ScrollHandler}
			 * @member ns.widget.mobile.ScrollHandler
			 * @private
			 * @static
			 */
			function handleScrollstop(self) {
				if (self._dragging === false) {
					syncHandleWithScroll(self);
					if (self._hideTimer) {
						window.clearTimeout(self._hideTimer);
					}
					self._hideTimer = window.setTimeout(function () {
						self.ui.handler.classList.remove(classes.visible);
					}, 1500);
				}
			}

			/**
			 * Handles dragging
			 * @param {ns.widget.mobile.ScrollHandler} self
			 * @param {number} x
			 * @param {number} y
			 * @member ns.widget.mobile.ScrollHandler
			 * @private
			 * @static
			 */
			function handleDragging(self, x, y) {
				var lastMouse = self._lastMouse,
					offsets = self._offsets,
					direction = self.options.direction,
					diffX = lastMouse.x - x,
					diffY = lastMouse.y - y;

				lastMouse.x = x;
				lastMouse.y = y;

				// translate with direction locking
				offsets.x += -diffX;
				offsets.y += -diffY;

				// cap to between limits
				offsets.x = max(0, offsets.x);
				offsets.y = max(0, offsets.y);
				offsets.x = min(offsets.maxX, offsets.x);
				offsets.y = min(offsets.maxY, offsets.y);

				translate(
					self,
					direction === "y" ? 0 : offsets.x,
					direction === "x" ? 0 : offsets.y
				);

				self.scrollTo(
					direction === "y" ? 0 : offsets.x / offsets.maxX * self._availableOffsetX,
					direction === "x" ? 0 : offsets.y / offsets.maxY * self._availableOffsetY
				);

				if (self._hideTimer) {
					window.clearTimeout(self._hideTimer);
				}
			}

			/**
			 * Handles touch start event
			 * @param {ns.widget.mobile.ScrollHandler} self
			 * @param {MouseEvent|TouchEvent} event
			 * @member ns.widget.mobile.ScrollHandler
			 * @private
			 * @static
			 */
			function handleTouchstart(self, event) {
				var lastMouse = self._lastMouse,
					touches = event.touches,
					touch = touches && touches[0],
					parent = self.element.parentNode;
				self._dragging = true;
				self._lastPointerEvents = CSSUtils.getCSSProperty(parent, "pointer-events");
				// this is just for scroll speedup purposes
				// through method since we are using important flag
				parent.style.setProperty("pointer-events", "none", "important");
				lastMouse.x = touch ? touch.clientX : event.clientX;
				lastMouse.y = touch ? touch.clientY : event.clientY;

				event.stopImmediatePropagation();
				event.preventDefault();
			}

			/**
			 * Handles touch move events
			 * @param {ns.widget.mobile.ScrollHandler} self
			 * @param {MouseEvent|TouchEvent} event
			 * @member ns.widget.mobile.ScrollHandler
			 * @private
			 * @static
			 */
			function handleTouchmove(self, event) {
				var touches = event.touches,
					touch = touches && touches[0],
					x = 0,
					y = 0;
				// check for exactly 1 touch event
				// or a mouse event
				if (self._dragging && (touches === undefined || touches.length <= 1)) {
					event.stopImmediatePropagation();
					event.preventDefault();

					x = touch ? touch.clientX : event.clientX;
					y = touch ? touch.clientY : event.clientY;
					handleDragging(self, x, y);
				}
			}

			/**
			 * Handles touch end event
			 * @param {ns.widget.mobile.ScrollHandler}
			 * @param {MouseEvent|TouchEvent}
			 * @member ns.widget.mobile.ScrollHandler
			 * @private
			 * @static
			 */
			function handleTouchend(self, event) {
				var lastPointerEvents = self._lastPointerEvents,
					parentStyle = self.element.parentNode.style;
				if (self._dragging) {
					parentStyle.removeProperty("pointer-events");
					if (lastPointerEvents !== "auto") {
						parentStyle.setProperty("pointer-events", lastPointerEvents);
					}
					self._dragging = false;

					event.stopImmediatePropagation();
					event.preventDefault();

					if (self._hideTimer) {
						window.clearTimeout(self._hideTimer);
					}
					self._hideTimer = window.setTimeout(function () {
						self.ui.handler.classList.remove(classes.visible);
					}, 1500);
				}
			}

			/**
			 * Build the scrollhander and scrollview DOM
			 * @param {HTMLElement} element
			 * @return {HTMLElement}
			 * @method _build
			 * @member ns.widget.mobile.ScrollHandler
			 * @protected
			 */
			prototype._build = function (element) {
				var node,
					nodeStyle,
					scrollviewViewStyle,
					handler = document.createElement("div"),
					handle = document.createElement("div"),
					track = document.createElement("div"),
					thumb = document.createElement("div"),
					options = this.options,
					ui = this.ui;

				// Set scroll option for scrollview
				options.scroll = options.direction === "y" ? "y" : "x";
				node = ScrollviewBuild.call(this, element);

				handler.className = classes.handler + " " + classes.themePrefix + options.handlerTheme + " " + classes.directionPrefix + options.direction;
				handle.className = classes.handle;
				thumb.className = classes.thumb;
				track.className = classes.track;

				handle.setAttribute("tabindex", 0);
				handle.setAttribute("aria-label", (options.direction === "y" ? "Vertical" : "Horizontal") + " handler, double tap and move to scroll");

				handle.appendChild(thumb);
				track.appendChild(handle);
				handler.appendChild(track);

				node.appendChild(handler);

				// Force scrollview to be full width of container
				nodeStyle = node.style;
				scrollviewViewStyle = node.firstElementChild.style;

				// NOTE: to hide native scrollbar, make sure that theme includes
				// *display* property set to *none* for
				// .ui-content.ui-scrollview-clip.ui-hide-scrollbar::-webkit-scrollbar
				element.classList.add(classes.hideNativeScrollbar);

				if (options.direction === "x") {
					scrollviewViewStyle.display = "inline-block";
					scrollviewViewStyle.minWidth = "100%";
				}
				if (options.direction === "y") {
					scrollviewViewStyle.display = "block";
					nodeStyle.minWidth = "100%";
				}

				ui.handler = handler;
				ui.handle = handle;
				ui.track = track;
				ui.thumb = thumb;

				return node;
			};

			/**
			 * Init the scrollhander and scrollview
			 * @param {HTMLElement} element
			 * @method _init
			 * @protected
			 * @member ns.widget.mobile.ScrollHandler
			 */
			prototype._init = function (element) {
				var self = this,
					ui = self.ui,
					page = ui.page;

				ScrollviewInit.call(self, element);

				if (ui.handler === null) {
					ui.handler = element.querySelector("." + classes.handler);
				}

				if (ui.track  === null) {
					ui.track = element.querySelector("." + classes.track);
				}

				if (ui.handle === null) {
					ui.handle = element.querySelector("." + classes.handle);
				}

				if (ui.thumb  === null) {
					ui.thumb = element.querySelector("." + classes.thumb);
				}

				if (page === null) {
					page = selectors.getClosestByClass(element, PageClasses.uiPage);
				}
				ui.page = page;

				self.enableHandler(true);
			};

			/**
			 * Refreshes the scrollhander bounds and dimensions
			 * @method _refresh
			 * @protected
			 * @member ns.widget.mobile.ScrollHandler
			 */
			prototype._refresh = function () {
				var self = this,
					element = self.element,
					offsets = self._offsets,
					ui = self.ui,
					handle = ui.handle,
					handleStyle = handle.style,
					parent = element.parentNode,
					childrenHeight = 0,
					clipHeight = CSSUtils.getElementHeight(element, "inner", true),
					clipWidth = CSSUtils.getElementWidth(element, "inner", true),
					view = element.querySelector("." + Scrollview.classes.view),
					viewHeight = CSSUtils.getElementHeight(view, "inner", true),
					viewWidth = CSSUtils.getElementWidth(view, "inner", true),
					marginTop = null,
					child = parent.firstElementChild;

				while (child) {
					// filter out current scrollview
					if (child !== element) {
						childrenHeight += CSSUtils.getElementHeight(child, "inner", true);
					} else if (marginTop === null) {
						marginTop = childrenHeight;
					}
					child = child.nextElementSibling;
				}

				marginTop = marginTop || 0;

				if (self.options.direction === 'y') {
					handleStyle.height = floor(clipHeight / viewHeight * clipHeight) + 'px';
				} else {
					handleStyle.width = floor(clipWidth / viewWidth * clipWidth) + 'px';
				}

				offsets.maxX = floor(max(0, clipWidth - CSSUtils.getElementWidth(handle, "inner", true)));
				offsets.maxY = floor(max(0, clipHeight - CSSUtils.getElementHeight(handle, "inner", true)));

				self._availableOffsetX = max(0, viewWidth - clipWidth);
				self._availableOffsetY = max(0, viewHeight - clipHeight);
				ui.handler.style.marginTop = marginTop + "px";
			};

			/**
			 * Binds the scrollhander and scrollview events
			 * @param {HTMLElement} element
			 * @method _bindEvents
			 * @protected
			 * @member ns.widget.mobile.ScrollHandler
			 */
			prototype._bindEvents = function (element) {
				var self = this,
					callbacks = self._callbacks,
					ui = self.ui;
				ScrollviewBindEvents.call(self, element);

				callbacks.scrollstart = handleScrollstart.bind(null, self);
				callbacks.scrollupdate = handleScrollupdate.bind(null, self);
				callbacks.scrollstop = handleScrollstop.bind(null, self);
				callbacks.touchstart = handleTouchstart.bind(null, self);
				callbacks.touchmove = handleTouchmove.bind(null, self);
				callbacks.touchend = handleTouchend.bind(null, self);
				callbacks.resize = self._refresh.bind(self);

				element.addEventListener("scrollstart", callbacks.scrollstart, false);
				element.addEventListener("scrollupdate", callbacks.scrollupdate, false);
				element.addEventListener("scrollstop", callbacks.scrollstop, false);
				ui.handle.addEventListener("vmousedown", callbacks.touchstart, false);
				ui.page.addEventListener("pageshow", callbacks.resize, false);
				document.addEventListener("vmousemove", callbacks.touchmove, false);
				document.addEventListener("vmouseup", callbacks.touchend, false);
				window.addEventListener("throttledresize", callbacks.resize, false);

			};

			/**
			 * Enables/disables handler
			 *
			 * #### TAU API
			 *
			 *		@example
			 *		<div data-role="page" id="myPage">
			 *			<div data-role="content">
			 *				pagecontent
			 *			<div>
			 *		</div>
			 *		<script>
			 *			var handlerElement = document.getElementById("myPage")
			 *						.querySelector("[data-role=content]"),
			 *				scrollhandler = tau.widget.ScrollHandler(handlerElement);
			 *			scrollhandler.enableHandler(true);
			 *		</script>
			 *
			 * #### jQuery API
			 *
			 *		@example
			 *		<div data-role="page" id="myPage">
			 *			<div data-role="content">
			 *				pagecontent
			 *			<div>
			 *		</div>
			 *		<script>
			 *			#("#myPage > div[data-role=content]).scrollhandler("enableHandler", true);
			 *		</script>
			 *
			 * @param {boolean} enable
			 * @return {boolean}
			 * @method enableHandler
			 * @member ns.widget.mobile.ScrollHandler
			 */
			prototype.enableHandler = function (enable) {
				var self = this,
					scrollBarDisabledClass = classes.scrollbarDisabled,
					disabledClass = classes.disabled,
					element = self.element,
					parentClassList = element.parentNode.classList,
					elementClassList = element.classList;

				if (enable !== undefined) {
					self.options.handler = enable;
					if (enable) {
						parentClassList.add(scrollBarDisabledClass);
						elementClassList.remove(disabledClass);
						self._refresh();
					} else {
						parentClassList.remove(scrollBarDisabledClass);
						elementClassList.add(disabledClass);
					}
				}

				return self.options.handler;
			};

			/**
			 * Sets the handlers theme
			 * @param {string} theme
			 * @method _setHandlerTheme
			 * @protected
			 * @member ns.widget.mobile.ScrollHandler
			 */
			prototype._setHandlerTheme = function (theme) {
				var elementClassList = this.element.classList,
					themePrefix = classes.themePrefix,
					themeClass = themePrefix + theme;
				if (elementClassList.contains(themeClass) === false) {
					elementClassList.remove(themePrefix + this.options.handlerTheme);
					elementClassList.add(themeClass);
				}
			};

			/**
			 * Destroys the scrollhander and scrollview DOM
			 * @method _destroy
			 * @protected
			 * @member ns.widget.mobile.ScrollHandler
			 */
			prototype._destroy = function () {
				var self = this,
					ui = self.ui,
					callbacks = self._callbacks,
					element = self.element;

				// Restore native scrollbar
				element.classList.remove(classes.hideNativeScrollbar);
				element.removeEventListener("scrollstart", callbacks.scrollstart, false);
				element.removeEventListener("scroll", callbacks.scrollupdate, false);
				element.removeEventListener("scrollstop", callbacks.scrollstop, false);
				ui.handle.removeEventListener("vmousedown", callbacks.touchstart, false);
				ui.page.removeEventListener("pageshow", callbacks.touchstart, false);
				document.removeEventListener("vmousemove", callbacks.touchmove, false);
				document.removeEventListener("vmouseup", callbacks.touchend, false);
				window.removeEventListener("throttledresize", callbacks.resize, false);

				ScrollviewDestroy.call(self);
			};

			ScrollHandler.prototype = prototype;

			ns.widget.mobile.ScrollHandler = ScrollHandler;
			engine.defineWidget(
				"ScrollHandler",
				"[data-role='content'][data-handler='true']:not([data-scroll='none']):not(.ui-scrollview-clip):not(.ui-scrolllistview),[data-handler='true'], .ui-scrollhandler",
				[
					"enableHandler",
					"scrollTo",
					"ensureElementIsVisible",
					"centerToElement",
					"getScrollPosition",
					"skipDragging",
					"translateTo"
				],
				ScrollHandler,
				"tizen"
			);
			}(window, window.document, ns));


/*global $, ns, define*/
/*
* Copyright  2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/*jslint nomen: true, plusplus: true, white: true, browser: true */
/**
 * #Virtual Grid Widget
 * Widget creates special grid which can contain big number of items.
 *
 * @class ns.widget.mobile.VirtualGrid
 * @extends ns.widget.mobile.VirtualListview
 * @author Maciej Urbanski <m.urbanski@samsung.com>
 * @author Piotr Karny <p.karny@samsung.com>
 */
(function (window, document, ns) {
	
				var VirtualList = ns.widget.mobile.VirtualListview,
				parentPrototype = VirtualList.prototype,
				engine = ns.engine,
				domUtils = ns.util.DOM,
				/**
				 * @property {Function} utilsObjectMerge
				 * @private
				 * @member ns.widget.mobile.VirtualGrid
				 * @static
				 */
				utilsObjectMerge = ns.util.object.merge,
				// @TODO HORIZONTAL is currently not used, it will be used when horizontal scrolling is ready
				/**
				 * @property {string} HORIZONTAL="x" constans for horizontal virtual grid
				 * @private
				 * @member ns.widget.mobile.VirtualGrid
				 * @static
				 */
				HORIZONTAL = "x",
				/**
				 * @property {string} VERTICAL="y" constans for vertical virtual grid
				 * @private
				 * @member ns.widget.mobile.VirtualGrid
				 * @static
				 */
				VERTICAL = "y",
				classes = {
					WRAP_BLOCK_Y: "ui-virtualgrid-wrapblock-y",
					WRAP_BLOCK_X: "ui-virtualgrid-wrapblock-x",
					ITEM: "virtualgrid-item"
				},
				VirtualGrid = function () {
					return this;
				},
				prototype = new VirtualList();

			prototype._configure = function () {
				var self = this;

				// Call parent _configure
				parentPrototype._configure.apply(self, arguments);

				/**
				 * @property {Object} options
				 * @property {number} options.numItemData number of lines in the grid
				 * @property {number} [options.rawNumItemData] number of items inside data source
				 * @property {string} options.direction='y' direction for scrolling elements
				 * @property {number} options.row number of lines displayed at once
				 * @property {number} options.itemsPerLine number of elements per one line
				 * @property {Function} [options.listItemUpdater=null] Method which modifies list item, depended at specified index from database.
				 * @property {boolean} [options.standalone=false] If true scrollview instance will be created inside of the widget
				 * **Method may be overriden by developer using {@link ns.widget.mobile.VirtualListview#create .create} method with proper arguments.**
				 */
				self.options = utilsObjectMerge({}, self.options, {
					numItemData: 0,
					direction: VERTICAL,
					row: 50,
					itemsPerLine: 1,
					listItemUpdater: null,
					standalone: false
				});

				/**
				 * @property {Object} ui Holds UI elements of the widget
				 * @member ns.widget.mobile.VirtualGrid
				 */
				self._ui = utilsObjectMerge({}, self._ui);

				/**
				 * @property {number} _currentIndex Current zero-based index of data set.
				 * @member ns.widget.mobile.VirtualGrid
				 */
				self._currentIndex = 0;

				// @TODO Developer currently needs to define direction="x" for VirtualGrid and scroll="x" for container with scrollview,
				// @TODO ...it would be better to set scroll="x" for scroll view when it's not forced (defined as HTML attribute)
			};

			prototype._build = function (element) {
				parentPrototype._build.apply(this, arguments);

				if (this.options.direction === HORIZONTAL) {
					element.style.height = "100%";
				}

				return element;
			};

			/**
			 * Determines grid sizes, row and column count.
			 * Temporary adds one element into list to fetch it's sizes.
			 * @method _setLineSize
			 * @protected
			 */
			prototype._setLineSize = function () {
				var self = this,
					options = self.options,
					tempElement = document.createElement('div'),
					tempFirstChild,
					tempElementFromTemplate,
					list = self.element,
					size,
					containerSize;

				// Add temporary element for fetching sizes
				list.appendChild(tempElement);
				self._updateListItem(tempElement, 0);
				tempFirstChild = tempElement.firstElementChild;
				tempElementFromTemplate = tempFirstChild.firstElementChild;

				// [NOTE] grid cells are floated to left for vertical scrolling
				// First row child element is the grid cell, it gets styles from CSS stylesheet.
				// We are clearing float to make list row expand to whole list width.
				// To fetch the raw width of template element we are going deeper (tempElementFromTemplate)
				// This ensures we fetch the authored value of width for grid cell element.

				// @TODO consider getting the height/width (.lineSize) each time a new line is parsed, currently all lines are based on the size of first element
				if (options.direction === VERTICAL) {
					// Reset width of first child set by updateListElement
					tempFirstChild.style.width = "";
					tempFirstChild.style.float = "none";
					// Fetch original width with everything (including margins)
					size = domUtils.getElementWidth(tempElementFromTemplate, "outer", true, true);
					// .lineSize is required to set the real height or width of a line
					options.lineSize = tempFirstChild.offsetHeight;
					containerSize = list.offsetWidth;
				} else {
					// @TODO create proper styles for horizontal scrolling
					size = tempElement.offsetHeight;
					if (options.standalone) {
						containerSize = self._ui.scrollview.element.offsetHeight;
					} else {
						containerSize = list.offsetHeight;
					}
					// .lineSize is required to set the real height or width of a line
					options.lineSize = tempFirstChild.offsetWidth;
				}

				// Remove element after fetching sizes
				list.removeChild(tempElement);

				// Calculate item count per line
				options.itemsPerLine = Math.max(Math.floor(containerSize / size), 1);
				// Save original element count
				options.rawNumItemData = options.numItemData;
				// Calculate limited element count
				options.numItemData = Math.ceil(options.numItemData / options.itemsPerLine);
			};

			/**
			 * Configures list. Sets data source and iterator behavior.
			 * @method _configureList
			 * @protected
			 * @param {Object} argumentsArray
			 */
			prototype._configureList = function (argumentsArray) {
				var self = this,
					options = self.options,
					args = argumentsArray[0] || {};

				// @TODO this is easy to use, but the code is confusing
				// and doesn't allow easy merging
				if (typeof args.itemData === "function" && (typeof args.numItemData === "function" || typeof args.numItemData === "number")) {
					if (typeof args.numItemData === "function") {
						options.numItemData = args.numItemData();
					} else {
						options.numItemData = args.numItemData <= 0 ? 0 : args.numItemData;
					}
					self.itemData = args.itemData;
				}

				// @TODO all options should be merged at once without the need of separate defining variables
				options.direction = args.direction || options.direction;

				// @TODO set minimum set size depending on current screen size
				options.row = Math.max(20, options.row);

				self._setLineSize();

				self._buildList();

				//Update scroll info: scroll position etc...
				if (options.standalone) {
					self._updateScrollInfo();
				}
			};

			/**
			 * @method _updateListItem
			 * Prepares list items.
			 * This method is used once while creating widget and later for every list update (on scroll for example)
			 * @param {HTMLElement} element Grid line element (usually a div with proper class)
			 * @param {number} index Index of the item to process
			 * @protected
			 */
			prototype._updateListItem = function (element, index) {
				var self = this,
					options = self.options,
					updateFunction = options.listItemUpdater,
					direction = options.direction,
					itemData = self.itemData,
					$jqTmpl = self._ui.$jqTmpl,
					itemsPerLine = options.itemsPerLine,
					rawNumItemData = options.rawNumItemData,
					elementPercentSize = (100 / itemsPerLine) + "%",
					// Offset for fetching elements from next line
					itemsOffset = itemsPerLine * index,
					templateElement,
					fragment,
					nextItemIndex,
					i = 0;

				// Clean insides before creating new content
				element.innerHTML = "";

				fragment = document.createDocumentFragment();
				nextItemIndex = itemsOffset + i;
				// Add items until line end or data source end
				// rawNumItemData may be undefined for first time size checking
				while (i < itemsPerLine && (rawNumItemData === undefined || nextItemIndex < rawNumItemData)) {
					//@TODO THIS IS A JQUERY INCLUSION IN A TAU WIDGET!!!
					//@TODO FIX THIS!!!
					templateElement = document.createElement('div');
					// Set item-in-line size
					templateElement.style[direction === VERTICAL ? "width" : "height"] = elementPercentSize;

					templateElement.classList.add(classes.ITEM);

					if (typeof updateFunction === "function") {
						updateFunction(templateElement, nextItemIndex);
					} else {
						templateElement.appendChild($.tmpl($jqTmpl, itemData(nextItemIndex))[0]);
					}

					fragment.appendChild(templateElement);

					i++;
					nextItemIndex = itemsOffset + i;
				}

				element.appendChild(fragment);
				engine.createWidgets(element);


				if (options.lineSize) {
					element.style[direction === VERTICAL ? "height" : "width"] = options.lineSize + "px";
				}
				element.classList.add(direction === VERTICAL ? classes.WRAP_BLOCK_Y : classes.WRAP_BLOCK_X);
			};

			/**
			 * List of classes used inside VirtualGrid
			 * @property {Object} classes
			 * @property {string} classes.WRAP_BLOCK_Y="ui-virtualgrid-wrapblock-y"
			 * @property {string} classes.WRAP_BLOCK_X="ui-virtualgrid-wrapblock-x"
			 * @property {string} classes.ITEM="virtualgrid-item"
			 * @static
			 */
			VirtualGrid.classes = classes;

			VirtualGrid.prototype = prototype;

			ns.widget.mobile.VirtualGrid = VirtualGrid;

			engine.defineWidget(
				"VirtualGrid",
				"[data-role=virtualgrid], .ui-virtualgrid",
				["create"],
				VirtualGrid,
				'mobile'
			);

			}(window, window.document, ns));

/*global window, define */
/*
* Copyright  2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/*jslint nomen: true */
/**
 * # Slider Widget
 * Slider widget changes browser input with type range to sliders
 *
 * ## Default selectors
 * In default all **INPUT** tags with type equals _range_ are changed
 * to Tizen WebUI sliders.
 * In addition all **INPUT** elements with _data-role=range_ and _data-role=slider_
 * and class _ui-tizenslider_ are changed to Tizen Web UI sliders.
 *
 * ###HTML Examples
 *
 * ####Create slider input
 *
 *		@example
 *		<input type="range" name="slider-1" id="slider" value="60" min="0" max="100">
 *
 * ## Manual constructor
 * For manual creation of slider widget you can use constructor of widget
 * from **tau** namespace:
 *
 *		@example
 *		<input id="slider" type="range" name="slider-1"
 *		 value="60" min="0" max="100">
 *		<script>
 *			var sliderElement = document.getElementById("slider"),
 *				slider = tau.widget.TizenSlider(sliderElement);
 *		</script>
 *
 * Constructor has one required parameter **element** which
 * is base **HTMLElement** to create widget. We recommend get this element
 * by method *document.getElementById*. Second parameter is **options**
 * and it is a object with options for widget.
 *
 *		@example
 *		<input id="slider" type="range" name="slider-1"
 *		 value="60" min="0" max="100">
 *		<script>
 *			var sliderElement = document.getElementById("slider"),
 *				slider = tau.widget.TizenSlider(sliderElement, {mini: true});
 *		</script>
 *
 * If jQuery library is loaded, its method can be used:
 *
 *		@example
 *		<input id="slider" type="range" name="slider-1"
 *		 value="60" min="0" max="100">
 *		<script>
 *			$("#slider").tizenslider({mini: true});
 *		</script>
 * jQuery Mobile constructor has one optional parameter **options**
 * and it is a object with options for widget.
 *
 * ##Methods
 *
 * To call method on widget you can use one of existing API:
 *
 * First API is from tau namespace:
 *
 *		@example
 *		<input id="slider" type="range" name="slider"
 *		 value="60" min="0" max="100">
 *		<script>
 *		var slider = document.getElementById("slider"),
 *			slider = tau.widget.TizenSlider(slider);
 *
 *		// slider.methodName(methodArgument1, methodArgument2, ...);
 *		// for example
 *		var value = slider.value("5");
 *		</script>
 *
 * Second API is jQuery Mobile API and for call _methodName_ you can use:
 *
 *		@example
 *		<input id="slider" type="range" name="slider"
 *		 value="60" min="0" max="100">
 *		<script>
 *		//$("#slider").tizenslider("methodName", argument1, argument2, ...);
 *		//for example
 *		$("#slider").tizenslider("value", "5");
 *		</script>
 *
 * @class ns.widget.mobile.TizenSlider
 * @extends ns.widget.mobile.Slider
 * @author Jadwiga Sosnowska <j.sosnowska@samsung.com>
 * @author Krzysztof Antoszek <k.antoszek@samsung.com>
 * @author Maciej Moczulski <m.moczulski@samsung.com>
 * @author Maciej Urbanski <m.urbanski@samsung.com>
 * @author Piotr Karny <p.karny@samsung.com>
 */
(function (window, document, ns) {
	
				var Slider = ns.widget.mobile.Slider,
				Button = ns.widget.mobile.Button,
				engine = ns.engine,
				events = ns.event,
				objectUtils = ns.util.object,
				DOM = ns.util.DOM,
				POPUP_WIDTH = {
					"SMALL": "2.3rem",
					"MEDIUM": "2.8rem",
					"LARGE": "3.0rem"
				},
				FONT_SIZE = {
					"SMALL": "0.95rem",
					"MEDIUM": "0.85rem",
					"LARGE": "0.65rem",
					"DEFAULT": "0.45rem"
				},
				FONT_TOP = {
					"SMALL": "0",
					"MEDIUM": "-0.01rem",
					"LARGE": "-0.1rem",
					"DEFAULT": "-0.15rem"
				},
				TizenSlider = function () {
					Slider.call(this);
					// Some properties for example .popup must be defined once per slider
					// we need to make a copy of base options, because simple assigment
					// would create references to a single object
					this.options = this.options ? objectUtils.copy(this.options) : {};
					// Redefine this._ui use instance property not prototype property
					// in further operations
					this._ui = this._ui || {};
					// @TODO recheck other properties for potential issues
					// like this._ui
					this._popup = null;
				},
				sliderBuild,
				sliderInit,
				sliderConfigure,
				sliderBindEvents,
				slider_refresh,
				slider_setValue,
				slider_getValue;

			/**
			 * Dictionary for TizenSlider related css class names
			 * @property {Object} classes
			 * @member ns.widget.mobile.TizenSlider
			 * @static
			 * @readonly
			 */
			TizenSlider.classes = {
				uiSliderPopup: "ui-slider-popup",
				uiSliderPopupContainer: "ui-slider-popup-container",
				uiSliderLeftPrefix: "ui-slider-left-",
				uiSliderRightPrefix: "ui-slider-right-",
				uiSliderLeftText: "ui-slider-left-text",
				uiSliderRightText: "ui-slider-right-text",
				uiSliderHandlePress: "ui-slider-handle-press",
				uiSliderCenter: "ui-slider-center"
			};

			TizenSlider.prototype = new Slider();
			sliderConfigure = TizenSlider.prototype._configure;
			sliderBuild = TizenSlider.prototype._build;
			sliderInit = TizenSlider.prototype._init;
			sliderBindEvents = TizenSlider.prototype._bindEvents;
			slider_refresh = TizenSlider.prototype._refresh,
			slider_setValue = TizenSlider.prototype._setValue
			slider_getValue = TizenSlider.prototype._getValue;

			/**
			 * Configure TizenSlider widget
			 * @method _configure
			 * @protected
			 * @member ns.widget.mobile.TizenSlider
			 */
			TizenSlider.prototype._configure = function () {
				/**
				 * All possible widget options
				 * @property {Object} options
				 * @property {boolean} [options.popup=true] enables popup
				 * @property {boolean} [options.center=false] creates additional markup to pointing center of the slider
				 * @property {string} [options.icon=""] icon type
				 * @property {string} [options.innerLabel=false] Displays the value inside the handler
				 * @property {string} [options.textLeft=""] text attached to left
				 * @property {string} [options.textRight=""] text attached to right
				 * @member ns.widget.mobile.TizenSlider
				 */
				var options = this.options;

				if (typeof sliderConfigure === "function") {
					sliderConfigure.call(this);
				}
				options.popup = false;
				options.center = false;
				options.innerLabel = false;
				options.icon = "";
				options.textLeft = "";
				options.textRight = "";
			};

			/**
			 * Check if value is not empty
			 * @method getValueLength
			 * @param {number} value
			 * @return {number}
			 * @private
			 * @static
			 * @member ns.widget.mobile.TizenSlider
			 */
			function getValueLength(value) {
				return (new String(value)).length;
			}

			/**
			 * Creates popup element and appends it container passed as argument
			 * @method _createPopup
			 * @param {HTMLElement} container
			 * @return {ns.widget.Popup} reference to new widget instance
			 * @protected
			 * @member ns.widget.mobile.TizenSlider
			 */
			TizenSlider.prototype._createPopup = function (container) {
				var classes = TizenSlider.classes,
					popup,
					popupInstance;

				// Create element and append it to slider
				popup = document.createElement("div");
				container.appendChild(popup);
				// Create widget instance out of popup element
				popupInstance = engine.instanceWidget(popup, "Popup", {
					positionTo: "origin", // popup with arrow
					link: this._ui.handle.id, // positioned to slider's element
					transition: "none",
					noScreen: true,
					directionPriority: [
						"top",
						"bottom"
					],
					tolerance: "10,0,10,0",
					specialContainerClass: classes.uiSliderPopupContainer
				});
				popup.classList.add(classes.uiSliderPopup);

				return popupInstance;
			};

			/**
			 * Creates slider with the marked center element
			 * @method _createCenter
			 * @param {HTMLElement} slider
			 * @return {HTMLElement} returns the inserted element
			 * @protected
			 * @member ns.widget.mobile.TizenSlider
			 */
			TizenSlider.prototype._createCenter = function (slider) {
				var centerElement = document.createElement("div");
				centerElement.className = TizenSlider.classes.uiSliderCenter;

				return slider.insertBefore(centerElement, slider.childNodes[0]);
			};

			/**
			 * Updates popup state
			 * @method _updateSlider
			 * @member ns.widget.mobile.TizenSlider
			 * @protected
			 */
			TizenSlider.prototype._updateSlider = function () {
				var self = this,
					newValue,
					options = self.options,
					element = self.element,
					popupElement;

				// As the options.popup could change
				// it may be required to create popup
				if (self.options.popup){
					if (!self._popup) {
						self._popup = self._createPopup(self._ui.container);
					}

					popupElement = self._popup.element;
				}

				self._ui.handle.removeAttribute("title");

				newValue = parseInt(element.value, 10);

				if (newValue !== self.currentValue) {
					self.currentValue = newValue;

					// Set same value for popup element if it exists
					if (popupElement) {
						popupElement.innerHTML = newValue;
					}

					self._refresh();

					events.trigger(element, "update", newValue);
				} else {
					// If text doesn't change reposition only popup
					// no need to run full refresh
					if (self._popup) {
						self._popup.refresh();
					}
				}
			};

			/**
			 * Show popup for tizenslider
			 * @method _showPopup
			 * @member ns.widget.mobile.TizenSlider
			 * @protected
			 */
			TizenSlider.prototype._showPopup = function () {
				var self = this;

				if (self.options.popup && !self.popupVisible) {
					self._popup.open();
					self.popupVisible = true;
				}
			};

			/**
			 * Hide popup for tizenslider
			 * @method _hidePopup
			 * @member ns.widget.mobile.TizenSlider
			 * @protected
			 */
			TizenSlider.prototype._hidePopup = function () {
				var self = this;

				if (self.options.popup && self.popupVisible) {
					self._popup.close();
					self.popupVisible = false;
				}
			};

			/**
			 * Set options for popup in tizenslider
			 * @method _setOption
			 * @param {string} key
			 * @param {number} value
			 * @member ns.widget.mobile.TizenSlider
			 * @protected
			 */
			TizenSlider.prototype._setOption = function (key, value) {
				var needToChange = (value !== this.options[key]);

				if (needToChange) {
					switch (key) {
					case "popup":
						this.options.popup = value;
						if (value) {
							this._updateSlider();
						} else {
							this._hidePopup();
						}
						break;
					case "center":
						this.options.center = value;
					}
				}
			};

			/**
			 * Close popup by triggering vmouseup event
			 * @method _closePopup
			 * @member ns.widget.mobile.TizenSlider
			 * @protected
			 */
			TizenSlider.prototype._closePopup = function () {
				this._hidePopup();
			};

			/**
			 * Build TizenSlider
			 * @method _build
			 * @private
			 * @param {HTMLElement} element
			 * @return {HTMLElement}
			 * @member ns.widget.mobile.TizenSlider
			 */
			TizenSlider.prototype._build = function (element) {
				var self = this,
					options = self.options,
					slider,
					icon = options.icon,
					textRight = options.textRight,
					textLeft = options.textLeft,
					textLength,
					elemLeft,
					elemRight,
					marginLeft,
					marginRight,
					sliderContainer,
					inner,
					minValue,
					maxValue,
					classes = TizenSlider.classes,
					btnClasses = Button.classes,
					sliderContainerStyle,
					ui = self._ui;

				self.currentValue = null;

				sliderBuild.call(self, element);
				sliderInit.call(self, element);

				slider = ui.slider;
				sliderContainer = ui.container;
				sliderContainerStyle = sliderContainer.style;

				// Create popup for element
				if (options.popup) {
					self._popup = self._createPopup(sliderContainer);
				}

				if (options.center) {
					ui.centerElement = self._createCenter(slider);
				}

				maxValue = parseInt(element.getAttribute("max"), 10);
				minValue = parseInt(element.getAttribute("min"), 10);

				// Set default visibility for popup
				// @TODO  consider removing this property and use popup widget instance
				// to determine current popup status
				self.popupVisible = false;

				slider.classList.remove(btnClasses.uiBtnCornerAll);
				if (ui && ui.background) {
					ui.background.classList.remove(btnClasses.uiBtnCornerAll);
				}
				self._ui.handle.classList.remove(btnClasses.uiBtnCornerAll);
				slider.querySelector('.' + btnClasses.uiBtnInner).classList.remove(btnClasses.uiBtnCornerAll);

				switch (icon) {
				case "bright":
				case "volume":
					elemLeft = document.createElement("div");
					elemLeft.classList.add(classes.uiSliderLeftPrefix + icon);

					slider.parentNode.insertBefore(elemLeft, slider);

					marginLeft = (DOM.getElementWidth(elemLeft) + 16) + "px";
					marginRight = "";
					break;

				case "text":
					textLeft = (textLeft && textLeft.substring(0, 3)) || "";
					textRight = (textRight && textRight.substring(0, 3)) || "";

					elemLeft = document.createElement("div");
					elemLeft.classList.add(classes.uiSliderLeftText);

					elemRight = document.createElement("div");
					elemRight.classList.add(classes.uiSliderRightText);

					textLength = Math.max(textLeft.length, textRight.length) + 1;

					marginLeft = textLength + "rem";
					marginRight = textLength + "rem";

					// Properties set before appending to element in DOM
					elemLeft.style.left = "-" + marginLeft;
					elemLeft.style.width = marginLeft;

					elemRight.style.right = "-" + marginRight;
					elemRight.style.width = marginRight;

					inner = document.createElement("span");
					inner.style.position = "relative";
					inner.style.top = "0.4em";
					inner.innerHTML = textLeft;

					// Second element is same as first one
					elemLeft.appendChild(inner.cloneNode(true));

					inner.innerHTML = textRight;

					elemRight.appendChild(inner);

					slider.parentNode.insertBefore(elemLeft, slider);
					slider.parentNode.appendChild(elemRight);

					break;
				}

				if (icon) {
					sliderContainerStyle.marginLeft = marginLeft;
					sliderContainerStyle.marginRight = marginRight;
				}

				self.handleText = slider.querySelector("." + btnClasses.uiBtnText);

				self.element = element;
				self._updateSlider(element);

				return element;
			};

			/**
			 * Callback responsible for opening popup, fires on change event
			 * @method onChangeHandler
			 * @param {ns.widget.mobile.TizenSlider} self
			 * @private
			 * @static
			 * @member ns.widget.mobile.TizenSlider
			 */
			function onChangeHandler(self) {
				if (self.popupVisible) {
					self._updateSlider();
					self._showPopup();
					document.addEventListener("vmouseup", self.onVmouseUpHandleHandler, false);
				} else {
					self.popupVisible = true;
					self._updateSlider();
					self.popupVisible = false;
				}
			}

			/**
			 * Callback responsible for refreshing the slider and showing the popup
			 * @method onSlideStartHandler
			 * @param {ns.widget.mobile.TizenSlider} self
			 * @private
			 * @static
			 * @member ns.widget.mobile.TizenSlider
			 */
			function onSlideStartHandler(self) {
				self._updateSlider();
				self._showPopup();
				document.addEventListener("vmouseup", self.onVmouseUpHandleHandler, false);
			}

			/**
			 * Callback shows popup and assign another callback, fires on mouse down event
			 * @method onVmouseDownHandler
			 * @param {ns.widget.mobile.TizenSlider} self
			 * @private
			 * @static
			 * @member ns.widget.mobile.TizenSlider
			 */
			function onVmouseDownHandler(self) {
				self.handle.classList.add(TizenSlider.classes.uiSliderHandlePress);
				self._showPopup();
				document.addEventListener("vmouseup", self.onVmouseUpHandleHandler, false);
			}

			/**
			 * Callback responsible for refreshing the slider and showing popup.
			 * @method onVmouseDownHandleHandler
			 * @param {ns.widget.mobile.TizenSlider} self
			 * @private
			 * @static
			 * @member ns.widget.mobile.TizenSlider
			 */
			function onVmouseDownHandleHandler(self) {
				self._updateSlider();
				self._ui.handle.classList.add(TizenSlider.classes.uiSliderHandlePress);
				self._showPopup();
				document.addEventListener("vmouseup", self.onVmouseUpHandleHandler, false);
			}

			/**
			 * Callback hides popup and stops the event
			 * @method onVmouseUpHandleHandler
			 * @param {ns.widget.mobile.TizenSlider} self
			 * @param {Event} event
			 * @private
			 * @static
			 * @member ns.widget.mobile.TizenSlider
			 */
			function onVmouseUpHandleHandler(self, event) {
				event.preventDefault();
				event.stopPropagation();
				self._hidePopup();
				self._ui.handle.classList.remove(TizenSlider.classes.uiSliderHandlePress);
				document.removeEventListener("vmouseup", self.onVmouseUpHandleHandler, false);
			}

			/**
			 * Bind events to widget
			 * @method _bindEvents
			 * @param {HTMLElement} element
			 * @protected
			 * @member ns.widget.mobile.TizenSlider
			 * @return {HTMLElement}
			 */
			TizenSlider.prototype._bindEvents = function (element) {
				sliderBindEvents.call(this, element);
				this.onChangeHandler = onChangeHandler.bind(null, this);
				this.onSlideStartHandler = onSlideStartHandler.bind(null, this);
				this.onVmouseDownHandler = onVmouseDownHandler.bind(null, this);
				this.onVmouseDownHandleHandler = onVmouseDownHandleHandler.bind(null, this);
				this.onVmouseUpHandleHandler = onVmouseUpHandleHandler.bind(null, this);
				this.onOrientationChangeHandler = this._closePopup.bind(this);

				element.addEventListener("change", this.onChangeHandler, false);
				element.addEventListener("slidestart", this.onSlideStartHandler, false);
				element.addEventListener("vmousedown", this.onVmouseDownHandler, false);
				this._ui.handle.addEventListener("vmousedown", this.onVmouseDownHandleHandler, false);
				window.addEventListener("orientationchange", this.onOrientationChangeHandler, false);

				return element;
			};

			/**
			 * @method _refresh
			 * @inheritdoc ns.widget.mobile.Slider#_refresh
			 * @protected
			 * @member ns.widget.mobile.TizenSlider
			 */
			TizenSlider.prototype._refresh = function () {
				var self = this,
					popup = self._popup;
				// Call parent refresh method with all passed arguments
				slider_refresh.apply(self, arguments);
				if (popup && self.popupVisible) {
					popup.refresh();
				}
			};

			ns.widget.mobile.TizenSlider = TizenSlider;
			engine.defineWidget(
				"TizenSlider",
				"input[type='range'], input[data-role='slider'], input[data-role='range']," +
				"input.ui-tizenslider",
				[],
				TizenSlider,
				"tizen"
			);
			}(window, window.document, ns));

/*global window, define */
/* 
 * Copyright (c) 2010 - 2014 Samsung Electronics Co., Ltd.
 * License : MIT License V2
 */
/*
 * #Namespace For Widgets
 * @author Krzysztof Antoszek <k.antoszek@samsung.com>
 * @class ns.widget
 */
(function (document, ns) {
	
				ns.widget.core = ns.widget.core || {};
			}(window.document, ns));

/*global window, define */
/*
 * Copyright (c) 2010 - 2014 Samsung Electronics Co., Ltd.
 * License : MIT License V2
 */
/**
 * #Drawer Widget
 * Core Drawer widget is a base for creating Drawer widgets for profiles. It
 * provides drawer functionality - container with ability to open and close with
 * an animation.
 *
 * ##Positioning Drawer left / right
 * To change position of a Drawer please set data-position attribute of Drawer
 * element to:
 * - left (left position, default)
 * - right (right position)
 *
 * ##Opening / Closing Drawer
 * To open / close Drawer one can use open() and close() methods.
 *
 * ##Checking if Drawer is opened.
 * To check if Drawer is opened use widget`s isOpen() method.
 *
 * ##Creating widget
 * Core drawer is a base class - examples of creating widgets are described in
 * documentation of profiles
 *
 * @class ns.widget.core.Drawer
 * @extends ns.widget.BaseWidget
 * @author Hyeoncheol Choi <hc7.choi@samsung.com>
 */
(function (document, ns) {
	
				/**
			 * @property {Object} Widget Alias for {@link ns.widget.BaseWidget}
			 * @member ns.widget.core.Drawer
			 * @private
			 * @static
			 */
			var BaseWidget = ns.widget.BaseWidget,
				/**
				 * @property {Object} selectors Alias for class ns.util.selectors
				 * @member ns.widget.core.Drawer
				 * @private
				 * @static
				 * @readonly
				 */
				selectors = ns.util.selectors,
				/**
				 * Drawer constructor
				 * @method Drawer
				 */
				Drawer = function () {
					var self = this;
					/**
					 * Drawer field containing options
					 * @property {number} Position of Drawer ("left" or "right")
					 * @property {number} Width of Drawer
					 * @property {number} Duration of Drawer entrance animation
					 * @property {boolean} If true Drawer will be closed on arrow click
					 * @property {boolean} Sets whether to show an overlay when Drawer is open.
					 */
					self.options = {
						position : "left",
						width : 240,
						duration : 100,
						closeOnClick: true,
						overlay: true
					};

					self._onOverlayClickBound = null;
					self._onTransitionEndBound = null;
					self._onResizeBound = null;
					self._onPageshowBound = null;

					self._pageSelector = null;

					self._isOpen = false;

					self._ui = {};

					self._drawerOverlay = null;
				},
				/**
				 * Dictionary object containing commonly used widget classes
				 * @property {Object} classes
				 * @member ns.widget.core.Drawer
				 * @private
				 * @static
				 * @readonly
				 */
				classes = {
					drawer : "ui-drawer",
					header : "ui-drawer-header",
					left : "ui-drawer-left",
					right : "ui-drawer-right",
					overlay : "ui-drawer-overlay",
					open : "ui-drawer-open",
					close : "ui-drawer-close"
				},
				/**
				 * {Object} Drawer widget prototype
				 * @member ns.widget.core.Drawer
				 * @private
				 * @static
				 */
				prototype = new BaseWidget();

			Drawer.prototype = prototype;
			Drawer.classes = classes;

			/**
			 * Click event handler
			 * @method onClick
			 * @param {ns.widget.core.Drawer} self
			 * @member ns.widget.core.Drawer
			 * @private
			 * @static
			 */
			function onClick(self) {
				// vclick event handler
				if (self._isOpen) {
					self.close();
				}
			}

			/**
			 * webkitTransitionEnd event handler
			 * @method onTransitionEnd
			 * @param {ns.widget.core.Drawer} self
			 * @member ns.widget.core.Drawer
			 * @private
			 * @static
			 */
			function onTransitionEnd(self) {
				var drawerOverlay = self._drawerOverlay;
				// webkitTransitionEnd event handler
				if (!self._isOpen) {
					// not open -> transition -> open
					self._isOpen = true;
				} else {
					// open -> transition -> close
					self._isOpen = false;
					if (drawerOverlay) {
						drawerOverlay.style.visibility = "hidden";
					}
				}
			}

			/**
			 * Resize event handler
			 * @method onResize
			 * @param {ns.widget.core.Drawer} self
			 * @member ns.widget.core.Drawer
			 * @private
			 * @static
			 */
			function onResize(self) {
				// resize event handler
				self._refresh();
			}

			/**
			 * Pageshow event handler
			 * @method onPageshow
			 * @param {ns.widget.core.Drawer} self
			 * @member ns.widget.core.Drawer
			 * @private
			 * @static
			 */
			function onPageshow(self) {
				self._refresh();
			}

			/**
			 * Drawer translate function
			 * @method _translate
			 * @param {number} x
			 * @param {number} duration
			 * @member ns.widget.core.Drawer
			 * @protected
			 */
			prototype._translate = function (x, duration) {
				var element = this.element,
					elementStyle = element.style,
					transition = "none";

				if (duration) {
					transition =  "-webkit-transform " + duration / 1000 + "s ease-out";
				}

				elementStyle.webkitTransform = "translate3d(" + x + "px, 0px, 0px)";
				elementStyle.webkitTransition = transition;
			};

			/**
			 * Build structure of Drawer widget
			 * @method _build
			 * @param {HTMLElement} element
			 * @return {HTMLElement} Returns built element
			 * @member ns.widget.core.Drawer
			 * @protected
			 */
			prototype._build = function (element) {
				var self = this,
					headerElement;
				element.classList.add(classes.drawer);
				self._drawerPage = selectors.getClosestByClass(element, this._pageSelector);
				self._drawerPage.style.overflow = "hidden";

				headerElement = element.nextElementSibling;
				while (headerElement) {
					if (headerElement.classList.contains("ui-header")) {
						break;
					}
					headerElement = headerElement.nextElementSibling;
				}

				if (headerElement) {
					headerElement.classList.add(classes.header);
				}

				self._headerElement = headerElement;

				if (self.options.overlay) {
					self._createOverlay(element);
					self._drawerOverlay.style.visibility = "hidden";
				}

				return element;
			};

			/**
			 * Initialization of Drawer widget
			 * @method _init
			 * @param {HTMLElement} element
			 * @member ns.widget.core.Drawer
			 * @protected
			 */
			prototype._init = function (element) {
				var self = this,
					options = self.options;

				if (options.position === "right") {
					element.classList.add(classes.right);
					self._translate(window.innerWidth, 0);
				} else {
					// left or default
					element.classList.add(classes.left);
					self._translate(-options.width, 0);
				}
			};

			/**
			 * Provides translation if position is set to right
			 * @method _translateRight
			 * @member ns.widget.core.Drawer
			 * @protected
			 */
			prototype._translateRight = function() {
				var self = this,
					options = self.options;
				if (options.position === "right") {
					// If drawer position is right, drawer should be moved right side
					if (self._isOpen) {
						// drawer opened
						self._translate(window.innerWidth - options.width, 0);
					} else {
						// drawer closed
						self._translate(window.innerWidth, 0);
					}
				}
			};

			/**
			 * Refreshes Drawer widget
			 * @method _refresh
			 * @member ns.widget.core.Drawer
			 * @protected
			 */
			prototype._refresh = function() {
				// Drawer layout has been set by parent element layout
				var self = this,
					options = self.options,
					drawerElementParent = self.element.parentNode,
					drawerHeight = drawerElementParent.clientHeight,
					drawerStyle = self.element.style,
					drawerOverlay = self._drawerOverlay,
					overlayStyle = drawerOverlay && drawerOverlay.style;

				drawerStyle.width = options.width + "px";
				drawerStyle.height = drawerHeight + "px";

				if (overlayStyle) {
					overlayStyle.width = window.innerWidth + "px";
					overlayStyle.height = drawerHeight + "px";
				}

				self._translateRight();
			};

			/**
			 * Creates Drawer overlay element
			 * @method _createOverlay
			 * @param {HTMLElement} element
			 * @member ns.widget.core.Drawer
			 * @protected
			 */
			prototype._createOverlay = function(element) {
				var self = this,
					overlayElement = document.createElement("div");

				overlayElement.classList.add(classes.overlay);
				element.parentNode.insertBefore(overlayElement, element);
				self._drawerOverlay = overlayElement;
			};

			/**
			 * Binds events to a Drawer widget
			 * @method _bindEvents
			 * @member ns.widget.core.Drawer
			 * @protected
			 */
			prototype._bindEvents = function() {
				var self = this,
					options = self.options,
					drawerOverlay = self._drawerOverlay;
				self._onClickBound = onClick.bind(null, self);
				self._onTransitionEndBound = onTransitionEnd.bind(null, self);
				self._onResizeBound = onResize.bind(null, self);
				self._onPageshowBound = onPageshow.bind(null, self);

				if (options.overlay && options.closeOnClick && drawerOverlay) {
					drawerOverlay.addEventListener("vclick", self._onClickBound, false);
				}
				self.element.addEventListener("webkitTransitionEnd", self._onTransitionEndBound, false);
				self.element.addEventListener("transitionEnd", self._onTransitionEndBound, false);
				window.addEventListener("resize", self._onResizeBound, false);
				self._drawerPage.addEventListener("pageshow", self._onPageshowBound, false);
			};

			/**
			 * Checks Drawer status
			 * @method isOpen
			 * @member ns.widget.core.Drawer
			 * @return {boolean} Returns true if Drawer is open
			 */
			prototype.isOpen = function() {
				return this._isOpen;
			};

			/**
			 * Opens Drawer widget
			 * @method open
			 * @member ns.widget.core.Drawer
			 */
			prototype.open = function() {
				var self = this,
					options = self.options,
					drawerClassList = self.element.classList,
					drawerOverlay = self._drawerOverlay;
				if (drawerOverlay) {
					drawerOverlay.style.visibility = "visible";
				}
				drawerClassList.remove(classes.close);
				drawerClassList.add(classes.open);
				if (options.position === "left") {
					self._translate(0, options.duration);
				} else {
					self._translate(window.innerWidth - options.width, options.duration);
				}
			};

			/**
			 * Closes Drawer widget
			 * @method close
			 * @member ns.widget.core.Drawer
			 */
			prototype.close = function() {
				var self = this,
					options = self.options,
					drawerClassList = self.element.classList;
				drawerClassList.remove(classes.open);
				drawerClassList.add(classes.close);
				if (options.position === "left") {
					self._translate(-options.width, options.duration);
				} else {
					self._translate(window.innerWidth, options.duration);
				}
			};

			/**
			 * Destroys Drawer widget
			 * @method _destroy
			 * @member ns.widget.core.Drawer
			 * @protected
			 */
			prototype._destroy = function() {
				var self = this,
					drawerOverlay = self._drawerOverlay;
				if (drawerOverlay) {
					drawerOverlay.removeEventListener("vclick", self._onClickBound, false);
				}
				self.element.removeEventListener("webkitTransitionEnd", self._onTransitionEndBound, false);
				window.removeEventListener("resize", self._onResizeBound, false);
				self._drawerPage.removeEventListener("pageshow", self._onPageshowBound, false);
			};

			ns.widget.core.Drawer = Drawer;


			}(window.document, ns));

/*global window, define */
/*
* Copyright  2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/**
 * #Drawer Widget
 * Drawer widget provide creating drawer widget and managing drawer operation.
 *
 * ##Default selector
 * You can make the drawer widget as data-role="drawer" with DIV tag.
 *
 * ###  HTML Examples
 *
 * ####  Create drawer using data-role
 *
 *        @example
 *        <div data-role="drawer" data-position="left" id="leftdrawer">
 *            <ul data-role="listview">
 *                <li class="ui-drawer-main-list"><a href="#">List item 1</a></li>
 *                <li class="ui-drawer-main-list"><a href="#">List item 2</a></li>
 *                <li class="ui-drawer-sub-list"><a href="#">Sub item 1</a></li>
 *            </ul>
 *        </div>
 *
 * ##Drawer positioning
 * You can declare to drawer position manually. (Default is left)
 *
 * If you implement data-position attributes value is 'left', drawer appear from left side.
 *
 *        @example
 *        <div data-role="drawer" data-position="left" id="leftdrawer">
 *
 * - "left" - drawer appear from left side
 * - "right" - drawer appear from right side
 *
 * ##Drawer inner list
 * Drawer has two list styles, main list style and sub list style.
 * You can implement two providing list styles as implement classes.
 *
 * - "ui-drawer-main-list" : Main list style of drawer
 * - "ui-drawer-sub-list" : Sub list style of drawer
 *
 * ##Drawer methods
 *
 * You can use some methods of drawer widget.
 *
 * - "open" - drawer open
 *
 *        @example
 *        $("#leftdrawer").drawer("open");
 *
 * - "close" - drawer close
 *
 *        @example
 *        $("#leftdrawer").drawer("isOpen");
 *
 * - "isOpen" - get drawer status, true is opened and false if closed
 *
 *        @example
 *        $("#leftdrawer").drawer"(isOpen");
 *
 * ##Drawer Options
 *
 * - position: drawer appeared position. Type is <String> and default is "left".
 * - width: drawer width. Type is <Integer> and default is 290.
 * - duration: drawer appreared duration. <Integer> and default is 100.
 *
 *

 * @class ns.widget.mobile.Drawer
 * @extends ns.widget.mobile.BaseWidgetMobile
 * @author Hyeoncheol Choi <hc7.choi@samsung.com>
 */
(function (document, ns) {
	
				var CoreDrawer = ns.widget.core.Drawer,
				CoreDrawerPrototype = CoreDrawer.prototype,
				Page = ns.widget.mobile.Page,
				engine = ns.engine,
				Drawer = function () {
					var self = this;
					CoreDrawer.call(self);
					self.options.swipeStartAreaRatio = 0.05;
					self._pageSelector = Page.classes.uiPage;

					self._onSwipeBound = null;
					self._onMouseDownBound = null;
					self._onSideEdgeMouseUpBound = null;
					self._swiped = false;
				},
				prototype = new CoreDrawer(),
				classes = CoreDrawer.classes;

			Drawer.prototype = prototype;
			Drawer.classes = classes;

			/**
			 * Swipe event handler
			 * @method _onSwipe
			 * @private
			 * @static
			 * @param {Event} event
			 * @member ns.widget.mobile.Drawer
			 */
			prototype._onSwipe = function(event) {
				// If swipeleft event was triggered at drawer position right,
				// drawer should be opend. So 'direction' has reverse value for swipe direction.
				var self = this,
					direction = event.type === "swipeleft" ? "right" : "left";

				if (self.options.position === direction && self._swiped) {
					self.open();
					self._swiped = false;
				}

			}

			/**
			 * Check vmousedown event whether triggerred on side edge area or not
			 * @method _checkSideEdgeMouseDown
			 * @private
			 * @static
			 * @param {Event} event
			 * @member ns.widget.mobile.Drawer
			 */
			prototype._checkSideEdgeMouseDown = function(event) {
				var self = this,
					eventClientX = event.clientX,
					options = self.options,
					position = options.position,
					swipeStartArea = window.innerWidth * options.swipeStartAreaRatio;

				if ((position === "left" && eventClientX > 0 && eventClientX < swipeStartArea) ||
					(position === "right" && eventClientX < window.innerWidth && eventClientX > window.innerWidth - swipeStartArea)) {
					self._swiped = true;
				}
			}
			/**
			 * Vmousedown event handler
			 * @method _onMouseDown
			 * @private
			 * @static
			 * @param {Event} event
			 * @member ns.widget.mobile.Drawer
			 */
			prototype._onMouseDown = function(event) {
				this._checkSideEdgeMouseDown(event);
			}

			/**
			 * Bind events to widget
			 * @method _bindEvents
			 * @protected
			 * @member ns.widget.mobile.Drawer
			 */
			prototype._bindEvents = function() {
				var self = this,
					page = self._drawerPage;
				CoreDrawerPrototype._bindEvents.call(self);

				self._onMouseDownBound = self._onMouseDown.bind(self);
				self._onSwipeBound = self._onSwipe.bind(self);
				page.addEventListener("vmousedown", self._onMouseDownBound, false);
				page.addEventListener("swipeleft", self._onSwipeBound, false);
				page.addEventListener("swiperight", self._onSwipeBound, false);
			};

			prototype._destroy = function() {
				var self = this,
					page = self._drawerPage;
				CoreDrawerPrototype._destroy.call(self);
				page.removeEventListener("vmousedown", self._onMouseDownBound, false);
				page.removeEventListener("swipeleft", self._onSwipeBound, false);
				page.removeEventListener("swiperight", self._onSwipeBound, false);
			};

			ns.widget.mobile.Drawer = Drawer;
			engine.defineWidget(
				"Drawer",
				"[data-role='drawer'], .ui-drawer",
				[
					"open",
					"close",
					"isOpen"
				],
				Drawer,
				"mobile"
			);

			}(window.document, ns));

/*global window, define */
/*
* Copyright  2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/*jslint nomen: true */
/**
 * # Toggle Switch Widget
 * Shows a 2-state switch.
 *
 * The toggle switch widget shows a 2-state switch on the screen.
 * If defined with select type with options it creates toggles with labels
 * On the toggle with labels its possible to drag or flip the handle
 * or tap one side of the switch.
 *
 * We still support toggles defined with select tag for backward compatibility
 *
 * ## Default selectors
 * INPUT tags with _data-role=toggleswitch_ or SELECT tags
 * with _data-role=slider_
 * or
 *  _data-role=toggleswitch_
 * changed to toggle switch
 * To add a toggle switch widget to the application, use the following code:
 *
 *		@example
 *		<input type="checkbox" data-role="toggleswitch">
 *
 *		@example
 *		<input type="checkbox" id="checkbox-1" data-role="toggleswitch"/>
 *		<label for="checkbox-1"></label>
 *
 *		@example
 *		<select name="flip-11" id="flip-11" data-role="slider">
 *			<option value="off"></option>
 *			<option value="on"></option>
 *		</select>
 *
 *		@example
 *		<select name="flip-11" id="flip-11" data-role="toggleswitch">
 *			<option value="off"></option>
 *			<option value="on"></option>
 *		</select>
 *
 *		@example
 *		<select name="flip-11" id="flip-11" data-role="toggleswitch">
 *			<option value="off">off option</option>
 *			<option value="on">on option</option>
 *		</select>
 *
 * ## Manual constructor
 * For manual creation of toggle switch widget you can use constructor of
 * widget from **tau** namespace:
 *
 *		@example
 *		<select id="toggle" name="flip-11" id="flip-11" data-role="slider"
 *		data-mini="true">
 *			<option value="off"></option>
 *			<option value="on"></option>
 *		</select>
 *		<script>
 *			var toggleElement = document.getElementById("toggle"),
 *				toggle = tau.widget.ToggleSwitch(toggleElement);
 *		</script>
 *
 * ## JavaScript API
 *
 * ToggleSwitch widget hasn't JavaScript API.
 *
 * @class ns.widget.mobile.ToggleSwitch
 * @extends ns.widget.BaseWidget
 */
(function (document, ns) {
	
				var ToggleSwitch = function () {
				var self = this;
					/**
					 * All possible widget options
					 * @property {Object} options
					 * @property {?string} [options.trackTheme=null] sets
					 * the color scheme (swatch) for the slider's track
					 * @property {boolean} [options.disabled=false] start
					 * widget as enabled / disabled
					 * @property {?boolean} [options.mini=false] size
					 * of toggle switch
					 * @property {boolean} [options.highlight=true] if set
					 * then toggle switch can be highligted
					 * @property {?boolean} [options.inline=false] if value is
					 * "true" then toggle switch has css property
					 * display = "inline"
					 * @property {string} [options.theme=null] theme of widget
					 * @member ns.widget.mobile.ToggleSwitch
					 */
					self.options = {
						trackTheme: null,
						disabled: false,
						mini: null,
						highlight: true,
						inline: null,
						theme: null
					};
					self._ui = {};
				},
				BaseWidget = ns.widget.mobile.BaseWidgetMobile,
				engine = ns.engine,
				events = ns.event,
				DOMutils = ns.util.DOM,
				Button = ns.widget.mobile.Button,
				themes = ns.theme,
				/**
				* @property {Object} selectors Alias for class ns.util.selectors
				* @member ns.widget.mobile.ToggleSwitch
				* @private
				* @static
				*/
				selectors = ns.util.selectors,

				classes = {
					//slider
					sliderSwitch: "ui-slider-switch",
					toggleInneroffset: "ui-slider-inneroffset",
					sliderInline: "ui-slider-inline",
					sliderMini: "ui-slider-mini",
					sliderHandle: "ui-slider-handle",
					flipHandle: "ui-flip-handle",
					slider: "ui-slider",
					sliderLabel: "ui-slider-label",
					sliderLabelTheme: "ui-slider-label-",
					sliderInneroffset: "ui-slider-inneroffset",
					sliderLabelA: "ui-slider-label-a",
					sliderSnapping : "ui-slider-handle-snapping",
					//sliderBg: "ui-slider-bg",
					sliderContainer: "ui-slider-container",
					sliderStateActive: "ui-state-active",

					//input
					toggleSwitchInput: "ui-slider-switch-input",
					toggle: "ui-toggle-switch",
					toggleInputLabel: "ui-toggle-label",
					toggleHandler: "ui-switch-handler",
					toggleOff: "ui-toggle-off",
					toggleOn: "ui-toggle-on"
				},
				keyCode = {
					HOME: 36,
					END: 35,
					PAGE_UP : 33,
					PAGE_DOWN: 34,
					UP: 38,
					RIGHT: 39,
					DOWN: 40,
					LEFT: 37
				};

			ToggleSwitch.prototype = new BaseWidget();

			/**
			 * Dictionary for ToggleSwitch related css class names
			 * @property {Object} classes
			 * @member ns.widget.mobile.ToggleSwitch
			 * @static
			 * @readonly
			 */
			ToggleSwitch.classes = classes;

			/**
			* Dictionary for keyboard codes
			* @property {Object} keyCode
			* @member ns.widget.mobile.ToggleSwitch
			* @static
			* @readonly
			*/
			ToggleSwitch.keyCode = keyCode;

			//for select
			/**
			 * Returns default position of the slider, if the element is input
			 * @method getInitialValue
			 * @param {string} tag
			 * @param {HTMLElement} element
			 * @return {number}
			 * @private
			 * @static
			 * @member ns.widget.mobile.ToggleSwitch
			 */
			function getInitialValue(tag, element) {
				return tag === "input" ? parseFloat(element.value) :
						element.selectedIndex;
			}

			/**
			 * Sets the width for labels which represents a value of widget
			 * @method refreshLabels
			 * @param {ns.widget.mobile.ToggleSwitch} self
			 * @param {number} percent
			 * @private
			 * @static
			 * @member ns.widget.mobile.ToggleSwitch
			 */
			function refreshLabels(self, percent) {
				var getElementWidth = DOMutils.getElementWidth,
					handlePercent = getElementWidth(self._ui.handle, "outer") /
							getElementWidth(self._ui.slider, "outer") * 100,
					aPercent = percent && handlePercent + (100 - handlePercent)
							* percent / 100,
					bPercent = percent === 100 ? 0 : Math.min(handlePercent +
							100 - aPercent, 100),
					i = self._labels.length,
					label;

				while (i--) {
					label = self._labels[i];
					label.style.width =
							(label.classList.contains(classes.sliderLabelA)
									? aPercent : bPercent) + "%";
				}
			}

			/**
			 * Sets the width for labels which represents a value of widget
			 * @method addRemoveClassesBasedOnProcentage
			 * @param {number} percent
			 * @param {classList} localClasses
			 * @private
			 * @static
			 * @member ns.widget.mobile.ToggleSwitch
			 */
			function addRemoveClassesBasedOnProcentage(percent, localClasses) {
				if (percent === 100 &&
						localClasses.contains(classes.sliderSnapping)) {
					localClasses.remove(classes.toggleOff);
					localClasses.add(classes.toggleOn);
				} else if (percent === 0 &&
						localClasses.contains(classes.sliderSnapping)) {
					localClasses.remove(classes.toggleOn);
					localClasses.add(classes.toggleOff);
				}
			}
			/**
			 * Refresh all the elements of Slider widget
			 * @method refresh
			 * @param {ns.widget.mobile.ToggleSwitch} self
			 * @param {Object|number|null} value
			 * @param {boolean} [isFromControl] tells if the refresh was called from callbacks
			 * @param {boolean} [preventInputUpdate] prevents change value for input
			 * @private
			 * @static
			 * @member ns.widget.mobile.ToggleSwitch
			 */
			function refresh(self, value, isFromControl, preventInputUpdate) {
				var data,
					percent,
					newValue,
					valModStep,
					alignValue,
					valueChanged,
					touchThreshold,
					newValueOption,
					sliderOffsetLeft,
					min = 0,
					control = self.element,
					handle = self._ui.handle,
					slider = self._ui.slider,
					localClasses = handle.classList,
					controlType = control.nodeName.toLowerCase(),
					max = control.querySelectorAll("option").length - 1,
					stepValue = DOMutils.getNumberFromAttribute(control,
							"step", "float", 0),
					step = (controlType === "input" && stepValue > 0) ?
							stepValue : 1;

				if (controlType === "input") {
					min = DOMutils.getNumberFromAttribute(control,
							"min",  "float", min);
					max = DOMutils.getNumberFromAttribute(control,
							"max", "float", max);
				}

				if (isNaN(step)) {
					step = 0;
				}

				if (self.options.disabled) {
					self._disable();
				}

				// If changes came from event
				if (typeof value === "object") {
					data = value;
					// @TODO take parameter out to config
					touchThreshold = 8;
					sliderOffsetLeft =
							DOMutils.getElementOffset(slider).left;

					// If refreshing while not dragging
					// or movement was within threshold
					if (!self._dragging ||
							data.pageX < sliderOffsetLeft - touchThreshold ||
							data.pageX > sliderOffsetLeft +
							slider.offsetWidth + touchThreshold) {
						return;
					}

					// Calculate new left side percent
					percent = ((data.pageX - sliderOffsetLeft) /
							slider.offsetWidth) * 100;

				// If changes came from input value change
				} else {
					if (value === null) {
						value = getInitialValue(tagName, control);
					}
					if (isNaN(value)) {
						return;
					}
					// While dragging prevent jumping by assigning
					// last percentage value
					if (self._dragging && self._lastPercent) {
						percent = self._lastPercent;
					} else {
						percent = (parseFloat(value) - min) / (max - min) * 100;
					}
				}

				// Make sure percent is a value between 0 - 100;
				percent = Math.max(0, Math.min(percent, 100));
				self._lastPercent = percent;

				newValue = (percent / 100) * (max - min) + min;

				//from jQuery UI slider, the following source will round
				// to the nearest step
				valModStep = (newValue - min) % step;
				alignValue = newValue - valModStep;

				if (Math.abs(valModStep) * 2 >= step) {
					alignValue += (valModStep > 0) ? step : (-step);
				}
				// Since JavaScript has problems with large floats, round
				// the final value to 5 digits after the decimal point
				// (see jQueryUI: #4124)
				newValue = parseFloat(alignValue.toFixed(5));

				newValue = Math.max(min, Math.min(newValue, max));

				handle.style.left = percent + "%";
				newValueOption = control.querySelectorAll("option")[newValue];
				handle.setAttribute("aria-valuenow", controlType === "input" ?
						newValue : newValueOption && newValueOption.value);
				handle.setAttribute("aria-valuetext", controlType === "input" ?
						newValue : newValueOption && newValueOption.innerText);
				handle.setAttribute("title", controlType === "input" ?
						newValue : newValueOption && newValueOption.innerText);

				addRemoveClassesBasedOnProcentage(percent, localClasses);

				// drag the label widths
				if (self._labels) {
					refreshLabels(self, percent);
				}

				if (!preventInputUpdate) {
					valueChanged = false;
					// update control"s value
					if (controlType === "input") {
						valueChanged = control.value !== newValue;
						control.value = newValue;
					} else {
						valueChanged = control.selectedIndex !== newValue;
						control.selectedIndex = newValue;
					}
					if (!isFromControl && valueChanged) {
						// Trigger change event on the control element
						events.trigger(control, "change");
					}
				}
			}

			/**
			 * Disable any action when TouchMove event appear
			 * @method onTouchMove
			 * @param {Event} event
			 * @private
			 * @static
			 * @member ns.widget.mobile.ToggleSwitch
			 */
			function onTouchMove(event) {
				event.stopPropagation();
				event.preventDefault();
			}

			/**
			 * Function fires on mouse move event
			 * @method onVmouseMove
			 * @param {ns.widget.mobile.ToggleSwitch} self
			 * @param {Event} event
			 * @private
			 * @static
			 * @member ns.widget.mobile.ToggleSwitch
			 */
			function onVmouseMove(self, event) {
				var element = self.element,
					tagName = element.nodeName.toLowerCase(),
					handle = self._ui.handle;
				// NOTE: we don't do this in refresh because we still want to
				//	support programmatic alteration of disabled inputs
				if (self._dragging && !self.options.disabled) {

					// self.mouseMoved must be updated before refresh()
					// because it will be used in the control "change" event
					self._mouseMoved = true;

					if (tagName === "select") {
						// make the handle move in sync with the mouse
						handle.classList.remove(classes.sliderSnapping);
					}

					refresh(self, event);
					// only after refresh() you can calculate self.userModified
					self._userModified = self._beforeStart !==
						element.selectedIndex;
					events.preventDefault(event);
				}
			}

			/**
			 * Function fires on mouse move event
			 * @method sliderMouseUp
			 * @param {ns.widget.mobile.ToggleSwitch} self
			 * @private
			 * @static
			 * @member ns.widget.mobile.ToggleSwitch
			 */
			function sliderMouseUp(self) {
				var _beforeStart;

				if (self._dragging) {
					self._dragging = false;
					_beforeStart = self._beforeStart;

					if (self.element.nodeName.toLowerCase() === "select") {
						// make the handle move with a smooth transition
						self._ui.handle.classList.add(classes.sliderSnapping);

						if (self._mouseMoved) {
							// this is a drag, change the value only
							// if user dragged enough
							if (self._userModified) {
								refresh(self, _beforeStart === 0 ? 1 : 0);
							} else {
								refresh(self, _beforeStart);
							}
						} else {
							refresh(self, _beforeStart === 0 ? 1 : 0);
						}
					}
					self._mouseMoved = false;
				}
			}

			/**
			* Callback change the value of input type=checkbox
			* (method stricly for toggleswitch based oninput tag)
			* @method onChangeValue
			* @param {ns.widget.mobile.ToggleSwitch} self
			* @private
			* @static
			* @member ns.widget.mobile.ToggleSwitch
			*/
			function onChangeValue(self){
				self.element.selectedIndex = (self._ui.input.checked) ? 1 :0;
			}

			/**
			 * Call refresh when state change
			 * @method onFocus
			 * @param {ns.widget.mobile.ToggleSwitch} self
			 * @private
			 * @static
			 * @member ns.widget.mobile.ToggleSwitch
			 */
			function onChange(self) {
				if (!self._mouseMoved) {
					refresh(self, self._getValue(), true);
				}
			}

			/**
			 * Call refresh when blur event ocur
			 * @method onBlur
			 * @param {ns.widget.mobile.ToggleSwitch} self
			 * @private
			 * @static
			 * @member ns.widget.mobile.ToggleSwitch
			 */
			function onBlur(self) {
				refresh(self, self._getValue(), true);
			}

			/**
			 * Triggers focus event on the target element
			 * @method onVmousedown
			 * @param {Event} event
			 * @private
			 * @static
			 * @member ns.widget.mobile.ToggleSwitch
			 */
			function onVmousedown(event) {
				events.trigger(event.target, "focus");
			}

			/**
			 * Stoping event
			 * @method onVclick
			 * @param {Event} event
			 * @private
			 * @static
			 * @member ns.widget.mobile.ToggleSwitch
			 */
			function onVclick(event) {
				event.stopPropagation();
				event.preventDefault();
			}

			/**
			 * Manage intearaction of widget with key down events
			 * @method onKeydown
			 * @param {ns.widget.mobile.ToggleSwitch} self
			 * @param {Event} event
			 * @private
			 * @static
			 * @member ns.widget.mobile.ToggleSwitch
			 */
			function onKeydown(self, event) {
				var element = self.element,
					tagName = element.nodeName.toLowerCase(),
					index = getInitialValue(tagName, element),
					eventkeyCode = event.keyCode,
					classList = event.target.classList,
					step = parseFloat(self.element.getAttribute( "step" ) ||
							1);

				if (self.options.disabled) {
					return;
				}

				// In all cases prevent the default and mark the handle
				// as active
				switch (eventkeyCode) {
					case keyCode.HOME:
					case keyCode.END:
					case keyCode.PAGE_UP:
					case keyCode.PAGE_DOWN:
					case keyCode.UP:
					case keyCode.RIGHT:
					case keyCode.DOWN:
					case keyCode.LEFT:
						event.preventDefault();
						if (!self._keySliding) {
							self._keySliding = true;
							classList.add(classes.sliderStateActive);
						}
						break;
				}
				// move the slider according to the keypress
				switch (eventkeyCode) {
					case keyCode.HOME:
						refresh(self, min);
						break;
					case keyCode.END:
						refresh(self, max);
						break;
					case keyCode.PAGE_UP:
					case keyCode.UP:
					case keyCode.RIGHT:
						refresh(self, index + step);
						break;
					case keyCode.PAGE_DOWN:
					case keyCode.DOWN:
					case keyCode.LEFT:
						refresh(self, index - step);
						break;
				}


			}

			/**
			 * Remove slider state active
			 * @method onKeyup
			 * @param {ns.widget.mobile.ToggleSwitch} self
			 * @private
			 * @static
			 * @member ns.widget.mobile.ToggleSwitch
			 */
			function onKeyupHandle (self) {
				if (self._keySliding) {
					self._keySliding = false;
					handle.classList.remove(classes.sliderStateActive);
				}
			}

			/**
			 * Call refresh when keyUp event ocur
			 * @method onKeyup
			 * @param {ns.widget.mobile.ToggleSwitch} self
			 * @private
			 * @static
			 * @member ns.widget.mobile.ToggleSwitch
			 */
			function onKeyupElement(self) {
				refresh(self, self._getValue(), true, true);
			}

			/**
			 * Refresh widget and add css class
			 * @method onTouchend
			 * @param {ns.widget.mobile.ToggleSwitch} self
			 * @private
			 * @static
			 * @member ns.widget.mobile.ToggleSwitch
			 */
			function onTouchend(self) {
				var element = self.element,
					tagName = element.nodeName.toLowerCase();

				self._dragging = false;
				self._ui.handle.classList.add(classes.sliderSnapping);
				refresh(self, getInitialValue(tagName, element),
						true, true);
			}

			/**
			 * Callback responsible for refreshing the widget
			 * @method onVmousedown
			 * @param {ns.widget.mobile.ToggleSwitch} self
			 * @param {Event} event
			 * @private
			 * @static
			 * @member ns.widget.mobile.ToggleSwitch
			 */
			function onVmousedownRefresh(self, event) {
				var element = self.element;

				if (self.options.disabled) {
					return false;
				}

				self._dragging = true;
				self._userModified = false;
				self._mouseMoved = false;
				//element.nodeName.toLowerCase()
				if (element.nodeName.toLowerCase() === "select") {
					self._beforeStart = element.selectedIndex;
				}
				refresh(self, event);
				return false;
			}

			/**
			* Take the label related to the given input
			* (method stricly for toggleswitch based oninput tag)
			* @method getLabel
			* @param {HTMLElement} input
			* @return {HTMLElement}
			* @private
			* @static
			* @member ns.widget.mobile.ToggleSwitch
			*/
			function getLabel(input) {
				var parent = selectors.getClosestByTag(input, "label"),
					label;
				if (parent) {
					parent.parentNode.replaceChild(parent.firstElementChild,
							parent);
					return parent;
				}
				if (input.id) {
					parent = selectors.getClosestBySelector(input,
						"form, fieldset, [data-role='page'], [data-role='dialog']");
					if (parent) {
						label = parent.querySelector("label[for='"+
								input.id + "']");
						if (label) {
							return label;
						}
					}
				}

				label = createElement("label");
				if (input.id) {
					label.setAttribute("for", input.id);
				}
				return label;
			}

			/**
			* Simplify creating dom elements
			* (method stricly for toggleswitch based oninput tag)
			* @method createElement
			* @param {String} name
			* @return {HTMLElement}
			* @private
			* @static
			* @member ns.widget.mobile.ToggleSwitch
			*/
			function createElement(name) {
				return document.createElement(name);
			}

			/**
			* Creates and set up input element
			* @method setUpInput
			* @return {HTMLElement}
			* @private
			* @static
			* @member ns.widget.mobile.ToggleSwitch
			*/
			function setUpInput() {
				var inputElement = createElement("input");

				inputElement.type = "checkbox";
				inputElement.className = classes.toggleSwitchInput;
				return inputElement;
			}

			/**
			* Creates wrapper for slider
			* @method createWrapper
			* @param {HTMLElement} domSlider
			* @return {HTMLElement}
			* @private
			* @static
			* @member ns.widget.mobile.ToggleSwitch
			*/
			function createWrapper(domSlider) {
				var wrapper,
					domSliderChildNode = domSlider.childNodes;

				wrapper = createElement("div");
				wrapper.className = classes.sliderInneroffset;

				for (j = 0, length = domSliderChildNode.length;
						j < length; j++) {
					wrapper.appendChild(domSliderChildNode[j]);
				}
				return wrapper;
			}

			/**
			* Adding classes for slider
			* @method addClassesForSlider
			* @param {HTMLElement} domSlider
			* @param {String} sliderBtnDownTheme
			* @param {Object} btnClasses
			* @param {Object} options
			* @private
			* @static
			* @member ns.widget.mobile.ToggleSwitch
			*/
			function addClassesForSlider(domSlider, sliderBtnDownTheme, btnClasses, options) {
				var domSliderClassList = domSlider.classList;

				domSliderClassList.add(classes.slider);
				domSliderClassList.add(classes.sliderSwitch);
				domSliderClassList.add(sliderBtnDownTheme);
				domSliderClassList.add(btnClasses.uiBtnCornerAll);

				if (options.inline) {
					domSliderClassList.add(classes.sliderInline);
				}
				if (options.mini) {
					domSliderClassList.add(classes.sliderMini);
				}
			}

			/**
			* Simplify creating dom elements
			* @method buildOptions
			* @param {HTMLElement} element
			* @param {Object} btnClasses
			* @param {String} sliderBtnDownTheme
			* @param {HTMLElement} domSlider
			* @private
			* @static
			* @member ns.widget.mobile.ToggleSwitch
			*/
			function buildOptions(element, btnClasses, sliderBtnDownTheme, domSlider) {
				var i,
					side,
					sliderImg,
					sliderTheme,
					sliderImgClassList = null;

				for (i = 0; i < element.length; i++) {
					side = i ? "a" : "b";
					sliderTheme = i ? btnClasses.uiBtnActive :
							sliderBtnDownTheme;
					/* TODO - check sliderlabel */
					sliderImg =
						createElement("span");
					sliderImgClassList = sliderImg.classList;
					sliderImgClassList.add(classes.sliderLabel);
					sliderImgClassList.add(classes.sliderLabelTheme +
							side);
					sliderImgClassList.add(sliderTheme);
					sliderImgClassList.add(btnClasses.uiBtnCornerAll);

					sliderImg.setAttribute("role", "img");
					sliderImg.appendChild(document.createTextNode(
							element[i].innerHTML));
					domSlider.insertBefore(
							sliderImg, domSlider.firstChild);
				}
			}

			/**
			* Adding widget object to the callbacks
			* @method bindCallbacksForSelectTag
			* @param {ns.widget.mobile.ToggleSwitch} self
			* @private
			* @static
			* @member ns.widget.mobile.ToggleSwitch
			*/
			function bindCallbacksForSelectTag(self){
				self._onKeyupElement = onKeyupElement.bind(null, self);
				self._sliderMouseUp = sliderMouseUp.bind(null, self);
				self._onKeyupHandle = onKeyupHandle.bind(null, self);
				self._onVmouseMove = onVmouseMove.bind(null, self);
				self._onTouchend = onTouchend.bind(null, self);
				self._onKeydown = onKeydown.bind(null, self);
				self._onChange = onChange.bind(null, self);
				self._onBlur = onBlur.bind(null, self);
				self._onVmousedownRefresh =
					onVmousedownRefresh.bind(null, self);
			}

			/**
			* Remove events from Slider which is based on Select Tag
			* @method removeEventsFromToggleBasedOnSelect
			* @param {HTMLElement} element
			* @param {HTMLElement} handle
			* @param {HTMLElement} slider
			* @private
			* @static
			* @member ns.widget.mobile.ToggleSwitch
			*/
			function removeEventsFromToggleBasedOnSelect(element, handle, slider) {
				element.removeEventListener("change", self._onChange,
						false);
				element.removeEventListener("keyup", self._onKeyupElement, false);
				element.removeEventListener("blur", self._onBlur, false);

				handle.removeEventListener("vmousedown", self._onVmousedown,
						false);
				handle.removeEventListener("vclick", self.onVclick, false);
				handle.removeEventListener("keydown", self._onKeydown, false);
				handle.removeEventListener("keyup", self._onKeyupHandle, false);

				slider.removeEventListener("vmousedown",
						self._onVmousedownRefresh, false);
				slider.removeEventListener("vmousemove", self._onVmouseMove,
						false);
				slider.removeEventListener("vmouseup", self._sliderMouseUp,
						false);
			}

			/**
			* Build Slider based on Select Tag
			* @method removeEventsFromToggleBasedOnSelect
			* @param {ns.widget.mobile.ToggleSwitch} self
			* @param {HTMLElement} element
			* @param {HTMLElement} sliderContainer
			* @private
			* @static
			* @member ns.widget.mobile.ToggleSwitch
			*/
			function buildSliderBasedOnSelectTag(self, element, sliderContainer) {
				var domSlider = createElement("div"),
					sliderBtnDownTheme,
					options = self.options,
					elementId = element.getAttribute("id"),
					btnClasses = Button.classes,
					protoOptions = ToggleSwitch.prototype.options,
					parentTheme = themes.getInheritedTheme(element,
							(protoOptions && protoOptions.theme) || "s"),
					domHandle = createElement("a"),
					trackTheme,
					theme = options.theme = options.theme || parentTheme;

				trackTheme = options.trackTheme = options.trackTheme ||
				parentTheme

				domSlider.setAttribute("id", elementId + "-slider");
				sliderBtnDownTheme = btnClasses.uiBtnDownThemePrefix +
						trackTheme;

				addClassesForSlider(domSlider, sliderBtnDownTheme, btnClasses, options);

				domHandle.className = classes.sliderHandle;
				domSlider.appendChild(domHandle);
				domHandle.setAttribute("id", elementId + "-handle");

				engine.instanceWidget(domHandle, "Button", {
					corners: true,
					theme: theme,
					shadow: true,
					inline: false,
					bar: true
				});

				domSlider.appendChild(createWrapper(domSlider));
				// make the handle move with a smooth transition
				domHandle.classList.add(classes.sliderSnapping);
				buildOptions(element, btnClasses, sliderBtnDownTheme, domSlider);
				// to make a difference between slider and flip type toggle
				domHandle.classList.add(classes.flipHandle);

				sliderContainer = domSlider;
				element.classList.add(classes.sliderSwitch);
				domHandle.style.right = "auto";
				element.parentNode.insertBefore(sliderContainer,
						element.nextSibling);
			}

			/**
			* Build Toggle based on Select Tag
			* @method buildToggleBasedOnSelectTag
			* @param {HTMLElement} element
			* @param {HTMLElement} divHandler
			* @param {HTMLElement} divInneroffset
			* @param {HTMLElement} sliderContainer
			* @param {HTMLElement} label
			* @private
			* @static
			* @member ns.widget.mobile.ToggleSwitch
			*/
			function buildToggleBasedOnSelectTag(element, divHandler, divInneroffset, sliderContainer, label) {
				ns.warn("Please use input[data-role='toggleswitch'] " +
						"selector in order to define button like " +
						"toggle, select[data-role='slider'] is " +
						"deprecated");

				label.className = classes.toggleInputLabel;
				sliderContainer.className = classes.toggle;
				divHandler.className = classes.toggleHandler;
				divInneroffset.className = classes.toggleInneroffset;

				sliderContainer.appendChild(divHandler);

				label.appendChild(setUpInput());
				label.appendChild(sliderContainer);
				label.appendChild(divInneroffset);

				element.parentNode.insertBefore(label,
						element.nextSibling);
				label.appendChild(element);
			}

			/**
			* Build Toggle based on Input Tag
			* @method buildToggleBasedOnInputTag
			* @param {HTMLElement} element
			* @param {HTMLElement} divHandler
			* @param {HTMLElement} divInneroffset
			* @param {HTMLElement} sliderContainer
			* @param {HTMLElement} label
			* @private
			* @static
			* @member ns.widget.mobile.ToggleSwitch
			*/
			function buildToggleBasedOnInputTag(element, divHandler, divInneroffset, sliderContainer, label) {
				var mountPointForLabel = element.nextSibling;

				sliderContainer.className = classes.toggle;
				divHandler.className = classes.toggleHandler;
				element.className = classes.toggleSwitchInput;
				divInneroffset.className = classes.toggleInneroffset;

				sliderContainer.appendChild(divHandler);

				label = getLabel(element);
				label.className = classes.toggleInputLabel;
				label.appendChild(element);
				label.appendChild(sliderContainer);
				label.appendChild(divInneroffset);

				mountPointForLabel.parentNode.insertBefore(label,
						mountPointForLabel);
			}

			/**
			 * Build ToggleSwitch
			 * @method _build
			 * @param {HTMLElement} element
			 * @return {HTMLElement}
			 * @protected
			 * @member ns.widget.mobile.ToggleSwitch
			 */
			ToggleSwitch.prototype._build = function (element) {
				var roleType,
					elementsOption,
					options = this.options,
					label = createElement("label"),
					divHandler = createElement("div"),
					divInneroffset = createElement("div"),
					controlType = element.nodeName.toLowerCase(),
					sliderContainer = createElement("div");

				//when the input with input[data-role='toggleswitch'],
				//button like toggle
				if (controlType === "input") {
					buildToggleBasedOnInputTag(element, divHandler, divInneroffset, sliderContainer, label);
				} else {
					roleType = element.getAttribute("role");
					elementsOption = element.querySelector("option");
					if (roleType === "slider"){
						ns.warn("Please use select[data-role='toggleswitch'] " +
								"selector in order to define widget, " +
								"select[data-role='slider'] is depreciated");
					}
					//hide select
					element.className = classes.sliderSwitch;

					//if the select type, two empty options (simple on/off)
					if (elementsOption && elementsOption.innerText === "") {
						buildToggleBasedOnSelectTag(element, divHandler, divInneroffset, sliderContainer, label);
					//logic moved from slider widget
					} else {
						buildSliderBasedOnSelectTag(this, element, sliderContainer);
					}
				}
				return element;
			};

			/**
			* Inits widget
			* @method _init
			* @param {HTMLElement} element
			* @protected
			* @member ns.widget.mobile.ToggleSwitch
			* @instance
			*/
			ToggleSwitch.prototype._init = function (element) {
				var controlType = element.nodeName.toLowerCase(),
					elementId,
					self = this,
					elementsOption = element.querySelector("option") || "";

				//because the select with empty options is replaced with
				//input I just need and input on widget instance
				if (controlType === "input" || elementsOption.innerText === "") {
					self._ui.input = element.parentElement.firstChild;
				} else {
					elementId = element.id;
					self._ui.slider = document.getElementById(elementId +
							"-slider");
					self._ui.handle = document.getElementById(elementId +
							"-handle");
					self._ui.container = document.getElementById(elementId +
							"-container") || element;
					self._type = element.tagName.toLowerCase();
					self._labels = selectors.getChildrenByClass(self._ui.slider,
							ToggleSwitch.classes.sliderLabel);
					refresh(self, self._getValue());
				}
			};

			/**
			 * Get or Set value of the widget
			 *
			 * Return element value or set the value
			 *
			 *		@example
			 *		<select id="slider" name="flip-11" data-role="slider">
			 *			<option value="off"></option>
			 *			<option value="on"></option>
			 *		</select>
			 *		<script>
			 *			var slider = document.getElementById("slider"),
			 *				sliderWidget = tau.widget.Slider(slider),
			 *			// value contains index of select tag
			 *			value = sliderWidget.value();
			 *			//sets the index for the toggle
			 *			sliderWidget.value("1");
			 *		</script>
			 *
			 * ####If jQuery library is loaded, its method can be used:
			 *
			 *		@example
			 *		<select id="slider" name="flip-11" data-role="slider">
			 *			<option value="off"></option>
			 *			<option value="on"></option>
			 *		</select>
			 *		<script>
			 *			// value contains index of select tag
			 *			$( "#slider" ).slider( "value" );
			 *			// sets the index for the toggle
			 *			$( "#slider" ).slider( "value", "1" );
			 *		</script>
			 *
			 * @method value
			 * @return {string} In get mode return element value or element
			 * selected index based on tag name.
			 * @since 2.3
			 * @member ns.widget.mobile.ToggleSwitch
			 */

			/**
			 * Get value of toggle switch. If widget is based on input type
			 * tag otherwise it return index of the element
			 * @method _getValue
			 * @protected
			 * @member ns.widget.mobile.ToggleSwitch
			 */
			ToggleSwitch.prototype._getValue = function () {
				var self = this,
					element = self.element;

				return self._type === "input" ?
						parseFloat(element.value) :
							element.selectedIndex;
			};

			/**
			 * Set value of toggle switch
			 * @method _setValue
			 * @param {string} value
			 * @protected
			 * @member ns.widget.mobile.ToggleSwitch
			 */
			ToggleSwitch.prototype._setValue = function (value) {
				var self = this,
					element = self.element;

				if (self._type === "input") {
					element.value = value;
				} else {
					element.selectedIndex = value;
				}
			};

			/**
			 * Refresh a slider markup.
			 *
			 * This method will rebuild while DOM structure of widget.
			 *
			 * This method should be called after are manually change in HTML
			 * attributes of widget DOM structure.
			 *
			 * This method is called automatically after change any option
			 * of widget.
			 *
			 *		@example
			 *		<select id="slider" name="flip-11" data-role="slider">
			 *			<option value="off"></option>
			 *			<option value="on"></option>
			 *		</select>
			 *		<script>
			 *			var slider = document.getElementById("slider"),
			 *				  sliderWidget = tau.widget.Slider(slider),
			 *			sliderWidget.refresh();
			 *		</script>
			 *
			 * ####If jQuery library is loaded, its method can be used:
			 *
			 *		@example
			 *		<select id="slider" name="flip-11" data-role="slider">
			 *			<option value="off"></option>
			 *			<option value="on"></option>
			 *		</select>
			 *		<script>
			 *			$( "#slider" ).slider( "refresh" );
			 *		</script>
			 *
			 * @method refresh
			 * @chainable
			 * @member ns.widget.mobile.ToggleSwitch
			 */

			/**
			 * Refresh slider
			 * @method _refresh
			 * @protected
			 * @member ns.widget.mobile.ToggleSwitch
			 */
			ToggleSwitch.prototype._refresh = function () {
				var self = this;
				if (self._ui.slider && self.value !== self._getValue()) {
					refresh(self, self._getValue());
				}
			};

			/**
			 * Enable the slider
			 *
			 * Method removes disabled attribute on slider and changes look
			 * of slider to enabled state.
			 *
			 *		@example
			 *		<select id="slider" name="flip-11" data-role="slider">
			 *			<option value="off"></option>
			 *			<option value="on"></option>
			 *		</select>
			 *		<script>
			 *			var slider = document.getElementById("slider"),
			 *				  sliderWidget = tau.widget.Slider(slider),
			 *			sliderWidget.enable();
			 *		</script>
			 *
			 * ####If jQuery library is loaded, its method can be used:
			 *
			 *		@example
			 *		<select id="slider" name="flip-11" data-role="slider">
			 *			<option value="off"></option>
			 *			<option value="on"></option>
			 *		</select>
			 *		<script>
			 *			$( "#slider" ).slider( "enable" );
			 *		</script>
			 *
			 * @method enable
			 * @chainable
			 * @member ns.widget.mobile.ToggleSwitch
			 */

			/**
			 * Enable slider
			 * @method _enable
			 * @param {HTMLElement} element
			 * @protected
			 * @member ns.widget.mobile.ToggleSwitch
			 */
			ToggleSwitch.prototype._enable = function (element) {
				var btnClasses = Button.classes,
					self = this,
					slider = self._ui.slider;

				if (slider) {
					element.removeAttribute("disabled");
					slider.classList.remove(btnClasses.uiDisabled);
					slider.setAttribute("aria-disabled", false);
					self.options.disabled = false;
				}
			};

			/**
			 * Disable the slider
			 *
			 * Method sets disabled attribute on slider and changes look
			 * of slider to disabled state.
			 *
			 *		@example
			 *		<select id="slider" name="flip-11" data-role="slider">
			 *			<option value="off"></option>
			 *			<option value="on"></option>
			 *		</select>
			 *		<script>
			 *			var slider = document.getElementById("slider"),
			 *				sliderWidget = tau.widget.Slider(slider),
			 *			sliderWidget.disable();
			 *		</script>
			 *
			 * ####If jQuery library is loaded, its method can be used:
			 *
			 *		@example
			 *		<select id="slider" name="flip-11" data-role="slider">
			 *			<option value="off"></option>
			 *			<option value="on"></option>
			 *		</select>
			 *		<script>
			 *			$( "#slider" ).slider( "disable" );
			 *		</script>
			 *
			 * @method disable
			 * @chainable
			 * @member ns.widget.mobile.ToggleSwitch
			 */

			/**
			 * Disable slider
			 * @method _disable
			 * @param {HTMLElement} element
			 * @protected
			 * @member ns.widget.mobile.ToggleSwitch
			 */
			ToggleSwitch.prototype._disable = function (element) {
				var btnClasses = Button.classes,
					slider = self._ui.slider;

				if (slider) {
					element.setAttribute("disabled", "disabled");
					slider.classList.add(btnClasses.uiDisabled);
					slider.setAttribute("aria-disabled", true);
					self.options.disabled = true;
				}
			};

			/**
			* Binds events to widget
			* @method _bindEvents
			* @protected
			* @member ns.widget.mobile.ToggleSwitch
			* @instance
			*/
			ToggleSwitch.prototype._bindEvents = function () {
				var self = this,
					element = self.element,
					handle = self._ui.handle,
					tagName = element.nodeName.toLowerCase(),
					slider = self._ui.slider,
					elementsOption = element.querySelector("option") || "";

				if (tagName === "input" || elementsOption.innerText === ""){
					self._onChangeValue = onChangeValue.bind(null, self);
					self._ui.input.addEventListener('change',
							self._onChangeValue, true);
				} else {
					bindCallbacksForSelectTag(self);

					element.addEventListener("keyup", self._onKeyupElement,
							false);
					element.addEventListener("change", self._onChange, false);
					element.addEventListener("blur", self._onBlur, false);

					handle.addEventListener("keyup", self._onKeyupHandle,
							false);
					handle.addEventListener("keydown", self._onKeydown, false);
					handle.addEventListener("vclick", onVclick, false);
					handle.addEventListener("vmousedown", onVmousedown,
							false);

					slider.addEventListener("vmousedown",
							self._onVmousedownRefresh, false);
					slider.addEventListener("vmousemove", self._onVmouseMove,
							false);
					slider.addEventListener("vmouseup", self._sliderMouseUp,
							false);
				}
			};

			function removeAttributesWhenDestroy(element) {
				element.removeAttribute("data-tau-name");
				element.removeAttribute("aria-disabled");
				element.removeAttribute("data-tau-bound");
				element.removeAttribute("data-tau-built");
			}
			/**
			 * Destroy widget
			 * @method _destroy
			 * @protected
			 * @member ns.widget.mobile.ToggleSwitch
			 */
			ToggleSwitch.prototype._destroy = function () {
				var label,
					self = this,
					element = self.element,
					handle = self._ui.handle,
					slider = self._ui.slider,
					tagName = element.nodeName.toLowerCase(),
					elementsOption = element.querySelector("option") || "";

				if (tagName === "input" || elementsOption.innerText === "") {
					self._ui.input.removeEventListener('change',
							self._onChangeValue, true);

					//cleaning toggle based on input type
					if (tagName === "input") {
						label = element.parentElement;

						label.innerHTML = '';
						label.classList.remove(classes.toggleInputLabel);
						label.parentElement.insertBefore(element,label);

						element.removeAttribute("aria-disabled");
						element.classList.remove(classes.toggleSwitchInput);

					//cleaning toggle based on select type
					} else {
						if (element.nextElementSibling.tagName.toLowerCase()
								=== "label") {
							//remove attributes
							removeAttributesWhenDestroy(element);
							//remove classes
							element.classList.remove(classes.sliderSwitch);
							//remove visible representative
							element.parentElement.removeChild(
									element.nextElementSibling);
						}
					}
				} else {
					removeEventsFromToggleBasedOnSelect(element, handle, slider);

					removeAttributesWhenDestroy(element);
					element.classList.remove(classes.sliderSwitch);
					element.parentElement.removeChild(element.nextElementSibling);
				}

				events.trigger(document, "destroyed", {
					widget: "ToggleSwitch",
					parent: element.parentNode
				});
			};

			ns.widget.mobile.ToggleSwitch = ToggleSwitch;
			engine.defineWidget(
				"ToggleSwitch",
				"select[data-role='toggleswitch']," +
				"input[data-role='toggleswitch']," +
				"select[data-role='slider']," +
				"select.ui-toggleswitch, input.ui-toggleswitch",
				[],
				ToggleSwitch,
				"mobile"
			);
			}(window.document, ns));

/*global window, define */
/* Copyright (c) 2013 - 2014 Samsung Electronics Co., Ltd
 * License : MIT License V2
 */
/**
 * #Navigation Widget
 * Navigation Bar inside header to navigate back and forth according to
 * navigational history array, which is created by application.
 * By clicking horizontally listed element on the Navigation Bar,
 * page is possible to be changed to the target page.
 *
 * ##Default selector
 * You can make the navigation widget as data-role="navigation".
 * On creation, to use *NAV* tag is recommended for semantic understanding.
 *
 * ###  HTML Examples
 *
 * ####  Create Navigation Bar using data-role
 *
 * 		@example
 *		<div data-role="page">
 *			<div data-role="header" data-position="fixed">
 *				<h1>title</h1>
 *				<nav data-role="navigation" id="navigation">
 *				</nav>
 *			</div>
 *			<div data-role="content">
 *			</div>
 *		</div>
 *
 * ##Navigation methods
 *
 * You can use method of navigation widget.
 *
 * - "create" - create navigation bar according to history array.
 * - To create a naviagtion bar, an array containing history is required.
 * And also, each value of the array is recommended to have identifiable value such as name.
 * In the example below, the array is named as historyArraytoUse.
 *
 * - This widget only provides creation of navigation bar visually, not funtional navigation.
 * So, it is required to implement the navigational function in application by using other
 * method such as history.go() or something.
 *
 *		@examples
 *		<script>
 *			var navigation = document.getElementById("navigation"),
 *			navigationBar = tau.widget.Navigation(navigation);
 *
 *			navigationBar.create(historyArraytoUse);
 *		</script>
 *
 * @class ns.widget.mobile.Navigation
 * @extends ns.widget.BaseWidget
 * @author Maciej Moczulski <m.moczulsku@samsung.com>
 * @author Hyunkook Cho <hk0713.cho@samsung.com>
 * @author Hyeoncheol Choi <hc7.choi@samsung.com>
 * @author Heeju Joo <heeju.joo@samsung.com>
 * @author Maciej Urbanski <m.urbanski@samsung.com>
 * @author Koeun Choi <koeun.choi@samsung.com>
 * @author Piort Karny <p.karny@samsung.com>
 * @author Krzysztof Antonszek <k.antonszek@samsung.com>
 * @author Junhyeon Lee <juneh.lee@samsung.com>
 */
(function (document, ns) {
	
				var BaseWidget = ns.widget.mobile.BaseWidgetMobile,
				engine = ns.engine,
				selectors = ns.util.selectors,
				events = ns.event,
				Navigation = function () {
					var self = this;

					self._navigateTrigger = null;
					self._ui = {
						container: null
					};
					self._barLength = null;
				},
				/**
				 * Dictionary object containing commonly used widget classes
				 * @property {Object} classes
				 * @static
				 * @member ns.widget.mobile.Navigation
				 */
				classes = {
					header : "ui-header",
					titleNavigation : "ui-title-navigation",
					navigation: "ui-navigation",
					navigationUl : "ui-navigation-ul",
					navigationLi : "ui-navigation-li",
					navigationLiPress : "ui-navigation-li-press"
				},
				prototype = new BaseWidget();

			Navigation.prototype = prototype;
			Navigation.classes = classes;

			/**
			 * Navigation navigateTrigger function
			 * @method navigateTrigger
			 * @private
			 * @static
			 * @param {ns.widget.mobile.Navigation} self
			 * @param {event} event
			 * @member ns.widget.mobile.Navigation
			 */
			function navigateTrigger(self, event) {
				var target = event.target,
					selectedIndex = target.selectedIndex;

				if(target.nodeName === "LI"){
					//not to trigger event on the last li click
					if (selectedIndex + 1 !== self._barLength) {
						events.trigger(target, "navigate", selectedIndex);
					}
				}
			};

			/**
			 * Initiate making navigation bar
			 * @method create
			 * @param {Array} navigationHistory
			 * @public
			 * @member ns.widget.mobile.Navigation
			 */
			prototype.create = function (navigationHistory) {
				if (!document.querySelector("." + classes.navigationUl + " > *:first-child")) {
					this._make(navigationHistory);
				} else {
					ns.warn("Navigation Bar should be created only once.");
				}
			};

			/**
			 * Make history array to navigation bar and add event
			 * @method _make
			 * @param {Array} navigationHistory
			 * @protected
			 * @member ns.widget.mobile.Navigation
			 */
			prototype._make = function (navigationHistory) {
				var self = this,
					container = self._ui.container,
					element = self.element,
					docFrag = document.createDocumentFragment(),
					barLength = navigationHistory.length,
					i,
					list,
					arrow;

				for (i = 0; i < barLength; i++) {
					list = document.createElement("li");
					list.className = classes.navigationLi;
					list.selectedIndex = i;
					list.innerHTML = navigationHistory[i].pageId;

					docFrag.appendChild(list);
				};
				self._barLength = barLength;

				container.appendChild(docFrag);

				container.style.width = container.offsetWidth + "px";
				element.scrollLeft = element.scrollWidth;
			};

			/**
			 * Build structure of Navigation widget
			 * @method _build
			 * @param {HTMLElement} element
			 * @protected
			 * @member ns.widget.mobile.Navigation
			 */
			prototype._build = function (element) {
				var header,
					container;

				header = selectors.getParentsByClass(element, classes.header)[0];
				container = document.createElement("ul");

				header.classList.add(classes.titleNavigation);
				element.className = classes.navigation;
				container.className = classes.navigationUl;

				element.appendChild(container);
				header.appendChild(element);
			};

			/**
			 * Initiate Navigation widget
			 * @method _init
			 * @param {HTMLElement} element
			 * @protected
			 * @member ns.widget.mobile.Navigation
			 */
			prototype._init = function (element){
				this._ui.container = selectors.getChildrenByClass(element, classes.navigationUl)[0];
			};

			/**
			 * Bind events of Navigation widget
			 * @method _bindEvents
			 * @param {HTMLElement} element
			 * @protected
			 * @member ns.widget.mobile.Navigation
			 */
			prototype._bindEvents = function (element) {
				var self = this;

				self._navigateTrigger = navigateTrigger.bind(null, self);

				element.addEventListener("vclick", self._navigateTrigger, false);
			};

			/**
			 * Destroy Navigation widget
			 * @method _destroy
			 * @protected
			 * @member ns.widget.mobile.Navigation
			 */
			prototype._destroy = function () {
				element.removeEventListener("vclick", this._navigateTrigger, false);
			};

			ns.widget.mobile.Navigation = Navigation;
			engine.defineWidget(
				"Navigation",
				"[data-role='navigation'], .ui-navigation",
				[
					"create"
				],
				Navigation,
				"mobile"
			);

			}(window.document, ns));

/*jslint plusplus: true, nomen: true */
/*global window, define, ns, HTMLElement */
/*
* Copyright  2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/**
 * #Mobile Router
 * Class is responsible for change pages in applications.
 * @class ns.router.Page
 * @author Maciej Urbanski <m.urbanski@samsung.com>
 * @author Grzegorz Osimowicz <g.osimowicz@samsung.com>
 * @author Piotr Karny <p.karny@samsung.com>
 * @author Krzysztof Antoszek <k.antoszek@samsung.com>
 * @author Jadwiga Sosnowska <j.sosnowska@samsung.com>
 * @author Damian Osipiuk <d.osipiuk@samsung.com>
 * @author Krzysztof Glodowski <k.glodowski@samsung.com>
 */
(function (window, document, ns) {
	
				var eventUtils = ns.event,
				DOM = ns.util.DOM,
				selectors = ns.util.selectors,
				object = ns.util.object,
				path = ns.util.path,
				Deferred = ns.util.deferred,
				engine = ns.engine,
				body = document.body,
				pageDefinition = engine.getWidgetDefinition("Page"),
				RouterPage = function () {
					var self = this;
					self.activePage = null;
					self.firstPage = null;
					self.container = null;
					self.lastClickedLink = null;
					self.settings = {};
					self.navreadyDeferred = new Deferred();
					self.navreadyDeferred.done(function () {
						self.bindEvents();
					});
				};

			/**
			 * Default router settings
			 * @property {object}
			 * @property {undefined} [transition=undefined]
			 * @property {boolean} [reverse=false]
			 * @property {boolean} [changeHash=true]
			 * @property {boolean} [fromHashChange=false]
			 * @property {undefined} [role=undefined]
			 * @property {undefined} [duplicateCachedPage=undefined]
			 * @property {boolean} [showLoadMsg=true]
			 * @property {undefined} [dataUrl=undefined]
			 * @property {undefined} [fromPage=undefined]
			 * @property {boolean} [allowSamePageTransition=false]
			 * @member ns.router.Page
			 * @static
			 * @readonly
			 */
			RouterPage.defaults = {
				transition: undefined, //@TODO all the "undefined" declarations should be
						//removed
				reverse: false,
				changeHash: true,
				fromHashChange: false,
				role: undefined, // By default we rely on the role defined by the @data-role
						//attribute.
				duplicateCachedPage: undefined,
				container: ns.getConfig("container") || body,
				showLoadMsg: true, //loading message shows by default when pages are being
						// fetched during changePage
				dataUrl: undefined,
				fromPage: undefined,
				allowSamePageTransition: false
			};

			/**
			 * Event definitions
			 * @property {Object}
			 * @property {string} [PAGE_CREATE="pagecreate"] Fired when page is created
			 * @property {string} [PAGE_INIT="pageinit"] Fired when page is initialized
			 * @property {string} [PAGE_BEFORE_LOAD="pagebeforeload"] Fired before page is
			 * 		loaded
			 * @property {string} [PAGE_LOAD="pageload"] Fired after page is loaded
			 * @property {string} [PAGE_LOAD_FAILED="pageloadfailed"] Fired on page load
			 * 		error
			 * @property {string} [PAGE_BEFORE_HIDE="pagebeforehide"] Fired before page is
			 * 		hidden
			 * @property {string} [PAGE_HIDE="pagehide"] Fired after page is hidden
			 * @property {string} [PAGE_BEFORE_SHOW="pagebeforeshow"] Fired before page is
			 * 		shown
			 * @property {string} [PAGE_SHOW="pageshow"] Fired after page is shown
			 * @property {string} [PAGE_BEFORE_CHANGE="pagebeforechange"] Fired before page
			 * 		change operation
			 * @property {string} [PAGE_CHANGE="pagachange"] Fired after page is changed
			 * @property {string} [PAGE_CHANGE_FAILED="pagechangefailed"] Fired on error
			 * 		when changing pages
			 * @property {string} [PAGE_REMOVE="pageremove"] Fired on page removal
			 * @property {string} [WIDGET_BOUND="widgetbound"] Fired when a DOM element has
			 * 		been bound to widget instance
			 * @property {string} [POP_STATE="popstate"] Fired on history change
			 * @property {string} [CLICK="click"] Fired on document click
			 * @property {string} [SUBMIT="submit"] Fired on form submit
			 * @member ns.router.Page
			 * @static
			 * @readonly
			 */
			RouterPage.events = {
				PAGE_CREATE : "pagecreate",
				PAGE_INIT : "pageinit",
				PAGE_BEFORE_LOAD : "pagebeforeload",
				PAGE_LOAD : "pageload",
				PAGE_LOAD_FAILED : "pageloadfailed",
				PAGE_BEFORE_HIDE : "pagebeforehide",
				PAGE_HIDE : "pagehide",
				PAGE_BEFORE_SHOW : "pagebeforeshow",
				PAGE_SHOW : "pageshow",
				PAGE_BEFORE_CHANGE : "pagebeforechange",
				PAGE_CHANGE : "pagechange",
				PAGE_CHANGE_FAILED : "pagechangefailed",
				PAGE_REMOVE : "pageremove",
				HASH_CHANGE : "hashchange",
				WIDGET_BOUND : "widgetbound",
				POP_STATE : "popstate",
				CLICK : "click",
				SUBMIT : "submit"
			};

			/**
			 * Before page change event handler
			 * @param {ns.router.Page} router
			 * @param {Event} event
			 * @member ns.router.Page
			 * @method pagebeforechangeHandler
			 * @private
			 * @static
			 */
			function pagebeforechangeHandler(router, event) {
				var linkId,
					linkElement,
					popup = event.detail.toPage,
					popupWidget;

				if (popup && selectors.matchesSelector(popup, '[data-role="popup"],.ui-popup')) {
					linkElement = router.lastClickedLink;
					linkId = linkElement.id;
					if (ns.activePopup) {
						ns.activePopup.close();
					}
					popupWidget = engine.getBinding(popup);
					popupWidget.open({
						link: linkId,
						positionTo: linkElement ? DOM.getNSData(linkElement, "position-to") :
								null,
						transition: linkElement ?  DOM.getNSData(linkElement, "transition") :
								null
					}, event);
					event.preventDefault();
				}
			}

			/**
			 * Handler for link clicks
			 * @param {ns.router.Page} router
			 * @param {Event} event
			 * @member ns.router.Page
			 * @method linkClickHandler
			 * @private
			 * @static
			 */
			function linkClickHandler(router, event) {
				var link = selectors.getClosestByTag(event.target, "a"),
					linkHref = link ? link.getAttribute("href") : null,
					element,
					isHash = linkHref && (linkHref.charAt(0) === "#"),
					options = {},
					useDefaultUrlHandling = false,
					inputInsideLink,
					inputInsideLinkLength,
					i;

				router.lastClickedLink = null;
				if (link) {
					useDefaultUrlHandling = (link.getAttribute("rel") === "external")
									|| link.hasAttribute("target")
									|| (linkHref ? linkHref.search(/^https?\:\/\//g) !== -1 : false);
					if (!useDefaultUrlHandling) {
						event.preventDefault();
						options.transition = DOM.getNSData(link, "transition");
						options.reverse = (DOM.getNSData(link, "direction") === "reverse");
						// Only swiching pages
						if (isHash) {
							element = document.getElementById(linkHref.substr(1));
							if (element) {
								router.lastClickedLink = link;
								router.open(element);
							}
						} else if (linkHref) {
							// Open link only if it exists
							router.open(linkHref, options);
						}

						//IMPORTANT / DEPRECIATED This following if statement
						//should be removed as soon
						//as we will stop to support controls tags like inputs
						//inside anchors, which is against W3C standards
						inputInsideLink = link.getElementsByClassName("ui-slider-switch-input");
						if (inputInsideLink) {
							inputInsideLinkLength = inputInsideLink.length;
							for (i = 0; i < inputInsideLinkLength; i++) {
								inputInsideLink[i].checked = !inputInsideLink[i].checked;
								eventUtils.trigger(inputInsideLink[i], "change");
							}
						}
					}
				}
			}

			/**
			 * Handler for form submitions
			 * @param {ns.router.Page} router
			 * @param {Event} event
			 * @member ns.router.Page
			 * @method submitHandler
			 * @private
			 * @static
			 */
			function submitHandler(router, event) {
				var form = selectors.getClosestByTag(event.target, "form"),
					elements = form.elements,
					length = elements.length,
					options = {
						data: {},
						type: form.method,
						transition: DOM.getNSData(form, "transition"),
						reverse: DOM.getNSData(form, "direction") === "reverse"
						//TODO Handle other options?
					},
					url = form.action || form.baseURI,
					i;

				eventUtils.preventDefault(event);

				for (i = 0; i < length; i++) {
					options.data[elements[i].name] = elements[i].value;
				}

				router.open(url, options);
				return false;
			}

			/**
			 * History change handler
			 * @param {ns.router.Page} router
			 * @param {Event} event
			 * @member ns.router.Page
			 * @method popStateHandler
			 * @private
			 * @static
			 */
			function popStateHandler(router, event) {
				var eventState = event.state,
					toPageId = (eventState && eventState.pageId) || window.location.hash
							.substr(1),
					toPage = document.getElementById(toPageId),
					settings = router.settings;

				if (toPage) {
					settings.reverse = true;
					settings.fromPage = settings.fromPage || router.activePage;
					settings.toPage = toPage;
					if (toPage && DOM.getNSData(toPage, "role") === "page"
							&& settings.fromPage !== toPage) {
						router.setActivePage(toPage);
					}
					settings.fromPage = null;
					settings.toPage = null;
				} else {
					if (eventState && eventState.url) {
						router.open(eventState.url.trim(), {});
					}
				}
			}

			/**
			 * URI Hash change handler
			 * @param {string} hash
			 * @member ns.router.Page
			 * @method _hashChangeHandler
			 * @protected
			 */
			RouterPage.prototype._hashChangeHandler = function (hash) {
				var router = this,
					toPageId = path.stripHash(hash),
					toPage = document.getElementById(toPageId),
					settings = router.settings;

				if (toPage) {
					settings.fromPage = settings.fromPage || router.activePage;
					settings.toPage = toPage;
					if (DOM.getNSData(toPage, "role") === "page"
							&& settings.fromPage !== toPage) {
						router.setActivePage(toPage);
					}
					settings.fromPage = null;
					settings.toPage = null;
				}
			};

			/**
			 * Returns loader widget
			 * @return {ns.widget.mobile.Loader}
			 * @member ns.router.Page
			 * @method getLoader
			 */
			RouterPage.prototype.getLoader = function () {
				var loaderElement = document.querySelector("[data-role=loader],.ui-loader");

				if (!loaderElement) {
					loaderElement = document.createElement("div");
					DOM.setNSData(loaderElement, "role", "loader");
				}

				return engine.instanceWidget(loaderElement, "Loader");
			};

			/**
			 * Sets focus on given page
			 * @param {ns.widget.mobile.Page} page
			 * @member ns.router.Page
			 * @method focusPage
			 */
			RouterPage.prototype.focusPage = function (page) {
				var autofocus = page.querySelector("[autofocus]");
				if (autofocus) {
					autofocus.focus();
					return;
				}
				page.focus();
			};

			/**
			 * Handles change page finish process
			 * @param {HTMLElement} fromPage
			 * @param {HTMLElement} toPage
			 * @param {boolean} noEvents
			 * @method changePageFinish
			 * @member ns.router.Page
			 */
			RouterPage.prototype.changePageFinish = function (fromPage, toPage, noEvents) {
				var events = RouterPage.events,
					self = this;
				self.activePage = toPage;
				if (!noEvents) {
					if (fromPage) {
						eventUtils.trigger(fromPage, events.PAGE_HIDE);
					}
					eventUtils.trigger(toPage, events.PAGE_SHOW);
					eventUtils.trigger(self.container, events.PAGE_CHANGE, toPage);
				}
			};

			/**
			 * Handles change page process
			 * @param {Object} settings
			 * @param {HTMLElement} [settings.fromPage]
			 * @param {HTMLElement} [settings.toPage]
			 * @param {boolan} noEvents
			 * @method changePage
			 * @member ns.router.Page
			 */
			RouterPage.prototype.changePage = function (settings, noEvents) {
				var fromPage = settings.fromPage,
					toPage = settings.toPage,
					fromPageWidget,
					toPageWidget,
					self = this;
								if (fromPage) {
					fromPageWidget = engine.getBinding(fromPage);
					if (fromPageWidget) {
						fromPageWidget.setActive(false, self.container);
					}
				}
				if (toPage) {
					toPageWidget = engine.getBinding(toPage);
					if (toPageWidget) {
						toPageWidget.setActive(true, self.container);
					}
				}
				self.changePageFinish(fromPage, toPage, noEvents);
			};

			/**
			* Set active page
			* @method setActivePage
			* @param {HTMLElement} page HTMLElement from Page or Dialog widget
			* @param {boolean} [noEvents=false]
			* @static
			* @member ns.router.Page
			*/
			RouterPage.prototype.setActivePage = function (page, noEvents) {
				var self = this,
					events = RouterPage.events,
					// @TODO Add type for .getBinding, but NOTICE that it may be a Page or
					// Dialog widget
					toPageWidget = engine.getBinding(page),
					callInit = true,
					pageRole,
					eventBound = function () {
						var fromPage = self.activePage;
						page.removeEventListener(events.WIDGET_BOUND, eventBound, false);

						// If autoBuild is turned off do not build widgets on newly activated
						// page
						if (ns.getConfig("autoBuildOnPageChange", true)) {
							engine.createWidgets(page);
						}

						if (!noEvents) {
							if (callInit) {
								eventUtils.trigger(page, events.PAGE_INIT);
							}
							if (fromPage) {
								eventUtils.trigger(fromPage, events.PAGE_BEFORE_HIDE);
							}
						}
						if (!noEvents) {
							eventUtils.trigger(page, events.PAGE_BEFORE_SHOW);
						}
						self.changePage(self.settings, noEvents);
					};

				eventUtils.trigger(window, events.HASH_CHANGE, true);
								if (toPageWidget && toPageWidget.isBuilt()) {
					//page is ready to show, just make sure it is active
					callInit = false;
					eventBound();
				} else {
					//add event which will make page active when enhancing is done
					page.addEventListener(events.WIDGET_BOUND, eventBound, false);
					//create page widget
					pageRole = DOM.getNSData(page, "role");
					if (pageRole === "page") {
						engine.instanceWidget(page, "Page");
					} else if (pageRole === "dialog") {
						engine.instanceWidget(page, "Dialog");
					}
					//engine.instanceWidget(page, "Page");
				}
			};

			/**
			* Open page
			* @method open
			* @param {HTMLElement} toPage
			* @param {Object} options
			* @param {string} [options.transition] transition for opening page
			* @param {boolean} [options.reverse=false] true, if transition should
			* 		be reversed
			* @static
			* @member ns.router.Page
			*/
			RouterPage.prototype.open = function (toPage, options) {
				var newHash = toPage.id ? "#" + toPage.id : "",
					settings = {},
					continuation,
					triggerData = {
						toPage: toPage,
						options: options
					},
					historyState = window.history.state || {},
					historyStateUrl = historyState.url,
					pageRole,
					parentElement,
					pageUrl,
					url,
					self = this;

				settings = object.merge({}, RouterPage.defaults, options);
				settings.pageContainer = self.container;

				settings.toPage = toPage;
				parentElement = toPage.parentNode;
				while (parentElement && parentElement !== settings.pageContainer) {
					parentElement = parentElement.parentNode;
				}

				if (parentElement) {
					self.settings = settings;
					continuation = eventUtils.trigger(settings.pageContainer,
							RouterPage.events.PAGE_BEFORE_CHANGE, triggerData);

					if (continuation) {
						pageUrl = DOM.getNSData(toPage, "url");

						if (!pageUrl) {
							pageUrl = "#" + toPage.id;
							DOM.setNSData(toPage, "url", pageUrl);
						}
						else{
							pageUrl = DOM.getNSData(toPage, "url");
						}

						pageUrl = DOM.getNSData(toPage, "url");
						if (toPage) {
							pageRole = DOM.getNSData(toPage, "role");
							if (!pageRole) {
								pageRole = toPage.classList.contains("ui-page") ? "page" : null;
								if (pageRole) { // set just in case ^_^
									DOM.setNSData(toPage, "role", pageRole);
								}
							}
						}

						if (historyStateUrl !== pageUrl) {
							if (pageRole === "dialog") {
								url = "#&ui-state=dialog";
							} else if ((!settings.fromSubmit) && ((historyStateUrl === undefined)
									|| (historyStateUrl.split("#")[0] === pageUrl.split("#")[0]))) {
								url =  (newHash.length > 1) ? newHash : "";
							} else if (toPage === this.firstPage) {
								url = pageUrl.split("#")[0];
							} else {
								url = pageUrl;
								settings.fromSubmit = false;
							}
							window.history.pushState({pageId: toPage.id, url: pageUrl}, "", url);
						}

						if (pageRole === "dialog") {
							ns.router.urlHistory.addNew("#&ui-state=dialog",
									DOM.getNSData(toPage, "transition"), "", pageUrl, pageRole);
						} else {
							ns.router.urlHistory.addNew(newHash,
									DOM.getNSData(toPage, "transition"), "", pageUrl, pageRole);
						}

						settings.reverse = options && options.reverse || false;
						settings.fromPage = settings.fromPage || self.activePage;
						settings.toPage = toPage;

						if ((pageRole === "page" || pageRole === "dialog")
								&& settings.fromPage !== toPage) {
							self.setActivePage(toPage);
						}
						self.settings.fromPage = null;
						self.settings.toPage = null;
					}
				}
			};

			/**
			 * Initializes router
			 * @param {boolean} justBuild
			 * @method init
			 * @member ns.router.Page
			 */
			RouterPage.prototype.init = function (justBuild) {
				var page,
					self = this,
					container = ns.getConfig("container") || RouterPage.defaults.container ||
							document.body;

				RouterPage.defaults.container = container;
				self.container = container;

				eventUtils.trigger(document, "themeinit", this);

								if (justBuild) {
					self.justBuild = justBuild;
					engine.createWidgets(container);
				}

				if (ns.getConfig("autoInitializePage", true)) {
					self.firstPage = container.querySelector(pageDefinition.selector);
					if (!self.firstPage) {
						DOM.wrapInHTML(container.childNodes,
								'<div data-role="page" id="' + ns.getUniqueId() + '"></div>');
						self.firstPage = container.children[0];
					}

					if (justBuild) {
						self.settings = self.settings || {};
						self.settings.toPage = self.firstPage;
						self.setActivePage(self.firstPage, true);
						return;
					}

					if (window.location.hash) {
						//simple check to determine if we should show firstPage or other
						page = document.getElementById(window.location.hash.replace("#", ""));
						if (page && selectors.matchesSelector(page, pageDefinition.selector)) {
							self.firstPage = page;
						}
					}

					container.appendChild(self.getLoader().element);

					//@todo add loader only if html is not built
					//find a way to determine if html is built
					//show body with loader
					//htmlClassList.remove("ui-mobile-rendering");

					self.open(self.firstPage);
					self.navreadyDeferred.resolve();

				}
			};

			/**
			 * Binds events to document and window
			 * @method bindEvents
			 * @member ns.router.Page
			 */
			RouterPage.prototype.bindEvents = function () {
				var self = this,
					events = RouterPage.events;
				self.pagebeforechangeHandler = pagebeforechangeHandler.bind(null, self);
				self.linkClickHandler = linkClickHandler.bind(null, self);
				self.popStateHandler = popStateHandler.bind(null, self);
				self.submitHandler = submitHandler.bind(null, self);
				window.addEventListener(events.POP_STATE, self.popStateHandler, false);
				document.addEventListener(events.PAGE_BEFORE_CHANGE,
						self.pagebeforechangeHandler, false);
				document.addEventListener(events.HASH_CHANGE, self._hashChangeHandler,
						false);
				document.addEventListener(events.CLICK, self.linkClickHandler, false);
				document.addEventListener(events.SUBMIT, self.submitHandler, false);
			};

			/**
			 * Destroys router
			 * @method destroy
			 * @member ns.router.Page
			 */
			RouterPage.prototype.destroy = function () {
				var self = this,
					events = RouterPage.events;
				window.removeEventListener(events.POP_STATE, self.popStateHandler, false);
				document.removeEventListener(events.PAGE_BEFORE_CHANGE,
						self.pagebeforechangeHandler, false);
				document.removeEventListener(events.HASH_CHANGE,
						self._hashChangeHandler, false);
				document.removeEventListener(events.CLICK, self.linkClickHandler, false);
				document.removeEventListener(events.SUBMIT, self.submitHandler, false);
			};

			/**
			 * Sets container for page elements
			 * @param {HTMLElement} element
			 * @method setContainer
			 * @member ns.router.Page
			 */
			RouterPage.prototype.setContainer = function (element) {
				this.container = element;
			};

			/**
			 * Returns container for pages
			 * @return {HTMLElement}
			 * @method getContainer
			 * @member ns.router.Page
			 */
			RouterPage.prototype.getContainer = function () {
				return this.container;
			};

			/**
			 * Returns first page
			 * @return {HTMLElement}
			 * @method getFirstPage
			 * @member ns.router.Page
			 */
			RouterPage.prototype.getFirstPage = function () {
				return this.firstPage;
			};

			ns.router.Page = RouterPage;

			engine.initRouter(RouterPage);
			}(window, window.document, ns));

/*global window, define, setTimeout, ns, clearTimeout, XMLHttpRequest, location */
/*jslint nomen: true */
/*
* Copyright  2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/**
 * #Mobile Router for External
 * Class is responsible for change pages in applications when pages
 * are in external files.
 * @class ns.router.PageExternal
 * @override ns.router.Page
 * @author Maciej Urbanski <m.urbanski@samsung.com>
 * @author Piotr Karny <p.karny@samsung.com>>
 * @author Piotr Kusztal <p.kusztal@samsung.com>
 * @author Hyunkook Cho <hk0713.cho@samsung.com>
 * @author Junhyeon Lee <juneh.lee@samsung.com>
 */
(function (document, ns) {
	
				var HIDE_PAGE_LOADING_TIMEOUT = 1500,
				DOM = ns.util.DOM,
				engine = ns.engine,
				util = ns.util,
				object = util.object,
				selectors = util.selectors,
				Page = ns.widget.mobile.Page,
				pageDefinition = engine.getWidgetDefinition("Page"),
				dialogDefinition = engine.getWidgetDefinition("Dialog"),
				pageSelectorWithData = pageDefinition
					.selector
					.split(",")
					.map(
						function (value) {
							return value + "[data-url]";
						}
					)
					.join(","),
				body = document.body,
				firstPage = null,
				container = ns.getConfig("container") || body,
				loadPageDefaults = {
					type: "get",
					data: undefined,
					reloadPage: false,
					role: undefined, // By default we rely on the role defined by the @data-role attribute.
					showLoadMsg: false,
					pageContainer: container,
					loadMsgDelay: 50 // This delay allows loads that pull from browser cache to occur without showing the loading message.
				},
				path = util.path,
				UtilsDeferred = ns.util.deferred,
				events = ns.event,
				//existing base tag?
				base = document.getElementsByTagName("base")[0],
				//tuck away the original document URL minus any fragment.
				documentUrl = path.parseLocation(),
				//if the document has an embedded base tag, documentBase is set to its
				//initial value. If a base tag does not exist, then we default to the documentUrl.
				documentBase = base ? path.parseUrl(path.makeUrlAbsolute(base.getAttribute("href"), documentUrl.href)) : documentUrl,
				documentBaseDiffers = (documentUrl.hrefNoHash !== documentBase.hrefNoHash),
				activeClickedLink,
				slice = [].slice,
				RouterPage = ns.router.Page,
				pageEvents = RouterPage.events,
				prototype = RouterPage.prototype,
				parentOpen = prototype.open,
				dialogHashKey = "&ui-state=dialog";

			/**
			 * @method removeActiveLinkClass
			 * @param {boolean} forceRemoval
			 * @member ns.router.PageExternal
			 * @private
			 * @static
			 */
			function removeActiveLinkClass(forceRemoval) {
				if (!!activeClickedLink && (!selectors.getClosestByClass(activeClickedLink, ns.getConfig("activePageClass")).length || forceRemoval)) {
					activeClickedLink.classList.remove(ns.getConfig("activeBtnClass"));
				}
				activeClickedLink = null;
			}

			/**
			 * @method findBaseWithDefault
			 * @param {ns.router.PageExternal} router
			 * @member ns.router.PageExternal
			 * @private
			 * @static
			 * @return {boolean}
			 */
			function findBaseWithDefault(router) {
				var closestBase = (router.activePage && path.getClosestBaseUrl(router.activePage, "." + Page.classes.uiPage));
				return closestBase || documentBase.hrefNoHash;
			}

			/**
			 * @method remove
			 * @param {Event} event
			 * @member ns.router.PageExternal
			 * @private
			 * @static
			 */
			function remove(event) {
				var target = event.target;
				target.removeEventListener(pageEvents.PAGE_HIDE, remove, false);
				if (document.location.hash !== "#&ui-state=dialog") {
					if (events.trigger(target, pageEvents.PAGE_REMOVE) && target.parentNode) {
						target.parentNode.removeChild(target);
					}
				}
			}

			/**
			 * When dom caching is not enabled or the page is embedded bind to remove the page on hide
			 * @method _bindPageRemove
			 * @param {HTMLElement} page
			 * @member ns.router.PageExternal
			 * @protected
			 */
			prototype._bindPageRemove = function (page) {
				var pageWidget = engine.getBinding(page);

				if (!pageWidget.options.domCache && DOM.getNSData(page, "external-page")) {
					page.addEventListener(pageEvents.PAGE_HIDE, remove, false);
				}
			};

			/**
			 * Load the page from a url
			 * @method loadPage
			 * @param {string} url
			 * @param {Object} options
			 * @param {string} [options.type] connection type
			 * @param {Object} [options.data] additional url query parameters
			 * @param {boolean} [options.showLoadMsg=false] whether to show loading message
			 * @param {number} [options.loadMsgDelay] loading message delay in milliseconds
			 * @param {boolean} [options.prefetch] if true, this loading will be only a prefetch
			 * @member ns.router.PageExternal
			 */
			prototype.loadPage = function (url, options) {
				var settings = {},

					// The DOM element for the page after it has been loaded.
					page = null,

					// If the reloadPage option is true, and the page is already
					// in the DOM, dupCachedPage will be set to the page element
					// so that it can be removed after the new version of the
					// page is loaded off the network.
					dupCachedPage = null,

					// The absolute version of the URL passed into the function. This
					// version of the URL may contain dialog/subpage params in it.
					absUrl = path.makeUrlAbsolute(url, findBaseWithDefault(this)),
					triggerData,
					deferred = new UtilsDeferred(),
					fileUrl,
					dataUrl,
					loadMsgDelay,
					hideMsg,
					request,
					connectionType,
					self = this,
					loader = self.getLoader(),
					dataUrlHashMask = /(^#)|(\?.*)/g,
					loaderProperties = ns.widget.mobile.Loader.properties;

				settings = object.merge(loadPageDefaults, options || {});
				settings.pageContainer = this.container;
				connectionType = settings.type;
				// If the caller provided data, and we're using "get" request,
				// append the data to the URL.
				if (settings.data) {
					if (connectionType === "get") {
						absUrl = path.addSearchParams(absUrl, settings.data);
						fileUrl = absUrl;
						settings.data = undefined;
						settings.fromSubmit = true;
					}

					// If the caller is using a "post" request, reloadPage must be true
					if (connectionType === "post") {
						settings.reloadPage = true;
					}
				}

				// The absolute version of the URL minus any dialog/subpage params.
				// In otherwords the real URL of the page to be loaded.
				fileUrl = fileUrl || path.getFilePath(absUrl);

					// The version of the Url actually stored in the data-url attribute of
					// the page. For embedded pages, it is just the id of the page. For pages
					// within the same domain as the document base, it is the site relative
					// path. For cross-domain pages (Phone Gap only) the entire absolute Url
					// used to load the page.
				dataUrl = path.convertUrlToDataUrl(absUrl, dialogHashKey, documentBase, documentUrl);

				// Make sure we have a pageContainer to work with.
				settings.pageContainer = settings.pageContainer || ns.getConfig("pageContainer", document.body);

				// Check to see if the page already exists in the DOM.
				// NOTE do _not_ use the :jqmData psuedo selector because parenthesis
				//	are a valid url char and it breaks on the first occurence
				page = selectors.getChildrenByDataNS(settings.pageContainer, "url='" + dataUrl + "'")[0];

				// If we failed to find the page, check to see if the url is a
				// reference to an embedded page. If so, it may have been dynamically
				// injected by a developer, in which case it would be lacking a data-url
				// attribute and in need of enhancement.
				if (!page && (dataUrl && !path.isPath(dataUrl))) {
					page = document.getElementById(dataUrl.replace(dataUrlHashMask, ""));
					if (page) {
						// The page can be in our DOM, but its current url can be different than
						// target page, so we are checking if the page uri matches desired location.
						// Added for JQM Router/Page tests.
						if (page.baseURI !== absUrl.split("#")[0]) {
							DOM.setNSData(page, "url", absUrl);
						} else {
							DOM.setNSData(page, "url", dataUrl);
						}
					}
				}

				// If we failed to find a page in the DOM, check the URL to see if it
				// refers to the first page in the application. If it isn't a reference
				// to the first page and refers to non-existent embedded page, error out.
				if (!page) {
					if (firstPage && path.isFirstPageUrl(fileUrl, documentBase, documentBaseDiffers, documentUrl)) {
						// Check to make sure our cached-first-page is actually
						// in the DOM. Some user deployed apps are pruning the first
						// page from the DOM for various reasons, we check for this
						// case here because we don't want a first-page with an id
						// falling through to the non-existent embedded page error
						// case. If the first-page is not in the DOM, then we let
						// things fall through to the ajax loading code below so
						// that it gets reloaded.
						if (firstPage.parentNode) {
							page = firstPage;
						}
					} else if (path.isEmbeddedPage(fileUrl)) {
						deferred.reject(absUrl, settings);
						return deferred.promise();
					}
				}

				// If the page we are interested in is already in the DOM,
				// and the caller did not indicate that we should force a
				// reload of the file, we are done. Otherwise, track the
				// existing page as a duplicated.
				if (page) {
					if (!settings.reloadPage) {
						DOM.setNSData(page, "url", dataUrl);
						parentOpen.call(this, page, settings);
						deferred.resolve(absUrl, settings, page);
						//if we are reloading the page make sure we update the base if its not a prefetch

						if (!settings || !settings.prefetch) {
							this.setBase(absUrl.split("#")[0]);
						}
						return deferred.promise();
					}
					engine.removeBinding(page);
					dupCachedPage = page;
				}

				triggerData = { url: url, absUrl: absUrl, dataUrl: dataUrl, deferred: deferred, settings: settings };

				// Let listeners know we're about to load a page.
				// If the default behavior is prevented, stop here!
				if (!events.trigger(settings.pageContainer, pageEvents.PAGE_BEFORE_LOAD, triggerData)) {
					return deferred.promise();
				}

				if (settings.showLoadMsg) {
					// This configurable timeout allows cached pages a brief delay to load without showing a message
					loadMsgDelay = setTimeout(function () {
						loader.show();
						return false;
					}, settings.loadMsgDelay);

						// Shared logic for clearing timeout and removing message.
					hideMsg = function () {
						// Stop message show timer
						clearTimeout(loadMsgDelay);
						// Hide loading message
						loader.hide();
					};
				}

				// Reset base to the default document base.
				// only reset if we are not prefetching
				if ((settings === undefined || settings.prefetch === undefined)) {
					this.resetBase();
				}

				if ((ns.getConfig("allowCrossDomainPages") || path.isSameDomain(documentUrl, absUrl))) {
					// Load the new page.
					request = new XMLHttpRequest();
					request.open(settings.type || "GET", fileUrl, true);
					request.responseType = "document";
					request.onreadystatechange = function () {
						var status,
							requestedDocument = null,
							title,
							page,
							url,
							body,
							scripts,
							scriptRunner,
							onPageCreate,
							eventData = {},
							tempDoc,
							newPath,
							elements;
						if (request.readyState === 4) {
							status = request.status;
							requestedDocument = request.responseXML;
							if ((status === 200 || status === 0) && requestedDocument) {

								title = requestedDocument.querySelector("title");
								if (title) {
									title = title.textContent;
								}

								//@TODO add support for selecting a specific page with #hashtag
								//in external page as the following algorithm does not support
								// external/document.html#page url syntax

								page = requestedDocument.querySelector(pageSelectorWithData);
								if (page) {
									url = path.getFilePath(DOM.getNSData(page, "url"));
								} else {
									url = absUrl;
								}

								if ((settings === undefined || settings.prefetch === undefined)) {
									self.setBase(absUrl);
								}

								// if no page with a proper data-url was found, find any other page
								if (!page) {
									page = requestedDocument.querySelector(pageDefinition.selector);
								}

								// if page not found check if a dialog was requested
								if (!page) {
									page = requestedDocument.querySelector(dialogDefinition.selector);
								}

								// if still there is no page element, create one
								if (!page) {
									tempDoc = document.implementation.createDocument("http://www.w3.org/1999/xhtml", "html", null);
									page = tempDoc.createElement("div");
									DOM.setNSData(page, "role", "page");
									body = tempDoc.importNode(requestedDocument.body, true);
									while (body.firstChild) {
										page.appendChild(body.firstChild);
									}
								}

								// page specific title has the highest priority
								if (DOM.hasNSData(page, "title")) {
									title = DOM.getNSData(page, "title");
								}

								//rewrite src and href attrs to use a base url
								if (!ns.getConfig("supportDynamicBaseTag")) {
									newPath = path.get(url);
									elements = selectors.getChildrenByDataNS(page, "ajax='false'");
									elements.concat(selectors.getChildrenBySelector(page, "[src], link[href], a[rel='external'], a[target]"));
									elements.forEach(function (element) {
										var thisAttr = element.href === undefined ? "href" : (element.src === undefined ? "action" : "src"),
											thisUrl = element.getAttribute(thisAttr);
										thisUrl = thisUrl.replace(location.protocol + "//" + location.host + location.pathname, "");
										if (!/^(\w+:|#|\/)/.test(thisUrl)) {
											element.setAttribute(thisAttr, newPath + thisUrl);
										}
									});
								}

								page = util.importEvaluateAndAppendElement(page, settings.pageContainer);

								// append to page and enhance
								// TODO taging a page with external to make sure that embedded pages aren't removed
								// by the various page handling code is bad. Having page handling code in many
								// places is bad. Solutions post 1.0
								dataUrl = path.convertUrlToDataUrl(url, dialogHashKey, documentBase);
								DOM.setNSData(page, "url", dataUrl);
								DOM.setNSData(page, "external-page", true);

								// wait for page creation to leverage options defined on widget
								onPageCreate = function () {
									page.removeEventListener(pageEvents.PAGE_CREATE, onPageCreate, false);
									// in jqm interface function _bindPageRemove have in this current page, in new interface page is call as first argument
									ns.getConfig("_bindPageRemove", self._bindPageRemove).call(page, page);
								};

								page.addEventListener(pageEvents.PAGE_CREATE, onPageCreate, false);

								// Enhancing the page may result in new dialogs/sub pages being inserted
								// into the DOM. If the original absUrl refers to a sub-page, that is the
								// real page we are interested in.
								if (absUrl.indexOf("&" + ns.getConfig("subPageUrlKey")) > -1) {
									page = selectors.getChildrenByDataNS("url='" + dataUrl)[0];
								}

								//bind pageHide to removePage after it's hidden, if the page options specify to do so

								// Remove loading message.
								if (settings.showLoadMsg) {
									hideMsg();
								}

								// Add the page reference and xhr to our eventData.
								eventData.xhr = request;
								eventData.textStatus = status;
								eventData.page = page;

								// Let listeners know the page loaded successfully.
								events.trigger(settings.pageContainer, pageEvents.PAGE_LOAD, eventData);

								deferred.resolve(absUrl, settings, page, dupCachedPage);
							} else {
								//set base back to current path
								if (base) {
									self.setBase(path.getDocumentUrl());
								}

								// Add error info to our eventData.
								eventData.xhr = request;
								eventData.textStatus = status;
								eventData.errorThrown = null;//errorThrown;

								// Let listeners know the page load failed.
								// If the default behavior is prevented, stop here!
								// Note that it is the responsibility of the listener/handler
								// that called preventDefault(), to resolve/reject the
								// deferred object within the eventData.
								if (!events.trigger(settings.pageContainer, pageEvents.PAGE_LOAD_FAILED, eventData)) {
									return;
								}

								// Remove loading message.
								if (settings.showLoadMsg) {
									// Remove loading message.
									hideMsg();
									// show error message
									loader.show(loaderProperties.pageLoadErrorMessageTheme, loaderProperties.pageLoadErrorMessage, true);

									// hide after delay
									setTimeout(loader.hide, HIDE_PAGE_LOADING_TIMEOUT);
								}

								deferred.reject(absUrl, settings);
							}
						} // if end
					};
					request.send(settings.data);
				} else {
					deferred.reject(absUrl, settings);
				}


				return deferred.promise();
			};

			/**
			 * Open a page
			 * @method open
			 * @param {string|HTMLElement} toPage page url or element
			 * @param {Object} options
			 * @param {string} [options.type] connection type
			 * @param {Object} [options.data] additional url query parameters
			 * @param {boolean} [options.showLoadMsg=false] whether to show loading message
			 * @param {number} [options.loadMsgDelay] loading message delay in milliseconds
			 * @member ns.router.PageExternal
			 */
			prototype.open = function (toPage, options) {
				var self = this;
				if (typeof toPage === "string") {
					self.loadPage(toPage, options)
						.done(function (url, newOptions, newPage, dupCachedPage) {
							newOptions.duplicateCachedPage = dupCachedPage;
							setTimeout(function () {
								parentOpen.call(self, newPage, newOptions);
							}, 10);
						})
						.fail(function (url, options) {
							//clear out the active button state
							removeActiveLinkClass(true);

							events.trigger(options.pageContainer, pageEvents.PAGE_CHANGE_FAILED, {});
						});
					return;
				}
				parentOpen.call(self, toPage, options);
			};
			/**
			 * @method getBaseElement
			 * @member ns.router.PageExternal
			 * @return {HTMLElement} base element
			 */
			prototype.getBaseElement = function () {
				if (!base && !this.justBuild) {
										base = document.createElement("base");
					document.head.appendChild(base);
				}
				return base;
			};
			/**
			 * Sets href url on base element
			 * @method setBase
			 * @param {string} href
			 * @member ns.router.PageExternal
			 * @return {HTMLElement} base element
			 */
			prototype.setBase = function (href) {
				var baseElement = this.getBaseElement();
				if (baseElement) {
					baseElement.setAttribute("href", path.makeUrlAbsolute(href, documentBase));
				}

				return baseElement;
			};
			/**
			 * Resets href url on base element
			 * @method resetBase
			 * @member ns.router.PageExternal
			 * @return {HTMLElement} base element
			 */
			prototype.resetBase = function () {
				var baseElement = this.getBaseElement();

				// Change nothing when just building
				if (!engine.getJustBuild() && baseElement) {
					baseElement.setAttribute("href", documentBase.hrefNoHash);
				}

				return baseElement;
			};

			}(window.document, ns));

/*global window, define, HTMLElement, ns, setTimeout */
/*jslint nomen: true */
/*
* Copyright  2010 - 2014 Samsung Electronics Co., Ltd.
* License : MIT License V2
*/
/**
 * #Mobile Router with Transition
 * Class is responsible for change pages in applications when
 * transition is enable.
 * @class ns.router.PageTransition
 * @override ns.router.Page
 * @author Maciej Urbanski <m.urbanski@samsung.com>
 * @author Piotr Karny <p.karny@samsung.com>>
 * @author Hyunkook Cho <hk0713.cho@samsung.com>
 * @author Junhyeon Lee <juneh.lee@samsung.com>
 */
(function (window, document, ns) {
	
				var MAX_SCROLL_FOR_TRANSITION_FACTOR = 3,
				util = ns.util,
				selectors = util.selectors,
				isPageTransitioning = false,
				pageTransitionQueue = [],
				RouterPage = ns.router.Page,
				parentInit = RouterPage.prototype.init,
				//existing base tag?
				//tuck away the original document URL minus any fragment.
				activeClickedLink,
				transitions = {},
				DOM = util.DOM,
				UtilsDeferred = util.deferred,
				engine = ns.engine,
				maxTransitionWidth = false,
				/**
				 * Returns max scroll amount
				 * @return {number}
				 * @method getMaxScrollForTransition
				 * @private
				 * @static
				 * @member ns.router.PageTransition
				 */
				getMaxScrollForTransition = function () {
					return window.offsetHeight * MAX_SCROLL_FOR_TRANSITION_FACTOR;
				},
				defaultHomeScroll = 0,
				classes = {
					uiPagePreIn: "ui-page-pre-in",
					uiMobileViewportTransitioning: "ui-mobile-viewport-transitioning",
					viewportPrefix: "viewport-",
					reverse: "reverse",
					out: "out",
					inClass: "in",
					uiBlocker: "ui-blocker"
				},
				/**
				 * Transition handler
				 * @param {boolean} sequential
				 * @method transitionHandler
				 * @private
				 * @static
				 * @member ns.router.PageTransition
				 */
				transitionHandler = function (sequential) {

					// Default to sequential
					if (sequential === undefined) {
						sequential = true;
					}

					return function (name, reverse, to, from) {

						var deferred = new UtilsDeferred(),
							router = ns.engine.getRouter(),
							focusPage = router.focusPage,
							container = router.container,
							reverseClass = reverse ? classes.reverse : "",
							toScroll = 0,//active.lastScroll || defaultHomeScroll,
							screenHeight = window.offsetHeight,
							maxTransitionOverride = maxTransitionWidth !== false
									&& window.offsetWidth > maxTransitionWidth,
							none = maxTransitionOverride || !name || name === "none" ||
									Math.max(window.scrollY, toScroll) > getMaxScrollForTransition(),
							toPreClass = classes.uiPagePreIn,
							toggleViewportClass = function () {
								var containerClassList = container.classList;
								containerClassList.toggle(classes.uiMobileViewportTransitioning);
								containerClassList.toggle(classes.viewportPrefix + name);
							},
							fromWidget,
							toWidget,
							fromClassList = from && from.classList,
							toClassList = to.classList,
							toStyle = to.style,
							fromStyle = from && from.style,
							scrollPage = function () {
								// Prevent blinking on page scrolling in Tizen/Android devices.
								// Don't scoll window, when current scroll top(scrollY) is already at
								// toScroll, or when current scroll top is 0 and toScroll is same to
								// defaultHomeScroll (which means the top position of page). In these
								// case, page scrolling is not needed.
								var st = window.scrollY;
								if (st === toScroll || (defaultHomeScroll === toScroll
										&& st === 0)) {
									return;
								}

								// By using scrollTo instead of silentScroll, we can keep things
								// better in order Just to be precautios, disable scrollstart
								// listening like silentScroll would
								ns.setConfig("event.special.scrollstart.enabled", false);

								window.scrollTo(0, toScroll);

								// reenable scrollstart listening like silentScroll would
								// 150ms timeout ensures that the scrolling will be complete
								setTimeout(function () {
									ns.setConfig("event.special.scrollstart.enabled", true);
								}, 150);
							},
							cleanFrom = function () {
								fromWidget = engine.getBinding(from);
								if (fromWidget) {
									fromWidget.setActive(false, router.getContainer());
								}
								fromClassList.remove(classes.out);
								fromClassList.remove(classes.inClass);
								fromClassList.remove(classes.reverse);
								fromClassList.remove(name);
								fromStyle.height = "";
							},
							doneIn = function () {
								to.removeEventListener("animationend", doneIn, false);
								to.removeEventListener("webkitAnimationEnd", doneIn, false);
								if (!sequential) {
									if (from) {
										cleanFrom();
									}
								}

								toClassList.remove(classes.out);
								toClassList.remove(classes.inClass);
								toClassList.remove(classes.reverse);
								toClassList.remove(name);
								toStyle.height = "";

								toggleViewportClass();

								// In some browsers (iOS5), 3D transitions block the ability to
								// scroll to the desired location during transition This ensures we
								// jump to that spot after the fact, if we aren't there already.
								if (window.scrollY !== toScroll) {
									scrollPage();
								}

								deferred.resolve(name, reverse, to, from, true);
							},
							startIn = function () {
								// Prevent flickering in phonegap container: see comments at #4024
								// regarding iOS
								toStyle.zIndex = -10;

								toWidget = engine.instanceWidget(to, DOM.getNSData(to, "role") ===
										"page" ? "Page" : "Dialog");
								toWidget.setActive(true, router.getContainer());

								toClassList.add(toPreClass);

								// Send focus to page as it is now display: block
								focusPage(to);

								// Set to page height
								toStyle.height = screenHeight + toScroll;

								scrollPage();

								// Restores visibility of the new page: added together with
								// $to.css("z-index", -10);
								toStyle.zIndex = "";

								if (!none) {
									to.addEventListener("animationend", doneIn, false);
									to.addEventListener("webkitAnimationEnd", doneIn, false);
								}

								toClassList.remove(toPreClass);
								toClassList.add(name);
								toClassList.add(classes.inClass);
								if (reverseClass) {
									toClassList.add(reverseClass);
								}

								if (none) {
									setTimeout(doneIn, 0);
								}

							},
							doneOut = function () {
								if (from && sequential) {
									from.removeEventListener("animationend", doneOut, false);
									from.removeEventListener("webkitAnimationEnd", doneOut, false);
									cleanFrom();
								}
								startIn();
							},
							startOut = function () {
								// if it's not sequential, call the doneOut transition to start the
								// TO page animating in simultaneously
								if (sequential) {
									from.addEventListener("animationend", doneOut, false);
									from.addEventListener("webkitAnimationEnd", doneOut, false);
								} else {
									doneOut();
								}

								// Set the from page's height and start it transitioning out
								// Note: setting an explicit height helps eliminate tiling in the
								// transitions
								fromStyle.height = screenHeight + window.scrollY;
								fromClassList.add(name);
								fromClassList.add(classes.out);
								if (reverseClass) {
									fromClassList.add(reverseClass);
								}
							};

						toggleViewportClass();

						if (from && !none) {
							startOut();
						} else {
							doneOut();
						}

						return deferred.promise();
					};
				};

			/**
			 * @method _maybeDegradeTransition
			 * @param {string} transition
			 * @member ns.router.PageTransition
			 * @private
			 * @static
			 * @return {string} transition
			 */
			function _maybeDegradeTransition(transition) {
				if (transition && !ns.support.cssTransform3d && transitions[transition]
						&& transitions[transition].fallback) {
					transition = transitions[transition].fallback;
				}

				return transition;
			}

			/**
			 * @method removeEventBlocker
			 * @member ns.router.PageTransition
			 * @private
			 * @static
			 */
			function removeEventBlocker() {
				var html = document.querySelector("html");
				html.classList.remove(classes.uiBlocker);
				//$html.unbind( "touchstart touchend vclick mousedown mouseup click" );
			}

			/**
			 * @method transitionPages
			 * @param {HTMLElement} toPage
			 * @param {HTMLElement} fromPage
			 * @param {string} transition
			 * @param {boolean} reverse
			 * @member ns.router.PageTransition
			 * @private
			 * @static
			 * @return {Object} promise
			 */
			function transitionPages(toPage, fromPage, transition, reverse) {
				var handler = (transitions[transition || "default"]
								&& transitions[transition || "default"].handler) ||
										transitions["default"].handler,
					promise = handler(transition, reverse, toPage, fromPage);

				//clear page loader
				//$.mobile.hidePageLoadingMsg();

				transition = _maybeDegradeTransition(transition);

				//find the transition handler for the specified transition. If there
				//isn't one in our transitionHandlers dictionary, use the default one.
				//call the handler immediately to kick-off the transition.

				promise.done(function () {
					util.requestAnimationFrame(function () {
						removeEventBlocker();
					});
				});

				return promise;
			}

			/**
			 * @method removeActiveLinkClass
			 * @param {boolean} forceRemoval
			 * @member ns.router.PageTransition
			 * @private
			 * @static
			 */
			function removeActiveLinkClass(forceRemoval) {
				if (!!activeClickedLink && (!selectors.getClosestByClass(activeClickedLink,
						ns.getConfig("activePageClass")).length || forceRemoval)) {
					activeClickedLink.classList.remove(ns.getConfig("activeBtnClass"));
				}
				activeClickedLink = null;
			}

			/**
			 * @method releasePageTransitionLock
			 * @param {ns.router.Page} router
			 * @member ns.router.PageTransition
			 * @private
			 * @static
			 */
			function releasePageTransitionLock(router) {
				isPageTransitioning = false;
				if (pageTransitionQueue.length > 0) {
					router.open(pageTransitionQueue.pop());
				}
			}

			/**
			 * Changes page.
			 * @method changePage
			 * @param {Object} settings
			 * @param {Object} [settings.fromPage]
			 * @param {Object} [settings.toPage]
			 * @param {string} [settings.transition]
			 * @param {boolean} [settings.reverse=false]
			 * @param {boolean} [settings.duplicateCachedPage]
			 * @member ns.router.PageTransition
			 */
			RouterPage.prototype.changePage = function (settings) {
				var fromPage = settings.fromPage,
					toPage = settings.toPage,
					router = this;

				if (isPageTransitioning) {
					pageTransitionQueue.unshift(arguments);
					return;
				}

				transitionPages(toPage, fromPage, settings.transition, settings.reverse)
					.done(function (name, reverse, toPage, fromPage) {
						var duplicateCachedPage = settings.duplicateCachedPage;
						removeActiveLinkClass();

						//if there's a duplicateCachedPage, remove it from the DOM now that it's
						//hidden
						if (duplicateCachedPage instanceof HTMLElement) {
							duplicateCachedPage.parentNode.removeChild(duplicateCachedPage);
						}

						releasePageTransitionLock(router);
						router.changePageFinish(fromPage, toPage);
						isPageTransitioning = false;
					});
			};

			/**
			 * Registers transition.
			 * @method registerTransition
			 * @param {string} name
			 * @param {Object} handler
			 * @param {Object} fallback
			 * @member ns.router.PageTransition
			 */
			RouterPage.prototype.registerTransition = function (name, handler, fallback) {
				transitions[name] = {
					handler: handler,
					fallback: fallback
				};
			};

			/**
			 * Returns list of transitions.
			 * @method getTransitions
			 * @member ns.router.PageTransition
			 * @return {Array} transitions
			 */
			RouterPage.prototype.getTransitions = function () {
				return transitions;
			};

			/**
			 * Returns transition.
			 * @method getTransition
			 * @param {string} name
			 * @member ns.router.PageTransition
			 * @return {Object} transition
			 */
			RouterPage.prototype.getTransition = function (name) {
				return transitions[name];
			};

			RouterPage.prototype._maybeDegradeTransition = _maybeDegradeTransition;

			RouterPage.prototype.getMaxScrollForTransition = getMaxScrollForTransition;

			/**
			 * Initializes router.
			 * @method init
			 * @param {boolean} justBuild
			 * @member ns.router.PageTransition
			 */
			RouterPage.prototype.init = function (justBuild) {
				var self = this;
				self.registerTransition("sequential", transitionHandler());
				self.registerTransition("simultaneous", transitionHandler(false));
				self.registerTransition("default", self.getTransition("sequential").handler);
				self.registerTransition("flip", null, "fade");
				self.registerTransition("depth", self.getTransition("simultaneous").handler,
						"fade");
				self.registerTransition("flow", null, "fade");
				self.registerTransition("pop", null, "fade");
				self.registerTransition("slide", self.getTransition("simultaneous").handler,
						"fade");
				self.registerTransition("slidedown", null, "fade");
				self.registerTransition("slideup", null, "fade");
				self.registerTransition("slidefade", null, "fade");
				self.registerTransition("turn", null, "fade");
				parentInit.call(self, justBuild);
			};

			}(window, window.document, ns));

/*global window, define, ns */
/*jslint plusplus: true, nomen: true */
(function (document, ns) {
	
	
			var engine = ns.engine,
				object = ns.util.object,
				router = null;

			/**
			 * Look to ns.router.Page#open
			 * @method changePage
			 * @inheritdoc ns.router.Page#open
			 * @member ns
			 */
			ns.changePage = function (toPage, options) {
				if (router) {
					router.open(toPage, options);
				}
			};

			/**
			 * Back in history.
			 * @method back
			 * @static
			 * @member ns
			 */
			ns.back = function () {
				window.history.back();
			};

			/**
			 * Look to ns.router.Page#open
			 * @method openPopup
			 * @inheritdoc ns.router.Page#open
			 * @member ns
			 */
			ns.openPopup = function (to, options) {
				if (router) {
					router.open(to, object.merge({}, options, {
						rel : "popup"
					}));
				}
			};

			/**
			 * Close active popup
			 * @method closePopup
			 * @static
			 * @member ns
			 */
			ns.closePopup = function () {
				var activePopup = ns.activePopup;
				if(activePopup) {
					activePopup.close();
				}
			};

			document.addEventListener("routerinit", function () {
				router = engine.getRouter();
			}, true);

			}(document, ns));

/*global define, ns */
(function (ns) {
	
				var THEME = 's',
				ThemeCommon = ns.theme.ThemeCommon,
				theme = new ThemeCommon(),

				customizePage = function () {
					var Page = ns.widget.mobile.Page;
						if (Page) {
						// Clear default theme for child elements
						(function (o) {
							o.backBtnTheme= THEME;
							o.headerTheme = THEME;
							o.footerTheme = THEME;
							o.theme = THEME;
						}(Page.prototype.options));
					}
				},

				customizeListview = function () {
					var Listview = ns.widget.mobile.Listview;
					if (Listview) {
						// clear listview
						(function (o) {
							o.theme = THEME;
							o.countTheme = THEME;
							o.headerTheme = THEME;
							o.dividerTheme = THEME;
							o.splitTheme = THEME;
						}(Listview.prototype.options));
					}
				},

				customizeButton = function () {
					var Button = ns.widget.mobile.Button;
					if (Button) {
						//clear button theme
						Button.prototype.options.theme = THEME;
					}
				},

				customizeFrameworkData = function () {
					if (ns.frameworkData) {
						// Original scale of the theme
						ns.frameworkData.defaultViewportWidth = 360; // Fit to device-width
						ns.frameworkData.defaultFontSize = 22;
					}
				};

				/*
				customizeCollapsible = function () {
					if (ns.widget.Collapsible) {
						// Collapsible
						(function (o) {
							o.heading = o.heading + ',li';		// Add listitem as a heading
							o.inset = false;
							o.iconPos = "right";	// Move iconPos to right position
							o.collapsedIcon = "arrow-u";
							o.expandedIcon = "arrow-d";
							o.animation = true;
							o.customEventHandler = function (isCollapse) {
								var self = this,
									c = $(self).children('.ui-collapsible-content')[0],
									h;

								function _getHeight(el) {
									var hh = 0,
										heading = $(el).children('.ui-collapsible-heading')[0],
										content = $(el).children('.ui-collapsible-content')[0];

									hh += heading.clientHeight;
									$(content).children().each(function (idx, _el) {
										if ($(_el).hasClass('ui-collapsible')) {	// recursive call for nested collapsible list
											hh += _getHeight(_el);
										} else {
											hh += _el.clientHeight;
										}
									});
									return hh;
								}

								if (isCollapse) {	// collapse!
									// remember current height
									$(c).data('max-height', _getHeight(self));
									$(self).parentsUntil('.ui-page', '.ui-collapsible').each(function (idx, el) {
										var content = $(el).children('.ui-collapsible-content')[0];
										$(content).data('max-height', _getHeight(el));
									});
								} else {	// expand!
									h = $(c).data('max-height');
									if (!h) {
										h = document.body.clientHeight;
										$(c).data('max-height', h);
									}
									$(c).css('max-height', h);
									$(self).parentsUntil('.ui-page', '.ui-collapsible').each(function (idx, el) {
										var content = $(el).children('.ui-collapsible-content')[0];
										$(content).css('max-height', _getHeight(el));
									});
								}
							};
						}(ns.widget.Collapsible.prototype.options));
					};
				};
				*/

			theme.enable = function () {
				var self = this;
				self._enable();

				customizePage();
				customizeListview();
				customizeButton();
				customizeFrameworkData();

				return self;
			};

			theme.disable = function () {
				var self = this;
				self._disable();
				return self;
			};

			// activate theme;
			theme.enable();
			return theme;
			}(ns));

/*global define, window */
/* 
 * Copyright (c) 2010 - 2014 Samsung Electronics Co., Ltd.
 * License : MIT License V2
 */
/*
 * @author Maciej Urbanski <m.urbanski@samsung.com>
 * @author Krzysztof Antoszek <k.antoszek@samsung.com>
 */
(function (ns) {
	
				if (ns.getConfig("autorun", true) === true) {
				ns.engine.run();
			}
			}(ns));

/*global window, define*/
/*
 * Copyright  2010 - 2014 Samsung Electronics Co., Ltd.
 * License : MIT License V2
 */
/**
 * #Application Page Layout
 *
 * In the mobile Tizen Advanced UI framework (TAU) the page and its elements
 * (header, content, and footer) are all <div> blocks with a specific data-role
 * property. The header is placed at the top, and displays the page title.
 * The content is the area below the header, showing the main content of the
 * page. The footer is at the bottom, and contains the page menu.
 *
 * The following table describes the specific information for each section.
 *
 * <table>
 * <caption>Table: Page sections</caption>
 * <tbody>
 * <tr>
 * <th style="width:10%;">Section</th>
 * <th>data-role</th>
 * <th>Description</th>
 * </tr>
 * <tr>
 * <td>Page</td>
 * <td><span style="font-family: Courier New,Courier,monospace">"page"</span></td>
 * <td><p>Defines the element as a page.</p>
 * <p>The page widget is used to manage a single item in a page-based architecture.</p>
 * <p>A page is composed of header (optional), content (mandatory), and footer (optional) elements.</p></td>
 * </tr>
 * <tr>
 * <td>Header</td>
 * <td><span style="font-family: Courier New,Courier,monospace">"header"</span></td>
 * <td><p>Defines the element as a header.</p>
 * <p>As the Tizen Wearable device screen size is small, avoid using the header element.</p></td>
 * </tr>
 * <tr>
 * <td>Content</td>
 * <td><span style="font-family: Courier New,Courier,monospace">"content"</span></td>
 * <td><p>Defines the element as content.</p></td>
 * </tr>
 * <tr>
 * <td>Footer</td>
 * <td><span style="font-family: Courier New,Courier,monospace">"footer"</span></td>
 * <td><p>Defines the element as a footer.</p>
 * <p>The footer section is mostly used to include option buttons.</p></td>
 * </tr>
 * </tbody>
 * </table>
 *
 * To add a page to the application, use the following code:
 *
 * 		@example
 * 		<div data-role="page">
 *			<!--Page area-->
 *			<div data-role="header"><!--Header area--></div>
 *			<div data-role="content"><!--Content area--></div>
 *			<div data-role="footer"><!--Footer area--></div>
 *		</div>
 *
 * In your application, you can:
 *
 * - [Create multi-page layouts](multipage.htm)
 * - [Change the active page](change.htm)
 * - [Handle page events and method](pageevents.htm)
 *
 * @page ns.page.layout
 * @seeMore ../index.htm Tizen Advanced UI Framework
 */
;
/*global window, define*/
/*
 * Copyright  2010 - 2014 Samsung Electronics Co., Ltd.
 * License : MIT License V2
 */
/**
 * #Multi-page Layout
 *
 * You can implement a template containing multiple page containers in the application index.html file.
 *
 * In the multi-page layout, we can define multi pages with data-role="page" attribute.
 *
 * You can link to internal pages by referring to the ID of the page. For example, to link to the page with an ID of two, the link element needs the href="#two" attribute in the code, as in the following example.
 *
 * 		@example
 * 		<div data-role="page" id="main">
 *			<div data-role="header" data-position="fixed">
 *				<!--Header-->
 *			</div>
 *			<div data-role="content">
 *				<a href="#two"data-role="button">TWO</a>
 *			</div>
 *		</div>
 *		<div data-role="page" id="two">
 *			<div data-role="header" data-position="fixed">
 *				<!--Header-->
 *			</div>
 *			<div data-role="content">
 *				<!--Content-->
 *			</div>
 *		</div>
 *
 * To find the currently active page, use the ui-page-active class.
 *
 * @page ns.page.multipage
 * @seeMore layout.htm Application Page Layout
 */
;
/*global window, define*/
/*
 * Copyright  2010 - 2014 Samsung Electronics Co., Ltd.
 * License : MIT License V2
 */
/**
 * #Changing Pages
 *
 * With TAU library, we can change page by method *changePage*.
 *
 * The following table lists the methods you can use to change the active page.
 *
 *!!!When you want to change pages with TAU, *DO NOT USE* _location.href_ or
 * _location.replace. TAU have self-method of managing histories. But when you
 * use above methods, it would lead to confusion. If you want to change pages,
 * you can use _tau.changePage()_ and _tau.back()_.!!!
 * ##Page changing methods
 * ### Summary
 *<table class="informaltable">
 *<thead>
 *<tr>
 *<th>Method</th>
 *<th>Description</th>
 *</tr>
 *</thead>
 *<tbody>
 *
 *
 *<tr>
 *<td>
 *<pre class="intable prettyprint"><a href="#method-changePage">tau.changePage</a> (toPage, options) </pre>
 *</td>
 *<td><p>Programmatically change to another page. The <span style="font-family: Courier New,Courier,monospace">to</span> argument is a page object or string.</p></td>
 *</tr>
 *
 *
 *
 *<tr>
 *<td>
 *<pre class="intable prettyprint"><a href="#method-back">tau.back</a> (  ) </pre>
 *</td>
 *<td><p>Loads the previous page in the history list.</p></td>
 *</tr>
 *</tbody>
 *</table>
 *
 *<dt class="method" id="addidp28072"><code><b><span class="methodName"
 *id="method-changePage">tau.changePage</span></b></code></dt>
 *<dd>
 *<div class="brief">
 *<p>Programmatically change to another page.</p>
 *</div>
 *<div class="synopsis">
 *<pre class="signature prettyprint">tau.changePage (toPage, options) </pre>
 *</div>
 *
 *<div class="description">
 *<p>
 *
 *</p>
 *</div>
 *
 *<div class="parameters">
 *<p><span class="param">Parameters:</span></p>
 *<table>
 *<tbody>
 *<tr>
 *<th>Parameter</th>
 *<th>Type</th>
 *<th>Required / optional</th>
 *<th>Description</th>
 *</tr>
 *
 *
 *<tr>
 *<td><span style="font-family: Courier New,Courier,monospace">toPage</span></td>
 *<td>HTMLElement | string</td>
 *<td>required</td>
 *<td>page to move <br>HTML element or relative url of page.</td>
 *</tr>
 *
 *<tr>
 *<td><span style="font-family: Courier New,Courier,monospace">options</span></td>
 *<td>Object</td>
 *<td>optional</td>
 *<td>options to change pages.</td>
 *</tr>
 *</table></tbody></div>
 *
 *<div class="parameters">
 *<p><span class="param">Options for changePage():</span></p>
 *<table>
 *<tbody>
 *<tr>
 *<th>option</th>
 *<th>Type</th>
 *<th>value</th>
 *<th>Description</th>
 *</tr>
 *
 *
 *<tr>
 *<td><span style="font-family: Courier New,Courier,monospace">transition</span></td>
 *<td>string</td>
 *<td>'sequential' | 'simultaneous' | 'flip' |'depth' | 'pop' | 'slide' |'turn'</td>
 *<td>transition for opening page</td>
 *</tr>
 *
 *<tr>
 *<td><span style="font-family: Courier New,Courier,monospace">reverse</span></td>
 *<td>boolean</td>
 *<td>true | false</td>
 *<td>true, if transition should be reversed</td>
 *</tr>
 *</table></tbody></div>
 *
 *<div class="example">
 *<span class="example"><p>Code
 *example (using HTML Element):</p><p></p></span>
 *<pre name="code" class="examplecode
 *prettyprint">
 *&lt;div data-role=&quot;page&quot; id=&quot;main&quot;&gt;...&lt;/div&gt;
 *&lt;script&gt;
 *var element = document.getElementById("main");
 *tau.changePage(element, {transition:'flip',reverse:false});
 *&lt;/script&gt;
 *</pre>
 *</div>
 *
 *<div class="example">
 *<span class="example"><p>Code
 *example2 (using url string):</p><p></p></span>
 *<pre name="code" class="examplecode
 *prettyprint">
 * // This is "index.html" and if there is "subPage.html" in same directory.
 *&lt;script&gt;
 *tau.changePage("subPage.html");
 *&lt;/script&gt;
 *</pre>
 *</div>
 *
 *
 *</dd>
 *
 *
 *<dt class="method" id="addidp28072"><code><b><span class="methodName"
 *id="method-back">back</span></b></code></dt>
 *<dd>
 *<div class="brief">
 *<p>Loads the previous page in the history list.</p>
 *</div>
 *<div class="synopsis">
 *<pre class="signature prettyprint">back ( ) </pre>
 *</div>
 *
 *<div class="description">
 *<p>
 *<b>Same as:</b> window.history.back()
 *</p>
 *</div>
 *
 *
 *
 *</div>
 *<div class="example">
 *<span class="example"><p>Code
 *example:</p><p></p></span>
 *<pre name="code" class="examplecode
 *prettyprint">
 *&lt;script&gt;
 *tau.back();
 *&lt;/script&gt;
 *</pre>
 *</div>
 *
 *
 *</dd>
 *
 * @page ns.page.change
 * @seeMore layout.htm Application Page Layout
 */
;
/*global window, define*/
/*
 * Copyright  2010 - 2014 Samsung Electronics Co., Ltd.
 * License : MIT License V2
 */
/**
 * #Handling Page Events and Methods
 *
 * TAU support "Page" as widget. So, when the page is created, it has several
 * events and methods. In this document, we would introduce events and methods in
 * TAU Page Widget.
 *
 * ## Events list
 *
 * The following table lists the events related to pages.
 *
 * <table>
 * <tbody>
 * <tr>
 * <th>Name</th>
 * <th>Description</th>
 * </tr>
 *
 * <tr>
 * <td class="option"><span style="font-family: Courier New,Courier,monospace">pagebeforchange</span></td>
 * <td><p>Triggered before switching current page</p></td>
 * </tr>
 *
 * <tr>
 * <td class="option"><span style="font-family: Courier New,Courier,monospace">pagebeforecreate</span></td>
 * <td><p>Triggered before the widget is created and initialized</p></td>
 * </tr>
 *
 * <tr>
 * <td class="option"><span style="font-family: Courier New,Courier,monospace">pagebeforehide</span></td>
 * <td><p>Triggered before current page is about to be closed</p></td>
 * </tr>
 *
 * <tr>
 * <td class="option"><span style="font-family: Courier New,Courier,monospace">pagebeforeload</span></td>
 * <td><p>Triggered before external page will be loaded</p></td>
 * </tr>
 *
 * <tr>
 * <td class="option"><span style="font-family: Courier New,Courier,monospace">pagebeforeshow</span></td>
 * <td><p>Triggered before page will be displayed</p></td>
 * </tr>
 *
 * <tr>
 * <td class="option"><span style="font-family: Courier New,Courier,monospace">pagechange</span></td>
 * <td><p>Triggered after switching current page</p></td>
 * </tr>
 *
 * <tr>
 * <td class="option"><span style="font-family: Courier New,Courier,monospace">pagechangefailed</span></td>
 * <td><p>Triggered when page switching failed</p></td>
 * </tr>
 *
 * <tr>
 * <td class="option"><span style="font-family: Courier New,Courier,monospace">pagecreate</span></td>
 * <td><p>Triggered after widget creation</p></td>
 * </tr>
 *
 * <tr>
 * <td class="option"><span style="font-family: Courier New,Courier,monospace">pagehide</span></td>
 * <td><p>Triggered after the page is hidden</p></td>
 * </tr>
 *
 * <tr>
 * <td class="option"><span style="font-family: Courier New,Courier,monospace">pageinit</span></td>
 * <td><p>Triggered after widget initialization occurs</p></td>
 * </tr>
 *
 * <tr>
 * <td class="option"><span style="font-family: Courier New,Courier,monospace">pageload</span></td>
 * <td><p>Triggered after an external page is loaded</p></td>
 * </tr>
 *
 * <tr>
 * <td class="option"><span style="font-family: Courier New,Courier,monospace">pagremove</span></td>
 * <td><p>Triggered after the external page is removed from the DOM</p></td>
 * </tr>
 *
 * <tr>
 * <td class="option"><span style="font-family: Courier New,Courier,monospace">pageshow</span></td>
 * <td><p>Triggered after the page is displayed</p></td>
 * </tr>
 *
 * </tbody>
 * </table>
 *
 * ## Binding H/W Back Key event
 *
 * To bind an event callback on the Back key, use the following code:
 *
 * 		@example
 * 		// JavaScript code
 *		window.addEventListener('tizenhwkey', function(ev)
 *			{
 *				if (ev.originalEvent.keyName == "back")
 *					{
 *					// Call window.history.back() to go to previous browser window
 *					// Call tizen.application.getCurrentApplication().exit() to exit application
 *					// Add script to add another behavior
 *					}
 *			});
 *
 * @page ns.page.pageevents
 * @seeMore layout.htm Application Page Layout
 */
;
/*global define */
/**
 * #Tizen Advanced UI Framework
 *
 * Tizen Advanced UI Framework(TAU) is new name of Tizen Web UI framework. It provides tools, such as widgets, events, effects, and animations, for Web application development. You can leverage these tools by just selecting the required screen elements and creating applications.
 *
 * TAU service is based on a template and works on a Web browser, which runs on the WebKit engine. You can code Web applications using the TAU, standard HTML5, and Tizen device APIs. You can also use different widgets with CSS animations and rendering optimized for Tizen Web browsers.
 *
 * For more information about the basic structure of a page in the Web application using the TAU, see [Application Page Structure](page/app_page_layout.htm).
 *
 * ##Framework Services
 *
 * The Web UI framework consists of the following services:
 *
 *  - Page navigation
 *
 *    Navigation JavaScript library is provided to allow smooth navigation between TAU based application [pages](page/layout.htm).
 *  - Web widgets and themes
 *
 *    We support APIs and CSS themes for Tizen web [widgets](widget/widget_reference.htm)
 *  - Element Events
 *
 *    Some special [events](event/event_reference.htm) are available with TAU that optimized for the Web applications.
 *  - Useful utility
 *
 *    Some special [utility](util/util_reference.htm) are available with TAU that supporting easy DOM methods for the Web applications.
 *
 * !!!The framework runs only on browsers supporting the HTML5/CSS standards. The draft version of the W3C specification is not fully supported.!!!
 * @class ns
 * @title Tizen Advanced UI Framework
 */

}(window, window.document));
