Вход Регистрация
Файл: templates/backend/default/assets/plugins/jquery-metrojs/MetroJs.js
Строк: 4146
<?php
/*!
* Metro JS for jQuery
* http://drewgreenwell.com/ 
* For details and usage info see: http://drewgreenwell.com/projects/metrojs

Copyright (C) 2013, 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 ($) {
    
// the metrojs object contains helper methods and theme settings
    
$.fn.metrojs = {
        
capabilitiesnull,
        
checkCapabilities: function(stgsrecheck){
            if($.
fn.metrojs.capabilities == null || (typeof(recheck) != "undefined" && recheck == true))
                $.
fn.metrojs.capabilities = new $.fn.metrojs.MetroModernizr(stgs);
            return  $.
fn.metrojs.capabilities;
        }
    };
    var 
metrojs = $.fn.metrojs,
        
console window.console;    
    if (
typeof console !== "object") {
        
console = {};
        
console.log = function() {};
        
console.error=function() {};
    }
    var 
throwError typeof ($.error) === "function" ? $.error console.error;
var 
MAX_LOOP_COUNT 99000;
// .liveTile
$.fn.liveTile = function (method) {
    if (
pubMethods[method]) {
        var 
args = [];
        for (var 
1<= arguments.lengthi++) {
            
args[1] = arguments[i];
        }
        return 
pubMethods[method].apply(thisargs);
    } else if (
typeof method === 'object' || !method) {
        return 
pubMethods.init.apply(thisarguments);
    } else {
        $.
error('Method ' method ' does not exist on jQuery.liveTile');
        return 
null;
    }
};


$.
fn.liveTile.contentModules = {
    
modules: [],
    
/* the default module layout
    [
        defaultModules.imageSwap,
        defaultModules.htmlSwap
    ],*/
    
addContentModule: function (moduleNamemodule) {
        if (!(
this.modules instanceof Array))
            
this.modules = [];
        
this.modules.push(module);
    },
    
hasContentModule: function (moduleName) {
        if (
typeof (moduleName) === "undefined" || !(this.modules instanceof Array))
            return -
1;
        for (var 
0this.modules.lengthi++) {
            if (
typeof (this.modules[i].moduleName) != "undefined" && this.modules[i].moduleName == moduleName)
                return 
i;
        }
        return -
1;
    }
};

