Created
February 6, 2016 00:05
-
-
Save alejandrorangel/c66f337e3ec85ce79b87 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Copyright Spotify AB 2012-2014. All rights reserved. | |
History.getInternetExplorerMajorVersion() | |
Get's the major version of Internet Explorer | |
@return {integer} | |
@license Public Domain | |
@author Benjamin Arthur Lupton <contact@balupton.com> | |
@author James Padolsey <https://gist.github.com/527683> | |
History.isInternetExplorer() | |
Are we using Internet Explorer? | |
@return {boolean} | |
@license Public Domain | |
@author Benjamin Arthur Lupton <contact@balupton.com> | |
History.js Core | |
@author Benjamin Arthur Lupton <contact@balupton.com> | |
@copyright 2010-2011 Benjamin Arthur Lupton <contact@balupton.com> | |
@license New BSD License <http://creativecommons.org/licenses/BSD/> | |
History.js HTML4 Support | |
Depends on the HTML5 Support | |
@author Benjamin Arthur Lupton <contact@balupton.com> | |
@copyright 2010-2011 Benjamin Arthur Lupton <contact@balupton.com> | |
@license New BSD License <http://creativecommons.org/licenses/BSD/> | |
CryptoJS v3.1.2 | |
code.google.com/p/crypto-js | |
(c) 2009-2013 by Jeff Mott. All rights reserved. | |
code.google.com/p/crypto-js/wiki/License | |
History.js Native Adapter | |
@author Benjamin Arthur Lupton <contact@balupton.com> | |
@copyright 2010-2011 Benjamin Arthur Lupton <contact@balupton.com> | |
@license New BSD License <http://creativecommons.org/licenses/BSD/> | |
*/ | |
Spotify.Web.ABTester = Spotify.Web.ABTester || {}; | |
(function(c) { | |
function a(a) { | |
var b = 0, | |
c = e[a]; | |
if (c) return c; | |
b = 0; | |
c = Array(1E4); | |
for (i = 0; i < c.length; i++) c[i] = i; | |
var h = f(d(j(a))), | |
b = parseInt(h.substring(0, 8), 16); | |
(function(a) { | |
for (var c = a.length - 1; c >= 1; c--) { | |
b = 16807 * b % 2147483647; | |
var v = b % (c + 1), | |
e = a[c]; | |
a[c] = a[v]; | |
a[v] = e | |
} | |
})(c); | |
return e[a] = c | |
} | |
function b(b, c) { | |
if (c && c.substring(0, 4) == "NTX_") { | |
var v = a(c), | |
e = parseInt(f(d(j("spotify:test:" + b))).substring(0, 8), 16), | |
e = Math.floor(1E4 * e * Math.pow(2, -32)); | |
return Math.floor(v[e] / 10) | |
} else return v = "spotify:test:", c && (v += c + ":"), v += | |
b, v = parseInt(f(d(j(v))).substring(0, 8), 16), Math.floor(1E3 * v * Math.pow(2, -32)) | |
} | |
function d(a) { | |
for (var b = Array(a.length >> 2), c = 0; c < b.length; c++) b[c] = 0; | |
for (c = 0; c < a.length * 8; c += 8) b[c >> 5] |= (a.charCodeAt(c / 8) & 255) << c % 32; | |
a = a.length * 8; | |
b[a >> 5] |= 128 << a % 32; | |
b[(a + 64 >>> 9 << 4) + 14] = a; | |
for (var a = 1732584193, c = -271733879, e = -1732584194, d = 271733878, f = 0; f < b.length; f += 16) var j = a, | |
o = c, | |
n = e, | |
B = d, | |
a = g(a, c, e, d, b[f + 0], 7, -680876936), | |
d = g(d, a, c, e, b[f + 1], 12, -389564586), | |
e = g(e, d, a, c, b[f + 2], 17, 606105819), | |
c = g(c, e, d, a, b[f + 3], 22, -1044525330), | |
a = g(a, c, e, d, b[f + 4], 7, -176418897), | |
d = g(d, a, c, e, b[f + 5], 12, 1200080426), | |
e = g(e, d, a, c, b[f + 6], 17, -1473231341), | |
c = g(c, e, d, a, b[f + 7], 22, -45705983), | |
a = g(a, c, e, d, b[f + 8], 7, 1770035416), | |
d = g(d, a, c, e, b[f + 9], 12, -1958414417), | |
e = g(e, d, a, c, b[f + 10], 17, -42063), | |
c = g(c, e, d, a, b[f + 11], 22, -1990404162), | |
a = g(a, c, e, d, b[f + 12], 7, 1804603682), | |
d = g(d, a, c, e, b[f + 13], 12, -40341101), | |
e = g(e, d, a, c, b[f + 14], 17, -1502002290), | |
c = g(c, e, d, a, b[f + 15], 22, 1236535329), | |
a = k(a, c, e, d, b[f + 1], 5, -165796510), | |
d = k(d, a, c, e, b[f + 6], 9, -1069501632), | |
e = k(e, d, a, c, b[f + 11], 14, 643717713), | |
c = k(c, e, d, a, b[f + 0], 20, -373897302), | |
a = k(a, c, e, d, b[f + 5], 5, -701558691), | |
d = k(d, a, c, e, b[f + 10], 9, 38016083), | |
e = k(e, d, a, c, b[f + 15], 14, -660478335), | |
c = k(c, e, d, a, b[f + 4], 20, -405537848), | |
a = k(a, c, e, d, b[f + 9], 5, 568446438), | |
d = k(d, a, c, e, b[f + 14], 9, -1019803690), | |
e = k(e, d, a, c, b[f + 3], 14, -187363961), | |
c = k(c, e, d, a, b[f + 8], 20, 1163531501), | |
a = k(a, c, e, d, b[f + 13], 5, -1444681467), | |
d = k(d, a, c, e, b[f + 2], 9, -51403784), | |
e = k(e, d, a, c, b[f + 7], 14, 1735328473), | |
c = k(c, e, d, a, b[f + 12], 20, -1926607734), | |
a = l(a, c, e, d, b[f + 5], 4, -378558), | |
d = l(d, a, c, e, b[f + 8], 11, -2022574463), | |
e = l(e, d, a, c, b[f + 11], 16, 1839030562), | |
c = l(c, e, d, a, b[f + 14], 23, -35309556), | |
a = l(a, c, e, d, b[f + 1], 4, -1530992060), | |
d = l(d, a, c, e, b[f + 4], 11, 1272893353), | |
e = l(e, d, a, c, b[f + 7], 16, -155497632), | |
c = l(c, e, d, a, b[f + 10], 23, -1094730640), | |
a = l(a, c, e, d, b[f + 13], 4, 681279174), | |
d = l(d, a, c, e, b[f + 0], 11, -358537222), | |
e = l(e, d, a, c, b[f + 3], 16, -722521979), | |
c = l(c, e, d, a, b[f + 6], 23, 76029189), | |
a = l(a, c, e, d, b[f + 9], 4, -640364487), | |
d = l(d, a, c, e, b[f + 12], 11, -421815835), | |
e = l(e, d, a, c, b[f + 15], 16, 530742520), | |
c = l(c, e, d, a, b[f + 2], 23, -995338651), | |
a = h(a, c, e, d, b[f + 0], 6, -198630844), | |
d = h(d, a, c, e, b[f + 7], 10, 1126891415), | |
e = h(e, d, a, c, b[f + 14], 15, -1416354905), | |
c = h(c, e, d, a, b[f + 5], 21, -57434055), | |
a = h(a, c, e, d, b[f + 12], 6, 1700485571), | |
d = h(d, a, c, e, b[f + 3], 10, -1894986606), | |
e = h(e, d, a, c, b[f + 10], 15, -1051523), | |
c = h(c, e, d, a, b[f + 1], 21, -2054922799), | |
a = h(a, c, e, d, b[f + 8], 6, 1873313359), | |
d = h(d, a, c, e, b[f + 15], 10, -30611744), | |
e = h(e, d, a, c, b[f + 6], 15, -1560198380), | |
c = h(c, e, d, a, b[f + 13], 21, 1309151649), | |
a = h(a, c, e, d, b[f + 4], 6, -145523070), | |
d = h(d, a, c, e, b[f + 11], 10, -1120210379), | |
e = h(e, d, a, c, b[f + 2], 15, 718787259), | |
c = h(c, e, d, a, b[f + 9], 21, -343485551), | |
a = m(a, j), | |
c = m(c, o), | |
e = m(e, n), | |
d = m(d, B); | |
b = [a, c, e, d]; | |
a = ""; | |
for (c = 0; c < b.length * 32; c += 8) a += String.fromCharCode(b[c >> 5] >>> c % 32 & 255); | |
return a | |
} | |
function f(a) { | |
for (var b = o ? "0123456789ABCDEF" : "0123456789abcdef", c = "", e, d = 0; d < a.length; d++) e = a.charCodeAt(d), c += b.charAt(e >>> 4 & 15) + b.charAt(e & 15); | |
return c | |
} | |
function j(a) { | |
for (var b = "", c = -1, e, d; ++c < a.length;) e = a.charCodeAt(c), d = c + 1 < a.length ? a.charCodeAt(c + 1) : 0, 55296 <= e && e <= 56319 && 56320 <= d && d <= 57343 && (e = 65536 + ((e & 1023) << 10) + (d & 1023), c++), e <= 127 ? b += String.fromCharCode(e) : | |
e <= 2047 ? b += String.fromCharCode(192 | e >>> 6 & 31, 128 | e & 63) : e <= 65535 ? b += String.fromCharCode(224 | e >>> 12 & 15, 128 | e >>> 6 & 63, 128 | e & 63) : e <= 2097151 && (b += String.fromCharCode(240 | e >>> 18 & 7, 128 | e >>> 12 & 63, 128 | e >>> 6 & 63, 128 | e & 63)); | |
return b | |
} | |
function g(a, b, c, e, d, h, f) { | |
return m(n(m(m(a, b & c | ~b & e), m(d, f)), h), b) | |
} | |
function k(a, b, c, e, d, h, f) { | |
return m(n(m(m(a, b & e | c & ~e), m(d, f)), h), b) | |
} | |
function l(a, b, c, e, d, h, f) { | |
return m(n(m(m(a, b ^ c ^ e), m(d, f)), h), b) | |
} | |
function h(a, b, c, e, d, h, f) { | |
return m(n(m(m(a, c ^ (b | ~e)), m(d, f)), h), b) | |
} | |
function m(a, b) { | |
var c = | |
(a & 65535) + (b & 65535); | |
return (a >> 16) + (b >> 16) + (c >> 16) << 16 | c & 65535 | |
} | |
function n(a, b) { | |
return a << b | a >>> 32 - b | |
} | |
var e = {}, | |
o = 0; | |
c.getGroupId = b; | |
c.getDefaultGroupId = function(a) { | |
return b(a, "") | |
} | |
})(Spotify.Web.ABTester); | |
(function(c, a) { | |
var b = c.History = c.History || {}; | |
if (typeof b.Adapter !== "undefined") throw Error("History.js Adapter has already been loaded..."); | |
b.Adapter = { | |
handlers: {}, | |
_uid: 1, | |
uid: function(a) { | |
return a._uid || (a._uid = b.Adapter._uid++) | |
}, | |
bind: function(a, c, j) { | |
var g = b.Adapter.uid(a); | |
b.Adapter.handlers[g] = b.Adapter.handlers[g] || {}; | |
b.Adapter.handlers[g][c] = b.Adapter.handlers[g][c] || []; | |
b.Adapter.handlers[g][c].push(j); | |
a["on" + c] = function(a, c) { | |
return function(d) { | |
b.Adapter.trigger(a, c, d) | |
} | |
}(a, c) | |
}, | |
trigger: function(a, | |
c, j) { | |
var j = j || {}, | |
a = b.Adapter.uid(a), | |
g, k; | |
b.Adapter.handlers[a] = b.Adapter.handlers[a] || {}; | |
b.Adapter.handlers[a][c] = b.Adapter.handlers[a][c] || []; | |
for (g = 0, k = b.Adapter.handlers[a][c].length; g < k; ++g) b.Adapter.handlers[a][c][g].apply(this, [j]) | |
}, | |
extractEventData: function(b, c) { | |
return c && c[b] || a | |
}, | |
onDomLoad: function(a) { | |
var b = c.setTimeout(function() { | |
a() | |
}, 2E3); | |
c.onload = function() { | |
clearTimeout(b); | |
a() | |
} | |
} | |
}; | |
typeof b.init !== "undefined" && b.init() | |
})(window); | |
(function(c, a) { | |
var b = c.console || a, | |
d = c.document, | |
f = c.navigator, | |
j = c.sessionStorage || !1, | |
g = c.setTimeout, | |
k = c.clearTimeout, | |
l = c.setInterval, | |
h = c.clearInterval, | |
m = c.JSON, | |
n = c.alert, | |
e = c.History = c.History || {}, | |
o = c.history; | |
m.stringify = m.stringify || m.encode; | |
m.parse = m.parse || m.decode; | |
if (typeof e.init !== "undefined") throw Error("History.js Core has already been loaded..."); | |
e.init = function() { | |
if (typeof e.Adapter === "undefined") return !1; | |
typeof e.initCore !== "undefined" && e.initCore(); | |
typeof e.initHtml4 !== "undefined" && e.initHtml4(); | |
return !0 | |
}; | |
e.initCore = function() { | |
if (typeof e.initCore.initialized !== "undefined") return !1; | |
else e.initCore.initialized = !0; | |
e.options = e.options || {}; | |
e.options.hashChangeInterval = e.options.hashChangeInterval || 100; | |
e.options.safariPollInterval = e.options.safariPollInterval || 500; | |
e.options.doubleCheckInterval = e.options.doubleCheckInterval || 500; | |
e.options.storeInterval = e.options.storeInterval || 1E3; | |
e.options.busyDelay = e.options.busyDelay || 250; | |
e.options.debug = e.options.debug || !1; | |
e.options.initialTitle = e.options.initialTitle || | |
d.title; | |
e.intervalList = []; | |
e.clearAllIntervals = function() { | |
var a, b = e.intervalList; | |
if (typeof b !== "undefined" && b !== null) { | |
for (a = 0; a < b.length; a++) h(b[a]); | |
e.intervalList = null | |
} | |
}; | |
e.debug = function() { | |
e.options.debug && e.log.apply(e, arguments) | |
}; | |
e.log = function() { | |
var a = !(typeof b === "undefined" || typeof b.log === "undefined" || typeof b.log.apply === "undefined"), | |
c = d.getElementById("log"), | |
e, h, f, g; | |
a ? (h = Array.prototype.slice.call(arguments), e = h.shift(), typeof b.debug !== "undefined" ? b.debug.apply(b, [e, h]) : b.log.apply(b, [e, | |
h | |
])) : e = "\n" + arguments[0] + "\n"; | |
for (h = 1, f = arguments.length; h < f; ++h) { | |
g = arguments[h]; | |
if (typeof g === "object" && typeof m !== "undefined") try { | |
g = m.stringify(g) | |
} catch (l) {} | |
e += "\n" + g + "\n" | |
} | |
c ? (c.value += e + "\n-----\n", c.scrollTop = c.scrollHeight - c.clientHeight) : a || n(e); | |
return !0 | |
}; | |
e.getInternetExplorerMajorVersion = function() { | |
return e.getInternetExplorerMajorVersion.cached = typeof e.getInternetExplorerMajorVersion.cached !== "undefined" ? e.getInternetExplorerMajorVersion.cached : function() { | |
for (var a = 3, b = d.createElement("div"), | |
c = b.getElementsByTagName("i"); | |
(b.innerHTML = "<\!--[if gt IE " + ++a + "]><i></i><![endif]--\>") && c[0];); | |
return a > 4 ? a : !1 | |
}() | |
}; | |
e.isInternetExplorer = function() { | |
return e.isInternetExplorer.cached = typeof e.isInternetExplorer.cached !== "undefined" ? e.isInternetExplorer.cached : Boolean(e.getInternetExplorerMajorVersion()) | |
}; | |
e.emulated = { | |
pushState: !Boolean(c.history && c.history.pushState && c.history.replaceState && !(/ Mobile\/([1-7][a-z]|(8([abcde]|f(1[0-8]))))/i.test(f.userAgent) || /AppleWebKit\/5([0-2]|3[0-2])/i.test(f.userAgent))), | |
hashChange: Boolean(!("onhashchange" in c || "onhashchange" in d) || e.isInternetExplorer() && e.getInternetExplorerMajorVersion() < 8) | |
}; | |
e.enabled = !e.emulated.pushState; | |
e.bugs = { | |
setHash: Boolean(!e.emulated.pushState && f.vendor === "Apple Computer, Inc." && /AppleWebKit\/5([0-2]|3[0-3])/.test(f.userAgent)), | |
safariPoll: Boolean(!e.emulated.pushState && f.vendor === "Apple Computer, Inc." && /AppleWebKit\/5([0-2]|3[0-3])/.test(f.userAgent)), | |
ieDoubleCheck: Boolean(e.isInternetExplorer() && e.getInternetExplorerMajorVersion() < 8), | |
hashEscape: Boolean(e.isInternetExplorer() && e.getInternetExplorerMajorVersion() < 7) | |
}; | |
e.isEmptyObject = function(a) { | |
for (var b in a) return !1; | |
return !0 | |
}; | |
e.cloneObject = function(a) { | |
a ? (a = m.stringify(a), a = m.parse(a)) : a = {}; | |
return a | |
}; | |
e.getRootUrl = function() { | |
var a = d.location.protocol + "//" + (d.location.hostname || d.location.host); | |
d.location.port && (a += ":" + d.location.port); | |
a += "/"; | |
return a | |
}; | |
e.getBaseHref = function() { | |
var a = d.getElementsByTagName("base"), | |
b = null, | |
b = ""; | |
a.length === 1 && (b = a[0], b = b.href.replace(/[^\/]+$/, "")); | |
(b = b.replace(/\/+$/, "")) && (b += "/"); | |
return b | |
}; | |
e.getBaseUrl = function() { | |
return e.getBaseHref() || e.getBasePageUrl() || e.getRootUrl() | |
}; | |
e.getPageUrl = function() { | |
return ((e.getState(!1, !1) || {}).url || d.location.href).replace(/\/+$/, "").replace(/[^\/]+$/, function(a) { | |
return /\./.test(a) ? a : a + "/" | |
}) | |
}; | |
e.getBasePageUrl = function() { | |
return d.location.href.replace(/[#\?].*/, "").replace(/[^\/]+$/, function(a) { | |
return /[^\/]$/.test(a) ? "" : a | |
}).replace(/\/+$/, "") + "/" | |
}; | |
e.getFullUrl = function(a, b) { | |
var c = a, | |
d = a.substring(0, 1), | |
b = typeof b === | |
"undefined" ? !0 : b; | |
/[a-z]+\:\/\//.test(a) || (c = d === "/" ? e.getRootUrl() + a.replace(/^\/+/, "") : d === "#" ? e.getPageUrl().replace(/#.*/, "") + a : d === "?" ? e.getPageUrl().replace(/[\?#].*/, "") + a : b ? e.getBaseUrl() + a.replace(/^(\.\/)+/, "") : e.getBasePageUrl() + a.replace(/^(\.\/)+/, "")); | |
return c.replace(/\#$/, "") | |
}; | |
e.getShortUrl = function(a) { | |
var b = e.getBaseUrl(), | |
c = e.getRootUrl(); | |
e.emulated.pushState && (a = a.replace(b, "")); | |
a = a.replace(c, "/"); | |
e.isTraditionalAnchor(a) && (a = "./" + a); | |
return a = a.replace(/^(\.\/)+/g, "./").replace(/\#$/, | |
"") | |
}; | |
e.getLocationHref = function(a) { | |
a = a || d; | |
return a.URL === a.location.href ? a.location.href : a.location.href === decodeURIComponent(a.URL) ? a.URL : a.location.hash && decodeURIComponent(a.location.href.replace(/^[^#]+/, "")) === a.location.hash ? a.location.href : a.URL.indexOf("#") == -1 && a.location.href.indexOf("#") != -1 ? a.location.href : a.URL || a.location.href | |
}; | |
e.store = {}; | |
e.idToState = e.idToState || {}; | |
e.stateToId = e.stateToId || {}; | |
e.urlToId = e.urlToId || {}; | |
e.storedStates = e.storedStates || []; | |
e.savedStates = e.savedStates || []; | |
e.normalizeStore = function() { | |
e.store.idToState = e.store.idToState || {}; | |
e.store.urlToId = e.store.urlToId || {}; | |
e.store.stateToId = e.store.stateToId || {} | |
}; | |
e.getState = function(a, b) { | |
typeof a === "undefined" && (a = !0); | |
typeof b === "undefined" && (b = !0); | |
var c = e.getLastSavedState(); | |
!c && b && (c = e.createStateObject()); | |
if (a) c = e.cloneObject(c), c.url = c.cleanUrl || c.url; | |
return c | |
}; | |
e.getIdByState = function(a) { | |
var b = e.extractId(a.url), | |
c; | |
if (!b) | |
if (c = e.getStateString(a), typeof e.stateToId[c] !== "undefined") b = e.stateToId[c]; | |
else if (typeof e.store.stateToId[c] !== | |
"undefined") b = e.store.stateToId[c]; | |
else { | |
for (;;) | |
if (b = (new Date).getTime() + String(Math.random()).replace(/\D/g, ""), typeof e.idToState[b] === "undefined" && typeof e.store.idToState[b] === "undefined") break; | |
e.stateToId[c] = b; | |
e.idToState[b] = a | |
} | |
return b | |
}; | |
e.normalizeState = function(a) { | |
var b; | |
if (!a || typeof a !== "object") a = {}; | |
if (typeof a.normalized !== "undefined") return a; | |
if (!a.data || typeof a.data !== "object") a.data = {}; | |
b = { | |
normalized: !0 | |
}; | |
b.title = a.title || ""; | |
b.url = e.getFullUrl(a.url || e.getLocationHref()); | |
b.hash = e.getShortUrl(b.url); | |
b.data = e.cloneObject(a.data); | |
b.id = e.getIdByState(b); | |
b.cleanUrl = b.url.replace(/\??\&_suid.*/, ""); | |
b.url = b.cleanUrl; | |
a = !e.isEmptyObject(b.data); | |
if (b.title || a) b.hash = e.getShortUrl(b.url).replace(/\??\&_suid.*/, ""), /\?/.test(b.hash) || (b.hash += "?"), b.hash += "&_suid=" + b.id; | |
b.hashedUrl = e.getFullUrl(b.hash); | |
if ((e.emulated.pushState || e.bugs.safariPoll) && e.hasUrlDuplicate(b)) b.url = b.hashedUrl; | |
return b | |
}; | |
e.createStateObject = function(a, b, c) { | |
a = { | |
data: a, | |
title: b, | |
url: c | |
}; | |
return a = e.normalizeState(a) | |
}; | |
e.getStateById = function(b) { | |
b = | |
String(b); | |
return e.idToState[b] || e.store.idToState[b] || a | |
}; | |
e.getStateString = function(a) { | |
a = { | |
data: e.normalizeState(a).data, | |
title: a.title, | |
url: a.url | |
}; | |
return m.stringify(a) | |
}; | |
e.getStateId = function(a) { | |
return e.normalizeState(a).id | |
}; | |
e.getHashByState = function(a) { | |
return e.normalizeState(a).hash | |
}; | |
e.extractId = function(a) { | |
return ((a = /(.*)\&_suid=([0-9]+)$/.exec(a)) ? String(a[2] || "") : "") || !1 | |
}; | |
e.isTraditionalAnchor = function(a) { | |
return !/[\/\?\.]/.test(a) | |
}; | |
e.extractState = function(a, b) { | |
var c = null, | |
d, h, b = b || !1; | |
(d = e.extractId(a)) && | |
(c = e.getStateById(d)); | |
c || (h = e.getFullUrl(a), (d = e.getIdByUrl(h) || !1) && (c = e.getStateById(d)), !c && b && !e.isTraditionalAnchor(a) && (c = e.createStateObject(null, null, h))); | |
return c | |
}; | |
e.getIdByUrl = function(b) { | |
return e.urlToId[b] || e.store.urlToId[b] || a | |
}; | |
e.getLastSavedState = function() { | |
return e.savedStates[e.savedStates.length - 1] || a | |
}; | |
e.getLastStoredState = function() { | |
return e.storedStates[e.storedStates.length - 1] || a | |
}; | |
e.hasUrlDuplicate = function(a) { | |
var b = !1; | |
return b = (b = e.extractState(a.url)) && b.id !== a.id | |
}; | |
e.storeState = | |
function(a) { | |
e.urlToId[a.url] = a.id; | |
e.storedStates.push(e.cloneObject(a)); | |
return a | |
}; | |
e.isLastSavedState = function(a) { | |
var b = !1; | |
if (e.savedStates.length) a = a.id, b = e.getLastSavedState(), b = b.id, b = a === b; | |
return b | |
}; | |
e.saveState = function(a) { | |
if (e.isLastSavedState(a)) return !1; | |
e.savedStates.push(e.cloneObject(a)); | |
return !0 | |
}; | |
e.getStateByIndex = function(a) { | |
var b = null; | |
return b = typeof a === "undefined" ? e.savedStates[e.savedStates.length - 1] : a < 0 ? e.savedStates[e.savedStates.length + a] : e.savedStates[a] | |
}; | |
e.getHash = function() { | |
return e.unescapeHash(d.location.hash) | |
}; | |
e.unescapeString = function(a) { | |
return a | |
}; | |
e.unescapeHash = function(a) { | |
a = e.normalizeHash(a); | |
return a = decodeURI(a) | |
}; | |
e.normalizeHash = function(a) { | |
return a.replace(/[^#]*#/, "").replace(/#.*/, "") | |
}; | |
e.setHash = function(a, b) { | |
var c, h; | |
if (b !== !1 && e.busy()) return e.pushQueue({ | |
scope: e, | |
callback: e.setHash, | |
args: arguments, | |
queue: b | |
}), !1; | |
c = e.escapeHash(a); | |
e.busy(!0); | |
if ((h = e.extractState(a, !0)) && !e.emulated.pushState) e.pushState(h.data, h.title, h.url, !1); | |
else if (d.location.hash !== c) e.bugs.setHash ? (h = e.getPageUrl(), e.pushState(null, | |
null, h + "#" + c, !1)) : d.location.hash = c; | |
return e | |
}; | |
e.escapeHash = function(a) { | |
a = e.normalizeHash(a); | |
a = c.encodeURI(a); | |
e.bugs.hashEscape || (a = a.replace(/\%21/g, "!").replace(/\%26/g, "&").replace(/\%3D/g, "=").replace(/\%3F/g, "?")); | |
return a | |
}; | |
e.getHashByUrl = function(a) { | |
a = String(a).replace(/([^#]*)#?([^#]*)#?(.*)/, "$2"); | |
return a = e.unescapeHash(a) | |
}; | |
e.setTitle = function(a) { | |
var b = a.title, | |
c; | |
b || (c = e.getStateByIndex(0)) && c.url === a.url && (b = c.title || e.options.initialTitle); | |
try { | |
d.getElementsByTagName("title")[0].innerHTML = | |
b.replace("<", "<").replace(">", ">").replace(" & ", " & ") | |
} catch (h) {} | |
d.title = b; | |
return e | |
}; | |
e.queues = []; | |
e.busy = function(a) { | |
if (typeof a !== "undefined") e.busy.flag = a; | |
else if (typeof e.busy.flag === "undefined") e.busy.flag = !1; | |
if (!e.busy.flag) { | |
k(e.busy.timeout); | |
var b = function() { | |
var a, c; | |
if (!e.busy.flag) | |
for (a = e.queues.length - 1; a >= 0; --a) | |
if (c = e.queues[a], c.length !== 0) c = c.shift(), e.fireQueueItem(c), e.busy.timeout = g(b, e.options.busyDelay) | |
}; | |
e.busy.timeout = g(b, e.options.busyDelay) | |
} | |
return e.busy.flag | |
}; | |
e.busy.flag = !1; | |
e.fireQueueItem = function(a) { | |
return a.callback.apply(a.scope || e, a.args || []) | |
}; | |
e.pushQueue = function(a) { | |
e.queues[a.queue || 0] = e.queues[a.queue || 0] || []; | |
e.queues[a.queue || 0].push(a); | |
return e | |
}; | |
e.queue = function(a, b) { | |
typeof a === "function" && (a = { | |
callback: a | |
}); | |
if (typeof b !== "undefined") a.queue = b; | |
e.busy() ? e.pushQueue(a) : e.fireQueueItem(a); | |
return e | |
}; | |
e.clearQueue = function() { | |
e.busy.flag = !1; | |
e.queues = []; | |
return e | |
}; | |
e.stateChanged = !1; | |
e.doubleChecker = !1; | |
e.doubleCheckComplete = function() { | |
e.stateChanged = !0; | |
e.doubleCheckClear(); | |
return e | |
}; | |
e.doubleCheckClear = function() { | |
if (e.doubleChecker) k(e.doubleChecker), e.doubleChecker = !1; | |
return e | |
}; | |
e.doubleCheck = function(a) { | |
e.stateChanged = !1; | |
e.doubleCheckClear(); | |
if (e.bugs.ieDoubleCheck) e.doubleChecker = g(function() { | |
e.doubleCheckClear(); | |
e.stateChanged || a(); | |
return !0 | |
}, e.options.doubleCheckInterval); | |
return e | |
}; | |
e.safariStatePoll = function() { | |
var a = e.extractState(d.location.href); | |
if (!e.isLastSavedState(a)) return a || e.createStateObject(), e.Adapter.trigger(c, "popstate"), e | |
}; | |
e.back = function(a) { | |
if (a !== | |
!1 && e.busy()) return e.pushQueue({ | |
scope: e, | |
callback: e.back, | |
args: arguments, | |
queue: a | |
}), !1; | |
e.busy(!0); | |
e.doubleCheck(function() { | |
e.back(!1) | |
}); | |
o.go(-1); | |
return !0 | |
}; | |
e.forward = function(a) { | |
if (a !== !1 && e.busy()) return e.pushQueue({ | |
scope: e, | |
callback: e.forward, | |
args: arguments, | |
queue: a | |
}), !1; | |
e.busy(!0); | |
e.doubleCheck(function() { | |
e.forward(!1) | |
}); | |
o.go(1); | |
return !0 | |
}; | |
e.go = function(a, b) { | |
var c; | |
if (a > 0) | |
for (c = 1; c <= a; ++c) e.forward(b); | |
else if (a < 0) | |
for (c = -1; c >= a; --c) e.back(b); | |
else throw Error("History.go: History.go requires a positive or negative integer passed."); | |
return e | |
}; | |
if (e.emulated.pushState) { | |
var t = function() {}; | |
e.pushState = e.pushState || t; | |
e.replaceState = e.replaceState || t | |
} else e.onPopState = function(a, b) { | |
var h = !1, | |
h = !1; | |
e.doubleCheckComplete(); | |
if (h = e.getHash()) return (h = e.extractState(h || d.location.href, !0)) ? e.replaceState(h.data, h.title, h.url, !1) : (e.Adapter.trigger(c, "anchorchange"), e.busy(!1)), e.expectedStateId = !1; | |
(h = (h = e.Adapter.extractEventData("state", a, b) || !1) ? e.getStateById(h) : e.expectedStateId ? e.getStateById(e.expectedStateId) : e.extractState(d.location.href)) || | |
(h = e.createStateObject(null, null, d.location.href)); | |
e.expectedStateId = !1; | |
if (e.isLastSavedState(h)) return e.busy(!1), !1; | |
e.storeState(h); | |
e.saveState(h); | |
e.setTitle(h); | |
e.Adapter.trigger(c, "statechange"); | |
e.busy(!1); | |
return !0 | |
}, e.Adapter.bind(c, "popstate", e.onPopState), e.pushState = function(a, b, d, h) { | |
if (e.getHashByUrl(d) && e.emulated.pushState) throw Error("History.js does not support states with fragement-identifiers (hashes/anchors)."); | |
if (h !== !1 && e.busy()) return e.pushQueue({ | |
scope: e, | |
callback: e.pushState, | |
args: arguments, | |
queue: h | |
}), !1; | |
e.busy(!0); | |
var f = e.createStateObject(a, b, d); | |
e.isLastSavedState(f) ? e.busy(!1) : (e.storeState(f), e.expectedStateId = f.id, o.pushState(f.id, f.title, f.url), e.Adapter.trigger(c, "popstate")); | |
return !0 | |
}, e.replaceState = function(a, b, d, h) { | |
if (e.getHashByUrl(d) && e.emulated.pushState) throw Error("History.js does not support states with fragement-identifiers (hashes/anchors)."); | |
if (h !== !1 && e.busy()) return e.pushQueue({ | |
scope: e, | |
callback: e.replaceState, | |
args: arguments, | |
queue: h | |
}), !1; | |
e.busy(!0); | |
var f = e.createStateObject(a, | |
b, d); | |
e.isLastSavedState(f) ? e.busy(!1) : (e.storeState(f), e.expectedStateId = f.id, o.replaceState(f.id, f.title, f.url), e.Adapter.trigger(c, "popstate")); | |
return !0 | |
}; | |
if (j) try { | |
e.store = m.parse(j.getItem("History.store")) || {} | |
} catch (C) { | |
e.store = {} | |
} else e.store = {}; | |
e.normalizeStore(); | |
e.Adapter.bind(c, "beforeunload", e.clearAllIntervals); | |
e.Adapter.bind(c, "unload", e.clearAllIntervals); | |
e.saveState(e.storeState(e.extractState(d.location.href, !0))); | |
if (j) e.onUnload = function() { | |
var a, b; | |
try { | |
a = m.parse(j.getItem("History.store")) || {} | |
} catch (c) { | |
a = {} | |
} | |
a.idToState = a.idToState || {}; | |
a.urlToId = a.urlToId || {}; | |
a.stateToId = a.stateToId || {}; | |
for (b in e.idToState) e.idToState.hasOwnProperty(b) && (a.idToState[b] = e.idToState[b]); | |
for (b in e.urlToId) e.urlToId.hasOwnProperty(b) && (a.urlToId[b] = e.urlToId[b]); | |
for (b in e.stateToId) e.stateToId.hasOwnProperty(b) && (a.stateToId[b] = e.stateToId[b]); | |
e.store = a; | |
e.normalizeStore(); | |
j.setItem("History.store", m.stringify(a)) | |
}, e.intervalList.push(l(e.onUnload, e.options.storeInterval)), e.Adapter.bind(c, "beforeunload", | |
e.onUnload), e.Adapter.bind(c, "unload", e.onUnload); | |
if (!e.emulated.pushState && (e.bugs.safariPoll && e.intervalList.push(l(e.safariStatePoll, e.options.safariPollInterval)), f.vendor === "Apple Computer, Inc." || (f.appCodeName || "") === "Mozilla")) | |
if (e.Adapter.bind(c, "hashchange", function() { | |
e.Adapter.trigger(c, "popstate") | |
}), e.getHash()) e.Adapter.onDomLoad(function() { | |
e.Adapter.trigger(c, "hashchange") | |
}) | |
}; | |
e.init() | |
})(window); | |
(function(c) { | |
var a = c.document, | |
b = c.setInterval || b, | |
d = c.History = c.History || {}; | |
if (typeof d.initHtml4 !== "undefined") throw Error("History.js HTML4 Support has already been loaded..."); | |
d.initHtml4 = function() { | |
if (typeof d.initHtml4.initialized !== "undefined") return !1; | |
else d.initHtml4.initialized = !0; | |
d.enabled = !0; | |
d.savedHashes = []; | |
d.isLastHash = function(a) { | |
var b = d.getHashByIndex(); | |
return a === b | |
}; | |
d.saveHash = function(a) { | |
if (d.isLastHash(a)) return !1; | |
d.savedHashes.push(a); | |
return !0 | |
}; | |
d.getHashByIndex = function(a) { | |
var b = | |
null; | |
return b = typeof a === "undefined" ? d.savedHashes[d.savedHashes.length - 1] : a < 0 ? d.savedHashes[d.savedHashes.length + a] : d.savedHashes[a] | |
}; | |
d.discardedHashes = {}; | |
d.discardedStates = {}; | |
d.discardState = function(a, b, c) { | |
var k = d.getHashByState(a); | |
d.discardedStates[k] = { | |
discardedState: a, | |
backState: c, | |
forwardState: b | |
}; | |
return !0 | |
}; | |
d.discardHash = function(a, b, c) { | |
d.discardedHashes[a] = { | |
discardedHash: a, | |
backState: c, | |
forwardState: b | |
}; | |
return !0 | |
}; | |
d.discardedState = function(a) { | |
a = d.getHashByState(a); | |
return d.discardedStates[a] || !1 | |
}; | |
d.discardedHash = function(a) { | |
return d.discardedHashes[a] || !1 | |
}; | |
d.recycleState = function(a) { | |
var b = d.getHashByState(a); | |
d.discardedState(a) && delete d.discardedStates[b]; | |
return !0 | |
}; | |
if (d.emulated.hashChange) d.hashChangeInit = function() { | |
d.checkerFunction = null; | |
var f = "", | |
j, g, k; | |
d.isInternetExplorer() ? (j = a.createElement("iframe"), j.setAttribute("id", "historyjs-iframe"), j.style.display = "none", a.body.appendChild(j), j.contentWindow.document.open(), j.contentWindow.document.close(), g = "", k = !1, d.checkerFunction = function() { | |
if (k) return !1; | |
k = !0; | |
var a = d.getHash() || "", | |
b = d.unescapeHash(j.contentWindow.document.location.hash) || ""; | |
if (a !== f) { | |
f = a; | |
if (b !== a) g = a, j.contentWindow.document.open(), j.contentWindow.document.close(), j.contentWindow.document.location.hash = d.escapeHash(a); | |
d.Adapter.trigger(c, "hashchange") | |
} else b !== g && (g = b, d.setHash(b, !1)); | |
k = !1; | |
return !0 | |
}) : d.checkerFunction = function() { | |
var a = d.getHash(); | |
a !== f && (f = a, d.Adapter.trigger(c, "hashchange")); | |
return !0 | |
}; | |
d.intervalList.push(b(d.checkerFunction, d.options.hashChangeInterval)); | |
return !0 | |
}, | |
d.Adapter.onDomLoad(d.hashChangeInit); | |
if (d.emulated.pushState) d.onHashChange = function(b) { | |
var j = d.getHashByUrl(b && b.newURL || a.location.href), | |
b = null; | |
if (d.isLastHash(j)) return d.busy(!1), !1; | |
d.doubleCheckComplete(); | |
d.saveHash(j); | |
if (j && d.isTraditionalAnchor(j)) return d.Adapter.trigger(c, "anchorchange"), d.busy(!1), !1; | |
b = d.extractState(d.getFullUrl(j || a.location.href, !1), !0); | |
if (d.isLastSavedState(b)) return d.busy(!1), !1; | |
d.getHashByState(b); | |
if (j = d.discardedState(b)) return d.getHashByIndex(-2) === d.getHashByState(j.forwardState) ? | |
d.back(!1) : d.forward(!1), !1; | |
d.pushState(b.data, b.title, b.url, !1); | |
return !0 | |
}, d.Adapter.bind(c, "hashchange", d.onHashChange), d.pushState = function(b, j, g, k) { | |
if (d.getHashByUrl(g)) throw Error("History.js does not support states with fragement-identifiers (hashes/anchors)."); | |
if (k !== !1 && d.busy()) return d.pushQueue({ | |
scope: d, | |
callback: d.pushState, | |
args: arguments, | |
queue: k | |
}), !1; | |
d.busy(!0); | |
var l = d.createStateObject(b, j, g), | |
h = d.getHashByState(l), | |
m = d.getState(!1), | |
m = d.getHashByState(m), | |
n = d.getHash(); | |
d.storeState(l); | |
d.expectedStateId = | |
l.id; | |
d.recycleState(l); | |
d.setTitle(l); | |
if (h === m) return d.busy(!1), !1; | |
if (h !== n && h !== d.getShortUrl(a.location.href)) return d.setHash(h, !1), !1; | |
d.saveState(l); | |
d.Adapter.trigger(c, "statechange"); | |
d.busy(!1); | |
return !0 | |
}, d.replaceState = function(a, b, c, k) { | |
if (d.getHashByUrl(c)) throw Error("History.js does not support states with fragement-identifiers (hashes/anchors)."); | |
if (k !== !1 && d.busy()) return d.pushQueue({ | |
scope: d, | |
callback: d.replaceState, | |
args: arguments, | |
queue: k | |
}), !1; | |
d.busy(!0); | |
var l = d.createStateObject(a, b, c), | |
h = d.getState(!1), | |
m = d.getStateByIndex(-2); | |
d.discardState(h, l, m); | |
d.pushState(l.data, l.title, l.url, !1); | |
return !0 | |
}; | |
if (d.emulated.pushState && d.getHash() && !d.emulated.hashChange) d.Adapter.onDomLoad(function() { | |
d.Adapter.trigger(c, "hashchange") | |
}) | |
}; | |
typeof d.init !== "undefined" && d.init() | |
})(window); | |
CryptoJS = window && window.CryptoJS || function(c, a) { | |
var b = {}, | |
d = b.lib = {}, | |
f = function() {}, | |
j = d.Base = { | |
extend: function(a) { | |
f.prototype = this; | |
var b = new f; | |
a && b.mixIn(a); | |
b.hasOwnProperty("init") || (b.init = function() { | |
b.$super.init.apply(this, arguments) | |
}); | |
b.init.prototype = b; | |
b.$super = this; | |
return b | |
}, | |
create: function() { | |
var a = this.extend(); | |
a.init.apply(a, arguments); | |
return a | |
}, | |
init: function() {}, | |
mixIn: function(a) { | |
for (var b in a) a.hasOwnProperty(b) && (this[b] = a[b]); | |
a.hasOwnProperty("toString") && | |
(this.toString = a.toString) | |
}, | |
clone: function() { | |
return this.init.prototype.extend(this) | |
} | |
}, | |
g = d.WordArray = j.extend({ | |
init: function(b, c) { | |
b = this.words = b || []; | |
this.sigBytes = c != a ? c : 4 * b.length | |
}, | |
toString: function(a) { | |
return (a || l).stringify(this) | |
}, | |
concat: function(a) { | |
var b = this.words, | |
c = a.words, | |
e = this.sigBytes, | |
a = a.sigBytes; | |
this.clamp(); | |
if (e % 4) | |
for (var d = 0; d < a; d++) b[e + d >>> 2] |= (c[d >>> 2] >>> 24 - 8 * (d % 4) & 255) << 24 - 8 * ((e + d) % 4); | |
else if (65535 < c.length) | |
for (d = 0; d < a; d += 4) b[e + d >>> 2] = c[d >>> 2]; | |
else b.push.apply(b, c); | |
this.sigBytes += | |
a; | |
return this | |
}, | |
clamp: function() { | |
var a = this.words, | |
b = this.sigBytes; | |
a[b >>> 2] &= 4294967295 << 32 - 8 * (b % 4); | |
a.length = c.ceil(b / 4) | |
}, | |
clone: function() { | |
var a = j.clone.call(this); | |
a.words = this.words.slice(0); | |
return a | |
}, | |
random: function(a) { | |
for (var b = [], e = 0; e < a; e += 4) b.push(4294967296 * c.random() | 0); | |
return new g.init(b, a) | |
} | |
}), | |
k = b.enc = {}, | |
l = k.Hex = { | |
stringify: function(a) { | |
for (var b = a.words, a = a.sigBytes, c = [], e = 0; e < a; e++) { | |
var d = b[e >>> 2] >>> 24 - 8 * (e % 4) & 255; | |
c.push((d >>> 4).toString(16)); | |
c.push((d & 15).toString(16)) | |
} | |
return c.join("") | |
}, | |
parse: function(a) { | |
for (var b = a.length, c = [], e = 0; e < b; e += 2) c[e >>> 3] |= parseInt(a.substr(e, 2), 16) << 24 - 4 * (e % 8); | |
return new g.init(c, b / 2) | |
} | |
}, | |
h = k.Latin1 = { | |
stringify: function(a) { | |
for (var b = a.words, a = a.sigBytes, c = [], e = 0; e < a; e++) c.push(String.fromCharCode(b[e >>> 2] >>> 24 - 8 * (e % 4) & 255)); | |
return c.join("") | |
}, | |
parse: function(a) { | |
for (var b = a.length, c = [], e = 0; e < b; e++) c[e >>> 2] |= (a.charCodeAt(e) & 255) << 24 - 8 * (e % 4); | |
return new g.init(c, b) | |
} | |
}, | |
m = k.Utf8 = { | |
stringify: function(a) { | |
try { | |
return decodeURIComponent(escape(h.stringify(a))) | |
} catch (b) { | |
throw Error("Malformed UTF-8 data"); | |
} | |
}, | |
parse: function(a) { | |
return h.parse(unescape(encodeURIComponent(a))) | |
} | |
}, | |
n = d.BufferedBlockAlgorithm = j.extend({ | |
reset: function() { | |
this._data = new g.init; | |
this._nDataBytes = 0 | |
}, | |
_append: function(a) { | |
"string" == typeof a && (a = m.parse(a)); | |
this._data.concat(a); | |
this._nDataBytes += a.sigBytes | |
}, | |
_process: function(a) { | |
var b = this._data, | |
e = b.words, | |
d = b.sigBytes, | |
h = this.blockSize, | |
f = d / (4 * h), | |
f = a ? c.ceil(f) : c.max((f | 0) - this._minBufferSize, 0), | |
a = f * h, | |
d = c.min(4 * a, d); | |
if (a) { | |
for (var l = 0; l < a; l += h) this._doProcessBlock(e, l); | |
l = e.splice(0, a); | |
b.sigBytes -= | |
d | |
} | |
return new g.init(l, d) | |
}, | |
clone: function() { | |
var a = j.clone.call(this); | |
a._data = this._data.clone(); | |
return a | |
}, | |
_minBufferSize: 0 | |
}); | |
d.Hasher = n.extend({ | |
cfg: j.extend(), | |
init: function(a) { | |
this.cfg = this.cfg.extend(a); | |
this.reset() | |
}, | |
reset: function() { | |
n.reset.call(this); | |
this._doReset() | |
}, | |
update: function(a) { | |
this._append(a); | |
this._process(); | |
return this | |
}, | |
finalize: function(a) { | |
a && this._append(a); | |
return this._doFinalize() | |
}, | |
blockSize: 16, | |
_createHelper: function(a) { | |
return function(b, c) { | |
return (new a.init(c)).finalize(b) | |
} | |
}, | |
_createHmacHelper: function(a) { | |
return function(b, | |
c) { | |
return (new e.HMAC.init(a, c)).finalize(b) | |
} | |
} | |
}); | |
var e = b.algo = {}; | |
return b | |
}(Math); | |
(function(c) { | |
function a(a, b, c, d, h, g, f) { | |
a = a + (b & c | ~b & d) + h + f; | |
return (a << g | a >>> 32 - g) + b | |
} | |
function b(a, b, c, d, h, g, f) { | |
a = a + (b & d | c & ~d) + h + f; | |
return (a << g | a >>> 32 - g) + b | |
} | |
function d(a, b, c, d, h, g, f) { | |
a = a + (b ^ c ^ d) + h + f; | |
return (a << g | a >>> 32 - g) + b | |
} | |
function f(a, b, c, d, h, g, f) { | |
a = a + (c ^ (b | ~d)) + h + f; | |
return (a << g | a >>> 32 - g) + b | |
} | |
for (var j = CryptoJS, g = j.lib, k = g.WordArray, l = g.Hasher, g = j.algo, h = [], m = 0; 64 > m; m++) h[m] = 4294967296 * c.abs(c.sin(m + 1)) | 0; | |
g = g.MD5 = l.extend({ | |
_doReset: function() { | |
this._hash = new k.init([1732584193, 4023233417, 2562383102, 271733878]) | |
}, | |
_doProcessBlock: function(c, e) { | |
for (var g = 0; 16 > g; g++) { | |
var l = e + g, | |
k = c[l]; | |
c[l] = (k << 8 | k >>> 24) & 16711935 | (k << 24 | k >>> 8) & 4278255360 | |
} | |
var g = this._hash.words, | |
l = c[e + 0], | |
k = c[e + 1], | |
j = c[e + 2], | |
m = c[e + 3], | |
w = c[e + 4], | |
A = c[e + 5], | |
x = c[e + 6], | |
u = c[e + 7], | |
y = c[e + 8], | |
B = c[e + 9], | |
D = c[e + 10], | |
G = c[e + 11], | |
E = c[e + 12], | |
F = c[e + 13], | |
I = c[e + 14], | |
H = c[e + 15], | |
p = g[0], | |
r = g[1], | |
s = g[2], | |
q = g[3], | |
p = a(p, r, s, q, l, 7, h[0]), | |
q = a(q, p, r, s, k, 12, h[1]), | |
s = a(s, q, p, r, j, 17, h[2]), | |
r = a(r, s, q, p, m, 22, h[3]), | |
p = a(p, r, s, q, w, 7, h[4]), | |
q = a(q, p, r, s, A, 12, h[5]), | |
s = a(s, q, p, r, x, 17, h[6]), | |
r = a(r, s, q, p, u, 22, h[7]), | |
p = a(p, r, s, q, y, 7, h[8]), | |
q = a(q, p, r, s, B, 12, h[9]), | |
s = a(s, q, p, r, D, 17, h[10]), | |
r = a(r, s, q, p, G, 22, h[11]), | |
p = a(p, r, s, q, E, 7, h[12]), | |
q = a(q, p, r, s, F, 12, h[13]), | |
s = a(s, q, p, r, I, 17, h[14]), | |
r = a(r, s, q, p, H, 22, h[15]), | |
p = b(p, r, s, q, k, 5, h[16]), | |
q = b(q, p, r, s, x, 9, h[17]), | |
s = b(s, q, p, r, G, 14, h[18]), | |
r = b(r, s, q, p, l, 20, h[19]), | |
p = b(p, r, s, q, A, 5, h[20]), | |
q = b(q, p, r, s, D, 9, h[21]), | |
s = b(s, q, p, r, H, 14, h[22]), | |
r = b(r, s, q, p, w, 20, h[23]), | |
p = b(p, r, s, q, B, 5, h[24]), | |
q = b(q, p, r, s, I, 9, h[25]), | |
s = b(s, q, p, r, m, 14, h[26]), | |
r = b(r, s, q, p, y, 20, h[27]), | |
p = b(p, r, s, q, F, 5, h[28]), | |
q = b(q, p, | |
r, s, j, 9, h[29]), | |
s = b(s, q, p, r, u, 14, h[30]), | |
r = b(r, s, q, p, E, 20, h[31]), | |
p = d(p, r, s, q, A, 4, h[32]), | |
q = d(q, p, r, s, y, 11, h[33]), | |
s = d(s, q, p, r, G, 16, h[34]), | |
r = d(r, s, q, p, I, 23, h[35]), | |
p = d(p, r, s, q, k, 4, h[36]), | |
q = d(q, p, r, s, w, 11, h[37]), | |
s = d(s, q, p, r, u, 16, h[38]), | |
r = d(r, s, q, p, D, 23, h[39]), | |
p = d(p, r, s, q, F, 4, h[40]), | |
q = d(q, p, r, s, l, 11, h[41]), | |
s = d(s, q, p, r, m, 16, h[42]), | |
r = d(r, s, q, p, x, 23, h[43]), | |
p = d(p, r, s, q, B, 4, h[44]), | |
q = d(q, p, r, s, E, 11, h[45]), | |
s = d(s, q, p, r, H, 16, h[46]), | |
r = d(r, s, q, p, j, 23, h[47]), | |
p = f(p, r, s, q, l, 6, h[48]), | |
q = f(q, p, r, s, u, 10, h[49]), | |
s = f(s, q, p, r, | |
I, 15, h[50]), | |
r = f(r, s, q, p, A, 21, h[51]), | |
p = f(p, r, s, q, E, 6, h[52]), | |
q = f(q, p, r, s, m, 10, h[53]), | |
s = f(s, q, p, r, D, 15, h[54]), | |
r = f(r, s, q, p, k, 21, h[55]), | |
p = f(p, r, s, q, y, 6, h[56]), | |
q = f(q, p, r, s, H, 10, h[57]), | |
s = f(s, q, p, r, x, 15, h[58]), | |
r = f(r, s, q, p, F, 21, h[59]), | |
p = f(p, r, s, q, w, 6, h[60]), | |
q = f(q, p, r, s, G, 10, h[61]), | |
s = f(s, q, p, r, j, 15, h[62]), | |
r = f(r, s, q, p, B, 21, h[63]); | |
g[0] = g[0] + p | 0; | |
g[1] = g[1] + r | 0; | |
g[2] = g[2] + s | 0; | |
g[3] = g[3] + q | 0 | |
}, | |
_doFinalize: function() { | |
var a = this._data, | |
b = a.words, | |
d = 8 * this._nDataBytes, | |
h = 8 * a.sigBytes; | |
b[h >>> 5] |= 128 << 24 - h % 32; | |
var g = c.floor(d / | |
4294967296); | |
b[(h + 64 >>> 9 << 4) + 15] = (g << 8 | g >>> 24) & 16711935 | (g << 24 | g >>> 8) & 4278255360; | |
b[(h + 64 >>> 9 << 4) + 14] = (d << 8 | d >>> 24) & 16711935 | (d << 24 | d >>> 8) & 4278255360; | |
a.sigBytes = 4 * (b.length + 1); | |
this._process(); | |
a = this._hash; | |
b = a.words; | |
for (d = 0; 4 > d; d++) h = b[d], b[d] = (h << 8 | h >>> 24) & 16711935 | (h << 24 | h >>> 8) & 4278255360; | |
return a | |
}, | |
clone: function() { | |
var a = l.clone.call(this); | |
a._hash = this._hash.clone(); | |
return a | |
} | |
}); | |
j.MD5 = l._createHelper(g); | |
j.HmacMD5 = l._createHmacHelper(g) | |
})(Math); | |
Spotify.Web.Widgets = Spotify.Web.Widgets || {}; | |
(function(c) { | |
function a(a) { | |
this.node = null; | |
this.isActive = a.activated === !0; | |
this.options = a; | |
this._activeText = a.activeText || _("ON"); | |
this._inactiveText = a.inactiveText || _("OFF"); | |
this.document = a.document || document; | |
this._buildNodes(); | |
this._setupEventHandling() | |
} | |
a.prototype._buildNodes = function() { | |
this.node = this.document.createElement("div"); | |
this.node.className = "sp-toggle"; | |
this.isActive && (this.node.className += " active"); | |
this._activeNode = this.document.createElement("span"); | |
this._activeNode.textContent = this._activeText; | |
this._activeNode.className = "active-text"; | |
this._inactiveNode = this.document.createElement("span"); | |
this._inactiveNode.textContent = this._inactiveText; | |
this._inactiveNode.className = "inactive-text"; | |
this._handle = this.document.createElement("button"); | |
this._handle.className = "handle"; | |
this._handleWrapper = this.document.createElement("span"); | |
this._handleWrapper.className = "sp-toggle-inner"; | |
this._overlay = this.document.createElement("span"); | |
this._overlay.className = "sp-toggle-overlay"; | |
this._handleWrapper.appendChild(this._activeNode); | |
this._handleWrapper.appendChild(this._handle); | |
this._handleWrapper.appendChild(this._inactiveNode); | |
this.node.appendChild(this._handleWrapper); | |
this.node.appendChild(this._overlay) | |
}; | |
a.prototype._setupEventHandling = function() { | |
var a = this, | |
c, f; | |
setTimeout(function() { | |
a._maxHandleTravel = a.node.offsetWidth - a._handle.offsetWidth | |
}, 10); | |
this.node.addEventListener("mouseup", function(j) { | |
j.preventDefault(); | |
c = (new Date).getTime(); | |
c - f < 250 && a.toggle() | |
}, !1); | |
this.node.addEventListener("mousedown", function(c) { | |
c.preventDefault(); | |
f = (new Date).getTime(); | |
(c.target === a._handle || c.target === a._overlay) && a._doDragHandle.call(a, c) | |
}, !1); | |
this._handle.addEventListener("keypress", function(c) { | |
c.preventDefault(); | |
a.toggle() | |
}, !1); | |
this._handle.addEventListener("click", function(a) { | |
a.stopPropagation(); | |
a.preventDefault() | |
}, !1) | |
}; | |
a.prototype._doDragHandle = function(a) { | |
function c(a) { | |
a = a || window.event; | |
k = a.clientX - g; | |
h = k + l; | |
h <= -40 && (h = -40); | |
h >= 0 && (h = 0); | |
j._handleWrapper.style.left = h + "px" | |
} | |
function f() { | |
j.node.className = j.node.className.replace(" dragging", | |
""); | |
j._handleWrapper.style.left = null; | |
Math.abs(k) > 5 && k * m >= j._maxHandleTravel / 2 && j.toggle(); | |
j.document.removeEventListener("mousemove", c); | |
j.document.removeEventListener("mouseup", f); | |
j.node.removeEventListener("mouseout", f) | |
} | |
var j = this, | |
a = a || window.event; | |
a.preventDefault(); | |
var g = a.clientX, | |
k = 0, | |
l = j._handleWrapper.offsetLeft, | |
h = null, | |
m = this.isActive ? -1 : 1; | |
this.node.className += " dragging"; | |
j.document.addEventListener("mousemove", c); | |
j.document.addEventListener("mouseup", f); | |
j.node.addEventListener("mouseout", f) | |
}; | |
a.prototype.toggle = function() { | |
this.isActive ? this.deactivate() : this.activate() | |
}; | |
a.prototype.activate = function(a) { | |
if (!this.isActive) this.isActive = !0, this.node.className += " active", !a && typeof this.options.onActivate === "function" && this.options.onActivate.apply(this), !a && typeof this.options.onChange === "function" && this.options.onChange.apply(this) | |
}; | |
a.prototype.deactivate = function(a) { | |
if (this.isActive) this.isActive = !1, this.node.className = this.node.className.replace(" active", ""), !a && typeof this.options.onDeactivate === | |
"function" && this.options.onDeactivate.apply(this), !a && typeof this.options.onChange === "function" && this.options.onChange.apply(this) | |
}; | |
c.Toggle = a | |
})(Spotify.Web.Widgets); | |
Spotify.Web.Sociomantic = function(c, a) { | |
function b(a) { | |
var b = a.services; | |
this.track = function(a) { | |
if (a) { | |
try { | |
window.sociomantic.sonar.adv[o].clear() | |
} catch (b) { | |
return | |
} | |
var c = "Listen to " + a.name + " on Spotify", | |
e = a.uri.split(":")[2], | |
d = this.getCategoryId(a), | |
g = a.image && a.image.replace("/unbranded/", "/300/"); | |
window.product = { | |
identifier: a.uri || "", | |
fn: "Spotify - Join Now", | |
brand: a.name || "", | |
description: c, | |
category: d, | |
price: "", | |
amount: "", | |
currency: m, | |
url: "http://open.spotify.com/artist/" + e, | |
photo: g || "" | |
}; | |
window.customer = { | |
mhash: n, | |
segment: j | |
}; | |
h > 0 && (window.customer.segment = h); | |
window.sociomantic.sonar.adv[o].track() | |
} | |
}; | |
this.getArtistDataAndTrack = function(a) { | |
var c = this; | |
b.getArtistMetadata("spotify:artist:" + a, function(a) { | |
a !== !1 && c.track(a) | |
}) | |
}; | |
this.getCategoryId = function(a) { | |
var b = ""; | |
if (typeof a.getRelatedArtists === "function") | |
for (var a = a.getRelatedArtists(), c = 0, e = Math.min(a.length, 3), d = null; c < e; c++) d = a[c], b += d.replace("spotify:artist:", ""); | |
return b | |
} | |
} | |
function d(a, c) { | |
if (!a.bridge || !a.bridge.player || !(c instanceof b)) return null; | |
var e = | |
a.bridge.player, | |
d, h = !1; | |
this.getArtistId = function(a) { | |
var b = this; | |
e.getState(function(c, e) { | |
if (c !== !0) { | |
try { | |
var d = e.track.artists[0].uri.split(":")[2] | |
} catch (h) { | |
return | |
} | |
typeof a === "function" && a.call(b, d) | |
} | |
}) | |
}; | |
this.startTimerAndMarkAsTracked = function() { | |
var a = this; | |
clearTimeout(d); | |
d = setTimeout(function() { | |
a.getArtistId(function(a) { | |
c.getArtistDataAndTrack(a); | |
h = !0 | |
}) | |
}, k) | |
}; | |
this.resetTimer = function() { | |
clearTimeout(d) | |
}; | |
this.subscribe = function() { | |
var a = this; | |
e.registerForPlayerEvents(function(b, c) { | |
c.type === "trackLoaded" ? | |
h = !1 : c.type === "play" && h === !1 ? a.startTimerAndMarkAsTracked() : c.type === "pause" && a.resetTimer(); | |
a.subscribe() | |
}) | |
}; | |
this.subscribe() | |
} | |
var f = { | |
free: 0, | |
unlimited: 1, | |
premium: 2 | |
}, | |
j = 3, | |
g = { | |
GB: { | |
code: "UK", | |
currency: "GBP" | |
}, | |
IE: { | |
code: "IE", | |
currency: "EUR" | |
}, | |
DE: { | |
code: "DE", | |
currency: "EUR" | |
} | |
}, | |
k = 3E4, | |
l = this, | |
h = null, | |
m = null, | |
n = a, | |
e, o; | |
this.load = function(a) { | |
o = "spotify-" + a.toLowerCase(); | |
var a = document.createElement("script"), | |
b = document.getElementsByTagName("script")[0]; | |
a.type = "text/javascript"; | |
a.async = !0; | |
a.src = ("https:" == document.location.protocol ? | |
"https://" : "http://") + "eu-sonar.sociomantic.com/js/2010-07-01/adpan/" + o; | |
b.parentNode.insertBefore(a, b) | |
}; | |
c.services.getUserInfo(function(a) { | |
var k = a.catalogue, | |
a = g[a.country]; | |
h = f[k] ? f[k] : 0; | |
if (a) m = a.currency, l.load(a.code), e = new b(c), new d(c, e) | |
}) | |
}; | |
Spotify.Web.Core = function(c, a, b, d) { | |
var f = this, | |
j = null, | |
g, k, l = Spotify.PlayerTypes.FLASH_RTMPS, | |
h = !1, | |
m, n = !1, | |
e; | |
this.setTracker = function(a) { | |
this.tracker = a | |
}; | |
var o = function() { | |
this.getMainPlayer(); | |
this.core.trigger("ON_TRY_TO_CONNECT"); | |
e = setTimeout(function() { | |
n || c.notify(Spotify.Web.PublisherMessages.ERROR, { | |
type: Spotify.Web.ErrorTypes.CONNECTING | |
}) | |
}, 2E3); | |
setTimeout(function() { | |
n || f.logAPConnectionFailure() | |
}, 1E4) | |
}, | |
t = function(a) { | |
var b = ""; | |
a.params && a.params.length && (b = a.params[2]); | |
b == "Region mismatch" && (n = !0); | |
c.notify(Spotify.Web.PublisherMessages.ERROR, { | |
type: Spotify.Web.ErrorTypes.CONNECTION_LOST, | |
reason: b | |
}) | |
}, | |
C = function() { | |
c.notify(Spotify.Web.PublisherMessages.ERROR, { | |
type: Spotify.Web.ErrorTypes.CONNECTION_LOST, | |
reason: "" | |
}) | |
}, | |
v = function() { | |
f.getMainPlayer().isPaused || c.notify(Spotify.Web.PublisherMessages.ERROR, { | |
type: Spotify.Web.ErrorTypes.TOKEN_LOST | |
}) | |
}, | |
z = function() { | |
f.core.migrateToIndexedDBStorage(function() {}, function() {}) | |
}, | |
w = function() { | |
c.notify(Spotify.Web.PublisherMessages.ERROR, { | |
type: Spotify.Web.ErrorTypes.WAIT_FOR_COMMERCIAL_TO_FINISH | |
}) | |
}, | |
A = function() { | |
c.notify(Spotify.Web.PublisherMessages.ERROR, { | |
type: Spotify.Web.ErrorTypes.CANNOT_CONNECT_TO_STREAMING_SERVER | |
}) | |
}, | |
x = function() { | |
c.notify(Spotify.Web.PublisherMessages.ERROR, { | |
type: Spotify.Web.ErrorTypes.NO_SOUND_CAPABILITIES | |
}) | |
}, | |
u = function() { | |
h || (c.notify(Spotify.Web.PublisherMessages.ERROR, { | |
type: Spotify.Web.ErrorTypes.FLASH_NOT_AVAILABLE | |
}), h = !0) | |
}, | |
y = function() { | |
this.core && this.core.dispose() | |
}, | |
B = function(a) { | |
c.notify(Spotify.Web.PublisherMessages.ERROR, { | |
type: Spotify.Web.ErrorTypes.TRACK_NOT_PLAYABLE_TIME_CAP, | |
trackUri: a.params.data | |
}) | |
}, | |
D = function() { | |
n = !0 | |
}, | |
G = function() { | |
m || (m = new Spotify.Web.AP.Resolver({ | |
hostname: a.aps.resolver.hostname, | |
site: a.aps.resolver.site, | |
override: a.aps.resolver.override, | |
protocol: window.location.protocol.replace(":", ""), | |
version: a.version | |
})); | |
m.get(function(a) { | |
var e = Spotify.Web.Utils.getQueryStringParameter("ap"); | |
e && (a = e); | |
a ? (a.match(/^(rtmp|ws)s?:\/\//) || (a = k + "://" + a), b.get(function(b) { | |
b === null ? (reloadWarning = !1, c.notify(Spotify.Web.PublisherMessages.ERROR, { | |
type: Spotify.Web.ErrorTypes.SESSION_LOST | |
})) : (d.log("Connecting to " + | |
a), f.core.connectWithToken(a, b)) | |
}, function() {})) : d.error("Couldn't resolve any access points to connect to") | |
}) | |
}; | |
this.detachPlayer = function() { | |
this.getMainPlayer().load = function() {} | |
}; | |
this.getMainPlayer = function() { | |
return this.core.audioManager.getPlayerAtIndex(0) | |
}; | |
this.logAPConnectionFailure = function() { | |
this.tracker && this.tracker.xhrLog("UNABLE_TO_CONNECT") | |
}; | |
this.initialize = function() { | |
g = window.location.href.indexOf("websockets") > -1 || Spotify.Web.BrowserDetect.shouldUseWebSockets ? Spotify.GatewayTypes.WEBSOCKETS : | |
Spotify.GatewayTypes.FLASH; | |
k = g == Spotify.GatewayTypes.FLASH ? "rtmps" : "wss"; | |
if (a.aps.resolver.override && a.aps.resolver.override.match(/^(rtmp|ws)s?:\/\//)) { | |
var b = a.aps.resolver.override.split(/:\/\//); | |
j = b[0]; | |
a.aps.resolver.override = b[1] | |
} | |
j && (k = j); | |
window.addEventListener("unload", y); | |
if (Spotify.Web.BrowserDetect.browser === "Explorer") b = Math.floor(Math.random() * 1E3), a.corejs.SWFUrl += "?rnd=" + b, a.corejs.SWFPlayerUrl += "?rnd=" + b, a.corejs.protoSchemasLocationRandomizer = "?rnd=" + b; | |
a.corejs.features = a.features; | |
Spotify.Storage.localStorage = | |
window.localStorage; | |
Spotify.Storage.indexedDB.storage = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB; | |
Spotify.Storage.indexedDB.IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange; | |
Spotify.Storage.indexedDB.IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction; | |
(l === Spotify.PlayerTypes.FLASH_HTTP || g === Spotify.GatewayTypes.FLASH) && window.addEvent("load", function() { | |
Spotify.Web.FeatureDetect.hasFlashMin() || window.setTimeout(function() { | |
u() | |
}, 1E3) | |
}); | |
Spotify.Web.Debugger.init(a) | |
}; | |
this.connect = function(d) { | |
this.core = new Spotify.Core(g, a.corejs); | |
this.core.onReady(o, this); | |
this.core.onConnect = function() { | |
e && clearTimeout(e); | |
f.core.audioManager.onReady(function() { | |
f.core.audioManager.bind("FAILED_CONNECTING", A, f); | |
f.getMainPlayer().bind("INVALID_TRACK_URI", function(a) { | |
a.params.domain === Spotify.Errors.Domains.TRACK_ERROR && a.params.code !== Spotify.Errors.Codes.TRACK_REQUEST_RATE_LIMITED && a.params.code !== Spotify.Errors.Codes.TIME_CAP && (a.params.code === Spotify.Errors.Codes.TRACK_CAP ? c.notify(Spotify.Web.PublisherMessages.ERROR, { | |
type: Spotify.Web.ErrorTypes.TRACK_NOT_PLAYABLE_TRACK_CAP, | |
trackUri: a.params.data | |
}) : c.notify(Spotify.Web.PublisherMessages.ERROR, { | |
type: Spotify.Web.ErrorTypes.TRACK_NOT_PLAYABLE, | |
trackUri: a.params.data | |
})) | |
}, f); | |
f.core.metadata.onReady(function() { | |
f.core.playlist.onReady(function() { | |
d() | |
}) | |
}) | |
}) | |
}; | |
this.core.onDisconnect = C; | |
this.core.onTokenLost = v; | |
this.core.onFailedConnecting = t.bind(this); | |
this.core.bind("CONNECTION_ESTABLISHED", D, this); | |
this.core.bind("ON_TRY_TO_CONNECT", G, this); | |
this.core.bind("NO_SOUND_CAPABILITIES", | |
x, this); | |
this.core.bind("STORAGE_FULL", z, this); | |
this.core.bind("WAIT_FOR_COMMERCIAL_TO_FINISH", w, this); | |
this.core.bind("FLASH_UNAVAILABLE", u, this); | |
this.core.bind("TIME_CAP", B, this); | |
this.core.bind("PASSWORD_CHANGED", function() { | |
b.dispose(); | |
window.location = window.location.origin + "/logout" | |
}) | |
} | |
}; | |
Spotify = Spotify || {}; | |
Spotify.Web = Spotify.Web || {}; | |
Spotify.Web.FacebookSDK = { | |
_config: null, | |
_scope: null, | |
_initAlreadyCalled: !1, | |
_onInitializedCallbacks: [], | |
_isInitialized: !1, | |
_immediateAuthResponse: null, | |
_triggerOnInitialized: function() { | |
for (var c; c = this._onInitializedCallbacks.shift();) c() | |
}, | |
_onFbAsyncInit: function() { | |
this._isInitialized = !0; | |
FB.Event.subscribe("auth.statusChange", function(c) { | |
this._immediateAuthResponse = c | |
}.bind(this)); | |
FB.init({ | |
version: "v2.2", | |
appId: this._config.appId, | |
status: !0, | |
music: !0 | |
}); | |
this._triggerOnInitialized() | |
}, | |
init: function(c) { | |
if (this._initAlreadyCalled) throw Error("Facebook SDK init() already called"); | |
else this._initAlreadyCalled = !0; | |
this._config = c.config; | |
this._scope = c.scope; | |
window.fbAsyncInit = this._onFbAsyncInit.bind(this); | |
var c = document.getElementsByTagName("script")[0], | |
a = document.createElement("script"); | |
a.id = "facebook-jssdk"; | |
a.src = "//connect.facebook.net/en_US/sdk.js"; | |
c.parentNode.insertBefore(a, c) | |
}, | |
login: function(c) { | |
this.onInitialized(function() { | |
this._immediateAuthResponse && this._immediateAuthResponse.status === "connected" ? c("already_connected", this._immediateAuthResponse.authResponse.userID, | |
this._immediateAuthResponse.authResponse.accessToken) : FB.login(function(a) { | |
a.status === "connected" ? c(a.status, a.authResponse.userID, a.authResponse.accessToken) : c(a.status, null, null) | |
}, { | |
scope: this._scope | |
}) | |
}.bind(this)) | |
}, | |
onInitialized: function(c) { | |
this._isInitialized ? c() : this._onInitializedCallbacks.push(c) | |
} | |
}; | |
Spotify.Web.Debugger = function(c) { | |
c._spdebugger = c._spdebugger || {}; | |
return { | |
store: function(a, b, d) { | |
c._spdebugger[a] = c._spdebugger[a] || {}; | |
c._spdebugger[a][b] = d | |
}, | |
init: function(a) { | |
if (a.debugger_on && typeof DebuggerJS !== "undefined" && typeof DebuggerJS.on === "function") DebuggerJS.on(a.debugger_on) | |
} | |
} | |
}(window || {}); | |
Spotify.Web.AP.Resolver = function(c) { | |
var a = this; | |
this._TTL = 6E4; | |
this._index = -1; | |
this._override = c.override ? c.override : null; | |
this._aps = []; | |
this._ajax = function(a, c, f, j) { | |
(new Request.CORS({ | |
url: a, | |
method: c, | |
onSuccess: f, | |
onFailure: j, | |
onException: j | |
})).send() | |
}; | |
this._identifier = function() { | |
return "24:0:0:" + c.version | |
}; | |
this._getEndpointURL = function() { | |
var a = "?client=" + this._identifier(); | |
return c.protocol + "://" + c.hostname + "/" + a + (c.site ? "&site=" + c.site : "") | |
}; | |
this._resolve = function(a) { | |
this._ajax(this._getEndpointURL(), "GET", | |
function(c) { | |
var f = []; | |
try { | |
f = JSON.parse(c).ap_list || [] | |
} catch (j) {} | |
a(f) | |
}, | |
function() { | |
a([]) | |
}) | |
}; | |
this._next = function() { | |
this._index++; | |
if (this._index + 1 > this._aps.length) this._index = 0; | |
return this._aps[this._index] | |
}; | |
this.override = function(a) { | |
this._override = a | |
}; | |
this.get = function(b) { | |
if (this._override) b(this._override); | |
else { | |
var c = (new Date).getTime(); | |
typeof this._aps !== "undefined" && this._expires > c ? b(this._next()) : this._resolve(function(f) { | |
if (f.length > 0) a._aps = f, a._expires = c + a._TTL, a._index = -1; | |
b(a._next()) | |
}) | |
} | |
} | |
}; | |
Spotify.Web.PostMessages.Handler = function(c, a, b, d, f, j, g) { | |
this.isAllowedOrigin = function(a) { | |
return c.allowed_origins.indexOf(a) > -1 | |
}; | |
this.handle = function(c) { | |
if (this.isAllowedOrigin(c.origin) && c.source && c.source.location) { | |
var f = Spotify.Web.Utils.appNameFromUrl(c.source.location.href); | |
if (c.data === "APP_ERROR_404") { | |
var h = d.getIFrameWithWindow(c.source); | |
h && (a.error("App not found: " + h.src), b.onReady(function() { | |
b.registerNotFound(f); | |
var c = b.getAppURL(f); | |
h.src !== c ? (a.info("Falling back to bundled version for app " + f), | |
h.src = c) : a.error("Got no other version of " + f + " to load...") | |
})) | |
} else { | |
var m; | |
try { | |
m = JSON.parse(c.data) | |
} catch (n) { | |
m = {} | |
} | |
m.type === "NOTIFICATION_CENTER_READY" && j && j.isVisible() ? j.getFrame().contentWindow.postMessage(JSON.stringify({ | |
type: "WINDOW_FOCUS" | |
}), "*") : m.type === "USER_ACTIVE" && g.userActivityRecorded() | |
} | |
} | |
} | |
}; | |
(function() { | |
var c = null; | |
Spotify.Web.AdAgent = function() { | |
if (c !== null) return c; | |
c = this; | |
var a, b, d, f = !1; | |
this.init = function(c, g, h) { | |
f || (b = c, d = g, a = h, j(), f = !0) | |
}; | |
var j = function() { | |
d && d.registerCallback(12, function() { | |
b.request("ads_user_inactive", [], function() {}); | |
b.request("ads_break_in_progress", [], function(a, b) { | |
g("ui_backgrounded", { | |
adBreakInProgress: !!b | |
}) | |
}) | |
}, function() { | |
b.request("ads_user_active", [], function() {}); | |
b.request("ads_break_in_progress", [], function(a, b) { | |
g("ui_foregrounded", { | |
adBreakInProgress: !!b | |
}) | |
}) | |
}) | |
}, | |
g = function(b, c) { | |
a && a.log({ | |
source: "spotify:main", | |
event: "user:hit", | |
event_version: b, | |
source_version: "", | |
source_vendor: "adagent", | |
data: c || {} | |
}) | |
} | |
} | |
})(); | |
Spotify.Web.AppLoader = function(c, a, b, d) { | |
var f = this, | |
j = new Spotify.Web.Environment(d); | |
this._thirdPartyApps = []; | |
this._apps = {}; | |
this._notFound = []; | |
this._ready = !1; | |
this._onReadyCallbacks = []; | |
this._timeout = 3E3; | |
this.appStoreEnabled = function() { | |
return d.document.cookie.indexOf("appstore-enabled") >= 0 || !c.apps.bundled_only | |
}; | |
this.getAppVersionsForCurrentUser = function(a, c) { | |
b.services.appstore.onReady(function() { | |
b.services.appstore.getAppVersionsForCurrentUser(f._market, f._active, f._bridgeVersion, a, c) | |
}) | |
}; | |
this.registerNotFound = | |
function(a) { | |
this._notFound.push(a); | |
Spotify.Web.Debugger.store("apps", "not_found", this._notFound); | |
this._apps[a] = c.apps.bundled[a] | |
}; | |
this.getPreferredLocale = function() { | |
if (!c.locale || !c.locale.preferred) return "en"; | |
var a = c.locale.preferred; | |
return a && a.length > 1 ? a.join(",") : a[0] || "en" | |
}; | |
this.getAppLoadingQueryString = function(a) { | |
var b = ["id=" + a, "cb=" + (c.apps.cache_buster || ""), "locale=" + this.getPreferredLocale()]; | |
c.locale && c.locale.rtl && b.push("rtl=1"); | |
var d = {}; | |
if (this._apps[a] && this._apps[a].dependencies) d = | |
this._apps[a].dependencies; | |
for (var h in d) d.hasOwnProperty(h) && b.push("spd-" + h + "=" + this.getDependencyVersion(a, h)); | |
c.developer && b.push("spogdomain=" + c.apps.domain); | |
return "?" + b.join("&") | |
}; | |
this.getAppDomainPrefix = function(a) { | |
return CryptoJS.MD5(a + this._username).toString().substring(0, 8) | |
}; | |
this.getAppVersion = function(a) { | |
return !this._apps[a] || !this._apps[a].version ? "" : this._apps[a].version | |
}; | |
this.getDependencyVersion = function(a, b) { | |
var c = this._apps[a] ? this._apps[a].dependencies : {}; | |
return (!c || !c[b]) && this._apps[b] ? | |
this._apps[b].version : c[b] | |
}; | |
this.getAppURL = function(a) { | |
if (!this._ready) throw 'Trying to get app URL for app "' + a + '" before AppLoader has been fully initialized'; | |
var b = ""; | |
if (j.isDesktop()) return "sp://" + a; | |
else if (this._apps[a] && this._apps[a].url) b = this._apps[a].url; | |
else var b = (b = this.getAppVersion(a)) ? "/" + b + "/" : "/", | |
d = c.apps.https ? "https" : "http", | |
h = this.getAppDomainPrefix(a), | |
b = c.developer ? "http://" + h + "-" + a + ".app.spotilocal.com:7768" + b : d + "://" + location.hostname + "/apps/" + a + b; | |
return b + this.getAppLoadingQueryString(a) | |
}; | |
this._onReady = function() { | |
if (!this._ready) | |
for (this._ready = !0; this._onReadyCallbacks.length !== 0;) this._onReadyCallbacks.shift()() | |
}; | |
this.onReady = function(a) { | |
this._ready && a(); | |
Spotify.Web.Debugger.store("apps", "active", this._apps); | |
this._onReadyCallbacks.push(a) | |
}; | |
this.init = function() { | |
if (!this._ready) | |
//TODO add Try/Catch. | |
if (this._apps = JSON.parse(JSON.stringify(c.apps.bundled)), this.appStoreEnabled()) { | |
this._active = []; | |
for (var d in c.apps.bundled) c.apps.bundled.hasOwnProperty(d) && this._active.push(d); | |
d = c.apps.bridge.split("."); | |
this._bridgeVersion = { | |
major: parseInt(d[0], 10), | |
minor: parseInt(d[1], 10), | |
patch: parseInt(d[2], 10) | |
}; | |
b.services.user.onReady(function() { | |
b.services.user.getUserInfo(function(b) { | |
f._username = b.user; | |
f._market = b.country; | |
f.getAppVersionsForCurrentUser(function(a) { | |
if (!f._ready) { | |
Spotify.Web.Debugger.store("apps", "appstore_response", a); | |
for (var b in a) a.hasOwnProperty(b) && a[b] && !(f._apps[b] && f._apps[b].version === "develop") && (f._apps[b] = a[b]); | |
f._onReady() | |
} | |
}, function(b) { | |
b = [b.code, b.description].join(", "); | |
a.error("[AppLoader] Unable to get users app list: " + | |
b); | |
f._onReady() | |
}); | |
setTimeout(function() { | |
f._ready || (a.error("[AppLoader] Timed out, using bundled apps"), f._onReady()) | |
}, f._timeout) | |
}, function() { | |
a.error("[AppLoader] Unable to get users username"); | |
f._onReady() | |
}) | |
}) | |
} else a.info("[AppLoader] Using only bundled apps"), f._onReady() | |
} | |
}; | |
Spotify.Web.Config = function(c, a) { | |
var b = this; | |
this.getFeatures = function() { | |
return c.features | |
}; | |
this.setFeature = function(a, b) { | |
c.features[a] = b | |
}; | |
this.getFeature = function(a) { | |
return typeof c.features[a] !== "undefined" ? c.features[a] : null | |
}; | |
this.getSettings = function() { | |
return c | |
}; | |
this.getSetting = function(a) { | |
return typeof c[a] !== "undefined" ? c[a] : null | |
}; | |
this.init = function() { | |
switch (a.getTestGroup("NTX_inline_playbutton")) { | |
case 0: | |
b.setFeature("listview-playbutton", !0); | |
break; | |
case 1: | |
b.setFeature("listview-playbutton-always-visible", !0) | |
} | |
} | |
}; | |
Spotify.Web.ABTests = function(c) { | |
var a = { | |
example_test: [250, 500, 750], | |
no_stacks: [100], | |
NTX_inline_playbutton: [800, 900], | |
NTX_login_xpromo: [0, 0], | |
NTX_sociomantic_track: [100] | |
}; | |
this.userValueForTest = function(a) { | |
return Spotify.Web.ABTester.getGroupId(c, a) | |
}; | |
this.getTestGroup = function(b) { | |
if (!a[b] || !a[b].length) throw Error("test " + b + " not found"); | |
for (var c = a[b], b = this.userValueForTest(b), f = 0; f < c.length;) { | |
if (b < c[f]) break; | |
f += 1 | |
} | |
return f | |
}; | |
this.isTestGroup = function(b) { | |
if (!a[b] || !a[b].length) return !1; | |
var c = a[b]; | |
if (c.length !== | |
1) throw Error("use getTestGroup for multivariant tests"); | |
return this.userValueForTest(b) < c[0] | |
} | |
}; | |
Spotify.Web.Dotter = function(c, a, b, d) { | |
if (d) d = document.createElement("span"), d.style.position = "absolute", c.appendChild(d), c = d; | |
var f = 0, | |
j, g = c.innerHTML; | |
this.start = function() { | |
j || (j = setInterval(function() { | |
f++; | |
f > a && (f = 0); | |
for (var b = g.trim(), d = 0; d < f; d++) b += "."; | |
c.innerHTML = b | |
}, b)) | |
}; | |
this.stop = function() { | |
j && (clearInterval(j), j = null, f = 0); | |
c.innerHTML = g | |
} | |
}; | |
Spotify.Web.Authenticator = function(c) { | |
var a = c.auth_proxy_host ? "/xhr/json/auth_proxy.php" : "/xhr/json/auth.php", | |
b = !1, | |
d = function(d, j, g) { | |
if (!b) { | |
b = !0; | |
var k = new XMLHttpRequest; | |
k.onreadystatechange = function() { | |
if (k.readyState === 4) { | |
setTimeout(function() { | |
b = !1 | |
}, 1E3); | |
var a = {}; | |
try { | |
a = JSON.parse(k.responseText) | |
} catch (c) {} | |
a.status === "OK" ? j(a.config) : g(a.error) | |
} | |
}; | |
var l = ""; | |
c.force_cat != -1 && (l = "&cat=" + c.force_cat); | |
var h = Spotify.Web.WebTracker.basic(c.tracking), | |
d = d == "" ? h + l : d + "&" + h + l; | |
k.open("POST", a, !0); | |
k.setRequestHeader("Content-type", | |
"application/x-www-form-urlencoded"); | |
k.send(d) | |
} | |
}; | |
this.creationFlow = ""; | |
this.authenticateWithFacebookCredentials = function(a, b, g, k) { | |
a = ["type=fb", "fbuid=" + encodeURIComponent(a), "token=" + encodeURIComponent(b), "secret=" + encodeURIComponent(c.csrftoken), "trackingId=" + encodeURIComponent(c.trackingId), "referrer=" + encodeURIComponent(c.tracking.referrer), "landingURL=" + encodeURIComponent(c.tracking.landingURL), "cf=" + encodeURIComponent(this.creationFlow)].join("&"); | |
d(a, g, k) | |
}; | |
this.authenticateWithUsernameAndPassword = | |
function(a, b, g, k) { | |
a = ["type=sp", "username=" + encodeURIComponent(a), "password=" + encodeURIComponent(b), "secret=" + encodeURIComponent(c.csrftoken), "trackingId=" + encodeURIComponent(c.trackingId), "referrer=" + encodeURIComponent(c.tracking.referrer), "landingURL=" + encodeURIComponent(c.tracking.landingURL), "cf=" + encodeURIComponent(this.creationFlow)].join("&"); | |
d(a, g, k) | |
}; | |
this.authenticateWithAnonymousUser = function(a, b) { | |
var g = ["type=anonymous", "secret=" + encodeURIComponent(c.csrftoken), "trackingId=" + encodeURIComponent(c.trackingId), | |
"referrer=" + encodeURIComponent(c.tracking.referrer), "landingURL=" + encodeURIComponent(c.tracking.landingURL), "cf=" + encodeURIComponent(this.creationFlow) | |
].join("&"); | |
d(g, a, b) | |
} | |
}; | |
Spotify.Web.Overlay = function(c) { | |
var a = c.ownerDocument.getElementById("overlay"); | |
this.hide = function() { | |
a.removeClass("visible") | |
}; | |
this.setFullscreen = function() { | |
a.addClass("fullscreen") | |
}; | |
this.show = function() { | |
for (; a.firstChild;) a.removeChild(a.firstChild); | |
a.appendChild(c); | |
a.addClass("visible") | |
} | |
}; | |
Spotify.Web.PlayNow = function(c, a, b, d, f) { | |
var j = "playlist_create,library_subscribe,library_star,library_unstar,library_tracks_append,library_albums_append,track_star,track_unstar,client_show_share_ui".split(","), | |
g = ["playNow", "limitedSubscribe"], | |
k = null, | |
l = a, | |
h = null, | |
m = null, | |
n = [], | |
e = [], | |
o = !1, | |
t = null, | |
C = !1, | |
v = null, | |
z = [], | |
w = null, | |
A = null, | |
x = null, | |
u = null, | |
y = function() { | |
u = setTimeout(function() { | |
o || (h.isPlaying && (v = !0), h.pause(), k && k.log({ | |
event: "pn_first_interaction_playback_paused" | |
}), t && t()) | |
}, 9E4) | |
}, | |
B = function() { | |
C || (C = !0, y()) | |
}, | |
D = function() { | |
return l === "anonymous" | |
}, | |
G = function() { | |
for (var a = D() ? n : e; a.length > 0;) a.shift().call(this) | |
}, | |
E = function(a) { | |
k && k.log({ | |
event: "pn_limited_feature", | |
data: { | |
feature: a | |
} | |
}); | |
z.forEach(function(b) { | |
b.call(this, a) | |
}) | |
}; | |
this.setAutoPlayTriggered = function(a) { | |
m = a | |
}; | |
this.authenticateUser = function(a, b) { | |
c.notify(Spotify.Web.PublisherMessages.USER_CONTEXT_FREEZE, { | |
user: a | |
}); | |
k ? k.log({ | |
event: "pn_authenticate_user", | |
data: { | |
user: a, | |
anonymousUser: b | |
} | |
}, function() { | |
x && x() | |
}) : x && x() | |
}; | |
this.setPlayer = function(a) { | |
h = a; | |
this.isAnonymous() && | |
!(Spotify.Web.Cookie.get("sp_fi") !== void 0 || Spotify.Web.Cookie.get("sp_cc") !== void 0) && h.bind("FIRST_BYTES", B, this) | |
}; | |
this.getBlocked = function() { | |
return j | |
}; | |
this.getLimitedFeatureFlags = function() { | |
return g | |
}; | |
this.onAnonymous = function(a) { | |
D() ? a() : n.push(a) | |
}; | |
this.onSignedIn = function(a) { | |
D() ? e.push(a) : a() | |
}; | |
this.onLimitedFeature = function(a) { | |
z.push(a) | |
}; | |
this.bindBeforeReload = function(a) { | |
x = a | |
}; | |
this.bindFirstInteractionNeeded = function(a) { | |
t = a | |
}; | |
this.bindSignUpHandler = function(a) { | |
w = a | |
}; | |
this.bindLoginHandler = function(a) { | |
A = | |
a | |
}; | |
this.limitedFeatureCalled = function(a) { | |
E(a) | |
}; | |
this.checkSignedIn = function(a) { | |
D() ? E("unknown") : a() | |
}; | |
this.signUp = function(a) { | |
k && k.log({ | |
event: "pn_show_signup" | |
}); | |
w && w(a) | |
}; | |
this.login = function(a) { | |
k && k.log({ | |
event: "pn_show_login" | |
}); | |
A && A(a) | |
}; | |
this.isAnonymous = function() { | |
return D() | |
}; | |
this.isYahooUser = function() { | |
return d === "yahoo" | |
}; | |
this.change = function(a) { | |
l = a; | |
G() | |
}; | |
this.setLogger = function(a) { | |
k = a | |
}; | |
this.getLogger = function() { | |
return k | |
}; | |
this.onNotify = function(a) { | |
a.messageType === Spotify.Web.PublisherMessages.USER_INTERACTION ? | |
m ? m = !1 : o || (k && k.log({ | |
event: "pn_first_interaction" | |
}), o = !0, clearTimeout(u), Spotify.Web.Cookie.set("sp_fi", 1, { | |
ttl: 180, | |
domain: b | |
}), v && (k && k.log({ | |
event: "pn_first_interaction_playback_resume" | |
}), h.resume())) : a.messageType === Spotify.Web.PublisherMessages.USER_INTERACTION_PAUSE_PLAYBACK && clearTimeout(u) | |
}; | |
this.isFacebookFlow = function() { | |
return f.indexOf("utm_campaign=fb") > -1 | |
}; | |
this.isOpenRedirect = function() { | |
return this.isAnonymous() && Spotify.Web.Cookie.get("sp_og") === "d64111d9de6b4b4db229f6c6aaec0d33" | |
}; | |
c.subscribe(Spotify.Web.PublisherMessages.USER_INTERACTION, | |
this); | |
c.subscribe(Spotify.Web.PublisherMessages.USER_INTERACTION_PAUSE_PLAYBACK, this); | |
this.isYahooUser() && (m = !0) | |
}; | |
Spotify.Web.PlayNowSignUp = function(c, a, b, d) { | |
Spotify.Web.Overlay.call(this, a); | |
var f = this, | |
j = null, | |
g = function() { | |
d.notify(Spotify.Web.PublisherMessages.USER_INTERACTION); | |
f.hide() | |
}, | |
k = function() { | |
var h = a.querySelector("#login-screen"); | |
h && a.removeChild(h); | |
h = a.ownerDocument.createElement("div"); | |
h.setAttribute("id", "login-screen"); | |
a.appendChild(h); | |
Spotify.Web.WebTracker.log({ | |
type: "INITIALIZE_LOGIN_SCREEN", | |
t: (new Date).getTime() | |
}); | |
j = new Spotify.Web.Screens.Login(h, b, function() {}, c, g); | |
j.init(); | |
c.isOpenRedirect() || | |
a.querySelector("#bg-wrap").addEventListener("click", function(a) { | |
a.target.id === "bg-wrap" && (d.notify(Spotify.Web.PublisherMessages.USER_INTERACTION), f.hide()) | |
}) | |
}, | |
l = function(a, b) { | |
k(); | |
a == "login-form" ? j.showLogin() : a == "continue-listening" ? j.showContinueListening() : b && j.showRestrictedFeature(b); | |
c.isOpenRedirect() && f.setFullscreen(!0); | |
f.show() | |
}; | |
this.initialize = function() { | |
c.bindSignUpHandler(function(a) { | |
l(a) | |
}); | |
c.bindLoginHandler(function() { | |
l("login-form") | |
}); | |
c.onLimitedFeature(function(a) { | |
l(!1, a) | |
}); | |
c.bindFirstInteractionNeeded(function() { | |
l(!1, | |
"first_interaction_needed") | |
}) | |
} | |
}; | |
Spotify.Web.PlayNowBanner = function(c, a, b, d, f, j) { | |
f.subscribe(Spotify.Web.PublisherMessages.COOKIES_ACCEPTED, this); | |
var g, k = !1, | |
l = !1, | |
h = !d.hasAccepted(), | |
m = function() { | |
a.removeClass("hidden"); | |
b.addClass("playnow") | |
}, | |
n = function() { | |
b.removeClass("playnow"); | |
a.addClass("auth"); | |
Spotify.Web.Utils.addTransitionEndedListener(a, function() { | |
a.addClass("hidden") | |
}, 500) | |
}, | |
e = function() { | |
k ? (a.querySelector("#playnow-cc").className = "", a.querySelector("#playnow-welcome").className = "show", k = l = !1) : l && !g && (g = setTimeout(function() { | |
k = !0 | |
}, 12E4)) | |
}, | |
o = function() { | |
var b = a.ownerDocument, | |
e = b.createElement("div"); | |
a.addClass("hidden"); | |
e.className = c.isYahooUser() ? "yahoo-banner" : ""; | |
var d, g = b.createElement("div"); | |
g.id = "playnow-welcome"; | |
var f = b.createElement("h1"), | |
k = b.createElement("p"); | |
f.textContent = _("Keep the music going!"); | |
g.appendChild(f); | |
k.textContent = _("playnow/signup_description"); | |
g.appendChild(k); | |
if (h) d = b.createElement("div"), d.id = "playnow-cc", f = b.createElement("h1"), f.textContent = _("Welcome to Spotify!"), k = b.createElement("p"), k.innerHTML = | |
_("By interacting with this web player (e.g. by controlling music playback, searching for music, etc.) you agree to our {{TERMS_START}}Terms and Conditions{{TERMS_END}} and our {{PP_START}}Privacy Policy{{PP_END}}, and you also consent to the use of cookies as described in {{COOKIES_START}}Information About Cookies & Similar Technologies{{COOKIES_END}}.", { | |
TERMS_START: '<a class="cookies-noaccept" href="https://www.spotify.com/legal/end-user-agreement/" target="_blank">', | |
TERMS_END: "</a>", | |
PP_START: '<a class="cookies-noaccept" href="https://www.spotify.com/legal/privacy-policy/" target="_blank">', | |
PP_END: "</a>", | |
COOKIES_START: '<a href="http://www.spotify.com/legal/privacy-policy/#cookies" class="cookies-noaccept" target="_blank">', | |
COOKIES_END: "</a>" | |
}), d.appendChild(f), d.appendChild(k), l = !0; | |
e.appendChild(g); | |
h && e.appendChild(d); | |
(h ? d : g).className += "show"; | |
d = b.createElement("button"); | |
d.innerHTML = _("Sign Up"); | |
g = document.createElement("span"); | |
d.appendChild(g); | |
d.className = c.isFacebookFlow() ? j ? "btn btn-primary signup fb" : "button signup fb" : j ? "btn btn-primary signup" : "button signup primary"; | |
e.appendChild(d); | |
d.addEventListener("click", function() { | |
c.signUp() | |
}); | |
b = b.createElement("button"); | |
b.textContent = _("Log In"); | |
b.className = j ? "btn btn-default login" : "button login"; | |
e.appendChild(b); | |
c.isFacebookFlow() && (b.className += " fb"); | |
b.addEventListener("click", function() { | |
c.login() | |
}); | |
a.appendChild(e) | |
}; | |
this.enableFacepile = function() { | |
var b = a.ownerDocument, | |
c = a.querySelectorAll("div")[0]; | |
if (a.querySelector("iframe") === null) { | |
var e = b.createElement("iframe"); | |
e.setAttribute("src", "//www.facebook.com/plugins/facepile.php?href=http%3A%2F%2Ffacebook.com%2FSpotify&app_id=134519659678&action&size=medium&show_count=true&colorscheme=light&appId=134519659678&width=200&max_rows=1"); | |
e.setAttribute("id", "facepile"); | |
e.setAttribute("scrolling", "no"); | |
e.setAttribute("frameborder", "0"); | |
e.setAttribute("allowTransparency", "true"); | |
c.appendChild(e); | |
b.querySelector("body").className += " facepile" | |
} | |
}; | |
this.initialize = function() { | |
o(); | |
c.isOpenRedirect() || (c.onAnonymous(m), c.onSignedIn(n)) | |
}; | |
this.onNotify = function(a) { | |
h && a.messageType === "COOKIES_ACCEPTED" && e() | |
} | |
}; | |
Spotify.Web.Bridge = function(c) { | |
var a = this; | |
this.hermes = { | |
load_schema: function(b, c) { | |
a.request("hermes_load_schema_data", [b], function(a, b) { | |
a ? c(null) : c(b.id) | |
}) | |
}, | |
request: function(b, c, f, j, g, k, l) { | |
a.hermes.load_schema(k, function(h) { | |
for (var k = [], n = 0, e = j.length; n < e; n += 1) k.push(h + "#" + j[n]); | |
for (var n = [], o = 0, e = g.length; o < e; o += 1) n.push(h + "#" + g[o]); | |
a.request("hermes_send_request", [b, c, n, k, f], l) | |
}) | |
} | |
}; | |
this.player = { | |
getState: function(b) { | |
a.request("player_query", ["main"], b) | |
}, | |
registerForPlayerEvents: function(b) { | |
a.request("player_event_wait_any", ["main"], b) | |
}, | |
registerForPlayerStateChange: function(b) { | |
a.request("player_event_wait", ["main"], b) | |
}, | |
pause: function(b) { | |
a.request("player_pause", ["main"], b) | |
}, | |
resume: function(b) { | |
a.request("player_play", ["main"], b) | |
}, | |
play_context: function(b, c, f, j) { | |
a.request("player_play_context", ["main", { | |
type: "list", | |
uri: b | |
}, c, f], j) | |
}, | |
play_context_as_app: function(b, c, f, j, g, k) { | |
a.requestAsApp(b, "player_play_context", ["main", { | |
type: "list", | |
uri: c | |
}, f, j, -1, g], k) | |
}, | |
play_track: function(b, c, f) { | |
a.request("player_play_track", ["main", b, c], | |
f) | |
}, | |
play_track_as_app: function(b, c, f, j, g) { | |
a.requestAsApp(b, "player_play_track", ["main", c, f, -1, j], g) | |
} | |
}; | |
this.user = { | |
setAttribute: function() {}, | |
getAttribute: function() {} | |
}; | |
this.logging = { | |
logClientEvent: function(b, c) { | |
a.request("application_client_event", Array.isArray(b) ? b : [b], c) | |
} | |
}; | |
this.request = function(a, d, f) { | |
c.request(a, d, this, function(a) { | |
f(null, a) | |
}, function(a) { | |
f(!0, a) | |
}) | |
}; | |
this.requestAsApp = function(a, d, f, j) { | |
c.requestAsApp(a, d, f, this, function(a) { | |
j(null, a) | |
}, function(a) { | |
j(!0, a) | |
}) | |
} | |
}; | |
Spotify.Web.Confirm = function(c, a) { | |
var b = this, | |
d = function(c) { | |
var d = !1; | |
!b.hasBeenShown() && a.isPlaying && (d = _("You need to have this page open to play music, are you sure you want to leave?"), b.markAsShown()); | |
if (d !== !1) return (c || window.event).returnValue = d | |
}; | |
b.enable = function() { | |
window.addEventListener("beforeunload", d) | |
}; | |
b.disable = function() { | |
window.removeEventListener("beforeunload", d) | |
}; | |
b.init = function() { | |
b.enable(); | |
setTimeout(b.disable, 18E5) | |
}; | |
b.markAsShown = function() { | |
c.set("confirm_shown", !0) | |
}; | |
b.hasBeenShown = | |
function() { | |
return c.get("confirm_shown") === !0 | |
} | |
}; | |
Spotify.Web.Cookie = { | |
get: function(c, a) { | |
for (var b = this.getAll(a), d = encodeURIComponent(c) + "=", f = 0; f < b.length; f++) { | |
var j = b[f].replace(/^\s+|\s+$/g, ""); | |
if (j.indexOf(d) === 0) return decodeURIComponent(j.substring(d.length, j.length)) | |
} | |
}, | |
getAll: function(c) { | |
c = c || window.document; | |
return (c.cookie ? c.cookie : "").split(";") | |
}, | |
set: function(c, a, b, d) { | |
var b = b || {}, | |
d = d || window.document, | |
f = b.ttl || 0, | |
j = b.path || "/", | |
g = b.domain || "", | |
b = b.secure || !1, | |
c = encodeURIComponent(c) + "=" + encodeURIComponent(a) + ";"; | |
f != 0 && (a = new Date, a.setDate(a.getDate() + | |
f), c += " expires=" + a.toUTCString() + ";"); | |
c += " path=" + j + ";"; | |
c += g != "" ? " domain=" + g + ";" : ""; | |
c += b ? " secure;" : ""; | |
d.cookie = c | |
}, | |
remove: function(c, a, b, d) { | |
this.set(c, "", { | |
domain: b, | |
ttl: -1, | |
secure: d | |
}, a) | |
}, | |
domain: function() { | |
return window.location.hostname ? window.location.hostname.match(/\.spotify\.(net|com)$/)[0] || ".spotify.com" : ".spotify.com" | |
}() | |
}; | |
Spotify.Web.CookieCompliance = function(c, a) { | |
var b = this; | |
a && a.subscribe(Spotify.Web.PublisherMessages.USER_INTERACTION, this); | |
var d = document.getElementById("cookie-compliance"), | |
f = window.location.hostname.match(/\.spotify\.(net|com)$/)[0] || ".spotify.com", | |
j = null, | |
g = { | |
BE: "BE", | |
ES: "ES", | |
FR: "FR", | |
GB: "GB", | |
IE: "IE", | |
IT: "IT", | |
NL: "NL", | |
PL: "PL", | |
PT: "PT", | |
GR: "GR", | |
HU: "HU", | |
CZ: "CZ", | |
MT: "MT", | |
BG: "BG", | |
SK: "SK", | |
CY: "CY" | |
}; | |
this.hasAccepted = function() { | |
return Spotify.Web.Cookie.get("sp_cc") !== void 0 | |
}; | |
this.show = function() { | |
if (!this.hasAccepted()) d.className = | |
"show" | |
}; | |
this.hide = function() { | |
d.className = "" | |
}; | |
this.mustAccept = function() { | |
return g[c] !== void 0 && Spotify.Web.Cookie.get("sp_cc") === void 0 | |
}; | |
this.setAutoPlayTriggered = function() { | |
j = !0 | |
}; | |
this.onNotify = function(a) { | |
a.messageType === "USER_INTERACTION" && (j ? j = !1 : b.accept()) | |
}; | |
this.accept = function(b) { | |
Spotify.Web.Cookie.set("sp_cc", 1, { | |
ttl: 180, | |
domain: f | |
}); | |
a && a.notify(Spotify.Web.PublisherMessages.COOKIES_ACCEPTED, {}); | |
typeof b === "function" && b.call() | |
} | |
}; | |
Spotify.Web.Screens.Intermediate = function(c, a, b) { | |
var d = new Spotify.Web.Authenticator(a), | |
f = function(a) { | |
c.className = "hidden"; | |
setTimeout(function() { | |
c.style.display = "none" | |
}, 1E3); | |
b(a) | |
}, | |
j = function() { | |
document.getElementById("timeout").style.display = "block"; | |
Spotify.Web.WebTracker.log({ | |
type: "FB_CONNECTION_FAILED", | |
error: "account_creation_failed" | |
}) | |
}, | |
g = function() { | |
Spotify.Web.FacebookSDK.onInitialized(function() { | |
FB.getLoginStatus(function(a) { | |
a.status === "connected" ? d.authenticateWithFacebookCredentials(a.authResponse.userID, | |
a.authResponse.accessToken, f, j) : a.status === "not_authorized" ? d.authenticateWithAnonymousUser(function(a) { | |
a.sessionType = "anonymous"; | |
f(a) | |
}, j) : (Spotify.Web.WebTracker.log({ | |
type: "FB_CONNECTION_FAILED", | |
error: "not_connected" | |
}, !1), document.location.href = "/login/") | |
}) | |
}) | |
}; | |
this.init = function() { | |
if (a.loginFlow === "spb") d.creationFlow = "spb_to_webplayer"; | |
else if (a.loginFlow === "new_spb") d.creationFlow = "new_spb_to_webplayer"; | |
else if (a.loginFlow === "fb") d.creationFlow = "facebook_play_to_webplayer"; | |
c.innerHTML = ['<div id="intermediate">\n <div class="mssg">', | |
" <h1>" + _("Loading Spotify") + "</h1>", " <p>" + _("Lots of music coming your way. Any second now...") + "</p>", " <form></form>", ' <img src="' + a.cdn + '/images/loading_throbber.gif" alt="" id="throbber">', ' <p id="timeout">', " " + _("Seems to be taking a while. {{LINK_START}}Please click here{{LINK_END}}.", { | |
LINK_START: '<a href="/login/">', | |
LINK_END: "</a>" | |
}), " </p>\n </div>\n</div>" | |
].join("\n"); | |
Spotify.Web.WebTracker.log({ | |
type: "INTERMEDIATE_JS_READY" | |
}); | |
g() | |
} | |
}; | |
Spotify.Web.Forms.Builder = function(c, a) { | |
this._container = document.createElement("div"); | |
this._container.className = "sign-up-form"; | |
this._fields = c.fields; | |
this._form = document.createElement("form"); | |
var b = this, | |
d = function(a, b) { | |
var c = document.createElement("p"), | |
e = document.createElement("label"), | |
d = document.createElement("input"); | |
c.id = "wrap-" + b; | |
d.id = b; | |
d.name = b; | |
d.type = a.type; | |
e.innerHTML = a.label; | |
e.setAttribute("for", b); | |
a.maxLength && d.setAttribute("maxlength", a.maxLength); | |
a.placeHolder && d.setAttribute("placeholder", | |
a.placeHolder); | |
d.addEventListener("blur", function() { | |
m(a); | |
n(!0) | |
}, !1); | |
d.addEventListener("focus", function() { | |
t(a.node) | |
}, !1); | |
c.appendChild(e); | |
c.appendChild(g()); | |
c.appendChild(d); | |
return a.node = c | |
}, | |
f = function(a, b) { | |
var c = document.createElement("p"), | |
e = document.createElement("label"); | |
c.id = "wrap-" + b; | |
e.innerHTML = a.label; | |
c.appendChild(e); | |
c.appendChild(g()); | |
for (var d in a.choices) { | |
var e = a.choices[d], | |
h = document.createElement("label"); | |
h.innerHTML = e.label; | |
h.className = "radio"; | |
var f = document.createElement("input"); | |
f.type = "radio"; | |
f.name = b; | |
f.value = d; | |
if (e.selected) f.checked = !0; | |
h.appendChild(f); | |
c.appendChild(h) | |
} | |
c.addEventListener("click", function() { | |
t(a.node) | |
}, !1); | |
f.onchange = function() { | |
n(!0) | |
}; | |
return a.node = c | |
}, | |
j = function(a, b) { | |
var c = document.createElement("p"), | |
e = document.createElement("label"), | |
d = document.createElement("input"), | |
h = document.createElement("span"); | |
c.id = "wrap-" + b; | |
d.name = b; | |
d.type = "checkbox"; | |
e.className = "checkbox"; | |
if (a.checked) d.checked = !0; | |
h.innerHTML = a.label; | |
e.appendChild(d); | |
e.appendChild(h); | |
c.appendChild(e); | |
c.appendChild(g()); | |
c.addEventListener("click", function() { | |
t(a.node) | |
}, !1); | |
c.addEventListener("mouseup", function() { | |
n(!0) | |
}, !1); | |
return a.node = c | |
}, | |
g = function() { | |
var a = document.createElement("div"); | |
a.className = "error"; | |
return a | |
}, | |
k = function(a, b) { | |
var c = document.createElement("input"); | |
c.name = b; | |
c.value = a.value; | |
c.type = "hidden"; | |
return a.node = c | |
}, | |
l = function(a, b) { | |
var c = document.createElement("select"); | |
c.id = b; | |
for (var e = a.getOptions(), d = 0; d < e.length; d++) { | |
var h = document.createElement("option"); | |
h.value = e[d][0]; | |
h.innerHTML = | |
e[d][1]; | |
c.appendChild(h) | |
} | |
c.addEventListener("focus", function() { | |
c.parentNode.clearErrors() | |
}); | |
return a.node = c | |
}, | |
h = function(a, b) { | |
var c = document.createElement("p"), | |
e = document.createElement("label"); | |
c.id = "wrap-" + b; | |
e.innerHTML = a.label; | |
c.appendChild(e); | |
c.appendChild(g()); | |
a.node = c; | |
c.clearErrors = function() { | |
t(this) | |
}; | |
return c | |
}, | |
m = function(a, b) { | |
var c = a.node.querySelector("input"), | |
e = !0, | |
d = "", | |
h = typeof b === "undefined" || !b, | |
d = _("This field is required"); | |
if (a.required) { | |
if (a.type === "checkbox" && !c.checked) return h && o(a.node, | |
a.requiredText || d), !1; | |
if (a.type === "radio" && !a.node.querySelector("input:checked")) return h && o(a.node, a.requiredText || d), !1; | |
if (c.value.length === 0 && h) return h && o(a.node, a.requiredText || d), !1 | |
} | |
for (var f in a.validate) { | |
var d = a.validate[f], | |
g; | |
switch (f) { | |
case "regEx": | |
e = d.rule.test(c.value); | |
break; | |
case "regExExclude": | |
e = !d.rule.test(c.value); | |
break; | |
case "matchField": | |
e = document.getElementById(d.rule); | |
e = c.value === e.value; | |
break; | |
case "minNum": | |
e = c.value >= d.rule; | |
break; | |
case "maxNum": | |
e = c.value <= d.rule; | |
break; | |
case "minLength": | |
e = | |
c.value.length >= d.rule; | |
break; | |
case "maxLength": | |
e = c.value.length <= d.rule; | |
break; | |
case "custom": | |
e = (g = d()) ? !1 : !0 | |
} | |
if (!e) return d = g ? g : d.message, h && o(a.node, d), !1 | |
} | |
return !0 | |
}, | |
n = function(a) { | |
var c = !0, | |
e = 0, | |
d = b._fields.length, | |
h; | |
for (h = 0; h < d; h++) | |
if (c = b._fields[h], c.node && (c.required || c.validate))(c = m(c, a)) || e++; | |
return e === 0 | |
}, | |
e = function() { | |
b._form.addEventListener("submit", function(c) { | |
c.preventDefault(); | |
if (n() && typeof a === "function") { | |
for (var c = {}, e = b._fields, d = 0; d < e.length; d++) { | |
var h = e[d], | |
f = e[d].name; | |
switch (h.type) { | |
case "hidden": | |
c[f] = | |
h.node.value; | |
break; | |
case "text": | |
case "password": | |
c[f] = h.node.querySelector("input").value; | |
break; | |
case "radio": | |
if (h.node.querySelector("input:checked")) c[f] = h.node.querySelector("input:checked").value; | |
break; | |
case "checkbox": | |
h.node.querySelector("input").checked && (c[f] = "yeaaahhh"); | |
break; | |
case "select": | |
c[f] = h.node.value | |
} | |
} | |
a(c) | |
} | |
}, !1) | |
}, | |
o = function(a, b) { | |
a.querySelector(".error").textContent = b; | |
a.className = "has-error" | |
}, | |
t = function(a) { | |
a.querySelector(".error").textContent = ""; | |
a.className = "" | |
}; | |
this.handleExternalErrors = | |
function(a) { | |
var c = b._fields, | |
e = c.length, | |
d, h, f; | |
for (f in a) | |
for (h = 0; h < e; h++) | |
if (c[h].name === f) d = c[h].node, t(d), o(d, a[f]) | |
}; | |
this.init = function() { | |
var a = document.createDocumentFragment(), | |
g = document.createElement("p"), | |
m = b._fields, | |
o = m.length, | |
n; | |
g.className = "submit-wrap"; | |
b.submitButton = document.createElement("button"); | |
b.submitButton.className = ""; | |
b._form.method = c.method; | |
b._form.action = c.endPoint; | |
var t = document.createElement("span"); | |
for (n = 0; n < o; n++) { | |
var u = m[n], | |
y = u.name, | |
B = a; | |
u.group && (B = a.querySelector("#wrap-" + u.group)); | |
switch (u.type) { | |
case "group": | |
B.appendChild(h(u, y)); | |
break; | |
case "text": | |
case "password": | |
B.appendChild(d(u, y)); | |
break; | |
case "radio": | |
B.appendChild(f(u, y)); | |
break; | |
case "checkbox": | |
B.appendChild(j(u, y)); | |
break; | |
case "hidden": | |
B.appendChild(k(u, y)); | |
break; | |
case "select": | |
B.appendChild(l(u, y)) | |
} | |
} | |
b.submitButton.type = "submit"; | |
b.submitButton.textContent = c.submitText || "Submit"; | |
g.appendChild(b.submitButton); | |
b.submitButton.appendChild(t); | |
a.appendChild(g); | |
b._form.appendChild(a); | |
e(); | |
this._container.appendChild(this._form); | |
this.node = | |
this._container | |
}; | |
this.init() | |
}; | |
Spotify.Web.Forms.Signup = function(c, a, b, d, f) { | |
var j = b.doubleCheckLicenseCountries, | |
g = function() { | |
var a = j.length, | |
c; | |
for (c = 0; c < a; c++) | |
if (j[c] === b.country) return !0; | |
return !1 | |
}(), | |
k = new Spotify.Web.Authenticator(b), | |
l = 0, | |
h = "", | |
m = "", | |
n = b.username, | |
e = /^.+@.+\..+/, | |
o = this, | |
t = { | |
TERMS_START: '<a href="https://www.spotify.com/legal/end-user-agreement/" target="_blank">', | |
TERMS_END: "</a>", | |
PP_START: '<a href="https://www.spotify.com/legal/privacy-policy/" target="_blank">', | |
PP_END: "</a>" | |
}, | |
C = a === !0, | |
v = !b.email_opt_out, | |
z = !v, | |
e = { | |
endPoint: "/xhr/json/signup.php", | |
method: "post", | |
submitText: _("Sign up"), | |
fields: [{ | |
name: "secret", | |
type: "hidden", | |
value: b.csrftoken | |
}, { | |
name: "username", | |
type: "text", | |
label: _("Username:"), | |
placeHolder: _("e.g. John Doe"), | |
required: !0, | |
requiredText: _("Please enter a username"), | |
validate: { | |
regExExclude: { | |
rule: /[&@\/\'":`\u00b4 ]/, | |
message: _("Please make sure there are no invalid characters in your username") | |
}, | |
minLength: { | |
rule: 4, | |
message: _("Your username should be at least 4 characters") | |
}, | |
maxLength: { | |
rule: 100, | |
message: _("Your username should be at most 100 characters") | |
} | |
} | |
}, { | |
name: "email", | |
type: "text", | |
label: _("Email:"), | |
placeHolder: _("e.g. john@email.com"), | |
required: !0, | |
requiredText: _("Please enter an email address"), | |
validate: { | |
regEx: { | |
rule: e, | |
message: _("The email address you supplied is invalid") | |
} | |
} | |
}, { | |
name: "email-confirm", | |
type: "text", | |
label: _("Confirm email") + ":", | |
placeHolder: _("Confirm email"), | |
required: !0, | |
requiredText: _("Please confirm your email address here"), | |
validate: { | |
matchField: { | |
rule: "email", | |
message: _("Email confirmation doesn't match") | |
}, | |
regEx: { | |
rule: e, | |
message: _("The email address you supplied is invalid") | |
} | |
} | |
}, { | |
name: "password", | |
type: "password", | |
label: _("Password:"), | |
placeHolder: _("Choose a password"), | |
required: !0, | |
requiredText: _("Please enter a password"), | |
validate: { | |
minLength: { | |
rule: 4, | |
message: _("Your password should be at least 4 characters") | |
} | |
} | |
}, { | |
name: "age", | |
type: "group", | |
label: _("Date of birth"), | |
validate: { | |
custom: function() { | |
for (var a = [document.getElementById("age-year").value, document.getElementById("age-month").value, document.getElementById("age-day").value], b = 0; b < a.length; b++) | |
if (a[b] === "-") return _("Please enter your date of birth"); | |
return null | |
} | |
} | |
}, { | |
name: "age-year", | |
type: "select", | |
group: "age", | |
getOptions: function() { | |
for (var a = [ | |
["-", _("Year")] | |
], b = 2013; b >= 1900; b--) a.push([b, b]); | |
return a | |
} | |
}, { | |
name: "age-month", | |
type: "select", | |
group: "age", | |
getOptions: function() { | |
for (var a = [ | |
["-", _("Month")] | |
], b = 1; b <= 12; b++) a.push([b, b]); | |
return a | |
} | |
}, { | |
name: "age-day", | |
type: "select", | |
group: "age", | |
getOptions: function() { | |
for (var a = [ | |
["-", _("Day")] | |
], b = 1; b <= 31; b++) a.push([b, b]); | |
return a | |
} | |
}, { | |
name: "gender", | |
type: "radio", | |
label: _("Gender:"), | |
required: !0, | |
requiredText: _("Please select your gender"), | |
choices: { | |
male: { | |
selected: !1, | |
label: _("Male") | |
}, | |
female: { | |
selected: !1, | |
label: _("Female") | |
} | |
} | |
}, { | |
name: "marketing-emails", | |
type: "checkbox", | |
label: _("Please send me Spotify news by e-mail"), | |
checked: v | |
}] | |
}, | |
g = g ? [{ | |
name: "terms", | |
type: "checkbox", | |
label: _("I agree to the {{TERMS_START}}Spotify Terms and Conditions of Use{{TERMS_END}}", t), | |
required: !0, | |
requiredText: _("You must agree to our Terms and Conditions of Service to use the Spotify Service."), | |
checked: C | |
}, { | |
name: "terms", | |
type: "checkbox", | |
label: _("I agree to the {{PP_START}}Spotify Privacy Policy{{PP_END}}", | |
t), | |
required: !0, | |
requiredText: _("You must agree to our Privacy Policy to use the Spotify Service."), | |
checked: C | |
}] : [{ | |
name: "terms", | |
type: "checkbox", | |
label: _("I agree to the {{TERMS_START}}Spotify Terms and Conditions of Use{{TERMS_END}} and {{PP_START}}Privacy Policy{{PP_END}}", t), | |
required: !0, | |
requiredText: _("You must agree to our Terms and Conditions of Service and Privacy Policy to use the Spotify Service."), | |
checked: C | |
}]; | |
e.fields.splice.apply(e.fields, [-1, 0].concat(g)); | |
var w = function(a) { | |
o._globalErrorNode.textContent = | |
a; | |
o._globalErrorNode.className = "show" | |
}, | |
A = function() { | |
o._form.style.visibility = "visible"; | |
o._loadingScreen.className = "" | |
}, | |
x = function() { | |
k.authenticateWithUsernameAndPassword(h, m, function(a) { | |
u(a) | |
}, function() { | |
l++; | |
l < 5 ? setTimeout(function() { | |
x() | |
}, 2E3) : (A(), w(_("Sorry, there was a problem during the signup process - please try again"))) | |
}) | |
}, | |
u = function(a) { | |
f === void 0 || f.isAnonymous() === !1 ? (c.className = "hidden", setTimeout(function() { | |
c.style.display = "none" | |
}, 1E3), window.dataLayer && Spotify.Web.Cookie.get("justRegistered") && | |
(window.dataLayer.push({ | |
event: "registration_flow_complete" | |
}), Spotify.Web.Cookie.remove("justRegistered")), d(a, window.FB || void 0)) : f.authenticateUser(a.username, n) | |
}, | |
y = !1; | |
this.builder = new Spotify.Web.Forms.Builder(e, function(a) { | |
Spotify.Web.WebTracker.log({ | |
type: "SPOTIFY_SIGNUP_CLICKED" | |
}); | |
o._globalErrorNode.className = ""; | |
o._form.style.visibility = "hidden"; | |
o._loadingScreen.className = "show"; | |
if (!y) { | |
y = !0; | |
var c = [], | |
e; | |
for (e in a) | |
if (e) { | |
var d = a[e]; | |
e === "username" && (h = d = d.toLowerCase()); | |
e === "password" && (m = d); | |
c.push(encodeURIComponent(e) + | |
"=" + encodeURIComponent(d)) | |
} | |
c.push("referrer=" + encodeURIComponent(b.tracking.referrer)); | |
c.push("landingURL=" + encodeURIComponent(b.tracking.landingURL)); | |
var f = new XMLHttpRequest; | |
f.onreadystatechange = function() { | |
if (f.readyState === 4) | |
if (y = !1, f.status === 200) { | |
//TODO Add Try Catch | |
var a = JSON.parse(f.responseText); | |
a.success ? (x(), typeof window.dataLayer != "undefined" && (dataLayer.push({ | |
event: "registration_success" | |
}), Spotify.Web.Cookie.get("justRegistered") || Spotify.Web.Cookie.set("justRegistered", 1, { | |
domain: Spotify.Web.Cookie.domain | |
}))) : | |
(A(), a.errors.global && w(a.errors.global), o.builder.handleExternalErrors(a.errors)) | |
} else alert("Oups! Something went wrong. Please try again later.") | |
}; | |
a = c.join("&"); | |
f.open("POST", "/xhr/json/signup.php", !0); | |
f.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); | |
f.send(a) | |
} | |
}); | |
this.node = this.builder.node; | |
C && (this.node.className += " terms-imp"); | |
z || (this.node.className += " marketing-emails-imp"); | |
this._globalErrorNode = document.createElement("div"); | |
this._globalErrorNode.id = "signup-global-error"; | |
this._loadingScreen = document.createElement("div"); | |
this._loadingScreen.id = "signup-loading"; | |
this._loadingScreen.textContent = _("Loading Spotify") + "..."; | |
this._form = this.node.querySelector("form"); | |
this.node.appendChild(this._globalErrorNode); | |
this.node.appendChild(this._loadingScreen); | |
if (a) this.node.querySelector("#wrap-terms input").setAttribute("disabled", "disabled"), a = document.createElement("div"), C = this.node.querySelector(".submit-wrap"), a.className = "terms", a.innerHTML = _("By clicking on Sign up, you agree to the {{TERMS_START}}Spotify Terms and Conditions of Use{{TERMS_END}} and {{PP_START}}Privacy Policy{{PP_END}}", | |
t), C.insertBefore(a, C.firstChild) | |
}; | |
Spotify.Web.Login = function(c, a, b, d) { | |
var f = a.cat_enabled; | |
this.init = function() { | |
Spotify.Web.FacebookSDK.init(a.fbjssdk); | |
Spotify.Web.WebTracker.setConfig(a.tracking); | |
if (a.locale && a.locale.current) document.getElementsByTagName("html")[0].className = "lang-" + a.locale.current; | |
if (a.credentials && a.credentials[0]) j(a); | |
else { | |
var b; | |
b = c.createElement("div"); | |
b.id = "login-screen"; | |
b.className = "main-login-class"; | |
c.body.appendChild(b); | |
a.loginFlow === "fb" || a.loginFlow === "spb" ? (Spotify.Web.WebTracker.log({ | |
type: "FACEBOOK_AUTO_LOGIN" | |
}), | |
b = new Spotify.Web.Screens.Intermediate(b, a, j)) : (Spotify.Web.WebTracker.log({ | |
type: "INITIALIZE_LOGIN_SCREEN", | |
t: (new Date).getTime() | |
}), b = new Spotify.Web.Screens.Login(b, a, j)); | |
b.init() | |
} | |
}; | |
var j = function(a) { | |
a.version !== b ? c.location.reload(!0) : f !== a.cat_enabled ? c.location.reload(!0) : d(a) | |
} | |
}; | |
Spotify.Web.Screens.Login = function(c, a, b, d, f) { | |
var j = this, | |
g = { | |
invalid_credentials: _("Incorrect username and password"), | |
invalid_country: _("Spotify is currently not available in your country"), | |
capped: _("You have reached your maximum number of login attempts, please try again later"), | |
service_unavailable: _("Service is currently unavailable. Please try again later"), | |
fallback: _("Authentication failed. Please try again.") | |
}, | |
k = ["GB", "US", "ZZ"], | |
k = a.country && k.indexOf(a.country) !== -1, | |
l = a.sessionType === "anonymous", | |
h = d && d.isFacebookFlow(), | |
m = a.features && a.features.signup || l, | |
n = new Spotify.Web.Authenticator(a), | |
e = new Spotify.Web.Forms.Signup(c, k, a, Spotify.Web.App.initialize.bind(Spotify.Web.App), d), | |
o, t, C, v, z, w, A, x, u, y, B, D, G, E, F = a.sessionType, | |
I = a.username, | |
H, p, r, s, q, L, S, M, K, N, O, P, Q, T = function() { | |
c.className = "hidden"; | |
document.body.classList.remove("login"); | |
setTimeout(function() { | |
c.style.display = "none" | |
}, 1E3) | |
}, | |
U = function(a) { | |
a.created === "created" && window.dataLayer && window.dataLayer.push({ | |
event: "registration_flow_complete" | |
}); | |
t.stop(); | |
C.stop(); | |
T(); | |
F === "anonymous" && d.authenticateUser(a.username, I); | |
b(a, window.FB || void 0) | |
}, | |
J = function(a) { | |
z.querySelector(".show").classList.remove("show"); | |
a.classList.add("show"); | |
E.style.display = "none" | |
}, | |
V = function(a) { | |
C.stop(); | |
t.stop(); | |
E.innerHTML = g[a] ? g[a] : g.fallback; | |
E.style.display = "block"; | |
z.classList.add("error"); | |
setTimeout(function() { | |
z.classList.remove("error") | |
}, 500) | |
}, | |
W = function(a) { | |
a.preventDefault(); | |
Spotify.Web.WebTracker.log({ | |
type: "FB_LOGIN_CLICKED" | |
}); | |
H.mustAccept() && (H.hide(), H.accept()); | |
t.start(); | |
L.start(); | |
Spotify.Web.FacebookSDK.login(function(a, b, c) { | |
Spotify.Web.WebTracker.log({ | |
type: "INITIALIZE_GDP" | |
}); | |
a === "unknown" || a === "not_authorized" ? (Spotify.Web.WebTracker.log({ | |
type: "REJECTED_GDP" | |
}), t.stop(), L.stop()) : (a === "already_connected" ? Spotify.Web.WebTracker.log({ | |
type: "ALREADY_CONNECTED_GDP" | |
}) : Spotify.Web.WebTracker.log({ | |
type: "ACCEPTED_GDP" | |
}), n.authenticateWithFacebookCredentials(b, c, U, V)) | |
}) | |
}, | |
X = function(a) { | |
a.preventDefault(); | |
T(); | |
f && f("continue") | |
}, | |
aa = function() { | |
v.addEventListener("submit", | |
function(a) { | |
a.preventDefault(); | |
Spotify.Web.WebTracker.log({ | |
type: "SPOTIFY_LOGIN_CLICKED" | |
}); | |
C.start(); | |
H.mustAccept() && (H.hide(), H.accept()); | |
var a = v.querySelector('[name="username"]').value, | |
b = v.querySelector('[name="password"]').value; | |
n.authenticateWithUsernameAndPassword(a, b, U, V) | |
}); | |
z.addEventListener("dragstart", function(a) { | |
a.preventDefault() | |
}); | |
A.addEventListener("click", function(a) { | |
a.preventDefault(); | |
J(u); | |
D.focus() | |
}); | |
G.addEventListener("click", function(a) { | |
a.preventDefault(); | |
J(p) | |
}); | |
y.addEventListener("click", | |
function(a) { | |
a.preventDefault(); | |
J(B) | |
}, !1); | |
x.addEventListener("click", function(a) { | |
a.preventDefault(); | |
J(p); | |
s.className = "" | |
}, !1); | |
N.addEventListener("click", function(a) { | |
a.preventDefault(); | |
J(u) | |
}, !1); | |
O.addEventListener("click", function(a) { | |
a.preventDefault(); | |
J(p) | |
}, !1); | |
Q.addEventListener("click", X, !1); | |
P.addEventListener("click", X, !1); | |
o.addEventListener("click", W, !1); | |
q.addEventListener("click", W, !1); | |
a.showLogin && j.showLogin() | |
}, | |
ba = function() { | |
var b = "", | |
b = m ? ["<h1>" + _("Get the right music, right now") + "</h1>", "<h2>" + | |
_("Listen to millions of songs for free.") + "</h2>", "<ul>", " <li>" + _("Search & discover music you'll love") + "</li>", " <li>" + _("Create playlists of your favorite music") + "</li>", " <li>" + _("Spotify Radio - unlimited stations and skips") + "</li>", "</ul>" | |
].join("\n") : ["<h2>" + _("Spotify hasn\u2019t launched in your country yet") + "</h2>", "<p>" + _('Want an invite when we launch? <a href="https://www.spotify.com/int/why-not-available/">Leave your contact</a>.') + "</p>", "<p>" + _("If you have a Spotify account in another part of the world, you can log into the web player as usual.") + | |
"</p>" | |
].join("\n"), | |
e = _("CookieComplianceBannerText", { | |
LINK_START: '<a class="cookie-link" target="_blank" href="http://www.spotify.com/legal/privacy-policy/#cookies">', | |
LINK_END: "</a>" | |
}); | |
c.innerHTML = ['<div id="cookie-compliance">', " " + e, '</div>\n<div id="bg-wrap">\n <div id="login">\n <div id="login-method">', ' <div class="step ' + (m ? "show" : "") + '" id="screen-signup-flow">', ' <div class="step-outer">\n <div class="step-inner">\n <div class="heading logo">', ' <img alt="" src="' + | |
a.cdn + '/images/logo.png"/>', " </div>", ' <button id="fb-signup-btn" href="#" class="button fb">' + _("Sign up with Facebook") + "</button>", ' <button id="signup-spotify" class="button hide-for-fb" data-or="' + _("or") + '">', " " + _("Sign up with your email address"), " </button>", ' <button id="continue-listening" class="button continue-listening">' + _("Continue Listening") + "</button>", ' <div class="acceptance text-small">' + _("signup/signup_acceptance", { | |
TERMS_START: '<a class="cookies-noaccept" href="https://www.spotify.com/legal/end-user-agreement/" target="_blank">', | |
TERMS_END: "</a>", | |
PP_START: '<a class="cookies-noaccept" href="https://www.spotify.com/legal/privacy-policy/" target="_blank">', | |
PP_END: "</a>" | |
}) + "</div>", ' <div class="has-account text-small">', ' <a id="has-account" href="#">' + _("Already have an account? Log in here.") + "</a>", " </div>\n </div>\n </div>\n </div>", ' <div class="step ' + | |
(m ? "" : "show") + '" id="screen-login-spotify">', ' <div class="step-outer">\n <div class="step-inner">\n <div class="heading logo">', ' <img class="logo-small" alt="" src="' + a.cdn + '/images/logo.png" />', ' <div class="error" id="error"></div>\n </div>\n <form id="sp-login-form" action="#" method="post">', ' <button type="button" id="fb-login-btn" class="button fb">' + _("Log in with Facebook") + "</button>", " <em>" + | |
_("or") + "</em>", " <div>", ' <label for="login-usr">' + _("Username") + "</label>", ' <input type="text" name="username" id="login-usr" placeholder="' + _("Spotify username") + '" />', ' <label for="login-pass" class="pass">' + _("Password") + "</label>", ' <input type="password" name="password" id="login-pass" class="pass" placeholder="' + _("Password") + '" />', ' <button type="submit">' + _("Login") + "</button>", ' </div>\n </form>\n <div class="footer text-small">', | |
' <a class="forgot" href="https://www.spotify.com/password-reset/" target="_blank">' + _("Forgotten your password?") + "</a>", " </div>", ' <div class="footer text-small ' + (m ? "" : "hide") + '">', " " + _("Don't have an account?") + ' <a id="login-cancel" href="#">' + _("Sign up here!") + "</a>", ' </div>\n </div>\n </div>\n </div>\n <div class="step" id="screen-signup-spotify">\n <div class="step-outer">\n <div class="step-inner">\n <div class="heading logo">', | |
' <img class="logo-small" alt="" src="' + a.cdn + '/images/logo.png" />', " <h3>" + _("Create your free Spotify account") + "</h3>", ' </div>\n <div id="signup-form"></div>\n <div class="footer text-small">', ' <a href="#" id="cancel-spotify-signup" class="go-back">« ' + _("Go back") + "</a>", ' </div>\n </div>\n </div>\n </div>\n <div class="step" id="screen-feature-restricted">\n <div class="step-outer">\n <div class="step-inner">\n <div class="heading logo">', | |
' <img class="logo-small" alt="" src="' + a.cdn + '/images/logo.png" />', " </div>", ' <h3 id="restricted-feature-title">' + _("Get access to all of Spotify's features!") + "</h3>", ' <div id="restricted-feature"></div>\n <div class="footer">', ' <button class="button primary hide" id="restricted-continue">' + _("Continue") + "</button>", ' <button class="button primary" id="restricted-signup">' + _("Sign up") + "</button>", ' <button class="button" id="restricted-login">' + | |
_("Log In") + "</button>", " </div>\n </div>\n </div>\n </div>", ' <div id="login-features"' + (!m ? ' class="no-signup"' : "") + ">", " " + b, " </div>\n </div>\n </div>\n</div>" | |
].join("\n") | |
}, | |
Y = function() { | |
var a = {}; | |
return function(b, e) { | |
typeof a[b] === "undefined" && (a[b] = c.querySelectorAll(b)); | |
for (var d = a[b], h = 0, f = d.length, g = null; h < f; h++) g = d[h], e.call(this, g) | |
} | |
}(), | |
Z = function(a) { | |
Y(a, function(a) { | |
a.style.display = "block" | |
}) | |
}, | |
R = function(a) { | |
Y(a, function(a) { | |
a.style.display = | |
"none" | |
}) | |
}; | |
this.init = function() { | |
document.body.classList.add("login"); | |
var b; | |
ba(); | |
z = c.querySelector("#login"); | |
w = c.querySelector("#bg-wrap"); | |
r = c.querySelector("#login-features"); | |
l && (z.classList.add("playNow"), w.classList.add("playNow"), r.classList.add("playNow"), b = "playnow"); | |
d && d.isOpenRedirect() && (b = "contextual_login", w.classList.add("fullscreen")); | |
h && (b = "facebook_login_only", R(".hide-for-fb")); | |
p = c.querySelector("#screen-signup-flow"); | |
c.querySelector("#cancel-spotify-signup"); | |
s = c.querySelector("h1"); | |
o = c.querySelector("#fb-login-btn"); | |
t = new Spotify.Web.Dotter(o, 3, 500); | |
q = c.querySelector("#fb-signup-btn"); | |
L = new Spotify.Web.Dotter(q, 3, 500); | |
v = c.querySelector("#sp-login-form"); | |
loginWithSpotifyBtn = v.querySelector("button"); | |
C = new Spotify.Web.Dotter(loginWithSpotifyBtn, 3, 500, !0); | |
x = c.querySelector("#cancel-spotify-signup"); | |
A = c.querySelector("#has-account"); | |
u = c.querySelector("#screen-login-spotify"); | |
y = c.querySelector("#signup-spotify"); | |
B = c.querySelector("#screen-signup-spotify"); | |
c.querySelector("#signup-form").appendChild(e.node); | |
D = c.querySelector("#login-usr"); | |
G = c.querySelector("#login-cancel"); | |
E = document.querySelector("#error"); | |
S = c.querySelector("#screen-feature-restricted"); | |
M = c.querySelector("#restricted-feature"); | |
K = c.querySelector("#restricted-feature-title"); | |
N = c.querySelector("#restricted-login"); | |
O = c.querySelector("#restricted-signup"); | |
P = c.querySelector("#restricted-continue"); | |
Q = c.querySelector("#continue-listening"); | |
Q.style.display = "none"; | |
H = new Spotify.Web.CookieCompliance(a.country); | |
H.mustAccept() && H.show(); | |
aa(); | |
l ? | |
w.classList.add("loaded") : (b = new Image, b.onload = function() { | |
w.classList.add("loaded") | |
}, b.src = a.cdn + "/images/login-overlay.png", b = "legacy_login"); | |
Spotify.Web.WebTracker.log({ | |
type: "LOGIN_SCREEN_DISPLAYED", | |
error: b, | |
t: (new Date).getTime() | |
}) | |
}; | |
this.showLogin = function() { | |
R(".continue-listening"); | |
h || Z(".hide-for-fb"); | |
J(u) | |
}; | |
this.showContinueListening = function() { | |
R(".hide-for-fb"); | |
Z(".continue-listening") | |
}; | |
this.resetProcess = function() { | |
J(p) | |
}; | |
this.showRestrictedFeature = function(a) { | |
J(S); | |
a === "first_interaction_needed" ? | |
(M.innerHTML = _("blocked/" + a, { | |
TERMS_START: '<a class="cookies-noaccept" href="https://www.spotify.com/legal/end-user-agreement/" target="_blank">', | |
TERMS_END: "</a>", | |
PP_START: '<a class="cookies-noaccept" href="https://www.spotify.com/legal/privacy-policy/" target="_blank">', | |
PP_END: "</a>", | |
COOKIES_START: '<a href="http://www.spotify.com/legal/privacy-policy/#cookies" class="cookies-noaccept" target="_blank">', | |
COOKIES_END: "</a>" | |
}), P.classList.remove("hide"), O.classList.add("hide"), N.classList.add("hide")) : | |
M.innerHTML = _("blocked/" + a); | |
switch (a) { | |
case "time_cap": | |
K.innerHTML = _("Want to keep listening?"); | |
break; | |
case "first_interaction_needed": | |
K.innerHTML = _("Want to keep listening? Press continue!"); | |
break; | |
default: | |
K.innerHTML = _("Get access to all of Spotify's features!") | |
} | |
} | |
}; | |
Spotify.Web.BrowserDetect = { | |
init: function(c) { | |
this._navigator = c || window.navigator; | |
this.browser = this._searchString(this.dataBrowser) || "An unknown browser"; | |
this.version = this._searchVersion(this._navigator.userAgent) || this._searchVersion(this._navigator.appVersion) || "an unknown version"; | |
this.OS = this._searchString(this.dataOS) || "an unknown OS"; | |
this.shouldUseWebSockets = this._useWebSockets() | |
}, | |
_useWebSockets: function() { | |
return Spotify.Web.FeatureDetect.getFlashVersion().major >= 11 && !(this.browser === "Explorer" && | |
this.version < 10 || this.browser === "Safari" && this.version < 6 || this.browser === "Firefox" && this.version < 11) | |
}, | |
_searchString: function(c) { | |
for (var a = 0; a < c.length; a++) { | |
var b = c[a].field ? this._navigator[c[a].field] : null; | |
this.versionSearchString = c[a].versionSearch || c[a].identity; | |
if (!(this.versionSearchString instanceof Array)) this.versionSearchString = [this.versionSearchString]; | |
if (b) { | |
if (!(c[a].subString instanceof Array)) c[a].subString = [c[a].subString]; | |
for (var d = 0; d < c[a].subString.length; d++) | |
if (b.indexOf(c[a].subString[d]) != | |
-1) return c[a].identity | |
} | |
} | |
}, | |
_searchVersion: function(c) { | |
for (var a = -1, b, d = 0; d < this.versionSearchString.length && a == -1; d++) b = this.versionSearchString[d], a = c.indexOf(b); | |
return a == -1 ? void 0 : parseFloat(c.substring(a + b.length + 1)) | |
}, | |
dataBrowser: [{ | |
field: "userAgent", | |
subString: "Chrome", | |
identity: "Chrome" | |
}, { | |
field: "userAgent", | |
subString: "OmniWeb", | |
versionSearch: "OmniWeb/", | |
identity: "OmniWeb" | |
}, { | |
field: "userAgent", | |
subString: "Apple", | |
identity: "Safari", | |
versionSearch: "Version" | |
}, { | |
field: "userAgent", | |
subString: ["Opera", "OPR"], | |
identity: "Opera", | |
versionSearch: ["Version", "OPR"] | |
}, { | |
field: "vendor", | |
subString: "iCab", | |
identity: "iCab" | |
}, { | |
field: "vendor", | |
subString: "KDE", | |
identity: "Konqueror" | |
}, { | |
field: "userAgent", | |
subString: "Firefox", | |
identity: "Firefox" | |
}, { | |
field: "vendor", | |
subString: "Camino", | |
identity: "Camino" | |
}, { | |
field: "userAgent", | |
subString: "Netscape", | |
identity: "Netscape" | |
}, { | |
field: "userAgent", | |
subString: ["MSIE", "Trident"], | |
identity: "Explorer", | |
versionSearch: ["MSIE", "rv"] | |
}, { | |
field: "userAgent", | |
subString: "Gecko", | |
identity: "Mozilla", | |
versionSearch: "rv" | |
}, { | |
field: "userAgent", | |
subString: "Mozilla", | |
identity: "Netscape", | |
versionSearch: "Mozilla" | |
}], | |
dataOS: [{ | |
field: "platform", | |
subString: "Win", | |
identity: "Windows" | |
}, { | |
field: "platform", | |
subString: "Mac", | |
identity: "Mac" | |
}, { | |
field: "userAgent", | |
subString: "iPhone", | |
identity: "iPhone/iPod" | |
}, { | |
field: "platform", | |
subString: "Linux", | |
identity: "Linux" | |
}], | |
getVendorPrefix: function() { | |
if ("result" in arguments.callee) return arguments.callee.result; | |
var c = /^(Moz|Webkit|Khtml|O|ms|Icab)(?=[A-Z])/, | |
a = document.getElementsByTagName("script")[0], | |
b; | |
for (b in a.style) | |
if (c.test(b)) return arguments.callee.result = | |
b.match(c)[0]; | |
return "WebkitOpacity" in a.style ? arguments.callee.result = "Webkit" : "KhtmlOpacity" in a.style ? arguments.callee.result = "Khtml" : arguments.callee.result = "" | |
} | |
}; | |
Spotify.Web.ScrollBlocker = function(c, a, b) { | |
this.publisher = a; | |
this.blocker = c; | |
this.popupManager = b | |
}; | |
Spotify.Web.ScrollBlocker.prototype.init = function() { | |
this.publisher.subscribe(Spotify.Web.PublisherMessages.SCROLL_BLOCK, this); | |
this.publisher.subscribe(Spotify.Web.PublisherMessages.SCROLL_ALLOW, this); | |
this.blocker.addEventListener("mouseover", function(a) { | |
a.stopPropagation() | |
}, !1); | |
this.blocker.addEventListener("contextmenu", function(a) { | |
a.preventDefault() | |
}, !1); | |
var c = this; | |
this.blocker.addEventListener("mousedown", function() { | |
c.deactivate() | |
}, !1) | |
}; | |
Spotify.Web.ScrollBlocker.prototype.activate = function() { | |
this.blocker.style.display = "block" | |
}; | |
Spotify.Web.ScrollBlocker.prototype.deactivate = function() { | |
if (this.popupManager.closeAll()) this.blocker.style.display = "none" | |
}; | |
Spotify.Web.ScrollBlocker.prototype.onNotify = function(c) { | |
switch (c.messageType) { | |
case Spotify.Web.PublisherMessages.SCROLL_BLOCK: | |
this.activate(); | |
break; | |
case Spotify.Web.PublisherMessages.SCROLL_ALLOW: | |
this.deactivate() | |
} | |
}; | |
Spotify.Web.Messaging = function(c, a) { | |
Spotify.Web.EventTarget.call(this); | |
var b = this; | |
this.notifications = {}; | |
this.init = function() { | |
a.onMessagingUnreadCountChange(function(a) { | |
c.notify(Spotify.Web.PublisherMessages.UNREAD_COUNT_CHANGE, { | |
count: a | |
}) | |
}); | |
window.Notification && a.subscribeMessagingEvents(function(a, c) { | |
var j = c[0]; | |
switch (j.type) { | |
case "NEW_MESSAGE": | |
b.onNewMessage(j); | |
break; | |
case "READ_CONVERSATION": | |
b.onReadConversation(j) | |
} | |
}) | |
}; | |
this.onNewMessage = function(d) { | |
var f = d.newMessage.conversation, | |
j = f.preview, | |
g = "spotify:app:messages:thread:" + | |
encodeURIComponent(f.id); | |
a.getUsername(function(d) { | |
"spotify:user:" + d !== j.sender && a.getSocialDataForUser(j.sender, function(a) { | |
if (a) { | |
var d = _("NewMessageWebNotificationTitle", { | |
USER_NAME: a.name | |
}), | |
a = new Notification(d, { | |
tag: g, | |
body: j.text, | |
icon: a.image | |
}); | |
a.show && a.show(); | |
b.notifications[f.id] = a; | |
a.addEventListener("click", function() { | |
var a = Spotify.Web.PublisherMessages.APPLICATION_OPEN_URI, | |
b = Spotify.Link.fromString(g); | |
c.notify(a, { | |
link: b | |
}); | |
window.focus() | |
}) | |
} | |
}) | |
}) | |
}; | |
this.onReadConversation = function(a) { | |
var a = a.readConversation.conversationId, | |
c = b.notifications[a]; | |
c && c.close && (c.close(), delete b.notifications[a]) | |
} | |
}; | |
Spotify.Web.Notifications = function(c, a) { | |
Spotify.Web.EventTarget.call(this); | |
this.init = function() { | |
a.onNotificationsUnreadCountChange(function(a) { | |
c.notify(Spotify.Web.PublisherMessages.UNREAD_NOTIFICATIONS_COUNT_CHANGE, { | |
count: a | |
}) | |
}) | |
} | |
}; | |
Spotify.Web.SocialData = function(c, a, b) { | |
Spotify.Web.EventTarget.call(this); | |
var d = this; | |
this._userSurname = this._userFirstName = this._userImage = ""; | |
this._fbComplete = this._apComplete = !1; | |
var f = function() { | |
c.notify(Spotify.Web.PublisherMessages.SOCIAL_DATA_SUCCESS, { | |
name: d._userFirstName, | |
surname: d._userSurname, | |
image: d._userImage | |
}) | |
}, | |
j = function() { | |
b.getUserImage(function(a) { | |
b.getUsersName(function(b) { | |
var c = a.message[0]; | |
if (d._userImage === "" && c && c.url !== "") d._userImage = c.url; | |
if (d._userFirstName === "" && b.message.first_name && | |
b.message.first_name !== "") d._userFirstName = b.message.first_name; | |
if (d._userSurname === "" && b.message.last_name && b.message.last_name !== "") d._userSurname = b.message.last_name; | |
d._fbComplete = !0; | |
f() | |
}) | |
}) | |
}, | |
g = function() { | |
a.getSocialDataForCurrentUser(function(a) { | |
d._apComplete = !0; | |
if (a) { | |
if (a.image && a.image !== "") d._userImage = a.image; | |
if (a.name && a.name !== "") { | |
var a = a.name, | |
b = a.split(" "); | |
d._userFirstName = b[0]; | |
d._userSurname = b.length > 1 ? a.substring(a.indexOf(" ") + 1) : "" | |
} | |
f() | |
} | |
}) | |
}; | |
this.init = function() { | |
g(); | |
c.subscribe(Spotify.Web.PublisherMessages.FB_APP_CONNECTED, | |
d) | |
}; | |
this.onNotify = function(a) { | |
a.messageType === Spotify.Web.PublisherMessages.FB_APP_CONNECTED && (this._userFirstName === "" || this._userImage === "") && j() | |
} | |
}; | |
Spotify.Web.Static = function() { | |
this.preloadImage = function(c, a) { | |
var b = new Image; | |
b.src = c; | |
if (typeof a !== "undefined") b.onload = a | |
}; | |
this.loadScript = function(c) { | |
var a = document.createElement("script"); | |
a.type = "text/javascript"; | |
a.async = !0; | |
a.src = c; | |
c = document.getElementsByTagName("script")[0]; | |
c.parentNode.insertBefore(a, c) | |
} | |
}; | |
Spotify.Web.EventTarget = function() { | |
var c = {}; | |
this.bind = function(a, b, d) { | |
var f = { | |
callback: b, | |
context: d | |
}, | |
j = !1, | |
g; | |
c[a] === void 0 && (c[a] = []); | |
g = c[a]; | |
for (var k = 0; k < g.length; k++) | |
if (g[k].callback === b && g[k].context === d) { | |
j = !0; | |
break | |
} | |
j === !1 && c[a].push(f) | |
}; | |
this.trigger = function(a, b) { | |
var d = c[a], | |
f; | |
if (typeof d !== "undefined") | |
for (f = 0; f < d.length; f++) { | |
var j = d[f]; | |
j.callback.call(j.context, { | |
type: a, | |
sender: this, | |
params: b | |
}) | |
} | |
}; | |
this.unbind = function(a, b, d) { | |
var f, j = c[a]; | |
if (typeof j !== "undefined") { | |
for (var g = 0; g < j.length; g++) | |
if (j[g].callback === | |
b && j[g].context === d) { | |
f = g; | |
break | |
} | |
f !== -1 && c[a].splice(f, 1) | |
} | |
} | |
}; | |
Spotify.Web.Publisher = function() { | |
var c = {}, | |
a = function(a) { | |
c[a] === void 0 && (c[a] = []); | |
return c[a] | |
}; | |
this.subscribe = function(b, c) { | |
if (!b) throw Error("Spotify.Web.Publisher message type must be set"); | |
if (!c) throw Error("Spotify.Web.Publisher listener object must be set"); | |
var f = a(b); | |
f.indexOf(c) === -1 && f.push(c) | |
}; | |
this.unsubscribe = function(b, c) { | |
var f = a(b), | |
j = f.indexOf(c); | |
j > -1 && f.splice(j, 1) | |
}; | |
this.notify = function(b, c, f) { | |
for (var j = a(b), g = 0; g < j.length; g++) j[g].onNotify({ | |
messageType: b, | |
message: c, | |
origin: f | |
}) | |
} | |
}; | |
Spotify.Web.PublisherMessages = { | |
ERROR: "ERROR", | |
APPLICATION_STATE_CHANGED: "APPLICATION_STATE_CHANGED", | |
APPLICATION_STATE_PUSH: "APPLICATION_STATE_PUSH", | |
APPLICATION_STATE_REPLACE: "APPLICATION_STATE_REPLACE", | |
APPLICATION_OPEN_URI: "APPLICATION_OPEN_URI", | |
APPLICATION_POST_MESSAGE: "APPLICATION_POST_MESSAGE", | |
APPLICATION_ENABLED: "APPLICATION_ENABLED", | |
APPLICATION_VERSION_CHANGED: "APPLICATION_VERSION_CHANGED", | |
APPLICATION_CLOSED: "APPLICATION_CLOSED", | |
APPLICATION_DISPOSED: "APPLICATION_DISPOSED", | |
APPLICATION_ACTIVATED: "APPLICATION_ACTIVATED", | |
APPLICATION_DEACTIVATED: "APPLICATION_DEACTIVATED", | |
APPLICATION_SET_PREFERRED_SIZE: "APPLICATION_SET_PREFERRED_SIZE", | |
LIMITED_FEATURE_CALL: "LIMITED_FEATURE_CALL", | |
CLIENT_SHOW_SHARE_UI: "CLIENT_SHOW_SHARE_UI", | |
CLIENT_SHOW_CONTEXT_UI: "CLIENT_SHOW_CONTEXT_UI", | |
CLIENT_SHOW_COLLECTION_UNION_REMOVE_UI: "CLIENT_SHOW_COLLECTION_UNION_REMOVE_UI", | |
CHROME_READY: "CHROME_READY", | |
FB_APP_CONNECTED: "FB_APP_CONNECTED", | |
FB_APP_NOT_AUTHENTICATED: "FB_APP_NOT_AUTHENTICATED", | |
FB_APP_UNKNOWN: "FB_APP_UNKNOWN", | |
FB_CONNECTION_FAILURE: "FB_CONNECTION_FAILURE", | |
FB_MESSAGE: "FB_MESSAGE", | |
FB_POST: "FB_POST", | |
FB_SESSION_QUERY: "FB_SESSION_QUERY", | |
FB_SESSION_USER_METADATA: "FB_SESSION_USER_METADATA", | |
USER_AUTHENTICATED: "USER_AUTHENTICATED", | |
USER_AUTHENTICATION_FAILURE: "USER_AUTHENTICATION_FAILURE", | |
USER_CONTEXT_FREEZE: "USER_CONTEXT_FREEZE", | |
WINDOW_FOCUS: "WINDOW_FOCUS", | |
SCROLL_ALLOW: "SCROLL_ALLOW", | |
SCROLL_BLOCK: "SCROLL_BLOCK", | |
SUGGEST_SHOW: "SUGGEST_SHOW", | |
SUGGEST_HIDE: "SUGGEST_HIDE", | |
SUGGEST_SHOWN: "SUGGEST_SHOWN", | |
SUGGEST_HIDDEN: "SUGGEST_HIDDEN", | |
NOTIFICATIONS_SHOW: "NOTIFICATIONS_SHOW", | |
NOTIFICATIONS_HIDE: "NOTIFICATIONS_HIDE", | |
NOTIFICATIONS_SHOWN: "NOTIFICATIONS_SHOWN", | |
NOTIFICATIONS_HIDDEN: "NOTIFICATIONS_HIDDEN", | |
SOCIAL_DATA_SUCCESS: "SOCIAL_DATA_SUCCESS", | |
UNREAD_COUNT_CHANGE: "UNREAD_COUNT_CHANGE", | |
UNREAD_NOTIFICATIONS_COUNT_CHANGE: "UNREAD_NOTIFICATIONS_COUNT_CHANGE", | |
MODEL_UPDATED: "MODEL_UPDATED", | |
USER_INTERACTION: "USER_INTERACTION", | |
USER_INTERACTION_PAUSE_PLAYBACK: "USER_INTERACTION_PAUSE_PLAYBACK", | |
COOKIES_ACCEPTED: "COOKIES_ACCEPTED", | |
LASTFM_CONNECT: "LASTFM_CONNECT", | |
APPLICATION_LOAD_TIME: "APPLICATION_LOAD_TIME", | |
APPLICATION_LOAD_STARTED: "APPLICATION_LOAD_STARTED" | |
}; | |
Spotify.Web.BaseModalWindow = function(c, a) { | |
Spotify.Web.EventTarget.call(this); | |
var b = this, | |
d = !1, | |
f = !1, | |
c = c || {}, | |
j = !1, | |
g = Spotify.Web.BrowserDetect.browser === "Explorer" && Spotify.Web.BrowserDetect.version < 10, | |
k = c.url, | |
l = c.id || null, | |
h = c.wrapper, | |
m = c.iframe, | |
n = function(a) { | |
//TODO add Try Catch. I think that assing a variable value inside of switch stament it's really good idea | |
if (a.source == m.contentWindow) switch (a = JSON.parse(a.data), a.type) { | |
case "POPUP_WINDOW_POSITION": | |
delete a.type; | |
b.position(a); | |
break; | |
case "POPUP_WINDOW_SHOW": | |
b.show(); | |
break; | |
case "POPUP_WINDOW_CLOSE": | |
b.hide(); | |
break; | |
case "POPUP_WINDOW_RESIZE": | |
b.resize(a.height, | |
a.width) | |
} | |
}, | |
e = function(a) { | |
m.contentWindow.postMessage(JSON.stringify({ | |
type: a | |
}), "*") | |
}; | |
this.getFrame = function() { | |
return m || null | |
}; | |
this.getElement = function() { | |
return h | |
}; | |
this.getUrl = function() { | |
return k | |
}; | |
this.isVisible = function() { | |
return j | |
}; | |
this.initialize = function() { | |
this._initializeWindow() | |
}; | |
this.show = function() { | |
this._showWindow() | |
}; | |
this.hide = function() { | |
this._hideWindow() | |
}; | |
this._initializeWindow = function() { | |
this.trigger("ON_BEFORE_INITIALIZE"); | |
if (!k) throw Error("Application URL not specified."); | |
h || (h = document.createElement("div")); | |
if (!m) { | |
var e = document.createElement("iframe"); | |
e.setAttribute("id", "app-" + k); | |
e.setAttribute("frameBorder", "no"); | |
e.style.width = "100%"; | |
e.style.height = "100%"; | |
m = e; | |
h.appendChild(m) | |
} | |
c.loadAfter !== "ON_DEMAND" && setTimeout(function() { | |
b.load() | |
}, c.loadAfter); | |
a.subscribe(Spotify.Web.PublisherMessages.APPLICATION_LOAD_TIME, this); | |
a.subscribe(Spotify.Web.PublisherMessages.APPLICATION_STATE_CHANGED, this) | |
}; | |
this.load = function() { | |
if (!d) a.notify(Spotify.Web.PublisherMessages.APPLICATION_LOAD_STARTED, { | |
uri: "spotify:app:" + | |
l, | |
start: (new Date).getTime() | |
}), m.src = k, window.addEventListener("message", n, !1), a.notify(Spotify.Web.PublisherMessages.APPLICATION_STATE_CHANGED, { | |
link: Spotify.Link.applicationLink(l), | |
iframe: m | |
}), d = !0, this.trigger("ON_AFTER_INITIALIZE") | |
}; | |
this.onNotify = function(a) { | |
switch (a.messageType) { | |
case Spotify.Web.PublisherMessages.APPLICATION_STATE_CHANGED: | |
a.message.link.id != l && e(a.message.link.id); | |
break; | |
case Spotify.Web.PublisherMessages.APPLICATION_LOAD_TIME: | |
!f && a.message.uri === "spotify:app:" + l && (f = !0) | |
} | |
}; | |
this._showWindow = | |
function(a) { | |
d || this.load(); | |
if (f) { | |
if (!j) { | |
try { | |
j = !0; | |
this.trigger("ON_BEFORE_SHOW"); | |
if (g) h.style.opacity = 1; | |
h.addClass("show"); | |
h.addClass("scale-start"); | |
setTimeout(function() { | |
h.addClass("scale-end") | |
}, 100); | |
Spotify.Web.Utils.addTransitionEndedListener(h, function() { | |
h.removeClass("scale-start").removeClass("scale-end") | |
}, 2E3); | |
Browser.firefox && this.getElement().id === c.id + "-area" && document.activeElement.blur(); | |
e("WINDOW_FOCUS"); | |
this.trigger("ON_SHOW") | |
} catch (l) {} | |
this.trigger("ON_AFTER_SHOW") | |
} | |
a && a() | |
} else setTimeout(function() { | |
b._showWindow(a) | |
}, | |
200) | |
}; | |
this._hideWindow = function() { | |
if (j) { | |
j = !1; | |
this.trigger("ON_BEFORE_HIDE"); | |
h.removeClass("show"); | |
if (g) h.style.opacity = 0; | |
this.trigger("ON_HIDE") | |
} | |
window.focus(); | |
e("WINDOW_CLOSED"); | |
this.trigger("ON_AFTER_HIDE") | |
} | |
}; | |
Spotify.Web.LightboxWindow = function(c, a) { | |
Spotify.Web.BaseModalWindow.call(this, c, a); | |
var b = this; | |
this.initialize = function() { | |
this._initializeWindow(); | |
this.getFrame(); | |
var a = this.getElement(), | |
b = a.className.split(" "); | |
b.push("lightbox"); | |
a.className = b.join(" ") | |
}; | |
this.show = function(c) { | |
this._showWindow(function() { | |
a.notify(Spotify.Web.PublisherMessages.APPLICATION_STATE_CHANGED, { | |
link: c, | |
iframe: b.getFrame() | |
}) | |
}) | |
} | |
}; | |
Spotify.Web.PopupWindow = function(c, a, b) { | |
Spotify.Web.BaseModalWindow.call(this, c, a); | |
var c = c || {}, | |
d = null, | |
f = c.width || 220, | |
j = null, | |
g = { | |
url: c.url, | |
id: c.id || null, | |
wrapper: c.wrapper, | |
iframe: c.iframe, | |
preventScrolling: c.preventScrolling || !1, | |
hideOnWindowResize: c.hideOnWindowResize || !1, | |
postShowCallback: c.postShowCallback, | |
postHideCallback: c.postHideCallback, | |
persistent: c.persistent || !1, | |
loadAfter: c.loadAfter | |
}; | |
this.initialize = function() { | |
this._initializeWindow(); | |
if (g.hideOnWindowResize) this.onWindowResize = this.onWindowResize.bind(this), | |
window.addEventListener("resize", this.onWindowResize, !1); | |
this.bind("ON_BEFORE_SHOW", this._onBeforeShow, this) | |
}; | |
this.onWindowResize = function() { | |
this.hide() | |
}; | |
this.getWidth = function() { | |
return f | |
}; | |
this.getHeight = function() { | |
return d | |
}; | |
this.updateSize = function() { | |
if (this.isVisible()) g.wrapper.style.width = f + "px", g.wrapper.style.height = d + "px" | |
}; | |
this.resize = function(a, b) { | |
d = a; | |
if (b && (f = b, j)) g.wrapper.style.left = j - b / 2 + "px"; | |
this.updateSize() | |
}; | |
this.position = function(a) { | |
if (!a.top && !a.bottom || !a.left && !a.right || a.top && | |
a.bottom || a.left && a.right) throw Error("Must specify position with either top/bottom and either left/right"); | |
var b, c, d, f, e = "top", | |
j = "left"; | |
a.top ? b = a.top : (e = "bottom", c = a.bottom); | |
a.left ? d = a.left : (j = "right", f = a.right); | |
e == "top" ? (g.wrapper.style.bottom = "auto", g.wrapper.style.top = b + "px") : (g.wrapper.style.top = "auto", g.wrapper.style.bottom = c + "px"); | |
j == "left" ? (g.wrapper.style.right = "auto", g.wrapper.style.left = d + "px") : (g.wrapper.style.left = "auto", g.wrapper.style.right = f + "px") | |
}; | |
this._onBeforeShow = function() { | |
this.updateSize() | |
}; | |
this.show = function(b, d) { | |
if (!this.isVisible()) { | |
this.trigger("onBeforeShow"); | |
if (b) g.wrapper.style.left = b.left + "px", b.direction == b.popupBelow ? (g.wrapper.style.bottom = "auto", g.wrapper.style.top = b.top + "px") : (g.wrapper.style.top = "auto", g.wrapper.style.bottom = b.bottom + "px"), g.wrapper.className = "popup-area popover", g.wrapper.addClass(b.direction), b.arrow && g.wrapper.addClass(b.arrow), j = b.arrowLeft, b.arrow || g.wrapper.addClass("no-arrow"); | |
this._showWindow(d); | |
c.showMessage && a.notify(c.showMessage); | |
g.preventScrolling && | |
a.notify(Spotify.Web.PublisherMessages.SCROLL_BLOCK); | |
g.postShowCallback && g.postShowCallback(); | |
this.trigger("onAfterShow") | |
} | |
}; | |
this.hide = function() { | |
this.isVisible() && (this._hideWindow(), c.hideMessage && a.notify(c.hideMessage), g.postHideCallback && g.postHideCallback()); | |
setTimeout(function() { | |
g.preventScrolling && !b.anyPopupVisible() && a.notify(Spotify.Web.PublisherMessages.SCROLL_ALLOW) | |
}, 250) | |
}; | |
this.isPersistent = function() { | |
return g.persistent | |
} | |
}; | |
Spotify.Web.PopupManager = function(c, a, b, d) { | |
var f = this, | |
j = {}, | |
g = {}, | |
k = !1, | |
l = d ? "arrow-top" : "top", | |
h = d ? "arrow-bottom" : "bottom", | |
m = function() { | |
k = !0 | |
}, | |
n = function() { | |
setTimeout(function() { | |
k = !1 | |
}, 250) | |
}; | |
this.createAndRegisterPopup = function(e, d) { | |
var h; | |
if (d.wrapper) h = d.wrapper; | |
else { | |
h = b.ownerDocument.createElement("div"); | |
h.className = "popup-area"; | |
h.setAttribute("id", e + "-area"); | |
var l = b.ownerDocument.createElement("iframe"); | |
l.setAttribute("id", e); | |
l.setAttribute("tabindex", "-1"); | |
l.setAttribute("frameborder", "0"); | |
l.setAttribute("scrolling", | |
"no"); | |
l.setAttribute("allowTransparency", "true"); | |
h.appendChild(l); | |
b.appendChild(h) | |
} | |
h = new Spotify.Web.PopupWindow({ | |
url: c.getAppUrl("/" + e + "/"), | |
id: e, | |
wrapper: h, | |
iframe: d.iframe || h.querySelectorAll("iframe")[0], | |
hideMessage: d.hideMessage, | |
showMessage: d.showMessage, | |
preventScrolling: d.preventScrolling, | |
hideOnWindowResize: d.hideOnWindowResize, | |
width: d.width, | |
postHideCallback: d.postHideCallback, | |
loadAfter: d.loadAfter || 0 | |
}, a, f); | |
h.resize(d.height || 200); | |
j[e] = h; | |
g[h.getFrame().id] = h; | |
h.bind("onBeforeShow", m); | |
h.bind("onAfterShow", | |
n); | |
return h | |
}; | |
this.registerPopup = function(a, b) { | |
j[a] = b | |
}; | |
this.anyPopupVisible = function() { | |
for (var a in j) | |
if (j[a].isVisible()) return !0; | |
return !1 | |
}; | |
this.initializePopups = function() { | |
for (var a in j) j[a].initialize() | |
}; | |
this.popup = function(c, f, g) { | |
var k = j[c.id]; | |
if (!k) throw Error("cannot find popup with id", c.id); | |
var m = k.getWidth(), | |
n, w, A, x = l, | |
u; | |
if (g) n = window.innerWidth / 2 - m / 2, w = 160; | |
else { | |
u = parseInt(c.args[0], 10); | |
var g = parseInt(c.args[1], 10), | |
y = parseInt(c.args[2], 10), | |
B = parseInt(c.args[3], 10); | |
if (!u || !g) throw Error("popup can only be triggered for popup URIs"); | |
if (!f) throw Error("unknown origin"); | |
f = Spotify.Web.Utils.getWindowPosition(f); | |
n = u + f.left; | |
w = g + f.top; | |
A = 0; | |
u = "middle"; | |
var D = b.ownerDocument.body.offsetWidth; | |
n -= m / 2 - y / 2; | |
w += B + (d ? 0 : 10); | |
if (w + 300 > window.innerHeight) x = document.body, A = document.documentElement, A = Math.max(x.scrollHeight, x.offsetHeight, A.clientHeight, A.scrollHeight, A.offsetHeight) - (g + f.top) + 10, x = h; | |
n + m > D && (n = n - m / 2 + 15, u = "arrow-position-right") | |
} | |
c.args.splice(0, 4); | |
k.show({ | |
left: n, | |
top: w, | |
bottom: A, | |
arrowLeft: n + m / 2, | |
direction: x, | |
arrow: u, | |
popupBelow: l | |
}, function() { | |
a.notify(Spotify.Web.PublisherMessages.APPLICATION_STATE_CHANGED, { | |
link: c, | |
iframe: k.getFrame() | |
}) | |
}) | |
}; | |
this.closeAll = function() { | |
if (k) return !1; | |
for (var a in j) j[a].isVisible() && !j[a].isPersistent() && j[a].hide(); | |
return !0 | |
}; | |
this.closeById = function(a) { | |
if (k) return !1; | |
j[a].isVisible() && j[a].hide(); | |
return !0 | |
}; | |
this.onNotify = function(a) { | |
var b = a.message; | |
switch (a.messageType) { | |
case Spotify.Web.PublisherMessages.APPLICATION_SET_PREFERRED_SIZE: | |
if (a = g[b.origin.id]) a.resize(b.height, b.width), b.callback(b.width, b.height) | |
} | |
}; | |
a.subscribe(Spotify.Web.PublisherMessages.APPLICATION_SET_PREFERRED_SIZE, | |
f) | |
}; | |
Spotify.Web.Window = function(c) { | |
Spotify.Web.EventTarget.call(this); | |
var a = this, | |
c = c || {}, | |
b = c.url, | |
d = c.iframe, | |
f = function(c) { | |
b.indexOf(c.origin) === 0 && c.origin !== "" && a.trigger("onMessage", c.data) | |
}; | |
this.initialize = function() { | |
if (!b) throw Error("Application URL not specified."); | |
if (!d) { | |
var a = document.createElement("iframe"); | |
a.setAttribute("frameBorder", "no"); | |
a.style.width = "100%"; | |
a.style.height = "100%"; | |
d = a | |
} | |
window.addEventListener("message", f); | |
a = "app-" + Spotify.Web.Utils.appNameFromUrl(b); | |
d.setAttribute("id", a); | |
d.src = b | |
}; | |
this.getElement = function() { | |
return d | |
}; | |
this.getUrl = function() { | |
return b | |
}; | |
this.show = function() { | |
d.style.display = "block" | |
}; | |
this.hide = function() { | |
d.style.display = "none" | |
} | |
}; | |
Spotify.Web.URLParser = function() { | |
var c = {}, | |
a = /^(?:(\w+):)?(?:\/\/(?:(?:([^:@\/]*):?([^:@\/]*))?@)?([^:\/?#]*)(?::(\d*))?)?(\.\.?$|(?:[^?#\/]*\/)*)([^?#]*)(?:\?([^#]*))?(?:#(.*))?/; | |
c.parseURL = function(b, c) { | |
var b = c ? b.match(a) : decodeURI(b).match(a), | |
f = { | |
protocol: b[1] || null, | |
user: b[2] || null, | |
domain: b[4] || null, | |
query: b[8] || null, | |
port: b[5] || null, | |
hash: b[9] || null, | |
path: ((b[6] || "") + (b[7] || "")).replace(/^\/|\/$/g, "") || null, | |
url: b[0] | |
}; | |
if (f.path) f.pathSegments = f.path.replace(/^\/|\/$/g, "").split("/"); | |
if (f.hash) f.hashSegments = | |
f.hash.replace(/^\/|\/$/g, "").split("/"); | |
if (f.query) { | |
f.params = {}; | |
for (var j = /([^=&]+)\=([^=&]+)/g, g = j.exec(f.query); g;) f.params[g[1]] = g[2], g = j.exec(f.query) | |
} | |
return f | |
}; | |
c.isRoot = function(a) { | |
return (a = c.parseURL(a)) && a.path === null | |
}; | |
return c | |
}(); | |
Spotify.Web.Notification = function(c) { | |
Spotify.Web.EventTarget.call(this); | |
var c = c || {}, | |
a = c.message || "", | |
b = c.id || null, | |
d = c.timeout, | |
f = this, | |
j = null; | |
this.initialize = function() { | |
j = document.createElement("div"); | |
var b = document.createElement("p"); | |
b.innerHTML = a; | |
var c = document.createElement("div"); | |
c.onclick = function() { | |
f.trigger("onclose", {}) | |
}; | |
j.appendChild(b); | |
j.appendChild(c) | |
}; | |
this.getElement = function() { | |
return j | |
}; | |
this.getId = function() { | |
return b | |
}; | |
this.getTimeout = function() { | |
return d | |
}; | |
this.setWidth = function(a) { | |
j.style.width = | |
"" + a + "px"; | |
j.style.position = "relative"; | |
j.style.left = [300 - a, "px"].join("") | |
} | |
}; | |
Spotify.Web.NotificationArea = function(c) { | |
var c = c || {}, | |
a = c.element || {}, | |
b = null, | |
d = [], | |
f = {}, | |
j = function(a) { | |
if (a) return f[a] | |
}, | |
g = function(a) { | |
var c = d.indexOf(a); | |
c > -1 && (d.splice(c, 1), b.removeChild(a.getElement()), a.getId() && delete f[a.getId()]) | |
}, | |
k = function(a) { | |
d.push(a); | |
b.appendChild(a.getElement()); | |
a.getId() && (f[a.getId()] = a); | |
a.getTimeout() && setTimeout(function() { | |
g(a) | |
}, a.getTimeout()) | |
}; | |
this.initialize = function() { | |
b = a; | |
if (b === null) throw Error("Spotify.Web.NotificationArea element not found"); | |
}; | |
this.show = function(a) { | |
var b; | |
b = j(a.id); | |
if (!b) return b = new Spotify.Web.Notification(a), b.initialize(), a.width && b.setWidth(a.width), b.bind("onclose", function(a) { | |
g(a.sender) | |
}), k(b), b | |
}; | |
this.hide = function(a) { | |
(a = j(a)) && g(a) | |
} | |
}; | |
Spotify.Web.Dialog = function(c) { | |
var c = c || {}, | |
a = c.element, | |
b = !1, | |
d = function() { | |
f() | |
}, | |
f; | |
this.initialize = function() { | |
if (!a) throw Error("Spotify.Web.Dialog element not specified"); | |
a.querySelector("button").onclick = d | |
}; | |
this.show = function(c) { | |
var d = a.querySelector("p"); | |
d.innerHTML = c.message; | |
d.className = c.className; | |
var d = a.querySelector("button"), | |
k = a.querySelector(".buttonContainer"); | |
c.button ? (d.innerHTML = c.button, f = c.action, k.style.display = "block") : k.style.display = "none"; | |
a.style.display = "block"; | |
b = !0 | |
}; | |
this.hide = | |
function() { | |
a.style.display = "none"; | |
b = !1 | |
}; | |
this.isVisible = function() { | |
return b | |
} | |
}; | |
Spotify.Web.ErrorTypes = { | |
SESSION_LOST: "SESSION_LOST", | |
TOKEN_LOST: "TOKEN_LOST", | |
NO_SOUND_CAPABILITIES: "NO_SOUND_CAPABILITIES", | |
AD_BLOCK_DETECTED: "AD_BLOCK_DETECTED", | |
CONNECTION_RESTORED: "CONNECTION_RESTORED", | |
HEARTBEAT: "HEARTBEAT", | |
CONNECTION_LOST: "CONNECTION_LOST", | |
CONNECTING: "CONNECTING", | |
TRACK_NOT_PLAYABLE: "TRACK_NOT_PLAYABLE", | |
TRACK_NOT_PLAYABLE_TRACK_CAP: "TRACK_NOT_PLAYABLE_TRACK_CAP", | |
TRACK_NOT_PLAYABLE_TIME_CAP: "TRACK_NOT_PLAYABLE_TIME_CAP", | |
WAIT_FOR_COMMERCIAL_TO_FINISH: "WAIT_FOR_COMMERCIAL_TO_FINISH", | |
FLASH_NOT_AVAILABLE: "FLASH_NOT_AVAILABLE", | |
FB_CONNECTING_TO: "FB_CONNECTING_TO", | |
FB_CONNECTION_FAILED: "FB_CONNECTION_FAILED", | |
APPLICATION_RELOAD_NEEDED: "APPLICATION_RELOAD_NEEDED", | |
UNCAUGHT_EXCEPTION: "UNCAUGHT_EXCEPTION", | |
CANNOT_CONNECT_TO_STREAMING_SERVER: "CANNOT_CONNECT_TO_STREAMING_SERVER", | |
BOOKMARK: "BOOKMARK" | |
}; | |
Spotify.Web.ErrorMessages = { | |
FLASH_NOT_AVAILABLE: { | |
message: _("To enjoy Spotify, please install Adobe Flash. It's free."), | |
className: "normal", | |
button: _("Get Flash"), | |
action: function() { | |
window.open("http://get.adobe.com/flashplayer/") | |
} | |
}, | |
SESSION_LOST: { | |
message: _("Session lost. Please login again."), | |
className: "normal", | |
button: _("Login"), | |
action: function() { | |
location.href = "/login/" | |
} | |
}, | |
NO_SOUND_CAPABILITIES: { | |
message: _("Your computer doesn't support audio."), | |
className: "normal", | |
button: _("Exit"), | |
action: function() { | |
window.open("/login/") | |
} | |
}, | |
APPLICATION_RELOAD_NEEDED: { | |
message: _("There's a new version of Spotify available. Please reload the page."), | |
className: "normal", | |
button: _("Reload"), | |
action: function() { | |
window.location.reload() | |
} | |
}, | |
CONNECTING: { | |
message: _("Connecting to Spotify{{LOADER}}", { | |
LOADER: '...<br /><span class="indicator"></span>' | |
}), | |
className: "indicator" | |
}, | |
FB_CONNECTING_TO: { | |
message: _("Connecting to Facebook{{LOADER}}", { | |
LOADER: '...<br /><span class="indicator"></span>' | |
}), | |
className: "indicator" | |
}, | |
FB_CONNECTION_FAILED: { | |
message: _("We're sorry but connection to Facebook is not working. Please, try to {{LINK_START}}login using the main page{{LINK_END}}.", { | |
LINK_START: '<a href="/">', | |
LINK_END: "</a>" | |
}), | |
className: "indicator" | |
} | |
}; | |
Spotify.Web.Error = function(c, a) { | |
var c = c || {}, | |
b = c.publisher, | |
d = c.element, | |
f = c.dialog, | |
j = c.timeout, | |
g = null, | |
k = null; | |
this.initialize = function() { | |
if (!b) throw Error("Spotify.Web.Error - Publisher instance is missing"); | |
if (!d) throw Error("Spotify.Web.Error container not specified"); | |
if (!f) throw Error("Spotify.Web.Error dialog element not specified"); | |
g = new Spotify.Web.NotificationArea({ | |
element: d | |
}); | |
g.initialize(); | |
k = new Spotify.Web.Dialog({ | |
element: f | |
}); | |
k.initialize(); | |
b.subscribe(Spotify.Web.PublisherMessages.ERROR, this) | |
}; | |
this.onNotify = function(b) { | |
var b = b.message, | |
c = Spotify.Web.ErrorTypes, | |
d = Spotify.Web.ErrorMessages; | |
switch (b.type) { | |
case c.TRACK_NOT_PLAYABLE: | |
switch (b.response) { | |
case "Rate limit reached": | |
c = _("Sorry, but you've reached your track limit."); | |
break; | |
case "Song only on storage": | |
c = _("Sorry, but this track is not yet available."); | |
break; | |
case "Track restricted": | |
c = _("Sorry, but this track is not yet available in your country."); | |
break; | |
default: | |
c = _("Track is currently not available") | |
} | |
g.show({ | |
message: c, | |
id: b.type + "_" + b.trackUri, | |
timeout: j | |
}); | |
break; | |
case c.TRACK_NOT_PLAYABLE_TRACK_CAP: | |
g.show({ | |
message: _("You've reached the limit of how many times you can listen to this track. This means you won't be able to play this track from our catalogue unless you {{LINK_START}}upgrade{{LINK_END}} your Spotify account.", { | |
LINK_START: '<a href="/redirect/www/account-page/" target="_blank">', | |
LINK_END: "</a>" | |
}), | |
id: b.type, | |
timeout: j + 2E4 | |
}); | |
break; | |
case c.TRACK_NOT_PLAYABLE_TIME_CAP: | |
c = "You've used all your free hours for this week. This means you won't be able to play music from our catalogue until next week unless you {{LINK_START}}upgrade{{LINK_END}} your Spotify account."; | |
a.isAnonymous() ? a.limitedFeatureCalled("time_cap") : g.show({ | |
message: _(c, { | |
LINK_START: '<a href="/redirect/www/account-page/" target="_blank">', | |
LINK_END: "</a>" | |
}), | |
id: b.type, | |
timeout: j + 2E4 | |
}); | |
break; | |
case c.WAIT_FOR_COMMERCIAL_TO_FINISH: | |
c = _("This song will be played after this commercial"); | |
g.show({ | |
message: c, | |
id: b.type, | |
timeout: j | |
}); | |
break; | |
case c.SESSION_LOST: | |
k.show(d.SESSION_LOST); | |
break; | |
case c.TOKEN_LOST: | |
c = _("Spotify has been paused because your account is in use somewhere else."); | |
g.show({ | |
message: c, | |
id: "token_lost", | |
timeout: j | |
}); | |
break; | |
case c.AD_BLOCK_DETECTED: | |
c = _("For the best Spotify experience, please disable adblock."); | |
g.show({ | |
message: c, | |
id: "adblocker_detected", | |
timeout: j + 1E4 | |
}); | |
break; | |
case c.BOOKMARK: | |
c = _("<strong>Drag this button to your Bookmarks Bar</strong> for an easy way to get back to the Spotify Web Player:"); | |
c += '<a id="bookmark-btn" href="https://play.spotify.com/?utm_source=web-player&utm_campaign=bookmark" onclick="return false;">' + _("Spotify Web Player") + "</a>"; | |
g.show({ | |
message: c, | |
id: "bookmark_notification", | |
timeout: j + 2E4, | |
width: 370 | |
}); | |
break; | |
case c.CANNOT_CONNECT_TO_STREAMING_SERVER: | |
c = _("Sorry, but it seems that we cannot stream music to you at this time. This is probably because of restrictions placed on your network, but we are working on ways to get around this"); | |
g.show({ | |
message: c, | |
id: "cannot_connect_to_streaming_service", | |
timeout: j + 2E4 | |
}); | |
break; | |
case c.NO_SOUND_CAPABILITIES: | |
k.show(d.NO_SOUND_CAPABILITIES); | |
break; | |
case c.FLASH_NOT_AVAILABLE: | |
k.show(d.FLASH_NOT_AVAILABLE); | |
break; | |
case c.APPLICATION_RELOAD_NEEDED: | |
k.show(d.APPLICATION_RELOAD_NEEDED); | |
break; | |
case c.CONNECTION_LOST: | |
b = b.reason; | |
switch (b) { | |
case "Invalid user": | |
b = _("ap/error/invalid_user") + "<br/><br/>"; | |
break; | |
case "Region mismatch": | |
b = _("ap/error/region_mismatch", { | |
ACCOUNT_URL: "/redirect/www/account-page/", | |
UPGRADE_URL: "/redirect/www/upgrade-product/" | |
}) + "<br/><br/>" | |
} | |
b = { | |
message: _("Can't connect to Spotify. {{REASON}}Trying again now{{LOADER}}", { | |
LOADER: '...<br /><span class="indicator"></span>', | |
REASON: b | |
}), | |
className: "indicator" | |
}; | |
k.show(b); | |
break; | |
case c.CONNECTING: | |
k.show(d.CONNECTING); | |
break; | |
case c.FB_CONNECTING_TO: | |
k.show(d.FB_CONNECTING_TO); | |
break; | |
case c.FB_CONNECTION_FAILED: | |
k.hide(); | |
k.show(d.FB_CONNECTION_FAILED); | |
break; | |
case c.CONNECTION_RESTORED: | |
k.hide(); | |
break; | |
default: | |
g.hide(b.type) | |
} | |
} | |
}; | |
Spotify.Web.FeatureDetect = new function() { | |
return { | |
testWebSockets: function() { | |
return window.WebSocket | |
}, | |
testHTML5Audio: function() { | |
var c = document.createElement("audio"); | |
return !(!c.canPlayType || !c.canPlayType("audio/mpeg;").replace(/no/, "")) | |
}, | |
getFlashVersion: function() { | |
return swfobject.getFlashPlayerVersion() | |
}, | |
hasFlashMin: function() { | |
return swfobject.hasFlashPlayerVersion("9") | |
}, | |
adBlockCheck: function() { | |
var c = document.getElementById("ads"); | |
if (c) { | |
if (c.offsetHeight === 0) return !0 | |
} else return !0; | |
document.body.removeChild(c); | |
return !1 | |
} | |
} | |
}; | |
Spotify.Web.Menu = function(c, a, b) { | |
Spotify.Web.EventTarget.call(this); | |
var d = this, | |
c = c || {}, | |
f = c.publisher, | |
j = c.container, | |
g = c.features || {}, | |
k = [], | |
l = !1, | |
h = null, | |
m = null, | |
n = null, | |
e = null, | |
o = c.container.querySelector("#nav-items"), | |
t = j.ownerDocument, | |
C = c.cat ? "active" : "current", | |
v = function(a) { | |
a || (a = ""); | |
for (var c = 0; c < k.length; c++) b(k[c]).toggleClass(C, k[c].getAttribute("id") == "nav-" + a) | |
}, | |
z = function(a) { | |
a.onmousedown = function() { | |
if (l) { | |
var b = a.getAttribute("data-href"); | |
d.trigger("onAppOpen", { | |
id: b | |
}) | |
} | |
} | |
}, | |
w = function() { | |
l = !0; | |
for (var a = | |
0; a < k.length; a++) b(k[a]).removeClass("disabled") | |
}, | |
A = function(a) { | |
if (!m) return !1; | |
if (!e && a.image !== "") { | |
var d = new Image; | |
d.onload = function() { | |
c.cat || m.appendChild(this); | |
setTimeout(function() { | |
c.cat ? b(m).getElement(".media-image-internal").style.backgroundImage = "url(" + d.src + ")" : d.className = "show" | |
}, 10) | |
}; | |
e = a.image; | |
if (typeof e === "string") e = e.replace("http://profile.ak.fbcdn.net", "https://fbcdn-profile-a.akamaihd.net"), d.src = e | |
} | |
if (!n && a.name !== "") c.cat ? b(m).getElement(".name").innerHTML = a.name : m.textContent = a.name, | |
n = a.name; | |
n && e && (m.parentNode.className += " show") | |
}, | |
x = function(a, b, c, e, d) { | |
var h = t.createElement("a"), | |
f = t.createElement("span"); | |
f.className = "nav-text"; | |
h.setAttribute("data-href", b); | |
h.id = "nav-" + a; | |
b = d ? "" : " spoticon-" + a + "-32"; | |
a === "settings" && (b = " spoticon-" + a + "-16"); | |
a === "messages" && (b = " spoticon-inbox-32"); | |
h.className = "disabled" + b + (e ? "" : " standard-menu-item"); | |
f.innerHTML = c || ""; | |
h.appendChild(f); | |
k.push(h); | |
a = t.createElement("li"); | |
if (typeof e !== "undefined") a.className = e; | |
a.appendChild(h); | |
o.appendChild(a); | |
return a | |
}, | |
u = function() { | |
x("search", "suggest", _("Search")); | |
g.browse && x("browse", "browse", _("Browse")); | |
x("radio", "radio", _("Radio")); | |
g.collection ? x("collection", "collection", _("Your Music")) : x("playlist", "playlist", _("Playlists")); | |
a.onSignedIn(function() { | |
g.follow && x("follow", "follow", _("Follow")); | |
var a; | |
a = !c.cat ? _("Me") : '<div class="media simple user"> <div class="media-image"> <div class="media-placeholder"> <span class="icon"></span> </div> <div class="media-image-internal"></div> </div></div><div class="name">' + | |
_("Me") + "</div>"; | |
a = g.profile ? x("profile", "user", a, "item-profile etched-top", !0) : x("profile", "playlist", a, "item-profile etched-top", !0); | |
(g.messaging || g.notifications) && a.addClass("has-extra-bottom-row"); | |
g.messaging && (a = x("messages", "messages", null, "messages-link"), g.notifications || a.addClass("alone-item")); | |
g.notifications && (a = x("notifications", "notification-center", null, "item-notifications"), g.messaging || a.addClass("alone-item")) | |
}); | |
x("settings", "settings", null, "settings-link clearfix") | |
}, | |
y = function(a, | |
b) { | |
var e = o.querySelector(a); | |
if (e) | |
if (c.cat) e.textContent = b; | |
else { | |
var d = e.querySelector(".badge"); | |
if (!d) d = document.createElement("span"), d.className = "badge", e.appendChild(d); | |
b ? (d.textContent = b, d.addClass("badge-lit")) : d.removeClass("badge-lit") | |
} | |
}; | |
this.initialize = function() { | |
if (!f) throw Error("Publisher instance not specified."); | |
u(); | |
f.subscribe(Spotify.Web.PublisherMessages.APPLICATION_STATE_CHANGED, this); | |
f.subscribe(Spotify.Web.PublisherMessages.APPLICATION_ENABLED, this); | |
f.subscribe(Spotify.Web.PublisherMessages.SUGGEST_SHOWN, | |
this); | |
f.subscribe(Spotify.Web.PublisherMessages.SUGGEST_HIDDEN, this); | |
f.subscribe(Spotify.Web.PublisherMessages.NOTIFICATIONS_SHOWN, this); | |
f.subscribe(Spotify.Web.PublisherMessages.NOTIFICATIONS_HIDDEN, this); | |
f.subscribe(Spotify.Web.PublisherMessages.SOCIAL_DATA_SUCCESS, this); | |
f.subscribe(Spotify.Web.PublisherMessages.UNREAD_COUNT_CHANGE, this); | |
f.subscribe(Spotify.Web.PublisherMessages.UNREAD_NOTIFICATIONS_COUNT_CHANGE, this); | |
f.subscribe(Spotify.Web.PublisherMessages.APPLICATION_POST_MESSAGE, this); | |
for (var b = | |
0; b < k.length; b++) k[b].id === "nav-profile" && (m = k[b]), z(k[b]); | |
c.container.querySelector("#logo").addEventListener("click", function(a) { | |
a.preventDefault(); | |
d.trigger("onAppOpen", { | |
id: g.browse ? "browse" : "home" | |
}) | |
}); | |
this.bind("onAppOpen", function(b) { | |
b = b.params.id; | |
b === "settings" && a.isAnonymous() ? c.settingsView.toggleOpenClose() : c.router.openUri(Spotify.Link.fromString("spotify:app:" + b).toAppLink()) | |
}) | |
}; | |
this.highlightMenu = function(a) { | |
h = a; | |
v(a) | |
}; | |
this.onNotify = function(a) { | |
switch (a.messageType) { | |
case Spotify.Web.PublisherMessages.SUGGEST_SHOWN: | |
v("search"); | |
break; | |
case Spotify.Web.PublisherMessages.SUGGEST_HIDDEN: | |
v(h); | |
break; | |
case Spotify.Web.PublisherMessages.NOTIFICATIONS_SHOWN: | |
v("notifications"); | |
break; | |
case Spotify.Web.PublisherMessages.NOTIFICATIONS_HIDDEN: | |
v(h); | |
break; | |
case Spotify.Web.PublisherMessages.APPLICATION_ENABLED: | |
w(); | |
break; | |
case Spotify.Web.PublisherMessages.SOCIAL_DATA_SUCCESS: | |
A(a.message); | |
break; | |
case Spotify.Web.PublisherMessages.UNREAD_COUNT_CHANGE: | |
y("#nav-messages", a.message.count); | |
break; | |
case Spotify.Web.PublisherMessages.UNREAD_NOTIFICATIONS_COUNT_CHANGE: | |
y("#nav-notifications", | |
a.message.count) | |
} | |
}; | |
this.setUpgradeButton = function(a) { | |
if (typeof this._upgradeButton === "undefined") this._upgradeButton = document.createElement("a"), this._upgradeButton.className = "upgrade", c.container.querySelector(".item-profile").appendChild(this._upgradeButton); | |
this._upgradeButton.textContent = a; | |
this._upgradeButton.setAttribute("data-href", "purchase"); | |
this._upgradeButton.setAttribute("id", "nav-purchase"); | |
z(this._upgradeButton) | |
}; | |
this.disable = function() { | |
l = !1; | |
for (var a = 0; a < k.length; a++) b(k[a]).addClass("disabled") | |
}; | |
this.enable = function() { | |
w() | |
}; | |
this.getNavItemElements = function() { | |
return k | |
} | |
}; | |
Spotify.Web.Credentials = function(c, a) { | |
var b = this, | |
d = null, | |
f = 0; | |
this.cache = function(a, b) { | |
f = (new Date).getTime() + b * 1E3; | |
d = a | |
}; | |
this.get = function(j, g) { | |
var k = (new Date).getTime(); | |
d && f > k ? j(d) : (new Request({ | |
url: c, | |
method: "post", | |
onSuccess: function(a) { | |
var c = {}; | |
try { | |
c = JSON.parse(a) | |
} catch (d) {}!c.config || !c.config.credentials ? g() : (b.cache(c.config.credentials[0], c.config.credentials[1]), j(c.config.credentials[0])) | |
}, | |
onFailure: g, | |
onException: g | |
})).send("secret=" + a) | |
}; | |
this.dispose = function() { | |
f = 0; | |
d = null | |
} | |
}; | |
Spotify.Web.WebTracker = { | |
_config: {}, | |
setConfig: function(c) { | |
this._config = c | |
}, | |
log: function(c, a) { | |
if (typeof c == "object") { | |
postData = []; | |
for (var b in c) c.hasOwnProperty(b) && postData.push(encodeURIComponent(b) + "=" + encodeURIComponent(c[b])); | |
c = postData.join("&") | |
} | |
b = this.basic(this._config); | |
c = !c ? b : c + "&" + b; | |
b = new XMLHttpRequest; | |
b.open("POST", "/xhr/json/log.php", a || !0); | |
b.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); | |
b.send(c) | |
}, | |
basic: function(c) { | |
var a = []; | |
c.flow && a.push("f=" + c.flow); | |
c.source && a.push("s=" + | |
c.source); | |
c.landingURL && a.push("landingURL=" + c.landingURL); | |
c.referrer && a.push("referrer=" + c.referrer); | |
return a.join("&") | |
} | |
}; | |
Spotify.Web.Tracking = function(c, a, b, d) { | |
this.LIMIT_PER_TYPE = 5; | |
var f = {}, | |
j = !0; | |
window._gaq = window._gaq || []; | |
var g = this; | |
this.initialize = function(d) { | |
if (b.gaId) { | |
_gaq.push(["_setAccount", b.gaId]); | |
typeof d == "string" && _gaq.push(["_trackPageview", d]); | |
a.loadScript("//stats.g.doubleclick.net/dc.js"); | |
var d = c.subscribe, | |
f = Spotify.Web.PublisherMessages; | |
d(f.APPLICATION_STATE_PUSH, this); | |
d(f.ERROR, this); | |
d(f.CHROME_READY, this); | |
d(f.WINDOW_FOCUS, this) | |
} | |
}; | |
this.onNotify = function(a) { | |
var b = a.message, | |
c = Spotify.Web.PublisherMessages; | |
switch (a.messageType) { | |
case c.APPLICATION_STATE_PUSH: | |
this.pageView(b.url); | |
break; | |
case c.WINDOW_FOCUS: | |
this.event("Window", a.messageType, b.type, 0, !0); | |
break; | |
case c.CHROME_READY: | |
this.xhrLog(a.messageType); | |
break; | |
case c.ERROR: | |
this.errors(b) | |
} | |
}; | |
this.pageView = function(a) { | |
_gaq.push(["_trackPageview", a]); | |
!j && window.dataLayer && window.dataLayer.push({ | |
event: "page_view" | |
}); | |
j = !1 | |
}; | |
this.event = function(a, b, c, d, f) { | |
_gaq.push(["_trackEvent", a, b, c, d, f]) | |
}; | |
this.handleException = function(a, b, c, f, j) { | |
b = escape(b) + "/" + escape(f) + "/" + | |
j + "/" + d.getAddressBarUrl(); | |
g.event("exception", a, b, void 0, !0) | |
}; | |
this.xhrLog = function(a) { | |
if (typeof f[a] === "undefined") f[a] = 1; | |
else { | |
if (f[a] >= g.LIMIT_PER_TYPE) return; | |
f[a]++ | |
} | |
a = { | |
type: a, | |
t: (new Date).getTime() | |
}; | |
Spotify.Web.WebTracker.log(a) | |
}; | |
this.errors = function(a) { | |
var b = "", | |
c = "", | |
b = Spotify.Web.ErrorTypes, | |
d = a.type; | |
switch (d) { | |
case b.CONNECTING: | |
case b.CONNECTION_LOST: | |
case b.CONNECTION_RESTORED: | |
b = "ap"; | |
break; | |
case b.FLASH_NOT_AVAILABLE: | |
b = "browser"; | |
break; | |
case b.APPLICATION_RELOAD_NEEDED: | |
b = "server"; | |
break; | |
case b.TRACK_NOT_PLAYABLE: | |
case b.CANNOT_CONNECT_TO_STREAMING_SERVER: | |
b = | |
"playback"; | |
c = a.trackUri || ""; | |
break; | |
case b.FB_CONNECTING_TO: | |
case b.FB_CONNECTION_FAILED: | |
b = "fb"; | |
break; | |
default: | |
b = "general" | |
} | |
if (b === "ap") return !1; | |
c !== "" && (d += "/" + c); | |
this.event("error", b, d, void 0, !0) | |
} | |
}; | |
Spotify.Web.ConsoleLogger = function() { | |
this.enabled = !0; | |
this.fallbackToAlert = !1; | |
this.consoleUnavailable = typeof console === "undefined" || typeof console.log === "undefined" | |
}; | |
Spotify.Web.ConsoleLogger.prototype.log = function(c) { | |
this._writeOut("log", c) | |
}; | |
Spotify.Web.ConsoleLogger.prototype.dir = function(c) { | |
this._writeOut("dir", c) | |
}; | |
Spotify.Web.ConsoleLogger.prototype.warn = function(c) { | |
this._writeOut("warn", c) | |
}; | |
Spotify.Web.ConsoleLogger.prototype.error = function(c) { | |
this._writeOut("error", c) | |
}; | |
Spotify.Web.ConsoleLogger.prototype.info = function(c) { | |
this._writeOut("info", c) | |
}; | |
Spotify.Web.ConsoleLogger.prototype._writeOut = function(c, a) { | |
if (this.enabled) | |
if (!this.consoleUnavailable && console[c]) console[c](a); | |
else this.fallbackToAlert && alert(a) | |
}; | |
Spotify.Web.ClientEventLogger = function(c) { | |
this.log = function(a, b) { | |
b || (b = function() {}); | |
c.logging.logClientEvent({ | |
source: a.source, | |
appVersion: a.source_version, | |
appVendor: a.source_vendor, | |
args: ["", a.event, a.event_version || null, a.test_version || null, a.data] | |
}, b) | |
} | |
}; | |
Spotify.Web.AppLogger = function(c, a, b) { | |
this._apps = {}; | |
this._maxApps = 15; | |
this._sessionID = a; | |
this._router = b; | |
this._applicationReadyLogged = !1; | |
this._logToAp = function(a, b) { | |
var j = Array.prototype.slice.call(arguments); | |
typeof a === "undefined" || typeof b === "undefined" || c.log.apply(c, j) | |
}; | |
this._logElapsedTime = function(a, b) { | |
this._logToAp(244, 1, this._sessionID, a, b) | |
} | |
}; | |
Spotify.Web.AppLogger.prototype.loadingStart = function(c) { | |
var a = 0, | |
b = !1, | |
d; | |
for (d in this._apps) | |
if (this._apps.hasOwnProperty(d)) { | |
if (!b || this._apps[d].msStart < this._apps[b].msStart) b = d; | |
a++ | |
} | |
b && a > this._maxApps && delete this._apps[b]; | |
this._apps[c.uri] = { | |
msStart: c.start, | |
intent: 0 | |
} | |
}; | |
Spotify.Web.AppLogger.prototype.loadingTime = function(c) { | |
var a; | |
if (c.complete) this.completeLogging(c); | |
else { | |
a = this._apps[c.uri]; | |
if (!a || !a.msStart) return !1; | |
a.containerInit = c.start - a.msStart; | |
a.containerReady = c.end - a.msStart | |
} | |
}; | |
Spotify.Web.AppLogger.prototype.completeLogging = function(c) { | |
var a; | |
a = this._apps[c.uri]; | |
if (!a || !a.msStart) return delete this._apps[c.uri], !1; | |
a.appReady = c.complete - a.msStart; | |
this._logElapsedTime("stitch-startup/intent/" + c.uri, 0); | |
a.containerInit && this._logElapsedTime("stitch-startup/container-initialized/" + c.uri, a.containerInit); | |
a.containerReady && this._logElapsedTime("stitch-startup/container-ready/" + c.uri, a.containerReady); | |
if (a.appReady) { | |
var b = this._router.getInitialUrl(); | |
if (!this._applicationReadyLogged && | |
b && window.spperformance && c.uri === b.toURI()) this._applicationReadyLogged = !0, window.spperformance.authenticated && (b = (new Date).getTime() - window.spperformance.page_received, this._logElapsedTime("web-player/application-ready/" + c.uri, b)); | |
this._logElapsedTime("stitch-startup/app-ready/" + c.uri, a.appReady) | |
} | |
delete this._apps[c.uri] | |
}; | |
Spotify.Web.Services = function(c, a) { | |
var b, d, f, j = [], | |
g = [], | |
k = !1, | |
l = !1, | |
h = function(a) { | |
j ? (j.push(a), k || (k = !0, o())) : a(d) | |
}, | |
m = function(a) { | |
g ? (g.push(a), l || (l = !0, t())) : a(f) | |
}, | |
n = function(a) { | |
d = a; | |
for (var b = 0, c = j.length; b < c; b++) j[b](a); | |
j = null | |
}, | |
e = function(a) { | |
f = a; | |
for (var b = 0, c = g.length; b < c; b++) g[b](a); | |
g = null | |
}, | |
o = function() { | |
c.hermes.load_schema("message ListRequest {\n optional int32 limit = 1;\n optional string lastId = 2; \n optional int64 lastTimestamp = 3;}\nmessage DirectMessage {\n optional string id = 1;\n optional int64 timestamp = 2;\n optional string text = 3;\n optional string attachment = 4;\n optional string sender = 5;\n}\nmessage Conversation {\n optional string id = 1;\n optional bool read = 2;\n repeated string users = 3;\n optional DirectMessage preview = 4;\n optional string readUntil = 5;\n}\nmessage ConversationList {\n optional int32 unread = 1;\n optional int32 total = 2;\n repeated Conversation threads = 3;\n}\nenum EventType {\n UNKNOWN = 0;\n NEW_MESSAGE = 1;\n READ_CONVERSATION = 2;\n UNREAD_COUNT_CHANGE = 3;\n}\nmessage MessagingEvent {\n optional EventType type = 1;\n optional NewMessageEvent newMessage = 2;\n optional ReadConversationEvent readConversation = 3;\n optional UnreadCountChangeEvent unreadCountChange = 4;\n}\nmessage NewMessageEvent {\n optional Conversation conversation = 1;\n optional bool wasRead = 2;\n}\nmessage ReadConversationEvent {\n optional string user = 1;\n optional string conversationId = 2;\n optional string messageId = 3;\n}\nmessage UnreadCountChangeEvent {\n optional int32 delta = 1;\n optional int32 total = 2;\n}", | |
n) | |
}, | |
t = function() { | |
c.hermes.load_schema("enum SocialReactionType {\n UNKNOWN_SOCIAL_REACTION = 0;\n LIKED_SOCIAL_REACTION = 1;\n STREAMED_SOCIAL_REACTION = 2;\n RESHARED_SOCIAL_REACTION = 3;\n}\nenum BouncerStoryType {\n FOLLOWED_PROFILE_BOUNCER_STORY = 0;\n PUBLISHED_PLAYLIST_BOUNCER_STORY = 1;\n FOLLOWED_PLAYLIST_BOUNCER_STORY = 2;\n SHARED_URI_BOUNCER_STORY = 3;\n}\nmessage SocialReactionObject {\n optional SocialReactionType reaction = 1;\n optional string story_creator = 2;\n optional string story_id = 3;\n optional BouncerStoryType story_type = 4;\n optional string item_uri = 5;\n optional int64 reaction_time_ms = 6;\n}\nenum AppType {\n TYPE_UNKNOWN_APP = 0;\n TYPE_IOS_APP = 1;\n TYPE_ANDROID_APP = 2;\n TYPE_LINK_APP = 3;\n TYPE_MFT_LAUNCH = 4;\n TYPE_MFT_REMINDER = 5;\n TYPE_MFT_SEASON = 6;\n}\nmessage User {\n optional string canonical_username = 1;\n optional string real_name = 2;\n}\nmessage PlaylistSubObject {\n optional string uri = 1;\n optional User owner = 2;\n optional User profile_user = 4;\n}\nmessage TrackAddObject {\n optional int32 track_count = 1;\n optional string uri = 2;\n repeated string track_uri = 3;\n}\nmessage AlbumReleaseObject {\n optional string album_gid = 1;\n optional string artist_gid = 2;\n optional string album_name = 3;\n optional string artist_name = 4;\n optional string track_gid = 5;\n optional string track_name = 6;\n optional bool exclusive = 7;\n}\nmessage ApplicationReleaseObject {\n optional AppType app = 1;\n optional string uri = 2;\n optional string image_url = 3;\n optional bool new_app = 4;\n}\nmessage MessagePlayedObject {\n optional string thread_id = 1;\n optional string message_id = 2;\n optional string attachment_uri = 3;\n optional User user = 4;\n}\nmessage InClientNotificationData {\n optional int32 version = 1;\n optional NotificationState state = 2;\n repeated User subject = 4;\n optional int32 subject_total = 5;\n optional string notification_verb = 6;\n repeated PlaylistSubObject playlist_sub_object = 8;\n repeated TrackAddObject track_add_object = 10;\n repeated AlbumReleaseObject album_release_object = 11;\n repeated ApplicationReleaseObject application_release_object=12;\n repeated SocialReactionObject social_reaction_object = 13;\n repeated MessagePlayedObject message_played_object = 14;\n}\nenum NotificationType {\n TYPE_UNKNOWN_NOTIFICATION = 0;\n TYPE_RESET_NOTIFICATION = 1;\n TYPE_IN_CLIENT_NOTIFICATION = 5;\n}\nmessage Notification {\n optional int32 version = 1;\n optional NotificationType type = 2;\n optional InClientNotificationData in_client_data = 5;\n optional bool dry = 7;\n}\nmessage NotificationState {\n optional bool seen = 2;\n optional bool dismissed = 3;\n optional bool followed_through = 4;\n optional string notification_id_hex = 5;\n optional string state_id_hex = 6;\n optional int64 notification_id_ms = 10;\n optional int64 state_id_ms = 11;\n}\nmessage NotificationList {\n repeated Notification notification = 1;\n}\nmessage NotificationStateList {\n repeated NotificationState state = 1;\n}\nmessage NotificationCounts {\n optional int32 version = 1;\n optional int32 active = 2;\n}\n", | |
e) | |
}; | |
this.getAlbumForTrack = function(a, b) { | |
c.request("track_metadata", [a], function(a, c) { | |
a ? b(null) : b(c.album.uri) | |
}) | |
}; | |
this.getTrackIndexInAlbum = function(a, b, e) { | |
var d = "spotify:track:" + b; | |
c.request("album_tracks_snapshot", [{ | |
type: "list", | |
uri: a | |
}, 0, -1], function(a, b) { | |
a ? e(-1) : e(b.array.indexOf(d)) | |
}) | |
}; | |
this.getTrackIndexInPlaylist = function(a, b, e) { | |
var d = [], | |
h, f = 0, | |
g = function(a, j, k) { | |
c.request("playlist_tracks_snapshot", [{ | |
type: "list", | |
uri: a | |
}, j, k], function(c, j) { | |
c ? e(-1) : (d = d.concat(j.array), h = d.indexOf("spotify:track:" + | |
b), h !== -1 ? (e(h), d = null) : (f += j.array.length, f >= j.length ? e(0) : g(a, f, -1))) | |
}) | |
}; | |
g(a, 0, -1) | |
}; | |
o(); | |
t(); | |
this.getUnreadThreadsCount = function(a) { | |
c.hermes.request("hm://messaging/threads", "GET", [{ | |
limit: 0 | |
}], ["ListRequest"], ["ConversationList"], "message ListRequest {\n optional int32 limit = 1;\n optional string lastId = 2; \n optional int64 lastTimestamp = 3;}\nmessage DirectMessage {\n optional string id = 1;\n optional int64 timestamp = 2;\n optional string text = 3;\n optional string attachment = 4;\n optional string sender = 5;\n}\nmessage Conversation {\n optional string id = 1;\n optional bool read = 2;\n repeated string users = 3;\n optional DirectMessage preview = 4;\n optional string readUntil = 5;\n}\nmessage ConversationList {\n optional int32 unread = 1;\n optional int32 total = 2;\n repeated Conversation threads = 3;\n}\nenum EventType {\n UNKNOWN = 0;\n NEW_MESSAGE = 1;\n READ_CONVERSATION = 2;\n UNREAD_COUNT_CHANGE = 3;\n}\nmessage MessagingEvent {\n optional EventType type = 1;\n optional NewMessageEvent newMessage = 2;\n optional ReadConversationEvent readConversation = 3;\n optional UnreadCountChangeEvent unreadCountChange = 4;\n}\nmessage NewMessageEvent {\n optional Conversation conversation = 1;\n optional bool wasRead = 2;\n}\nmessage ReadConversationEvent {\n optional string user = 1;\n optional string conversationId = 2;\n optional string messageId = 3;\n}\nmessage UnreadCountChangeEvent {\n optional int32 delta = 1;\n optional int32 total = 2;\n}", | |
function(b, c) { | |
b ? a(null) : c.result ? a(c.result[0].unread) : a(null) | |
}) | |
}; | |
this.onMessagingUnreadCountChange = function(a) { | |
var b = this, | |
c = 0; | |
this.getUnreadThreadsCount(function(e) { | |
c = e; | |
a(c); | |
b.subscribeMessagingEvents(function(b, e) { | |
var d = e[0]; | |
if (d.type == "UNREAD_COUNT_CHANGE") { | |
d = d.unreadCountChange; | |
if ("total" in d) c = d.total; | |
"delta" in d && (c += d.delta); | |
a(c) | |
} | |
}) | |
}) | |
}; | |
this.subscribeMessagingEvents = function(b) { | |
this.getUsername(function(c) { | |
var d = encodeURIComponent(c); | |
h(function(c) { | |
a.subscribe("hm://messaging/user/" + d, [], [], [c + "#MessagingEvent"], function() {}, function() {}, b, null) | |
}) | |
}) | |
}; | |
this.getUnreadNotificationsCount = function(a) { | |
this.getUsername(function(b) { | |
b = "hm://inclient-notifications/feed/" + encodeURIComponent(b + ":inclient") + "/counts"; | |
c.hermes.request(b, "GET", [], [], ["NotificationCounts"], "enum SocialReactionType {\n UNKNOWN_SOCIAL_REACTION = 0;\n LIKED_SOCIAL_REACTION = 1;\n STREAMED_SOCIAL_REACTION = 2;\n RESHARED_SOCIAL_REACTION = 3;\n}\nenum BouncerStoryType {\n FOLLOWED_PROFILE_BOUNCER_STORY = 0;\n PUBLISHED_PLAYLIST_BOUNCER_STORY = 1;\n FOLLOWED_PLAYLIST_BOUNCER_STORY = 2;\n SHARED_URI_BOUNCER_STORY = 3;\n}\nmessage SocialReactionObject {\n optional SocialReactionType reaction = 1;\n optional string story_creator = 2;\n optional string story_id = 3;\n optional BouncerStoryType story_type = 4;\n optional string item_uri = 5;\n optional int64 reaction_time_ms = 6;\n}\nenum AppType {\n TYPE_UNKNOWN_APP = 0;\n TYPE_IOS_APP = 1;\n TYPE_ANDROID_APP = 2;\n TYPE_LINK_APP = 3;\n TYPE_MFT_LAUNCH = 4;\n TYPE_MFT_REMINDER = 5;\n TYPE_MFT_SEASON = 6;\n}\nmessage User {\n optional string canonical_username = 1;\n optional string real_name = 2;\n}\nmessage PlaylistSubObject {\n optional string uri = 1;\n optional User owner = 2;\n optional User profile_user = 4;\n}\nmessage TrackAddObject {\n optional int32 track_count = 1;\n optional string uri = 2;\n repeated string track_uri = 3;\n}\nmessage AlbumReleaseObject {\n optional string album_gid = 1;\n optional string artist_gid = 2;\n optional string album_name = 3;\n optional string artist_name = 4;\n optional string track_gid = 5;\n optional string track_name = 6;\n optional bool exclusive = 7;\n}\nmessage ApplicationReleaseObject {\n optional AppType app = 1;\n optional string uri = 2;\n optional string image_url = 3;\n optional bool new_app = 4;\n}\nmessage MessagePlayedObject {\n optional string thread_id = 1;\n optional string message_id = 2;\n optional string attachment_uri = 3;\n optional User user = 4;\n}\nmessage InClientNotificationData {\n optional int32 version = 1;\n optional NotificationState state = 2;\n repeated User subject = 4;\n optional int32 subject_total = 5;\n optional string notification_verb = 6;\n repeated PlaylistSubObject playlist_sub_object = 8;\n repeated TrackAddObject track_add_object = 10;\n repeated AlbumReleaseObject album_release_object = 11;\n repeated ApplicationReleaseObject application_release_object=12;\n repeated SocialReactionObject social_reaction_object = 13;\n repeated MessagePlayedObject message_played_object = 14;\n}\nenum NotificationType {\n TYPE_UNKNOWN_NOTIFICATION = 0;\n TYPE_RESET_NOTIFICATION = 1;\n TYPE_IN_CLIENT_NOTIFICATION = 5;\n}\nmessage Notification {\n optional int32 version = 1;\n optional NotificationType type = 2;\n optional InClientNotificationData in_client_data = 5;\n optional bool dry = 7;\n}\nmessage NotificationState {\n optional bool seen = 2;\n optional bool dismissed = 3;\n optional bool followed_through = 4;\n optional string notification_id_hex = 5;\n optional string state_id_hex = 6;\n optional int64 notification_id_ms = 10;\n optional int64 state_id_ms = 11;\n}\nmessage NotificationList {\n repeated Notification notification = 1;\n}\nmessage NotificationStateList {\n repeated NotificationState state = 1;\n}\nmessage NotificationCounts {\n optional int32 version = 1;\n optional int32 active = 2;\n}\n", | |
function(b, c) { | |
b || !c.result ? a(null) : a(c.result[0].active) | |
}) | |
}) | |
}; | |
this.onNotificationsUnreadCountChange = function(a) { | |
var b = 0; | |
this.getUnreadNotificationsCount(function(c) { | |
b = c; | |
a(b); | |
this.subscribeNotificationEvents(function(c, d) { | |
var e = d[0]; | |
e.type == "TYPE_IN_CLIENT_NOTIFICATION" ? (b++, a(b)) : e.type === "TYPE_RESET_NOTIFICATION" && (b = 0, a(b)) | |
}) | |
}.bind(this)) | |
}; | |
this.subscribeNotificationEvents = function(b) { | |
this.getUsername(function(c) { | |
var d = "hm://inclient-notifications/feed/" + encodeURIComponent(c + ":inclient") + "/"; | |
m(function(c) { | |
a.subscribe(d, [], [], [c + "#Notification"], function() {}, function() {}, b, null) | |
}) | |
}) | |
}; | |
this.getUsername = function(a) { | |
b ? a(b) : this.getUserInfo(function(c) { | |
if (c) b = c._username, a(b) | |
}) | |
}; | |
this.getUserInfo = function(a) { | |
c.request("session_query", [], function(b, c) { | |
b ? a(null) : a(c) | |
}) | |
}; | |
this.getSocialDataForCurrentUser = function(a) { | |
var b = this; | |
this.getUsername(function(c) { | |
c ? b.getSocialDataForUser("spotify:user:" + c, a) : a(null) | |
}) | |
}; | |
this.getSocialDataForUser = function(a, b) { | |
c.request("user_metadata", [a], function(a, c) { | |
b(a || c) | |
}) | |
}; | |
this.isOwnPlaylist = | |
function(a, b) { | |
var d = this, | |
e = a.toURI().replace("app:", ""); | |
c.request("playlist_metadata", [e], function(a, c) { | |
a ? b(!1) : c.subscribed ? b(!0) : d.getUsername(function(a) { | |
b(c.owner.uri === "spotify:user:" + a) | |
}) | |
}) | |
}; | |
this.canPublishPlaylist = function(a, b) { | |
var d = a.toURI().replace("app:", ""); | |
c.request("playlist_metadata", [d], function(a, c) { | |
a ? b(a) : b(null, !(c.collaborative || c.ownedByCurrentUser && !c.published)) | |
}) | |
}; | |
this.isSubscribedPlaylist = function(a, b) { | |
var d = a.toURI().replace("app:", ""); | |
c.request("playlist_metadata", [d], function(a, | |
c) { | |
a ? b(!1) : b(c.subscribed) | |
}) | |
}; | |
this.getFacebookUserId = function(a) { | |
this.getUsername(function(b) { | |
b ? c.hermes.request("hm://username/splookup", "GET", [{ | |
usernames: [b] | |
}], ["UserRequest"], ["UserIdentifier"], "message UserRequest {\n repeated string usernames = 1;\n}\nmessage UserIdentifier {\n optional string username = 1;\n optional string facebook_uid = 2;\n optional bool deleted = 3 [default = false];\n}", function(b, c) { | |
b ? a(null) : c.result ? c.result[0] && a(c.result[0].facebook_uid || null) : a(null) | |
}) : a(null) | |
}) | |
}; | |
this.getArtistMetadata = function(a, b) { | |
c.request("artist_metadata", [a], function(a, c) { | |
a ? b(!1) : b(c) | |
}) | |
} | |
}; | |
Spotify.Web.AutoPlay = function(c, a, b, d) { | |
var f = [new Spotify.Web.FacebookURLSchema, new Spotify.Web.OpenURLSchema], | |
j = function(a, b, d, f, g, e) { | |
f = typeof f !== "function" ? function() {} : f; | |
g = typeof g !== "function" ? function() {} : g; | |
d === void 0 && (d = -1); | |
a ? c.player.play_context_as_app(a, b, d, 0, e, function(a, b) { | |
a ? g(b) : f(b) | |
}) : c.player.play_context(b, d, 0, function(a, b) { | |
a ? g(b) : f(b) | |
}) | |
}, | |
g = function(a, b, d, f) { | |
d = typeof d !== "function" ? function() {} : d; | |
f = typeof f !== "function" ? function() {} : f; | |
a ? c.player.play_track_as_app(a, b, 0, function(a, | |
b) { | |
a ? f(b) : d(b) | |
}) : c.player.play_track(b, 0, function(a, b) { | |
a ? f(b) : d(b) | |
}) | |
}; | |
this.shouldPlay = function(a) { | |
for (var b = !1, c = 0; c < f.length; c++) | |
if (f[c].shouldPlay(a)) { | |
b = !0; | |
break | |
} | |
return b | |
}; | |
this.play = function(a, b, c, d, f) { | |
return this.playAsApp(null, a, b, c, d, f) | |
}.bind(this); | |
this.playAsApp = function(a, f, h, m, n, e) { | |
var o, t; | |
try { | |
o = b.fromString(f), t = o.toURI() | |
} catch (C) { | |
return null | |
} | |
switch (o.type) { | |
case "track": | |
d.getAlbumForTrack(t, function(b) { | |
var c = t.split(":")[2]; | |
d.getTrackIndexInAlbum(b, c, function(c) { | |
j(a, b, c, m, n, e) | |
}, n) | |
}, n); | |
break; | |
case "playlist": | |
h ? d.getTrackIndexInPlaylist(t, h, function(b) { | |
j(a, t, b, m, n, e) | |
}) : j(a, t, void 0, m, n, e); | |
break; | |
case "album": | |
h ? d.getTrackIndexInAlbum(t, h, function(b) { | |
j(a, t, b, m, n, e) | |
}) : j(a, t, void 0, m, n, e); | |
break; | |
case "artist": | |
j(a, t + ":top:tracks", void 0, m, n, e); | |
break; | |
case "artist-toplist": | |
j(a, t, void 0, m, n, e); | |
break; | |
case "ad": | |
g(a, t, m, n); | |
break; | |
case "trackset": | |
if (h) | |
for (var h = Spotify.Utils.Base62.toHex(h, 32), f = 0, v = o.tracks.length; f < v; f++) | |
if (h == o.tracks[f].id) { | |
o.index = f; | |
break | |
} | |
a ? c.player.play_context_as_app(a, t, o.index, | |
0, e, | |
function(a, b) { | |
a ? n(b) : m(b) | |
}) : c.player.play_context(t, o.index, 0, function(a, b) { | |
a ? n(b) : m(b) | |
}) | |
} | |
}; | |
this.pause = function() { | |
c.request("player_pause", ["main"], function() {}) | |
}; | |
this.resume = function() { | |
c.request("player_play", ["main"], function() {}) | |
}; | |
this.playUrl = function(a, b, c) { | |
for (var d = 0; d < f.length; d++) | |
if (f[d].playUrl(a, this.play, b, c)) break | |
}; | |
this.enableRepeatMode = function() { | |
c.request("player_set_repeat", ["main", !0], function() {}) | |
}; | |
this.getUrl = function(a, b) { | |
for (var c, g = 0; g < f.length; g++) | |
if (c = f[g].getUrl(a), f[g].shouldPlay(a)) break; | |
(g = Spotify.Web.Utils.decodeOpenGraphUrl(c)) && g.context === "track" ? d.getAlbumForTrack("spotify:track:" + g.contextId, function(a) { | |
var a = a.replace("spotify:album:", ""), | |
d = Spotify.Web.URLParser.parseURL(c); | |
b(d.protocol + "://" + d.domain + "/album/" + a) | |
}) : b(c) | |
} | |
}; | |
Spotify.Web.Exceptions = function() { | |
Spotify.Web.EventTarget.call(this); | |
var c = this, | |
a = function(a, d, f, j, g) { | |
c.trigger(Spotify.Web.ErrorTypes.UNCAUGHT_EXCEPTION, { | |
module: a, | |
message: d + (f ? " " + f : ""), | |
url: j, | |
lineNumber: g | |
}) | |
}; | |
this.bindWindow = function(b, d) { | |
var f; | |
typeof b.onerror === "function" && c.bind("INTERNAL_ONERROR", c._wrapOnErrorCallback(b.onerror)); | |
f = b.onerror = function(a, b, d) { | |
c.trigger("INTERNAL_ONERROR", arguments) | |
}; | |
try { | |
Object.defineProperty(b, "onerror", { | |
get: function() { | |
return f | |
}, | |
set: function(a) { | |
c.bind("INTERNAL_ONERROR", | |
c._wrapOnErrorCallback(a)) | |
} | |
}) | |
} catch (j) {} | |
b.onerror = function(b, c, f) { | |
c = c || History.getPageUrl(); | |
c = Spotify.Web.URLParser.parseURL(c).path; | |
a(d, b, "", c, f) | |
} | |
}; | |
this.restoreOnErrorHandlers = function(a) { | |
try { | |
Object.defineProperty(a, "onerror", { | |
value: null | |
}) | |
} catch (c) {} | |
}; | |
this.logError = function(b, c, f) { | |
a(b, c, f, "", "") | |
}; | |
this._wrapOnErrorCallback = function(a) { | |
return function(c) { | |
try { | |
a.apply(window, c.params) | |
} catch (f) {} | |
} | |
} | |
}; | |
Spotify.Web.Router = function(c, a, b, d) { | |
Spotify.Web.EventTarget.call(this); | |
var f = this, | |
j = !0, | |
g, k, l = "browse,collection,discover,follow,messages,playlists,profile,radio,settings,social-feed,home".split(","); | |
this.EVENT_TRACK_URI_ROUTED = "TRACK_URI_ROUTED"; | |
this.setServices = function(a) { | |
g = a | |
}; | |
this.getInitialUrl = function() { | |
return k | |
}; | |
this._isBrandedProfileArgumentBlacklisted = function(b) { | |
return a.apps.blacklisted_branded_profile_args.indexOf(b) != -1 | |
}; | |
this._mapBrandedProfileAppLinkToUserLink = function(b) { | |
var c = a.apps.user_to_app; | |
if (c !== void 0 && b.type == "application") { | |
var d = {}, | |
e; | |
for (e in c) c.hasOwnProperty(e) && typeof d[c[e]] === "undefined" && (d[c[e]] = e); | |
c = d[b.id]; | |
if (typeof c !== "undefined" && !this._isBrandedProfileArgumentBlacklisted(b.args[0])) return d = Spotify.Link.fromString(b.toURI()), d.id = "user", d.args = b.args && b.args.length > 0 ? [c].concat(b.args) : [c], d | |
} | |
}; | |
this._mapBrandedProfileUsernameToAppName = function(b) { | |
var c = a.apps.user_to_app; | |
if (c !== void 0) return b = c[b], b === void 0 ? void 0 : b | |
}; | |
this._isBrandProfilesDeeplink = function(a) { | |
var b = !1; | |
a && a.type == Spotify.Link.Type.APPLICATION && a.id == "user" && (a.args.length == 1 ? b = !0 : a.args.length > 1 && (b = !this._isBrandedProfileArgumentBlacklisted(a.args[1]))); | |
return b | |
}; | |
this.openUri = function(d, l, k) { | |
j || b.notify(Spotify.Web.PublisherMessages.USER_INTERACTION); | |
var e = d.toURI(), | |
o = this._mapBrandedProfileAppLinkToUserLink(d); | |
o ? d = o : d.type == Spotify.Link.Type.APPLICATION && d.id == "user" && this._mapBrandedProfileUsernameToAppName(d.args[0]) && (this._isBrandedProfileArgumentBlacklisted(d.args[1]) || (k = !1)); | |
if (e.indexOf("%40") !== | |
-1 && e.indexOf("spotify:app:search") !== 0) g.getUsername(function(a) { | |
if ("username" in d) d.username = a; | |
else if (d.type === Spotify.Link.Type.APPLICATION) | |
for (var b = 0; b < d.args.length; b++) d.args[b] = d.args[b].replace("@", a); | |
f.openUri(d, l, k) | |
}); | |
else if (d.type !== "application" && (d = d.toAppLink()), d.id === "user" && d.args[0] === "tunigo" && (d.args[0] = "spotify"), d.id === "home" && (d = Spotify.Link.fromString("spotify:app:browse").toAppLink(), k = !0), a.features && a.features.collection && d.id === "playlist" ? d = Spotify.Link.fromString("spotify:app:collection:playlists").toAppLink() : | |
(!a.features || !a.features.collection) && d.id === "collection" && d.args[0] === "playlists" && (d = Spotify.Link.fromString("spotify:app:playlist").toAppLink()), k = k || !1, l = l || "", d.type === "application" && d.id === "track") e = Spotify.Link.fromString("spotify:track:" + d.args[0]), this.trigger(this.EVENT_TRACK_URI_ROUTED, { | |
link: e | |
}), g.getAlbumForTrack(e.toURI(), function(a) { | |
a = Spotify.Link.fromString(a).toAppLink(); | |
c.openUri(a, l, k) | |
}, function() {}); | |
else { | |
var e = {}, | |
o = this._isBrandProfilesDeeplink(c.getCurrentLink()) ? 1 : 0, | |
t = this._isBrandProfilesDeeplink(d) ? | |
1 : 0; | |
if ((o ^ t) == 1) e.forceOpen = !0; | |
c.openUri(d, l, k, e) | |
} | |
}; | |
this.getAppUrl = function(a) { | |
a.charAt(0) === "/" && (a = a.substr(1, a.length - 1)); | |
var a = a.split("/"), | |
b = a[0]; | |
if (b == "user" && a.length > 1) { | |
var c = f._mapBrandedProfileUsernameToAppName(a[1]); | |
c && !f._isBrandedProfileArgumentBlacklisted(a[2]) && (b = c, a.splice(0, 3)) | |
} | |
b === "user" && (b = "profile"); | |
if (b === "profile" && (a[2] === "playlist" || a[2] === "starred" || a[2] === "toplist")) b = "playlist"; | |
if (b === "collection" && a[1] === "album" && a[2] || a[0] === "user" && a[2] === "collection" && a[3] === "album" && | |
a[4]) b = "collection-album"; | |
if (b === "collection" && a[1] === "artist" && a[2] || a[0] === "user" && a[2] === "collection" && a[3] === "artist" && a[4]) b = "collection-artist"; | |
return d.getAppURL(b) | |
}; | |
this.openInitialUrl = function(b) { | |
b = Spotify.Web.Utils.openGraphUrlToSpotifyUri(b); | |
b === "" && (b = a.features && a.features.browseAsStartPage ? "spotify:app:browse" : "spotify:app:browse"); | |
b = Spotify.Link.fromString(b).toAppLink(); | |
if (a.developer || l.indexOf(b.id) === -1 && !(a.features && a.features.collection && b.id === "playlist")) a.features && a.features.browseAsStartPage ? | |
this.openUri(Spotify.Link.fromString("spotify:app:browse").toAppLink(), "", !1) : this.openUri(Spotify.Link.fromString("spotify:app:browse").toAppLink(), "", !1); | |
f.openUri(b, "", !1); | |
j = !1; | |
k = b | |
} | |
}; | |
Spotify.Web.Router.History = function(c, a) { | |
Spotify.Web.EventTarget.call(this); | |
var b = ["play", "ap", "websockets"], | |
d = this, | |
f = this, | |
j = 0, | |
g = 0, | |
k = function() { | |
var b = a.getState(); | |
d.trigger("pageChange", { | |
url: b.url | |
}); | |
if (g > 0) g -= 1; | |
else { | |
var h = b.data.index, | |
b = 0, | |
k = "undo"; | |
h > j ? (b = h - j, k = "redo") : h < j && (b = -(j - h)); | |
j = h; | |
for (h = 0; h < Math.abs(b); h += 1) k === "undo" ? (c.undo(), f && f.event("ux", "history_back")) : (c.redo(), f && f.event("ux", "history_forward")) | |
} | |
}; | |
this.setTracking = function(a) { | |
f = a | |
}; | |
this.getAddressBarUrl = function() { | |
var c = a.getPageUrl(), | |
d = c.indexOf("?"), | |
f = d > -1, | |
g = !1, | |
e; | |
for (e in b) | |
if (c.indexOf("?" + b[e] + "=") > -1) { | |
g = !0; | |
break | |
} | |
f && !g && (c = c.substr(0, d)); | |
return c | |
}; | |
this.push = function(b) { | |
var c = "/" + b.toURLPath(); | |
j += 1; | |
g += 1; | |
a.pushState({ | |
index: j, | |
link: b | |
}, document.title, c) | |
}; | |
this.replace = function(b) { | |
url = "/" + b.toURLPath(); | |
a.replaceState({ | |
index: j, | |
link: b | |
}, document.title, url) | |
}; | |
(function() { | |
a.Adapter.bind(window, "statechange", k, this) | |
})() | |
}; | |
Spotify.Web.StateHistory = {}; | |
Spotify.Web.StateHistory.Commands = {}; | |
Spotify.Web.StateHistory.CommandTypes = { | |
EMPTY: "EMPTY", | |
SHOW_SECTION: "SHOW_SECTION", | |
UPDATE_APP_ARGUMENTS: "UPDATE_APP_ARGUMENTS", | |
PUSH: "PUSH", | |
POP: "POP", | |
MOVE_VIEWPORT: "MOVE_VIEWPORT", | |
COMPOSED_COMMAND: "COMPOSED_COMMAND", | |
UPDATE_VIEWPORT_BEGIN: "UPDATE_VIEWPORT_BEGIN", | |
UPDATE_VIEWPORT_END: "UPDATE_VIEWPORT_END", | |
BROWSER_HISTORY_PUSH_URL: "BROWSER_HISTORY_PUSH_URL" | |
}; | |
Spotify.Web.StateHistory.Manager = function(c, a, b) { | |
Spotify.Web.EventTarget.call(this); | |
if (typeof c === "undefined") throw Error("No arguments were supplied while initializing the State History Manager class."); | |
this.activeSection = null; | |
var d = this, | |
f = {}, | |
j = a, | |
g = new Spotify.Web.StateHistory.Stack, | |
k = new Spotify.Web.StateHistory.Stack, | |
l = function(a) { | |
this.activeSection = f[a.params.id] | |
}, | |
h = function(a, b) { | |
a.execute(function(a) { | |
b && a.type === Spotify.Web.StateHistory.CommandTypes.BROWSER_HISTORY_PUSH_URL && d.trigger("onBrowserHistoryPush", { | |
link: a.link | |
}); | |
d.trigger("doCommand", { | |
command: a | |
}) | |
}) | |
}, | |
m = function(a) { | |
var a = new Spotify.Web.StateHistory.App(d.activeSection.id, d.activeSection.viewport.endsAt, a), | |
b = []; | |
b.push(new Spotify.Web.StateHistory.Commands.PushApp(d.activeSection, a)); | |
b.push(new Spotify.Web.StateHistory.Commands.MoveViewport(d.activeSection, 1)); | |
b.push(new Spotify.Web.StateHistory.Commands.BrowserHistoryPushUrl(a.link)); | |
a = new Spotify.Web.StateHistory.Commands.ComposedCommand(b); | |
d.run(a) | |
}, | |
n = function(a, b, c, e) { | |
if (!c) c = d.activeSection; | |
e || (e = c.getTopApp()); | |
var f = []; | |
f.push(new Spotify.Web.StateHistory.Commands.UpdateAppLink(c, e, a)); | |
b || f.push(new Spotify.Web.StateHistory.Commands.BrowserHistoryPushUrl(a)); | |
a = new Spotify.Web.StateHistory.Commands.ComposedCommand(f); | |
d.run(a, b) | |
}, | |
e = function(a) { | |
var b = ["playlist", "starred", "toplist"]; | |
return a.id === "playlist" || a.id === "user" && b.indexOf(a.args[1]) > -1 | |
}, | |
o = function(a) { | |
var b = ["overview", "playlists", "songs", "albums", "artists"]; | |
return a.id === "user" && a.args && a.args[1] === "collection" && (a.args.length === | |
2 || b.indexOf(a.args[2]) !== -1 && a.args.length === 3) | |
}, | |
t = function() { | |
var a = d.activeSection; | |
a.persistent && a.viewport.endsAt === 0 && d.trigger("onBrowserHistoryReplace", { | |
link: a.apps[0].link | |
}) | |
}; | |
this.initialize = function() { | |
if (typeof c.sections === "undefined") throw Error("No sections were supplied."); | |
for (var a = 0, b = c.sections.length, d = c.sections; a < b; a += 1) { | |
var e = d[a].link; | |
f[e.id] = new Spotify.Web.StateHistory.Section(e, d[a].type, d[a].persistent); | |
f[e.id].bind("onActive", l, this) | |
} | |
}; | |
this.getCurrentLink = function() { | |
return this.activeSection && | |
this.activeSection.getTopApp() ? this.activeSection.getTopApp().link : null | |
}; | |
this.run = function(a, b) { | |
b || (k.push(a), g.clear()); | |
h(a, !b) | |
}; | |
this.undo = function() { | |
var a = k.pop().invert(); | |
h(a); | |
g.push(a); | |
t(); | |
return a | |
}; | |
this.redo = function() { | |
var a = g.pop().invert(); | |
h(a); | |
k.push(a); | |
t(); | |
return a | |
}; | |
this.openUri = function(a, g, h, k) { | |
var l = (k || {}).forceOpen || !1; | |
if (typeof a === "undefined") throw Error("openUri needs a Spotify.Link as an argument"); | |
if ((k = this.getCurrentLink()) && a.toURI() === k.toURI()) this.trigger("onCurrentLink", { | |
link: a | |
}); | |
else { | |
this.trigger("beforeOpenUri", { | |
link: a | |
}); | |
var t = a.id, | |
k = !1, | |
u; | |
for (u in f) | |
if (u === t && (k = !0, f[u].type === "popup")) { | |
this.trigger("onPopup", { | |
link: a, | |
origin: g | |
}); | |
return | |
} | |
if (k && (!a.args || a.args.length === 0)) c.useClassicMode ? this.goToRoot(f[t]) : this.activeSection !== f[t] ? this.showSection(f[t], h) : this.activeSection.viewport.endsAt !== 0 && this.goToRoot(); | |
else if (h) { | |
var g = b.features.collection ? "collection" : "playlist", | |
y = e(a) ? g : a.id; | |
y === this.activeSection.getTopApp().id ? (this.trigger("onBrowserHistoryReplace", { | |
link: a | |
}), n(a, !0)) : (y === "radio" || y === g) && n(a, !0, f[y], f[y].apps[0]) | |
} else if (e(a)) y = b.features.collection ? "collection" : "playlist", (this.activeSection.id === "playlist" || this.activeSection.id === "collection") && this.activeSection.apps.length === 1 ? n(a, h) : j.isOwnPlaylist(a, function(b) { | |
b ? d.goToRoot(f[y], a) : m(a, h) | |
}); | |
else if (o(a)) m(a, h); | |
else if (a.id === "user" && a.args[1] === "collection" && a.args[2] === "album" && a.args[3]) m(a, h); | |
else if (a.id === "user" && a.args[1] === "collection" && a.args[2] === "artist" && a.args[3]) m(a, h); | |
else if (k) | |
if (a.id === "user" && a.args[0]) { | |
var B = a.args[0]; | |
j.getUsername(function(b) { | |
if (b === B) d.goToRoot(f[t], a); | |
else { | |
var c = d.activeSection.getTopApp(), | |
b = !e(c.link) && c.link.id === "user", | |
c = a.args[0] === c.link.args[0]; | |
b && c && !l ? n(a, h) : m(a, h) | |
} | |
}) | |
} else a.args && a.args.length > 0 && this.goToRoot(f[t], a); | |
else m(a, h) | |
} | |
}; | |
this.goToRoot = function(a, b) { | |
var c = [], | |
d = this.activeSection; | |
a && this.activeSection !== a && (c.push(new Spotify.Web.StateHistory.Commands.ShowSection(this.activeSection, a)), d = a); | |
c.push(new Spotify.Web.StateHistory.Commands.UpdateViewportBegin(d)); | |
for (var e = d.viewport.endsAt + 1; --e;) { | |
var f = d.apps[e]; | |
c.push(new Spotify.Web.StateHistory.Commands.MoveViewport(d, -1)); | |
c.push(new Spotify.Web.StateHistory.Commands.PopApp(d, f)) | |
} | |
c.push(new Spotify.Web.StateHistory.Commands.UpdateViewportEnd(d)); | |
b ? (c.push(new Spotify.Web.StateHistory.Commands.UpdateAppLink(d, d.apps[0], b)), d = b) : d = a ? d.getTopApp().link : d.apps[0].link; | |
c.push(new Spotify.Web.StateHistory.Commands.BrowserHistoryPushUrl(d)); | |
this.run(new Spotify.Web.StateHistory.Commands.ComposedCommand(c)) | |
}; | |
this.showSection = function(a) { | |
var b = []; | |
b.push(new Spotify.Web.StateHistory.Commands.ShowSection(this.activeSection, a)); | |
b.push(new Spotify.Web.StateHistory.Commands.BrowserHistoryPushUrl(a.getTopApp().link)); | |
this.run(new Spotify.Web.StateHistory.Commands.ComposedCommand(b)) | |
}; | |
this.moveViewport = function(a) { | |
if (a !== -1) throw Error("not supported"); | |
this.trigger("beforeOpenUri", {}); | |
var b = this.activeSection.apps.length - 1 + a; | |
b < 0 || this.run(new Spotify.Web.StateHistory.Commands.ComposedCommand([new Spotify.Web.StateHistory.Commands.MoveViewport(this.activeSection, | |
a), new Spotify.Web.StateHistory.Commands.PopApp(this.activeSection, this.activeSection.getTopApp()), new Spotify.Web.StateHistory.Commands.BrowserHistoryPushUrl(this.activeSection.apps[b].link)])) | |
}; | |
this.getSection = function(a) { | |
return typeof f[a] !== "undefined" ? f[a] : null | |
}; | |
this.isRootActive = function() { | |
return this.activeSection.viewport.endsAt === 0 | |
}; | |
this.getSections = function() { | |
return f | |
}; | |
this.getUndoStack = function() { | |
return k | |
}; | |
this.getRedoStack = function() { | |
return g | |
}; | |
this.setServices = function(a) { | |
j = a | |
} | |
}; | |
Spotify.Web.StateHistory.Stack = function() { | |
var c = []; | |
this.isEmpty = function() { | |
return c.length === 0 | |
}; | |
this.clear = function() { | |
c = [] | |
}; | |
this.getLength = function() { | |
return c.length | |
}; | |
this.getItemAtIndex = function(a) { | |
return typeof c[a] !== "undefined" ? c[a] : null | |
}; | |
this.push = function(a) { | |
c.push(a) | |
}; | |
this.pop = function() { | |
return c.pop() | |
} | |
}; | |
Spotify.Web.StateHistory.Section = function(c, a, b) { | |
Spotify.Web.EventTarget.call(this); | |
if (typeof c === "undefined") throw Error("The link argument is required!"); | |
this.id = c.id; | |
this.type = a; | |
this.persistent = b || !1; | |
this.apps = [new Spotify.Web.StateHistory.App(this.id, 0, c)]; | |
this.viewport = new Spotify.Web.StateHistory.Viewport; | |
this.clear = function() { | |
this.apps = this.apps.slice(0, 1) | |
}; | |
this.setActive = function() { | |
this.trigger("onActive", { | |
id: this.id | |
}) | |
}; | |
this.getTopApp = function() { | |
return this.apps[this.apps.length - 1] | |
} | |
}; | |
Spotify.Web.StateHistory.App = function(c, a, b) { | |
if (typeof b === "undefined") throw Error("Argument missing: link"); | |
var d = c + "-app-" + b.toAppURI() + "-" + a + "-" + Date.now(); | |
this.link = b; | |
this.id = b.id; | |
this.uri = b.toAppURI(); | |
this.args = b.args || []; | |
this.updateLink = function(a) { | |
this.link = a; | |
this.id = a.id; | |
this.uri = a.toAppURI(); | |
this.args = a.args || [] | |
}; | |
this.getUniqueId = function() { | |
return d | |
} | |
}; | |
Spotify.Web.StateHistory.Viewport = function() { | |
this.length = 2; | |
this.endsAt = 0 | |
}; | |
Spotify.Web.StateHistory.Commands.PushApp = function(c, a) { | |
this.section = c; | |
this.app = a; | |
this.type = Spotify.Web.StateHistory.CommandTypes.PUSH; | |
this.execute = function(b) { | |
c.apps.push(a); | |
b(this) | |
}; | |
this.invert = function() { | |
return new Spotify.Web.StateHistory.Commands.PopApp(c, a) | |
} | |
}; | |
Spotify.Web.StateHistory.Commands.PopApp = function(c, a) { | |
this.section = c; | |
this.app = a; | |
this.type = Spotify.Web.StateHistory.CommandTypes.POP; | |
this.execute = function(a) { | |
c.apps.pop(); | |
a(this) | |
}; | |
this.invert = function() { | |
return new Spotify.Web.StateHistory.Commands.PushApp(c, a) | |
} | |
}; | |
Spotify.Web.StateHistory.Commands.MoveViewport = function(c, a) { | |
this.section = c; | |
this.type = Spotify.Web.StateHistory.CommandTypes.MOVE_VIEWPORT; | |
this.execute = function(b) { | |
c.viewport.endsAt += a; | |
b(this) | |
}; | |
this.getOffset = function() { | |
return a | |
}; | |
this.invert = function() { | |
return new Spotify.Web.StateHistory.Commands.MoveViewport(c, -1 * a) | |
} | |
}; | |
Spotify.Web.StateHistory.Commands.ShowSection = function(c, a) { | |
this.section = a; | |
this.app = a.apps[0]; | |
this.type = Spotify.Web.StateHistory.CommandTypes.SHOW_SECTION; | |
this.execute = function(a) { | |
this.app = this.section.apps[0]; | |
this.section.setActive(!0); | |
a(this) | |
}; | |
this.invert = function() { | |
return new Spotify.Web.StateHistory.Commands.ShowSection(this.section, c) | |
} | |
}; | |
Spotify.Web.StateHistory.Commands.UpdateAppLink = function(c, a, b) { | |
var d = a.link; | |
this.section = c; | |
this.type = Spotify.Web.StateHistory.CommandTypes.UPDATE_APP_ARGUMENTS; | |
this.execute = function(c) { | |
a.updateLink(b); | |
c(this) | |
}; | |
this.invert = function() { | |
return this.section.persistent ? new Spotify.Web.StateHistory.Commands.Empty : new Spotify.Web.StateHistory.Commands.UpdateAppLink(c, a, d) | |
} | |
}; | |
Spotify.Web.StateHistory.Commands.Empty = function() { | |
this.type = Spotify.Web.StateHistory.CommandTypes.EMPTY; | |
this.execute = function(c) { | |
c(this) | |
}; | |
this.invert = function() { | |
return new Spotify.Web.StateHistory.Commands.Empty | |
} | |
}; | |
Spotify.Web.StateHistory.Commands.UpdateViewportBegin = function(c) { | |
this.section = c; | |
this.execute = function(a) { | |
a(this) | |
}; | |
this.type = Spotify.Web.StateHistory.CommandTypes.UPDATE_VIEWPORT_BEGIN; | |
this.invert = function() { | |
return new Spotify.Web.StateHistory.Commands.UpdateViewportEnd(c) | |
} | |
}; | |
Spotify.Web.StateHistory.Commands.UpdateViewportEnd = function(c) { | |
this.section = c; | |
this.type = Spotify.Web.StateHistory.CommandTypes.UPDATE_VIEWPORT_END; | |
this.execute = function(a) { | |
a(this) | |
}; | |
this.invert = function() { | |
return new Spotify.Web.StateHistory.Commands.UpdateViewportBegin(c) | |
} | |
}; | |
Spotify.Web.StateHistory.Commands.BrowserHistoryPushUrl = function(c) { | |
this.type = Spotify.Web.StateHistory.CommandTypes.BROWSER_HISTORY_PUSH_URL; | |
this.link = c; | |
this.execute = function(a) { | |
a(this) | |
}; | |
this.invert = function() { | |
return this | |
} | |
}; | |
Spotify.Web.StateHistory.Commands.ComposedCommand = function(c) { | |
if (!c.length || !(c.length > 0)) throw Error("The ComposedCommand argument must be an array"); | |
this.type = Spotify.Web.StateHistory.CommandTypes.COMPOSED_COMMAND; | |
this.execute = function(a) { | |
for (var b = 0; b < c.length; b++) c[b].execute(a) | |
}; | |
this.invert = function() { | |
for (var a = [], b = c.length - 1; b >= 0; b--) a.push(c[b].invert()); | |
return new Spotify.Web.StateHistory.Commands.ComposedCommand(a) | |
}; | |
this.getCommands = function() { | |
return c | |
}; | |
this.getCommandAtIndex = function(a) { | |
a = | |
c[a]; | |
return typeof a !== "undefined" ? a : null | |
} | |
}; | |
Spotify.Web.AppManager = function(c, a, b) { | |
Spotify.Web.EventTarget.call(this); | |
var d = {}, | |
f = {}, | |
j = [], | |
g = this, | |
k = []; | |
c.bind("doCommand", function(a) { | |
a = a.params.command; | |
if (a.type === Spotify.Web.StateHistory.CommandTypes.UPDATE_APP_ARGUMENTS) { | |
var b = a.section.apps[a.section.viewport.endsAt], | |
f = c.getSection(a.section.id).apps[a.section.viewport.endsAt].getUniqueId(); | |
g.trigger("onFrameUpdated", { | |
app: b, | |
node: d[a.section.id][f] | |
}) | |
} | |
}); | |
this.getActiveFrame = function() { | |
var a = c.activeSection, | |
b = a.id, | |
a = c.getSection(b).apps[a.viewport.endsAt].getUniqueId(); | |
return d[b][a] | |
}; | |
this.registerDiv = function(a, b) { | |
f[a] = b | |
}; | |
this.get = function(g, h) { | |
var m = c.getSection(g).apps[h], | |
n = m.getUniqueId(), | |
e = d[g] || (d[g] = {}), | |
o = e[n]; | |
if (o) return o; | |
if (f[m.id]) return m = f[m.id].getElement(), e[n] = m; | |
var t = a(m.link.toURLPath()), | |
o = j.length ? j.shift() : b.createElement("iframe"); | |
o.id = n; | |
o.src = t; | |
e[n] = o; | |
n = k[m.id] ? !0 : !1; | |
k[m.id] = 1; | |
this.trigger("onFrameCreated", { | |
app: m, | |
node: o, | |
cached: n | |
}); | |
return o | |
}; | |
this.dispose = function(a, b) { | |
if (b !== 0) { | |
var f = c.getSection(a).apps[b], | |
g = f.getUniqueId(), | |
e = d[a], | |
k = e[g]; | |
this.trigger("onFrameDisposed", { | |
app: f, | |
node: k | |
}); | |
delete e[g]; | |
j.push(k) | |
} | |
return this | |
}; | |
this.registerAppWindow = function(a, b) { | |
this.trigger("onFrameCreated", { | |
app: { | |
link: b | |
}, | |
node: a | |
}) | |
}; | |
this.getIFrameWithWindow = function(a) { | |
for (var b in d) | |
for (var c in d[b]) { | |
var f = d[b][c]; | |
if (f.contentWindow === a) return f | |
} | |
return null | |
} | |
}; | |
Spotify.Web.Queue = function() { | |
var c = null; | |
this.execute = function(a) { | |
c && c.forceFinish(); | |
c = a; | |
c.execute() | |
}; | |
this.forceFinish = function() { | |
c && c.forceFinish() | |
} | |
}; | |
Spotify.Web.Queue.TransitionStep = function(c, a) { | |
var b = !1, | |
d = null, | |
f = function() { | |
try { | |
c() | |
} finally { | |
b = !0 | |
} | |
}; | |
this.execute = function() { | |
a ? d = setTimeout(f, a) : f() | |
}; | |
this.forceFinish = function() { | |
b || (clearTimeout(d), f()) | |
}; | |
this.delay = a | |
}; | |
Spotify.Web.Queue.Transition = function(c) { | |
this.execute = function() { | |
for (var a = 0; a < c.length; a++) c[a].execute() | |
}; | |
this.forceFinish = function() { | |
for (var a = 0; a < c.length; a++) c[a].forceFinish() | |
} | |
}; | |
Spotify.Web.View = function(c, a, b, d, f) { | |
Spotify.Web.EventTarget.call(this); | |
var j = this, | |
g = {}, | |
k, l = null, | |
h = function(e) { | |
var h = c.getSections()[e], | |
h = new Spotify.Web.View.Section(h, a, b.ownerDocument, f); | |
g[e] = h; | |
b.appendChild(h.getWrapper()); | |
d ? h.getWrapper().addClass("classic") : h.getWrapper().addClass("stacked"); | |
h.bind("onMoveViewportLeft", function() { | |
c.moveViewport(-1); | |
l && l.event("ux", "stacks_overlay_clicked") | |
}, j); | |
h.bind("onFrontPaneUpdate", function(a) { | |
this.trigger("onFrontPaneUpdate", a.params) | |
}, j) | |
}, | |
m = function(a) { | |
a = | |
a.params.command; | |
switch (a.type) { | |
case Spotify.Web.StateHistory.CommandTypes.SHOW_SECTION: | |
a = g[a.section.id]; | |
if (!a) throw Error("incorrect section id"); | |
k !== a && (k && (k.hide(), f.notify(Spotify.Web.PublisherMessages.APPLICATION_DEACTIVATED, { | |
node: k.getFrontPane().iFrame | |
})), a.show(), k = a, f.notify(Spotify.Web.PublisherMessages.APPLICATION_ACTIVATED, { | |
node: a.getFrontPane().iFrame | |
})); | |
break; | |
case Spotify.Web.StateHistory.CommandTypes.MOVE_VIEWPORT: | |
var b = a.getOffset(); | |
g[a.section.id].moveViewport(b); | |
break; | |
case Spotify.Web.StateHistory.CommandTypes.UPDATE_VIEWPORT_BEGIN: | |
k.updateViewportBegin(); | |
break; | |
case Spotify.Web.StateHistory.CommandTypes.UPDATE_VIEWPORT_END: | |
k.updateViewportEnd() | |
} | |
}, | |
n = function() { | |
k && k.forceQueue() | |
}; | |
this.setTracking = function(a) { | |
l = a | |
}; | |
(function() { | |
var a = c.getSections(), | |
b; | |
for (b in a) a.hasOwnProperty(b) && h(a[b].id); | |
c.bind("doCommand", m, j); | |
c.bind("beforeOpenUri", n, j) | |
})() | |
}; | |
Spotify.Web.View.Section = function(c, a, b, d) { | |
Spotify.Web.EventTarget.call(this); | |
var f = this, | |
j, g = Array(3), | |
k = new Spotify.Web.Queue, | |
l = !1, | |
h = null, | |
m = function() { | |
var a = g[g.length - 1].iFrame; | |
f.trigger("onFrontPaneUpdate", { | |
node: a | |
}); | |
h && d.notify(Spotify.Web.PublisherMessages.APPLICATION_DEACTIVATED, { | |
node: h | |
}); | |
d.notify(Spotify.Web.PublisherMessages.APPLICATION_ACTIVATED, { | |
node: a | |
}); | |
h = a | |
}, | |
n = function(a) { | |
a.isRoot() ? a.wrapper.className = "limbo" : (a.updatePaneStyle("fadeOut"), setTimeout(function() { | |
j.removeChild(a.wrapper) | |
}, | |
500)) | |
}, | |
e = function(a, b, c, d) { | |
a = new Spotify.Web.Queue.Transition([new Spotify.Web.Queue.TransitionStep(a), new Spotify.Web.Queue.TransitionStep(b, 5), new Spotify.Web.Queue.TransitionStep(c, d ? d : 25)]); | |
k.execute(a) | |
}, | |
o = function(d) { | |
var e = d === 0, | |
g = new Spotify.Web.View.Pane(e), | |
d = a.get(c.id, d); | |
g.updateIFrame(d); | |
if (!e || !j.querySelectorAll(".limbo")[0]) { | |
if (g.wrapper = b.createElement("div"), g.wrapper.appendChild(g.iFrame), g.wrapper.addEventListener("click", function() { | |
f.trigger("onMoveViewportLeft", {}) | |
}), e = b.createElement("div"), | |
e.className = "overlay", g.wrapper.appendChild(e), g.iFrame.tagName.toLowerCase() === "iframe") { | |
var h = b.createElement("div"); | |
h.className = "loading-indicator"; | |
g.wrapper.appendChild(h); | |
var k = !1; | |
setTimeout(function() { | |
if (!k) h.style.display = "block" | |
}, 500); | |
var l = function() { | |
k = !0; | |
h.style.display = "none"; | |
g.iFrame.removeEventListener("load", l, !1) | |
}; | |
g.iFrame.addEventListener("load", l, !1) | |
} | |
} else g.wrapper = j.querySelectorAll(".limbo")[0]; | |
return g | |
}, | |
t = function() { | |
for (var a = 0, b = g.length - 1; b >= 0; b--) g[b] && a++; | |
return a | |
}, | |
C = function() { | |
var b, | |
d, f; | |
t(); | |
e(function() { | |
b = g[0]; | |
for (var a = 0; a < g.length - 1; a++) g[a] = g[a + 1], g[a] && (g[a].isRoot() && g[a].updatePaneStyle("root", "covered"), a === g.length - 2 && !g[a].isRoot() && (f = g[a], f.updatePaneStyle("back"))); | |
g[g.length - 1] = o(c.viewport.endsAt); | |
d = g[2]; | |
d.updatePaneStyle("front", "fadeIn"); | |
j.appendChild(d.wrapper) | |
}, function() {}, function() { | |
f && f.updatePaneStyle("back"); | |
b && (n(b), a.dispose(c.id, c.viewport.endsAt - c.viewport.length - 1)); | |
m() | |
}) | |
}; | |
this.getWrapper = function() { | |
if (!j) { | |
var a = b.createElement("div"); | |
a.setAttribute("id", | |
"section-" + c.id); | |
a.className = "hidden"; | |
j = a | |
} | |
return j | |
}; | |
this.show = function() { | |
if (!g[2]) { | |
g[2] = o(0); | |
var a = g[2]; | |
a.updatePaneStyle(); | |
j.appendChild(a.wrapper) | |
} | |
j.addClass("active"); | |
j.removeClass("hidden") | |
}; | |
this.forceQueue = function() { | |
k.forceFinish() | |
}; | |
this.hide = function() { | |
j.addClass("hidden"); | |
j.removeClass("active") | |
}; | |
this.getFrontPane = function() { | |
return g[2] | |
}; | |
this.moveViewport = function(b) { | |
if (!l) | |
if (b === 1) C(); | |
else if (b === -1) { | |
for (var b = g[2], d = t(), e = g.length - 1; e > 0; e--) { | |
g[e] = g[e - 1]; | |
if (g[e] && g[e].isRoot()) | |
if (d > 1) g[e].updatePaneStyle("root", | |
"covered"); | |
else { | |
g[e].updatePaneStyle(); | |
break | |
} else g[e] && e === g.length - 1 ? g[e].updatePaneStyle("front") : g[e] && g[e].updatePaneStyle("back"); | |
g[e - 1] = null | |
} | |
n(b); | |
b = g[2]; | |
b.updatePaneStyle("front"); | |
b = c.viewport.endsAt - c.viewport.length; | |
b >= 0 && (g[0] = o(b), b > 0 && j.insertBefore(g[0].wrapper, j.childNodes[1])); | |
a.dispose(c.id, c.viewport.endsAt + 1); | |
m() | |
} else throw Error("not implemented"); | |
}; | |
this.updateViewportBegin = function() { | |
l = !0; | |
for (var b = 0; b < g.length; b++) g[b] && (n(g[b]), a.dispose(c.id, c.viewport.endsAt - g.length + 1 + b), | |
g[b] = null) | |
}; | |
this.updateViewportEnd = function() { | |
l = !1; | |
for (var a = -1, b = c.viewport.endsAt - 2; b <= c.viewport.endsAt; b++) | |
if (a += 1, !(b < 0)) { | |
var d = o(b); | |
g[a] = d; | |
d.isRoot() && d.updatePaneStyle(); | |
d.wrapper.parentElement !== j && j.appendChild(d.wrapper) | |
} | |
} | |
}; | |
Spotify.Web.View.Pane = function(c) { | |
this.wrapper = this.iFrame = null; | |
this.updateIFrame = function(a) { | |
this.iFrame = a | |
}; | |
this.updatePaneStyle = function(a, b) { | |
var d = this; | |
if (b) this.wrapper.className = b; | |
c === !0 ? this.wrapper.className = "root" + (b ? " " + b : "") : typeof a !== "undefined" && setTimeout(function() { | |
d.wrapper.className = a | |
}, 25) | |
}; | |
this.isRoot = function() { | |
return c | |
} | |
}; | |
Spotify.Web.NowPlaying = function() { | |
var c = document.getElementById("now-playing-widgets"); | |
this._displayRecomendations = function(a) { | |
a = new Spotify.Web.Window({ | |
url: a.getAppUrl("/now-playing-recs/") | |
}); | |
a.initialize(); | |
a = a.getElement(); | |
a.tabIndex = -1; | |
c.appendChild(a); | |
return a | |
}; | |
this._displayAndRegisterRecommendations = function(a, b, c) { | |
a = this._displayRecomendations(b); | |
b = Spotify.Link.fromString("spotify:app:now-playing-recs").toAppLink(); | |
c.registerAppWindow(a, b) | |
}; | |
this._displayUpsell = function(a, b, d, f) { | |
a = new Spotify.Web.Upsell({ | |
useCat: d, | |
useMft: f | |
}, a, b); | |
c.appendChild(a.getElement()); | |
return a | |
}; | |
this.displayWidget = function(a) { | |
a.core.core.user.getUserInfo(function(b) { | |
var c = this, | |
f = b.catalogue === "free", | |
j = a.config.getFeature("nowPlayingRecs"), | |
g = a.config.getFeature("underPlayerUpsell"), | |
k = function() { | |
c._displayUpsell(a.core.core.user, a.tracking, a.config.getSetting("cat_enabled"), f).init() | |
}, | |
l = function() { | |
c._displayAndRegisterRecommendations(a.config, a.router, a.appManager) | |
}, | |
h = function(a, b) { | |
//TODO add Try/Catch | |
a || JSON.parse(b.result[0]) ? k() : j && l() | |
}; | |
f ? g ? (b = "hm://xpromo/user/" + | |
encodeURIComponent(b.user) + "/platform/webplayer/promote/desktop", a.bridge.request("hermes_send_request", [b, "GET", [], | |
[], | |
[] | |
], h)) : j && l() : j ? l() : g && k() | |
}.bind(this)) | |
} | |
}; | |
Spotify.Web.FocusTracker = function(c) { | |
var a = this, | |
b = [], | |
d = (new Date).getTime(), | |
f = 0, | |
j = 0, | |
g = !0, | |
k = function() { | |
d = (new Date).getTime(); | |
f = 0; | |
g = !0; | |
l() | |
}, | |
l = function() { | |
for (var a, d = 0; d < b.length; d++) { | |
a = b[d]; | |
if (g && a.fired) { | |
a.onActive.call(); | |
a.fired = !1; | |
f = 0; | |
c.clearTimeout(a.timeout); | |
a.timeout = h(a.timeMS); | |
break | |
} | |
if (!g && !a.fired && f >= a.timeMS) { | |
a.onInactive.call(); | |
a.fired = !0; | |
break | |
} | |
} | |
}, | |
h = function() { | |
c.setInterval(function() { | |
a.onBackgroundActivity() | |
}, 1E3) | |
}; | |
this.registerCallback = function(a, c, d) { | |
b.push({ | |
timeMS: a * 1E3, | |
onInactive: c, | |
onActive: d, | |
fired: !1 | |
}) | |
}; | |
this.onBackgroundActivity = function() { | |
j++; | |
j === 10 && (j = 0, f = (new Date).getTime() - d, g = !1, l()) | |
}; | |
this.userActivityRecorded = function() { | |
k() | |
}; | |
this.init = function() { | |
c.addEventListener("mousemove", Spotify.Web.Utils.debounce(function() { | |
k() | |
}, 1E3)); | |
h() | |
} | |
}; | |
window._debug = !1; | |
Spotify = Spotify || {}; | |
Spotify.Web = Spotify.Web || {}; | |
window.addEventListener("mousewheel", function() {}, !1); | |
Spotify.Web.App = function() { | |
var c = this, | |
a, b = {}, | |
d, f, j, g, k, l, h, m, n, e, o, t, C, v, z = [], | |
w, A, x, u, y, B = function() { | |
G(); | |
a.popupManager.createAndRegisterPopup("context-actions", { | |
preventScrolling: !0, | |
hideOnWindowResize: !0, | |
loadAfter: 2E3 | |
}); | |
a.config.getFeature("share") && a.popupManager.createAndRegisterPopup("share", { | |
preventScrolling: !0, | |
hideOnWindowResize: !0, | |
loadAfter: "ON_DEMAND" | |
}); | |
a.config.getFeature("collection") === 2 && a.popupManager.createAndRegisterPopup("col-union-rem-dialog", { | |
preventScrolling: !0, | |
hideOnWindowResize: !0, | |
width: 400, | |
loadAfter: "ON_DEMAND" | |
}); | |
u = new Spotify.Web.LightboxWindow({ | |
url: a.router.getAppUrl("/revgen-modal/"), | |
id: "revgen-modal", | |
wrapper: document.getElementById("modal-ad-area"), | |
iframe: document.getElementById("ad-modal"), | |
loadAfter: "ON_DEMAND" | |
}, a.publisher, a.popupManager); | |
u.initialize(); | |
x.displayWidget(a); | |
g = a.popupManager.createAndRegisterPopup("suggest", { | |
preventScrolling: !0, | |
wrapper: document.getElementById("suggest-area"), | |
iframe: document.getElementById("suggest"), | |
hideMessage: Spotify.Web.PublisherMessages.SUGGEST_HIDDEN, | |
showMessage: Spotify.Web.PublisherMessages.SUGGEST_SHOWN, | |
postHideCallback: function() { | |
Spotify.Web.BrowserDetect.browser === "Firefox" && document.activeElement.blur(); | |
a.appManager.getActiveFrame().focus() | |
}, | |
loadAfter: 2E3 | |
}); | |
if (a.config.getFeature("notifications")) { | |
var b = a.config.getSetting("cat_enabled") ? [280, 240] : [314, 280]; | |
k = a.popupManager.createAndRegisterPopup("notification-center", { | |
width: b[0], | |
height: b[1], | |
preventScrolling: !0, | |
wrapper: document.getElementById("notifications-area"), | |
iframe: document.getElementById("notifications"), | |
hideMessage: Spotify.Web.PublisherMessages.NOTIFICATIONS_HIDDEN, | |
showMessage: Spotify.Web.PublisherMessages.NOTIFICATIONS_SHOWN, | |
postHideCallback: function() { | |
Spotify.Web.BrowserDetect.browser === "Firefox" && document.activeElement.blur(); | |
a.appManager.getActiveFrame().focus() | |
}, | |
loadAfter: "ON_DEMAND" | |
}) | |
} | |
a.popupManager.initializePopups(); | |
Spotify.Web.GA.trackEvent("landing", "render", "web-player-load-finished") | |
}, | |
D = function() { | |
var b = a.history.getAddressBarUrl(), | |
d = !0; | |
a.publisher.notify(Spotify.Web.PublisherMessages.APPLICATION_ENABLED, {}); | |
o = new Spotify.Web.AutoPlay(a.bridge, Spotify.Bridge, Spotify.Link, a.services, a.router.getAppUrl); | |
if (o.shouldPlay(b) || Spotify.Web.SpbMusicBridge.isReferrerFromSPB(a.config.getSetting("playLandingURL"))) d = !1; | |
Spotify.Shuttle.init(a.core.core, { | |
publisher: a.publisher, | |
getAppUrl: a.router.getAppUrl, | |
shouldGetSavedState: d, | |
blackList: a.playNow.isAnonymous() ? a.playNow.getBlocked() : {} | |
}); | |
Spotify.Shuttle.onReady(function(a, b) { | |
b.contextPlayer.once("trackLoaded", function() { | |
Spotify.Web.GA.trackEvent("landing", "render", | |
"web-player-playing") | |
}) | |
}); | |
clientEventLogger = new Spotify.Web.ClientEventLogger(a.bridge); | |
a.playNow.setLogger(clientEventLogger); | |
a.playNow.isOpenRedirect() && a.core.detachPlayer(); | |
if (o.shouldPlay(b) && !a.playNow.isOpenRedirect()) { | |
a.playNow.setAutoPlayTriggered(!0); | |
A.setAutoPlayTriggered(!0); | |
var e = function() { | |
a.appLoader.onReady(function() { | |
o.getUrl(b, function(b) { | |
a.router.openInitialUrl(b) | |
}); | |
B(); | |
j.showPlayer() | |
}) | |
}, | |
f = function() { | |
w.unbind("FIRST_BYTES", g, c); | |
w.unbind("CANNOT_PLAY_TRACK", k, c); | |
w.unbind("PLAYBACK_FAILED", | |
k, c); | |
w.unbind("INVALID_TRACK_URI", k, c) | |
}, | |
g = function() { | |
clearTimeout(h); | |
f(); | |
e() | |
}, | |
h, k = function() { | |
clearTimeout(h); | |
f(); | |
e() | |
}; | |
w.bind("FIRST_BYTES", g, c); | |
w.bind("CANNOT_PLAY_TRACK", k, c); | |
w.bind("PLAYBACK_FAILED", k, c); | |
w.bind("INVALID_TRACK_URI", k, c); | |
h = setTimeout(function() { | |
k() | |
}, 5E3); | |
o.playUrl(b, function() { | |
setTimeout(o.enableRepeatMode, 5E3); | |
F() | |
}, function(a) { | |
k(a); | |
F(a) | |
}) | |
} else a.appLoader.onReady(function() { | |
a.router.openInitialUrl(b); | |
B(); | |
F() | |
}); | |
d = new Spotify.Web.Storage.Cookie("settingsShort", a.services, Spotify.Utils.Base64, { | |
expires: 0 | |
}, document); | |
d.init(function() {}); | |
var l = new Spotify.Web.Storage.Cookie("settings", a.services, Spotify.Utils.Base64, { | |
expires: 366 | |
}, document); | |
l.init(function() {}); | |
a.services.getUserInfo(function(b) { | |
b = b.product; | |
b === "unlimited" || b === "premium" || a.playNow.isAnonymous() || m.setUpgradeButton(_("Upgrade")) | |
}); | |
I(); | |
n = new Spotify.Web.Settings.Model(a.core.core, a.bridge, d, l, a.fbBridge, a.playNow); | |
n.init(); | |
n.setServices(a.services); | |
m.setModel(n); | |
a.appManager.registerAppWindow(document.getElementById("app-player"), | |
Spotify.Link.fromString("spotify:app:player").toAppLink()); | |
(new Spotify.Web.AppNotifications(a.bridge, n, a.config.getSettings())).init(); | |
C = new Spotify.Web.LastFm(a.bridge, a.core.core, n, a.config.getSetting("lastfm")); | |
C.init(); | |
(new Spotify.Web.AdAgent).init(a.bridge, y, clientEventLogger) | |
}, | |
G = function() { | |
var b = document.getElementById("app-player"); | |
j = new Spotify.Web.Player(a.bridge, a.core.core, { | |
url: a.router.getAppUrl("/player/"), | |
iframe: b, | |
publisher: a.publisher | |
}); | |
j.initialize() | |
}, | |
E = function() { | |
p(); | |
if (!e) { | |
w = a.core.getMainPlayer(); | |
a.playNow.setPlayer(w); | |
if (window.localStorage && window.localStorage.playNow_isPlaying === "true") { | |
window.localStorage.playNow_isPlaying = "false"; | |
var b = function() { | |
var c = a.core.core.contextPlayer; | |
c && c.resume(); | |
w.unbind("LOAD", b) | |
}; | |
w.bind("LOAD", b, c) | |
} | |
e = !0; | |
D() | |
} | |
a.publisher.notify(Spotify.Web.PublisherMessages.ERROR, { | |
type: Spotify.Web.ErrorTypes.CONNECTION_RESTORED | |
}); | |
document.getElementById("main").style["background-image"] = "none" | |
}, | |
F = function(b) { | |
Spotify.Web.SpbMusicBridge.initMusicBridge(a.stateHistory, a.bridge, | |
a.publisher, a.config.getSettings(), a.consoleLogger, o, b) | |
}, | |
I = function() { | |
a.fbBridge.connect(a.config.getSettings().fbjssdk.config, function() { | |
t = new Spotify.Web.OpenGraph(a.fbBridge, a.bridge, v, n, a.services); | |
t.start(); | |
d.enableFacepile() | |
}, function(b) { | |
a.consoleLogger.warn("[FB] error", b); | |
window.setTimeout(I, 3E5); | |
b === "not_authorized" && d.enableFacepile() | |
}) | |
}, | |
H = function(a) { | |
z.push(a.params); | |
p() | |
}, | |
p = function() { | |
try { | |
for (var b = 0, c = z.length; b < c; b += 1) a.core.core.logging.logger.logJSExceptions(z[b].module, z[b].message, | |
z[b].url + ":" + a.history.getAddressBarUrl(), z[b].lineNumber); | |
z = [] | |
} catch (d) {} | |
}; | |
b.developerMode = !1; | |
b.initialize = function(c) { | |
Spotify.Web.GA.trackEvent("landing", "render", "web-player-load-initiated"); | |
Spotify.Web.BrowserDetect.init(); | |
var e = window.location.href; | |
if (!c) throw Error("Server-side settings not provided"); | |
var j = Spotify.Web.URLParser.parseURL(e), | |
n = Spotify.Web.Utils.filterQSParams(["utm_source", "utm_medium", "utm_term", "utm_content", "utm_campaign"], e); | |
if (c.force_zow == 1 || c.features.zow) e = "", n ? (e = "?" + | |
n, c.http_flag && (e += "&http=1")) : c.http_flag && (e = "?http=1"), window.location = "/" + (j && j.path ? j.path : "") + e; | |
else if (c.needsToAcceptEULA && c.needsToAcceptEULA === !0) window.location = "/legal/?fwdurl=" + encodeURIComponent(!j || !j.path ? "/" : "/" + j.path + (j.query ? "?" + j.query : "")) + (n ? "&" + n : ""); | |
else { | |
v = new Spotify.Web.Exceptions(window); | |
v.bind(Spotify.Web.ErrorTypes.UNCAUGHT_EXCEPTION, H, this); | |
v.bindWindow(window, "global"); | |
a = new Spotify.Web.Setup(c, e); | |
a.init(E); | |
A = new Spotify.Web.CookieCompliance(a.config.getSetting("country"), | |
a.publisher); | |
d = new Spotify.Web.PlayNowBanner(a.playNow, document.getElementById("playnow"), document.getElementById("main"), A, a.publisher, a.config.getSetting("cat_enabled")); | |
d.initialize(); | |
if (a.playNow.isAnonymous()) { | |
j = a.playNow.getLimitedFeatureFlags(); | |
for (n = 0; n < j.length; n++) c.features[j[n]] = !0 | |
} | |
if (!c) throw Error("Server-side settings not provided"); | |
b.developerMode = a.config.getSetting("developer") || !1; | |
a.config.getFeature("collection") && (Spotify.Web.Utils.enableAppInUrl("collection"), Spotify.Web.Utils.enableAppInUrl("collection-album"), | |
Spotify.Web.Utils.enableAppInUrl("collection-artist")); | |
a.config.getFeature("social-feed") && Spotify.Web.Utils.enableAppInUrl("social-feed"); | |
a.publisher.subscribe(Spotify.Web.PublisherMessages.APPLICATION_STATE_PUSH, this); | |
a.publisher.subscribe(Spotify.Web.PublisherMessages.APPLICATION_OPEN_URI, this); | |
a.publisher.subscribe(Spotify.Web.PublisherMessages.APPLICATION_CLOSED, this); | |
a.publisher.subscribe(Spotify.Web.PublisherMessages.CLIENT_SHOW_SHARE_UI, this); | |
a.publisher.subscribe(Spotify.Web.PublisherMessages.CLIENT_SHOW_CONTEXT_UI, | |
this); | |
a.publisher.subscribe(Spotify.Web.PublisherMessages.CLIENT_SHOW_COLLECTION_UNION_REMOVE_UI, this); | |
a.publisher.subscribe(Spotify.Web.PublisherMessages.FB_APP_UNKNOWN, this); | |
a.publisher.subscribe(Spotify.Web.PublisherMessages.FB_APP_CONNECTED, this); | |
a.publisher.subscribe(Spotify.Web.PublisherMessages.FB_APP_NOT_AUTHENTICATED, this); | |
a.publisher.subscribe(Spotify.Web.PublisherMessages.FB_CONNECTION_FAILURE, this); | |
a.publisher.subscribe(Spotify.Web.PublisherMessages.FB_MESSAGE, this); | |
a.publisher.subscribe(Spotify.Web.PublisherMessages.FB_POST, | |
this); | |
a.publisher.subscribe(Spotify.Web.PublisherMessages.FB_SESSION_QUERY, this); | |
a.publisher.subscribe(Spotify.Web.PublisherMessages.FB_SESSION_USER_METADATA, this); | |
a.publisher.subscribe(Spotify.Web.PublisherMessages.USER_AUTHENTICATION_FAILURE, this); | |
a.publisher.subscribe(Spotify.Web.PublisherMessages.APPLICATION_VERSION_CHANGED, this); | |
a.publisher.subscribe(Spotify.Web.PublisherMessages.APPLICATION_POST_MESSAGE, this); | |
a.publisher.subscribe(Spotify.Web.PublisherMessages.LIMITED_FEATURE_CALL, this); | |
a.publisher.subscribe(Spotify.Web.PublisherMessages.SUGGEST_SHOW, | |
this); | |
a.publisher.subscribe(Spotify.Web.PublisherMessages.SUGGEST_HIDE, this); | |
a.publisher.subscribe(Spotify.Web.PublisherMessages.APPLICATION_LOAD_TIME, this); | |
a.publisher.subscribe(Spotify.Web.PublisherMessages.APPLICATION_LOAD_STARTED, this); | |
a.publisher.subscribe(Spotify.Web.PublisherMessages.NOTIFICATIONS_SHOW, this); | |
a.publisher.subscribe(Spotify.Web.PublisherMessages.NOTIFICATIONS_HIDE, this); | |
window.addEventListener("message", function(b) { | |
var c = Spotify.Web.Utils.appNameFromUrl(b.origin); | |
a.publisher.notify(Spotify.Web.PublisherMessages.APPLICATION_POST_MESSAGE, { | |
url: c, | |
name: c, | |
data: b.data, | |
evt: b | |
}) | |
}, !1); | |
b.abTests = a.abTests; | |
x = new Spotify.Web.NowPlaying; | |
a.router.bind(a.router.EVENT_TRACK_URI_ROUTED, function(b) { | |
if (!a.playNow.isOpenRedirect()) { | |
var c = b.params.link; | |
o.play(c.toURI(), c.id, function() { | |
a.consoleLogger.log("Autoplaying track", c) | |
}, function() { | |
a.consoleLogger.warn("Unable to auto play track") | |
}) | |
} | |
}); | |
document.getElementById("main-nav").addEventListener("click", function(b) { | |
b.target.id === "main-nav" && !a.stateHistory.isRootActive() && (a.stateHistory.moveViewport(-1), | |
a.tracking.event("ux", "stacks_overlay_clicked")) | |
}); | |
a.stateHistory.bind("doCommand", function(a) { | |
a = a.params.command; | |
a.type === Spotify.Web.StateHistory.CommandTypes.SHOW_SECTION && f.highlightMenu(a.section.id) | |
}); | |
a.stateHistory.bind("onPopup", function(b) { | |
var c = b.params.link.id, | |
d = b.params.origin; | |
c === "suggest" ? g.isVisible() ? a.publisher.notify(Spotify.Web.PublisherMessages.SUGGEST_HIDE) : a.publisher.notify(Spotify.Web.PublisherMessages.SUGGEST_SHOW) : c === "notification-center" ? k.isVisible() ? a.publisher.notify(Spotify.Web.PublisherMessages.NOTIFICATIONS_HIDE) : | |
a.publisher.notify(Spotify.Web.PublisherMessages.NOTIFICATIONS_SHOW) : c === "context-actions" || c === "share" ? a.popupManager.popup(b.params.link, d) : c === "revgen-modal" && (a.popupManager.closeAll(), u.show(b.params.link, d)) | |
}); | |
a.stateHistory.bind("onCurrentLink", function() { | |
g.isVisible() && a.publisher.notify(Spotify.Web.PublisherMessages.SUGGEST_HIDE); | |
k.isVisible() && a.publisher.notify(Spotify.Web.PublisherMessages.NOTIFICATIONS_HIDE) | |
}); | |
a.history.bind("pageChange", function(b) { | |
a.tracking.pageView("/" + Spotify.Web.URLParser.parseURL(b.params.url).path); | |
a.popupManager.closeAll() | |
}); | |
a.stateHistory.bind("onBrowserHistoryPush", function(b) { | |
a.history.push(b.params.link) | |
}); | |
a.stateHistory.bind("onBrowserHistoryReplace", function(b) { | |
a.history.replace(b.params.link) | |
}); | |
h = new Spotify.Web.Error({ | |
publisher: a.publisher, | |
element: document.getElementById("notification-area"), | |
dialog: document.getElementById("modal-notification-area"), | |
timeout: 4E3 | |
}, a.playNow); | |
h.initialize(); | |
a.playNow.isAnonymous() ? m = new Spotify.Web.Settings.Anonymous({ | |
wrapper: document.getElementById("settings"), | |
scrollBlocker: a.scrollBlocker, | |
publisher: a.publisher | |
}, c) : (j = new Spotify.Web.SettingsApp(a.config.getSetting("cat_enabled")), a.appManager.registerDiv("settings", j), m = new Spotify.Web.Settings.View({ | |
wrapper: j.getElement(), | |
scrollBlocker: a.scrollBlocker, | |
publisher: a.publisher | |
}, c)); | |
m.init(); | |
m.bind(Spotify.Web.PublisherMessages.APPLICATION_OPEN_URI, function(b) { | |
a.router.openUri(b.params.link) | |
}); | |
f = new Spotify.Web.Menu({ | |
publisher: a.publisher, | |
container: document.getElementById("main-nav"), | |
features: a.config.getFeatures(), | |
settingsView: m, | |
router: a.router, | |
cat: a.config.getSetting("cat_enabled") | |
}, a.playNow, $); | |
f.initialize(); | |
v.bind(Spotify.Web.ErrorTypes.UNCAUGHT_EXCEPTION, function(b) { | |
b = b.params; | |
a.tracking.handleException(b.module, b.message, "", b.url, b.lineNumber) | |
}); | |
Spotify.Web.FeatureDetect.adBlockCheck() && a.publisher.notify(Spotify.Web.PublisherMessages.ERROR, { | |
type: Spotify.Web.ErrorTypes.AD_BLOCK_DETECTED | |
}); | |
y = new Spotify.Web.FocusTracker(window); | |
y.init(); | |
l = new Spotify.Web.PostMessages.Handler({ | |
allowed_origins: [window.location.protocol + | |
"//" + window.location.hostname | |
] | |
}, a.consoleLogger, a.appLoader, a.appManager, a.popupManager, k, y); | |
a.publisher.notify(Spotify.Web.PublisherMessages.CHROME_READY); | |
setTimeout(function() { | |
(new Spotify.Web.CookieCleaner(Spotify.Web.Cookie)).clean() | |
}, 2E3) | |
} | |
}; | |
b.onNotify = function(b) { | |
var c = b.message, | |
d = Spotify.Web.PublisherMessages; | |
switch (b.messageType) { | |
case d.APPLICATION_POST_MESSAGE: | |
l.handle(c.evt); | |
break; | |
case d.APPLICATION_OPEN_URI: | |
f.enable(); | |
a.router.openUri(c.link, c.origin, c.replace); | |
break; | |
case d.APPLICATION_VERSION_CHANGED: | |
a.publisher.notify(d.ERROR, { | |
type: Spotify.Web.ErrorTypes.APPLICATION_RELOAD_NEEDED | |
}); | |
break; | |
case d.LIMITED_FEATURE_CALL: | |
a.playNow.limitedFeatureCalled(c.feature); | |
break; | |
case d.CLIENT_SHOW_SHARE_UI: | |
b = "spotify:share:" + c.left + ":" + (c.top + 10) + ":0:0:" + encodeURIComponent(c.uri); | |
b = Spotify.Link.fromString(b); | |
d = a.appManager.getIFrameWithWindow(c.origin); | |
a.popupManager.popup(b, d, !0); | |
c.callback(!0); | |
break; | |
case d.CLIENT_SHOW_CONTEXT_UI: | |
b = "spotify:app:context-actions:" + c.left + ":" + c.top + ":0:0:"; | |
b += encodeURIComponent(c.items[0]); | |
b += ":" + (c.itemContext ? | |
encodeURIComponent(c.itemContext) : ""); | |
b += ":" + (typeof c.itemIndex !== "undefined" ? c.itemIndex : ""); | |
b = Spotify.Link.fromString(b); | |
d = a.appManager.getIFrameWithWindow(c.origin); | |
a.popupManager.popup(b, c.origin); | |
break; | |
case d.CLIENT_SHOW_COLLECTION_UNION_REMOVE_UI: | |
b = Spotify.Link.applicationLink("col-union-rem-dialog", [0, 0, 0, 0].concat(c.uri.split(":").slice(1))); | |
d = a.appManager.getIFrameWithWindow(c.origin); | |
a.popupManager.popup(b, d, !0); | |
c.callback(!0); | |
break; | |
case d.SUGGEST_SHOW: | |
g.show(); | |
break; | |
case d.SUGGEST_HIDE: | |
g.hide(); | |
break; | |
case d.NOTIFICATIONS_SHOW: | |
k.show(); | |
break; | |
case d.NOTIFICATIONS_HIDE: | |
k.hide(); | |
break; | |
case d.APPLICATION_LOAD_STARTED: | |
a.appLogger.loadingStart(c); | |
break; | |
case d.APPLICATION_LOAD_TIME: | |
a.appLogger.loadingTime(c); | |
break; | |
case d.APPLICATION_CLOSED: | |
b = w.trackUri; | |
b.indexOf("spotify:ad:") > -1 && a.core.core.adChooser.recordAdEvent(b, "attempt"); | |
break; | |
case d.FB_MESSAGE: | |
a.fbBridge.sendMessage(c.uids, c.url, c.message, function(a) { | |
c.callback(a) | |
}); | |
break; | |
case d.FB_POST: | |
a.fbBridge.postToWall(c.url, c.message, function(a) { | |
c.callback(a) | |
}); | |
break; | |
case d.FB_SESSION_QUERY: | |
a.fbBridge.getFacebookSession(function(a) { | |
c.callback(a) | |
}); | |
break; | |
case d.FB_SESSION_USER_METADATA: | |
a.fbBridge.getUsersName(function(a) { | |
c.callback(a) | |
}) | |
} | |
}; | |
return b | |
}(); | |
Spotify.Web.GA = Spotify.Web.GA || {}; | |
Spotify.Web.GA.RETRY_MS = 50; | |
Spotify.Web.GA.trackEvent = function(c, a, b, d) { | |
var f = setInterval(function() { | |
window.ga && (ga("send", "event", c, a, b, d), clearInterval(f)) | |
}, Spotify.Web.GA.RETRY_MS) | |
}; | |
Spotify.Web.GDP = function(c) { | |
function a(a) { | |
if (a.status === "connected") { | |
var c = a.authResponse.userID, | |
a = a.authResponse.accessToken; | |
d.notify(Spotify.Web.PublisherMessages.FB_APP_CONNECTED, { | |
userID: c, | |
accessToken: a | |
}); | |
b.hide(); | |
(new Request({ | |
url: "/xhr/json/gdp/create.php", | |
method: "get", | |
data: { | |
fbuid: c, | |
access_token: a | |
}, | |
onSuccess: k | |
})).send() | |
} | |
} | |
var b = this, | |
d = c.publisher, | |
f = c.fbBridge, | |
j, g = new Spotify.Web.GDP.View({ | |
player: c.core.player | |
}); | |
this.initialize = function() { | |
j = f.getAPI(); | |
d.subscribe(Spotify.Web.PublisherMessages.FB_APP_CONNECTED, | |
b); | |
d.subscribe(Spotify.Web.PublisherMessages.FB_APP_NOT_AUTHENTICATED, b); | |
j.Event.subscribe("auth.statusChange", a) | |
}; | |
this.createDialog = function() { | |
g.initialize(null, b.show) | |
}; | |
this.show = function() { | |
g.show() | |
}; | |
this.hide = function() { | |
g.hide() | |
}; | |
this.error = function() { | |
g.render(g.templates.ERROR) | |
}; | |
this.deny = function() { | |
g.render(g.templates.CANCEL) | |
}; | |
this.authenticate = function() { | |
f.getLoginStatus() | |
}; | |
this.onNotify = function(a) { | |
var c = Spotify.Web.PublisherMessages; | |
switch (a.messageType) { | |
case c.APPLICATION_ENABLED: | |
setupTrack(); | |
break; | |
case c.FB_APP_NOT_AUTHENTICATED: | |
d.unsubscribe(Spotify.Web.PublisherMessages.FB_APP_CONNECTED, b); | |
break; | |
case c.FB_APP_CONNECTED: | |
window.location.href = "/login/?forward=" + encodeURIComponent("/welcome/") | |
} | |
}; | |
var k = function(a) { | |
//TODO add Try/Catch | |
a = JSON.parse(a); | |
a.status === "success" ? d.notify(Spotify.Web.PublisherMessages.USER_AUTHENTICATED) : d.notify(Spotify.Web.PublisherMessages.USER_AUTHENTICATION_FAILURE, a) | |
} | |
}; | |
Spotify.Web.GDP = Spotify.Web.GDP || {}; | |
Spotify.Web.GDP.View = function() { | |
function c(a, b) { | |
var c = f[a]; | |
c ? (d.node.innerHTML = c, typeof b === "function" && b.call(this, c)) : (new Request({ | |
url: a, | |
method: "get", | |
onSuccess: function(c) { | |
f[a] = c; | |
d.node.innerHTML = c; | |
typeof b === "function" && b.call(this, c) | |
} | |
})).send() | |
} | |
function a() { | |
document.getElementById("retry-button").addEventListener("click", function() { | |
d.render(d.templates.MAIN) | |
}) | |
} | |
function b() { | |
var a = document.createElement("div"); | |
a.id = "gdp-container"; | |
a.classList.add("modal-notification"); | |
document.body.appendChild(a); | |
return a | |
} | |
var d = this, | |
f = {}; | |
this.player = this.node = null; | |
this.templates = { | |
MAIN: "/static/templates/gdp-main.html", | |
ERROR: "/static/templates/gdp-error.html", | |
CANCEL: "/static/templates/gdp-cancel.html" | |
}; | |
this.initialize = function(a, c) { | |
d.node = d.node || b(); | |
this.render(this.templates.MAIN, function() { | |
typeof c === "function" && c.call(this) | |
}) | |
}; | |
this.render = function(b, d) { | |
var f; | |
switch (b) { | |
case this.templates.ERROR: | |
f = a; | |
break; | |
case this.templates.CANCEL: | |
f = a; | |
break; | |
default: | |
f = d | |
} | |
c(b, f) | |
}; | |
this.show = function() { | |
d.node.style.display = "block" | |
}; | |
this.hide = function() { | |
d.node.style.display = "none" | |
} | |
}; | |
Spotify.Web.Utils = function() { | |
function c() { | |
d = RegExp("^https?://[^/]+/(?:user/([^/]*)/)?(" + b.join("|") + ")/?(.*)?/?(.*)?/?") | |
} | |
var a = {}, | |
b = "hub,home,browse,article,genre,collection-album,discover,starred,welcome,radio,trackset,labs,track,artist,album,messages,playlist,purchase,search,settings,debug,user,test-runner,pitchfork,promo-mft,songkick,follow(?!ers|ing),cosmosecho,cosmos-artist,brand-header,queue,social-chart,charts,chart".split(","), | |
d, f = /^https?:\/\/.*\/(?:user\/([^/]*)\/)?([a-z]{1}[a-z0-9-]+)\/?(.*)?\/?(.*)?\/?/; | |
c(); | |
a.enableAppInUrl = function(a) { | |
b.indexOf(a) !== 0 && (b.push(a), c()) | |
}; | |
a.disableAppInUrl = function(a) { | |
a = b.indexOf(a); | |
a !== 0 && (b.splice(a, 1), c()) | |
}; | |
a.spotifyUriToOrigin = function(a) { | |
var a = a.split(":"), | |
b = a[1], | |
c = a[2]; | |
b === "user" && a[3] === "playlist" ? (b = "playlist", c += ":" + a[4]) : b === "user" && a[3] === "collection" && (b = "collection-album", c += ":" + a[5]); | |
return "spotify:app:" + b + ":" + c | |
}; | |
a.spotifyUriToOpenUrl = function(a, b) { | |
if (a) { | |
for (var c = a.split(":"), d = b || "http://open.spotify.com", f = 1; f < c.length; f++) { | |
if (c[f] === "top") break; | |
d += | |
"/" + c[f] | |
} | |
return d | |
} else return "" | |
}; | |
a.decodeOpenGraphUrl = function(a) { | |
a = a.replace("#_=_", ""); | |
if (a = a.match(typeof Spotify.Web.App !== "undefined" && Spotify.Web.App.developerMode ? f : d)) { | |
var b = a[3] || null; | |
b !== null && (b = b.replace(/\?.*/g, ""), b = b.replace(/\//g, ":"), b = b[b.length - 1] === ":" ? b.slice(0, -1) : b); | |
return { | |
user: a[1] || null, | |
context: a[2] || null, | |
contextId: b | |
} | |
} else return null | |
}; | |
a.openGraphUrlToSpotifyUri = function(b) { | |
if (!b) return null; | |
var c = a.decodeOpenGraphUrl(b); | |
if (!c) return ""; | |
c.user ? b = c.contextId ? "spotify:user:" + | |
c.user + ":" + c.context + ":" + c.contextId : "spotify:user:" + c.user + ":" + c.context : c.contextId ? c.context === "search" ? (b = b.replace("#_=_", "").replace(/\/$/, "").split("/"), b.splice(0, 3), b.unshift("https://play.spotify.com/app"), b = b.join("/"), b = Spotify.Link.fromString(b).toURI()) : b = c.context === "collection" ? !c.contextId || ["overview", "playlists", "songs", "albums", "artists"].indexOf(c.contextId) !== -1 ? "spotify:app:collection" + (c.contextId ? ":" + c.contextId : "") : "spotify:user:@:" + c.context + ":" + c.contextId : "spotify:" + c.context + | |
":" + c.contextId : b = "spotify:app:" + c.context; | |
return b | |
}; | |
a.addTransitionEndedListener = function(a, b, c) { | |
var d = !1, | |
f = function(a) { | |
d = !0; | |
b(a); | |
m() | |
}, | |
m = function() { | |
a.removeEventListener("webkitTransitionEnd", f, !1); | |
a.removeEventListener("transitionend", f, !1); | |
a.removeEventListener("msTransitionEnd", f, !1); | |
a.removeEventListener("oTransitionEnd", f, !1) | |
}; | |
a.addEventListener("webkitTransitionEnd", f, !1); | |
a.addEventListener("transitionend", f, !1); | |
a.addEventListener("msTransitionEnd", f, !1); | |
a.addEventListener("oTransitionEnd", | |
f, !1); | |
setTimeout(function() { | |
d || m() | |
}, c || 2E3) | |
}; | |
a.getWindowPosition = function(a) { | |
var b = 0, | |
c = 0; | |
do b += a.offsetLeft, c += a.offsetTop; while (a = a.offsetParent); | |
return { | |
left: b, | |
top: c | |
} | |
}; | |
a.appNameFromUrl = function(a) { | |
var b = null; | |
b = a.indexOf("/apps/") >= 0 ? a.split("/apps/")[1].split("/")[0] : (a = a.match(/^https?:\/\/[A-Za-z0-9]{8,40}-([A-Za-z0-9_-]+).*/)) ? a[1] : null; | |
return b | |
}; | |
a.getQueryStringParameter = function(a) { | |
if (!window) return null; | |
for (var b = window.location.search.substr(1).split("&"), c = {}, d = 0; d < b.length; d++) | |
if (b[d].indexOf("=") > | |
-1) { | |
var f = b[d].split("="); | |
c[f[0]] = f[1] | |
} | |
return c[a] ? c[a] : null | |
}; | |
a.stripQSParams = function(a, b) { | |
var c = b.split("?"); | |
if (c.length < 2 || c[1].length == 0) return b; | |
for (var d = c[1].split("&"), f = [], m = 0; m < d.length; m++) { | |
var n = d[m].split("="); | |
a.indexOf(n[0]) == -1 && f.push(d[m]) | |
} | |
return c[0] + (f.length > 0 ? "?" + f.join("&") : "") | |
}; | |
a.filterQSParams = function(a, b) { | |
var c = b.split("?"); | |
if (c.length < 2 || c[1].length == 0) return ""; | |
for (var c = c[1].split("&"), d = [], f = 0; f < c.length; f++) { | |
var m = c[f].split("="); | |
a.indexOf(m[0]) != -1 && d.push(c[f]) | |
} | |
return d.join("&") | |
}; | |
a.debounce = function(a, b) { | |
var c = null; | |
return function() { | |
var d = this, | |
f = arguments; | |
window.clearTimeout(c); | |
c = window.setTimeout(function() { | |
a.apply(d, f) | |
}, b) | |
} | |
}; | |
return a | |
}(); | |
Spotify.Web.Fb = function(c, a, b) { | |
var d = this, | |
f = window.FB || null, | |
j = Spotify.Web.PublisherMessages; | |
this.getFacebookSession = function(a) { | |
b.getFacebookUserId(function(b) { | |
a({ | |
facebookUser: b | |
}) | |
}) | |
}; | |
var g = function(a, b) { | |
d.getFacebookSession(function(c) { | |
if (!c || !c.facebookUser) b("not_authorized"); | |
else { | |
var d = f.getUserID(); | |
c.facebookUser === d ? a() : b("not_authorized") | |
} | |
}) | |
}, | |
k = function(a, b) { | |
f.getLoginStatus(function(d) { | |
switch (d.status) { | |
case "connected": | |
g(function() { | |
c.notify(j.FB_APP_CONNECTED); | |
a() | |
}, b); | |
break; | |
case "not_authorized": | |
b("not_authorized"); | |
break; | |
default: | |
b("not_logged_in") | |
} | |
}, !0) | |
}, | |
l = function(a) { | |
var b = { | |
status: "failure", | |
message: "" | |
}; | |
typeof a.error_msg != "undefined" ? b.message = a.error_msg : (b.status = "success", b.message = a); | |
return b | |
}; | |
this.connect = function(a, b, c) { | |
if (!a || typeof a.appId !== "string") throw Error("AppId required"); | |
Spotify.Web.FacebookSDK.onInitialized(function() { | |
f = window.FB; | |
k(b, c) | |
}) | |
}; | |
this.getApi = function() { | |
if (f) return f; | |
else throw Error("FB API not initialized"); | |
}; | |
this.requestExtentedPermissions = function(a) { | |
Spotify.Web.FacebookSDK.onInitialized(function() { | |
f.login(function(b) { | |
b.authResponse ? | |
d.checkPublishActionsPermissions(a) : a(Error("User not logged in")) | |
}, { | |
scope: "publish_actions" | |
}) | |
}) | |
}; | |
this.checkPublishActionsPermissions = function(a) { | |
Spotify.Web.FacebookSDK.onInitialized(function() { | |
k(function() { | |
f.api("/me/permissions", function(b) { | |
if (b.error) a(b.error); | |
else { | |
for (var b = b.data, c = 0, d = b.length; c < d; c++) { | |
var f = b[c]; | |
if (f.permission == "publish_actions" && f.status == "granted") { | |
a(null, !0); | |
return | |
} | |
} | |
a(null, !1) | |
} | |
}) | |
}, function(b) { | |
a(b) | |
}) | |
}) | |
}; | |
this.getDevices = function(a) { | |
this.getApi().api("/me?fields=devices", | |
function(b) { | |
if (typeof a === "function") { | |
var c = []; | |
if (typeof b.devices !== "undefined" && b.devices.length > 0) | |
for (var b = b.devices, d = b.length, f = 0; f < d; f++) typeof b[f].hardware !== "undefined" ? c.push(b[f].hardware.toLowerCase()) : typeof b[f].os !== "undefined" && c.push(b[f].os.toLowerCase()); | |
a.call(this, c) | |
} | |
}) | |
}; | |
this.getFriendsUsingApp = function(a) { | |
this.getApi().api({ | |
method: "fql.query", | |
query: "SELECT uid, name FROM user WHERE is_app_user = 1 AND uid IN (SELECT uid2 FROM friend WHERE uid1 = me())" | |
}, function(b) { | |
b = l(b); | |
typeof a === | |
"function" && a.call(this, b) | |
}) | |
}; | |
this.getFriendsNotUsingApp = function(a) { | |
this.getApi().api({ | |
method: "fql.query", | |
query: "SELECT uid, name FROM user WHERE is_app_user = 0 AND uid IN (SELECT uid2 FROM friend WHERE uid1 = me())" | |
}, function(b) { | |
b = l(b); | |
typeof a === "function" && a.call(this, b) | |
}) | |
}; | |
this.getUserImage = function(a) { | |
this.getApi().api({ | |
method: "fql.query", | |
query: "select id, width, height, url, is_silhouette, real_width, real_height from profile_pic where id=me()" | |
}, function(b) { | |
b = l(b); | |
typeof a === "function" && a.call(this, | |
b) | |
}) | |
}; | |
this.getUsersName = function(a) { | |
this.getApi().api("/me?fields=name,last_name,first_name", function(b) { | |
b = l(b); | |
typeof a === "function" && a.call(this, b) | |
}) | |
}; | |
this.postToWall = function(a, b, c) { | |
this.getApi().api("/feed", "post", { | |
link: a, | |
message: b | |
}, c) | |
}; | |
this.sendMessage = function(a, b, c, e) { | |
var f = d.getApi(), | |
a = { | |
to: "[" + a.join(",") + "]", | |
message: c | |
}; | |
if (b) a.link = b; | |
f.api("/threads", "post", a, e) | |
}; | |
this.connectUser = function(a, b) { | |
this.getApi().getLoginStatus(function(f) { | |
f.status === "connected" ? (a(f.authResponse.userID, f.authResponse.accessToken), | |
c.notify(j.FB_APP_CONNECTED)) : d.getApi().login(function(d) { | |
d.authResponse ? (a(d.authResponse.userID, d.authResponse.accessToken), c.notify(j.FB_APP_CONNECTED)) : b(d) | |
}, { | |
scope: "publish_actions" | |
}) | |
}) | |
} | |
}; | |
Spotify.Web.Context = function(c) { | |
this._parseRadioUri = function(a) { | |
return "spotify:radio:" + a.split(":")[3].replace(/%3A/g, ":").replace("spotify:", "") | |
}; | |
this.getState = function(a) { | |
c.player.getState(a) | |
}; | |
this.getFacebookContextType = function(a) { | |
var b = this; | |
this.getState(function(c, f) { | |
var j = f.context; | |
if (!j || !j.uri) a(null); | |
else { | |
var g = j.uri.split(":"), | |
k = null; | |
switch (g[1]) { | |
case "user": | |
k = "playlist"; | |
break; | |
case "album": | |
k = "album"; | |
break; | |
case "artist": | |
k = "musician"; | |
break; | |
case "temp-playlist": | |
if (g[2] === "radio") k = "radio_station", | |
j.uri = b._parseRadioUri(j.uri), j.stationUri = j.uri.replace("spotify:radio:", "spotify:") | |
} | |
a(k, f) | |
} | |
}) | |
} | |
}; | |
Spotify.Web.FacebookURLSchema = function() { | |
var c = function(a) { | |
var b = {}; | |
if (a.song) b.trackUrl = decodeURIComponent(a.song); | |
if (a.musician) b.contextUrl = decodeURIComponent(a.musician); | |
else if (a.album) b.contextUrl = decodeURIComponent(a.album); | |
else if (a.playlist) b.contextUrl = decodeURIComponent(a.playlist); | |
return b | |
}; | |
this.shouldPlay = function(a) { | |
a = Spotify.Web.URLParser.parseURL(a).params; | |
return !(!a || !a.song && !a.musician && !a.album && !a.playlist) | |
}; | |
this.getUrl = function(a) { | |
var b = Spotify.Web.URLParser.parseURL(a, !0); | |
if (!b.path) b.path = | |
""; | |
if (this.shouldPlay(a)) { | |
a = Spotify.Web.URLParser.parseURL(a).params; | |
a = c(a); | |
if (!a.contextUrl && a.trackUrl) a.contextUrl = a.trackUrl, a.trackUrl = void 0; | |
if (a.contextUrl) a = Spotify.Web.Utils.decodeOpenGraphUrl(a.contextUrl), b.path = "", a.user && (b.path += "user/" + a.user + "/"), b.path += a.context + "/" + a.contextId | |
} | |
return b.protocol + "://" + b.domain + "/" + b.path | |
}; | |
this.playUrl = function(a, b, d, f) { | |
if (this.shouldPlay(a)) { | |
a = Spotify.Web.URLParser.parseURL(a).params; | |
a = c(a); | |
if (!a.contextUrl && a.trackUrl) a.contextUrl = a.trackUrl, a.trackUrl = | |
void 0; | |
if (a.contextUrl) { | |
var j = Spotify.Web.Utils.openGraphUrlToSpotifyUri(a.contextUrl), | |
g; | |
if (a.trackUrl) g = Spotify.Web.Utils.decodeOpenGraphUrl(a.trackUrl).contextId; | |
Spotify.Web.Utils.decodeOpenGraphUrl(a.contextUrl).context === "artist" && g && (j = Spotify.Web.Utils.openGraphUrlToSpotifyUri(a.trackUrl), g = void 0); | |
b(j, g, d, f); | |
return !0 | |
} | |
} else return !1 | |
} | |
}; | |
Spotify.Web.OpenURLSchema = function() { | |
var c = RegExp("/(?:user/([\\w|\\-|\\.]*))?/?(ad|playlist|album|artist|track|radio/genre|radio/album|radio/artist|radio/track|radio)/(\\w{0,32})(?:.*?play=)?(true|\\w{0,32})?"), | |
a = RegExp("(trackset)/((?:[A-Za-z0-9]|%[0-9a-fA-F]{2}){0,32})?/?([\\w,%]+)/?(%23/(\\d{0,2})|\\?play=(true|\\w{0,32}))?/?"), | |
b = function(b) { | |
var f; | |
if (f = b.match(c)) return { | |
user: f[1] || null, | |
context: f[2] || null, | |
contextId: f[3] || null, | |
play: f[4] || null | |
}; | |
else if (f = b.match(a)) { | |
var j = f[3].split(/%2C|,/g), | |
b = | |
j.join(","), | |
g = f[1] + ":" + f[2], | |
k = f[5] || 0; | |
f = j.indexOf(f[6]); | |
f >= 0 && (k = f); | |
return { | |
user: null, | |
context: g, | |
contextId: b + ":%23:" + k, | |
play: "true" | |
} | |
} else return null | |
}; | |
this.shouldPlay = function(a) { | |
a = b(a); | |
return !(!a || !a.context || !(a.context === "track" || a.context === "ad" || a.play)) | |
}; | |
this.getUrl = function(a) { | |
a = Spotify.Web.URLParser.parseURL(a, !0); | |
if (!a.path) a.path = ""; | |
return a.protocol + "://" + a.domain + "/" + a.path | |
}; | |
this.playUrl = function(a, c, j, g) { | |
if (this.shouldPlay(a)) { | |
var a = b(a), | |
k = "spotify:"; | |
a.user && (k += "user:" + a.user + ":"); | |
k += a.context + | |
":" + a.contextId; | |
var l; | |
if (a.play !== "true") l = a.play; | |
a.context === "artist" && l && (k = "spotify:track:" + l, l = void 0); | |
c(k, l, j, g); | |
return !0 | |
} else return !1 | |
} | |
}; | |
Spotify.Web.OpenGraph = function(c, a, b, d, f) { | |
var j = new Spotify.Web.Context(a), | |
g = c.getApi().getAccessToken(); | |
new Spotify.Events; | |
var k, l = function(a, c, d) { | |
a = "https://graph.facebook.com/me/music.listens?song=" + a; | |
c && (a += "&" + c + "=" + d); | |
a += "&access_token=" + g; | |
(new Request.CORS({ | |
url: a, | |
data: null, | |
method: "post", | |
onSuccess: function(a) { | |
//TODO add Try/Catch | |
JSON.parse(a) | |
}, | |
onFailure: function(a) { | |
b.logError("web.fb.opengraph.js", a.statusText, a.responseText) | |
} | |
})).send() | |
}, | |
h = function(a, b, c) { | |
k && clearTimeout(k); | |
k = setTimeout(function() { | |
l(a, b, c); | |
clearTimeout(k) | |
}, | |
15E3) | |
}, | |
m = function() { | |
a.player.registerForPlayerEvents(function(a, b) { | |
if (!a) switch (b.type) { | |
case "play": | |
e(b); | |
break; | |
case "pause": | |
k && clearTimeout(k); | |
break; | |
case "stop": | |
k && clearTimeout(k) | |
} | |
m() | |
}) | |
}, | |
n = function(a) { | |
d.getPrivateSession() || d.getPostToOpenGraph(function(b) { | |
b && a() | |
}) | |
}, | |
e = function() { | |
j.getFacebookContextType(function(a, b) { | |
if (a) { | |
var c = b.context.uri, | |
d = b.track.uri, | |
e = Spotify.Web.Utils.spotifyUriToOpenUrl(d), | |
g = Spotify.Web.Utils.spotifyUriToOpenUrl(c); | |
d.indexOf(":ad:") > -1 || n(function() { | |
if (a === "playlist" || a === | |
"radio_station") { | |
var d; | |
d = a === "playlist" ? Spotify.Link.fromString(c) : Spotify.Link.fromString(b.context.stationUri); | |
f.canPublishPlaylist(d, function(b, c) { | |
c ? h(e, a, g) : h(e, null, null) | |
}) | |
} else h(e, a, g) | |
}) | |
} | |
}) | |
}; | |
this.start = function() { | |
m() | |
} | |
}; | |
Spotify.Web.AppNotifications = function(c, a, b) { | |
new Spotify.Events; | |
var d = null, | |
f = null, | |
j = null, | |
g = b.cdn + "/images/48.png", | |
k = function(a, b) { | |
f && f.cancel(); | |
f = webkitNotifications.createNotification(g, a, b); | |
f.show(); | |
setTimeout(function() { | |
f.cancel() | |
}, 3500) | |
}, | |
l = function(b, f) { | |
var e = f.data.track.uri; | |
h(); | |
if (typeof chrome !== "undefined" && chrome.app.isInstalled && a.getAppNotifications() && e && !(e.indexOf(":ad:") !== -1 || f.data.playing === !1)) clearTimeout(d), d = setTimeout(function() { | |
c.request("track_metadata", [e], function(a, b) { | |
if (b.uri !== | |
j) { | |
for (var c = "", d = 0; d < b.artists.length; d++) c += b.artists[d].name, d !== b.artists.length - 1 && (c += ", "); | |
j = b.uri; | |
k(b.name, c) | |
} | |
}) | |
}, 1E3) | |
}, | |
h = function() { | |
c.request("player_event_wait", ["main"], l) | |
}; | |
this.init = function() { | |
h() | |
} | |
}; | |
Spotify.Web.Player = function(c, a, b) { | |
var d = this, | |
f, j = b.iframe, | |
g = b.url, | |
k = b.publisher, | |
l = !1; | |
new Spotify.Events; | |
var h = !1, | |
m = a.audioManager.getPlayerAtIndex(0), | |
n = function(a, b) { | |
if (h !== b.data.playing) h = b.data.playing, h === !0 ? k.notify(Spotify.Web.PublisherMessages.USER_INTERACTION) : k.notify(Spotify.Web.PublisherMessages.USER_INTERACTION_PAUSE_PLAYBACK); | |
c.player.registerForPlayerStateChange(n); | |
!l && b.data.track && b.data.track.uri && (l = !0, d.showPlayer()) | |
}; | |
this.showPlayer = function() { | |
document.body.addClass("started"); | |
j.tabIndex = "0" | |
}; | |
this.initialize = function() { | |
f = new Spotify.Web.Window({ | |
url: g, | |
iframe: j | |
}); | |
f.initialize(); | |
c.player.registerForPlayerStateChange(n); | |
f.bind("onMessage", function(b) { | |
b.params && b.params.indexOf && b.params.indexOf("ad_clicked") !== -1 && c.player.getState(function(b, c) { | |
if (c.track && c.track.advertisement) a.adChooser.recordAdEvent("spotify:ad:" + m.ad.file_id, "click"), m.ad.clicked = !0 | |
}) | |
}) | |
} | |
}; | |
Spotify.Web.Ads = {}; | |
Spotify.Web.Ads.PixelTracker = function(c) { | |
this.bridge = c | |
}; | |
Spotify.Web.Ads.PixelTracker.prototype._registerForPlayerEvents = function() { | |
this.bridge.player.registerForPlayerEvents(this._onPlayerEvent.bind(this)) | |
}; | |
Spotify.Web.Ads.PixelTracker.prototype._onPlayerEvent = function(c, a) { | |
if (!c && a.type === "play") this.onTrackAboutToBePlayed(); | |
this._registerForPlayerEvents() | |
}; | |
Spotify.Web.Ads.PixelTracker.prototype.init = function() { | |
img = document.createElement("img"); | |
img.id = "tpx"; | |
document.getElementById("main-nav").appendChild(img); | |
this._registerForPlayerEvents() | |
}; | |
Spotify.Web.Ads.PixelTracker.prototype.onTrackAboutToBePlayed = function() { | |
this.bridge.player.getState(function(c, a) { | |
var b = a.track; | |
if (b && b.advertisement && typeof b.popularity === "string" && b.popularity.match(/^https/)) { | |
var d = b.popularity.replace(/\[timestamp\]/i, Date.now()); | |
setTimeout(function() { | |
img.src = d | |
}, 10) | |
} | |
}) | |
}; | |
Spotify.Web.Upsell = function(c, a, b) { | |
var d, f, j, g, k, l, h; | |
function m() { | |
var a = document.createElement("div"), | |
b = a.cloneNode(); | |
b.id = d; | |
var c = a.cloneNode(); | |
c.className = "content"; | |
var e = document.createElement("h3"); | |
e.className = "title"; | |
e.innerHTML = _("Enjoy"); | |
a = a.cloneNode(); | |
a.className = "subtitle"; | |
a.innerHTML = _("The full Spotify Experience"); | |
var g = document.createElement("button"); | |
g.id = f; | |
g.type = "button"; | |
g.tabIndex = -1; | |
g.className = j ? "btn btn-default" : "button"; | |
g.innerHTML = _("Get Started"); | |
var h = document.createElement("A"); | |
h.href = "https://itunes.apple.com/us/app/spotify/id324684580"; | |
h.className = "app-store-links iphone"; | |
h.target = "_blank"; | |
var k = document.createElement("A"); | |
k.href = "https://play.google.com/store/apps/details?id=com.spotify.music"; | |
k.className = "app-store-links android"; | |
k.target = "_blank"; | |
var l = document.createElement("A"); | |
l.href = "http://windowsphone.com/s?appId=10f2995d-1f82-4203-b7fa-46ddbd07a6e6"; | |
l.className = "app-store-links wp"; | |
l.target = "_blank"; | |
c.appendChild(e); | |
c.appendChild(a); | |
c.appendChild(g); | |
c.appendChild(h); | |
c.appendChild(k); | |
c.appendChild(l); | |
b.appendChild(c); | |
return b | |
} | |
var n = this, | |
c = c || {}; | |
g = c.onBeforeTimeout || 500; | |
k = c.loggingEnabled || !0; | |
l = c.controlGroup || 0; | |
j = c.useCat || !1; | |
h = c.useMft || !1; | |
var e = null, | |
o = !1, | |
t = _("An unexpected error occurred when sending the SMS"), | |
C = _("The phone number is invalid"); | |
this.simulation = !1; | |
f = "download-spotify"; | |
d = "desktop"; | |
var v = m(), | |
z = null, | |
w = null, | |
A = null; | |
this.init = function() { | |
var a = this.getDisplayMode(); | |
a && this.applyDisplayMode(a) | |
}; | |
this.getElement = function() { | |
v || (v = m()); | |
return v | |
}; | |
var c = function(a) { | |
window.location = | |
a.downloadLink | |
}, | |
x = function() { | |
var a = z.querySelector('input[name="phone_number"]'), | |
b = z.querySelector('button[class="button"]'), | |
c = z.querySelector(".error"); | |
/^\d{7,}$/.test(a.value.replace(/[\s()+\-\.]|ext/gi, "")) ? (a.setAttribute("disabled", "disabled"), b.setAttribute("disabled", "disabled"), c.innerHTML = "", (new Request({ | |
url: "/xhr/json/sms/send_sms.php", | |
method: "get", | |
data: { | |
phone_number: a.value | |
}, | |
onSuccess: function(d) { | |
try { | |
d = JSON.parse(d) | |
} catch (e) { | |
d = {} | |
} | |
if (typeof d.status !== "undefined" && d.status) z.querySelector(".phone-input").style.display = | |
"none", $(z.querySelector(".success-feedback")).addClass("show"), I("send_sms"); | |
else { | |
var f = t; | |
if (typeof d.message !== "undefined") f = d.message; | |
c.innerHTML = f; | |
a.removeAttribute("disabled"); | |
b.removeAttribute("disabled") | |
} | |
}, | |
onError: function() { | |
c.innerHTML = t; | |
a.removeAttribute("disabled"); | |
b.removeAttribute("disabled") | |
} | |
})).send()) : c.innerHTML = C | |
}, | |
u = { | |
mft: { | |
id: d, | |
label: "mft", | |
text: _("MftLaunchTitle"), | |
subText: "", | |
mainClass: "mft", | |
options: { | |
actions: { | |
".app-store-links": function(a) { | |
a.stop(); | |
var a = a.target, | |
b = a.className.replace("app-store-links ", | |
""); | |
I("mft_click", b); | |
window.open(a.href) | |
} | |
} | |
} | |
}, | |
android: { | |
id: "send-sms-android", | |
label: "android", | |
text: _("Get Spotify"), | |
subText: _("on your Android"), | |
buttonText: _("Get Started"), | |
mainClass: "android", | |
options: { | |
actions: { | |
".button": x | |
} | |
} | |
}, | |
iphone: { | |
id: "send-sms-iphone", | |
label: "iphone", | |
text: _("Get Spotify"), | |
subText: _("on your iPhone"), | |
buttonText: _("Get Started"), | |
mainClass: "iphone", | |
options: { | |
actions: { | |
".button": x | |
} | |
} | |
}, | |
windows: { | |
id: "download-dialog-windows", | |
label: "windows", | |
text: _("Install Spotify on Windows"), | |
subText: _("For the full Spotify experience"), | |
buttonText: _("Install Spotify"), | |
downloadLink: "http://download.spotify.com/Spotify%20Installer.exe", | |
mainClass: "desktop-background", | |
options: {}, | |
onBefore: c | |
}, | |
mac: { | |
id: "download-dialog-mac", | |
label: "mac", | |
text: _("Install Spotify on Your Mac"), | |
subText: _("For the full Spotify experience"), | |
buttonText: _("Install Spotify"), | |
downloadLink: "http://download.spotify.com/SpotifyInstaller.zip", | |
mainClass: "desktop-background", | |
options: {}, | |
onBefore: c | |
} | |
}; | |
this.getDisplayMode = function(a) { | |
var b; | |
if (h) b = u.mft; | |
else { | |
b = null; | |
var c = Spotify.Web.BrowserDetect.OS.toLowerCase(); | |
typeof u[c] !== "undefined" && (b = u[c]) | |
} | |
if (typeof a === "function") a(b); | |
else return b | |
}; | |
this.isEnabled = function() { | |
return e == null || e >= l || this.simulation | |
}; | |
this.applyDisplayMode = function(b) { | |
if (a !== null) a.onReady(function() { | |
a.getUserInfo(function(a) { | |
a && (e = parseInt(a.ab_test_group, 10)); | |
n.setDisplayMode(b) | |
}) | |
}, this) | |
}; | |
this.showPopup = function(a) { | |
if (!o) A = document.getElementById(f), z = document.getElementById(a.id), z.style.display = "block", w = z.querySelector(".dialog"), E(w, A), w.className += " show", o = !0, window.addEventListener("resize", | |
y, !1), window.addEventListener("keydown", B), z.addEventListener("click", F) | |
}; | |
this.hidePopup = function() { | |
if (o) { | |
var a = z.querySelector(".dialog"); | |
$(a).removeClass("show"); | |
z.style.display = "none"; | |
o = !1; | |
window.removeEventListener && (window.removeEventListener("resize", y), window.removeEventListener("keydown", B), z.removeEventListener("click", F)) | |
} | |
}; | |
this.setDisplayMode = function(a) { | |
if (a && this.isEnabled()) { | |
v.querySelector(".title").innerHTML = a.text; | |
v.querySelector(".subtitle").innerHTML = a.subText; | |
v.querySelector("button").innerHTML = | |
a.buttonText; | |
if (typeof a.mainClass !== "undefined") { | |
var b = v.querySelector(".content"); | |
b.className = "content"; | |
$(b).addClass("upsell-background"); | |
$(b).addClass(a.mainClass) | |
} | |
D(a); | |
G(a); | |
v.querySelector(".content").addClass("show"); | |
I("show_version", a.label) | |
} | |
}; | |
this.simulate = function(a) { | |
if (typeof u[a] !== "undefined") this.simulation = !0, this.setDisplayMode(u[a]) | |
}; | |
var y = function() { | |
E(w, A) | |
}, | |
B = function(a) { | |
a.keyCode == 27 && n.hidePopup() | |
}, | |
D = function(a) { | |
v.querySelector("#" + f).onclick = function() { | |
typeof a.onBefore !== "undefined" ? | |
(n.showPopup(a), window.setTimeout(function() { | |
a.onBefore(a) | |
}, g)) : n.showPopup(a); | |
I("click_version") | |
} | |
}, | |
G = function(a) { | |
if (typeof a.options.actions !== "undefined") | |
for (action in a.options.actions) a.options.actions.hasOwnProperty(action) && $$("#" + a.id).getElements(action).each(function(b) { | |
b.addEvent("click", function(b) { | |
a.options.actions[action](b) | |
}) | |
}) | |
}, | |
E = function(a, b) { | |
var c = $(b).getSize().y / 2, | |
d = $(b).getPosition(), | |
c = { | |
x: d.x - (a.getSize().x + 15), | |
y: d.y - a.getSize().y * 0.7 + c | |
}; | |
$(a).position(c) | |
}, | |
F = function(a) { | |
o && (!a.target || | |
!$(a.target).getParents().contains(z)) && n.hidePopup() | |
}, | |
I = function(a, c) { | |
k && b && b.event("upsell", a, c || "", 1) | |
} | |
}; | |
Spotify.Web.Storage.Cookie = function(c, a, b, d, f) { | |
var d = d || {}, | |
j = d.expires === 0 ? d.expires : d.expires || 360, | |
g = d.path || "/", | |
k, l; | |
this._read = function(a) { | |
this._getCookieName(function(c) { | |
if (c = Spotify.Web.Cookie.get(c, f)) try { | |
l = JSON.parse(b.decode(c.replace(/\_/g, "="))) | |
} catch (d) { | |
l = {} | |
} else l = {}; | |
typeof a !== "undefined" && a(l) | |
}) | |
}; | |
this._write = function(a) { | |
this._getCookieName(function(c) { | |
var d = h(b.encode(l ? JSON.stringify(l) : "")); | |
Spotify.Web.Cookie.set(c, d, { | |
ttl: j, | |
path: g, | |
secure: window.location && window.location.protocol === | |
"https:" | |
}, f); | |
typeof a !== "undefined" && a() | |
}) | |
}; | |
var h = function(a) { | |
return a.replace(/\=/g, "_") | |
}; | |
this._getCookieName = function(b) { | |
typeof k !== "undefined" && b(k); | |
a.getUsername(function(a) { | |
k = "spp_" + CryptoJS.MD5(c + a).toString().substring(0, 8); | |
b(k) | |
}, function() {}) | |
}; | |
this.init = function(a) { | |
var b = this; | |
typeof l !== "undefined" ? a() : this._read(function() { | |
b._migrate(a) | |
}) | |
}; | |
this._migrate = function(a) { | |
if (typeof l !== "undefined") | |
for (var c in l) | |
if (l.hasOwnProperty(c)) { | |
a(); | |
return | |
} | |
var d = this; | |
this._getOldCookieName(function(c) { | |
var g = | |
Spotify.Web.Cookie.get(c, f), | |
h; | |
if (g) try { | |
h = JSON.parse(b.decode(g.replace(/\_/g, "="))) | |
} catch (j) {} | |
typeof h !== "undefined" && (l = h, d._write(), Spotify.Web.Cookie.remove(c)); | |
a() | |
}, function() { | |
a() | |
}) | |
}; | |
this._getOldCookieName = function(d) { | |
a.getUsername(function(a) { | |
d(h(b.encode(c + a))) | |
}, function() { | |
d(void 0) | |
}) | |
}; | |
this.get = function(a) { | |
if (typeof l === "undefined") throw Error("Cookie " + c + " is not ready to be used yet!"); | |
return l[a] | |
}; | |
this.set = function(a, b) { | |
l || (l = {}); | |
l[a] = b; | |
this._write() | |
}; | |
this.remove = function(a) { | |
return typeof l[a] !== | |
"undefined" ? (delete l[a], this._write(), !0) : !1 | |
}; | |
this.destroy = function() { | |
l = {}; | |
this._write() | |
} | |
}; | |
Spotify.Web.Bookmark = function(c, a) { | |
this.STORAGE_KEY = "bookmark_seen"; | |
this.TIME_UNTIL_SHOWN = 1E4; | |
var b = this; | |
this.init = function() { | |
this.hasBeenShown() || typeof chrome !== "undefined" && chrome.app.isInstalled || setTimeout(function() { | |
b.show(); | |
b.markAsShown() | |
}, this.TIME_UNTIL_SHOWN) | |
}; | |
this.show = function() { | |
c.notify(Spotify.Web.PublisherMessages.ERROR, { | |
type: Spotify.Web.ErrorTypes.BOOKMARK | |
}) | |
}; | |
this.markAsShown = function() { | |
a.set(this.STORAGE_KEY, !0) | |
}; | |
this.hasBeenShown = function() { | |
return a.get(this.STORAGE_KEY) | |
} | |
}; | |
Spotify.Web.Settings.Model = function(c, a, b, d, f, j, g) { | |
Spotify.Web.EventTarget.call(this); | |
var k = this, | |
g = g || Spotify.Web.Cookie, | |
l, h, m, n, e, o, t, C, v = !1, | |
z = "", | |
w, A, x, u, y = window.navigator.userAgent.indexOf("MSIE 9") !== -1; | |
this._callbacks = []; | |
this._ready = !1; | |
this.init = function() { | |
function c(a, f) { | |
if (!a) l = f.product, u = f.publicToplist, A = f.publishActivity, x = f.publishPlaylists, m = f.postOpenGraph === "1", t = (C = f.developer) && d.get("dm") === "1", y || d.get("lastfm"), h = b.get("ps") === "1", n = g.get("is_spotified") === "yes", e = d.get("appnotifs") === | |
"1", o = g.get("locale", null), h && (x = A = !1), k._onReady() | |
} | |
d.init(function() { | |
a.request("session_query", [], c) | |
}) | |
}; | |
this._onReady = function() { | |
this._ready = !0; | |
for (var a = 0; a < this._callbacks.length; a++) this._callbacks[a](); | |
this._callbacks = [] | |
}; | |
this.setServices = function(a) { | |
w = a | |
}; | |
this.onReady = function(a) { | |
this._ready ? a() : this._callbacks.push(a) | |
}; | |
this.getLastFmUser = function() { | |
return z | |
}; | |
this.setLastFmUser = function(a) { | |
z = a; | |
d.set("lastfm-user", a); | |
this.onUpdated() | |
}; | |
this.getProduct = function() { | |
return j.isAnonymous() ? "anonymous" : | |
l | |
}; | |
this.getPrivateSession = function() { | |
return h | |
}; | |
this.getPublishToFacebookState = function(a) { | |
w.getFacebookUserId(function(b) { | |
!b || b === "None" ? a(null, { | |
is_connected: !1 | |
}) : f.checkPublishActionsPermissions(function(b, c) { | |
b ? b === "not_logged_in" ? a(null, { | |
is_connected: !0, | |
is_logged_in: !1 | |
}) : a(b) : a(null, { | |
is_connected: !0, | |
is_logged_in: !0, | |
publish_allowed: c | |
}) | |
}) | |
}) | |
}; | |
this.setPrivateSession = function(a, c, d, e) { | |
h = a; | |
c && b.set("ps", h ? "1" : "0"); | |
if (!e && (h ? (b.set("soc_pa", this.getPublishActivity() ? "1" : "0"), b.set("soc_pp", this.getPublishPlaylist() ? | |
"1" : "0"), b.set("soc_og", m ? "1" : "0"), this.setPublishActivity(!1, !1, !1), this.setPublishPlaylist(!1, !1, !1), this.setPostToOpenGraph(!1, !1, !1)) : (this.setPublishActivity(b.get("soc_pa") === "1", !1, !1), this.setPublishPlaylist(b.get("soc_pp") === "1", !1, !1), this.setPostToOpenGraph(b.get("soc_og") === "1", !1, !1)), d)) this.onUpdated() | |
}; | |
this.getOpenUrlsDesktops = function() { | |
return n || !1 | |
}; | |
this.setOpenUrlsDesktops = function(a) { | |
(n = a) ? g.set("is_spotified", "yes", { | |
domain: g.domain, | |
ttl: 1337 | |
}): g.remove("is_spotified", null, g.domain) | |
}; | |
this.getAppNotifications = function() { | |
return e | |
}; | |
this.setAppNotifications = function(a) { | |
e = a; | |
d.set("appnotifs", e ? "1" : "0") | |
}; | |
this.getLastFmConnected = function() { | |
return v | |
}; | |
this.setLastFmConnected = function(a) { | |
v = a; | |
d.set("lastfm-connected", v ? "1" : "0"); | |
this.onUpdated() | |
}; | |
this.lastFmDisconnect = function() { | |
var a = this; | |
c.user.setUserAttribute("lastfm_session", "", function() { | |
a.setLastFmConnected(!1); | |
a.setLastFmUser("") | |
}, function() {}) | |
}; | |
this.lastFmConnect = function(a, b) { | |
var d = this; | |
c.user.setUserAttribute("lastfm_session", | |
b + "|" + a, | |
function() { | |
d.setLastFmConnected(!0); | |
d.setLastFmUser(a) | |
}, | |
function() {}) | |
}; | |
this.getLastFmScrobble = function() { | |
return this.getLastFmConnected() && !h | |
}; | |
this.connectToLastFm = function() { | |
this.trigger(Spotify.Web.PublisherMessages.LASTFM_CONNECT) | |
}; | |
this.connectToFacebook = function(a, b) { | |
f.connectUser(function(d, e) { | |
c.facebook.enable(e, a, b) | |
}, b) | |
}; | |
this.getPublishActivity = function() { | |
return A | |
}; | |
this.setPublishActivity = function(a, b, c) { | |
A = a; | |
if (b) this._setUserAttribute("publish_activity", A ? "1" : "0", c); | |
else if (c) k.onUpdated() | |
}; | |
this.getPublishPlaylist = function() { | |
return x | |
}; | |
this.setPublishPlaylist = function(a, b, c) { | |
x = a; | |
if (b) this._setUserAttribute("publish_playlist", x ? "1" : "0", c); | |
else if (c) k.onUpdated() | |
}; | |
this.getPostToOpenGraph = function(a) { | |
this.getPublishToFacebookState(function(b, c) { | |
b || !c.is_connected || !c.publish_allowed ? a(!1) : a(m) | |
}) | |
}; | |
this.setPostToOpenGraph = function(a, b, c) { | |
var d = function(a) { | |
m = a; | |
if (b) k._setUserAttribute("post_open_graph", a ? "1" : "0", c); | |
else if (c) k.onUpdated() | |
}; | |
a ? this.getPublishToFacebookState(function(a, b) { | |
!a && | |
b.is_connected && b.publish_allowed ? d(!0) : f.requestExtentedPermissions(function(a, b) { | |
if (a || !b) { | |
if (c) k.onUpdated() | |
} else d(!0) | |
}) | |
}) : d(!1) | |
}; | |
this.getPublicTopTracks = function() { | |
return u & 4 ? !0 : !1 | |
}; | |
this.setPublicTopTracks = function(a, b, c) { | |
u = a ? u |= 4 : u &= -5; | |
if (b) this._setUserAttribute("public_toplist", u.toString(), c); | |
else if (c) k.onUpdated() | |
}; | |
this.getPublicTopArtists = function() { | |
return u & 1 ? !0 : !1 | |
}; | |
this.setPublicTopArtists = function(a, b, c) { | |
u = a ? u |= 1 : u &= -2; | |
if (b) this._setUserAttribute("public_toplist", u.toString(), c); | |
else if (c) k.onUpdated() | |
}; | |
this.setLocale = function(a, b) { | |
o = a; | |
Spotify.Web.Cookie.set("locale", a, { | |
ttl: 1460 | |
}); | |
this._setUserAttribute("preferred_locale", o ? o : "", !1); | |
if (b) this.onUpdated() | |
}; | |
this._setUserAttribute = function(b, c, d) { | |
a.request("user_set_attribute", [b, c], function() { | |
if (d) k.onUpdated() | |
}) | |
}; | |
this.getLocale = function() { | |
return o || "en" | |
}; | |
this.setDeveloperMode = function(a) { | |
t = a; | |
d.set("dm", t ? "1" : "0") | |
}; | |
this.getDeveloperMode = function() { | |
return t || !1 | |
}; | |
this.isDeveloperModeAllowed = function() { | |
return C || !1 | |
}; | |
this.triggerSignUp = function() { | |
j.signUp(function() {}) | |
}; | |
this.triggerLogin = function() { | |
j.login(function() {}) | |
}; | |
this.onUpdated = function() { | |
this.trigger(Spotify.Web.PublisherMessages.MODEL_UPDATED) | |
} | |
}; | |
Spotify.Web.Settings.View = function(c, a) { | |
Spotify.Web.EventTarget.call(this); | |
var b = this; | |
this._scrollBlocker = c.scrollBlocker; | |
this._wrapper = c.wrapper; | |
this._isOpen = !1; | |
var d = window.navigator.userAgent.indexOf("MSIE 9") !== -1, | |
f = c.publisher, | |
j = function(a) { | |
a.preventDefault(); | |
b._model.triggerSignUp() | |
}, | |
g = function(a) { | |
a.preventDefault(); | |
b.trigger(Spotify.Web.PublisherMessages.APPLICATION_OPEN_URI, { | |
link: Spotify.Link.fromString("spotify:app:purchase") | |
}) | |
}; | |
this.init = function() { | |
b._eUserBasedSettings = b._wrapper.querySelector(".user-settings"); | |
d && (b._eUserBasedSettings.className += " ie9"); | |
var a = b._wrapper.querySelector("#about-link"); | |
a && a.addEventListener("click", function(a) { | |
a.preventDefault(); | |
b.trigger(Spotify.Web.PublisherMessages.APPLICATION_OPEN_URI, { | |
link: Spotify.Link.fromString("spotify:app:" + this.getAttribute("data-href")) | |
}); | |
b._wrapper.blur() | |
}, !1); | |
(a = b._wrapper.querySelector("#spotify-jazz-panel a")) && a.addEventListener("click", function(a) { | |
a.preventDefault(); | |
b.trigger(Spotify.Web.PublisherMessages.APPLICATION_OPEN_URI, { | |
link: Spotify.Link.fromString("spotify:app:labs") | |
}); | |
b._wrapper.blur() | |
}, !1); | |
f.subscribe(Spotify.Web.PublisherMessages.SOCIAL_DATA_SUCCESS, this); | |
f.subscribe(Spotify.Web.PublisherMessages.USER_INTERACTION, this) | |
}; | |
this.onNotify = function(a) { | |
switch (a.messageType) { | |
case Spotify.Web.PublisherMessages.SOCIAL_DATA_SUCCESS: | |
b.addUserInfo(a.message) | |
} | |
}; | |
this.setServices = function() {}; | |
this.setModel = function(a) { | |
this.hideLoadingIndicator(); | |
this.createUserBasedDOM(); | |
this.addUserBasedEventListeners(); | |
this._model = a; | |
this._model.onReady(function() { | |
b._model.setLocale(b._currentLocale, !1); | |
b._model.bind(Spotify.Web.PublisherMessages.MODEL_UPDATED, b.onModelUpdated); | |
b.onModelUpdated() | |
}) | |
}; | |
this.hideLoadingIndicator = function() { | |
b._wrapper.querySelector(".initial").style.display = "none" | |
}; | |
this.createUserBasedDOM = function() { | |
var c = "", | |
c = a.cat_enabled ? ['<div class="account" id="account-info">\n <div id="account-info-pic" class="media simple user">\n <div class="media-image placeholder-visible">\n <a class="media-placeholder">\n <svg viewBox="0 0 10 10" preserveAspectRatio="xMidYMid meet">\n <text class="user-placeholder" x="5" y="9.8"></text>\n </svg>\n </a>\n <div class="media-image-internal">\n <span class="verified-badge">\n <span class="spoticon-check-16"></span>\n </span>\n </div>\n </div>\n </div>\n <div class="clearfix"></div>\n <div id="user-name" class="hdr-l text-center"></div>\n <div class="account text-center text-secondary">', | |
" " + _("Account") + " :", ' <span id="account-type"></span>\n </div>\n <div class="account-links text-center">', ' <a target="_blank" class="btn btn-info" href="/redirect/www/account-page/">' + _("View Account") + "</a>", ' <a id="btn-upgrade" target="_blank" href="/redirect/www/upgrade-product/" class="btn btn-primary">' + _("Upgrade") + "</a>", ' </div>\n</div>\n<div class="section hidden">', ' <div class="description lang-select">' + _("Choose language") + "</div>", ' <div class="action" id="lang-select"></div>\n <div id="lang-changed">\n <span></span>\n <a class="reload" href="/"></a>\n </div>\n</div>\n<div class="section privatesession">', | |
' <div class="description">' + _("Private Session"), ' <div id="private-session-indicator" class="description-subtitle">', " " + _("Private session lasts until you log out."), ' </div>\n </div>\n <div class="action" id="private-session"></div>\n</div>' | |
].join("\n") : ['<div class="section account" id="account-info">\n <div class="description">\n <div class="wrapper" id="user-info">\n <div id="user-name"></div>\n <div class="account">', " " + _("Account") + " :", ' <span id="account-type"></span>\n </div>\n </div>\n </div>\n <div class="action account-links">', | |
' <a target="_blank" class="button" href="/redirect/www/account-page/">' + _("View Account") + "</a>", ' <a id="btn-upgrade" target="_blank" href="/redirect/www/upgrade-product/" class="button primary">' + _("Upgrade") + "</a>", ' </div>\n</div>\n<div class="section hidden">', ' <div class="description lang-select">' + _("Choose language") + "</div>", ' <div class="action" id="lang-select"></div>\n <div id="lang-changed">\n <span></span>\n <a class="reload" href="/"></a>\n </div>\n</div>\n<div class="section privatesession">', | |
' <div class="description">' + _("Private Session") + "</div>", ' <div class="action" id="private-session"></div>\n <div id="private-session-indicator"><span></span>', " <p><strong>" + _("Private Session") + "</strong>", " <span>" + _("Private session lasts until you log out.") + "</span></p>", " </div>\n</div>" | |
].join("\n"); | |
b._eUserBasedSettings.innerHTML = [c, '<div class="section hidden fbconnect" id="fbconnect">', ' <div class="description">' + _("Connect my account to Facebook") + "</div>", ' <div class="action" id="connect-to-fb"></div>', | |
' <a id="fbconnect-btn" href="#" class="button btn btn-info pull-right">' + _("Connect") + "</a>", ' <div class="spinner" class="hidden" id="fbconnect-spinner"><img src="' + a.cdn + '/images/loading_throbber.gif" alt=""></div>', '</div>\n<div class="section hidden fb" id="og-share">', ' <div class="description">' + _("Share activity on Facebook") + "</div>", ' <div class="action" id="post-to-open-graph"></div>\n <div class="privatemode"></div>\n</div>\n<div class="section">', ' <div class="description">' + _("Share my activity and what I listen to with my followers on Spotify") + | |
"</div>", ' <div class="action" id="publish-activity"></div>\n <div class="privatemode"></div>\n</div>\n<div class="section">', ' <div class="description">' + _("Automatically make new playlists public") + "</div>", ' <div class="action" id="publish-playlist"></div>\n</div>\n<div class="section">', ' <div class="description">' + _("Show the Top Artists I've been listening to") + "</div>", ' <div class="action" id="public-top-artists"></div>\n</div>\n<div class="section">', ' <div class="description">' + _("Play open.spotify.com URLs in desktop app") + | |
"</div>", ' <div class="action" id="open-urls-desktop"></div>\n</div>\n<div class="section hidden notif">', ' <div class="description">' + _("Show app notifications") + "</div>", ' <div class="action" id="app-notifications"></div>\n</div>\n<div class="section hidden devmode">', ' <div class="description">' + _("Enable developer mode") + "</div>", ' <div class="action" id="developer-mode"></div>', ' <div id="developer-mode-changed"><span>' + _("Your changes will be applied when you reload the page."), ' </span><a class="button primary" href="/">' + | |
_("Reload now") + "</a>", ' </div>\n</div>\n<div class="section lastfm">', ' <div class="description">' + _("Scrobble to Last.fm") + "</div>", ' <div class="action" id="lastfm-scrobble"></div>', ' <a id="lastfm-connect" href="#" class="button btn btn-info pull-right">' + _("Connect") + "</a>", ' <div id="lastfm-connected"></div>\n <div class="privatemode"></div>\n</div>' | |
].join("\n"); | |
this._eAccountInfoWrap = b._eUserBasedSettings.querySelector("#account-info"); | |
this._eUserInfo = b._eUserBasedSettings.querySelector("#user-info"); | |
this._eUserName = b._eUserBasedSettings.querySelector("#user-name"); | |
this._eLangSelectWrap = b._eUserBasedSettings.querySelector("#lang-select"); | |
this._eLangSelector = b._eUserBasedSettings.ownerDocument.createElement("select"); | |
this._eLangChangedNotifier = b._eUserBasedSettings.querySelector("#lang-changed"); | |
this._eProduct = b._eUserBasedSettings.querySelector("#account-type"); | |
this._ePrivateSessionWrapper = b._eUserBasedSettings.querySelector("#private-session"); | |
this._ePrivateSessionIndicator = b._eUserBasedSettings.querySelector("#private-session-indicator"); | |
this._ePostToOpenGraphWrapper = b._eUserBasedSettings.querySelector("#post-to-open-graph"); | |
this._ePublishActivityWrapper = b._eUserBasedSettings.querySelector("#publish-activity"); | |
this._ePublishPlaylistWrapper = b._eUserBasedSettings.querySelector("#publish-playlist"); | |
this._ePublicTopArtistsWrapper = b._eUserBasedSettings.querySelector("#public-top-artists"); | |
this._eOpenUrlsDesktopsWrapper = b._eUserBasedSettings.querySelector("#open-urls-desktop"); | |
this._eAppNotificationsWrapper = b._eUserBasedSettings.querySelector("#app-notifications"); | |
this._eMediaImage = b._eUserBasedSettings.querySelector(".media-image"); | |
this._eMediaImageInternal = b._eUserBasedSettings.querySelector(".media-image-internal"); | |
this._eDeveloperModeWrapper = b._eUserBasedSettings.querySelector("#developer-mode"); | |
this._eDeveloperModeChangedNotifier = b._eUserBasedSettings.querySelector("#developer-mode-changed"); | |
this._eFbConnectWrapper = b._eUserBasedSettings.querySelector("#fbconnect"); | |
this._eFbConnectBtn = b._eUserBasedSettings.querySelector("#fbconnect-btn"); | |
this._eFbConnectSpinner = | |
b._eUserBasedSettings.querySelector("#fbconnect-spinner"); | |
this._eFbOptionsWrapper = b._eUserBasedSettings.querySelector("#og-share"); | |
this._eLastFmWrapper = b._eUserBasedSettings.querySelector("#lastfm-scrobble"); | |
this._eLastFmConnect = b._eUserBasedSettings.querySelector("#lastfm-connect"); | |
this._eLastFmConnected = b._eUserBasedSettings.querySelector("#lastfm-connected"); | |
this._eUpgradeBtn = b._eUserBasedSettings.querySelector("#btn-upgrade"); | |
b._eUpgradeBtn.style.display = "none"; | |
this._eLogoutBtn = b._wrapper.querySelector(".logout"); | |
this._ePrivateModeDisablers = b._wrapper.querySelectorAll(".privatemode"); | |
this._spotifyJazzPanel = b._wrapper.querySelectorAll("#spotify-jazz-panel")[0]; | |
this._ePrivateSession = new Spotify.Web.Widgets.Toggle({ | |
onChange: function() { | |
b._model.setPrivateSession(this.isActive, !0, !0) | |
}, | |
activated: !1, | |
document: b._eUserBasedSettings.ownerDocument | |
}); | |
this._ePrivateSessionWrapper.appendChild(this._ePrivateSession.node); | |
this._ePostToOpenGraph = new Spotify.Web.Widgets.Toggle({ | |
onChange: function() { | |
b._model.setPostToOpenGraph(this.isActive, !0, !0) | |
}, | |
activated: !1, | |
document: b._eUserBasedSettings.ownerDocument | |
}); | |
this._ePostToOpenGraphWrapper.appendChild(this._ePostToOpenGraph.node); | |
this._ePublishActivity = new Spotify.Web.Widgets.Toggle({ | |
onChange: function() { | |
b._model.setPublishActivity(this.isActive, !0, !0) | |
}, | |
activated: !1, | |
document: b._eUserBasedSettings.ownerDocument | |
}); | |
this._ePublishActivityWrapper.appendChild(this._ePublishActivity.node); | |
this._ePublishPlaylist = new Spotify.Web.Widgets.Toggle({ | |
onChange: function() { | |
b._model.setPublishPlaylist(this.isActive, !0, !0) | |
}, | |
activated: !1, | |
document: b._eUserBasedSettings.ownerDocument | |
}); | |
this._ePublishPlaylistWrapper.appendChild(this._ePublishPlaylist.node); | |
this._ePublicTopArtists = new Spotify.Web.Widgets.Toggle({ | |
onChange: function() { | |
b._model.setPublicTopArtists(this.isActive, !0, !0) | |
}, | |
activated: !1, | |
document: b._eUserBasedSettings.ownerDocument | |
}); | |
this._ePublicTopArtistsWrapper.appendChild(this._ePublicTopArtists.node); | |
this._eOpenUrlsDesktops = new Spotify.Web.Widgets.Toggle({ | |
onChange: function() { | |
b._model.setOpenUrlsDesktops(this.isActive) | |
}, | |
activated: !1, | |
document: b._eUserBasedSettings.ownerDocument | |
}); | |
this._eOpenUrlsDesktopsWrapper.appendChild(this._eOpenUrlsDesktops.node); | |
this._eAppNotifications = new Spotify.Web.Widgets.Toggle({ | |
onChange: function() { | |
b._model.setAppNotifications(this.isActive) | |
}, | |
activated: !1, | |
document: b._eUserBasedSettings.ownerDocument | |
}); | |
this._eAppNotificationsWrapper.appendChild(this._eAppNotifications.node); | |
this._eDeveloperMode = new Spotify.Web.Widgets.Toggle({ | |
onChange: function() { | |
b._model.setDeveloperMode(this.isActive); | |
b.onDeveloperModeChange() | |
}, | |
activated: !1, | |
document: b._eUserBasedSettings.ownerDocument | |
}); | |
this._eDeveloperModeWrapper.appendChild(this._eDeveloperMode.node); | |
this._eLastFmConnect.addEventListener("click", function(a) { | |
a.preventDefault(); | |
b._model.connectToLastFm() | |
}, !1); | |
var d = function(a) { | |
a.className.indexOf("hidden") == -1 && (a.className += " hidden") | |
}, | |
f = function(a) { | |
a.className = a.className.replace("hidden", "") | |
}; | |
this.userHasFacebook = function() { | |
b._eFbOptionsWrapper.className = "section"; | |
d(b._eFbConnectWrapper) | |
}; | |
this.userDoesNotHaveFacebook = | |
function() { | |
f(b._eFbConnectWrapper); | |
d(b._eFbOptionsWrapper) | |
}; | |
this.manageFacebookOptions = function() { | |
b._model.getPublishToFacebookState(function(a, c) { | |
d(b._eFbConnectSpinner); | |
f(b._eFbConnectBtn); | |
a || !c.is_connected ? b.userDoesNotHaveFacebook() : b.userHasFacebook() | |
}) | |
}; | |
b._eFbConnectBtn.addEventListener("click", function(a) { | |
a.preventDefault(); | |
d(b._eFbConnectBtn); | |
f(b._eFbConnectSpinner); | |
b._model.connectToFacebook(b.manageFacebookOptions, function() { | |
f(b._eFbConnectBtn); | |
d(b._eFbConnectSpinner) | |
}) | |
}, !1); | |
if (typeof chrome !== | |
"undefined" && chrome.app.isInstalled) b._eUserBasedSettings.querySelector(".notif").className = "section"; | |
if (a.locale.available.length > 1) b._eLangSelectWrap.parentNode.className = "section"; | |
b._currentLocale = a.locale.current; | |
for (var c = b._eUserBasedSettings.ownerDocument.createDocumentFragment(), g = 0; g < a.locale.available.length; g++) { | |
var e = a.locale.available[g], | |
j = b._eUserBasedSettings.ownerDocument.createElement("option"); | |
j.textContent = _("lang/" + e); | |
j.value = e; | |
e === a.locale.current && j.setAttribute("selected", "selected"); | |
c.appendChild(j) | |
} | |
b._eLangSelector.appendChild(c); | |
b._eLangSelectWrap.appendChild(b._eLangSelector); | |
b._eLangSelector.addEventListener("change", function() { | |
var a = this.options[this.selectedIndex].value; | |
a !== b._model.getLocale() && b._model.setLocale(a, !0) | |
}) | |
}; | |
this.addUserInfo = function(c) { | |
if (c.image !== "") { | |
if (a.cat_enabled) this._eMediaImageInternal.style.backgroundImage = "url(" + c.image + ")", this._eMediaImage.removeClass("placeholder-visible"); | |
else { | |
var d = new Image; | |
d.onload = function() { | |
b._eUserInfo.addClass("user-info-added"); | |
b._eAccountInfoWrap.addClass("user-info-added"); | |
b._eUserInfo.appendChild(this); | |
setTimeout(function() { | |
d.className = "show" | |
}, 10) | |
}; | |
d.src = c.image | |
} | |
profileImage = c.image | |
} | |
if (c.name !== "") b._eUserName.textContent = c.name + " " + c.surname | |
}; | |
this.addUserBasedEventListeners = function() { | |
this._eLogoutBtn.addEventListener("click", k, !1) | |
}; | |
this.getVerboseProductName = function(a) { | |
if (a === "anonymous") return _("Not signed in"); | |
else if (a === "free" || a === "open") return _("Free"); | |
else if (a === "basic-desktop") return _("Unlimited"); | |
else if (a === | |
"premium") return _("Premium"); | |
return _("Unknown") | |
}; | |
this.onDeveloperModeChange = function() { | |
this._eDeveloperModeChangedNotifier.className = "show" | |
}; | |
this.onLocaleChange = function() { | |
var c = new XMLHttpRequest; | |
c.onreadystatechange = function() { | |
if (c.readyState === 4 && c.status === 200) { | |
//TODO add Try/Catch. What would happen if you can't parse c.responseText? | |
var a = JSON.parse(c.responseText), | |
d = "Your language choice will be applied when you reload the page."; | |
a[d] && (d = a[d]); | |
var e = "Reload now"; | |
a[e] && (e = a[e]); | |
b._eLangChangedNotifier.querySelector("span").innerHTML = d; | |
b._eLangChangedNotifier.querySelector("a").innerHTML = | |
e; | |
b._eLangChangedNotifier.className = "show" | |
} | |
}; | |
var d = "/xhr/json/translations.php?locale=" + b._model.getLocale() + "&cb=" + a.version; | |
c.open("GET", d, !0); | |
c.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); | |
c.send() | |
}; | |
this.onPrivateSessionOn = function() { | |
this._ePrivateSession.activate(!0); | |
this._ePrivateSessionIndicator.addClass("show"); | |
for (var a = 0; a < this._ePrivateModeDisablers.length; a++) this._ePrivateModeDisablers[a].addClass("show") | |
}; | |
this.onPrivateSessionOff = function() { | |
this._ePrivateSession.deactivate(!0); | |
this._ePrivateSessionIndicator.removeClass("show"); | |
for (var a = 0; a < this._ePrivateModeDisablers.length; a++) this._ePrivateModeDisablers[a].removeClass("show") | |
}; | |
this.getContent = function() { | |
return this._wrapper | |
}; | |
this.onModelUpdated = function() { | |
b.manageFacebookOptions(); | |
var c = b._model.getProduct(); | |
if (c === "free" || c === "open") b._eLogoutBtn.style.display = "inline-block"; | |
if (c === "anonymous") b._eLogoutBtn.style.display = "none"; | |
if (c === "premium") b._eProduct.className = "premium"; | |
b._eProduct.innerHTML = b.getVerboseProductName(c); | |
b._upgradeBtnUrl && b._upgradeBtnText ? (b._eUpgradeBtn.textContent = b._upgradeBtnText, b._eUpgradeBtn.style.display = "inline-block", b._eUpgradeBtn.addEventListener("click", g)) : c === "anonymous" ? (b._eUpgradeBtn.style.display = "inline-block", b._eUpgradeBtn.textContent = _("Sign Up"), b._eUpgradeBtn.addEventListener("click", j), b._eUpgradeBtn.removeEventListener("click", g)) : (b._eUpgradeBtn.removeEventListener("click", j), b._eUpgradeBtn.addEventListener("click", g)); | |
b._model.getPrivateSession() ? b.onPrivateSessionOn() : | |
b.onPrivateSessionOff(); | |
b._model.getPostToOpenGraph(function(a) { | |
a ? b._ePostToOpenGraph.activate(!0) : b._ePostToOpenGraph.deactivate(!0) | |
}); | |
b._model.getPublishActivity() ? b._ePublishActivity.activate(!0) : b._ePublishActivity.deactivate(!0); | |
b._model.getPublishPlaylist() ? b._ePublishPlaylist.activate(!0) : b._ePublishPlaylist.deactivate(!0); | |
b._model.getPublicTopArtists() ? b._ePublicTopArtists.activate(!0) : b._ePublicTopArtists.deactivate(!0); | |
b._model.getOpenUrlsDesktops() ? b._eOpenUrlsDesktops.activate() : b._eOpenUrlsDesktops.deactivate(); | |
b._model.getAppNotifications() ? b._eAppNotifications.activate() : b._eAppNotifications.deactivate(); | |
c = b._model.getLocale(); | |
b._model.getDeveloperMode() ? b._eDeveloperMode.activate(!0) : b._eDeveloperMode.deactivate(!0); | |
if (b._model.isDeveloperModeAllowed()) { | |
var d = b._eUserBasedSettings.querySelector(".devmode"); | |
if (d) d.className = "section" | |
} | |
if (b._currentLocale && c !== b._currentLocale) b._currentLocale = c, b.onLocaleChange(); | |
b._model.getLastFmConnected() ? (b._eLastFmConnect.style.display = "none", b._eLastFmConnected.style.display = | |
"block", b._eLastFmConnected.innerHTML = ": " + _("Connected as <strong>{{USERNAME}}</strong>. <a target='_blank' href='{{DISCONNECT_URL}}'>(Disconnect)</a>", { | |
USERNAME: b._model.getLastFmUser() || "", | |
DISCONNECT_URL: "http://www.last.fm/settings/applications" | |
}), b._eLastFmConnected.querySelector("a").addEventListener("click", function() { | |
b._model.lastFmDisconnect() | |
}, !1)) : (b._eLastFmConnect.style.display = "block", b._eLastFmConnected.style.display = "none"); | |
b._spotifyJazzPanel.style.display = a.features.labs ? "block" : | |
"none" | |
}; | |
this.setUpgradeButton = function(a, b) { | |
this._upgradeBtnUrl = b ? b : "/redirect/www/upgrade-product/"; | |
this._upgradeBtnText = a; | |
this._eUpgradeBtn.style.display = "inline" | |
}; | |
var k = function() { | |
b._model.setPrivateSession(!1, !0, !1, !0) | |
} | |
}; | |
Spotify.Web.SettingsApp = function(c) { | |
var a = document.createElement("div"); | |
a.id = "settings-pane"; | |
a.className = "col-sm-12 col-md-10 col-lg-8 col-md-offset-1 col-lg-offset-2"; | |
_("Need more help? {{LINK_START}}Read the guide{{LINK_END}}", { | |
LINK_START: '<a target="_blank" href="http://www.spotify.com/help/guides/account/">', | |
LINK_END: "</a>" | |
}); | |
_("Your Spotify Download should start within seconds. If it doesn't, {{LINK_START}}restart the download{{LINK_END}}", { | |
LINK_START: '<a href="http://download.spotify.com/Spotify%20Installer.exe">', | |
LINK_END: "</a>" | |
}); | |
_("Your Spotify Download should start within seconds. If it doesn't, {{LINK_START}}restart the download{{LINK_END}}", { | |
LINK_START: '<a href="http://download.spotify.com/SpotifyInstaller.zip">', | |
LINK_END: "</a>" | |
}); | |
a.innerHTML = c ? ['<div class="main">\n <div class="initial section">\n <div class="description">', " " + _("Loading") + "...", ' </div>\n </div>\n <div class="user-settings"><\!-- User based settings will be added here --\></div>\n <div id="spotify-jazz-panel" style="display: none">', | |
" " + _("SettingsJazzIntroLine"), ' <a href="#">' + _("SettingsJazzLink") + "</a>", ' </div>\n <div class="logout-area text-center">', ' <a id="logout-settings" href="/logout" class="logout btn btn-info">' + _("Log Out") + "</a>", ' </div>\n <div class="text-center text-secondary">', ' <a href="/about" data-href="about" id="about-link">' + _("About") + "</a> | ", ' <a href="https://www.spotify.com/legal/end-user-agreement/?utm_source=web-player" target="_blank" id="legal-link">' + _("Legal") + | |
"</a> | ", ' <a href="/redirect/www/help/" target="_blank" id="help-link">' + _("Help") + "</a>", " </div>\n</div>" | |
].join("\n") : ['<div class="main">', " <h2>" + _("Settings") + "</h2>", ' <a id="logout-settings" href="/logout" class="logout button">' + _("Log Out") + "</a>", ' <div class="initial section">\n <div class="description">', " " + _("Loading") + "...", ' </div>\n </div>\n <div class="user-settings"><\!-- User based settings will be added here --\></div>\n <div id="spotify-jazz-panel" style="display: none">', | |
" " + _("SettingsJazzIntroLine"), ' <a href="#">' + _("SettingsJazzLink") + "</a>", ' </div>\n <div class="bottom">\n <div class="description">', ' <a href="/about" data-href="about" id="about-link">' + _("About") + "</a> | ", ' <a href="https://www.spotify.com/legal/end-user-agreement/?utm_source=web-player" target="_blank" id="legal-link">' + _("Legal") + "</a> | ", ' <a href="/redirect/www/help/" target="_blank" id="help-link">' + _("Help") + "</a>", " </div>\n </div>\n</div>" | |
].join("\n"); | |
this.getElement = function() { | |
return a | |
}; | |
this.destroyElement = function() {} | |
}; | |
Spotify.Web.Settings.Anonymous = function(c, a) { | |
Spotify.Web.EventTarget.call(this); | |
var b = this; | |
this._scrollBlocker = c.scrollBlocker; | |
this._wrapper = c.wrapper; | |
this._isOpen = !1; | |
var d = c.publisher; | |
this.init = function() { | |
b._eUserBasedSettings = b._wrapper.querySelector(".user-settings"); | |
var a = b._wrapper.querySelector("#about-link"); | |
a && a.addEventListener("click", function(a) { | |
a.preventDefault(); | |
b.trigger(Spotify.Web.PublisherMessages.APPLICATION_OPEN_URI, { | |
link: Spotify.Link.fromString("spotify:app:" + this.getAttribute("data-href")) | |
}); | |
b._wrapper.blur() | |
}, !1); | |
d.subscribe(Spotify.Web.PublisherMessages.USER_INTERACTION, this) | |
}; | |
this.onNotify = function(a) { | |
switch (a.messageType) { | |
case Spotify.Web.PublisherMessages.USER_INTERACTION: | |
b.close() | |
} | |
}; | |
this.setServices = function() {}; | |
this.setModel = function(a) { | |
this.hideLoadingIndicator(); | |
this.createUserBasedDOM(); | |
this._model = a; | |
this._model.bind(Spotify.Web.PublisherMessages.MODEL_UPDATED, this.onModelUpdated); | |
this.onModelUpdated() | |
}; | |
this.hideLoadingIndicator = function() { | |
b._wrapper.querySelector(".initial").style.display = | |
"none" | |
}; | |
this.createUserBasedDOM = function() { | |
b._eUserBasedSettings.innerHTML = ['<div class="section account anon">\n <div class="description">\n </div>\n <div class="action">', ' <a id="btn-login" href="#" class="button">' + _("Log In") + "</a> ", ' <a id="btn-signup" href="#" class="button primary">' + _("Sign Up") + "</a>", ' </div>\n</div>\n<div class="section hidden">', ' <div class="description">' + _("Choose language") + ": </div>", ' <div class="action anon" id="lang-select"></div>\n <div id="lang-changed">\n <span></span>\n <a class="reload" href="/"></a>\n </div>\n</div>'].join("\n"); | |
this._eLangSelectWrap = b._eUserBasedSettings.querySelector("#lang-select"); | |
this._eLangSelector = b._eUserBasedSettings.ownerDocument.createElement("select"); | |
this._eLangChangedNotifier = b._eUserBasedSettings.querySelector("#lang-changed"); | |
this._eSignupButton = b._eUserBasedSettings.querySelector("#btn-signup"); | |
this._eLoginButton = b._eUserBasedSettings.querySelector("#btn-login"); | |
if (a.locale.available.length > 1) b._eLangSelectWrap.parentNode.className = "section"; | |
b._currentLocale = a.locale.current; | |
for (var c = b._eUserBasedSettings.ownerDocument.createDocumentFragment(), | |
d = 0; d < a.locale.available.length; d++) { | |
var f = a.locale.available[d], | |
h = b._eUserBasedSettings.ownerDocument.createElement("option"); | |
h.textContent = _("lang/" + f); | |
h.value = f; | |
f === a.locale.current && h.setAttribute("selected", "selected"); | |
c.appendChild(h) | |
} | |
b._eLangSelector.appendChild(c); | |
b._eLangSelectWrap.appendChild(b._eLangSelector); | |
b._eLangSelector.addEventListener("change", function() { | |
var a = this.options[this.selectedIndex].value; | |
a !== b._model.getLocale() && b._model.setLocale(a, !0) | |
}); | |
b._eSignupButton.addEventListener("click", | |
function(a) { | |
a.preventDefault(); | |
b._model.triggerSignUp() | |
}, !1); | |
b._eLoginButton.addEventListener("click", function(a) { | |
a.preventDefault(); | |
b._model.triggerLogin() | |
}, !1) | |
}; | |
this.onLocaleChange = function() { | |
var c = new XMLHttpRequest; | |
c.onreadystatechange = function() { | |
if (c.readyState === 4 && c.status === 200) { | |
//TODO add Try/Catch. What would happen if you can't c.responseText | |
var a = JSON.parse(c.responseText), | |
d = "Your language choice will be applied when you reload the page."; | |
a[d] && (d = a[d]); | |
var f = "Reload now"; | |
a[f] && (f = a[f]); | |
b._eLangChangedNotifier.querySelector("span").innerHTML = d; | |
b._eLangChangedNotifier.querySelector("a").innerHTML = | |
f; | |
b._eLangChangedNotifier.className = "show" | |
} | |
}; | |
var d = "/xhr/json/translations.php?locale=" + b._model.getLocale() + "&cb=" + a.version; | |
c.open("GET", d, !0); | |
c.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); | |
c.send() | |
}; | |
this.onModelUpdated = function() { | |
b._model.getProduct(); | |
var a = b._model.getLocale(); | |
if (b._currentLocale) document.getElementsByTagName("html")[0].className = "lang-" + b._currentLocale; | |
if (b._currentLocale && a !== b._currentLocale) b._currentLocale = a, b.onLocaleChange() | |
}; | |
this.open = function() { | |
if (!b._isOpen) b._wrapper.addClass("show"), | |
b._isOpen = !0, b._wrapper.focus(), b._wrapper.addClass("scale-start"), setTimeout(function() { | |
b._wrapper.addClass("scale-end") | |
}, 150), Spotify.Web.Utils.addTransitionEndedListener(b._wrapper, function() { | |
b._wrapper.removeClass("scale-start").removeClass("scale-end") | |
}, 2E3), b._scrollBlocker.activate(), window.addEventListener("keydown", j, !1), setTimeout(function() { | |
document.addEventListener("click", f, !1) | |
}, 500) | |
}; | |
this.close = function() { | |
if (b._isOpen) b._scrollBlocker.deactivate(), b._wrapper.removeClass("show"), b._isOpen = !1, window.removeEventListener("keydown", j, !1), document.removeEventListener("click", f, !1) | |
}; | |
var f = function(a) { | |
for (var c = !1, d = a.target; d.parentNode;) | |
if (d = d.parentNode, d.id === b._wrapper.id) { | |
c = !0; | |
a.target.tagName.toLowerCase() === "a" && setTimeout(function() { | |
b.close() | |
}, 300); | |
break | |
} | |
c || b.close() | |
}, | |
j = function(a) { | |
a.keyCode === 27 && b.close() | |
}; | |
this.toggleOpenClose = function() { | |
b._isOpen ? b.close() : b.open() | |
} | |
}; | |
Spotify.Web.SpbMusicBridge = function(c, a, b, d, f, j, g) { | |
function k(a, b) { | |
F.hasOwnProperty(a) && (typeof E[a] == "undefined" && (E[a] = []), E[a].push(b)) | |
} | |
function l(a, b, c) { | |
for (var c = c || u, b = b instanceof Array ? b : [b], d, e = 0, f = E[a].length; e < f; e++) d = E[a][e], d.apply(c, b) | |
} | |
function h(a, b) { | |
D.contentWindow.postMessage(JSON.stringify({ | |
key: a, | |
data: b || {} | |
}), B) | |
} | |
function m(a) { | |
h("spb-error", a) | |
} | |
function n(a) { | |
z(function(b, c) { | |
if (c.track) { | |
var d = c.track.uri || "", | |
e = { | |
playing: a || c.playing, | |
playing_position: typeof c.position !== "object" ? c.position : 0, | |
track: d, | |
isAd: c.track.advertisement, | |
time: Date.now() | |
}; | |
l("STATUS", e, d) | |
} | |
}) | |
} | |
function e(a) { | |
if (typeof y.indexOf === "undefined") y.indexOf = function(a) { | |
for (var b = 0, c = this.length; b < c; b++) | |
if (this[b] == a) return b; | |
return -1 | |
}; | |
return y.indexOf(a) < 0 ? !1 : !0 | |
} | |
function o() { | |
G || (G = !0, window.setTimeout(function() { | |
G = !1 | |
}, 1E3)) | |
} | |
function t(a) { | |
if (!G) { | |
o(); | |
var b = a.track, | |
d = a.reason || null; | |
if (b && b.test(/^spotify:\w+(:.+)+$/) !== !1) { | |
var e = b.split(":"), | |
g = e[1] == "trackset" ? null : e[2], | |
h = a.context; | |
z(function(a, e) { | |
var j = e.track ? e.track.uri : | |
null, | |
k; | |
I[j] && (k = I[j]); | |
(b === j || b === k) && !e.playing ? f.resume() : setTimeout(function() { | |
c.openUri(Spotify.Link.fromString(h).toAppLink(), "", !1); | |
f.play(h, g, function() { | |
z(function(a, c) { | |
b !== c.track.uri && (I[c.track.uri] = b) | |
}) | |
}, function(a) { | |
if (b && typeof a.uri === "undefined") a.uri = b; | |
l("ERROR", a); | |
n() | |
}, d) | |
}, 5) | |
}) | |
} | |
} | |
} | |
function C() { | |
G || (o(), f.pause()) | |
} | |
function v() { | |
z(function(a, b) { | |
n(b.playing) | |
}) | |
} | |
function z(b) { | |
a.player.getState(b) | |
} | |
function w() { | |
a.player.registerForPlayerEvents(function(a, b) { | |
if (!a) switch (b.type) { | |
case "play": | |
n(!0); | |
break; | |
case "pause": | |
n(!1); | |
break; | |
case "stop": | |
n(!1); | |
break; | |
case "positionChanged": | |
A(b) | |
} | |
w() | |
}) | |
} | |
function A() { | |
z(function(a, b) { | |
b.playing && n(b.playing) | |
}) | |
} | |
function x(a) { | |
//TODO add Try/Catch. What would happen if you can't parse a.data? | |
if (e(a.origin)) switch (a = typeof a.data == "object" ? a.data : JSON.parse(a.data), a.key) { | |
case "connection-request": | |
l(F.CONNECT, a.data); | |
break; | |
case "spb-connected": | |
H = !0; | |
E = { | |
ERROR: [m], | |
STATUS: [p] | |
}; | |
k(F.PLAY, t); | |
k(F.PAUSE, C); | |
k(F.CONNECT, v); | |
w(); | |
b.subscribe(Spotify.Web.PublisherMessages.APPLICATION_CLOSED, u); | |
typeof g !== "undefined" ? l("ERROR", g) : l(F.CONNECT, a.data); | |
break; | |
case "status-message": | |
a.data.play === !0 ? l(F.PLAY, a.data) : l(F.PAUSE, a.data) | |
} | |
} | |
var u = this, | |
y = d || [], | |
B, D, G = !1, | |
E, F = { | |
PLAY: "PLAY", | |
PAUSE: "PAUSE", | |
STATUS: "STATUS", | |
CONNECT: "CONNECT" | |
}, | |
I = {}, | |
H = !1, | |
p = function() { | |
var a, b, c = 0; | |
return function(d) { | |
b = d; | |
c++; | |
a && clearTimeout(a); | |
a = setTimeout(function() { | |
a = null; | |
c = 0; | |
h("spb-event", b) | |
}, 10) | |
} | |
}(); | |
return { | |
loadIframe: function(a) { | |
B = a; | |
a = document.createElement("iframe"); | |
a.src = B; | |
document.body.appendChild(a); | |
D = a; | |
window.attachEvent && !window.addEventListener ? window.attachEvent("onmessage", | |
x) : window.addEventListener("message", x) | |
}, | |
removeIframe: function() { | |
D && D.parentNode && D.parentNode.removeChild(D); | |
window.detachEvent && !window.removeEventListener ? window.detachEvent("onmessage", x) : window.removeEventListener("message", x) | |
}, | |
isLoaded: function() { | |
return H | |
} | |
} | |
}; | |
Spotify.Web.SpbMusicBridge._musicBridge = null; | |
Spotify.Web.SpbMusicBridge.initMusicBridge = function(c, a, b, d, f, j, g) { | |
if (Spotify.Web.SpbMusicBridge._musicBridge === null && d.music_bridge.enable === !0) { | |
var k = d.music_bridge, | |
l = k && k.retries || 1, | |
h = 0, | |
m = (k.timeout || 1) * 1E3, | |
n = null, | |
e = function(a, b) { | |
!a || !b || isNaN(b) ? f.warn("[SPB iframe could not load]") : (Spotify.Web.SpbMusicBridge._musicBridge.loadIframe(a), n = setTimeout(o, b)) | |
}, | |
o = function() { | |
clearTimeout(n); | |
Spotify.Web.SpbMusicBridge._musicBridge.isLoaded() || (Spotify.Web.SpbMusicBridge._musicBridge.removeIframe(), ++h < | |
l ? e(k.url, m) : f.warn("[SPB iframe could not load]")) | |
}; | |
Spotify.Web.SpbMusicBridge._musicBridge = new Spotify.Web.SpbMusicBridge(c, a, b, k.allowed_sites, j, new Spotify.Events, g); | |
e(k.url, m) | |
} | |
}; | |
Spotify.Web.SpbMusicBridge.isReferrerFromSPB = function(c) { | |
return /utm_source=(embed\.spotify|\w+\.yahoo)\.com/.test(c) | |
}; | |
Spotify.Web.LastFm = function(c, a, b, d) { | |
Spotify.Web.EventTarget.call(this); | |
var f = this, | |
j = {}; | |
new Spotify.Events; | |
var g, k, l = null, | |
h = null, | |
m = function(a) { | |
if (a.playing && a.__uid != h) { | |
var b = a.track; | |
if (b && !b.advertisement && (h = a.__uid, !(b.duration < 3E4))) { | |
var c = b.artists[0] || {}, | |
a = Math.min(Math.floor(b.duration / 2) - a.position, 24E4); | |
clearTimeout(l); | |
l = setTimeout(function() { | |
k.scrobble(b.name, c.name || "", b.albumName || "", b.duration || 0) | |
}, a) | |
} | |
} | |
}; | |
this.onModelUpdated = function() { | |
!b.getLastFmScrobble() || !k || k.getSession() | |
}; | |
this.authenticateWithApi = | |
function() { | |
g.authenticate() | |
}; | |
this.onSessionLost = function() { | |
k.setSession(""); | |
b.lastFmDisconnect() | |
}; | |
this.onScrobbleFailed = function() {}; | |
var n = function(a, c) { | |
e(); | |
j = c.data; | |
b.getLastFmScrobble() && c.type === "change" && m(j) | |
}, | |
e = function() { | |
c.request("player_event_wait", ["main"], n) | |
}; | |
this.init = function() { | |
if (d.enabled) a.user.onReady(function() { | |
a.user.getUserInfo(function(a) { | |
a = a || {}; | |
g = new Spotify.Web.LastFmApi(d.key); | |
g.bind("SESSION_LOST", f.onSessionLost); | |
g.bind("SCROBBLE_FAILED", f.onScrobbleFailed); | |
k = new Spotify.Web.LastFmScrobbler(g, | |
a.user); | |
b.bind(Spotify.Web.PublisherMessages.MODEL_UPDATED, f.onModelUpdated); | |
b.bind(Spotify.Web.PublisherMessages.LASTFM_CONNECT, f.authenticateWithApi); | |
e(); | |
d.token ? g.getSession(d.token, function(a) { | |
var c = a.split("|"); | |
b.lastFmConnect(c[1], c[0]); | |
k.setSession(a) | |
}) : a && a.lastfm_session && (k.setSession(a.lastfm_session), b.setLastFmConnected(!0), b.setLastFmUser(a.lastfm_session.split("|")[1])) | |
}, function() {}) | |
}) | |
} | |
}; | |
Spotify.Web.LastFmApi = function(c) { | |
Spotify.Web.EventTarget.call(this); | |
var a = this, | |
b = location.protocol + "//ws.audioscrobbler.com/2.0/"; | |
this.call = function(a, b, c, d) { | |
var l = new Request({ | |
url: b !== "GET" ? a : a += "&format=json", | |
method: b, | |
onSuccess: function(a) { | |
//TODO Add Try/Catch. I guess that d is a callback, What would happen if you can't parse a? and if this value is pass to d function? | |
d(JSON.parse(a)) | |
}, | |
onFailure: function(a) { | |
Spotify.Web.WebTracker.log({ | |
type: "LASTFM_API_CALL_FAILED", | |
error: JSON.stringify({ | |
request: l, | |
data: a | |
}) | |
}) | |
} | |
}); | |
b === "POST" && (c += "&format=json"); | |
l.setHeader("Content-type", "application/x-www-form-urlencoded"); | |
l.send(c) | |
}; | |
this.authenticate = | |
function() { | |
var a = encodeURIComponent("http://" + window.location.host + "/settings?lastfm=1"); | |
window.location = "http://www.last.fm/api/auth/?api_key=" + c + "&cb=" + a | |
}; | |
this.sign = function(a, b) { | |
var c = new XMLHttpRequest; | |
c.onreadystatechange = function() { | |
if (c.readyState === 4) | |
if (c.status !== 200 || c.responseText === "error") Spotify.Web.WebTracker.log({ | |
type: "LASTFM_UNABLE_TO_SIGN_SCROBBLE_REQUEST", | |
error: JSON.stringify(a) | |
}); | |
else { | |
//TODO add Try/Catch. What would happen if you can't parse c.responseText?, I guess that b is a callback function | |
var d = JSON.parse(c.responseText); | |
b(d.signature) | |
} | |
}; | |
c.open("POST", "/xhr/json/lastfm/sign.php", !0); | |
c.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); | |
c.send("data=" + a) | |
}; | |
this.getSession = function(f, j) { | |
var g = d({ | |
method: "auth.getSession", | |
api_key: c, | |
token: f | |
}), | |
k = b + "?" + g.query; | |
a.sign(g.string, function(b) { | |
k += "&api_sig=" + b; | |
a.call(k, "GET", null, function(a) { | |
a.session && a.session.key && j(a.session.key + "|" + a.session.name || "") | |
}, function(a) { | |
Spotify.Web.WebTracker.log({ | |
type: "LASTFM_UNABLE_TO_COMMUNICATE_WITH_LASTFM", | |
error: JSON.stringify({ | |
endpoint: k, | |
response: a | |
}) | |
}) | |
}) | |
}) | |
}; | |
this.scrobble = function(f, j) { | |
var g = { | |
method: "track.scrobble", | |
api_key: c, | |
sk: j, | |
track: encodeURIComponent(f.track), | |
artist: encodeURIComponent(f.artist), | |
album: encodeURIComponent(f.album), | |
timestamp: f.timestamp | |
}; | |
if (f.duration) g.duration = Math.round(f.duration / 1E3); | |
var k = d(g); | |
a.sign(k.string, function(c) { | |
for (var d in g) | |
if (d.indexOf("track") === 0 || d.indexOf("artist") === 0) encodeURIComponent(g[d] = g[d]); | |
a.call(b, "POST", k.query + "&api_sig=" + c, function(b) { | |
if (b.error) switch (Spotify.Web.WebTracker.log({ | |
type: "LASTFM_UNABLE_TO_SCROBBLE", | |
error: JSON.stringify(b.error) | |
}), | |
b.error) { | |
case 9: | |
a.trigger("SESSION_LOST"); | |
break; | |
default: | |
a.trigger("SCROBBLE_FAILED") | |
} | |
}) | |
}) | |
}; | |
var d = function(a) { | |
var b = [], | |
c = "", | |
d = "", | |
l; | |
for (l in a) a.hasOwnProperty(l) && b.push(l); | |
b.sort(); | |
for (l = 0; l < b.length; l++) c += b[l] + a[b[l]], d += b[l] + "=" + a[b[l]], l < b.length - 1 && (d += "&"); | |
return { | |
string: c, | |
query: d | |
} | |
} | |
}; | |
Spotify.Web.LastFmScrobbler = function(c) { | |
var a; | |
this.scrobble = function(b, d, f, j) { | |
a && a !== "" && (b = { | |
track: b, | |
artist: d, | |
album: f, | |
timestamp: Math.floor((new Date).getTime() / 1E3), | |
duration: j | |
}, c.scrobble(b, a)) | |
}; | |
this.getSession = function() { | |
return a || "" | |
}; | |
this.setSession = function(b) { | |
a = b.split("|")[0] | |
} | |
}; | |
Spotify.Web.Setup = function(c, a) { | |
var b = this, | |
d = CryptoJS.MD5((c.username || "") + (new Date).getTime()).toString().substring(0, 16); | |
this.publisher = new Spotify.Web.Publisher; | |
this._preloadAssets = function() { | |
for (var a = [c.cdn + "/images/loading_throbber.gif", c.cdn + "/images/logo.png"], b = 0; b < a.length; b++) this.assets.preloadImage(a[b]) | |
}; | |
this._onCoreConnected = function() { | |
this.appLoader.init(); | |
this.bridge = new Spotify.Web.Bridge(SpotifyApi.api); | |
this.services = new Spotify.Web.Services(this.bridge, this.core.core.pubsub, this.tracking); | |
this.router.setServices(this.services); | |
this.stateHistory.setServices(this.services); | |
(new Spotify.Web.Ads.PixelTracker(this.bridge)).init(); | |
this.appLogger = new Spotify.Web.AppLogger(this.core.core.logging.logger, d, this.router); | |
this.fbBridge = new Spotify.Web.Fb(this.publisher, this.assets, this.services); | |
(new Spotify.Web.SocialData(this.publisher, this.services, this.fbBridge)).init(); | |
this.config.getFeature("messaging") && (new Spotify.Web.Messaging(this.publisher, this.services)).init(); | |
this.config.getFeature("notifications") && | |
(new Spotify.Web.Notifications(this.publisher, this.services)).init(); | |
if (this.abTests.getTestGroup("NTX_sociomantic_track")) this.sociomantic = new Spotify.Web.Sociomantic(this, c.mhash) | |
}; | |
this.init = function() { | |
try { | |
//TODO what is this line for? | |
JSON.parse = JSON.parse && function() { | |
var a = JSON.parse; | |
return function(b) { | |
try { | |
return a.apply(JSON, arguments) | |
} catch (c) { | |
throw new SyntaxError(c.message + ", context: " + b); | |
} | |
} | |
}() | |
} catch (d) {} | |
this.assets = new Spotify.Web.Static; | |
this.consoleLogger = new Spotify.Web.ConsoleLogger; | |
this.abTests = new Spotify.Web.ABTests(c.username); | |
this.config = new Spotify.Web.Config(c, this.abTests); | |
this.config.init(); | |
this.stateHistory = new Spotify.Web.StateHistory.Manager({ | |
sections: [{ | |
link: Spotify.Link.applicationLink("home"), | |
type: "section" | |
}, { | |
link: Spotify.Link.applicationLink("browse"), | |
type: "section" | |
}, { | |
link: Spotify.Link.applicationLink("collection"), | |
type: "section" | |
}, { | |
link: Spotify.Link.applicationLink("labs"), | |
type: "section" | |
}, { | |
link: Spotify.Link.applicationLink("discover"), | |
type: "section" | |
}, { | |
link: Spotify.Link.applicationLink("radio"), | |
type: "section", | |
persistent: !0 | |
}, { | |
link: Spotify.Link.applicationLink("playlist"), | |
type: "section" | |
}, { | |
link: Spotify.Link.applicationLink("purchase"), | |
type: "section" | |
}, { | |
link: Spotify.Link.applicationLink("follow"), | |
type: "section" | |
}, { | |
link: Spotify.Link.applicationLink("messages"), | |
type: "section" | |
}, { | |
link: Spotify.Link.applicationLink("social-feed"), | |
type: "section" | |
}, { | |
link: Spotify.Link.applicationLink("welcome"), | |
type: "section" | |
}, { | |
link: Spotify.Link.applicationLink("user"), | |
type: "section" | |
}, { | |
link: Spotify.Link.applicationLink("settings"), | |
type: "section", | |
persistent: !0 | |
}, { | |
link: Spotify.Link.applicationLink("brand-header"), | |
type: "section" | |
}, { | |
link: Spotify.Link.applicationLink("suggest"), | |
type: "popup" | |
}, { | |
link: Spotify.Link.applicationLink("notification-center"), | |
type: "popup" | |
}, { | |
link: Spotify.Link.applicationLink("context-actions"), | |
type: "popup" | |
}, { | |
link: Spotify.Link.applicationLink("about"), | |
type: "section" | |
}, { | |
link: Spotify.Link.applicationLink("revgen-modal"), | |
type: "popup" | |
}, { | |
link: Spotify.Link.applicationLink("share"), | |
type: "popup" | |
}, { | |
link: Spotify.Link.applicationLink("queue"), | |
type: "section" | |
}, { | |
link: Spotify.Link.applicationLink("charts"), | |
type: "section" | |
}], | |
useClassicMode: !1 | |
}, null, { | |
features: c.features | |
}); | |
this.stateHistory.initialize(); | |
this.history = new Spotify.Web.Router.History(this.stateHistory, History); | |
this.tracking = new Spotify.Web.Tracking(this.publisher, this.assets, c.tracking, this.history); | |
this.core.setTracker(this.tracking); | |
this.tracking.initialize(a); | |
this.history.setTracking(this.tracking); | |
this.playNow = new Spotify.Web.PlayNow(this.publisher, c.sessionType, Spotify.Web.Cookie.domain, | |
c.spb_referrer, a); | |
this._preloadAssets(); | |
this.appLoader = new Spotify.Web.AppLoader(c, this.consoleLogger, this.core.core, window); | |
this.router = new Spotify.Web.Router(this.stateHistory, c, this.publisher, this.appLoader); | |
this.appManager = new Spotify.Web.AppManager(this.stateHistory, this.router.getAppUrl, document); | |
this.appManager.bind("onFrameCreated", function(a) { | |
var c = a.params.app, | |
d = a.params.node, | |
a = a.params.cached; | |
b.publisher.notify(Spotify.Web.PublisherMessages.APPLICATION_LOAD_STARTED, { | |
uri: c.link.toURI(), | |
start: (new Date).getTime() | |
}); | |
b.publisher.notify(Spotify.Web.PublisherMessages.APPLICATION_STATE_CHANGED, { | |
link: c.link, | |
iframe: d, | |
cached: a | |
}) | |
}); | |
this.appManager.bind("onFrameUpdated", function(a) { | |
b.publisher.notify(Spotify.Web.PublisherMessages.APPLICATION_STATE_CHANGED, { | |
link: a.params.app.link, | |
iframe: a.params.node | |
}) | |
}); | |
this.appManager.bind("onFrameDisposed", function(a) { | |
b.publisher.notify(Spotify.Web.PublisherMessages.APPLICATION_DISPOSED, { | |
link: a.params.app.link, | |
iframe: a.params.node | |
}) | |
}); | |
var f = new Spotify.Web.View(this.stateHistory, | |
this.appManager, document.getElementById("main"), !1, this.publisher); | |
f.bind("onFrontPaneUpdate", function(a) { | |
a.params.node.focus() | |
}); | |
f.setTracking(this.tracking); | |
this.popupManager = new Spotify.Web.PopupManager(this.router, this.publisher, document.getElementById("wrapper"), this.config.getSetting("cat_enabled")); | |
this.scrollBlocker = new Spotify.Web.ScrollBlocker(document.getElementById("sb"), this.publisher, this.popupManager); | |
this.scrollBlocker.init() | |
}; | |
var f = new Spotify.Web.Environment(window); | |
if (f.isWeb()) f = | |
Spotify.Web.Setup.WebSetup; | |
else if (f.isDesktop()) f = Spotify.Web.Setup.DesktopSetup; | |
else throw Error("Invalid environment"); | |
f.prototype = this; | |
return new f(c, a) | |
}; | |
Spotify.Web.Setup.WebSetup = function(c, a) { | |
var b = this, | |
d = !1, | |
f, j = function(a) { | |
return function() { | |
d || (d = !1, b._onCoreConnected()); | |
a() | |
} | |
}; | |
this._onCoreConnected = function() { | |
Spotify.Web.Setup.WebSetup.prototype._onCoreConnected.call(this); | |
f = new Spotify.Web.Storage.Cookie("common", this.services, Spotify.Utils.Base64, {}, document); | |
f.init(function() { | |
b.playNow.onSignedIn(function() { | |
(new Spotify.Web.Bookmark(b.publisher, f)).init() | |
}) | |
}) | |
}; | |
this.init = function(d) { | |
var f = new Spotify.Web.Credentials("/xhr/json/auth.php", c.csrftoken); | |
c.credentials && f.cache(c.credentials[0], c.credentials[1]); | |
this.core = new Spotify.Web.Core(this.publisher, c, f, new Spotify.Web.ConsoleLogger); | |
this.core.initialize(); | |
this.core.connect(j(d)); | |
Spotify.Web.Setup.WebSetup.prototype.init.call(this); | |
this.playNow.bindBeforeReload(function() { | |
if (window.localStorage) { | |
var c = b.core.core.contextPlayer; | |
window.localStorage.playNow_isPlaying = c && c.getState().playing ? "true" : "false" | |
} | |
b.playNow.isOpenRedirect() ? window.location.replace(Spotify.Web.Utils.stripQSParams("s,f,utm_medium,utm_campaign,utm_source,cp,cr".split(","), | |
a)) : window.location.reload() | |
}); | |
(new Spotify.Web.PlayNowSignUp(this.playNow, document.getElementById("playNowSignUp"), c, this.publisher)).initialize(); | |
this.playNow.isOpenRedirect() && this.playNow.signUp() | |
} | |
}; | |
Spotify.Web.Environment = function(c) { | |
var a = c.location.protocol === "sp:" ? "desktop" : "web"; | |
this.isWeb = function() { | |
return a === "web" | |
}; | |
this.isDesktop = function() { | |
return a === "desktop" | |
} | |
}; | |
Spotify.Web.CookieCleaner = function(c) { | |
this.MAX_COOKIE_NAME_LENGTH = 50; | |
this.clean = function() { | |
this.removeHugeAnonymousSettingsCookies() | |
}; | |
this.removeHugeAnonymousSettingsCookies = function() { | |
for (var a = c.getAll(), b = 0; b < a.length; b++) { | |
var d = a[b].split("="); | |
(d = d[0] ? d[0].trim() : "") && d.length > this.MAX_COOKIE_NAME_LENGTH && c.remove(d, window.document, null, window.location.protocol === "https:") | |
} | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment