scripts.js 63 KB

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