// default option values for .liveTile
$.fn.liveTile.defaults = {
    
mode'slide',                          // 'fade', 'slide', 'flip', 'flip-list', carousel
    
speed500,                             // how fast should animations be performed, in milliseconds
    
initDelay: -1,                          // how long to wait before the initial animation
    
delay5000,                            // how long to wait between animations 
    
stops"100%",                          // how much of the back tile should 'slide' reveal before starting a delay
    
stackfalse,                           // should tiles in slide mode appear stacked (e.g Me tile) 
    
direction'vertical',                  // which direction should animations be performed(horizontal | vertical)
    
animationDirection'forward',          // the direction that carousel mode uses to determine which way to slide in tiles
    
tileSelector'>div,>li,>p,>img,>a',    // the selector used by carousel mode and flip-list to choose tile containers
    
tileFaceSelector'>div,>li,>p,>img,>a',// the selector used to choose the front and back containers
    
ignoreDataAttributesfalse,            // should data attributes be ignored
    
clicknull,                            // function ($tile, tdata) { return true; }
    
link'',                               // a url to go to when clicked
    
newWindowfalse,                       // should the link be opened in a new window
    
bouncefalse,                          // should the tile shrink when tapped
    
bounceDirections'all',                // which direction the tile will tile 'all', 'edges, 'corners'
    
bounceFollowsMovetrue,                // should a tile in bounce state tilt in the direction of the mouse as it moves
    
pauseOnHoverfalse,                    // should tile animations be paused on hover in and restarted on hover out
    
pauseOnHoverEvent'both',              // pause is called on mouseover, mouseout, or both
    
playOnHoverfalse,                     // should "play" be called on hover
    
playOnHoverEvent'both',               // play is called on mouseover, mouseout, or both
    
onHoverDelay0,                        // the amount of time to wait before the onHover event is fired
    
onHoverOutDelay200,                    // the amount of time in addition to the speed to wait before the onHoverOut event is fired
    
repeatCount: -1,                        // number of times to repeat the animation        
    
appendBacktrue,                       // appends the .last tile if one doesnt exist (slide and flip only)        
    
alwaysTriggerfalse,                   // should every item in a flip list trigger every time a delay passes 
    
flipListOnHoverfalse,                 // should items in flip-list flip and stop when hovered
    
flipListOnHoverEvent'mouseout',       // which event should be used to trigger the flip-list faces
    
noHAflipOpacity'1',                   // the opacity level set for the backside of the flip animation on unaccelerated browsers
    
haTransFunc'ease',                    // the tranisiton-timing function to use in hardware accelerated mode
    
noHaTransFunc'linear',                // the tranisiton-timing function to use in non hardware accelerated mode
    
currentIndex0,                        // what is the current stop index for slide mode or slide index for carousel mode
    
startNowtrue,                         // should the tile immediately start or wait util play or restart has been called
    
useModernizr: (typeof (window.Modernizr) !== "undefined"), // checks to see if modernizer is already in use
    
useHardwareAcceltrue,                 // should css animations, transitions and transforms be used when available
    
useTranslatetrue,
    
faces: {
        
$frontnull,                        // the jQuery element to use as the front face of the tile; this will bypass tileCssSelector
        
$backnull                          // the jQuery element to use as the back face of the tile; this will bypass tileCssSelector
    
},
    
animationStarting: function (tileData$front$back) {
        
// returning false will cancel the animation
    
},
    
animationComplete: function (tileData$front$back) {
    },
    
triggerDelay: function (idx) {          // used by flip-list to decide how random the tile flipping should be
        
return Math.random() * 3000;
    },
    
swap'',                               // which swap modules are active for this tile (image, html)
    
swapFront'-',                         // override the available swap modules for the front face
    
swapBack'-',                          // override the available swap modules for the back face
    
contentModules: [],
    
rebindMessage"tile data is missing. Are you missing a call to rebind or destroy? You may also be able to avoid this error by calling stop or pause"
};
// public methods that can be called via .liveTile(method name)
var pubMethods = {
    
init: function (options) {
        
// Setup the public options for the livetile
        
var settings = $.extend({}, $.fn.liveTile.defaultsoptions);
        
// checks for browser feature support to enable hardware acceleration                        
        
metrojs.checkCapabilities(settings);
        
helperMethods.getBrowserPrefix();
        
// setup the default content modules
        
if ($.fn.liveTile.contentModules.hasContentModule("image") == -1)
            $.
fn.liveTile.contentModules.addContentModule("image"defaultModules.imageSwap);
        if ($.
fn.liveTile.contentModules.hasContentModule("html") == -1)
            $.
fn.liveTile.contentModules.addContentModule("html"defaultModules.htmlSwap);
        
// this is where the magic happens
        
return $(this).each(function (tileIndexele) {
            var 
$this = $(ele),
            
data privMethods.initTileData($thissettings);
            
// append back tiles and add appropriate classes to prepare tiles
            
data.faces privMethods.prepTile($thisdata);
            
// action methods
            
data.fade = function (count) { privMethods.fade($thiscount); };
            
data.slide = function (count) { privMethods.slide($thiscount); };
            
data.carousel = function (count) { privMethods.carousel($thiscount); };
            
data.flip = function (count) { privMethods.flip($thiscount); };
            
data.flipList = function (count) { privMethods.flipList($thiscount); };
            var 
actions = {
                
fadedata.fade,
                
slidedata.slide,
                
carouseldata.carousel,
                
flipdata.flip,
                
'flip-list'data.flipList
            
};
            
data.doAction = function (count) {
                
// get the action for the current mode
                
var action actions[data.mode];
                if (
typeof (action) === "function") {
                    
action(count);
                    
data.hasRun true;
                }
                
// prevent pauseOnHover from resuming a tile that has finished
                
if (count == data.timer.repeatCount)
                    
data.runEvents false;
            };

            
// create a new tile timer
            
data.timer = new $.fn.metrojs.TileTimer(data.delaydata.doActiondata.repeatCount);
            
// apply the data
            
$this.data("LiveTile"data);
            
// handle events
            // only bind pause / play on hover if we are not using a fliplist or flipListOnHover isn't set set
            
if (data.mode !== "flip-list" || data.flipListOnHover == false) {
                if (
data.pauseOnHover) {
                    
privMethods.bindPauseOnHover($this);
                } else if (
data.playOnHover) {
                    
privMethods.bindPlayOnHover($thisdata);
                }
            }
            
// add a click / link to the tile
            
if (data.link.length || typeof (data.click) === "function") {
                
$this.css({ cursor'pointer' }).bind("click.liveTile", function (e) {
                    var 
proceed true;
                    if (
typeof (data.click) === "function") {
                        
proceed data.click($thisdata) || false;
                    }
                    if (
proceed && data.link.length 0) {
                        
e.preventDefault();
                        if (
data.newWindow)
                            
window.open(data.link);
                        else
                            
window.location data.link;
                    }
                });
            }
            
// add bounce if set            
            
privMethods.bindBounce($thisdata);
            
// start timer
            
if (data.startNow && data.mode != "none") {
                
data.runEvents true;
                
data.timer.start(data.initDelay);
            }
        });
    },
    
// goto is a future reserved word
    
'goto': function (options) {
        var 
optstypeof (options);
        if (
=== "undefined") {
            
opts = {
                
index: -99//  same as next
                
delay0,
                
autoAniDirectionfalse
            
};
        }
        if (
=== "number" || !isNaN(options)) {
            
opts = {
                
indexparseInt(options10),
                
delay0
            
};
        } else if (
=== "string") {
            if (
options == "next") {
                
opts = {
                    
index: -99,
                    
delay0
                
};
            } else if (
options.indexOf("prev") === 0) {
                
opts = {
                    
index: -100,
                    
delay0
                
};
            } else {
                $.
error(options " is not a recognized action for .liveTile("goto")");
                return $(
this);
            }
        } else if (
=== "object") {
            if (
typeof (options.delay) === "undefined") {
                
options.delay 0;
            }
            var 
ti typeof (options.index);
            if (
ti === "undefined") {
                
options.index 0;
            } else if (
ti === "string") {
                if (
options.index === "next")
                    
options.index = -99;
                else if (
options.index.indexOf("prev") === 0)
                    
options.index = -100;
            }
            
opts options;
        }
        return $(
this).each(function (tileIndexele) {
            var 
$tile = $(ele),
                
data $tile.data("LiveTile"),
                
aniData $tile.data("metrojs.tile"),
                goTo = 
opts.index;
            if (
aniData.animating === true)
                return $(
this);
            if (
data.mode === "carousel") {
                
// get the index based off of the active carousel slide
                
var $cur data.faces.$listTiles.filter(".active");
                var 
curIdx data.faces.$listTiles.index($cur);
                
// carousel will look for these values as triggers
                
if (goTo === -100) { // prev
                    // autoAniDirection determines if a forward or backward animation should be used based on the goTo index
                    
if (typeof (opts.autoAniDirection) === "undefined" || opts.autoAniDirection == true)
                        
data.tempValues.animationDirection typeof (opts.animationDirection) === "undefined" "backward" opts.animationDirection;
                    goTo = 
curIdx === data.faces.$listTiles.length curIdx 1;
                } else if (goTo === -
99) { // next
                    
if (typeof (opts.autoAniDirection) === "undefined" || opts.autoAniDirection == true)
                        
data.tempValues.animationDirection typeof (opts.animationDirection) === "undefined" "forward" opts.animationDirection;
                    goTo = 
curIdx 1;
                }
                if (
curIdx == goTo) {
                    return;
                }
                if (
typeof (opts.direction) !== "undefined") {
                    
data.tempValues.direction opts.direction;
                }
                if (
typeof (opts.animationDirection) !== "undefined") {
                    
data.tempValues.animationDirection opts.animationDirection;
                }
                
// the index is offset by 1 and incremented on animate
                
if (goTo == 0)
                    
data.currentIndex data.faces.$listTiles.length;
                else
                    
data.currentIndex = goTo - 1;
            } else 
// slide mode will use the index directly
                
data.currentIndex = goTo;
            
// start the timer
            
data.runEvents true;
            
data.timer.start(opts.delay >= opts.delay data.delay);
        });
    },
    
play: function (options) {
        var 
optstypeof (options);
        if (
=== "undefined") {
            
opts = {
                
delay: -1
            
};
        } else if (
=== "number") {
            
opts = {
                
delayoptions
            
};
        } else if (
=== "object") {
            if (
typeof (options.delay) === "undefined") {
                
options.delay = -1;
            }
            
opts options;
        }
        return $(
this).each(function (tileIndexele) {
            var 
$tile = $(ele),
                
data $tile.data("LiveTile");
            
data.runEvents true;
            if (
opts.delay && !data.hasRun)
                
opts.delay data.initDelay;
            
data.timer.start(opts.delay >= opts.delay data.delay);
        });
    },
    
animate: function () { // this is really only useful for certain edge cases in slide mode, use 'play' to toggle animations
        
return $(this).each(function (tileIndexele) {
            var 
$tile = $(ele),
                
data $tile.data("LiveTile");
            
data.doAction();
        });
    },
    
stop: function () {
        return $(
this).each(function (tileIndexele) {
            var 
$tile = $(ele),
                
data $tile.data("LiveTile");
            
data.hasRun false;
            
data.runEvents false;
            
data.timer.stop();
            
window.clearTimeout(data.eventTimeout);
            
window.clearTimeout(data.flCompleteTimeout);
            
window.clearTimeout(data.completeTimeout);
            if (
data.mode === "flip-list") {
                
data.faces.$listTiles.each(function (idxli) {
                    var 
ldata = $(li).data("metrojs.tile");
                    
window.clearTimeout(ldata.eventTimeout);
                    
window.clearTimeout(ldata.flCompleteTimeout);
                    
window.clearTimeout(ldata.completeTimeout);
                });
            }
        });
    },
    
pause: function () {
        return $(
this).each(function (tileIndexele) {
            var 
$tile = $(ele),
                
data $tile.data("LiveTile");
            
data.timer.pause();
            
data.runEvents false;
            
window.clearTimeout(data.eventTimeout);
            
window.clearTimeout(data.flCompleteTimeout);
            
window.clearTimeout(data.completeTimeout);
            if (
data.mode === "flip-list") {
                
data.faces.$listTiles.each(function (idxli) {
                    var 
ldata = $(li).data("metrojs.tile");
                    
window.clearTimeout(ldata.eventTimeout);
                    
window.clearTimeout(ldata.flCompleteTimeout);
                    
window.clearTimeout(ldata.completeTimeout);
                });
            }
        });
    },
    
restart: function (options) {
        var 
optstypeof (options);
        if (
=== "undefined") {
            
opts = {
                
delay: -1
            
};
        } else if (
=== "number") {
            
opts = {
                
delayoptions
            
};
        } else if (
=== "object") {
            if (
typeof (options.delay) === "undefined") {
                
options.delay = -1;
            }
            
opts options;
        }
        return $(
this).each(function (tileIndexele) {
            var 
$tile = $(ele),
                
data $tile.data("LiveTile");
            if (
opts.delay && !data.hasRun)
                
opts.delay data.initDelay;
            
data.hasRun false;
            
data.runEvents true;
            
data.timer.restart(opts.delay >= opts.delay data.delay);
        });
    },
    
rebind: function (options) {
        return $(
this).each(function (tileIndexele) {
            if (
typeof (options) !== "undefined") {
                if (
typeof (options.timer) !== "undefined" && options.timer != null) {
                    
options.timer.stop();
                }
                
options.hasRun false;
                
pubMethods["init"].apply(ele, [options]);
            } else {
                
pubMethods["init"].apply(ele, [{}]);
            }
        });
    },
    
destroy: function (options) {
        var 
typeof (options), opts;
        if (
=== "undefined") {
            
opts = {
                
removeCssfalse
            
};
        } else if (
=== "boolean") {
            
opts = {
                
removeCssoptions
            
};
        } else if (
=== "object") {
            if (
typeof (options.removeCss) === "undefined") {
                
options.removeCss false;
            }
            
opts options;
        }
        return $(
this).each(function (tileIndexele) {
            var 
$tile = $(ele);
            var 
data $tile.data("LiveTile");
            if (
typeof (data) === "undefined")
                return;
            
$tile.unbind(".liveTile");
            var 
resetCss helperMethods.appendStyleProperties({ margin''cursor'' }, ['transform''transition'], ['''']);
            
data.timer.stop();
            
window.clearTimeout(data.eventTimeout);
            
window.clearTimeout(data.flCompleteTimeout);
            
window.clearTimeout(data.completeTimeout);
            if (
data.faces.$listTiles != null) {
                
data.faces.$listTiles.each(function (idxli) {
                    var 
$li = $(li);
                    if (
data.mode === "flip-list") {
                        var 
ldata $li.data("metrojs.tile");
                        
window.clearTimeout(ldata.eventTimeout);
                        
window.clearTimeout(ldata.flCompleteTimeout);
                        
window.clearTimeout(ldata.completeTimeout);
                    } else if (
data.mode === "carousel") {
                        var 
sdata data.listData[idx];
                        if (
sdata.bounce) {
                            
privMethods.unbindMsBounce($lisdata);
                        }
                    }
                    if (
opts.removeCss) {
                        
$li.removeClass("ha");
                        
$li.find(data.tileFaceSelector)
                            .
unbind(".liveTile")
                            .
removeClass("bounce flip-front flip-back ha slide slide-front slide-back")
                            .
css(resetCss);
                    } else {
                        
$li.find(data.tileFaceSelector).unbind(".liveTile");
                    }
                    
$li.removeData("metrojs.tile");
                }).
unbind(".liveTile");
            }
            if (
data.faces.$front != null && opts.removeCss) {
                
data.faces.$front.removeClass("flip-front flip-back ha slide slide-front slide-back")
                    .
css(resetCss);
            }
            if (
data.faces.$back != null && opts.removeCss) {
                
data.faces.$back.removeClass("flip-front flip-back ha slide slide-front slide-back")
                    .
css(resetCss);
            }
            
// remove the bounce and hover methods
            // todo: combine all mouse/touch events (down, move, up)
            
if (data.bounce) {
                
privMethods.unbindMsBounce($tiledata);
            }
            if (
data.playOnHover) {
                
privMethods.unbindMsPlayOnHover($tiledata);
            }
            if (
data.pauseOnhover) {
                
privMethods.unbindMsPauseOnHover($tiledata);
            }
            
$tile.removeClass("ha");
            
$tile.removeData("LiveTile");
            
$tile.removeData("metrojs.tile");
            
data null;
        });
    }
};

// private methods that are called by .liveTile
var privMethods = {
    
//getDataOrDefault for older versions of jQuery that dont look for 'data-' properties
    
dataAtr: function ($elenamedef) {
        return 
typeof ($ele.attr('data-' name)) !== "undefined" $ele.attr('data-' name) : def;
    },
    
dataMethod: function ($elenamedef) {
        return 
typeof ($ele.data(name)) !== "undefined" $ele.data(name) : def;
    },
    
getDataOrDefaultnull,
    
initTileData: function ($tilestgs) {
        var 
useData stgs.ignoreDataAttributes == false,
            
tdata null;
        if (
this.getDataOrDefault == null)
            
this.getDataOrDefault metrojs.capabilities.isOldJQuery this.dataAtr this.dataMethod;
        if (
useData) {
            
tdata = { //an object to store settings for later access                
                
speedthis.getDataOrDefault($tile"speed"stgs.speed),
                
delaythis.getDataOrDefault($tile"delay"stgs.delay),
                
stopsthis.getDataOrDefault($tile"stops"stgs.stops),
                
stackthis.getDataOrDefault($tile"stack"stgs.stack),
                
modethis.getDataOrDefault($tile"mode"stgs.mode),
                
directionthis.getDataOrDefault($tile"direction"stgs.direction),
                
useHardwareAccelthis.getDataOrDefault($tile"ha"stgs.useHardwareAccel),
                
repeatCountthis.getDataOrDefault($tile"repeat"stgs.repeatCount),
                
swapthis.getDataOrDefault($tile"swap"stgs.swap),
                
appendBackthis.getDataOrDefault($tile"appendback"stgs.appendBack),
                
currentIndexthis.getDataOrDefault($tile"start-index"stgs.currentIndex),
                
animationDirectionthis.getDataOrDefault($tile"ani-direction"stgs.animationDirection),
                
startNowthis.getDataOrDefault($tile"start-now"stgs.startNow),
                
tileSelectorthis.getDataOrDefault($tile"tile-selector"stgs.tileSelector),
                
tileFaceSelectorthis.getDataOrDefault($tile"face-selector"stgs.tileFaceSelector),
                
bouncethis.getDataOrDefault($tile"bounce"stgs.bounce),
                
bounceDirectionsthis.getDataOrDefault($tile"bounce-dir"stgs.bounceDirections),
                
bounceFollowsMovethis.getDataOrDefault($tile"bounce-follows"stgs.bounceFollowsMove),
                
clickthis.getDataOrDefault($tile"click"stgs.click),
                
linkthis.getDataOrDefault($tile"link"stgs.link),
                
newWindowthis.getDataOrDefault($tile"new-window"stgs.newWindow),
                
alwaysTriggerthis.getDataOrDefault($tile"always-trigger"stgs.alwaysTrigger),
                
flipListOnHoverthis.getDataOrDefault($tile"flip-onhover"stgs.flipListOnHover),
                
pauseOnHoverthis.getDataOrDefault($tile"pause-onhover"stgs.pauseOnHover),
                
playOnHoverthis.getDataOrDefault($tile"play-onhover"stgs.playOnHover),
                
onHoverDelaythis.getDataOrDefault($tile"hover-delay"stgs.onHoverDelay),
                
onHoverOutDelaythis.getDataOrDefault($tile"hoverout-delay"stgs.onHoverOutDelay),
                
noHAflipOpacitythis.getDataOrDefault($tile"flip-opacity"stgs.noHAflipOpacity),
                
useTranslatethis.getDataOrDefault($tile"use-translate"stgs.useTranslate),
                
runEventsfalse,
                
isReversedfalse,
                
loopCount0,
                
contentModules: [],
                
listData: [],
                
height$tile.height(),
                
width$tile.width(),
                
tempValues: {}
            };
        } else {
            
tdata = $.extend(true, {
                
runEventsfalse,
                
isReversedfalse,
                
loopCount0,
                
contentModules: [],
                
listData: [],
                
height$tile.height(),
                
width$tile.width(),
                
tempValues: {}
            }, 
stgs);
        }
        
tdata.useTranslate tdata.useTranslate && tdata.useHardwareAccel && metrojs.capabilities.canTransform && metrojs.capabilities.canTransition;
        
// set the margin to half of the height or width based on the direction
        
tdata.margin = (tdata.direction === "vertical") ? tdata.height tdata.width 2;
        
// convert stops if needed
        
tdata.stops = (typeof (stgs.stops) === "object" && (stgs.stops instanceof Array)) ? stgs.stops : ("" tdata.stops).split(",");
        
// add a return stop
        
if (tdata.stops.length === 1)
            
tdata.stops.push("0px");
        
// add content modules, start with global swaps            
        
var swaps tdata.swap instanceof Array ? tdata.swap tdata.swap.replace(' ''').split(",");
        
// get the front and back swap data
        
var sf useData this.getDataOrDefault($tile"swap-front"stgs.swapFront) : stgs.swapFront;
        var 
sb useData this.getDataOrDefault($tile"swap-back"stgs.swapBack) : stgs.swapBack;
        
// set the data to the global value if its still the default
        
if (sf instanceof Array) {
            
tdata.swapFront sf;
        } else {
            
tdata.swapFront sf === '-' swaps sf.replace(' ''').split(",");
        }

        if (
sb instanceof Array) {
            
tdata.swapBack sb;
        } else {
            
tdata.swapBack sb === '-' swaps sb.replace(' ''').split(",");
        }
        
// make sure the swaps includes all front and back swaps
        
var i;
        for (
0tdata.swapFront.lengthi++) {
            if (
tdata.swapFront[i].length && $.inArray(tdata.swapFront[i], swaps) === -1)
                
swaps.push(tdata.swapFront[i]);
        }
        for (
0tdata.swapBack.lengthi++) {
            if (
tdata.swapBack[i].length && $.inArray(tdata.swapBack[i], swaps) === -1)
                
swaps.push(tdata.swapBack[i]);
        }
        
tdata.swap swaps;
        
// add all required content modules for the swaps
        
for (0swaps.lengthi++) {
            if (
swaps[i].length 0) {
                var 
moduleIdx = $.fn.liveTile.contentModules.hasContentModule(swaps[i]);
                if (
moduleIdx > -1) {
                    
tdata.contentModules.push($.fn.liveTile.contentModules.modules[moduleIdx]);
                }
            }
        }
        
// set the initDelay value to the delay if it's not set
        
tdata.initDelay useData this.getDataOrDefault($tile"initdelay"stgs.initDelay) : stgs.initDelay;
        
// if the delay is -1 call the triggerDelay function to get a value
        
if (tdata.delay < -1)
            
tdata.delay stgs.triggerDelay(1);
        else if (
tdata.delay 0)
            
tdata.delay 3500 + (Math.random() * 4501);
        
// match the delay value if less than 0
        
if (tdata.initDelay 0)
            
tdata.initDelay tdata.delay;
        
// merge the objects
        
var mergedData = {};
        for (
0tdata.contentModules.lengthi++)
            $.
extend(mergedDatatdata.contentModules[i].data);
        $.
extend(mergedDatastgstdata);
        
// add flip-list / carousel data
        
var $tiles;
        if (
mergedData.mode === "flip-list") {
            
$tiles $tile.find(mergedData.tileSelector).not(".tile-title");
            
$tiles.each(function (idxele) {
                var 
$li = $(ele);
                var 
ldata = {
                    
directionuseData privMethods.getDataOrDefault($li"direction"mergedData.direction) : mergedData.direction,
                    
newWindowuseData privMethods.getDataOrDefault($li"new-window"false) : false,
                    
linkuseData privMethods.getDataOrDefault($li"link""") : "",
                    
faces: { $frontnull$backnull },
                    
height$li.height(),
                    
width$li.width(),
                    
isReversedfalse
                
};
                
ldata.margin ldata.direction === "vertical" ldata.height ldata.width 2;
                
mergedData.listData.push(ldata);
            });
        } else if (
mergedData.mode === "carousel") {
            
mergedData.stack true;
            
$tiles $tile.find(mergedData.tileSelector).not(".tile-title");
            
$tiles.each(function (idxele) {
                var 
$slide = $(ele);
                var 
sdata = {
                    
bounceuseData privMethods.getDataOrDefault($slide"bounce"false) : false,
                    
bounceDirectionsuseData privMethods.getDataOrDefault($slide"bounce-dir""all") : "all",
                    
linkuseData privMethods.getDataOrDefault($slide"link""") : "",
                    
newWindowuseData privMethods.getDataOrDefault($slide"new-window"false) : false,
                    
animationDirectionuseData privMethods.getDataOrDefault($slide"ani-direction""") : "",
                    
directionuseData privMethods.getDataOrDefault($slide"direction""") : ""
                
};
                
mergedData.listData.push(sdata);
            });
        }
        
// get any additional options from the modules
        
for (0tdata.contentModules.lengthi++) {
            if (
typeof (mergedData.contentModules[i].initData) === "function")
                
mergedData.contentModules[i].initData(mergedData$tile);
        }
        
tdata null;
        return 
mergedData;
    },
    
prepTile: function ($tiletdata) {
        
//add the mode to the tile if it's not already there.
        
$tile.addClass(tdata.mode);
        var 
ret = {
            
$tileFacesnull,     // all possible tile faces in a liveTile in a non list mode
            
$listTilesnull,     // all possible tiles in a liveTile in a list mode
            
$frontnull,         // the front face of a tile in a non list mode
            
$backnull          // the back face of a tile in a non list mode
        
};
        var 
rotateDirfrontCssbackCsstileCss;
        
// prepare the tile based on the current mode
        
switch (tdata.mode) {
            case 
"fade":
                
// front and back tile faces
                
ret.$tileFaces $tile.find(tdata.tileFaceSelector).not(".tile-title");
                
ret.$front = (tdata.faces.$front != null && tdata.faces.$front.length 0) ?
                               
tdata.faces.$front.addClass('fade-front') :
                               
ret.$tileFaces.filter(":first").addClass('fade-front');
                
// get back face from settings, via selector, or append it if necessary
                
if (tdata.faces.$back != null && tdata.faces.$back.length 0)    // use $back option
                    
ret.$back tdata.faces.$back.addClass('fade-back');
                else if (
ret.$tileFaces.length 1)                             // get the last tile face
                    
ret.$back ret.$tileFaces.filter(":last").addClass('fade-back');
                else if (
tdata.appendBack)                                       // append the back tile
                    
ret.$back = $('<div class="fade-back"></div>').appendTo($tile);
                else                                                            
// just keep an empty placeholder
                    
ret.$back = $('<div></div>');
                break;
            case 
"slide":
                
// front and back tile faces
                
ret.$tileFaces $tile.find(tdata.tileFaceSelector).not(".tile-title");
                
// get front face from settings or via selector
                
ret.$front = (tdata.faces.$front != null && tdata.faces.$front.length 0) ?
                                
tdata.faces.$front.addClass('slide-front') :
                                
ret.$tileFaces.filter(":first").addClass('slide-front'); // using :first for pre jQuery 1.4
                // get back face from settings, via selector, or append it if necessary
                
if (tdata.faces.$back != null && tdata.faces.$back.length 0)    // use $back option
                    
ret.$back tdata.faces.$back.addClass('slide-back');
                else if (
ret.$tileFaces.length 1)                             // get the last tile face
                    
ret.$back ret.$tileFaces.filter(":last").addClass('slide-back');
                else if (
tdata.appendBack)                                       // append the back tile
                    
ret.$back = $('<div class="slide-back"></div>').appendTo($tile);
                else                                                            
// just keep an empty placeholder
                    
ret.$back = $('<div></div>');
                
// stack mode
                
if (tdata.stack == true) {
                    var 
prop,
                        
translate;
                    if (
tdata.direction === "vertical") {
                        
prop "top",
                        
translate 'translate(0%, -100%) translateZ(0)';
                    } else {
                        
prop "left",
                        
translate 'translate(-100%, 0%) translateZ(0)';
                    }
                    
backCss = {};
                    if (
tdata.useTranslate)
                        
helperMethods.appendStyleProperties(backCss, ['transform'], [translate]);
                    else
                        
backCss[prop] = "-100%";
                    
ret.$back.css(backCss);
                }
                
$tile.data("metrojs.tile", { animatingfalse });
                if (
metrojs.capabilities.canTransition && tdata.useHardwareAccel) {   // hardware accelerated :)                        
                    
$tile.addClass("ha");
                    
ret.$front.addClass("ha");
                    
ret.$back.addClass("ha");
                }
                break;
            case 
"carousel":
                
ret.$listTiles $tile.find(tdata.tileSelector).not(".tile-title");
                var 
numberOfSlides ret.$listTiles.length;
                
$tile.data("metrojs.tile", { animatingfalse });
                
tdata.currentIndex Math.min(tdata.currentIndexnumberOfSlides 1);
                
ret.$listTiles.each(function (idxele) {
                    var 
$slide = $(ele).addClass("slide");
                    var 
sdata tdata.listData[idx],
                        
aniDir typeof (sdata.animationDirection) === "string" && sdata.animationDirection.length sdata.animationDirection tdata.animationDirection,
                        
dir typeof (sdata.direction) === "string" && sdata.direction.length sdata.direction tdata.direction;
                    if (
idx == tdata.currentIndex) {
                        
$slide.addClass("active");
                    } else if (
aniDir === "forward") {
                        if (
dir === "vertical") {
                            
tileCss tdata.useTranslate helperMethods.appendStyleProperties({}, ['transform'], ['translate(0%, 100%) translateZ(0)']) :
                                                   { 
left'0%'top'100%' };
                            
$slide.css(tileCss);
                        } else {
                            
tileCss tdata.useTranslate helperMethods.appendStyleProperties({}, ['transform'], ['translate(100%, 0%) translateZ(0)']) :
                                                   { 
left'100%'top'0%' };
                            
$slide.css(tileCss);
                        }
                    } else if (
aniDir === "backward") {
                        if (
dir === "vertical") {
                            
tileCss tdata.useTranslate helperMethods.appendStyleProperties({}, ['transform'], ['translate(0%, -100%) translateZ(0)']) :
                                                   { 
left'0%'top'-100%' };
                            
$slide.css(tileCss);
                        } else {
                            
tileCss tdata.useTranslate helperMethods.appendStyleProperties({}, ['transform'], ['translate(-100%, 0%) translateZ(0)']) :
                                                   { 
left'-100%'top'0%' };
                            
$slide.css(tileCss);
                        }
                    }
                    
// link and bounce can be bound per slide
                    // add the click handler and link property
                    
privMethods.bindLink($slidesdata);
                    
// add the bounce effect
                    
if (tdata.useHardwareAccel && metrojs.capabilities.canTransition)
                        
privMethods.bindBounce($slidesdata);
                    
$slide null;
                    
sdata null;
                });
                
// hardware accelerated :)
                
if (metrojs.capabilities.canFlip3d && tdata.useHardwareAccel) {
                    
$tile.addClass("ha");
                    
ret.$listTiles.addClass("ha");
                }
                break;
            case 
"flip-list":
                
// the tile containers inside the list
                
ret.$listTiles $tile.find(tdata.tileSelector).not(".tile-title");
                
ret.$listTiles.each(function (idxele) {
                    var 
$li = $(ele).addClass("tile-" + (idx 1));
                    
// add the flip class to the front face
                    
var $lFront $li.find(tdata.tileFaceSelector).filter(":first").addClass("flip-front").css({ margin"0px" });
                    
// append a back tile face if one isnt present
                    
if ($li.find(tdata.tileFaceSelector).length === && tdata.appendBack == true)
                        
$li.append("<div></div>");
                    
// add the flip class to the back face
                    
var $lBack $li.find(tdata.tileFaceSelector).filter(":last").addClass("flip-back").css({ margin"0px" });
                    
// update the tdata object with the faces
                    
tdata.listData[idx].faces.$front $lFront;
                    
tdata.listData[idx].faces.$back $lBack;
                    
// set data for overrides and easy access
                    
$li.data("metrojs.tile", {
                        
animatingfalse,
                        
count1,
                        
completeTimeoutnull,
                        
flCompleteTimeoutnull,
                        
indexidx
                    
});
                    var 
ldata $li.data("metrojs.tile");
                    
// add the hardware accelerated classes
                    
if (metrojs.capabilities.canFlip3d && tdata.useHardwareAccel) {   // hardware accelerated :)
                        
$li.addClass("ha");
                        
$lFront.addClass("ha");
                        
$lBack.addClass("ha");
                        
rotateDir tdata.listData[idx].direction === "vertical" "rotateX(180deg)" "rotateY(180deg)";
                        
backCss helperMethods.appendStyleProperties({}, ["transform"], [rotateDir]);
                        
$lBack.css(backCss);
                    } else { 
// not hardware accelerated :(
                        // the front tile face will take up the entire tile
                        
frontCss = (tdata.listData[idx].direction === "vertical") ?
                { 
height'100%'width'100%'marginTop'0px'opacity'1' } :
                { 
height'100%'width'100%'marginLeft'0px'opacity'1' };
                        
// the back tile face is hidden by default and expanded halfway through a flip
                        
backCss = (tdata.listData[idx].direction === "vertical") ?
                { 
height'0px'width'100%'marginToptdata.listData[idx].margin 'px'opacitytdata.noHAflipOpacity } :
                { 
height'100%'width'0px'marginLefttdata.listData[idx].margin 'px'opacitytdata.noHAflipOpacity };
                        
$lFront.css(frontCss);
                        
$lBack.css(backCss);
                    }
                    var 
flipEnded = function () {
                        
ldata.count++;
                        if (
ldata.count >= MAX_LOOP_COUNT)
                            
ldata.count 1;
                    };
                    if (
tdata.flipListOnHover) {
                        var 
event tdata.flipListOnHoverEvent ".liveTile";
                        
$lFront.bind(event, function () {
                            
privMethods.flip($lildata.counttdataflipEnded);
                        });
                        
$lBack.bind(event, function () {
                            
privMethods.flip($lildata.counttdataflipEnded);
                        });
                    }
                    if (
tdata.listData[idx].link.length 0) {
                        
$li.css({ cursor'pointer' }).bind("click.liveTile", function () {
                            if (
tdata.listData[idx].newWindow)
                                
window.open(tdata.listData[idx].link);
                            else
                                
window.location tdata.listData[idx].link;
                        });
                    }
                });
                break;
            case 
"flip":
                
// front and back tile faces
                
ret.$tileFaces $tile.find(tdata.tileFaceSelector).not(".tile-title");
                
// get front face from settings or via selector
                
ret.$front = (tdata.faces.$front != null && tdata.faces.$front.length 0) ?
                                
tdata.faces.$front.addClass('flip-front') :
                                
ret.$tileFaces.filter(":first").addClass('flip-front');
                
// get back face from settings, via selector, or append it if necessary
                
if (tdata.faces.$back != null && tdata.faces.$back.length 0) {
                    
// use $back option
                    
ret.$back tdata.faces.$back.addClass('flip-back');
                } else if (
ret.$tileFaces.length 1) {
                    
// get the last tile face
                    
ret.$back ret.$tileFaces.filter(":last").addClass('flip-back');
                } else if (
tdata.appendBack) {
                    
// append the back tile
                    
ret.$back = $('<div class="flip-back"></div>').appendTo($tile);
                } else {
                    
// just keep an empty placeholder
                    
ret.$back = $('<div></div>');
                }
                
$tile.data("metrojs.tile", { animatingfalse });
                if (
metrojs.capabilities.canFlip3d && tdata.useHardwareAccel) {
                    
// hardware accelerated :)
                    
$tile.addClass("ha");
                    
ret.$front.addClass("ha");
                    
ret.$back.addClass("ha");
                    
rotateDir tdata.direction === "vertical" "rotateX(180deg)" "rotateY(180deg)";
                    
backCss helperMethods.appendStyleProperties({}, ["transform"], [rotateDir]);
                    
ret.$back.css(backCss);

                } else {
                    
// not hardware accelerated :(
                    // the front tile face will take up the entire tile
                    
frontCss = (tdata.direction === "vertical") ?
            { 
height'100%'width'100%'marginTop'0px'opacity'1' } :
            { 
height'100%'width'100%'marginLeft'0px'opacity'1' };
                    
// the back tile face is hidden by default and expanded halfway through a flip
                    
backCss = (tdata.direction === "vertical") ?
            { 
height'0%'width'100%'marginToptdata.margin 'px'opacity'0' } :
            { 
height'100%'width'0%'marginLefttdata.margin 'px'opacity'0' };
                    
ret.$front.css(frontCss);
                    
ret.$back.css(backCss);
                }
                break;
        }
        return 
ret;
    },
    
bindPauseOnHover: function ($tile) {
        
// stop the tile when hovered and resume after a delay
        
(function () {
            var 
data $tile.data("LiveTile"),
                
isOver false,
                
isPending false,
                
pauseIn = (data.pauseOnHoverEvent == "both" || data.pauseOnHoverEvent == "mouseover" || data.pauseOnHoverEvent == "mouseenter"),
                
pauseOut = (data.pauseOnHoverEvent == "both" || data.pauseOnHoverEvent == "mouseout" || data.pauseOnHoverEvent == "mouseleave");
            
data.pOnHoverMethods = {
                
pause: function () {
                    
data.timer.pause();
                    if (
data.mode === "flip-list") {
                        
data.faces.$listTiles.each(function (idxli) {
                            
window.clearTimeout($(li).data("metrojs.tile").completeTimeout);
                        });
                    }
                },
                
over: function (e) {
                    if (
isOver || isPending)
                        return;
                    if (
data.runEvents) {
                        
isPending true;
                        
data.eventTimeout window.setTimeout(function () {
                            
isPending false;
                            if (
pauseOut)
                                
isOver true;
                            
data.pOnHoverMethods.pause();
                        }, 
data.onHoverDelay);
                    }
                },
                
out: function (e) {
                    if (
isPending) {
                        
window.clearTimeout(data.eventTimeout);
                        
isPending false;
                        return;
                    }
                    if (
pauseIn) {
                        if (!
isOver && !isPending)
                            return;
                        if (
data.runEvents) {
                            
// todo: use a custom value if provided
                            
data.timer.start(data.hasRun data.delay data.initDelay);
                        }
                    } else {
                        
data.pOnHoverMethods.pause();
                    }
                    
isOver false;
                }
            };
            if (!
metrojs.capabilities.canTouch) {
                if (
pauseIn)
                    
$tile.bind("mouseover.liveTile"data.pOnHoverMethods.over);
                if (
pauseOut)
                    
$tile.bind("mouseout.liveTile"data.pOnHoverMethods.out);
            } else {
                if (
window.navigator.msPointerEnabled) { // pointer
                    
if (pauseIn)
                        
$tile[0].addEventListener('MSPointerOver'data.pOnHoverMethods.overfalse);
                    if (
pauseOut)
                        
$tile[0].addEventListener('MSPointerOut'data.pOnHoverMethods.outfalse);
                } else { 
// touch events
                    
if (pauseIn)
                        
$tile.bind("touchstart.liveTile"data.pOnHoverMethods.over);
                    if (
pauseOut)
                        
$tile.bind("touchend.liveTile"data.pOnHoverMethods.out);
                }
            }
        })();
    },
    
unbindMsPauseOnHover: function ($tiledata) {
        if (
typeof (data.pOnHoverMethods) !== "undefined" && window.navigator.msPointerEnabled) {
            
$tile[0].removeEventListener('MSPointerOver'data.pOnHoverMethods.overfalse);
            
$tile[0].removeEventListener('MSPointerOut'data.pOnHoverMethods.outfalse);
        }
    },
    
bindPlayOnHover: function ($tiledata) {
        
// play the tile immediately when hovered
        
(function () {
            var 
isOver false,
                
isPending false,
                
playIn = (data.playOnHoverEvent == "both" || data.playOnHoverEvent == "mouseover" || data.playOnHoverEvent == "mouseenter"),
                
playOut = (data.playOnHoverEvent == "both" || data.playOnHoverEvent == "mouseout" || data.playOnHoverEvent == "mouseleave");
            
data.onHoverMethods = {
                
over: function (event) {
                    if (
isOver || isPending || (data.bounce && data.bounceMethods.down != "no"))
                        return;
                    
// if startNow is set use the opposite of isReversed so we're in sync            
                    
var rev = (data.mode == "flip") || (data.startNow ? !data.isReversed data.isReversed);
                    
window.clearTimeout(data.eventTimeout);
                    if ((
data.runEvents && rev) || !data.hasRun) {
                        
isPending true;
                        
data.eventTimeout window.setTimeout(function () {
                            
isPending false;
                            if (
playOut)
                                
isOver true;
                            
pubMethods["play"].apply($tile[0], [0]);
                        }, 
data.onHoverDelay);
                    }
                },
                
out: function (event) {
                    if (
isPending) {
                        
window.clearTimeout(data.eventTimeout);
                        
isPending false;
                        return;
                    }
                    if (
playIn) {
                        if (!
isOver && !isPending) {
                            return;
                        }
                    }
                    
window.clearTimeout(data.eventTimeout);
                    
data.eventTimeout window.setTimeout(function () {
                        var 
rev = (data.mode == "flip") || (data.startNow data.isReversed : !data.isReversed);
                        if (
data.runEvents && rev) {
                            
pubMethods["play"].apply($tile[0], [0]);
                        }
                        
isOver false;
                    }, 
data.speed data.onHoverOutDelay);
                }
            };
            if (!
metrojs.capabilities.canTouch) {
                if (
playIn)
                    
$tile.bind('mouseenter.liveTile'data.onHoverMethods.over);
                if (
playOut)
                    
$tile.bind('mouseleave.liveTile'data.onHoverMethods.out);
            } else {
                if (
window.navigator.msPointerEnabled) { // pointer
                    
if (playIn)
                        
$tile[0].addEventListener('MSPointerDown'data.onHoverMethods.overfalse);
                    
// mouseleave gives a more consistent effect than out when the children are transformed
                    
if (playOut)
                        
$tile.bind("mouseleave.liveTile"data.onHoverMethods.out);
                } else { 
// touch events
                    
if (playIn)
                        
$tile.bind("touchstart.liveTile"data.onHoverMethods.over);
                    if (
playOut)
                        
$tile.bind("touchend.liveTile"data.onHoverMethods.out);
                }

            }
        })();
    },
    
unbindMsPlayOnHover: function ($tiledata) {
        if (
typeof (data.onHoverMethods) !== "undefined" && window.navigator.msPointerEnabled) {
            
$tile[0].removeEventListener('MSPointerDown'data.onHoverMethods.overfalse);
        }
    },
    
bindBounce: function ($tiledata) {
        
// add bounce
        
if (data.bounce) {
            
$tile.addClass("bounce");
            
$tile.addClass("noselect");
            (function () {
                
data.bounceMethods = {
                    
down"no",
                    
threshold30,
                    
zeroPos: { x0y},
                    
eventPos: { x0y},
                    
inTilePos: { x0y},
                    
pointPos: { x0y},
                    
regions: {
                        
c: [00],      // center
                        
tl: [-1, -1],   // top left
                        
tr: [1, -1],    // top right
                        
bl: [-11],    // bottom left
                        
br: [11],     // bottom right
                        
t: [null, -1],  // top
                        
r: [1null],   // right
                        
b: [null1],   // bottom
                        
l: [-1null]   // left
                    
},
                    
targets: {
                        
all: ['c''t''r''b''l''tl''tr''bl''br'],
                        
edges: ['c''t''r''b''l'],
                        
corners: ['c''tl''tr''bl''br']
                    },
                    
hitTest: function ($elpostargetRegionsomegaC) {
                        var 
regions data.bounceMethods.regions,
                            
checkFor data.bounceMethods.targets[targetRegions],
                            
0,
                            
strictMatch null,
                            
looseMatch null,
                            
defResult = { hit: [00], name'c' };
                        
// scale only for android 2.x and old ie
                        
if (metrojs.capabilities.isOldAndroid || !metrojs.capabilities.canTransition)
                            return 
defResult;
                        if (
typeof (checkFor) == "undefined") {
                            if (
typeof (targetRegions) === "string")
                                
checkFor targetRegions.split(',');
                            
// only default to center if explicitly requested
                            
if ($.isArray(checkFor) && $.inArray('c') == -1) {
                                
omegaC 0;
                                
defResult null;
                            }
                        }
                        
// check for a matching region
                        
var $el.width(),
                           
$el.height(),
                           
// center threshold -  maximum amount from center
                           
ct = [omegaComegaC],
                           
// how far from the center is the point
                           
diffX pos.- (0.5),
                           
diffY pos.- (0.5),
                            
// if we're beyond the center threshold, set -1 or 1 else 0
                           
hit = [
                               
diffX ? (Math.abs(diffX) <= ct[0] ? 1) : (Math.abs(diffX) <= ct[0] ? : -1),
                               
diffY ? (Math.abs(diffY) <= ct[1] ? 1) : (Math.abs(diffY) <= ct[1] ? : -1)
                           ];
                        for (; 
checkFor.lengthi++) {
                            if (
strictMatch != null)
                                return 
strictMatch;
                            var 
checkFor[i],
                                
region regions[r];
                            if (
== "*") {
                                
checkFor[1];
                                return { 
regionregions[r], name};
                            }
                            if (
hit[0] == region[0] && hit[1] == region[1]) {
                                
// found the region with a strict lookup
                                
strictMatch = { hitregionname};
                            } else if ((
hit[0] == region[0] || region[0] == null) && (hit[1] == region[1] || region[1] == null)) {
                                
// found the region with a loose lookup
                                
looseMatch = { hitregionname};
                            }
                        }
                        
// prefer a strict match
                        
if (strictMatch != null)
                            return 
strictMatch;
                        else if (
looseMatch != null)
                            return 
looseMatch;
                        else 
// no matches were found, return center
                            
return defResult;
                    },
                    
bounceDown: function (e) {
                        if (
e.target.tagName == "A" && !$(e).is(".bounce"))
                            return;
                        var 
point e.originalEvent && e.originalEvent.touches e.originalEvent.touches[0] : e,
                            
offsetOfTile $tile.offset(),
                            
scrollX window.pageXOffset,
                            
scrollY window.pageYOffset;
                        
data.bounceMethods.pointPos = {
                            
xpoint.pageX,
                            
ypoint.pageY
                        
};
                        
data.bounceMethods.inTilePos = {
                            
xpoint.pageX offsetOfTile.left,
                            
ypoint.pageY offsetOfTile.top
                        
};

                        if (!
data.$tileParent) {
                            
data.$tileParent $tile.parent();
                        }
                        var 
offsetOfParent data.$tileParent.offset();
                        
data.bounceMethods.eventPos = {
                            
x: (offsetOfTile.left offsetOfParent.left) + ($tile.width() / 2),
                            
y: (offsetOfTile.top offsetOfParent.top) + ($tile.height() / 2)
                        };
                        var 
hit data.bounceMethods.hitTest($tiledata.bounceMethods.inTilePosdata.bounceDirections0.25);
                        if (
hit == null)
                            
data.bounceMethods.down "no";
                        else {
                            if (
window.navigator.msPointerEnabled) {
                                
document.addEventListener('MSPointerUp'data.bounceMethods.bounceUpfalse);
                                
$tile[0].addEventListener('MSPointerUp'data.bounceMethods.bounceUpfalse);
                                
document.addEventListener('MSPointerCancel'data.bounceMethods.bounceUpfalse);
                                if (
data.bounceFollowsMove)
                                    
$tile[0].addEventListener('MSPointerMove'data.bounceMethods.bounceMovefalse);
                            } else {
                                $(
document).bind("mouseup.liveTile, touchend.liveTile, touchcancel.liveTile, dragstart.liveTile"data.bounceMethods.bounceUp);
                                if (
data.bounceFollowsMove) {
                                    
$tile.bind("touchmove.liveTile"data.bounceMethods.bounceMove);
                                    
$tile.bind("mousemove.liveTile"data.bounceMethods.bounceMove);
                                }
                            }
                            var 
bClass "bounce-" hit.name;
                            
$tile.addClass(bClass);
                            
data.bounceMethods.down bClass;
                            
data.bounceMethods.downPcss helperMethods.appendStyleProperties({}, ['perspective-origin'], [data.bounceMethods.eventPos."px " data.bounceMethods.eventPos."px"]);
                            
data.$tileParent.css(data.bounceMethods.downPcss);
                        }
                    },
                    
bounceUp: function () {
                        if (
data.bounceMethods.down != "no") {
                            
data.bounceMethods.unBounce();
                            if (
window.navigator.msPointerEnabled) {
                                
document.removeEventListener('MSPointerUp'data.bounceMethods.bounceUpfalse);
                                
$tile[0].removeEventListener('MSPointerUp'data.bounceMethods.bounceUpfalse);
                                
document.removeEventListener('MSPointerCancel'data.bounceMethods.bounceUpfalse);
                                if (
data.bounceFollowsMove)
                                    
$tile[0].removeEventListener('MSPointerMove'data.bounceMethods.bounceMovefalse);

                            } else
                                $(
document).unbind("mouseup.liveTile, touchend.liveTile, touchcancel.liveTile, dragstart.liveTile"data.bounceMethods.bounceUp);
                            if (
data.bounceFollowsMove) {
                                
$tile.unbind("touchmove.liveTile"data.bounceMethods.bounceMove);
                                
$tile.unbind("mousemove.liveTile"data.bounceMethods.bounceMove);
                            }
                        }
                    },
                    
bounceMove: function (e) {
                        if (
data.bounceMethods.down != "no") {
                            var 
point e.originalEvent && e.originalEvent.touches e.originalEvent.touches[0] : e,
                                
Math.abs(point.pageX data.bounceMethods.pointPos.x),
                                
Math.abs(point.pageY data.bounceMethods.pointPos.y);
                            if (
data.bounceMethods.threshold || data.bounceMethods.threshold) {
                                var 
bounceClass data.bounceMethods.down;
                                
data.bounceMethods.bounceDown(e);
                                if (
bounceClass != data.bounceMethods.down)
                                    
$tile.removeClass(bounceClass);
                            }
                        }
                    },
                    
unBounce: function () {
                        
$tile.removeClass(data.bounceMethods.down);
                        if (
typeof (data.bounceMethods.downPcss) == "object") {
                            var 
names = ['perspective-origin''perspective-origin-x''perspective-origin-y'],
                                
vals = [''''''];
                            
data.bounceMethods.downPcss helperMethods.appendStyleProperties({}, namesvals);
                            
// let the bounce finish and then strip out the perspective
                            
window.setTimeout(function () {
                                
data.$tileParent.css(data.bounceMethods.downPcss);
                            }, 
200);
                        }
                        
data.bounceMethods.down "no";
                        
data.bounceMethods.inTilePos data.bounceMethods.zeroPos;
                        
data.bounceMethods.eventPos data.bounceMethods.zeroPos;
                    }
                };
                
// IE 10+
                
if (window.navigator.msPointerEnabled) {// touch only -> // && window.navigator.msMaxTouchPoints) {
                    
$tile[0].addEventListener('MSPointerDown'data.bounceMethods.bounceDownfalse);
                } else if (
metrojs.capabilities.canTouch) {
                    
// everybody else                    
                    
$tile.bind("touchstart.liveTile"data.bounceMethods.bounceDown);

                } else {
                    
$tile.bind("mousedown.liveTile"data.bounceMethods.bounceDown);
                }
            })();
        }
    },
    
unbindMsBounce: function ($tiledata) {
        if (
data.bounce && window.navigator.msPointerEnabled) {// touch only -> // && window.navigator.msMaxTouchPoints) {
            
$tile[0].removeEventListener('MSPointerDown'data.bounceMethods.bounceDownfalse);
            
$tile[0].removeEventListener('MSPointerCancel'data.bounceMethods.bounceUpfalse);
            
$tile[0].removeEventListener('MSPointerOut'data.bounceMethods.bounceUpfalse);
            
//$tile[0].removeEventListener('MSPointerMove', data.bounceMethods.bounceMove, false);
        
}
    },
    
bindLink: function ($tiledata) {
        if (
data.link.length 0) {
            
$tile.css({ cursor'pointer' }).bind("click.liveTile", function (e) {
                if (
e.target.tagName == "A" && !$(e).is(".live-tile,.slide,.flip"))
                    return;
                if (
data.newWindow)
                    
window.open(data.link);
                else
                    
window.location data.link;
            });
        }
    },
    
runContenModules: function (data$front$backindex) {
        for (var 
0data.contentModules.lengthi++) {
            var 
currentModule data.contentModules[i];
            if (
typeof (currentModule.action) == "function")
                
currentModule.action(data$front$backindex);
        }
    },
    
fade: function ($tilecountdata) {
        var 
tdata typeof (data) === "object" data $tile.data("LiveTile"),
            
resumeTimer = function () {
                
// if the tile should run again start the timer back with the current delay
                
if (tdata.timer.repeatCount || tdata.timer.repeatCount == -1) {
                    if (
tdata.timer.count != tdata.timer.repeatCount) {
                        
tdata.timer.start(tdata.delay);
                    }
                }
            };
        if (
typeof (tdata) === "undefined") {
            
throwError($.fn.liveTile.defaults.rebindMessage);
            return;
        }
        if (
tdata.faces.$front.is(":animated"))
            return;
        
tdata.timer.pause();
        var 
loopCount tdata.loopCount 1;
        
tdata.isReversed loopCount === 0// the count starts at 1
        
var start tdata.animationStarting.call($tile[0], tdatatdata.faces.$fronttdata.faces.$back);
        if (
typeof (start) != "undefined" && start == false) {
            
resumeTimer();
            return;
        }
        
tdata.loopCount loopCount;
        var 
faded = function () {
            
resumeTimer();
            
// run content modules and animationComplete callback
            
privMethods.runContenModules(tdatatdata.faces.$fronttdata.faces.$back);
            
tdata.animationComplete.call($tile[0], tdatatdata.faces.$fronttdata.faces.$back);
        };
        if (
tdata.isReversed)
            
tdata.faces.$front.fadeIn(tdata.speedtdata.noHaTransFuncfaded);
        else
            
tdata.faces.$front.fadeOut(tdata.speedtdata.noHaTransFuncfaded);
    },
    
slide: function ($tilecountdatastopIndexcallback) {
        var 
tdata typeof (data) === "object" data $tile.data("LiveTile"),
            
aniData $tile.data("metrojs.tile");
        if (
typeof (tdata) === "undefined") {
            
throwError($.fn.liveTile.defaults.rebindMessage);
            return;
        }
        if (
aniData.animating == true || $tile.is(":animated")) {
            
tdata null;
            
aniData null;
            return;
        }
        var 
resumeTimer = function () {
            
// if the tile should run again start the timer back with the current delay
            
if (tdata.timer.repeatCount || tdata.timer.repeatCount == -1) {
                if (
tdata.timer.count != tdata.timer.repeatCount) {
                    
tdata.timer.start(tdata.delay);
                }
            }
        };
        if (
tdata.mode !== "carousel") {
            
tdata.isReversed tdata.currentIndex !== 0;  // the count starts at 1
            // carousel mode maintains its own timer
            
tdata.timer.pause();
            var 
start tdata.animationStarting.call($tile[0], tdatatdata.faces.$fronttdata.faces.$back);
            if (
typeof (start) != "undefined" && start == false) {
                
resumeTimer();
                return;
            }
            
tdata.loopCount tdata.loopCount 1;
        } else {
            
// in carousel mode the face that just left the stage is always the $back
            
tdata.isReversed true;
        }
        
// get temp values passed in from data methods
        
var direction;
        if (
typeof (tdata.tempValues.direction) === "string" && tdata.tempValues.direction.length 0)
            
direction tdata.tempValues.direction;
        else
            
direction tdata.direction;
        
tdata.tempValues.direction null;
        var 
css = {},
            
cssback = {},
            
// the stop index is overridden in carousel mode
            
stopIdx typeof (stopIndex) === "undefined" tdata.currentIndex stopIndex,
            
stop = $.trim(tdata.stops[Math.min(stopIdxtdata.stops.length 1)]),
            
pxIdx stop.indexOf('px'),
            
offset 0,
            
amount 0,
            
metric = (direction === "vertical") ? tdata.height tdata.width,
            
tProp = (direction === "vertical") ? "top" "left",
            
stack tdata.stack == true;
        
// when the slide is complete increment the index or call the callback
        
var slideFinished = function () {
            if (
typeof (callback) === "undefined") {
                
tdata.currentIndex tdata.currentIndex 1;
                if (
tdata.currentIndex tdata.stops.length 1) {
                    
tdata.currentIndex 0;
                }
            } else {
                
callback();
            }
            if (
tdata.mode != "carousel") {
                
resumeTimer();
            }
            
// run content modules and animationComplete callback            
            
privMethods.runContenModules(tdatatdata.faces.$fronttdata.faces.$backtdata.currentIndex);
            
tdata.animationComplete.call($tile[0], tdatatdata.faces.$fronttdata.faces.$back);
            
tdata null;
            
aniData null;
        };
        if (
pxIdx 0) {
            
amount parseInt(stop.substring(0pxIdx), 10);
            
offset = (amount metric) + 'px';
        } else {
            
//is a percentage
            
amount parseInt(stop.replace('%'''), 10);
            
offset = (amount 100) + '%';
        }
        
// hardware accelerated :)
        
if (metrojs.capabilities.canTransition && tdata.useHardwareAccel) {
            if (
typeof (aniData.animating) !== "undefined" && aniData.animating == true)
                return;
            
aniData.animating true;
            var 
props = ['transition-property''transition-duration''transition-timing-function'],
                
vals = [tdata.useTranslate "transform" tProptdata.speed 'ms'tdata.haTransFunc];
            
vals[helperMethods.browserPrefix 'transition-property'] = helperMethods.browserPrefix "transform";
            
css helperMethods.appendStyleProperties(csspropsvals);
            
cssback helperMethods.appendStyleProperties(cssbackpropsvals);
            var 
vertical direction === "vertical",
                
prop vertical "top" "left",
                
translateTo;
            if (!
tdata.useTranslate) {
                
css[prop] = stop;
                if (
stack)
                    
cssback[prop] = offset;
            } else {
                
translateTo vertical "translate(0%, " stop ")" "translate(" stop ", 0%)";
                
css helperMethods.appendStyleProperties(css, ['transform'], [translateTo "translateZ(0)"]);
                if (
stack) {
                    
translateTo vertical "translate(0%, " offset ")" "translate(" offset ", 0%)";
                    
cssback helperMethods.appendStyleProperties(cssback, ['transform'], [translateTo "translateZ(0)"]);
                }
            }
            
tdata.faces.$front.css(css);
            if (
stack)
                
tdata.faces.$back.css(cssback);
            
window.clearTimeout(tdata.completeTimeout);
            
tdata.completeTimeout window.setTimeout(function () {
                
aniData.animating false;
                
slideFinished();
            }, 
tdata.speed);
        } else {
            
// not hardware accelerated :(
            
css[tProp] = stop;
            
cssback[tProp] = offset;
            
aniData.animating true;
            var 
$front tdata.faces.$front.stop(),
                
$back tdata.faces.$back.stop();
            
$front.animate(csstdata.speedtdata.noHaTransFunc, function () {
                
aniData.animating false;
                
slideFinished();
            });
            
// change the css value to the offset
            
if (stack)
                
$back.animate(cssbacktdata.speedtdata.noHaTransFunc, function () { });
        }
    },
    
carousel: function ($tilecount) {
        var 
tdata $tile.data("LiveTile");
        if (
typeof (tdata) === "undefined") {
            
throwError($.fn.liveTile.defaults.rebindMessage);
            return;
        }
        
// dont update css or call slide if animated or if there's only one face
        
var aniData $tile.data("metrojs.tile");
        if (
aniData.animating == true || tdata.faces.$listTiles.length <= 1) {
            
aniData null;
            return;
        }
        var 
resumeTimer = function () {
            if (
tdata.timer.repeatCount || tdata.timer.repeatCount == -1) {
                if (
tdata.timer.count != tdata.timer.repeatCount) {
                    
tdata.timer.start(tdata.delay);
                }
            }
        };
        
// pause the timer and use a per slide delay
        
tdata.timer.pause();
        var 
$cur tdata.faces.$listTiles.filter(".active"),
            
idx tdata.faces.$listTiles.index($cur),
            goTo = 
tdata.currentIndex,
            
eq = goTo != idx ? goTo : idx,
            
nxtIdx eq >= tdata.faces.$listTiles.length eq 1,
            
sdata tdata.listData[nxtIdx];
        if (
idx == nxtIdx) {
            
aniData null;
            
$cur null;
            return;
        }
        
// get temp values passed in from data methods
        
var animationDirection;
        if (
typeof (tdata.tempValues.animationDirection) === "string" && tdata.tempValues.animationDirection.length 0)
            
animationDirection tdata.tempValues.animationDirection;
        else if (
typeof (sdata.animationDirection) === "string" && sdata.animationDirection.length 0) {
            
animationDirection sdata.animationDirection;
        } else
            
animationDirection tdata.animationDirection;
        
// the temp value for animation direction is not used in slide so i'm setting it to null
        
tdata.tempValues.animationDirection null;
        var 
direction;
        if (
typeof (tdata.tempValues.direction) === "string" && tdata.tempValues.direction.length 0) {
            
direction tdata.tempValues.direction;
        } else if (
typeof (sdata.direction) === "string" && sdata.direction.length 0) {
            
direction sdata.direction;
            
tdata.tempValues.direction direction;
        } else {
            
direction tdata.direction;
        }
        var 
$nxt tdata.faces.$listTiles.eq(nxtIdx),
            
start tdata.animationStarting.call($tile[0], tdata$cur$nxt);
        if (
typeof (start) != "undefined" && start == false) {
            
resumeTimer();
            return;
        }
        
tdata.loopCount tdata.loopCount 1;
        var 
nxtCss helperMethods.appendStyleProperties({}, ['transition-duration'], ['0s']),
            
vertical direction === "vertical",
            
translateTo;
        if (
animationDirection === "backward") {
            if (!
tdata.useTranslate || !metrojs.capabilities.canTransition) {
                if (
vertical) {
                    
nxtCss.top "-100%";
                    
nxtCss.left "0%";
                } else {
                    
nxtCss.top "0%";
                    
nxtCss.left "-100%";
                }
                
tdata.stops = ['100%'];
            } else {
                
translateTo vertical "translate(0%, -100%)" "translate(-100%, 0%)";
                
nxtCss helperMethods.appendStyleProperties(nxtCss, ["transform"], [translateTo " translateZ(0)"]);
                
tdata.stops = ['100%'];
            }
            
tdata.faces.$front $cur;
            
tdata.faces.$back $nxt;

        } else {
            if (!
tdata.useTranslate || !metrojs.capabilities.canTransition) {
                if (
vertical) {
                    
nxtCss.top "100%";
                    
nxtCss.left "0%";
                } else {
                    
nxtCss.top "0%";
                    
nxtCss.left "100%";
                }
            } else {
                
translateTo vertical "translate(0%, 100%)" "translate(100%, 0%)";
                
nxtCss helperMethods.appendStyleProperties(nxtCss, ["transform"], [translateTo " translateZ(0)"]);
            }
            
tdata.faces.$front $nxt;
            
tdata.faces.$back $cur;
            
tdata.stops = ['0%'];
        }
        
$nxt.css(nxtCss);
        
// the timeout wrapper gives the css call above enough time to finish in case we dynamically set the direction
        
window.setTimeout(function () {
            
$cur.removeClass("active");
            
$nxt.addClass("active");
            
privMethods.slide($tilecounttdata0, function () {
                
tdata.currentIndex nxtIdx;
                
aniData null;
                
$cur null;
                
$nxt null;
                
resumeTimer();
            });
        }, 
150);

    },
    
flip: function ($tilecountdatacallback) {
        var 
aniData $tile.data("metrojs.tile");
        if (
typeof (aniData) !== "undefined" && aniData.animating == true) {
            
aniData null;
            return;
        }
        var 
tdata typeof (data) === "object" data $tile.data("LiveTile");
        if (
typeof (tdata) === "undefined") {
            
throwError($.fn.liveTile.defaults.rebindMessage);
            return;
        }
        var 
$front$backdirectiondegrotateDircss,
            
raiseEvt typeof (callback) === "undefined",
            
index 0,
            
isReversed,  // the count starts at 1
            
resumeTimer = function () {
                
// if the tile should run again start the timer back with the current delay
                
if (tdata.timer.repeatCount || tdata.timer.repeatCount == -1) {
                    if (
tdata.timer.count != tdata.timer.repeatCount) {
                        
tdata.timer.start(tdata.delay);
                    }
                }
            };
        
// the timer is only paused if animationComplete is fired
        
if (raiseEvt) {
            
tdata.timer.pause();
            var 
loopCount tdata.loopCount 1;
            
isReversed loopCount === 0;
            
tdata.isReversed isReversed;
            
$front tdata.faces.$front;
            
$back tdata.faces.$back;
            var 
args isReversed ? [tdata$back$front] : [tdata$front$back];
            var 
start tdata.animationStarting.apply($tile[0], args);
            if (
typeof (start) != "undefined" && start == false) {
                
resumeTimer();
                return;
            }
            
direction tdata.direction;
            
height tdata.height;
            
width tdata.width;
            
margin tdata.margin;
            
tdata.loopCount loopCount;
        } else {
            
isReversed count === 0;
            
index aniData.index;
            
$front tdata.listData[index].faces.$front;
            
$back tdata.listData[index].faces.$back;
            
tdata.listData[index].isReversed isReversed;
            
direction tdata.listData[index].direction;
            
height tdata.listData[index].height;
            
width tdata.listData[index].width;
            
margin tdata.listData[index].margin;
        }

        if (
metrojs.capabilities.canFlip3d && tdata.useHardwareAccel) { // Hardware accelerated :)
            
deg = !isReversed "180deg" "360deg";
            
rotateDir direction === "vertical" "rotateX(" deg ")" "rotateY(" deg ")";
            
css helperMethods.appendStyleProperties({}, ["transform""transition"], [rotateDir"all " tdata.speed "ms " tdata.haTransFunc " 0s"]);
            var 
bDeg = !isReversed "360deg" "540deg";
            var 
bRotateDir direction === "vertical" "rotateX(" bDeg ")" "rotateY(" bDeg ")";
            var 
bCss helperMethods.appendStyleProperties({}, ["transform""transition"], [bRotateDir"all " tdata.speed "ms " tdata.haTransFunc " 0s"]);
            
$front.css(css);
            
$back.css(bCss);

            var 
action = function () {
                
aniData.animating false;
                var 
resetDirnewCss;
                if (!
isReversed) {
                    
privMethods.runContenModules(tdata$back$frontindex);
                    if (
raiseEvt) {
                        
resumeTimer();
                        
tdata.animationComplete.call($tile[0], tdata$back$front);
                    } else
                        
callback(tdata$back$front);
                } else {
                    
resetDir direction === "vertical" "rotateX(0deg)" "rotateY(0deg)";
                    
newCss helperMethods.appendStyleProperties({}, ["transform""transition"], [resetDir"all 0s " tdata.haTransFunc " 0s"]);
                    
$front.css(newCss);
                    
//call content modules
                    
privMethods.runContenModules(tdata$front$backindex);
                    if (
raiseEvt) {
                        
resumeTimer();
                        
tdata.animationComplete.call($tile[0], tdata$front$back);
                    } else
                        
callback(tdata$front$back);
                    
$front null;
                    
$back null;
                    
tdata null;
                    
aniData null;
                }
            };
            if (
tdata.mode === "flip-list") {
                
window.clearTimeout(tdata.listData[index].completeTimeout);
                
tdata.listData[index].completeTimeout window.setTimeout(actiontdata.speed);
            } else {
                
window.clearTimeout(tdata.completeTimeout);
                
tdata.completeTimeout window.setTimeout(actiontdata.speed);
            }
        } else { 
// not Hardware accelerated :(
            
var speed tdata.speed 2;
            var 
hideCss = (direction === "vertical") ?
                        { 
height'0px'width'100%'marginTopmargin 'px'opacitytdata.noHAflipOpacity } :
                        { 
height'100%'width'0px'marginLeftmargin 'px'opacitytdata.noHAflipOpacity };
            var 
showCss = (direction === "vertical") ?
                        { 
height'100%'width'100%'marginTop'0px'opacity'1' } :
                        { 
height'100%'width'100%'marginLeft'0px'opacity'1' };
            var 
noHaAction;
            if (!
isReversed) {
                
aniData.animating true;
                
$front.stop().animate(hideCss, { durationspeed });
                
noHaAction = function () {
                    
aniData.animating false;
                    
$back.stop().animate(showCss, {
                        
durationspeed,
                        
complete: function () {
                            
privMethods.runContenModules(tdata$back$frontindex);
                            if (
raiseEvt) {
                                
resumeTimer();
                                
tdata.animationComplete.call($tile[0], tdata$back$front);
                            } else
                                
callback(tdata$back$front);
                            
$front null;
                            
$back null;
                            
tdata null;
                            
aniData null;
                        }
                    });
                };
                if (
tdata.mode === "flip-list") {
                    
window.clearTimeout(tdata.listData[aniData.index].completeTimeout);
                    
tdata.listData[aniData.index].completeTimeout window.setTimeout(noHaActionspeed);
                } else {
                    
window.clearTimeout(tdata.completeTimeout);
                    
tdata.completeTimeout window.setTimeout(noHaActionspeed);
                }
            } else {
                
aniData.animating true;
                
$back.stop().animate(hideCss, { durationspeed });
                
noHaAction = function () {
                    
aniData.animating false;
                    
$front.stop().animate(showCss, {
                        
durationspeed,
                        
complete: function () {
                            
privMethods.runContenModules(tdata$front$backindex);
                            if (
raiseEvt) {
                                
resumeTimer();
                                
tdata.animationComplete.call($tile[0], tdata$front$back);
                            } else
                                
callback(tdata$front$back);
                            
aniData null;
                            
$front null;
                            
$back null;
                        }
                    });
                };
                if (
tdata.mode === "flip-list") {
                    
window.clearTimeout(tdata.listData[aniData.index].completeTimeout);
                    
tdata.listData[aniData.index].completeTimeout window.setTimeout(noHaActionspeed);
                } else {
                    
window.clearTimeout(tdata.completeTimeout);
                    
tdata.completeTimeout window.setTimeout(noHaActionspeed);
                }
            }

        }
    },
    
flipList: function ($tilecount) {
        var 
tdata $tile.data("LiveTile"),
            
maxDelay tdata.speed,
            
triggered false,
            
resumeTimer = function () {
                if (
tdata.timer.repeatCount || tdata.timer.repeatCount == -1) {
                    if (
tdata.timer.count != tdata.timer.repeatCount) {
                        
tdata.timer.start(tdata.delay);
                    }
                }
            };
        if (
typeof (tdata) === "undefined") {
            
throwError($.fn.liveTile.defaults.rebindMessage);
            return;
        }
        
tdata.timer.pause();
        var 
start tdata.animationStarting.call($tile[0], tdatanullnull);
        if (
typeof (start) != "undefined" && start == false) {
            
resumeTimer();
            return;
        }
        
tdata.loopCount tdata.loopCount 1;
        
tdata.faces.$listTiles.each(function (idxele) {
            var 
$li = $(ele),
                
ldata $li.data("metrojs.tile"),
                
tDelay tdata.triggerDelay(idx),
                
triggerDelay tdata.speed Math.max(tDelay0),
                
trigger tdata.alwaysTrigger;
            if (!
trigger)
                
trigger = (Math.random() * 351) > 150 true false;
            if (
trigger) {
                
triggered true;
                
maxDelay Math.max(triggerDelay tdata.speedmaxDelay);
                
window.clearTimeout(ldata.flCompleteTimeout);
                
ldata.flCompleteTimeout window.setTimeout(function () {
                    
// call the flip method with the merged data, but dont fire animationComplete
                    
privMethods.flip($lildata.counttdata, function (data) {
                        
ldata.count++;
                        if (
ldata.count >= MAX_LOOP_COUNT)
                            
ldata.count 1;
                        
$li null;
                        
ldata null;
                    });
                }, 
triggerDelay);
            }
        });
        if (
triggered) {
            
window.clearTimeout(tdata.flCompleteTimeout);
            
tdata.flCompleteTimeout window.setTimeout(function () {
                
privMethods.runContenModules(tdatanullnull, -1);
                
tdata.animationComplete.call($tile[0], tdatanullnull);
                
resumeTimer();
            }, 
maxDelay tdata.speed); // add some padding to make sure the final callback finished

        
}
    }
};


// methods that can be called more universally
var helperMethods = {
    
stylePrefixes'Webkit Moz O ms Khtml '.split(' '),
    
domPrefixes'-webkit- -moz- -o- -ms- -khtml- '.split(' '),
    
browserPrefixnull,
    
// a method to append css3 properties for each browser
    // note: values are identical for each property
    
appendStyleProperties: function (objnamesvalues) {
        for (var 
0<= names.length 1i++) {
            
obj[$.trim(this.browserPrefix names[i])] = values[i];
            
obj[$.trim(names[i])] = values[i];
        }
        return 
obj;
    },
    
applyStyleValue: function (objnamevalue) {
        
obj[$.trim(this.browserPrefix name)] = value;
        
obj[name] = value;
        return 
obj;
    },
    
getBrowserPrefix: function () {
        if (
this.browserPrefix == null) {
            var 
prefix "";
            for (var 
0<= this.domPrefixes.length 1i++) {
                if (
typeof (document.body.style[this.domPrefixes[i] + "transform"]) != "undefined")
                    
prefix this.domPrefixes[i];
            }
            return 
this.browserPrefix prefix;
        }
        return 
this.browserPrefix;
    },
    
//a shuffle method to provide more randomness than sort
    //credit: http://javascript.about.com/library/blshuffle.htm
    //note: avoiding prototype for sharepoint compatability
    
shuffleArray: function (array) {
        var 
= [];
        while (array.
lengths.push(array.splice(Math.random() * array.length1));
        while (
s.length) array.push(s.pop());
        return array;
    }
};

var 
defaultModules = {
    
moduleName'custom',
    
customSwap: {
        
data: {
            
customDoSwapFront: function () { return false; },
            
customDoSwapBack: function () { return false; },
            
customGetContent: function (tdata$front$backindex) { return null; }
        },
        
initData: function (tdata$ele) {
            var 
swapData = {};
            
swapData.doSwapFront = $.inArray('custom'tdata.swapFront) > -&& tdata.customDoSwapFront();
            
swapData.doSwapBack = $.inArray('custom'tdata.swapBack) > -&& tdata.customDoSwapBack();
            if (
typeof (tdata.customSwap) !== "undefined")
                
tdata.customSwap = $.extend(swapDatatdata.customSwap);
            else
                
tdata.customSwap swapData;
        },
        
action: function (tdata$front$backindex) {

        }
    },
    
htmlSwap: {
        
moduleName'html',
        
data: { // public data for the swap module                
            
frontContent: [],                       // a list of html to use for the front
            
frontIsRandomtrue,                    // should html be chosen at random or in order                
            
frontIsInGridfalse,                   // only chooses one item for each iteration in flip-list                
            
backContent: [],                        // a list of html to use for the back
            
backIsRandomtrue,                     // should html be chosen at random or in order                
            
backIsInGridfalse                     // only chooses one item for each iteration in flip-list                
        
},
        
initData: function (tdata$ele) {
            var 
swapData = { // private data for the swap module
                
backBag: [],
                
backIndex0,
                
backStaticIndex0,
                
backStaticRndm: -1,
                
prevBackIndex: -1,
                
frontBag: [],
                
frontIndex0,
                
frontStaticIndex0,
                
frontStaticRndm: -1,
                
prevFrontIndex: -1
            
};
            if (!
tdata.ignoreDataAttributes) {
                
swapData.frontIsRandom privMethods.getDataOrDefault($ele"front-israndom"tdata.frontIsRandom);
                
swapData.frontIsInGrid privMethods.getDataOrDefault($ele"front-isingrid"tdata.frontIsInGrid);
                
swapData.backIsRandom privMethods.getDataOrDefault($ele"back-israndom"tdata.backIsRandom);
                
swapData.backIsInGrid privMethods.getDataOrDefault($ele"back-isingrid"tdata.backIsInGrid);
            } else {
                
swapData.frontIsRandom tdata.frontIsRandom;
                
swapData.frontIsInGrid tdata.frontIsInGrid;
                
swapData.backIsRandom tdata.backIsRandom;
                
swapData.backIsInGrid tdata.backIsInGrid;
            }
            
swapData.doSwapFront = $.inArray('html'tdata.swapFront) > -&& (tdata.frontContent instanceof Array) && tdata.frontContent.length 0;
            
swapData.doSwapBack = $.inArray('html'tdata.swapBack) > -&& (tdata.backContent instanceof Array) && tdata.backContent.length 0;
            if (
typeof (tdata.htmlSwap) !== "undefined")
                
tdata.htmlSwap = $.extend(swapDatatdata.htmlSwap);
            else
                
tdata.htmlSwap swapData;
            if (
tdata.htmlSwap.doSwapFront) {
                
tdata.htmlSwap.frontBag this.prepBag(tdata.htmlSwap.frontBagtdata.frontContenttdata.htmlSwap.prevFrontIndex);
                
tdata.htmlSwap.frontStaticRndm tdata.htmlSwap.frontBag.pop();
            }
            if (
tdata.htmlSwap.doSwapBack) {
                
tdata.htmlSwap.backBag this.prepBag(tdata.htmlSwap.backBagtdata.backContenttdata.htmlSwap.prevBackIndex);
                
tdata.htmlSwap.backStaticRndm tdata.htmlSwap.backBag.pop();
            }
        },
        
prepBag: function (bagcontentprevIdx) {
            
bag bag || [];
            var 
bagCount 0;
            for (var 
0content.lengthi++) {
                
//make sure there's not an immediate repeat
                
if (!= prevIdx || bag.length === 1) {
                    
bag[bagCount] = i;
                    
bagCount++;
                }
            }
            return 
helperMethods.shuffleArray(bag);
        },
        
getFrontSwapIndex: function (tdata) {
            var 
idx 0;
            if (!
tdata.htmlSwap.frontIsRandom) {
                
idx tdata.htmlSwap.frontIsInGrid tdata.htmlSwap.frontStaticIndex tdata.htmlSwap.frontIndex;
            } else {
                if (
tdata.htmlSwap.frontBag.length === 0) {
                    
tdata.htmlSwap.frontBag this.prepBag(tdata.htmlSwap.frontBagtdata.frontContenttdata.htmlSwap.prevFrontIndex);
                }
                if (
tdata.htmlSwap.frontIsInGrid) {
                    
idx tdata.htmlSwap.frontStaticRndm;
                } else {
                    
idx tdata.htmlSwap.frontBag.pop();
                }
            }
            return 
idx;
        },
        
getBackSwapIndex: function (tdata) {
            var 
idx 0;
            if (!
tdata.htmlSwap.backIsRandom) {
                
idx tdata.htmlSwap.backIsInGrid tdata.htmlSwap.backStaticIndex tdata.htmlSwap.backIndex;
            } else {
                if (
tdata.htmlSwap.backBag.length === 0) {
                    
tdata.htmlSwap.backBag this.prepBag(tdata.htmlSwap.backBagtdata.backContenttdata.htmlSwap.prevBackIndex);
                }
                if (
tdata.htmlSwap.backIsInGrid) {
                    
idx tdata.htmlSwap.backStaticRndm;
                } else {
                    
idx tdata.htmlSwap.backBag.pop();
                }
            }
            return 
idx;
        },
        
action: function (tdata$front$backindex) {
            if (!
tdata.htmlSwap.doSwapFront && !tdata.htmlSwap.doSwapBack)
                return;
            var 
isList tdata.mode === "flip-list";
            var 
swapIndex 0;
            var 
isReversed isList tdata.listData[Math.max(index0)].isReversed tdata.isReversed;
            if (
isList && index == -1) {
                
// flip list completed
                
if (!isReversed) {
                    if (
tdata.htmlSwap.doSwapFront) {
                        
// update the random value for grid mode
                        
if (tdata.htmlSwap.frontBag.length === 0)
                            
tdata.htmlSwap.frontBag this.prepBag(tdata.htmlSwap.frontBagtdata.frontContenttdata.htmlSwap.frontStaticRndm);
                        
tdata.htmlSwap.frontStaticRndm tdata.htmlSwap.frontBag.pop();
                        
// update the static index
                        
tdata.htmlSwap.frontStaticIndex++;
                        if (
tdata.htmlSwap.frontStaticIndex >= tdata.frontContent.length)
                            
tdata.htmlSwap.frontStaticIndex 0;
                    }
                } else {
                    if (
tdata.htmlSwap.doSwapBack) {
                        
// update the random value for grid mode
                        
if (tdata.htmlSwap.backBag.length === 0)
                            
tdata.htmlSwap.backBag this.prepBag(tdata.htmlSwap.backBagtdata.backContenttdata.htmlSwap.backStaticRndm);
                        
tdata.htmlSwap.backStaticRndm tdata.htmlSwap.backBag.pop();
                        
// update the static index
                        
tdata.htmlSwap.backStaticIndex++;
                        if (
tdata.htmlSwap.backStaticIndex >= tdata.backContent.length)
                            
tdata.htmlSwap.backStaticIndex 0;
                    }
                }
                return;
            }
            if (!
isReversed) {
                if (!
tdata.htmlSwap.doSwapFront)
                    return;
                
swapIndex this.getFrontSwapIndex(tdata);
                
tdata.htmlSwap.prevFrontIndex swapIndex;
                if (
tdata.mode === "slide") {
                    if (!
tdata.startNow)
                        
$front.html(tdata.frontContent[swapIndex]);
                    else
                        
$back.html(tdata.frontContent[swapIndex]);
                } else
                    
$back.html(tdata.frontContent[swapIndex]);
                
// increment the front index to get the next item from the list
                
tdata.htmlSwap.frontIndex++;
                if (
tdata.htmlSwap.frontIndex >= tdata.frontContent.length)
                    
tdata.htmlSwap.frontIndex 0;
                if (!
isList) {
                    
// increment the static index if we're not in list mode
                    
tdata.htmlSwap.frontStaticIndex++;
                    if (
tdata.htmlSwap.frontStaticIndex >= tdata.frontContent.length)
                        
tdata.htmlSwap.frontStaticIndex 0;
                } else {
                    
// flip list
                
}
            } else {
                if (!
tdata.htmlSwap.doSwapBack)
                    return;
                
swapIndex this.getBackSwapIndex(tdata);
                
tdata.htmlSwap.prevBackIndex swapIndex;
                
$back.html(tdata.backContent[tdata.htmlSwap.backIndex]);
                
tdata.htmlSwap.backIndex++;
                if (
tdata.htmlSwap.backIndex >= tdata.backContent.length)
                    
tdata.htmlSwap.backIndex 0;
                if (!
isList) {
                    
tdata.htmlSwap.backStaticIndex++;
                    if (
tdata.htmlSwap.backStaticIndex >= tdata.backContent.length)
                        
tdata.htmlSwap.backStaticIndex 0;
                } else {
                    
// flip list
                
}
            }
        }
    },
    
imageSwap: {
        
moduleName'image',
        
data: {
            
preloadImagesfalse,
            
imageCssSelector'>img,>a>img',        // the selector used to choose a an image to apply a src or background to
            
fadeSwapfalse,                        // fade the image before swapping
            
frontImages: [],                        // a list of images to use for the front
            
frontIsRandomtrue,                    // should images be chosen at random or in order
            
frontIsBackgroundImagefalse,          // set the src attribute or css background-image property
            
frontIsInGridfalse,                   // only chooses one item for each iteration in flip-list
            
backImagesnull,                       // a list of images to use for the back
            
backIsRandomtrue,                     // should images be chosen at random or in order
            
backIsBackgroundImagefalse,           // set the src attribute or css background-image property
            
backIsInGridfalse                     // only chooses one item for each iteration in flip-list                
        
},
        
initData: function (tdata$ele) {
            var 
swapData = {
                
backBag: [],
                
backIndex0,
                
backStaticIndex0,
                
backStaticRndm: -1,
                
frontBag: [],
                
frontIndex0,
                
frontStaticIndex0,
                
frontStaticRndm: -1,
                
prevBackIndex: -1,
                
prevFrontIndex: -1
            
}, useData tdata.ignoreDataAttributes;
            if (
useData) {
                
swapData.imageCssSelector privMethods.getDataOrDefault($ele"image-css"tdata.imageCssSelector);
                
swapData.fadeSwap privMethods.getDataOrDefault($ele"fadeswap"tdata.fadeSwap);
                
swapData.frontIsRandom privMethods.getDataOrDefault($ele"front-israndom"tdata.frontIsRandom);
                
swapData.frontIsInGrid privMethods.getDataOrDefault($ele"front-isingrid"tdata.frontIsInGrid);
                
swapData.frontIsBackgroundImage privMethods.getDataOrDefault($ele"front-isbg"tdata.frontIsBackgroundImage);
                
swapData.backIsRandom privMethods.getDataOrDefault($ele"back-israndom"tdata.backIsRandom);
                
swapData.backIsInGrid privMethods.getDataOrDefault($ele"back-isingrid"tdata.backIsInGrid);
                
swapData.backIsBackgroundImage privMethods.getDataOrDefault($ele"back-isbg"tdata.backIsBackgroundImage);
                
swapData.doSwapFront = $.inArray('image'tdata.swapFront) > -&& (tdata.frontImages instanceof Array) && tdata.frontImages.length 0;
                
swapData.doSwapBack = $.inArray('image'tdata.swapBack) > -&& (tdata.backImages instanceof Array) && tdata.backImages.length 0;
                
swapData.alwaysSwapFront privMethods.getDataOrDefault($ele"front-alwaysswap"tdata.alwaysSwapFront);
                
swapData.alwaysSwapBack privMethods.getDataOrDefault($ele"back-alwaysswap"tdata.alwaysSwapBack);
            } else {
                
swapData.imageCssSelector tdata.imageCssSelector;
                
swapData.fadeSwap tdata.fadeSwap;
                
swapData.frontIsRandom tdata.frontIsRandom;
                
swapData.frontIsInGrid tdata.frontIsInGrid;
                
swapData.frontIsBackgroundImage tdata.frontIsBackgroundImage;
                
swapData.backIsRandom tdata.backIsRandom;
                
swapData.backIsInGrid tdata.backIsInGrid;
                
swapData.backIsBackgroundImage tdata.backIsBackgroundImage;
                
swapData.doSwapFront = $.inArray('image'tdata.swapFront) > -&& (tdata.frontImages instanceof Array) && tdata.frontImages.length 0;
                
swapData.doSwapBack = $.inArray('image'tdata.swapBack) > -&& (tdata.backImages instanceof Array) && tdata.backImages.length 0;
                
swapData.alwaysSwapFront tdata.alwaysSwapFront;
                
swapData.alwaysSwapBack tdata.alwaysSwapBack;
            }
            if (
typeof (tdata.imgSwap) !== "undefined")
                
tdata.imgSwap = $.extend(swapDatatdata.imgSwap);
            else
                
tdata.imgSwap swapData;
            if (
tdata.imgSwap.doSwapFront) {
                
tdata.imgSwap.frontBag this.prepBag(tdata.imgSwap.frontBagtdata.frontImagestdata.imgSwap.prevFrontIndex);
                
tdata.imgSwap.frontStaticRndm tdata.imgSwap.frontBag.pop();
                if (
tdata.preloadImages)
                    $(
tdata.frontImages).metrojs.preloadImages(function () { });
            }
            if (
tdata.imgSwap.doSwapBack) {
                
tdata.imgSwap.backBag this.prepBag(tdata.imgSwap.backBagtdata.backImagestdata.imgSwap.prevBackIndex);
                
tdata.imgSwap.backStaticRndm tdata.imgSwap.backBag.pop();
                if (
tdata.preloadImages)
                    $(
tdata.backImages).metrojs.preloadImages(function () { });
            }
        },
        
prepBag: function (bagcontentprevIdx) {
            
bag bag || [];
            var 
bagCount 0;
            for (var 
0content.lengthi++) {
                
//make sure there's not an immediate repeat
                
if (!= prevIdx || content.length === 1) {
                    
bag[bagCount] = i;
                    
bagCount++;
                }
            }
            return 
helperMethods.shuffleArray(bag);
        },
        
getFrontSwapIndex: function (tdata) {
            var 
idx 0;
            if (!
tdata.imgSwap.frontIsRandom) {
                
idx tdata.imgSwap.frontIsInGrid tdata.imgSwap.frontStaticIndex tdata.imgSwap.frontIndex;
            } else {
                if (
tdata.imgSwap.frontBag.length === 0) {
                    
tdata.imgSwap.frontBag this.prepBag(tdata.imgSwap.frontBagtdata.frontImagestdata.imgSwap.prevFrontIndex);
                }
                if (
tdata.imgSwap.frontIsInGrid) {
                    
idx tdata.imgSwap.frontStaticRndm;
                } else {
                    
idx tdata.imgSwap.frontBag.pop();
                }
            }
            return 
idx;
        },
        
getBackSwapIndex: function (tdata) {
            var 
idx 0;
            if (!
tdata.imgSwap.backIsRandom) {
                
idx tdata.imgSwap.backIsInGrid tdata.imgSwap.backStaticIndex tdata.imgSwap.backIndex;
            } else {
                if (
tdata.imgSwap.backBag.length === 0) {
                    
tdata.imgSwap.backBag this.prepBag(tdata.imgSwap.backBagtdata.backImagestdata.imgSwap.prevBackIndex);
                }
                if (
tdata.imgSwap.backIsInGrid) {
                    
idx tdata.imgSwap.backStaticRndm;
                } else {
                    
idx tdata.imgSwap.backBag.pop();
                }
            }
            return 
idx;
        },
        
setImageProperties: function ($imgimageisBackground) {
            var 
css = {}, // css object to apply
                
attr = {}; // attribute values to apply
            // get image source
            
if (typeof (image.src) !== 'undefined') {
                if (!
isBackground)
                    
attr.src image.src;
                else
                    
css.backgroundImage "url('" image.src "')";
            }
            
// get alt text
            
if (typeof (image.alt) !== 'undefined')
                
attr.alt image.alt;
            
// set css
            
if (typeof (image.css) === 'object')
                
$img.css($.extend(cssimage.css));
            else
                
$img.css(css);
            
// set attributes
            
if (typeof (image.attr) === 'object')
                
$img.attr($.extend(attrimage.attr));
            else
                
$img.attr(attr);
        },
        
action: function (tdata$front$backindex) {
            if (!
tdata.imgSwap.doSwapFront && !tdata.imgSwap.doSwapBack)
                return;
            var 
isList tdata.mode === "flip-list",
                
isSlide tdata.mode == "slide",
                
swapIndex 0,
                
isReversed isList tdata.listData[Math.max(index0)].isReversed tdata.isReversed;
            if (
isList && index == -1) {
                
// flip list completed
                
if (tdata.alwaysSwapFront || !isReversed) {
                    if (
tdata.imgSwap.doSwapFront) {
                        
// update the random value for grid mode
                        
if (tdata.imgSwap.frontBag.length === 0)
                            
tdata.imgSwap.frontBag this.prepBag(tdata.imgSwap.frontBagtdata.frontImagestdata.imgSwap.frontStaticRndm);
                        
tdata.imgSwap.frontStaticRndm tdata.imgSwap.frontBag.pop();
                        
// update the static index
                        
tdata.imgSwap.frontStaticIndex++;
                        if (
tdata.imgSwap.frontStaticIndex >= tdata.frontImages.length)
                            
tdata.imgSwap.frontStaticIndex 0;
                    }
                }
                if (
tdata.alwaysSwapBack || isReversed) {
                    if (
tdata.imgSwap.doSwapBack) {
                        
// update the random value for grid mode
                        
if (tdata.imgSwap.backBag.length === 0)
                            
tdata.imgSwap.backBag this.prepBag(tdata.imgSwap.backBagtdata.backImagestdata.imgSwap.backStaticRndm);
                        
tdata.imgSwap.backStaticRndm tdata.imgSwap.backBag.pop();
                        
// update the static index
                        
tdata.imgSwap.backStaticIndex++;
                        if (
tdata.imgSwap.backStaticIndex >= tdata.backImages.length)
                            
tdata.imgSwap.backStaticIndex 0;
                    }
                }
                return;
            }
            var 
$face// face being swapped
                
$img// image to apply values
                
image,// image object to hold properties
                
swap// wrapper for setimageProperties for fade
            
if (tdata.alwaysSwapFront || !isReversed) {
                if (!
tdata.imgSwap.doSwapFront)
                    return;
                
swapIndex this.getFrontSwapIndex(tdata);
                
tdata.imgSwap.prevFrontIndex swapIndex;
                
// slide mode has a static front and back face
                
$face = (tdata.mode === "slide") ? $front $back;
                
$img $face.find(tdata.imgSwap.imageCssSelector);
                
image typeof (tdata.frontImages[swapIndex]) === "object" tdata.frontImages[swapIndex] : { srctdata.frontImages[swapIndex] };
                
swap = function (callback) {
                    
// set src, alt, css and attribute values
                    
var isBg tdata.imgSwap.frontIsBackgroundImage;
                    if (
typeof (callback) == "function") {
                        if (
isBg)
                            
window.setTimeout(callback100);
                        else
                            
$img[0].onload callback;
                    }
                    
defaultModules.imageSwap.setImageProperties($imgimageisBg);

                };
                if (
tdata.fadeSwap) {
                    
$img.fadeOut(function () {
                        
swap(function () {
                            
$img.fadeIn();
                        });
                    });
                } else
                    
swap();
                
// increment indexes
                
tdata.imgSwap.frontIndex++;
                if (
tdata.imgSwap.frontIndex >= tdata.frontImages.length)
                    
tdata.imgSwap.frontIndex 0;
                if (!
isList) {
                    
tdata.imgSwap.frontStaticIndex++;
                    if (
tdata.imgSwap.frontStaticIndex >= tdata.frontImages.length)
                        
tdata.imgSwap.frontStaticIndex 0;
                } else {

                }
            }
            if (
tdata.alwaysSwapBack || isReversed) {
                if (!
tdata.imgSwap.doSwapBack)
                    return;
                
// get the new index
                
swapIndex this.getBackSwapIndex(tdata);
                
tdata.imgSwap.prevBackIndex swapIndex;
                
// use the $face var for consistency
                
$face $back;
                
$img $face.find(tdata.imgSwap.imageCssSelector);
                
image typeof (tdata.backImages[swapIndex]) === "object" tdata.backImages[swapIndex] : { srctdata.backImages[swapIndex] };
                
swap = function () {
                    
// set src, alt, css and attribute values
                    
defaultModules.imageSwap.setImageProperties($imgimagetdata.imgSwap.backIsBackgroundImage);
                };
                if (
tdata.fadeSwap) {
                    
$img.fadeOut(function () {
                        
swap(function () {
                            
$img.fadeIn();
                        });
                    });
                } else
                    
swap();
                
// increment indexes
                
tdata.imgSwap.backIndex++;
                if (
tdata.imgSwap.backIndex >= tdata.backImages.length)
                    
tdata.imgSwap.backIndex 0;
                if (!
isList) {
                    
tdata.imgSwap.backStaticIndex++;
                    if (
tdata.imgSwap.backStaticIndex >= tdata.backImages.length)
                        
tdata.imgSwap.backStaticIndex 0;
                } else {

                }
            }
        }
    }
};

// object to maintain timer state
$.fn.metrojs.TileTimer = function (intervalcallbackrepeatCount) {
    
this.timerId null;                                                        // the id of the current timeout
    
this.interval interval;                                                   // the amount of time to wait between each action call
    
this.action callback;                                                     // the method that is fired on each tick
    
this.count 0;                                                             // the number of times the action has been fired
    
this.repeatCount typeof (repeatCount) === "undefined" repeatCount;   // the number of times the action will be fired        
    // call the action method after a delay and call start | stop based on repeat count
    
this.start = function (delay) {
        
window.clearTimeout(this.timerId);
        var 
this;
        
this.timerId window.setTimeout(function () {
            
t.tick.call(tinterval);
        }, 
delay);
    };

    
this.tick = function (when) {
        
this.action(this.count 1);
        
this.count++;
        
// reset the loop count
        
if (this.count >= MAX_LOOP_COUNT)
            
this.count 0;
        if (
this.repeatCount || this.repeatCount == -1) {
            if (
this.count != this.repeatCount) {
                
this.start(when);
            } else
                
this.stop();
        }
    }
    
// clear the timer and reset the count
    
this.stop = function () {
        
this.timerId window.clearTimeout(this.timerId);
        
this.reset();
    };

    
this.resume = function () {
        if (
this.repeatCount || this.repeatCount == -1) {
            if (
this.count != this.repeatCount) {
                
this.start(interval);
            }
        }
    };

    
// clear the timer but leave the count intact
    
this.pause = function () {
        
this.timerId window.clearTimeout(this.timerId);
    };

    
// reset count
    
this.reset = function () {
        
this.count 0;
    };

    
// reset count and timer
    
this.restart = function (delay) {
        
this.stop();
        
this.start(delay);
    };
};
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(stgstgs);
            
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 (
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.baseThemestgs.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.baseThemestgs.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.baseThemestgs.accentColor);
                
//preload light theme image
                
if (typeof (stgs.preloadAltBaseTheme) !== "undefined" && stgs.preloadAltBaseTheme)
                    
jQuery([(stgs.baseTheme == 'dark') ? stgs.metroLightUrl stgs.metroDarkUrl]).metrojs.preloadImages(function () { });
            }
        }
    },
    
applyTheme: function (tColoraColorstgs) {
        if (
typeof (stgs) === "undefined" || stgs == null) {
            
stgs jQuery.fn.metrojs.theme.defaults;
        } else {
            var 
stg jQuery.fn.metrojs.theme.defaults;
            
stgs jQuery.extend({}, stgstgs);
        }

        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);
            }
        }
    },
    
