/*
* textillate.js
* http://jschr.github.com/textillate
* mit licensed
*
* copyright (c) 2012-2013 jordan schroter
*/
(function ($) {
"use strict";
function isineffect (effect) {
return /in/.test(effect) || $.inarray(effect, $.fn.textillate.defaults.ineffects) >= 0;
};
function isouteffect (effect) {
return /out/.test(effect) || $.inarray(effect, $.fn.textillate.defaults.outeffects) >= 0;
};
function stringtoboolean(str) {
if (str !== "true" && str !== "false") return str;
return (str === "true");
};
// custom get data api method
function getdata (node) {
var attrs = node.attributes || []
, data = {};
if (!attrs.length) return data;
$.each(attrs, function (i, attr) {
var nodename = attr.nodename.replace(/delayscale/, 'delayscale');
if (/^data-in-*/.test(nodename)) {
data.in = data.in || {};
data.in[nodename.replace(/data-in-/, '')] = stringtoboolean(attr.nodevalue);
} else if (/^data-out-*/.test(nodename)) {
data.out = data.out || {};
data.out[nodename.replace(/data-out-/, '')] =stringtoboolean(attr.nodevalue);
} else if (/^data-*/.test(nodename)) {
data[nodename.replace(/data-/, '')] = stringtoboolean(attr.nodevalue);
}
})
return data;
}
function shuffle (o) {
for (var j, x, i = o.length; i; j = parseint(math.random() * i), x = o[--i], o[i] = o[j], o[j] = x);
return o;
}
function animate ($t, effect, cb) {
$t.addclass('animated ' + effect)
.css('visibility', 'visible')
.show();
$t.one('webkitanimationend mozanimationend msanimationend oanimationend animationend', function () {
$t.removeclass('animated ' + effect);
cb && cb();
});
}
function animatetokens ($tokens, options, cb) {
var that = this
, count = $tokens.length;
if (!count) {
cb && cb();
return;
}
if (options.shuffle) $tokens = shuffle($tokens);
if (options.reverse) $tokens = $tokens.toarray().reverse();
$.each($tokens, function (i, t) {
var $token = $(t);
function complete () {
if (isineffect(options.effect)) {
$token.css('visibility', 'visible');
} else if (isouteffect(options.effect)) {
$token.css('visibility', 'hidden');
}
count -= 1;
if (!count && cb) cb();
}
var delay = options.sync ? options.delay : options.delay * i * options.delayscale;
$token.text() ?
settimeout(function () { animate($token, options.effect, complete) }, delay) :
complete();
});
};
var textillate = function (element, options) {
var base = this
, $element = $(element);
base.init = function () {
base.$texts = $element.find(options.selector);
if (!base.$texts.length) {
base.$texts = $('
');
$element.html(base.$texts);
}
base.$texts.hide();
base.$current = $('')
.html(base.$texts.find(':first-child').html())
.prependto($element);
if (isineffect(options.in.effect)) {
base.$current.css('visibility', 'hidden');
} else if (isouteffect(options.out.effect)) {
base.$current.css('visibility', 'visible');
}
base.setoptions(options);
base.timeoutrun = null;
settimeout(function () {
base.options.autostart && base.start();
}, base.options.initialdelay)
};
base.setoptions = function (options) {
base.options = options;
};
base.triggerevent = function (name) {
var e = $.event(name + '.tlt');
$element.trigger(e, base);
return e;
};
base.in = function (index, cb) {
index = index || 0;
var $elem = base.$texts.find(':nth-child(' + ((index||0) + 1) + ')')
, options = $.extend(true, {}, base.options, $elem.length ? getdata($elem[0]) : {})
, $tokens;
$elem.addclass('current');
base.triggerevent('inanimationbegin');
$element.attr('data-active', $elem.data('id'));
base.$current
.html($elem.html())
.lettering('words');
// split words to individual characters if token type is set to 'char'
if (base.options.type == "char") {
base.$current.find('[class^="word"]')
.css({
'display': 'inline-block',
// fix for poor ios performance
'-webkit-transform': 'translate3d(0,0,0)',
'-moz-transform': 'translate3d(0,0,0)',
'-o-transform': 'translate3d(0,0,0)',
'transform': 'translate3d(0,0,0)'
})
.each(function () { $(this).lettering() });
}
$tokens = base.$current
.find('[class^="' + base.options.type + '"]')
.css('display', 'inline-block');
if (isineffect(options.in.effect)) {
$tokens.css('visibility', 'hidden');
} else if (isouteffect(options.in.effect)) {
$tokens.css('visibility', 'visible');
}
base.currentindex = index;
animatetokens($tokens, options.in, function () {
base.triggerevent('inanimationend');
if (options.in.callback) options.in.callback();
if (cb) cb(base);
});
};
base.out = function (cb) {
var $elem = base.$texts.find(':nth-child(' + ((base.currentindex||0) + 1) + ')')
, $tokens = base.$current.find('[class^="' + base.options.type + '"]')
, options = $.extend(true, {}, base.options, $elem.length ? getdata($elem[0]) : {})
base.triggerevent('outanimationbegin');
animatetokens($tokens, options.out, function () {
$elem.removeclass('current');
base.triggerevent('outanimationend');
$element.removeattr('data-active');
if (options.out.callback) options.out.callback();
if (cb) cb(base);
});
};
base.start = function (index) {
settimeout(function () {
base.triggerevent('start');
(function run (index) {
base.in(index, function () {
var length = base.$texts.children().length;
index += 1;
if (!base.options.loop && index >= length) {
if (base.options.callback) base.options.callback();
base.triggerevent('end');
} else {
index = index % length;
base.timeoutrun = settimeout(function () {
base.out(function () {
run(index)
});
}, base.options.mindisplaytime);
}
});
}(index || 0));
}, base.options.initialdelay);
};
base.stop = function () {
if (base.timeoutrun) {
clearinterval(base.timeoutrun);
base.timeoutrun = null;
}
};
base.init();
}
$.fn.textillate = function (settings, args) {
return this.each(function () {
var $this = $(this)
, data = $this.data('textillate')
, options = $.extend(true, {}, $.fn.textillate.defaults, getdata(this), typeof settings == 'object' && settings);
if (!data) {
$this.data('textillate', (data = new textillate(this, options)));
} else if (typeof settings == 'string') {
data[settings].apply(data, [].concat(args));
} else {
data.setoptions.call(data, options);
}
})
};
$.fn.textillate.defaults = {
selector: '.texts',
loop: false,
mindisplaytime: 2000,
initialdelay: 0,
in: {
effect: 'fadeinleftbig',
delayscale: 1.5,
delay: 50,
sync: false,
reverse: false,
shuffle: false,
callback: function () {}
},
out: {
effect: 'hinge',
delayscale: 1.5,
delay: 50,
sync: false,
reverse: false,
shuffle: false,
callback: function () {}
},
autostart: true,
ineffects: [],
outeffects: [ 'hinge' ],
callback: function () {},
type: 'char'
};
}(jquery));