jquery.textillate.js (11288B)
1 "use strict"; 2 3 function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } 4 5 /* 6 * textillate.js 7 * http://jschr.github.com/textillate 8 * MIT licensed 9 * 10 * Copyright (C) 2012-2013 Jordan Schroter 11 */ 12 (function ($) { 13 "use strict"; 14 15 function isInEffect(effect) { 16 return /In/.test(effect) || $.inArray(effect, $.fn.textillate.defaults.inEffects) >= 0; 17 } 18 19 ; 20 21 function isOutEffect(effect) { 22 return /Out/.test(effect) || $.inArray(effect, $.fn.textillate.defaults.outEffects) >= 0; 23 } 24 25 ; 26 27 function stringToBoolean(str) { 28 if (str !== "true" && str !== "false") return str; 29 return str === "true"; 30 } 31 32 ; // custom get data api method 33 34 function getData(node) { 35 var attrs = node.attributes || [], 36 data = {}; 37 if (!attrs.length) return data; 38 $.each(attrs, function (i, attr) { 39 var nodeName = attr.nodeName.replace(/delayscale/, 'delayScale'); 40 41 if (/^data-in-*/.test(nodeName)) { 42 data.in = data.in || {}; 43 data.in[nodeName.replace(/data-in-/, '')] = stringToBoolean(attr.nodeValue); 44 } else if (/^data-out-*/.test(nodeName)) { 45 data.out = data.out || {}; 46 data.out[nodeName.replace(/data-out-/, '')] = stringToBoolean(attr.nodeValue); 47 } else if (/^data-*/.test(nodeName)) { 48 data[nodeName.replace(/data-/, '')] = stringToBoolean(attr.nodeValue); 49 } 50 }); 51 return data; 52 } 53 54 function shuffle(o) { 55 for (var j, x, i = o.length; i; j = parseInt(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x) { 56 ; 57 } 58 59 return o; 60 } 61 62 function animate($t, effect, cb) { 63 $t.addClass('animated ' + effect).css('visibility', 'visible').show(); 64 $t.one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', function () { 65 $t.removeClass('animated ' + effect); 66 cb && cb(); 67 }); 68 } 69 70 function animateTokens($tokens, options, cb) { 71 var that = this, 72 count = $tokens.length; 73 74 if (!count) { 75 cb && cb(); 76 return; 77 } 78 79 if (options.shuffle) $tokens = shuffle($tokens); 80 if (options.reverse) $tokens = $tokens.toArray().reverse(); 81 $.each($tokens, function (i, t) { 82 var $token = $(t); 83 84 function complete() { 85 if (isInEffect(options.effect)) { 86 if ("typeOut" === options.effect) { 87 $token.css("display", "inline-block"); 88 } else { 89 $token.css('visibility', 'visible'); 90 } 91 } else if (isOutEffect(options.effect)) { 92 if ("typeOut" === options.effect) { 93 $token.css("display", "none"); 94 } else { 95 $token.css('visibility', 'hidden'); 96 } 97 } 98 99 count -= 1; 100 if (!count && cb) cb(); 101 } 102 103 var delay = options.sync ? options.delay : options.delay * i * options.delayScale; 104 $token.text() ? setTimeout(function () { 105 //animate($token, options.effect, complete) 106 var $el; 107 var name; 108 var filter; 109 var strip_width; 110 $el = $token; 111 name = options.effect; 112 filter = complete; 113 strip_width = 0; 114 115 if ("clipIn" === name) { 116 $el.css("width", "auto"); 117 strip_width = $el.width(); 118 $el.css("overflow", "hidden"); 119 $el.css("width", "0"); 120 $el.css("visibility", "visible"); 121 $el.animate({ 122 width: strip_width + .3 * parseFloat($el.css("font-size")) 123 }, 1200, function () { 124 setTimeout(function () { 125 if (filter) { 126 filter(); 127 } 128 }, 100); 129 }); 130 } else { 131 if ("clipOut" === name) { 132 $el.animate({ 133 width: "2px" 134 }, 1200, function () { 135 setTimeout(function () { 136 if (filter) { 137 filter(); 138 } 139 }, 100); 140 }); 141 } else { 142 if ("typeIn" === name) { 143 $el.addClass("sp-title-animated " + name).show(); 144 } else { 145 $el.addClass("sp-title-animated " + name).css("visibility", "visible").show(); 146 } 147 } 148 } 149 150 if (!("typeIn" !== name && "typeOut" !== name || !jQuery("html").hasClass("ua-edge") && !jQuery("html").hasClass("ua-ie"))) { 151 $el.removeClass("sp-title-animated " + name).css("visibility", "visible"); 152 153 if (filter) { 154 filter(); 155 } 156 } 157 158 $el.one("webkitAnimationEnd mozAnimationEnd MSAnimationEnd oAnimationEnd AnimationEnd", function () { 159 $el.removeClass("sp-title-animated " + name); 160 161 if (filter) { 162 filter(); 163 } 164 }); 165 }, delay) : complete(); 166 }); 167 } 168 169 ; 170 171 var Textillate = function Textillate(element, options) { 172 var base = this, 173 $element = $(element); 174 175 base.init = function () { 176 base.$texts = $element.find(options.selector); 177 178 if (!base.$texts.length) { 179 base.$texts = $('<ul class="texts"><li>' + $element.html() + '</li></ul>'); 180 $element.html(base.$texts); 181 } 182 183 base.$texts.hide(); 184 base.$current = $('<span class="sp-textillate">').html(base.$texts.find(':first-child').html()).prependTo($element); 185 186 if (isInEffect(options.in.effect)) { 187 base.$current.css('visibility', 'hidden'); 188 } else if (isOutEffect(options.out.effect)) { 189 base.$current.css('visibility', 'visible'); 190 } 191 192 base.setOptions(options); 193 base.timeoutRun = null; 194 setTimeout(function () { 195 base.options.autoStart && base.start(); 196 }, base.options.initialDelay); 197 }; 198 199 base.setOptions = function (options) { 200 base.options = options; 201 }; 202 203 base.triggerEvent = function (name) { 204 var e = $.Event(name + '.tlt'); 205 $element.trigger(e, base); 206 return e; 207 }; 208 209 base.in = function (index, cb) { 210 index = index || 0; 211 var $elem = base.$texts.find(':nth-child(' + ((index || 0) + 1) + ')'), 212 options = $.extend(true, {}, base.options, $elem.length ? getData($elem[0]) : {}), 213 $tokens; 214 var sparklineElement = base.$current.closest(".sp-animated-texts-wrapper"); 215 $elem.addClass('current'); 216 base.triggerEvent('inAnimationBegin'); 217 $element.attr('data-active', $elem.data('id')); 218 219 if ("line" == base.options.length) { 220 base.$current.html($elem.html()).lettering("lines"); 221 } else { 222 base.$current.html($elem.html()).lettering("words"); 223 } 224 /* 225 base.$current 226 .html($elem.html()) 227 .lettering('words'); 228 */ 229 // split words to individual characters if token type is set to 'char' 230 231 232 if (base.options.type == "char") { 233 base.$current.find('[class^="word"]').css({ 234 'display': 'inline-block', 235 // fix for poor ios performance 236 '-webkit-transform': 'translate3d(0,0,0)', 237 '-moz-transform': 'translate3d(0,0,0)', 238 '-o-transform': 'translate3d(0,0,0)', 239 'transform': 'translate3d(0,0,0)' 240 }).each(function () { 241 $(this).lettering(); 242 }); 243 } 244 245 $tokens = base.$current.find('[class^="' + base.options.length + '"]').css("display", "inline-block"); 246 /* 247 $tokens = base.$current 248 .find('[class^="' + base.options.type + '"]') 249 .css('display', 'inline-block'); 250 */ 251 252 if (isInEffect(options.in.effect)) { 253 if ("typeIn" === options.in.effect) { 254 $tokens.css("display", "none"); 255 } else { 256 $tokens.css("visibility", "hidden"); 257 } //$tokens.css('visibility', 'hidden'); 258 259 } else if (isOutEffect(options.in.effect)) { 260 $tokens.css('visibility', 'visible'); 261 } 262 263 if (!("typeIn" !== options.in.effect && "clipIn" !== options.in.effect || void 0 !== sparklineElement.attr("style") && -1 !== sparklineElement.attr("style").indexOf("width"))) { 264 base.$current.closest(".sp-animated-texts-wrapper").css("width", "auto"); 265 } 266 267 base.currentIndex = index; 268 animateTokens($tokens, options.in, function () { 269 base.triggerEvent('inAnimationEnd'); 270 if (options.in.callback) options.in.callback(); 271 if (cb) cb(base); 272 }); 273 }; 274 275 base.out = function (cb) { 276 var $elem = base.$texts.find(':nth-child(' + ((base.currentIndex || 0) + 1) + ')'), 277 $tokens = base.$current.find('[class^="' + base.options.length + '"]'), 278 options = $.extend(true, {}, base.options, $elem.length ? getData($elem[0]) : {}); 279 base.triggerEvent('outAnimationBegin'); 280 animateTokens($tokens, options.out, function () { 281 $elem.removeClass('current'); 282 base.triggerEvent('outAnimationEnd'); 283 $element.removeAttr('data-active'); 284 if (options.out.callback) options.out.callback(); 285 if (cb) cb(base); 286 }); 287 }; 288 289 base.start = function (index) { 290 setTimeout(function () { 291 base.triggerEvent('start'); 292 293 (function run(index) { 294 base.in(index, function () { 295 var length = base.$texts.children().length; 296 index += 1; 297 298 if (!base.options.loop && index >= length) { 299 if (base.options.callback) base.options.callback(); 300 base.triggerEvent('end'); 301 } else { 302 index = index % length; 303 base.timeoutRun = setTimeout(function () { 304 base.out(function () { 305 run(index); 306 }); 307 }, base.options.minDisplayTime); 308 } 309 }); 310 })(index || 0); 311 }, base.options.initialDelay); 312 }; 313 314 base.stop = function () { 315 if (base.timeoutRun) { 316 clearInterval(base.timeoutRun); 317 base.timeoutRun = null; 318 } 319 }; 320 321 base.init(); 322 }; 323 324 $.fn.textillate = function (settings, args) { 325 return this.each(function () { 326 var $this = $(this), 327 data = $this.data('textillate'), 328 options = $.extend(true, {}, $.fn.textillate.defaults, getData(this), _typeof(settings) == 'object' && settings); 329 330 if (!data) { 331 $this.data('textillate', data = new Textillate(this, options)); 332 } else if (typeof settings == 'string') { 333 data[settings].apply(data, [].concat(args)); 334 } else { 335 data.setOptions.call(data, options); 336 } 337 }); 338 }; 339 340 $.fn.textillate.defaults = { 341 selector: '.texts', 342 loop: true, 343 minDisplayTime: 2000, 344 initialDelay: 0, 345 in: { 346 effect: 'fadeInLeftBig', 347 delayScale: 1.5, 348 delay: 50, 349 sync: false, 350 reverse: false, 351 shuffle: false, 352 callback: function callback() {} 353 }, 354 out: { 355 effect: 'hinge', 356 delayScale: 1.5, 357 delay: 50, 358 sync: false, 359 reverse: false, 360 shuffle: false, 361 callback: function callback() {} 362 }, 363 autoStart: true, 364 inEffects: [], 365 outEffects: ['hinge'], 366 callback: function callback() {}, 367 type: 'char' 368 }; 369 })(jQuery);