appendAccentColors: function (stgs) {
        if (
typeof (stgs) === "undefined" || stgs == null) {
            
stgs jQuery.fn.metrojs.theme.defaults;
        } else {
            var 
stg jQuery.fn.metrojs.theme.defaults;
            
stgs jQuery.extend({}, stgstgs);
        }
        var 
themeList "";
        var 
themes stgs.accentColors;
        var 
template stgs.accentListTemplate;
        for (var 
0themes.lengthi++) {
            
themeList += template.replace(/{0}/gthemes[i]);
        }
        $(
themeList).appendTo(stgs.accentListContainer);
    },
    
appendBaseThemes: function (stgs) {
        if (
typeof (stgs) === "undefined" || stgs == null) {
            
stgs jQuery.fn.metrojs.theme.defaults;
        } else {
            var 
stg jQuery.fn.metrojs.theme.defaults;
            
stgs jQuery.extend({}, stgstgs);
        }
        var 
themeList "",
            
themes stgs.baseThemes,
            
template stgs.baseThemeListTemplate;
        for (var 
0themes.lengthi++) {
            
themeList += template.replace(/{0}/gthemes[i]);
        }
        $(
themeList).appendTo(stgs.baseThemeListContainer);
    },
    
// default options for 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''blue''brown''cobalt''crimson''cyan',
             
