summaryrefslogtreecommitdiff
path: root/studio-susie/public/assets/js
diff options
context:
space:
mode:
Diffstat (limited to 'studio-susie/public/assets/js')
-rw-r--r--studio-susie/public/assets/js/app.js108
-rw-r--r--studio-susie/public/assets/js/lib/_router.js83
-rw-r--r--studio-susie/public/assets/js/lib/nav/DesktopNav.js43
-rw-r--r--studio-susie/public/assets/js/lib/nav/MobileNav.js32
-rw-r--r--studio-susie/public/assets/js/lib/view/HomeView.js27
-rw-r--r--studio-susie/public/assets/js/lib/view/ListView.js37
-rw-r--r--studio-susie/public/assets/js/lib/view/PageView.js41
-rw-r--r--studio-susie/public/assets/js/lib/view/PaintingView.js32
-rw-r--r--studio-susie/public/assets/js/vendor/confetti.js122
-rw-r--r--studio-susie/public/assets/js/vendor/es5-shim.min.js6
-rw-r--r--studio-susie/public/assets/js/vendor/fastclick.js790
-rw-r--r--studio-susie/public/assets/js/vendor/froogaloop.js287
-rw-r--r--studio-susie/public/assets/js/vendor/hammer.min.js6
-rw-r--r--studio-susie/public/assets/js/vendor/history.min.js1
-rw-r--r--studio-susie/public/assets/js/vendor/html5shiv.min.js4
-rw-r--r--studio-susie/public/assets/js/vendor/iscroll.js2011
-rw-r--r--studio-susie/public/assets/js/vendor/jquery.fullpage.js3079
-rw-r--r--studio-susie/public/assets/js/vendor/liquid-lite.min.js2
-rwxr-xr-xstudio-susie/public/assets/js/vendor/loader.js99
-rw-r--r--studio-susie/public/assets/js/vendor/lodash.min.js98
-rw-r--r--studio-susie/public/assets/js/vendor/okcms.js45
-rw-r--r--studio-susie/public/assets/js/vendor/oktween.js159
-rw-r--r--studio-susie/public/assets/js/vendor/prefixfree.min.js18
-rw-r--r--studio-susie/public/assets/js/vendor/util.js200
-rw-r--r--studio-susie/public/assets/js/vendor/view/OKTmplView.js97
-rw-r--r--studio-susie/public/assets/js/vendor/view/Router.js82
-rw-r--r--studio-susie/public/assets/js/vendor/view/ScrollableView.js31
-rw-r--r--studio-susie/public/assets/js/vendor/view/View.js150
28 files changed, 7690 insertions, 0 deletions
diff --git a/studio-susie/public/assets/js/app.js b/studio-susie/public/assets/js/app.js
new file mode 100644
index 0000000..0f64ad2
--- /dev/null
+++ b/studio-susie/public/assets/js/app.js
@@ -0,0 +1,108 @@
+var app = (function() {
+
+ var app = {}
+ var last_t = 0, initial_t = 0
+
+ app.init = function() {
+ app.loader = new Loader ()
+ app.okcms = new OKCMS ()
+ app.okcms.getAll().done(function(data) {
+ app.bind()
+ app.build(data)
+ app.resize()
+ app.ready()
+ }).fail(function(err) {
+ console.error('error loading cms', err)
+ })
+ }
+
+ app.bind = function() {
+ if (is_mobile) {
+ document.addEventListener('touchmove', function(e) {
+ e.preventDefault()
+ })
+ FastClick.attach(document.body)
+ }
+ $(window).resize(app.resize)
+ }
+
+ app.build = function(data) {
+ window.scrollTo(0,0)
+ app.views = {}
+ app.nav = new NavView ()
+ app.views.home = new HomeView({
+ data: data.home
+ })
+ app.views.page = new PageView({
+ data: data.page
+ })
+ app.views.painting = new PaintingView({
+ data: data.painting
+ })
+ app.views.list = new ListView({
+ })
+
+ app.preload()
+ }
+
+ app.preload = function(){
+ var $sections = $("#fullpage .section")
+ var $first = $sections.first()
+ app.loader.preloadImage( $first.data("image"), function(){
+ $sections.each(function(index){
+ var img = new Image ()
+ var $div = $("<div>")
+ $div.data("index", index)
+ $("#list").append($div)
+ var url = $(this).data("image")
+ var loaded = false
+ var $el = $(this)
+ img.onload = function(){
+ $el.css("background-image", "url(" + url + ")")
+ $div.css("background-image", "url(" + url + ")")
+ }
+ img.src = url
+ })
+ $('#fullpage').fullpage({
+ css3: true,
+ scrollingSpeed: 1000
+ })
+ })
+ }
+
+ app.ready = function() {
+ if (last_t) return
+ setTimeout(function () {
+ $("html").removeClass("loading")
+ }, 50)
+ app.view = null
+ app.router = new SiteRouter()
+ app.router.launch()
+ // app.animate(0)
+ }
+
+ app.animate = function (t) {
+ requestAnimationFrame(app.animate)
+ if (! initial_t) {
+ initial_t = t
+ return
+ }
+ t -= initial_t
+ var dt = t - last_t
+ last_t = t
+ }
+
+ app.resize = function () {
+ }
+
+ app.iscroll_options = {
+ mouseWheel: true,
+ scrollbars: true,
+ click: is_android,
+ }
+
+ return app
+
+})()
+
+document.addEventListener('DOMContentLoaded', app.init)
diff --git a/studio-susie/public/assets/js/lib/_router.js b/studio-susie/public/assets/js/lib/_router.js
new file mode 100644
index 0000000..8d27b9c
--- /dev/null
+++ b/studio-susie/public/assets/js/lib/_router.js
@@ -0,0 +1,83 @@
+var SiteRouter = Router.extend({
+
+ el: 'body',
+ routeByHash: false,
+
+ routes: {
+ '/': 'home',
+ '/page/:id': 'pageById',
+ '/painting/:id': 'paintingById',
+ '/picture/:id': 'paintingById',
+ '/paintings': 'list',
+ '/pictures': 'list',
+ },
+
+ initialize: function(){
+ var fn
+ for (var route in this.routes) {
+ fn = this.routes[route]
+ if (! this[fn]) {
+ this[fn] = this.default_view(fn)
+ }
+ }
+ },
+
+ initial_route: null,
+ launch: function(){
+ if (this.initial_route) {
+ this.parseRoute( this.initial_route )
+ }
+ else {
+ this.route()
+ }
+ this.initial_route = null
+ },
+
+ go: function(url){
+ if (app.view && app.view.hide) {
+ app.view.hide()
+ }
+ this.pushState(url)
+ this.parseRoute(url)
+ },
+
+ default_view: function(name){
+ var fn = function(){
+ if (app.view != app.login && app.view != app.signin) {
+ app.last_view = app.view
+ }
+ if (app.view && app.view.hide) {
+ app.view.hide()
+ }
+ if (name.match(/\./)) {
+ var n = name.split(".")
+ app.view = app.views[n[0]][n[1]]
+ }
+ else {
+ app.view = app.views[name]
+ }
+ app.view.show()
+ }.bind(this)
+ return fn
+ },
+
+ paintingById: function(id){
+ if (app.view && app.view.hide) {
+ app.view.hide()
+ }
+ app.view = app.views.painting
+ app.views.painting.show()
+ app.views.painting.load(id)
+ },
+
+ pageById: function(id){
+ if (app.view && app.view.hide) {
+ app.view.hide()
+ }
+ app.view = app.views.page
+ app.views.page.show()
+ app.views.page.load(id)
+ }
+
+})
+
diff --git a/studio-susie/public/assets/js/lib/nav/DesktopNav.js b/studio-susie/public/assets/js/lib/nav/DesktopNav.js
new file mode 100644
index 0000000..5d00c23
--- /dev/null
+++ b/studio-susie/public/assets/js/lib/nav/DesktopNav.js
@@ -0,0 +1,43 @@
+var NavView = View.extend({
+
+ el: "#mobile-nav",
+
+ events: {
+ "click .pages a": "go",
+ },
+
+ initialize: function(){
+ },
+
+ home: function(){
+ app.router.go("/")
+ this.$headings.find(".active").removeClass("active")
+ if (app.mobile_nav && app.mobile_nav.state.open) {
+ app.mobile_nav.hamburger()
+ }
+ },
+
+ go: function(e){
+ e.preventDefault()
+ var href = $(e.currentTarget).attr("href")
+ app.router.go(href)
+ console.log(href)
+ if (is_mobile) {
+ app.mobile_nav.hamburger()
+ }
+ this.after_go()
+ },
+
+ after_go: function(){
+ },
+
+ setActive: function(id){
+ var href = '/' + id
+ var $el = $('[href="' + href + '"]')
+ this.$('.active').removeClass('active')
+ if ($el.length) {
+ $el.addClass('active')
+ }
+ },
+
+});
diff --git a/studio-susie/public/assets/js/lib/nav/MobileNav.js b/studio-susie/public/assets/js/lib/nav/MobileNav.js
new file mode 100644
index 0000000..5c0f253
--- /dev/null
+++ b/studio-susie/public/assets/js/lib/nav/MobileNav.js
@@ -0,0 +1,32 @@
+var MobileNav = View.extend({
+
+ el: '#mobile_nav',
+
+ events: {
+ 'touchstart .logo': 'home',
+ 'touchstart .hamburger': 'hamburger'
+ },
+
+ initialize: function(options){
+ options = options || {}
+ this.state = {
+ open: false
+ }
+ },
+
+ home: function (){
+ app.nav.home()
+ },
+
+ hamburger: function (e){
+ $('html').toggleClass('navopen')
+ app.mobile_nav.state.open = ! app.mobile_nav.state.open
+ if (app.mobile_nav.state.open) {
+ $("#rapper").on("click", app.mobile_nav.hamburger)
+ }
+ else {
+ $("#rapper").off("click", app.mobile_nav.hamburger)
+ }
+ },
+
+})
diff --git a/studio-susie/public/assets/js/lib/view/HomeView.js b/studio-susie/public/assets/js/lib/view/HomeView.js
new file mode 100644
index 0000000..3eac71e
--- /dev/null
+++ b/studio-susie/public/assets/js/lib/view/HomeView.js
@@ -0,0 +1,27 @@
+var HomeView = View.extend({
+
+ el: "#home",
+
+ // template: liquid($('#tmpl-home').html()),
+
+ events: {
+ },
+
+ initialize: function(options){
+ options = options || {}
+ var data = this.data = options.data
+ },
+
+ render: function(){
+ if (this.rendered) return
+ this.rendered = true
+ },
+
+ show: function(){
+ this.render(this.data)
+ },
+
+ hide: function(){
+ },
+
+})
diff --git a/studio-susie/public/assets/js/lib/view/ListView.js b/studio-susie/public/assets/js/lib/view/ListView.js
new file mode 100644
index 0000000..5161a31
--- /dev/null
+++ b/studio-susie/public/assets/js/lib/view/ListView.js
@@ -0,0 +1,37 @@
+var ListView = View.extend({
+
+ el: "#list",
+
+ events: {
+ "click div": "load",
+ },
+
+ initialize: function(options){
+ options = options || {}
+ var data = this.data = options.data
+ },
+
+ render: function(){
+ if (this.rendered) return
+ this.rendered = true
+ },
+
+ show: function(){
+ this.render(this.data)
+ document.body.className = "listopen"
+ },
+
+ hide: function(){
+ document.body.className = ""
+ $(".visible").removeClass("visible")
+ $("#nav a.active").removeClass('active')
+ },
+
+ load: function(e){
+ var index = $(e.currentTarget).data("index")
+ $.fn.fullpage.moveTo(index+1)
+ console.log(index)
+ this.hide()
+ },
+
+})
diff --git a/studio-susie/public/assets/js/lib/view/PageView.js b/studio-susie/public/assets/js/lib/view/PageView.js
new file mode 100644
index 0000000..d69328e
--- /dev/null
+++ b/studio-susie/public/assets/js/lib/view/PageView.js
@@ -0,0 +1,41 @@
+var PageView = View.extend({
+
+ el: "body",
+
+ events: {
+ "click #close": "close",
+ },
+
+ initialize: function(options){
+ options = options || {}
+ var data = this.data = options.data
+ },
+
+ render: function(){
+ if (this.rendered) return
+ this.rendered = true
+ },
+
+ show: function(){
+ this.render(this.data)
+ document.body.className = "pageopen"
+ MAKE_CONFETTI()
+ },
+
+ hide: function(){
+ document.body.className = ""
+ $(".visible").removeClass("visible")
+ $("#nav a.active").removeClass('active')
+ },
+
+ close: function(){
+ app.router.go("/")
+ },
+
+ load: function(id){
+ $("#nav a[href='/page/" + id + "']").addClass('active')
+ this.$("#" + id).addClass("visible")
+ },
+
+
+})
diff --git a/studio-susie/public/assets/js/lib/view/PaintingView.js b/studio-susie/public/assets/js/lib/view/PaintingView.js
new file mode 100644
index 0000000..1fdc179
--- /dev/null
+++ b/studio-susie/public/assets/js/lib/view/PaintingView.js
@@ -0,0 +1,32 @@
+var PaintingView = View.extend({
+
+ el: "body",
+
+ // template: liquid($('#tmpl-about').html()),
+
+ events: {
+ },
+
+ initialize: function(options){
+ options = options || {}
+ var data = this.data = options.data
+ },
+
+ render: function(){
+ if (this.rendered) return
+ this.rendered = true
+ },
+
+ show: function(){
+ this.render(this.data)
+ document.body.className = "painting"
+ },
+
+ hide: function(){
+ // document.body.className = "about"
+ },
+
+ load: function(id){
+ },
+
+})
diff --git a/studio-susie/public/assets/js/vendor/confetti.js b/studio-susie/public/assets/js/vendor/confetti.js
new file mode 100644
index 0000000..d7eaeb2
--- /dev/null
+++ b/studio-susie/public/assets/js/vendor/confetti.js
@@ -0,0 +1,122 @@
+var made_confetti = false
+function MAKE_CONFETTI() {
+ if (made_confetti) return
+ made_confetti = true
+
+ var COLORS, Confetti, NUM_CONFETTI, PI_2, canvas, confetti, context, drawCircle, i, range, resizeWindow, xpos;
+
+ NUM_CONFETTI = 350;
+
+ COLORS = [[254, 163, 170], [248, 184, 139], [250, 248, 132], [186, 237, 145], [178, 206, 254], [242, 162, 232]];
+
+ PI_2 = 2 * Math.PI;
+
+ var canvas = document.createElement("canvas")
+ $("#rapper").append(canvas)
+
+ if (! canvas) return;
+
+ context = canvas.getContext("2d");
+
+ window.w = 0;
+
+ window.h = 0;
+
+ resizeWindow = function() {
+ window.w = canvas.width = window.innerWidth;
+ return window.h = canvas.height = window.innerHeight;
+ };
+
+ window.addEventListener('resize', resizeWindow, false);
+
+ setTimeout(resizeWindow, 0);
+
+ range = function(a, b) {
+ return (b - a) * Math.random() + a;
+ };
+
+ drawCircle = function(x, y, r, style) {
+ context.beginPath();
+ context.arc(x, y, r, 0, PI_2, false);
+ context.fillStyle = style;
+ return context.fill();
+ };
+
+ xpos = 0.5;
+
+ document.onmousemove = function(e) {
+ return xpos = e.pageX / w;
+ };
+
+ window.requestAnimationFrame = (function() {
+ return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(callback) {
+ return window.setTimeout(callback, 1000 / 60);
+ };
+ })();
+
+ Confetti = (function() {
+ function Confetti() {
+ this.style = COLORS[~~range(0, 5)];
+ this.rgb = "rgba(" + this.style[0] + "," + this.style[1] + "," + this.style[2];
+ this.r = ~~range(2, 6);
+ this.r2 = 2 * this.r;
+ this.replace();
+ }
+
+ Confetti.prototype.replace = function() {
+ this.opacity = 0;
+ this.dop = 0.03 * range(1, 4);
+ this.x = range(-this.r2, w - this.r2);
+ this.y = range(-20, h - this.r2);
+ this.xmax = w - this.r;
+ this.ymax = h - this.r;
+ this.vx = range(0, 2) + 8 * xpos - 5;
+ return this.vy = 0.7 * this.r + range(-1, 1);
+ };
+
+ Confetti.prototype.draw = function() {
+ var ref;
+ this.x += this.vx;
+ this.y += this.vy;
+ this.opacity += this.dop;
+ if (this.opacity > 1) {
+ this.opacity = 1;
+ this.dop *= -1;
+ }
+ if (this.opacity < 0 || this.y > this.ymax) {
+ this.replace();
+ }
+ if (!((0 < (ref = this.x) && ref < this.xmax))) {
+ this.x = (this.x + this.xmax) % this.xmax;
+ }
+ return drawCircle(~~this.x, ~~this.y, this.r, this.rgb + "," + this.opacity + ")");
+ };
+
+ return Confetti;
+
+ })();
+
+ confetti = (function() {
+ var j, ref, results;
+ results = [];
+ for (i = j = 1, ref = NUM_CONFETTI; 1 <= ref ? j <= ref : j >= ref; i = 1 <= ref ? ++j : --j) {
+ results.push(new Confetti);
+ }
+ return results;
+ })();
+
+ confetti_step = function() {
+ var c, j, len, results;
+ requestAnimationFrame(confetti_step);
+ context.clearRect(0, 0, w, h);
+ results = [];
+ for (j = 0, len = confetti.length; j < len; j++) {
+ c = confetti[j];
+ results.push(c.draw());
+ }
+ return results;
+ };
+
+ confetti_step();
+
+} \ No newline at end of file
diff --git a/studio-susie/public/assets/js/vendor/es5-shim.min.js b/studio-susie/public/assets/js/vendor/es5-shim.min.js
new file mode 100644
index 0000000..bec775e
--- /dev/null
+++ b/studio-susie/public/assets/js/vendor/es5-shim.min.js
@@ -0,0 +1,6 @@
+/*!
+ * https://github.com/es-shims/es5-shim
+ * @license es5-shim Copyright 2009-2015 by contributors, MIT License
+ * see https://github.com/es-shims/es5-shim/blob/v4.4.0/LICENSE
+ */
+(function(r,t){"use strict";if(typeof define==="function"&&define.amd){define(t)}else if(typeof exports==="object"){module.exports=t()}else{r.returnExports=t()}})(this,function(){var r=Array;var t=r.prototype;var e=Object;var n=e.prototype;var i=Function.prototype;var a=String;var o=a.prototype;var u=Number;var f=u.prototype;var l=t.slice;var s=t.splice;var c=t.push;var v=t.unshift;var p=t.concat;var h=i.call;var g=i.apply;var y=Math.max;var d=Math.min;var m=n.toString;var w=typeof Symbol==="function"&&typeof Symbol.toStringTag==="symbol";var b;var T=Function.prototype.toString,x=function tryFunctionObject(r){try{T.call(r);return true}catch(t){return false}},O="[object Function]",S="[object GeneratorFunction]";b=function isCallable(r){if(typeof r!=="function"){return false}if(w){return x(r)}var t=m.call(r);return t===O||t===S};var E;var j=RegExp.prototype.exec,I=function tryRegexExec(r){try{j.call(r);return true}catch(t){return false}},D="[object RegExp]";E=function isRegex(r){if(typeof r!=="object"){return false}return w?I(r):m.call(r)===D};var N;var k=String.prototype.valueOf,M=function tryStringObject(r){try{k.call(r);return true}catch(t){return false}},U="[object String]";N=function isString(r){if(typeof r==="string"){return true}if(typeof r!=="object"){return false}return w?M(r):m.call(r)===U};var R=e.defineProperty&&function(){try{var r={};e.defineProperty(r,"x",{enumerable:false,value:r});for(var t in r){return false}return r.x===r}catch(n){return false}}();var F=function(r){var t;if(R){t=function(r,t,n,i){if(!i&&t in r){return}e.defineProperty(r,t,{configurable:true,enumerable:false,writable:true,value:n})}}else{t=function(r,t,e,n){if(!n&&t in r){return}r[t]=e}}return function defineProperties(e,n,i){for(var a in n){if(r.call(n,a)){t(e,a,n[a],i)}}}}(n.hasOwnProperty);var A=function isPrimitive(r){var t=typeof r;return r===null||t!=="object"&&t!=="function"};var P=u.isNaN||function(r){return r!==r};var $={ToInteger:function ToInteger(r){var t=+r;if(P(t)){t=0}else if(t!==0&&t!==1/0&&t!==-(1/0)){t=(t>0||-1)*Math.floor(Math.abs(t))}return t},ToPrimitive:function ToPrimitive(r){var t,e,n;if(A(r)){return r}e=r.valueOf;if(b(e)){t=e.call(r);if(A(t)){return t}}n=r.toString;if(b(n)){t=n.call(r);if(A(t)){return t}}throw new TypeError},ToObject:function(r){if(r==null){throw new TypeError("can't convert "+r+" to object")}return e(r)},ToUint32:function ToUint32(r){return r>>>0}};var C=function Empty(){};F(i,{bind:function bind(r){var t=this;if(!b(t)){throw new TypeError("Function.prototype.bind called on incompatible "+t)}var n=l.call(arguments,1);var i;var a=function(){if(this instanceof i){var a=t.apply(this,p.call(n,l.call(arguments)));if(e(a)===a){return a}return this}else{return t.apply(r,p.call(n,l.call(arguments)))}};var o=y(0,t.length-n.length);var u=[];for(var f=0;f<o;f++){c.call(u,"$"+f)}i=Function("binder","return function ("+u.join(",")+"){ return binder.apply(this, arguments); }")(a);if(t.prototype){C.prototype=t.prototype;i.prototype=new C;C.prototype=null}return i}});var Z=h.bind(n.hasOwnProperty);var J=h.bind(n.toString);var z=h.bind(l);var B=g.bind(l);var G=h.bind(o.slice);var H=h.bind(o.split);var L=h.bind(o.indexOf);var X=h.bind(c);var Y=h.bind(n.propertyIsEnumerable);var q=h.bind(t.sort);var K=r.isArray||function isArray(r){return J(r)==="[object Array]"};var Q=[].unshift(0)!==1;F(t,{unshift:function(){v.apply(this,arguments);return this.length}},Q);F(r,{isArray:K});var V=e("a");var W=V[0]!=="a"||!(0 in V);var _=function properlyBoxed(r){var t=true;var e=true;if(r){r.call("foo",function(r,e,n){if(typeof n!=="object"){t=false}});r.call([1],function(){"use strict";e=typeof this==="string"},"x")}return!!r&&t&&e};F(t,{forEach:function forEach(r){var t=$.ToObject(this);var e=W&&N(this)?H(this,""):t;var n=-1;var i=$.ToUint32(e.length);var a;if(arguments.length>1){a=arguments[1]}if(!b(r)){throw new TypeError("Array.prototype.forEach callback must be a function")}while(++n<i){if(n in e){if(typeof a==="undefined"){r(e[n],n,t)}else{r.call(a,e[n],n,t)}}}}},!_(t.forEach));F(t,{map:function map(t){var e=$.ToObject(this);var n=W&&N(this)?H(this,""):e;var i=$.ToUint32(n.length);var a=r(i);var o;if(arguments.length>1){o=arguments[1]}if(!b(t)){throw new TypeError("Array.prototype.map callback must be a function")}for(var u=0;u<i;u++){if(u in n){if(typeof o==="undefined"){a[u]=t(n[u],u,e)}else{a[u]=t.call(o,n[u],u,e)}}}return a}},!_(t.map));F(t,{filter:function filter(r){var t=$.ToObject(this);var e=W&&N(this)?H(this,""):t;var n=$.ToUint32(e.length);var i=[];var a;var o;if(arguments.length>1){o=arguments[1]}if(!b(r)){throw new TypeError("Array.prototype.filter callback must be a function")}for(var u=0;u<n;u++){if(u in e){a=e[u];if(typeof o==="undefined"?r(a,u,t):r.call(o,a,u,t)){X(i,a)}}}return i}},!_(t.filter));F(t,{every:function every(r){var t=$.ToObject(this);var e=W&&N(this)?H(this,""):t;var n=$.ToUint32(e.length);var i;if(arguments.length>1){i=arguments[1]}if(!b(r)){throw new TypeError("Array.prototype.every callback must be a function")}for(var a=0;a<n;a++){if(a in e&&!(typeof i==="undefined"?r(e[a],a,t):r.call(i,e[a],a,t))){return false}}return true}},!_(t.every));F(t,{some:function some(r){var t=$.ToObject(this);var e=W&&N(this)?H(this,""):t;var n=$.ToUint32(e.length);var i;if(arguments.length>1){i=arguments[1]}if(!b(r)){throw new TypeError("Array.prototype.some callback must be a function")}for(var a=0;a<n;a++){if(a in e&&(typeof i==="undefined"?r(e[a],a,t):r.call(i,e[a],a,t))){return true}}return false}},!_(t.some));var rr=false;if(t.reduce){rr=typeof t.reduce.call("es5",function(r,t,e,n){return n})==="object"}F(t,{reduce:function reduce(r){var t=$.ToObject(this);var e=W&&N(this)?H(this,""):t;var n=$.ToUint32(e.length);if(!b(r)){throw new TypeError("Array.prototype.reduce callback must be a function")}if(n===0&&arguments.length===1){throw new TypeError("reduce of empty array with no initial value")}var i=0;var a;if(arguments.length>=2){a=arguments[1]}else{do{if(i in e){a=e[i++];break}if(++i>=n){throw new TypeError("reduce of empty array with no initial value")}}while(true)}for(;i<n;i++){if(i in e){a=r(a,e[i],i,t)}}return a}},!rr);var tr=false;if(t.reduceRight){tr=typeof t.reduceRight.call("es5",function(r,t,e,n){return n})==="object"}F(t,{reduceRight:function reduceRight(r){var t=$.ToObject(this);var e=W&&N(this)?H(this,""):t;var n=$.ToUint32(e.length);if(!b(r)){throw new TypeError("Array.prototype.reduceRight callback must be a function")}if(n===0&&arguments.length===1){throw new TypeError("reduceRight of empty array with no initial value")}var i;var a=n-1;if(arguments.length>=2){i=arguments[1]}else{do{if(a in e){i=e[a--];break}if(--a<0){throw new TypeError("reduceRight of empty array with no initial value")}}while(true)}if(a<0){return i}do{if(a in e){i=r(i,e[a],a,t)}}while(a--);return i}},!tr);var er=t.indexOf&&[0,1].indexOf(1,2)!==-1;F(t,{indexOf:function indexOf(r){var t=W&&N(this)?H(this,""):$.ToObject(this);var e=$.ToUint32(t.length);if(e===0){return-1}var n=0;if(arguments.length>1){n=$.ToInteger(arguments[1])}n=n>=0?n:y(0,e+n);for(;n<e;n++){if(n in t&&t[n]===r){return n}}return-1}},er);var nr=t.lastIndexOf&&[0,1].lastIndexOf(0,-3)!==-1;F(t,{lastIndexOf:function lastIndexOf(r){var t=W&&N(this)?H(this,""):$.ToObject(this);var e=$.ToUint32(t.length);if(e===0){return-1}var n=e-1;if(arguments.length>1){n=d(n,$.ToInteger(arguments[1]))}n=n>=0?n:e-Math.abs(n);for(;n>=0;n--){if(n in t&&r===t[n]){return n}}return-1}},nr);var ir=function(){var r=[1,2];var t=r.splice();return r.length===2&&K(t)&&t.length===0}();F(t,{splice:function splice(r,t){if(arguments.length===0){return[]}else{return s.apply(this,arguments)}}},!ir);var ar=function(){var r={};t.splice.call(r,0,0,1);return r.length===1}();F(t,{splice:function splice(r,t){if(arguments.length===0){return[]}var e=arguments;this.length=y($.ToInteger(this.length),0);if(arguments.length>0&&typeof t!=="number"){e=z(arguments);if(e.length<2){X(e,this.length-r)}else{e[1]=$.ToInteger(t)}}return s.apply(this,e)}},!ar);var or=function(){var t=new r(1e5);t[8]="x";t.splice(1,1);return t.indexOf("x")===7}();var ur=function(){var r=256;var t=[];t[r]="a";t.splice(r+1,0,"b");return t[r]==="a"}();F(t,{splice:function splice(r,t){var e=$.ToObject(this);var n=[];var i=$.ToUint32(e.length);var o=$.ToInteger(r);var u=o<0?y(i+o,0):d(o,i);var f=d(y($.ToInteger(t),0),i-u);var l=0;var s;while(l<f){s=a(u+l);if(Z(e,s)){n[l]=e[s]}l+=1}var c=z(arguments,2);var v=c.length;var p;if(v<f){l=u;while(l<i-f){s=a(l+f);p=a(l+v);if(Z(e,s)){e[p]=e[s]}else{delete e[p]}l+=1}l=i;while(l>i-f+v){delete e[l-1];l-=1}}else if(v>f){l=i-f;while(l>u){s=a(l+f-1);p=a(l+v-1);if(Z(e,s)){e[p]=e[s]}else{delete e[p]}l-=1}}l=u;for(var h=0;h<c.length;++h){e[l]=c[h];l+=1}e.length=i-f+v;return n}},!or||!ur);var fr=t.join;var lr=Array.prototype.join.call("123",",")!=="1,2,3";if(lr){F(t,{join:function join(r){var t=typeof r==="undefined"?",":r;return fr.call(N(this)?H(this,""):this,t)}},lr)}var sr=[1,2].join(undefined)!=="1,2";if(sr){F(t,{join:function join(r){var t=typeof r==="undefined"?",":r;return fr.call(this,t)}},sr)}var cr=function push(r){var t=$.ToObject(this);var e=$.ToUint32(t.length);var n=0;while(n<arguments.length){t[e+n]=arguments[n];n+=1}t.length=e+n;return e+n};var vr=function(){var r={};var t=Array.prototype.push.call(r,undefined);return t!==1||r.length!==1||typeof r[0]!=="undefined"||!Z(r,0)}();F(t,{push:function push(r){if(K(this)){return c.apply(this,arguments)}return cr.apply(this,arguments)}},vr);var pr=function(){var r=[];var t=r.push(undefined);return t!==1||r.length!==1||typeof r[0]!=="undefined"||!Z(r,0)}();F(t,{push:cr},pr);F(t,{slice:function(r,t){var e=N(this)?H(this,""):this;return B(e,arguments)}},W);var hr=function(){try{[1,2].sort(null);[1,2].sort({});return true}catch(r){}return false}();var gr=function(){try{[1,2].sort(/a/);return false}catch(r){}return true}();var yr=function(){try{[1,2].sort(undefined);return true}catch(r){}return false}();F(t,{sort:function sort(r){if(typeof r==="undefined"){return q(this)}if(!b(r)){throw new TypeError("Array.prototype.sort callback must be a function")}return q(this,r)}},hr||!yr||!gr);var dr=!{toString:null}.propertyIsEnumerable("toString");var mr=function(){}.propertyIsEnumerable("prototype");var wr=!Z("x","0");var br=function(r){var t=r.constructor;return t&&t.prototype===r};var Tr={$window:true,$console:true,$parent:true,$self:true,$frame:true,$frames:true,$frameElement:true,$webkitIndexedDB:true,$webkitStorageInfo:true,$external:true};var xr=function(){if(typeof window==="undefined"){return false}for(var r in window){try{if(!Tr["$"+r]&&Z(window,r)&&window[r]!==null&&typeof window[r]==="object"){br(window[r])}}catch(t){return true}}return false}();var Or=function(r){if(typeof window==="undefined"||!xr){return br(r)}try{return br(r)}catch(t){return false}};var Sr=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"];var Er=Sr.length;var jr=function isArguments(r){return J(r)==="[object Arguments]"};var Ir=function isArguments(r){return r!==null&&typeof r==="object"&&typeof r.length==="number"&&r.length>=0&&!K(r)&&b(r.callee)};var Dr=jr(arguments)?jr:Ir;F(e,{keys:function keys(r){var t=b(r);var e=Dr(r);var n=r!==null&&typeof r==="object";var i=n&&N(r);if(!n&&!t&&!e){throw new TypeError("Object.keys called on a non-object")}var o=[];var u=mr&&t;if(i&&wr||e){for(var f=0;f<r.length;++f){X(o,a(f))}}if(!e){for(var l in r){if(!(u&&l==="prototype")&&Z(r,l)){X(o,a(l))}}}if(dr){var s=Or(r);for(var c=0;c<Er;c++){var v=Sr[c];if(!(s&&v==="constructor")&&Z(r,v)){X(o,v)}}}return o}});var Nr=e.keys&&function(){return e.keys(arguments).length===2}(1,2);var kr=e.keys&&function(){var r=e.keys(arguments);return arguments.length!==1||r.length!==1||r[0]!==1}(1);var Mr=e.keys;F(e,{keys:function keys(r){if(Dr(r)){return Mr(z(r))}else{return Mr(r)}}},!Nr||kr);var Ur=-621987552e5;var Rr="-000001";var Fr=Date.prototype.toISOString&&new Date(Ur).toISOString().indexOf(Rr)===-1;var Ar=Date.prototype.toISOString&&new Date(-1).toISOString()!=="1969-12-31T23:59:59.999Z";F(Date.prototype,{toISOString:function toISOString(){var r,t,e,n,i;if(!isFinite(this)){throw new RangeError("Date.prototype.toISOString called on non-finite value.")}n=this.getUTCFullYear();i=this.getUTCMonth();n+=Math.floor(i/12);i=(i%12+12)%12;r=[i+1,this.getUTCDate(),this.getUTCHours(),this.getUTCMinutes(),this.getUTCSeconds()];n=(n<0?"-":n>9999?"+":"")+G("00000"+Math.abs(n),0<=n&&n<=9999?-4:-6);t=r.length;while(t--){e=r[t];if(e<10){r[t]="0"+e}}return n+"-"+z(r,0,2).join("-")+"T"+z(r,2).join(":")+"."+G("000"+this.getUTCMilliseconds(),-3)+"Z"}},Fr||Ar);var Pr=function(){try{return Date.prototype.toJSON&&new Date(NaN).toJSON()===null&&new Date(Ur).toJSON().indexOf(Rr)!==-1&&Date.prototype.toJSON.call({toISOString:function(){return true}})}catch(r){return false}}();if(!Pr){Date.prototype.toJSON=function toJSON(r){var t=e(this);var n=$.ToPrimitive(t);if(typeof n==="number"&&!isFinite(n)){return null}var i=t.toISOString;if(!b(i)){throw new TypeError("toISOString property is not callable")}return i.call(t)}}var $r=Date.parse("+033658-09-27T01:46:40.000Z")===1e15;var Cr=!isNaN(Date.parse("2012-04-04T24:00:00.500Z"))||!isNaN(Date.parse("2012-11-31T23:59:59.000Z"))||!isNaN(Date.parse("2012-12-31T23:59:60.000Z"));var Zr=isNaN(Date.parse("2000-01-01T00:00:00.000Z"));if(Zr||Cr||!$r){var Jr=Math.pow(2,31)-1;var zr=P(new Date(1970,0,1,0,0,0,Jr+1).getTime());Date=function(r){var t=function Date(e,n,i,o,u,f,l){var s=arguments.length;var c;if(this instanceof r){var v=f;var p=l;if(zr&&s>=7&&l>Jr){var h=Math.floor(l/Jr)*Jr;var g=Math.floor(h/1e3);v+=g;p-=g*1e3}c=s===1&&a(e)===e?new r(t.parse(e)):s>=7?new r(e,n,i,o,u,v,p):s>=6?new r(e,n,i,o,u,v):s>=5?new r(e,n,i,o,u):s>=4?new r(e,n,i,o):s>=3?new r(e,n,i):s>=2?new r(e,n):s>=1?new r(e):new r}else{c=r.apply(this,arguments)}if(!A(c)){F(c,{constructor:t},true)}return c};var e=new RegExp("^"+"(\\d{4}|[+-]\\d{6})"+"(?:-(\\d{2})"+"(?:-(\\d{2})"+"(?:"+"T(\\d{2})"+":(\\d{2})"+"(?:"+":(\\d{2})"+"(?:(\\.\\d{1,}))?"+")?"+"("+"Z|"+"(?:"+"([-+])"+"(\\d{2})"+":(\\d{2})"+")"+")?)?)?)?"+"$");var n=[0,31,59,90,120,151,181,212,243,273,304,334,365];var i=function dayFromMonth(r,t){var e=t>1?1:0;return n[t]+Math.floor((r-1969+e)/4)-Math.floor((r-1901+e)/100)+Math.floor((r-1601+e)/400)+365*(r-1970)};var o=function toUTC(t){var e=0;var n=t;if(zr&&n>Jr){var i=Math.floor(n/Jr)*Jr;var a=Math.floor(i/1e3);e+=a;n-=a*1e3}return u(new r(1970,0,1,0,0,e,n))};for(var f in r){if(Z(r,f)){t[f]=r[f]}}F(t,{now:r.now,UTC:r.UTC},true);t.prototype=r.prototype;F(t.prototype,{constructor:t},true);var l=function parse(t){var n=e.exec(t);if(n){var a=u(n[1]),f=u(n[2]||1)-1,l=u(n[3]||1)-1,s=u(n[4]||0),c=u(n[5]||0),v=u(n[6]||0),p=Math.floor(u(n[7]||0)*1e3),h=Boolean(n[4]&&!n[8]),g=n[9]==="-"?1:-1,y=u(n[10]||0),d=u(n[11]||0),m;var w=c>0||v>0||p>0;if(s<(w?24:25)&&c<60&&v<60&&p<1e3&&f>-1&&f<12&&y<24&&d<60&&l>-1&&l<i(a,f+1)-i(a,f)){m=((i(a,f)+l)*24+s+y*g)*60;m=((m+c+d*g)*60+v)*1e3+p;if(h){m=o(m)}if(-864e13<=m&&m<=864e13){return m}}return NaN}return r.parse.apply(this,arguments)};F(t,{parse:l});return t}(Date)}if(!Date.now){Date.now=function now(){return(new Date).getTime()}}var Br=f.toFixed&&(8e-5.toFixed(3)!=="0.000"||.9.toFixed(0)!=="1"||1.255.toFixed(2)!=="1.25"||0xde0b6b3a7640080.toFixed(0)!=="1000000000000000128");var Gr={base:1e7,size:6,data:[0,0,0,0,0,0],multiply:function multiply(r,t){var e=-1;var n=t;while(++e<Gr.size){n+=r*Gr.data[e];Gr.data[e]=n%Gr.base;n=Math.floor(n/Gr.base)}},divide:function divide(r){var t=Gr.size,e=0;while(--t>=0){e+=Gr.data[t];Gr.data[t]=Math.floor(e/r);e=e%r*Gr.base}},numToString:function numToString(){var r=Gr.size;var t="";while(--r>=0){if(t!==""||r===0||Gr.data[r]!==0){var e=a(Gr.data[r]);if(t===""){t=e}else{t+=G("0000000",0,7-e.length)+e}}}return t},pow:function pow(r,t,e){return t===0?e:t%2===1?pow(r,t-1,e*r):pow(r*r,t/2,e)},log:function log(r){var t=0;var e=r;while(e>=4096){t+=12;e/=4096}while(e>=2){t+=1;e/=2}return t}};var Hr=function toFixed(r){var t,e,n,i,o,f,l,s;t=u(r);t=P(t)?0:Math.floor(t);if(t<0||t>20){throw new RangeError("Number.toFixed called with invalid number of decimals")}e=u(this);if(P(e)){return"NaN"}if(e<=-1e21||e>=1e21){return a(e)}n="";if(e<0){n="-";e=-e}i="0";if(e>1e-21){o=Gr.log(e*Gr.pow(2,69,1))-69;f=o<0?e*Gr.pow(2,-o,1):e/Gr.pow(2,o,1);f*=4503599627370496;o=52-o;if(o>0){Gr.multiply(0,f);l=t;while(l>=7){Gr.multiply(1e7,0);l-=7}Gr.multiply(Gr.pow(10,l,1),0);l=o-1;while(l>=23){Gr.divide(1<<23);l-=23}Gr.divide(1<<l);Gr.multiply(1,1);Gr.divide(2);i=Gr.numToString()}else{Gr.multiply(0,f);Gr.multiply(1<<-o,0);i=Gr.numToString()+G("0.00000000000000000000",2,2+t)}}if(t>0){s=i.length;if(s<=t){i=n+G("0.0000000000000000000",0,t-s+2)+i}else{i=n+G(i,0,s-t)+"."+G(i,s-t)}}else{i=n+i}return i};F(f,{toFixed:Hr},Br);var Lr=function(){try{return 1..toPrecision(undefined)==="1"}catch(r){return true}}();var Xr=f.toPrecision;F(f,{toPrecision:function toPrecision(r){return typeof r==="undefined"?Xr.call(this):Xr.call(this,r)}},Lr);if("ab".split(/(?:ab)*/).length!==2||".".split(/(.?)(.?)/).length!==4||"tesst".split(/(s)*/)[1]==="t"||"test".split(/(?:)/,-1).length!==4||"".split(/.?/).length||".".split(/()()/).length>1){(function(){var r=typeof/()??/.exec("")[1]==="undefined";var t=Math.pow(2,32)-1;o.split=function(e,n){var i=String(this);if(typeof e==="undefined"&&n===0){return[]}if(!E(e)){return H(this,e,n)}var a=[];var o=(e.ignoreCase?"i":"")+(e.multiline?"m":"")+(e.unicode?"u":"")+(e.sticky?"y":""),u=0,f,l,s,v;var p=new RegExp(e.source,o+"g");if(!r){f=new RegExp("^"+p.source+"$(?!\\s)",o)}var h=typeof n==="undefined"?t:$.ToUint32(n);l=p.exec(i);while(l){s=l.index+l[0].length;if(s>u){X(a,G(i,u,l.index));if(!r&&l.length>1){l[0].replace(f,function(){for(var r=1;r<arguments.length-2;r++){if(typeof arguments[r]==="undefined"){l[r]=void 0}}})}if(l.length>1&&l.index<i.length){c.apply(a,z(l,1))}v=l[0].length;u=s;if(a.length>=h){break}}if(p.lastIndex===l.index){p.lastIndex++}l=p.exec(i)}if(u===i.length){if(v||!p.test("")){X(a,"")}}else{X(a,G(i,u))}return a.length>h?G(a,0,h):a}})()}else if("0".split(void 0,0).length){o.split=function split(r,t){if(typeof r==="undefined"&&t===0){return[]}return H(this,r,t)}}var Yr=o.replace;var qr=function(){var r=[];"x".replace(/x(.)?/g,function(t,e){X(r,e)});return r.length===1&&typeof r[0]==="undefined"}();if(!qr){o.replace=function replace(r,t){var e=b(t);var n=E(r)&&/\)[*?]/.test(r.source);if(!e||!n){return Yr.call(this,r,t)}else{var i=function(e){var n=arguments.length;var i=r.lastIndex;r.lastIndex=0;var a=r.exec(e)||[];r.lastIndex=i;X(a,arguments[n-2],arguments[n-1]);return t.apply(this,a)};return Yr.call(this,r,i)}}}var Kr=o.substr;var Qr="".substr&&"0b".substr(-1)!=="b";F(o,{substr:function substr(r,t){var e=r;if(r<0){e=y(this.length+r,0)}return Kr.call(this,e,t)}},Qr);var Vr=" \n\x0B\f\r \xa0\u1680\u180e\u2000\u2001\u2002\u2003"+"\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028"+"\u2029\ufeff";var Wr="\u200b";var _r="["+Vr+"]";var rt=new RegExp("^"+_r+_r+"*");var tt=new RegExp(_r+_r+"*$");var et=o.trim&&(Vr.trim()||!Wr.trim());F(o,{trim:function trim(){if(typeof this==="undefined"||this===null){throw new TypeError("can't convert "+this+" to object")}return a(this).replace(rt,"").replace(tt,"")}},et);var nt=o.lastIndexOf&&"abc\u3042\u3044".lastIndexOf("\u3042\u3044",2)!==-1;F(o,{lastIndexOf:function lastIndexOf(r){if(typeof this==="undefined"||this===null){throw new TypeError("can't convert "+this+" to object")}var t=a(this);var e=a(r);var n=arguments.length>1?u(arguments[1]):NaN;var i=P(n)?Infinity:$.ToInteger(n);var o=d(y(i,0),t.length);var f=e.length;var l=o+f;while(l>0){l=y(0,l-f);var s=L(G(t,l,o+f),e);if(s!==-1){return l+s}}return-1}},nt);var it=o.lastIndexOf;F(o,{lastIndexOf:function lastIndexOf(r){return it.apply(this,arguments)}},o.lastIndexOf.length!==1);if(parseInt(Vr+"08")!==8||parseInt(Vr+"0x16")!==22){parseInt=function(r){var t=/^[\-+]?0[xX]/;return function parseInt(e,n){var i=a(e).trim();var o=u(n)||(t.test(i)?16:10);return r(i,o)}}(parseInt)}if(String(new RangeError("test"))!=="RangeError: test"){var at=function toString(){if(typeof this==="undefined"||this===null){throw new TypeError("can't convert "+this+" to object")}var r=this.name;if(typeof r==="undefined"){r="Error"}else if(typeof r!=="string"){r=a(r)}var t=this.message;if(typeof t==="undefined"){t=""}else if(typeof t!=="string"){t=a(t)}if(!r){return t}if(!t){return r}return r+": "+t};Error.prototype.toString=at}if(R){var ot=function(r,t){if(Y(r,t)){var e=Object.getOwnPropertyDescriptor(r,t);e.enumerable=false;Object.defineProperty(r,t,e)}};ot(Error.prototype,"message");if(Error.prototype.message!==""){Error.prototype.message=""}ot(Error.prototype,"name")}if(String(/a/gim)!=="/a/gim"){var ut=function toString(){var r="/"+this.source+"/";if(this.global){r+="g"}if(this.ignoreCase){r+="i"}if(this.multiline){r+="m"}return r};RegExp.prototype.toString=ut}});
diff --git a/studio-susie/public/assets/js/vendor/fastclick.js b/studio-susie/public/assets/js/vendor/fastclick.js
new file mode 100644
index 0000000..9c746c2
--- /dev/null
+++ b/studio-susie/public/assets/js/vendor/fastclick.js
@@ -0,0 +1,790 @@
+/**
+ * @preserve FastClick: polyfill to remove click delays on browsers with touch UIs.
+ *
+ * @version 1.0.1
+ * @codingstandard ftlabs-jsv2
+ * @copyright The Financial Times Limited [All Rights Reserved]
+ * @license MIT License (see LICENSE.txt)
+ */
+
+/*jslint browser:true, node:true*/
+/*global define, Event, Node*/
+
+
+/**
+ * Instantiate fast-clicking listeners on the specified layer.
+ *
+ * @constructor
+ * @param {Element} layer The layer to listen on
+ * @param {Object} options The options to override the defaults
+ */
+function FastClick(layer, options) {
+ 'use strict';
+ var oldOnClick;
+
+ options = options || {};
+
+ /**
+ * Whether a click is currently being tracked.
+ *
+ * @type boolean
+ */
+ this.trackingClick = false;
+
+
+ /**
+ * Timestamp for when click tracking started.
+ *
+ * @type number
+ */
+ this.trackingClickStart = 0;
+
+
+ /**
+ * The element being tracked for a click.
+ *
+ * @type EventTarget
+ */
+ this.targetElement = null;
+
+
+ /**
+ * X-coordinate of touch start event.
+ *
+ * @type number
+ */
+ this.touchStartX = 0;
+
+
+ /**
+ * Y-coordinate of touch start event.
+ *
+ * @type number
+ */
+ this.touchStartY = 0;
+
+
+ /**
+ * ID of the last touch, retrieved from Touch.identifier.
+ *
+ * @type number
+ */
+ this.lastTouchIdentifier = 0;
+
+
+ /**
+ * Touchmove boundary, beyond which a click will be cancelled.
+ *
+ * @type number
+ */
+ this.touchBoundary = options.touchBoundary || 10;
+
+
+ /**
+ * The FastClick layer.
+ *
+ * @type Element
+ */
+ this.layer = layer;
+
+ /**
+ * The minimum time between tap(touchstart and touchend) events
+ *
+ * @type number
+ */
+ this.tapDelay = options.tapDelay || 200;
+
+ if (FastClick.notNeeded(layer)) {
+ return;
+ }
+
+ // Some old versions of Android don't have Function.prototype.bind
+ function bind(method, context) {
+ return function() { return method.apply(context, arguments); };
+ }
+
+
+ var methods = ['onMouse', 'onClick', 'onTouchStart', 'onTouchMove', 'onTouchEnd', 'onTouchCancel'];
+ var context = this;
+ for (var i = 0, l = methods.length; i < l; i++) {
+ context[methods[i]] = bind(context[methods[i]], context);
+ }
+
+ // Set up event handlers as required
+ if (deviceIsAndroid) {
+ layer.addEventListener('mouseover', this.onMouse, true);
+ layer.addEventListener('mousedown', this.onMouse, true);
+ layer.addEventListener('mouseup', this.onMouse, true);
+ }
+
+ layer.addEventListener('click', this.onClick, true);
+ layer.addEventListener('touchstart', this.onTouchStart, false);
+ layer.addEventListener('touchmove', this.onTouchMove, false);
+ layer.addEventListener('touchend', this.onTouchEnd, false);
+ layer.addEventListener('touchcancel', this.onTouchCancel, false);
+
+ // Hack is required for browsers that don't support Event#stopImmediatePropagation (e.g. Android 2)
+ // which is how FastClick normally stops click events bubbling to callbacks registered on the FastClick
+ // layer when they are cancelled.
+ if (!Event.prototype.stopImmediatePropagation) {
+ layer.removeEventListener = function(type, callback, capture) {
+ var rmv = Node.prototype.removeEventListener;
+ if (type === 'click') {
+ rmv.call(layer, type, callback.hijacked || callback, capture);
+ } else {
+ rmv.call(layer, type, callback, capture);
+ }
+ };
+
+ layer.addEventListener = function(type, callback, capture) {
+ var adv = Node.prototype.addEventListener;
+ if (type === 'click') {
+ adv.call(layer, type, callback.hijacked || (callback.hijacked = function(event) {
+ if (!event.propagationStopped) {
+ callback(event);
+ }
+ }), capture);
+ } else {
+ adv.call(layer, type, callback, capture);
+ }
+ };
+ }
+
+ // If a handler is already declared in the element's onclick attribute, it will be fired before
+ // FastClick's onClick handler. Fix this by pulling out the user-defined handler function and
+ // adding it as listener.
+ if (typeof layer.onclick === 'function') {
+
+ // Android browser on at least 3.2 requires a new reference to the function in layer.onclick
+ // - the old one won't work if passed to addEventListener directly.
+ oldOnClick = layer.onclick;
+ layer.addEventListener('click', function(event) {
+ oldOnClick(event);
+ }, false);
+ layer.onclick = null;
+ }
+}
+
+
+/**
+ * Android requires exceptions.
+ *
+ * @type boolean
+ */
+var deviceIsAndroid = navigator.userAgent.indexOf('Android') > 0;
+
+
+/**
+ * iOS requires exceptions.
+ *
+ * @type boolean
+ */
+var deviceIsIOS = /iP(ad|hone|od)/.test(navigator.userAgent);
+
+
+/**
+ * iOS 4 requires an exception for select elements.
+ *
+ * @type boolean
+ */
+var deviceIsIOS4 = deviceIsIOS && (/OS 4_\d(_\d)?/).test(navigator.userAgent);
+
+
+/**
+ * iOS 6.0(+?) requires the target element to be manually derived
+ *
+ * @type boolean
+ */
+var deviceIsIOSWithBadTarget = deviceIsIOS && (/OS ([6-9]|\d{2})_\d/).test(navigator.userAgent);
+
+
+/**
+ * Determine whether a given element requires a native click.
+ *
+ * @param {EventTarget|Element} target Target DOM element
+ * @returns {boolean} Returns true if the element needs a native click
+ */
+FastClick.prototype.needsClick = function(target) {
+ 'use strict';
+ switch (target.nodeName.toLowerCase()) {
+
+ // Don't send a synthetic click to disabled inputs (issue #62)
+ case 'button':
+ case 'select':
+ case 'textarea':
+ if (target.disabled) {
+ return true;
+ }
+
+ break;
+ case 'input':
+
+ // File inputs need real clicks on iOS 6 due to a browser bug (issue #68)
+ if ((deviceIsIOS && target.type === 'file') || target.disabled) {
+ return true;
+ }
+
+ break;
+ case 'label':
+ case 'video':
+ return true;
+ }
+
+ return (/\bneedsclick\b/).test(target.className);
+};
+
+
+/**
+ * Determine whether a given element requires a call to focus to simulate click into element.
+ *
+ * @param {EventTarget|Element} target Target DOM element
+ * @returns {boolean} Returns true if the element requires a call to focus to simulate native click.
+ */
+FastClick.prototype.needsFocus = function(target) {
+ 'use strict';
+ switch (target.nodeName.toLowerCase()) {
+ case 'textarea':
+ return true;
+ case 'select':
+ return !deviceIsAndroid;
+ case 'input':
+ switch (target.type) {
+ case 'button':
+ case 'checkbox':
+ case 'file':
+ case 'image':
+ case 'radio':
+ case 'submit':
+ return false;
+ }
+
+ // No point in attempting to focus disabled inputs
+ return !target.disabled && !target.readOnly;
+ default:
+ return (/\bneedsfocus\b/).test(target.className);
+ }
+};
+
+
+/**
+ * Send a click event to the specified element.
+ *
+ * @param {EventTarget|Element} targetElement
+ * @param {Event} event
+ */
+FastClick.prototype.sendClick = function(targetElement, event) {
+ 'use strict';
+ var clickEvent, touch;
+
+ // On some Android devices activeElement needs to be blurred otherwise the synthetic click will have no effect (#24)
+ if (document.activeElement && document.activeElement !== targetElement) {
+ document.activeElement.blur();
+ }
+
+ touch = event.changedTouches[0];
+
+ // Synthesise a click event, with an extra attribute so it can be tracked
+ clickEvent = document.createEvent('MouseEvents');
+ clickEvent.initMouseEvent(this.determineEventType(targetElement), true, true, window, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null);
+ clickEvent.forwardedTouchEvent = true;
+ targetElement.dispatchEvent(clickEvent);
+};
+
+FastClick.prototype.determineEventType = function(targetElement) {
+ 'use strict';
+
+ //Issue #159: Android Chrome Select Box does not open with a synthetic click event
+ if (deviceIsAndroid && targetElement.tagName.toLowerCase() === 'select') {
+ return 'mousedown';
+ }
+
+ return 'click';
+};
+
+
+/**
+ * @param {EventTarget|Element} targetElement
+ */
+FastClick.prototype.focus = function(targetElement) {
+ 'use strict';
+ var length;
+
+ // Issue #160: on iOS 7, some input elements (e.g. date datetime) throw a vague TypeError on setSelectionRange. These elements don't have an integer value for the selectionStart and selectionEnd properties, but unfortunately that can't be used for detection because accessing the properties also throws a TypeError. Just check the type instead. Filed as Apple bug #15122724.
+ if (deviceIsIOS && targetElement.setSelectionRange && targetElement.type.indexOf('date') !== 0 && targetElement.type !== 'time') {
+ length = targetElement.value.length;
+ targetElement.setSelectionRange(length, length);
+ } else {
+ targetElement.focus();
+ }
+};
+
+
+/**
+ * Check whether the given target element is a child of a scrollable layer and if so, set a flag on it.
+ *
+ * @param {EventTarget|Element} targetElement
+ */
+FastClick.prototype.updateScrollParent = function(targetElement) {
+ 'use strict';
+ var scrollParent, parentElement;
+
+ scrollParent = targetElement.fastClickScrollParent;
+
+ // Attempt to discover whether the target element is contained within a scrollable layer. Re-check if the
+ // target element was moved to another parent.
+ if (!scrollParent || !scrollParent.contains(targetElement)) {
+ parentElement = targetElement;
+ do {
+ if (parentElement.scrollHeight > parentElement.offsetHeight) {
+ scrollParent = parentElement;
+ targetElement.fastClickScrollParent = parentElement;
+ break;
+ }
+
+ parentElement = parentElement.parentElement;
+ } while (parentElement);
+ }
+
+ // Always update the scroll top tracker if possible.
+ if (scrollParent) {
+ scrollParent.fastClickLastScrollTop = scrollParent.scrollTop;
+ }
+};
+
+
+/**
+ * @param {EventTarget} targetElement
+ * @returns {Element|EventTarget}
+ */
+FastClick.prototype.getTargetElementFromEventTarget = function(eventTarget) {
+ 'use strict';
+
+ // On some older browsers (notably Safari on iOS 4.1 - see issue #56) the event target may be a text node.
+ if (eventTarget.nodeType === Node.TEXT_NODE) {
+ return eventTarget.parentNode;
+ }
+
+ return eventTarget;
+};
+
+
+/**
+ * On touch start, record the position and scroll offset.
+ *
+ * @param {Event} event
+ * @returns {boolean}
+ */
+FastClick.prototype.onTouchStart = function(event) {
+ 'use strict';
+ var targetElement, touch, selection;
+
+ // Ignore multiple touches, otherwise pinch-to-zoom is prevented if both fingers are on the FastClick element (issue #111).
+ if (event.targetTouches.length > 1) {
+ return true;
+ }
+
+ targetElement = this.getTargetElementFromEventTarget(event.target);
+ touch = event.targetTouches[0];
+
+ if (deviceIsIOS) {
+
+ // Only trusted events will deselect text on iOS (issue #49)
+ selection = window.getSelection();
+ if (selection.rangeCount && !selection.isCollapsed) {
+ return true;
+ }
+
+ if (!deviceIsIOS4) {
+
+ // Weird things happen on iOS when an alert or confirm dialog is opened from a click event callback (issue #23):
+ // when the user next taps anywhere else on the page, new touchstart and touchend events are dispatched
+ // with the same identifier as the touch event that previously triggered the click that triggered the alert.
+ // Sadly, there is an issue on iOS 4 that causes some normal touch events to have the same identifier as an
+ // immediately preceeding touch event (issue #52), so this fix is unavailable on that platform.
+ if (touch.identifier === this.lastTouchIdentifier) {
+ event.preventDefault();
+ return false;
+ }
+
+ this.lastTouchIdentifier = touch.identifier;
+
+ // If the target element is a child of a scrollable layer (using -webkit-overflow-scrolling: touch) and:
+ // 1) the user does a fling scroll on the scrollable layer
+ // 2) the user stops the fling scroll with another tap
+ // then the event.target of the last 'touchend' event will be the element that was under the user's finger
+ // when the fling scroll was started, causing FastClick to send a click event to that layer - unless a check
+ // is made to ensure that a parent layer was not scrolled before sending a synthetic click (issue #42).
+ this.updateScrollParent(targetElement);
+ }
+ }
+
+ this.trackingClick = true;
+ this.trackingClickStart = event.timeStamp;
+ this.targetElement = targetElement;
+
+ this.touchStartX = touch.pageX;
+ this.touchStartY = touch.pageY;
+
+ // Prevent phantom clicks on fast double-tap (issue #36)
+ if ((event.timeStamp - this.lastClickTime) < this.tapDelay) {
+ event.preventDefault();
+ }
+
+ return true;
+};
+
+
+/**
+ * Based on a touchmove event object, check whether the touch has moved past a boundary since it started.
+ *
+ * @param {Event} event
+ * @returns {boolean}
+ */
+FastClick.prototype.touchHasMoved = function(event) {
+ 'use strict';
+ var touch = event.changedTouches[0], boundary = this.touchBoundary;
+
+ if (Math.abs(touch.pageX - this.touchStartX) > boundary || Math.abs(touch.pageY - this.touchStartY) > boundary) {
+ return true;
+ }
+
+ return false;
+};
+
+
+/**
+ * Update the last position.
+ *
+ * @param {Event} event
+ * @returns {boolean}
+ */
+FastClick.prototype.onTouchMove = function(event) {
+ 'use strict';
+ if (!this.trackingClick) {
+ return true;
+ }
+
+ // If the touch has moved, cancel the click tracking
+ if (this.targetElement !== this.getTargetElementFromEventTarget(event.target) || this.touchHasMoved(event)) {
+ this.trackingClick = false;
+ this.targetElement = null;
+ }
+
+ return true;
+};
+
+
+/**
+ * Attempt to find the labelled control for the given label element.
+ *
+ * @param {EventTarget|HTMLLabelElement} labelElement
+ * @returns {Element|null}
+ */
+FastClick.prototype.findControl = function(labelElement) {
+ 'use strict';
+
+ // Fast path for newer browsers supporting the HTML5 control attribute
+ if (labelElement.control !== undefined) {
+ return labelElement.control;
+ }
+
+ // All browsers under test that support touch events also support the HTML5 htmlFor attribute
+ if (labelElement.htmlFor) {
+ return document.getElementById(labelElement.htmlFor);
+ }
+
+ // If no for attribute exists, attempt to retrieve the first labellable descendant element
+ // the list of which is defined here: http://www.w3.org/TR/html5/forms.html#category-label
+ return labelElement.querySelector('button, input:not([type=hidden]), keygen, meter, output, progress, select, textarea');
+};
+
+
+/**
+ * On touch end, determine whether to send a click event at once.
+ *
+ * @param {Event} event
+ * @returns {boolean}
+ */
+FastClick.prototype.onTouchEnd = function(event) {
+ 'use strict';
+ var forElement, trackingClickStart, targetTagName, scrollParent, touch, targetElement = this.targetElement;
+
+ if (!this.trackingClick) {
+ return true;
+ }
+
+ // Prevent phantom clicks on fast double-tap (issue #36)
+ if ((event.timeStamp - this.lastClickTime) < this.tapDelay) {
+ this.cancelNextClick = true;
+ return true;
+ }
+
+ // Reset to prevent wrong click cancel on input (issue #156).
+ this.cancelNextClick = false;
+
+ this.lastClickTime = event.timeStamp;
+
+ trackingClickStart = this.trackingClickStart;
+ this.trackingClick = false;
+ this.trackingClickStart = 0;
+
+ // On some iOS devices, the targetElement supplied with the event is invalid if the layer
+ // is performing a transition or scroll, and has to be re-detected manually. Note that
+ // for this to function correctly, it must be called *after* the event target is checked!
+ // See issue #57; also filed as rdar://13048589 .
+ if (deviceIsIOSWithBadTarget) {
+ touch = event.changedTouches[0];
+
+ // In certain cases arguments of elementFromPoint can be negative, so prevent setting targetElement to null
+ targetElement = document.elementFromPoint(touch.pageX - window.pageXOffset, touch.pageY - window.pageYOffset) || targetElement;
+ targetElement.fastClickScrollParent = this.targetElement.fastClickScrollParent;
+ }
+
+ targetTagName = targetElement.tagName.toLowerCase();
+ if (targetTagName === 'label') {
+ forElement = this.findControl(targetElement);
+ if (forElement) {
+ this.focus(targetElement);
+ if (deviceIsAndroid) {
+ return false;
+ }
+
+ targetElement = forElement;
+ }
+ } else if (this.needsFocus(targetElement)) {
+
+ // Case 1: If the touch started a while ago (best guess is 100ms based on tests for issue #36) then focus will be triggered anyway. Return early and unset the target element reference so that the subsequent click will be allowed through.
+ // Case 2: Without this exception for input elements tapped when the document is contained in an iframe, then any inputted text won't be visible even though the value attribute is updated as the user types (issue #37).
+ if ((event.timeStamp - trackingClickStart) > 100 || (deviceIsIOS && window.top !== window && targetTagName === 'input')) {
+ this.targetElement = null;
+ return false;
+ }
+
+ this.focus(targetElement);
+ this.sendClick(targetElement, event);
+
+ // Select elements need the event to go through on iOS 4, otherwise the selector menu won't open.
+ // Also this breaks opening selects when VoiceOver is active on iOS6, iOS7 (and possibly others)
+ if (!deviceIsIOS || targetTagName !== 'select') {
+ this.targetElement = null;
+ event.preventDefault();
+ }
+
+ return false;
+ }
+
+ if (deviceIsIOS && !deviceIsIOS4) {
+
+ // Don't send a synthetic click event if the target element is contained within a parent layer that was scrolled
+ // and this tap is being used to stop the scrolling (usually initiated by a fling - issue #42).
+ scrollParent = targetElement.fastClickScrollParent;
+ if (scrollParent && scrollParent.fastClickLastScrollTop !== scrollParent.scrollTop) {
+ return true;
+ }
+ }
+
+ // Prevent the actual click from going though - unless the target node is marked as requiring
+ // real clicks or if it is in the whitelist in which case only non-programmatic clicks are permitted.
+ if (!this.needsClick(targetElement)) {
+ event.preventDefault();
+ this.sendClick(targetElement, event);
+ }
+
+ return false;
+};
+
+
+/**
+ * On touch cancel, stop tracking the click.
+ *
+ * @returns {void}
+ */
+FastClick.prototype.onTouchCancel = function() {
+ 'use strict';
+ this.trackingClick = false;
+ this.targetElement = null;
+};
+
+
+/**
+ * Determine mouse events which should be permitted.
+ *
+ * @param {Event} event
+ * @returns {boolean}
+ */
+FastClick.prototype.onMouse = function(event) {
+ 'use strict';
+
+ // If a target element was never set (because a touch event was never fired) allow the event
+ if (!this.targetElement) {
+ return true;
+ }
+
+ if (event.forwardedTouchEvent) {
+ return true;
+ }
+
+ // Programmatically generated events targeting a specific element should be permitted
+ if (!event.cancelable) {
+ return true;
+ }
+
+ // Derive and check the target element to see whether the mouse event needs to be permitted;
+ // unless explicitly enabled, prevent non-touch click events from triggering actions,
+ // to prevent ghost/doubleclicks.
+ if (!this.needsClick(this.targetElement) || this.cancelNextClick) {
+
+ // Prevent any user-added listeners declared on FastClick element from being fired.
+ if (event.stopImmediatePropagation) {
+ event.stopImmediatePropagation();
+ } else {
+
+ // Part of the hack for browsers that don't support Event#stopImmediatePropagation (e.g. Android 2)
+ event.propagationStopped = true;
+ }
+
+ // Cancel the event
+ event.stopPropagation();
+ event.preventDefault();
+
+ return false;
+ }
+
+ // If the mouse event is permitted, return true for the action to go through.
+ return true;
+};
+
+
+/**
+ * On actual clicks, determine whether this is a touch-generated click, a click action occurring
+ * naturally after a delay after a touch (which needs to be cancelled to avoid duplication), or
+ * an actual click which should be permitted.
+ *
+ * @param {Event} event
+ * @returns {boolean}
+ */
+FastClick.prototype.onClick = function(event) {
+ 'use strict';
+ var permitted;
+
+ // It's possible for another FastClick-like library delivered with third-party code to fire a click event before FastClick does (issue #44). In that case, set the click-tracking flag back to false and return early. This will cause onTouchEnd to return early.
+ if (this.trackingClick) {
+ this.targetElement = null;
+ this.trackingClick = false;
+ return true;
+ }
+
+ // Very odd behaviour on iOS (issue #18): if a submit element is present inside a form and the user hits enter in the iOS simulator or clicks the Go button on the pop-up OS keyboard the a kind of 'fake' click event will be triggered with the submit-type input element as the target.
+ if (event.target.type === 'submit' && event.detail === 0) {
+ return true;
+ }
+
+ permitted = this.onMouse(event);
+
+ // Only unset targetElement if the click is not permitted. This will ensure that the check for !targetElement in onMouse fails and the browser's click doesn't go through.
+ if (!permitted) {
+ this.targetElement = null;
+ }
+
+ // If clicks are permitted, return true for the action to go through.
+ return permitted;
+};
+
+
+/**
+ * Remove all FastClick's event listeners.
+ *
+ * @returns {void}
+ */
+FastClick.prototype.destroy = function() {
+ 'use strict';
+ var layer = this.layer;
+
+ if (deviceIsAndroid) {
+ layer.removeEventListener('mouseover', this.onMouse, true);
+ layer.removeEventListener('mousedown', this.onMouse, true);
+ layer.removeEventListener('mouseup', this.onMouse, true);
+ }
+
+ layer.removeEventListener('click', this.onClick, true);
+ layer.removeEventListener('touchstart', this.onTouchStart, false);
+ layer.removeEventListener('touchmove', this.onTouchMove, false);
+ layer.removeEventListener('touchend', this.onTouchEnd, false);
+ layer.removeEventListener('touchcancel', this.onTouchCancel, false);
+};
+
+
+/**
+ * Check whether FastClick is needed.
+ *
+ * @param {Element} layer The layer to listen on
+ */
+FastClick.notNeeded = function(layer) {
+ 'use strict';
+ var metaViewport;
+ var chromeVersion;
+
+ // Devices that don't support touch don't need FastClick
+ if (typeof window.ontouchstart === 'undefined') {
+ return true;
+ }
+
+ // Chrome version - zero for other browsers
+ chromeVersion = +(/Chrome\/([0-9]+)/.exec(navigator.userAgent) || [,0])[1];
+
+ if (chromeVersion) {
+
+ if (deviceIsAndroid) {
+ metaViewport = document.querySelector('meta[name=viewport]');
+
+ if (metaViewport) {
+ // Chrome on Android with user-scalable="no" doesn't need FastClick (issue #89)
+ if (metaViewport.content.indexOf('user-scalable=no') !== -1) {
+ return true;
+ }
+ // Chrome 32 and above with width=device-width or less don't need FastClick
+ if (chromeVersion > 31 && document.documentElement.scrollWidth <= window.outerWidth) {
+ return true;
+ }
+ }
+
+ // Chrome desktop doesn't need FastClick (issue #15)
+ } else {
+ return true;
+ }
+ }
+
+ // IE10 with -ms-touch-action: none, which disables double-tap-to-zoom (issue #97)
+ if (layer.style.msTouchAction === 'none') {
+ return true;
+ }
+
+ return false;
+};
+
+
+/**
+ * Factory method for creating a FastClick object
+ *
+ * @param {Element} layer The layer to listen on
+ * @param {Object} options The options to override the defaults
+ */
+FastClick.attach = function(layer, options) {
+ 'use strict';
+ return new FastClick(layer, options);
+};
+
+
+if (typeof define !== 'undefined' && define.amd) {
+
+ // AMD. Register as an anonymous module.
+ define(function() {
+ 'use strict';
+ return FastClick;
+ });
+} else if (typeof module !== 'undefined' && module.exports) {
+ module.exports = FastClick.attach;
+ module.exports.FastClick = FastClick;
+} else {
+ window.FastClick = FastClick;
+}
diff --git a/studio-susie/public/assets/js/vendor/froogaloop.js b/studio-susie/public/assets/js/vendor/froogaloop.js
new file mode 100644
index 0000000..e2220b2
--- /dev/null
+++ b/studio-susie/public/assets/js/vendor/froogaloop.js
@@ -0,0 +1,287 @@
+// Init style shamelessly stolen from jQuery http://jquery.com
+var Froogaloop = (function(){
+ // Define a local copy of Froogaloop
+ function Froogaloop(iframe) {
+ // The Froogaloop object is actually just the init constructor
+ return new Froogaloop.fn.init(iframe);
+ }
+
+ var eventCallbacks = {},
+ hasWindowEvent = false,
+ isReady = false,
+ slice = Array.prototype.slice,
+ playerDomain = '';
+
+ Froogaloop.fn = Froogaloop.prototype = {
+ element: null,
+
+ init: function(iframe) {
+ if (typeof iframe === "string") {
+ iframe = document.getElementById(iframe);
+ }
+
+ this.element = iframe;
+
+ // Register message event listeners
+ playerDomain = getDomainFromUrl(this.element.getAttribute('src'));
+
+ return this;
+ },
+
+ /*
+ * Calls a function to act upon the player.
+ *
+ * @param {string} method The name of the Javascript API method to call. Eg: 'play'.
+ * @param {Array|Function} valueOrCallback params Array of parameters to pass when calling an API method
+ * or callback function when the method returns a value.
+ */
+ api: function(method, valueOrCallback) {
+ if (!this.element || !method) {
+ return false;
+ }
+
+ var self = this,
+ element = self.element,
+ target_id = element.id !== '' ? element.id : null,
+ params = !isFunction(valueOrCallback) ? valueOrCallback : null,
+ callback = isFunction(valueOrCallback) ? valueOrCallback : null;
+
+ // Store the callback for get functions
+ if (callback) {
+ storeCallback(method, callback, target_id);
+ }
+
+ postMessage(method, params, element);
+ return self;
+ },
+
+ /*
+ * Registers an event listener and a callback function that gets called when the event fires.
+ *
+ * @param eventName (String): Name of the event to listen for.
+ * @param callback (Function): Function that should be called when the event fires.
+ */
+ addEvent: function(eventName, callback) {
+ if (!this.element) {
+ return false;
+ }
+
+ var self = this,
+ element = self.element,
+ target_id = element.id !== '' ? element.id : null;
+
+ storeCallback(eventName, callback, target_id);
+
+ // The ready event is not registered via postMessage. It fires regardless.
+ if (eventName != 'ready') {
+ postMessage('addEventListener', eventName, element);
+ }
+ else if (eventName == 'ready' && isReady) {
+ callback.call(null, target_id);
+ }
+
+ return self;
+ },
+
+ /*
+ * Unregisters an event listener that gets called when the event fires.
+ *
+ * @param eventName (String): Name of the event to stop listening for.
+ */
+ removeEvent: function(eventName) {
+ if (!this.element) {
+ return false;
+ }
+
+ var self = this,
+ element = self.element,
+ target_id = element.id !== '' ? element.id : null,
+ removed = removeCallback(eventName, target_id);
+
+ // The ready event is not registered
+ if (eventName != 'ready' && removed) {
+ postMessage('removeEventListener', eventName, element);
+ }
+ }
+ };
+
+ /**
+ * Handles posting a message to the parent window.
+ *
+ * @param method (String): name of the method to call inside the player. For api calls
+ * this is the name of the api method (api_play or api_pause) while for events this method
+ * is api_addEventListener.
+ * @param params (Object or Array): List of parameters to submit to the method. Can be either
+ * a single param or an array list of parameters.
+ * @param target (HTMLElement): Target iframe to post the message to.
+ */
+ function postMessage(method, params, target) {
+ if (! target.contentWindow || ! target.contentWindow.postMessage) {
+ return false;
+ }
+
+ var url = target.getAttribute('src').split('?')[0],
+ data = JSON.stringify({
+ method: method,
+ value: params
+ });
+
+ if (url.substr(0, 2) === '//') {
+ url = window.location.protocol + url;
+ }
+
+ target.contentWindow.postMessage(data, url);
+ }
+
+ /**
+ * Event that fires whenever the window receives a message from its parent
+ * via window.postMessage.
+ */
+ function onMessageReceived(event) {
+ var data, method;
+
+ try {
+ data = JSON.parse(event.data);
+ method = data.event || data.method;
+ }
+ catch(e) {
+ //fail silently... like a ninja!
+ }
+
+ if (method == 'ready' && !isReady) {
+ isReady = true;
+ }
+
+ // Handles messages from moogaloop only
+ if (event.origin != playerDomain) {
+ return false;
+ }
+
+ var value = data.value,
+ eventData = data.data,
+ target_id = target_id === '' ? null : data.player_id,
+
+ callback = getCallback(method, target_id),
+ params = [];
+
+ if (!callback) {
+ return false;
+ }
+
+ if (value !== undefined) {
+ params.push(value);
+ }
+
+ if (eventData) {
+ params.push(eventData);
+ }
+
+ if (target_id) {
+ params.push(target_id);
+ }
+
+ return params.length > 0 ? callback.apply(null, params) : callback.call();
+ }
+
+
+ /**
+ * Stores submitted callbacks for each iframe being tracked and each
+ * event for that iframe.
+ *
+ * @param eventName (String): Name of the event. Eg. api_onPlay
+ * @param callback (Function): Function that should get executed when the
+ * event is fired.
+ * @param target_id (String) [Optional]: If handling more than one iframe then
+ * it stores the different callbacks for different iframes based on the iframe's
+ * id.
+ */
+ function storeCallback(eventName, callback, target_id) {
+ if (target_id) {
+ if (!eventCallbacks[target_id]) {
+ eventCallbacks[target_id] = {};
+ }
+ eventCallbacks[target_id][eventName] = callback;
+ }
+ else {
+ eventCallbacks[eventName] = callback;
+ }
+ }
+
+ /**
+ * Retrieves stored callbacks.
+ */
+ function getCallback(eventName, target_id) {
+ if (target_id) {
+ return eventCallbacks[target_id][eventName];
+ }
+ else {
+ return eventCallbacks[eventName];
+ }
+ }
+
+ function removeCallback(eventName, target_id) {
+ if (target_id && eventCallbacks[target_id]) {
+ if (!eventCallbacks[target_id][eventName]) {
+ return false;
+ }
+ eventCallbacks[target_id][eventName] = null;
+ }
+ else {
+ if (!eventCallbacks[eventName]) {
+ return false;
+ }
+ eventCallbacks[eventName] = null;
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns a domain's root domain.
+ * Eg. returns http://vimeo.com when http://vimeo.com/channels is sbumitted
+ *
+ * @param url (String): Url to test against.
+ * @return url (String): Root domain of submitted url
+ */
+ function getDomainFromUrl(url) {
+ if (url.substr(0, 2) === '//') {
+ url = window.location.protocol + url;
+ }
+
+ var url_pieces = url.split('/'),
+ domain_str = '';
+
+ for(var i = 0, length = url_pieces.length; i < length; i++) {
+ if(i<3) {domain_str += url_pieces[i];}
+ else {break;}
+ if(i<2) {domain_str += '/';}
+ }
+
+ return domain_str;
+ }
+
+ function isFunction(obj) {
+ return !!(obj && obj.constructor && obj.call && obj.apply);
+ }
+
+ function isArray(obj) {
+ return toString.call(obj) === '[object Array]';
+ }
+
+ // Give the init function the Froogaloop prototype for later instantiation
+ Froogaloop.fn.init.prototype = Froogaloop.fn;
+
+ // Listens for the message event.
+ // W3C
+ if (window.addEventListener) {
+ window.addEventListener('message', onMessageReceived, false);
+ }
+ // IE
+ else {
+ window.attachEvent('onmessage', onMessageReceived);
+ }
+
+ // Expose froogaloop to the global object
+ return (window.Froogaloop = window.$f = Froogaloop);
+
+})(); \ No newline at end of file
diff --git a/studio-susie/public/assets/js/vendor/hammer.min.js b/studio-susie/public/assets/js/vendor/hammer.min.js
new file mode 100644
index 0000000..a81e23b
--- /dev/null
+++ b/studio-susie/public/assets/js/vendor/hammer.min.js
@@ -0,0 +1,6 @@
+/*! Hammer.JS - v2.0.6 - 2016-01-06
+ * http://hammerjs.github.io/
+ *
+ * Copyright (c) 2016 Jorik Tangelder;
+ * Licensed under the license */
+!function(a,b,c,d){"use strict";function e(a,b,c){return setTimeout(j(a,c),b)}function f(a,b,c){return Array.isArray(a)?(g(a,c[b],c),!0):!1}function g(a,b,c){var e;if(a)if(a.forEach)a.forEach(b,c);else if(a.length!==d)for(e=0;e<a.length;)b.call(c,a[e],e,a),e++;else for(e in a)a.hasOwnProperty(e)&&b.call(c,a[e],e,a)}function h(b,c,d){var e="DEPRECATED METHOD: "+c+"\n"+d+" AT \n";return function(){var c=new Error("get-stack-trace"),d=c&&c.stack?c.stack.replace(/^[^\(]+?[\n$]/gm,"").replace(/^\s+at\s+/gm,"").replace(/^Object.<anonymous>\s*\(/gm,"{anonymous}()@"):"Unknown Stack Trace",f=a.console&&(a.console.warn||a.console.log);return f&&f.call(a.console,e,d),b.apply(this,arguments)}}function i(a,b,c){var d,e=b.prototype;d=a.prototype=Object.create(e),d.constructor=a,d._super=e,c&&ha(d,c)}function j(a,b){return function(){return a.apply(b,arguments)}}function k(a,b){return typeof a==ka?a.apply(b?b[0]||d:d,b):a}function l(a,b){return a===d?b:a}function m(a,b,c){g(q(b),function(b){a.addEventListener(b,c,!1)})}function n(a,b,c){g(q(b),function(b){a.removeEventListener(b,c,!1)})}function o(a,b){for(;a;){if(a==b)return!0;a=a.parentNode}return!1}function p(a,b){return a.indexOf(b)>-1}function q(a){return a.trim().split(/\s+/g)}function r(a,b,c){if(a.indexOf&&!c)return a.indexOf(b);for(var d=0;d<a.length;){if(c&&a[d][c]==b||!c&&a[d]===b)return d;d++}return-1}function s(a){return Array.prototype.slice.call(a,0)}function t(a,b,c){for(var d=[],e=[],f=0;f<a.length;){var g=b?a[f][b]:a[f];r(e,g)<0&&d.push(a[f]),e[f]=g,f++}return c&&(d=b?d.sort(function(a,c){return a[b]>c[b]}):d.sort()),d}function u(a,b){for(var c,e,f=b[0].toUpperCase()+b.slice(1),g=0;g<ia.length;){if(c=ia[g],e=c?c+f:b,e in a)return e;g++}return d}function v(){return qa++}function w(b){var c=b.ownerDocument||b;return c.defaultView||c.parentWindow||a}function x(a,b){var c=this;this.manager=a,this.callback=b,this.element=a.element,this.target=a.options.inputTarget,this.domHandler=function(b){k(a.options.enable,[a])&&c.handler(b)},this.init()}function y(a){var b,c=a.options.inputClass;return new(b=c?c:ta?M:ua?P:sa?R:L)(a,z)}function z(a,b,c){var d=c.pointers.length,e=c.changedPointers.length,f=b&Aa&&d-e===0,g=b&(Ca|Da)&&d-e===0;c.isFirst=!!f,c.isFinal=!!g,f&&(a.session={}),c.eventType=b,A(a,c),a.emit("hammer.input",c),a.recognize(c),a.session.prevInput=c}function A(a,b){var c=a.session,d=b.pointers,e=d.length;c.firstInput||(c.firstInput=D(b)),e>1&&!c.firstMultiple?c.firstMultiple=D(b):1===e&&(c.firstMultiple=!1);var f=c.firstInput,g=c.firstMultiple,h=g?g.center:f.center,i=b.center=E(d);b.timeStamp=na(),b.deltaTime=b.timeStamp-f.timeStamp,b.angle=I(h,i),b.distance=H(h,i),B(c,b),b.offsetDirection=G(b.deltaX,b.deltaY);var j=F(b.deltaTime,b.deltaX,b.deltaY);b.overallVelocityX=j.x,b.overallVelocityY=j.y,b.overallVelocity=ma(j.x)>ma(j.y)?j.x:j.y,b.scale=g?K(g.pointers,d):1,b.rotation=g?J(g.pointers,d):0,b.maxPointers=c.prevInput?b.pointers.length>c.prevInput.maxPointers?b.pointers.length:c.prevInput.maxPointers:b.pointers.length,C(c,b);var k=a.element;o(b.srcEvent.target,k)&&(k=b.srcEvent.target),b.target=k}function B(a,b){var c=b.center,d=a.offsetDelta||{},e=a.prevDelta||{},f=a.prevInput||{};(b.eventType===Aa||f.eventType===Ca)&&(e=a.prevDelta={x:f.deltaX||0,y:f.deltaY||0},d=a.offsetDelta={x:c.x,y:c.y}),b.deltaX=e.x+(c.x-d.x),b.deltaY=e.y+(c.y-d.y)}function C(a,b){var c,e,f,g,h=a.lastInterval||b,i=b.timeStamp-h.timeStamp;if(b.eventType!=Da&&(i>za||h.velocity===d)){var j=b.deltaX-h.deltaX,k=b.deltaY-h.deltaY,l=F(i,j,k);e=l.x,f=l.y,c=ma(l.x)>ma(l.y)?l.x:l.y,g=G(j,k),a.lastInterval=b}else c=h.velocity,e=h.velocityX,f=h.velocityY,g=h.direction;b.velocity=c,b.velocityX=e,b.velocityY=f,b.direction=g}function D(a){for(var b=[],c=0;c<a.pointers.length;)b[c]={clientX:la(a.pointers[c].clientX),clientY:la(a.pointers[c].clientY)},c++;return{timeStamp:na(),pointers:b,center:E(b),deltaX:a.deltaX,deltaY:a.deltaY}}function E(a){var b=a.length;if(1===b)return{x:la(a[0].clientX),y:la(a[0].clientY)};for(var c=0,d=0,e=0;b>e;)c+=a[e].clientX,d+=a[e].clientY,e++;return{x:la(c/b),y:la(d/b)}}function F(a,b,c){return{x:b/a||0,y:c/a||0}}function G(a,b){return a===b?Ea:ma(a)>=ma(b)?0>a?Fa:Ga:0>b?Ha:Ia}function H(a,b,c){c||(c=Ma);var d=b[c[0]]-a[c[0]],e=b[c[1]]-a[c[1]];return Math.sqrt(d*d+e*e)}function I(a,b,c){c||(c=Ma);var d=b[c[0]]-a[c[0]],e=b[c[1]]-a[c[1]];return 180*Math.atan2(e,d)/Math.PI}function J(a,b){return I(b[1],b[0],Na)+I(a[1],a[0],Na)}function K(a,b){return H(b[0],b[1],Na)/H(a[0],a[1],Na)}function L(){this.evEl=Pa,this.evWin=Qa,this.allow=!0,this.pressed=!1,x.apply(this,arguments)}function M(){this.evEl=Ta,this.evWin=Ua,x.apply(this,arguments),this.store=this.manager.session.pointerEvents=[]}function N(){this.evTarget=Wa,this.evWin=Xa,this.started=!1,x.apply(this,arguments)}function O(a,b){var c=s(a.touches),d=s(a.changedTouches);return b&(Ca|Da)&&(c=t(c.concat(d),"identifier",!0)),[c,d]}function P(){this.evTarget=Za,this.targetIds={},x.apply(this,arguments)}function Q(a,b){var c=s(a.touches),d=this.targetIds;if(b&(Aa|Ba)&&1===c.length)return d[c[0].identifier]=!0,[c,c];var e,f,g=s(a.changedTouches),h=[],i=this.target;if(f=c.filter(function(a){return o(a.target,i)}),b===Aa)for(e=0;e<f.length;)d[f[e].identifier]=!0,e++;for(e=0;e<g.length;)d[g[e].identifier]&&h.push(g[e]),b&(Ca|Da)&&delete d[g[e].identifier],e++;return h.length?[t(f.concat(h),"identifier",!0),h]:void 0}function R(){x.apply(this,arguments);var a=j(this.handler,this);this.touch=new P(this.manager,a),this.mouse=new L(this.manager,a)}function S(a,b){this.manager=a,this.set(b)}function T(a){if(p(a,db))return db;var b=p(a,eb),c=p(a,fb);return b&&c?db:b||c?b?eb:fb:p(a,cb)?cb:bb}function U(a){this.options=ha({},this.defaults,a||{}),this.id=v(),this.manager=null,this.options.enable=l(this.options.enable,!0),this.state=gb,this.simultaneous={},this.requireFail=[]}function V(a){return a&lb?"cancel":a&jb?"end":a&ib?"move":a&hb?"start":""}function W(a){return a==Ia?"down":a==Ha?"up":a==Fa?"left":a==Ga?"right":""}function X(a,b){var c=b.manager;return c?c.get(a):a}function Y(){U.apply(this,arguments)}function Z(){Y.apply(this,arguments),this.pX=null,this.pY=null}function $(){Y.apply(this,arguments)}function _(){U.apply(this,arguments),this._timer=null,this._input=null}function aa(){Y.apply(this,arguments)}function ba(){Y.apply(this,arguments)}function ca(){U.apply(this,arguments),this.pTime=!1,this.pCenter=!1,this._timer=null,this._input=null,this.count=0}function da(a,b){return b=b||{},b.recognizers=l(b.recognizers,da.defaults.preset),new ea(a,b)}function ea(a,b){this.options=ha({},da.defaults,b||{}),this.options.inputTarget=this.options.inputTarget||a,this.handlers={},this.session={},this.recognizers=[],this.element=a,this.input=y(this),this.touchAction=new S(this,this.options.touchAction),fa(this,!0),g(this.options.recognizers,function(a){var b=this.add(new a[0](a[1]));a[2]&&b.recognizeWith(a[2]),a[3]&&b.requireFailure(a[3])},this)}function fa(a,b){var c=a.element;c.style&&g(a.options.cssProps,function(a,d){c.style[u(c.style,d)]=b?a:""})}function ga(a,c){var d=b.createEvent("Event");d.initEvent(a,!0,!0),d.gesture=c,c.target.dispatchEvent(d)}var ha,ia=["","webkit","Moz","MS","ms","o"],ja=b.createElement("div"),ka="function",la=Math.round,ma=Math.abs,na=Date.now;ha="function"!=typeof Object.assign?function(a){if(a===d||null===a)throw new TypeError("Cannot convert undefined or null to object");for(var b=Object(a),c=1;c<arguments.length;c++){var e=arguments[c];if(e!==d&&null!==e)for(var f in e)e.hasOwnProperty(f)&&(b[f]=e[f])}return b}:Object.assign;var oa=h(function(a,b,c){for(var e=Object.keys(b),f=0;f<e.length;)(!c||c&&a[e[f]]===d)&&(a[e[f]]=b[e[f]]),f++;return a},"extend","Use `assign`."),pa=h(function(a,b){return oa(a,b,!0)},"merge","Use `assign`."),qa=1,ra=/mobile|tablet|ip(ad|hone|od)|android/i,sa="ontouchstart"in a,ta=u(a,"PointerEvent")!==d,ua=sa&&ra.test(navigator.userAgent),va="touch",wa="pen",xa="mouse",ya="kinect",za=25,Aa=1,Ba=2,Ca=4,Da=8,Ea=1,Fa=2,Ga=4,Ha=8,Ia=16,Ja=Fa|Ga,Ka=Ha|Ia,La=Ja|Ka,Ma=["x","y"],Na=["clientX","clientY"];x.prototype={handler:function(){},init:function(){this.evEl&&m(this.element,this.evEl,this.domHandler),this.evTarget&&m(this.target,this.evTarget,this.domHandler),this.evWin&&m(w(this.element),this.evWin,this.domHandler)},destroy:function(){this.evEl&&n(this.element,this.evEl,this.domHandler),this.evTarget&&n(this.target,this.evTarget,this.domHandler),this.evWin&&n(w(this.element),this.evWin,this.domHandler)}};var Oa={mousedown:Aa,mousemove:Ba,mouseup:Ca},Pa="mousedown",Qa="mousemove mouseup";i(L,x,{handler:function(a){var b=Oa[a.type];b&Aa&&0===a.button&&(this.pressed=!0),b&Ba&&1!==a.which&&(b=Ca),this.pressed&&this.allow&&(b&Ca&&(this.pressed=!1),this.callback(this.manager,b,{pointers:[a],changedPointers:[a],pointerType:xa,srcEvent:a}))}});var Ra={pointerdown:Aa,pointermove:Ba,pointerup:Ca,pointercancel:Da,pointerout:Da},Sa={2:va,3:wa,4:xa,5:ya},Ta="pointerdown",Ua="pointermove pointerup pointercancel";a.MSPointerEvent&&!a.PointerEvent&&(Ta="MSPointerDown",Ua="MSPointerMove MSPointerUp MSPointerCancel"),i(M,x,{handler:function(a){var b=this.store,c=!1,d=a.type.toLowerCase().replace("ms",""),e=Ra[d],f=Sa[a.pointerType]||a.pointerType,g=f==va,h=r(b,a.pointerId,"pointerId");e&Aa&&(0===a.button||g)?0>h&&(b.push(a),h=b.length-1):e&(Ca|Da)&&(c=!0),0>h||(b[h]=a,this.callback(this.manager,e,{pointers:b,changedPointers:[a],pointerType:f,srcEvent:a}),c&&b.splice(h,1))}});var Va={touchstart:Aa,touchmove:Ba,touchend:Ca,touchcancel:Da},Wa="touchstart",Xa="touchstart touchmove touchend touchcancel";i(N,x,{handler:function(a){var b=Va[a.type];if(b===Aa&&(this.started=!0),this.started){var c=O.call(this,a,b);b&(Ca|Da)&&c[0].length-c[1].length===0&&(this.started=!1),this.callback(this.manager,b,{pointers:c[0],changedPointers:c[1],pointerType:va,srcEvent:a})}}});var Ya={touchstart:Aa,touchmove:Ba,touchend:Ca,touchcancel:Da},Za="touchstart touchmove touchend touchcancel";i(P,x,{handler:function(a){var b=Ya[a.type],c=Q.call(this,a,b);c&&this.callback(this.manager,b,{pointers:c[0],changedPointers:c[1],pointerType:va,srcEvent:a})}}),i(R,x,{handler:function(a,b,c){var d=c.pointerType==va,e=c.pointerType==xa;if(d)this.mouse.allow=!1;else if(e&&!this.mouse.allow)return;b&(Ca|Da)&&(this.mouse.allow=!0),this.callback(a,b,c)},destroy:function(){this.touch.destroy(),this.mouse.destroy()}});var $a=u(ja.style,"touchAction"),_a=$a!==d,ab="compute",bb="auto",cb="manipulation",db="none",eb="pan-x",fb="pan-y";S.prototype={set:function(a){a==ab&&(a=this.compute()),_a&&this.manager.element.style&&(this.manager.element.style[$a]=a),this.actions=a.toLowerCase().trim()},update:function(){this.set(this.manager.options.touchAction)},compute:function(){var a=[];return g(this.manager.recognizers,function(b){k(b.options.enable,[b])&&(a=a.concat(b.getTouchAction()))}),T(a.join(" "))},preventDefaults:function(a){if(!_a){var b=a.srcEvent,c=a.offsetDirection;if(this.manager.session.prevented)return void b.preventDefault();var d=this.actions,e=p(d,db),f=p(d,fb),g=p(d,eb);if(e){var h=1===a.pointers.length,i=a.distance<2,j=a.deltaTime<250;if(h&&i&&j)return}if(!g||!f)return e||f&&c&Ja||g&&c&Ka?this.preventSrc(b):void 0}},preventSrc:function(a){this.manager.session.prevented=!0,a.preventDefault()}};var gb=1,hb=2,ib=4,jb=8,kb=jb,lb=16,mb=32;U.prototype={defaults:{},set:function(a){return ha(this.options,a),this.manager&&this.manager.touchAction.update(),this},recognizeWith:function(a){if(f(a,"recognizeWith",this))return this;var b=this.simultaneous;return a=X(a,this),b[a.id]||(b[a.id]=a,a.recognizeWith(this)),this},dropRecognizeWith:function(a){return f(a,"dropRecognizeWith",this)?this:(a=X(a,this),delete this.simultaneous[a.id],this)},requireFailure:function(a){if(f(a,"requireFailure",this))return this;var b=this.requireFail;return a=X(a,this),-1===r(b,a)&&(b.push(a),a.requireFailure(this)),this},dropRequireFailure:function(a){if(f(a,"dropRequireFailure",this))return this;a=X(a,this);var b=r(this.requireFail,a);return b>-1&&this.requireFail.splice(b,1),this},hasRequireFailures:function(){return this.requireFail.length>0},canRecognizeWith:function(a){return!!this.simultaneous[a.id]},emit:function(a){function b(b){c.manager.emit(b,a)}var c=this,d=this.state;jb>d&&b(c.options.event+V(d)),b(c.options.event),a.additionalEvent&&b(a.additionalEvent),d>=jb&&b(c.options.event+V(d))},tryEmit:function(a){return this.canEmit()?this.emit(a):void(this.state=mb)},canEmit:function(){for(var a=0;a<this.requireFail.length;){if(!(this.requireFail[a].state&(mb|gb)))return!1;a++}return!0},recognize:function(a){var b=ha({},a);return k(this.options.enable,[this,b])?(this.state&(kb|lb|mb)&&(this.state=gb),this.state=this.process(b),void(this.state&(hb|ib|jb|lb)&&this.tryEmit(b))):(this.reset(),void(this.state=mb))},process:function(a){},getTouchAction:function(){},reset:function(){}},i(Y,U,{defaults:{pointers:1},attrTest:function(a){var b=this.options.pointers;return 0===b||a.pointers.length===b},process:function(a){var b=this.state,c=a.eventType,d=b&(hb|ib),e=this.attrTest(a);return d&&(c&Da||!e)?b|lb:d||e?c&Ca?b|jb:b&hb?b|ib:hb:mb}}),i(Z,Y,{defaults:{event:"pan",threshold:10,pointers:1,direction:La},getTouchAction:function(){var a=this.options.direction,b=[];return a&Ja&&b.push(fb),a&Ka&&b.push(eb),b},directionTest:function(a){var b=this.options,c=!0,d=a.distance,e=a.direction,f=a.deltaX,g=a.deltaY;return e&b.direction||(b.direction&Ja?(e=0===f?Ea:0>f?Fa:Ga,c=f!=this.pX,d=Math.abs(a.deltaX)):(e=0===g?Ea:0>g?Ha:Ia,c=g!=this.pY,d=Math.abs(a.deltaY))),a.direction=e,c&&d>b.threshold&&e&b.direction},attrTest:function(a){return Y.prototype.attrTest.call(this,a)&&(this.state&hb||!(this.state&hb)&&this.directionTest(a))},emit:function(a){this.pX=a.deltaX,this.pY=a.deltaY;var b=W(a.direction);b&&(a.additionalEvent=this.options.event+b),this._super.emit.call(this,a)}}),i($,Y,{defaults:{event:"pinch",threshold:0,pointers:2},getTouchAction:function(){return[db]},attrTest:function(a){return this._super.attrTest.call(this,a)&&(Math.abs(a.scale-1)>this.options.threshold||this.state&hb)},emit:function(a){if(1!==a.scale){var b=a.scale<1?"in":"out";a.additionalEvent=this.options.event+b}this._super.emit.call(this,a)}}),i(_,U,{defaults:{event:"press",pointers:1,time:251,threshold:9},getTouchAction:function(){return[bb]},process:function(a){var b=this.options,c=a.pointers.length===b.pointers,d=a.distance<b.threshold,f=a.deltaTime>b.time;if(this._input=a,!d||!c||a.eventType&(Ca|Da)&&!f)this.reset();else if(a.eventType&Aa)this.reset(),this._timer=e(function(){this.state=kb,this.tryEmit()},b.time,this);else if(a.eventType&Ca)return kb;return mb},reset:function(){clearTimeout(this._timer)},emit:function(a){this.state===kb&&(a&&a.eventType&Ca?this.manager.emit(this.options.event+"up",a):(this._input.timeStamp=na(),this.manager.emit(this.options.event,this._input)))}}),i(aa,Y,{defaults:{event:"rotate",threshold:0,pointers:2},getTouchAction:function(){return[db]},attrTest:function(a){return this._super.attrTest.call(this,a)&&(Math.abs(a.rotation)>this.options.threshold||this.state&hb)}}),i(ba,Y,{defaults:{event:"swipe",threshold:10,velocity:.3,direction:Ja|Ka,pointers:1},getTouchAction:function(){return Z.prototype.getTouchAction.call(this)},attrTest:function(a){var b,c=this.options.direction;return c&(Ja|Ka)?b=a.overallVelocity:c&Ja?b=a.overallVelocityX:c&Ka&&(b=a.overallVelocityY),this._super.attrTest.call(this,a)&&c&a.offsetDirection&&a.distance>this.options.threshold&&a.maxPointers==this.options.pointers&&ma(b)>this.options.velocity&&a.eventType&Ca},emit:function(a){var b=W(a.offsetDirection);b&&this.manager.emit(this.options.event+b,a),this.manager.emit(this.options.event,a)}}),i(ca,U,{defaults:{event:"tap",pointers:1,taps:1,interval:300,time:250,threshold:9,posThreshold:10},getTouchAction:function(){return[cb]},process:function(a){var b=this.options,c=a.pointers.length===b.pointers,d=a.distance<b.threshold,f=a.deltaTime<b.time;if(this.reset(),a.eventType&Aa&&0===this.count)return this.failTimeout();if(d&&f&&c){if(a.eventType!=Ca)return this.failTimeout();var g=this.pTime?a.timeStamp-this.pTime<b.interval:!0,h=!this.pCenter||H(this.pCenter,a.center)<b.posThreshold;this.pTime=a.timeStamp,this.pCenter=a.center,h&&g?this.count+=1:this.count=1,this._input=a;var i=this.count%b.taps;if(0===i)return this.hasRequireFailures()?(this._timer=e(function(){this.state=kb,this.tryEmit()},b.interval,this),hb):kb}return mb},failTimeout:function(){return this._timer=e(function(){this.state=mb},this.options.interval,this),mb},reset:function(){clearTimeout(this._timer)},emit:function(){this.state==kb&&(this._input.tapCount=this.count,this.manager.emit(this.options.event,this._input))}}),da.VERSION="2.0.6",da.defaults={domEvents:!1,touchAction:ab,enable:!0,inputTarget:null,inputClass:null,preset:[[aa,{enable:!1}],[$,{enable:!1},["rotate"]],[ba,{direction:Ja}],[Z,{direction:Ja},["swipe"]],[ca],[ca,{event:"doubletap",taps:2},["tap"]],[_]],cssProps:{userSelect:"none",touchSelect:"none",touchCallout:"none",contentZooming:"none",userDrag:"none",tapHighlightColor:"rgba(0,0,0,0)"}};var nb=1,ob=2;ea.prototype={set:function(a){return ha(this.options,a),a.touchAction&&this.touchAction.update(),a.inputTarget&&(this.input.destroy(),this.input.target=a.inputTarget,this.input.init()),this},stop:function(a){this.session.stopped=a?ob:nb},recognize:function(a){var b=this.session;if(!b.stopped){this.touchAction.preventDefaults(a);var c,d=this.recognizers,e=b.curRecognizer;(!e||e&&e.state&kb)&&(e=b.curRecognizer=null);for(var f=0;f<d.length;)c=d[f],b.stopped===ob||e&&c!=e&&!c.canRecognizeWith(e)?c.reset():c.recognize(a),!e&&c.state&(hb|ib|jb)&&(e=b.curRecognizer=c),f++}},get:function(a){if(a instanceof U)return a;for(var b=this.recognizers,c=0;c<b.length;c++)if(b[c].options.event==a)return b[c];return null},add:function(a){if(f(a,"add",this))return this;var b=this.get(a.options.event);return b&&this.remove(b),this.recognizers.push(a),a.manager=this,this.touchAction.update(),a},remove:function(a){if(f(a,"remove",this))return this;if(a=this.get(a)){var b=this.recognizers,c=r(b,a);-1!==c&&(b.splice(c,1),this.touchAction.update())}return this},on:function(a,b){var c=this.handlers;return g(q(a),function(a){c[a]=c[a]||[],c[a].push(b)}),this},off:function(a,b){var c=this.handlers;return g(q(a),function(a){b?c[a]&&c[a].splice(r(c[a],b),1):delete c[a]}),this},emit:function(a,b){this.options.domEvents&&ga(a,b);var c=this.handlers[a]&&this.handlers[a].slice();if(c&&c.length){b.type=a,b.preventDefault=function(){b.srcEvent.preventDefault()};for(var d=0;d<c.length;)c[d](b),d++}},destroy:function(){this.element&&fa(this,!1),this.handlers={},this.session={},this.input.destroy(),this.element=null}},ha(da,{INPUT_START:Aa,INPUT_MOVE:Ba,INPUT_END:Ca,INPUT_CANCEL:Da,STATE_POSSIBLE:gb,STATE_BEGAN:hb,STATE_CHANGED:ib,STATE_ENDED:jb,STATE_RECOGNIZED:kb,STATE_CANCELLED:lb,STATE_FAILED:mb,DIRECTION_NONE:Ea,DIRECTION_LEFT:Fa,DIRECTION_RIGHT:Ga,DIRECTION_UP:Ha,DIRECTION_DOWN:Ia,DIRECTION_HORIZONTAL:Ja,DIRECTION_VERTICAL:Ka,DIRECTION_ALL:La,Manager:ea,Input:x,TouchAction:S,TouchInput:P,MouseInput:L,PointerEventInput:M,TouchMouseInput:R,SingleTouchInput:N,Recognizer:U,AttrRecognizer:Y,Tap:ca,Pan:Z,Swipe:ba,Pinch:$,Rotate:aa,Press:_,on:m,off:n,each:g,merge:pa,extend:oa,assign:ha,inherit:i,bindFn:j,prefixed:u});var pb="undefined"!=typeof a?a:"undefined"!=typeof self?self:{};pb.Hammer=da,"function"==typeof define&&define.amd?define(function(){return da}):"undefined"!=typeof module&&module.exports?module.exports=da:a[c]=da}(window,document,"Hammer");
diff --git a/studio-susie/public/assets/js/vendor/history.min.js b/studio-susie/public/assets/js/vendor/history.min.js
new file mode 100644
index 0000000..65b09c6
--- /dev/null
+++ b/studio-susie/public/assets/js/vendor/history.min.js
@@ -0,0 +1 @@
+!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.History=t():e.History=t()}(this,function(){return function(e){function t(r){if(n[r])return n[r].exports;var a=n[r]={exports:{},id:r,loaded:!1};return e[r].call(a.exports,a,a.exports,t),a.loaded=!0,a.exports}var n={};return t.m=e,t.c=n,t.p="",t(0)}([function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{"default":e}}t.__esModule=!0;var a=n(17),o=r(a);t.createHistory=o["default"];var u=n(18),i=r(u);t.createHashHistory=i["default"];var s=n(19),f=r(s);t.createMemoryHistory=f["default"];var c=n(12),l=r(c);t.createLocation=l["default"];var d=n(22),p=r(d);t.useBasename=p["default"];var h=n(14),g=r(h);t.useBeforeUnload=g["default"];var v=n(15),y=r(v);t.useQueries=y["default"];var m=n(2),w=r(m);t.Actions=w["default"];var O=n(20),_=r(O);t.enableBeforeUnload=_["default"];var b=n(21),P=r(b);t.enableQueries=P["default"]},function(e,t,n){"use strict";var r=function(){};e.exports=r},function(e,t){"use strict";t.__esModule=!0;var n="PUSH";t.PUSH=n;var r="REPLACE";t.REPLACE=r;var a="POP";t.POP=a,t["default"]={PUSH:n,REPLACE:r,POP:a}},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{"default":e}}function a(e,t){return function(){return e.apply(this,arguments)}}t.__esModule=!0;var o=n(1);r(o);t["default"]=a,e.exports=t["default"]},function(e,t){"use strict";t.__esModule=!0;var n=!("undefined"==typeof window||!window.document||!window.document.createElement);t.canUseDOM=n},function(e,t){"use strict";function n(e,t,n){e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent("on"+t,n)}function r(e,t,n){e.removeEventListener?e.removeEventListener(t,n,!1):e.detachEvent("on"+t,n)}function a(){return window.location.href.split("#")[1]||""}function o(e){window.location.replace(window.location.pathname+window.location.search+"#"+e)}function u(){return window.location.pathname+window.location.search+window.location.hash}function i(e){e&&window.history.go(e)}function s(e,t){t(window.confirm(e))}function f(){var e=navigator.userAgent;return-1===e.indexOf("Android 2.")&&-1===e.indexOf("Android 4.0")||-1===e.indexOf("Mobile Safari")||-1!==e.indexOf("Chrome")||-1!==e.indexOf("Windows Phone")?-1!==e.indexOf("CriOS")?!1:window.history&&"pushState"in window.history:!1}function c(){var e=navigator.userAgent;return-1===e.indexOf("Firefox")}t.__esModule=!0,t.addEventListener=n,t.removeEventListener=r,t.getHashPath=a,t.replaceHashPath=o,t.getWindowPath=u,t.go=i,t.getUserConfirmation=s,t.supportsHistory=f,t.supportsGoWithoutReloadUsingHash=c},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{"default":e}}function a(e){var t=i["default"](e),n="",r="",a=t.indexOf("#");-1!==a&&(r=t.substring(a),t=t.substring(0,a));var o=t.indexOf("?");return-1!==o&&(n=t.substring(o),t=t.substring(0,o)),""===t&&(t="/"),{pathname:t,search:n,hash:r}}t.__esModule=!0;var o=n(1),u=(r(o),n(13)),i=r(u);t["default"]=a,e.exports=t["default"]},function(e,t,n){"use strict";var r=function(e,t,n,r,a,o,u,i){if(!e){var s;if(void 0===t)s=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var f=[n,r,a,o,u,i],c=0;s=new Error("Invariant Violation: "+t.replace(/%s/g,function(){return f[c++]}))}throw s.framesToPop=1,s}};e.exports=r},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{"default":e}}function a(e,t,n){var r=e(t,n);e.length<2&&n(r)}t.__esModule=!0;var o=n(1);r(o);t["default"]=a,e.exports=t["default"]},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{"default":e}}function a(e){return s+e}function o(e,t){try{window.sessionStorage.setItem(a(e),JSON.stringify(t))}catch(n){if(n.name===c)return;if(n.name===f&&0===window.sessionStorage.length)return;throw n}}function u(e){var t=void 0;try{t=window.sessionStorage.getItem(a(e))}catch(n){if(n.name===c)return null}if(t)try{return JSON.parse(t)}catch(n){}return null}t.__esModule=!0,t.saveState=o,t.readState=u;var i=n(1),s=(r(i),"@@History/"),f="QuotaExceededError",c="SecurityError"},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{"default":e}}function a(e){function t(e){return s.canUseDOM?void 0:i["default"](!1),n.listen(e)}var n=l["default"](o({getUserConfirmation:f.getUserConfirmation},e,{go:f.go}));return o({},n,{listen:t})}t.__esModule=!0;var o=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},u=n(7),i=r(u),s=n(4),f=n(5),c=n(11),l=r(c);t["default"]=a,e.exports=t["default"]},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{"default":e}}function a(e){return Math.random().toString(36).substr(2,e)}function o(e,t){return e.pathname===t.pathname&&e.search===t.search&&e.key===t.key&&f["default"](e.state,t.state)}function u(){function e(e){return R.push(e),function(){R=R.filter(function(t){return t!==e})}}function t(){return I&&I.action===l.POP?q.indexOf(I.key):Q?q.indexOf(Q.key):-1}function n(e){var n=t();Q=e,Q.action===l.PUSH?q=[].concat(q.slice(0,n+1),[Q.key]):Q.action===l.REPLACE&&(q[n]=Q.key),D.forEach(function(e){e(Q)})}function r(e){if(D.push(e),Q)e(Q);else{var t=U();q=[t.key],n(t)}return function(){D=D.filter(function(t){return t!==e})}}function u(e,t){c.loopAsync(R.length,function(t,n,r){y["default"](R[t],e,function(e){null!=e?r(e):n()})},function(e){C&&"string"==typeof e?C(e,function(e){t(e!==!1)}):t(e!==!1)})}function s(e){Q&&o(Q,e)||(I=e,u(e,function(t){if(I===e)if(t){if(e.action===l.PUSH){var r=_(Q),a=_(e);a===r&&(e.action=l.REPLACE)}L(e)!==!1&&n(e)}else if(Q&&e.action===l.POP){var o=q.indexOf(Q.key),u=q.indexOf(e.key);-1!==o&&-1!==u&&B(o-u)}}))}function f(e){s(P(e,null,l.PUSH,m()))}function d(e){s(P(e,null,l.REPLACE,m()))}function h(){B(-1)}function v(){B(1)}function m(){return a(T)}function _(e){if(null==e||"string"==typeof e)return e;var t=e.pathname,n=e.search,r=e.hash,a=t;return n&&(a+=n),r&&(a+=r),a}function b(e){return _(e)}function P(e,t,n){var r=arguments.length<=3||void 0===arguments[3]?m():arguments[3];return p["default"](e,t,n,r)}function S(e){Q?(x(Q,e),n(Q)):x(U(),e)}function x(e,t){e.state=i({},e.state,t),A(e.key,e.state)}function H(e){-1===R.indexOf(e)&&R.push(e)}function k(e){R=R.filter(function(t){return t!==e})}function M(e,t){"string"==typeof t&&(t=g["default"](t)),f(i({state:e},t))}function E(e,t){"string"==typeof t&&(t=g["default"](t)),d(i({state:e},t))}var j=arguments.length<=0||void 0===arguments[0]?{}:arguments[0],U=j.getCurrentLocation,L=j.finishTransition,A=j.saveState,B=j.go,T=j.keyLength,C=j.getUserConfirmation;"number"!=typeof T&&(T=O);var R=[],q=[],D=[],Q=void 0,I=void 0;return{listenBefore:e,listen:r,transitionTo:s,push:f,replace:d,go:B,goBack:h,goForward:v,createKey:m,createPath:_,createHref:b,createLocation:P,setState:w["default"](S,"setState is deprecated; use location.key to save state instead"),registerTransitionHook:w["default"](H,"registerTransitionHook is deprecated; use listenBefore instead"),unregisterTransitionHook:w["default"](k,"unregisterTransitionHook is deprecated; use the callback returned from listenBefore instead"),pushState:w["default"](M,"pushState is deprecated; use push instead"),replaceState:w["default"](E,"replaceState is deprecated; use replace instead")}}t.__esModule=!0;var i=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},s=n(23),f=r(s),c=n(16),l=n(2),d=n(12),p=r(d),h=n(6),g=r(h),v=n(8),y=r(v),m=n(3),w=r(m),O=6;t["default"]=u,e.exports=t["default"]},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{"default":e}}function a(){var e=arguments.length<=0||void 0===arguments[0]?"/":arguments[0],t=arguments.length<=1||void 0===arguments[1]?null:arguments[1],n=arguments.length<=2||void 0===arguments[2]?o.POP:arguments[2],r=arguments.length<=3||void 0===arguments[3]?null:arguments[3];"string"==typeof e&&(e=i["default"](e));var a=e.pathname||"/",u=e.search||"",s=e.hash||"";return t=e.state||t,{pathname:a,search:u,hash:s,state:t,action:n,key:r}}t.__esModule=!0;var o=n(2),u=n(6),i=r(u);t["default"]=a,e.exports=t["default"]},function(e,t){"use strict";function n(e){var t=e.match(/^https?:\/\/[^\/]*/);return null==t?e:e.substring(t[0].length)}t.__esModule=!0,t["default"]=n,e.exports=t["default"]},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{"default":e}}function a(e){function t(t){var n=e();return"string"==typeof n?((t||window.event).returnValue=n,n):void 0}return f.addEventListener(window,"beforeunload",t),function(){f.removeEventListener(window,"beforeunload",t)}}function o(e){return function(t){function n(){for(var e=void 0,t=0,n=d.length;null==e&&n>t;++t)e=d[t].call();return e}function r(e){return d.push(e),1===d.length&&s.canUseDOM&&(c=a(n)),function(){d=d.filter(function(t){return t!==e}),0===d.length&&c&&(c(),c=null)}}function o(e){s.canUseDOM&&-1===d.indexOf(e)&&(d.push(e),1===d.length&&(c=a(n)))}function i(e){d.length>0&&(d=d.filter(function(t){return t!==e}),0===d.length&&c())}var f=e(t),c=void 0,d=[];return u({},f,{listenBeforeUnload:r,registerBeforeUnloadHook:l["default"](o,"registerBeforeUnloadHook is deprecated; use listenBeforeUnload instead"),unregisterBeforeUnloadHook:l["default"](i,"unregisterBeforeUnloadHook is deprecated; use the callback returned from listenBeforeUnload instead")})}}t.__esModule=!0;var u=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},i=n(1),s=(r(i),n(4)),f=n(5),c=n(3),l=r(c);t["default"]=o,e.exports=t["default"]},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{"default":e}}function a(e,t){var n={};for(var r in e)t.indexOf(r)>=0||Object.prototype.hasOwnProperty.call(e,r)&&(n[r]=e[r]);return n}function o(e){return f.stringify(e).replace(/%20/g,"+")}function u(e){return function(){function t(e){if(null==e.query){var t=e.search;e.query=b(t.substring(1)),e[v]={search:t,searchBase:""}}return e}function n(e,t){var n,r=void 0;if(!t||""===(r=_(t)))return e;"string"==typeof e&&(e=p["default"](e));var a=e[v],o=void 0;o=a&&e.search===a.search?a.searchBase:e.search||"";var u=o+(o?"&":"?")+r;return i({},e,(n={search:u},n[v]={search:u,searchBase:o},n))}function r(e){return S.listenBefore(function(n,r){l["default"](e,t(n),r)})}function u(e){return S.listen(function(n){e(t(n))})}function s(e){S.push(n(e,e.query))}function f(e){S.replace(n(e,e.query))}function c(e,t){return S.createPath(n(e,t||e.query))}function d(e,t){return S.createHref(n(e,t||e.query))}function h(){return t(S.createLocation.apply(S,arguments))}function m(e,t,n){"string"==typeof t&&(t=p["default"](t)),s(i({state:e},t,{query:n}))}function w(e,t,n){"string"==typeof t&&(t=p["default"](t)),f(i({state:e},t,{query:n}))}var O=arguments.length<=0||void 0===arguments[0]?{}:arguments[0],_=O.stringifyQuery,b=O.parseQueryString,P=a(O,["stringifyQuery","parseQueryString"]),S=e(P);return"function"!=typeof _&&(_=o),"function"!=typeof b&&(b=y),i({},S,{listenBefore:r,listen:u,push:s,replace:f,createPath:c,createHref:d,createLocation:h,pushState:g["default"](m,"pushState is deprecated; use push instead"),replaceState:g["default"](w,"replaceState is deprecated; use replace instead")})}}t.__esModule=!0;var i=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},s=n(1),f=(r(s),n(26)),c=n(8),l=r(c),d=n(6),p=r(d),h=n(3),g=r(h),v="$searchBase",y=f.parse;t["default"]=u,e.exports=t["default"]},function(e,t){"use strict";function n(e,t,n){function r(){u=!0,n.apply(this,arguments)}function a(){u||(e>o?t.call(this,o++,a,r):r.apply(this,arguments))}var o=0,u=!1;a()}t.__esModule=!0,t.loopAsync=n},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{"default":e}}function a(){function e(e){e=e||window.history.state||{};var t=c.getWindowPath(),n=e,r=n.key,a=void 0;return r?a=l.readState(r):(a=null,r=m.createKey(),v&&window.history.replaceState(o({},e,{key:r}),null,t)),m.createLocation(t,a,void 0,r)}function t(t){function n(t){void 0!==t.state&&r(e(t.state))}var r=t.transitionTo;return c.addEventListener(window,"popstate",n),function(){c.removeEventListener(window,"popstate",n)}}function n(e){var t=e.basename,n=e.pathname,r=e.search,a=e.hash,o=e.state,u=e.action,i=e.key;if(u!==s.POP){l.saveState(i,o);var f=(t||"")+n+r+a,c={key:i};if(u===s.PUSH){if(y)return window.location.href=f,!1;window.history.pushState(c,null,f)}else{if(y)return window.location.replace(f),!1;window.history.replaceState(c,null,f)}}}function r(e){1===++w&&(O=t(m));var n=m.listenBefore(e);return function(){n(),0===--w&&O()}}function a(e){1===++w&&(O=t(m));var n=m.listen(e);return function(){n(),0===--w&&O()}}function u(e){1===++w&&(O=t(m)),m.registerTransitionHook(e)}function d(e){m.unregisterTransitionHook(e),0===--w&&O()}var h=arguments.length<=0||void 0===arguments[0]?{}:arguments[0];f.canUseDOM?void 0:i["default"](!1);var g=h.forceRefresh,v=c.supportsHistory(),y=!v||g,m=p["default"](o({},h,{getCurrentLocation:e,finishTransition:n,saveState:l.saveState})),w=0,O=void 0;return o({},m,{listenBefore:r,listen:a,registerTransitionHook:u,unregisterTransitionHook:d})}t.__esModule=!0;var o=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},u=n(7),i=r(u),s=n(2),f=n(4),c=n(5),l=n(9),d=n(10),p=r(d);t["default"]=a,e.exports=t["default"]},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{"default":e}}function a(e){return"string"==typeof e&&"/"===e.charAt(0)}function o(){var e=v.getHashPath();return a(e)?!0:(v.replaceHashPath("/"+e),!1)}function u(e,t,n){return e+(-1===e.indexOf("?")?"?":"&")+(t+"="+n)}function i(e,t){return e.replace(new RegExp("[?&]?"+t+"=[a-zA-Z0-9]+"),"")}function s(e,t){var n=e.match(new RegExp("\\?.*?\\b"+t+"=(.+?)\\b"));return n&&n[1]}function f(){function e(){var e=v.getHashPath(),t=void 0,n=void 0;return H?(t=s(e,H),e=i(e,H),t?n=y.readState(t):(n=null,t=k.createKey(),v.replaceHashPath(u(e,H,t)))):t=n=null,k.createLocation(e,n,void 0,t)}function t(t){function n(){o()&&r(e())}var r=t.transitionTo;return o(),v.addEventListener(window,"hashchange",n),function(){v.removeEventListener(window,"hashchange",n)}}function n(e){var t=e.basename,n=e.pathname,r=e.search,a=e.state,o=e.action,i=e.key;if(o!==h.POP){var s=(t||"")+n+r;H?(s=u(s,H,i),y.saveState(i,a)):e.key=e.state=null;var f=v.getHashPath();o===h.PUSH?f!==s&&(window.location.hash=s):f!==s&&v.replaceHashPath(s)}}function r(e){1===++M&&(E=t(k));var n=k.listenBefore(e);return function(){n(),0===--M&&E()}}function a(e){1===++M&&(E=t(k));var n=k.listen(e);return function(){n(),0===--M&&E()}}function f(e){k.push(e)}function l(e){k.replace(e)}function d(e){k.go(e)}function m(e){return"#"+k.createHref(e)}function _(e){1===++M&&(E=t(k)),k.registerTransitionHook(e)}function b(e){k.unregisterTransitionHook(e),0===--M&&E()}function P(e,t){k.pushState(e,t)}function S(e,t){k.replaceState(e,t)}var x=arguments.length<=0||void 0===arguments[0]?{}:arguments[0];g.canUseDOM?void 0:p["default"](!1);var H=x.queryKey;(void 0===H||H)&&(H="string"==typeof H?H:O);var k=w["default"](c({},x,{getCurrentLocation:e,finishTransition:n,saveState:y.saveState})),M=0,E=void 0;v.supportsGoWithoutReloadUsingHash();return c({},k,{listenBefore:r,listen:a,push:f,replace:l,go:d,createHref:m,registerTransitionHook:_,unregisterTransitionHook:b,pushState:P,replaceState:S})}t.__esModule=!0;var c=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},l=n(1),d=(r(l),n(7)),p=r(d),h=n(2),g=n(4),v=n(5),y=n(9),m=n(10),w=r(m),O="_k";t["default"]=f,e.exports=t["default"]},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{"default":e}}function a(e){return e.filter(function(e){return e.state}).reduce(function(e,t){return e[t.key]=t.state,e},{})}function o(){function e(e,t){v[e]=t}function t(e){return v[e]}function n(){var e=h[g],n=e.key,r=e.basename,a=e.pathname,o=e.search,u=(r||"")+a+(o||""),i=void 0;return n?i=t(n):(i=null,n=d.createKey(),e.key=n),d.createLocation(u,i,void 0,n)}function r(e){var t=g+e;return t>=0&&t<h.length}function o(e){if(e){r(e)?void 0:s["default"](!1),g+=e;var t=n();d.transitionTo(u({},t,{action:f.POP}))}}function i(t){switch(t.action){case f.PUSH:g+=1,g<h.length&&h.splice(g),h.push(t),e(t.key,t.state);break;case f.REPLACE:h[g]=t,e(t.key,t.state)}}var c=arguments.length<=0||void 0===arguments[0]?{}:arguments[0];Array.isArray(c)?c={entries:c}:"string"==typeof c&&(c={entries:[c]});var d=l["default"](u({},c,{getCurrentLocation:n,finishTransition:i,saveState:e,go:o})),p=c,h=p.entries,g=p.current;"string"==typeof h?h=[h]:Array.isArray(h)||(h=["/"]),h=h.map(function(e){var t=d.createKey();return"string"==typeof e?{pathname:e,key:t}:"object"==typeof e&&e?u({},e,{key:t}):void s["default"](!1)}),null==g?g=h.length-1:g>=0&&g<h.length?void 0:s["default"](!1);var v=a(h);return d}t.__esModule=!0;var u=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},i=n(7),s=r(i),f=n(2),c=n(11),l=r(c);t["default"]=o,e.exports=t["default"]},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{"default":e}}t.__esModule=!0;var a=n(3),o=r(a),u=n(14),i=r(u);t["default"]=o["default"](i["default"],"enableBeforeUnload is deprecated, use useBeforeUnload instead"),e.exports=t["default"]},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{"default":e}}t.__esModule=!0;var a=n(3),o=r(a),u=n(15),i=r(u);t["default"]=o["default"](i["default"],"enableQueries is deprecated, use useQueries instead"),e.exports=t["default"]},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{"default":e}}function a(e,t){var n={};for(var r in e)t.indexOf(r)>=0||Object.prototype.hasOwnProperty.call(e,r)&&(n[r]=e[r]);return n}function o(e){return function(){function t(e){return O&&null==e.basename&&(0===e.pathname.indexOf(O)?(e.pathname=e.pathname.substring(O.length),e.basename=O,""===e.pathname&&(e.pathname="/")):e.basename=""),e}function n(e){if(!O)return e;"string"==typeof e&&(e=p["default"](e));var t=e.pathname,n="/"===O.slice(-1)?O:O+"/",r="/"===t.charAt(0)?t.slice(1):t,a=n+r;return u({},e,{pathname:a})}function r(e){return b.listenBefore(function(n,r){f["default"](e,t(n),r)})}function o(e){return b.listen(function(n){e(t(n))})}function s(e){b.push(n(e))}function c(e){b.replace(n(e))}function d(e){return b.createPath(n(e))}function h(e){return b.createHref(n(e))}function v(){return t(b.createLocation.apply(b,arguments))}function y(e,t){"string"==typeof t&&(t=p["default"](t)),s(u({state:e},t))}function m(e,t){"string"==typeof t&&(t=p["default"](t)),c(u({state:e},t))}var w=arguments.length<=0||void 0===arguments[0]?{}:arguments[0],O=w.basename,_=a(w,["basename"]),b=e(_);if(null==O&&i.canUseDOM){var P=document.getElementsByTagName("base")[0];P&&(O=l["default"](P.href))}return u({},b,{listenBefore:r,listen:o,push:s,replace:c,createPath:d,createHref:h,createLocation:v,pushState:g["default"](y,"pushState is deprecated; use push instead"),replaceState:g["default"](m,"replaceState is deprecated; use replace instead")})}}t.__esModule=!0;var u=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},i=n(4),s=n(8),f=r(s),c=n(13),l=r(c),d=n(6),p=r(d),h=n(3),g=r(h);t["default"]=o,e.exports=t["default"]},function(e,t,n){function r(e){return null===e||void 0===e}function a(e){return e&&"object"==typeof e&&"number"==typeof e.length?"function"!=typeof e.copy||"function"!=typeof e.slice?!1:e.length>0&&"number"!=typeof e[0]?!1:!0:!1}function o(e,t,n){var o,c;if(r(e)||r(t))return!1;if(e.prototype!==t.prototype)return!1;if(s(e))return s(t)?(e=u.call(e),t=u.call(t),f(e,t,n)):!1;if(a(e)){if(!a(t))return!1;if(e.length!==t.length)return!1;for(o=0;o<e.length;o++)if(e[o]!==t[o])return!1;return!0}try{var l=i(e),d=i(t)}catch(p){return!1}if(l.length!=d.length)return!1;for(l.sort(),d.sort(),o=l.length-1;o>=0;o--)if(l[o]!=d[o])return!1;for(o=l.length-1;o>=0;o--)if(c=l[o],!f(e[c],t[c],n))return!1;return typeof e==typeof t}var u=Array.prototype.slice,i=n(25),s=n(24),f=e.exports=function(e,t,n){return n||(n={}),e===t?!0:e instanceof Date&&t instanceof Date?e.getTime()===t.getTime():!e||!t||"object"!=typeof e&&"object"!=typeof t?n.strict?e===t:e==t:o(e,t,n)}},function(e,t){function n(e){return"[object Arguments]"==Object.prototype.toString.call(e)}function r(e){return e&&"object"==typeof e&&"number"==typeof e.length&&Object.prototype.hasOwnProperty.call(e,"callee")&&!Object.prototype.propertyIsEnumerable.call(e,"callee")||!1}var a="[object Arguments]"==function(){return Object.prototype.toString.call(arguments)}();t=e.exports=a?n:r,t.supported=n,t.unsupported=r},function(e,t){function n(e){var t=[];for(var n in e)t.push(n);return t}t=e.exports="function"==typeof Object.keys?Object.keys:n,t.shim=n},function(e,t,n){"use strict";var r=n(27);t.extract=function(e){return e.split("?")[1]||""},t.parse=function(e){return"string"!=typeof e?{}:(e=e.trim().replace(/^(\?|#|&)/,""),e?e.split("&").reduce(function(e,t){var n=t.replace(/\+/g," ").split("="),r=n.shift(),a=n.length>0?n.join("="):void 0;return r=decodeURIComponent(r),a=void 0===a?null:decodeURIComponent(a),e.hasOwnProperty(r)?Array.isArray(e[r])?e[r].push(a):e[r]=[e[r],a]:e[r]=a,e},{}):{})},t.stringify=function(e){return e?Object.keys(e).sort().map(function(t){var n=e[t];return void 0===n?"":null===n?t:Array.isArray(n)?n.sort().map(function(e){return r(t)+"="+r(e)}).join("&"):r(t)+"="+r(n)}).filter(function(e){return e.length>0}).join("&"):""}},function(e,t){"use strict";e.exports=function(e){return encodeURIComponent(e).replace(/[!'()*]/g,function(e){return"%"+e.charCodeAt(0).toString(16)})}}])}); \ No newline at end of file
diff --git a/studio-susie/public/assets/js/vendor/html5shiv.min.js b/studio-susie/public/assets/js/vendor/html5shiv.min.js
new file mode 100644
index 0000000..355afd1
--- /dev/null
+++ b/studio-susie/public/assets/js/vendor/html5shiv.min.js
@@ -0,0 +1,4 @@
+/**
+* @preserve HTML5 Shiv 3.7.3 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
+*/
+!function(a,b){function c(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x<style>"+b+"</style>",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=t.elements;return"string"==typeof a?a.split(" "):a}function e(a,b){var c=t.elements;"string"!=typeof c&&(c=c.join(" ")),"string"!=typeof a&&(a=a.join(" ")),t.elements=c+" "+a,j(b)}function f(a){var b=s[a[q]];return b||(b={},r++,a[q]=r,s[r]=b),b}function g(a,c,d){if(c||(c=b),l)return c.createElement(a);d||(d=f(c));var e;return e=d.cache[a]?d.cache[a].cloneNode():p.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!e.canHaveChildren||o.test(a)||e.tagUrn?e:d.frag.appendChild(e)}function h(a,c){if(a||(a=b),l)return a.createDocumentFragment();c=c||f(a);for(var e=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)e.createElement(h[g]);return e}function i(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return t.shivMethods?g(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-:]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(t,b.frag)}function j(a){a||(a=b);var d=f(a);return!t.shivCSS||k||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),l||i(a,d),a}var k,l,m="3.7.3",n=a.html5||{},o=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,p=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,q="_html5shiv",r=0,s={};!function(){try{var a=b.createElement("a");a.innerHTML="<xyz></xyz>",k="hidden"in a,l=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){k=!0,l=!0}}();var t={elements:n.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:m,shivCSS:n.shivCSS!==!1,supportsUnknownElements:l,shivMethods:n.shivMethods!==!1,type:"default",shivDocument:j,createElement:g,createDocumentFragment:h,addElements:e};a.html5=t,j(b),"object"==typeof module&&module.exports&&(module.exports=t)}("undefined"!=typeof window?window:this,document); \ No newline at end of file
diff --git a/studio-susie/public/assets/js/vendor/iscroll.js b/studio-susie/public/assets/js/vendor/iscroll.js
new file mode 100644
index 0000000..8bd2b8d
--- /dev/null
+++ b/studio-susie/public/assets/js/vendor/iscroll.js
@@ -0,0 +1,2011 @@
+/*! iScroll v5.1.3 ~ (c) 2008-2014 Matteo Spinelli ~ http://cubiq.org/license */
+(function (window, document, Math) {
+var rAF = window.requestAnimationFrame ||
+ window.webkitRequestAnimationFrame ||
+ window.mozRequestAnimationFrame ||
+ window.oRequestAnimationFrame ||
+ window.msRequestAnimationFrame ||
+ function (callback) { window.setTimeout(callback, 1000 / 60); };
+
+var utils = (function () {
+ var me = {};
+
+ var _elementStyle = document.createElement('div').style;
+ var _vendor = (function () {
+ var vendors = ['t', 'webkitT', 'MozT', 'msT', 'OT'],
+ transform,
+ i = 0,
+ l = vendors.length;
+
+ for ( ; i < l; i++ ) {
+ transform = vendors[i] + 'ransform';
+ if ( transform in _elementStyle ) return vendors[i].substr(0, vendors[i].length-1);
+ }
+
+ return false;
+ })();
+
+ function _prefixStyle (style) {
+ if ( _vendor === false ) return false;
+ if ( _vendor === '' ) return style;
+ return _vendor + style.charAt(0).toUpperCase() + style.substr(1);
+ }
+
+ me.getTime = Date.now || function getTime () { return new Date().getTime(); };
+
+ me.extend = function (target, obj) {
+ for ( var i in obj ) {
+ target[i] = obj[i];
+ }
+ };
+
+ me.addEvent = function (el, type, fn, capture) {
+ el.addEventListener(type, fn, !!capture);
+ };
+
+ me.removeEvent = function (el, type, fn, capture) {
+ el.removeEventListener(type, fn, !!capture);
+ };
+
+ me.prefixPointerEvent = function (pointerEvent) {
+ return window.MSPointerEvent ?
+ 'MSPointer' + pointerEvent.charAt(9).toUpperCase() + pointerEvent.substr(10):
+ pointerEvent;
+ };
+
+ me.momentum = function (current, start, time, lowerMargin, wrapperSize, deceleration) {
+ var distance = current - start,
+ speed = Math.abs(distance) / time,
+ destination,
+ duration;
+
+ deceleration = deceleration === undefined ? 0.0006 : deceleration;
+
+ destination = current + ( speed * speed ) / ( 2 * deceleration ) * ( distance < 0 ? -1 : 1 );
+ duration = speed / deceleration;
+
+ if ( destination < lowerMargin ) {
+ destination = wrapperSize ? lowerMargin - ( wrapperSize / 2.5 * ( speed / 8 ) ) : lowerMargin;
+ distance = Math.abs(destination - current);
+ duration = distance / speed;
+ } else if ( destination > 0 ) {
+ destination = wrapperSize ? wrapperSize / 2.5 * ( speed / 8 ) : 0;
+ distance = Math.abs(current) + destination;
+ duration = distance / speed;
+ }
+
+ return {
+ destination: Math.round(destination),
+ duration: duration
+ };
+ };
+
+ var _transform = _prefixStyle('transform');
+
+ me.extend(me, {
+ hasTransform: _transform !== false,
+ hasPerspective: _prefixStyle('perspective') in _elementStyle,
+ hasTouch: 'ontouchstart' in window,
+ hasPointer: window.PointerEvent || window.MSPointerEvent, // IE10 is prefixed
+ hasTransition: _prefixStyle('transition') in _elementStyle
+ });
+
+ // This should find all Android browsers lower than build 535.19 (both stock browser and webview)
+ me.isBadAndroid = /Android /.test(window.navigator.appVersion) && !(/Chrome\/\d/.test(window.navigator.appVersion));
+
+ me.extend(me.style = {}, {
+ transform: _transform,
+ transitionTimingFunction: _prefixStyle('transitionTimingFunction'),
+ transitionDuration: _prefixStyle('transitionDuration'),
+ transitionDelay: _prefixStyle('transitionDelay'),
+ transformOrigin: _prefixStyle('transformOrigin')
+ });
+
+ me.hasClass = function (e, c) {
+ var re = new RegExp("(^|\\s)" + c + "(\\s|$)");
+ return re.test(e.className);
+ };
+
+ me.addClass = function (e, c) {
+ if ( me.hasClass(e, c) ) {
+ return;
+ }
+
+ var newclass = e.className.split(' ');
+ newclass.push(c);
+ e.className = newclass.join(' ');
+ };
+
+ me.removeClass = function (e, c) {
+ if ( !me.hasClass(e, c) ) {
+ return;
+ }
+
+ var re = new RegExp("(^|\\s)" + c + "(\\s|$)", 'g');
+ e.className = e.className.replace(re, ' ');
+ };
+
+ me.offset = function (el) {
+ var left = -el.offsetLeft,
+ top = -el.offsetTop;
+
+ // jshint -W084
+ while (el = el.offsetParent) {
+ left -= el.offsetLeft;
+ top -= el.offsetTop;
+ }
+ // jshint +W084
+
+ return {
+ left: left,
+ top: top
+ };
+ };
+
+ me.preventDefaultException = function (el, exceptions) {
+ for ( var i in exceptions ) {
+ if ( exceptions[i].test(el[i]) ) {
+ return true;
+ }
+ }
+
+ return false;
+ };
+
+ me.extend(me.eventType = {}, {
+ touchstart: 1,
+ touchmove: 1,
+ touchend: 1,
+
+ mousedown: 2,
+ mousemove: 2,
+ mouseup: 2,
+
+ pointerdown: 3,
+ pointermove: 3,
+ pointerup: 3,
+
+ MSPointerDown: 3,
+ MSPointerMove: 3,
+ MSPointerUp: 3
+ });
+
+ me.extend(me.ease = {}, {
+ quadratic: {
+ style: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',
+ fn: function (k) {
+ return k * ( 2 - k );
+ }
+ },
+ circular: {
+ style: 'cubic-bezier(0.1, 0.57, 0.1, 1)', // Not properly "circular" but this looks better, it should be (0.075, 0.82, 0.165, 1)
+ fn: function (k) {
+ return Math.sqrt( 1 - ( --k * k ) );
+ }
+ },
+ back: {
+ style: 'cubic-bezier(0.175, 0.885, 0.32, 1.275)',
+ fn: function (k) {
+ var b = 4;
+ return ( k = k - 1 ) * k * ( ( b + 1 ) * k + b ) + 1;
+ }
+ },
+ bounce: {
+ style: '',
+ fn: function (k) {
+ if ( ( k /= 1 ) < ( 1 / 2.75 ) ) {
+ return 7.5625 * k * k;
+ } else if ( k < ( 2 / 2.75 ) ) {
+ return 7.5625 * ( k -= ( 1.5 / 2.75 ) ) * k + 0.75;
+ } else if ( k < ( 2.5 / 2.75 ) ) {
+ return 7.5625 * ( k -= ( 2.25 / 2.75 ) ) * k + 0.9375;
+ } else {
+ return 7.5625 * ( k -= ( 2.625 / 2.75 ) ) * k + 0.984375;
+ }
+ }
+ },
+ elastic: {
+ style: '',
+ fn: function (k) {
+ var f = 0.22,
+ e = 0.4;
+
+ if ( k === 0 ) { return 0; }
+ if ( k == 1 ) { return 1; }
+
+ return ( e * Math.pow( 2, - 10 * k ) * Math.sin( ( k - f / 4 ) * ( 2 * Math.PI ) / f ) + 1 );
+ }
+ }
+ });
+
+ me.tap = function (e, eventName) {
+ var ev = document.createEvent('Event');
+ ev.initEvent(eventName, true, true);
+ ev.pageX = e.pageX;
+ ev.pageY = e.pageY;
+ e.target.dispatchEvent(ev);
+ };
+
+ me.click = function (e) {
+ var target = e.target,
+ ev;
+
+ if ( !(/(SELECT|INPUT|TEXTAREA)/i).test(target.tagName) ) {
+ ev = document.createEvent('MouseEvents');
+ ev.initMouseEvent('click', true, true, e.view, 1,
+ target.screenX, target.screenY, target.clientX, target.clientY,
+ e.ctrlKey, e.altKey, e.shiftKey, e.metaKey,
+ 0, null);
+
+ ev._constructed = true;
+ target.dispatchEvent(ev);
+ }
+ };
+
+ return me;
+})();
+
+function IScroll (el, options) {
+ this.wrapper = typeof el == 'string' ? document.querySelector(el) : el;
+ this.scroller = this.wrapper.children[0];
+ this.scrollerStyle = this.scroller.style; // cache style for better performance
+
+ this.options = {
+
+ resizeScrollbars: true,
+
+ mouseWheelSpeed: 20,
+
+ snapThreshold: 0.334,
+
+// INSERT POINT: OPTIONS
+
+ startX: 0,
+ startY: 0,
+ scrollY: true,
+ directionLockThreshold: 5,
+ momentum: true,
+
+ bounce: true,
+ bounceTime: 600,
+ bounceEasing: '',
+
+ preventDefault: true,
+ preventDefaultException: { tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT)$/ },
+
+ HWCompositing: true,
+ useTransition: true,
+ useTransform: true
+ };
+
+ for ( var i in options ) {
+ this.options[i] = options[i];
+ }
+
+ // Normalize options
+ this.translateZ = this.options.HWCompositing && utils.hasPerspective ? ' translateZ(0)' : '';
+
+ this.options.useTransition = utils.hasTransition && this.options.useTransition;
+ this.options.useTransform = utils.hasTransform && this.options.useTransform;
+
+ this.options.eventPassthrough = this.options.eventPassthrough === true ? 'vertical' : this.options.eventPassthrough;
+ this.options.preventDefault = !this.options.eventPassthrough && this.options.preventDefault;
+
+ // If you want eventPassthrough I have to lock one of the axes
+ this.options.scrollY = this.options.eventPassthrough == 'vertical' ? false : this.options.scrollY;
+ this.options.scrollX = this.options.eventPassthrough == 'horizontal' ? false : this.options.scrollX;
+
+ // With eventPassthrough we also need lockDirection mechanism
+ this.options.freeScroll = this.options.freeScroll && !this.options.eventPassthrough;
+ this.options.directionLockThreshold = this.options.eventPassthrough ? 0 : this.options.directionLockThreshold;
+
+ this.options.bounceEasing = typeof this.options.bounceEasing == 'string' ? utils.ease[this.options.bounceEasing] || utils.ease.circular : this.options.bounceEasing;
+
+ this.options.resizePolling = this.options.resizePolling === undefined ? 60 : this.options.resizePolling;
+
+ if ( this.options.tap === true ) {
+ this.options.tap = 'tap';
+ }
+
+ if ( this.options.shrinkScrollbars == 'scale' ) {
+ this.options.useTransition = false;
+ }
+
+ this.options.invertWheelDirection = this.options.invertWheelDirection ? -1 : 1;
+
+// INSERT POINT: NORMALIZATION
+
+ // Some defaults
+ this.x = 0;
+ this.y = 0;
+ this.directionX = 0;
+ this.directionY = 0;
+ this._events = {};
+
+// INSERT POINT: DEFAULTS
+
+ this._init();
+ this.refresh();
+
+ this.scrollTo(this.options.startX, this.options.startY);
+ this.enable();
+}
+
+IScroll.prototype = {
+ version: '5.1.3',
+
+ _init: function () {
+ this._initEvents();
+
+ if ( this.options.scrollbars || this.options.indicators ) {
+ this._initIndicators();
+ }
+
+ if ( this.options.mouseWheel ) {
+ this._initWheel();
+ }
+
+ if ( this.options.snap ) {
+ this._initSnap();
+ }
+
+ if ( this.options.keyBindings ) {
+ this._initKeys();
+ }
+
+// INSERT POINT: _init
+
+ },
+
+ destroy: function () {
+ this._initEvents(true);
+
+ this._execEvent('destroy');
+ },
+
+ _transitionEnd: function (e) {
+ if ( e.target != this.scroller || !this.isInTransition ) {
+ return;
+ }
+
+ this._transitionTime();
+ if ( !this.resetPosition(this.options.bounceTime) ) {
+ this.isInTransition = false;
+ this._execEvent('scrollEnd');
+ }
+ },
+
+ _start: function (e) {
+ // React to left mouse button only
+ if ( utils.eventType[e.type] != 1 ) {
+ if ( e.button !== 0 ) {
+ return;
+ }
+ }
+
+ if ( !this.enabled || (this.initiated && utils.eventType[e.type] !== this.initiated) ) {
+ return;
+ }
+
+ if ( this.options.preventDefault && !utils.isBadAndroid && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) {
+ e.preventDefault();
+ }
+
+ var point = e.touches ? e.touches[0] : e,
+ pos;
+
+ this.initiated = utils.eventType[e.type];
+ this.moved = false;
+ this.distX = 0;
+ this.distY = 0;
+ this.directionX = 0;
+ this.directionY = 0;
+ this.directionLocked = 0;
+
+ this._transitionTime();
+
+ this.startTime = utils.getTime();
+
+ if ( this.options.useTransition && this.isInTransition ) {
+ this.isInTransition = false;
+ pos = this.getComputedPosition();
+ this._translate(Math.round(pos.x), Math.round(pos.y));
+ this._execEvent('scrollEnd');
+ } else if ( !this.options.useTransition && this.isAnimating ) {
+ this.isAnimating = false;
+ this._execEvent('scrollEnd');
+ }
+
+ this.startX = this.x;
+ this.startY = this.y;
+ this.absStartX = this.x;
+ this.absStartY = this.y;
+ this.pointX = point.pageX;
+ this.pointY = point.pageY;
+
+ this._execEvent('beforeScrollStart');
+ },
+
+ _move: function (e) {
+ if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) {
+ return;
+ }
+
+ if ( this.options.preventDefault ) { // increases performance on Android? TODO: check!
+ e.preventDefault();
+ }
+
+ var point = e.touches ? e.touches[0] : e,
+ deltaX = point.pageX - this.pointX,
+ deltaY = point.pageY - this.pointY,
+ timestamp = utils.getTime(),
+ newX, newY,
+ absDistX, absDistY;
+
+ this.pointX = point.pageX;
+ this.pointY = point.pageY;
+
+ this.distX += deltaX;
+ this.distY += deltaY;
+ absDistX = Math.abs(this.distX);
+ absDistY = Math.abs(this.distY);
+
+ // We need to move at least 10 pixels for the scrolling to initiate
+ if ( timestamp - this.endTime > 300 && (absDistX < 10 && absDistY < 10) ) {
+ return;
+ }
+
+ // If you are scrolling in one direction lock the other
+ if ( !this.directionLocked && !this.options.freeScroll ) {
+ if ( absDistX > absDistY + this.options.directionLockThreshold ) {
+ this.directionLocked = 'h'; // lock horizontally
+ } else if ( absDistY >= absDistX + this.options.directionLockThreshold ) {
+ this.directionLocked = 'v'; // lock vertically
+ } else {
+ this.directionLocked = 'n'; // no lock
+ }
+ }
+
+ if ( this.directionLocked == 'h' ) {
+ if ( this.options.eventPassthrough == 'vertical' ) {
+ e.preventDefault();
+ } else if ( this.options.eventPassthrough == 'horizontal' ) {
+ this.initiated = false;
+ return;
+ }
+
+ deltaY = 0;
+ } else if ( this.directionLocked == 'v' ) {
+ if ( this.options.eventPassthrough == 'horizontal' ) {
+ e.preventDefault();
+ } else if ( this.options.eventPassthrough == 'vertical' ) {
+ this.initiated = false;
+ return;
+ }
+
+ deltaX = 0;
+ }
+
+ deltaX = this.hasHorizontalScroll ? deltaX : 0;
+ deltaY = this.hasVerticalScroll ? deltaY : 0;
+
+ newX = this.x + deltaX;
+ newY = this.y + deltaY;
+
+ // Slow down if outside of the boundaries
+ if ( newX > 0 || newX < this.maxScrollX ) {
+ newX = this.options.bounce ? this.x + deltaX / 3 : newX > 0 ? 0 : this.maxScrollX;
+ }
+ if ( newY > 0 || newY < this.maxScrollY ) {
+ newY = this.options.bounce ? this.y + deltaY / 3 : newY > 0 ? 0 : this.maxScrollY;
+ }
+
+ this.directionX = deltaX > 0 ? -1 : deltaX < 0 ? 1 : 0;
+ this.directionY = deltaY > 0 ? -1 : deltaY < 0 ? 1 : 0;
+
+ if ( !this.moved ) {
+ this._execEvent('scrollStart');
+ }
+
+ this.moved = true;
+
+ this._translate(newX, newY);
+
+/* REPLACE START: _move */
+
+ if ( timestamp - this.startTime > 300 ) {
+ this.startTime = timestamp;
+ this.startX = this.x;
+ this.startY = this.y;
+ }
+
+/* REPLACE END: _move */
+
+ },
+
+ _end: function (e) {
+ if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) {
+ return;
+ }
+
+ if ( this.options.preventDefault && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) {
+ e.preventDefault();
+ }
+
+ var point = e.changedTouches ? e.changedTouches[0] : e,
+ momentumX,
+ momentumY,
+ duration = utils.getTime() - this.startTime,
+ newX = Math.round(this.x),
+ newY = Math.round(this.y),
+ distanceX = Math.abs(newX - this.startX),
+ distanceY = Math.abs(newY - this.startY),
+ time = 0,
+ easing = '';
+
+ this.isInTransition = 0;
+ this.initiated = 0;
+ this.endTime = utils.getTime();
+
+ // reset if we are outside of the boundaries
+ if ( this.resetPosition(this.options.bounceTime) ) {
+ return;
+ }
+
+ this.scrollTo(newX, newY); // ensures that the last position is rounded
+
+ // we scrolled less than 10 pixels
+ if ( !this.moved ) {
+ if ( this.options.tap ) {
+ utils.tap(e, this.options.tap);
+ }
+
+ if ( this.options.click ) {
+ utils.click(e);
+ }
+
+ this._execEvent('scrollCancel');
+ return;
+ }
+
+ if ( this._events.flick && duration < 200 && distanceX < 100 && distanceY < 100 ) {
+ this._execEvent('flick');
+ return;
+ }
+
+ // start momentum animation if needed
+ if ( this.options.momentum && duration < 300 ) {
+ momentumX = this.hasHorizontalScroll ? utils.momentum(this.x, this.startX, duration, this.maxScrollX, this.options.bounce ? this.wrapperWidth : 0, this.options.deceleration) : { destination: newX, duration: 0 };
+ momentumY = this.hasVerticalScroll ? utils.momentum(this.y, this.startY, duration, this.maxScrollY, this.options.bounce ? this.wrapperHeight : 0, this.options.deceleration) : { destination: newY, duration: 0 };
+ newX = momentumX.destination;
+ newY = momentumY.destination;
+ time = Math.max(momentumX.duration, momentumY.duration);
+ this.isInTransition = 1;
+ }
+
+
+ if ( this.options.snap ) {
+ var snap = this._nearestSnap(newX, newY);
+ this.currentPage = snap;
+ time = this.options.snapSpeed || Math.max(
+ Math.max(
+ Math.min(Math.abs(newX - snap.x), 1000),
+ Math.min(Math.abs(newY - snap.y), 1000)
+ ), 300);
+ newX = snap.x;
+ newY = snap.y;
+
+ this.directionX = 0;
+ this.directionY = 0;
+ easing = this.options.bounceEasing;
+ }
+
+// INSERT POINT: _end
+
+ if ( newX != this.x || newY != this.y ) {
+ // change easing function when scroller goes out of the boundaries
+ if ( newX > 0 || newX < this.maxScrollX || newY > 0 || newY < this.maxScrollY ) {
+ easing = utils.ease.quadratic;
+ }
+
+ this.scrollTo(newX, newY, time, easing);
+ return;
+ }
+
+ this._execEvent('scrollEnd');
+ },
+
+ _resize: function () {
+ var that = this;
+
+ clearTimeout(this.resizeTimeout);
+
+ this.resizeTimeout = setTimeout(function () {
+ that.refresh();
+ }, this.options.resizePolling);
+ },
+
+ resetPosition: function (time) {
+ var x = this.x,
+ y = this.y;
+
+ time = time || 0;
+
+ if ( !this.hasHorizontalScroll || this.x > 0 ) {
+ x = 0;
+ } else if ( this.x < this.maxScrollX ) {
+ x = this.maxScrollX;
+ }
+
+ if ( !this.hasVerticalScroll || this.y > 0 ) {
+ y = 0;
+ } else if ( this.y < this.maxScrollY ) {
+ y = this.maxScrollY;
+ }
+
+ if ( x == this.x && y == this.y ) {
+ return false;
+ }
+
+ this.scrollTo(x, y, time, this.options.bounceEasing);
+
+ return true;
+ },
+
+ disable: function () {
+ this.enabled = false;
+ },
+
+ enable: function () {
+ this.enabled = true;
+ },
+
+ refresh: function () {
+ var rf = this.wrapper.offsetHeight; // Force reflow
+
+ this.wrapperWidth = this.wrapper.clientWidth;
+ this.wrapperHeight = this.wrapper.clientHeight;
+
+/* REPLACE START: refresh */
+
+ this.scrollerWidth = this.scroller.offsetWidth;
+ this.scrollerHeight = this.scroller.offsetHeight;
+
+ this.maxScrollX = this.wrapperWidth - this.scrollerWidth;
+ this.maxScrollY = this.wrapperHeight - this.scrollerHeight;
+
+/* REPLACE END: refresh */
+
+ this.hasHorizontalScroll = this.options.scrollX && this.maxScrollX < 0;
+ this.hasVerticalScroll = this.options.scrollY && this.maxScrollY < 0;
+
+ if ( !this.hasHorizontalScroll ) {
+ this.maxScrollX = 0;
+ this.scrollerWidth = this.wrapperWidth;
+ }
+
+ if ( !this.hasVerticalScroll ) {
+ this.maxScrollY = 0;
+ this.scrollerHeight = this.wrapperHeight;
+ }
+
+ this.endTime = 0;
+ this.directionX = 0;
+ this.directionY = 0;
+
+ this.wrapperOffset = utils.offset(this.wrapper);
+
+ this._execEvent('refresh');
+
+ this.resetPosition();
+
+// INSERT POINT: _refresh
+
+ },
+
+ on: function (type, fn) {
+ if ( !this._events[type] ) {
+ this._events[type] = [];
+ }
+
+ this._events[type].push(fn);
+ },
+
+ off: function (type, fn) {
+ if ( !this._events[type] ) {
+ return;
+ }
+
+ var index = this._events[type].indexOf(fn);
+
+ if ( index > -1 ) {
+ this._events[type].splice(index, 1);
+ }
+ },
+
+ _execEvent: function (type) {
+ if ( !this._events[type] ) {
+ return;
+ }
+
+ var i = 0,
+ l = this._events[type].length;
+
+ if ( !l ) {
+ return;
+ }
+
+ for ( ; i < l; i++ ) {
+ this._events[type][i].apply(this, [].slice.call(arguments, 1));
+ }
+ },
+
+ scrollBy: function (x, y, time, easing) {
+ x = this.x + x;
+ y = this.y + y;
+ time = time || 0;
+
+ this.scrollTo(x, y, time, easing);
+ },
+
+ scrollTo: function (x, y, time, easing) {
+ easing = easing || utils.ease.circular;
+
+ this.isInTransition = this.options.useTransition && time > 0;
+
+ if ( !time || (this.options.useTransition && easing.style) ) {
+ this._transitionTimingFunction(easing.style);
+ this._transitionTime(time);
+ this._translate(x, y);
+ } else {
+ this._animate(x, y, time, easing.fn);
+ }
+ },
+
+ scrollToElement: function (el, time, offsetX, offsetY, easing) {
+ el = el.nodeType ? el : this.scroller.querySelector(el);
+
+ if ( !el ) {
+ return;
+ }
+
+ var pos = utils.offset(el);
+
+ pos.left -= this.wrapperOffset.left;
+ pos.top -= this.wrapperOffset.top;
+
+ // if offsetX/Y are true we center the element to the screen
+ if ( offsetX === true ) {
+ offsetX = Math.round(el.offsetWidth / 2 - this.wrapper.offsetWidth / 2);
+ }
+ if ( offsetY === true ) {
+ offsetY = Math.round(el.offsetHeight / 2 - this.wrapper.offsetHeight / 2);
+ }
+
+ pos.left -= offsetX || 0;
+ pos.top -= offsetY || 0;
+
+ pos.left = pos.left > 0 ? 0 : pos.left < this.maxScrollX ? this.maxScrollX : pos.left;
+ pos.top = pos.top > 0 ? 0 : pos.top < this.maxScrollY ? this.maxScrollY : pos.top;
+
+ time = time === undefined || time === null || time === 'auto' ? Math.max(Math.abs(this.x-pos.left), Math.abs(this.y-pos.top)) : time;
+
+ this.scrollTo(pos.left, pos.top, time, easing);
+ },
+
+ _transitionTime: function (time) {
+ time = time || 0;
+
+ this.scrollerStyle[utils.style.transitionDuration] = time + 'ms';
+
+ if ( !time && utils.isBadAndroid ) {
+ this.scrollerStyle[utils.style.transitionDuration] = '0.001s';
+ }
+
+
+ if ( this.indicators ) {
+ for ( var i = this.indicators.length; i--; ) {
+ this.indicators[i].transitionTime(time);
+ }
+ }
+
+
+// INSERT POINT: _transitionTime
+
+ },
+
+ _transitionTimingFunction: function (easing) {
+ this.scrollerStyle[utils.style.transitionTimingFunction] = easing;
+
+
+ if ( this.indicators ) {
+ for ( var i = this.indicators.length; i--; ) {
+ this.indicators[i].transitionTimingFunction(easing);
+ }
+ }
+
+
+// INSERT POINT: _transitionTimingFunction
+
+ },
+
+ _translate: function (x, y) {
+ if ( this.options.useTransform ) {
+
+/* REPLACE START: _translate */
+
+ this.scrollerStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.translateZ;
+
+/* REPLACE END: _translate */
+
+ } else {
+ x = Math.round(x);
+ y = Math.round(y);
+ this.scrollerStyle.left = x + 'px';
+ this.scrollerStyle.top = y + 'px';
+ }
+
+ this.x = x;
+ this.y = y;
+
+
+ if ( this.indicators ) {
+ for ( var i = this.indicators.length; i--; ) {
+ this.indicators[i].updatePosition();
+ }
+ }
+
+
+// INSERT POINT: _translate
+
+ },
+
+ _initEvents: function (remove) {
+ var eventType = remove ? utils.removeEvent : utils.addEvent,
+ target = this.options.bindToWrapper ? this.wrapper : window;
+
+ eventType(window, 'orientationchange', this);
+ eventType(window, 'resize', this);
+
+ if ( this.options.click ) {
+ eventType(this.wrapper, 'click', this, true);
+ }
+
+ if ( !this.options.disableMouse ) {
+ eventType(this.wrapper, 'mousedown', this);
+ eventType(target, 'mousemove', this);
+ eventType(target, 'mousecancel', this);
+ eventType(target, 'mouseup', this);
+ }
+
+ if ( utils.hasPointer && !this.options.disablePointer ) {
+ eventType(this.wrapper, utils.prefixPointerEvent('pointerdown'), this);
+ eventType(target, utils.prefixPointerEvent('pointermove'), this);
+ eventType(target, utils.prefixPointerEvent('pointercancel'), this);
+ eventType(target, utils.prefixPointerEvent('pointerup'), this);
+ }
+
+ if ( utils.hasTouch && !this.options.disableTouch ) {
+ eventType(this.wrapper, 'touchstart', this);
+ eventType(target, 'touchmove', this);
+ eventType(target, 'touchcancel', this);
+ eventType(target, 'touchend', this);
+ }
+
+ eventType(this.scroller, 'transitionend', this);
+ eventType(this.scroller, 'webkitTransitionEnd', this);
+ eventType(this.scroller, 'oTransitionEnd', this);
+ eventType(this.scroller, 'MSTransitionEnd', this);
+ },
+
+ getComputedPosition: function () {
+ var matrix = window.getComputedStyle(this.scroller, null),
+ x, y;
+
+ if ( this.options.useTransform ) {
+ matrix = matrix[utils.style.transform].split(')')[0].split(', ');
+ x = +(matrix[12] || matrix[4]);
+ y = +(matrix[13] || matrix[5]);
+ } else {
+ x = +matrix.left.replace(/[^-\d.]/g, '');
+ y = +matrix.top.replace(/[^-\d.]/g, '');
+ }
+
+ return { x: x, y: y };
+ },
+
+ _initIndicators: function () {
+ var interactive = this.options.interactiveScrollbars,
+ customStyle = typeof this.options.scrollbars != 'string',
+ indicators = [],
+ indicator;
+
+ var that = this;
+
+ this.indicators = [];
+
+ if ( this.options.scrollbars ) {
+ // Vertical scrollbar
+ if ( this.options.scrollY ) {
+ indicator = {
+ el: createDefaultScrollbar('v', interactive, this.options.scrollbars),
+ interactive: interactive,
+ defaultScrollbars: true,
+ customStyle: customStyle,
+ resize: this.options.resizeScrollbars,
+ shrink: this.options.shrinkScrollbars,
+ fade: this.options.fadeScrollbars,
+ listenX: false
+ };
+
+ this.wrapper.appendChild(indicator.el);
+ indicators.push(indicator);
+ }
+
+ // Horizontal scrollbar
+ if ( this.options.scrollX ) {
+ indicator = {
+ el: createDefaultScrollbar('h', interactive, this.options.scrollbars),
+ interactive: interactive,
+ defaultScrollbars: true,
+ customStyle: customStyle,
+ resize: this.options.resizeScrollbars,
+ shrink: this.options.shrinkScrollbars,
+ fade: this.options.fadeScrollbars,
+ listenY: false
+ };
+
+ this.wrapper.appendChild(indicator.el);
+ indicators.push(indicator);
+ }
+ }
+
+ if ( this.options.indicators ) {
+ // TODO: check concat compatibility
+ indicators = indicators.concat(this.options.indicators);
+ }
+
+ for ( var i = indicators.length; i--; ) {
+ this.indicators.push( new Indicator(this, indicators[i]) );
+ }
+
+ // TODO: check if we can use array.map (wide compatibility and performance issues)
+ function _indicatorsMap (fn) {
+ for ( var i = that.indicators.length; i--; ) {
+ fn.call(that.indicators[i]);
+ }
+ }
+
+ if ( this.options.fadeScrollbars ) {
+ this.on('scrollEnd', function () {
+ _indicatorsMap(function () {
+ this.fade();
+ });
+ });
+
+ this.on('scrollCancel', function () {
+ _indicatorsMap(function () {
+ this.fade();
+ });
+ });
+
+ this.on('scrollStart', function () {
+ _indicatorsMap(function () {
+ this.fade(1);
+ });
+ });
+
+ this.on('beforeScrollStart', function () {
+ _indicatorsMap(function () {
+ this.fade(1, true);
+ });
+ });
+ }
+
+
+ this.on('refresh', function () {
+ _indicatorsMap(function () {
+ this.refresh();
+ });
+ });
+
+ this.on('destroy', function () {
+ _indicatorsMap(function () {
+ this.destroy();
+ });
+
+ delete this.indicators;
+ });
+ },
+
+ _initWheel: function () {
+ utils.addEvent(this.wrapper, 'wheel', this);
+ utils.addEvent(this.wrapper, 'mousewheel', this);
+ utils.addEvent(this.wrapper, 'DOMMouseScroll', this);
+
+ this.on('destroy', function () {
+ utils.removeEvent(this.wrapper, 'wheel', this);
+ utils.removeEvent(this.wrapper, 'mousewheel', this);
+ utils.removeEvent(this.wrapper, 'DOMMouseScroll', this);
+ });
+ },
+
+ _wheel: function (e) {
+ if ( !this.enabled ) {
+ return;
+ }
+
+ e.preventDefault();
+ e.stopPropagation();
+
+ var wheelDeltaX, wheelDeltaY,
+ newX, newY,
+ that = this;
+
+ if ( this.wheelTimeout === undefined ) {
+ that._execEvent('scrollStart');
+ }
+
+ // Execute the scrollEnd event after 400ms the wheel stopped scrolling
+ clearTimeout(this.wheelTimeout);
+ this.wheelTimeout = setTimeout(function () {
+ that._execEvent('scrollEnd');
+ that.wheelTimeout = undefined;
+ }, 400);
+
+ if ( 'deltaX' in e ) {
+ if (e.deltaMode === 1) {
+ wheelDeltaX = -e.deltaX * this.options.mouseWheelSpeed;
+ wheelDeltaY = -e.deltaY * this.options.mouseWheelSpeed;
+ } else {
+ wheelDeltaX = -e.deltaX;
+ wheelDeltaY = -e.deltaY;
+ }
+ } else if ( 'wheelDeltaX' in e ) {
+ wheelDeltaX = e.wheelDeltaX / 120 * this.options.mouseWheelSpeed;
+ wheelDeltaY = e.wheelDeltaY / 120 * this.options.mouseWheelSpeed;
+ } else if ( 'wheelDelta' in e ) {
+ wheelDeltaX = wheelDeltaY = e.wheelDelta / 120 * this.options.mouseWheelSpeed;
+ } else if ( 'detail' in e ) {
+ wheelDeltaX = wheelDeltaY = -e.detail / 3 * this.options.mouseWheelSpeed;
+ } else {
+ return;
+ }
+
+ wheelDeltaX *= this.options.invertWheelDirection;
+ wheelDeltaY *= this.options.invertWheelDirection;
+
+ if ( !this.hasVerticalScroll ) {
+ wheelDeltaX = wheelDeltaY;
+ wheelDeltaY = 0;
+ }
+
+ if ( this.options.snap ) {
+ newX = this.currentPage.pageX;
+ newY = this.currentPage.pageY;
+
+ if ( wheelDeltaX > 0 ) {
+ newX--;
+ } else if ( wheelDeltaX < 0 ) {
+ newX++;
+ }
+
+ if ( wheelDeltaY > 0 ) {
+ newY--;
+ } else if ( wheelDeltaY < 0 ) {
+ newY++;
+ }
+
+ this.goToPage(newX, newY);
+
+ return;
+ }
+
+ newX = this.x + Math.round(this.hasHorizontalScroll ? wheelDeltaX : 0);
+ newY = this.y + Math.round(this.hasVerticalScroll ? wheelDeltaY : 0);
+
+ if ( newX > 0 ) {
+ newX = 0;
+ } else if ( newX < this.maxScrollX ) {
+ newX = this.maxScrollX;
+ }
+
+ if ( newY > 0 ) {
+ newY = 0;
+ } else if ( newY < this.maxScrollY ) {
+ newY = this.maxScrollY;
+ }
+
+ this.scrollTo(newX, newY, 0);
+
+// INSERT POINT: _wheel
+ },
+
+ _initSnap: function () {
+ this.currentPage = {};
+
+ if ( typeof this.options.snap == 'string' ) {
+ this.options.snap = this.scroller.querySelectorAll(this.options.snap);
+ }
+
+ this.on('refresh', function () {
+ var i = 0, l,
+ m = 0, n,
+ cx, cy,
+ x = 0, y,
+ stepX = this.options.snapStepX || this.wrapperWidth,
+ stepY = this.options.snapStepY || this.wrapperHeight,
+ el;
+
+ this.pages = [];
+
+ if ( !this.wrapperWidth || !this.wrapperHeight || !this.scrollerWidth || !this.scrollerHeight ) {
+ return;
+ }
+
+ if ( this.options.snap === true ) {
+ cx = Math.round( stepX / 2 );
+ cy = Math.round( stepY / 2 );
+
+ while ( x > -this.scrollerWidth ) {
+ this.pages[i] = [];
+ l = 0;
+ y = 0;
+
+ while ( y > -this.scrollerHeight ) {
+ this.pages[i][l] = {
+ x: Math.max(x, this.maxScrollX),
+ y: Math.max(y, this.maxScrollY),
+ width: stepX,
+ height: stepY,
+ cx: x - cx,
+ cy: y - cy
+ };
+
+ y -= stepY;
+ l++;
+ }
+
+ x -= stepX;
+ i++;
+ }
+ } else {
+ el = this.options.snap;
+ l = el.length;
+ n = -1;
+
+ for ( ; i < l; i++ ) {
+ if ( i === 0 || el[i].offsetLeft <= el[i-1].offsetLeft ) {
+ m = 0;
+ n++;
+ }
+
+ if ( !this.pages[m] ) {
+ this.pages[m] = [];
+ }
+
+ x = Math.max(-el[i].offsetLeft, this.maxScrollX);
+ y = Math.max(-el[i].offsetTop, this.maxScrollY);
+ cx = x - Math.round(el[i].offsetWidth / 2);
+ cy = y - Math.round(el[i].offsetHeight / 2);
+
+ this.pages[m][n] = {
+ x: x,
+ y: y,
+ width: el[i].offsetWidth,
+ height: el[i].offsetHeight,
+ cx: cx,
+ cy: cy
+ };
+
+ if ( x > this.maxScrollX ) {
+ m++;
+ }
+ }
+ }
+
+ this.goToPage(this.currentPage.pageX || 0, this.currentPage.pageY || 0, 0);
+
+ // Update snap threshold if needed
+ if ( this.options.snapThreshold % 1 === 0 ) {
+ this.snapThresholdX = this.options.snapThreshold;
+ this.snapThresholdY = this.options.snapThreshold;
+ } else {
+ this.snapThresholdX = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].width * this.options.snapThreshold);
+ this.snapThresholdY = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].height * this.options.snapThreshold);
+ }
+ });
+
+ this.on('flick', function () {
+ var time = this.options.snapSpeed || Math.max(
+ Math.max(
+ Math.min(Math.abs(this.x - this.startX), 1000),
+ Math.min(Math.abs(this.y - this.startY), 1000)
+ ), 300);
+
+ this.goToPage(
+ this.currentPage.pageX + this.directionX,
+ this.currentPage.pageY + this.directionY,
+ time
+ );
+ });
+ },
+
+ _nearestSnap: function (x, y) {
+ if ( !this.pages.length ) {
+ return { x: 0, y: 0, pageX: 0, pageY: 0 };
+ }
+
+ var i = 0,
+ l = this.pages.length,
+ m = 0;
+
+ // Check if we exceeded the snap threshold
+ if ( Math.abs(x - this.absStartX) < this.snapThresholdX &&
+ Math.abs(y - this.absStartY) < this.snapThresholdY ) {
+ return this.currentPage;
+ }
+
+ if ( x > 0 ) {
+ x = 0;
+ } else if ( x < this.maxScrollX ) {
+ x = this.maxScrollX;
+ }
+
+ if ( y > 0 ) {
+ y = 0;
+ } else if ( y < this.maxScrollY ) {
+ y = this.maxScrollY;
+ }
+
+ for ( ; i < l; i++ ) {
+ if ( x >= this.pages[i][0].cx ) {
+ x = this.pages[i][0].x;
+ break;
+ }
+ }
+
+ l = this.pages[i].length;
+
+ for ( ; m < l; m++ ) {
+ if ( y >= this.pages[0][m].cy ) {
+ y = this.pages[0][m].y;
+ break;
+ }
+ }
+
+ if ( i == this.currentPage.pageX ) {
+ i += this.directionX;
+
+ if ( i < 0 ) {
+ i = 0;
+ } else if ( i >= this.pages.length ) {
+ i = this.pages.length - 1;
+ }
+
+ x = this.pages[i][0].x;
+ }
+
+ if ( m == this.currentPage.pageY ) {
+ m += this.directionY;
+
+ if ( m < 0 ) {
+ m = 0;
+ } else if ( m >= this.pages[0].length ) {
+ m = this.pages[0].length - 1;
+ }
+
+ y = this.pages[0][m].y;
+ }
+
+ return {
+ x: x,
+ y: y,
+ pageX: i,
+ pageY: m
+ };
+ },
+
+ goToPage: function (x, y, time, easing) {
+ easing = easing || this.options.bounceEasing;
+
+ if ( x >= this.pages.length ) {
+ x = this.pages.length - 1;
+ } else if ( x < 0 ) {
+ x = 0;
+ }
+
+ if ( y >= this.pages[x].length ) {
+ y = this.pages[x].length - 1;
+ } else if ( y < 0 ) {
+ y = 0;
+ }
+
+ var posX = this.pages[x][y].x,
+ posY = this.pages[x][y].y;
+
+ time = time === undefined ? this.options.snapSpeed || Math.max(
+ Math.max(
+ Math.min(Math.abs(posX - this.x), 1000),
+ Math.min(Math.abs(posY - this.y), 1000)
+ ), 300) : time;
+
+ this.currentPage = {
+ x: posX,
+ y: posY,
+ pageX: x,
+ pageY: y
+ };
+
+ this.scrollTo(posX, posY, time, easing);
+ },
+
+ next: function (time, easing) {
+ var x = this.currentPage.pageX,
+ y = this.currentPage.pageY;
+
+ x++;
+
+ if ( x >= this.pages.length && this.hasVerticalScroll ) {
+ x = 0;
+ y++;
+ }
+
+ this.goToPage(x, y, time, easing);
+ },
+
+ prev: function (time, easing) {
+ var x = this.currentPage.pageX,
+ y = this.currentPage.pageY;
+
+ x--;
+
+ if ( x < 0 && this.hasVerticalScroll ) {
+ x = 0;
+ y--;
+ }
+
+ this.goToPage(x, y, time, easing);
+ },
+
+ _initKeys: function (e) {
+ // default key bindings
+ var keys = {
+ pageUp: 33,
+ pageDown: 34,
+ end: 35,
+ home: 36,
+ left: 37,
+ up: 38,
+ right: 39,
+ down: 40
+ };
+ var i;
+
+ // if you give me characters I give you keycode
+ if ( typeof this.options.keyBindings == 'object' ) {
+ for ( i in this.options.keyBindings ) {
+ if ( typeof this.options.keyBindings[i] == 'string' ) {
+ this.options.keyBindings[i] = this.options.keyBindings[i].toUpperCase().charCodeAt(0);
+ }
+ }
+ } else {
+ this.options.keyBindings = {};
+ }
+
+ for ( i in keys ) {
+ this.options.keyBindings[i] = this.options.keyBindings[i] || keys[i];
+ }
+
+ utils.addEvent(window, 'keydown', this);
+
+ this.on('destroy', function () {
+ utils.removeEvent(window, 'keydown', this);
+ });
+ },
+
+ _key: function (e) {
+ if ( !this.enabled ) {
+ return;
+ }
+
+ var snap = this.options.snap, // we are using this alot, better to cache it
+ newX = snap ? this.currentPage.pageX : this.x,
+ newY = snap ? this.currentPage.pageY : this.y,
+ now = utils.getTime(),
+ prevTime = this.keyTime || 0,
+ acceleration = 0.250,
+ pos;
+
+ if ( this.options.useTransition && this.isInTransition ) {
+ pos = this.getComputedPosition();
+
+ this._translate(Math.round(pos.x), Math.round(pos.y));
+ this.isInTransition = false;
+ }
+
+ this.keyAcceleration = now - prevTime < 200 ? Math.min(this.keyAcceleration + acceleration, 50) : 0;
+
+ switch ( e.keyCode ) {
+ case this.options.keyBindings.pageUp:
+ if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) {
+ newX += snap ? 1 : this.wrapperWidth;
+ } else {
+ newY += snap ? 1 : this.wrapperHeight;
+ }
+ break;
+ case this.options.keyBindings.pageDown:
+ if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) {
+ newX -= snap ? 1 : this.wrapperWidth;
+ } else {
+ newY -= snap ? 1 : this.wrapperHeight;
+ }
+ break;
+ case this.options.keyBindings.end:
+ newX = snap ? this.pages.length-1 : this.maxScrollX;
+ newY = snap ? this.pages[0].length-1 : this.maxScrollY;
+ break;
+ case this.options.keyBindings.home:
+ newX = 0;
+ newY = 0;
+ break;
+ case this.options.keyBindings.left:
+ newX += snap ? -1 : 5 + this.keyAcceleration>>0;
+ break;
+ case this.options.keyBindings.up:
+ newY += snap ? 1 : 5 + this.keyAcceleration>>0;
+ break;
+ case this.options.keyBindings.right:
+ newX -= snap ? -1 : 5 + this.keyAcceleration>>0;
+ break;
+ case this.options.keyBindings.down:
+ newY -= snap ? 1 : 5 + this.keyAcceleration>>0;
+ break;
+ default:
+ return;
+ }
+
+ if ( snap ) {
+ this.goToPage(newX, newY);
+ return;
+ }
+
+ if ( newX > 0 ) {
+ newX = 0;
+ this.keyAcceleration = 0;
+ } else if ( newX < this.maxScrollX ) {
+ newX = this.maxScrollX;
+ this.keyAcceleration = 0;
+ }
+
+ if ( newY > 0 ) {
+ newY = 0;
+ this.keyAcceleration = 0;
+ } else if ( newY < this.maxScrollY ) {
+ newY = this.maxScrollY;
+ this.keyAcceleration = 0;
+ }
+
+ this.scrollTo(newX, newY, 0);
+
+ this.keyTime = now;
+ },
+
+ _animate: function (destX, destY, duration, easingFn) {
+ var that = this,
+ startX = this.x,
+ startY = this.y,
+ startTime = utils.getTime(),
+ destTime = startTime + duration;
+
+ function step () {
+ var now = utils.getTime(),
+ newX, newY,
+ easing;
+
+ if ( now >= destTime ) {
+ that.isAnimating = false;
+ that._translate(destX, destY);
+
+ if ( !that.resetPosition(that.options.bounceTime) ) {
+ that._execEvent('scrollEnd');
+ }
+
+ return;
+ }
+
+ now = ( now - startTime ) / duration;
+ easing = easingFn(now);
+ newX = ( destX - startX ) * easing + startX;
+ newY = ( destY - startY ) * easing + startY;
+ that._translate(newX, newY);
+
+ if ( that.isAnimating ) {
+ rAF(step);
+ }
+ }
+
+ this.isAnimating = true;
+ step();
+ },
+ handleEvent: function (e) {
+ switch ( e.type ) {
+ case 'touchstart':
+ case 'pointerdown':
+ case 'MSPointerDown':
+ case 'mousedown':
+ this._start(e);
+ break;
+ case 'touchmove':
+ case 'pointermove':
+ case 'MSPointerMove':
+ case 'mousemove':
+ this._move(e);
+ break;
+ case 'touchend':
+ case 'pointerup':
+ case 'MSPointerUp':
+ case 'mouseup':
+ case 'touchcancel':
+ case 'pointercancel':
+ case 'MSPointerCancel':
+ case 'mousecancel':
+ this._end(e);
+ break;
+ case 'orientationchange':
+ case 'resize':
+ this._resize();
+ break;
+ case 'transitionend':
+ case 'webkitTransitionEnd':
+ case 'oTransitionEnd':
+ case 'MSTransitionEnd':
+ this._transitionEnd(e);
+ break;
+ case 'wheel':
+ case 'DOMMouseScroll':
+ case 'mousewheel':
+ this._wheel(e);
+ break;
+ case 'keydown':
+ this._key(e);
+ break;
+ case 'click':
+ if ( !e._constructed ) {
+ e.preventDefault();
+ e.stopPropagation();
+ }
+ break;
+ }
+ }
+};
+function createDefaultScrollbar (direction, interactive, type) {
+ var scrollbar = document.createElement('div'),
+ indicator = document.createElement('div');
+
+ if ( type === true ) {
+ scrollbar.style.cssText = 'position:absolute;z-index:9999';
+ indicator.style.cssText = '-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;position:absolute;background:rgba(0,0,0,0.5);border:1px solid rgba(255,255,255,0.9);border-radius:3px';
+ }
+
+ indicator.className = 'iScrollIndicator';
+
+ if ( direction == 'h' ) {
+ if ( type === true ) {
+ scrollbar.style.cssText += ';height:7px;left:2px;right:2px;bottom:0';
+ indicator.style.height = '100%';
+ }
+ scrollbar.className = 'iScrollHorizontalScrollbar';
+ } else {
+ if ( type === true ) {
+ scrollbar.style.cssText += ';width:7px;bottom:2px;top:2px;right:1px';
+ indicator.style.width = '100%';
+ }
+ scrollbar.className = 'iScrollVerticalScrollbar';
+ }
+
+ scrollbar.style.cssText += ';overflow:hidden';
+
+ if ( !interactive ) {
+ scrollbar.style.pointerEvents = 'none';
+ }
+
+ scrollbar.appendChild(indicator);
+
+ return scrollbar;
+}
+
+function Indicator (scroller, options) {
+ this.wrapper = typeof options.el == 'string' ? document.querySelector(options.el) : options.el;
+ this.wrapperStyle = this.wrapper.style;
+ this.indicator = this.wrapper.children[0];
+ this.indicatorStyle = this.indicator.style;
+ this.scroller = scroller;
+
+ this.options = {
+ listenX: true,
+ listenY: true,
+ interactive: false,
+ resize: true,
+ defaultScrollbars: false,
+ shrink: false,
+ fade: false,
+ speedRatioX: 0,
+ speedRatioY: 0
+ };
+
+ for ( var i in options ) {
+ this.options[i] = options[i];
+ }
+
+ this.sizeRatioX = 1;
+ this.sizeRatioY = 1;
+ this.maxPosX = 0;
+ this.maxPosY = 0;
+
+ if ( this.options.interactive ) {
+ if ( !this.options.disableTouch ) {
+ utils.addEvent(this.indicator, 'touchstart', this);
+ utils.addEvent(window, 'touchend', this);
+ }
+ if ( !this.options.disablePointer ) {
+ utils.addEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this);
+ utils.addEvent(window, utils.prefixPointerEvent('pointerup'), this);
+ }
+ if ( !this.options.disableMouse ) {
+ utils.addEvent(this.indicator, 'mousedown', this);
+ utils.addEvent(window, 'mouseup', this);
+ }
+ }
+
+ if ( this.options.fade ) {
+ this.wrapperStyle[utils.style.transform] = this.scroller.translateZ;
+ this.wrapperStyle[utils.style.transitionDuration] = utils.isBadAndroid ? '0.001s' : '0ms';
+ this.wrapperStyle.opacity = '0';
+ }
+}
+
+Indicator.prototype = {
+ handleEvent: function (e) {
+ switch ( e.type ) {
+ case 'touchstart':
+ case 'pointerdown':
+ case 'MSPointerDown':
+ case 'mousedown':
+ this._start(e);
+ break;
+ case 'touchmove':
+ case 'pointermove':
+ case 'MSPointerMove':
+ case 'mousemove':
+ this._move(e);
+ break;
+ case 'touchend':
+ case 'pointerup':
+ case 'MSPointerUp':
+ case 'mouseup':
+ case 'touchcancel':
+ case 'pointercancel':
+ case 'MSPointerCancel':
+ case 'mousecancel':
+ this._end(e);
+ break;
+ }
+ },
+
+ destroy: function () {
+ if ( this.options.interactive ) {
+ utils.removeEvent(this.indicator, 'touchstart', this);
+ utils.removeEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this);
+ utils.removeEvent(this.indicator, 'mousedown', this);
+
+ utils.removeEvent(window, 'touchmove', this);
+ utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this);
+ utils.removeEvent(window, 'mousemove', this);
+
+ utils.removeEvent(window, 'touchend', this);
+ utils.removeEvent(window, utils.prefixPointerEvent('pointerup'), this);
+ utils.removeEvent(window, 'mouseup', this);
+ }
+
+ if ( this.options.defaultScrollbars ) {
+ this.wrapper.parentNode.removeChild(this.wrapper);
+ }
+ },
+
+ _start: function (e) {
+ var point = e.touches ? e.touches[0] : e;
+
+ e.preventDefault();
+ e.stopPropagation();
+
+ this.transitionTime();
+
+ this.initiated = true;
+ this.moved = false;
+ this.lastPointX = point.pageX;
+ this.lastPointY = point.pageY;
+
+ this.startTime = utils.getTime();
+
+ if ( !this.options.disableTouch ) {
+ utils.addEvent(window, 'touchmove', this);
+ }
+ if ( !this.options.disablePointer ) {
+ utils.addEvent(window, utils.prefixPointerEvent('pointermove'), this);
+ }
+ if ( !this.options.disableMouse ) {
+ utils.addEvent(window, 'mousemove', this);
+ }
+
+ this.scroller._execEvent('beforeScrollStart');
+ },
+
+ _move: function (e) {
+ var point = e.touches ? e.touches[0] : e,
+ deltaX, deltaY,
+ newX, newY,
+ timestamp = utils.getTime();
+
+ if ( !this.moved ) {
+ this.scroller._execEvent('scrollStart');
+ }
+
+ this.moved = true;
+
+ deltaX = point.pageX - this.lastPointX;
+ this.lastPointX = point.pageX;
+
+ deltaY = point.pageY - this.lastPointY;
+ this.lastPointY = point.pageY;
+
+ newX = this.x + deltaX;
+ newY = this.y + deltaY;
+
+ this._pos(newX, newY);
+
+// INSERT POINT: indicator._move
+
+ e.preventDefault();
+ e.stopPropagation();
+ },
+
+ _end: function (e) {
+ if ( !this.initiated ) {
+ return;
+ }
+
+ this.initiated = false;
+
+ e.preventDefault();
+ e.stopPropagation();
+
+ utils.removeEvent(window, 'touchmove', this);
+ utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this);
+ utils.removeEvent(window, 'mousemove', this);
+
+ if ( this.scroller.options.snap ) {
+ var snap = this.scroller._nearestSnap(this.scroller.x, this.scroller.y);
+
+ var time = this.options.snapSpeed || Math.max(
+ Math.max(
+ Math.min(Math.abs(this.scroller.x - snap.x), 1000),
+ Math.min(Math.abs(this.scroller.y - snap.y), 1000)
+ ), 300);
+
+ if ( this.scroller.x != snap.x || this.scroller.y != snap.y ) {
+ this.scroller.directionX = 0;
+ this.scroller.directionY = 0;
+ this.scroller.currentPage = snap;
+ this.scroller.scrollTo(snap.x, snap.y, time, this.scroller.options.bounceEasing);
+ }
+ }
+
+ if ( this.moved ) {
+ this.scroller._execEvent('scrollEnd');
+ }
+ },
+
+ transitionTime: function (time) {
+ time = time || 0;
+ this.indicatorStyle[utils.style.transitionDuration] = time + 'ms';
+
+ if ( !time && utils.isBadAndroid ) {
+ this.indicatorStyle[utils.style.transitionDuration] = '0.001s';
+ }
+ },
+
+ transitionTimingFunction: function (easing) {
+ this.indicatorStyle[utils.style.transitionTimingFunction] = easing;
+ },
+
+ refresh: function () {
+ this.transitionTime();
+
+ if ( this.options.listenX && !this.options.listenY ) {
+ this.indicatorStyle.display = this.scroller.hasHorizontalScroll ? 'block' : 'none';
+ } else if ( this.options.listenY && !this.options.listenX ) {
+ this.indicatorStyle.display = this.scroller.hasVerticalScroll ? 'block' : 'none';
+ } else {
+ this.indicatorStyle.display = this.scroller.hasHorizontalScroll || this.scroller.hasVerticalScroll ? 'block' : 'none';
+ }
+
+ if ( this.scroller.hasHorizontalScroll && this.scroller.hasVerticalScroll ) {
+ utils.addClass(this.wrapper, 'iScrollBothScrollbars');
+ utils.removeClass(this.wrapper, 'iScrollLoneScrollbar');
+
+ if ( this.options.defaultScrollbars && this.options.customStyle ) {
+ if ( this.options.listenX ) {
+ this.wrapper.style.right = '8px';
+ } else {
+ this.wrapper.style.bottom = '8px';
+ }
+ }
+ } else {
+ utils.removeClass(this.wrapper, 'iScrollBothScrollbars');
+ utils.addClass(this.wrapper, 'iScrollLoneScrollbar');
+
+ if ( this.options.defaultScrollbars && this.options.customStyle ) {
+ if ( this.options.listenX ) {
+ this.wrapper.style.right = '2px';
+ } else {
+ this.wrapper.style.bottom = '2px';
+ }
+ }
+ }
+
+ var r = this.wrapper.offsetHeight; // force refresh
+
+ if ( this.options.listenX ) {
+ this.wrapperWidth = this.wrapper.clientWidth;
+ if ( this.options.resize ) {
+ this.indicatorWidth = Math.max(Math.round(this.wrapperWidth * this.wrapperWidth / (this.scroller.scrollerWidth || this.wrapperWidth || 1)), 8);
+ this.indicatorStyle.width = this.indicatorWidth + 'px';
+ } else {
+ this.indicatorWidth = this.indicator.clientWidth;
+ }
+
+ this.maxPosX = this.wrapperWidth - this.indicatorWidth;
+
+ if ( this.options.shrink == 'clip' ) {
+ this.minBoundaryX = -this.indicatorWidth + 8;
+ this.maxBoundaryX = this.wrapperWidth - 8;
+ } else {
+ this.minBoundaryX = 0;
+ this.maxBoundaryX = this.maxPosX;
+ }
+
+ this.sizeRatioX = this.options.speedRatioX || (this.scroller.maxScrollX && (this.maxPosX / this.scroller.maxScrollX));
+ }
+
+ if ( this.options.listenY ) {
+ this.wrapperHeight = this.wrapper.clientHeight;
+ if ( this.options.resize ) {
+ this.indicatorHeight = Math.max(Math.round(this.wrapperHeight * this.wrapperHeight / (this.scroller.scrollerHeight || this.wrapperHeight || 1)), 8);
+ this.indicatorStyle.height = this.indicatorHeight + 'px';
+ } else {
+ this.indicatorHeight = this.indicator.clientHeight;
+ }
+
+ this.maxPosY = this.wrapperHeight - this.indicatorHeight;
+
+ if ( this.options.shrink == 'clip' ) {
+ this.minBoundaryY = -this.indicatorHeight + 8;
+ this.maxBoundaryY = this.wrapperHeight - 8;
+ } else {
+ this.minBoundaryY = 0;
+ this.maxBoundaryY = this.maxPosY;
+ }
+
+ this.maxPosY = this.wrapperHeight - this.indicatorHeight;
+ this.sizeRatioY = this.options.speedRatioY || (this.scroller.maxScrollY && (this.maxPosY / this.scroller.maxScrollY));
+ }
+
+ this.updatePosition();
+ },
+
+ updatePosition: function () {
+ var x = this.options.listenX && Math.round(this.sizeRatioX * this.scroller.x) || 0,
+ y = this.options.listenY && Math.round(this.sizeRatioY * this.scroller.y) || 0;
+
+ if ( !this.options.ignoreBoundaries ) {
+ if ( x < this.minBoundaryX ) {
+ if ( this.options.shrink == 'scale' ) {
+ this.width = Math.max(this.indicatorWidth + x, 8);
+ this.indicatorStyle.width = this.width + 'px';
+ }
+ x = this.minBoundaryX;
+ } else if ( x > this.maxBoundaryX ) {
+ if ( this.options.shrink == 'scale' ) {
+ this.width = Math.max(this.indicatorWidth - (x - this.maxPosX), 8);
+ this.indicatorStyle.width = this.width + 'px';
+ x = this.maxPosX + this.indicatorWidth - this.width;
+ } else {
+ x = this.maxBoundaryX;
+ }
+ } else if ( this.options.shrink == 'scale' && this.width != this.indicatorWidth ) {
+ this.width = this.indicatorWidth;
+ this.indicatorStyle.width = this.width + 'px';
+ }
+
+ if ( y < this.minBoundaryY ) {
+ if ( this.options.shrink == 'scale' ) {
+ this.height = Math.max(this.indicatorHeight + y * 3, 8);
+ this.indicatorStyle.height = this.height + 'px';
+ }
+ y = this.minBoundaryY;
+ } else if ( y > this.maxBoundaryY ) {
+ if ( this.options.shrink == 'scale' ) {
+ this.height = Math.max(this.indicatorHeight - (y - this.maxPosY) * 3, 8);
+ this.indicatorStyle.height = this.height + 'px';
+ y = this.maxPosY + this.indicatorHeight - this.height;
+ } else {
+ y = this.maxBoundaryY;
+ }
+ } else if ( this.options.shrink == 'scale' && this.height != this.indicatorHeight ) {
+ this.height = this.indicatorHeight;
+ this.indicatorStyle.height = this.height + 'px';
+ }
+ }
+
+ this.x = x;
+ this.y = y;
+
+ if ( this.scroller.options.useTransform ) {
+ this.indicatorStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.scroller.translateZ;
+ } else {
+ this.indicatorStyle.left = x + 'px';
+ this.indicatorStyle.top = y + 'px';
+ }
+ },
+
+ _pos: function (x, y) {
+ if ( x < 0 ) {
+ x = 0;
+ } else if ( x > this.maxPosX ) {
+ x = this.maxPosX;
+ }
+
+ if ( y < 0 ) {
+ y = 0;
+ } else if ( y > this.maxPosY ) {
+ y = this.maxPosY;
+ }
+
+ x = this.options.listenX ? Math.round(x / this.sizeRatioX) : this.scroller.x;
+ y = this.options.listenY ? Math.round(y / this.sizeRatioY) : this.scroller.y;
+
+ this.scroller.scrollTo(x, y);
+ },
+
+ fade: function (val, hold) {
+ if ( hold && !this.visible ) {
+ return;
+ }
+
+ clearTimeout(this.fadeTimeout);
+ this.fadeTimeout = null;
+
+ var time = val ? 250 : 500,
+ delay = val ? 0 : 300;
+
+ val = val ? '1' : '0';
+
+ this.wrapperStyle[utils.style.transitionDuration] = time + 'ms';
+
+ this.fadeTimeout = setTimeout((function (val) {
+ this.wrapperStyle.opacity = val;
+ this.visible = +val;
+ }).bind(this, val), delay);
+ }
+};
+
+IScroll.utils = utils;
+
+if ( typeof module != 'undefined' && module.exports ) {
+ module.exports = IScroll;
+} else {
+ window.IScroll = IScroll;
+}
+
+})(window, document, Math); \ No newline at end of file
diff --git a/studio-susie/public/assets/js/vendor/jquery.fullpage.js b/studio-susie/public/assets/js/vendor/jquery.fullpage.js
new file mode 100644
index 0000000..74b5640
--- /dev/null
+++ b/studio-susie/public/assets/js/vendor/jquery.fullpage.js
@@ -0,0 +1,3079 @@
+/*!
+ * fullPage 2.9.2
+ * https://github.com/alvarotrigo/fullPage.js
+ * @license MIT licensed
+ *
+ * Copyright (C) 2015 alvarotrigo.com - A project by Alvaro Trigo
+ */
+(function(global, factory) {
+ 'use strict';
+ if (typeof define === 'function' && define.amd) {
+ define(['jquery'], function($) {
+ return factory($, global, global.document, global.Math);
+ });
+ } else if (typeof exports === "object" && exports) {
+ module.exports = factory(require('jquery'), global, global.document, global.Math);
+ } else {
+ factory(jQuery, global, global.document, global.Math);
+ }
+})(typeof window !== 'undefined' ? window : this, function($, window, document, Math, undefined) {
+ 'use strict';
+
+ // keeping central set of classnames and selectors
+ var WRAPPER = 'fullpage-wrapper';
+ var WRAPPER_SEL = '.' + WRAPPER;
+
+ // slimscroll
+ var SCROLLABLE = 'fp-scrollable';
+ var SCROLLABLE_SEL = '.' + SCROLLABLE;
+
+ // util
+ var RESPONSIVE = 'fp-responsive';
+ var NO_TRANSITION = 'fp-notransition';
+ var DESTROYED = 'fp-destroyed';
+ var ENABLED = 'fp-enabled';
+ var VIEWING_PREFIX = 'fp-viewing';
+ var ACTIVE = 'active';
+ var ACTIVE_SEL = '.' + ACTIVE;
+ var COMPLETELY = 'fp-completely';
+ var COMPLETELY_SEL = '.' + COMPLETELY;
+
+ // section
+ var SECTION_DEFAULT_SEL = '.section';
+ var SECTION = 'fp-section';
+ var SECTION_SEL = '.' + SECTION;
+ var SECTION_ACTIVE_SEL = SECTION_SEL + ACTIVE_SEL;
+ var SECTION_FIRST_SEL = SECTION_SEL + ':first';
+ var SECTION_LAST_SEL = SECTION_SEL + ':last';
+ var TABLE_CELL = 'fp-tableCell';
+ var TABLE_CELL_SEL = '.' + TABLE_CELL;
+ var AUTO_HEIGHT = 'fp-auto-height';
+ var AUTO_HEIGHT_SEL = '.fp-auto-height';
+ var NORMAL_SCROLL = 'fp-normal-scroll';
+ var NORMAL_SCROLL_SEL = '.fp-normal-scroll';
+
+ // section nav
+ var SECTION_NAV = 'fp-nav';
+ var SECTION_NAV_SEL = '#' + SECTION_NAV;
+ var SECTION_NAV_TOOLTIP = 'fp-tooltip';
+ var SECTION_NAV_TOOLTIP_SEL='.'+SECTION_NAV_TOOLTIP;
+ var SHOW_ACTIVE_TOOLTIP = 'fp-show-active';
+
+ // slide
+ var SLIDE_DEFAULT_SEL = '.slide';
+ var SLIDE = 'fp-slide';
+ var SLIDE_SEL = '.' + SLIDE;
+ var SLIDE_ACTIVE_SEL = SLIDE_SEL + ACTIVE_SEL;
+ var SLIDES_WRAPPER = 'fp-slides';
+ var SLIDES_WRAPPER_SEL = '.' + SLIDES_WRAPPER;
+ var SLIDES_CONTAINER = 'fp-slidesContainer';
+ var SLIDES_CONTAINER_SEL = '.' + SLIDES_CONTAINER;
+ var TABLE = 'fp-table';
+
+ // slide nav
+ var SLIDES_NAV = 'fp-slidesNav';
+ var SLIDES_NAV_SEL = '.' + SLIDES_NAV;
+ var SLIDES_NAV_LINK_SEL = SLIDES_NAV_SEL + ' a';
+ var SLIDES_ARROW = 'fp-controlArrow';
+ var SLIDES_ARROW_SEL = '.' + SLIDES_ARROW;
+ var SLIDES_PREV = 'fp-prev';
+ var SLIDES_PREV_SEL = '.' + SLIDES_PREV;
+ var SLIDES_ARROW_PREV = SLIDES_ARROW + ' ' + SLIDES_PREV;
+ var SLIDES_ARROW_PREV_SEL = SLIDES_ARROW_SEL + SLIDES_PREV_SEL;
+ var SLIDES_NEXT = 'fp-next';
+ var SLIDES_NEXT_SEL = '.' + SLIDES_NEXT;
+ var SLIDES_ARROW_NEXT = SLIDES_ARROW + ' ' + SLIDES_NEXT;
+ var SLIDES_ARROW_NEXT_SEL = SLIDES_ARROW_SEL + SLIDES_NEXT_SEL;
+
+ var $window = $(window);
+ var $document = $(document);
+
+ // Default options for iScroll.js used when using scrollOverflow
+ var iscrollOptions = {
+ scrollbars: true,
+ mouseWheel: true,
+ hideScrollbars: false,
+ fadeScrollbars: false,
+ disableMouse: true,
+ interactiveScrollbars: true
+ };
+
+ $.fn.fullpage = function(options) {
+ //only once my friend!
+ if($('html').hasClass(ENABLED)){ displayWarnings(); return; }
+
+ // common jQuery objects
+ var $htmlBody = $('html, body');
+ var $body = $('body');
+
+ var FP = $.fn.fullpage;
+
+ // Create some defaults, extending them with any options that were provided
+ options = $.extend({
+ //navigation
+ menu: false,
+ anchors:[],
+ lockAnchors: false,
+ navigation: false,
+ navigationPosition: 'right',
+ navigationTooltips: [],
+ showActiveTooltip: false,
+ slidesNavigation: false,
+ slidesNavPosition: 'bottom',
+ scrollBar: false,
+ hybrid: false,
+
+ //scrolling
+ css3: true,
+ scrollingSpeed: 700,
+ autoScrolling: true,
+ fitToSection: true,
+ fitToSectionDelay: 1000,
+ easing: 'easeInOutCubic',
+ easingcss3: 'ease',
+ loopBottom: false,
+ loopTop: false,
+ loopHorizontal: true,
+ continuousVertical: false,
+ continuousHorizontal: false,
+ scrollHorizontally: false,
+ interlockedSlides: false,
+ dragAndMove: false,
+ offsetSections: false,
+ resetSliders: false,
+ fadingEffect: false,
+ normalScrollElements: null,
+ scrollOverflow: false,
+ scrollOverflowReset: false,
+ scrollOverflowHandler: iscrollHandler,
+ scrollOverflowOptions: null,
+ touchSensitivity: 5,
+ normalScrollElementTouchThreshold: 5,
+ bigSectionsDestination: null,
+
+ //Accessibility
+ keyboardScrolling: true,
+ animateAnchor: true,
+ recordHistory: true,
+
+ //design
+ controlArrows: true,
+ controlArrowColor: '#fff',
+ verticalCentered: true,
+ sectionsColor : [],
+ paddingTop: 0,
+ paddingBottom: 0,
+ fixedElements: null,
+ responsive: 0, //backwards compabitility with responsiveWiddth
+ responsiveWidth: 0,
+ responsiveHeight: 0,
+ responsiveSlides: false,
+
+ //Custom selectors
+ sectionSelector: SECTION_DEFAULT_SEL,
+ slideSelector: SLIDE_DEFAULT_SEL,
+
+ //events
+ afterLoad: null,
+ onLeave: null,
+ afterRender: null,
+ afterResize: null,
+ afterReBuild: null,
+ afterSlideLoad: null,
+ onSlideLeave: null,
+ afterResponsive: null,
+
+ lazyLoading: true
+ }, options);
+
+ //flag to avoid very fast sliding for landscape sliders
+ var slideMoving = false;
+
+ var isTouchDevice = navigator.userAgent.match(/(iPhone|iPod|iPad|Android|playbook|silk|BlackBerry|BB10|Windows Phone|Tizen|Bada|webOS|IEMobile|Opera Mini)/);
+ var isTouch = (('ontouchstart' in window) || (navigator.msMaxTouchPoints > 0) || (navigator.maxTouchPoints));
+ var container = $(this);
+ var windowsHeight = $window.height();
+ var isResizing = false;
+ var isWindowFocused = true;
+ var lastScrolledDestiny;
+ var lastScrolledSlide;
+ var canScroll = true;
+ var scrollings = [];
+ var controlPressed;
+ var isScrollAllowed = {};
+ isScrollAllowed.m = { 'up':true, 'down':true, 'left':true, 'right':true };
+ isScrollAllowed.k = $.extend(true,{}, isScrollAllowed.m);
+
+ //timeouts
+ var resizeId;
+ var afterSectionLoadsId;
+ var afterSlideLoadsId;
+ var scrollId;
+ var scrollId2;
+ var keydownId;
+ var originals = $.extend(true, {}, options); //deep copy
+
+ displayWarnings();
+
+ //fixing bug in iScroll with links: https://github.com/cubiq/iscroll/issues/783
+ iscrollOptions.click = isTouch; // see #2035
+
+ //extending iScroll options with the user custom ones
+ iscrollOptions = $.extend(iscrollOptions, options.scrollOverflowOptions);
+
+ //easeInOutCubic animation included in the plugin
+ $.extend($.easing,{ easeInOutCubic: function (x, t, b, c, d) {if ((t/=d/2) < 1) return c/2*t*t*t + b;return c/2*((t-=2)*t*t + 2) + b;}});
+
+ /**
+ * Sets the autoScroll option.
+ * It changes the scroll bar visibility and the history of the site as a result.
+ */
+ function setAutoScrolling(value, type){
+ //removing the transformation
+ if(!value){
+ silentScroll(0);
+ }
+
+ setVariableState('autoScrolling', value, type);
+
+ var element = $(SECTION_ACTIVE_SEL);
+
+ if(options.autoScrolling && !options.scrollBar){
+ $htmlBody.css({
+ 'overflow' : 'hidden',
+ 'height' : '100%'
+ });
+
+ setRecordHistory(originals.recordHistory, 'internal');
+
+ //for IE touch devices
+ container.css({
+ '-ms-touch-action': 'none',
+ 'touch-action': 'none'
+ });
+
+ if(element.length){
+ //moving the container up
+ silentScroll(element.position().top);
+ }
+
+ }else{
+ $htmlBody.css({
+ 'overflow' : 'visible',
+ 'height' : 'initial'
+ });
+
+ setRecordHistory(false, 'internal');
+
+ //for IE touch devices
+ container.css({
+ '-ms-touch-action': '',
+ 'touch-action': ''
+ });
+
+ //scrolling the page to the section with no animation
+ if (element.length) {
+ $htmlBody.scrollTop(element.position().top);
+ }
+ }
+ }
+
+ /**
+ * Defines wheter to record the history for each hash change in the URL.
+ */
+ function setRecordHistory(value, type){
+ setVariableState('recordHistory', value, type);
+ }
+
+ /**
+ * Defines the scrolling speed
+ */
+ function setScrollingSpeed(value, type){
+ setVariableState('scrollingSpeed', value, type);
+ }
+
+ /**
+ * Sets fitToSection
+ */
+ function setFitToSection(value, type){
+ setVariableState('fitToSection', value, type);
+ }
+
+ /**
+ * Sets lockAnchors
+ */
+ function setLockAnchors(value){
+ options.lockAnchors = value;
+ }
+
+ /**
+ * Adds or remove the possiblity of scrolling through sections by using the mouse wheel or the trackpad.
+ */
+ function setMouseWheelScrolling(value){
+ if(value){
+ addMouseWheelHandler();
+ addMiddleWheelHandler();
+ }else{
+ removeMouseWheelHandler();
+ removeMiddleWheelHandler();
+ }
+ }
+
+ /**
+ * Adds or remove the possibility of scrolling through sections by using the mouse wheel/trackpad or touch gestures.
+ * Optionally a second parameter can be used to specify the direction for which the action will be applied.
+ *
+ * @param directions string containing the direction or directions separated by comma.
+ */
+ function setAllowScrolling(value, directions){
+ if(typeof directions !== 'undefined'){
+ directions = directions.replace(/ /g,'').split(',');
+
+ $.each(directions, function (index, direction){
+ setIsScrollAllowed(value, direction, 'm');
+ });
+ }
+ else if(value){
+ setMouseWheelScrolling(true);
+ addTouchHandler();
+ }else{
+ setMouseWheelScrolling(false);
+ removeTouchHandler();
+ }
+ }
+
+ /**
+ * Adds or remove the possibility of scrolling through sections by using the keyboard arrow keys
+ */
+ function setKeyboardScrolling(value, directions){
+ if(typeof directions !== 'undefined'){
+ directions = directions.replace(/ /g,'').split(',');
+
+ $.each(directions, function (index, direction){
+ setIsScrollAllowed(value, direction, 'k');
+ });
+ }else{
+ options.keyboardScrolling = value;
+ }
+ }
+
+ /**
+ * Moves the page up one section.
+ */
+ function moveSectionUp(){
+ var prev = $(SECTION_ACTIVE_SEL).prev(SECTION_SEL);
+
+ //looping to the bottom if there's no more sections above
+ if (!prev.length && (options.loopTop || options.continuousVertical)) {
+ prev = $(SECTION_SEL).last();
+ }
+
+ if (prev.length) {
+ scrollPage(prev, null, true);
+ }
+ }
+
+ /**
+ * Moves the page down one section.
+ */
+ function moveSectionDown(){
+ var next = $(SECTION_ACTIVE_SEL).next(SECTION_SEL);
+
+ //looping to the top if there's no more sections below
+ if(!next.length &&
+ (options.loopBottom || options.continuousVertical)){
+ next = $(SECTION_SEL).first();
+ }
+
+ if(next.length){
+ scrollPage(next, null, false);
+ }
+ }
+
+ /**
+ * Moves the page to the given section and slide with no animation.
+ * Anchors or index positions can be used as params.
+ */
+ function silentMoveTo(sectionAnchor, slideAnchor){
+ setScrollingSpeed (0, 'internal');
+ moveTo(sectionAnchor, slideAnchor);
+ setScrollingSpeed (originals.scrollingSpeed, 'internal');
+ }
+
+ /**
+ * Moves the page to the given section and slide.
+ * Anchors or index positions can be used as params.
+ */
+ function moveTo(sectionAnchor, slideAnchor){
+ var destiny = getSectionByAnchor(sectionAnchor);
+
+ if (typeof slideAnchor !== 'undefined'){
+ scrollPageAndSlide(sectionAnchor, slideAnchor);
+ }else if(destiny.length > 0){
+ scrollPage(destiny);
+ }
+ }
+
+ /**
+ * Slides right the slider of the active section.
+ * Optional `section` param.
+ */
+ function moveSlideRight(section){
+ moveSlide('right', section);
+ }
+
+ /**
+ * Slides left the slider of the active section.
+ * Optional `section` param.
+ */
+ function moveSlideLeft(section){
+ moveSlide('left', section);
+ }
+
+ /**
+ * When resizing is finished, we adjust the slides sizes and positions
+ */
+ function reBuild(resizing){
+ if(container.hasClass(DESTROYED)){ return; } //nothing to do if the plugin was destroyed
+
+ isResizing = true;
+
+ windowsHeight = $window.height(); //updating global var
+
+ $(SECTION_SEL).each(function(){
+ var slidesWrap = $(this).find(SLIDES_WRAPPER_SEL);
+ var slides = $(this).find(SLIDE_SEL);
+
+ //adjusting the height of the table-cell for IE and Firefox
+ if(options.verticalCentered){
+ $(this).find(TABLE_CELL_SEL).css('height', getTableHeight($(this)) + 'px');
+ }
+
+ $(this).css('height', windowsHeight + 'px');
+
+ //resizing the scrolling divs
+ if(options.scrollOverflow){
+ if(slides.length){
+ slides.each(function(){
+ createScrollBar($(this));
+ });
+ }else{
+ createScrollBar($(this));
+ }
+ }
+
+ //adjusting the position fo the FULL WIDTH slides...
+ if (slides.length > 1) {
+ landscapeScroll(slidesWrap, slidesWrap.find(SLIDE_ACTIVE_SEL));
+ }
+ });
+
+ var activeSection = $(SECTION_ACTIVE_SEL);
+ var sectionIndex = activeSection.index(SECTION_SEL);
+
+ //isn't it the first section?
+ if(sectionIndex){
+ //adjusting the position for the current section
+ silentMoveTo(sectionIndex + 1);
+ }
+
+ isResizing = false;
+ $.isFunction( options.afterResize ) && resizing && options.afterResize.call(container);
+ $.isFunction( options.afterReBuild ) && !resizing && options.afterReBuild.call(container);
+ }
+
+ /**
+ * Turns fullPage.js to normal scrolling mode when the viewport `width` or `height`
+ * are smaller than the set limit values.
+ */
+ function setResponsive(active){
+ var isResponsive = $body.hasClass(RESPONSIVE);
+
+ if(active){
+ if(!isResponsive){
+ setAutoScrolling(false, 'internal');
+ setFitToSection(false, 'internal');
+ $(SECTION_NAV_SEL).hide();
+ $body.addClass(RESPONSIVE);
+ $.isFunction( options.afterResponsive ) && options.afterResponsive.call( container, active);
+ }
+ }
+ else if(isResponsive){
+ setAutoScrolling(originals.autoScrolling, 'internal');
+ setFitToSection(originals.autoScrolling, 'internal');
+ $(SECTION_NAV_SEL).show();
+ $body.removeClass(RESPONSIVE);
+ $.isFunction( options.afterResponsive ) && options.afterResponsive.call( container, active);
+ }
+ }
+
+ if($(this).length){
+ //public functions
+ FP.setAutoScrolling = setAutoScrolling;
+ FP.setRecordHistory = setRecordHistory;
+ FP.setScrollingSpeed = setScrollingSpeed;
+ FP.setFitToSection = setFitToSection;
+ FP.setLockAnchors = setLockAnchors;
+ FP.setMouseWheelScrolling = setMouseWheelScrolling;
+ FP.setAllowScrolling = setAllowScrolling;
+ FP.setKeyboardScrolling = setKeyboardScrolling;
+ FP.moveSectionUp = moveSectionUp;
+ FP.moveSectionDown = moveSectionDown;
+ FP.silentMoveTo = silentMoveTo;
+ FP.moveTo = moveTo;
+ FP.moveSlideRight = moveSlideRight;
+ FP.moveSlideLeft = moveSlideLeft;
+ FP.reBuild = reBuild;
+ FP.setResponsive = setResponsive;
+ FP.destroy = destroy;
+
+ init();
+
+ bindEvents();
+ }
+
+ function init(){
+ //if css3 is not supported, it will use jQuery animations
+ if(options.css3){
+ options.css3 = support3d();
+ }
+
+ options.scrollBar = options.scrollBar || options.hybrid;
+
+ setOptionsFromDOM();
+
+ prepareDom();
+ setAllowScrolling(true);
+
+ setAutoScrolling(options.autoScrolling, 'internal');
+
+ //the starting point is a slide?
+ var activeSlide = $(SECTION_ACTIVE_SEL).find(SLIDE_ACTIVE_SEL);
+
+ //the active section isn't the first one? Is not the first slide of the first section? Then we load that section/slide by default.
+ if( activeSlide.length && ($(SECTION_ACTIVE_SEL).index(SECTION_SEL) !== 0 || ($(SECTION_ACTIVE_SEL).index(SECTION_SEL) === 0 && activeSlide.index() !== 0))){
+ silentLandscapeScroll(activeSlide);
+ }
+
+ responsive();
+
+ //setting the class for the body element
+ setBodyClass();
+
+ if(document.readyState === 'complete'){
+ scrollToAnchor();
+ }
+ $window.on('load', scrollToAnchor);
+ }
+
+ function bindEvents(){
+ $window
+ //when scrolling...
+ .on('scroll', scrollHandler)
+
+ //detecting any change on the URL to scroll to the given anchor link
+ //(a way to detect back history button as we play with the hashes on the URL)
+ .on('hashchange', hashChangeHandler)
+
+ //when opening a new tab (ctrl + t), `control` won't be pressed when coming back.
+ .blur(blurHandler)
+
+ //when resizing the site, we adjust the heights of the sections, slimScroll...
+ .resize(resizeHandler);
+
+ $document
+ //Sliding with arrow keys, both, vertical and horizontal
+ .keydown(keydownHandler)
+
+ //to prevent scrolling while zooming
+ .keyup(keyUpHandler)
+
+ //Scrolls to the section when clicking the navigation bullet
+ .on('click touchstart', SECTION_NAV_SEL + ' a', sectionBulletHandler)
+
+ //Scrolls the slider to the given slide destination for the given section
+ .on('click touchstart', SLIDES_NAV_LINK_SEL, slideBulletHandler)
+
+ .on('click', SECTION_NAV_TOOLTIP_SEL, tooltipTextHandler);
+
+ //Scrolling horizontally when clicking on the slider controls.
+ $(SECTION_SEL).on('click touchstart', SLIDES_ARROW_SEL, slideArrowHandler);
+
+ /**
+ * Applying normalScroll elements.
+ * Ignoring the scrolls over the specified selectors.
+ */
+ if(options.normalScrollElements){
+ $document.on('mouseenter', options.normalScrollElements, function () {
+ setMouseWheelScrolling(false);
+ });
+
+ $document.on('mouseleave', options.normalScrollElements, function(){
+ setMouseWheelScrolling(true);
+ });
+ }
+ }
+
+ /**
+ * Setting options from DOM elements if they are not provided.
+ */
+ function setOptionsFromDOM(){
+ var sections = container.find(options.sectionSelector);
+
+ //no anchors option? Checking for them in the DOM attributes
+ if(!options.anchors.length){
+ options.anchors = sections.filter('[data-anchor]').map(function(){
+ return $(this).data('anchor').toString();
+ }).get();
+ }
+
+ //no tooltips option? Checking for them in the DOM attributes
+ if(!options.navigationTooltips.length){
+ options.navigationTooltips = sections.filter('[data-tooltip]').map(function(){
+ return $(this).data('tooltip').toString();
+ }).get();
+ }
+ }
+
+ /**
+ * Works over the DOM structure to set it up for the current fullpage options.
+ */
+ function prepareDom(){
+ container.css({
+ 'height': '100%',
+ 'position': 'relative'
+ });
+
+ //adding a class to recognize the container internally in the code
+ container.addClass(WRAPPER);
+ $('html').addClass(ENABLED);
+
+ //due to https://github.com/alvarotrigo/fullPage.js/issues/1502
+ windowsHeight = $window.height();
+
+ container.removeClass(DESTROYED); //in case it was destroyed before initializing it again
+
+ addInternalSelectors();
+
+ //styling the sections / slides / menu
+ $(SECTION_SEL).each(function(index){
+ var section = $(this);
+ var slides = section.find(SLIDE_SEL);
+ var numSlides = slides.length;
+
+ styleSection(section, index);
+ styleMenu(section, index);
+
+ // if there's any slide
+ if (numSlides > 0) {
+ styleSlides(section, slides, numSlides);
+ }else{
+ if(options.verticalCentered){
+ addTableClass(section);
+ }
+ }
+ });
+
+ //fixed elements need to be moved out of the plugin container due to problems with CSS3.
+ if(options.fixedElements && options.css3){
+ $(options.fixedElements).appendTo($body);
+ }
+
+ //vertical centered of the navigation + active bullet
+ if(options.navigation){
+ addVerticalNavigation();
+ }
+
+ enableYoutubeAPI();
+
+ if(options.scrollOverflow){
+ if(document.readyState === 'complete'){
+ createScrollBarHandler();
+ }
+ //after DOM and images are loaded
+ $window.on('load', createScrollBarHandler);
+ }else{
+ afterRenderActions();
+ }
+ }
+
+ /**
+ * Styles the horizontal slides for a section.
+ */
+ function styleSlides(section, slides, numSlides){
+ var sliderWidth = numSlides * 100;
+ var slideWidth = 100 / numSlides;
+
+ slides.wrapAll('<div class="' + SLIDES_CONTAINER + '" />');
+ slides.parent().wrap('<div class="' + SLIDES_WRAPPER + '" />');
+
+ section.find(SLIDES_CONTAINER_SEL).css('width', sliderWidth + '%');
+
+ if(numSlides > 1){
+ if(options.controlArrows){
+ createSlideArrows(section);
+ }
+
+ if(options.slidesNavigation){
+ addSlidesNavigation(section, numSlides);
+ }
+ }
+
+ slides.each(function(index) {
+ $(this).css('width', slideWidth + '%');
+
+ if(options.verticalCentered){
+ addTableClass($(this));
+ }
+ });
+
+ var startingSlide = section.find(SLIDE_ACTIVE_SEL);
+
+ //if the slide won't be an starting point, the default will be the first one
+ //the active section isn't the first one? Is not the first slide of the first section? Then we load that section/slide by default.
+ if( startingSlide.length && ($(SECTION_ACTIVE_SEL).index(SECTION_SEL) !== 0 || ($(SECTION_ACTIVE_SEL).index(SECTION_SEL) === 0 && startingSlide.index() !== 0))){
+ silentLandscapeScroll(startingSlide);
+ }else{
+ slides.eq(0).addClass(ACTIVE);
+ }
+ }
+
+ /**
+ * Styling vertical sections
+ */
+ function styleSection(section, index){
+ //if no active section is defined, the 1st one will be the default one
+ if(!index && $(SECTION_ACTIVE_SEL).length === 0) {
+ section.addClass(ACTIVE);
+ }
+
+ section.css('height', windowsHeight + 'px');
+
+ if(options.paddingTop){
+ section.css('padding-top', options.paddingTop);
+ }
+
+ if(options.paddingBottom){
+ section.css('padding-bottom', options.paddingBottom);
+ }
+
+ if (typeof options.sectionsColor[index] !== 'undefined') {
+ section.css('background-color', options.sectionsColor[index]);
+ }
+
+ if (typeof options.anchors[index] !== 'undefined') {
+ section.attr('data-anchor', options.anchors[index]);
+ }
+ }
+
+ /**
+ * Sets the data-anchor attributes to the menu elements and activates the current one.
+ */
+ function styleMenu(section, index){
+ if (typeof options.anchors[index] !== 'undefined') {
+ //activating the menu / nav element on load
+ if(section.hasClass(ACTIVE)){
+ activateMenuAndNav(options.anchors[index], index);
+ }
+ }
+
+ //moving the menu outside the main container if it is inside (avoid problems with fixed positions when using CSS3 tranforms)
+ if(options.menu && options.css3 && $(options.menu).closest(WRAPPER_SEL).length){
+ $(options.menu).appendTo($body);
+ }
+ }
+
+ /**
+ * Adds internal classes to be able to provide customizable selectors
+ * keeping the link with the style sheet.
+ */
+ function addInternalSelectors(){
+ container.find(options.sectionSelector).addClass(SECTION);
+ container.find(options.slideSelector).addClass(SLIDE);
+ }
+
+ /**
+ * Creates the control arrows for the given section
+ */
+ function createSlideArrows(section){
+ section.find(SLIDES_WRAPPER_SEL).after('<div class="' + SLIDES_ARROW_PREV + '"></div><div class="' + SLIDES_ARROW_NEXT + '"></div>');
+
+ if(options.controlArrowColor!='#fff'){
+ section.find(SLIDES_ARROW_NEXT_SEL).css('border-color', 'transparent transparent transparent '+options.controlArrowColor);
+ section.find(SLIDES_ARROW_PREV_SEL).css('border-color', 'transparent '+ options.controlArrowColor + ' transparent transparent');
+ }
+
+ if(!options.loopHorizontal){
+ section.find(SLIDES_ARROW_PREV_SEL).hide();
+ }
+ }
+
+ /**
+ * Creates a vertical navigation bar.
+ */
+ function addVerticalNavigation(){
+ $body.append('<div id="' + SECTION_NAV + '"><ul></ul></div>');
+ var nav = $(SECTION_NAV_SEL);
+
+ nav.addClass(function() {
+ return options.showActiveTooltip ? SHOW_ACTIVE_TOOLTIP + ' ' + options.navigationPosition : options.navigationPosition;
+ });
+
+ for (var i = 0; i < $(SECTION_SEL).length; i++) {
+ var link = '';
+ if (options.anchors.length) {
+ link = options.anchors[i];
+ }
+
+ var li = '<li><a href="#' + link + '"><span></span></a>';
+
+ // Only add tooltip if needed (defined by user)
+ var tooltip = options.navigationTooltips[i];
+
+ if (typeof tooltip !== 'undefined' && tooltip !== '') {
+ li += '<div class="' + SECTION_NAV_TOOLTIP + ' ' + options.navigationPosition + '">' + tooltip + '</div>';
+ }
+
+ li += '</li>';
+
+ nav.find('ul').append(li);
+ }
+
+ //centering it vertically
+ $(SECTION_NAV_SEL).css('margin-top', '-' + ($(SECTION_NAV_SEL).height()/2) + 'px');
+
+ //activating the current active section
+ $(SECTION_NAV_SEL).find('li').eq($(SECTION_ACTIVE_SEL).index(SECTION_SEL)).find('a').addClass(ACTIVE);
+ }
+
+ /**
+ * Creates the slim scroll scrollbar for the sections and slides inside them.
+ */
+ function createScrollBarHandler(){
+ $(SECTION_SEL).each(function(){
+ var slides = $(this).find(SLIDE_SEL);
+
+ if(slides.length){
+ slides.each(function(){
+ createScrollBar($(this));
+ });
+ }else{
+ createScrollBar($(this));
+ }
+
+ });
+ afterRenderActions();
+ }
+
+ /*
+ * Enables the Youtube videos API so we can control their flow if necessary.
+ */
+ function enableYoutubeAPI(){
+ container.find('iframe[src*="youtube.com/embed/"]').each(function(){
+ addURLParam($(this), 'enablejsapi=1');
+ });
+ }
+
+ /**
+ * Adds a new parameter and its value to the `src` of a given element
+ */
+ function addURLParam(element, newParam){
+ var originalSrc = element.attr('src');
+ element.attr('src', originalSrc + getUrlParamSign(originalSrc) + newParam);
+ }
+
+ /*
+ * Returns the prefix sign to use for a new parameter in an existen URL.
+ *
+ * @return {String} ? | &
+ */
+ function getUrlParamSign(url){
+ return ( !/\?/.test( url ) ) ? '?' : '&';
+ }
+
+ /**
+ * Actions and callbacks to fire afterRender
+ */
+ function afterRenderActions(){
+ var section = $(SECTION_ACTIVE_SEL);
+
+ section.addClass(COMPLETELY);
+
+ if(options.scrollOverflowHandler.afterRender){
+ options.scrollOverflowHandler.afterRender(section);
+ }
+ lazyLoad(section);
+ playMedia(section);
+ options.scrollOverflowHandler.afterLoad();
+
+ $.isFunction( options.afterLoad ) && options.afterLoad.call(section, section.data('anchor'), (section.index(SECTION_SEL) + 1));
+ $.isFunction( options.afterRender ) && options.afterRender.call(container);
+ }
+
+
+ var isScrolling = false;
+ var lastScroll = 0;
+
+ //when scrolling...
+ function scrollHandler(){
+ var currentSection;
+
+ if(!options.autoScrolling || options.scrollBar){
+ var currentScroll = $window.scrollTop();
+ var scrollDirection = getScrollDirection(currentScroll);
+ var visibleSectionIndex = 0;
+ var screen_mid = currentScroll + ($window.height() / 2.0);
+ var isAtBottom = $body.height() - $window.height() === currentScroll;
+ var sections = document.querySelectorAll(SECTION_SEL);
+
+ //when using `auto-height` for a small last section it won't be centered in the viewport
+ if(isAtBottom){
+ visibleSectionIndex = sections.length - 1;
+ }
+ //is at top? when using `auto-height` for a small first section it won't be centered in the viewport
+ else if(!currentScroll){
+ visibleSectionIndex = 0;
+ }
+
+ //taking the section which is showing more content in the viewport
+ else{
+ for (var i = 0; i < sections.length; ++i) {
+ var section = sections[i];
+
+ // Pick the the last section which passes the middle line of the screen.
+ if (section.offsetTop <= screen_mid)
+ {
+ visibleSectionIndex = i;
+ }
+ }
+ }
+
+ if(isCompletelyInViewPort(scrollDirection)){
+ if(!$(SECTION_ACTIVE_SEL).hasClass(COMPLETELY)){
+ $(SECTION_ACTIVE_SEL).addClass(COMPLETELY).siblings().removeClass(COMPLETELY);
+ }
+ }
+
+ //geting the last one, the current one on the screen
+ currentSection = $(sections).eq(visibleSectionIndex);
+
+ //setting the visible section as active when manually scrolling
+ //executing only once the first time we reach the section
+ if(!currentSection.hasClass(ACTIVE)){
+ isScrolling = true;
+ var leavingSection = $(SECTION_ACTIVE_SEL);
+ var leavingSectionIndex = leavingSection.index(SECTION_SEL) + 1;
+ var yMovement = getYmovement(currentSection);
+ var anchorLink = currentSection.data('anchor');
+ var sectionIndex = currentSection.index(SECTION_SEL) + 1;
+ var activeSlide = currentSection.find(SLIDE_ACTIVE_SEL);
+ var slideIndex;
+ var slideAnchorLink;
+
+ if(activeSlide.length){
+ slideAnchorLink = activeSlide.data('anchor');
+ slideIndex = activeSlide.index();
+ }
+
+ if(canScroll){
+ currentSection.addClass(ACTIVE).siblings().removeClass(ACTIVE);
+
+ $.isFunction( options.onLeave ) && options.onLeave.call( leavingSection, leavingSectionIndex, sectionIndex, yMovement);
+ $.isFunction( options.afterLoad ) && options.afterLoad.call( currentSection, anchorLink, sectionIndex);
+
+ stopMedia(leavingSection);
+ lazyLoad(currentSection);
+ playMedia(currentSection);
+
+ activateMenuAndNav(anchorLink, sectionIndex - 1);
+
+ if(options.anchors.length){
+ //needed to enter in hashChange event when using the menu with anchor links
+ lastScrolledDestiny = anchorLink;
+ }
+ setState(slideIndex, slideAnchorLink, anchorLink, sectionIndex);
+ }
+
+ //small timeout in order to avoid entering in hashChange event when scrolling is not finished yet
+ clearTimeout(scrollId);
+ scrollId = setTimeout(function(){
+ isScrolling = false;
+ }, 100);
+ }
+
+ if(options.fitToSection){
+ //for the auto adjust of the viewport to fit a whole section
+ clearTimeout(scrollId2);
+
+ scrollId2 = setTimeout(function(){
+ //checking fitToSection again in case it was set to false before the timeout delay
+ if(canScroll && options.fitToSection){
+ //allows to scroll to an active section and
+ //if the section is already active, we prevent firing callbacks
+ if($(SECTION_ACTIVE_SEL).is(currentSection)){
+ isResizing = true;
+ }
+ scrollPage($(SECTION_ACTIVE_SEL));
+
+ isResizing = false;
+ }
+ }, options.fitToSectionDelay);
+ }
+ }
+ }
+
+ /**
+ * Determines whether the active section has seen in its whole or not.
+ */
+ function isCompletelyInViewPort(movement){
+ var top = $(SECTION_ACTIVE_SEL).position().top;
+ var bottom = top + $window.height();
+
+ if(movement == 'up'){
+ return bottom >= ($window.scrollTop() + $window.height());
+ }
+ return top <= $window.scrollTop();
+ }
+
+ /**
+ * Gets the directon of the the scrolling fired by the scroll event.
+ */
+ function getScrollDirection(currentScroll){
+ var direction = currentScroll > lastScroll ? 'down' : 'up';
+
+ lastScroll = currentScroll;
+
+ //needed for auto-height sections to determine if we want to scroll to the top or bottom of the destination
+ previousDestTop = currentScroll;
+
+ return direction;
+ }
+
+ /**
+ * Determines the way of scrolling up or down:
+ * by 'automatically' scrolling a section or by using the default and normal scrolling.
+ */
+ function scrolling(type, scrollable){
+ if (!isScrollAllowed.m[type]){
+ return;
+ }
+ var check = (type === 'down') ? 'bottom' : 'top';
+ var scrollSection = (type === 'down') ? moveSectionDown : moveSectionUp;
+
+ if(scrollable.length > 0 ){
+ //is the scrollbar at the start/end of the scroll?
+ if(options.scrollOverflowHandler.isScrolled(check, scrollable)){
+ scrollSection();
+ }else{
+ return true;
+ }
+ }else{
+ // moved up/down
+ scrollSection();
+ }
+ }
+
+ /*
+ * Preventing bouncing in iOS #2285
+ */
+ function preventBouncing(event){
+ var e = event.originalEvent;
+ if(!checkParentForNormalScrollElement(event.target) && options.autoScrolling && isReallyTouch(e)){
+ //preventing the easing on iOS devices
+ event.preventDefault();
+ }
+ }
+
+ var touchStartY = 0;
+ var touchStartX = 0;
+ var touchEndY = 0;
+ var touchEndX = 0;
+
+ /* Detecting touch events
+
+ * As we are changing the top property of the page on scrolling, we can not use the traditional way to detect it.
+ * This way, the touchstart and the touch moves shows an small difference between them which is the
+ * used one to determine the direction.
+ */
+ function touchMoveHandler(event){
+ var e = event.originalEvent;
+ var activeSection = $(e.target).closest(SECTION_SEL);
+
+ // additional: if one of the normalScrollElements isn't within options.normalScrollElementTouchThreshold hops up the DOM chain
+ if (!checkParentForNormalScrollElement(event.target) && isReallyTouch(e) ) {
+
+ if(options.autoScrolling){
+ //preventing the easing on iOS devices
+ event.preventDefault();
+ }
+
+ var scrollable = options.scrollOverflowHandler.scrollable(activeSection);
+ var touchEvents = getEventsPage(e);
+
+ touchEndY = touchEvents.y;
+ touchEndX = touchEvents.x;
+
+ //if movement in the X axys is greater than in the Y and the currect section has slides...
+ if (activeSection.find(SLIDES_WRAPPER_SEL).length && Math.abs(touchStartX - touchEndX) > (Math.abs(touchStartY - touchEndY))) {
+
+ //is the movement greater than the minimum resistance to scroll?
+ if (!slideMoving && Math.abs(touchStartX - touchEndX) > ($window.outerWidth() / 100 * options.touchSensitivity)) {
+ if (touchStartX > touchEndX) {
+ if(isScrollAllowed.m.right){
+ moveSlideRight(activeSection); //next
+ }
+ } else {
+ if(isScrollAllowed.m.left){
+ moveSlideLeft(activeSection); //prev
+ }
+ }
+ }
+ }
+
+ //vertical scrolling (only when autoScrolling is enabled)
+ else if(options.autoScrolling && canScroll){
+
+ //is the movement greater than the minimum resistance to scroll?
+ if (Math.abs(touchStartY - touchEndY) > ($window.height() / 100 * options.touchSensitivity)) {
+ if (touchStartY > touchEndY) {
+ scrolling('down', scrollable);
+ } else if (touchEndY > touchStartY) {
+ scrolling('up', scrollable);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * recursive function to loop up the parent nodes to check if one of them exists in options.normalScrollElements
+ * Currently works well for iOS - Android might need some testing
+ * @param {Element} el target element / jquery selector (in subsequent nodes)
+ * @param {int} hop current hop compared to options.normalScrollElementTouchThreshold
+ * @return {boolean} true if there is a match to options.normalScrollElements
+ */
+ function checkParentForNormalScrollElement (el, hop) {
+ hop = hop || 0;
+ var parent = $(el).parent();
+
+ if (hop < options.normalScrollElementTouchThreshold &&
+ parent.is(options.normalScrollElements) ) {
+ return true;
+ } else if (hop == options.normalScrollElementTouchThreshold) {
+ return false;
+ } else {
+ return checkParentForNormalScrollElement(parent, ++hop);
+ }
+ }
+
+ /**
+ * As IE >= 10 fires both touch and mouse events when using a mouse in a touchscreen
+ * this way we make sure that is really a touch event what IE is detecting.
+ */
+ function isReallyTouch(e){
+ //if is not IE || IE is detecting `touch` or `pen`
+ return typeof e.pointerType === 'undefined' || e.pointerType != 'mouse';
+ }
+
+ /**
+ * Handler for the touch start event.
+ */
+ function touchStartHandler(event){
+ var e = event.originalEvent;
+
+ //stopping the auto scroll to adjust to a section
+ if(options.fitToSection){
+ $htmlBody.stop();
+ }
+
+ if(isReallyTouch(e)){
+ var touchEvents = getEventsPage(e);
+ touchStartY = touchEvents.y;
+ touchStartX = touchEvents.x;
+ }
+ }
+
+ /**
+ * Gets the average of the last `number` elements of the given array.
+ */
+ function getAverage(elements, number){
+ var sum = 0;
+
+ //taking `number` elements from the end to make the average, if there are not enought, 1
+ var lastElements = elements.slice(Math.max(elements.length - number, 1));
+
+ for(var i = 0; i < lastElements.length; i++){
+ sum = sum + lastElements[i];
+ }
+
+ return Math.ceil(sum/number);
+ }
+
+ /**
+ * Detecting mousewheel scrolling
+ *
+ * http://blogs.sitepointstatic.com/examples/tech/mouse-wheel/index.html
+ * http://www.sitepoint.com/html5-javascript-mouse-wheel/
+ */
+ var prevTime = new Date().getTime();
+
+ function MouseWheelHandler(e) {
+ var curTime = new Date().getTime();
+ var isNormalScroll = $(COMPLETELY_SEL).hasClass(NORMAL_SCROLL);
+
+ //autoscrolling and not zooming?
+ if(options.autoScrolling && !controlPressed && !isNormalScroll){
+ // cross-browser wheel delta
+ e = e || window.event;
+ var value = e.wheelDelta || -e.deltaY || -e.detail;
+ var delta = Math.max(-1, Math.min(1, value));
+
+ var horizontalDetection = typeof e.wheelDeltaX !== 'undefined' || typeof e.deltaX !== 'undefined';
+ var isScrollingVertically = (Math.abs(e.wheelDeltaX) < Math.abs(e.wheelDelta)) || (Math.abs(e.deltaX ) < Math.abs(e.deltaY) || !horizontalDetection);
+
+ //Limiting the array to 150 (lets not waste memory!)
+ if(scrollings.length > 149){
+ scrollings.shift();
+ }
+
+ //keeping record of the previous scrollings
+ scrollings.push(Math.abs(value));
+
+ //preventing to scroll the site on mouse wheel when scrollbar is present
+ if(options.scrollBar){
+ e.preventDefault ? e.preventDefault() : e.returnValue = false;
+ }
+
+ var activeSection = $(SECTION_ACTIVE_SEL);
+ var scrollable = options.scrollOverflowHandler.scrollable(activeSection);
+
+ //time difference between the last scroll and the current one
+ var timeDiff = curTime-prevTime;
+ prevTime = curTime;
+
+ //haven't they scrolled in a while?
+ //(enough to be consider a different scrolling action to scroll another section)
+ if(timeDiff > 200){
+ //emptying the array, we dont care about old scrollings for our averages
+ scrollings = [];
+ }
+
+ if(canScroll){
+ var averageEnd = getAverage(scrollings, 10);
+ var averageMiddle = getAverage(scrollings, 70);
+ var isAccelerating = averageEnd >= averageMiddle;
+
+ //to avoid double swipes...
+ if(isAccelerating && isScrollingVertically){
+ //scrolling down?
+ if (delta < 0) {
+ scrolling('down', scrollable);
+
+ //scrolling up?
+ }else {
+ scrolling('up', scrollable);
+ }
+ }
+ }
+
+ return false;
+ }
+
+ if(options.fitToSection){
+ //stopping the auto scroll to adjust to a section
+ $htmlBody.stop();
+ }
+ }
+
+ /**
+ * Slides a slider to the given direction.
+ * Optional `section` param.
+ */
+ function moveSlide(direction, section){
+ var activeSection = typeof section === 'undefined' ? $(SECTION_ACTIVE_SEL) : section;
+ var slides = activeSection.find(SLIDES_WRAPPER_SEL);
+ var numSlides = slides.find(SLIDE_SEL).length;
+
+ // more than one slide needed and nothing should be sliding
+ if (!slides.length || slideMoving || numSlides < 2) {
+ return;
+ }
+
+ var currentSlide = slides.find(SLIDE_ACTIVE_SEL);
+ var destiny = null;
+
+ if(direction === 'left'){
+ destiny = currentSlide.prev(SLIDE_SEL);
+ }else{
+ destiny = currentSlide.next(SLIDE_SEL);
+ }
+
+ //isn't there a next slide in the secuence?
+ if(!destiny.length){
+ //respect loopHorizontal settin
+ if (!options.loopHorizontal) return;
+
+ if(direction === 'left'){
+ destiny = currentSlide.siblings(':last');
+ }else{
+ destiny = currentSlide.siblings(':first');
+ }
+ }
+
+ slideMoving = true;
+
+ landscapeScroll(slides, destiny, direction);
+ }
+
+ /**
+ * Maintains the active slides in the viewport
+ * (Because the `scroll` animation might get lost with some actions, such as when using continuousVertical)
+ */
+ function keepSlidesPosition(){
+ $(SLIDE_ACTIVE_SEL).each(function(){
+ silentLandscapeScroll($(this), 'internal');
+ });
+ }
+
+ var previousDestTop = 0;
+ /**
+ * Returns the destination Y position based on the scrolling direction and
+ * the height of the section.
+ */
+ function getDestinationPosition(element){
+ var elemPosition = element.position();
+
+ //top of the desination will be at the top of the viewport
+ var position = elemPosition.top;
+ var isScrollingDown = elemPosition.top > previousDestTop;
+ var sectionBottom = position - windowsHeight + element.outerHeight();
+ var bigSectionsDestination = options.bigSectionsDestination;
+
+ //is the destination element bigger than the viewport?
+ if(element.outerHeight() > windowsHeight){
+ //scrolling up?
+ if(!isScrollingDown && !bigSectionsDestination || bigSectionsDestination === 'bottom' ){
+ position = sectionBottom;
+ }
+ }
+
+ //sections equal or smaller than the viewport height && scrolling down? || is resizing and its in the last section
+ else if(isScrollingDown || (isResizing && element.is(':last-child')) ){
+ //The bottom of the destination will be at the bottom of the viewport
+ position = sectionBottom;
+ }
+
+ /*
+ Keeping record of the last scrolled position to determine the scrolling direction.
+ No conventional methods can be used as the scroll bar might not be present
+ AND the section might not be active if it is auto-height and didnt reach the middle
+ of the viewport.
+ */
+ previousDestTop = position;
+ return position;
+ }
+
+ /**
+ * Scrolls the site to the given element and scrolls to the slide if a callback is given.
+ */
+ function scrollPage(element, callback, isMovementUp){
+ if(typeof element === 'undefined'){ return; } //there's no element to scroll, leaving the function
+
+ var dtop = getDestinationPosition(element);
+ var slideAnchorLink;
+ var slideIndex;
+
+ //local variables
+ var v = {
+ element: element,
+ callback: callback,
+ isMovementUp: isMovementUp,
+ dtop: dtop,
+ yMovement: getYmovement(element),
+ anchorLink: element.data('anchor'),
+ sectionIndex: element.index(SECTION_SEL),
+ activeSlide: element.find(SLIDE_ACTIVE_SEL),
+ activeSection: $(SECTION_ACTIVE_SEL),
+ leavingSection: $(SECTION_ACTIVE_SEL).index(SECTION_SEL) + 1,
+
+ //caching the value of isResizing at the momment the function is called
+ //because it will be checked later inside a setTimeout and the value might change
+ localIsResizing: isResizing
+ };
+
+ //quiting when destination scroll is the same as the current one
+ if((v.activeSection.is(element) && !isResizing) || (options.scrollBar && $window.scrollTop() === v.dtop && !element.hasClass(AUTO_HEIGHT) )){ return; }
+
+ if(v.activeSlide.length){
+ slideAnchorLink = v.activeSlide.data('anchor');
+ slideIndex = v.activeSlide.index();
+ }
+
+ // If continuousVertical && we need to wrap around
+ if (options.autoScrolling && options.continuousVertical && typeof (v.isMovementUp) !== "undefined" &&
+ ((!v.isMovementUp && v.yMovement == 'up') || // Intending to scroll down but about to go up or
+ (v.isMovementUp && v.yMovement == 'down'))) { // intending to scroll up but about to go down
+
+ v = createInfiniteSections(v);
+ }
+
+ //callback (onLeave) if the site is not just resizing and readjusting the slides
+ if($.isFunction(options.onLeave) && !v.localIsResizing){
+ if(options.onLeave.call(v.activeSection, v.leavingSection, (v.sectionIndex + 1), v.yMovement) === false){
+ return;
+ }
+ }
+
+ stopMedia(v.activeSection);
+
+ options.scrollOverflowHandler.beforeLeave();
+ element.addClass(ACTIVE).siblings().removeClass(ACTIVE);
+ lazyLoad(element);
+ options.scrollOverflowHandler.onLeave();
+
+
+ //preventing from activating the MouseWheelHandler event
+ //more than once if the page is scrolling
+ canScroll = false;
+
+ setState(slideIndex, slideAnchorLink, v.anchorLink, v.sectionIndex);
+
+ performMovement(v);
+
+ //flag to avoid callingn `scrollPage()` twice in case of using anchor links
+ lastScrolledDestiny = v.anchorLink;
+
+ //avoid firing it twice (as it does also on scroll)
+ activateMenuAndNav(v.anchorLink, v.sectionIndex);
+ }
+
+ /**
+ * Performs the vertical movement (by CSS3 or by jQuery)
+ */
+ function performMovement(v){
+ // using CSS3 translate functionality
+ if (options.css3 && options.autoScrolling && !options.scrollBar) {
+
+ // The first section can have a negative value in iOS 10. Not quite sure why: -0.0142822265625
+ // that's why we round it to 0.
+ var translate3d = 'translate3d(0px, -' + Math.round(v.dtop) + 'px, 0px)';
+ transformContainer(translate3d, true);
+
+ //even when the scrollingSpeed is 0 there's a little delay, which might cause the
+ //scrollingSpeed to change in case of using silentMoveTo();
+ if(options.scrollingSpeed){
+ clearTimeout(afterSectionLoadsId);
+ afterSectionLoadsId = setTimeout(function () {
+ afterSectionLoads(v);
+ }, options.scrollingSpeed);
+ }else{
+ afterSectionLoads(v);
+ }
+ }
+
+ // using jQuery animate
+ else{
+ var scrollSettings = getScrollSettings(v);
+
+ $(scrollSettings.element).animate(
+ scrollSettings.options,
+ options.scrollingSpeed, options.easing).promise().done(function () { //only one single callback in case of animating `html, body`
+ if(options.scrollBar){
+
+ /* Hack!
+ The timeout prevents setting the most dominant section in the viewport as "active" when the user
+ scrolled to a smaller section by using the mousewheel (auto scrolling) rather than draging the scroll bar.
+
+ When using scrollBar:true It seems like the scroll events still getting propagated even after the scrolling animation has finished.
+ */
+ setTimeout(function(){
+ afterSectionLoads(v);
+ },30);
+ }else{
+ afterSectionLoads(v);
+ }
+ });
+ }
+ }
+
+ /**
+ * Gets the scrolling settings depending on the plugin autoScrolling option
+ */
+ function getScrollSettings(v){
+ var scroll = {};
+
+ if(options.autoScrolling && !options.scrollBar){
+ scroll.options = { 'top': -v.dtop};
+ scroll.element = WRAPPER_SEL;
+ }else{
+ scroll.options = { 'scrollTop': v.dtop};
+ scroll.element = 'html, body';
+ }
+
+ return scroll;
+ }
+
+ /**
+ * Adds sections before or after the current one to create the infinite effect.
+ */
+ function createInfiniteSections(v){
+ // Scrolling down
+ if (!v.isMovementUp) {
+ // Move all previous sections to after the active section
+ $(SECTION_ACTIVE_SEL).after(v.activeSection.prevAll(SECTION_SEL).get().reverse());
+ }
+ else { // Scrolling up
+ // Move all next sections to before the active section
+ $(SECTION_ACTIVE_SEL).before(v.activeSection.nextAll(SECTION_SEL));
+ }
+
+ // Maintain the displayed position (now that we changed the element order)
+ silentScroll($(SECTION_ACTIVE_SEL).position().top);
+
+ // Maintain the active slides visible in the viewport
+ keepSlidesPosition();
+
+ // save for later the elements that still need to be reordered
+ v.wrapAroundElements = v.activeSection;
+
+ // Recalculate animation variables
+ v.dtop = v.element.position().top;
+ v.yMovement = getYmovement(v.element);
+
+ return v;
+ }
+
+ /**
+ * Fix section order after continuousVertical changes have been animated
+ */
+ function continuousVerticalFixSectionOrder (v) {
+ // If continuousVertical is in effect (and autoScrolling would also be in effect then),
+ // finish moving the elements around so the direct navigation will function more simply
+ if (!v.wrapAroundElements || !v.wrapAroundElements.length) {
+ return;
+ }
+
+ if (v.isMovementUp) {
+ $(SECTION_FIRST_SEL).before(v.wrapAroundElements);
+ }
+ else {
+ $(SECTION_LAST_SEL).after(v.wrapAroundElements);
+ }
+
+ silentScroll($(SECTION_ACTIVE_SEL).position().top);
+
+ // Maintain the active slides visible in the viewport
+ keepSlidesPosition();
+ }
+
+
+ /**
+ * Actions to do once the section is loaded.
+ */
+ function afterSectionLoads (v){
+ continuousVerticalFixSectionOrder(v);
+
+ //callback (afterLoad) if the site is not just resizing and readjusting the slides
+ $.isFunction(options.afterLoad) && !v.localIsResizing && options.afterLoad.call(v.element, v.anchorLink, (v.sectionIndex + 1));
+ options.scrollOverflowHandler.afterLoad();
+
+ if(!v.localIsResizing){
+ playMedia(v.element);
+ }
+
+ v.element.addClass(COMPLETELY).siblings().removeClass(COMPLETELY);
+
+ canScroll = true;
+
+ $.isFunction(v.callback) && v.callback.call(this);
+ }
+
+ /**
+ * Lazy loads image, video and audio elements.
+ */
+ function lazyLoad(destiny){
+ if (!options.lazyLoading){
+ return;
+ }
+
+ var panel = getSlideOrSection(destiny);
+ var element;
+
+ panel.find('img[data-src], source[data-src], audio[data-src], iframe[data-src]').each(function(){
+ element = $(this);
+ element.attr('src', element.data('src'));
+ element.removeAttr('data-src');
+
+ if(element.is('source')){
+ element.closest('video').get(0).load();
+ }
+ });
+ }
+
+ /**
+ * Plays video and audio elements.
+ */
+ function playMedia(destiny){
+ var panel = getSlideOrSection(destiny);
+
+ //playing HTML5 media elements
+ panel.find('video, audio').each(function(){
+ var element = $(this).get(0);
+
+ if( element.hasAttribute('data-autoplay') && typeof element.play === 'function' ) {
+ element.play();
+ }
+ });
+
+ //youtube videos
+ panel.find('iframe[src*="youtube.com/embed/"]').each(function(){
+ var element = $(this).get(0);
+
+ if ( element.hasAttribute('data-autoplay') ){
+ playYoutube(element);
+ }
+
+ //in case the URL was not loaded yet. On page load we need time for the new URL (with the API string) to load.
+ element.onload = function() {
+ if ( element.hasAttribute('data-autoplay') ){
+ playYoutube(element);
+ }
+ };
+ });
+ }
+
+ /**
+ * Plays a youtube video
+ */
+ function playYoutube(element){
+ element.contentWindow.postMessage('{"event":"command","func":"playVideo","args":""}', '*');
+ }
+
+ /**
+ * Stops video and audio elements.
+ */
+ function stopMedia(destiny){
+ var panel = getSlideOrSection(destiny);
+
+ //stopping HTML5 media elements
+ panel.find('video, audio').each(function(){
+ var element = $(this).get(0);
+
+ if( !element.hasAttribute('data-keepplaying') && typeof element.pause === 'function' ) {
+ element.pause();
+ }
+ });
+
+ //youtube videos
+ panel.find('iframe[src*="youtube.com/embed/"]').each(function(){
+ var element = $(this).get(0);
+
+ if( /youtube\.com\/embed\//.test($(this).attr('src')) && !element.hasAttribute('data-keepplaying')){
+ $(this).get(0).contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}','*');
+ }
+ });
+ }
+
+ /**
+ * Gets the active slide (or section) for the given section
+ */
+ function getSlideOrSection(destiny){
+ var slide = destiny.find(SLIDE_ACTIVE_SEL);
+ if( slide.length ) {
+ destiny = $(slide);
+ }
+
+ return destiny;
+ }
+
+ /**
+ * Scrolls to the anchor in the URL when loading the site
+ */
+ function scrollToAnchor(){
+ //getting the anchor link in the URL and deleting the `#`
+ var value = window.location.hash.replace('#', '').split('/');
+ var sectionAnchor = decodeURIComponent(value[0]);
+ var slideAnchor = decodeURIComponent(value[1]);
+
+ if(sectionAnchor){ //if theres any #
+ if(options.animateAnchor){
+ scrollPageAndSlide(sectionAnchor, slideAnchor);
+ }else{
+ silentMoveTo(sectionAnchor, slideAnchor);
+ }
+ }
+ }
+
+ /**
+ * Detecting any change on the URL to scroll to the given anchor link
+ * (a way to detect back history button as we play with the hashes on the URL)
+ */
+ function hashChangeHandler(){
+ if(!isScrolling && !options.lockAnchors){
+ var value = window.location.hash.replace('#', '').split('/');
+ var sectionAnchor = decodeURIComponent(value[0]);
+ var slideAnchor = decodeURIComponent(value[1]);
+
+ //when moving to a slide in the first section for the first time (first time to add an anchor to the URL)
+ var isFirstSlideMove = (typeof lastScrolledDestiny === 'undefined');
+ var isFirstScrollMove = (typeof lastScrolledDestiny === 'undefined' && typeof slideAnchor === 'undefined' && !slideMoving);
+
+
+ if(sectionAnchor.length){
+ /*in order to call scrollpage() only once for each destination at a time
+ It is called twice for each scroll otherwise, as in case of using anchorlinks `hashChange`
+ event is fired on every scroll too.*/
+ if ((sectionAnchor && sectionAnchor !== lastScrolledDestiny) && !isFirstSlideMove || isFirstScrollMove || (!slideMoving && lastScrolledSlide != slideAnchor )) {
+ scrollPageAndSlide(sectionAnchor, slideAnchor);
+ }
+ }
+ }
+ }
+
+ //Sliding with arrow keys, both, vertical and horizontal
+ function keydownHandler(e) {
+
+ clearTimeout(keydownId);
+
+ var activeElement = $(':focus');
+
+ if(!activeElement.is('textarea') && !activeElement.is('input') && !activeElement.is('select') &&
+ activeElement.attr('contentEditable') !== "true" && activeElement.attr('contentEditable') !== '' &&
+ options.keyboardScrolling && options.autoScrolling){
+ var keyCode = e.which;
+
+ //preventing the scroll with arrow keys & spacebar & Page Up & Down keys
+ var keyControls = [40, 38, 32, 33, 34];
+ if($.inArray(keyCode, keyControls) > -1){
+ e.preventDefault();
+ }
+
+ controlPressed = e.ctrlKey;
+
+ keydownId = setTimeout(function(){
+ onkeydown(e);
+ },150);
+ }
+ }
+
+ function tooltipTextHandler(){
+ $(this).prev().trigger('click');
+ }
+
+ //to prevent scrolling while zooming
+ function keyUpHandler(e){
+ if(isWindowFocused){ //the keyup gets fired on new tab ctrl + t in Firefox
+ controlPressed = e.ctrlKey;
+ }
+ }
+
+ //binding the mousemove when the mouse's middle button is released
+ function mouseDownHandler(e){
+ //middle button
+ if (e.which == 2){
+ oldPageY = e.pageY;
+ container.on('mousemove', mouseMoveHandler);
+ }
+ }
+
+ //unbinding the mousemove when the mouse's middle button is released
+ function mouseUpHandler(e){
+ //middle button
+ if (e.which == 2){
+ container.off('mousemove');
+ }
+ }
+
+ //Scrolling horizontally when clicking on the slider controls.
+ function slideArrowHandler(){
+ var section = $(this).closest(SECTION_SEL);
+
+ if ($(this).hasClass(SLIDES_PREV)) {
+ if(isScrollAllowed.m.left){
+ moveSlideLeft(section);
+ }
+ } else {
+ if(isScrollAllowed.m.right){
+ moveSlideRight(section);
+ }
+ }
+ }
+
+ //when opening a new tab (ctrl + t), `control` won't be pressed when coming back.
+ function blurHandler(){
+ isWindowFocused = false;
+ controlPressed = false;
+ }
+
+ //Scrolls to the section when clicking the navigation bullet
+ function sectionBulletHandler(e){
+ e.preventDefault();
+ var index = $(this).parent().index();
+ scrollPage($(SECTION_SEL).eq(index));
+ }
+
+ //Scrolls the slider to the given slide destination for the given section
+ function slideBulletHandler(e){
+ e.preventDefault();
+ var slides = $(this).closest(SECTION_SEL).find(SLIDES_WRAPPER_SEL);
+ var destiny = slides.find(SLIDE_SEL).eq($(this).closest('li').index());
+
+ landscapeScroll(slides, destiny);
+ }
+
+ /**
+ * Keydown event
+ */
+ function onkeydown(e){
+ var shiftPressed = e.shiftKey;
+
+ //do nothing if we can not scroll or we are not using horizotnal key arrows.
+ if(!canScroll && [37,39].indexOf(e.which) < 0){
+ return;
+ }
+
+ switch (e.which) {
+ //up
+ case 38:
+ case 33:
+ if(isScrollAllowed.k.up){
+ moveSectionUp();
+ }
+ break;
+
+ //down
+ case 32: //spacebar
+ if(shiftPressed && isScrollAllowed.k.up){
+ moveSectionUp();
+ break;
+ }
+ /* falls through */
+ case 40:
+ case 34:
+ if(isScrollAllowed.k.down){
+ moveSectionDown();
+ }
+ break;
+
+ //Home
+ case 36:
+ if(isScrollAllowed.k.up){
+ moveTo(1);
+ }
+ break;
+
+ //End
+ case 35:
+ if(isScrollAllowed.k.down){
+ moveTo( $(SECTION_SEL).length );
+ }
+ break;
+
+ //left
+ case 37:
+ if(isScrollAllowed.k.left){
+ moveSlideLeft();
+ }
+ break;
+
+ //right
+ case 39:
+ if(isScrollAllowed.k.right){
+ moveSlideRight();
+ }
+ break;
+
+ default:
+ return; // exit this handler for other keys
+ }
+ }
+
+ /**
+ * Detecting the direction of the mouse movement.
+ * Used only for the middle button of the mouse.
+ */
+ var oldPageY = 0;
+ function mouseMoveHandler(e){
+ if(canScroll){
+ // moving up
+ if (e.pageY < oldPageY && isScrollAllowed.m.up){
+ moveSectionUp();
+ }
+
+ // moving down
+ else if(e.pageY > oldPageY && isScrollAllowed.m.down){
+ moveSectionDown();
+ }
+ }
+ oldPageY = e.pageY;
+ }
+
+ /**
+ * Scrolls horizontal sliders.
+ */
+ function landscapeScroll(slides, destiny, direction){
+ var section = slides.closest(SECTION_SEL);
+ var v = {
+ slides: slides,
+ destiny: destiny,
+ direction: direction,
+ destinyPos: destiny.position(),
+ slideIndex: destiny.index(),
+ section: section,
+ sectionIndex: section.index(SECTION_SEL),
+ anchorLink: section.data('anchor'),
+ slidesNav: section.find(SLIDES_NAV_SEL),
+ slideAnchor: getAnchor(destiny),
+ prevSlide: section.find(SLIDE_ACTIVE_SEL),
+ prevSlideIndex: section.find(SLIDE_ACTIVE_SEL).index(),
+
+ //caching the value of isResizing at the momment the function is called
+ //because it will be checked later inside a setTimeout and the value might change
+ localIsResizing: isResizing
+ };
+ v.xMovement = getXmovement(v.prevSlideIndex, v.slideIndex);
+
+ //important!! Only do it when not resizing
+ if(!v.localIsResizing){
+ //preventing from scrolling to the next/prev section when using scrollHorizontally
+ canScroll = false;
+ }
+
+ if(options.onSlideLeave){
+
+ //if the site is not just resizing and readjusting the slides
+ if(!v.localIsResizing && v.xMovement!=='none'){
+ if($.isFunction( options.onSlideLeave )){
+ if(options.onSlideLeave.call( v.prevSlide, v.anchorLink, (v.sectionIndex + 1), v.prevSlideIndex, v.xMovement, v.slideIndex ) === false){
+ slideMoving = false;
+ return;
+ }
+ }
+ }
+ }
+
+ destiny.addClass(ACTIVE).siblings().removeClass(ACTIVE);
+
+ if(!v.localIsResizing){
+ stopMedia(v.prevSlide);
+ lazyLoad(destiny);
+ }
+
+ if(!options.loopHorizontal && options.controlArrows){
+ //hidding it for the fist slide, showing for the rest
+ section.find(SLIDES_ARROW_PREV_SEL).toggle(v.slideIndex!==0);
+
+ //hidding it for the last slide, showing for the rest
+ section.find(SLIDES_ARROW_NEXT_SEL).toggle(!destiny.is(':last-child'));
+ }
+
+ //only changing the URL if the slides are in the current section (not for resize re-adjusting)
+ if(section.hasClass(ACTIVE)){
+ setState(v.slideIndex, v.slideAnchor, v.anchorLink, v.sectionIndex);
+ }
+
+ performHorizontalMove(slides, v, true);
+ }
+
+
+ function afterSlideLoads(v){
+ activeSlidesNavigation(v.slidesNav, v.slideIndex);
+
+ //if the site is not just resizing and readjusting the slides
+ if(!v.localIsResizing){
+ $.isFunction( options.afterSlideLoad ) && options.afterSlideLoad.call( v.destiny, v.anchorLink, (v.sectionIndex + 1), v.slideAnchor, v.slideIndex);
+
+ //needs to be inside the condition to prevent problems with continuousVertical and scrollHorizontally
+ //and to prevent double scroll right after a windows resize
+ canScroll = true;
+
+ playMedia(v.destiny);
+ }
+
+ //letting them slide again
+ slideMoving = false;
+ }
+
+ /**
+ * Performs the horizontal movement. (CSS3 or jQuery)
+ *
+ * @param fireCallback {Bool} - determines whether or not to fire the callback
+ */
+ function performHorizontalMove(slides, v, fireCallback){
+ var destinyPos = v.destinyPos;
+
+ if(options.css3){
+ var translate3d = 'translate3d(-' + Math.round(destinyPos.left) + 'px, 0px, 0px)';
+
+ addAnimation(slides.find(SLIDES_CONTAINER_SEL)).css(getTransforms(translate3d));
+
+ afterSlideLoadsId = setTimeout(function(){
+ fireCallback && afterSlideLoads(v);
+ }, options.scrollingSpeed, options.easing);
+ }else{
+ slides.animate({
+ scrollLeft : Math.round(destinyPos.left)
+ }, options.scrollingSpeed, options.easing, function() {
+
+ fireCallback && afterSlideLoads(v);
+ });
+ }
+ }
+
+ /**
+ * Sets the state for the horizontal bullet navigations.
+ */
+ function activeSlidesNavigation(slidesNav, slideIndex){
+ slidesNav.find(ACTIVE_SEL).removeClass(ACTIVE);
+ slidesNav.find('li').eq(slideIndex).find('a').addClass(ACTIVE);
+ }
+
+ var previousHeight = windowsHeight;
+
+ //when resizing the site, we adjust the heights of the sections, slimScroll...
+ function resizeHandler(){
+ //checking if it needs to get responsive
+ responsive();
+
+ // rebuild immediately on touch devices
+ if (isTouchDevice) {
+ var activeElement = $(document.activeElement);
+
+ //if the keyboard is NOT visible
+ if (!activeElement.is('textarea') && !activeElement.is('input') && !activeElement.is('select')) {
+ var currentHeight = $window.height();
+
+ //making sure the change in the viewport size is enough to force a rebuild. (20 % of the window to avoid problems when hidding scroll bars)
+ if( Math.abs(currentHeight - previousHeight) > (20 * Math.max(previousHeight, currentHeight) / 100) ){
+ reBuild(true);
+ previousHeight = currentHeight;
+ }
+ }
+ }else{
+ //in order to call the functions only when the resize is finished
+ //http://stackoverflow.com/questions/4298612/jquery-how-to-call-resize-event-only-once-its-finished-resizing
+ clearTimeout(resizeId);
+
+ resizeId = setTimeout(function(){
+ reBuild(true);
+ }, 350);
+ }
+ }
+
+ /**
+ * Checks if the site needs to get responsive and disables autoScrolling if so.
+ * A class `fp-responsive` is added to the plugin's container in case the user wants to use it for his own responsive CSS.
+ */
+ function responsive(){
+ var widthLimit = options.responsive || options.responsiveWidth; //backwards compatiblity
+ var heightLimit = options.responsiveHeight;
+
+ //only calculating what we need. Remember its called on the resize event.
+ var isBreakingPointWidth = widthLimit && $window.outerWidth() < widthLimit;
+ var isBreakingPointHeight = heightLimit && $window.height() < heightLimit;
+
+ if(widthLimit && heightLimit){
+ setResponsive(isBreakingPointWidth || isBreakingPointHeight);
+ }
+ else if(widthLimit){
+ setResponsive(isBreakingPointWidth);
+ }
+ else if(heightLimit){
+ setResponsive(isBreakingPointHeight);
+ }
+ }
+
+ /**
+ * Adds transition animations for the given element
+ */
+ function addAnimation(element){
+ var transition = 'all ' + options.scrollingSpeed + 'ms ' + options.easingcss3;
+
+ element.removeClass(NO_TRANSITION);
+ return element.css({
+ '-webkit-transition': transition,
+ 'transition': transition
+ });
+ }
+
+ /**
+ * Remove transition animations for the given element
+ */
+ function removeAnimation(element){
+ return element.addClass(NO_TRANSITION);
+ }
+
+ /**
+ * Activating the vertical navigation bullets according to the given slide name.
+ */
+ function activateNavDots(name, sectionIndex){
+ if(options.navigation){
+ $(SECTION_NAV_SEL).find(ACTIVE_SEL).removeClass(ACTIVE);
+ if(name){
+ $(SECTION_NAV_SEL).find('a[href="#' + name + '"]').addClass(ACTIVE);
+ }else{
+ $(SECTION_NAV_SEL).find('li').eq(sectionIndex).find('a').addClass(ACTIVE);
+ }
+ }
+ }
+
+ /**
+ * Activating the website main menu elements according to the given slide name.
+ */
+ function activateMenuElement(name){
+ if(options.menu){
+ $(options.menu).find(ACTIVE_SEL).removeClass(ACTIVE);
+ $(options.menu).find('[data-menuanchor="'+name+'"]').addClass(ACTIVE);
+ }
+ }
+
+ /**
+ * Sets to active the current menu and vertical nav items.
+ */
+ function activateMenuAndNav(anchor, index){
+ activateMenuElement(anchor);
+ activateNavDots(anchor, index);
+ }
+
+ /**
+ * Retuns `up` or `down` depending on the scrolling movement to reach its destination
+ * from the current section.
+ */
+ function getYmovement(destiny){
+ var fromIndex = $(SECTION_ACTIVE_SEL).index(SECTION_SEL);
+ var toIndex = destiny.index(SECTION_SEL);
+ if( fromIndex == toIndex){
+ return 'none';
+ }
+ if(fromIndex > toIndex){
+ return 'up';
+ }
+ return 'down';
+ }
+
+ /**
+ * Retuns `right` or `left` depending on the scrolling movement to reach its destination
+ * from the current slide.
+ */
+ function getXmovement(fromIndex, toIndex){
+ if( fromIndex == toIndex){
+ return 'none';
+ }
+ if(fromIndex > toIndex){
+ return 'left';
+ }
+ return 'right';
+ }
+
+ /**
+ * Checks if the element needs scrollbar and if the user wants to apply it.
+ * If so it creates it.
+ *
+ * @param {Object} element jQuery object of the section or slide
+ */
+ function createScrollBar(element){
+ //User doesn't want scrollbar here? Sayonara baby!
+ if(element.hasClass('fp-noscroll')) return;
+
+ //needed to make `scrollHeight` work under Opera 12
+ element.css('overflow', 'hidden');
+
+ var scrollOverflowHandler = options.scrollOverflowHandler;
+ var wrap = scrollOverflowHandler.wrapContent();
+ //in case element is a slide
+ var section = element.closest(SECTION_SEL);
+ var scrollable = scrollOverflowHandler.scrollable(element);
+ var contentHeight;
+
+ //if there was scroll, the contentHeight will be the one in the scrollable section
+ if(scrollable.length){
+ contentHeight = scrollOverflowHandler.scrollHeight(element);
+ }else{
+ contentHeight = element.get(0).scrollHeight;
+ if(options.verticalCentered){
+ contentHeight = element.find(TABLE_CELL_SEL).get(0).scrollHeight;
+ }
+ }
+
+ var scrollHeight = windowsHeight - parseInt(section.css('padding-bottom')) - parseInt(section.css('padding-top'));
+
+ //needs scroll?
+ if ( contentHeight > scrollHeight) {
+ //did we already have an scrollbar ? Updating it
+ if(scrollable.length){
+ scrollOverflowHandler.update(element, scrollHeight);
+ }
+ //creating the scrolling
+ else{
+ if(options.verticalCentered){
+ element.find(TABLE_CELL_SEL).wrapInner(wrap);
+ }else{
+ element.wrapInner(wrap);
+ }
+ scrollOverflowHandler.create(element, scrollHeight);
+ }
+ }
+ //removing the scrolling when it is not necessary anymore
+ else{
+ scrollOverflowHandler.remove(element);
+ }
+
+ //undo
+ element.css('overflow', '');
+ }
+
+ function addTableClass(element){
+ //In case we are styling for the 2nd time as in with reponsiveSlides
+ if(!element.hasClass(TABLE)){
+ element.addClass(TABLE).wrapInner('<div class="' + TABLE_CELL + '" style="height:' + getTableHeight(element) + 'px;" />');
+ }
+ }
+
+ function getTableHeight(element){
+ var sectionHeight = windowsHeight;
+
+ if(options.paddingTop || options.paddingBottom){
+ var section = element;
+ if(!section.hasClass(SECTION)){
+ section = element.closest(SECTION_SEL);
+ }
+
+ var paddings = parseInt(section.css('padding-top')) + parseInt(section.css('padding-bottom'));
+ sectionHeight = (windowsHeight - paddings);
+ }
+
+ return sectionHeight;
+ }
+
+ /**
+ * Adds a css3 transform property to the container class with or without animation depending on the animated param.
+ */
+ function transformContainer(translate3d, animated){
+ if(animated){
+ addAnimation(container);
+ }else{
+ removeAnimation(container);
+ }
+
+ container.css(getTransforms(translate3d));
+
+ //syncronously removing the class after the animation has been applied.
+ setTimeout(function(){
+ container.removeClass(NO_TRANSITION);
+ },10);
+ }
+
+ /**
+ * Gets a section by its anchor / index
+ */
+ function getSectionByAnchor(sectionAnchor){
+ //section
+ var section = container.find(SECTION_SEL + '[data-anchor="'+sectionAnchor+'"]');
+ if(!section.length){
+ section = $(SECTION_SEL).eq( (sectionAnchor -1) );
+ }
+
+ return section;
+ }
+
+ /**
+ * Gets a slide inside a given section by its anchor / index
+ */
+ function getSlideByAnchor(slideAnchor, section){
+ var slides = section.find(SLIDES_WRAPPER_SEL);
+ var slide = slides.find(SLIDE_SEL + '[data-anchor="'+slideAnchor+'"]');
+
+ if(!slide.length){
+ slide = slides.find(SLIDE_SEL).eq(slideAnchor);
+ }
+
+ return slide;
+ }
+
+ /**
+ * Scrolls to the given section and slide anchors
+ */
+ function scrollPageAndSlide(destiny, slide){
+ var section = getSectionByAnchor(destiny);
+
+ //do nothing if there's no section with the given anchor name
+ if(!section.length) return;
+
+ //default slide
+ if (typeof slide === 'undefined') {
+ slide = 0;
+ }
+
+ //we need to scroll to the section and then to the slide
+ if (destiny !== lastScrolledDestiny && !section.hasClass(ACTIVE)){
+ scrollPage(section, function(){
+ scrollSlider(section, slide);
+ });
+ }
+ //if we were already in the section
+ else{
+ scrollSlider(section, slide);
+ }
+ }
+
+ /**
+ * Scrolls the slider to the given slide destination for the given section
+ */
+ function scrollSlider(section, slideAnchor){
+ if(typeof slideAnchor !== 'undefined'){
+ var slides = section.find(SLIDES_WRAPPER_SEL);
+ var destiny = getSlideByAnchor(slideAnchor, section);
+
+ if(destiny.length){
+ landscapeScroll(slides, destiny);
+ }
+ }
+ }
+
+ /**
+ * Creates a landscape navigation bar with dots for horizontal sliders.
+ */
+ function addSlidesNavigation(section, numSlides){
+ section.append('<div class="' + SLIDES_NAV + '"><ul></ul></div>');
+ var nav = section.find(SLIDES_NAV_SEL);
+
+ //top or bottom
+ nav.addClass(options.slidesNavPosition);
+
+ for(var i=0; i< numSlides; i++){
+ nav.find('ul').append('<li><a href="#"><span></span></a></li>');
+ }
+
+ //centering it
+ nav.css('margin-left', '-' + (nav.width()/2) + 'px');
+
+ nav.find('li').first().find('a').addClass(ACTIVE);
+ }
+
+
+ /**
+ * Sets the state of the website depending on the active section/slide.
+ * It changes the URL hash when needed and updates the body class.
+ */
+ function setState(slideIndex, slideAnchor, anchorLink, sectionIndex){
+ var sectionHash = '';
+
+ if(options.anchors.length && !options.lockAnchors){
+
+ //isn't it the first slide?
+ if(slideIndex){
+ if(typeof anchorLink !== 'undefined'){
+ sectionHash = anchorLink;
+ }
+
+ //slide without anchor link? We take the index instead.
+ if(typeof slideAnchor === 'undefined'){
+ slideAnchor = slideIndex;
+ }
+
+ lastScrolledSlide = slideAnchor;
+ setUrlHash(sectionHash + '/' + slideAnchor);
+
+ //first slide won't have slide anchor, just the section one
+ }else if(typeof slideIndex !== 'undefined'){
+ lastScrolledSlide = slideAnchor;
+ setUrlHash(anchorLink);
+ }
+
+ //section without slides
+ else{
+ setUrlHash(anchorLink);
+ }
+ }
+
+ setBodyClass();
+ }
+
+ /**
+ * Sets the URL hash.
+ */
+ function setUrlHash(url){
+ if(options.recordHistory){
+ location.hash = url;
+ }else{
+ //Mobile Chrome doesn't work the normal way, so... lets use HTML5 for phones :)
+ if(isTouchDevice || isTouch){
+ window.history.replaceState(undefined, undefined, '#' + url);
+ }else{
+ var baseUrl = window.location.href.split('#')[0];
+ window.location.replace( baseUrl + '#' + url );
+ }
+ }
+ }
+
+ /**
+ * Gets the anchor for the given slide / section. Its index will be used if there's none.
+ */
+ function getAnchor(element){
+ var anchor = element.data('anchor');
+ var index = element.index();
+
+ //Slide without anchor link? We take the index instead.
+ if(typeof anchor === 'undefined'){
+ anchor = index;
+ }
+
+ return anchor;
+ }
+
+ /**
+ * Sets a class for the body of the page depending on the active section / slide
+ */
+ function setBodyClass(){
+ var section = $(SECTION_ACTIVE_SEL);
+ var slide = section.find(SLIDE_ACTIVE_SEL);
+
+ var sectionAnchor = getAnchor(section);
+ var slideAnchor = getAnchor(slide);
+
+ var text = String(sectionAnchor);
+
+ if(slide.length){
+ text = text + '-' + slideAnchor;
+ }
+
+ //changing slash for dash to make it a valid CSS style
+ text = text.replace('/', '-').replace('#','');
+
+ //removing previous anchor classes
+ var classRe = new RegExp('\\b\\s?' + VIEWING_PREFIX + '-[^\\s]+\\b', "g");
+ $body[0].className = $body[0].className.replace(classRe, '');
+
+ //adding the current anchor
+ $body.addClass(VIEWING_PREFIX + '-' + text);
+ }
+
+ /**
+ * Checks for translate3d support
+ * @return boolean
+ * http://stackoverflow.com/questions/5661671/detecting-transform-translate3d-support
+ */
+ function support3d() {
+ var el = document.createElement('p'),
+ has3d,
+ transforms = {
+ 'webkitTransform':'-webkit-transform',
+ 'OTransform':'-o-transform',
+ 'msTransform':'-ms-transform',
+ 'MozTransform':'-moz-transform',
+ 'transform':'transform'
+ };
+
+ // Add it to the body to get the computed style.
+ document.body.insertBefore(el, null);
+
+ for (var t in transforms) {
+ if (el.style[t] !== undefined) {
+ el.style[t] = 'translate3d(1px,1px,1px)';
+ has3d = window.getComputedStyle(el).getPropertyValue(transforms[t]);
+ }
+ }
+
+ document.body.removeChild(el);
+
+ return (has3d !== undefined && has3d.length > 0 && has3d !== 'none');
+ }
+
+ /**
+ * Removes the auto scrolling action fired by the mouse wheel and trackpad.
+ * After this function is called, the mousewheel and trackpad movements won't scroll through sections.
+ */
+ function removeMouseWheelHandler(){
+ if (document.addEventListener) {
+ document.removeEventListener('mousewheel', MouseWheelHandler, false); //IE9, Chrome, Safari, Oper
+ document.removeEventListener('wheel', MouseWheelHandler, false); //Firefox
+ document.removeEventListener('MozMousePixelScroll', MouseWheelHandler, false); //old Firefox
+ } else {
+ document.detachEvent('onmousewheel', MouseWheelHandler); //IE 6/7/8
+ }
+ }
+
+ /**
+ * Adds the auto scrolling action for the mouse wheel and trackpad.
+ * After this function is called, the mousewheel and trackpad movements will scroll through sections
+ * https://developer.mozilla.org/en-US/docs/Web/Events/wheel
+ */
+ function addMouseWheelHandler(){
+ var prefix = '';
+ var _addEventListener;
+
+ if (window.addEventListener){
+ _addEventListener = "addEventListener";
+ }else{
+ _addEventListener = "attachEvent";
+ prefix = 'on';
+ }
+
+ // detect available wheel event
+ var support = 'onwheel' in document.createElement('div') ? 'wheel' : // Modern browsers support "wheel"
+ document.onmousewheel !== undefined ? 'mousewheel' : // Webkit and IE support at least "mousewheel"
+ 'DOMMouseScroll'; // let's assume that remaining browsers are older Firefox
+
+
+ if(support == 'DOMMouseScroll'){
+ document[ _addEventListener ](prefix + 'MozMousePixelScroll', MouseWheelHandler, false);
+ }
+
+ //handle MozMousePixelScroll in older Firefox
+ else{
+ document[ _addEventListener ](prefix + support, MouseWheelHandler, false);
+ }
+ }
+
+ /**
+ * Binding the mousemove when the mouse's middle button is pressed
+ */
+ function addMiddleWheelHandler(){
+ container
+ .on('mousedown', mouseDownHandler)
+ .on('mouseup', mouseUpHandler);
+ }
+
+ /**
+ * Unbinding the mousemove when the mouse's middle button is released
+ */
+ function removeMiddleWheelHandler(){
+ container
+ .off('mousedown', mouseDownHandler)
+ .off('mouseup', mouseUpHandler);
+ }
+
+ /**
+ * Adds the possibility to auto scroll through sections on touch devices.
+ */
+ function addTouchHandler(){
+ if(isTouchDevice || isTouch){
+ //Microsoft pointers
+ var MSPointer = getMSPointer();
+
+ if(options.autoScrolling){
+ $body.off('touchmove ' + MSPointer.move).on('touchmove ' + MSPointer.move, preventBouncing);
+ }
+
+ $(WRAPPER_SEL)
+ .off('touchstart ' + MSPointer.down).on('touchstart ' + MSPointer.down, touchStartHandler)
+ .off('touchmove ' + MSPointer.move).on('touchmove ' + MSPointer.move, touchMoveHandler);
+ }
+ }
+
+ /**
+ * Removes the auto scrolling for touch devices.
+ */
+ function removeTouchHandler(){
+ if(isTouchDevice || isTouch){
+ //Microsoft pointers
+ var MSPointer = getMSPointer();
+
+ $(WRAPPER_SEL)
+ .off('touchstart ' + MSPointer.down)
+ .off('touchmove ' + MSPointer.move);
+ }
+ }
+
+ /*
+ * Returns and object with Microsoft pointers (for IE<11 and for IE >= 11)
+ * http://msdn.microsoft.com/en-us/library/ie/dn304886(v=vs.85).aspx
+ */
+ function getMSPointer(){
+ var pointer;
+
+ //IE >= 11 & rest of browsers
+ if(window.PointerEvent){
+ pointer = { down: 'pointerdown', move: 'pointermove'};
+ }
+
+ //IE < 11
+ else{
+ pointer = { down: 'MSPointerDown', move: 'MSPointerMove'};
+ }
+
+ return pointer;
+ }
+
+ /**
+ * Gets the pageX and pageY properties depending on the browser.
+ * https://github.com/alvarotrigo/fullPage.js/issues/194#issuecomment-34069854
+ */
+ function getEventsPage(e){
+ var events = [];
+
+ events.y = (typeof e.pageY !== 'undefined' && (e.pageY || e.pageX) ? e.pageY : e.touches[0].pageY);
+ events.x = (typeof e.pageX !== 'undefined' && (e.pageY || e.pageX) ? e.pageX : e.touches[0].pageX);
+
+ //in touch devices with scrollBar:true, e.pageY is detected, but we have to deal with touch events. #1008
+ if(isTouch && isReallyTouch(e) && options.scrollBar){
+ events.y = e.touches[0].pageY;
+ events.x = e.touches[0].pageX;
+ }
+
+ return events;
+ }
+
+ /**
+ * Slides silently (with no animation) the active slider to the given slide.
+ * @param noCallback {bool} true or defined -> no callbacks
+ */
+ function silentLandscapeScroll(activeSlide, noCallbacks){
+ setScrollingSpeed (0, 'internal');
+
+ if(typeof noCallbacks !== 'undefined'){
+ //preventing firing callbacks afterSlideLoad etc.
+ isResizing = true;
+ }
+
+ landscapeScroll(activeSlide.closest(SLIDES_WRAPPER_SEL), activeSlide);
+
+ if(typeof noCallbacks !== 'undefined'){
+ isResizing = false;
+ }
+
+ setScrollingSpeed(originals.scrollingSpeed, 'internal');
+ }
+
+ /**
+ * Scrolls silently (with no animation) the page to the given Y position.
+ */
+ function silentScroll(top){
+ // The first section can have a negative value in iOS 10. Not quite sure why: -0.0142822265625
+ // that's why we round it to 0.
+ var roundedTop = Math.round(top);
+
+ if (options.css3 && options.autoScrolling && !options.scrollBar){
+ var translate3d = 'translate3d(0px, -' + roundedTop + 'px, 0px)';
+ transformContainer(translate3d, false);
+ }
+ else if(options.autoScrolling && !options.scrollBar){
+ container.css('top', -roundedTop);
+ }
+ else{
+ $htmlBody.scrollTop(roundedTop);
+ }
+ }
+
+ /**
+ * Returns the cross-browser transform string.
+ */
+ function getTransforms(translate3d){
+ return {
+ '-webkit-transform': translate3d,
+ '-moz-transform': translate3d,
+ '-ms-transform':translate3d,
+ 'transform': translate3d
+ };
+ }
+
+ /**
+ * Allowing or disallowing the mouse/swipe scroll in a given direction. (not for keyboard)
+ * @type m (mouse) or k (keyboard)
+ */
+ function setIsScrollAllowed(value, direction, type){
+ switch (direction){
+ case 'up': isScrollAllowed[type].up = value; break;
+ case 'down': isScrollAllowed[type].down = value; break;
+ case 'left': isScrollAllowed[type].left = value; break;
+ case 'right': isScrollAllowed[type].right = value; break;
+ case 'all':
+ if(type == 'm'){
+ setAllowScrolling(value);
+ }else{
+ setKeyboardScrolling(value);
+ }
+ }
+ }
+
+ /*
+ * Destroys fullpage.js plugin events and optinally its html markup and styles
+ */
+ function destroy(all){
+ setAutoScrolling(false, 'internal');
+ setAllowScrolling(false);
+ setKeyboardScrolling(false);
+ container.addClass(DESTROYED);
+
+ clearTimeout(afterSlideLoadsId);
+ clearTimeout(afterSectionLoadsId);
+ clearTimeout(resizeId);
+ clearTimeout(scrollId);
+ clearTimeout(scrollId2);
+
+ $window
+ .off('scroll', scrollHandler)
+ .off('hashchange', hashChangeHandler)
+ .off('resize', resizeHandler);
+
+ $document
+ .off('click touchstart', SECTION_NAV_SEL + ' a')
+ .off('mouseenter', SECTION_NAV_SEL + ' li')
+ .off('mouseleave', SECTION_NAV_SEL + ' li')
+ .off('click touchstart', SLIDES_NAV_LINK_SEL)
+ .off('mouseover', options.normalScrollElements)
+ .off('mouseout', options.normalScrollElements);
+
+ $(SECTION_SEL)
+ .off('click touchstart', SLIDES_ARROW_SEL);
+
+ clearTimeout(afterSlideLoadsId);
+ clearTimeout(afterSectionLoadsId);
+
+ //lets make a mess!
+ if(all){
+ destroyStructure();
+ }
+ }
+
+ /*
+ * Removes inline styles added by fullpage.js
+ */
+ function destroyStructure(){
+ //reseting the `top` or `translate` properties to 0
+ silentScroll(0);
+
+ //loading all the lazy load content
+ container.find('img[data-src], source[data-src], audio[data-src], iframe[data-src]').each(function(){
+ $(this).attr('src', $(this).data('src'));
+ $(this).removeAttr('data-src');
+ });
+
+ $(SECTION_NAV_SEL + ', ' + SLIDES_NAV_SEL + ', ' + SLIDES_ARROW_SEL).remove();
+
+ //removing inline styles
+ $(SECTION_SEL).css( {
+ 'height': '',
+ 'background-color' : '',
+ 'padding': ''
+ });
+
+ $(SLIDE_SEL).css( {
+ 'width': ''
+ });
+
+ container.css({
+ 'height': '',
+ 'position': '',
+ '-ms-touch-action': '',
+ 'touch-action': ''
+ });
+
+ $htmlBody.css({
+ 'overflow': '',
+ 'height': ''
+ });
+
+ // remove .fp-enabled class
+ $('html').removeClass(ENABLED);
+
+ // remove .fp-responsive class
+ $body.removeClass(RESPONSIVE);
+
+ // remove all of the .fp-viewing- classes
+ $.each($body.get(0).className.split(/\s+/), function (index, className) {
+ if (className.indexOf(VIEWING_PREFIX) === 0) {
+ $body.removeClass(className);
+ }
+ });
+
+ //removing added classes
+ $(SECTION_SEL + ', ' + SLIDE_SEL).each(function(){
+ options.scrollOverflowHandler.remove($(this));
+ $(this).removeClass(TABLE + ' ' + ACTIVE);
+ });
+
+ removeAnimation(container);
+
+ //Unwrapping content
+ container.find(TABLE_CELL_SEL + ', ' + SLIDES_CONTAINER_SEL + ', ' + SLIDES_WRAPPER_SEL).each(function(){
+ //unwrap not being use in case there's no child element inside and its just text
+ $(this).replaceWith(this.childNodes);
+ });
+
+ //scrolling the page to the top with no animation
+ $htmlBody.scrollTop(0);
+
+ //removing selectors
+ var usedSelectors = [SECTION, SLIDE, SLIDES_CONTAINER];
+ $.each(usedSelectors, function(index, value){
+ $('.' + value).removeClass(value);
+ });
+ }
+
+ /*
+ * Sets the state for a variable with multiple states (original, and temporal)
+ * Some variables such as `autoScrolling` or `recordHistory` might change automatically its state when using `responsive` or `autoScrolling:false`.
+ * This function is used to keep track of both states, the original and the temporal one.
+ * If type is not 'internal', then we assume the user is globally changing the variable.
+ */
+ function setVariableState(variable, value, type){
+ options[variable] = value;
+ if(type !== 'internal'){
+ originals[variable] = value;
+ }
+ }
+
+ /**
+ * Displays warnings
+ */
+ function displayWarnings(){
+ var extensions = ['fadingEffect', 'continuousHorizontal', 'scrollHorizontally', 'interlockedSlides', 'resetSliders', 'responsiveSlides', 'offsetSections', 'dragAndMove', 'scrollOverflowReset'];
+ if($('html').hasClass(ENABLED)){
+ showError('error', 'Fullpage.js can only be initialized once and you are doing it multiple times!');
+ return;
+ }
+
+ // Disable mutually exclusive settings
+ if (options.continuousVertical &&
+ (options.loopTop || options.loopBottom)) {
+ options.continuousVertical = false;
+ showError('warn', 'Option `loopTop/loopBottom` is mutually exclusive with `continuousVertical`; `continuousVertical` disabled');
+ }
+
+ if(options.scrollBar && options.scrollOverflow){
+ showError('warn', 'Option `scrollBar` is mutually exclusive with `scrollOverflow`. Sections with scrollOverflow might not work well in Firefox');
+ }
+
+ if(options.continuousVertical && (options.scrollBar || !options.autoScrolling)){
+ options.continuousVertical = false;
+ showError('warn', 'Scroll bars (`scrollBar:true` or `autoScrolling:false`) are mutually exclusive with `continuousVertical`; `continuousVertical` disabled');
+ }
+
+ //using extensions? Wrong file!
+ $.each(extensions, function(index, extension){
+ //is the option set to true?
+ if(options[extension]){
+ showError('warn', 'fullpage.js extensions require jquery.fullpage.extensions.min.js file instead of the usual jquery.fullpage.js. Requested: '+ extension);
+ }
+ });
+
+ //anchors can not have the same value as any element ID or NAME
+ $.each(options.anchors, function(index, name){
+
+ //case insensitive selectors (http://stackoverflow.com/a/19465187/1081396)
+ var nameAttr = $document.find('[name]').filter(function() {
+ return $(this).attr('name') && $(this).attr('name').toLowerCase() == name.toLowerCase();
+ });
+
+ var idAttr = $document.find('[id]').filter(function() {
+ return $(this).attr('id') && $(this).attr('id').toLowerCase() == name.toLowerCase();
+ });
+
+ if(idAttr.length || nameAttr.length ){
+ showError('error', 'data-anchor tags can not have the same value as any `id` element on the site (or `name` element for IE).');
+ idAttr.length && showError('error', '"' + name + '" is is being used by another element `id` property');
+ nameAttr.length && showError('error', '"' + name + '" is is being used by another element `name` property');
+ }
+ });
+ }
+
+ /**
+ * Shows a message in the console of the given type.
+ */
+ function showError(type, text){
+ console && console[type] && console[type]('fullPage: ' + text);
+ }
+
+ }; //end of $.fn.fullpage
+
+ if(typeof IScroll !== 'undefined'){
+ /*
+ * Turns iScroll `mousewheel` option off dynamically
+ * https://github.com/cubiq/iscroll/issues/1036
+ */
+ IScroll.prototype.wheelOn = function () {
+ this.wrapper.addEventListener('wheel', this);
+ this.wrapper.addEventListener('mousewheel', this);
+ this.wrapper.addEventListener('DOMMouseScroll', this);
+ };
+
+ /*
+ * Turns iScroll `mousewheel` option on dynamically
+ * https://github.com/cubiq/iscroll/issues/1036
+ */
+ IScroll.prototype.wheelOff = function () {
+ this.wrapper.removeEventListener('wheel', this);
+ this.wrapper.removeEventListener('mousewheel', this);
+ this.wrapper.removeEventListener('DOMMouseScroll', this);
+ };
+ }
+
+ /**
+ * An object to handle overflow scrolling.
+ * This uses jquery.slimScroll to accomplish overflow scrolling.
+ * It is possible to pass in an alternate scrollOverflowHandler
+ * to the fullpage.js option that implements the same functions
+ * as this handler.
+ *
+ * @type {Object}
+ */
+ var iscrollHandler = {
+ refreshId: null,
+ iScrollInstances: [],
+
+ // Enables or disables the mouse wheel for the active section or all slides in it
+ toggleWheel: function(value){
+ var scrollable = $(SECTION_ACTIVE_SEL).find(SCROLLABLE_SEL);
+ scrollable.each(function(){
+ var iScrollInstance = $(this).data('iscrollInstance');
+ if(typeof iScrollInstance !== 'undefined' && iScrollInstance){
+ if(value){
+ iScrollInstance.wheelOn();
+ }
+ else{
+ iScrollInstance.wheelOff();
+ }
+ }
+ });
+ },
+
+ /**
+ * Turns off iScroll for the destination section.
+ * When scrolling very fast on some trackpads (and Apple laptops) the inertial scrolling would
+ * scroll the destination section/slide before the sections animations ends.
+ */
+ onLeave: function(){
+ iscrollHandler.toggleWheel(false);
+ },
+
+ // Turns off iScroll for the leaving section
+ beforeLeave: function(){
+ iscrollHandler.onLeave()
+ },
+
+ // Turns on iScroll on section load
+ afterLoad: function(){
+ iscrollHandler.toggleWheel(true);
+ },
+
+ /**
+ * Called when overflow scrolling is needed for a section.
+ *
+ * @param {Object} element jQuery object containing current section
+ * @param {Number} scrollHeight Current window height in pixels
+ */
+ create: function(element, scrollHeight) {
+ var scrollable = element.find(SCROLLABLE_SEL);
+
+ scrollable.height(scrollHeight);
+ scrollable.each(function() {
+ var $this = $(this);
+ var iScrollInstance = $this.data('iscrollInstance');
+ if (iScrollInstance) {
+ $.each(iscrollHandler.iScrollInstances, function(){
+ $(this).destroy();
+ });
+ }
+
+ iScrollInstance = new IScroll($this.get(0), iscrollOptions);
+ iscrollHandler.iScrollInstances.push(iScrollInstance);
+
+ //off by default until the section gets active
+ iScrollInstance.wheelOff();
+
+ $this.data('iscrollInstance', iScrollInstance);
+ });
+ },
+
+ /**
+ * Return a boolean depending on whether the scrollable element is a
+ * the end or at the start of the scrolling depending on the given type.
+ *
+ * @param {String} type Either 'top' or 'bottom'
+ * @param {Object} scrollable jQuery object for the scrollable element
+ * @return {Boolean}
+ */
+ isScrolled: function(type, scrollable) {
+ var scroller = scrollable.data('iscrollInstance');
+
+ //no scroller?
+ if (!scroller) {
+ return true;
+ }
+
+ if (type === 'top') {
+ return scroller.y >= 0 && !scrollable.scrollTop();
+ } else if (type === 'bottom') {
+ return (0 - scroller.y) + scrollable.scrollTop() + 1 + scrollable.innerHeight() >= scrollable[0].scrollHeight;
+ }
+ },
+
+ /**
+ * Returns the scrollable element for the given section.
+ * If there are landscape slides, will only return a scrollable element
+ * if it is in the active slide.
+ *
+ * @param {Object} activeSection jQuery object containing current section
+ * @return {Boolean}
+ */
+ scrollable: function(activeSection){
+ // if there are landscape slides, we check if the scrolling bar is in the current one or not
+ if (activeSection.find(SLIDES_WRAPPER_SEL).length) {
+ return activeSection.find(SLIDE_ACTIVE_SEL).find(SCROLLABLE_SEL);
+ }
+ return activeSection.find(SCROLLABLE_SEL);
+ },
+
+ /**
+ * Returns the scroll height of the wrapped content.
+ * If this is larger than the window height minus section padding,
+ * overflow scrolling is needed.
+ *
+ * @param {Object} element jQuery object containing current section
+ * @return {Number}
+ */
+ scrollHeight: function(element) {
+ return element.find(SCROLLABLE_SEL).children().first().get(0).scrollHeight;
+ },
+
+ /**
+ * Called when overflow scrolling is no longer needed for a section.
+ *
+ * @param {Object} element jQuery object containing current section
+ */
+ remove: function(element) {
+ var scrollable = element.find(SCROLLABLE_SEL);
+ if (scrollable.length) {
+ var iScrollInstance = scrollable.data('iscrollInstance');
+ iScrollInstance.destroy();
+
+ scrollable.data('iscrollInstance', null);
+ }
+ element.find(SCROLLABLE_SEL).children().first().children().first().unwrap().unwrap();
+ },
+
+ /**
+ * Called when overflow scrolling has already been setup but the
+ * window height has potentially changed.
+ *
+ * @param {Object} element jQuery object containing current section
+ * @param {Number} scrollHeight Current window height in pixels
+ */
+ update: function(element, scrollHeight) {
+ //using a timeout in order to execute the refresh function only once when `update` is called multiple times in a
+ //short period of time.
+ //it also comes on handy because iScroll requires the use of timeout when using `refresh`.
+ clearTimeout(iscrollHandler.refreshId);
+ iscrollHandler.refreshId = setTimeout(function(){
+ $.each(iscrollHandler.iScrollInstances, function(){
+ $(this).get(0).refresh();
+ });
+ }, 150);
+
+ //updating the wrappers height
+ element.find(SCROLLABLE_SEL).css('height', scrollHeight + 'px').parent().css('height', scrollHeight + 'px');
+ },
+
+ /**
+ * Called to get any additional elements needed to wrap the section
+ * content in order to facilitate overflow scrolling.
+ *
+ * @return {String|Object} Can be a string containing HTML,
+ * a DOM element, or jQuery object.
+ */
+ wrapContent: function() {
+ return '<div class="' + SCROLLABLE + '"><div class="fp-scroller"></div></div>';
+ }
+ };
+});
diff --git a/studio-susie/public/assets/js/vendor/liquid-lite.min.js b/studio-susie/public/assets/js/vendor/liquid-lite.min.js
new file mode 100644
index 0000000..d4e0d8e
--- /dev/null
+++ b/studio-susie/public/assets/js/vendor/liquid-lite.min.js
@@ -0,0 +1,2 @@
+this.liquid=function(c){function e(a,b){if(a=a.match(/^\s*(?:new\b|typeof\b|[^a-z].*)?(\w*)/)[1])f[a+(b||'=""')]=1}var f={"_=[]":1};c=c.replace(/\r?\n/g,"\\n").replace(/{{(.+?)}}/g,function(a,b){e(b);return"',("+b.replace(/([^|])\|\s*(\w+)(?:\s*\:([^|]+))?/g,"$1).$2($3")+"),'"}).replace(/{%\s*(for|if|elsif)?\s*(\!?)\s*(.+?)%}(?:\\n)?/g,function(a,b,c,d){"for"==b?((a=d.match(/^(\w+) in (\w*)(.*)/))?(e(a[2],"={}"),b="var loop={i:0,offset:0},_3=loop,_2="+a[2]+a[3].replace(/ (limit|offset):\s*(\d+)/ig,
+";_3.$1=$2")+";if(_2)for",a="_1 in _2)if(_2.hasOwnProperty(_1)&&!(_3.offset&&_3.offset--)){_3.i++;if(_3.limit&&_3.i-_3.offset>_3.limit)break;_3.key=_1;var "+a[1]+"=_2[_1];"):a=d+"){",a="');"+b+"(var "+a):b?(e(d),a="')"+("if"==b?";":"}else ")+"if("+c+"("+d+")){"):a="else "==d?"')}else{":"')};";return a+"_.push('"});return new Function("_0","var "+Object.keys(f).join(",")+";with(_0||{}){_.push('"+c+"')}return _.join('')")};
diff --git a/studio-susie/public/assets/js/vendor/loader.js b/studio-susie/public/assets/js/vendor/loader.js
new file mode 100755
index 0000000..4b4fde4
--- /dev/null
+++ b/studio-susie/public/assets/js/vendor/loader.js
@@ -0,0 +1,99 @@
+var Loader = Loader || (function(){
+ function Loader (readyCallback, view){
+ this.assets = {};
+ this.images = [];
+ this.readyCallback = readyCallback || function(){};
+ this.count = 0
+ this.view = view
+ this.loaded = false
+ }
+
+ // Register an asset as loading
+ Loader.prototype.register = function(s){
+ this.assets[s] = false;
+ this.count += 1
+ }
+
+ // Signal that an asset has loaded
+ Loader.prototype.ready = function(s){
+ window.debug && console.log("ready >> " + s);
+
+ this.assets[s] = true;
+ if (this.loaded) return;
+
+ this.view && this.view.update( this.percentRemaining() )
+
+ if (! this.isReady()) return;
+
+ this.loaded = true;
+ if (this.view) {
+ this.view && this.view.finish(this.readyCallback)
+ }
+ else {
+ this.readyCallback && this.readyCallback();
+ }
+ }
+
+ // (boolean) Is the loader ready?
+ Loader.prototype.isReady = function(){
+ for (var s in this.assets) {
+ if (this.assets.hasOwnProperty(s) && this.assets[s] != true) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ // (float) Percentage of assets remaining
+ Loader.prototype.percentRemaining = function(){
+ return this.remainingAssets() / this.count
+ }
+
+ // (int) Number of assets remaining
+ Loader.prototype.remainingAssets = function(){
+ var n = 0;
+ for (var s in this.assets) {
+ if (this.assets.hasOwnProperty(s) && this.assets[s] != true) {
+ n++;
+ // console.log('remaining: ' + s);
+ }
+ }
+ return n;
+ }
+
+ // Preload the images in config.images
+ Loader.prototype.preloadImages = function(images){
+ this.register("preload");
+ for (var i = 0; i < images.length; i++) {
+ this.preloadImage(images[i]);
+ }
+ this.ready("preload");
+ }
+ Loader.prototype.preloadImage = function(src, register, cb){
+ if (! src || src == "none") return;
+ var _this = this;
+ if (! cb && typeof register === "function") {
+ cb = register
+ register = null
+ }
+ if (register) {
+ this.register(src);
+ }
+ var img = new Image(), loaded = false;
+ img.onload = function(){
+ if (loaded) return
+ loaded = true
+ if (cb) {
+ cb(img);
+ }
+ if (register) {
+ _this.ready(src);
+ }
+ }
+ img.src = src;
+ if (img.complete) img.onload();
+ _this.images.push(img);
+ }
+
+ return Loader;
+})();
diff --git a/studio-susie/public/assets/js/vendor/lodash.min.js b/studio-susie/public/assets/js/vendor/lodash.min.js
new file mode 100644
index 0000000..e6c9820
--- /dev/null
+++ b/studio-susie/public/assets/js/vendor/lodash.min.js
@@ -0,0 +1,98 @@
+/**
+ * @license
+ * lodash 3.10.1 (Custom Build) lodash.com/license | Underscore.js 1.8.3 underscorejs.org/LICENSE
+ * Build: `lodash modern -o ./lodash.js`
+ */
+;(function(){function n(n,t){if(n!==t){var r=null===n,e=n===w,u=n===n,o=null===t,i=t===w,f=t===t;if(n>t&&!o||!u||r&&!i&&f||e&&f)return 1;if(n<t&&!r||!f||o&&!e&&u||i&&u)return-1}return 0}function t(n,t,r){for(var e=n.length,u=r?e:-1;r?u--:++u<e;)if(t(n[u],u,n))return u;return-1}function r(n,t,r){if(t!==t)return p(n,r);r-=1;for(var e=n.length;++r<e;)if(n[r]===t)return r;return-1}function e(n){return typeof n=="function"||false}function u(n){return null==n?"":n+""}function o(n,t){for(var r=-1,e=n.length;++r<e&&-1<t.indexOf(n.charAt(r)););
+return r}function i(n,t){for(var r=n.length;r--&&-1<t.indexOf(n.charAt(r)););return r}function f(t,r){return n(t.a,r.a)||t.b-r.b}function a(n){return Nn[n]}function c(n){return Tn[n]}function l(n,t,r){return t?n=Bn[n]:r&&(n=Dn[n]),"\\"+n}function s(n){return"\\"+Dn[n]}function p(n,t,r){var e=n.length;for(t+=r?0:-1;r?t--:++t<e;){var u=n[t];if(u!==u)return t}return-1}function h(n){return!!n&&typeof n=="object"}function _(n){return 160>=n&&9<=n&&13>=n||32==n||160==n||5760==n||6158==n||8192<=n&&(8202>=n||8232==n||8233==n||8239==n||8287==n||12288==n||65279==n);
+}function v(n,t){for(var r=-1,e=n.length,u=-1,o=[];++r<e;)n[r]===t&&(n[r]=z,o[++u]=r);return o}function g(n){for(var t=-1,r=n.length;++t<r&&_(n.charCodeAt(t)););return t}function y(n){for(var t=n.length;t--&&_(n.charCodeAt(t)););return t}function d(n){return Ln[n]}function m(_){function Nn(n){if(h(n)&&!(Oo(n)||n instanceof zn)){if(n instanceof Ln)return n;if(nu.call(n,"__chain__")&&nu.call(n,"__wrapped__"))return Mr(n)}return new Ln(n)}function Tn(){}function Ln(n,t,r){this.__wrapped__=n,this.__actions__=r||[],
+this.__chain__=!!t}function zn(n){this.__wrapped__=n,this.__actions__=[],this.__dir__=1,this.__filtered__=false,this.__iteratees__=[],this.__takeCount__=Ru,this.__views__=[]}function Bn(){this.__data__={}}function Dn(n){var t=n?n.length:0;for(this.data={hash:gu(null),set:new lu};t--;)this.push(n[t])}function Mn(n,t){var r=n.data;return(typeof t=="string"||ge(t)?r.set.has(t):r.hash[t])?0:-1}function qn(n,t){var r=-1,e=n.length;for(t||(t=Be(e));++r<e;)t[r]=n[r];return t}function Pn(n,t){for(var r=-1,e=n.length;++r<e&&false!==t(n[r],r,n););
+return n}function Kn(n,t){for(var r=-1,e=n.length;++r<e;)if(!t(n[r],r,n))return false;return true}function Vn(n,t){for(var r=-1,e=n.length,u=-1,o=[];++r<e;){var i=n[r];t(i,r,n)&&(o[++u]=i)}return o}function Gn(n,t){for(var r=-1,e=n.length,u=Be(e);++r<e;)u[r]=t(n[r],r,n);return u}function Jn(n,t){for(var r=-1,e=t.length,u=n.length;++r<e;)n[u+r]=t[r];return n}function Xn(n,t,r,e){var u=-1,o=n.length;for(e&&o&&(r=n[++u]);++u<o;)r=t(r,n[u],u,n);return r}function Hn(n,t){for(var r=-1,e=n.length;++r<e;)if(t(n[r],r,n))return true;
+return false}function Qn(n,t,r,e){return n!==w&&nu.call(e,r)?n:t}function nt(n,t,r){for(var e=-1,u=zo(t),o=u.length;++e<o;){var i=u[e],f=n[i],a=r(f,t[i],i,n,t);(a===a?a===f:f!==f)&&(f!==w||i in n)||(n[i]=a)}return n}function tt(n,t){return null==t?n:et(t,zo(t),n)}function rt(n,t){for(var r=-1,e=null==n,u=!e&&Er(n),o=u?n.length:0,i=t.length,f=Be(i);++r<i;){var a=t[r];f[r]=u?Cr(a,o)?n[a]:w:e?w:n[a]}return f}function et(n,t,r){r||(r={});for(var e=-1,u=t.length;++e<u;){var o=t[e];r[o]=n[o]}return r}function ut(n,t,r){
+var e=typeof n;return"function"==e?t===w?n:Bt(n,t,r):null==n?Fe:"object"==e?bt(n):t===w?ze(n):xt(n,t)}function ot(n,t,r,e,u,o,i){var f;if(r&&(f=u?r(n,e,u):r(n)),f!==w)return f;if(!ge(n))return n;if(e=Oo(n)){if(f=kr(n),!t)return qn(n,f)}else{var a=ru.call(n),c=a==K;if(a!=Z&&a!=B&&(!c||u))return Fn[a]?Rr(n,a,t):u?n:{};if(f=Ir(c?{}:n),!t)return tt(f,n)}for(o||(o=[]),i||(i=[]),u=o.length;u--;)if(o[u]==n)return i[u];return o.push(n),i.push(f),(e?Pn:_t)(n,function(e,u){f[u]=ot(e,t,r,u,n,o,i)}),f}function it(n,t,r){
+if(typeof n!="function")throw new Ge(L);return su(function(){n.apply(w,r)},t)}function ft(n,t){var e=n?n.length:0,u=[];if(!e)return u;var o=-1,i=xr(),f=i===r,a=f&&t.length>=F&&gu&&lu?new Dn(t):null,c=t.length;a&&(i=Mn,f=false,t=a);n:for(;++o<e;)if(a=n[o],f&&a===a){for(var l=c;l--;)if(t[l]===a)continue n;u.push(a)}else 0>i(t,a,0)&&u.push(a);return u}function at(n,t){var r=true;return Su(n,function(n,e,u){return r=!!t(n,e,u)}),r}function ct(n,t,r,e){var u=e,o=u;return Su(n,function(n,i,f){i=+t(n,i,f),(r(i,u)||i===e&&i===o)&&(u=i,
+o=n)}),o}function lt(n,t){var r=[];return Su(n,function(n,e,u){t(n,e,u)&&r.push(n)}),r}function st(n,t,r,e){var u;return r(n,function(n,r,o){return t(n,r,o)?(u=e?r:n,false):void 0}),u}function pt(n,t,r,e){e||(e=[]);for(var u=-1,o=n.length;++u<o;){var i=n[u];h(i)&&Er(i)&&(r||Oo(i)||pe(i))?t?pt(i,t,r,e):Jn(e,i):r||(e[e.length]=i)}return e}function ht(n,t){Nu(n,t,Re)}function _t(n,t){return Nu(n,t,zo)}function vt(n,t){return Tu(n,t,zo)}function gt(n,t){for(var r=-1,e=t.length,u=-1,o=[];++r<e;){var i=t[r];
+ve(n[i])&&(o[++u]=i)}return o}function yt(n,t,r){if(null!=n){r!==w&&r in Br(n)&&(t=[r]),r=0;for(var e=t.length;null!=n&&r<e;)n=n[t[r++]];return r&&r==e?n:w}}function dt(n,t,r,e,u,o){if(n===t)n=true;else if(null==n||null==t||!ge(n)&&!h(t))n=n!==n&&t!==t;else n:{var i=dt,f=Oo(n),a=Oo(t),c=D,l=D;f||(c=ru.call(n),c==B?c=Z:c!=Z&&(f=xe(n))),a||(l=ru.call(t),l==B?l=Z:l!=Z&&xe(t));var s=c==Z,a=l==Z,l=c==l;if(!l||f||s){if(!e&&(c=s&&nu.call(n,"__wrapped__"),a=a&&nu.call(t,"__wrapped__"),c||a)){n=i(c?n.value():n,a?t.value():t,r,e,u,o);
+break n}if(l){for(u||(u=[]),o||(o=[]),c=u.length;c--;)if(u[c]==n){n=o[c]==t;break n}u.push(n),o.push(t),n=(f?yr:mr)(n,t,i,r,e,u,o),u.pop(),o.pop()}else n=false}else n=dr(n,t,c)}return n}function mt(n,t,r){var e=t.length,u=e,o=!r;if(null==n)return!u;for(n=Br(n);e--;){var i=t[e];if(o&&i[2]?i[1]!==n[i[0]]:!(i[0]in n))return false}for(;++e<u;){var i=t[e],f=i[0],a=n[f],c=i[1];if(o&&i[2]){if(a===w&&!(f in n))return false}else if(i=r?r(a,c,f):w,i===w?!dt(c,a,r,true):!i)return false}return true}function wt(n,t){var r=-1,e=Er(n)?Be(n.length):[];
+return Su(n,function(n,u,o){e[++r]=t(n,u,o)}),e}function bt(n){var t=Ar(n);if(1==t.length&&t[0][2]){var r=t[0][0],e=t[0][1];return function(n){return null==n?false:n[r]===e&&(e!==w||r in Br(n))}}return function(n){return mt(n,t)}}function xt(n,t){var r=Oo(n),e=Wr(n)&&t===t&&!ge(t),u=n+"";return n=Dr(n),function(o){if(null==o)return false;var i=u;if(o=Br(o),!(!r&&e||i in o)){if(o=1==n.length?o:yt(o,Et(n,0,-1)),null==o)return false;i=Zr(n),o=Br(o)}return o[i]===t?t!==w||i in o:dt(t,o[i],w,true)}}function At(n,t,r,e,u){
+if(!ge(n))return n;var o=Er(t)&&(Oo(t)||xe(t)),i=o?w:zo(t);return Pn(i||t,function(f,a){if(i&&(a=f,f=t[a]),h(f)){e||(e=[]),u||(u=[]);n:{for(var c=a,l=e,s=u,p=l.length,_=t[c];p--;)if(l[p]==_){n[c]=s[p];break n}var p=n[c],v=r?r(p,_,c,n,t):w,g=v===w;g&&(v=_,Er(_)&&(Oo(_)||xe(_))?v=Oo(p)?p:Er(p)?qn(p):[]:me(_)||pe(_)?v=pe(p)?ke(p):me(p)?p:{}:g=false),l.push(_),s.push(v),g?n[c]=At(v,_,r,l,s):(v===v?v!==p:p===p)&&(n[c]=v)}}else c=n[a],l=r?r(c,f,a,n,t):w,(s=l===w)&&(l=f),l===w&&(!o||a in n)||!s&&(l===l?l===c:c!==c)||(n[a]=l);
+}),n}function jt(n){return function(t){return null==t?w:t[n]}}function kt(n){var t=n+"";return n=Dr(n),function(r){return yt(r,n,t)}}function It(n,t){for(var r=n?t.length:0;r--;){var e=t[r];if(e!=u&&Cr(e)){var u=e;pu.call(n,e,1)}}}function Rt(n,t){return n+yu(ku()*(t-n+1))}function Ot(n,t,r,e,u){return u(n,function(n,u,o){r=e?(e=false,n):t(r,n,u,o)}),r}function Et(n,t,r){var e=-1,u=n.length;for(t=null==t?0:+t||0,0>t&&(t=-t>u?0:u+t),r=r===w||r>u?u:+r||0,0>r&&(r+=u),u=t>r?0:r-t>>>0,t>>>=0,r=Be(u);++e<u;)r[e]=n[e+t];
+return r}function Ct(n,t){var r;return Su(n,function(n,e,u){return r=t(n,e,u),!r}),!!r}function Ut(n,t){var r=n.length;for(n.sort(t);r--;)n[r]=n[r].c;return n}function Wt(t,r,e){var u=wr(),o=-1;return r=Gn(r,function(n){return u(n)}),t=wt(t,function(n){return{a:Gn(r,function(t){return t(n)}),b:++o,c:n}}),Ut(t,function(t,r){var u;n:{for(var o=-1,i=t.a,f=r.a,a=i.length,c=e.length;++o<a;)if(u=n(i[o],f[o])){if(o>=c)break n;o=e[o],u*="asc"===o||true===o?1:-1;break n}u=t.b-r.b}return u})}function $t(n,t){
+var r=0;return Su(n,function(n,e,u){r+=+t(n,e,u)||0}),r}function St(n,t){var e=-1,u=xr(),o=n.length,i=u===r,f=i&&o>=F,a=f&&gu&&lu?new Dn(void 0):null,c=[];a?(u=Mn,i=false):(f=false,a=t?[]:c);n:for(;++e<o;){var l=n[e],s=t?t(l,e,n):l;if(i&&l===l){for(var p=a.length;p--;)if(a[p]===s)continue n;t&&a.push(s),c.push(l)}else 0>u(a,s,0)&&((t||f)&&a.push(s),c.push(l))}return c}function Ft(n,t){for(var r=-1,e=t.length,u=Be(e);++r<e;)u[r]=n[t[r]];return u}function Nt(n,t,r,e){for(var u=n.length,o=e?u:-1;(e?o--:++o<u)&&t(n[o],o,n););
+return r?Et(n,e?0:o,e?o+1:u):Et(n,e?o+1:0,e?u:o)}function Tt(n,t){var r=n;r instanceof zn&&(r=r.value());for(var e=-1,u=t.length;++e<u;)var o=t[e],r=o.func.apply(o.thisArg,Jn([r],o.args));return r}function Lt(n,t,r){var e=0,u=n?n.length:e;if(typeof t=="number"&&t===t&&u<=Eu){for(;e<u;){var o=e+u>>>1,i=n[o];(r?i<=t:i<t)&&null!==i?e=o+1:u=o}return u}return zt(n,t,Fe,r)}function zt(n,t,r,e){t=r(t);for(var u=0,o=n?n.length:0,i=t!==t,f=null===t,a=t===w;u<o;){var c=yu((u+o)/2),l=r(n[c]),s=l!==w,p=l===l;
+(i?p||e:f?p&&s&&(e||null!=l):a?p&&(e||s):null==l?0:e?l<=t:l<t)?u=c+1:o=c}return xu(o,Ou)}function Bt(n,t,r){if(typeof n!="function")return Fe;if(t===w)return n;switch(r){case 1:return function(r){return n.call(t,r)};case 3:return function(r,e,u){return n.call(t,r,e,u)};case 4:return function(r,e,u,o){return n.call(t,r,e,u,o)};case 5:return function(r,e,u,o,i){return n.call(t,r,e,u,o,i)}}return function(){return n.apply(t,arguments)}}function Dt(n){var t=new ou(n.byteLength);return new hu(t).set(new hu(n)),
+t}function Mt(n,t,r){for(var e=r.length,u=-1,o=bu(n.length-e,0),i=-1,f=t.length,a=Be(f+o);++i<f;)a[i]=t[i];for(;++u<e;)a[r[u]]=n[u];for(;o--;)a[i++]=n[u++];return a}function qt(n,t,r){for(var e=-1,u=r.length,o=-1,i=bu(n.length-u,0),f=-1,a=t.length,c=Be(i+a);++o<i;)c[o]=n[o];for(i=o;++f<a;)c[i+f]=t[f];for(;++e<u;)c[i+r[e]]=n[o++];return c}function Pt(n,t){return function(r,e,u){var o=t?t():{};if(e=wr(e,u,3),Oo(r)){u=-1;for(var i=r.length;++u<i;){var f=r[u];n(o,f,e(f,u,r),r)}}else Su(r,function(t,r,u){
+n(o,t,e(t,r,u),u)});return o}}function Kt(n){return le(function(t,r){var e=-1,u=null==t?0:r.length,o=2<u?r[u-2]:w,i=2<u?r[2]:w,f=1<u?r[u-1]:w;for(typeof o=="function"?(o=Bt(o,f,5),u-=2):(o=typeof f=="function"?f:w,u-=o?1:0),i&&Ur(r[0],r[1],i)&&(o=3>u?w:o,u=1);++e<u;)(i=r[e])&&n(t,i,o);return t})}function Vt(n,t){return function(r,e){var u=r?Bu(r):0;if(!Sr(u))return n(r,e);for(var o=t?u:-1,i=Br(r);(t?o--:++o<u)&&false!==e(i[o],o,i););return r}}function Zt(n){return function(t,r,e){var u=Br(t);e=e(t);for(var o=e.length,i=n?o:-1;n?i--:++i<o;){
+var f=e[i];if(false===r(u[f],f,u))break}return t}}function Yt(n,t){function r(){return(this&&this!==Zn&&this instanceof r?e:n).apply(t,arguments)}var e=Jt(n);return r}function Gt(n){return function(t){var r=-1;t=$e(Ce(t));for(var e=t.length,u="";++r<e;)u=n(u,t[r],r);return u}}function Jt(n){return function(){var t=arguments;switch(t.length){case 0:return new n;case 1:return new n(t[0]);case 2:return new n(t[0],t[1]);case 3:return new n(t[0],t[1],t[2]);case 4:return new n(t[0],t[1],t[2],t[3]);case 5:
+return new n(t[0],t[1],t[2],t[3],t[4]);case 6:return new n(t[0],t[1],t[2],t[3],t[4],t[5]);case 7:return new n(t[0],t[1],t[2],t[3],t[4],t[5],t[6])}var r=$u(n.prototype),t=n.apply(r,t);return ge(t)?t:r}}function Xt(n){function t(r,e,u){return u&&Ur(r,e,u)&&(e=w),r=gr(r,n,w,w,w,w,w,e),r.placeholder=t.placeholder,r}return t}function Ht(n,t){return le(function(r){var e=r[0];return null==e?e:(r.push(t),n.apply(w,r))})}function Qt(n,t){return function(r,e,u){if(u&&Ur(r,e,u)&&(e=w),e=wr(e,u,3),1==e.length){
+u=r=Oo(r)?r:zr(r);for(var o=e,i=-1,f=u.length,a=t,c=a;++i<f;){var l=u[i],s=+o(l);n(s,a)&&(a=s,c=l)}if(u=c,!r.length||u!==t)return u}return ct(r,e,n,t)}}function nr(n,r){return function(e,u,o){return u=wr(u,o,3),Oo(e)?(u=t(e,u,r),-1<u?e[u]:w):st(e,u,n)}}function tr(n){return function(r,e,u){return r&&r.length?(e=wr(e,u,3),t(r,e,n)):-1}}function rr(n){return function(t,r,e){return r=wr(r,e,3),st(t,r,n,true)}}function er(n){return function(){for(var t,r=arguments.length,e=n?r:-1,u=0,o=Be(r);n?e--:++e<r;){
+var i=o[u++]=arguments[e];if(typeof i!="function")throw new Ge(L);!t&&Ln.prototype.thru&&"wrapper"==br(i)&&(t=new Ln([],true))}for(e=t?-1:r;++e<r;){var i=o[e],u=br(i),f="wrapper"==u?zu(i):w;t=f&&$r(f[0])&&f[1]==(E|k|R|C)&&!f[4].length&&1==f[9]?t[br(f[0])].apply(t,f[3]):1==i.length&&$r(i)?t[u]():t.thru(i)}return function(){var n=arguments,e=n[0];if(t&&1==n.length&&Oo(e)&&e.length>=F)return t.plant(e).value();for(var u=0,n=r?o[u].apply(this,n):e;++u<r;)n=o[u].call(this,n);return n}}}function ur(n,t){
+return function(r,e,u){return typeof e=="function"&&u===w&&Oo(r)?n(r,e):t(r,Bt(e,u,3))}}function or(n){return function(t,r,e){return(typeof r!="function"||e!==w)&&(r=Bt(r,e,3)),n(t,r,Re)}}function ir(n){return function(t,r,e){return(typeof r!="function"||e!==w)&&(r=Bt(r,e,3)),n(t,r)}}function fr(n){return function(t,r,e){var u={};return r=wr(r,e,3),_t(t,function(t,e,o){o=r(t,e,o),e=n?o:e,t=n?t:o,u[e]=t}),u}}function ar(n){return function(t,r,e){return t=u(t),(n?t:"")+pr(t,r,e)+(n?"":t)}}function cr(n){
+var t=le(function(r,e){var u=v(e,t.placeholder);return gr(r,n,w,e,u)});return t}function lr(n,t){return function(r,e,u,o){var i=3>arguments.length;return typeof e=="function"&&o===w&&Oo(r)?n(r,e,u,i):Ot(r,wr(e,o,4),u,i,t)}}function sr(n,t,r,e,u,o,i,f,a,c){function l(){for(var m=arguments.length,b=m,j=Be(m);b--;)j[b]=arguments[b];if(e&&(j=Mt(j,e,u)),o&&(j=qt(j,o,i)),_||y){var b=l.placeholder,k=v(j,b),m=m-k.length;if(m<c){var I=f?qn(f):w,m=bu(c-m,0),E=_?k:w,k=_?w:k,C=_?j:w,j=_?w:j;return t|=_?R:O,t&=~(_?O:R),
+g||(t&=~(x|A)),j=[n,t,r,C,E,j,k,I,a,m],I=sr.apply(w,j),$r(n)&&Du(I,j),I.placeholder=b,I}}if(b=p?r:this,I=h?b[n]:n,f)for(m=j.length,E=xu(f.length,m),k=qn(j);E--;)C=f[E],j[E]=Cr(C,m)?k[C]:w;return s&&a<j.length&&(j.length=a),this&&this!==Zn&&this instanceof l&&(I=d||Jt(n)),I.apply(b,j)}var s=t&E,p=t&x,h=t&A,_=t&k,g=t&j,y=t&I,d=h?w:Jt(n);return l}function pr(n,t,r){return n=n.length,t=+t,n<t&&mu(t)?(t-=n,r=null==r?" ":r+"",Ue(r,vu(t/r.length)).slice(0,t)):""}function hr(n,t,r,e){function u(){for(var t=-1,f=arguments.length,a=-1,c=e.length,l=Be(c+f);++a<c;)l[a]=e[a];
+for(;f--;)l[a++]=arguments[++t];return(this&&this!==Zn&&this instanceof u?i:n).apply(o?r:this,l)}var o=t&x,i=Jt(n);return u}function _r(n){var t=Pe[n];return function(n,r){return(r=r===w?0:+r||0)?(r=au(10,r),t(n*r)/r):t(n)}}function vr(n){return function(t,r,e,u){var o=wr(e);return null==e&&o===ut?Lt(t,r,n):zt(t,r,o(e,u,1),n)}}function gr(n,t,r,e,u,o,i,f){var a=t&A;if(!a&&typeof n!="function")throw new Ge(L);var c=e?e.length:0;if(c||(t&=~(R|O),e=u=w),c-=u?u.length:0,t&O){var l=e,s=u;e=u=w}var p=a?w:zu(n);
+return r=[n,t,r,e,u,l,s,o,i,f],p&&(e=r[1],t=p[1],f=e|t,u=t==E&&e==k||t==E&&e==C&&r[7].length<=p[8]||t==(E|C)&&e==k,(f<E||u)&&(t&x&&(r[2]=p[2],f|=e&x?0:j),(e=p[3])&&(u=r[3],r[3]=u?Mt(u,e,p[4]):qn(e),r[4]=u?v(r[3],z):qn(p[4])),(e=p[5])&&(u=r[5],r[5]=u?qt(u,e,p[6]):qn(e),r[6]=u?v(r[5],z):qn(p[6])),(e=p[7])&&(r[7]=qn(e)),t&E&&(r[8]=null==r[8]?p[8]:xu(r[8],p[8])),null==r[9]&&(r[9]=p[9]),r[0]=p[0],r[1]=f),t=r[1],f=r[9]),r[9]=null==f?a?0:n.length:bu(f-c,0)||0,(p?Lu:Du)(t==x?Yt(r[0],r[2]):t!=R&&t!=(x|R)||r[4].length?sr.apply(w,r):hr.apply(w,r),r);
+}function yr(n,t,r,e,u,o,i){var f=-1,a=n.length,c=t.length;if(a!=c&&(!u||c<=a))return false;for(;++f<a;){var l=n[f],c=t[f],s=e?e(u?c:l,u?l:c,f):w;if(s!==w){if(s)continue;return false}if(u){if(!Hn(t,function(n){return l===n||r(l,n,e,u,o,i)}))return false}else if(l!==c&&!r(l,c,e,u,o,i))return false}return true}function dr(n,t,r){switch(r){case M:case q:return+n==+t;case P:return n.name==t.name&&n.message==t.message;case V:return n!=+n?t!=+t:n==+t;case Y:case G:return n==t+""}return false}function mr(n,t,r,e,u,o,i){var f=zo(n),a=f.length,c=zo(t).length;
+if(a!=c&&!u)return false;for(c=a;c--;){var l=f[c];if(!(u?l in t:nu.call(t,l)))return false}for(var s=u;++c<a;){var l=f[c],p=n[l],h=t[l],_=e?e(u?h:p,u?p:h,l):w;if(_===w?!r(p,h,e,u,o,i):!_)return false;s||(s="constructor"==l)}return s||(r=n.constructor,e=t.constructor,!(r!=e&&"constructor"in n&&"constructor"in t)||typeof r=="function"&&r instanceof r&&typeof e=="function"&&e instanceof e)?true:false}function wr(n,t,r){var e=Nn.callback||Se,e=e===Se?ut:e;return r?e(n,t,r):e}function br(n){for(var t=n.name+"",r=Wu[t],e=r?r.length:0;e--;){
+var u=r[e],o=u.func;if(null==o||o==n)return u.name}return t}function xr(n,t,e){var u=Nn.indexOf||Vr,u=u===Vr?r:u;return n?u(n,t,e):u}function Ar(n){n=Oe(n);for(var t=n.length;t--;){var r=n[t][1];n[t][2]=r===r&&!ge(r)}return n}function jr(n,t){var r=null==n?w:n[t];return ye(r)?r:w}function kr(n){var t=n.length,r=new n.constructor(t);return t&&"string"==typeof n[0]&&nu.call(n,"index")&&(r.index=n.index,r.input=n.input),r}function Ir(n){return n=n.constructor,typeof n=="function"&&n instanceof n||(n=Ve),
+new n}function Rr(n,t,r){var e=n.constructor;switch(t){case J:return Dt(n);case M:case q:return new e(+n);case X:case H:case Q:case nn:case tn:case rn:case en:case un:case on:return t=n.buffer,new e(r?Dt(t):t,n.byteOffset,n.length);case V:case G:return new e(n);case Y:var u=new e(n.source,kn.exec(n));u.lastIndex=n.lastIndex}return u}function Or(n,t,r){return null==n||Wr(t,n)||(t=Dr(t),n=1==t.length?n:yt(n,Et(t,0,-1)),t=Zr(t)),t=null==n?n:n[t],null==t?w:t.apply(n,r)}function Er(n){return null!=n&&Sr(Bu(n));
+}function Cr(n,t){return n=typeof n=="number"||On.test(n)?+n:-1,t=null==t?Cu:t,-1<n&&0==n%1&&n<t}function Ur(n,t,r){if(!ge(r))return false;var e=typeof t;return("number"==e?Er(r)&&Cr(t,r.length):"string"==e&&t in r)?(t=r[t],n===n?n===t:t!==t):false}function Wr(n,t){var r=typeof n;return"string"==r&&dn.test(n)||"number"==r?true:Oo(n)?false:!yn.test(n)||null!=t&&n in Br(t)}function $r(n){var t=br(n),r=Nn[t];return typeof r=="function"&&t in zn.prototype?n===r?true:(t=zu(r),!!t&&n===t[0]):false}function Sr(n){return typeof n=="number"&&-1<n&&0==n%1&&n<=Cu;
+}function Fr(n,t){return n===w?t:Eo(n,t,Fr)}function Nr(n,t){n=Br(n);for(var r=-1,e=t.length,u={};++r<e;){var o=t[r];o in n&&(u[o]=n[o])}return u}function Tr(n,t){var r={};return ht(n,function(n,e,u){t(n,e,u)&&(r[e]=n)}),r}function Lr(n){for(var t=Re(n),r=t.length,e=r&&n.length,u=!!e&&Sr(e)&&(Oo(n)||pe(n)),o=-1,i=[];++o<r;){var f=t[o];(u&&Cr(f,e)||nu.call(n,f))&&i.push(f)}return i}function zr(n){return null==n?[]:Er(n)?ge(n)?n:Ve(n):Ee(n)}function Br(n){return ge(n)?n:Ve(n)}function Dr(n){if(Oo(n))return n;
+var t=[];return u(n).replace(mn,function(n,r,e,u){t.push(e?u.replace(An,"$1"):r||n)}),t}function Mr(n){return n instanceof zn?n.clone():new Ln(n.__wrapped__,n.__chain__,qn(n.__actions__))}function qr(n,t,r){return n&&n.length?((r?Ur(n,t,r):null==t)&&(t=1),Et(n,0>t?0:t)):[]}function Pr(n,t,r){var e=n?n.length:0;return e?((r?Ur(n,t,r):null==t)&&(t=1),t=e-(+t||0),Et(n,0,0>t?0:t)):[]}function Kr(n){return n?n[0]:w}function Vr(n,t,e){var u=n?n.length:0;if(!u)return-1;if(typeof e=="number")e=0>e?bu(u+e,0):e;else if(e)return e=Lt(n,t),
+e<u&&(t===t?t===n[e]:n[e]!==n[e])?e:-1;return r(n,t,e||0)}function Zr(n){var t=n?n.length:0;return t?n[t-1]:w}function Yr(n){return qr(n,1)}function Gr(n,t,e,u){if(!n||!n.length)return[];null!=t&&typeof t!="boolean"&&(u=e,e=Ur(n,t,u)?w:t,t=false);var o=wr();if((null!=e||o!==ut)&&(e=o(e,u,3)),t&&xr()===r){t=e;var i;e=-1,u=n.length;for(var o=-1,f=[];++e<u;){var a=n[e],c=t?t(a,e,n):a;e&&i===c||(i=c,f[++o]=a)}n=f}else n=St(n,e);return n}function Jr(n){if(!n||!n.length)return[];var t=-1,r=0;n=Vn(n,function(n){
+return Er(n)?(r=bu(n.length,r),true):void 0});for(var e=Be(r);++t<r;)e[t]=Gn(n,jt(t));return e}function Xr(n,t,r){return n&&n.length?(n=Jr(n),null==t?n:(t=Bt(t,r,4),Gn(n,function(n){return Xn(n,t,w,true)}))):[]}function Hr(n,t){var r=-1,e=n?n.length:0,u={};for(!e||t||Oo(n[0])||(t=[]);++r<e;){var o=n[r];t?u[o]=t[r]:o&&(u[o[0]]=o[1])}return u}function Qr(n){return n=Nn(n),n.__chain__=true,n}function ne(n,t,r){return t.call(r,n)}function te(n,t,r){var e=Oo(n)?Kn:at;return r&&Ur(n,t,r)&&(t=w),(typeof t!="function"||r!==w)&&(t=wr(t,r,3)),
+e(n,t)}function re(n,t,r){var e=Oo(n)?Vn:lt;return t=wr(t,r,3),e(n,t)}function ee(n,t,r,e){var u=n?Bu(n):0;return Sr(u)||(n=Ee(n),u=n.length),r=typeof r!="number"||e&&Ur(t,r,e)?0:0>r?bu(u+r,0):r||0,typeof n=="string"||!Oo(n)&&be(n)?r<=u&&-1<n.indexOf(t,r):!!u&&-1<xr(n,t,r)}function ue(n,t,r){var e=Oo(n)?Gn:wt;return t=wr(t,r,3),e(n,t)}function oe(n,t,r){if(r?Ur(n,t,r):null==t){n=zr(n);var e=n.length;return 0<e?n[Rt(0,e-1)]:w}r=-1,n=je(n);var e=n.length,u=e-1;for(t=xu(0>t?0:+t||0,e);++r<t;){var e=Rt(r,u),o=n[e];
+n[e]=n[r],n[r]=o}return n.length=t,n}function ie(n,t,r){var e=Oo(n)?Hn:Ct;return r&&Ur(n,t,r)&&(t=w),(typeof t!="function"||r!==w)&&(t=wr(t,r,3)),e(n,t)}function fe(n,t){var r;if(typeof t!="function"){if(typeof n!="function")throw new Ge(L);var e=n;n=t,t=e}return function(){return 0<--n&&(r=t.apply(this,arguments)),1>=n&&(t=w),r}}function ae(n,t,r){function e(t,r){r&&iu(r),a=p=h=w,t&&(_=ho(),c=n.apply(s,f),p||a||(f=s=w))}function u(){var n=t-(ho()-l);0>=n||n>t?e(h,a):p=su(u,n)}function o(){e(g,p);
+}function i(){if(f=arguments,l=ho(),s=this,h=g&&(p||!y),false===v)var r=y&&!p;else{a||y||(_=l);var e=v-(l-_),i=0>=e||e>v;i?(a&&(a=iu(a)),_=l,c=n.apply(s,f)):a||(a=su(o,e))}return i&&p?p=iu(p):p||t===v||(p=su(u,t)),r&&(i=true,c=n.apply(s,f)),!i||p||a||(f=s=w),c}var f,a,c,l,s,p,h,_=0,v=false,g=true;if(typeof n!="function")throw new Ge(L);if(t=0>t?0:+t||0,true===r)var y=true,g=false;else ge(r)&&(y=!!r.leading,v="maxWait"in r&&bu(+r.maxWait||0,t),g="trailing"in r?!!r.trailing:g);return i.cancel=function(){p&&iu(p),a&&iu(a),
+_=0,a=p=h=w},i}function ce(n,t){function r(){var e=arguments,u=t?t.apply(this,e):e[0],o=r.cache;return o.has(u)?o.get(u):(e=n.apply(this,e),r.cache=o.set(u,e),e)}if(typeof n!="function"||t&&typeof t!="function")throw new Ge(L);return r.cache=new ce.Cache,r}function le(n,t){if(typeof n!="function")throw new Ge(L);return t=bu(t===w?n.length-1:+t||0,0),function(){for(var r=arguments,e=-1,u=bu(r.length-t,0),o=Be(u);++e<u;)o[e]=r[t+e];switch(t){case 0:return n.call(this,o);case 1:return n.call(this,r[0],o);
+case 2:return n.call(this,r[0],r[1],o)}for(u=Be(t+1),e=-1;++e<t;)u[e]=r[e];return u[t]=o,n.apply(this,u)}}function se(n,t){return n>t}function pe(n){return h(n)&&Er(n)&&nu.call(n,"callee")&&!cu.call(n,"callee")}function he(n,t,r,e){return e=(r=typeof r=="function"?Bt(r,e,3):w)?r(n,t):w,e===w?dt(n,t,r):!!e}function _e(n){return h(n)&&typeof n.message=="string"&&ru.call(n)==P}function ve(n){return ge(n)&&ru.call(n)==K}function ge(n){var t=typeof n;return!!n&&("object"==t||"function"==t)}function ye(n){
+return null==n?false:ve(n)?uu.test(Qe.call(n)):h(n)&&Rn.test(n)}function de(n){return typeof n=="number"||h(n)&&ru.call(n)==V}function me(n){var t;if(!h(n)||ru.call(n)!=Z||pe(n)||!(nu.call(n,"constructor")||(t=n.constructor,typeof t!="function"||t instanceof t)))return false;var r;return ht(n,function(n,t){r=t}),r===w||nu.call(n,r)}function we(n){return ge(n)&&ru.call(n)==Y}function be(n){return typeof n=="string"||h(n)&&ru.call(n)==G}function xe(n){return h(n)&&Sr(n.length)&&!!Sn[ru.call(n)]}function Ae(n,t){
+return n<t}function je(n){var t=n?Bu(n):0;return Sr(t)?t?qn(n):[]:Ee(n)}function ke(n){return et(n,Re(n))}function Ie(n){return gt(n,Re(n))}function Re(n){if(null==n)return[];ge(n)||(n=Ve(n));for(var t=n.length,t=t&&Sr(t)&&(Oo(n)||pe(n))&&t||0,r=n.constructor,e=-1,r=typeof r=="function"&&r.prototype===n,u=Be(t),o=0<t;++e<t;)u[e]=e+"";for(var i in n)o&&Cr(i,t)||"constructor"==i&&(r||!nu.call(n,i))||u.push(i);return u}function Oe(n){n=Br(n);for(var t=-1,r=zo(n),e=r.length,u=Be(e);++t<e;){var o=r[t];
+u[t]=[o,n[o]]}return u}function Ee(n){return Ft(n,zo(n))}function Ce(n){return(n=u(n))&&n.replace(En,a).replace(xn,"")}function Ue(n,t){var r="";if(n=u(n),t=+t,1>t||!n||!mu(t))return r;do t%2&&(r+=n),t=yu(t/2),n+=n;while(t);return r}function We(n,t,r){var e=n;return(n=u(n))?(r?Ur(e,t,r):null==t)?n.slice(g(n),y(n)+1):(t+="",n.slice(o(n,t),i(n,t)+1)):n}function $e(n,t,r){return r&&Ur(n,t,r)&&(t=w),n=u(n),n.match(t||Wn)||[]}function Se(n,t,r){return r&&Ur(n,t,r)&&(t=w),h(n)?Ne(n):ut(n,t)}function Fe(n){
+return n}function Ne(n){return bt(ot(n,true))}function Te(n,t,r){if(null==r){var e=ge(t),u=e?zo(t):w;((u=u&&u.length?gt(t,u):w)?u.length:e)||(u=false,r=t,t=n,n=this)}u||(u=gt(t,zo(t)));var o=true,e=-1,i=ve(n),f=u.length;false===r?o=false:ge(r)&&"chain"in r&&(o=r.chain);for(;++e<f;){r=u[e];var a=t[r];n[r]=a,i&&(n.prototype[r]=function(t){return function(){var r=this.__chain__;if(o||r){var e=n(this.__wrapped__);return(e.__actions__=qn(this.__actions__)).push({func:t,args:arguments,thisArg:n}),e.__chain__=r,e}return t.apply(n,Jn([this.value()],arguments));
+}}(a))}return n}function Le(){}function ze(n){return Wr(n)?jt(n):kt(n)}_=_?Yn.defaults(Zn.Object(),_,Yn.pick(Zn,$n)):Zn;var Be=_.Array,De=_.Date,Me=_.Error,qe=_.Function,Pe=_.Math,Ke=_.Number,Ve=_.Object,Ze=_.RegExp,Ye=_.String,Ge=_.TypeError,Je=Be.prototype,Xe=Ve.prototype,He=Ye.prototype,Qe=qe.prototype.toString,nu=Xe.hasOwnProperty,tu=0,ru=Xe.toString,eu=Zn._,uu=Ze("^"+Qe.call(nu).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),ou=_.ArrayBuffer,iu=_.clearTimeout,fu=_.parseFloat,au=Pe.pow,cu=Xe.propertyIsEnumerable,lu=jr(_,"Set"),su=_.setTimeout,pu=Je.splice,hu=_.Uint8Array,_u=jr(_,"WeakMap"),vu=Pe.ceil,gu=jr(Ve,"create"),yu=Pe.floor,du=jr(Be,"isArray"),mu=_.isFinite,wu=jr(Ve,"keys"),bu=Pe.max,xu=Pe.min,Au=jr(De,"now"),ju=_.parseInt,ku=Pe.random,Iu=Ke.NEGATIVE_INFINITY,Ru=Ke.POSITIVE_INFINITY,Ou=4294967294,Eu=2147483647,Cu=9007199254740991,Uu=_u&&new _u,Wu={};
+Nn.support={},Nn.templateSettings={escape:_n,evaluate:vn,interpolate:gn,variable:"",imports:{_:Nn}};var $u=function(){function n(){}return function(t){if(ge(t)){n.prototype=t;var r=new n;n.prototype=w}return r||{}}}(),Su=Vt(_t),Fu=Vt(vt,true),Nu=Zt(),Tu=Zt(true),Lu=Uu?function(n,t){return Uu.set(n,t),n}:Fe,zu=Uu?function(n){return Uu.get(n)}:Le,Bu=jt("length"),Du=function(){var n=0,t=0;return function(r,e){var u=ho(),o=S-(u-t);if(t=u,0<o){if(++n>=$)return r}else n=0;return Lu(r,e)}}(),Mu=le(function(n,t){
+return h(n)&&Er(n)?ft(n,pt(t,false,true)):[]}),qu=tr(),Pu=tr(true),Ku=le(function(n){for(var t=n.length,e=t,u=Be(l),o=xr(),i=o===r,f=[];e--;){var a=n[e]=Er(a=n[e])?a:[];u[e]=i&&120<=a.length&&gu&&lu?new Dn(e&&a):null}var i=n[0],c=-1,l=i?i.length:0,s=u[0];n:for(;++c<l;)if(a=i[c],0>(s?Mn(s,a):o(f,a,0))){for(e=t;--e;){var p=u[e];if(0>(p?Mn(p,a):o(n[e],a,0)))continue n}s&&s.push(a),f.push(a)}return f}),Vu=le(function(t,r){r=pt(r);var e=rt(t,r);return It(t,r.sort(n)),e}),Zu=vr(),Yu=vr(true),Gu=le(function(n){return St(pt(n,false,true));
+}),Ju=le(function(n,t){return Er(n)?ft(n,t):[]}),Xu=le(Jr),Hu=le(function(n){var t=n.length,r=2<t?n[t-2]:w,e=1<t?n[t-1]:w;return 2<t&&typeof r=="function"?t-=2:(r=1<t&&typeof e=="function"?(--t,e):w,e=w),n.length=t,Xr(n,r,e)}),Qu=le(function(n){return n=pt(n),this.thru(function(t){t=Oo(t)?t:[Br(t)];for(var r=n,e=-1,u=t.length,o=-1,i=r.length,f=Be(u+i);++e<u;)f[e]=t[e];for(;++o<i;)f[e++]=r[o];return f})}),no=le(function(n,t){return rt(n,pt(t))}),to=Pt(function(n,t,r){nu.call(n,r)?++n[r]:n[r]=1}),ro=nr(Su),eo=nr(Fu,true),uo=ur(Pn,Su),oo=ur(function(n,t){
+for(var r=n.length;r--&&false!==t(n[r],r,n););return n},Fu),io=Pt(function(n,t,r){nu.call(n,r)?n[r].push(t):n[r]=[t]}),fo=Pt(function(n,t,r){n[r]=t}),ao=le(function(n,t,r){var e=-1,u=typeof t=="function",o=Wr(t),i=Er(n)?Be(n.length):[];return Su(n,function(n){var f=u?t:o&&null!=n?n[t]:w;i[++e]=f?f.apply(n,r):Or(n,t,r)}),i}),co=Pt(function(n,t,r){n[r?0:1].push(t)},function(){return[[],[]]}),lo=lr(Xn,Su),so=lr(function(n,t,r,e){var u=n.length;for(e&&u&&(r=n[--u]);u--;)r=t(r,n[u],u,n);return r},Fu),po=le(function(n,t){
+if(null==n)return[];var r=t[2];return r&&Ur(t[0],t[1],r)&&(t.length=1),Wt(n,pt(t),[])}),ho=Au||function(){return(new De).getTime()},_o=le(function(n,t,r){var e=x;if(r.length)var u=v(r,_o.placeholder),e=e|R;return gr(n,e,t,r,u)}),vo=le(function(n,t){t=t.length?pt(t):Ie(n);for(var r=-1,e=t.length;++r<e;){var u=t[r];n[u]=gr(n[u],x,n)}return n}),go=le(function(n,t,r){var e=x|A;if(r.length)var u=v(r,go.placeholder),e=e|R;return gr(t,e,n,r,u)}),yo=Xt(k),mo=Xt(I),wo=le(function(n,t){return it(n,1,t)}),bo=le(function(n,t,r){
+return it(n,t,r)}),xo=er(),Ao=er(true),jo=le(function(n,t){if(t=pt(t),typeof n!="function"||!Kn(t,e))throw new Ge(L);var r=t.length;return le(function(e){for(var u=xu(e.length,r);u--;)e[u]=t[u](e[u]);return n.apply(this,e)})}),ko=cr(R),Io=cr(O),Ro=le(function(n,t){return gr(n,C,w,w,w,pt(t))}),Oo=du||function(n){return h(n)&&Sr(n.length)&&ru.call(n)==D},Eo=Kt(At),Co=Kt(function(n,t,r){return r?nt(n,t,r):tt(n,t)}),Uo=Ht(Co,function(n,t){return n===w?t:n}),Wo=Ht(Eo,Fr),$o=rr(_t),So=rr(vt),Fo=or(Nu),No=or(Tu),To=ir(_t),Lo=ir(vt),zo=wu?function(n){
+var t=null==n?w:n.constructor;return typeof t=="function"&&t.prototype===n||typeof n!="function"&&Er(n)?Lr(n):ge(n)?wu(n):[]}:Lr,Bo=fr(true),Do=fr(),Mo=le(function(n,t){if(null==n)return{};if("function"!=typeof t[0])return t=Gn(pt(t),Ye),Nr(n,ft(Re(n),t));var r=Bt(t[0],t[1],3);return Tr(n,function(n,t,e){return!r(n,t,e)})}),qo=le(function(n,t){return null==n?{}:"function"==typeof t[0]?Tr(n,Bt(t[0],t[1],3)):Nr(n,pt(t))}),Po=Gt(function(n,t,r){return t=t.toLowerCase(),n+(r?t.charAt(0).toUpperCase()+t.slice(1):t);
+}),Ko=Gt(function(n,t,r){return n+(r?"-":"")+t.toLowerCase()}),Vo=ar(),Zo=ar(true),Yo=Gt(function(n,t,r){return n+(r?"_":"")+t.toLowerCase()}),Go=Gt(function(n,t,r){return n+(r?" ":"")+(t.charAt(0).toUpperCase()+t.slice(1))}),Jo=le(function(n,t){try{return n.apply(w,t)}catch(r){return _e(r)?r:new Me(r)}}),Xo=le(function(n,t){return function(r){return Or(r,n,t)}}),Ho=le(function(n,t){return function(r){return Or(n,r,t)}}),Qo=_r("ceil"),ni=_r("floor"),ti=Qt(se,Iu),ri=Qt(Ae,Ru),ei=_r("round");return Nn.prototype=Tn.prototype,
+Ln.prototype=$u(Tn.prototype),Ln.prototype.constructor=Ln,zn.prototype=$u(Tn.prototype),zn.prototype.constructor=zn,Bn.prototype["delete"]=function(n){return this.has(n)&&delete this.__data__[n]},Bn.prototype.get=function(n){return"__proto__"==n?w:this.__data__[n]},Bn.prototype.has=function(n){return"__proto__"!=n&&nu.call(this.__data__,n)},Bn.prototype.set=function(n,t){return"__proto__"!=n&&(this.__data__[n]=t),this},Dn.prototype.push=function(n){var t=this.data;typeof n=="string"||ge(n)?t.set.add(n):t.hash[n]=true;
+},ce.Cache=Bn,Nn.after=function(n,t){if(typeof t!="function"){if(typeof n!="function")throw new Ge(L);var r=n;n=t,t=r}return n=mu(n=+n)?n:0,function(){return 1>--n?t.apply(this,arguments):void 0}},Nn.ary=function(n,t,r){return r&&Ur(n,t,r)&&(t=w),t=n&&null==t?n.length:bu(+t||0,0),gr(n,E,w,w,w,w,t)},Nn.assign=Co,Nn.at=no,Nn.before=fe,Nn.bind=_o,Nn.bindAll=vo,Nn.bindKey=go,Nn.callback=Se,Nn.chain=Qr,Nn.chunk=function(n,t,r){t=(r?Ur(n,t,r):null==t)?1:bu(yu(t)||1,1),r=0;for(var e=n?n.length:0,u=-1,o=Be(vu(e/t));r<e;)o[++u]=Et(n,r,r+=t);
+return o},Nn.compact=function(n){for(var t=-1,r=n?n.length:0,e=-1,u=[];++t<r;){var o=n[t];o&&(u[++e]=o)}return u},Nn.constant=function(n){return function(){return n}},Nn.countBy=to,Nn.create=function(n,t,r){var e=$u(n);return r&&Ur(n,t,r)&&(t=w),t?tt(e,t):e},Nn.curry=yo,Nn.curryRight=mo,Nn.debounce=ae,Nn.defaults=Uo,Nn.defaultsDeep=Wo,Nn.defer=wo,Nn.delay=bo,Nn.difference=Mu,Nn.drop=qr,Nn.dropRight=Pr,Nn.dropRightWhile=function(n,t,r){return n&&n.length?Nt(n,wr(t,r,3),true,true):[]},Nn.dropWhile=function(n,t,r){
+return n&&n.length?Nt(n,wr(t,r,3),true):[]},Nn.fill=function(n,t,r,e){var u=n?n.length:0;if(!u)return[];for(r&&typeof r!="number"&&Ur(n,t,r)&&(r=0,e=u),u=n.length,r=null==r?0:+r||0,0>r&&(r=-r>u?0:u+r),e=e===w||e>u?u:+e||0,0>e&&(e+=u),u=r>e?0:e>>>0,r>>>=0;r<u;)n[r++]=t;return n},Nn.filter=re,Nn.flatten=function(n,t,r){var e=n?n.length:0;return r&&Ur(n,t,r)&&(t=false),e?pt(n,t):[]},Nn.flattenDeep=function(n){return n&&n.length?pt(n,true):[]},Nn.flow=xo,Nn.flowRight=Ao,Nn.forEach=uo,Nn.forEachRight=oo,Nn.forIn=Fo,
+Nn.forInRight=No,Nn.forOwn=To,Nn.forOwnRight=Lo,Nn.functions=Ie,Nn.groupBy=io,Nn.indexBy=fo,Nn.initial=function(n){return Pr(n,1)},Nn.intersection=Ku,Nn.invert=function(n,t,r){r&&Ur(n,t,r)&&(t=w),r=-1;for(var e=zo(n),u=e.length,o={};++r<u;){var i=e[r],f=n[i];t?nu.call(o,f)?o[f].push(i):o[f]=[i]:o[f]=i}return o},Nn.invoke=ao,Nn.keys=zo,Nn.keysIn=Re,Nn.map=ue,Nn.mapKeys=Bo,Nn.mapValues=Do,Nn.matches=Ne,Nn.matchesProperty=function(n,t){return xt(n,ot(t,true))},Nn.memoize=ce,Nn.merge=Eo,Nn.method=Xo,Nn.methodOf=Ho,
+Nn.mixin=Te,Nn.modArgs=jo,Nn.negate=function(n){if(typeof n!="function")throw new Ge(L);return function(){return!n.apply(this,arguments)}},Nn.omit=Mo,Nn.once=function(n){return fe(2,n)},Nn.pairs=Oe,Nn.partial=ko,Nn.partialRight=Io,Nn.partition=co,Nn.pick=qo,Nn.pluck=function(n,t){return ue(n,ze(t))},Nn.property=ze,Nn.propertyOf=function(n){return function(t){return yt(n,Dr(t),t+"")}},Nn.pull=function(){var n=arguments,t=n[0];if(!t||!t.length)return t;for(var r=0,e=xr(),u=n.length;++r<u;)for(var o=0,i=n[r];-1<(o=e(t,i,o));)pu.call(t,o,1);
+return t},Nn.pullAt=Vu,Nn.range=function(n,t,r){r&&Ur(n,t,r)&&(t=r=w),n=+n||0,r=null==r?1:+r||0,null==t?(t=n,n=0):t=+t||0;var e=-1;t=bu(vu((t-n)/(r||1)),0);for(var u=Be(t);++e<t;)u[e]=n,n+=r;return u},Nn.rearg=Ro,Nn.reject=function(n,t,r){var e=Oo(n)?Vn:lt;return t=wr(t,r,3),e(n,function(n,r,e){return!t(n,r,e)})},Nn.remove=function(n,t,r){var e=[];if(!n||!n.length)return e;var u=-1,o=[],i=n.length;for(t=wr(t,r,3);++u<i;)r=n[u],t(r,u,n)&&(e.push(r),o.push(u));return It(n,o),e},Nn.rest=Yr,Nn.restParam=le,
+Nn.set=function(n,t,r){if(null==n)return n;var e=t+"";t=null!=n[e]||Wr(t,n)?[e]:Dr(t);for(var e=-1,u=t.length,o=u-1,i=n;null!=i&&++e<u;){var f=t[e];ge(i)&&(e==o?i[f]=r:null==i[f]&&(i[f]=Cr(t[e+1])?[]:{})),i=i[f]}return n},Nn.shuffle=function(n){return oe(n,Ru)},Nn.slice=function(n,t,r){var e=n?n.length:0;return e?(r&&typeof r!="number"&&Ur(n,t,r)&&(t=0,r=e),Et(n,t,r)):[]},Nn.sortBy=function(n,t,r){if(null==n)return[];r&&Ur(n,t,r)&&(t=w);var e=-1;return t=wr(t,r,3),n=wt(n,function(n,r,u){return{a:t(n,r,u),
+b:++e,c:n}}),Ut(n,f)},Nn.sortByAll=po,Nn.sortByOrder=function(n,t,r,e){return null==n?[]:(e&&Ur(t,r,e)&&(r=w),Oo(t)||(t=null==t?[]:[t]),Oo(r)||(r=null==r?[]:[r]),Wt(n,t,r))},Nn.spread=function(n){if(typeof n!="function")throw new Ge(L);return function(t){return n.apply(this,t)}},Nn.take=function(n,t,r){return n&&n.length?((r?Ur(n,t,r):null==t)&&(t=1),Et(n,0,0>t?0:t)):[]},Nn.takeRight=function(n,t,r){var e=n?n.length:0;return e?((r?Ur(n,t,r):null==t)&&(t=1),t=e-(+t||0),Et(n,0>t?0:t)):[]},Nn.takeRightWhile=function(n,t,r){
+return n&&n.length?Nt(n,wr(t,r,3),false,true):[]},Nn.takeWhile=function(n,t,r){return n&&n.length?Nt(n,wr(t,r,3)):[]},Nn.tap=function(n,t,r){return t.call(r,n),n},Nn.throttle=function(n,t,r){var e=true,u=true;if(typeof n!="function")throw new Ge(L);return false===r?e=false:ge(r)&&(e="leading"in r?!!r.leading:e,u="trailing"in r?!!r.trailing:u),ae(n,t,{leading:e,maxWait:+t,trailing:u})},Nn.thru=ne,Nn.times=function(n,t,r){if(n=yu(n),1>n||!mu(n))return[];var e=-1,u=Be(xu(n,4294967295));for(t=Bt(t,r,1);++e<n;)4294967295>e?u[e]=t(e):t(e);
+return u},Nn.toArray=je,Nn.toPlainObject=ke,Nn.transform=function(n,t,r,e){var u=Oo(n)||xe(n);return t=wr(t,e,4),null==r&&(u||ge(n)?(e=n.constructor,r=u?Oo(n)?new e:[]:$u(ve(e)?e.prototype:w)):r={}),(u?Pn:_t)(n,function(n,e,u){return t(r,n,e,u)}),r},Nn.union=Gu,Nn.uniq=Gr,Nn.unzip=Jr,Nn.unzipWith=Xr,Nn.values=Ee,Nn.valuesIn=function(n){return Ft(n,Re(n))},Nn.where=function(n,t){return re(n,bt(t))},Nn.without=Ju,Nn.wrap=function(n,t){return t=null==t?Fe:t,gr(t,R,w,[n],[])},Nn.xor=function(){for(var n=-1,t=arguments.length;++n<t;){
+var r=arguments[n];if(Er(r))var e=e?Jn(ft(e,r),ft(r,e)):r}return e?St(e):[]},Nn.zip=Xu,Nn.zipObject=Hr,Nn.zipWith=Hu,Nn.backflow=Ao,Nn.collect=ue,Nn.compose=Ao,Nn.each=uo,Nn.eachRight=oo,Nn.extend=Co,Nn.iteratee=Se,Nn.methods=Ie,Nn.object=Hr,Nn.select=re,Nn.tail=Yr,Nn.unique=Gr,Te(Nn,Nn),Nn.add=function(n,t){return(+n||0)+(+t||0)},Nn.attempt=Jo,Nn.camelCase=Po,Nn.capitalize=function(n){return(n=u(n))&&n.charAt(0).toUpperCase()+n.slice(1)},Nn.ceil=Qo,Nn.clone=function(n,t,r,e){return t&&typeof t!="boolean"&&Ur(n,t,r)?t=false:typeof t=="function"&&(e=r,
+r=t,t=false),typeof r=="function"?ot(n,t,Bt(r,e,3)):ot(n,t)},Nn.cloneDeep=function(n,t,r){return typeof t=="function"?ot(n,true,Bt(t,r,3)):ot(n,true)},Nn.deburr=Ce,Nn.endsWith=function(n,t,r){n=u(n),t+="";var e=n.length;return r=r===w?e:xu(0>r?0:+r||0,e),r-=t.length,0<=r&&n.indexOf(t,r)==r},Nn.escape=function(n){return(n=u(n))&&hn.test(n)?n.replace(sn,c):n},Nn.escapeRegExp=function(n){return(n=u(n))&&bn.test(n)?n.replace(wn,l):n||"(?:)"},Nn.every=te,Nn.find=ro,Nn.findIndex=qu,Nn.findKey=$o,Nn.findLast=eo,
+Nn.findLastIndex=Pu,Nn.findLastKey=So,Nn.findWhere=function(n,t){return ro(n,bt(t))},Nn.first=Kr,Nn.floor=ni,Nn.get=function(n,t,r){return n=null==n?w:yt(n,Dr(t),t+""),n===w?r:n},Nn.gt=se,Nn.gte=function(n,t){return n>=t},Nn.has=function(n,t){if(null==n)return false;var r=nu.call(n,t);if(!r&&!Wr(t)){if(t=Dr(t),n=1==t.length?n:yt(n,Et(t,0,-1)),null==n)return false;t=Zr(t),r=nu.call(n,t)}return r||Sr(n.length)&&Cr(t,n.length)&&(Oo(n)||pe(n))},Nn.identity=Fe,Nn.includes=ee,Nn.indexOf=Vr,Nn.inRange=function(n,t,r){
+return t=+t||0,r===w?(r=t,t=0):r=+r||0,n>=xu(t,r)&&n<bu(t,r)},Nn.isArguments=pe,Nn.isArray=Oo,Nn.isBoolean=function(n){return true===n||false===n||h(n)&&ru.call(n)==M},Nn.isDate=function(n){return h(n)&&ru.call(n)==q},Nn.isElement=function(n){return!!n&&1===n.nodeType&&h(n)&&!me(n)},Nn.isEmpty=function(n){return null==n?true:Er(n)&&(Oo(n)||be(n)||pe(n)||h(n)&&ve(n.splice))?!n.length:!zo(n).length},Nn.isEqual=he,Nn.isError=_e,Nn.isFinite=function(n){return typeof n=="number"&&mu(n)},Nn.isFunction=ve,Nn.isMatch=function(n,t,r,e){
+return r=typeof r=="function"?Bt(r,e,3):w,mt(n,Ar(t),r)},Nn.isNaN=function(n){return de(n)&&n!=+n},Nn.isNative=ye,Nn.isNull=function(n){return null===n},Nn.isNumber=de,Nn.isObject=ge,Nn.isPlainObject=me,Nn.isRegExp=we,Nn.isString=be,Nn.isTypedArray=xe,Nn.isUndefined=function(n){return n===w},Nn.kebabCase=Ko,Nn.last=Zr,Nn.lastIndexOf=function(n,t,r){var e=n?n.length:0;if(!e)return-1;var u=e;if(typeof r=="number")u=(0>r?bu(e+r,0):xu(r||0,e-1))+1;else if(r)return u=Lt(n,t,true)-1,n=n[u],(t===t?t===n:n!==n)?u:-1;
+if(t!==t)return p(n,u,true);for(;u--;)if(n[u]===t)return u;return-1},Nn.lt=Ae,Nn.lte=function(n,t){return n<=t},Nn.max=ti,Nn.min=ri,Nn.noConflict=function(){return Zn._=eu,this},Nn.noop=Le,Nn.now=ho,Nn.pad=function(n,t,r){n=u(n),t=+t;var e=n.length;return e<t&&mu(t)?(e=(t-e)/2,t=yu(e),e=vu(e),r=pr("",e,r),r.slice(0,t)+n+r):n},Nn.padLeft=Vo,Nn.padRight=Zo,Nn.parseInt=function(n,t,r){return(r?Ur(n,t,r):null==t)?t=0:t&&(t=+t),n=We(n),ju(n,t||(In.test(n)?16:10))},Nn.random=function(n,t,r){r&&Ur(n,t,r)&&(t=r=w);
+var e=null==n,u=null==t;return null==r&&(u&&typeof n=="boolean"?(r=n,n=1):typeof t=="boolean"&&(r=t,u=true)),e&&u&&(t=1,u=false),n=+n||0,u?(t=n,n=0):t=+t||0,r||n%1||t%1?(r=ku(),xu(n+r*(t-n+fu("1e-"+((r+"").length-1))),t)):Rt(n,t)},Nn.reduce=lo,Nn.reduceRight=so,Nn.repeat=Ue,Nn.result=function(n,t,r){var e=null==n?w:n[t];return e===w&&(null==n||Wr(t,n)||(t=Dr(t),n=1==t.length?n:yt(n,Et(t,0,-1)),e=null==n?w:n[Zr(t)]),e=e===w?r:e),ve(e)?e.call(n):e},Nn.round=ei,Nn.runInContext=m,Nn.size=function(n){var t=n?Bu(n):0;
+return Sr(t)?t:zo(n).length},Nn.snakeCase=Yo,Nn.some=ie,Nn.sortedIndex=Zu,Nn.sortedLastIndex=Yu,Nn.startCase=Go,Nn.startsWith=function(n,t,r){return n=u(n),r=null==r?0:xu(0>r?0:+r||0,n.length),n.lastIndexOf(t,r)==r},Nn.sum=function(n,t,r){if(r&&Ur(n,t,r)&&(t=w),t=wr(t,r,3),1==t.length){n=Oo(n)?n:zr(n),r=n.length;for(var e=0;r--;)e+=+t(n[r])||0;n=e}else n=$t(n,t);return n},Nn.template=function(n,t,r){var e=Nn.templateSettings;r&&Ur(n,t,r)&&(t=r=w),n=u(n),t=nt(tt({},r||t),e,Qn),r=nt(tt({},t.imports),e.imports,Qn);
+var o,i,f=zo(r),a=Ft(r,f),c=0;r=t.interpolate||Cn;var l="__p+='";r=Ze((t.escape||Cn).source+"|"+r.source+"|"+(r===gn?jn:Cn).source+"|"+(t.evaluate||Cn).source+"|$","g");var p="sourceURL"in t?"//# sourceURL="+t.sourceURL+"\n":"";if(n.replace(r,function(t,r,e,u,f,a){return e||(e=u),l+=n.slice(c,a).replace(Un,s),r&&(o=true,l+="'+__e("+r+")+'"),f&&(i=true,l+="';"+f+";\n__p+='"),e&&(l+="'+((__t=("+e+"))==null?'':__t)+'"),c=a+t.length,t}),l+="';",(t=t.variable)||(l="with(obj){"+l+"}"),l=(i?l.replace(fn,""):l).replace(an,"$1").replace(cn,"$1;"),
+l="function("+(t||"obj")+"){"+(t?"":"obj||(obj={});")+"var __t,__p=''"+(o?",__e=_.escape":"")+(i?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+l+"return __p}",t=Jo(function(){return qe(f,p+"return "+l).apply(w,a)}),t.source=l,_e(t))throw t;return t},Nn.trim=We,Nn.trimLeft=function(n,t,r){var e=n;return(n=u(n))?n.slice((r?Ur(e,t,r):null==t)?g(n):o(n,t+"")):n},Nn.trimRight=function(n,t,r){var e=n;return(n=u(n))?(r?Ur(e,t,r):null==t)?n.slice(0,y(n)+1):n.slice(0,i(n,t+"")+1):n;
+},Nn.trunc=function(n,t,r){r&&Ur(n,t,r)&&(t=w);var e=U;if(r=W,null!=t)if(ge(t)){var o="separator"in t?t.separator:o,e="length"in t?+t.length||0:e;r="omission"in t?u(t.omission):r}else e=+t||0;if(n=u(n),e>=n.length)return n;if(e-=r.length,1>e)return r;if(t=n.slice(0,e),null==o)return t+r;if(we(o)){if(n.slice(e).search(o)){var i,f=n.slice(0,e);for(o.global||(o=Ze(o.source,(kn.exec(o)||"")+"g")),o.lastIndex=0;n=o.exec(f);)i=n.index;t=t.slice(0,null==i?e:i)}}else n.indexOf(o,e)!=e&&(o=t.lastIndexOf(o),
+-1<o&&(t=t.slice(0,o)));return t+r},Nn.unescape=function(n){return(n=u(n))&&pn.test(n)?n.replace(ln,d):n},Nn.uniqueId=function(n){var t=++tu;return u(n)+t},Nn.words=$e,Nn.all=te,Nn.any=ie,Nn.contains=ee,Nn.eq=he,Nn.detect=ro,Nn.foldl=lo,Nn.foldr=so,Nn.head=Kr,Nn.include=ee,Nn.inject=lo,Te(Nn,function(){var n={};return _t(Nn,function(t,r){Nn.prototype[r]||(n[r]=t)}),n}(),false),Nn.sample=oe,Nn.prototype.sample=function(n){return this.__chain__||null!=n?this.thru(function(t){return oe(t,n)}):oe(this.value());
+},Nn.VERSION=b,Pn("bind bindKey curry curryRight partial partialRight".split(" "),function(n){Nn[n].placeholder=Nn}),Pn(["drop","take"],function(n,t){zn.prototype[n]=function(r){var e=this.__filtered__;if(e&&!t)return new zn(this);r=null==r?1:bu(yu(r)||0,0);var u=this.clone();return e?u.__takeCount__=xu(u.__takeCount__,r):u.__views__.push({size:r,type:n+(0>u.__dir__?"Right":"")}),u},zn.prototype[n+"Right"]=function(t){return this.reverse()[n](t).reverse()}}),Pn(["filter","map","takeWhile"],function(n,t){
+var r=t+1,e=r!=T;zn.prototype[n]=function(n,t){var u=this.clone();return u.__iteratees__.push({iteratee:wr(n,t,1),type:r}),u.__filtered__=u.__filtered__||e,u}}),Pn(["first","last"],function(n,t){var r="take"+(t?"Right":"");zn.prototype[n]=function(){return this[r](1).value()[0]}}),Pn(["initial","rest"],function(n,t){var r="drop"+(t?"":"Right");zn.prototype[n]=function(){return this.__filtered__?new zn(this):this[r](1)}}),Pn(["pluck","where"],function(n,t){var r=t?"filter":"map",e=t?bt:ze;zn.prototype[n]=function(n){
+return this[r](e(n))}}),zn.prototype.compact=function(){return this.filter(Fe)},zn.prototype.reject=function(n,t){return n=wr(n,t,1),this.filter(function(t){return!n(t)})},zn.prototype.slice=function(n,t){n=null==n?0:+n||0;var r=this;return r.__filtered__&&(0<n||0>t)?new zn(r):(0>n?r=r.takeRight(-n):n&&(r=r.drop(n)),t!==w&&(t=+t||0,r=0>t?r.dropRight(-t):r.take(t-n)),r)},zn.prototype.takeRightWhile=function(n,t){return this.reverse().takeWhile(n,t).reverse()},zn.prototype.toArray=function(){return this.take(Ru);
+},_t(zn.prototype,function(n,t){var r=/^(?:filter|map|reject)|While$/.test(t),e=/^(?:first|last)$/.test(t),u=Nn[e?"take"+("last"==t?"Right":""):t];u&&(Nn.prototype[t]=function(){function t(n){return e&&i?u(n,1)[0]:u.apply(w,Jn([n],o))}var o=e?[1]:arguments,i=this.__chain__,f=this.__wrapped__,a=!!this.__actions__.length,c=f instanceof zn,l=o[0],s=c||Oo(f);return s&&r&&typeof l=="function"&&1!=l.length&&(c=s=false),l={func:ne,args:[t],thisArg:w},a=c&&!a,e&&!i?a?(f=f.clone(),f.__actions__.push(l),n.call(f)):u.call(w,this.value())[0]:!e&&s?(f=a?f:new zn(this),
+f=n.apply(f,o),f.__actions__.push(l),new Ln(f,i)):this.thru(t)})}),Pn("join pop push replace shift sort splice split unshift".split(" "),function(n){var t=(/^(?:replace|split)$/.test(n)?He:Je)[n],r=/^(?:push|sort|unshift)$/.test(n)?"tap":"thru",e=/^(?:join|pop|replace|shift)$/.test(n);Nn.prototype[n]=function(){var n=arguments;return e&&!this.__chain__?t.apply(this.value(),n):this[r](function(r){return t.apply(r,n)})}}),_t(zn.prototype,function(n,t){var r=Nn[t];if(r){var e=r.name+"";(Wu[e]||(Wu[e]=[])).push({
+name:t,func:r})}}),Wu[sr(w,A).name]=[{name:"wrapper",func:w}],zn.prototype.clone=function(){var n=new zn(this.__wrapped__);return n.__actions__=qn(this.__actions__),n.__dir__=this.__dir__,n.__filtered__=this.__filtered__,n.__iteratees__=qn(this.__iteratees__),n.__takeCount__=this.__takeCount__,n.__views__=qn(this.__views__),n},zn.prototype.reverse=function(){if(this.__filtered__){var n=new zn(this);n.__dir__=-1,n.__filtered__=true}else n=this.clone(),n.__dir__*=-1;return n},zn.prototype.value=function(){
+var n,t=this.__wrapped__.value(),r=this.__dir__,e=Oo(t),u=0>r,o=e?t.length:0;n=o;for(var i=this.__views__,f=0,a=-1,c=i.length;++a<c;){var l=i[a],s=l.size;switch(l.type){case"drop":f+=s;break;case"dropRight":n-=s;break;case"take":n=xu(n,f+s);break;case"takeRight":f=bu(f,n-s)}}if(n={start:f,end:n},i=n.start,f=n.end,n=f-i,u=u?f:i-1,i=this.__iteratees__,f=i.length,a=0,c=xu(n,this.__takeCount__),!e||o<F||o==n&&c==n)return Tt(t,this.__actions__);e=[];n:for(;n--&&a<c;){for(u+=r,o=-1,l=t[u];++o<f;){var p=i[o],s=p.type,p=p.iteratee(l);
+if(s==T)l=p;else if(!p){if(s==N)continue n;break n}}e[a++]=l}return e},Nn.prototype.chain=function(){return Qr(this)},Nn.prototype.commit=function(){return new Ln(this.value(),this.__chain__)},Nn.prototype.concat=Qu,Nn.prototype.plant=function(n){for(var t,r=this;r instanceof Tn;){var e=Mr(r);t?u.__wrapped__=e:t=e;var u=e,r=r.__wrapped__}return u.__wrapped__=n,t},Nn.prototype.reverse=function(){function n(n){return n.reverse()}var t=this.__wrapped__;return t instanceof zn?(this.__actions__.length&&(t=new zn(this)),
+t=t.reverse(),t.__actions__.push({func:ne,args:[n],thisArg:w}),new Ln(t,this.__chain__)):this.thru(n)},Nn.prototype.toString=function(){return this.value()+""},Nn.prototype.run=Nn.prototype.toJSON=Nn.prototype.valueOf=Nn.prototype.value=function(){return Tt(this.__wrapped__,this.__actions__)},Nn.prototype.collect=Nn.prototype.map,Nn.prototype.head=Nn.prototype.first,Nn.prototype.select=Nn.prototype.filter,Nn.prototype.tail=Nn.prototype.rest,Nn}var w,b="3.10.1",x=1,A=2,j=4,k=8,I=16,R=32,O=64,E=128,C=256,U=30,W="...",$=150,S=16,F=200,N=1,T=2,L="Expected a function",z="__lodash_placeholder__",B="[object Arguments]",D="[object Array]",M="[object Boolean]",q="[object Date]",P="[object Error]",K="[object Function]",V="[object Number]",Z="[object Object]",Y="[object RegExp]",G="[object String]",J="[object ArrayBuffer]",X="[object Float32Array]",H="[object Float64Array]",Q="[object Int8Array]",nn="[object Int16Array]",tn="[object Int32Array]",rn="[object Uint8Array]",en="[object Uint8ClampedArray]",un="[object Uint16Array]",on="[object Uint32Array]",fn=/\b__p\+='';/g,an=/\b(__p\+=)''\+/g,cn=/(__e\(.*?\)|\b__t\))\+'';/g,ln=/&(?:amp|lt|gt|quot|#39|#96);/g,sn=/[&<>"'`]/g,pn=RegExp(ln.source),hn=RegExp(sn.source),_n=/<%-([\s\S]+?)%>/g,vn=/<%([\s\S]+?)%>/g,gn=/<%=([\s\S]+?)%>/g,yn=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\n\\]|\\.)*?\1)\]/,dn=/^\w*$/,mn=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\n\\]|\\.)*?)\2)\]/g,wn=/^[:!,]|[\\^$.*+?()[\]{}|\/]|(^[0-9a-fA-Fnrtuvx])|([\n\r\u2028\u2029])/g,bn=RegExp(wn.source),xn=/[\u0300-\u036f\ufe20-\ufe23]/g,An=/\\(\\)?/g,jn=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,kn=/\w*$/,In=/^0[xX]/,Rn=/^\[object .+?Constructor\]$/,On=/^\d+$/,En=/[\xc0-\xd6\xd8-\xde\xdf-\xf6\xf8-\xff]/g,Cn=/($^)/,Un=/['\n\r\u2028\u2029\\]/g,Wn=RegExp("[A-Z\\xc0-\\xd6\\xd8-\\xde]+(?=[A-Z\\xc0-\\xd6\\xd8-\\xde][a-z\\xdf-\\xf6\\xf8-\\xff]+)|[A-Z\\xc0-\\xd6\\xd8-\\xde]?[a-z\\xdf-\\xf6\\xf8-\\xff]+|[A-Z\\xc0-\\xd6\\xd8-\\xde]+|[0-9]+","g"),$n="Array ArrayBuffer Date Error Float32Array Float64Array Function Int8Array Int16Array Int32Array Math Number Object RegExp Set String _ clearTimeout isFinite parseFloat parseInt setTimeout TypeError Uint8Array Uint8ClampedArray Uint16Array Uint32Array WeakMap".split(" "),Sn={};
+Sn[X]=Sn[H]=Sn[Q]=Sn[nn]=Sn[tn]=Sn[rn]=Sn[en]=Sn[un]=Sn[on]=true,Sn[B]=Sn[D]=Sn[J]=Sn[M]=Sn[q]=Sn[P]=Sn[K]=Sn["[object Map]"]=Sn[V]=Sn[Z]=Sn[Y]=Sn["[object Set]"]=Sn[G]=Sn["[object WeakMap]"]=false;var Fn={};Fn[B]=Fn[D]=Fn[J]=Fn[M]=Fn[q]=Fn[X]=Fn[H]=Fn[Q]=Fn[nn]=Fn[tn]=Fn[V]=Fn[Z]=Fn[Y]=Fn[G]=Fn[rn]=Fn[en]=Fn[un]=Fn[on]=true,Fn[P]=Fn[K]=Fn["[object Map]"]=Fn["[object Set]"]=Fn["[object WeakMap]"]=false;var Nn={"\xc0":"A","\xc1":"A","\xc2":"A","\xc3":"A","\xc4":"A","\xc5":"A","\xe0":"a","\xe1":"a","\xe2":"a",
+"\xe3":"a","\xe4":"a","\xe5":"a","\xc7":"C","\xe7":"c","\xd0":"D","\xf0":"d","\xc8":"E","\xc9":"E","\xca":"E","\xcb":"E","\xe8":"e","\xe9":"e","\xea":"e","\xeb":"e","\xcc":"I","\xcd":"I","\xce":"I","\xcf":"I","\xec":"i","\xed":"i","\xee":"i","\xef":"i","\xd1":"N","\xf1":"n","\xd2":"O","\xd3":"O","\xd4":"O","\xd5":"O","\xd6":"O","\xd8":"O","\xf2":"o","\xf3":"o","\xf4":"o","\xf5":"o","\xf6":"o","\xf8":"o","\xd9":"U","\xda":"U","\xdb":"U","\xdc":"U","\xf9":"u","\xfa":"u","\xfb":"u","\xfc":"u","\xdd":"Y",
+"\xfd":"y","\xff":"y","\xc6":"Ae","\xe6":"ae","\xde":"Th","\xfe":"th","\xdf":"ss"},Tn={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;","`":"&#96;"},Ln={"&amp;":"&","&lt;":"<","&gt;":">","&quot;":'"',"&#39;":"'","&#96;":"`"},zn={"function":true,object:true},Bn={0:"x30",1:"x31",2:"x32",3:"x33",4:"x34",5:"x35",6:"x36",7:"x37",8:"x38",9:"x39",A:"x41",B:"x42",C:"x43",D:"x44",E:"x45",F:"x46",a:"x61",b:"x62",c:"x63",d:"x64",e:"x65",f:"x66",n:"x6e",r:"x72",t:"x74",u:"x75",v:"x76",x:"x78"},Dn={"\\":"\\",
+"'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},Mn=zn[typeof exports]&&exports&&!exports.nodeType&&exports,qn=zn[typeof module]&&module&&!module.nodeType&&module,Pn=zn[typeof self]&&self&&self.Object&&self,Kn=zn[typeof window]&&window&&window.Object&&window,Vn=qn&&qn.exports===Mn&&Mn,Zn=Mn&&qn&&typeof global=="object"&&global&&global.Object&&global||Kn!==(this&&this.window)&&Kn||Pn||this,Yn=m();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(Zn._=Yn, define(function(){
+return Yn})):Mn&&qn?Vn?(qn.exports=Yn)._=Yn:Mn._=Yn:Zn._=Yn}).call(this); \ No newline at end of file
diff --git a/studio-susie/public/assets/js/vendor/okcms.js b/studio-susie/public/assets/js/vendor/okcms.js
new file mode 100644
index 0000000..ddf0892
--- /dev/null
+++ b/studio-susie/public/assets/js/vendor/okcms.js
@@ -0,0 +1,45 @@
+function OKCMS () {
+
+ var cache = null
+
+ this.getAll = function () {
+ var deferred = $.Deferred()
+ if (cache) {
+ deferred.resolve(cache)
+ } else {
+ $.ajax({
+ method: 'GET',
+ url: '/db.json',
+ dataType: 'json'
+ }).done(onFetch).fail(onError)
+ }
+
+ return deferred
+
+ function onFetch (data) {
+ cache = sort(data)
+ // Freeze that mutha
+ // if (Object.freeze)
+ // deepFreeze(cache)
+ deferred.resolve(data)
+ }
+
+ function onError (err) {
+ deferred.reject(err)
+ }
+
+ // In-place sort by __index
+ function sort (data) {
+ Object.keys(data).forEach(function (key) {
+ data[key] = (data[key] || []).sort(byIndex)
+ })
+ return data
+ }
+
+ function byIndex (a, b) {
+ var iA = a && a.__index
+ var iB = b && b.__index
+ return iA > iB ? -1 : (iB > iA ? 1 : 0)
+ }
+ }
+}
diff --git a/studio-susie/public/assets/js/vendor/oktween.js b/studio-susie/public/assets/js/vendor/oktween.js
new file mode 100644
index 0000000..668c6f9
--- /dev/null
+++ b/studio-susie/public/assets/js/vendor/oktween.js
@@ -0,0 +1,159 @@
+/*
+ oktween.add({
+ obj: el.style,
+ units: "px",
+ from: { left: 0 },
+ to: { left: 100 },
+ duration: 1000,
+ easing: oktween.easing.circ_out,
+ update: function(obj){
+ console.log(obj.left)
+ }
+ finished: function(){
+ console.log("done")
+ }
+ })
+*/
+
+var oktween = (function(){
+ var oktween = {}
+ var tweens = oktween.tweens = []
+ var last_t = 0
+ var id = 0
+ oktween.speed = 1
+ oktween.add = function(tween){
+ tween.id = id++
+ tween.obj = tween.obj || {}
+ if (tween.easing) {
+ if (typeof tween.easing == "string" && oktween.easing[tween.easing]) {
+ tween.easing = oktween.easing[tween.easing]
+ }
+ }
+ else {
+ tween.easing = oktween.easing.linear
+ }
+ if (! ('from' in tween) && ! ('to' in tween)) {
+ tween.keys = []
+ }
+ else if (! ('from' in tween) ) {
+ tween.from = {}
+ tween.keys = Object.keys(tween.to)
+ tween.keys.forEach(function(prop){
+ tween.from[prop] = parseFloat(tween.obj[prop])
+ })
+ }
+ else {
+ tween.keys = Object.keys(tween.from)
+ }
+ tween.delay = tween.delay || 0
+ tween.start = last_t + tween.delay
+ tween.done = false
+ tween.after = tween.after || []
+ tween.then = function(fn){ tween.after.push(fn); return tween }
+ tween.tick = 0
+ tween.skip = tween.skip || 1
+ tween.dt = 0
+ tweens.push(tween)
+ return tween
+ }
+ oktween.update = function(t) {
+ requestAnimationFrame(oktween.update)
+ last_t = t * oktween.speed
+ if (tweens.length == 0) return
+ var done = false
+ tweens.forEach(function(tween, i){
+ var dt = Math.min(1.0, (t - tween.start) / tween.duration)
+ tween.tick++
+ if (dt < 0 || (dt < 1 && (tween.tick % tween.skip != 0))) return
+ var ddt = tween.dt = tween.easing(dt)
+ tween.keys.forEach(function(prop){
+ val = lerp( ddt, tween.from[prop], tween.to[prop] )
+ if (tween.round) val = Math.round(val)
+ if (tween.units) val = (Math.round(val)) + tween.units
+ tween.obj[prop] = val
+ })
+ tween.update && tween.update(tween.obj, dt)
+ if (dt == 1) {
+ tween.finished && tween.finished(tween)
+ if (tween.after.length) {
+ var twn = tween.after.shift()
+ twn.obj = twn.obj || tween.obj
+ twn.after = tween.after
+ oktween.add(twn)
+ }
+ if (tween.loop) {
+ tween.start = t + tween.delay
+ }
+ else {
+ done = tween.done = true
+ }
+ }
+ })
+ if (done) {
+ tweens = tweens.filter(function(tween){ return ! tween.done })
+ }
+ }
+ function lerp(n,a,b){ return (b-a)*n+a }
+
+ requestAnimationFrame(oktween.update)
+
+ oktween.easing = {
+ linear: function(t){
+ return t
+ },
+ circ_out: function(t) {
+ return Math.sqrt(1 - (t = t - 1) * t)
+ },
+ circ_in: function(t){
+ return -(Math.sqrt(1 - (t * t)) - 1)
+ },
+ circ_in_out: function(t) {
+ return ((t*=2) < 1) ? -0.5 * (Math.sqrt(1 - t * t) - 1) : 0.5 * (Math.sqrt(1 - (t -= 2) * t) + 1)
+ },
+ quad_in: function(n){
+ return Math.pow(n, 2)
+ },
+ quad_out: function(n){
+ return n * (n - 2) * -1
+ },
+ quad_in_out: function(n){
+ n = n * 2
+ if(n < 1){ return Math.pow(n, 2) / 2 }
+ return -1 * ((--n) * (n - 2) - 1) / 2
+ },
+ cubic_bezier: function (mX1, mY1, mX2, mY2) {
+ function A(aA1, aA2) { return 1.0 - 3.0 * aA2 + 3.0 * aA1; }
+ function B(aA1, aA2) { return 3.0 * aA2 - 6.0 * aA1; }
+ function C(aA1) { return 3.0 * aA1; }
+
+ // Returns x(t) given t, x1, and x2, or y(t) given t, y1, and y2.
+ function CalcBezier(aT, aA1, aA2) {
+ return ((A(aA1, aA2)*aT + B(aA1, aA2))*aT + C(aA1))*aT;
+ }
+
+ // Returns dx/dt given t, x1, and x2, or dy/dt given t, y1, and y2.
+ function GetSlope(aT, aA1, aA2) {
+ return 3.0 * A(aA1, aA2)*aT*aT + 2.0 * B(aA1, aA2) * aT + C(aA1);
+ }
+
+ function GetTForX(aX) {
+ // Newton raphson iteration
+ var aGuessT = aX;
+ for (var i = 0; i < 10; ++i) {
+ var currentSlope = GetSlope(aGuessT, mX1, mX2);
+ if (currentSlope == 0.0) return aGuessT;
+ var currentX = CalcBezier(aGuessT, mX1, mX2) - aX;
+ aGuessT -= currentX / currentSlope;
+ }
+ return aGuessT;
+ }
+
+ return function(aX) {
+ if (mX1 == mY1 && mX2 == mY2) return aX; // linear
+ return CalcBezier(aX, mY1, mY2);
+ }
+ }
+ }
+
+ return oktween
+})()
diff --git a/studio-susie/public/assets/js/vendor/prefixfree.min.js b/studio-susie/public/assets/js/vendor/prefixfree.min.js
new file mode 100644
index 0000000..5e88f56
--- /dev/null
+++ b/studio-susie/public/assets/js/vendor/prefixfree.min.js
@@ -0,0 +1,18 @@
+/**
+ * StyleFix 1.0.3 & PrefixFree 1.0.7
+ * @author Lea Verou
+ * MIT license
+ */
+(function(){function k(a,b){return[].slice.call((b||document).querySelectorAll(a))}if(window.addEventListener){var e=window.StyleFix={link:function(a){try{if("stylesheet"!==a.rel||a.hasAttribute("data-noprefix"))return}catch(b){return}var c=a.href||a.getAttribute("data-href"),d=c.replace(/[^\/]+$/,""),h=(/^[a-z]{3,10}:/.exec(d)||[""])[0],l=(/^[a-z]{3,10}:\/\/[^\/]+/.exec(d)||[""])[0],g=/^([^?]*)\??/.exec(c)[1],m=a.parentNode,f=new XMLHttpRequest,n;f.onreadystatechange=function(){4===f.readyState&&
+n()};n=function(){var b=f.responseText;if(b&&a.parentNode&&(!f.status||400>f.status||600<f.status)){b=e.fix(b,!0,a);if(d)var b=b.replace(/url\(\s*?((?:"|')?)(.+?)\1\s*?\)/gi,function(b,a,c){return/^([a-z]{3,10}:|#)/i.test(c)?b:/^\/\//.test(c)?'url("'+h+c+'")':/^\//.test(c)?'url("'+l+c+'")':/^\?/.test(c)?'url("'+g+c+'")':'url("'+d+c+'")'}),c=d.replace(/([\\\^\$*+[\]?{}.=!:(|)])/g,"\\$1"),b=b.replace(RegExp("\\b(behavior:\\s*?url\\('?\"?)"+c,"gi"),"$1");c=document.createElement("style");c.textContent=
+b;c.media=a.media;c.disabled=a.disabled;c.setAttribute("data-href",a.getAttribute("href"));m.insertBefore(c,a);m.removeChild(a);c.media=a.media}};try{f.open("GET",c),f.send(null)}catch(p){"undefined"!=typeof XDomainRequest&&(f=new XDomainRequest,f.onerror=f.onprogress=function(){},f.onload=n,f.open("GET",c),f.send(null))}a.setAttribute("data-inprogress","")},styleElement:function(a){if(!a.hasAttribute("data-noprefix")){var b=a.disabled;a.textContent=e.fix(a.textContent,!0,a);a.disabled=b}},styleAttribute:function(a){var b=
+a.getAttribute("style"),b=e.fix(b,!1,a);a.setAttribute("style",b)},process:function(){k('link[rel="stylesheet"]:not([data-inprogress])').forEach(StyleFix.link);k("style").forEach(StyleFix.styleElement);k("[style]").forEach(StyleFix.styleAttribute)},register:function(a,b){(e.fixers=e.fixers||[]).splice(void 0===b?e.fixers.length:b,0,a)},fix:function(a,b,c){for(var d=0;d<e.fixers.length;d++)a=e.fixers[d](a,b,c)||a;return a},camelCase:function(a){return a.replace(/-([a-z])/g,function(b,a){return a.toUpperCase()}).replace("-",
+"")},deCamelCase:function(a){return a.replace(/[A-Z]/g,function(b){return"-"+b.toLowerCase()})}};(function(){setTimeout(function(){k('link[rel="stylesheet"]').forEach(StyleFix.link)},10);document.addEventListener("DOMContentLoaded",StyleFix.process,!1)})()}})();
+(function(k){function e(b,c,d,h,l){b=a[b];b.length&&(b=RegExp(c+"("+b.join("|")+")"+d,"gi"),l=l.replace(b,h));return l}if(window.StyleFix&&window.getComputedStyle){var a=window.PrefixFree={prefixCSS:function(b,c,d){var h=a.prefix;-1<a.functions.indexOf("linear-gradient")&&(b=b.replace(/(\s|:|,)(repeating-)?linear-gradient\(\s*(-?\d*\.?\d*)deg/ig,function(b,a,c,d){return a+(c||"")+"linear-gradient("+(90-d)+"deg"}));b=e("functions","(\\s|:|,)","\\s*\\(","$1"+h+"$2(",b);b=e("keywords","(\\s|:)","(\\s|;|\\}|$)",
+"$1"+h+"$2$3",b);b=e("properties","(^|\\{|\\s|;)","\\s*:","$1"+h+"$2:",b);if(a.properties.length){var l=RegExp("\\b("+a.properties.join("|")+")(?!:)","gi");b=e("valueProperties","\\b",":(.+?);",function(a){return a.replace(l,h+"$1")},b)}c&&(b=e("selectors","","\\b",a.prefixSelector,b),b=e("atrules","@","\\b","@"+h+"$1",b));b=b.replace(RegExp("-"+h,"g"),"-");return b=b.replace(/-\*-(?=[a-z]+)/gi,a.prefix)},property:function(b){return(0<=a.properties.indexOf(b)?a.prefix:"")+b},value:function(b,c){b=
+e("functions","(^|\\s|,)","\\s*\\(","$1"+a.prefix+"$2(",b);b=e("keywords","(^|\\s)","(\\s|$)","$1"+a.prefix+"$2$3",b);0<=a.valueProperties.indexOf(c)&&(b=e("properties","(^|\\s|,)","($|\\s|,)","$1"+a.prefix+"$2$3",b));return b},prefixSelector:function(b){return b.replace(/^:{1,2}/,function(b){return b+a.prefix})},prefixProperty:function(b,c){var d=a.prefix+b;return c?StyleFix.camelCase(d):d}};(function(){var b={},c=[],d=getComputedStyle(document.documentElement,null),h=document.createElement("div").style,
+l=function(a){if("-"===a.charAt(0)){c.push(a);a=a.split("-");var d=a[1];for(b[d]=++b[d]||1;3<a.length;)a.pop(),d=a.join("-"),StyleFix.camelCase(d)in h&&-1===c.indexOf(d)&&c.push(d)}};if(0<d.length)for(var g=0;g<d.length;g++)l(d[g]);else for(var e in d)l(StyleFix.deCamelCase(e));var g=0,f,k;for(k in b)d=b[k],g<d&&(f=k,g=d);a.prefix="-"+f+"-";a.Prefix=StyleFix.camelCase(a.prefix);a.properties=[];for(g=0;g<c.length;g++)e=c[g],0===e.indexOf(a.prefix)&&(f=e.slice(a.prefix.length),StyleFix.camelCase(f)in
+h||a.properties.push(f));!("Ms"!=a.Prefix||"transform"in h||"MsTransform"in h)&&"msTransform"in h&&a.properties.push("transform","transform-origin");a.properties.sort()})();(function(){function b(a,b){h[b]="";h[b]=a;return!!h[b]}var c={"linear-gradient":{property:"backgroundImage",params:"red, teal"},calc:{property:"width",params:"1px + 5%"},element:{property:"backgroundImage",params:"#foo"},"cross-fade":{property:"backgroundImage",params:"url(a.png), url(b.png), 50%"}};c["repeating-linear-gradient"]=
+c["repeating-radial-gradient"]=c["radial-gradient"]=c["linear-gradient"];var d={initial:"color","zoom-in":"cursor","zoom-out":"cursor",box:"display",flexbox:"display","inline-flexbox":"display",flex:"display","inline-flex":"display",grid:"display","inline-grid":"display","max-content":"width","min-content":"width","fit-content":"width","fill-available":"width"};a.functions=[];a.keywords=[];var h=document.createElement("div").style,e;for(e in c){var g=c[e],k=g.property,g=e+"("+g.params+")";!b(g,k)&&
+b(a.prefix+g,k)&&a.functions.push(e)}for(var f in d)k=d[f],!b(f,k)&&b(a.prefix+f,k)&&a.keywords.push(f)})();(function(){function b(a){e.textContent=a+"{}";return!!e.sheet.cssRules.length}var c={":read-only":null,":read-write":null,":any-link":null,"::selection":null},d={keyframes:"name",viewport:null,document:'regexp(".")'};a.selectors=[];a.atrules=[];var e=k.appendChild(document.createElement("style")),l;for(l in c){var g=l+(c[l]?"("+c[l]+")":"");!b(g)&&b(a.prefixSelector(g))&&a.selectors.push(l)}for(var m in d)g=
+m+" "+(d[m]||""),!b("@"+g)&&b("@"+a.prefix+g)&&a.atrules.push(m);k.removeChild(e)})();a.valueProperties=["transition","transition-property"];k.className+=" "+a.prefix;StyleFix.register(a.prefixCSS)}})(document.documentElement);
diff --git a/studio-susie/public/assets/js/vendor/util.js b/studio-susie/public/assets/js/vendor/util.js
new file mode 100644
index 0000000..b42b832
--- /dev/null
+++ b/studio-susie/public/assets/js/vendor/util.js
@@ -0,0 +1,200 @@
+// window.addEventListener('message', function(e) {
+// console.log(e.data)
+// if (e.data == "click") {
+// document.body.click()
+// }
+// if (e.data == "ready") {
+// app.ready()
+// }
+// })
+
+var TWO_PI = Math.PI * 2
+var DEG_TO_RAD = Math.PI/180
+var RAD_TO_DEG = 180/Math.PI
+
+function gray(n) {
+ var s = Math.round(n * 255).toString(16) + ""
+ if (s.length == 1) s = "0" + s
+ return "#" + s + s + s
+}
+
+function rand(n){ return (Math.random()*n) }
+function randint(n){ return rand(n)|0 }
+function randrange(a,b){ return a + rand(b-a) }
+function randsign(){ return Math.random() > 0.5 ? 1 : -1 }
+function choice(a){ return a[randint(a.length)] }
+function clamp(n,a,b){ return n<a?a:n<b?n:b }
+function lerp(n,a,b){ return (b-a)*n+a }
+function avg(m,n,a){ return (m*(a-1)+n)/a }
+function mod(n,m){ return n-(m * Math.floor(n/m)) }
+function quantize(a,b){ return Math.round(a/b)*b }
+function dist(x0,y0,x1,y1){
+ var dx = x1-x0
+ var dy = y1-y0
+ return Math.sqrt(dx*dx + dy*dy)
+}
+function angle(x0,y0,x1,y1){ return Math.atan2(y1-y0,x1-x0) }
+function pluck(h,a){
+ var hh = {}
+ if (typeof a == "string") a = a.split(" ");
+ a.forEach(function(s){ hh[s] = h[s] })
+ return hh
+}
+function shuffle(a){
+ for (var i = a.length; i > 0; i--){
+ var r = randint(i)
+ var swap = a[i-1]
+ a[i-1] = a[r]
+ a[r] = swap
+ }
+ return a
+}
+function defaults (dest, src) {
+ dest = dest || {}
+ for (var i in src) {
+ dest[i] = typeof dest[i] == 'undefined' ? src[i] : dest[i]
+ }
+ return dest
+}
+
+function getFirstTouch(fn){
+ return function(e){
+ e.preventDefault()
+ var touch = e.touches[0]
+ fn(touch)
+ }
+}
+
+function offsetFromPoint(event, element) {
+ function a(width) {
+ var l = 0, r = 200;
+ while (r - l > 0.0001) {
+ var mid = (r + l) / 2;
+ var a = document.createElement('div');
+ a.style.cssText = 'position: absolute;left:0;top:0;background: red;z-index: 1000;';
+ a.style[width ? 'width' : 'height'] = mid.toFixed(3) + '%';
+ a.style[width ? 'height' : 'width'] = '100%';
+ element.appendChild(a);
+ var x = document.elementFromPoint(event.clientX, event.clientY);
+ element.removeChild(a);
+ if (x === a) {
+ r = mid;
+ } else {
+ if (r === 200) {
+ return null;
+ }
+ l = mid;
+ }
+ }
+ return mid;
+ }
+ var l = a(1),
+ t = a(0);
+ return l && t ? {
+ left: l / 100,
+ top: t / 100,
+ toString: function () {
+ return 'left: ' + l + '%, top: ' + t + '%';
+ }
+ } : null;
+}
+
+// Check if supports 3D transforms
+function has3d(){
+ var el = $('<p>')[0], $iframe = $('<iframe>'), has3d, t,
+ transforms = {
+ 'webkitTransform': '-webkit-transform',
+ 'OTransform': '-o-transform',
+ 'msTransform': '-ms-transform',
+ 'transform': 'transform'
+ };
+
+ // Add it to the body to get the computed style
+ // Sandbox it inside an iframe to avoid Android Browser quirks
+ $iframe.appendTo('body').contents().find('body').append( el );
+
+ for (t in transforms) {
+ if (el.style[t] !== undefined) {
+ el.style[t] = 'translate3d(1px,1px,1px)';
+ has3d = window.getComputedStyle(el).getPropertyValue(transforms[t]);
+ }
+ }
+
+ $iframe.remove();
+
+ return has3d !== undefined && has3d.length > 0 && has3d !== "none";
+}
+
+// Identify browser based on useragent string
+;(function( ua ) {
+ ua = ua.toLowerCase();
+ var match = /(chrome)[ \/]([\w.]+)/.exec( ua ) ||
+ /(webkit)[ \/]([\w.]+)/.exec( ua ) ||
+ /(opera)(?:.*version|)[ \/]([\w.]+)/.exec( ua ) ||
+ /(msie) ([\w.]+)/.exec( ua ) ||
+ ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec( ua ) ||
+ [];
+ var matched = {
+ browser: match[ 1 ] || "",
+ version: match[ 2 ] || "0"
+ };
+ browser = {};
+ if ( matched.browser ) {
+ browser[ matched.browser ] = true;
+ browser.version = matched.version;
+ }
+ // Chrome is Webkit, but Webkit is also Safari.
+ if ( browser.chrome ) {
+ browser.webkit = true;
+ } else if ( browser.webkit ) {
+ browser.safari = true;
+ }
+ if (window.$) $.browser = browser;
+ return browser;
+})( navigator.userAgent );
+
+// Naive useragent detection pattern
+var is_iphone = (navigator.userAgent.match(/iPhone/i)) || (navigator.userAgent.match(/iPod/i))
+var is_ipad = (navigator.userAgent.match(/iPad/i))
+var is_android = (navigator.userAgent.match(/Android/i))
+var is_mobile = is_iphone || is_ipad || is_android
+var is_desktop = ! is_mobile;
+var app_devicePixelRatio = 1;
+var transformProp = browser.safari ? "WebkitTransform" : "transform";
+
+if (is_mobile) {
+ $("html").addClass("mobile")
+}
+else {
+ $("html").addClass("desktop")
+}
+
+// rAF shim
+;(function() {
+ var lastTime = 0;
+ var vendors = ['ms', 'moz', 'webkit', 'o'];
+ for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
+ window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
+ window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame']
+ || window[vendors[x]+'CancelRequestAnimationFrame'];
+ }
+
+ if (!window.requestAnimationFrame)
+ window.requestAnimationFrame = function(callback, element) {
+ var currTime = new Date().getTime();
+ var timeToCall = Math.max(0, 16 - (currTime - lastTime));
+ var id = window.setTimeout(function() { callback(currTime + timeToCall); },
+ timeToCall);
+ lastTime = currTime + timeToCall;
+ return id;
+ };
+
+ if (!window.cancelAnimationFrame)
+ window.cancelAnimationFrame = function(id) {
+ clearTimeout(id);
+ };
+}());
+
+function cloneDeep(data) {
+ return JSON.parse(JSON.stringify(data || null))
+} \ No newline at end of file
diff --git a/studio-susie/public/assets/js/vendor/view/OKTmplView.js b/studio-susie/public/assets/js/vendor/view/OKTmplView.js
new file mode 100644
index 0000000..86f1ee3
--- /dev/null
+++ b/studio-susie/public/assets/js/vendor/view/OKTmplView.js
@@ -0,0 +1,97 @@
+/**
+ * An OK templating language I just made up
+ *
+ * Templates:
+ * <!-- Add data-ok-* attrs -->
+ * <span data-ok-msg></span
+ *
+ * Usage:
+ * // "Compile"
+ * var view = new OKTmplView('tmpl-id')
+ * // Attach to DOM before render
+ * document.body.appendChild(view.el)
+ * // Render to heart's content
+ * view.render(data)
+ */
+function OKTmplView (id) {
+ var $el = this.$el = $('#ok-' + id).children().clone()
+ var el = this.el = $el[0]
+ var pathMetas = reduceToPathMetas(el)
+
+ this.render = function (data) {
+ data = data || {}
+ pathMetas.forEach(function (pathMeta) {
+ $el.find('[' + pathMeta.attr + ']').html(
+ getPath(data, pathMeta.path)
+ )
+ })
+ }
+
+ this.hide = function () {
+ $el.hide()
+ }
+
+ this.show = function () {
+ $el.show()
+ }
+
+ function reduceToPathMetas (el) {
+ return flatten(next([el]))
+
+ function next (children) {
+ return Array.prototype.slice.call(children)
+ .reduce(function (result, child) {
+ result.push(getPathMetas(child).concat(next(child.childNodes)))
+ return result
+ }, [])
+ }
+
+ function getPathMetas (el) {
+ var attrs = Array.prototype.slice.call(el.attributes || [])
+ return attrs
+ .filter(specified)
+ .reduce(function (result, attrNode) {
+ if (/^data-ok-/.test(attrNode.nodeName)) {
+ result.push({
+ attr: attrNode.nodeName,
+ path: attrNode.nodeName.split('-').slice(2),
+ })
+ }
+ return result
+ }, [])
+
+ function specified (attrNode) {
+ return typeof attrNode.specified === 'undefined' ||
+ attrNode.specified
+ }
+ }
+ }
+}
+
+/**
+ * Get value for key at path where path is an array of keys
+ */
+function getPath (obj, path) {
+ obj = obj || {}
+ path = path || []
+ return path.reduce(function (obj, key, i) {
+ if (i < path.length - 1)
+ return obj[key] || {}
+ else
+ return obj[key]
+ }, obj)
+}
+
+function flatten (list) {
+ var result = []
+ next(list || [])
+ return result
+
+ function next (list) {
+ list.forEach(function (item) {
+ return typeof item.length !== 'undefined'
+ ? next(item)
+ : result.push(item)
+ })
+ }
+}
diff --git a/studio-susie/public/assets/js/vendor/view/Router.js b/studio-susie/public/assets/js/vendor/view/Router.js
new file mode 100644
index 0000000..3b0d939
--- /dev/null
+++ b/studio-susie/public/assets/js/vendor/view/Router.js
@@ -0,0 +1,82 @@
+var Router = View.extend({
+
+ routeByHash: false,
+
+ go: function(url){
+ this.parseRoute(url)
+ },
+
+ pushState: function(url){
+ if (this.routeByHash) {
+ window.location.hash = url
+ }
+ else if (window.history) {
+ window.history.pushState(null, null, url)
+ }
+ },
+
+ route: function(){
+ var path = this.routeByHash ? window.location.hash.substr(0) : window.location.pathname
+ path = path || "/"
+ this.originalPath = path
+ this.parseRoute(path)
+ },
+
+ parseRoute: function(pathname){
+
+ pathname = pathname.replace(/^#/, "")
+
+ if (pathname[0] !== "/") { pathname = "/" + pathname }
+
+ var routes = this.routes,
+ path = pathname.split("/");
+
+ for (var i = 0; i < path.length; i++) {
+ if (! path[i].length) {
+ path[i] = null
+ }
+ }
+
+ if (pathname in routes) {
+ this[this.routes[pathname]]()
+ return
+ }
+
+ if (path[path.length-1] == null) {
+ path.pop()
+ }
+
+ for (var route in routes) {
+ var routePath = route.split("/")
+ if (routePath[1] == path[1]) {
+ if (routePath[2] && routePath[2].indexOf(":") !== -1 && path[2] && (path[3] === routePath[3]) ) {
+ this[this.routes[route]](path[2])
+ return
+ }
+ else if (routePath[2] == path[2]) {
+ if (routePath[3] && path[3]) {
+ if (routePath[3].indexOf(":") !== -1) {
+ this[this.routes[route]](path[3])
+ return
+ }
+ else if (routePath[3] == path[3]) {
+ this[this.routes[route]]()
+ return
+ }
+ }
+ else if (! routePath[3] && ! path[3]) {
+ this[this.routes[route]]()
+ return
+ }
+ }
+ else if (! routePath[2] && (! path[2].length || ! path[2])) {
+ this[this.routes[route]]()
+ return
+ }
+ }
+ }
+ // Redirect to root on 404
+ window.location = '/'
+ }
+
+})
diff --git a/studio-susie/public/assets/js/vendor/view/ScrollableView.js b/studio-susie/public/assets/js/vendor/view/ScrollableView.js
new file mode 100644
index 0000000..a01809c
--- /dev/null
+++ b/studio-susie/public/assets/js/vendor/view/ScrollableView.js
@@ -0,0 +1,31 @@
+var ScrollableView = View.extend({
+
+ events: {
+ "load img": "deferRefresh",
+ },
+
+ deferScrollToTop: function(){
+ if (! this.scroller) return
+ setTimeout(this.scrollToTop.bind(this), 0)
+ },
+
+ refreshScroller: function(){
+ if (! this.scroller) return
+ this.scroller.refresh()
+ clearTimeout( this.scrollerRefreshTimeout )
+ },
+
+ scrollerRefreshTimeout: null,
+ deferRefresh: function(){
+ if (! this.scroller) return
+ clearTimeout( this.scrollerRefreshTimeout )
+ this.scrollerRefreshTimeout = setTimeout(this.refreshScroller.bind(this))
+ },
+
+ scrollToTop: function(){
+ if (! this.scroller) return
+ this.scroller.refresh()
+ app.collection.scroller.scrollTo(0, 0)
+ },
+
+}) \ No newline at end of file
diff --git a/studio-susie/public/assets/js/vendor/view/View.js b/studio-susie/public/assets/js/vendor/view/View.js
new file mode 100644
index 0000000..09b722e
--- /dev/null
+++ b/studio-susie/public/assets/js/vendor/view/View.js
@@ -0,0 +1,150 @@
+var View = (function($, _){
+
+ var View = function(options) {
+ this._id = _.uniqueId('view')
+ this.type = "view"
+ options || (options = {});
+ _.extend(this, _.pick(options, viewOptions))
+ this._ensureElement()
+ this.initialize.apply(this, arguments)
+ this.delegateEvents()
+ }
+
+ var delegateEventSplitter = /^(\S+)\s*(.*)$/;
+
+ var viewOptions = ['model', 'collection', 'el', 'id', 'attributes', 'className', 'tagName', 'events'];
+
+ _.extend(View.prototype, {
+
+ // The default `tagName` of a View's element is `"div"`.
+ tagName: 'div',
+
+ $: function(selector) {
+ return this.$el.find(selector);
+ },
+
+ initialize: function(){},
+
+ setElement: function(element, delegate) {
+ if (this.$el) this.undelegateEvents();
+ this.$el = element instanceof $ ? element : $(element);
+ this.el = this.$el[0];
+ if (delegate !== false) this.delegateEvents();
+ return this;
+ },
+
+ // Set callbacks, where `this.events` is a hash of
+ //
+ // *{"event selector": "callback"}*
+ //
+ // {
+ // 'mousedown .title': 'edit',
+ // 'click .button': 'save',
+ // 'click .open': function(e) { ... }
+ // }
+ //
+ // pairs. Callbacks will be bound to the view, with `this` set properly.
+ // Uses event delegation for efficiency.
+ // Omitting the selector binds the event to `this.el`.
+ // This only works for delegate-able events: not `focus`, `blur`, and
+ // not `change`, `submit`, and `reset` in Internet Explorer.
+ delegateEvents: function(events) {
+ if (!(events || (events = _.result(this, 'events')))) return this;
+ this.undelegateEvents();
+ for (var key in events) {
+ var method = events[key];
+ if (!_.isFunction(method)) method = this[events[key]];
+ if (!method) continue;
+
+ var match = key.match(delegateEventSplitter);
+ var eventName = match[1], selector = match[2];
+ method = _.bind(method, this);
+ if (is_mobile) {
+ if (eventName === 'mouseenter' || eventName === 'mouseleave') {
+ continue
+ }
+/*
+ // cordova apps have some issue with click on android
+ if (is_android && eventName === 'click') {
+ eventName = 'touchstart'
+ }
+*/
+ }
+ eventName += '.delegateEvents' + this._id;
+ if (selector === '') {
+ this.$el.on(eventName, method);
+ } else {
+ this.$el.on(eventName, selector, method);
+ }
+ }
+ return this;
+ },
+
+ // Clears all callbacks previously bound to the view with `delegateEvents`.
+ undelegateEvents: function() {
+ this.$el.off('.delegateEvents' + this._id);
+ return this;
+ },
+
+ // Ensure that the View has a DOM element to render into.
+ // If `this.el` is a string, pass it through `$()`, take the first
+ // matching element, and re-assign it to `el`. Otherwise, create
+ // an element from the `id`, `className` and `tagName` properties.
+ _ensureElement: function() {
+ this.setElement(_.result(this, 'el'), false);
+ },
+
+ preventDefault: function(e){
+ e && e.preventDefault()
+ },
+
+ stopPropagation: function(e){
+ e && e.stopPropagation()
+ },
+
+ });
+
+
+ var extend = function(protoProps, staticProps) {
+ var staticProps = staticProps || {}
+ var parent = this;
+ var child;
+ var childEvents = {};
+
+ // The constructor function for the new subclass is either defined by you
+ // (the "constructor" property in your `extend` definition), or defaulted
+ // by us to simply call the parent's constructor.
+ if (protoProps && _.has(protoProps, 'constructor')) {
+ child = protoProps.constructor;
+ } else {
+ child = function(){ return parent.apply(this, arguments); };
+ }
+
+ // Extend events so we can subclass views
+ _.extend(childEvents, parent.prototype.events, protoProps.events)
+
+ // Add static properties to the constructor function, if supplied.
+ _.extend(child, parent, staticProps);
+
+ // Set the prototype chain to inherit from `parent`, without calling
+ // `parent`'s constructor function.
+ var Surrogate = function(){ this.constructor = child; };
+ Surrogate.prototype = parent.prototype;
+ child.prototype = new Surrogate;
+
+ // Add prototype properties (instance properties) to the subclass,
+ // if supplied.
+ if (protoProps) _.extend(child.prototype, protoProps);
+
+ // Set a convenience property in case the parent's prototype is needed
+ // later.
+ child.prototype.__super__ = parent.prototype;
+ child.prototype.events = childEvents
+
+ return child;
+ };
+
+ View.extend = extend;
+
+ return View;
+})(jQuery, _)