scripts.js 56 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611
  1. // ------------- JQUERY TYPED.JS -------------------------------------------- //
  2. // ============ https://github.com/mattboldt/typed.js/ ====================== //
  3. // -------------------------------------------------------------------------- //
  4. !function($){
  5. "use strict";
  6. var Typed = function(el, options){
  7. // chosen element to manipulate text
  8. this.el = $(el);
  9. // options
  10. this.options = $.extend({}, $.fn.typed.defaults, options);
  11. // text content of element
  12. this.baseText = this.el.text() || this.el.attr('placeholder') || '';
  13. // typing speed
  14. this.typeSpeed = this.options.typeSpeed;
  15. // add a delay before typing starts
  16. this.startDelay = this.options.startDelay;
  17. // backspacing speed
  18. this.backSpeed = this.options.backSpeed;
  19. // amount of time to wait before backspacing
  20. this.backDelay = this.options.backDelay;
  21. // input strings of text
  22. this.strings = this.options.strings;
  23. // character number position of current string
  24. this.strPos = 0;
  25. // current array position
  26. this.arrayPos = 0;
  27. // number to stop backspacing on.
  28. // default 0, can change depending on how many chars
  29. // you want to remove at the time
  30. this.stopNum = 0;
  31. // Looping logic
  32. this.loop = this.options.loop;
  33. this.loopCount = this.options.loopCount;
  34. this.curLoop = 0;
  35. // for stopping
  36. this.stop = false;
  37. // show cursor
  38. this.showCursor = this.isInput ? false : this.options.showCursor;
  39. // custom cursor
  40. this.cursorChar = this.options.cursorChar;
  41. // attribute to type
  42. this.isInput = this.el.is('input');
  43. this.attr = this.options.attr || (this.isInput ? 'placeholder' : null);
  44. // All systems go!
  45. this.build();
  46. };
  47. Typed.prototype = {
  48. constructor: Typed
  49. , init: function(){
  50. // begin the loop w/ first current string (global self.string)
  51. // current string will be passed as an argument each time after this
  52. var self = this;
  53. self.timeout = setTimeout(function() {
  54. // Start typing
  55. self.typewrite(self.strings[self.arrayPos], self.strPos);
  56. }, self.startDelay);
  57. }
  58. , build: function(){
  59. // Insert cursor
  60. if (this.showCursor === true){
  61. this.cursor = $("<span class=\"typed-cursor\">" + this.cursorChar + "</span>");
  62. this.el.after(this.cursor);
  63. }
  64. this.init();
  65. }
  66. // pass current string state to each function, types 1 char per call
  67. , typewrite: function(curString, curStrPos){
  68. // exit when stopped
  69. if(this.stop === true)
  70. return;
  71. // varying values for setTimeout during typing
  72. // can't be global since number changes each time loop is executed
  73. var humanize = Math.round(Math.random() * (100 - 30)) + this.typeSpeed;
  74. var self = this;
  75. // ------------- optional ------------- //
  76. // backpaces a certain string faster
  77. // ------------------------------------ //
  78. // if (self.arrayPos == 1){
  79. // self.backDelay = 50;
  80. // }
  81. // else{ self.backDelay = 500; }
  82. // contain typing function in a timeout humanize'd delay
  83. self.timeout = setTimeout(function() {
  84. // check for an escape character before a pause value
  85. // format: \^\d+ .. eg: ^1000 .. should be able to print the ^ too using ^^
  86. // single ^ are removed from string
  87. var charPause = 0;
  88. var substr = curString.substr(curStrPos);
  89. if (substr.charAt(0) === '^') {
  90. var skip = 1; // skip atleast 1
  91. if(/^\^\d+/.test(substr)) {
  92. substr = /\d+/.exec(substr)[0];
  93. skip += substr.length;
  94. charPause = parseInt(substr);
  95. }
  96. // strip out the escape character and pause value so they're not printed
  97. curString = curString.substring(0,curStrPos)+curString.substring(curStrPos+skip);
  98. }
  99. // timeout for any pause after a character
  100. self.timeout = setTimeout(function() {
  101. if(curStrPos === curString.length) {
  102. // fires callback function
  103. self.options.onStringTyped(self.arrayPos);
  104. // is this the final string
  105. if(self.arrayPos === self.strings.length-1) {
  106. // animation that occurs on the last typed string
  107. self.options.callback();
  108. self.curLoop++;
  109. // quit if we wont loop back
  110. if(self.loop === false || self.curLoop === self.loopCount)
  111. return;
  112. }
  113. self.timeout = setTimeout(function(){
  114. self.backspace(curString, curStrPos);
  115. }, self.backDelay);
  116. } else {
  117. /* call before functions if applicable */
  118. if(curStrPos === 0)
  119. self.options.preStringTyped(self.arrayPos);
  120. // start typing each new char into existing string
  121. // curString: arg, self.baseText: original text inside element
  122. var nextString = self.baseText + curString.substr(0, curStrPos+1);
  123. if (self.attr) {
  124. self.el.attr(self.attr, nextString);
  125. } else {
  126. self.el.text(nextString);
  127. }
  128. // add characters one by one
  129. curStrPos++;
  130. // loop the function
  131. self.typewrite(curString, curStrPos);
  132. }
  133. // end of character pause
  134. }, charPause);
  135. // humanized value for typing
  136. }, humanize);
  137. }
  138. , backspace: function(curString, curStrPos){
  139. // exit when stopped
  140. if (this.stop === true) {
  141. return;
  142. }
  143. // varying values for setTimeout during typing
  144. // can't be global since number changes each time loop is executed
  145. var humanize = Math.round(Math.random() * (100 - 30)) + this.backSpeed;
  146. var self = this;
  147. self.timeout = setTimeout(function() {
  148. // ----- this part is optional ----- //
  149. // check string array position
  150. // on the first string, only delete one word
  151. // the stopNum actually represents the amount of chars to
  152. // ------------- CUSTOM OPTIONS --------------------------------------------- //
  153. // ========================================================================== //
  154. // -------------------------------------------------------------------------- //
  155. if (self.arrayPos == 1) {
  156. self.stopNum = 17;
  157. self.backDelay = 500;
  158. }
  159. else if (self.arrayPos == 2) {
  160. self.stopNum = 54;
  161. }
  162. else{self.stopNum = 0;}
  163. // ----- continue important stuff ----- //
  164. // replace text with base text + typed characters
  165. var nextString = self.baseText + curString.substr(0, curStrPos);
  166. if (self.attr) {
  167. self.el.attr(self.attr, nextString);
  168. } else {
  169. self.el.text(nextString);
  170. }
  171. // if the number (id of character in current string) is
  172. // less than the stop number, keep going
  173. if (curStrPos > self.stopNum){
  174. // subtract characters one by one
  175. curStrPos--;
  176. // loop the function
  177. self.backspace(curString, curStrPos);
  178. }
  179. // if the stop number has been reached, increase
  180. // array position to next string
  181. else if (curStrPos <= self.stopNum) {
  182. self.arrayPos++;
  183. if(self.arrayPos === self.strings.length) {
  184. self.arrayPos = 0;
  185. self.init();
  186. } else
  187. self.typewrite(self.strings[self.arrayPos], curStrPos);
  188. }
  189. // humanized value for typing
  190. }, humanize);
  191. }
  192. // Start & Stop currently not working
  193. // , stop: function() {
  194. // var self = this;
  195. // self.stop = true;
  196. // clearInterval(self.timeout);
  197. // }
  198. // , start: function() {
  199. // var self = this;
  200. // if(self.stop === false)
  201. // return;
  202. // this.stop = false;
  203. // this.init();
  204. // }
  205. // Reset and rebuild the element
  206. , reset: function(){
  207. var self = this;
  208. clearInterval(self.timeout);
  209. var id = this.el.attr('id');
  210. this.el.after('<span id="' + id + '"/>')
  211. this.el.remove();
  212. this.cursor.remove();
  213. // Send the callback
  214. self.options.resetCallback();
  215. }
  216. };
  217. $.fn.typed = function (option) {
  218. return this.each(function () {
  219. var $this = $(this)
  220. , data = $this.data('typed')
  221. , options = typeof option == 'object' && option;
  222. if (!data) $this.data('typed', (data = new Typed(this, options)));
  223. if (typeof option == 'string') data[option]();
  224. });
  225. };
  226. $.fn.typed.defaults = {
  227. strings: ["These are the default values...", "You know what you should do?", "Use your own!", "Have a great day!"],
  228. // typing speed
  229. typeSpeed: 0,
  230. // time before typing starts
  231. startDelay: 0,
  232. // backspacing speed
  233. backSpeed: 0,
  234. // time before backspacing
  235. backDelay: 500,
  236. // loop
  237. loop: false,
  238. // false = infinite
  239. loopCount: false,
  240. // show cursor
  241. showCursor: true,
  242. // character for cursor
  243. cursorChar: "|",
  244. // attribute to type (null == text)
  245. attr: null,
  246. // call when done callback function
  247. callback: function() {},
  248. // starting callback function before each string
  249. preStringTyped: function() {},
  250. //callback for every typed string
  251. onStringTyped: function() {},
  252. // callback for reset
  253. resetCallback: function() {}
  254. };
  255. }(window.jQuery);
  256. // ------------- JQUERY SCROLLTO--------------------------------------------- //
  257. // ============ https://github.com/balupton/jquery-scrollto ================= //
  258. // -------------------------------------------------------------------------- //
  259. /*global define:false require:false */
  260. (function (name, context, definition) {
  261. if (typeof module != 'undefined' && module.exports) module.exports = definition();
  262. else if (typeof define == 'function' && define.amd) define(definition);
  263. else context[name] = definition();
  264. })('jquery-scrollto', this, function(){
  265. // Prepare
  266. var jQuery, $, ScrollTo;
  267. jQuery = $ = window.jQuery || require('jquery');
  268. // Fix scrolling animations on html/body on safari
  269. $.propHooks.scrollTop = $.propHooks.scrollLeft = {
  270. get: function(elem,prop) {
  271. var result = null;
  272. if ( elem.tagName === 'HTML' || elem.tagName === 'BODY' ) {
  273. if ( prop === 'scrollLeft' ) {
  274. result = window.scrollX;
  275. } else if ( prop === 'scrollTop' ) {
  276. result = window.scrollY;
  277. }
  278. }
  279. if ( result == null ) {
  280. result = elem[prop];
  281. }
  282. return result;
  283. }
  284. };
  285. $.Tween.propHooks.scrollTop = $.Tween.propHooks.scrollLeft = {
  286. get: function(tween) {
  287. return $.propHooks.scrollTop.get(tween.elem, tween.prop);
  288. },
  289. set: function(tween) {
  290. // Our safari fix
  291. if ( tween.elem.tagName === 'HTML' || tween.elem.tagName === 'BODY' ) {
  292. // Defaults
  293. tween.options.bodyScrollLeft = (tween.options.bodyScrollLeft || window.scrollX);
  294. tween.options.bodyScrollTop = (tween.options.bodyScrollTop || window.scrollY);
  295. // Apply
  296. if ( tween.prop === 'scrollLeft' ) {
  297. tween.options.bodyScrollLeft = Math.round(tween.now);
  298. }
  299. else if ( tween.prop === 'scrollTop' ) {
  300. tween.options.bodyScrollTop = Math.round(tween.now);
  301. }
  302. // Apply
  303. window.scrollTo(tween.options.bodyScrollLeft, tween.options.bodyScrollTop);
  304. }
  305. // jQuery's IE8 Fix
  306. else if ( tween.elem.nodeType && tween.elem.parentNode ) {
  307. tween.elem[ tween.prop ] = tween.now;
  308. }
  309. }
  310. };
  311. // jQuery ScrollTo
  312. ScrollTo = {
  313. // Configuration
  314. config: {
  315. duration: 400,
  316. easing: 'swing',
  317. callback: undefined,
  318. durationMode: 'each',
  319. offsetTop: 0,
  320. offsetLeft: 0
  321. },
  322. // Set Configuration
  323. configure: function(options){
  324. // Apply Options to Config
  325. $.extend(ScrollTo.config, options||{});
  326. // Chain
  327. return this;
  328. },
  329. // Perform the Scroll Animation for the Collections
  330. // We use $inline here, so we can determine the actual offset start for each overflow:scroll item
  331. // Each collection is for each overflow:scroll item
  332. scroll: function(collections, config){
  333. // Prepare
  334. var collection, $container, container, $target, $inline, position, containerTagName,
  335. containerScrollTop, containerScrollLeft,
  336. containerScrollTopEnd, containerScrollLeftEnd,
  337. startOffsetTop, targetOffsetTop, targetOffsetTopAdjusted,
  338. startOffsetLeft, targetOffsetLeft, targetOffsetLeftAdjusted,
  339. scrollOptions,
  340. callback;
  341. // Determine the Scroll
  342. collection = collections.pop();
  343. $container = collection.$container;
  344. $target = collection.$target;
  345. containerTagName = $container.prop('tagName');
  346. // Prepare the Inline Element of the Container
  347. $inline = $('<span/>').css({
  348. 'position': 'absolute',
  349. 'top': '0px',
  350. 'left': '0px'
  351. });
  352. position = $container.css('position');
  353. // Insert the Inline Element of the Container
  354. $container.css({position:'relative'});
  355. $inline.appendTo($container);
  356. // Determine the top offset
  357. startOffsetTop = $inline.offset().top;
  358. targetOffsetTop = $target.offset().top;
  359. targetOffsetTopAdjusted = targetOffsetTop - startOffsetTop - parseInt(config.offsetTop,10);
  360. // Determine the left offset
  361. startOffsetLeft = $inline.offset().left;
  362. targetOffsetLeft = $target.offset().left;
  363. targetOffsetLeftAdjusted = targetOffsetLeft - startOffsetLeft - parseInt(config.offsetLeft,10);
  364. // Determine current scroll positions
  365. containerScrollTop = $container.prop('scrollTop');
  366. containerScrollLeft = $container.prop('scrollLeft');
  367. // Reset the Inline Element of the Container
  368. $inline.remove();
  369. $container.css({position:position});
  370. // Prepare the scroll options
  371. scrollOptions = {};
  372. // Prepare the callback
  373. callback = function(event){
  374. // Check
  375. if ( collections.length === 0 ) {
  376. // Callback
  377. if ( typeof config.callback === 'function' ) {
  378. config.callback();
  379. }
  380. }
  381. else {
  382. // Recurse
  383. ScrollTo.scroll(collections,config);
  384. }
  385. // Return true
  386. return true;
  387. };
  388. // Handle if we only want to scroll if we are outside the viewport
  389. if ( config.onlyIfOutside ) {
  390. // Determine current scroll positions
  391. containerScrollTopEnd = containerScrollTop + $container.height();
  392. containerScrollLeftEnd = containerScrollLeft + $container.width();
  393. // Check if we are in the range of the visible area of the container
  394. if ( containerScrollTop < targetOffsetTopAdjusted && targetOffsetTopAdjusted < containerScrollTopEnd ) {
  395. targetOffsetTopAdjusted = containerScrollTop;
  396. }
  397. if ( containerScrollLeft < targetOffsetLeftAdjusted && targetOffsetLeftAdjusted < containerScrollLeftEnd ) {
  398. targetOffsetLeftAdjusted = containerScrollLeft;
  399. }
  400. }
  401. // Determine the scroll options
  402. if ( targetOffsetTopAdjusted !== containerScrollTop ) {
  403. scrollOptions.scrollTop = targetOffsetTopAdjusted;
  404. }
  405. if ( targetOffsetLeftAdjusted !== containerScrollLeft ) {
  406. scrollOptions.scrollLeft = targetOffsetLeftAdjusted;
  407. }
  408. // Check to see if the scroll is necessary
  409. if ( $container.prop('scrollHeight') === $container.width() ) {
  410. delete scrollOptions.scrollTop;
  411. }
  412. if ( $container.prop('scrollWidth') === $container.width() ) {
  413. delete scrollOptions.scrollLeft;
  414. }
  415. // Perform the scroll
  416. if ( scrollOptions.scrollTop != null || scrollOptions.scrollLeft != null ) {
  417. $container.animate(scrollOptions, {
  418. duration: config.duration,
  419. easing: config.easing,
  420. complete: callback
  421. });
  422. }
  423. else {
  424. callback();
  425. }
  426. // Return true
  427. return true;
  428. },
  429. // ScrollTo the Element using the Options
  430. fn: function(options){
  431. // Prepare
  432. var collections, config, $container, container;
  433. collections = [];
  434. // Prepare
  435. var $target = $(this);
  436. if ( $target.length === 0 ) {
  437. // Chain
  438. return this;
  439. }
  440. // Handle Options
  441. config = $.extend({},ScrollTo.config,options);
  442. // Fetch
  443. $container = $target.parent();
  444. container = $container.get(0);
  445. // Cycle through the containers
  446. while ( ($container.length === 1) && (container !== document.body) && (container !== document) ) {
  447. // Check Container for scroll differences
  448. var containerScrollTop, containerScrollLeft;
  449. containerScrollTop = $container.css('overflow-y') !== 'visible' && container.scrollHeight !== container.clientHeight;
  450. containerScrollLeft = $container.css('overflow-x') !== 'visible' && container.scrollWidth !== container.clientWidth;
  451. if ( containerScrollTop || containerScrollLeft ) {
  452. // Push the Collection
  453. collections.push({
  454. '$container': $container,
  455. '$target': $target
  456. });
  457. // Update the Target
  458. $target = $container;
  459. }
  460. // Update the Container
  461. $container = $container.parent();
  462. container = $container.get(0);
  463. }
  464. // Add the final collection
  465. collections.push({
  466. '$container': $('html'),
  467. // document.body doesn't work in firefox, html works for all
  468. // internet explorer starts at the beggining
  469. '$target': $target
  470. });
  471. // Adjust the Config
  472. if ( config.durationMode === 'all' ) {
  473. config.duration /= collections.length;
  474. }
  475. // Handle
  476. ScrollTo.scroll(collections,config);
  477. // Chain
  478. return this;
  479. }
  480. };
  481. // Apply our extensions to jQuery
  482. $.ScrollTo = $.ScrollTo || ScrollTo;
  483. $.fn.ScrollTo = $.fn.ScrollTo || ScrollTo.fn;
  484. // Export
  485. return ScrollTo;
  486. });
  487. // ------------- WOW ANIMATE ------------------------------------------------ //
  488. // ==============https://github.com/matthieua/WOW =========================== //
  489. // -------------------------------------------------------------------------- //
  490. (function() {
  491. var MutationObserver, Util, WeakMap, getComputedStyle, getComputedStyleRX,
  492. __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
  493. __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
  494. Util = (function() {
  495. function Util() {}
  496. Util.prototype.extend = function(custom, defaults) {
  497. var key, value;
  498. for (key in defaults) {
  499. value = defaults[key];
  500. if (custom[key] == null) {
  501. custom[key] = value;
  502. }
  503. }
  504. return custom;
  505. };
  506. Util.prototype.isMobile = function(agent) {
  507. return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(agent);
  508. };
  509. Util.prototype.addEvent = function(elem, event, fn) {
  510. if (elem.addEventListener != null) {
  511. return elem.addEventListener(event, fn, false);
  512. } else if (elem.attachEvent != null) {
  513. return elem.attachEvent("on" + event, fn);
  514. } else {
  515. return elem[event] = fn;
  516. }
  517. };
  518. Util.prototype.removeEvent = function(elem, event, fn) {
  519. if (elem.removeEventListener != null) {
  520. return elem.removeEventListener(event, fn, false);
  521. } else if (elem.detachEvent != null) {
  522. return elem.detachEvent("on" + event, fn);
  523. } else {
  524. return delete elem[event];
  525. }
  526. };
  527. Util.prototype.innerHeight = function() {
  528. if ('innerHeight' in window) {
  529. return window.innerHeight;
  530. } else {
  531. return document.documentElement.clientHeight;
  532. }
  533. };
  534. return Util;
  535. })();
  536. WeakMap = this.WeakMap || this.MozWeakMap || (WeakMap = (function() {
  537. function WeakMap() {
  538. this.keys = [];
  539. this.values = [];
  540. }
  541. WeakMap.prototype.get = function(key) {
  542. var i, item, _i, _len, _ref;
  543. _ref = this.keys;
  544. for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
  545. item = _ref[i];
  546. if (item === key) {
  547. return this.values[i];
  548. }
  549. }
  550. };
  551. WeakMap.prototype.set = function(key, value) {
  552. var i, item, _i, _len, _ref;
  553. _ref = this.keys;
  554. for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
  555. item = _ref[i];
  556. if (item === key) {
  557. this.values[i] = value;
  558. return;
  559. }
  560. }
  561. this.keys.push(key);
  562. return this.values.push(value);
  563. };
  564. return WeakMap;
  565. })());
  566. MutationObserver = this.MutationObserver || this.WebkitMutationObserver || this.MozMutationObserver || (MutationObserver = (function() {
  567. function MutationObserver() {
  568. if (typeof console !== "undefined" && console !== null) {
  569. console.warn('MutationObserver is not supported by your browser.');
  570. }
  571. if (typeof console !== "undefined" && console !== null) {
  572. console.warn('WOW.js cannot detect dom mutations, please call .sync() after loading new content.');
  573. }
  574. }
  575. MutationObserver.notSupported = true;
  576. MutationObserver.prototype.observe = function() {};
  577. return MutationObserver;
  578. })());
  579. getComputedStyle = this.getComputedStyle || function(el, pseudo) {
  580. this.getPropertyValue = function(prop) {
  581. var _ref;
  582. if (prop === 'float') {
  583. prop = 'styleFloat';
  584. }
  585. if (getComputedStyleRX.test(prop)) {
  586. prop.replace(getComputedStyleRX, function(_, char) {
  587. return char.toUpperCase();
  588. });
  589. }
  590. return ((_ref = el.currentStyle) != null ? _ref[prop] : void 0) || null;
  591. };
  592. return this;
  593. };
  594. getComputedStyleRX = /(\-([a-z]){1})/g;
  595. this.WOW = (function() {
  596. WOW.prototype.defaults = {
  597. boxClass: 'wow',
  598. animateClass: 'animated',
  599. offset: 0,
  600. mobile: true,
  601. live: true
  602. };
  603. function WOW(options) {
  604. if (options == null) {
  605. options = {};
  606. }
  607. this.scrollCallback = __bind(this.scrollCallback, this);
  608. this.scrollHandler = __bind(this.scrollHandler, this);
  609. this.start = __bind(this.start, this);
  610. this.scrolled = true;
  611. this.config = this.util().extend(options, this.defaults);
  612. this.animationNameCache = new WeakMap();
  613. }
  614. WOW.prototype.init = function() {
  615. var _ref;
  616. this.element = window.document.documentElement;
  617. if ((_ref = document.readyState) === "interactive" || _ref === "complete") {
  618. this.start();
  619. } else {
  620. this.util().addEvent(document, 'DOMContentLoaded', this.start);
  621. }
  622. return this.finished = [];
  623. };
  624. WOW.prototype.start = function() {
  625. var box, _i, _len, _ref;
  626. this.stopped = false;
  627. this.boxes = (function() {
  628. var _i, _len, _ref, _results;
  629. _ref = this.element.querySelectorAll("." + this.config.boxClass);
  630. _results = [];
  631. for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  632. box = _ref[_i];
  633. _results.push(box);
  634. }
  635. return _results;
  636. }).call(this);
  637. this.all = (function() {
  638. var _i, _len, _ref, _results;
  639. _ref = this.boxes;
  640. _results = [];
  641. for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  642. box = _ref[_i];
  643. _results.push(box);
  644. }
  645. return _results;
  646. }).call(this);
  647. if (this.boxes.length) {
  648. if (this.disabled()) {
  649. this.resetStyle();
  650. } else {
  651. _ref = this.boxes;
  652. for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  653. box = _ref[_i];
  654. this.applyStyle(box, true);
  655. }
  656. this.util().addEvent(window, 'scroll', this.scrollHandler);
  657. this.util().addEvent(window, 'resize', this.scrollHandler);
  658. this.interval = setInterval(this.scrollCallback, 50);
  659. }
  660. }
  661. if (this.config.live) {
  662. return new MutationObserver((function(_this) {
  663. return function(records) {
  664. var node, record, _j, _len1, _results;
  665. _results = [];
  666. for (_j = 0, _len1 = records.length; _j < _len1; _j++) {
  667. record = records[_j];
  668. _results.push((function() {
  669. var _k, _len2, _ref1, _results1;
  670. _ref1 = record.addedNodes || [];
  671. _results1 = [];
  672. for (_k = 0, _len2 = _ref1.length; _k < _len2; _k++) {
  673. node = _ref1[_k];
  674. _results1.push(this.doSync(node));
  675. }
  676. return _results1;
  677. }).call(_this));
  678. }
  679. return _results;
  680. };
  681. })(this)).observe(document.body, {
  682. childList: true,
  683. subtree: true
  684. });
  685. }
  686. };
  687. WOW.prototype.stop = function() {
  688. this.stopped = true;
  689. this.util().removeEvent(window, 'scroll', this.scrollHandler);
  690. this.util().removeEvent(window, 'resize', this.scrollHandler);
  691. if (this.interval != null) {
  692. return clearInterval(this.interval);
  693. }
  694. };
  695. WOW.prototype.sync = function(element) {
  696. if (MutationObserver.notSupported) {
  697. return this.doSync(this.element);
  698. }
  699. };
  700. WOW.prototype.doSync = function(element) {
  701. var box, _i, _len, _ref, _results;
  702. if (element == null) {
  703. element = this.element;
  704. }
  705. if (element.nodeType !== 1) {
  706. return;
  707. }
  708. element = element.parentNode || element;
  709. _ref = element.querySelectorAll("." + this.config.boxClass);
  710. _results = [];
  711. for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  712. box = _ref[_i];
  713. if (__indexOf.call(this.all, box) < 0) {
  714. this.boxes.push(box);
  715. this.all.push(box);
  716. if (this.stopped || this.disabled()) {
  717. this.resetStyle();
  718. } else {
  719. this.applyStyle(box, true);
  720. }
  721. _results.push(this.scrolled = true);
  722. } else {
  723. _results.push(void 0);
  724. }
  725. }
  726. return _results;
  727. };
  728. WOW.prototype.show = function(box) {
  729. this.applyStyle(box);
  730. return box.className = "" + box.className + " " + this.config.animateClass;
  731. };
  732. WOW.prototype.applyStyle = function(box, hidden) {
  733. var delay, duration, iteration;
  734. duration = box.getAttribute('data-wow-duration');
  735. delay = box.getAttribute('data-wow-delay');
  736. iteration = box.getAttribute('data-wow-iteration');
  737. return this.animate((function(_this) {
  738. return function() {
  739. return _this.customStyle(box, hidden, duration, delay, iteration);
  740. };
  741. })(this));
  742. };
  743. WOW.prototype.animate = (function() {
  744. if ('requestAnimationFrame' in window) {
  745. return function(callback) {
  746. return window.requestAnimationFrame(callback);
  747. };
  748. } else {
  749. return function(callback) {
  750. return callback();
  751. };
  752. }
  753. })();
  754. WOW.prototype.resetStyle = function() {
  755. var box, _i, _len, _ref, _results;
  756. _ref = this.boxes;
  757. _results = [];
  758. for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  759. box = _ref[_i];
  760. _results.push(box.style.visibility = 'visible');
  761. }
  762. return _results;
  763. };
  764. WOW.prototype.customStyle = function(box, hidden, duration, delay, iteration) {
  765. if (hidden) {
  766. this.cacheAnimationName(box);
  767. }
  768. box.style.visibility = hidden ? 'hidden' : 'visible';
  769. if (duration) {
  770. this.vendorSet(box.style, {
  771. animationDuration: duration
  772. });
  773. }
  774. if (delay) {
  775. this.vendorSet(box.style, {
  776. animationDelay: delay
  777. });
  778. }
  779. if (iteration) {
  780. this.vendorSet(box.style, {
  781. animationIterationCount: iteration
  782. });
  783. }
  784. this.vendorSet(box.style, {
  785. animationName: hidden ? 'none' : this.cachedAnimationName(box)
  786. });
  787. return box;
  788. };
  789. WOW.prototype.vendors = ["moz", "webkit"];
  790. WOW.prototype.vendorSet = function(elem, properties) {
  791. var name, value, vendor, _results;
  792. _results = [];
  793. for (name in properties) {
  794. value = properties[name];
  795. elem["" + name] = value;
  796. _results.push((function() {
  797. var _i, _len, _ref, _results1;
  798. _ref = this.vendors;
  799. _results1 = [];
  800. for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  801. vendor = _ref[_i];
  802. _results1.push(elem["" + vendor + (name.charAt(0).toUpperCase()) + (name.substr(1))] = value);
  803. }
  804. return _results1;
  805. }).call(this));
  806. }
  807. return _results;
  808. };
  809. WOW.prototype.vendorCSS = function(elem, property) {
  810. var result, style, vendor, _i, _len, _ref;
  811. style = getComputedStyle(elem);
  812. result = style.getPropertyCSSValue(property);
  813. _ref = this.vendors;
  814. for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  815. vendor = _ref[_i];
  816. result = result || style.getPropertyCSSValue("-" + vendor + "-" + property);
  817. }
  818. return result;
  819. };
  820. WOW.prototype.animationName = function(box) {
  821. var animationName;
  822. try {
  823. animationName = this.vendorCSS(box, 'animation-name').cssText;
  824. } catch (_error) {
  825. animationName = getComputedStyle(box).getPropertyValue('animation-name');
  826. }
  827. if (animationName === 'none') {
  828. return '';
  829. } else {
  830. return animationName;
  831. }
  832. };
  833. WOW.prototype.cacheAnimationName = function(box) {
  834. return this.animationNameCache.set(box, this.animationName(box));
  835. };
  836. WOW.prototype.cachedAnimationName = function(box) {
  837. return this.animationNameCache.get(box);
  838. };
  839. WOW.prototype.scrollHandler = function() {
  840. return this.scrolled = true;
  841. };
  842. WOW.prototype.scrollCallback = function() {
  843. var box;
  844. if (this.scrolled) {
  845. this.scrolled = false;
  846. this.boxes = (function() {
  847. var _i, _len, _ref, _results;
  848. _ref = this.boxes;
  849. _results = [];
  850. for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  851. box = _ref[_i];
  852. if (!(box)) {
  853. continue;
  854. }
  855. if (this.isVisible(box)) {
  856. this.show(box);
  857. continue;
  858. }
  859. _results.push(box);
  860. }
  861. return _results;
  862. }).call(this);
  863. if (!(this.boxes.length || this.config.live)) {
  864. return this.stop();
  865. }
  866. }
  867. };
  868. WOW.prototype.offsetTop = function(element) {
  869. var top;
  870. while (element.offsetTop === void 0) {
  871. element = element.parentNode;
  872. }
  873. top = element.offsetTop;
  874. while (element = element.offsetParent) {
  875. top += element.offsetTop;
  876. }
  877. return top;
  878. };
  879. WOW.prototype.isVisible = function(box) {
  880. var bottom, offset, top, viewBottom, viewTop;
  881. offset = box.getAttribute('data-wow-offset') || this.config.offset;
  882. viewTop = window.pageYOffset;
  883. viewBottom = viewTop + Math.min(this.element.clientHeight, this.util().innerHeight()) - offset;
  884. top = this.offsetTop(box);
  885. bottom = top + box.clientHeight;
  886. return top <= viewBottom && bottom >= viewTop;
  887. };
  888. WOW.prototype.util = function() {
  889. return this._util != null ? this._util : this._util = new Util();
  890. };
  891. WOW.prototype.disabled = function() {
  892. return !this.config.mobile && this.util().isMobile(navigator.userAgent);
  893. };
  894. return WOW;
  895. })();
  896. }).call(this);
  897. // ------------- JQUERY SMOOTHSTATE ----------------------------------------- //
  898. // ============ https://github.com/miguel-perez/jquery.smoothState.js ======= //
  899. // -------------------------------------------------------------------------- //
  900. ;(function ( $, window, document, undefined ) {
  901. "use strict";
  902. var
  903. /** Used later to scroll page to the top */
  904. $body = $("html, body"),
  905. /** Used in development mode to console out useful warnings */
  906. consl = (window.console || false),
  907. /** Plugin default options */
  908. defaults = {
  909. /** jquery element string to specify which anchors smoothstate should bind to */
  910. anchors : "a",
  911. /** If set to true, smoothState will prefetch a link's contents on hover */
  912. prefetch : false,
  913. /** A selecor that deinfes with links should be ignored by smoothState */
  914. blacklist : ".no-smoothstate, [target]",
  915. /** If set to true, smoothState will log useful debug information instead of aborting */
  916. development : false,
  917. /** The number of pages smoothState will try to store in memory and not request again */
  918. pageCacheSize : 0,
  919. /** A function that can be used to alter urls before they are used to request content */
  920. alterRequestUrl : function (url) {
  921. return url;
  922. },
  923. /** Run when a link has been activated */
  924. onStart : {
  925. duration: 0,
  926. render: function (url, $container) {
  927. $body.scrollTop(0);
  928. }
  929. },
  930. /** Run if the page request is still pending and onStart has finished animating */
  931. onProgress : {
  932. duration: 0,
  933. render: function (url, $container) {
  934. $body.css("cursor", "wait");
  935. $body.find("a").css("cursor", "wait");
  936. }
  937. },
  938. /** Run when requested content is ready to be injected into the page */
  939. onEnd : {
  940. duration: 0,
  941. render: function (url, $container, $content) {
  942. $body.css("cursor", "auto");
  943. $body.find("a").css("cursor", "auto");
  944. $container.html($content);
  945. }
  946. },
  947. /** Run when content has been injected and all animations are complete */
  948. callback : function(url, $container, $content) {
  949. }
  950. },
  951. /** Utility functions that are decoupled from SmoothState */
  952. utility = {
  953. /**
  954. * Checks to see if the url is external
  955. * @param {string} url - url being evaluated
  956. * @see http://stackoverflow.com/questions/6238351/fastest-way-to-detect-external-urls
  957. *
  958. */
  959. isExternal: function (url) {
  960. var match = url.match(/^([^:\/?#]+:)?(?:\/\/([^\/?#]*))?([^?#]+)?(\?[^#]*)?(#.*)?/);
  961. if (typeof match[1] === "string" && match[1].length > 0 && match[1].toLowerCase() !== window.location.protocol) {
  962. return true;
  963. }
  964. if (typeof match[2] === "string" && match[2].length > 0 && match[2].replace(new RegExp(":(" + {"http:": 80, "https:": 443}[window.location.protocol] + ")?$"), "") !== window.location.host) {
  965. return true;
  966. }
  967. return false;
  968. },
  969. /**
  970. * Checks to see if the url is an internal hash
  971. * @param {string} url - url being evaluated
  972. *
  973. */
  974. isHash: function (url) {
  975. var hasPathname = (url.indexOf(window.location.pathname) > 0) ? true : false,
  976. hasHash = (url.indexOf("#") > 0) ? true : false;
  977. return (hasPathname && hasHash) ? true : false;
  978. },
  979. /**
  980. * Checks to see if we should be loading this URL
  981. * @param {string} url - url being evaluated
  982. * @param {string} blacklist - jquery selector
  983. *
  984. */
  985. shouldLoad: function ($anchor, blacklist) {
  986. var url = $anchor.prop("href");
  987. // URL will only be loaded if it"s not an external link, hash, or blacklisted
  988. return (!utility.isExternal(url) && !utility.isHash(url) && !$anchor.is(blacklist));
  989. },
  990. /**
  991. * Prevents jQuery from stripping elements from $(html)
  992. * @param {string} url - url being evaluated
  993. * @author Ben Alman http://benalman.com/
  994. * @see https://gist.github.com/cowboy/742952
  995. *
  996. */
  997. htmlDoc: function (html) {
  998. var parent,
  999. elems = $(),
  1000. matchTag = /<(\/?)(html|head|body|title|base|meta)(\s+[^>]*)?>/ig,
  1001. prefix = "ss" + Math.round(Math.random() * 100000),
  1002. htmlParsed = html.replace(matchTag, function(tag, slash, name, attrs) {
  1003. var obj = {};
  1004. if (!slash) {
  1005. elems = elems.add("<" + name + "/>");
  1006. if (attrs) {
  1007. $.each($("<div" + attrs + "/>")[0].attributes, function(i, attr) {
  1008. obj[attr.name] = attr.value;
  1009. });
  1010. }
  1011. elems.eq(-1).attr(obj);
  1012. }
  1013. return "<" + slash + "div" + (slash ? "" : " id='" + prefix + (elems.length - 1) + "'") + ">";
  1014. });
  1015. // If no placeholder elements were necessary, just return normal
  1016. // jQuery-parsed HTML.
  1017. if (!elems.length) {
  1018. return $(html);
  1019. }
  1020. // Create parent node if it hasn"t been created yet.
  1021. if (!parent) {
  1022. parent = $("<div/>");
  1023. }
  1024. // Create the parent node and append the parsed, place-held HTML.
  1025. parent.html(htmlParsed);
  1026. // Replace each placeholder element with its intended element.
  1027. $.each(elems, function(i) {
  1028. var elem = parent.find("#" + prefix + i).before(elems[i]);
  1029. elems.eq(i).html(elem.contents());
  1030. elem.remove();
  1031. });
  1032. return parent.children().unwrap();
  1033. },
  1034. /**
  1035. * Resets an object if it has too many properties
  1036. *
  1037. * This is used to clear the "cache" object that stores
  1038. * all of the html. This would prevent the client from
  1039. * running out of memory and allow the user to hit the
  1040. * server for a fresh copy of the content.
  1041. *
  1042. * @param {object} obj
  1043. * @param {number} cap
  1044. *
  1045. */
  1046. clearIfOverCapacity: function (obj, cap) {
  1047. // Polyfill Object.keys if it doesn"t exist
  1048. if (!Object.keys) {
  1049. Object.keys = function (obj) {
  1050. var keys = [],
  1051. k;
  1052. for (k in obj) {
  1053. if (Object.prototype.hasOwnProperty.call(obj, k)) {
  1054. keys.push(k);
  1055. }
  1056. }
  1057. return keys;
  1058. };
  1059. }
  1060. if (Object.keys(obj).length > cap) {
  1061. obj = {};
  1062. }
  1063. return obj;
  1064. },
  1065. /**
  1066. * Finds the inner content of an element, by an ID, from a jQuery object
  1067. * @param {string} id
  1068. * @param {object} $html
  1069. *
  1070. */
  1071. getContentById: function (id, $html) {
  1072. $html = ($html instanceof jQuery) ? $html : utility.htmlDoc($html);
  1073. var $insideElem = $html.find(id),
  1074. updatedContainer = ($insideElem.length) ? $.trim($insideElem.html()) : $html.filter(id).html(),
  1075. newContent = (updatedContainer.length) ? $(updatedContainer) : null;
  1076. return newContent;
  1077. },
  1078. /**
  1079. * Stores html content as jquery object in given object
  1080. * @param {object} object - object contents will be stored into
  1081. * @param {string} url - url to be used as the prop
  1082. * @param {jquery} html - contents to store
  1083. *
  1084. */
  1085. storePageIn: function (object, url, $html) {
  1086. $html = ($html instanceof jQuery) ? $html : utility.htmlDoc($html);
  1087. object[url] = { // Content is indexed by the url
  1088. status: "loaded",
  1089. title: $html.find("title").text(), // Stores the title of the page
  1090. html: $html // Stores the contents of the page
  1091. };
  1092. return object;
  1093. },
  1094. /**
  1095. * Triggers an "allanimationend" event when all animations are complete
  1096. * @param {object} $element - jQuery object that should trigger event
  1097. * @param {string} resetOn - which other events to trigger allanimationend on
  1098. *
  1099. */
  1100. triggerAllAnimationEndEvent: function ($element, resetOn) {
  1101. resetOn = " " + resetOn || "";
  1102. var animationCount = 0,
  1103. animationstart = "animationstart webkitAnimationStart oanimationstart MSAnimationStart",
  1104. animationend = "animationend webkitAnimationEnd oanimationend MSAnimationEnd",
  1105. eventname = "allanimationend",
  1106. onAnimationStart = function (e) {
  1107. if ($(e.delegateTarget).is($element)) {
  1108. e.stopPropagation();
  1109. animationCount ++;
  1110. }
  1111. },
  1112. onAnimationEnd = function (e) {
  1113. if ($(e.delegateTarget).is($element)) {
  1114. e.stopPropagation();
  1115. animationCount --;
  1116. if(animationCount === 0) {
  1117. $element.trigger(eventname);
  1118. }
  1119. }
  1120. };
  1121. $element.on(animationstart, onAnimationStart);
  1122. $element.on(animationend, onAnimationEnd);
  1123. $element.on("allanimationend" + resetOn, function(){
  1124. animationCount = 0;
  1125. utility.redraw($element);
  1126. });
  1127. },
  1128. /** Forces browser to redraw elements */
  1129. redraw: function ($element) {
  1130. $element.height(0);
  1131. setTimeout(function(){$element.height("auto");}, 0);
  1132. }
  1133. },
  1134. /** Handles the popstate event, like when the user hits "back" */
  1135. onPopState = function ( e ) {
  1136. if(e.state !== null) {
  1137. var url = window.location.href,
  1138. $page = $("#" + e.state.id),
  1139. page = $page.data("smoothState");
  1140. if(page.href !== url && !utility.isHash(url)) {
  1141. page.load(url, true);
  1142. }
  1143. }
  1144. },
  1145. /** Constructor function */
  1146. SmoothState = function ( element, options ) {
  1147. var
  1148. /** Container element smoothState is run on */
  1149. $container = $(element),
  1150. /** Variable that stores pages after they are requested */
  1151. cache = {},
  1152. /** Url of the content that is currently displayed */
  1153. currentHref = window.location.href,
  1154. /**
  1155. * Loads the contents of a url into our container
  1156. *
  1157. * @param {string} url
  1158. * @param {bool} isPopped - used to determine if whe should
  1159. * add a new item into the history object
  1160. *
  1161. */
  1162. load = function (url, isPopped) {
  1163. /** Makes this an optional variable by setting a default */
  1164. isPopped = isPopped || false;
  1165. var
  1166. /** Used to check if the onProgress function has been run */
  1167. hasRunCallback = false,
  1168. callbBackEnded = false,
  1169. /** List of responses for the states of the page request */
  1170. responses = {
  1171. /** Page is ready, update the content */
  1172. loaded: function() {
  1173. var eventName = hasRunCallback ? "ss.onProgressEnd" : "ss.onStartEnd";
  1174. if(!callbBackEnded || !hasRunCallback) {
  1175. $container.one(eventName, function(){
  1176. updateContent(url);
  1177. });
  1178. } else if(callbBackEnded) {
  1179. updateContent(url);
  1180. }
  1181. if(!isPopped) {
  1182. window.history.pushState({ id: $container.prop("id") }, cache[url].title, url);
  1183. }
  1184. },
  1185. /** Loading, wait 10 ms and check again */
  1186. fetching: function() {
  1187. if(!hasRunCallback) {
  1188. hasRunCallback = true;
  1189. // Run the onProgress callback and set trigger
  1190. $container.one("ss.onStartEnd", function(){
  1191. options.onProgress.render(url, $container, null);
  1192. setTimeout(function(){
  1193. $container.trigger("ss.onProgressEnd");
  1194. callbBackEnded = true;
  1195. }, options.onStart.duration);
  1196. });
  1197. }
  1198. setTimeout(function () {
  1199. // Might of been canceled, better check!
  1200. if(cache.hasOwnProperty(url)){
  1201. responses[cache[url].status]();
  1202. }
  1203. }, 10);
  1204. },
  1205. /** Error, abort and redirect */
  1206. error: function(){
  1207. window.location = url;
  1208. }
  1209. };
  1210. if (!cache.hasOwnProperty(url)) {
  1211. fetch(url);
  1212. }
  1213. // Run the onStart callback and set trigger
  1214. options.onStart.render(url, $container, null);
  1215. setTimeout(function(){
  1216. $container.trigger("ss.onStartEnd");
  1217. }, options.onStart.duration);
  1218. // Start checking for the status of content
  1219. responses[cache[url].status]();
  1220. },
  1221. /** Updates the contents from cache[url] */
  1222. updateContent = function (url) {
  1223. // If the content has been requested and is done:
  1224. var containerId = "#" + $container.prop("id"),
  1225. $content = cache[url] ? utility.getContentById(containerId, cache[url].html) : null;
  1226. if($content) {
  1227. document.title = cache[url].title;
  1228. $container.data("smoothState").href = url;
  1229. // Call the onEnd callback and set trigger
  1230. options.onEnd.render(url, $container, $content);
  1231. $container.one("ss.onEndEnd", function(){
  1232. options.callback(url, $container, $content);
  1233. });
  1234. setTimeout(function(){
  1235. $container.trigger("ss.onEndEnd");
  1236. }, options.onEnd.duration);
  1237. } else if (!$content && options.development && consl) {
  1238. // Throw warning to help debug in development mode
  1239. consl.warn("No element with an id of " + containerId + " in response from " + url + " in " + cache);
  1240. } else {
  1241. // No content availble to update with, aborting...
  1242. window.location = url;
  1243. }
  1244. },
  1245. /**
  1246. * Fetches the contents of a url and stores it in the "cache" varible
  1247. * @param {string} url
  1248. *
  1249. */
  1250. fetch = function (url) {
  1251. // Don"t fetch we have the content already
  1252. if(cache.hasOwnProperty(url)) {
  1253. return;
  1254. }
  1255. cache = utility.clearIfOverCapacity(cache, options.pageCacheSize);
  1256. cache[url] = { status: "fetching" };
  1257. var requestUrl = options.alterRequestUrl(url) || url,
  1258. request = $.ajax(requestUrl);
  1259. // Store contents in cache variable if successful
  1260. request.success(function (html) {
  1261. // Clear cache varible if it"s getting too big
  1262. utility.storePageIn(cache, url, html);
  1263. $container.data("smoothState").cache = cache;
  1264. });
  1265. // Mark as error
  1266. request.error(function () {
  1267. cache[url].status = "error";
  1268. });
  1269. },
  1270. /**
  1271. * Binds to the hover event of a link, used for prefetching content
  1272. *
  1273. * @param {object} event
  1274. *
  1275. */
  1276. hoverAnchor = function (event) {
  1277. var $anchor = $(event.currentTarget),
  1278. url = $anchor.prop("href");
  1279. if (utility.shouldLoad($anchor, options.blacklist)) {
  1280. event.stopPropagation();
  1281. fetch(url);
  1282. }
  1283. },
  1284. /**
  1285. * Binds to the click event of a link, used to show the content
  1286. *
  1287. * @param {object} event
  1288. *
  1289. */
  1290. clickAnchor = function (event) {
  1291. var $anchor = $(event.currentTarget),
  1292. url = $anchor.prop("href");
  1293. // Ctrl (or Cmd) + click must open a new tab
  1294. if (!event.metaKey && !event.ctrlKey && utility.shouldLoad($anchor, options.blacklist)) {
  1295. // stopPropagation so that event doesn"t fire on parent containers.
  1296. event.stopPropagation();
  1297. event.preventDefault();
  1298. load(url);
  1299. }
  1300. },
  1301. /**
  1302. * Binds all events and inits functionality
  1303. *
  1304. * @param {object} event
  1305. *
  1306. */
  1307. bindEventHandlers = function ($element) {
  1308. //@todo: Handle form submissions
  1309. $element.on("click", options.anchors, clickAnchor);
  1310. if (options.prefetch) {
  1311. $element.on("mouseover touchstart", options.anchors, hoverAnchor);
  1312. }
  1313. },
  1314. /** Used to restart css animations with a class */
  1315. toggleAnimationClass = function (classname) {
  1316. var classes = $container.addClass(classname).prop("class");
  1317. $container.removeClass(classes);
  1318. setTimeout(function(){
  1319. $container.addClass(classes);
  1320. },0);
  1321. $container.one("ss.onStartEnd ss.onProgressEnd ss.onEndEnd", function(){
  1322. $container.removeClass(classname);
  1323. });
  1324. };
  1325. /** Override defaults with options passed in */
  1326. options = $.extend(defaults, options);
  1327. /** Sets a default state */
  1328. if(window.history.state === null) {
  1329. window.history.replaceState({ id: $container.prop("id") }, document.title, currentHref);
  1330. }
  1331. /** Stores the current page in cache variable */
  1332. utility.storePageIn(cache, currentHref, document.documentElement.outerHTML);
  1333. /** Bind all of the event handlers on the container, not anchors */
  1334. utility.triggerAllAnimationEndEvent($container, "ss.onStartEnd ss.onProgressEnd ss.onEndEnd");
  1335. /** Bind all of the event handlers on the container, not anchors */
  1336. bindEventHandlers($container);
  1337. /** Public methods */
  1338. return {
  1339. href: currentHref,
  1340. cache: cache,
  1341. load: load,
  1342. fetch: fetch,
  1343. toggleAnimationClass: toggleAnimationClass
  1344. };
  1345. },
  1346. /** Returns elements with SmoothState attached to it */
  1347. declareSmoothState = function ( options ) {
  1348. return this.each(function () {
  1349. // Checks to make sure the smoothState element has an id and isn"t already bound
  1350. if(this.id && !$.data(this, "smoothState")) {
  1351. // Makes public methods available via $("element").data("smoothState");
  1352. $.data(this, "smoothState", new SmoothState(this, options));
  1353. } else if (!this.id && consl) {
  1354. // Throw warning if in development mode
  1355. consl.warn("Every smoothState container needs an id but the following one does not have one:", this);
  1356. }
  1357. });
  1358. };
  1359. /** Sets the popstate function */
  1360. window.onpopstate = onPopState;
  1361. /** Makes utility functions public for unit tests */
  1362. $.smoothStateUtility = utility;
  1363. /** Defines the smoothState plugin */
  1364. $.fn.smoothState = declareSmoothState;
  1365. })(jQuery, window, document);