'magenta''lime''indigo''green''emerald',
             
'mango''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"ul.theme-options,.theme-options>ul",                   // selector of container to append accents
        
baseThemeListTemplate"<li><a href='javascript:;' title='{0}' class='accent {0}'></a></li>"// template to generate accent options
        
baseThemeListContainer"ul.base-theme-options,.base-theme-options>ul"                    // 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(stgsjQuery.fn.applicationBar.defaultsoptions);
    if (
typeof (jQuery.fn.metrojs.theme) != "undefined") {
        var 
theme jQuery.fn.metrojs.theme;
        if (
stgs.shouldApplyTheme) {         
            
theme.loadDefaultTheme(stgs);
        }
        var 
themeContainer stgs.accentListContainer.replace(","" a,") + " a";
        var 
themeContainerClick = function () {
            var 
accent jQuery(this).attr("class").replace("accent""").replace(" """);
            
theme.applyTheme(nullaccentstgs);
            if (
typeof (stgs.accentPicked) == "function")
                
stgs.accentPicked(accent);
        };
        var 
baseContainer stgs.baseThemeListContainer.replace(","," a,") + " a";
        var 
baseContainerClick = function () {
            var 
accent jQuery(this).attr("class").replace("accent"'').replace(' ''');
            
theme.applyTheme(accentnullstgs);
            if (
typeof (stgs.themePicked) == "function")
                
stgs.themePicked(accent);
        };
        if (
typeof ($.fn.on) === "function") {
            $(
this).on("click.appBar"themeContainerthemeContainerClick);
            $(
this).on("click.appBar"baseContainerbaseContainerClick);
        } else {
            $(
themeContainer).live("click.appBar"themeContainerClick);
            $(
baseContainer).live("click.appBar"baseContainerClick);
        }
    }
    
