(function ()()

in assets/www/scripts/MetroJs.lt.js [18:1047]


(function () {
jQuery.fn.metrojs = {};


/* Preload Images */
// Usage: jQuery(['img1.jpg','img2.jpg']).metrojs.preloadImages(function(){ ... });
// Callback function gets called after all images are preloaded
jQuery.fn.metrojs.preloadImages = function (callback) {
    var checklist = jQuery(this).toArray();
    var $img = jQuery("<img style='display:none;'>").appendTo("body");
    jQuery(this).each(function () {
        $img.attr({ src: this }).load(function () {
            var src = jQuery(this).attr('src');
            for (var i = 0; i < checklist.length; i++) {
                if (checklist[i] == element) { checklist.splice(i, 1); }
            }
            if (checklist.length == 0) { callback(); }
        });
    });
    $img.remove();
};	jQuery.fn.liveTile = function (method) {
		if (pubMethods[method]) {
			var args = [];
			for (var i = 1; i <= arguments.length; i++) {
				args[i - 1] = arguments[i];
			}
			return pubMethods[method].apply(this, args);
		} else if (typeof method === 'object' || !method) {
			return pubMethods.init.apply(this, arguments);
		} else {
			jQuery.error('Method ' + method + ' does not exist on jQuery.liveTile');
		}
	};
	jQuery.fn.liveTile.State = {
		RUNNING: "running",
		STOPPED: "stopped"
	};
	jQuery.fn.liveTile.defaults = {
		mode: 'slide',                          // 'slide', 'flip', 'flip-list'
		speed: 500,                             // how fast should animations be performed, in milliseconds
		initDelay: -1,                          // how long to wait before the initial animation
		delay: 5000,                            // how long to wait between animations 
		stops: "100%",                          // how much of the back tile should 'slide' reveal before starting a delay
		stack: false,                           // should tiles in slide mode appear stacked (e.g Me tile) 
		direction: 'vertical',                  // which direction should animations be performed(horizontal | vertical)
		tileCssSelector: '>div,>li',            // The selector used by slide, flip, and flip-list mode to choose the front and back containers
		listTileCssSelector: '>div,>p,>img,>a', // The selector used by flip-tile mode to choose the front and back containers.2
		imageCssSelector: '>img,>a>img',        // the selector used to choose a an image to apply a src or background to
		ignoreDataAttributes: false,            // should data attributes be ignored
		pauseOnHover: false,                    // should tile animations be paused on hover in and restarted on hover out
		repeatCount: -1,                        // number of times to repeat the animation        
		animationComplete: function (tileData, $front, $back) {
		},
		preloadImages: false,                   // should the images arrays be preloaded
		fadeSlideSwap: false,                   // fade any image swaps on slides (e.g. mode: 'slide', stops:'50%', frontImages: ['img1.jpg', 'img2.jpg'])
		appendBack: true,                       // appends the .last tile if one doesnt exist (slide and flip only)
		triggerDelay: function (idx) {          // used by flip-list to decide how random the tile flipping should be
			return Math.random() * 3000;
		},
		alwaysTrigger: false,                   // used by flip-list to decide if all tiles are triggered every time	    
		frontImages: null,                      // a list of images to use for the front
		frontIsRandom: true,                    // should images be chosen at random or in order
		frontIsBackgroundImage: false,          // set the src attribute or css background-image property
		frontIsInGrid: false,                   // only chooses one item for each iteration in flip-list
		backImages: null,                       // a list of images to use for the back
		backIsRandom: true,                     // should images be chosen at random or in order
		backIsBackgroundImage: false,           // set the src attribute or css background-image property
		backIsInInGrid: false,                  // only chooses one item for each iteration in flip-list
		flipListOnHover: false,                 // should items in flip-list flip and stop when hovered
		useModernizr: (typeof (window.Modernizr) != "undefined"), // checks to see if modernizer is already in use
		useHardwareAccel: true,                 // should css animations, transitions and transforms be used when available
		$front: null,                           // the jQuery element to use as the front face of the tile; this will bypass tileCssSelector
		$back: null                            // the jQuery element to use as the back face of the tile; this will bypass tileCssSelector
	};

	var privMethods = {
		//a shuffle method to provide more randomness than sort
		//credit: http://javascript.about.com/library/blshuffle.htm
		//*avoiding prototype for sharepoint compatability
		shuffleArray: function (array) {
			var s = [];
			while (array.length) s.push(array.splice(Math.random() * array.length, 1));
			while (s.length) array.push(s.pop());
			return array;
		},
		setTimer: function (func, interval) {
			return setInterval(func, interval);
		},
		stopTimer: function (handle) {
			clearInterval(handle);
			return null;
		},
		setExtraProperties: function ($ele, imageObj) {
			if (typeof (imageObj.alt) != "undefined")
				$ele.attr("alt", imageObj.alt);
			var $parent = $ele.parent();
			if (typeof (imageObj.href) != "undefined" && $parent[0].tagName == "A") {
				$parent.attr("href", imageObj.href);
				if (typeof (imageObj.target) != "undefined")
					$parent.attr("target", imageObj.target);
				if (typeof (imageObj.onclick) != "undefined") {
					$parent.attr("onclick", imageObj.onclick);
					$ele.attr("onclick", "");
				}
			} else {
				if (typeof (imageObj.onclick) != "undefined")
					$ele.attr("onclick", imageObj.onclick);
			}
		},
		// changes the src or background image property of an image in a flip-list
		handleListItemSwap: function ($cont, image, isBgroundImg, stgs) {
			var $img = $cont.find(stgs.imageCssSelector);
			if (!isBgroundImg) {
				$img.attr("src", image.src);
			} else {
				$img.css({ backgroundImage: "url('" + image.src + "')" });
			}
			privMethods.setExtraProperties($img, image);
		},
		handleSlide: function (isSlidingUp, $cont, swapFrontSource, stgs, index) {
			if (!isSlidingUp && swapFrontSource) {
				var image;
				var $img = $cont.find(stgs.imageCssSelector);
				image = stgs.frontImages[index];
				if (stgs.fadeSlideSwap == true) {
					$img.fadeOut(function () {
						$img.attr("src", image.src);
						privMethods.setExtraProperties($img, image);
						$img.fadeIn();
					});
				} else {
					$img.attr("src", image.src);
					privMethods.setExtraProperties($img, image);
				}
			}

		},
		// fired if an image swap is needed. gets the image and applies properties
		handleSwap: function ($cont, isFront, stgs, index) {
			var image = privMethods.getImage(isFront, stgs, index);
			var $img = $cont.find(stgs.imageCssSelector);
			$img.attr("src", image.src);
			privMethods.setExtraProperties($img, image);
		},
		// get an image from the frontImages or backImages array
		getImage: function (isFront, stgs, index) {
			var imgs = (isFront) ? stgs.frontImages : stgs.backImages;
			var image;
			image = imgs[Math.min(index, imgs.length - 1)];
			return image;
		}
	};
	var pubMethods = {
		init: function (options) {
			// Setup the public options for the livetile
			var stgs = {};
			jQuery.extend(stgs, jQuery.fn.liveTile.defaults, options);

			//is there at least one item in the front images list?
			var swapFrontSource = (typeof (stgs.frontImages) == 'object' && (stgs.frontImages instanceof Array) && stgs.frontImages.length > 0);
			//is there at least one item in the back images list?
			var swapBackSource = (typeof (stgs.backImages) == 'object' && (stgs.backImages instanceof Array) && stgs.backImages.length > 0);
			var canTransform = false;
			var canTransition = false;
			var canTransform3d = false;
			var canAnimate = false;
			var canFlip3d = stgs.useHardwareAccel;
			if (stgs.useHardwareAccel == true) {
				if (stgs.useModernizr == false) {
					//determine if the browser supports the neccessary accelerated features
					if (typeof (window.MetroModernizr) != "undefined") {
						canTransform = window.MetroModernizr.canTransform;
						canTransition = window.MetroModernizr.canTransition;
						canTransform3d = window.MetroModernizr.canTransform3d;
						canAnimate = window.MetroModernizr.canAnimate;
					} else {
						window.MetroModernizr = {};
						/***** check for browser capabilities credit: modernizr-1.7 *****/
						var mod = 'metromodernizr';
						var docElement = document.documentElement;
						var docHead = document.head || document.getElementsByTagName('head')[0];
						var modElem = document.createElement(mod);
						var m_style = modElem.style;
						var prefixes = ' -webkit- -moz- -o- -ms- -khtml- '.split(' ');
						var domPrefixes = 'Webkit Moz O ms Khtml'.split(' ');
						var test_props = function (props, callback) {
							for (var i in props) {
								if (m_style[props[i]] !== undefined && (!callback || callback(props[i], modElem))) {
									return true;
								}
							}
						};
						var test_props_all = function (prop, callback) {

							var uc_prop = prop.charAt(0).toUpperCase() + prop.substr(1),
							props = (prop + ' ' + domPrefixes.join(uc_prop + ' ') + uc_prop).split(' ');

							return !!test_props(props, callback);
						};
						var test_3d = function () {
							var ret = !!test_props(['perspectiveProperty', 'WebkitPerspective', 'MozPerspective', 'OPerspective', 'msPerspective']);
							if (ret && 'webkitPerspective' in docElement.style) {
								// Webkit allows this media query to succeed only if the feature is enabled.    
								// '@media (transform-3d),(-o-transform-3d),(-moz-transform-3d),(-ms-transform-3d),(-webkit-transform-3d),(modernizr){ ... }'
								ret = testMediaQuery('@media (' + prefixes.join('transform-3d),(') + 'metromodernizr)');
							}
							return ret;
						};
						var testMediaQuery = function (mq) {
							var st = document.createElement('style'),
						div = document.createElement('div'),
						ret;
							st.textContent = mq + '{#metromodernizr{height:3px}}';
							docHead.appendChild(st);
							div.id = 'metromodernizr';
							docElement.appendChild(div);
							ret = div.offsetHeight === 3;
							st.parentNode.removeChild(st);
							div.parentNode.removeChild(div);
							return !!ret;
						};
						canTransform = !!test_props(['transformProperty', 'WebkitTransform', 'MozTransform', 'OTransform', 'msTransform']);
						canTransition = test_props_all('transitionProperty');
						canTransform3d = test_3d();
						canAnimate = test_props_all('animationName');
						window.MetroModernizr.canTransform = canTransform;
						window.MetroModernizr.canTransition = canTransition;
						window.MetroModernizr.canTransform3d = canTransform3d;
						window.MetroModernizr.canAnimate = canAnimate;
						docElement = null;
						docHead = null;
						modElem = null;
						m_style = null;
					}
				} else {
					canTransform = jQuery("html").hasClass("csstransforms");
					canTransition = jQuery("html").hasClass("csstransitions");
					canTransform3d = jQuery("html").hasClass("csstransforms3d");
					canAnimate = jQuery("html").hasClass("cssanimations");
				}
			}
			canFlip3d = canFlip3d && canAnimate && canTransform && canTransform3d;
			/****** end capabilities check ******/
			if (stgs.preloadImages) {
				if (swapFrontSource)
					jQuery(stgs.frontImages).metrojs.preloadImages(function () { });
				if (swapBackSource)
					jQuery(stgs.backImages).metrojs.preloadImages(function () { });
			}
			return jQuery(this).each(function (tileIndex) {
				var $this = jQuery(this);
				$this.slideTimer = null;
				var tdata = {}; //an object to store settings for later access
				tdata.state = $this.slideTimer == null ? jQuery.fn.liveTile.State.STOPPED : jQuery.fn.liveTile.State.RUNNING;
				tdata.speed = (!stgs.ignoreDataAttributes && typeof ($this.data("speed")) != "undefined") ? $this.data("speed") : stgs.speed;
				tdata.delay = (!stgs.ignoreDataAttributes && typeof ($this.data("delay")) != "undefined") ? $this.data("delay") : stgs.delay;
				if (tdata.delay < -1)
					tdata.delay = stgs.triggerDelay(tileIndex);
				else if (tdata.delay < 0)
					tdata.delay = 3500 + (Math.random() * 4501);
				tdata.stops = (!stgs.ignoreDataAttributes && typeof ($this.data("stops")) != "undefined") ? $this.data("stops") : stgs.stops;
				tdata.stack = (!stgs.ignoreDataAttributes && typeof ($this.data("stack")) != "undefined") ? $this.data("stack") : stgs.mode;
				tdata.mode = (!stgs.ignoreDataAttributes && typeof ($this.data("mode")) != "undefined") ? $this.data("mode") : stgs.mode;
				tdata.direction = (!stgs.ignoreDataAttributes && typeof ($this.data("direction")) != "undefined") ? $this.data("direction") : stgs.direction;
				tdata.useHwAccel = (!stgs.ignoreDataAttributes && typeof ($this.data("ha")) != "undefined") ? $this.data("ha") : stgs.useHardwareAccel;
				tdata.initDelay = (!stgs.ignoreDataAttributes && typeof ($this.data("initdelay")) != "undefined") ? $this.data("initdelay") : (stgs.initDelay < 0) ? tdata.delay : stgs.initDelay;
				tdata.repeatCount = (!stgs.ignoreDataAttributes && typeof ($this.data("repeat")) != "undefined") ? $this.data("repeat") : stgs.repeatCount;                
				tdata.hasRun = false; // init delay flag
				tdata.isReversed = false;
				tdata.loopCount = 0;
				tdata.slideIndex = 0;
				//convert stops if needed
				tdata.stops = (typeof (stgs.stops) == 'object' && (stgs.stops instanceof Array)) ? stgs.stops : ('' + tdata.stops).split(',');
				//add the mode to the tile if it's not already there.
				$this.addClass(tdata.mode);
				var $tileContainer = $this.find(stgs.tileCssSelector);
				var $firstContainer = null;
				if (stgs.$front != null && stgs.$front.length > 0) {
					$firstContainer = (tdata.mode == "flip-list") ? null : (tdata.mode == 'slide') ?
										stgs.$front.addClass('slide-front') :
										stgs.$front.addClass('flip-front');
				} else {
					$firstContainer = (tdata.mode == "flip-list") ? null : (tdata.mode == 'slide') ?
										$tileContainer.first().addClass('slide-front') :
										$tileContainer.first().addClass('flip-front');
				}
				var lClass = (tdata.mode == 'slide') ? 'slide-back' : 'flip-back';
				var $scndContainer = null;
				if (stgs.$back != null && stgs.$back.length > 0) {
					$scndContainer = (tdata.mode == "flip-list") ? null : stgs.$back.addClass(lClass);
				} else {
					$scndContainer = (tdata.mode == "flip-list") ? null : ($tileContainer.length > 1) ?
								$tileContainer.last().addClass(lClass) :
								(stgs.appendBack == true) ?
								jQuery('<div class="' + lClass + '"></div>').appendTo($this) :
								jQuery('<div></div>');
				}
				var height = $this.height();
				var width = $this.width();
				var margin = (tdata.direction == "vertical") ? height / 2 : width / 2;
				

				var staticCount = 0;
				var staticIndexBack = 0;
				var staticIndexFront = 0;
				var doAnimations = false;
				var flistData = []; // an array to cache flip list selectors
				var frontRandomBag = [];
				var prevFrontIndex = -1;
				var backRandomBag = [];
				var prevBackIndex = -1;
				/* Mouse over and out functions*/

				if (stgs.pauseOnHover) {
					$this.find(stgs.tileCssSelector).hover(
					function () {
						tdata.stopTimer(false);
					},
					function () {
						tdata.setTimer();
					});
				}
				// prep tiles
				if (tdata.mode == 'flip-list') {
					$this.find(stgs.tileCssSelector).each(function () {
						var $li = jQuery(this);
						var $front = stgs.$front != null ? stgs.$front : $li.find(stgs.listTileCssSelector).first().addClass("flip-front");
						if ($li.find(stgs.listTileCssSelector).length == 1 && stgs.appendBack == true) {
							$li.append("<div></div>");
						}
						var $back = stgs.$back != null ? stgs.$back : $li.find(stgs.listTileCssSelector).last().addClass("flip-back").css({ marginTop: "0px" });
						if (canFlip3d && tdata.useHwAccel) {
							$li.addClass("ha");
							$front.addClass("ha").data("tile", { animating: false });
							$back.addClass("ha").data("tile", { animating: false });
							if (stgs.flipListOnHover == true) {
								$front.bind("mouseout.liveTile", null, function () {
									$this.flipListItem(false, $li, $back, $front);
								});
								$back.bind("mouseout.liveTile", null, function () {
									$this.flipListItem(true, $li, $front, $back);
								});
							}
						} else {
							if (stgs.flipListOnHover == true) {
								$front.bind("mouseout.liveTile", function () {
									$this.flipListItem(true, $li, $front, $back);
								});
								$back.bind("mouseout.liveTile", function () {
									$this.flipListItem(false, $li, $back, $front);
								});
							}
						}
					});
				} else if (tdata.mode == 'slide') {
					if (tdata.stack == true) {
						if (tdata.direction == "vertical") {
							$scndContainer.css({ top: -height + 'px' });
						} else {
							$scndContainer.css({ left: -width + 'px' });
						}
					}
					if (canTransition && tdata.useHwAccel) {
						$this.addClass("ha");
						$firstContainer.addClass("ha").data("tile", { animating: false });
					}
				} else if (tdata.mode == 'flip') {
					if (canFlip3d && tdata.useHwAccel) {
						$this.addClass("ha");
						$firstContainer.addClass("ha").data("tile", { animating: false });
						$scndContainer.addClass("ha").data("tile", { animating: false });
					} else {
						var fCss = (tdata.direction == "vertical") ?
							   { height: '0px', width: width + 'px', marginTop: margin + 'px', opacity: '0'} :
							   { height: '100%', width: '0px !important', marginLeft: margin + 'px', opacity: '0' };
						var fCss2 = (tdata.direction == "vertical") ?
								{ height: '100%', width: '100%', marginTop: '0px', opacity: '1'} :
								{ height: '100%', width: '100%', marginLeft: '0px', opacity: '1' };
						$scndContainer.css(fCss);
						$firstContainer.css(fCss2);
						//temp fix                       
						// TODO: debug and remove instances of jQuery.browser for compatibility with jq 1.8+
						if (tdata.repeatCount > -1 && jQuery.browser.msie) {
							tdata.repeatCount += 1;
						}
						//                        if (tdata.direction == "horizontal")
						//                            $scndContainer.css({ marginLeft: $scndContainer.width() / 2 + 'px', width: '0px' });
						//                        else
						//                            $scndContainer.css({ marginTop: $scndContainer.height() / 2 + 'px', height: '0px' });
					}
				}


				//slide animation
				$this.slide = function (callback) {
					if (typeof (callback) == "undefined" || callback == null)
						callback = null;
					if (tdata.repeatCount > -1) {                        
						if (tdata.loopCount > tdata.repeatCount) {                            
							tdata.stopTimer(false);
							tdata.loopCount = 0;
							tdata.hasRun = false;
							$this.data("LiveTile", tdata);
							return;
						}
					}
					if (!doAnimations)
						return;
					var clojIsReversed = tdata.isReversed;
					var fData = $firstContainer.data("tile");
					var stop = jQuery.trim(tdata.stops[tdata.slideIndex]);
					var pxIdx = stop.indexOf('px');
					var offset = 0;
					var amount = 0
					var metric = (tdata.direction == "vertical") ? height : width;
					var prop = (tdata.direction == "vertical") ? "top" : "left";
					if (pxIdx > 0) {
						amount = parseInt(stop.substring(0, pxIdx));
						offset = (amount - metric) + 'px';
					} else {
						//is a percentage
						amount = parseInt(stop.replace('%', ''));
						offset = (amount - 100) + '%';
					}
					if (canTransition && tdata.useHwAccel) {
						if (typeof (fData.animated) != "undefined" && fData.animated == true)
							return;
						fData.animated = true;
						var css = {
							WebkitTransitionProperty: prop, WebkitTransitionDuration: tdata.speed + 'ms',
							MozTransitionProperty: prop, MozTransitionDuration: tdata.speed + 'ms',
							OTransitionProperty: prop, OTransitionDuration: tdata.speed + 'ms',
							msTransitionProperty: prop, msTransitionDuration: tdata.speed + 'ms',
							KhtmlTransitionProperty: prop, KhtmlTransitionDuration: tdata.speed + 'ms',
							TransitionProperty: prop, TransitionDuration: tdata.speed + 'ms'
						};
						if (tdata.direction == "vertical") {
							css.top = (clojIsReversed && tdata.stops.length == 1) ? "0px" : stop;
						} else {
							css.left = (clojIsReversed && tdata.stops.length == 1) ? "0px" : stop;
						}
						$firstContainer.css(css);
						if (tdata.stack == true) {
							if (tdata.direction == "vertical") {
								css.top = (clojIsReversed && tdata.stops.length == 1) ? -metric + 'px' : offset;
							} else {
								css.left = (clojIsReversed && tdata.stops.length == 1) ? -metric + 'px' : offset;
							}
							$scndContainer.css(css);
						}
						window.setTimeout(function () {
							var index = staticCount;
							if (swapFrontSource && stgs.frontIsRandom) {
								//make sure the random bag is ready
								if (frontRandomBag.length == 0) {
									for (var i = 0; i < stgs.frontImages.length; i++) {
										//make sure there's not an immediate repeat
										if (i != prevBackIndex || stgs.frontImages.length == 1)
											frontRandomBag[i] = i;
									}
									frontRandomBag = privMethods.shuffleArray(frontRandomBag);
								}
								index = frontRandomBag.pop();
								prevFrontIndex = index;
							}
							privMethods.handleSlide(clojIsReversed, $firstContainer, swapFrontSource, stgs, index);
							fData.animated = false;
							$firstContainer.data("tile", fData);
							if (!clojIsReversed && swapFrontSource) {
								staticCount += 1;
								if (staticCount >= stgs.frontImages.length)
									staticCount = 0;
							}
							stgs.animationComplete(tdata, $firstContainer, $scndContainer);
							if (callback != null)
								callback();
						}, tdata.speed);
					} else {
						if ($firstContainer.is(':animated')) {
							return;
						}
						var uCss = (tdata.direction == "vertical") ?
									{ top: (clojIsReversed && tdata.stops.length == 1) ? "0px" : stop} :
									{ left: (clojIsReversed && tdata.stops.length == 1) ? "0px" : stop };
						var dCss = (tdata.direction == "vertical") ?
									{ top: (clojIsReversed && tdata.stops.length == 1) ? -metric + 'px' : offset} :
									{ left: (clojIsReversed && tdata.stops.length == 1) ? -metric + 'px' : offset };

						$firstContainer.animate(uCss, tdata.speed, function () {
							var index = staticCount;
							if (swapFrontSource && stgs.frontIsRandom) {
								//make sure the random bag is ready
								if (frontRandomBag.length == 0) {
									for (var i = 0; i < stgs.frontImages.length; i++) {
										//make sure there's not an immediate repeat
										if (i != prevBackIndex || stgs.frontImages.length == 1)
											frontRandomBag[i] = i;
									}
									frontRandomBag = privMethods.shuffleArray(frontRandomBag);
								}
								index = frontRandomBag.pop();
								prevFrontIndex = index;
							}
							privMethods.handleSlide(clojIsReversed, $firstContainer, swapFrontSource, stgs, index);
							if (!clojIsReversed && swapFrontSource) {
								staticCount += 1;
								if (staticCount >= stgs.frontImages.length)
									staticCount = 0;
							}
							stgs.animationComplete(tdata, $firstContainer, $scndContainer);
							if (callback != null)
								callback();
						});
						if (tdata.stack == true) {
							$scndContainer.animate(dCss, tdata.speed, function () { });
						}
					}
					//increment slide count
					tdata.slideIndex += 1;
					if (tdata.slideIndex >= tdata.stops.length) {
						tdata.slideIndex = 0;
						tdata.isReversed = !tdata.isReversed;
						tdata.loopCount += 1;
					}
				};


				//flip mode
				$this.flip = function (callback) {
					if (typeof (callback) == "undefined" || callback == null)
						callback = null;
					if (tdata.repeatCount > -1) {
						if (tdata.loopCount > tdata.repeatCount) {
							tdata.stopTimer(false);
							tdata.loopCount = 0;
							// TODO: debug and remove instances of jQuery.browser for compatibility with jq 1.8+
							if (jQuery.browser.msie) /* straighten out issue with loopcount in IE */
								tdata.loopCount += 1;
							tdata.hasRun = false;
							$this.data("LiveTile", tdata);
							return;
						} else {
							tdata.loopCount += 1;
						}
					}
					if (canFlip3d && tdata.useHwAccel) {
						var spd = (tdata.speed * 2); // accelerated flip speeds are calculated on 1/2 rotation rather than 1/4 rotation like jQuery animate
						var duration = spd + 'ms';
						var aniFName = (tdata.direction == "vertical") ? 'flipfront180' : 'flipfrontY180';
						var aniBName = (tdata.direction == "vertical") ? 'flipback180' : 'flipbackY180';
						var data = $firstContainer.data("tile");
						if (typeof (data.animated) != "undefined" && data.animated == true) {
							return;
						}
						data.animated = true;
						if (doAnimations) {
							if (tdata.isReversed) {
								var uCss = {
									WebkitAnimationPlayState: 'running', WebkitAnimationName: aniBName, WebkitAnimationDuration: duration,
									MozAnimationPlayState: 'running', MozAnimationName: aniBName, MozAnimationDuration: duration,
									OAnimationPlayState: 'running', OAnimationName: aniBName, OAnimationDuration: duration,
									msAnimationPlayState: 'running', msAnimationName: aniBName, msAnimationDuration: duration,
									AnimationPlayState: 'running', AnimationName: aniBName, AnimationDuration: duration
								};
								$firstContainer.css(uCss).data("tile", data);
								uCss.WebkitAnimationName = aniFName;
								uCss.MozAnimationName = aniFName;
								uCss.msAnimationName = aniFName;
								uCss.OAnimationName = aniFName;
								uCss.AnimationName = aniFName;
								$scndContainer.css(uCss).data("tile", data);
								window.setTimeout(function () {
									if (swapBackSource) { // change the source image when the animation is finished
										var isRandom = stgs.backIsRandom;
										var index = staticIndexBack;
										if (isRandom) {
											//make sure the random bag is ready
											if (backRandomBag.length == 0) {
												for (var i = 0; i < stgs.backImages.length; i++) {
													//make sure there's not an immediate repeat
													if (i != prevBackIndex || stgs.backImages.length == 1)
														backRandomBag[i] = i;
												}
												backRandomBag = privMethods.shuffleArray(backRandomBag);
											}
											index = backRandomBag.pop();
											prevBackIndex = index;
										}
										privMethods.handleSwap($scndContainer, false, stgs, index);
										staticIndexBack += 1;
										if (staticIndexBack >= stgs.backImages.length) {
											staticIndexBack = 0;
										}
									}
									stgs.animationComplete(tdata, $firstContainer, $scndContainer);
									if (callback != null)
										callback();
									data.animated = false;
									$firstContainer.data("tile", data);
									$scndContainer.data("tile", data);
								}, spd);
							} else {
								var dCss = { WebkitAnimationPlayState: 'running', WebkitAnimationName: aniFName, WebkitAnimationDuration: duration,
									MozAnimationPlayState: 'running', MozAnimationName: aniFName, MozAnimationDuration: duration,
									OAnimationPlayState: 'running', OAnimationName: aniFName, OAnimationDuration: duration,
									msAnimationPlayState: 'running', msAnimationName: aniFName, msAnimationDuration: duration,
									AnimationPlayState: 'running', AnimationName: aniFName, AnimationDuration: duration
								};
								$firstContainer.css(dCss).data("tile", data);
								dCss.WebkitAnimationName = aniBName;
								dCss.MozAnimationName = aniBName;
								dCss.msAnimationName = aniBName;
								dCss.OAnimationName = aniBName;
								dCss.AnimationName = aniBName;
								$scndContainer.css(dCss).data("tile", data);
								window.setTimeout(function () {
									if (swapFrontSource) {
										// change the source image when the animation is finished
										var isRandom = stgs.frontIsRandom;
										var index = staticIndexFront;
										if (isRandom) {
											//make sure the random bag is ready
											if (frontRandomBag.length == 0) {
												for (var i = 0; i < stgs.frontImages.length; i++) {
													//make sure there's not an immediate repeat
													if (i != prevBackIndex || stgs.frontImages.length == 1)
														frontRandomBag[i] = i;
												}
												frontRandomBag = privMethods.shuffleArray(frontRandomBag);
											}
											index = frontRandomBag.pop();
											prevFrontIndex = index;
										}
										privMethods.handleSwap($firstContainer, true, stgs, index);
										staticIndexFront += 1;
										if (staticIndexFront >= stgs.frontImages.length) {
											staticIndexFront = 0;
										}
									}
									stgs.animationComplete(tdata, $scndContainer, $firstContainer);
									if (callback != null) {
										callback();
									}
									data.animated = false;
									$firstContainer.data("tile", data);
									$scndContainer.data("tile", data);
								}, spd);
							}
						}
						//an interval isnt needed
						tdata.isReversed = !tdata.isReversed;
					} else {

						//crossbrowser single tile flip illusion (works best with images)
						if (tdata.isReversed) {
							var upCss = (tdata.direction == "vertical") ?
							   { height: '0px', width: '100%', marginTop: margin + 'px', opacity: '0'} :
							   { height: '100%', width: '0px', marginLeft: margin + 'px', opacity: '0' };
							var upCss2 = (tdata.direction == "vertical") ?
								{ height: '100%', width: '100%', marginTop: '0px', opacity: '1'} :
								{ height: '100%', width: '100%', marginLeft: '0px', opacity: '1' };

							$firstContainer.stop().animate(upCss, { duration: tdata.speed });
							window.setTimeout(function () {
								$scndContainer.stop().animate(upCss2, { duration: tdata.speed });
								if (swapFrontSource) {
									var isRandom = stgs.frontIsRandom;
									var index = staticIndexFront;
									if (isRandom) {
										//make sure the random bag is ready
										if (frontRandomBag.length == 0) {
											for (var i = 0; i < stgs.frontImages.length; i++) {
												//make sure there's not an immediate repeat
												if (i != prevFrontIndex || stgs.frontImages.length == 1)
													frontRandomBag[i] = i;
											}
											frontRandomBag = privMethods.shuffleArray(frontRandomBag);
										}
										index = frontRandomBag.pop();
										prevFrontIndex = index;
									}
									privMethods.handleSwap($firstContainer, true, stgs, index);
									staticIndexFront += 1;
									if (staticIndexFront >= stgs.frontImages.length) {
										staticIndexFront = 0;
									}
								}
								tdata.isReversed = !tdata.isReversed;
								stgs.animationComplete(tdata, $scndContainer, $firstContainer);
								if (callback != null)
									callback();
							}, tdata.speed);
						} else {
							var dwnCss = (tdata.direction == "vertical") ?
							   { height: '0px', width: '100%', marginTop: margin + 'px', opacity: '0'} :
							   { height: '100%', width: '0px', marginLeft: margin + 'px', opacity: '0' };
							var dwnCss2 = (tdata.direction == "vertical") ?
								{ height: '100%', width: '100%', marginTop: '0px', opacity: '1'} :
								{ height: '100%', width: '100%', marginLeft: '0px', opacity: '1' };
							$scndContainer.stop().animate(dwnCss, { duration: tdata.speed });
							window.setTimeout(function () {
								$firstContainer.stop().animate(dwnCss2, { duration: tdata.speed });
								if (swapBackSource) {
									var isRandom = stgs.backIsRandom;
									var index = staticIndexBack;
									if (isRandom) {
										//make sure the random bag is ready
										if (backRandomBag.length == 0) {
											for (var i = 0; i < stgs.backImages.length; i++) {
												//make sure there's not an immediate repeat
												if (i != prevBackIndex || stgs.backImages.length == 1)
													backRandomBag[i] = i;
											}
											backRandomBag = privMethods.shuffleArray(backRandomBag);
										}
										index = backRandomBag.pop();
										prevBackIndex = index;
									}
									privMethods.handleSwap($scndContainer, false, stgs, index);
									staticIndexBack += 1;
									if (staticIndexBack >= stgs.backImages.length) {
										staticIndexBack = 0;
									}
								}
								tdata.isReversed = !tdata.isReversed;
								stgs.animationComplete(tdata, $firstContainer, $scndContainer);
								if (callback != null)
									callback();
							}, tdata.speed);
						}
					}
				};
				// flip arbitrary number of items and swap sources accordingly
				$this.flipList = function (callback) {
					if (typeof (callback) == "undefined" || callback == null)
						callback = null;
					if (tdata.repeatCount > -1) {
						if (tdata.loopCount > tdata.repeatCount) {
							tdata.stopTimer(false);
							tdata.loopCount = 0;
							tdata.hasRun = false;
							$this.data("LiveTile", tdata);
							return;
						} else {
							tdata.loopCount += 1;
						}
					}
					var fBag = [];  // two bags to make sure we don't duplicate images
					var bBag = [];
					var $tiles = $this.find(stgs.tileCssSelector);
					//in case we want to pick one image per loop
					var fStaticRndm = 0;
					if (swapFrontSource) {
						if (frontRandomBag.length == 0) {
							for (var i = 0; i < stgs.frontImages.length; i++) {
								if (i != prevFrontIndex || stgs.frontImages.length == 1)
									frontRandomBag[i] = i;
							}
							frontRandomBag = privMethods.shuffleArray(frontRandomBag);
						}
						fStaticRndm = frontRandomBag.pop();
						prevFrontIndex = fStaticRndm;
					}
					var bStaticRndm = 0;
					if (swapBackSource) {
						if (backRandomBag.length == 0) {
							for (var i = 0; i < stgs.backImages.length; i++) {
								if (i != prevBackIndex || stgs.backImages.length == 1)
									backRandomBag[i] = i;
							}
							backRandomBag = privMethods.shuffleArray(backRandomBag);
						}
						bStaticRndm = backRandomBag.pop();
						prevBackIndex = bStaticRndm;
					}
					$tiles.each(function (idx) {
						var $t = jQuery(this);
						if (flistData.length < idx + 1) {
							// cache the selector
							var data = {};
							data.$front = $t.find(stgs.listTileCssSelector).first();
							data.$back = $t.find(stgs.listTileCssSelector).last();
							data.isReversed = false;
							flistData[idx] = data;
						}
						var $front = flistData[idx].$front;
						var $back = flistData[idx].$back;

						var tDelay = stgs.triggerDelay(idx);
						var triggerSpeed = (tDelay > 0) ? (tdata.speed + tDelay) : tdata.speed;
						var trigger = (!stgs.alwaysTrigger) ? ((Math.random() * 351) > 150 ? true : false) : true;
						var newImage;
						if (flistData[idx].isReversed) {
							if (trigger && tDelay >= 0) {
								window.setTimeout(function () {
									flistData[idx].isReversed = false;
									if (!swapFrontSource) {
										$this.flipListItem(true, $t, $front, $back);
									} else {
										var isRandom = stgs.frontIsRandom;
										var isInGrid = stgs.frontIsInGrid;
										var isBground = stgs.frontIsBackgroundImage;
										var frontImages = stgs.frontImages;
										if (isRandom && !isInGrid) {
											//make sure the random bag is ready
											if (fBag.length == 0) {
												for (var i = 0; i < stgs.frontImages.length; i++) {
													fBag[i] = i;
												}
												fBag = privMethods.shuffleArray(fBag);
											}
											newImage = frontImages[fBag.pop()];
										} else {
											if (!isInGrid) {
												newImage = frontImages[Math.min(idx, frontImages.length)];
											} else {
												newImage = frontImages[Math.min(fStaticRndm, frontImages.length)];
											}
										}
										$this.flipListItem(true, $t, $front, $back, newImage, isBground);
									}
								}, triggerSpeed);
							}
						} else {
							if (trigger && tDelay >= 0) {
								window.setTimeout(function () {
									flistData[idx].isReversed = true;
									if (!swapBackSource) {
										$this.flipListItem(false, $t, $back, $front);
									} else {
										var isRandom = stgs.backIsRandom;
										var isInGrid = stgs.backIsInGrid;
										var isBground = stgs.backIsBackgroundImage;
										var backImages = stgs.backImages;
										if (isRandom && !isInGrid) {
											//make sure the random bag is ready
											if (bBag.length == 0) {
												for (var i = 0; i < stgs.backImages.length; i++) {
													bBag[i] = i;
												}
												bBag = privMethods.shuffleArray(bBag);
											}
											newImage = backImages[bBag.pop()];
										} else {
											if (!isInGrid) {
												newImage = backImages[Math.min(idx, backImages.length)];
											} else {
												newImage = backImages[Math.min(bStaticRndm, backImages.length)];
											}
										}
										$this.flipListItem(false, $t, $back, $front, newImage, isBground);
									}
								}, triggerSpeed);
							}
						}
					});
					window.setTimeout(function () {
						tdata.isReversed = !tdata.isReversed;
					}, tdata.speed);

				};

				//does the actual animation of a flip list item 
				$this.flipListItem = function (isFront, $itm, $front, $back, newSrc, isBgroundImg) {

					var dir = (!stgs.ignoreDataAttributes && typeof ($itm.data("direction")) != "undefined") ? $itm.data("direction") : tdata.direction;
					if (canFlip3d && tdata.useHwAccel) {
						// avoid any z-index flickering from reversing an animation too early                
						isBgroundImg = isFront ? stgs.frontIsBackgroundImage : stgs.backIsBackgroundImage;
						var animating = isFront ? $front.data("tile").animating : $back.data("tile").animating;
						if (animating == true) {
							return;
						}
						var spd = (tdata.speed * 2);
						var duration = spd + 'ms';
						var aniFName = (dir == "vertical") ? 'flipfront180' : 'flipfrontY180';
						var aniBName = (dir == "vertical") ? 'flipback180' : 'flipbackY180';
						var fCss = {
							WebkitAnimationPlayState: 'running', WebkitAnimationName: aniBName, WebkitAnimationDuration: duration,
							MozAnimationPlayState: 'running', MozAnimationName: aniBName, MozAnimationDuration: duration,
							msAnimationPlayState: 'running', msAnimationName: aniBName, msAnimationDuration: duration,
							OAnimationPlayState: 'running', OAnimationName: aniBName, OAnimationDuration: duration,
							AnimationPlayState: 'running', AnimationName: aniBName, AnimationDuration: duration
						};
						var bCss = {
							WebkitAnimationPlayState: 'running', WebkitAnimationName: aniFName, WebkitAnimationDuration: duration,
							MozAnimationPlayState: 'running', MozAnimationName: aniFName, MozAnimationDuration: duration,
							msAnimationPlayState: 'running', msAnimationName: aniFName, msAnimationDuration: duration,
							OAnimationPlayState: 'running', OAnimationName: aniFName, OAnimationDuration: duration,
							AnimationPlayState: 'running', AnimationName: aniFName, AnimationDuration: duration
						};
						$front.css(fCss).data("tile").animating = true;
						$back.css(bCss).data("tile").animating = true;
						window.setTimeout(function () {
							if (typeof (newSrc) != "undefined") {
								privMethods.handleListItemSwap($front, newSrc, isBgroundImg, stgs);
							}
							$front.data("tile").animating = false;
							$back.data("tile").animating = false;
						}, 0); // once the animation is half through it can be reversed

					} else {
						var height = $itm.height();
						var width = $itm.width();
						var margin = (dir == "vertical") ? height / 2 : width / 2;
						var uCss = (dir == "vertical") ?
							{ height: '0px', width: '100%', marginTop: margin + 'px', opacity: 0} :
							{ height: '100%', width: '0px', marginLeft: margin + 'px', opacity: 0 };
						var dCss = (dir == "vertical") ?
							{ height: '100%', width: '100%', marginTop: '0px', opacity: 1} :
							{ height: '100%', width: '100%', marginLeft: '0px', opacity: 1 };
						$front.stop().animate(uCss, { duration: tdata.speed });
						window.setTimeout(function () {
							$back.stop().animate(dCss, { duration: tdata.speed });
							if (typeof (newSrc) != "undefined") {
								privMethods.handleListItemSwap($front, newSrc, isBgroundImg, stgs);
							}
						}, tdata.speed);
					}
				};

				/* Delay the tile action*/
				tdata.doAction = function () {
					var action = null;
					tdata.stopTimer(false);
					switch (tdata.mode) {
						case 'slide':
							action = $this.slide;
							break;
						case 'flip':
							action = $this.flip;
							break;
						case 'flip-list':
							action = $this.flipList;
							break;
					}
					var callBack = function () {
						tdata.setTimer();
					};
					if (action != null) {
						doAnimations = true;
						action(callBack);
					}
				};
				tdata.setTimer = function () {
					var action = null;
					switch (tdata.mode) {
						case 'slide':
							action = $this.slide;
							break;
						case 'flip':
							action = $this.flip;
							break;
						case 'flip-list':
							action = $this.flipList;
							break;
					}

					if (action != null) {
						if (tdata.hasRun == false) {
							window.setTimeout(function () {
								doAnimations = true;
								action();
								tdata.setTimer();
							}, tdata.initDelay);
						} else {
							if ($this.slideTimer != null)
								$this.slideTimer = privMethods.stopTimer($this.slideTimer);
							$this.slideTimer = privMethods.setTimer(function () { doAnimations = true; action(); }, tdata.speed + tdata.delay);
						}
					}
					tdata.hasRun = true;
				};

				tdata.stopTimer = function (restart) {
					$this.slideTimer = privMethods.stopTimer($this.slideTimer);
					doAnimations = false;

					if (typeof (restart) != "undefined" && restart == true) {
						tdata.setTimer();
					}
				};
				$this.data("LiveTile", tdata);
				tdata.setTimer();
			});
		},
		animate: function () {
			jQuery(this).each(function () {
				var tData = jQuery(this).data("LiveTile");
				tData.doAction();
			});
		},
		destroy: function () {
			jQuery(this).each(function () {
				var $t = jQuery(this);
				$t.unbind(".liveTile");
				var $tile = jQuery(this).data("LiveTile");
				if ($tile != null) {
					$tile.stopTimer(false);
					$t.removeData("LiveTile");
					$t.removeData("ha");
					$t.removeData("tile");
					delete $tile;
					delete $t.slide;
					delete $t.flip;
					delete $t.flipList;
					delete $t.liveTile;
				}

			});
		},
		stop: function (restart) {
			jQuery(this).each(function () {
				var $tile = jQuery(this).data("LiveTile");
				$tile.stopTimer(restart);
				$tile.loopCount = 0;
				$tile.hasRun = false;
			});
		},
		pause: function () {
			jQuery(this).each(function () {
				jQuery(this).data("LiveTile").stopTimer();
			});
		},
		play: function () {
			jQuery(this).each(function () {
				jQuery(this).data("LiveTile").setTimer();
			});
		}
	};})();