jam/js/ui/cordova/www/js/app.js

5760 lines
184 KiB
JavaScript

/**
** ==============================
** O O O OOOO
** O O O O O O
** O O O O O O
** OOOO OOOO O OOO OOOO
** O O O O O O O
** O O O O O O O
** OOOO OOOO O O OOOO
** ==============================
** Dr. Stefan Bosse http://www.sblab.de
**
** COPYRIGHT: THIS SOFTWARE, EXECUTABLE AND SOURCE CODE IS OWNED
** BY THE AUTHOR(S).
** THIS SOURCE CODE MAY NOT BE COPIED, EXTRACTED,
** MODIFIED, OR OTHERWISE USED IN A CONTEXT
** OUTSIDE OF THE SOFTWARE SYSTEM.
**
** $AUTHORS: Stefan Bosse, Kik Interactive, Matteo Spinelli
** $INITIAL: (C) 2006-2019 bLAB
** $CREATED: 12-12-18 by sbosse.
** $VERSION: 1.1.10
** $ORIGINAL:
** $INFO:
**
** CORDOVA/NW.JS APP.js Framework
**
** App.js v3.0.8
** Instant mobile web app creation
** Copyright (c) 2012 Kik Interactive, http://kik.com
** Released under the MIT license
**
** iScroll v4.1.6
** Copyright (c) 2011 Matteo Spinelli, http://cubiq.org
** Released under the MIT license
**
** $ENDOFINFO
**
*/
var Swapper = function(c, b) {
function a(e, d, f, g) {
a._swapper(e, d, f, g)
}
if (c && c.fn) {
c.extend(c.fn, {
swapper: function(d, e, f) {
d = c(d)[0];
this.forEach(function(g) {
a._swapper(g, d, e, f)
});
return this
}
})
}
if (b && b.fn) {
b.fn.swapper = function(d, e, f) {
d = b(d)[0];
this.each(function() {
a._swapper(this, d, e, f)
});
return this
}
}
return a
}(window.Zepto, window.jQuery);
Swapper._os = function(f, d) {
var c, a, b;
if (b = /\bCPU.*OS (\d+(_\d+)?)/i.exec(f)) {
c = "ios";
a = b[1].replace("_", ".")
} else {
if (b = /\bAndroid (\d+(\.\d+)?)/.exec(f)) {
c = "android";
a = b[1]
}
}
var e = {
name: c,
version: a && d(a)
};
e[c] = true;
return e
}(navigator.userAgent, parseFloat);
Swapper._isNode = function(a, b) {
return function(d) {
if (!d) {
return false
}
try {
return (d instanceof a) || (d instanceof b)
} catch (c) {}
if (typeof d !== "object") {
return false
}
if (typeof d.nodeType !== "number") {
return false
}
if (typeof d.nodeName !== "string") {
return false
}
return true
}
}(Node, HTMLElement);
Swapper._isInDOM = function(a) {
return function(c, b) {
if (!b && !a(c)) {
throw TypeError("element must be a DOM node, got " + c)
}
while (c = c.parentNode) {
if (c === document) {
return true
}
}
return false
}
}(Swapper._isNode);
Swapper._insertBefore = function() {
return function(a, b) {
b.parentNode.insertBefore(a, b)
}
}();
Swapper._insertAfter = function() {
return function(a, c) {
var b = c.parentNode;
if (b.lastchild === c) {
b.appendChild(a)
} else {
b.insertBefore(a, c.nextSibling)
}
}
}();
Swapper._removeNode = function() {
return function(a) {
if (a.parentNode) {
a.parentNode.removeChild(a)
}
}
}();
Swapper._setTransform = function() {
return function(b, a) {
b.style["-webkit-transform"] = a;
b.style["-moz-transform"] = a;
b.style["-ms-transform"] = a;
b.style["-o-transform"] = a;
b.style.transform = a
}
}();
Swapper._setTransition = function() {
return function(a, b) {
if (b) {
a.style["-webkit-transition"] = "-webkit-" + b;
a.style["-moz-transition"] = "-moz-" + b;
a.style["-ms-transition"] = "-ms-" + b;
a.style["-o-transition"] = "-o-" + b;
a.style.transition = b
} else {
a.style["-webkit-transition"] = "";
a.style["-moz-transition"] = "";
a.style["-ms-transition"] = "";
a.style["-o-transition"] = "";
a.style.transition = ""
}
}
}();
Swapper._getStyles = function(a) {
return function(c, d) {
var b;
if (d) {
b = c.style
} else {
b = a.defaultView.getComputedStyle(c, null)
}
return {
"-webkit-transition": b["-webkit-transition"],
"-moz-transition": b["-moz-transition"],
"-ms-transition": b["-ms-transition"],
"-o-transition": b["-o-transition"],
transition: b.transition,
display: b.display,
opacity: b.opacity,
top: b.top,
left: b.left,
height: b.height,
width: b.width,
position: b.position
}
}
}(document);
Swapper._easings = {
linear: "linear",
ease: "ease",
"ease-in": "ease-in",
"ease-out": "ease-out",
"ease-in-out": "ease-in-out",
"step-start": "step-start",
"step-end": "step-end"
};
Swapper._transitions = {
fade: [{
fade: true
}, {
fade: true
}],
"fade-on": [{
fade: true
}, {}],
"fade-off": [{}, {
fade: true
}, true],
"scale-in": [{
transform: "scale(0.01)"
}, {}],
"scale-out": [{}, {
transform: "scale(0.01)"
}, true],
"rotate-left": [{
transform: "rotateY(-180deg) perspective(360px)",
fade: true
}, {
transform: "rotateY( 180deg) perspective(360px)",
fade: true
}],
"rotate-right": [{
transform: "rotateY( 180deg) perspective(360px)",
fade: true
}, {
transform: "rotateY(-180deg) perspective(360px)",
fade: true
}],
"cube-left": [{
transform: "translate3d( 50%,0,0) rotateY(-90deg) perspective(360px)"
}, {
transform: "translate3d(-50%,0,0) rotateY( 90deg) perspective(360px)"
}],
"cube-right": [{
transform: "translate3d(-50%,0,0) rotateY( 90deg) perspective(360px)"
}, {
transform: "translate3d( 50%,0,0) rotateY(-90deg) perspective(360px)"
}],
"swap-left": [{
transform: "translate3d( 65%,0,0) rotateY( 90deg) perspective(360px)"
}, {
transform: "translate3d(-65%,0,0) rotateY(-90deg) perspective(360px)"
}],
"swap-right": [{
transform: "translate3d(-65%,0,0) rotateY(-90deg) perspective(360px)"
}, {
transform: "translate3d( 65%,0,0) rotateY( 90deg) perspective(360px)"
}],
"explode-in": [{
fade: true,
transform: "scale(1.25)"
}, {}],
"explode-out": [{}, {
fade: true,
transform: "scale(1.25)"
}, true],
"implode-in": [{}, {
fade: true,
transform: "scale(0.60)"
}, true],
"implode-out": [{
fade: true,
transform: "scale(0.80)"
}, {}],
"slide-left": [{
transform: "translate3d( 100%,0,0)"
}, {
transform: "translate3d(-100%,0,0)"
}],
"slide-right": [{
transform: "translate3d(-100%,0,0)"
}, {
transform: "translate3d( 100%,0,0)"
}],
"slide-up": [{
transform: "translate3d(0, 100%,0)"
}, {
transform: "translate3d(0,-100%,0)"
}],
"slide-down": [{
transform: "translate3d(0,-100%,0)"
}, {
transform: "translate3d(0, 100%,0)"
}],
"slideon-left": [{
transform: "translate3d(-100%,0,0)"
}, {}],
"slideoff-left": [{}, {
transform: "translate3d(-100%,0,0)"
}, true],
"slideon-right": [{
transform: "translate3d(100%,0,0)"
}, {}],
"slideoff-right": [{}, {
transform: "translate3d(100%,0,0)"
}, true],
"slideon-up": [{
transform: "translate3d(0,-100%,0)"
}, {}],
"slideoff-up": [{}, {
transform: "translate3d(0,-100%,0)"
}, true],
"slideon-down": [{
transform: "translate3d(0,100%,0)"
}, {}],
"slideoff-down": [{}, {
transform: "translate3d(0,100%,0)"
}, true],
"slideon-left-ios": [{
transform: "translate3d(100%,0,0)"
}, {
transform: "translate3d(-30%,0,0)"
}],
"slideoff-right-ios": [{
transform: "translate3d(-30%,0,0)"
}, {
transform: "translate3d(100%,0,0)"
}, true],
"glideon-right": [{
transform: "translate3d(110%,0,0)"
}, {
transform: "translate3d(-20%,0,0)"
}],
"glideoff-right": [{
transform: "translate3d(-20%,0,0)"
}, {
transform: "translate3d(110%,0,0)"
}, true],
"glideon-left": [{
transform: "translate3d(-110%,0,0)"
}, {
transform: "translate3d(20%,0,0)"
}],
"glideoff-left": [{
transform: "translate3d(20%,0,0)"
}, {
transform: "translate3d(-110%,0,0)"
}, true],
"glideon-down": [{
transform: "translate3d(0,110%,0)"
}, {
transform: "translate3d(0,-20%,0)"
}],
"glideoff-down": [{
transform: "translate3d(0,-20%,0)"
}, {
transform: "translate3d(0,110%,0)"
}, true],
"glideon-up": [{
transform: "translate3d(0,-110%,0)"
}, {
transform: "translate3d(0,20%,0)"
}],
"glideoff-up": [{
transform: "translate3d(0,20%,0)"
}, {
transform: "translate3d(0,-110%,0)"
}, true],
"android-l-in": [{
transform: "translate3d(0,6%,0)",
fade: true
}, {}],
"android-l-out": [{}, {
transform: "translate3d(0,6%,0)",
fade: true
}, true]
};
Swapper._validate = function(e, f, d) {
return {
element: c,
options: b,
callback: a
};
function c(g) {
if (!e(g)) {
throw TypeError("element must be a DOM node, got " + g)
}
}
function b(g) {
switch (typeof g) {
case "string":
g = {
transition: g
};
break;
case "undefined":
g = {};
break;
case "object":
break;
default:
throw TypeError("options must be an object if defined, got " + g)
}
switch (typeof g.transition) {
case "string":
if (!(g.transition in f) && (g.transition !== "instant")) {
throw TypeError(g.transition + " is not a valid transition")
}
break;
case "undefined":
break;
default:
throw TypeError("transition must be a string if defined, got " + g.transition)
}
switch (typeof g.duration) {
case "number":
if (g.duration < 0) {
throw TypeError("duration must be a non-negative integer, got " + g.duration)
}
break;
case "undefined":
break;
default:
throw TypeError("duration must be a number if defined, got " + g.duration)
}
switch (typeof g.easing) {
case "string":
if (!(g.easing in d) && (g.easing.substr(0, 13) !== "cubic-bezier(")) {
throw TypeError(g.easing + " is not a valid easing")
}
break;
case "undefined":
break;
default:
throw TypeError("easing must be a string if defined, got " + g.easing)
}
return g
}
function a(g) {
switch (typeof g) {
case "undefined":
g = function() {};
break;
case "function":
break;
default:
throw TypeError("callback must be a function if defined, got " + g)
}
return g
}
}(Swapper._isNode, Swapper._transitions, Swapper._easings);
Swapper._swapper = function(k, w, f, e, A, x, g, h, j, D, l, q, m, s) {
var a = "translate3d(0,0,0) scale(1)",
E = "fade",
z = "ease-in-out";
var p = (k.ios && (Math.floor(k.version) === 5));
function r(G, F, H, I) {
q.element(G);
q.element(F);
if (typeof H === "function") {
I = H;
H = {}
}
H = q.options(H);
I = q.callback(I);
if (G._swapper) {
throw Error("elem1 is currently being swapped")
} else {
if (F._swapper) {
throw Error("elem2 is currently being swapped")
}
}
if (!f(G, true)) {
throw Error("elem1 must be in the DOM to be swapped")
}
G._swapper = true;
F._swapper = true;
x(F);
o(G, F, H, function() {
G._swapper = false;
F._swapper = false;
I()
})
}
function o(O, N, P, M) {
if (P.transition === "instant") {
A(N, O);
x(O);
M();
return
}
var L = D[P.transition || E],
K = P.easing || z,
J = P.duration || 300;
if (K.substr(0, 13) !== "cubic-bezier(") {
K = l[K]
}
A(N, O);
var I = j(O),
H = j(N),
G = j(O, true),
F = j(N, true);
C(O, N, I, H);
if (L[2]) {
e(N, O)
}
N.style.opacity = "0";
u(O, N);
setTimeout(function() {
N.style.opacity = H.opacity;
b(O, N, L);
setTimeout(function() {
n(O, N, J, K);
setTimeout(function() {
y(O, N, L);
B(O, N, I, H, L, J, function() {
x(O);
t(O, N, J, K);
setTimeout(function() {
v(O, N, G, F, L);
d(O, N, G, F);
setTimeout(function() {
c(O, N, G, F);
M()
}, 0)
}, 0)
})
}, 0)
}, 50)
}, 0)
}
function C(G, F, I, H) {
var J = G.getBoundingClientRect();
if (I.display !== "none") {
if (p) {
F.style.position = "absolute"
} else {
F.style.position = "fixed"
}
F.style.top = J.top + "px";
F.style.left = J.left + "px"
}
F.style.height = H.height || I.height;
F.style.width = H.width || I.width
}
function d(G, F, I, H) {
F.style.position = H.position;
F.style.top = H.top;
F.style.left = H.left;
F.style.height = H.height;
F.style.width = H.width
}
function b(G, F, H) {
g(G, a);
g(F, H[0].transform || a);
if (H[0].fade) {
F.style.opacity = "0"
}
if (H[1].fade) {
G.style.opacity = "1"
}
}
function y(G, F, H) {
g(G, H[1].transform || a);
g(F, a);
if (H[0].fade) {
F.style.opacity = "1"
}
if (H[1].fade) {
G.style.opacity = "0"
}
}
function v(G, F, I, H, J) {
g(G, "");
g(F, "");
if (J[0].fade) {
F.style.opacity = H.opacity
}
if (J[1].fade) {
G.style.opacity = I.opacity
}
}
function n(G, F, H, J) {
var I = "transform " + (H / 1000) + "s " + J + ",opacity " + (H / 1000) + "s " + J;
h(G, I);
h(F, I)
}
function t(G, F, H, I) {
h(G, "");
h(F, "")
}
function u(G, F) {
h(G, "");
h(F, "")
}
function c(G, F, I, H) {
G.style["-webkit-transition"] = I["-webkit-transition"];
G.style["-moz-transition"] = I["-moz-transition"];
G.style["-ms-transition"] = I["-ms-transition"];
G.style["-o-transition"] = I["-o-transition"];
G.style.transition = I.transition;
F.style["-webkit-transition"] = H["-webkit-transition"];
F.style["-moz-transition"] = H["-moz-transition"];
F.style["-ms-transition"] = H["-ms-transition"];
F.style["-o-transition"] = H["-o-transition"];
F.style.transition = H.transition
}
function i(F, G) {
if (F.display === "none") {
return false
}
if (G.fade) {
return true
}
if (!G.transform) {
return false
} else {
if (G.transform === a) {
return false
} else {
return true
}
}
}
function B(Q, N, H, F, K, I, M) {
var G;
if (i(F, K[0])) {
G = N;
P()
} else {
if (i(H, K[1])) {
G = Q;
P()
} else {
setTimeout(L, I)
}
}
function P() {
G.addEventListener("webkitTransitionEnd", L, false);
G.addEventListener("transitionend", L, false);
G.addEventListener("oTransitionEnd", L, false);
G.addEventListener("otransitionend", L, false);
G.addEventListener("MSTransitionEnd", L, false);
G.addEventListener("transitionend", L, false)
}
function O() {
G.removeEventListener("webkitTransitionEnd", L);
G.removeEventListener("transitionend", L);
G.removeEventListener("oTransitionEnd", L);
G.removeEventListener("otransitionend", L);
G.removeEventListener("MSTransitionEnd", L);
G.removeEventListener("transitionend", L)
}
var J = false;
function L(R) {
if (J || !R || !R.target || (R.target !== G)) {
return
}
J = true;
if (G) {
O()
}
M()
}
}
return r
}(Swapper._os, Swapper._isNode, Swapper._isInDOM, Swapper._insertBefore, Swapper._insertAfter, Swapper._removeNode, Swapper._setTransform, Swapper._setTransition, Swapper._getStyles, Swapper._transitions, Swapper._easings, Swapper._validate, window, document);
var Clickable = function(c, b) {
function a() {
a._enableClicking.apply(this, arguments)
}
a.touchable = function() {
return a._os.touchable
};
a.sticky = function() {
a._enableStickyClick.apply(this, arguments)
};
a.unsticky = function(d) {
if (typeof d === "object" && d && typeof d._removeStickyClick === "function") {
d._removeStickyClick()
}
};
if (b && b.fn) {
b.fn.clickable = function(d) {
this.each(function() {
a._enableClicking(this, d)
});
return this
};
b.fn.stickyClick = function(d) {
this.each(function() {
a._enableStickyClick(this, d)
});
return this
};
b.fn.unstickyClick = function(d) {
this.each(function() {
a.unsticky(this)
});
return this
}
}
if (c && c.fn) {
c.extend(c.fn, {
clickable: function(d) {
this.forEach(function(e) {
a._enableClicking(e, d)
});
return this
},
stickyClick: function(d) {
this.forEach(function(e) {
a._enableStickyClick(e, d)
});
return this
},
unstickyClick: function(d) {
this.forEach(function(e) {
a.unsticky(this)
});
return this
}
})
}
return a
}(window.Zepto, window.jQuery);
Clickable._os = function(f, d) {
var c, a, b;
if (b = /\bCPU.*OS (\d+(_\d+)?)/i.exec(f)) {
c = "ios";
a = b[1].replace("_", ".")
} else {
if (b = /\bAndroid (\d+(\.\d+)?)/.exec(f)) {
c = "android";
a = b[1]
}
}
var e = {
name: c,
version: a && d(a),
touchable: !!c
};
e[c] = true;
return e
}(navigator.userAgent, parseFloat);
Clickable._trimString = function(a) {
var b = /^\s+|\s+$/g;
return function(c) {
return a(c).replace(b, "")
}
}(String);
Clickable._isDOMNode = function(a, b) {
return function(d) {
if (!d) {
return false
}
try {
return (d instanceof a) || (d instanceof b)
} catch (c) {}
if (typeof d !== "object") {
return false
}
if (typeof d.nodeType !== "number") {
return false
}
if (typeof d.nodeName !== "string") {
return false
}
return true
}
}(Node, HTMLElement);
Clickable._isInDOM = function() {
return function(a) {
while (a = a.parentNode) {
if (a === document) {
return true
}
}
return false
}
}();
Clickable._bindEvents = function() {
return function(c, b) {
for (var a in b) {
if (c.addEventListener) {
c.addEventListener(a, b[a], false)
} else {
if (c.attachEvent) {
c.attachEvent("on" + a, b[a])
}
}
}
}
}();
Clickable._unbindEvents = function() {
return function(c, b) {
for (var a in b) {
if (c.removeEventListener) {
c.removeEventListener(a, b[a])
}
}
}
}();
Clickable._addClass = function() {
return function(b, a) {
b.className += " " + a
}
}();
Clickable._removeClass = function(a) {
return function(c, b) {
c.className = a(c.className.replace(new RegExp("\\b" + b + "\\b"), ""))
}
}(Clickable._trimString);
Clickable._enableClicking = function(h, o, a, f, c, k, n) {
var i = "active",
m = "data-clickable-class",
g = 40;
var p = false,
l = !!h.ios;
function b(L, O) {
if (!o(L)) {
throw TypeError("element " + L + " must be a DOM element")
}
if (L._clickable) {
return
}
L._clickable = true;
switch (typeof O) {
case "undefined":
O = i;
break;
case "string":
break;
default:
throw TypeError("active class " + O + " must be a string")
}
var E = false,
q = false,
G, F, J, K, s;
L.setAttribute(m, O);
L.style["-webkit-tap-highlight-color"] = "rgba(255,255,255,0)";
v();
return;
function M(Q, R) {
E = true;
J = +new Date();
G = Q;
F = R;
K = j(L);
if (K) {
s = K.scrollTop;
K.addEventListener("scroll", A, true)
}
}
function I() {
if (K) {
K.removeEventListener("scroll", A)
}
K = null;
s = null;
G = null;
F = null;
E = false
}
function A() {
B()
}
function P() {
return E
}
function t() {
k(L, O)
}
function r() {
n(L, O)
}
function v() {
f(L, {
click: x
});
if (!h.touchable) {
f(L, {
mousedown: C,
mousemove: D,
mouseout: D,
mouseup: z
});
return
}
if (h.ios) {
f(L, {
DOMNodeInsertedIntoDocument: N,
DOMNodeRemovedFromDocument: y
});
if (a(L)) {
N()
}
} else {
N()
}
}
function N() {
f(L, {
touchstart: w,
touchmove: H,
touchcancel: B,
touchend: u
})
}
function y() {
c(L, {
touchstart: w,
touchmove: H,
touchcancel: B,
touchend: u
})
}
function x(Q) {
Q = Q || window.event;
if (!L.disabled && q) {
q = false;
setTimeout(function() {
p = false
}, 0)
} else {
if (Q.stopImmediatePropagation) {
Q.stopImmediatePropagation()
}
Q.preventDefault();
Q.stopPropagation();
Q.cancelBubble = true;
Q.returnValue = false;
return false
}
}
function C(Q) {
q = false;
if (L.disabled || !e(Q.target, L)) {
Q.preventDefault();
I();
return
}
M(Q.clientX, Q.clientY);
t()
}
function D(Q) {
Q.preventDefault();
I();
q = false;
r()
}
function z(Q) {
if (L.disabled) {
Q.preventDefault();
I();
q = false;
return
}
if (!P()) {
Q.preventDefault();
q = false
} else {
q = true
}
I();
r()
}
function w(Q) {
q = false;
if (p || L.disabled || (Q.touches.length !== 1) || !e(Q.target, L)) {
I();
return
}
p = true;
var R = Q.changedTouches[0];
M(R.clientX, R.clientY);
if (K) {
if (K._isScrolling || (s < 0) || (K.scrollHeight < s)) {
I();
return
}
}
var R = J;
setTimeout(function() {
if (P() && (R === J)) {
t()
}
}, g)
}
function B(Q) {
q = false;
I();
if (Q) {
p = false
}
if (L.disabled) {
return
}
r()
}
function H(R) {
var Q = document.elementFromPoint(R.touches[0].pageX, R.touches[0].pageY);
if (L !== Q) {
B(R)
}
}
function u(V) {
var R = P(),
S = K,
T = s,
Q = G,
W = F;
B();
if (!R || L.disabled) {
p = false;
return
}
if (S) {
if (S._isScrolling || (S.scrollTop !== T)) {
return
}
}
if (!V.stopImmediatePropagation) {
q = true;
return
}
var U = +new Date() - J;
if (U > g) {
q = true;
d(L, Q, W)
} else {
t();
setTimeout(function() {
r();
q = true;
d(L, Q, W)
}, 1)
}
}
}
function e(r, q) {
do {
if (r === q) {
return true
} else {
if (r._clickable) {
return false
}
}
} while (r = r.parentNode);
return false
}
function d(s, q, t) {
var r = document.createEvent("MouseEvents");
r.initMouseEvent("click", true, true, window, 1, q || 0, t || 0, q || 0, t || 0, false, false, false, false, 0, null);
s.dispatchEvent(r)
}
function j(q) {
if (!h.ios || (h.version < 5)) {
return
}
while (q = q.parentNode) {
if (q._scrollable) {
if (q._iScroll) {
return
}
return q
}
}
}
return b
}(Clickable._os, Clickable._isDOMNode, Clickable._isInDOM, Clickable._bindEvents, Clickable._unbindEvents, Clickable._addClass, Clickable._removeClass);
Clickable._enableStickyClick = function(a, c, f) {
var d = "data-clickable-class";
function e(i, h, g) {
if (!c(i)) {
throw TypeError("button must be a DOM element, got " + i)
}
switch (typeof h) {
case "string":
break;
case "function":
g = h;
h = undefined;
break;
default:
throw TypeError("button active class must be a string if defined, got " + h)
}
if (typeof g !== "function") {
throw TypeError("sticky click handler must be a function, got " + g)
}
f(i, h);
var j = b(i, g);
i.addEventListener("click", j, false);
if (i._removeStickyClick) {
i._removeStickyClick = function() {
i.removeEventListener("click", j)
}
}
}
function b(i, h) {
var j = false,
g = i.getAttribute(d);
return function() {
if (j) {
return
}
j = true;
var k = false,
n;
i.disabled = true;
i.className += " " + g;
try {
n = h.call(i, m)
} catch (l) {
if (window.console && window.console.error) {
if ((typeof l === "object") && l.stack) {
window.console.error(l.stack)
} else {
window.console.error(l + "")
}
}
m()
}
if (n === false) {
m()
}
function m() {
if (k) {
return
}
k = true;
j = false;
if (i.disabled) {
i.disabled = false;
i.className = a(i.className.replace(new RegExp("\\b" + g + "\\b", "g"), ""))
}
}
}
}
return e
}(Clickable._trimString, Clickable._isDOMNode, Clickable._enableClicking);
var iScroll = function(an, Z) {
function ah(f) {
if ("" === am) {
return f
}
f = f.charAt(0).toUpperCase() + f.substr(1);
return am + f
}
var ao = Math,
P = Z.createElement("div").style,
am;
a: {
for (var aj = ["t", "webkitT", "MozT", "msT", "OT"], Y, X = 0, k = aj.length; X < k; X++) {
if (Y = aj[X] + "ransform", Y in P) {
am = aj[X].substr(0, aj[X].length - 1);
break a
}
}
am = !1
}
var ak = am ? "-" + am.toLowerCase() + "-" : "",
ai = ah("transform"),
g = ah("transitionProperty"),
ad = ah("transitionDuration"),
e = ah("transformOrigin"),
d = ah("transitionTimingFunction"),
i = ah("transitionDelay"),
ag = /android/gi.test(navigator.appVersion),
W = /iphone|ipad/gi.test(navigator.appVersion),
aj = /hp-tablet/gi.test(navigator.appVersion),
V = ah("perspective") in P,
al = "ontouchstart" in an && !aj,
T = !!am,
c = ah("transition") in P,
af = "onorientationchange" in an ? "orientationchange" : "resize",
ac = al ? "touchstart" : "mousedown",
U = al ? "touchmove" : "mousemove",
S = al ? "touchend" : "mouseup",
R = al ? "touchcancel" : "mouseup",
ab = "Moz" == am ? "DOMMouseScroll" : "mousewheel",
aa;
aa = !1 === am ? !1 : {
"": "transitionend",
webkit: "webkitTransitionEnd",
Moz: "transitionend",
O: "oTransitionEnd",
ms: "MSTransitionEnd"
}[am];
var b = an.requestAnimationFrame || an.webkitRequestAnimationFrame || an.mozRequestAnimationFrame || an.oRequestAnimationFrame || an.msRequestAnimationFrame || function(f) {
return setTimeout(f, 1)
},
Q = an.cancelRequestAnimationFrame || an.webkitCancelAnimationFrame || an.webkitCancelRequestAnimationFrame || an.mozCancelRequestAnimationFrame || an.oCancelRequestAnimationFrame || an.msCancelRequestAnimationFrame || clearTimeout,
ae = V ? " translateZ(0)" : "",
aj = function(f, h) {
var l = this,
j;
l.wrapper = "object" == typeof f ? f : Z.getElementById(f);
l.wrapper.style.overflow = "hidden";
l.scroller = l.wrapper.children[0];
l.options = {
hScroll: !0,
vScroll: !0,
x: 0,
y: 0,
bounce: !0,
bounceLock: !1,
momentum: !0,
lockDirection: !0,
useTransform: !0,
useTransition: !1,
topOffset: 0,
checkDOMChanges: !1,
handleClick: !0,
hScrollbar: !0,
vScrollbar: !0,
fixedScrollbar: ag,
hideScrollbar: W,
fadeScrollbar: W && V,
scrollbarClass: "",
zoom: !1,
zoomMin: 1,
zoomMax: 4,
doubleTapZoom: 2,
wheelAction: "scroll",
snap: !1,
snapThreshold: 1,
onRefresh: null,
onBeforeScrollStart: function(m) {
m.preventDefault()
},
onScrollStart: null,
onBeforeScrollMove: null,
onScrollMove: null,
onBeforeScrollEnd: null,
onScrollEnd: null,
onTouchEnd: null,
onDestroy: null,
onZoomStart: null,
onZoom: null,
onZoomEnd: null
};
for (j in h) {
l.options[j] = h[j]
}
l.x = l.options.x;
l.y = l.options.y;
l.options.useTransform = T && l.options.useTransform;
l.options.hScrollbar = l.options.hScroll && l.options.hScrollbar;
l.options.vScrollbar = l.options.vScroll && l.options.vScrollbar;
l.options.zoom = l.options.useTransform && l.options.zoom;
l.options.useTransition = c && l.options.useTransition;
l.options.zoom && ag && (ae = "");
l.scroller.style[g] = l.options.useTransform ? ak + "transform" : "top left";
l.scroller.style[ad] = "0";
l.scroller.style[e] = "0 0";
l.options.useTransition && (l.scroller.style[d] = "cubic-bezier(0.33,0.66,0.66,1)");
l.options.useTransform ? l.scroller.style[ai] = "translate(" + l.x + "px," + l.y + "px)" + ae : l.scroller.style.cssText += ";position:absolute;top:" + l.y + "px;left:" + l.x + "px";
l.options.useTransition && (l.options.fixedScrollbar = !0);
l.refresh();
l._bind(af, an);
l._bind(ac);
al || (l._bind("mouseout", l.wrapper), "none" != l.options.wheelAction && l._bind(ab));
l.options.checkDOMChanges && (l.checkDOMTime = setInterval(function() {
l._checkDOMChanges()
}, 500))
};
aj.prototype = {
enabled: !0,
x: 0,
y: 0,
steps: [],
scale: 1,
currPageX: 0,
currPageY: 0,
pagesX: [],
pagesY: [],
aniTime: null,
wheelZoomCount: 0,
handleEvent: function(f) {
switch (f.type) {
case ac:
if (!al && 0 !== f.button) {
break
}
this._start(f);
break;
case U:
this._move(f);
break;
case S:
case R:
this._end(f);
break;
case af:
this._resize();
break;
case ab:
this._wheel(f);
break;
case "mouseout":
this._mouseout(f);
break;
case aa:
this._transitionEnd(f)
}
},
_checkDOMChanges: function() {
!this.moved && (!this.zoomed && !(this.animating || this.scrollerW == this.scroller.offsetWidth * this.scale && this.scrollerH == this.scroller.offsetHeight * this.scale)) && this.refresh()
},
_scrollbar: function(f) {
var h;
this[f + "Scrollbar"] ? (this[f + "ScrollbarWrapper"] || (h = Z.createElement("div"), this.options.scrollbarClass ? h.className = this.options.scrollbarClass + f.toUpperCase() : h.style.cssText = "position:absolute;z-index:100;" + ("h" == f ? "height:7px;bottom:1px;left:2px;right:" + (this.vScrollbar ? "7" : "2") + "px" : "width:7px;bottom:" + (this.hScrollbar ? "7" : "2") + "px;top:2px;right:1px"), h.style.cssText += ";pointer-events:none;" + ak + "transition-property:opacity;" + ak + "transition-duration:" + (this.options.fadeScrollbar ? "350ms" : "0") + ";overflow:hidden;opacity:" + (this.options.hideScrollbar ? "0" : "1"), this.wrapper.appendChild(h), this[f + "ScrollbarWrapper"] = h, h = Z.createElement("div"), this.options.scrollbarClass || (h.style.cssText = "position:absolute;z-index:100;background:rgba(0,0,0,0.5);border:1px solid rgba(255,255,255,0.9);" + ak + "background-clip:padding-box;" + ak + "box-sizing:border-box;" + ("h" == f ? "height:100%" : "width:100%") + ";" + ak + "border-radius:3px;border-radius:3px"), h.style.cssText += ";pointer-events:none;" + ak + "transition-property:" + ak + "transform;" + ak + "transition-timing-function:cubic-bezier(0.33,0.66,0.66,1);" + ak + "transition-duration:0;" + ak + "transform: translate(0,0)" + ae, this.options.useTransition && (h.style.cssText += ";" + ak + "transition-timing-function:cubic-bezier(0.33,0.66,0.66,1)"), this[f + "ScrollbarWrapper"].appendChild(h), this[f + "ScrollbarIndicator"] = h), "h" == f ? (this.hScrollbarSize = this.hScrollbarWrapper.clientWidth, this.hScrollbarIndicatorSize = ao.max(ao.round(this.hScrollbarSize * this.hScrollbarSize / this.scrollerW), 8), this.hScrollbarIndicator.style.width = this.hScrollbarIndicatorSize + "px", this.hScrollbarMaxScroll = this.hScrollbarSize - this.hScrollbarIndicatorSize, this.hScrollbarProp = this.hScrollbarMaxScroll / this.maxScrollX) : (this.vScrollbarSize = this.vScrollbarWrapper.clientHeight, this.vScrollbarIndicatorSize = ao.max(ao.round(this.vScrollbarSize * this.vScrollbarSize / this.scrollerH), 8), this.vScrollbarIndicator.style.height = this.vScrollbarIndicatorSize + "px", this.vScrollbarMaxScroll = this.vScrollbarSize - this.vScrollbarIndicatorSize, this.vScrollbarProp = this.vScrollbarMaxScroll / this.maxScrollY), this._scrollbarPos(f, !0)) : this[f + "ScrollbarWrapper"] && (T && (this[f + "ScrollbarIndicator"].style[ai] = ""), this[f + "ScrollbarWrapper"].parentNode.removeChild(this[f + "ScrollbarWrapper"]), this[f + "ScrollbarWrapper"] = null, this[f + "ScrollbarIndicator"] = null)
},
_resize: function() {
var f = this;
setTimeout(function() {
f.refresh()
}, ag ? 200 : 0)
},
_pos: function(f, h) {
this.zoomed || (f = this.hScroll ? f : 0, h = this.vScroll ? h : 0, this.options.useTransform ? this.scroller.style[ai] = "translate(" + f + "px," + h + "px) scale(" + this.scale + ")" + ae : (f = ao.round(f), h = ao.round(h), this.scroller.style.left = f + "px", this.scroller.style.top = h + "px"), this.x = f, this.y = h, this._scrollbarPos("h"), this._scrollbarPos("v"))
},
_scrollbarPos: function(f, h) {
var j = "h" == f ? this.x : this.y;
this[f + "Scrollbar"] && (j *= this[f + "ScrollbarProp"], 0 > j ? (this.options.fixedScrollbar || (j = this[f + "ScrollbarIndicatorSize"] + ao.round(3 * j), 8 > j && (j = 8), this[f + "ScrollbarIndicator"].style["h" == f ? "width" : "height"] = j + "px"), j = 0) : j > this[f + "ScrollbarMaxScroll"] && (this.options.fixedScrollbar ? j = this[f + "ScrollbarMaxScroll"] : (j = this[f + "ScrollbarIndicatorSize"] - ao.round(3 * (j - this[f + "ScrollbarMaxScroll"])), 8 > j && (j = 8), this[f + "ScrollbarIndicator"].style["h" == f ? "width" : "height"] = j + "px", j = this[f + "ScrollbarMaxScroll"] + (this[f + "ScrollbarIndicatorSize"] - j))), this[f + "ScrollbarWrapper"].style[i] = "0", this[f + "ScrollbarWrapper"].style.opacity = h && this.options.hideScrollbar ? "0" : "1", this[f + "ScrollbarIndicator"].style[ai] = "translate(" + ("h" == f ? j + "px,0)" : "0," + j + "px)") + ae)
},
_start: function(f) {
var h = al ? f.touches[0] : f,
l, j;
if (this.enabled) {
this.options.onBeforeScrollStart && this.options.onBeforeScrollStart.call(this, f);
(this.options.useTransition || this.options.zoom) && this._transitionTime(0);
this.zoomed = this.animating = this.moved = !1;
this.dirY = this.dirX = this.absDistY = this.absDistX = this.distY = this.distX = 0;
this.options.zoom && (al && 1 < f.touches.length) && (j = ao.abs(f.touches[0].pageX - f.touches[1].pageX), l = ao.abs(f.touches[0].pageY - f.touches[1].pageY), this.touchesDistStart = ao.sqrt(j * j + l * l), this.originX = ao.abs(f.touches[0].pageX + f.touches[1].pageX - 2 * this.wrapperOffsetLeft) / 2 - this.x, this.originY = ao.abs(f.touches[0].pageY + f.touches[1].pageY - 2 * this.wrapperOffsetTop) / 2 - this.y, this.options.onZoomStart && this.options.onZoomStart.call(this, f));
if (this.options.momentum && (this.options.useTransform ? (l = getComputedStyle(this.scroller, null)[ai].replace(/[^0-9\-.,]/g, "").split(","), j = 1 * l[4], l = 1 * l[5]) : (j = 1 * getComputedStyle(this.scroller, null).left.replace(/[^0-9-]/g, ""), l = 1 * getComputedStyle(this.scroller, null).top.replace(/[^0-9-]/g, "")), j != this.x || l != this.y)) {
this.options.useTransition ? this._unbind(aa) : Q(this.aniTime), this.steps = [], this._pos(j, l)
}
this.absStartX = this.x;
this.absStartY = this.y;
this.startX = this.x;
this.startY = this.y;
this.pointX = h.pageX;
this.pointY = h.pageY;
this.startTime = f.timeStamp || Date.now();
this.options.onScrollStart && this.options.onScrollStart.call(this, f);
this._bind(U);
this._bind(S);
this._bind(R)
}
},
_move: function(f) {
var h = al ? f.touches[0] : f,
o = h.pageX - this.pointX,
n = h.pageY - this.pointY,
m = this.x + o,
l = this.y + n,
j = f.timeStamp || Date.now();
this.options.onBeforeScrollMove && this.options.onBeforeScrollMove.call(this, f);
if (this.options.zoom && al && 1 < f.touches.length) {
m = ao.abs(f.touches[0].pageX - f.touches[1].pageX), l = ao.abs(f.touches[0].pageY - f.touches[1].pageY), this.touchesDist = ao.sqrt(m * m + l * l), this.zoomed = !0, h = 1 / this.touchesDistStart * this.touchesDist * this.scale, h < this.options.zoomMin ? h = 0.5 * this.options.zoomMin * Math.pow(2, h / this.options.zoomMin) : h > this.options.zoomMax && (h = 2 * this.options.zoomMax * Math.pow(0.5, this.options.zoomMax / h)), this.lastScale = h / this.scale, m = this.originX - this.originX * this.lastScale + this.x, l = this.originY - this.originY * this.lastScale + this.y, this.scroller.style[ai] = "translate(" + m + "px," + l + "px) scale(" + h + ")" + ae, this.options.onZoom && this.options.onZoom.call(this, f)
} else {
this.pointX = h.pageX;
this.pointY = h.pageY;
if (0 < m || m < this.maxScrollX) {
m = this.options.bounce ? this.x + o / 2 : 0 <= m || 0 <= this.maxScrollX ? 0 : this.maxScrollX
}
if (l > this.minScrollY || l < this.maxScrollY) {
l = this.options.bounce ? this.y + n / 2 : l >= this.minScrollY || 0 <= this.maxScrollY ? this.minScrollY : this.maxScrollY
}
this.distX += o;
this.distY += n;
this.absDistX = ao.abs(this.distX);
this.absDistY = ao.abs(this.distY);
6 > this.absDistX && 6 > this.absDistY || (this.options.lockDirection && (this.absDistX > this.absDistY + 5 ? (l = this.y, n = 0) : this.absDistY > this.absDistX + 5 && (m = this.x, o = 0)), this.moved = !0, this._pos(m, l), this.dirX = 0 < o ? -1 : 0 > o ? 1 : 0, this.dirY = 0 < n ? -1 : 0 > n ? 1 : 0, 300 < j - this.startTime && (this.startTime = j, this.startX = this.x, this.startY = this.y), this.options.onScrollMove && this.options.onScrollMove.call(this, f))
}
},
_end: function(s) {
if (!(al && 0 !== s.touches.length)) {
var t = this,
r = al ? s.changedTouches[0] : s,
q, p, o = {
dist: 0,
time: 0
},
m = {
dist: 0,
time: 0
},
n = (s.timeStamp || Date.now()) - t.startTime,
f = t.x,
l = t.y;
t._unbind(U);
t._unbind(S);
t._unbind(R);
t.options.onBeforeScrollEnd && t.options.onBeforeScrollEnd.call(t, s);
if (t.zoomed) {
f = t.scale * t.lastScale, f = Math.max(t.options.zoomMin, f), f = Math.min(t.options.zoomMax, f), t.lastScale = f / t.scale, t.scale = f, t.x = t.originX - t.originX * t.lastScale + t.x, t.y = t.originY - t.originY * t.lastScale + t.y, t.scroller.style[ad] = "200ms", t.scroller.style[ai] = "translate(" + t.x + "px," + t.y + "px) scale(" + t.scale + ")" + ae, t.zoomed = !1, t.refresh(), t.options.onZoomEnd && t.options.onZoomEnd.call(t, s)
} else {
if (t.moved) {
if (300 > n && t.options.momentum) {
o = f ? t._momentum(f - t.startX, n, -t.x, t.scrollerW - t.wrapperW + t.x, t.options.bounce ? t.wrapperW : 0) : o;
m = l ? t._momentum(l - t.startY, n, -t.y, 0 > t.maxScrollY ? t.scrollerH - t.wrapperH + t.y - t.minScrollY : 0, t.options.bounce ? t.wrapperH : 0) : m;
f = t.x + o.dist;
l = t.y + m.dist;
if (0 < t.x && 0 < f || t.x < t.maxScrollX && f < t.maxScrollX) {
o = {
dist: 0,
time: 0
}
}
if (t.y > t.minScrollY && l > t.minScrollY || t.y < t.maxScrollY && l < t.maxScrollY) {
m = {
dist: 0,
time: 0
}
}
}
o.dist || m.dist ? (o = ao.max(ao.max(o.time, m.time), 10), t.options.snap && (m = f - t.absStartX, n = l - t.absStartY, ao.abs(m) < t.options.snapThreshold && ao.abs(n) < t.options.snapThreshold ? t.scrollTo(t.absStartX, t.absStartY, 200) : (m = t._snap(f, l), f = m.x, l = m.y, o = ao.max(m.time, o))), t.scrollTo(ao.round(f), ao.round(l), o)) : t.options.snap ? (m = f - t.absStartX, n = l - t.absStartY, ao.abs(m) < t.options.snapThreshold && ao.abs(n) < t.options.snapThreshold ? t.scrollTo(t.absStartX, t.absStartY, 200) : (m = t._snap(t.x, t.y), (m.x != t.x || m.y != t.y) && t.scrollTo(m.x, m.y, m.time))) : t._resetPos(200)
} else {
al && (t.doubleTapTimer && t.options.zoom ? (clearTimeout(t.doubleTapTimer), t.doubleTapTimer = null, t.options.onZoomStart && t.options.onZoomStart.call(t, s), t.zoom(t.pointX, t.pointY, 1 == t.scale ? t.options.doubleTapZoom : 1), t.options.onZoomEnd && setTimeout(function() {
t.options.onZoomEnd.call(t, s)
}, 200)) : this.options.handleClick && (t.doubleTapTimer = setTimeout(function() {
t.doubleTapTimer = null;
for (q = r.target; 1 != q.nodeType;) {
q = q.parentNode
}
"SELECT" != q.tagName && ("INPUT" != q.tagName && "TEXTAREA" != q.tagName) && (p = Z.createEvent("MouseEvents"), p.initMouseEvent("click", !0, !0, s.view, 1, r.screenX, r.screenY, r.clientX, r.clientY, s.ctrlKey, s.altKey, s.shiftKey, s.metaKey, 0, null), p._fake = !0, q.dispatchEvent(p))
}, t.options.zoom ? 250 : 0))), t._resetPos(200)
}
t.options.onTouchEnd && t.options.onTouchEnd.call(t, s)
}
}
},
_resetPos: function(f) {
var h = 0 <= this.x ? 0 : this.x < this.maxScrollX ? this.maxScrollX : this.x,
j = this.y >= this.minScrollY || 0 < this.maxScrollY ? this.minScrollY : this.y < this.maxScrollY ? this.maxScrollY : this.y;
if (h == this.x && j == this.y) {
if (this.moved && (this.moved = !1, this.options.onScrollEnd && this.options.onScrollEnd.call(this)), this.hScrollbar && this.options.hideScrollbar && ("webkit" == am && (this.hScrollbarWrapper.style[i] = "300ms"), this.hScrollbarWrapper.style.opacity = "0"), this.vScrollbar && this.options.hideScrollbar) {
"webkit" == am && (this.vScrollbarWrapper.style[i] = "300ms"), this.vScrollbarWrapper.style.opacity = "0"
}
} else {
this.scrollTo(h, j, f || 0)
}
},
_wheel: function(f) {
var h = this,
l, j;
if ("wheelDeltaX" in f) {
l = f.wheelDeltaX / 12, j = f.wheelDeltaY / 12
} else {
if ("wheelDelta" in f) {
l = j = f.wheelDelta / 12
} else {
if ("detail" in f) {
l = j = 3 * -f.detail
} else {
return
}
}
}
if ("zoom" == h.options.wheelAction) {
if (j = h.scale * Math.pow(2, 1 / 3 * (j ? j / Math.abs(j) : 0)), j < h.options.zoomMin && (j = h.options.zoomMin), j > h.options.zoomMax && (j = h.options.zoomMax), j != h.scale) {
!h.wheelZoomCount && h.options.onZoomStart && h.options.onZoomStart.call(h, f), h.wheelZoomCount++, h.zoom(f.pageX, f.pageY, j, 400), setTimeout(function() {
h.wheelZoomCount--;
!h.wheelZoomCount && h.options.onZoomEnd && h.options.onZoomEnd.call(h, f)
}, 400)
}
} else {
l = h.x + l, j = h.y + j, 0 < l ? l = 0 : l < h.maxScrollX && (l = h.maxScrollX), j > h.minScrollY ? j = h.minScrollY : j < h.maxScrollY && (j = h.maxScrollY), 0 > h.maxScrollY && h.scrollTo(l, j, 0)
}
},
_mouseout: function(f) {
var h = f.relatedTarget;
if (h) {
for (; h = h.parentNode;) {
if (h == this.wrapper) {
return
}
}
}
this._end(f)
},
_transitionEnd: function(f) {
f.target == this.scroller && (this._unbind(aa), this._startAni())
},
_startAni: function() {
var f = this,
h = f.x,
o = f.y,
n = Date.now(),
m, l, j;
f.animating || (f.steps.length ? (m = f.steps.shift(), m.x == h && m.y == o && (m.time = 0), f.animating = !0, f.moved = !0, f.options.useTransition) ? (f._transitionTime(m.time), f._pos(m.x, m.y), f.animating = !1, m.time ? f._bind(aa) : f._resetPos(0)) : (j = function() {
var q = Date.now(),
p;
if (q >= n + m.time) {
f._pos(m.x, m.y);
f.animating = false;
f.options.onAnimationEnd && f.options.onAnimationEnd.call(f);
f._startAni()
} else {
q = (q - n) / m.time - 1;
l = ao.sqrt(1 - q * q);
q = (m.x - h) * l + h;
p = (m.y - o) * l + o;
f._pos(q, p);
if (f.animating) {
f.aniTime = b(j)
}
}
}, j()) : f._resetPos(400))
},
_transitionTime: function(f) {
f += "ms";
this.scroller.style[ad] = f;
this.hScrollbar && (this.hScrollbarIndicator.style[ad] = f);
this.vScrollbar && (this.vScrollbarIndicator.style[ad] = f)
},
_momentum: function(f, h, n, m, l) {
var h = ao.abs(f) / h,
j = h * h / 0.0012;
0 < f && j > n ? (n += l / (6 / (0.0006 * (j / h))), h = h * n / j, j = n) : 0 > f && j > m && (m += l / (6 / (0.0006 * (j / h))), h = h * m / j, j = m);
return {
dist: j * (0 > f ? -1 : 1),
time: ao.round(h / 0.0006)
}
},
_offset: function(f) {
for (var h = -f.offsetLeft, j = -f.offsetTop; f = f.offsetParent;) {
h -= f.offsetLeft, j -= f.offsetTop
}
f != this.wrapper && (h *= this.scale, j *= this.scale);
return {
left: h,
top: j
}
},
_snap: function(f, h) {
var m, l, j;
j = this.pagesX.length - 1;
m = 0;
for (l = this.pagesX.length; m < l; m++) {
if (f >= this.pagesX[m]) {
j = m;
break
}
}
j == this.currPageX && (0 < j && 0 > this.dirX) && j--;
f = this.pagesX[j];
l = (l = ao.abs(f - this.pagesX[this.currPageX])) ? 500 * (ao.abs(this.x - f) / l) : 0;
this.currPageX = j;
j = this.pagesY.length - 1;
for (m = 0; m < j; m++) {
if (h >= this.pagesY[m]) {
j = m;
break
}
}
j == this.currPageY && (0 < j && 0 > this.dirY) && j--;
h = this.pagesY[j];
m = (m = ao.abs(h - this.pagesY[this.currPageY])) ? 500 * (ao.abs(this.y - h) / m) : 0;
this.currPageY = j;
j = ao.round(ao.max(l, m)) || 200;
return {
x: f,
y: h,
time: j
}
},
_bind: function(f, h, j) {
(h || this.scroller).addEventListener(f, this, !!j)
},
_unbind: function(f, h, j) {
(h || this.scroller).removeEventListener(f, this, !!j)
},
destroy: function() {
this.scroller.style[ai] = "";
this.vScrollbar = this.hScrollbar = !1;
this._scrollbar("h");
this._scrollbar("v");
this._unbind(af, an);
this._unbind(ac);
this._unbind(U);
this._unbind(S);
this._unbind(R);
this.options.hasTouch || (this._unbind("mouseout", this.wrapper), this._unbind(ab));
this.options.useTransition && this._unbind(aa);
this.options.checkDOMChanges && clearInterval(this.checkDOMTime);
this.options.onDestroy && this.options.onDestroy.call(this)
},
refresh: function() {
var f, h, l, j = 0;
h = 0;
this.scale < this.options.zoomMin && (this.scale = this.options.zoomMin);
this.wrapperW = this.wrapper.clientWidth || 1;
this.wrapperH = this.wrapper.clientHeight || 1;
this.minScrollY = -this.options.topOffset || 0;
this.scrollerW = ao.round(this.scroller.offsetWidth * this.scale);
this.scrollerH = ao.round((this.scroller.offsetHeight + this.minScrollY) * this.scale);
this.maxScrollX = this.wrapperW - this.scrollerW;
this.maxScrollY = this.wrapperH - this.scrollerH + this.minScrollY;
this.dirY = this.dirX = 0;
this.options.onRefresh && this.options.onRefresh.call(this);
this.hScroll = this.options.hScroll && 0 > this.maxScrollX;
this.vScroll = this.options.vScroll && (!this.options.bounceLock && !this.hScroll || this.scrollerH > this.wrapperH);
this.hScrollbar = this.hScroll && this.options.hScrollbar;
this.vScrollbar = this.vScroll && this.options.vScrollbar && this.scrollerH > this.wrapperH;
f = this._offset(this.wrapper);
this.wrapperOffsetLeft = -f.left;
this.wrapperOffsetTop = -f.top;
if ("string" == typeof this.options.snap) {
this.pagesX = [];
this.pagesY = [];
l = this.scroller.querySelectorAll(this.options.snap);
f = 0;
for (h = l.length; f < h; f++) {
j = this._offset(l[f]), j.left += this.wrapperOffsetLeft, j.top += this.wrapperOffsetTop, this.pagesX[f] = j.left < this.maxScrollX ? this.maxScrollX : j.left * this.scale, this.pagesY[f] = j.top < this.maxScrollY ? this.maxScrollY : j.top * this.scale
}
} else {
if (this.options.snap) {
for (this.pagesX = []; j >= this.maxScrollX;) {
this.pagesX[h] = j, j -= this.wrapperW, h++
}
this.maxScrollX % this.wrapperW && (this.pagesX[this.pagesX.length] = this.maxScrollX - this.pagesX[this.pagesX.length - 1] + this.pagesX[this.pagesX.length - 1]);
h = j = 0;
for (this.pagesY = []; j >= this.maxScrollY;) {
this.pagesY[h] = j, j -= this.wrapperH, h++
}
this.maxScrollY % this.wrapperH && (this.pagesY[this.pagesY.length] = this.maxScrollY - this.pagesY[this.pagesY.length - 1] + this.pagesY[this.pagesY.length - 1])
}
}
this._scrollbar("h");
this._scrollbar("v");
this.zoomed || (this.scroller.style[ad] = "0", this._resetPos(200))
},
scrollTo: function(f, h, m, l) {
var j = f;
this.stop();
j.length || (j = [{
x: f,
y: h,
time: m,
relative: l
}]);
f = 0;
for (h = j.length; f < h; f++) {
j[f].relative && (j[f].x = this.x - j[f].x, j[f].y = this.y - j[f].y), this.steps.push({
x: j[f].x,
y: j[f].y,
time: j[f].time || 0
})
}
this._startAni()
},
scrollToElement: function(f, h) {
var j;
if (f = f.nodeType ? f : this.scroller.querySelector(f)) {
j = this._offset(f), j.left += this.wrapperOffsetLeft, j.top += this.wrapperOffsetTop, j.left = 0 < j.left ? 0 : j.left < this.maxScrollX ? this.maxScrollX : j.left, j.top = j.top > this.minScrollY ? this.minScrollY : j.top < this.maxScrollY ? this.maxScrollY : j.top, h = void 0 === h ? ao.max(2 * ao.abs(j.left), 2 * ao.abs(j.top)) : h, this.scrollTo(j.left, j.top, h)
}
},
scrollToPage: function(f, h, j) {
j = void 0 === j ? 400 : j;
this.options.onScrollStart && this.options.onScrollStart.call(this);
if (this.options.snap) {
f = "next" == f ? this.currPageX + 1 : "prev" == f ? this.currPageX - 1 : f, h = "next" == h ? this.currPageY + 1 : "prev" == h ? this.currPageY - 1 : h, f = 0 > f ? 0 : f > this.pagesX.length - 1 ? this.pagesX.length - 1 : f, h = 0 > h ? 0 : h > this.pagesY.length - 1 ? this.pagesY.length - 1 : h, this.currPageX = f, this.currPageY = h, f = this.pagesX[f], h = this.pagesY[h]
} else {
if (f *= -this.wrapperW, h *= -this.wrapperH, f < this.maxScrollX && (f = this.maxScrollX), h < this.maxScrollY) {
h = this.maxScrollY
}
}
this.scrollTo(f, h, j)
},
disable: function() {
this.stop();
this._resetPos(0);
this.enabled = !1;
this._unbind(U);
this._unbind(S);
this._unbind(R)
},
enable: function() {
this.enabled = !0
},
stop: function() {
this.options.useTransition ? this._unbind(aa) : Q(this.aniTime);
this.steps = [];
this.animating = this.moved = !1
},
zoom: function(f, h, m, l) {
var j = m / this.scale;
this.options.useTransform && (this.zoomed = !0, l = void 0 === l ? 200 : l, f = f - this.wrapperOffsetLeft - this.x, h = h - this.wrapperOffsetTop - this.y, this.x = f - f * j + this.x, this.y = h - h * j + this.y, this.scale = m, this.refresh(), this.x = 0 < this.x ? 0 : this.x < this.maxScrollX ? this.maxScrollX : this.x, this.y = this.y > this.minScrollY ? this.minScrollY : this.y < this.maxScrollY ? this.maxScrollY : this.y, this.scroller.style[ad] = l + "ms", this.scroller.style[ai] = "translate(" + this.x + "px," + this.y + "px) scale(" + m + ")" + ae, this.zoomed = !1)
},
isReady: function() {
return !this.moved && !this.zoomed && !this.animating
}
};
P = null;
return aj
}(window, document);
var Scrollable = function(h, g) {
function b() {
b._enableScrolling.apply(this, arguments)
}
b.node = function() {
return b._getScrollableNode.apply(this, arguments)
};
b.infinite = function() {
return b._enableInfiniteScrolling.apply(this, arguments)
};
if (h && h.fn) {
h.extend(h.fn, {
scrollable: function(i) {
this.forEach(function(j) {
b._enableScrolling(j, i)
});
return this
},
scrollableNode: function() {
return h(this.map(function() {
return b._getScrollableNode(this)
}))
},
scrollableInfinite: function(j, k) {
var i;
this.forEach(function(m) {
var l = b._enableInfiniteScrolling(m, j, k);
if (!i) {
i = l
}
});
return i
}
});
var d = h.fn.scrollTop,
f = h.fn.scrollLeft;
h.fn.scrollTop = function(k) {
if (typeof k === "undefined") {
var i = this[0],
j = b._isDOMNode(i);
if (j && i._scrollTop) {
return i._scrollTop()
} else {
if (d) {
return d.apply(this, arguments)
} else {
if (j) {
return i.scrollTop
} else {
return null
}
}
}
}
this.forEach(function(l) {
var m = b._isDOMNode(l);
if (m && l._scrollTop) {
l._scrollTop(k)
} else {
if (d) {
d.call(h(l), k)
} else {
if (m) {
l.scrollTop = k
}
}
}
});
return this
};
h.fn.scrollLeft = function(k) {
if (typeof k === "undefined") {
var i = this[0],
j = b._isDOMNode(i);
if (j && i._scrollLeft) {
return i._scrollLeft()
} else {
if (d) {
return f.apply(this, arguments)
} else {
if (j) {
return i.scrollLeft
} else {
return null
}
}
}
}
this.forEach(function(l) {
var m = b._isDOMNode(l);
if (m && l._scrollLeft) {
l._scrollLeft(k)
} else {
if (f) {
f.call(h(l), k)
} else {
if (m) {
l.scrollLeft = k
}
}
}
});
return this
}
}
if (g && g.fn) {
g.fn.scrollable = function(i) {
this.each(function() {
b._enableScrolling(this, i)
});
return this
};
g.fn.scrollableNode = function() {
return g(this.map(function() {
return b._getScrollableNode(this)
}))
};
g.fn.scrollableInfinite = function(j, k) {
var i;
this.each(function() {
var l = b._enableInfiniteScrolling(this, j, k);
if (!i) {
i = l
}
});
return i
};
var c = g.fn.scrollTop,
e = g.fn.scrollLeft;
g.fn.scrollTop = function(j) {
if (typeof j === "undefined") {
var i = this[0];
if (b._isDOMNode(i) && i._scrollTop) {
return i._scrollTop()
} else {
return c.apply(this, arguments)
}
}
this.each(function() {
if (b._isDOMNode(this) && this._scrollTop) {
this._scrollTop(j)
} else {
c.call(g(this), j)
}
});
return this
};
g.fn.scrollLeft = function(j) {
if (typeof j === "undefined") {
var i = this[0];
if (b._isDOMNode(i) && i._scrollLeft) {
return i._scrollLeft()
} else {
return e.apply(this, arguments)
}
}
this.each(function() {
if (b._isDOMNode(this) && this._scrollLeft) {
this._scrollLeft(j)
} else {
e.call(g(this), j)
}
});
return this
}
}
return b
}(window.Zepto, window.jQuery);
Scrollable._os = function(g, e) {
var d, b, c;
if (c = /\bCPU.*OS (\d+(_\d+)?)/i.exec(g)) {
d = "ios";
b = c[1].replace("_", ".")
} else {
if (c = /\bAndroid (\d+(\.\d+)?)/.exec(g)) {
d = "android";
b = c[1]
}
}
var f = {
name: d,
version: b && e(b),
mobile: !!d
};
f[d] = true;
return f
}(navigator.userAgent, parseFloat);
Scrollable._isArray = function(b) {
return function(c) {
if (b) {
return b(c)
} else {
return Object.prototype.toString.call(c) !== "[object Array]"
}
}
}(Array.isArray);
Scrollable._isDOMNode = function(b, c) {
return function(e) {
if (!e) {
return false
}
try {
return (e instanceof b) || (e instanceof c)
} catch (d) {}
if (typeof e !== "object") {
return false
}
if (typeof e.nodeType !== "number") {
return false
}
if (typeof e.nodeName !== "string") {
return false
}
return true
}
}(Node, HTMLElement);
Scrollable._isjQueryElem = function(b) {
if (typeof b !== "object" || b === null) {
return false
} else {
return (b.val && b.addClass && b.css && b.html && b.show)
}
};
Scrollable._findInArray = function(b) {
return function(d, f, g) {
if (b) {
return b.call(d, f, g)
}
for (var e = g || 0, c = d.length; e < c; e++) {
if ((e in d) && (d[e] === f)) {
return e
}
}
return -1
}
}(Array.prototype.indexOf);
Scrollable._forEachInArray = function(b) {
return function(d, g, e) {
if (b) {
return b.call(d, g, e)
}
for (var f = 0, c = d.length; f < c; f++) {
if (f in d) {
g.call(e, d[f], f, d)
}
}
}
}(Array.prototype.forEach);
Scrollable._onReady = function(c, d, i) {
var h = [],
g = false;
e(f);
return function(j) {
if (g) {
j()
} else {
h.push(j)
}
};
function f() {
if (g) {
return
}
g = true;
i(h, function(j) {
setTimeout(j, 0)
})
}
function b(k) {
try {
c.documentElement.doScroll("left")
} catch (j) {
setTimeout(function() {
b(k)
}, 1);
return
}
k()
}
function e(l) {
if (c.readyState === "complete") {
setTimeout(l, 0);
return
}
if (c.addEventListener) {
c.addEventListener("DOMContentLoaded", l, false);
d.addEventListener("load", l, false)
} else {
if (c.attachEvent) {
c.attachEvent("onreadystatechange", l);
d.attachEvent("onload", l);
var j = false;
try {
j = (d.frameElement === null)
} catch (k) {}
if (c.documentElement.doScroll && j) {
setTimeout(function() {
b(l)
}, 0)
}
}
}
}
}(document, window, Scrollable._forEachInArray);
Scrollable._scrollWatcher = function(b) {
return c;
function c(i) {
var j = false,
e = false,
l = i.scrollTop;
i.addEventListener("touchstart", h);
i.addEventListener("touchmove", d);
i.addEventListener("touchcancel", g);
i.addEventListener("touchend", o);
i.addEventListener("scroll", k);
n();
i._resetScrolling = f;
return;
function n() {
i._isScrolling = (e || j)
}
function f() {
e = false;
j = false;
n()
}
function m(r, q, p) {
if ((r.touches.length <= q) && ((typeof p === "undefined") || (r.changedTouches.length <= p))) {
return false
}
r.preventDefault();
f();
return true
}
function h(p) {
if (m(p, 1)) {
return
}
f()
}
function d(p) {
if (m(p, 1)) {
return
}
j = true;
l = i.scrollTop;
n()
}
function g(p) {
if (m(p, 0, 1)) {
return
}
f()
}
function o(p) {
if (m(p, 0, 1)) {
return
}
var q;
if (j) {
q = Math.abs(i.scrollTop - l);
if (q > 5) {
e = true
}
j = false;
n()
}
}
function k() {
if (!j && e) {
f()
}
}
}
}(Scrollable._os);
Scrollable._enableScrolling = function(f, o, k, e, d, p, m, n) {
var j = i();
return q;
function i() {
if ((f.ios && (f.version >= 5)) || (f.android && (f.version >= 4))) {
return true
} else {
return false
}
}
function q(t, s) {
if (!o(t)) {
throw t + " is not a DOM element"
}
if (t._scrollable) {
return
}
t._scrollable = true;
var r;
t._scrollTop = function(u, v) {
if (typeof u === "undefined") {
return r ? Math.max(parseInt(-r.y), 0) : t.scrollTop
}
if (!r && (!f.mobile || j)) {
t.scrollTop = u;
v && v();
return
}
k(function() {
r.scrollTo(r.x, Math.min(-u, 0), 1);
v && v()
})
};
t._scrollLeft = function(u) {
if (typeof u === "undefined") {
return r ? Math.max(parseInt(-r.x), 0) : t.scrollLeft
}
if (!r && (!f.mobile || j)) {
t.scrollLeft = u;
return
}
k(function() {
r.scrollTo(Math.min(-u, 0), r.y, 1)
})
};
t.style.overflow = "scroll";
if (!s) {
if (!f.mobile) {
return
}
if (j) {
t.style["-webkit-overflow-scrolling"] = "touch";
if (f.ios) {
d(t)
}
return
}
}
c(t, function(u) {
r = u
})
}
function c(s, t) {
s._iScroll = true;
l(s);
var r = g(s);
k(function() {
var u = new p(s, {
checkDOMChanges: true,
useTransform: true,
useTransition: true,
hScrollbar: false,
vScrollbar: false,
bounce: !!f.ios,
onScrollMove: r,
onBeforeScrollEnd: r,
onScrollEnd: function() {
s._iScrolling = false;
r()
},
onBeforeScrollStart: h,
onScrollStart: function() {
s._iScrolling = true
}
});
s._iScroll = u;
t(u)
})
}
function l(s) {
var t = n.createElement("div"),
r = Array.prototype.slice.call(s.childNodes || []);
e(r, function(v) {
var u = s.removeChild(v);
t.appendChild(u)
});
s.appendChild(t);
s.style.position = "relative";
t.style["min-height"] = "100%";
t.style["min-width"] = "100%"
}
function g(s) {
var r, t;
return function() {
var v = s._scrollTop(),
u = s._scrollLeft();
if ((v === r) && (u === t)) {
return
}
r = v;
t = u;
b(s)
}
}
function b(s) {
if (s.dispatchEvent) {
var r = n.createEvent("MouseEvents");
r.initMouseEvent("scroll", false, false, m, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
s.dispatchEvent(r)
}
}
function h(s) {
var r = s.target;
while (r.nodeType !== 1) {
r = r.parentNode
}
if ((r.tagName !== "SELECT") && (r.tagName !== "INPUT") && (r.tagName !== "TEXTAREA")) {
s.preventDefault()
}
}
}(Scrollable._os, Scrollable._isDOMNode, Scrollable._onReady, Scrollable._forEachInArray, Scrollable._scrollWatcher, iScroll, window, document);
Scrollable._getScrollableNode = function(b) {
return function(c) {
if (b(c) && c._iScroll) {
return c.childNodes[0]
} else {
return c
}
}
}(Scrollable._isDOMNode);
Scrollable._enableInfiniteScrolling = function(g, l, f, h, i, m, d, n) {
var e = 320;
return j;
function j(J, q, y) {
if (f(J)) {
if (J.length) {
var E = J.length - 1;
for (var F = 0; F < E; F++) {
j(J[F], q, y)
}
return j(J[E], q, y)
} else {
return
}
}
if (!l(J)) {
throw J + " is not a DOM element"
}
if (!y && typeof q === "function") {
y = q;
q = {}
}
if (y) {
if (q.downGenerator) {
throw Error("Two downGenerator functions specified")
}
q.downGenerator = y
}
if ((typeof q !== "object") || (q === null)) {
throw TypeError("options must be an object if defined, got " + q)
}
if (!q.downGenerator && !q.upGenerator) {
throw Error("No generators specified. What are you even scrolling?")
}
if (typeof q.autoStart === "undefined") {
q.autoStart = true
}
if (q.downGenerator && typeof q.downGenerator !== "function") {
throw "downGenerator " + downGenerator + " is not a function"
}
if (q.upGenerator && typeof q.upGenerator !== "function") {
throw "upGenerator " + upGenerator + " is not a function"
}
if (q.scroller && !l(q.scroller)) {
throw TypeError("options.scroller must be a DOM node, got " + q.scroller)
}
var I = q.scroller || b(J),
t = q.loading,
s = q.triggerRadius,
x = false,
z = !q.upGenerator,
G = !q.downGenerator,
B = false,
L = false,
C, K, w;
if (f(I)) {
I = I[0]
}
if (f(t)) {
t = t[0]
}
if (t === null) {
t = undefined
}
if (typeof t !== "undefined") {
if (q.downGenerator) {
C = c([t])[0];
if (q.downGenerator) {
K = C.cloneNode(true)
}
} else {
K = c([t])[0]
}
}
if (s === null) {
s = undefined
}
switch (typeof s) {
case "undefined":
s = e;
case "number":
break;
default:
throw TypeError("trigger radius must be a number if defined, got " + s)
}
if (!I) {
m(J);
I = J
}
if (C) {
d(J).appendChild(C)
}
D();
if (q.autoStart) {
A()
}
var H = {
layout: A,
forceLayout: v,
isEnabled: M,
enable: D,
disable: u,
destroy: p
};
if (!I._infinites) {
I._infinites = []
}
I._infinites.push(H);
return H;
function M() {
return x
}
function D() {
if (x) {
return
}
if (B) {
throw Error("cannot enable infinite scroller that has been destroyed")
}
x = true;
I.addEventListener("scroll", A, false)
}
function u() {
if (!x) {
return
}
x = false;
I.removeEventListener("scroll", A)
}
function A() {
if (!x || L || B) {
return
}
var O = o(I, s);
if (!O) {
return
}
var N = (O === "up");
if (N && (J._isScrolling || J._iScrolling)) {
if (w) {
clearTimeout(w)
}
w = setTimeout(function() {
A()
}, 100);
return
}
L = true;
r(N, function(P) {
L = false;
if (P) {
A()
} else {
p(N)
}
})
}
function v(N) {
if (!x || B || L) {
return
}
L = true;
if (typeof N === "undefined") {
N = !q.downGenerator
}
r(N, function(O) {
L = false;
if (O) {
A()
} else {
p(N)
}
})
}
function r(Q, S) {
var R = Q ? q.upGenerator : q.downGenerator;
var N = R(O);
if (typeof N !== "undefined") {
O(N)
}
function O(U, X) {
if (B || (z && Q) || (G && !Q)) {
return
}
var aa = Q ? K : C;
var T = U && U.length && !X;
if (U) {
if (!h(U) && !f(U)) {
U = [U]
}
U = c(U);
var Y = d(J);
var W = I.scrollHeight;
i(U, function(ab) {
P(Y, ab)
});
if (aa) {
P(Y, aa)
}
var V = I.scrollHeight;
if (Q) {
var Z = V - W;
I._scrollTop(I._scrollTop() + Z, function() {
if (!!g.ios && !I._iScroll) {
k(U)
}
S(T)
})
} else {
S(T)
}
} else {
S(T)
}
}
function P(U, T) {
if (Q) {
U.insertBefore(T, U.firstChild)
} else {
U.appendChild(T)
}
}
}
function p(N) {
if (B) {
return
}
if (N) {
z = true;
if (K && K.parentNode) {
K.parentNode.removeChild(K)
}
} else {
G = true;
if (C && C.parentNode) {
C.parentNode.removeChild(C)
}
}
B = (G || !q.downGenerator) && (z || !q.upGenerator);
if (B) {
u()
}
}
function o(O, N) {
var R = O;
while (R !== document.documentElement) {
if (R.parentNode) {
R = R.parentNode
} else {
return false
}
}
var P = O.clientHeight,
S = (O._scrollTop ? O._scrollTop() : O.scrollTop),
Q = O.scrollHeight;
if (!G && Q - S - P <= N) {
return "down"
} else {
if (!z && S < N) {
return "up"
} else {
return false
}
}
}
}
function b(o) {
do {
if (o._scrollable) {
return o
}
o = o.parentNode
} while (o)
}
function c(o) {
var p = [];
i(o, function(q) {
switch (typeof q) {
case "undefined":
return;
case "string":
var r = document.createElement("div");
r.innerHTML = q;
if (r.childNodes) {
i(c(r.childNodes), function(s) {
p.push(s)
})
}
return;
case "object":
if (q === null) {
return
} else {
if (l(q)) {
p.push(q);
return
} else {
if (f(q)) {
i(q, function(s) {
p.push(s)
});
return
}
}
}
default:
throw TypeError("expected an element, got " + q)
}
});
return p
}
function k(o) {
i(o, function(q) {
var p = q.style.webkitTransform;
q.style.webkitTransform = "translate3d(0,0,0)";
setTimeout(function() {
q.style.webkitTransform = p
}, 0)
})
}
}(Scrollable._os, Scrollable._isDOMNode, Scrollable._isjQueryElem, Scrollable._isArray, Scrollable._forEachInArray, Scrollable._enableScrolling, Scrollable._getScrollableNode, window.jQuery);
window.App = function(OldApp) {
var App = {
noConflict: noConflict
};
return App;
function noConflict() {
if (window.App === App) {
window.App = OldApp;
}
return App;
}
}(window.App);
App._Utils = function(window, document, App) {
var query = function(queryString) {
var re = /([^&=]+)=([^&]+)/g,
decodedSpace = /\+/g;
var result = {},
m, key, value;
if (queryString) {
queryString = queryString.replace(decodedSpace, '%20');
while ((m = re.exec(queryString))) {
key = decodeURIComponent(m[1]);
value = decodeURIComponent(m[2]);
result[key] = value;
}
}
return result;
}(window.location.href.split('?')[1]);
var os = function(userAgent) {
var faked = false,
name, version, match;
if (query['_app_platform'] === 'android') {
faked = true;
name = 'android';
version = '5.0';
} else if (query['_app_platform'] === 'ios') {
faked = true;
name = 'ios';
version = '8.1';
} else if (match = /\bCPU.*OS (\d+(_\d+)?)/i.exec(userAgent)) {
name = 'ios';
version = match[1].replace('_', '.');
} else if (match = /\bAndroid (\d+(\.\d+)?)/.exec(userAgent)) {
name = 'android';
version = match[1];
} else {
if (typeof process != 'undefined' && process.versions) {
name = 'node-webkit';
version = process.versions['node-webkit'];
} else
name = 'unknown';
}
var data = {
faked: faked,
name: name,
versionString: version,
version: version && parseFloat(version)
};
data[name] = true;
if (data.ios) {
document.body.className += ' app-ios app-ios-' + parseInt(version);
} else if (data.android) {
document.body.className += ' app-android app-android-' + parseInt(version);
}
if (data.faked || !data.ios) {
document.body.className += ' app-no-scrollbar';
}
return data;
}(navigator.userAgent);
var forEach = function(forEach) {
if (forEach) {
return function(arr, callback, self) {
return forEach.call(arr, callback, self);
};
} else {
return function(arr, callback, self) {
for (var i = 0, len = arr.length; i < len; i++) {
if (i in arr) {
callback.call(self, arr[i], i, arr);
}
}
};
}
}(Array.prototype.forEach);
function isArray(arr) {
if (Array.isArray) {
return Array.isArray(arr);
} else {
return Object.prototype.toString.call(arr) !== '[object Array]';
}
}
function isNode(elem) {
if (!elem) {
return false;
}
try {
return (elem instanceof Node) || (elem instanceof HTMLElement);
} catch (err) {}
if (typeof elem !== 'object') {
return false;
}
if (typeof elem.nodeType !== 'number') {
return false;
}
if (typeof elem.nodeName !== 'string') {
return false;
}
return true;
}
function isjQueryElem($elem) {
if (typeof $elem !== 'object' || $elem === null) {
return false;
} else {
return ($elem.val && $elem.addClass && $elem.css && $elem.html && $elem.show);
}
}
function onReady(func) {
if (document.readyState === 'complete') {
setTimeout(function() {
func();
}, 0);
return;
}
window.addEventListener('load', runCallback, false);
function runCallback() {
window.removeEventListener('load', runCallback);
setTimeout(function() {
func();
}, 0);
}
}
var queueAnimation = function() {
var animationQueue;
return queueAnimation;
function queueAnimation(func) {
if (animationQueue) {
animationQueue.push(func);
} else {
animationQueue = [func];
foregroundFlush();
}
}
function foregroundFlush() {
if (typeof kik === 'object' && typeof kik.browser === 'object' && kik.browser.background && typeof kik.browser.once === 'function') {
kik.browser.once('foreground', flushAnimations);
} else {
flushAnimations();
}
}
function flushAnimations() {
var anim = animationQueue.shift();
if (anim) {
onReady(function() {
var unlocked = false;
function unlock() {
// prevent unlocking mult. times
if (unlocked) {
return;
}
unlocked = true;
setTimeout(foregroundFlush, 0);
}
anim(unlock);
});
} else {
animationQueue = null;
}
}
}();
function setTransform(elem, transform) {
elem.style['-webkit-transform'] = transform;
elem.style['-moz-transform'] = transform;
elem.style['-ms-transform'] = transform;
elem.style['-o-transform'] = transform;
elem.style['transform'] = transform;
}
function setTransition(elem, transition) {
if (transition) {
elem.style['-webkit-transition'] = '-webkit-' + transition;
elem.style['-moz-transition'] = '-moz-' + transition;
elem.style['-ms-transition'] = '-ms-' + transition;
elem.style['-o-transition'] = '-o-' + transition;
elem.style['transition'] = transition;
} else {
elem.style['-webkit-transition'] = '';
elem.style['-moz-transition'] = '';
elem.style['-ms-transition'] = '';
elem.style['-o-transition'] = '';
elem.style['transition'] = '';
}
}
function getStyles(elem, notComputed) {
var styles;
if (notComputed) {
styles = elem.style;
} else {
styles = document.defaultView.getComputedStyle(elem, null);
}
return {
display: styles.display,
opacity: styles.opacity,
paddingRight: styles.paddingRight,
paddingLeft: styles.paddingLeft,
marginRight: styles.marginRight,
marginLeft: styles.marginLeft,
borderRightWidth: styles.borderRightWidth,
borderLeftWidth: styles.borderLeftWidth,
top: styles.top,
left: styles.left,
height: styles.height,
width: styles.width,
position: styles.position
};
}
function isVisible(elem) {
var styles = getStyles(elem);
return (styles.display !== 'none' && styles.opacity !== '0');
}
// this is tuned for use with the iOS transition
// be careful if using this elsewhere
function transitionElems(transitions, timeout, easing, callback) {
if (typeof transitions.length !== 'number') {
transitions = [transitions];
}
var opacities = transitions.map(function(transition) {
return transition.elem.style.opacity;
});
setInitialStyles(function() {
animateElems(function() {
restoreStyles(function() {
callback();
});
});
});
function setInitialStyles(callback) {
forEach(transitions, function(transition) {
if (typeof transition.transitionStart !== 'undefined') {
setTransform(transition.elem, transition.transitionStart);
}
if (typeof transition.opacityStart !== 'undefined') {
transition.elem.style.opacity = transition.opacityStart + '';
}
});
setTimeout(function() {
forEach(transitions, function(transition) {
var e = transition.easing || easing,
transitionString = 'transform ' + (timeout / 1000) + 's ' + e + ', opacity ' + (timeout / 1000) + 's ' + e;
setTransition(transition.elem, transitionString);
});
setTimeout(callback, 0);
}, 0);
}
function animateElems(callback) {
forEach(transitions, function(transition) {
if (typeof transition.transitionEnd !== 'undefined') {
setTransform(transition.elem, transition.transitionEnd);
}
if (typeof transition.opacityEnd !== 'undefined') {
transition.elem.style.opacity = transition.opacityEnd + '';
}
});
var lastTransition = transitions[transitions.length - 1];
lastTransition.elem.addEventListener('webkitTransitionEnd', transitionFinished, false);
lastTransition.elem.addEventListener('transitionend', transitionFinished, false);
lastTransition.elem.addEventListener('onTransitionEnd', transitionFinished, false);
lastTransition.elem.addEventListener('ontransitionend', transitionFinished, false);
lastTransition.elem.addEventListener('MSTransitionEnd', transitionFinished, false);
lastTransition.elem.addEventListener('transitionend', transitionFinished, false);
var done = false;
function transitionFinished(e) {
if (done || (e.target !== lastTransition.elem)) {
return;
}
done = true;
forEach(transitions, function(transition) {
lastTransition.elem.removeEventListener('webkitTransitionEnd', transitionFinished);
lastTransition.elem.removeEventListener('transitionend', transitionFinished);
lastTransition.elem.removeEventListener('onTransitionEnd', transitionFinished);
lastTransition.elem.removeEventListener('ontransitionend', transitionFinished);
lastTransition.elem.removeEventListener('MSTransitionEnd', transitionFinished);
lastTransition.elem.removeEventListener('transitionend', transitionFinished);
});
callback();
}
}
function restoreStyles(callback) {
forEach(transitions, function(transition) {
setTransition(transition.elem, '');
});
setTimeout(function() {
forEach(transitions, function(transition, i) {
setTransform(transition.elem, '');
transition.elem.style.opacity = opacities[i];
});
callback();
}, 0);
}
}
App.platform = os.name;
App.platformVersion = os.version;
App.queue = queueAnimation;
return {
query: query,
os: os,
ready: onReady,
forEach: forEach,
isArray: isArray,
isNode: isNode,
isjQueryElem: isjQueryElem,
setTransform: setTransform,
setTransition: setTransition,
animate: transitionElems,
getStyles: getStyles,
isVisible: isVisible
};
}(window, document, App);
App._Events = function(Utils) {
var APPJS_EVENTS_VAR = '__appjsCustomEventing';
var hasCustomEvents = supportsCustomEventing();
return {
init: setupCustomEventing,
fire: fireEvent
};
function supportsCustomEventing() {
try {
var elem = document.createElement('div'),
evt = document.createEvent('CustomEvent');
evt.initEvent('fooBarFace', false, true);
elem.dispatchEvent(evt);
return true;
} catch (err) {
return false;
}
}
function setupCustomEventing(elem, names) {
if (hasCustomEvents) {
return;
}
if (elem[APPJS_EVENTS_VAR]) {
Utils.forEach(names, elem[APPJS_EVENTS_VAR].addEventType);
return;
}
elem[APPJS_EVENTS_VAR] = {
fire: fireElemEvent,
addEventType: addEventType,
addEventListener: elem.addEventListener,
removeEventListener: elem.removeEventListener
};
var listeners = {};
Utils.forEach(names, function(name) {
listeners[name] = [];
});
function addEventType(name) {
if (names.indexOf(name) !== -1) {
return;
}
names.push(name);
listeners[name] = [];
}
function fireElemEvent(name) {
if (names.indexOf(name) === -1) {
return false;
}
var prevented = false,
evt = {
preventDefault: function() {
prevented = true
}
};
Utils.forEach(listeners[name], function(listener) {
setTimeout(function() {
if (listener.call(elem, evt) === false) {
prevented = true;
}
}, 0);
});
return !prevented;
}
elem.addEventListener = function(name, listener) {
if (names.indexOf(name) === -1) {
elem[APPJS_EVENTS_VAR].addEventListener.apply(this, arguments);
return;
}
var eventListeners = listeners[name];
if (eventListeners.indexOf(listener) === -1) {
eventListeners.push(listener);
}
};
elem.removeEventListener = function(name, listener) {
if (names.indexOf(name) === -1) {
elem[APPJS_EVENTS_VAR].removeEventListener.apply(this, arguments);
return;
}
var eventListeners = listeners[name],
index = eventListeners.indexOf(listener);
if (index !== -1) {
eventListeners.splice(index, 1);
}
};
}
function fireEvent(elem, eventName) {
if (elem[APPJS_EVENTS_VAR]) {
return elem[APPJS_EVENTS_VAR].fire(eventName);
} else {
var evt = document.createEvent('CustomEvent');
evt.initEvent(eventName, false, true);
return elem.dispatchEvent(evt);
}
}
}(App._Utils);
App._Metrics = function(window, App) {
var analyticsEnabled = false;
App.enableGoogleAnalytics = function() {
enableGoogleAnalytics();
};
return {
watchPage: watchPage
};
function enableGoogleAnalytics() {
analyticsEnabled = true;
}
function addPageView(pageName, pageID) {
if (!analyticsEnabled) {
return;
}
var pathname = '/' + pageName;
if (typeof pageID !== 'undefined') {
pathname += '/' + pageID;
}
if (typeof window.ga === 'function') {
window.ga('send', 'pageview', pathname);
return;
}
if (!window._gaq) {
window._gaq = [];
}
if (typeof window._gaq.push === 'function') {
window._gaq.push([
'_trackPageview',
pathname
]);
}
}
function watchPage(page, pageName, pageArgs) {
var data;
if ((typeof pageArgs === 'object') && (typeof pageArgs.id !== 'undefined')) {
data = pageArgs.id + '';
}
page.addEventListener('appShow', function() {
addPageView(pageName, data);
}, false);
}
}(window, App);
App._Dialog = function(window, document, Clickable, App, Utils) {
var DIALOG_INDICATOR_CLASS = 'app-dialog-visible';
var currentCallback,
dialogQueue;
App.dialog = function(options, callback) {
if ((typeof options !== 'object') || (options === null)) {
throw TypeError('dialog options must be an object, got ' + options);
}
switch (typeof options.text) {
case 'undefined':
case 'string':
break;
default:
if (!Utils.isNode(options.text)) {
throw TypeError('dialog text must be a string if defined, got ' + options.text);
}
}
for (var key in options) {
if ((key === 'theme') || (key === 'title') || (key.substr(key.length - 6) === 'Button')) {
switch (typeof options[key]) {
case 'undefined':
case 'string':
break;
default:
throw TypeError('dialog button (' + key + ') must be a string if defined, got ' + options[key]);
}
}
}
switch (typeof callback) {
case 'undefined':
callback = function() {};
case 'function':
break;
default:
throw TypeError('callback must be a function if defined, got ' + callback);
}
return showDialog(options, callback);
};
App.dialog.close = function(status) {
return closeDialog(status || false);
};
App.dialog.status = function() {
return hasDialog();
};
return App.dialog;
function createDialog(options, callback) {
var dialogContainer = document.createElement('div');
dialogContainer.className += ' app-dialog-container';
if (!Utils.os.android || (Utils.os.version >= 4)) {
dialogContainer.addEventListener('touchstart', function(e) {
if (e.target === dialogContainer) {
e.preventDefault();
}
}, false);
}
var dialog = document.createElement('div');
dialog.className = 'app-dialog';
if (options.theme) {
dialog.className += ' ' + options.theme;
}
dialogContainer.appendChild(dialog);
if (options.title) {
var title = document.createElement('div');
title.className = 'title';
title.textContent = options.title;
dialog.appendChild(title);
}
if (options.text || options.rawText) {
var text = document.createElement('div');
text.className = 'text';
if (Utils.isNode(options.text)) {
text.appendChild(options.text);
} else if (options.rawText) {
text.innerHTML = options.rawText;
} else {
text.textContent = options.text;
}
dialog.appendChild(text);
}
if (options.rawHTML) {
dialog.appendChild(options.rawHTML);
}
if (options.okButton) {
var button = document.createElement('div');
button.className = 'button ok last';
if (!options.cancelButton) {
button.className += ' first';
}
button.setAttribute('data-button', 'ok');
button.textContent = options.okButton;
Clickable(button);
button.addEventListener('click', handleChoice, false);
dialog.appendChild(button);
}
if (options.cancelButton) {
var button = document.createElement('div');
button.className = 'button cancel first';
if (!options.okButton) {
button.className += ' last';
}
button.setAttribute('data-button', 'cancel');
button.textContent = options.cancelButton;
Clickable(button);
button.addEventListener('click', handleChoice, false);
dialog.appendChild(button);
}
function handleChoice() {
var buttonName = this.getAttribute('data-button');
if (buttonName === 'cancel') {
buttonName = false;
}
callback(buttonName);
}
return dialogContainer;
}
function showDialog(options, callback, force) {
if (dialogQueue && !force) {
dialogQueue.push([options, callback]);
return;
}
dialogQueue = dialogQueue || [];
var dialogLock = false,
dialog = createDialog(options, dialogClosed),
innerDialog = dialog.firstChild;
currentCallback = dialogClosed;
Utils.ready(function() {
document.body.appendChild(dialog);
setTimeout(function() {
dialog.className += ' enabled';
document.body.className += ' ' + DIALOG_INDICATOR_CLASS;
}, 50);
});
function dialogClosed(status) {
if (dialogLock) {
return;
}
dialogLock = true;
currentCallback = null;
dialog.className = dialog.className.replace(/\benabled\b/g, '') + ' closing';
if (status) {
dialog.className += ' closing-success';
} else {
dialog.className += ' closing-fail';
}
document.body.className = document.body.className.replace(new RegExp('\\b' + DIALOG_INDICATOR_CLASS + '\\b', 'g'), '');
setTimeout(function() {
processDialogQueue();
callback(status);
}, 0);
setTimeout(function() {
try {
dialog.parentNode.removeChild(dialog);
} catch (err) {}
}, 600);
return true;
}
}
function closeDialog(status) {
if (currentCallback) {
return currentCallback(status || false);
}
}
function hasDialog() {
return !!currentCallback;
}
function processDialogQueue() {
if (!dialogQueue) {
return;
}
if (!dialogQueue.length) {
dialogQueue = null;
return;
}
var args = dialogQueue.shift();
args.push(true);
showDialog.apply(window, args);
}
}(window, document, Clickable, App, App._Utils);
App._Form = function(window, document, App, Utils) {
App.form = function(form, callback) {
if (Utils.isjQueryElem(form)) {
form.each(function() {
App.form(this, callback);
});
return;
}
if (!Utils.isNode(form)) {
throw TypeError('form must be a DOM node, got ' + form);
}
if (typeof callback !== 'function') {
throw TypeError('callback must be a function, got ' + callback);
}
setupForm(form, callback);
};
return {};
function setupForm(form, callback) {
var isForm = (form.nodeName === 'FORM'),
locked = false,
submitButtons;
if (isForm) {
var submit = document.createElement('input');
submit.style.display = 'none';
submit.type = 'submit';
form.appendChild(submit);
form.addEventListener('submit', function(e) {
e.preventDefault();
submitForm();
}, false);
submitButtons = form.querySelectorAll('.app-submit');
} else {
submitButtons = [form];
}
Utils.forEach(submitButtons, function(submitButton) {
if (submitButton.nodeName === 'TEXTAREA') {
isText = true;
} else if (submitButton.nodeName !== 'INPUT') {
isText = false;
} else {
switch ((submitButton.type || '').toLowerCase()) {
case 'button':
case 'submit':
case 'reset':
case 'hidden':
isText = false;
break;
default:
isText = true;
break;
}
}
if (isText) {
submitButton.addEventListener('keydown', function(e) {
if (e.which === 13) {
e.preventDefault();
submitForm();
}
}, false);
} else {
submitButton.addEventListener('click', function(e) {
e.preventDefault();
submitForm();
}, false);
}
});
function submitForm() {
if (locked) {
return;
}
locked = true;
form.disabled = true;
var params = {},
inputs = isForm ? form.querySelectorAll('[name]') : [form],
done = false;
if (isForm) {
Utils.forEach(
form.querySelectorAll('[name]'),
function(elem) {
params[elem.name] = elem.value;
}
);
} else {
params.value = form.value;
if (form.name) {
params[form.name] = form.value;
}
}
Utils.forEach(inputs, function(elem) {
elem.disabled = true;
if (elem.blur) {
elem.blur();
}
});
if (isForm && form.blur) {
form.blur();
}
callback.call(this, params, function() {
if (done) {
return;
}
done = true;
Utils.forEach(inputs, function(elem) {
elem.disabled = false;
});
locked = false;
form.disabled = false;
});
}
}
}(window, document, App, App._Utils);
App._Scroll = function(Scrollable, App, Utils) {
var TAGS = {
APP_CONTENT: 'app-content',
APP_SCROLLABLE: 'app-scrollable',
APP_SCROLLHACK: 'app-scrollhack',
NO_SCROLL: 'data-no-scroll',
SCROLLABLE: 'data-scrollable',
LAST_SCROLL: 'data-last-scroll',
SCROLL_STYLE: 'data-scroll-style',
TOUCH_SCROLL: '-webkit-overflow-scrolling'
},
PAGE_MANAGER_VAR = '__appjsPageManager';
App.infiniteScroll = function(elem, options, generator) {
if (Utils.isjQueryElem(elem)) {
if (elem.length) {
var l = elem.length - 1;
for (var i = 0; i < l; i++) {
App.infiniteScroll(elem[i], options, generator);
}
return App.infiniteScroll(elem[l], options, generator);
} else {
return;
}
}
if (!Utils.isNode(elem)) {
throw TypeError('infinite scroll container must be a DOM node, got ' + elem);
}
return setupInfiniteScroll(elem, options, generator);
};
return {
setup: setupScrollers,
disable: disableScrolling,
saveScrollPosition: savePageScrollPosition,
saveScrollStyle: savePageScrollStyle,
restoreScrollPosition: restorePageScrollPosition,
restoreScrollStyle: restorePageScrollStyle
};
function setupScrollers(page) {
Utils.forEach(
page.querySelectorAll('.' + TAGS.APP_CONTENT),
function(content) {
if (content.getAttribute(TAGS.NO_SCROLL) === null) {
setupScroller(content);
}
}
);
Utils.forEach(
page.querySelectorAll('[' + TAGS.SCROLLABLE + ']'),
function(content) {
setupScroller(content);
}
);
}
function setupScroller(content) {
var forceIScroll = !!window['APP_FORCE_ISCROLL'];
Scrollable(content, forceIScroll);
content.className += ' ' + TAGS.APP_SCROLLABLE;
if (!forceIScroll && Utils.os.ios && Utils.os.version < 6) {
content.className += ' ' + TAGS.APP_SCROLLHACK;
}
}
function disableScrolling(page) {
Utils.forEach(
page.querySelectorAll('*'),
function(elem) {
elem.style[TAGS.TOUCH_SCROLL] = '';
}
);
}
function getScrollableElems(page) {
var elems = [];
if (page) {
Utils.forEach(
page.querySelectorAll('.' + TAGS.APP_SCROLLABLE),
function(elem) {
if (elem._scrollable) {
elems.push(elem);
}
}
);
}
return elems;
}
function savePageScrollPosition(page) {
Utils.forEach(
getScrollableElems(page),
function(elem) {
if (elem._iScroll) {
return;
}
var scrollTop = elem._scrollTop();
elem.setAttribute(TAGS.LAST_SCROLL, scrollTop + '');
}
);
}
function savePageScrollStyle(page) {
Utils.forEach(
getScrollableElems(page),
function(elem) {
if (elem._iScroll) {
return;
}
var scrollStyle = elem.style[TAGS.TOUCH_SCROLL] || '';
elem.style[TAGS.TOUCH_SCROLL] = '';
elem.setAttribute(TAGS.SCROLL_STYLE, scrollStyle);
}
);
}
function restorePageScrollPosition(page, noTimeout) {
Utils.forEach(
getScrollableElems(page),
function(elem) {
if (elem._iScroll) {
return;
}
var scrollTop = parseInt(elem.getAttribute(TAGS.LAST_SCROLL));
if (scrollTop) {
if (!noTimeout) {
setTimeout(function() {
elem._scrollTop(scrollTop);
}, 0);
} else {
elem._scrollTop(scrollTop);
}
}
}
);
}
function restorePageScrollStyle(page) {
Utils.forEach(
getScrollableElems(page),
function(elem) {
if (elem._iScroll) {
return;
}
var scrollStyle = elem.getAttribute(TAGS.SCROLL_STYLE) || '';
if (scrollStyle) {
elem.style[TAGS.TOUCH_SCROLL] = scrollStyle;
}
}
);
restorePageScrollPosition(page, true);
}
function setupInfiniteScroll(elem, options, generator) {
var page = options.page || getParentPage(elem),
pageManager = getPageManager(page);
if (!page || !pageManager) {
throw Error('could not find parent app-page');
}
if (!options) {
options = {};
}
if (typeof options.scroller === 'undefined') {
options.scroller = getParentScroller(elem);
}
options.autoStart = false;
var scroller = Scrollable.infinite(elem, options, generator);
scroller.forceLayout();
scroller.disable();
pageManager.ready(function() {
scrollReady = true;
try {
scroller.enable();
} catch (err) {
// scroll is already destroyed
return;
}
scroller.layout();
page.addEventListener('appShow', function() {
scroller.layout();
});
page.addEventListener('appDestroy', function() {
scroller.destroy();
});
});
return scroller;
}
function getParentPage(elem) {
var parent = elem;
do {
if (/\bapp\-page\b/.test(parent.className)) {
return parent;
}
} while (parent = parent.parentNode);
}
function getParentScroller(elem) {
var parent = elem;
do {
if (parent._scrollable || /\bapp\-content\b/.test(parent.className)) {
return parent;
}
} while (parent = parent.parentNode);
}
function getPageManager(page) {
if (page) {
return page[PAGE_MANAGER_VAR];
}
}
}(Scrollable, App, App._Utils);
// fixes ios bounce scrolling in mobile safari
(function(document, App, Utils) {
var touches = {};
if (App.platform === 'ios' && App.platformVersion >= 5 && !Utils.os.faked && (typeof kik !== 'object' || kik === null || !kik.enabled)) {
bindListeners();
}
return;
function bindListeners() {
document.addEventListener('touchstart', function(e) {
var target = getTargetScroller(e);
if (target && !target._iScroll) {
if ((target.scrollHeight - target.clientHeight > 1) && ((target.scrollTop <= 0) || (target.scrollTop + target.clientHeight >= target.scrollHeight))) {
addTouches(e);
}
}
});
document.addEventListener('touchmove', function(e) {
var target = getTargetScroller(e);
if (!target) {
e.preventDefault();
} else if (target._iScroll) {
e.preventDefault();
} else if (e.changedTouches) {
if (e.changedTouches.length === 1) {
onMove(e);
}
updateTouches(e);
}
});
document.addEventListener('touchcancel', function(e) {
clearTouches(e);
});
document.addEventListener('touchend', function(e) {
clearTouches(e);
});
}
function getTargetScroller(e) {
var target = e.target;
if (target) {
do {
if (target._scrollable) {
break;
}
} while (target = target.parentNode);
}
return target;
}
function onMove(e) {
var target = getTargetScroller(e),
touch = e.changedTouches[0],
y0 = touches[touch.identifier],
y1 = touch.pageY;
if (target && typeof y0 !== 'undefined') {
if (target.scrollTop <= 0) {
if (y0 > y1) {
delete touches[touch.identifier];
} else {
e.preventDefault();
}
} else if (target.scrollTop + target.clientHeight >= target.scrollHeight) {
if (y0 < y1) {
delete touches[touch.identifier];
} else {
e.preventDefault();
}
} else {
delete touches[touch.identifier];
}
}
}
function addTouches(e) {
if (e.changedTouches) {
for (var i = 0, l = e.changedTouches.length; i < l; i++) {
touches[e.changedTouches[i].identifier] = e.changedTouches[i].pageY;
}
}
}
function updateTouches(e) {
if (e.changedTouches) {
for (var i = 0, l = e.changedTouches.length; i < l; i++) {
if (e.changedTouches[i].identifier in touches) {
touches[e.changedTouches[i].identifier] = e.changedTouches[i].pageY;
}
}
}
}
function clearTouches(e) {
if (e.changedTouches) {
for (var i = 0, l = e.changedTouches.length; i < l; i++) {
delete touches[e.changedTouches[i].identifier];
}
}
if (e.touches) {
var ids = [];
for (var i = 0, l = e.touches.length; i < l; i++) {
ids.push(e.touches[i].identifier + '');
}
for (var id in touches) {
if (ids.indexOf(id) === -1) {
delete touches[id];
}
}
}
}
})(document, App, App._Utils);
App._Pages = function(window, document, Clickable, Scrollable, App, Utils, Events, Metrics, Scroll) {
var PAGE_NAME = 'data-page',
PAGE_CLASS = 'app-page',
APP_LOADED = 'app-loaded',
APP_IOS_STATUSBAR = 'app-ios-statusbar',
APP_ANDROID_STATUSBAR = 'app-android-statusbar',
PAGE_READY_VAR = '__appjsFlushReadyQueue',
PAGE_MANAGER_VAR = '__appjsPageManager',
EVENTS = {
SHOW: 'show',
HIDE: 'hide',
BACK: 'back',
FORWARD: 'forward',
BEFORE_BACK: 'beforeBack',
READY: 'ready',
DESTROY: 'destroy',
LAYOUT: 'layout',
ONLINE: 'online',
OFFLINE: 'offline'
};
var preloaded = false,
forceIScroll = !!window['APP_FORCE_ISCROLL'],
pages = {},
controllers = {},
cleanups = {},
statusBarEnabled = false;
setupPageListeners();
if (window.APP_ENABLE_STATUSBAR || window.APP_ENABLE_IOS_STATUSBAR) {
enableStatusBar();
}
App.add = function(pageName, page) {
if (typeof pageName !== 'string') {
page = pageName;
pageName = undefined;
}
if (!Utils.isNode(page)) {
throw TypeError('page template node must be a DOM node, got ' + page);
}
addPage(page, pageName);
};
App.controller = function(pageName, controller, cleanup) {
if (typeof pageName !== 'string') {
throw TypeError('page name must be a string, got ' + pageName);
}
if (typeof controller !== 'function') {
throw TypeError('page controller must be a function, got ' + controller);
}
switch (typeof cleanup) {
case 'undefined':
cleanup = function() {};
break;
case 'function':
break;
default:
throw TypeError('page cleanup handler must be a function, got ' + cleanup);
}
if (controller) {
addController(pageName, controller);
}
if (cleanup) {
addCleanup(pageName, cleanup);
}
};
App.populator = App.controller; // backwards compat
App.generate = function(pageName, args) {
if (typeof pageName !== 'string') {
throw TypeError('page name must be a string, got ' + pageName);
}
switch (typeof args) {
case 'undefined':
args = {};
break;
case 'object':
break;
default:
throw TypeError('page arguments must be an object if defined, got ' + args);
}
return generatePage(pageName, args);
};
App.destroy = function(page) {
if (!Utils.isNode(page)) {
throw TypeError('page node must be a DOM node, got ' + page);
}
return destroyPage(page);
};
App._layout = triggerPageSizeFix;
App._enableStatusBar = enableStatusBar;
App._enableIOSStatusBar = enableStatusBar;
return {
EVENTS: EVENTS,
has: hasPage,
createManager: createPageManager,
startGeneration: startPageGeneration,
finishGeneration: finishPageGeneration,
fire: firePageEvent,
startDestruction: startPageDestruction,
finishDestruction: finishPageDestruction,
fixContent: fixContentHeight,
populateBackButton: populatePageBackButton
};
/* Page elements */
function preloadPages() {
if (preloaded) {
return;
}
preloaded = true;
var pageNodes = document.getElementsByClassName(PAGE_CLASS);
for (var i = pageNodes.length; i--;) {
addPage(pageNodes[i]);
}
document.body.className += ' ' + APP_LOADED;
}
function addPage(page, pageName) {
if (!pageName) {
pageName = page.getAttribute(PAGE_NAME);
}
if (!pageName) {
throw TypeError('page name was not specified');
}
page.setAttribute(PAGE_NAME, pageName);
if (page.parentNode) {
page.parentNode.removeChild(page);
}
pages[pageName] = page.cloneNode(true);
}
function hasPage(pageName) {
preloadPages();
return (pageName in pages);
}
function clonePage(pageName) {
if (!hasPage(pageName)) {
throw TypeError(pageName + ' is not a known page');
}
return pages[pageName].cloneNode(true);
}
/* Page controllers */
function addController(pageName, controller) {
controllers[pageName] = controller;
}
function addCleanup(pageName, cleanup) {
cleanups[pageName] = cleanup;
}
function populatePage(pageName, pageManager, page, args) {
var controller = controllers[pageName];
if (!controller) {
return;
}
for (var prop in controller) {
pageManager[prop] = controller[prop];
}
for (var prop in controller.prototype) {
pageManager[prop] = controller.prototype[prop];
}
pageManager.page = page; //TODO: getter
pageManager.args = args; //TODO: getter (dont want this to hit localStorage)
controller.call(pageManager, page, args);
}
function unpopulatePage(pageName, pageManager, page, args) {
var cleanup = cleanups[pageName];
if (cleanup) {
cleanup.call(pageManager, page, args);
}
firePageEvent(pageManager, page, EVENTS.DESTROY);
}
/* Page generation */
function createPageManager(restored) {
var pageManager = {
restored: restored,
showing: false,
online: navigator.onLine
};
var readyQueue = [];
pageManager.ready = function(func) {
if (typeof func !== 'function') {
throw TypeError('ready must be called with a function, got ' + func);
}
if (readyQueue) {
readyQueue.push(func);
} else {
func.call(pageManager);
}
};
pageManager[PAGE_READY_VAR] = function() {
Utils.ready(function() {
if (!readyQueue) {
return;
}
var queue = readyQueue.slice();
readyQueue = null;
if (Utils.isNode(pageManager.page)) {
firePageEvent(pageManager, pageManager.page, EVENTS.READY);
}
Utils.forEach(queue, function(func) {
func.call(pageManager);
});
});
};
return pageManager;
}
function generatePage(pageName, args) {
var pageManager = {},
page = startPageGeneration(pageName, pageManager, args);
finishPageGeneration(pageName, pageManager, page, args);
return page;
}
function destroyPage(page) {
var pageName = page.getAttribute(PAGE_NAME);
startPageDestruction(pageName, {}, page, {});
finishPageDestruction(pageName, {}, page, {});
}
function startPageGeneration(pageName, pageManager, args) {
var page = clonePage(pageName);
var eventNames = [];
for (var evt in EVENTS) {
eventNames.push(eventTypeToName(EVENTS[evt]));
}
Events.init(page, eventNames);
Metrics.watchPage(page, pageName, args);
page[PAGE_MANAGER_VAR] = pageManager;
fixContentHeight(page);
Utils.forEach(page.querySelectorAll('.app-button'), attachButtonEvent);
//Attach click events for buttons added later on
page.addEventListener('DOMNodeInserted', function(e) {
var element = e.srcElement;
if (element && element.classList && element.classList.contains('app-button')) {
attachButtonEvent(element);
}
});
populatePage(pageName, pageManager, page, args);
page.addEventListener(eventTypeToName(EVENTS.SHOW), function() {
setTimeout(function() {
if (typeof pageManager[PAGE_READY_VAR] === 'function') {
pageManager[PAGE_READY_VAR]();
}
}, 0);
}, false);
return page;
}
function attachButtonEvent(button) {
if (button.getAttribute('data-no-click') !== null || button._clickable) {
return;
}
Clickable(button);
button.addEventListener('click', function() {
var target = button.getAttribute('data-target'),
targetArgs = button.getAttribute('data-target-args'),
back = (button.getAttribute('data-back') !== null),
manualBack = (button.getAttribute('data-manual-back') !== null),
args;
try {
args = JSON.parse(targetArgs);
} catch (err) {}
if ((typeof args !== 'object') || (args === null)) {
args = {};
}
if (!back && !target) {
return;
}
if (back && manualBack) {
return;
}
var clickableClass = button.getAttribute('data-clickable-class');
if (clickableClass) {
button.disabled = true;
button.classList.add(clickableClass);
}
if (back) {
App.back(finish);
} else if (target) {
App.load(target, args, {}, finish);
}
function finish() {
if (clickableClass) {
button.disabled = false;
button.classList.remove(clickableClass);
}
}
}, false);
}
function firePageEvent(pageManager, page, eventType) {
var eventName = eventTypeToName(eventType),
funcName = eventTypeToFunctionName(eventType),
success = true;
if (!Events.fire(page, eventName)) {
success = false;
}
if (typeof pageManager[funcName] === 'function') {
if (pageManager[funcName]() === false) {
success = false;
}
}
return success;
}
function eventTypeToName(eventType) {
return 'app' + eventType[0].toUpperCase() + eventType.slice(1);
}
function eventTypeToFunctionName(eventType) {
return 'on' + eventType[0].toUpperCase() + eventType.slice(1);
}
function finishPageGeneration(pageName, pageManager, page, args) {
Scroll.setup(page);
}
function startPageDestruction(pageName, pageManager, page, args) {
if (!Utils.os.ios || Utils.os.version < 6) {
Scroll.disable(page);
}
if (typeof pageManager.reply === 'function') {
pageManager._appNoBack = true;
pageManager.reply();
}
}
function finishPageDestruction(pageName, pageManager, page, args) {
unpopulatePage(pageName, pageManager, page, args);
}
/* Page layout */
function setupPageListeners() {
window.addEventListener('orientationchange', triggerPageSizeFix);
window.addEventListener('resize', triggerPageSizeFix);
window.addEventListener('load', triggerPageSizeFix);
setTimeout(triggerPageSizeFix, 0);
window.addEventListener('online', function() {
if (App._Stack) {
Utils.forEach(App._Stack.get(), function(pageInfo) {
pageInfo[2].online = true;
firePageEvent(pageInfo[2], pageInfo[3], EVENTS.ONLINE);
});
}
}, false);
window.addEventListener('offline', function() {
if (App._Stack) {
Utils.forEach(App._Stack.get(), function(pageInfo) {
pageInfo[2].online = false;
firePageEvent(pageInfo[2], pageInfo[3], EVENTS.OFFLINE);
});
}
}, false);
}
function triggerPageSizeFix() {
fixContentHeight();
var pageData;
if (App._Stack) {
pageData = App._Stack.getCurrent();
}
if (pageData) {
firePageEvent(pageData[2], pageData[3], EVENTS.LAYOUT);
}
//TODO: turns out this isnt all that expensive, but still, lets kill it if we can
setTimeout(fixContentHeight, 0);
setTimeout(fixContentHeight, 10);
setTimeout(fixContentHeight, 100);
}
function fixContentHeight(page) {
if (!page) {
if (App._Navigation) {
page = App._Navigation.getCurrentNode();
}
if (!page) {
return;
}
}
var topbar = page.querySelector('.app-topbar'),
content = page.querySelector('.app-content'),
height = window.innerHeight;
if (!content) {
return;
}
if (!topbar) {
content.style.height = height + 'px';
return;
}
var topbarStyles = document.defaultView.getComputedStyle(topbar, null),
topbarHeight = Utils.os.android ? 56 : 44;
if (statusBarEnabled) {
topbarHeight += Utils.os.android ? 24 : 20;
}
if (topbarStyles.height) {
topbarHeight = (parseInt(topbarStyles.height) || 0);
if ((topbarStyles.boxSizing || topbarStyles.webkitBoxSizing) !== 'border-box') {
topbarHeight += (parseInt(topbarStyles.paddingBottom) || 0) + (parseInt(topbarStyles.paddingTop) || 0);
topbarHeight += (parseInt(topbarStyles.borderBottomWidth) || 0) + (parseInt(topbarStyles.borderTopWidth) || 0);
}
}
content.style.height = (height - topbarHeight) + 'px';
}
function populatePageBackButton(page, oldPage) {
if (!oldPage) {
return;
}
var backButton = page.querySelector('.app-topbar .left.app-button'),
oldTitle = oldPage.querySelector('.app-topbar .app-title');
if (!backButton || !oldTitle || (backButton.getAttribute('data-autotitle') === null)) {
return;
}
var oldText = oldTitle.textContent,
newText = backButton.textContent;
if (!oldText || newText) {
return;
}
if (oldText.length > 13) {
oldText = oldText.substr(0, 12) + '..';
}
backButton.textContent = oldText;
}
function enableStatusBar() {
if (statusBarEnabled) {
return;
}
statusBarEnabled = true;
if (Utils.os.android) {
document.body.className += ' ' + APP_ANDROID_STATUSBAR;
} else {
document.body.className += ' ' + APP_IOS_STATUSBAR;
}
Utils.ready(function() {
setTimeout(triggerPageSizeFix, 6);
});
}
}(window, document, Clickable, Scrollable, App, App._Utils, App._Events, App._Metrics, App._Scroll);
App._Stack = function(window, document, App, Utils, Scroll, Pages) {
var STACK_KEY = '__APP_JS_STACK__' + window.location.pathname,
STACK_TIME = '__APP_JS_TIME__' + window.location.pathname;
var stack = [];
App.getStack = function() {
return fetchStack();
};
App.getPage = function(index) {
var stackSize = stack.length - 1;
switch (typeof index) {
case 'undefined':
index = stackSize;
break;
case 'number':
if (Math.abs(index) > stackSize) {
throw TypeError('absolute index cannot be greater than stack size, got ' + index);
}
if (index < 0) {
index = stackSize + index;
}
break;
default:
throw TypeError('page index must be a number if defined, got ' + index);
}
return fetchPage(index);
};
App.removeFromStack = function(startIndex, endIndex) {
// minus 1 because last item on stack is current page (which is untouchable)
var stackSize = stack.length - 1;
switch (typeof startIndex) {
case 'undefined':
startIndex = 0;
break;
case 'number':
if (Math.abs(startIndex) > stackSize) {
throw TypeError('absolute start index cannot be greater than stack size, got ' + startIndex);
}
if (startIndex < 0) {
startIndex = stackSize + startIndex;
}
break;
default:
throw TypeError('start index must be a number if defined, got ' + startIndex);
}
switch (typeof endIndex) {
case 'undefined':
endIndex = stackSize;
break;
case 'number':
if (Math.abs(endIndex) > stackSize) {
throw TypeError('absolute end index cannot be greater than stack size, got ' + endIndex);
}
if (endIndex < 0) {
endIndex = stackSize + endIndex;
}
break;
default:
throw TypeError('end index must be a number if defined, got ' + endIndex);
}
if (startIndex > endIndex) {
throw TypeError('start index cannot be greater than end index');
}
removeFromStack(startIndex, endIndex);
};
App.addToStack = function(index, newPages) {
// minus 1 because last item on stack is current page (which is untouchable)
var stackSize = stack.length - 1;
switch (typeof index) {
case 'undefined':
index = 0;
break;
case 'number':
if (Math.abs(index) > stackSize) {
throw TypeError('absolute index cannot be greater than stack size, got ' + index);
}
if (index < 0) {
index = stackSize + index;
}
break;
default:
throw TypeError('index must be a number if defined, got ' + index);
}
if (!Utils.isArray(newPages)) {
throw TypeError('added pages must be an array, got ' + newPages);
}
newPages = newPages.slice();
Utils.forEach(newPages, function(page, i) {
if (typeof page === 'string') {
page = [page, {}];
} else if (Utils.isArray(page)) {
page = page.slice();
} else {
throw TypeError('page description must be an array (page name, arguments), got ' + page);
}
if (typeof page[0] !== 'string') {
throw TypeError('page name must be a string, got ' + page[0]);
}
switch (typeof page[1]) {
case 'undefined':
page[1] = {};
case 'object':
break;
default:
throw TypeError('page arguments must be an object if defined, got ' + page[1]);
}
switch (typeof page[2]) {
case 'undefined':
page[2] = {};
case 'object':
break;
default:
throw TypeError('page options must be an object if defined, got ' + page[2]);
}
newPages[i] = page;
});
addToStack(index, newPages);
};
App.saveStack = function() {
saveStack();
};
App.destroyStack = function() {
destroyStack();
};
App.restore = setupRestoreFunction();
return {
get: fetchStack,
getCurrent: fetchLastStackItem,
getPage: fetchPage,
pop: popLastStackItem,
push: pushNewStackItem,
size: fetchStackSize,
save: saveStack,
destroy: destroyStack
};
function saveStack() {
try {
var storedStack = [];
for (var i = 0, l = stack.length; i < l; i++) {
if (stack[i][4].restorable === false) {
break;
}
storedStack.push([stack[i][0], stack[i][3], stack[i][2]]);
}
localStorage[STACK_KEY] = JSON.stringify(storedStack);
localStorage[STACK_TIME] = +new Date() + '';
} catch (err) {}
}
function destroyStack() {
delete localStorage[STACK_KEY];
delete localStorage[STACK_TIME];
}
function fetchStack() {
return stack.slice().map(reorganisePageData);
}
function fetchStackSize() {
return stack.length;
}
function fetchLastStackItem() {
var pageData = stack[stack.length - 1];
if (pageData) {
return reorganisePageData(pageData);
}
}
function popLastStackItem() {
var pageData = stack.pop();
if (pageData) {
return reorganisePageData(pageData);
}
}
function pushNewStackItem(pageData) {
stack.push([pageData[0], pageData[3], pageData[4], pageData[1], pageData[2]]);
}
function fetchPage(index) {
var pageData = stack[index];
if (pageData) {
return pageData[1];
}
}
function reorganisePageData(pageData) {
var pageArgs = {};
for (var key in pageData[3]) {
pageArgs[key] = pageData[3][key];
}
return [pageData[0], pageArgs, pageData[4], pageData[1], pageData[2]];
}
// you must manually save the stack if you choose to use this method
function removeFromStackNow(startIndex, endIndex) {
var deadPages = stack.splice(startIndex, endIndex - startIndex);
Utils.forEach(deadPages, function(pageData) {
Pages.startDestruction(pageData[0], pageData[4], pageData[1], pageData[3]);
Pages.finishDestruction(pageData[0], pageData[4], pageData[1], pageData[3]);
});
}
function removeFromStack(startIndex, endIndex) {
App._Navigation.enqueue(function(finish) {
removeFromStackNow(startIndex, endIndex);
finish();
});
}
// you must manually save the stack if you choose to use this method
function addToStackNow(index, newPages, restored) {
var pageDatas = [],
lastPage;
Utils.forEach(newPages, function(pageData) {
var pageManager = Pages.createManager(true),
page = Pages.startGeneration(pageData[0], pageManager, pageData[1]);
if (!pageData[2].transition && pageManager.transition) {
pageData[2].transition = pageManager.transition;
}
if (!pageData[2].duration && pageManager.duration) {
pageData[2].duration = pageManager.duration;
}
Pages.populateBackButton(page, lastPage);
Pages.finishGeneration(pageData[0], pageManager, page, pageData[1]);
Scroll.saveScrollPosition(page);
Scroll.saveScrollStyle(page);
pageDatas.push([pageData[0], page, pageData[2], pageData[1], pageManager]);
lastPage = page;
});
pageDatas.unshift(0);
pageDatas.unshift(index);
Array.prototype.splice.apply(stack, pageDatas);
}
function addToStack(index, newPages) {
App._Navigation.enqueue(function(finish) {
addToStackNow(index, newPages);
finish();
});
}
function setupRestoreFunction(options) {
var storedStack, lastPage;
try {
storedStack = JSON.parse(localStorage[STACK_KEY]);
storedTime = parseInt(localStorage[STACK_TIME]);
lastPage = storedStack.pop();
} catch (err) {
return;
}
if (!lastPage) {
return;
}
return function(options, callback) {
switch (typeof options) {
case 'function':
callback = options;
case 'undefined':
options = {};
case 'object':
if (options !== null) {
break;
}
default:
throw TypeError('restore options must be an object if defined, got ' + options);
}
switch (typeof callback) {
case 'undefined':
callback = function() {};
case 'function':
break;
default:
throw TypeError('restore callback must be a function if defined, got ' + callback);
}
if (+new Date() - storedTime >= options.maxAge) {
throw TypeError('restore content is too old');
}
if (!Pages.has(lastPage[0])) {
throw TypeError(lastPage[0] + ' is not a known page');
}
Utils.forEach(storedStack, function(pageData) {
if (!Pages.has(pageData[0])) {
throw TypeError(pageData[0] + ' is not a known page');
}
});
try {
addToStackNow(0, storedStack, true);
} catch (err) {
removeFromStackNow(0, stack.length);
throw Error('failed to restore stack');
}
saveStack();
try {
App.load(lastPage[0], lastPage[1], lastPage[2], callback);
} catch (err) {
removeFromStackNow(0, stack.length);
throw Error('failed to restore stack');
}
};
}
}(window, document, App, App._Utils, App._Scroll, App._Pages);
App._Transitions = function(window, document, Swapper, App, Utils, Scroll, Pages, Stack) {
var TRANSITION_CLASS = 'app-transition',
DEFAULT_TRANSITION_IOS = 'slide-left',
DEFAULT_TRANSITION_ANDROID = 'android-l-in',
DEFAULT_TRANSITION_ANDROID_OLD = 'fade-on',
DEFAULT_TRANSITION_ANDROID_GHETTO = 'instant',
REVERSE_TRANSITION = {
'instant': 'instant',
'fade': 'fade',
'fade-on': 'fade-off',
'fade-off': 'fade-on',
'scale-in': 'scale-out',
'scale-out': 'scale-in',
'rotate-left': 'rotate-right',
'rotate-right': 'rotate-left',
'cube-left': 'cube-right',
'cube-right': 'cube-left',
'swap-left': 'swap-right',
'swap-right': 'swap-left',
'explode-in': 'explode-out',
'explode-out': 'explode-in',
'implode-in': 'implode-out',
'implode-out': 'implode-in',
'slide-left': 'slide-right',
'slide-right': 'slide-left',
'slide-up': 'slide-down',
'slide-down': 'slide-up',
'slideon-left': 'slideoff-left',
'slideon-right': 'slideoff-right',
'slideon-up': 'slideoff-up',
'slideon-down': 'slideoff-down',
'slideoff-left': 'slideon-left',
'slideoff-right': 'slideon-right',
'slideoff-up': 'slideon-up',
'slideoff-down': 'slideon-down',
'slideon-left-ios': 'slideoff-right-ios',
'glideon-right': 'glideoff-right',
'glideoff-right': 'slideon-right',
'glideon-left': 'glideoff-left',
'glideoff-left': 'slideon-left',
'glideon-down': 'glideoff-down',
'glideoff-down': 'slideon-down',
'glideon-up': 'glideoff-up',
'glideoff-up': 'slideon-up',
'android-l-in': 'android-l-out',
'android-l-out': 'android-l-in'
},
WALL_RADIUS = 10;
var shouldDrag = false,
defaultTransition, reverseTransition, dragLock;
if (Utils.os.ios) {
setDefaultTransition(DEFAULT_TRANSITION_IOS);
} else if (Utils.os.android) {
if (Utils.os.version >= 4) {
setDefaultTransition(DEFAULT_TRANSITION_ANDROID);
} else if ((Utils.os.version < 2.3) || /LT15a/i.test(navigator.userAgent)) {
setDefaultTransition(DEFAULT_TRANSITION_ANDROID_GHETTO);
} else {
setDefaultTransition(DEFAULT_TRANSITION_ANDROID_OLD);
}
}
checkForDragTransitionMetaTag();
App.setDefaultTransition = function(transition) {
if (typeof transition === 'object') {
switch (Utils.os.name) {
case 'android':
if ((Utils.os.version < 4) && transition.androidFallback) {
transition = transition.androidFallback;
} else {
transition = transition.android;
}
break;
case 'ios':
if ((Utils.os.version < 5) && transition.iosFallback) {
transition = transition.iosFallback;
} else {
transition = transition.ios;
}
break;
default:
transition = transition.fallback;
break;
}
if (!transition) {
return;
}
}
if (typeof transition !== 'string') {
throw TypeError('transition must be a string if defined, got ' + transition);
}
if (!(transition in REVERSE_TRANSITION)) {
throw TypeError('invalid transition type, got ' + transition);
}
setDefaultTransition(transition);
};
App.getDefaultTransition = function() {
return defaultTransition;
};
App.getReverseTransition = function() {
return reverseTransition;
};
App.enableDragTransition = function() {
allowDragging();
};
return {
REVERSE_TRANSITION: REVERSE_TRANSITION,
run: performTransition,
enableDrag: enableIOS7DragTransition,
disableDrag: disableIOS7DragTransition
};
function setDefaultTransition(transition) {
defaultTransition = transition;
reverseTransition = REVERSE_TRANSITION[defaultTransition];
}
function shouldUseNativeIOSTransition(transition) {
if (!Utils.os.ios) {
return false;
} else if (transition === 'slide-left') {
return true;
} else if (transition === 'slide-right') {
return true;
} else {
return false;
}
}
function performTransition(oldPage, page, options, callback, reverse) {
if (!options.transition) {
options.transition = (reverse ? reverseTransition : defaultTransition);
}
var isIOS7SlideUp = (Utils.os.ios && (Utils.os.version >= 7) && {
'slideon-down': 1,
'slideoff-down': 1
}[options.transition]);
if (!options.duration) {
if (!Utils.os.ios) {
options.duration = 180;
} else if (Utils.os.version < 7) {
options.duration = 325;
} else if (isIOS7SlideUp) {
options.duration = 475;
} else {
options.duration = 425;
}
}
if (!options.easing) {
if (Utils.os.ios) {
if (isIOS7SlideUp) {
options.easing = 'cubic-bezier(0.4,0.6,0.05,1)';
} else if (options.transition === 'slideon-left-ios' || options.transition === 'slideoff-right-ios') {
if (Utils.os.version < 7) {
options.easing = 'ease-in-out';
} else {
options.easing = 'cubic-bezier(0.4,0.6,0.2,1)';
}
}
} else if (Utils.os.android) {
if (options.transition === 'android-l-in') {
options.easing = 'ease-out';
} else if (options.transition === 'android-l-out') {
options.easing = 'ease-in';
}
}
}
document.body.className += ' ' + TRANSITION_CLASS;
if (options.transition === 'instant') {
Swapper(oldPage, page, options, function() {
//TODO: this is stupid. let it be synchronous if it can be.
//TODO: fix the root of the race in core navigation.
setTimeout(finish, 0);
});
} else if (shouldUseNativeIOSTransition(options.transition)) {
performNativeIOSTransition(oldPage, page, options, finish);
} else {
Swapper(oldPage, page, options, finish);
}
function finish() {
document.body.className = document.body.className.replace(new RegExp('\\b' + TRANSITION_CLASS + '\\b'), '');
callback();
}
}
function performNativeIOSTransition(oldPage, page, options, callback) {
var slideLeft = (options.transition === 'slide-left'),
topPage = slideLeft ? page : oldPage,
transitions = getNativeIOSTransitionList(page, oldPage, slideLeft);
if (!transitions) {
// proper iOS transition not possible, fallback to normal
Swapper(oldPage, page, options, callback);
return;
}
var oldPosition = topPage.style.position,
oldZIndex = topPage.style.zIndex,
oldBackground = topPage.style.background;
topPage.style.position = 'fixed';
topPage.style.zIndex = '4000';
topPage.style.background = 'none';
if (slideLeft) {
oldPage.parentNode.insertBefore(page, oldPage);
} else if (oldPage.nextSibling) {
oldPage.parentNode.insertBefore(page, oldPage.nextSibling);
} else {
oldPage.parentNode.appendChild(page);
}
if (App._Pages) {
App._Pages.fixContent(oldPage);
App._Pages.fixContent(page);
}
if (Utils.os.version < 7) {
options.easing = 'ease-in-out';
} else {
options.easing = 'cubic-bezier(0.4,0.6,0.2,1)';
}
Utils.animate(transitions, options.duration, options.easing, function() {
oldPage.parentNode.removeChild(oldPage);
topPage.style.position = oldPosition;
topPage.style.zIndex = oldZIndex;
topPage.style.background = oldBackground;
callback();
});
}
function getNativeIOSTransitionList(page, oldPage, slideLeft) {
var currentBar = oldPage.querySelector('.app-topbar'),
currentTitle = oldPage.querySelector('.app-topbar .app-title'),
currentBack = oldPage.querySelector('.app-topbar .left.app-button'),
currentContent = oldPage.querySelector('.app-content'),
newBar = page.querySelector('.app-topbar'),
newTitle = page.querySelector('.app-topbar .app-title'),
newBack = page.querySelector('.app-topbar .left.app-button'),
newContent = page.querySelector('.app-content'),
transitions = [];
if (!currentBar || !newBar || !currentContent || !newContent || !Utils.isVisible(currentBar) || !Utils.isVisible(newBar)) {
return;
}
if (currentBack && (currentBack.getAttribute('data-noslide') !== null)) {
currentBack = undefined;
}
if (newBack && (newBack.getAttribute('data-noslide') !== null)) {
newBack = undefined;
}
// fade topbar
if (slideLeft) {
transitions.push({
opacityStart: 0,
opacityEnd: 1,
elem: newBar
});
} else {
transitions.push({
opacityStart: 1,
opacityEnd: 0,
elem: currentBar
});
}
// slide titles
if (currentTitle) {
transitions.push({
transitionStart: 'translate3d(0,0,0)',
transitionEnd: 'translate3d(' + getTitleTransform(newBack, slideLeft) + 'px,0,0)',
elem: currentTitle
});
}
if (newTitle) {
transitions.push({
transitionStart: 'translate3d(' + getTitleTransform(currentBack, !slideLeft) + 'px,0,0)',
transitionEnd: 'translate3d(0,0,0)',
elem: newTitle
});
}
// slide back button
if (Utils.os.version >= 5) {
if (currentBack) {
transitions.push({
transitionStart: 'translate3d(0,0,0)',
transitionEnd: 'translate3d(' + getBackTransform(currentBack, newBack, !slideLeft) + 'px,0,0)',
elem: currentBack
});
}
if (newBack) {
transitions.push({
transitionStart: 'translate3d(' + getBackTransform(newBack, currentBack, slideLeft) + 'px,0,0)',
transitionEnd: 'translate3d(0,0,0)',
elem: newBack
});
}
}
// slide contents
if (Utils.os.version < 7) {
transitions.push({
transitionStart: 'translate3d(0,0,0)',
transitionEnd: 'translate3d(' + (slideLeft ? -100 : 100) + '%,0,0)',
elem: currentContent
}, {
transitionStart: 'translate3d(' + (slideLeft ? 100 : -100) + '%,0,0)',
transitionEnd: 'translate3d(0,0,0)',
elem: newContent
});
} else {
transitions.push({
transitionStart: 'translate3d(0,0,0)',
transitionEnd: 'translate3d(' + (slideLeft ? -30 : 100) + '%,0,0)',
elem: currentContent
}, {
transitionStart: 'translate3d(' + (slideLeft ? 100 : -30) + '%,0,0)',
transitionEnd: 'translate3d(0,0,0)',
elem: newContent
});
}
return transitions;
}
function getBackTransform(backButton, oldButton, toCenter) {
var fullWidth = backButton.textContent.length * (Utils.os.version < 7 ? 10 : 12),
oldWidth = oldButton ? (oldButton.textContent.length * 15) : 0;
if (!toCenter) {
return (oldWidth - window.innerWidth) / 2;
} else {
return (window.innerWidth - fullWidth) / 2;
}
}
function getTitleTransform(backButton, toLeft) {
var fullWidth = 0;
if (backButton && (Utils.os.version >= 5)) {
fullWidth = backButton.textContent.length * (Utils.os.version < 7 ? 10 : 12);
}
if (!toLeft) {
return (window.innerWidth / 2);
} else {
return (fullWidth - window.innerWidth) / 2;
}
}
function allowDragging() {
shouldDrag = true;
}
function checkForDragTransitionMetaTag() {
var metas = document.querySelectorAll('meta');
for (var i = 0, l = metas.length; i < l; i++) {
if ((metas[i].name === 'app-drag-transition') && (metas[i].content === 'true')) {
allowDragging();
return;
}
}
}
function enableIOS7DragTransition() {
if (!shouldDrag || !Utils.os.ios || (Utils.os.version < 7)) {
return;
}
var pages = Stack.get().slice(-2),
previousPage = pages[0],
currentPage = pages[1],
draggingTouch, lastTouch, navigationLock, dead, slideLeft;
if (!previousPage || !currentPage) {
return;
}
var currentNode = currentPage[3],
currentBar = currentPage[3].querySelector('.app-topbar'),
currentTitle = currentPage[3].querySelector('.app-topbar .app-title'),
currentBack = currentPage[3].querySelector('.app-topbar .left.app-button'),
currentContent = currentPage[3].querySelector('.app-content'),
oldNode = previousPage[3],
oldBar = previousPage[3].querySelector('.app-topbar'),
oldTitle = previousPage[3].querySelector('.app-topbar .app-title'),
oldBack = previousPage[3].querySelector('.app-topbar .left.app-button'),
oldContent = previousPage[3].querySelector('.app-content');
if (!currentNode || !currentBar || !currentContent || !oldNode || !oldBar || !oldContent) {
return;
}
var dragableTransitions = ['slide-left', 'slideon-left-ios'];
if ((dragableTransitions.indexOf(currentPage[4].transition) === -1) && (currentPage[4].transition || dragableTransitions.indexOf(defaultTransition) === -1)) {
return;
} else if ((currentPage[4].transition === 'slide-left') || (!currentPage[4].transition && 'slide-left' === defaultTransition)) {
slideLeft = true;
}
var oldPosition = currentPage[3].style.position,
oldZIndex = currentPage[3].style.zIndex,
oldBackground = currentPage[3].style.background;
currentPage[3].style.position = 'fixed';
currentPage[3].style.zIndex = '4000';
currentPage[3].style.background = 'none'; //TODO: this sucks
if (currentPage[3].nextSibling) {
currentPage[3].parentNode.insertBefore(previousPage[3], currentPage[3].nextSibling);
} else {
currentPage[3].parentNode.appendChild(previousPage[3]);
}
Pages.fixContent(oldNode);
Scroll.restoreScrollPosition(oldNode);
window.addEventListener('touchstart', startDrag, false);
window.addEventListener('touchmove', dragMove, false);
window.addEventListener('touchcancel', finishDrag, false);
window.addEventListener('touchend', finishDrag, false);
var goBack = false;
dragLock = function() {
unbindListeners();
cleanupElems();
};
function unbindListeners() {
window.removeEventListener('touchstart', startDrag);
window.removeEventListener('touchmove', dragMove);
window.removeEventListener('touchcancel', finishDrag);
window.removeEventListener('touchend', finishDrag);
}
function cleanupElems() {
currentPage[3].style.position = oldPosition;
currentPage[3].style.zIndex = oldZIndex;
currentPage[3].style.background = oldBackground;
if (previousPage[3].parentNode) {
previousPage[3].parentNode.removeChild(previousPage[3]);
}
}
function startDrag(e) {
if (draggingTouch || navigationLock || dead) {
return;
}
var touch = (e.touches && e.touches[0]);
if (!touch || (touch.pageX > WALL_RADIUS)) {
return;
}
if (!Pages.fire(currentPage[2], currentPage[3], Pages.EVENTS.BEFORE_BACK)) {
return;
}
e.preventDefault();
App._Navigation.enqueue(function(unlock) {
navigationLock = unlock;
//TODO: what if transition is already over?
}, true);
document.body.className += ' ' + TRANSITION_CLASS;
draggingTouch = lastTouch = {
x: touch.pageX,
y: touch.pageY
};
currentBar.style.webkitTransition = 'all 0s linear';
if (currentTitle) {
currentTitle.style.webkitTransition = 'all 0s linear';
}
if (currentBack) {
currentBack.style.webkitTransition = 'all 0s linear';
}
currentContent.style.webkitTransition = 'all 0s linear';
oldBar.style.webkitTransition = 'all 0s linear';
if (oldTitle) {
oldTitle.style.webkitTransition = 'all 0s linear';
}
if (oldBack) {
oldBack.style.webkitTransition = 'all 0s linear';
}
oldContent.style.webkitTransition = 'all 0s linear';
}
function dragMove(e) {
if (draggingTouch && e.touches && e.touches[0] && !dead) {
if (lastTouch) {
goBack = (lastTouch.x < e.touches[0].pageX);
}
lastTouch = {
x: e.touches[0].pageX,
y: e.touches[0].pageY
};
var progress = Math.min(Math.max(0, (lastTouch.x - draggingTouch.x) / window.innerWidth), 1);
setDragPosition(progress);
}
}
function finishDrag(e) {
if (!draggingTouch || !navigationLock || dead) {
return;
}
unbindListeners();
lastTouch = (e.touches && e.touches[0]) || lastTouch;
var progess = 0;
if (lastTouch) {
progress = (lastTouch.x - draggingTouch.x) / window.innerWidth;
}
var dontTransition = ((progress < 0.1 && !goBack) || (0.9 < progress && goBack));
if (!dontTransition) {
currentBar.style.webkitTransitionDuration = '0.15s';
if (currentTitle) {
currentTitle.style.webkitTransitionDuration = '0.15s';
}
if (currentBack) {
currentBack.style.webkitTransitionDuration = '0.15s';
}
currentContent.style.webkitTransitionDuration = '0.15s';
oldBar.style.webkitTransitionDuration = '0.15s';
if (oldTitle) {
oldTitle.style.webkitTransitionDuration = '0.15s';
}
if (oldBack) {
oldBack.style.webkitTransitionDuration = '0.15s';
}
oldContent.style.webkitTransitionDuration = '0.15s';
}
if (goBack) {
Pages.fire(currentPage[2], currentPage[3], Pages.EVENTS.BACK);
setDragPosition(1);
} else {
setDragPosition(0);
}
draggingTouch = lastTouch = null;
if (!dontTransition) {
currentPage[3].addEventListener('webkitTransitionEnd', finishTransition, false);
} else {
finishTransition();
}
function finishTransition() {
currentPage[3].removeEventListener('webkitTransitionEnd', finishTransition);
if (goBack) {
if (currentPage[3].parentNode) {
currentPage[3].parentNode.removeChild(currentPage[3]);
}
} else {
if (previousPage[3].parentNode) {
previousPage[3].parentNode.removeChild(previousPage[3]);
}
}
currentPage[3].style.position = oldPosition;
currentPage[3].style.zIndex = oldZIndex;
currentPage[3].style.background = oldBackground;
currentBar.style.webkitTransition = '';
currentBar.style.webkitTransform = '';
if (currentTitle) {
currentTitle.style.webkitTransition = '';
currentTitle.style.webkitTransform = '';
}
if (currentBack) {
currentBack.style.webkitTransition = '';
currentBack.style.webkitTransform = '';
}
currentContent.style.webkitTransition = '';
currentContent.style.webkitTransform = '';
oldBar.style.webkitTransition = '';
oldBar.style.webkitTransform = '';
if (oldTitle) {
oldTitle.style.webkitTransition = '';
oldTitle.style.webkitTransform = '';
}
if (oldBack) {
oldBack.style.webkitTransition = '';
oldBack.style.webkitTransform = '';
}
oldContent.style.webkitTransition = '';
oldContent.style.webkitTransform = '';
document.body.className = document.body.className.replace(new RegExp('\\b' + TRANSITION_CLASS + '\\b'), '');
if (goBack) {
Pages.startDestruction(currentPage[0], currentPage[2], currentPage[3], currentPage[1]);
Pages.fixContent(oldNode);
Scroll.restoreScrollStyle(oldNode);
currentPage[2].showing = false
Pages.fire(currentPage[2], currentPage[3], Pages.EVENTS.HIDE);
previousPage[2].showing = true
Pages.fire(previousPage[2], oldNode, Pages.EVENTS.SHOW);
Pages.finishDestruction(currentPage[0], currentPage[2], currentPage[3], currentPage[1]);
Stack.pop();
App._Navigation.update();
}
dragLock = null;
navigationLock();
}
}
function setDragPosition(progress) {
if (slideLeft) {
currentBar.style.opacity = 1 - progress;
if (currentTitle) {
currentTitle.style.webkitTransform = 'translate3d(' + (progress * window.innerWidth / 2) + 'px,0,0)';
}
if (currentBack) {
currentBack.style.webkitTransform = 'translate3d(' + (progress * (window.innerWidth - currentBack.textContent.length * 12) / 2) + 'px,0,0)';
}
if (oldTitle) {
oldTitle.style.webkitTransform = 'translate3d(' + ((1 - progress) * (window.innerWidth - currentBack.textContent.length * 12) / -2) + 'px,0,0)';
}
if (oldBack) {
oldBack.style.webkitTransform = 'translate3d(' + ((1 - progress) * -150) + '%,0,0)';
}
} else {
currentBar.style.webkitTransform = 'translate3d(' + (progress * 100) + '%,0,0)';
oldBar.style.webkitTransform = 'translate3d(' + ((1 - progress) * -30) + '%,0,0)';
}
currentContent.style.webkitTransform = 'translate3d(' + (progress * 100) + '%,0,0)';
oldContent.style.webkitTransform = 'translate3d(' + ((1 - progress) * -30) + '%,0,0)';
}
}
function disableIOS7DragTransition() {
if (dragLock) {
dragLock();
dragLock = null;
}
}
}(window, document, Swapper, App, App._Utils, App._Scroll, App._Pages, App._Stack);
App._Navigation = function(window, document, App, Dialog, Scroll, Pages, Stack, Transitions) {
var navQueue = [],
navLock = false,
current, currentNode;
App.current = function() {
return current;
};
App.load = function(pageName, args, options, callback) {
if (typeof pageName !== 'string') {
throw TypeError('page name must be a string, got ' + pageName);
}
switch (typeof args) {
case 'function':
options = args;
args = {};
case 'string':
callback = options;
options = args;
case 'undefined':
args = {};
case 'object':
break;
default:
throw TypeError('page arguments must be an object if defined, got ' + args);
}
switch (typeof options) {
case 'function':
callback = options;
case 'undefined':
options = {};
case 'object':
break;
case 'string':
options = {
transition: options
};
break;
default:
throw TypeError('options must be an object if defined, got ' + options);
}
switch (typeof callback) {
case 'undefined':
callback = function() {};
case 'function':
break;
default:
throw TypeError('callback must be a function if defined, got ' + callback);
}
return loadPage(pageName, args, options, callback);
};
App.back = function(pageName, callback) {
switch (typeof pageName) {
case 'function':
callback = pageName;
case 'undefined':
pageName = undefined;
case 'string':
break;
default:
throw TypeError('pageName must be a string if defined, got ' + pageName);
}
switch (typeof callback) {
case 'undefined':
callback = function() {};
case 'function':
break;
default:
throw TypeError('callback must be a function if defined, got ' + callback);
}
return navigateBack(pageName, callback);
};
App.pick = function(pageName, args, options, loadCallback, callback) {
if (typeof pageName !== 'string') {
throw TypeError('page name must be a string, got ' + pageName);
}
switch (typeof args) {
case 'function':
options = args;
args = {};
case 'string':
callback = loadCallback;
loadCallback = options;
options = args;
case 'undefined':
args = {};
case 'object':
break;
default:
throw TypeError('page arguments must be an object if defined, got ' + args);
}
switch (typeof options) {
case 'function':
callback = loadCallback;
loadCallback = options;
case 'undefined':
options = {};
case 'object':
break;
case 'string':
options = {
transition: options
};
break;
default:
throw TypeError('options must be an object if defined, got ' + options);
}
if (typeof loadCallback !== 'function') {
throw TypeError('callback must be a function, got ' + loadCallback);
}
switch (typeof callback) {
case 'undefined':
callback = loadCallback;
loadCallback = function() {};
case 'function':
break;
default:
throw TypeError('callback must be a function, got ' + callback);
}
return pickPage(pageName, args, options, loadCallback, callback);
};
App.info = function () {
return {
platform:App.platform
}
}
return {
getCurrentNode: getCurrentNode,
update: updateCurrentNode,
enqueue: navigate
};
function navigate(handler, dragTransition) {
if (navLock) {
navQueue.push(handler);
return false;
}
navLock = true;
if (!dragTransition) {
Transitions.disableDrag();
}
handler(function() {
Stack.save();
navLock = false;
if (!processNavigationQueue()) {
Transitions.enableDrag();
}
});
return true;
}
function processNavigationQueue() {
if (navQueue.length) {
navigate(navQueue.shift());
return true;
} else {
return false;
}
}
function getCurrentNode() {
return currentNode;
}
function updateCurrentNode() {
var lastStackItem = Stack.getCurrent();
current = lastStackItem[0]
currentNode = lastStackItem[3];
}
function loadPage(pageName, args, options, callback, setupPickerMode) {
navigate(function(unlock) {
var oldNode = currentNode,
pageManager = Pages.createManager(false);
if (setupPickerMode) {
setupPickerMode(pageManager);
}
var page = Pages.startGeneration(pageName, pageManager, args),
restoreData = Stack.getCurrent(),
restoreNode = restoreData && restoreData[3],
restoreManager = restoreData && restoreData[2];
if (!options.transition && pageManager.transition) {
options.transition = pageManager.transition;
}
if (!options.duration && pageManager.duration) {
options.duration = pageManager.duration;
}
Pages.populateBackButton(page, oldNode || restoreNode);
if (!current) {
App.restore = null;
document.body.appendChild(page);
Pages.fire(pageManager, page, Pages.EVENTS.LAYOUT);
updatePageData();
finish();
} else {
Scroll.saveScrollPosition(currentNode);
var newOptions = {};
for (var key in options) {
newOptions[key] = options[key];
}
uiBlockedTask(function(unlockUI) {
Transitions.run(currentNode, page, newOptions, function() {
Pages.fixContent(page);
unlockUI();
finish();
});
Pages.fire(pageManager, page, Pages.EVENTS.LAYOUT);
});
//TODO: what if instant swap?
updatePageData();
}
function updatePageData() {
current = pageName;
currentNode = page;
Stack.push([pageName, args, pageManager, page, options]);
if (oldNode && restoreManager) {
Pages.fire(restoreManager, oldNode, Pages.EVENTS.FORWARD);
}
}
function finish() {
Scroll.saveScrollStyle(oldNode);
Pages.finishGeneration(pageName, pageManager, page, args);
unlock();
callback();
if (oldNode && restoreManager) {
restoreManager.showing = false
Pages.fire(restoreManager, oldNode, Pages.EVENTS.HIDE);
}
pageManager.showing = true;
Pages.fire(pageManager, page, Pages.EVENTS.SHOW);
}
});
if (!Pages.has(pageName)) {
return false;
}
}
function navigateBack(backPageName, callback) {
if (Dialog.status() && Dialog.close() && !backPageName) {
callback();
return;
}
var stack = Stack.get().map(function(page) {
return page[0];
});
if (!stack.length) {
throw Error(backPageName + ' is not currently in the stack, cannot go back to it');
}
if (backPageName) {
var index = -1;
for (var i = stack.length - 1; i >= 0; i--) {
if (stack[i] === backPageName) {
index = i;
break;
}
}
if (index === -1) {
throw Error(backPageName + ' is not currently in the stack, cannot go back to it');
}
if (index !== stack.length - 2) {
App.removeFromStack(index + 1);
}
}
var stackLength = stack.length,
cancelled = false;
var navigatedImmediately = navigate(function(unlock) {
if (Stack.size() < 2) {
unlock();
callback();
return;
}
var oldPage = Stack.getCurrent();
if (!Pages.fire(oldPage[2], oldPage[3], Pages.EVENTS.BEFORE_BACK)) {
cancelled = true;
unlock();
callback();
return;
} else {
Stack.pop();
}
var data = Stack.getCurrent(),
pageName = data[0],
page = data[3],
oldOptions = oldPage[4];
Pages.fire(oldPage[2], oldPage[3], Pages.EVENTS.BACK);
Pages.fixContent(page);
Pages.startDestruction(oldPage[0], oldPage[2], oldPage[3], oldPage[1]);
Scroll.restoreScrollPosition(page);
var newOptions = {};
for (var key in oldOptions) {
if (key === 'transition') {
newOptions[key] = Transitions.REVERSE_TRANSITION[oldOptions[key]] || oldOptions[key];
} else {
newOptions[key] = oldOptions[key];
}
}
uiBlockedTask(function(unlockUI) {
Transitions.run(currentNode, page, newOptions, function() {
Pages.fixContent(page);
Scroll.restoreScrollStyle(page);
unlockUI();
oldPage[2].showing = false
Pages.fire(oldPage[2], oldPage[3], Pages.EVENTS.HIDE);
data[2].showing = true
Pages.fire(data[2], page, Pages.EVENTS.SHOW);
setTimeout(function() {
Pages.finishDestruction(oldPage[0], oldPage[2], oldPage[3], oldPage[1]);
unlock();
callback();
}, 0);
}, true);
Pages.fixContent(page);
Pages.fire(data[2], page, Pages.EVENTS.LAYOUT);
});
current = pageName;
currentNode = page;
});
if (cancelled || (navigatedImmediately && (stackLength < 2))) {
return false;
}
}
function pickPage(pageName, args, options, loadCallback, callback) {
var finished = false;
loadPage(pageName, args, options, loadCallback, function(pageManager) {
pageManager.restorable = false;
pageManager.reply = function() {
if (!finished) {
finished = true;
if (!pageManager._appNoBack) {
navigateBack(undefined, function() {});
}
callback.apply(App, arguments);
}
};
});
}
// blocks UI interaction during some aysnchronous task
// is not locked because multiple calls dont effect eachother
function uiBlockedTask(task) {
var taskComplete = false;
var clickBlocker = document.createElement('div');
clickBlocker.className = 'app-clickblocker';
document.body.appendChild(clickBlocker);
clickBlocker.addEventListener('touchstart', function(e) {
e.preventDefault();
}, false);
task(function() {
if (taskComplete) {
return;
}
taskComplete = true;
document.body.removeChild(clickBlocker);
});
}
}(window, document, App, App._Dialog, App._Scroll, App._Pages, App._Stack, App._Transitions);
// Hack to fix Android L issue where touch events don't get propagated
(function(document, App, Utils) {
if (App.platform !== 'android' || App.platformVersion < 5) {
return;
}
Utils.ready(function() {
setTimeout(function() {
var nodes = [].slice.call(document.body.childNodes);
nodes.forEach(function(node) {
document.body.removeChild(node);
});
nodes.forEach(function(node) {
document.body.appendChild(node);
});
}, 200);
});
})(document, App, App._Utils);