//this should really only run once but we can support multiple application bars
    
return $(this).each(function (idxele) {
        var 
$this = $(ele),
            
data = $.extend({}, stgs);
        if(
data.collapseHeight == "auto")
            
data.collapseHeight = $(this).outerHeight();

        
//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
        //todo: find/come up with a better fixed position test
        
if (navigator.userAgent.match(/(Android|webOS|iPhone|iPod|BlackBerry|PIE|IEMobile)/i)) {
            
// IEMobile10 supports position:fixed. This should cover up to IE20 or at least until fixed positioning gets sorted            
            // let iOS 5+ pass as well, hopefully by iOS 9 fixed pos will be standard :/
            
if (!navigator.userAgent.match(/(IEMobile/1)/i) && !navigator.userAgent.match(/(iPhone OS [56789])/i)) {
                
$this.css({ position'absolute'bottom'0px' });
            }
        }
        
data.slideOpen = function () {
            if (!
$this.hasClass("expanded"))
                
data.animateAppBar(false);
        };
        
data.slideClosed = function () {
            if (
$this.hasClass("expanded"))
                
data.animateAppBar(true);
        };
        
data.animateAppBar = function (isExpanded) {
            var 
hgt isExpanded data.collapseHeight data.expandHeight;
            if (
isExpanded)
                
$this.removeClass("expanded");
            else
                if (!
$this.hasClass("expanded"))
                    
$this.addClass("expanded");
            
$this.stop().animate({ heighthgt }, { durationdata.duration });
        };
        
$this.data("ApplicationBar"data)

        
$this.find(stgs.handleSelector).click(function () {
            
data.animateAppBar($this.hasClass("expanded"));
        });

        if (
data.bindKeyboard == true) {
            
jQuery(document.documentElement).keyup(function (event) {
                
// handle cursor keys
                
if (event.keyCode == 38) {
                    
// expand
                    
if (event.target && event.target.tagName.match(/INPUT|TEXTAREA|SELECT/i) == null) {
                        if (!
$this.hasClass("expanded")) {
                            
data.animateAppBar(false);
                        }
                    }
                    
                } else if (
event.keyCode == 40) {
                    
// collapse
                    
if (event.target && event.target.tagName.match(/INPUT|TEXTAREA|SELECT/i) == null) {
                        if (
$this.hasClass("expanded")) {
                            
data.animateAppBar(true);
                        }
                    }
                }
            });            
        }
    });
};

