blob: 870d63c0f456eb389a32f74257a04adfbacb3ccd [file] [log] [blame]
/*
* Metro JS for jQuery
* http://drewgreenwell.com/
* For details and usage info see: http://drewgreenwell.com/projects/metrojs
Copyright (C) 2012, Drew Greenwell
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
(function () {
jQuery.fn.metrojs = {};
/* Preload Images */
// Usage: jQuery(['img1.jpg','img2.jpg']).metrojs.preloadImages(function(){ ... });
// Callback function gets called after all images are preloaded
jQuery.fn.metrojs.preloadImages = function (callback) {
var checklist = jQuery(this).toArray();
var $img = jQuery("<img style='display:none;'>").appendTo("body");
jQuery(this).each(function () {
$img.attr({ src: this }).load(function () {
var src = jQuery(this).attr('src');
for (var i = 0; i < checklist.length; i++) {
if (checklist[i] == element) { checklist.splice(i, 1); }
}
if (checklist.length == 0) { callback(); }
});
});
$img.remove();
}; jQuery.fn.liveTile = function (method) {
if (pubMethods[method]) {
var args = [];
for (var i = 1; i <= arguments.length; i++) {
args[i - 1] = arguments[i];
}
return pubMethods[method].apply(this, args);
} else if (typeof method === 'object' || !method) {
return pubMethods.init.apply(this, arguments);
} else {
jQuery.error('Method ' + method + ' does not exist on jQuery.liveTile');
}
};
jQuery.fn.liveTile.State = {
RUNNING: "running",
STOPPED: "stopped"
};
jQuery.fn.liveTile.defaults = {
mode: 'slide', // 'slide', 'flip', 'flip-list'
speed: 500, // how fast should animations be performed, in milliseconds
initDelay: -1, // how long to wait before the initial animation
delay: 5000, // how long to wait between animations
stops: "100%", // how much of the back tile should 'slide' reveal before starting a delay
stack: false, // should tiles in slide mode appear stacked (e.g Me tile)
direction: 'vertical', // which direction should animations be performed(horizontal | vertical)
tileCssSelector: '>div,>li', // The selector used by slide, flip, and flip-list mode to choose the front and back containers
listTileCssSelector: '>div,>p,>img,>a', // The selector used by flip-tile mode to choose the front and back containers.2
imageCssSelector: '>img,>a>img', // the selector used to choose a an image to apply a src or background to
ignoreDataAttributes: false, // should data attributes be ignored
pauseOnHover: false, // should tile animations be paused on hover in and restarted on hover out
repeatCount: -1, // number of times to repeat the animation
animationComplete: function (tileData, $front, $back) {
},
preloadImages: false, // should the images arrays be preloaded
fadeSlideSwap: false, // fade any image swaps on slides (e.g. mode: 'slide', stops:'50%', frontImages: ['img1.jpg', 'img2.jpg'])
appendBack: true, // appends the .last tile if one doesnt exist (slide and flip only)
triggerDelay: function (idx) { // used by flip-list to decide how random the tile flipping should be
return Math.random() * 3000;
},
alwaysTrigger: false, // used by flip-list to decide if all tiles are triggered every time
frontImages: null, // a list of images to use for the front
frontIsRandom: true, // should images be chosen at random or in order
frontIsBackgroundImage: false, // set the src attribute or css background-image property
frontIsInGrid: false, // only chooses one item for each iteration in flip-list
backImages: null, // a list of images to use for the back
backIsRandom: true, // should images be chosen at random or in order
backIsBackgroundImage: false, // set the src attribute or css background-image property
backIsInInGrid: false, // only chooses one item for each iteration in flip-list
flipListOnHover: false, // should items in flip-list flip and stop when hovered
useModernizr: (typeof (window.Modernizr) != "undefined"), // checks to see if modernizer is already in use
useHardwareAccel: true, // should css animations, transitions and transforms be used when available
$front: null, // the jQuery element to use as the front face of the tile; this will bypass tileCssSelector
$back: null // the jQuery element to use as the back face of the tile; this will bypass tileCssSelector
};
var privMethods = {
//a shuffle method to provide more randomness than sort
//credit: http://javascript.about.com/library/blshuffle.htm
//*avoiding prototype for sharepoint compatability
shuffleArray: function (array) {
var s = [];
while (array.length) s.push(array.splice(Math.random() * array.length, 1));
while (s.length) array.push(s.pop());
return array;
},
setTimer: function (func, interval) {
return setInterval(func, interval);
},
stopTimer: function (handle) {
clearInterval(handle);
return null;
},
setExtraProperties: function ($ele, imageObj) {
if (typeof (imageObj.alt) != "undefined")
$ele.attr("alt", imageObj.alt);
var $parent = $ele.parent();
if (typeof (imageObj.href) != "undefined" && $parent[0].tagName == "A") {
$parent.attr("href", imageObj.href);
if (typeof (imageObj.target) != "undefined")
$parent.attr("target", imageObj.target);
if (typeof (imageObj.onclick) != "undefined") {
$parent.attr("onclick", imageObj.onclick);
$ele.attr("onclick", "");
}
} else {
if (typeof (imageObj.onclick) != "undefined")
$ele.attr("onclick", imageObj.onclick);
}
},
// changes the src or background image property of an image in a flip-list
handleListItemSwap: function ($cont, image, isBgroundImg, stgs) {
var $img = $cont.find(stgs.imageCssSelector);
if (!isBgroundImg) {
$img.attr("src", image.src);
} else {
$img.css({ backgroundImage: "url('" + image.src + "')" });
}
privMethods.setExtraProperties($img, image);
},
handleSlide: function (isSlidingUp, $cont, swapFrontSource, stgs, index) {
if (!isSlidingUp && swapFrontSource) {
var image;
var $img = $cont.find(stgs.imageCssSelector);
image = stgs.frontImages[index];
if (stgs.fadeSlideSwap == true) {
$img.fadeOut(function () {
$img.attr("src", image.src);
privMethods.setExtraProperties($img, image);
$img.fadeIn();
});
} else {
$img.attr("src", image.src);
privMethods.setExtraProperties($img, image);
}
}
},
// fired if an image swap is needed. gets the image and applies properties
handleSwap: function ($cont, isFront, stgs, index) {
var image = privMethods.getImage(isFront, stgs, index);
var $img = $cont.find(stgs.imageCssSelector);
$img.attr("src", image.src);
privMethods.setExtraProperties($img, image);
},
// get an image from the frontImages or backImages array
getImage: function (isFront, stgs, index) {
var imgs = (isFront) ? stgs.frontImages : stgs.backImages;
var image;
image = imgs[Math.min(index, imgs.length - 1)];
return image;
}
};
var pubMethods = {
init: function (options) {
// Setup the public options for the livetile
var stgs = {};
jQuery.extend(stgs, jQuery.fn.liveTile.defaults, options);
//is there at least one item in the front images list?
var swapFrontSource = (typeof (stgs.frontImages) == 'object' && (stgs.frontImages instanceof Array) && stgs.frontImages.length > 0);
//is there at least one item in the back images list?
var swapBackSource = (typeof (stgs.backImages) == 'object' && (stgs.backImages instanceof Array) && stgs.backImages.length > 0);
var canTransform = false;
var canTransition = false;
var canTransform3d = false;
var canAnimate = false;
var canFlip3d = stgs.useHardwareAccel;
if (stgs.useHardwareAccel == true) {
if (stgs.useModernizr == false) {
//determine if the browser supports the neccessary accelerated features
if (typeof (window.MetroModernizr) != "undefined") {
canTransform = window.MetroModernizr.canTransform;
canTransition = window.MetroModernizr.canTransition;
canTransform3d = window.MetroModernizr.canTransform3d;
canAnimate = window.MetroModernizr.canAnimate;
} else {
window.MetroModernizr = {};
/***** check for browser capabilities credit: modernizr-1.7 *****/
var mod = 'metromodernizr';
var docElement = document.documentElement;
var docHead = document.head || document.getElementsByTagName('head')[0];
var modElem = document.createElement(mod);
var m_style = modElem.style;
var prefixes = ' -webkit- -moz- -o- -ms- -khtml- '.split(' ');
var domPrefixes = 'Webkit Moz O ms Khtml'.split(' ');
var test_props = function (props, callback) {
for (var i in props) {
if (m_style[props[i]] !== undefined && (!callback || callback(props[i], modElem))) {
return true;
}
}
};
var test_props_all = function (prop, callback) {
var uc_prop = prop.charAt(0).toUpperCase() + prop.substr(1),
props = (prop + ' ' + domPrefixes.join(uc_prop + ' ') + uc_prop).split(' ');
return !!test_props(props, callback);
};
var test_3d = function () {
var ret = !!test_props(['perspectiveProperty', 'WebkitPerspective', 'MozPerspective', 'OPerspective', 'msPerspective']);
if (ret && 'webkitPerspective' in docElement.style) {
// Webkit allows this media query to succeed only if the feature is enabled.
// '@media (transform-3d),(-o-transform-3d),(-moz-transform-3d),(-ms-transform-3d),(-webkit-transform-3d),(modernizr){ ... }'
ret = testMediaQuery('@media (' + prefixes.join('transform-3d),(') + 'metromodernizr)');
}
return ret;
};
var testMediaQuery = function (mq) {
var st = document.createElement('style'),
div = document.createElement('div'),
ret;
st.textContent = mq + '{#metromodernizr{height:3px}}';
docHead.appendChild(st);
div.id = 'metromodernizr';
docElement.appendChild(div);
ret = div.offsetHeight === 3;
st.parentNode.removeChild(st);
div.parentNode.removeChild(div);
return !!ret;
};
canTransform = !!test_props(['transformProperty', 'WebkitTransform', 'MozTransform', 'OTransform', 'msTransform']);
canTransition = test_props_all('transitionProperty');
canTransform3d = test_3d();
canAnimate = test_props_all('animationName');
window.MetroModernizr.canTransform = canTransform;
window.MetroModernizr.canTransition = canTransition;
window.MetroModernizr.canTransform3d = canTransform3d;
window.MetroModernizr.canAnimate = canAnimate;
docElement = null;
docHead = null;
modElem = null;
m_style = null;
}
} else {
canTransform = jQuery("html").hasClass("csstransforms");
canTransition = jQuery("html").hasClass("csstransitions");
canTransform3d = jQuery("html").hasClass("csstransforms3d");
canAnimate = jQuery("html").hasClass("cssanimations");
}
}
canFlip3d = canFlip3d && canAnimate && canTransform && canTransform3d;
/****** end capabilities check ******/
if (stgs.preloadImages) {
if (swapFrontSource)
jQuery(stgs.frontImages).metrojs.preloadImages(function () { });
if (swapBackSource)
jQuery(stgs.backImages).metrojs.preloadImages(function () { });
}
return jQuery(this).each(function (tileIndex) {
var $this = jQuery(this);
$this.slideTimer = null;
var tdata = {}; //an object to store settings for later access
tdata.state = $this.slideTimer == null ? jQuery.fn.liveTile.State.STOPPED : jQuery.fn.liveTile.State.RUNNING;
tdata.speed = (!stgs.ignoreDataAttributes && typeof ($this.data("speed")) != "undefined") ? $this.data("speed") : stgs.speed;
tdata.delay = (!stgs.ignoreDataAttributes && typeof ($this.data("delay")) != "undefined") ? $this.data("delay") : stgs.delay;
if (tdata.delay < -1)
tdata.delay = stgs.triggerDelay(tileIndex);
else if (tdata.delay < 0)
tdata.delay = 3500 + (Math.random() * 4501);
tdata.stops = (!stgs.ignoreDataAttributes && typeof ($this.data("stops")) != "undefined") ? $this.data("stops") : stgs.stops;
tdata.stack = (!stgs.ignoreDataAttributes && typeof ($this.data("stack")) != "undefined") ? $this.data("stack") : stgs.mode;
tdata.mode = (!stgs.ignoreDataAttributes && typeof ($this.data("mode")) != "undefined") ? $this.data("mode") : stgs.mode;
tdata.direction = (!stgs.ignoreDataAttributes && typeof ($this.data("direction")) != "undefined") ? $this.data("direction") : stgs.direction;
tdata.useHwAccel = (!stgs.ignoreDataAttributes && typeof ($this.data("ha")) != "undefined") ? $this.data("ha") : stgs.useHardwareAccel;
tdata.initDelay = (!stgs.ignoreDataAttributes && typeof ($this.data("initdelay")) != "undefined") ? $this.data("initdelay") : (stgs.initDelay < 0) ? tdata.delay : stgs.initDelay;
tdata.repeatCount = (!stgs.ignoreDataAttributes && typeof ($this.data("repeat")) != "undefined") ? $this.data("repeat") : stgs.repeatCount;
tdata.hasRun = false; // init delay flag
tdata.isReversed = false;
tdata.loopCount = 0;
tdata.slideIndex = 0;
//convert stops if needed
tdata.stops = (typeof (stgs.stops) == 'object' && (stgs.stops instanceof Array)) ? stgs.stops : ('' + tdata.stops).split(',');
//add the mode to the tile if it's not already there.
$this.addClass(tdata.mode);
var $tileContainer = $this.find(stgs.tileCssSelector);
var $firstContainer = null;
if (stgs.$front != null && stgs.$front.length > 0) {
$firstContainer = (tdata.mode == "flip-list") ? null : (tdata.mode == 'slide') ?
stgs.$front.addClass('slide-front') :
stgs.$front.addClass('flip-front');
} else {
$firstContainer = (tdata.mode == "flip-list") ? null : (tdata.mode == 'slide') ?
$tileContainer.first().addClass('slide-front') :
$tileContainer.first().addClass('flip-front');
}
var lClass = (tdata.mode == 'slide') ? 'slide-back' : 'flip-back';
var $scndContainer = null;
if (stgs.$back != null && stgs.$back.length > 0) {
$scndContainer = (tdata.mode == "flip-list") ? null : stgs.$back.addClass(lClass);
} else {
$scndContainer = (tdata.mode == "flip-list") ? null : ($tileContainer.length > 1) ?
$tileContainer.last().addClass(lClass) :
(stgs.appendBack == true) ?
jQuery('<div class="' + lClass + '"></div>').appendTo($this) :
jQuery('<div></div>');
}
var height = $this.height();
var width = $this.width();
var margin = (tdata.direction == "vertical") ? height / 2 : width / 2;
var staticCount = 0;
var staticIndexBack = 0;
var staticIndexFront = 0;
var doAnimations = false;
var flistData = []; // an array to cache flip list selectors
var frontRandomBag = [];
var prevFrontIndex = -1;
var backRandomBag = [];
var prevBackIndex = -1;
/* Mouse over and out functions*/
if (stgs.pauseOnHover) {
$this.find(stgs.tileCssSelector).hover(
function () {
tdata.stopTimer(false);
},
function () {
tdata.setTimer();
});
}
// prep tiles
if (tdata.mode == 'flip-list') {
$this.find(stgs.tileCssSelector).each(function () {
var $li = jQuery(this);
var $front = stgs.$front != null ? stgs.$front : $li.find(stgs.listTileCssSelector).first().addClass("flip-front");
if ($li.find(stgs.listTileCssSelector).length == 1 && stgs.appendBack == true) {
$li.append("<div></div>");
}
var $back = stgs.$back != null ? stgs.$back : $li.find(stgs.listTileCssSelector).last().addClass("flip-back").css({ marginTop: "0px" });
if (canFlip3d && tdata.useHwAccel) {
$li.addClass("ha");
$front.addClass("ha").data("tile", { animating: false });
$back.addClass("ha").data("tile", { animating: false });
if (stgs.flipListOnHover == true) {
$front.bind("mouseout.liveTile", null, function () {
$this.flipListItem(false, $li, $back, $front);
});
$back.bind("mouseout.liveTile", null, function () {
$this.flipListItem(true, $li, $front, $back);
});
}
} else {
if (stgs.flipListOnHover == true) {
$front.bind("mouseout.liveTile", function () {
$this.flipListItem(true, $li, $front, $back);
});
$back.bind("mouseout.liveTile", function () {
$this.flipListItem(false, $li, $back, $front);
});
}
}
});
} else if (tdata.mode == 'slide') {
if (tdata.stack == true) {
if (tdata.direction == "vertical") {
$scndContainer.css({ top: -height + 'px' });
} else {
$scndContainer.css({ left: -width + 'px' });
}
}
if (canTransition && tdata.useHwAccel) {
$this.addClass("ha");
$firstContainer.addClass("ha").data("tile", { animating: false });
}
} else if (tdata.mode == 'flip') {
if (canFlip3d && tdata.useHwAccel) {
$this.addClass("ha");
$firstContainer.addClass("ha").data("tile", { animating: false });
$scndContainer.addClass("ha").data("tile", { animating: false });
} else {
var fCss = (tdata.direction == "vertical") ?
{ height: '0px', width: width + 'px', marginTop: margin + 'px', opacity: '0'} :
{ height: '100%', width: '0px !important', marginLeft: margin + 'px', opacity: '0' };
var fCss2 = (tdata.direction == "vertical") ?
{ height: '100%', width: '100%', marginTop: '0px', opacity: '1'} :
{ height: '100%', width: '100%', marginLeft: '0px', opacity: '1' };
$scndContainer.css(fCss);
$firstContainer.css(fCss2);
//temp fix
// TODO: debug and remove instances of jQuery.browser for compatibility with jq 1.8+
if (tdata.repeatCount > -1 && jQuery.browser.msie) {
tdata.repeatCount += 1;
}
// if (tdata.direction == "horizontal")
// $scndContainer.css({ marginLeft: $scndContainer.width() / 2 + 'px', width: '0px' });
// else
// $scndContainer.css({ marginTop: $scndContainer.height() / 2 + 'px', height: '0px' });
}
}
//slide animation
$this.slide = function (callback) {
if (typeof (callback) == "undefined" || callback == null)
callback = null;
if (tdata.repeatCount > -1) {
if (tdata.loopCount > tdata.repeatCount) {
tdata.stopTimer(false);
tdata.loopCount = 0;
tdata.hasRun = false;
$this.data("LiveTile", tdata);
return;
}
}
if (!doAnimations)
return;
var clojIsReversed = tdata.isReversed;
var fData = $firstContainer.data("tile");
var stop = jQuery.trim(tdata.stops[tdata.slideIndex]);
var pxIdx = stop.indexOf('px');
var offset = 0;
var amount = 0
var metric = (tdata.direction == "vertical") ? height : width;
var prop = (tdata.direction == "vertical") ? "top" : "left";
if (pxIdx > 0) {
amount = parseInt(stop.substring(0, pxIdx));
offset = (amount - metric) + 'px';
} else {
//is a percentage
amount = parseInt(stop.replace('%', ''));
offset = (amount - 100) + '%';
}
if (canTransition && tdata.useHwAccel) {
if (typeof (fData.animated) != "undefined" && fData.animated == true)
return;
fData.animated = true;
var css = {
WebkitTransitionProperty: prop, WebkitTransitionDuration: tdata.speed + 'ms',
MozTransitionProperty: prop, MozTransitionDuration: tdata.speed + 'ms',
OTransitionProperty: prop, OTransitionDuration: tdata.speed + 'ms',
msTransitionProperty: prop, msTransitionDuration: tdata.speed + 'ms',
KhtmlTransitionProperty: prop, KhtmlTransitionDuration: tdata.speed + 'ms',
TransitionProperty: prop, TransitionDuration: tdata.speed + 'ms'
};
if (tdata.direction == "vertical") {
css.top = (clojIsReversed && tdata.stops.length == 1) ? "0px" : stop;
} else {
css.left = (clojIsReversed && tdata.stops.length == 1) ? "0px" : stop;
}
$firstContainer.css(css);
if (tdata.stack == true) {
if (tdata.direction == "vertical") {
css.top = (clojIsReversed && tdata.stops.length == 1) ? -metric + 'px' : offset;
} else {
css.left = (clojIsReversed && tdata.stops.length == 1) ? -metric + 'px' : offset;
}
$scndContainer.css(css);
}
window.setTimeout(function () {
var index = staticCount;
if (swapFrontSource && stgs.frontIsRandom) {
//make sure the random bag is ready
if (frontRandomBag.length == 0) {
for (var i = 0; i < stgs.frontImages.length; i++) {
//make sure there's not an immediate repeat
if (i != prevBackIndex || stgs.frontImages.length == 1)
frontRandomBag[i] = i;
}
frontRandomBag = privMethods.shuffleArray(frontRandomBag);
}
index = frontRandomBag.pop();
prevFrontIndex = index;
}
privMethods.handleSlide(clojIsReversed, $firstContainer, swapFrontSource, stgs, index);
fData.animated = false;
$firstContainer.data("tile", fData);
if (!clojIsReversed && swapFrontSource) {
staticCount += 1;
if (staticCount >= stgs.frontImages.length)
staticCount = 0;
}
stgs.animationComplete(tdata, $firstContainer, $scndContainer);
if (callback != null)
callback();
}, tdata.speed);
} else {
if ($firstContainer.is(':animated')) {
return;
}
var uCss = (tdata.direction == "vertical") ?
{ top: (clojIsReversed && tdata.stops.length == 1) ? "0px" : stop} :
{ left: (clojIsReversed && tdata.stops.length == 1) ? "0px" : stop };
var dCss = (tdata.direction == "vertical") ?
{ top: (clojIsReversed && tdata.stops.length == 1) ? -metric + 'px' : offset} :
{ left: (clojIsReversed && tdata.stops.length == 1) ? -metric + 'px' : offset };
$firstContainer.animate(uCss, tdata.speed, function () {
var index = staticCount;
if (swapFrontSource && stgs.frontIsRandom) {
//make sure the random bag is ready
if (frontRandomBag.length == 0) {
for (var i = 0; i < stgs.frontImages.length; i++) {
//make sure there's not an immediate repeat
if (i != prevBackIndex || stgs.frontImages.length == 1)
frontRandomBag[i] = i;
}
frontRandomBag = privMethods.shuffleArray(frontRandomBag);
}
index = frontRandomBag.pop();
prevFrontIndex = index;
}
privMethods.handleSlide(clojIsReversed, $firstContainer, swapFrontSource, stgs, index);
if (!clojIsReversed && swapFrontSource) {
staticCount += 1;
if (staticCount >= stgs.frontImages.length)
staticCount = 0;
}
stgs.animationComplete(tdata, $firstContainer, $scndContainer);
if (callback != null)
callback();
});
if (tdata.stack == true) {
$scndContainer.animate(dCss, tdata.speed, function () { });
}
}
//increment slide count
tdata.slideIndex += 1;
if (tdata.slideIndex >= tdata.stops.length) {
tdata.slideIndex = 0;
tdata.isReversed = !tdata.isReversed;
tdata.loopCount += 1;
}
};
//flip mode
$this.flip = function (callback) {
if (typeof (callback) == "undefined" || callback == null)
callback = null;
if (tdata.repeatCount > -1) {
if (tdata.loopCount > tdata.repeatCount) {
tdata.stopTimer(false);
tdata.loopCount = 0;
// TODO: debug and remove instances of jQuery.browser for compatibility with jq 1.8+
if (jQuery.browser.msie) /* straighten out issue with loopcount in IE */
tdata.loopCount += 1;
tdata.hasRun = false;
$this.data("LiveTile", tdata);
return;
} else {
tdata.loopCount += 1;
}
}
if (canFlip3d && tdata.useHwAccel) {
var spd = (tdata.speed * 2); // accelerated flip speeds are calculated on 1/2 rotation rather than 1/4 rotation like jQuery animate
var duration = spd + 'ms';
var aniFName = (tdata.direction == "vertical") ? 'flipfront180' : 'flipfrontY180';
var aniBName = (tdata.direction == "vertical") ? 'flipback180' : 'flipbackY180';
var data = $firstContainer.data("tile");
if (typeof (data.animated) != "undefined" && data.animated == true) {
return;
}
data.animated = true;
if (doAnimations) {
if (tdata.isReversed) {
var uCss = {
WebkitAnimationPlayState: 'running', WebkitAnimationName: aniBName, WebkitAnimationDuration: duration,
MozAnimationPlayState: 'running', MozAnimationName: aniBName, MozAnimationDuration: duration,
OAnimationPlayState: 'running', OAnimationName: aniBName, OAnimationDuration: duration,
msAnimationPlayState: 'running', msAnimationName: aniBName, msAnimationDuration: duration,
AnimationPlayState: 'running', AnimationName: aniBName, AnimationDuration: duration
};
$firstContainer.css(uCss).data("tile", data);
uCss.WebkitAnimationName = aniFName;
uCss.MozAnimationName = aniFName;
uCss.msAnimationName = aniFName;
uCss.OAnimationName = aniFName;
uCss.AnimationName = aniFName;
$scndContainer.css(uCss).data("tile", data);
window.setTimeout(function () {
if (swapBackSource) { // change the source image when the animation is finished
var isRandom = stgs.backIsRandom;
var index = staticIndexBack;
if (isRandom) {
//make sure the random bag is ready
if (backRandomBag.length == 0) {
for (var i = 0; i < stgs.backImages.length; i++) {
//make sure there's not an immediate repeat
if (i != prevBackIndex || stgs.backImages.length == 1)
backRandomBag[i] = i;
}
backRandomBag = privMethods.shuffleArray(backRandomBag);
}
index = backRandomBag.pop();
prevBackIndex = index;
}
privMethods.handleSwap($scndContainer, false, stgs, index);
staticIndexBack += 1;
if (staticIndexBack >= stgs.backImages.length) {
staticIndexBack = 0;
}
}
stgs.animationComplete(tdata, $firstContainer, $scndContainer);
if (callback != null)
callback();
data.animated = false;
$firstContainer.data("tile", data);
$scndContainer.data("tile", data);
}, spd);
} else {
var dCss = { WebkitAnimationPlayState: 'running', WebkitAnimationName: aniFName, WebkitAnimationDuration: duration,
MozAnimationPlayState: 'running', MozAnimationName: aniFName, MozAnimationDuration: duration,
OAnimationPlayState: 'running', OAnimationName: aniFName, OAnimationDuration: duration,
msAnimationPlayState: 'running', msAnimationName: aniFName, msAnimationDuration: duration,
AnimationPlayState: 'running', AnimationName: aniFName, AnimationDuration: duration
};
$firstContainer.css(dCss).data("tile", data);
dCss.WebkitAnimationName = aniBName;
dCss.MozAnimationName = aniBName;
dCss.msAnimationName = aniBName;
dCss.OAnimationName = aniBName;
dCss.AnimationName = aniBName;
$scndContainer.css(dCss).data("tile", data);
window.setTimeout(function () {
if (swapFrontSource) {
// change the source image when the animation is finished
var isRandom = stgs.frontIsRandom;
var index = staticIndexFront;
if (isRandom) {
//make sure the random bag is ready
if (frontRandomBag.length == 0) {
for (var i = 0; i < stgs.frontImages.length; i++) {
//make sure there's not an immediate repeat
if (i != prevBackIndex || stgs.frontImages.length == 1)
frontRandomBag[i] = i;
}
frontRandomBag = privMethods.shuffleArray(frontRandomBag);
}
index = frontRandomBag.pop();
prevFrontIndex = index;
}
privMethods.handleSwap($firstContainer, true, stgs, index);
staticIndexFront += 1;
if (staticIndexFront >= stgs.frontImages.length) {
staticIndexFront = 0;
}
}
stgs.animationComplete(tdata, $scndContainer, $firstContainer);
if (callback != null) {
callback();
}
data.animated = false;
$firstContainer.data("tile", data);
$scndContainer.data("tile", data);
}, spd);
}
}
//an interval isnt needed
tdata.isReversed = !tdata.isReversed;
} else {
//crossbrowser single tile flip illusion (works best with images)
if (tdata.isReversed) {
var upCss = (tdata.direction == "vertical") ?
{ height: '0px', width: '100%', marginTop: margin + 'px', opacity: '0'} :
{ height: '100%', width: '0px', marginLeft: margin + 'px', opacity: '0' };
var upCss2 = (tdata.direction == "vertical") ?
{ height: '100%', width: '100%', marginTop: '0px', opacity: '1'} :
{ height: '100%', width: '100%', marginLeft: '0px', opacity: '1' };
$firstContainer.stop().animate(upCss, { duration: tdata.speed });
window.setTimeout(function () {
$scndContainer.stop().animate(upCss2, { duration: tdata.speed });
if (swapFrontSource) {
var isRandom = stgs.frontIsRandom;
var index = staticIndexFront;
if (isRandom) {
//make sure the random bag is ready
if (frontRandomBag.length == 0) {
for (var i = 0; i < stgs.frontImages.length; i++) {
//make sure there's not an immediate repeat
if (i != prevFrontIndex || stgs.frontImages.length == 1)
frontRandomBag[i] = i;
}
frontRandomBag = privMethods.shuffleArray(frontRandomBag);
}
index = frontRandomBag.pop();
prevFrontIndex = index;
}
privMethods.handleSwap($firstContainer, true, stgs, index);
staticIndexFront += 1;
if (staticIndexFront >= stgs.frontImages.length) {
staticIndexFront = 0;
}
}
tdata.isReversed = !tdata.isReversed;
stgs.animationComplete(tdata, $scndContainer, $firstContainer);
if (callback != null)
callback();
}, tdata.speed);
} else {
var dwnCss = (tdata.direction == "vertical") ?
{ height: '0px', width: '100%', marginTop: margin + 'px', opacity: '0'} :
{ height: '100%', width: '0px', marginLeft: margin + 'px', opacity: '0' };
var dwnCss2 = (tdata.direction == "vertical") ?
{ height: '100%', width: '100%', marginTop: '0px', opacity: '1'} :
{ height: '100%', width: '100%', marginLeft: '0px', opacity: '1' };
$scndContainer.stop().animate(dwnCss, { duration: tdata.speed });
window.setTimeout(function () {
$firstContainer.stop().animate(dwnCss2, { duration: tdata.speed });
if (swapBackSource) {
var isRandom = stgs.backIsRandom;
var index = staticIndexBack;
if (isRandom) {
//make sure the random bag is ready
if (backRandomBag.length == 0) {
for (var i = 0; i < stgs.backImages.length; i++) {
//make sure there's not an immediate repeat
if (i != prevBackIndex || stgs.backImages.length == 1)
backRandomBag[i] = i;
}
backRandomBag = privMethods.shuffleArray(backRandomBag);
}
index = backRandomBag.pop();
prevBackIndex = index;
}
privMethods.handleSwap($scndContainer, false, stgs, index);
staticIndexBack += 1;
if (staticIndexBack >= stgs.backImages.length) {
staticIndexBack = 0;
}
}
tdata.isReversed = !tdata.isReversed;
stgs.animationComplete(tdata, $firstContainer, $scndContainer);
if (callback != null)
callback();
}, tdata.speed);
}
}
};
// flip arbitrary number of items and swap sources accordingly
$this.flipList = function (callback) {
if (typeof (callback) == "undefined" || callback == null)
callback = null;
if (tdata.repeatCount > -1) {
if (tdata.loopCount > tdata.repeatCount) {
tdata.stopTimer(false);
tdata.loopCount = 0;
tdata.hasRun = false;
$this.data("LiveTile", tdata);
return;
} else {
tdata.loopCount += 1;
}
}
var fBag = []; // two bags to make sure we don't duplicate images
var bBag = [];
var $tiles = $this.find(stgs.tileCssSelector);
//in case we want to pick one image per loop
var fStaticRndm = 0;
if (swapFrontSource) {
if (frontRandomBag.length == 0) {
for (var i = 0; i < stgs.frontImages.length; i++) {
if (i != prevFrontIndex || stgs.frontImages.length == 1)
frontRandomBag[i] = i;
}
frontRandomBag = privMethods.shuffleArray(frontRandomBag);
}
fStaticRndm = frontRandomBag.pop();
prevFrontIndex = fStaticRndm;
}
var bStaticRndm = 0;
if (swapBackSource) {
if (backRandomBag.length == 0) {
for (var i = 0; i < stgs.backImages.length; i++) {
if (i != prevBackIndex || stgs.backImages.length == 1)
backRandomBag[i] = i;
}
backRandomBag = privMethods.shuffleArray(backRandomBag);
}
bStaticRndm = backRandomBag.pop();
prevBackIndex = bStaticRndm;
}
$tiles.each(function (idx) {
var $t = jQuery(this);
if (flistData.length < idx + 1) {
// cache the selector
var data = {};
data.$front = $t.find(stgs.listTileCssSelector).first();
data.$back = $t.find(stgs.listTileCssSelector).last();
data.isReversed = false;
flistData[idx] = data;
}
var $front = flistData[idx].$front;
var $back = flistData[idx].$back;
var tDelay = stgs.triggerDelay(idx);
var triggerSpeed = (tDelay > 0) ? (tdata.speed + tDelay) : tdata.speed;
var trigger = (!stgs.alwaysTrigger) ? ((Math.random() * 351) > 150 ? true : false) : true;
var newImage;
if (flistData[idx].isReversed) {
if (trigger && tDelay >= 0) {
window.setTimeout(function () {
flistData[idx].isReversed = false;
if (!swapFrontSource) {
$this.flipListItem(true, $t, $front, $back);
} else {
var isRandom = stgs.frontIsRandom;
var isInGrid = stgs.frontIsInGrid;
var isBground = stgs.frontIsBackgroundImage;
var frontImages = stgs.frontImages;
if (isRandom && !isInGrid) {
//make sure the random bag is ready
if (fBag.length == 0) {
for (var i = 0; i < stgs.frontImages.length; i++) {
fBag[i] = i;
}
fBag = privMethods.shuffleArray(fBag);
}
newImage = frontImages[fBag.pop()];
} else {
if (!isInGrid) {
newImage = frontImages[Math.min(idx, frontImages.length)];
} else {
newImage = frontImages[Math.min(fStaticRndm, frontImages.length)];
}
}
$this.flipListItem(true, $t, $front, $back, newImage, isBground);
}
}, triggerSpeed);
}
} else {
if (trigger && tDelay >= 0) {
window.setTimeout(function () {
flistData[idx].isReversed = true;
if (!swapBackSource) {
$this.flipListItem(false, $t, $back, $front);
} else {
var isRandom = stgs.backIsRandom;
var isInGrid = stgs.backIsInGrid;
var isBground = stgs.backIsBackgroundImage;
var backImages = stgs.backImages;
if (isRandom && !isInGrid) {
//make sure the random bag is ready
if (bBag.length == 0) {
for (var i = 0; i < stgs.backImages.length; i++) {
bBag[i] = i;
}
bBag = privMethods.shuffleArray(bBag);
}
newImage = backImages[bBag.pop()];
} else {
if (!isInGrid) {
newImage = backImages[Math.min(idx, backImages.length)];
} else {
newImage = backImages[Math.min(bStaticRndm, backImages.length)];
}
}
$this.flipListItem(false, $t, $back, $front, newImage, isBground);
}
}, triggerSpeed);
}
}
});
window.setTimeout(function () {
tdata.isReversed = !tdata.isReversed;
}, tdata.speed);
};
//does the actual animation of a flip list item
$this.flipListItem = function (isFront, $itm, $front, $back, newSrc, isBgroundImg) {
var dir = (!stgs.ignoreDataAttributes && typeof ($itm.data("direction")) != "undefined") ? $itm.data("direction") : tdata.direction;
if (canFlip3d && tdata.useHwAccel) {
// avoid any z-index flickering from reversing an animation too early
isBgroundImg = isFront ? stgs.frontIsBackgroundImage : stgs.backIsBackgroundImage;
var animating = isFront ? $front.data("tile").animating : $back.data("tile").animating;
if (animating == true) {
return;
}
var spd = (tdata.speed * 2);
var duration = spd + 'ms';
var aniFName = (dir == "vertical") ? 'flipfront180' : 'flipfrontY180';
var aniBName = (dir == "vertical") ? 'flipback180' : 'flipbackY180';
var fCss = {
WebkitAnimationPlayState: 'running', WebkitAnimationName: aniBName, WebkitAnimationDuration: duration,
MozAnimationPlayState: 'running', MozAnimationName: aniBName, MozAnimationDuration: duration,
msAnimationPlayState: 'running', msAnimationName: aniBName, msAnimationDuration: duration,
OAnimationPlayState: 'running', OAnimationName: aniBName, OAnimationDuration: duration,
AnimationPlayState: 'running', AnimationName: aniBName, AnimationDuration: duration
};
var bCss = {
WebkitAnimationPlayState: 'running', WebkitAnimationName: aniFName, WebkitAnimationDuration: duration,
MozAnimationPlayState: 'running', MozAnimationName: aniFName, MozAnimationDuration: duration,
msAnimationPlayState: 'running', msAnimationName: aniFName, msAnimationDuration: duration,
OAnimationPlayState: 'running', OAnimationName: aniFName, OAnimationDuration: duration,
AnimationPlayState: 'running', AnimationName: aniFName, AnimationDuration: duration
};
$front.css(fCss).data("tile").animating = true;
$back.css(bCss).data("tile").animating = true;
window.setTimeout(function () {
if (typeof (newSrc) != "undefined") {
privMethods.handleListItemSwap($front, newSrc, isBgroundImg, stgs);
}
$front.data("tile").animating = false;
$back.data("tile").animating = false;
}, 0); // once the animation is half through it can be reversed
} else {
var height = $itm.height();
var width = $itm.width();
var margin = (dir == "vertical") ? height / 2 : width / 2;
var uCss = (dir == "vertical") ?
{ height: '0px', width: '100%', marginTop: margin + 'px', opacity: 0} :
{ height: '100%', width: '0px', marginLeft: margin + 'px', opacity: 0 };
var dCss = (dir == "vertical") ?
{ height: '100%', width: '100%', marginTop: '0px', opacity: 1} :
{ height: '100%', width: '100%', marginLeft: '0px', opacity: 1 };
$front.stop().animate(uCss, { duration: tdata.speed });
window.setTimeout(function () {
$back.stop().animate(dCss, { duration: tdata.speed });
if (typeof (newSrc) != "undefined") {
privMethods.handleListItemSwap($front, newSrc, isBgroundImg, stgs);
}
}, tdata.speed);
}
};
/* Delay the tile action*/
tdata.doAction = function () {
var action = null;
tdata.stopTimer(false);
switch (tdata.mode) {
case 'slide':
action = $this.slide;
break;
case 'flip':
action = $this.flip;
break;
case 'flip-list':
action = $this.flipList;
break;
}
var callBack = function () {
tdata.setTimer();
};
if (action != null) {
doAnimations = true;
action(callBack);
}
};
tdata.setTimer = function () {
var action = null;
switch (tdata.mode) {
case 'slide':
action = $this.slide;
break;
case 'flip':
action = $this.flip;
break;
case 'flip-list':
action = $this.flipList;
break;
}
if (action != null) {
if (tdata.hasRun == false) {
window.setTimeout(function () {
doAnimations = true;
action();
tdata.setTimer();
}, tdata.initDelay);
} else {
if ($this.slideTimer != null)
$this.slideTimer = privMethods.stopTimer($this.slideTimer);
$this.slideTimer = privMethods.setTimer(function () { doAnimations = true; action(); }, tdata.speed + tdata.delay);
}
}
tdata.hasRun = true;
};
tdata.stopTimer = function (restart) {
$this.slideTimer = privMethods.stopTimer($this.slideTimer);
doAnimations = false;
if (typeof (restart) != "undefined" && restart == true) {
tdata.setTimer();
}
};
$this.data("LiveTile", tdata);
tdata.setTimer();
});
},
animate: function () {
jQuery(this).each(function () {
var tData = jQuery(this).data("LiveTile");
tData.doAction();
});
},
destroy: function () {
jQuery(this).each(function () {
var $t = jQuery(this);
$t.unbind(".liveTile");
var $tile = jQuery(this).data("LiveTile");
if ($tile != null) {
$tile.stopTimer(false);
$t.removeData("LiveTile");
$t.removeData("ha");
$t.removeData("tile");
delete $tile;
delete $t.slide;
delete $t.flip;
delete $t.flipList;
delete $t.liveTile;
}
});
},
stop: function (restart) {
jQuery(this).each(function () {
var $tile = jQuery(this).data("LiveTile");
$tile.stopTimer(restart);
$tile.loopCount = 0;
$tile.hasRun = false;
});
},
pause: function () {
jQuery(this).each(function () {
jQuery(this).data("LiveTile").stopTimer();
});
},
play: function () {
jQuery(this).each(function () {
jQuery(this).data("LiveTile").setTimer();
});
}
};})();