text: ﻿/*
  * Metro JS for jQuery
  * http://drewgreenwell.com/ 
  * For details and usage info see: http://drewgreenwell.com/projects/metrojs
  
  Copyright (C) 2012, Drew Greenwell
  
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), 
  to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 
  and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
  
  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
  
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
  (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;
  	    },
  	    appendStyleProperties: function (obj, names, values) {
  	        var stylePrefixes = 'Webkit Moz O ms Khtml '.split(' ');
  	        for (var i = 0; i <= names.length - 1; i++) {
  	            for (var j = 0; j <= stylePrefixes.length - 1; j++)
  	                obj[$.trim(stylePrefixes[j] + names[i])] = values[i];
  	        }
  	        return obj;
  	    },
  	    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 = 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;
  	            $this.actionTimer = 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.stack;
  	            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).bind("mouseover.liveTile", function () {
  	                    tdata.stopTimer(false);
  	                }).bind("mouseout.liveTile", 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("metrojs.tile", { animating: false });
  	                        $back.addClass("ha").data("metrojs.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("metrojs.tile", { animating: false });
  	                }
  	            } else if (tdata.mode == 'flip') {
  	                if (canFlip3d && tdata.useHwAccel) {
  	                    $this.addClass("ha");
  	                    $firstContainer.addClass("ha").data("metrojs.tile", { animating: false });
  	                    $scndContainer.addClass("ha").data("metrojs.tile", { animating: false });
  	                } else {
  	                    var backCss = (tdata.direction == "vertical") ?
  							   { height: '0px', width: width + 'px', marginTop: margin + 'px', opacity: '0'} :
  							   { height: '100%', width: '0px !important', marginLeft: margin + 'px', opacity: '0' };
  	                    var frontCss = (tdata.direction == "vertical") ?
  								{ height: '100%', width: '100%', marginTop: '0px', opacity: '1'} :
  								{ height: '100%', width: '100%', marginLeft: '0px', opacity: '1' };
  	                    $firstContainer.css(frontCss);
  	                    $scndContainer.css(backCss);
  	                    //temp fix                       
  	                    // TODO: debug and remove instances of jQuery.browser for compatibility with jq 1.8+
  	                    if (tdata.repeatCount > -1 && jQuery.browser.msie && parseInt(jQuery.browser.version, 10) < 10) {
  	                        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 = typeof ($firstContainer.data("metrojs.tile")) != "undefined" ? $firstContainer.data("metrojs.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 tProp = (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 = privMethods.appendStyleProperties({}, ['TransitionProperty', 'TransitionDuration'], [tProp, tdata.speed + 'ms']);
  	                    /*var css = {
  	                    WebkitTransitionProperty: tProp, WebkitTransitionDuration: tdata.speed + 'ms',
  	                    MozTransitionProperty: tProp, MozTransitionDuration: tdata.speed + 'ms',
  	                    OTransitionProperty: tProp, OTransitionDuration: tdata.speed + 'ms',
  	                    msTransitionProperty: tProp, msTransitionDuration: tdata.speed + 'ms',
  	                    KhtmlTransitionProperty: tProp, KhtmlTransitionDuration: tdata.speed + 'ms',
  	                    TransitionProperty: tProp, 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("metrojs.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 && parseInt(jQuery.browser.version, 10) < 10) /* 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("metrojs.tile");
  	                    if (typeof (data.animated) != "undefined" && data.animated == true) {
  	                        return;
  	                    }
  	                    data.animated = true;
  	                    if (doAnimations) {
  	                        if (tdata.isReversed) {
  	                            var uCssNames = ['AnimationPlayState', 'AnimationName', 'AnimationDuration'];
  	                            var uCssValues = ['running', aniBName, duration];
  	                            var uCss = privMethods.appendStyleProperties({}, uCssNames, uCssValues);
  	                            // apply styles to front container
  	                            $firstContainer.css(uCss).data("metrojs.tile", data);
  	                            uCss = privMethods.appendStyleProperties(uCss, ['AnimationName'], [aniFName]);
  	                            // apply styles to back container
  	                            $scndContainer.css(uCss).data("metrojs.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("metrojs.tile", data);
  	                                $scndContainer.data("metrojs.tile", data);
  	                            }, spd);
  	                        } else {
  	                            var dCssNames = ['AnimationPlayState', 'AnimationName', 'AnimationDuration'];
  	                            var dCssValues = ['running', aniFName, duration];
  	                            var dCss = privMethods.appendStyleProperties({}, dCssNames, dCssValues);
  	                            // apply styles to front container
  	                            $firstContainer.css(dCss).data("metrojs.tile", data);
  	                            dCss = privMethods.appendStyleProperties(dCss, ['AnimationName'], [aniBName]);
  	                            // apply styles to back container
  	                            $scndContainer.css(dCss).data("metrojs.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("metrojs.tile", data);
  	                                $scndContainer.data("metrojs.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("metrojs.tile").animating : $back.data("metrojs.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 = privMethods.appendStyleProperties({},
                                                                      ['AnimationPlayState', 'AnimationName', 'AnimationDuration'],
                                                                      ['running', aniBName, duration]);
  	                    var bCss = privMethods.appendStyleProperties({},
                                                                      ['AnimationPlayState', 'AnimationName', 'AnimationDuration'],
                                                                      ['running', aniFName, duration]);
  	                    /*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("metrojs.tile").animating = true;
  	                    $back.css(bCss).data("metrojs.tile").animating = true;
  	                    window.setTimeout(function () {
  	                        if (typeof (newSrc) != "undefined") {
  	                            privMethods.handleListItemSwap($front, newSrc, isBgroundImg, stgs);
  	                        }
  	                        $front.data("metrojs.tile").animating = false;
  	                        $back.data("metrojs.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.clearTimeout($this.actionTimer);
  	                        $this.actionTimer = 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);
  	                $this.actionTimer = window.clearTimeout($this.actionTimer);
  	                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 (idx, ele) {	            
  	            var $t = jQuery(ele);
  	            $t.unbind(".liveTile");
  	            $t.slideTimer = null;
  	            var data = $t.data("LiveTile");
  	            if (data != null) {	                
  	                var $li = $t.find(jQuery.fn.liveTile.defaults.tileCssSelector);
  	                var $lifaces = $li.find(jQuery.fn.liveTile.defaults.listTileCssSelector);	                
  	                $li.unbind(".liveTile").removeClass("ha");
  	                $lifaces.unbind(".liveTile").removeClass("ha");
  	                delete data.setTimer;
  	                data.stopTimer(false);
  	                delete data;
  	                $li.slide = null;
  	                $li.flip = null;
  	                $li.flipList = null;
  	                $li.liveTile = null;
  	                delete $li.slide;
  	                delete $li.flip;
  	                delete $li.flipList;
  	                delete $li.liveTile;
  	            }
  	            $t.data("LiveTile", null);
  	            $t.removeData("LiveTile");
  	            $t.removeData("ha");
  	            $t.removeData("metrojs.tile");
  	            $t.slide = null;
  	            $t.flip = null;
  	            $t.flipList = null;
  	            $t.liveTile = null;
  	            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();
  	        });
  	    },
  	    rebind: function (tileData) {
  	        jQuery(this).each(function () {
  	            var $tile = tileData;
  	            $tile.stopTimer(false);
  	            $tile.loopCount = 0;
  	            $tile.hasRun = false;
  	            pubMethods["init"].apply(this, $tile);
  	        });
  	    }
  	};jQuery.fn.metrojs.theme = {};
  jQuery.fn.metrojs.theme.loadDefaultTheme = function (stgs) {
      if (typeof (stgs) == "undefined" || stgs == null) {
          stgs = jQuery.fn.metrojs.theme.defaults;
      } else {
          var stg = jQuery.fn.metrojs.theme.defaults;
          jQuery.extend(stg, stgs);
          stgs = stg;
      }
      //get theme from local storage or set base theme
      var hasLocalStorage = typeof (window.localStorage) != "undefined";
      var hasKeyAndValue = function (key) {
          return (typeof (window.localStorage[key]) != "undefined" && window.localStorage[key] != null);
      };
      if (stgs.applyTheme == true) {
          if (hasLocalStorage && (!hasKeyAndValue("Metro.JS.AccentColor") || !hasKeyAndValue("Metro.JS.BaseAccentColor"))) {
              //base theme
              window.localStorage["Metro.JS.AccentColor"] = stgs.accentColor;
              window.localStorage["Metro.JS.BaseAccentColor"] = stgs.baseTheme;
              jQuery(stgs.accentCssSelector).addClass(stgs.accentColor).data("accent", stgs.accentColor);
              jQuery(stgs.baseThemeCssSelector).addClass(stgs.baseTheme);
              if (typeof (stgs.loaded == "function"))
                  stgs.loaded(stgs.baseTheme, stgs.accentColor);
              //preload light theme image
              if (typeof (stgs.preloadAltBaseTheme) != "undefined" && stgs.preloadAltBaseTheme)
                  jQuery([(stgs.baseTheme == 'dark') ? stgs.metroLightUrl : stgs.metroDarkUrl]).metrojs.preloadImages(function () { });
          } else {
              if (hasLocalStorage) {
                  stgs.accentColor = window.localStorage["Metro.JS.AccentColor"];
                  stgs.baseTheme = window.localStorage["Metro.JS.BaseAccentColor"];
                  jQuery(stgs.accentCssSelector).addClass(stgs.accentColor).data("accent", stgs.accentColor);
                  jQuery(stgs.baseThemeCssSelector).addClass(stgs.baseTheme);
                  if (typeof (stgs.loaded == "function"))
                      stgs.loaded(stgs.baseTheme, stgs.accentColor);
              } else {
                  jQuery(stgs.accentCssSelector).addClass(stgs.accentColor).data("accent", stgs.accentColor);
                  jQuery(stgs.baseThemeCssSelector).addClass(stgs.baseTheme);
                  if (typeof (stgs.loaded == "function"))
                      stgs.loaded(stgs.baseTheme, stgs.accentColor);
                  //preload light theme image
                  if (typeof (stgs.preloadAltBaseTheme) != "undefined" && stgs.preloadAltBaseTheme)
                      jQuery([(stgs.baseTheme == 'dark') ? stgs.metroLightUrl : stgs.metroDarkUrl]).metrojs.preloadImages(function () { });
              }
          }
      }
  };
  jQuery.fn.metrojs.theme.applyTheme = function (tColor, aColor, stgs) {
      if (typeof (stgs) == "undefined" || stgs == null) {
          stgs = jQuery.fn.metrojs.theme.defaults;
      } else {
          var stg = jQuery.fn.metrojs.theme.defaults;
          jQuery.extend(stg, stgs);
          stgs = stg;
      }
  
      if (typeof (tColor) != "undefined" && tColor != null) {
          if (typeof (window.localStorage) != "undefined") {
              window.localStorage["Metro.JS.BaseAccentColor"] = tColor;
          }
          var $theme = jQuery(stgs.baseThemeCssSelector);
          if ($theme.length > 0) {
              if (tColor == "dark")
                  $theme.addClass("dark").removeClass("light");
              else if (tColor == "light")
                  $theme.addClass("light").removeClass("dark");
          }
      }
      if (typeof (aColor) != "undefined" && aColor != null) {
          if (typeof (window.localStorage) != "undefined") {
              window.localStorage["Metro.JS.AccentColor"] = aColor;
          }
          var $accent = jQuery(stgs.accentCssSelector);
          if ($accent.length > 0) {
              var themeset = false;
              $accent.each(function () {
                  jQuery(this).addClass(aColor);
                  var dAccent = jQuery(this).data("accent");
                  if (dAccent != aColor) {
                      var cleanClass = jQuery(this).attr("class").replace(dAccent, "");
                      cleanClass = cleanClass.replace(/(\s)+/, ' ');
                      jQuery(this).attr("class", cleanClass);
                      jQuery(this).data("accent", aColor);
                      themeset = true;
                  }
              });
              if (themeset && typeof (stgs.accentPicked) == "function")
                  stgs.accentPicked(aColor);
          }
      }
  };
  
  jQuery.fn.metrojs.theme.appendAccentColors = function (stgs) {
      if (typeof (stgs) == "undefined" || stgs == null) {
          stgs = jQuery.fn.metrojs.theme.defaults;
      } else {
          var stg = jQuery.fn.metrojs.theme.defaults;
          jQuery.extend(stg, stgs);
          stgs = stg;
      }
      var themeList = "";
      var themes = stgs.accentColors;
      var template = stgs.accentListTemplate;
      for (var i = 0; i < themes.length; i++) {
          themeList += template.replace(/\{0\}/g, themes[i]);
      }
      $(themeList).appendTo(stgs.accentListContainer);
  };
  
  jQuery.fn.metrojs.theme.appendBaseThemes = function (stgs) {
      if (typeof (stgs) == "undefined" || stgs == null) {
          stgs = jQuery.fn.metrojs.theme.defaults;
      } else {
          var stg = jQuery.fn.metrojs.theme.defaults;
          jQuery.extend(stg, stgs);
          stgs = stg;
      }
      var themeList = "";
      var themes = stgs.baseThemes;
      var template = stgs.baseThemeListTemplate;
      for (var i = 0; i < themes.length; i++) {
          themeList += template.replace(/\{0\}/g, themes[i]);
      }
      $(themeList).appendTo(stgs.baseThemeListContainer);
  };
  
  // default options for theme
  jQuery.fn.metrojs.theme.defaults = {
      baseThemeCssSelector: 'body',                           // selector to place dark or light class after load or selection
      accentCssSelector: '.tiles',                            // selector to place accent color class after load or selection
      accentColor: 'blue',                                    // the default accent color. options are blue, brown, green, lime, magenta, mango, pink, purple, red, teal
      baseTheme: 'dark',                                      // the default theme color. options are dark, light
      accentColors: [
           'amber', 'brown', 'cobalt', 'crimson', 'cyan',
           'magenta', 'lime', 'indigo', 'green', 'emerald',
           'mauve', 'olive', 'orange', 'pink', 'red',
           'sienna', 'steel', 'teal', 'violet', 'yellow'
       ],
      baseThemes: [
          'light',
          'dark'
       ],
      accentListTemplate: "<li><a href='javascript:;' title='{0}' class='accent {0}'></a></li>", // template to generate accent options
      accentListContainer: ".theme-options",                    // selector of container to append accents
      baseThemeListTemplate: "<li><a href='javascript:;' title='{0}' class='accent {0}'></a></li>", // template to generate accent options
      baseThemeListContainer: ".base-theme-options"                    // selector of container to append accents
  };jQuery.fn.applicationBar = function (options) {
      /* Setup the public options for the applicationBar  */
      var stgs = typeof (jQuery.fn.metrojs.theme) != "undefined" ? jQuery.fn.metrojs.theme.defaults : {};
      jQuery.extend(stgs, jQuery.fn.applicationBar.defaults, options);
      if (typeof (jQuery.fn.metrojs.theme) != "undefined") {
          var theme = jQuery.fn.metrojs.theme;
          theme.loadDefaultTheme(stgs);
          var themeContainer = stgs.accentListContainer + " a";
          $(themeContainer).live("click", function () {
              var accent = jQuery(this).attr("class").replace("accent", "").replace(" ", "");           
              theme.applyTheme(null, accent, stgs);
              if (typeof (stgs.accentPicked) == "function")
                  stgs.accentPicked(accent);
          });
          var baseContainer = stgs.baseThemeListContainer + " a";
          $(baseContainer).live("click", function () {
              var accent = jQuery(this).attr("class").replace("accent", '').replace(' ', '');
              theme.applyTheme(accent, null, stgs);
              if (typeof (stgs.themePicked) == "function")
                  stgs.themePicked(accent);
          });
      }
  
      //this should really only run once but we can support multiple application bars
      jQuery(this).each(function () {
  
          var $this = jQuery(this);
  
          //unfortunately we have to sniff out mobile browsers because of the inconsistent implementation of position:fixed
          //most desktop methods return false positives on a mobile
          if (navigator.userAgent.match(/(Android|webOS|iPhone|iPod|BlackBerry|PIE|IEMobile)/i)) {
              $this.css({ position: 'absolute', bottom: '0px' });
          }
  
          $this.animateAppBar = function (isExpanded) {
              var hgt = isExpanded ? stgs.collapseHeight : stgs.expandHeight;
              if (isExpanded)
                  $this.removeClass("expanded");
              else
                  if (!$this.hasClass("expanded"))
                      $this.addClass("expanded");
              $this.stop().animate({ height: hgt }, { duration: stgs.duration });
          };
  
          $this.find("a.etc").click(function () {
              $this.animateAppBar($this.hasClass("expanded"));
          });
  
          if (stgs.bindKeyboard == true) {
              jQuery(document.documentElement).keyup(function (event) {
                  // handle cursor keys
                  if (event.keyCode == 38) {
                      // expand
                      if (!$this.hasClass("expanded")) {
                          $this.animateAppBar(false);
                      }
                  } else if (event.keyCode == 40) {
                      // collapse
                      if ($this.hasClass("expanded")) {
                          $this.animateAppBar(true);
                      }
                  }
              });
          }
      });
  };
  
  // default options for applicationBar, the theme defaults are merged with this object when the applicationBar function is called
  jQuery.fn.applicationBar.defaults = {
      applyTheme: true,                                       // should the theme be loaded from local storage and applied to the page
      themePicked: function (tColor) { },                     // called when a new theme is chosen. the chosen theme (dark | light)
      accentPicked: function (aColor) { },                    // called when a new accent is chosen. the chosen theme (blue, mango, purple, etc.)
      loaded: function (tColor, aColor) { },                  // called if applyTheme is true onload when a theme has been loaded from local storage or overridden by options
      duration: 500,                                          // how fast should animation be performed, in milliseconds
      expandHeight: "320px",                                  // height the application bar to expand to when opened
      collapseHeight: "60px",                                 // height the application bar will collapse back to when closed
      bindKeyboard: true,                                     // should up and down keys on keyborad be bound to the application bar
      metroLightUrl: 'images/metroIcons_light.jpg',  // the url for the metro light icons (only needed if preload 'preloadAltBaseTheme' is true)
      metroDarkUrl: 'images/metroIcons.jpg',         // the url for the metro dark icons (only needed if preload 'preloadAltBaseTheme' is true)
      preloadAltBaseTheme: false                             // should the applicationBar icons be pre loaded for the alternate theme to enable fast theme switching    
  };})();