// default options for applicationBar, the theme defaults are merged with this object when the applicationBar function is called
jQuery.fn.applicationBar.defaults = {
    
applyThemetrue,                                       // 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 (tColoraColor) { },                  // called if applyTheme is true onload when a theme has been loaded from local storage or overridden by options
    
duration300,                                          // how fast should animation be performed, in milliseconds
    
expandHeight"320px",                                  // height the application bar to expand to when opened
    
collapseHeight"auto",                                 // height the application bar will collapse back to when closed
    
bindKeyboardtrue,                                     // should up and down keys on keyborad be bound to the application bar
    
handleSelector"a.etc",
    
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)
    
preloadAltBaseThemefalse                             // should the applicationBar icons be pre loaded for the alternate theme to enable fast theme switching    
};
/* Preload Images */
// Usage: jQuery(['img1.jpg', { src: 'img2.jpg' }]).metrojs.preloadImages(function(){ ... });
// Callback function gets called after all images are preloaded
$.fn.metrojs.preloadImages = function (callback) {
        var 
checklist = $(this).toArray();
        var 
$img = $("<img style='display:none;' />").appendTo("body");
        $(
this).each(function () {
                var 
src this;
                if (
typeof(this) == "object")
                        
src this.src;
                
$img.attr({ srcsrc }).load(function() {
                        for (var 
0checklist.lengthi++) {
                                if (
checklist[i] == element) {
                                        
checklist.splice(i1);
                                }
                        }
                        if (
checklist.length == 0) {
                                
callback();
                        }
                });
               
        });
    
$img.remove();
};
// object used for compatibility checks
$.fn.metrojs.MetroModernizr = function (stgs) {
    if(
typeof(stgs) === "undefined") {
                
stgs = { useHardwareAcceltrueuseModernizrtypeof(window.Modernizr) !== "undefined" };
        }
    
this.isOldJQuery =  /^1.[0123]/.test($.fn.jquery),
    
this.isOldAndroid = (function(){
        try{
            var 
ua navigator.userAgent;        
            if( 
ua.indexOf("Android") >= )
            {
                var 
androidversion parseFloat(ua.slice(ua.indexOf("Android")+8));
                if (
androidversion 2.3)
                    return 
true;
            }
        }catch(
err){ $.error(err); }
        return 
false;
    })();
    
this.canTransform false;
    
this.canTransition false;
    
this.canTransform3d false;
    
this.canAnimate false;
    
this.canTouch false;
    
this.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") {
                
this.canTransform window.MetroModernizr.canTransform;
                
this.canTransition window.MetroModernizr.canTransition;
                
this.canTransform3d window.MetroModernizr.canTransform3d;
                
this.canAnimate window.MetroModernizr.canAnimate;
                
this.canTouch window.MetroModernizr.canTouch;
            } else {
                
window.MetroModernizr = {};
                
/***** check for browser capabilities credit: modernizr-1.7 http://modernizr.com/ *****/
                
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- '.split(' ');
                var 
domPrefixes 'Webkit Moz O ms Khtml'.split(' ');
                var 
test_props = function (propscallback) {
                    for (var 
i in props) {
                        if (
m_style[props[i]] !== undefined && (!callback || callback(props[i], modElem))) {
                            return 
true;
                        }
                    }
                };
                var 
test_props_all = function (propcallback) {
                    var 
uc_prop prop.charAt(0).toUpperCase() + prop.substr(1),
                    
props = (prop ' ' domPrefixes.join(uc_prop ' ') + uc_prop).split(' ');
                    return !!
test_props(propscallback);
                };
                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),('),mod,')','{#metromodernizr{left:9px;position:absolute;height:3px;}}'].join(''), function(div){
                            return 
div.offsetHeight === && div.offsetLeft === 9;
                        });
                    }
                    return 
ret;
                };
                var 
testMediaQuery = function (mqpredicate) {
                    var 
st document.createElement('style'),
                        
div document.createElement('div'),
                        
ret;
                    
st.textContent mq;
                    
docHead.appendChild(st);
                    
div.id mod;
                    
docElement.appendChild(div);
                    
ret predicate(div);
                    
st.parentNode.removeChild(st);
                    
div.parentNode.removeChild(div);
                    return !!
ret;
                };
                var 
test_touch = function() {
                    return 
canTouch = ('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch ||
                        (
typeof(window.navigator.msMaxTouchPoints) !== "undefined" && window.navigator.msMaxTouchPoints 0) ||
                        
testMediaQuery(['@media (',prefixes.join('touch-enabled),('),mod,')','{#metromodernizr{top:9px;position:absolute}}'].join(''), function(div){
                            return 
div.offsetTop === 9;
                        });
                };
                
this.canTransform = !!test_props(['transformProperty''WebkitTransform''MozTransform''OTransform''msTransform']);
                
this.canTransition test_props_all('transitionProperty');
                
this.canTransform3d test_3d();
                
this.canAnimate test_props_all('animationName');
                
this.canTouch test_touch();
                
window.MetroModernizr.canTransform this.canTransform;
                
window.MetroModernizr.canTransition this.canTransition;
                
window.MetroModernizr.canTransform3d this.canTransform3d;
                
window.MetroModernizr.canAnimate this.canAnimate;
                
window.MetroModernizr.canTouch this.canTouch;
                
docElement null;
                
docHead null;
                
modElem null;
                
m_style null;
            }
        } else {
            
this.canTransform = $("html").hasClass("csstransforms");
            
this.canTransition = $("html").hasClass("csstransitions");
            
this.canTransform3d = $("html").hasClass("csstransforms3d");
            
this.canAnimate = $("html").hasClass("cssanimations");
            
this.canTouch = $("html").hasClass("touch") || (typeof(window.navigator.msMaxTouchPoints) !== "undefined" && window.navigator.msMaxTouchPoints 0);
        }
    }
    
this.canFlip3d this.canFlip3d && this.canAnimate && this.canTransform && this.canTransform3d;
};

})(
jQuery);
?>
Онлайн: 0
Реклама