YouTube Lyrics by Rob W

By Rob W Last update May 19, 2013 — Installed 6,894 times.

There are 22 previous versions of this script.

the source is over 100KB, syntax highlighting in the browser is too slow

// ==UserScript==
// @name        YouTube Lyrics by Rob W
// @description Instant Lyrics for YouTube, Grooveshark and Spotify. Multiple sources and a manual search form ensure that most lyrics are found. To configure this script, visit https://rob.lekensteyn.nl/youtubelyrics/
// @author      Rob W <gwnRob@gmail.com>
// @namespace   Rob W
// @version     3.5.1
// @website     http://userscripts.org/scripts/show/112070
// @updateURL   http://userscripts.org/scripts/source/112070.meta.js
// @downloadURL http://userscripts.org/scripts/source/112070.user.js
// @include     http://www.youtube.com/*
// @include     https://www.youtube.com/*
// @include     http://grooveshark.com/*
// @include     http://html5.grooveshark.com/*
// @include     http://retro.grooveshark.com/*
// @include     http://play.spotify.com/*
// @include     https://play.spotify.com/*
// @include     http://rob.lekensteyn.nl/youtubelyrics/*
// @include     https://rob.lekensteyn.nl/youtubelyrics/*
// @icon        https://rob.lekensteyn.nl/youtubelyrics/icons/32.png
// @run-at      document-start
// @grant       GM_getValue
// @grant       GM_setValue
// @grant       GM_deleteValue
// @grant       GM_listValues
// @grant       GM_xmlhttpRequest
// ==/UserScript==

/**
 * (c) 2013 Rob W <gwnRob@gmail.com>
 * Website: https://rob.lekensteyn.nl/youtubelyrics/
 * 
 * Distributed under the MIT license (http://opensource.org/licenses/MIT)
 *
 * Milestones:
 *  4 sep 2011 - Initial release of version 1 and 2 branches
 *  8 jan 2013 - Public release of version 3 branch - new features and a modular codebase
 *  9 jan 2013 - Released Safari extension
 * 10 jan 2013 - Released Opera extension
 * 11 jan 2013 - Released Firefox add-on
 *  5 feb 2013 - Published Internet Explorer extension
 * 12 feb 2013 - Grooveshark support (13 Feb: added support for HTML5 and Retro Grooveshark)
 * 
 * Websites:
 * - https://rob.lekensteyn.nl/youtubelyrics/
 * - http://userscripts.org/scripts/show/112070
 * - https://chrome.google.com/webstore/detail/lifkpflabnobkgbjpcmocmgcajlecbcp
 * - https://addons.mozilla.org/firefox/addon/youtube-lyrics-by-rob-w/
 * - https://addons.opera.com/en/extensions/details/youtube-lyrics-by-rob-w/
 * 
 * Contact:
 * - Rob W <gwnRob@gmail.com>
 * 
 * Distributed in the following forms:
 * - Chrome extension
 * - Firefox add-on
 * - Safari extension
 * - Opera extension
 * - Internet Explorer extension (32 and 64 bits)
 * - Hybrid userscript (Greasemonkey / NinjaKit / Tampermonkey / Opera)
 * 
 * A full list plus links to the distributed versions can be found at
 * https://rob.lekensteyn.nl/youtubelyrics/#get-extension
 *
 * Change log:
 * https://rob.lekensteyn.nl/youtubelyrics/CHANGELOG
 */
(function() {
    var e, t, r;
    (function(n) {
        function o(e, t) {
            return S.call(e, t);
        }
        function i(e, t) {
            var r, n, o, i, s, a, c, l, u, p, d = t && t.split("/"), f = v.map, h = f && f["*"] || {};
            if (e && "." === e.charAt(0)) if (t) {
                for (d = d.slice(0, d.length - 1), e = d.concat(e.split("/")), l = 0; e.length > l; l += 1) if (p = e[l], 
                "." === p) e.splice(l, 1), l -= 1; else if (".." === p) {
                    if (1 === l && (".." === e[2] || ".." === e[0])) break;
                    l > 0 && (e.splice(l - 1, 2), l -= 2);
                }
                e = e.join("/");
            } else 0 === e.indexOf("./") && (e = e.substring(2));
            if ((d || h) && f) {
                for (r = e.split("/"), l = r.length; l > 0; l -= 1) {
                    if (n = r.slice(0, l).join("/"), d) for (u = d.length; u > 0; u -= 1) if (o = f[d.slice(0, u).join("/")], 
                    o && (o = o[n])) {
                        i = o, s = l;
                        break;
                    }
                    if (i) break;
                    !a && h && h[n] && (a = h[n], c = l);
                }
                !i && a && (i = a, s = c), i && (r.splice(0, s, i), e = r.join("/"));
            }
            return e;
        }
        function s(e, t) {
            return function() {
                return f.apply(n, L.call(arguments, 0).concat([ e, t ]));
            };
        }
        function a(e) {
            return function(t) {
                return i(t, e);
            };
        }
        function c(e) {
            return function(t) {
                g[e] = t;
            };
        }
        function l(e) {
            if (o(y, e)) {
                var t = y[e];
                delete y[e], b[e] = !0, d.apply(n, t);
            }
            if (!o(g, e) && !o(b, e)) throw Error("No " + e);
            return g[e];
        }
        function u(e) {
            var t, r = e ? e.indexOf("!") : -1;
            return r > -1 && (t = e.substring(0, r), e = e.substring(r + 1, e.length)), [ t, e ];
        }
        function p(e) {
            return function() {
                return v && v.config && v.config[e] || {};
            };
        }
        var d, f, h, m, g = {}, y = {}, v = {}, b = {}, S = Object.prototype.hasOwnProperty, L = [].slice;
        h = function(e, t) {
            var r, n = u(e), o = n[0];
            return e = n[1], o && (o = i(o, t), r = l(o)), o ? e = r && r.normalize ? r.normalize(e, a(t)) : i(e, t) : (e = i(e, t), 
            n = u(e), o = n[0], e = n[1], o && (r = l(o))), {
                f: o ? o + "!" + e : e,
                n: e,
                pr: o,
                p: r
            };
        }, m = {
            require: function(e) {
                return s(e);
            },
            exports: function(e) {
                var t = g[e];
                return t !== void 0 ? t : g[e] = {};
            },
            module: function(e) {
                return {
                    id: e,
                    uri: "",
                    exports: g[e],
                    config: p(e)
                };
            }
        }, d = function(e, t, r, i) {
            var a, u, p, d, f, v, S = [];
            if (i = i || e, "function" == typeof r) {
                for (t = !t.length && r.length ? [ "require", "exports", "module" ] : t, f = 0; t.length > f; f += 1) if (d = h(t[f], i), 
                u = d.f, "require" === u) S[f] = m.require(e); else if ("exports" === u) S[f] = m.exports(e), 
                v = !0; else if ("module" === u) a = S[f] = m.module(e); else if (o(g, u) || o(y, u) || o(b, u)) S[f] = l(u); else {
                    if (!d.p) throw Error(e + " missing " + u);
                    d.p.load(d.n, s(i, !0), c(u), {}), S[f] = g[u];
                }
                p = r.apply(g[e], S), e && (a && a.exports !== n && a.exports !== g[e] ? g[e] = a.exports : p === n && v || (g[e] = p));
            } else e && (g[e] = r);
        }, e = t = f = function(e, t, r, o, i) {
            return "string" == typeof e ? m[e] ? m[e](t) : l(h(e, t).f) : (e.splice || (v = e, 
            t.splice ? (e = t, t = r, r = null) : e = n), t = t || function() {}, "function" == typeof r && (r = o, 
            o = i), o ? d(n, e, t, r) : setTimeout(function() {
                d(n, e, t, r);
            }, 15), f);
        }, f.config = function(e) {
            return v = e, f;
        }, r = function(e, t, r) {
            t.splice || (r = t, t = []), o(g, e) || o(y, e) || (y[e] = [ e, t, r ]);
        }, r.amd = {
            jQuery: !0
        };
    })(), r("config-greasemonkey", [], function() {
        var e = {};
        return e.getItem = function(e, t) {
            setTimeout(function() {
                var r = GM_getValue(e);
                "string" == typeof r && (r = JSON.parse(r)), t(r);
            }, 0);
        }, e.setItem = function(e, t, r) {
            t = JSON.stringify(t), setTimeout(function() {
                GM_setValue(e, t), r(!0);
            }, 0);
        }, e.removeItem = function(e, t) {
            setTimeout(function() {
                GM_deleteValue(e), t(!0);
            }, 0);
        }, e.clear = function(e) {
            setTimeout(function() {
                for (var t = GM_listValues(), r = 0; t.length > r; r++) GM_deleteValue(t[r]);
                e(!0);
            }, 0);
        }, e.init = function() {}, e;
    }), r("config-userscript", [], function() {
        var e = function(e, t, r) {
            console && console.log(e + ": " + r);
        }, t = {}, r = "rwYTL.", n = "robw_ytl", o = "/robots.txt#lyrics-settings", i = [ "http://www.youtube.com", "https://www.youtube.com" ], s = i.concat("https://rob.lekensteyn.nl", "http://rob.lekensteyn.nl");
        return t.getItem = function(t, n) {
            var o = localStorage.getItem(r + t);
            if ("string" == typeof o) try {
                o = JSON.parse(o);
            } catch (i) {
                e("config.getItem error: " + i), o = void 0;
            }
            n(o);
        }, t.setItem = function(t, n, o) {
            var i = !1;
            try {
                localStorage.setItem(r + t, JSON.stringify(n)), i = !0;
            } catch (s) {
                e("config.setItem error: " + s);
            }
            o(i);
        }, t.removeItem = function(e, t) {
            localStorage.removeItem(r + e), t(!0);
        }, t.clear = function(e) {
            for (var t = [], n = localStorage.length - 1; n >= 0; --n) {
                var o = localStorage.key(n);
                o && 0 === o.indexOf(r) && t.push(o);
            }
            t.forEach(function(e) {
                localStorage.removeItem(e);
            }), e(!0);
        }, t.init = function() {
            function r() {
                return (location.protocol + "//" + location.host).toLowerCase();
            }
            function a() {
                return (location.pathname + location.hash).toLowerCase();
            }
            if (-1 !== i.indexOf(r()) && a() === o && (addEventListener("message", function(e) {
                if (-1 !== s.indexOf(e.origin) && "string" == typeof e.data) {
                    var r = e.data.match(/^(@(\D+)\d+)(getItem|setItem|removeItem|clear)(\[[\S\s]*\])$/);
                    if (r) {
                        var o = r[1], i = r[2];
                        if (n === i) {
                            var a = r[3], c = JSON.parse(r[4]);
                            c.push(function() {
                                var t = [].slice.call(arguments), r = o + "callback" + JSON.stringify(t);
                                e.source.postMessage(r, e.origin);
                            }), t[a].apply(t, c);
                        }
                    }
                }
            }, !0), parent.postMessage("Hello", "*")), -1 !== s.indexOf(r()) && a() !== o) {
                var c = {}, l = {}, u = {};
                i.forEach(function(e) {
                    u[e] = {
                        frame: null,
                        queue: [],
                        useless: null
                    };
                }), addEventListener("message", function(t) {
                    if (-1 !== s.indexOf(t.origin) && "string" == typeof t.data) if ("Hello" !== t.data) {
                        var r = t.data.match(/^(@(\D+)\d+)callback(\[[\S\s]*\])$/);
                        if (r) {
                            var o = r[1], i = r[2];
                            if (i === n) {
                                var a = JSON.parse(r[3]);
                                l[o] ? l[o](a) : e("Callback not found for ID " + o);
                            }
                        }
                    } else {
                        clearTimeout(c[t.origin]), u[t.origin].useless = !1;
                        for (var p; p = u[t.origin].queue.shift(); ) p(t.source);
                    }
                }, !0);
                var p = function(e, t, r, i) {
                    var s = "@" + n + (0 | 1e9 * Math.random()), a = s + t + JSON.stringify(r), p = u[e];
                    if (l[s] = function(e) {
                        delete l[s], i.apply(this, e);
                    }, null !== p.useless) p.useless ? l[s]([]) : p.frame.contentWindow.postMessage(a, e); else if (p.queue.push(function(t) {
                        t.postMessage(a, e);
                    }), !p.frame) {
                        p.frame = document.createElement("iframe"), p.frame.style.cssText = "border:0;margin:0;width:1px;height:1px;pointer-events: none;", 
                        p.frame.src = e + o;
                        var d = function() {
                            p.useless !== !1 && (p.useless = !0), p.frame.removeEventListener("error", d, !0), 
                            l[s] && l[s]([]);
                        };
                        p.frame.addEventListener("error", d, !0);
                        var f = function() {
                            p.frame.removeEventListener("load", f, !0), p.useless !== !1 && (c[e] = setTimeout(d, 2e3));
                        };
                        p.frame.addEventListener("load", f, !0), (document.body || document.documentElement).appendChild(p.frame);
                    }
                }, d = function(e, r) {
                    var n = t[e], o = "getItem" === e;
                    t[e] = function() {
                        var s = [].slice.call(arguments), a = s.pop(), c = o ? null : !0, l = 0, u = function(e) {
                            o ? (null === c || void 0 === c) && (c = e) : c = c && e, ++l === i.length && a(c);
                        };
                        n.apply(t, s.concat(u));
                        for (var d = 0; i.length > d; d++) {
                            var f = i[d];
                            f !== r && p(f, e, s, u);
                        }
                    };
                };
                -1 !== i.indexOf(r()) ? (d("setItem", r()), d("removeItem", r()), d("clear", r())) : (d("setItem"), 
                d("getItem"), d("removeItem"), d("clear"));
            }
        }, t;
    }), r("config", [ "config-greasemonkey", "config-userscript" ], function(e, t) {
        return "function" == typeof GM_getValue && "function" == typeof GM_setValue && "function" == typeof GM_listValues && (t = e), 
        t.init(), t;
    }), r("setwmode", [], function() {
        function e(e) {
            if (!/^opaque$/i.test(e.getAttribute("wmode"))) {
                var t, r;
                t = e.parentNode, r = e.nextSibling, t.removeChild(e), e.setAttribute("wmode", "opaque"), 
                t.insertBefore(e, r);
            }
        }
        function t() {
            var t = !1;
            setTimeout(function() {
                t = !0;
            }, 6e4);
            var r = setInterval(function() {
                var n = document.getElementsByTagName("embed")[0];
                n ? (clearInterval(r), e(n)) : t && clearInterval(r);
            }, 50);
        }
        return function() {
            if (!(0 > Object.prototype.toString.call(window.HTMLElement).indexOf("Constructor") || /mac/i.test(navigator.platform))) {
                var r = document.getElementsByTagName("embed")[0];
                r ? e(r) : t();
            }
        };
    }), r("domready", [], function() {
        function e() {
            clearInterval(r);
            for (var e; e = n.shift(); ) e();
        }
        function t() {
            r = setInterval(function() {
                "complete" === document.readyState && e();
            }, 50), document.addEventListener("DOMContentLoaded", e, !0);
        }
        var r, n = [];
        return function(e) {
            e && ("complete" === document.readyState ? e() : (void 0 === r && t(), n.push(e)));
        };
    }), r("processRequest-greasemonkey", [ "require", "exports", "module" ], function(e, t) {
        function r(e) {
            var t = e.url, r = {
                url: t,
                abort: function() {
                    o && o.abort();
                }
            }, o = GM_xmlhttpRequest({
                method: e.method || "GET",
                url: t,
                headers: e.headers,
                onload: function(i) {
                    var s = i.status, a = i.responseText;
                    r.abort = n, o = null, s >= 200 && 300 > s || 304 === s ? e.found({
                        url: t,
                        responseText: a
                    }) : e.fail({
                        url: t
                    });
                },
                onerror: function() {
                    r.abort = n, o = null, e.fail({
                        url: t
                    });
                },
                data: e.payload
            });
            o && e.afterSend(r);
        }
        var n = function() {};
        t.processRequest = r;
    }), r("processRequest-cors", [ "require", "exports", "module" ], function(e, t) {
        function r(e, t) {
            var i = e.url, s = new XMLHttpRequest(), a = {
                url: i,
                abort: function() {
                    s && s.abort();
                }
            }, c = "http:" === location.protocol ? "http:" : "https:";
            if (s.open(e.method || "GET", c + "//cors-anywhere.herokuapp.com/" + i, !0), s.setRequestHeader("X-Requested-With", "XMLHttpRequest"), 
            e.headers) for (var l = Object.keys(e.headers), u = 0; l.length > u; u++) {
                var p = l[u];
                if (n.call(e.headers, p)) {
                    var d = e.headers[p];
                    s.setRequestHeader(p, d);
                }
            }
            return s.onload = function() {
                var n = s.status, c = s.statusText, l = s.responseText, u = 333 === n && s.getResponseHeader("Location");
                if (i = s.getResponseHeader("X-Request-URL") || i, a.abort = o, s = null, 333 === n) if (t = +t ? +t + 1 : 1, 
                u && 5 >= t) {
                    var p = +/\d+/.exec(c);
                    307 !== p && 308 !== p && (e.method = "GET", e.payload = null), e.url = u;
                    var d = r(e, t);
                    a.url = d.url, a.abort = d.abort, d = null;
                } else e.fail({
                    url: i
                }); else n >= 200 && 300 > n || 304 === n ? e.found({
                    url: i,
                    responseText: l
                }) : e.fail({
                    url: i
                });
            }, s.onerror = function() {
                a.abort = o, s = null, e.fail({
                    url: i
                });
            }, s.send(e.payload), s && e.afterSend(a), a;
        }
        var n = Object.prototype.hasOwnProperty, o = function() {};
        t.processRequest = r;
    }), r("processRequest", [ "processRequest-greasemonkey", "processRequest-cors" ], function(e, t) {
        return "function" == typeof GM_xmlhttpRequest ? e : t;
    }), r("ScrapedSource", [ "require", "exports", "module" ], function(e, t) {
        function r(e) {
            return this instanceof r ? (this.parseOptions(e), this.validate(), void 0) : (n("ScrapedSource", "invalid_constructor_call", 'Constructor cannot be called as a function. Use "new ScrapedSource(options)" instead of "ScrapedSource(options)"'), 
            void 0);
        }
        var n = function(e, t, r) {
            var n = Error(e + ": " + r);
            throw n.type = t, n;
        }, o = /^\$[A-Za-z]+$/, i = /\$\{([A-Za-z]+)\}|\$([A-Za-z]+)/g;
        r.Scheme = {
            identifier: "string",
            disabled: [ "undefined", "boolean" ],
            url_result: [ "string", "function" ],
            method_result: [ "undefined", "string" ],
            payload_result: [ "undefined", "string", "function" ],
            headers_result: [ "undefined", "object" ],
            process_result: "function",
            url_search: [ "string", "function" ],
            method_search: [ "undefined", "string" ],
            payload_search: [ "undefined", "string", "function" ],
            headers_search: [ "undefined", "object" ],
            process_search: "function"
        }, r.StrictScheme = !1, r.prototype.disabled = !1, r.prototype.validate = function() {
            var e = this;
            return Object.keys(this.constructor.Scheme).every(function(t) {
                return e.validateKey(t, e[t]);
            });
        }, r.prototype.validateKey = function(e, t) {
            if (!this.constructor || !this.constructor.Scheme) return n("ScrapedSource::validateKey", "scheme_not_found", 'The caller\'s constructor must have a property "Scheme"!'), 
            !1;
            var r = this.constructor.Scheme[e];
            if (!r) {
                if (!o.test(e)) return this.constructor.StrictScheme ? (n("ScrapedSource::validateKey", "unknown_key", "Unknown key " + e + ", forbidden by strict scheme!"), 
                !1) : !0;
                r = "function";
            }
            Array.isArray(r) || (r = [ r ]);
            var i = typeof t;
            return -1 === r.indexOf(i) ? (n("ScrapedSource::validateKey", "type_mismatch", 'typeof "' + e + '" must be "' + r + '"! Actual type: "' + i + '"'), 
            !1) : !0;
        }, r.prototype.parseOptions = function(e) {
            if ("object" != typeof e) return n("ScrapedSource::parseOptions", "type_mismatch", "Argument options is required and must be an object!"), 
            !1;
            var t = this;
            return Object.keys(e).every(function(r) {
                var n = t.validateKey(r, e[r]);
                return n && (t[r] = e[r]), n;
            });
        }, r.prototype.get_url = function(e, t) {
            var r = this, o = r["url_" + e];
            "function" == typeof o && (o = o.call(r, t)), "string" != typeof o && n("ScrapedSource::get_url", "type_mismatch", "url_" + e + " is not a string.");
            var s = !0;
            return o = o.replace(i, function(e, o, i) {
                return o = "$" + (o || i), "function" == typeof r[o] ? r[o](t) : (n("ScrapedSource::get_url", "invalid_parameter", "No function found for " + o), 
                s = !1, void 0);
            }), s ? o : null;
        }, r.prototype.getMethod = function(e) {
            var t = this["method_" + e];
            return "string" == typeof t ? t : null;
        }, r.prototype.getHeaders = function(e, t) {
            var r = this, n = r["headers_" + e];
            return "function" == typeof n && n.call(r, t), !n || "object" != typeof n || n instanceof Array ? null : n;
        }, r.prototype.getPayload = function(e, t) {
            var r = this, o = r["payload_" + e];
            if ("function" == typeof o && o.call(r, t), "string" != typeof o) return null;
            var s = !0;
            return o = o.replace(i, function(e, o, i) {
                return o = "$" + (o || i), "function" == typeof r[o] ? r[o](t) : (n("ScrapedSource::getPayload", "invalid_parameter", "No function found for " + o), 
                s = !1, void 0);
            }), s ? o : null;
        }, t.ScrapedSource = r;
    }), r("InfoProvider", [ "require", "exports", "module", "processRequest", "ScrapedSource" ], function(e, t) {
        function r(e) {
            this.parseSources(e);
        }
        var n = e("processRequest").processRequest, o = e("ScrapedSource").ScrapedSource, i = Object.prototype.hasOwnProperty, s = function(e, t, r) {
            var n = Error(e + ": " + r);
            throw n.type = t, n;
        }, a = function(e, t) {
            if (t) {
                for (var r in t) i.call(t, r) && (e[r] = t[r]);
                return e;
            }
        }, c = function(e, t) {
            var r = [].slice.call(arguments, 2);
            return function() {
                return e.apply(t, r);
            };
        };
        r.prototype.parseSources = function(e) {
            if (!(e instanceof Array)) return s("InfoProvider::parseSources", "type_mismatch", "The only argument must be an array of ScrapedSource instances!"), 
            void 0;
            var t = [];
            e.forEach(function(e, r) {
                e instanceof o ? t.push(e) : s("InfoProvider::parseSources", "type_mismatch", "Source " + r + " is not a ScrapedSource instance!");
            }), this.sources = t, this.sourceCount = e.length;
        }, r.prototype.query = function(e, t, r, o) {
            function i(e, r) {
                if (++w > 7) return v(), s("InfoProvider::query:_processURL", "redirect_loop", "Too many redirects"), 
                void 0;
                var o = {
                    url: e.redir,
                    afterSend: S,
                    fail: v,
                    found: function(e) {
                        e.tempData = r, l(e);
                    }
                }, i = "result", a = d.getMethod(i, t);
                a && "GET" !== a.toUpperCase() && (o.payload = d.getPayload(i, t), o.headers = d.getHeaders(i, t)), 
                n(o);
            }
            function l(e) {
                g.url = e.url, d.process_result(e.responseText, {
                    fail: v,
                    found: function(e) {
                        e.redir ? i(e, e.tempData) : b(e);
                    }
                }, {
                    url: e.url,
                    query: t,
                    tempData: e.tempData
                });
            }
            function u(e) {
                g.url = e.redir || e.url, d.process_search(e.responseText, {
                    fail: v,
                    found: i
                }, {
                    url: e.url,
                    query: t,
                    tempData: e.tempData
                });
            }
            var p = this;
            if (p.abort(), "function" != typeof r || !t || !e) return s("InfoProvider::query", "invalid_args", "Usage: function( String type, object query, function callback(result) )"), 
            void 0;
            o = +o || 0;
            var d = p.sources[o], f = !1, h = p.lastTimeAborted, m = a({}, t), g = {
                sourceIndex: o,
                sourceCount: p.sourceCount,
                sourceIdentifier: "<unknown>",
                searchTerms: t.searchTerms,
                url: "",
                retry: c(p.query, p, e, m, r, o),
                query: t,
                abort: null
            };
            p.sourceCount > o + 1 ? g.next = c(p.query, p, e, m, r, o + 1) : g.restart = c(p.query, p, e, m, r);
            var y = function(e, t, n) {
                if (!f && p.lastTimeAborted === h) {
                    f = n;
                    var o = {};
                    a(o, g), a(o, t), o.type = e, r(o);
                }
            }, v = function(e) {
                y("fail", e, !0);
            }, b = function(e) {
                y("found", e, !0);
            }, S = function(e) {
                p._abort = e.abort, y("fetching", e, !1);
            };
            if (!d) return v(), void 0;
            d.$SEARCHTERMS && (g.searchTerms = d.$SEARCHTERMS(t));
            var L = d.get_url(e, t);
            if (g.url = L, g.sourceIdentifier = d.identifier, !L) return v(), void 0;
            var w = 0, x = {
                url: L,
                afterSend: S,
                fail: v,
                found: function(t) {
                    f || ("search" === e ? u(t) : l(t));
                }
            }, A = d.getMethod(e, t);
            A && (x.method = A, "GET" !== A.toUpperCase() && (x.payload = d.getPayload(e, t), 
            x.headers = d.getHeaders(e, t))), n(x);
        }, r.prototype.lastTimeAborted = 0, r.prototype.abort = function() {
            this.lastTimeAborted++;
            var e = this._abort;
            e && (this._abort = null, e());
        }, t.InfoProvider = r;
    }), r("normalize_accents", [ "require", "exports", "module" ], function(e, t) {
        var r = Object.prototype.hasOwnProperty, n = {
            a: [ "ª", "à", "á", "â", "ã", "ä", "å", "ā", "ă", "ą", "ǎ", "ȁ", "ȃ", "ȧ", "ᵃ", "ḁ", "ẚ", "ạ", "ả", "ₐ", "a" ],
            A: [ "À", "Á", "Â", "Ã", "Ä", "Å", "Ā", "Ă", "Ą", "Ǎ", "Ȁ", "Ȃ", "Ȧ", "ᴬ", "Ḁ", "Ạ", "Ả", "A" ],
            b: [ "ᵇ", "ḃ", "ḅ", "ḇ", "b" ],
            B: [ "ᴮ", "Ḃ", "Ḅ", "Ḇ", "B" ],
            c: [ "ç", "ć", "ĉ", "ċ", "č", "ᶜ", "ⅽ", "c" ],
            C: [ "Ç", "Ć", "Ĉ", "Ċ", "Č", "Ⅽ", "C" ],
            d: [ "ď", "ᵈ", "ḋ", "ḍ", "ḏ", "ḑ", "ḓ", "ⅾ", "d" ],
            D: [ "Ď", "ᴰ", "Ḋ", "Ḍ", "Ḏ", "Ḑ", "Ḓ", "Ⅾ", "D" ],
            e: [ "è", "é", "ê", "ë", "ē", "ĕ", "ė", "ę", "ě", "ȅ", "ȇ", "ȩ", "ᵉ", "ḙ", "ḛ", "ẹ", "ẻ", "ẽ", "ₑ", "e" ],
            E: [ "È", "É", "Ê", "Ë", "Ē", "Ĕ", "Ė", "Ę", "Ě", "Ȅ", "Ȇ", "Ȩ", "ᴱ", "Ḙ", "Ḛ", "Ẹ", "Ẻ", "Ẽ", "E" ],
            f: [ "ᶠ", "ḟ", "f" ],
            F: [ "Ḟ", "℉", "F" ],
            g: [ "ĝ", "ğ", "ġ", "ģ", "ǧ", "ǵ", "ᵍ", "ḡ", "g" ],
            G: [ "Ĝ", "Ğ", "Ġ", "Ģ", "Ǧ", "Ǵ", "ᴳ", "Ḡ", "G" ],
            h: [ "ĥ", "ȟ", "ʰ", "ḣ", "ḥ", "ḧ", "ḩ", "ḫ", "ẖ", "ℎ", "h" ],
            H: [ "Ĥ", "Ȟ", "ᴴ", "Ḣ", "Ḥ", "Ḧ", "Ḩ", "Ḫ", "H" ],
            i: [ "ì", "í", "î", "ï", "ĩ", "ī", "ĭ", "į", "ǐ", "ȉ", "ȋ", "ᵢ", "ḭ", "ỉ", "ị", "ⁱ", "i" ],
            I: [ "Ì", "Í", "Î", "Ï", "Ĩ", "Ī", "Ĭ", "Į", "İ", "Ǐ", "Ȉ", "Ȋ", "ᴵ", "Ḭ", "Ỉ", "Ị", "I" ],
            j: [ "ĵ", "ǰ", "ʲ", "j" ],
            J: [ "Ĵ", "ᴶ", "J" ],
            k: [ "ķ", "ǩ", "ᵏ", "ḱ", "ḳ", "ḵ", "k" ],
            K: [ "Ķ", "Ǩ", "ᴷ", "Ḱ", "Ḳ", "Ḵ", "K", "K" ],
            l: [ "ĺ", "ļ", "ľ", "ˡ", "ŀ", "ḷ", "ḻ", "ḽ", "ⅼ", "l" ],
            L: [ "Ĺ", "Ļ", "Ľ", "ᴸ", "Ḷ", "Ḻ", "Ḽ", "Ⅼ", "L" ],
            m: [ "ᵐ", "ḿ", "ṁ", "ṃ", "ⅿ", "m" ],
            M: [ "ᴹ", "Ḿ", "Ṁ", "Ṃ", "Ⅿ", "M" ],
            n: [ "ñ", "ń", "ņ", "ň", "ʼn", "ṅ", "ṇ", "ṉ", "ṋ", "n" ],
            N: [ "Ñ", "Ń", "Ņ", "Ň", "ᴺ", "Ṅ", "Ṇ", "Ṉ", "Ṋ", "N" ],
            o: [ "º", "ò", "ó", "ô", "õ", "ö", "ō", "ŏ", "ő", "ǒ", "ǫ", "ȍ", "ȏ", "ȯ", "ᵒ", "ọ", "ỏ", "o" ],
            O: [ "Ò", "Ó", "Ô", "Ö", "Õ", "Ō", "Ŏ", "Ő", "Ǒ", "Ǫ", "Ȍ", "Ȏ", "Ȯ", "ᴼ", "Ọ", "Ỏ", "O" ],
            p: [ "ᵖ", "ṕ", "ṗ", "p" ],
            P: [ "ᴾ", "Ṕ", "Ṗ", "P" ],
            q: [ "q" ],
            Q: [ "Q" ],
            r: [ "ŕ", "ŗ", "ř", "ȑ", "ȓ", "ʳ", "ᵣ", "ṙ", "Ṛ", "ṛ", "ṟ", "r" ],
            R: [ "Ŕ", "Ŗ", "Ř", "Ȑ", "Ȓ", "ᴿ", "Ṙ", "Ṟ", "R" ],
            s: [ "ś", "ŝ", "ş", "š", "ș", "ṡ", "ṣ", "s" ],
            S: [ "Ś", "Ŝ", "Ş", "Š", "Ș", "Ṡ", "Ṣ", "S" ],
            t: [ "ţ", "ť", "ț", "ᵗ", "ṫ", "ṭ", "ṯ", "ṱ", "ẗ", "t" ],
            T: [ "Ţ", "Ť", "Ț", "ᵀ", "Ṫ", "Ṭ", "Ṯ", "Ṱ", "T" ],
            u: [ "ù", "ú", "û", "ü", "ũ", "ū", "ŭ", "ů", "ű", "ư", "ǔ", "ȕ", "ȗ", "ᵘ", "ᵤ", "ṳ", "ṵ", "ṷ", "ụ", "ủ", "u" ],
            U: [ "Ù", "Ú", "Ü", "Û", "Ũ", "Ū", "Ŭ", "Ů", "Ű", "Ų", "Ư", "Ǔ", "Ȕ", "Ȗ", "ᵁ", "Ṳ", "Ṵ", "Ṷ", "Ụ", "Ủ", "U" ],
            v: [ "ṽ", "ṿ", "ᵛ", "ᵥ", "v" ],
            V: [ "Ṽ", "Ṿ", "ⱽ", "V" ],
            w: [ "ŵ", "ʷ", "ẁ", "ẃ", "ẅ", "ẇ", "ẉ", "ẘ", "w" ],
            W: [ "Ŵ", "ᵂ", "Ẁ", "Ẃ", "Ẅ", "Ẇ", "Ẉ", "W" ],
            x: [ "ˣ", "ẋ", "ẍ", "ₓ", "x" ],
            X: [ "Ẋ", "Ẍ", "X" ],
            y: [ "ý", "ÿ", "ŷ", "ȳ", "ʸ", "ẏ", "ẙ", "ỳ", "ỵ", "ỷ", "ỹ", "y" ],
            Y: [ "Ý", "Ŷ", "Ÿ", "Ȳ", "Ẏ", "Ỳ", "Ỵ", "Ỷ", "Ỹ", "Y" ],
            z: [ "ź", "ż", "ž", "ẑ", "ẓ", "ẕ", "z" ],
            Z: [ "Ź", "Ż", "Ž", "Ẑ", "Ẓ", "Ẕ", "Z" ]
        }, o = {}, i = "";
        for (var s in n) if (r.call(n, s)) for (var a = n[s], c = 0; a.length > c; c++) o[a[c]] = s, 
        i += a[c];
        i = RegExp("[" + i + "]", "gi"), t.normalize_accents = function(e) {
            return e ? e.replace(i, function(e) {
                return r.call(o, e) ? o[e] : e;
            }) : e;
        };
    }), r("SourceScraperUtils", [ "require", "exports", "module", "normalize_accents" ], function(e, t) {
        var r = e("normalize_accents").normalize_accents, n = function(e, t, r) {
            console && console.log(e + ": " + r);
        }, o = {};
        o.toStringArray = function(e, t) {
            if (!e || !(e = e.firstChild)) return [];
            t || (t = {});
            var r = {};
            for (r.tags = t.tags || /^(?:[bui]|strong|em)$/i, r.flushBefore = t.flushBefore || /^br$/i, 
            r.flushAfter = t.flushAfter, r.lineAfterFlush = t.lineAfterFlush, r.isEndNode = t.isEndNode, 
            r.tmpLine = "", r.lines = [], i(e, r), r.tmpLine && r.lines.push(r.tmpLine); r.lines.length && !r.lines[0].trim(); ) r.lines.shift();
            for (var n = r.lines.length; --n > 0 && !r.lines[n].trim(); ) r.lines.pop();
            return r.lines;
        };
        var i = function(e, t) {
            if (e) do {
                if (t.isEndNode && t.isEndNode(e)) return;
                if (3 === e.nodeType) t.tmpLine += e.nodeValue; else if (1 === e.nodeType) {
                    var r = e.tagName;
                    t.flushBefore && t.flushBefore.test(r) && (t.lines.push(t.tmpLine), t.tmpLine = ""), 
                    t.tags && t.tags.test(r) && i(e.firstChild, t), t.flushAfter && t.flushAfter.test(r) && (t.tmpLine && (t.lines.push(t.tmpLine), 
                    t.tmpLine = ""), t.lineAfterFlush && t.lineAfterFlush.test(r) && t.lines.push(""));
                }
            } while (e = e.nextSibling);
        };
        try {
            new DOMParser().parseFromString("", "text/html").body, o.toDOM = function(e) {
                return new DOMParser().parseFromString(e, "text/html");
            };
        } catch (s) {
            if (o.toDOM = function(e) {
                var t = document.implementation.createHTMLDocument("");
                return e && !/^\s+$/.test(e) && (t.open(), t.write(e + "</html>"), t.close()), t;
            }, window.opera) o.toDOM = function(e) {
                var t = document.implementation.createHTMLDocument("");
                return e = e.replace(/<img\s/gi, "<img src "), t.documentElement.innerHTML = e, 
                t;
            }; else try {
                if (!o.toDOM("<body><p></p></body>").querySelector("p")) return o.toDOM = function(e) {
                    var t = document.implementation.createHTMLDocument("");
                    return t.documentElement.innerHTML = e, t;
                }, void 0;
            } catch (s) {
                o.toDOM = function(e) {
                    var t = /<title\b[^>]*>([\S\s]+)<\/title/i.exec(e);
                    if (t) {
                        var r = document.createElement("div");
                        t = t[1].split(/<\/textarea/i)[0], r.innerHTML = "<textarea>" + t + "</textarea>", 
                        t = r.firstChild.value, r = null;
                    } else t = "";
                    e = e.replace(/^\s*<!doctype[^>]*>/i, ""), e = e.replace(/<(link|image)\b/gi, "$& href=data: "), 
                    e = e.replace(/<(img|script|style|video|audio|source|bgsound)\b/gi, "$& src=data: "), 
                    e = e.replace(/<\/?(object|applet)\b/gi, "$&dp"), e = e.replace(/<style\b/gi, "$& disabled "), 
                    e = e.replace(/\bo([Nn])/g, "&#111;$1").replace(/\bO([Nn])/g, "&#79;$1"), e = e.replace(/\b(style\s*=)/gi, "s$1");
                    var n;
                    e = e.replace(/<body\b/i, "<s tub></s>$&"), document.implementation.createHTMLDocument ? n = document.implementation.createHTMLDocument(t) : (n = document.createElement("html"), 
                    n.documentElement = n, n.getElementById = function(e) {
                        return n.querySelector("#" + ("" + e).replace(/\W/g, "\\$&"));
                    }, n.head = n.appendChild(document.createElement("head")), n.title = t, n.body = n.appendChild(document.createElement("body"))), 
                    n.body.innerHTML = e;
                    var o = n.body.querySelector("s[tub]");
                    if (o && o.parentNode === n.body) {
                        for (var i; (i = n.body.firstChild) != o; ) n.head.appendChild(i);
                        n.body.removeChild(o);
                    }
                    return n;
                };
            }
        }
        o.normalize_accents = r, o.search = {}, o.search.isSearchURL = function(e) {
            return /^https?:\/\/m\.bing\.com\//.test(e);
        }, o.search.get_url = function(e) {
            var t = "http://m.bing.com/search?q=", r = e.query;
            return e.site && (r = "site:" + e.site + " " + r), t += encodeURIComponent(r);
        }, o.search.getResultsFromResponse = function(e) {
            if (!e || "string" != typeof e) return [];
            for (var t, r = [], o = /<a href="(\/ins\?[^"]*?&amp;url=([A-Za-z0-9+\/=_]+)&amp;[^"]+)/g; null !== (t = o.exec(e)); ) {
                var i, s = t[2];
                try {
                    for (var a = s.split("_"), c = 0; a.length > c; ++c) 0 === c ? i = "" : i += 1 === c ? "?" : "&", 
                    i += window.atob(a[c]);
                } catch (l) {
                    n("SourceScraperUtils:search:getResultsFromResponse", "atob_error", "Failed to decode the URL, " + l), 
                    i = t[1].replace(/&amp;/g, "&");
                }
                r.push(i);
            }
            return r;
        }, t.SourceScraperUtils = o;
    }), r("LyricsSource", [ "require", "exports", "module", "ScrapedSource", "SourceScraperUtils" ], function(e, t) {
        function r(e) {
            o.call(this, e);
        }
        function n(e, t) {
            return t && t.keepAccents || (e = i.normalize_accents(e)), e;
        }
        var o = e("ScrapedSource").ScrapedSource, i = e("SourceScraperUtils").SourceScraperUtils;
        r.prototype = Object.create(o.prototype), r.prototype.constructor = r, r.Scheme = {
            identifier: "string",
            disabled: [ "undefined", "boolean" ],
            homepage: "string",
            description: [ "undefined", "string" ],
            url_result: [ "string", "function" ],
            method_result: [ "undefined", "string" ],
            payload_result: [ "undefined", "string", "function" ],
            headers_result: [ "undefined", "object" ],
            process_result: "function",
            url_search: [ "string", "function" ],
            method_search: [ "undefined", "string" ],
            payload_search: [ "undefined", "string", "function" ],
            headers_search: [ "undefined", "object" ],
            process_search: "function"
        }, r.prototype.handleSearch = function(e, t) {
            return this.process_lyrics(e, t);
        }, r.prototype.$ARTIST$SONG = function(e, t) {
            return e += "", e = e.replace(/\([^)]*\)/g, ""), e = e.replace(/\[[^\]]*\]/g, ""), 
            e = n(e, t), e = e.replace(/ +/g, " "), e = e.trim();
        }, r.prototype.$ARTIST = function(e, t) {
            return this.$ARTIST$SONG(e.artist + "", t);
        }, r.prototype.$SONG = function(e, t) {
            return this.$ARTIST$SONG(e.song + "", t);
        }, r.prototype.$SEARCHTERMS = function(e, t) {
            if (!e.videotitle) {
                if (e.searchTerms) return e.searchTerms;
                if (e.artist && e.song) return e.artist + " - " + e.song;
            }
            var r = e.videotitle + "";
            return r = r.replace(/\([^)]*\)/g, " "), r = r.replace(/\[[^\]]*\]/g, " "), r = r.replace(/\b(ft|feat)\b[^\-]+/i, ""), 
            r = r.replace(/\bhd\b/i, ""), r = r.replace(/(?:w.(?:th)? ?)?((?:on)?.?screen ?)?lyrics?/i, ""), 
            r = r.replace(/\b(?:(?:piano|guitar|drum|acoustic|instrument(?:al)?) ?)?cover( by [^ )\]]+)?/i, ""), 
            r = r.replace(/\b(?:recorded )?live (?:at|@|on).+$/i, ""), r = r.replace(/\b\d{1,2}[\-.\/]\d{1,2}[\-.\/](?:(?:1[789]|20)\d{2}|\d{2})\b/, ""), 
            r = r.replace(/[(\[][^\])]*(?:20|19)\d{2}[^\])]*[)\]]/, ""), r = r.replace(/\b1[789]\d{2}|20\d{2}\b/, ""), 
            r = r.replace(/\bYouTube\b/gi, ""), r = r.replace(/\bre.?uploaded\b/i, ""), r = r.replace(/\bhigh[\- ]?quality\b/i, ""), 
            r = r.replace(/\boffici?al\b/i, ""), r = r.replace(/\b(minecraft|rsmv|mmv|(?:(?:naruto|bleach|avatar|toradora|final ?fantasy ?\d{0,2})[^a-z0-9]+)?amv)/i, ""), 
            r = r.replace(/\b(?:full )?music\b/gi, ""), r = r.replace(/\bdemo\b/i, ""), r = r.replace(/\bfan(?:[\- ]?(?:video|made))?\b/i, ""), 
            r = r.replace(/\b(videos?|audio|acoustic)/gi, ""), r = r.replace(/\b(on ?)?iTunes\b/i, ""), 
            r = r.replace(/(^|[^a-z0-9])(?:240|360|480)p\b/i, ""), r = r.replace(/\.(3gp?[2p]|as[fx]|avi|flv|m[4o]v|mpe?g?[34]|rm|webm|wmv)\s*$/i, ""), 
            r = n(r, t), r = r.replace(/(?:^|\s)([^a-z0-9 ])(\1+)(?=\s|$)/gi, " "), r = r.replace(/^[\s\-']+|[\s\-']+$/g, ""), 
            r = r.replace(/\s{2,}/g, " ");
        }, r.prototype.$encSEARCHTERMS = function(e, t) {
            return encodeURIComponent(this.$SEARCHTERMS(e), t);
        }, t.LyricsSource = r;
    }), r("sources/lyrics.wikia.com", [ "require", "exports", "module", "LyricsSource", "SourceScraperUtils" ], function(e, t) {
        var r = e("LyricsSource").LyricsSource, n = e("SourceScraperUtils").SourceScraperUtils;
        t.source = new r({
            disabled: !1,
            identifier: "lyrics.wikia.com",
            homepage: "http://lyrics.wikia.com/",
            description: "The biggest lyrics database, containing millions of lyrics in several languages.",
            url_result: "http://lyrics.wikia.com/$ARTIST:$SONG",
            url_search: function(e) {
                return n.search.get_url({
                    site: "lyrics.wikia.com",
                    query: '"This song is performed by" ' + this.$SEARCHTERMS(e)
                });
            },
            process_result: function(e, t) {
                var r = n.toDOM(e), o = r.querySelector(".lyricbox");
                if (!o) {
                    var i = r.querySelector(".redirectText a[href]");
                    if (i && (i = i.getAttribute("href") || "", "/" === i.charAt(0) && (i = "http://lyrics.wikia.com" + i), 
                    i)) return t.found({
                        url: i
                    }), void 0;
                }
                var s = n.toStringArray(o);
                if (s.length) {
                    var a = r.title.split(" Lyrics - Lyric Wiki")[0].replace(":", " - ");
                    t.found({
                        lyrics: s,
                        title: a
                    });
                } else t.fail();
            },
            process_search: function(e, t) {
                for (var r = n.search.getResultsFromResponse(e), o = 0; r.length > o; o++) {
                    var i = r[o];
                    if (/^https?:\/\/lyrics\.wikia\.com\/(?!Category:)(?!User:)(?!Special:)[^:]+:./i.test(i)) return t.found({
                        redir: i
                    }), void 0;
                }
                t.fail();
            },
            $ARTIST$SONG: function(e, t) {
                return (t || (t = {})).keepAccents = !0, e = r.prototype.$ARTIST$SONG.call(this, e, t), 
                e = e.replace(/ /g, "_"), e = e.replace(/^_+|_+$/g, ""), e = e.replace(/(_|^)(.)/g, function(e, t, r) {
                    return t + r.toUpperCase();
                });
            },
            $ARTIST: function(e, t) {
                var n = r.prototype.$ARTIST.call(this, e, t);
                return /^(Category|User|Special)$/i.test(n) && (n += "_(Artist)"), n;
            }
        });
    }), r("sources/lyrics.com", [ "require", "exports", "module", "LyricsSource", "SourceScraperUtils" ], function(e, t) {
        var r = e("LyricsSource").LyricsSource, n = e("SourceScraperUtils").SourceScraperUtils;
        t.source = new r({
            disabled: !1,
            identifier: "lyrics.com",
            homepage: "http://www.lyrics.com/",
            description: "Millions of lyrics in several languages.",
            url_result: "http://www.lyrics.com/$SONG-lyrics-$ARTIST.html",
            method_search: "POST",
            headers_search: {
                "Content-Type": "application/x-www-form-urlencoded"
            },
            payload_search: "what=all&keyword=$encSEARCHTERMS",
            url_search: "http://www.lyrics.com/search.php?what=all&keyword=$encSEARCHTERMS",
            process_result: function(e, t) {
                var r = n.toDOM(e), o = r.querySelector("#lyrics,#lyric_space"), i = o && o.querySelector("a[href]");
                if (i && /^\s*Submit Lyrics\s*$/i.test(i.textContent)) return t.fail(), void 0;
                var s = n.toStringArray(o, {
                    tags: /^(?:[buiap]|div|strong|em)$/i,
                    flushBefore: /^(p|br|div)$/i,
                    flushAfter: /^(p|br|div)$/i
                });
                if (s.length) {
                    var a = r.title.replace(/\s+Lyrics$/, "");
                    t.found({
                        lyrics: s,
                        title: a
                    });
                } else t.fail();
            },
            process_search: function(e, t) {
                var r = n.toDOM(e), o = r.querySelector('a[href^="http://www.lyrics.com/search.php?what=rd"][href*="&rd="][href*="-lyrics-"]'), i = o && /&rd=([^&#]+)/.exec(o.getAttribute("href"));
                i ? (i = "http://www.lyrics.com/" + i[1], t.found({
                    redir: i
                })) : t.fail();
            },
            $ARTIST$SONG: function(e, t) {
                return e = r.prototype.$ARTIST$SONG.call(this, e, t), e = e.toLowerCase(), e = e.replace(/[^a-z0-9\- ]/g, ""), 
                e = e.replace(/ /g, "-"), e = e.replace(/-{2,}/, "-"), e = e.replace(/^-|-$/, "");
            }
        });
    }), r("sources/metrolyrics.com", [ "require", "exports", "module", "LyricsSource", "SourceScraperUtils" ], function(e, t) {
        var r = e("LyricsSource").LyricsSource, n = e("SourceScraperUtils").SourceScraperUtils;
        t.source = new r({
            disabled: !1,
            identifier: "metrolyrics.com",
            homepage: "http://www.metrolyrics.com/",
            description: "Millions of lyrics in several languages.",
            url_result: "http://m.metrolyrics.com/$SONG-lyrics-$ARTIST.html",
            url_search: function(e) {
                return n.search.get_url({
                    site: "metrolyrics.com",
                    query: this.$SEARCHTERMS(e)
                });
            },
            process_result: function(e, t, r) {
                var o = n.toDOM(e), i = o.querySelector(".lyricsbody,.gnlyricsbody"), s = n.toStringArray(i);
                if (s.length) {
                    var a = o.title.replace(/\s+Lyrics$/, ""), c = r.url.replace(/^(https?:\/\/)m\./, "$1www.");
                    t.found({
                        lyrics: s,
                        title: a,
                        url: c
                    });
                } else t.fail();
            },
            process_search: function(e, t) {
                for (var r = n.search.getResultsFromResponse(e), o = 0; r.length > o; o++) {
                    var i = r[o];
                    if (/^https?:\/\/(m|www)\.metrolyrics\.com\/[a-z0-9\-]+-lyrics-[a-z0-9\-]+\.html$/i.test(i)) return i = i.replace(/^(https?:\/\/)www\./, "$1m."), 
                    t.found({
                        redir: i
                    }), void 0;
                }
                t.fail();
            },
            $ARTIST$SONG: function(e, t) {
                return e = r.prototype.$ARTIST$SONG.call(this, e, t), e = e.toLowerCase(), e = e.replace(/([a-z])!([a-z])/g, "$1i$2"), 
                e = e.replace(/[^a-z0-9+\- ]/g, ""), e = e.replace(/[\- ]+/g, "-"), e = e.replace(/^-+|-+$/g, "");
            }
        });
    }), r("sources/lyricsmania.com", [ "require", "exports", "module", "LyricsSource", "SourceScraperUtils" ], function(e, t) {
        var r = e("LyricsSource").LyricsSource, n = e("SourceScraperUtils").SourceScraperUtils;
        t.source = new r({
            disabled: !0,
            identifier: "lyricsmania.com",
            homepage: "http://www.lyricsmania.com/",
            description: "Millions of English, French, German, Spanish and Italian lyrics (and others).",
            url_result: "http://www.lyricsmania.com/$SONG_lyrics_$ARTIST.html",
            url_search: function(e) {
                return n.search.get_url({
                    site: "lyricsmania.com",
                    query: this.$SEARCHTERMS(e)
                });
            },
            process_result: function(e, t) {
                var r = n.toDOM(e), o = r.querySelector("#songlyrics_h,#songlyrics"), i = n.toStringArray(o);
                if (i.length) {
                    var s = r.title.replace(/\s+Lyrics$/, "");
                    t.found({
                        lyrics: i,
                        title: s
                    });
                } else t.fail();
            },
            process_search: function(e, t) {
                for (var r = n.search.getResultsFromResponse(e), o = 0; r.length > o; o++) {
                    var i = r[o];
                    if (/^https?:\/\/www\.lyricsmania\.com\/.+_lyrics_.+\.html$/i.test(i)) return t.found({
                        redir: i
                    }), void 0;
                }
                t.fail();
            },
            $ARTIST$SONG: function(e, t) {
                return e = r.prototype.$ARTIST$SONG.call(this, e, t), e = e.toLowerCase(), e = e.replace(/&/g, "and"), 
                e = e.replace("[ost]", "_soundtrack_"), e = e.replace(/[ \/]/g, "_"), e = e.replace(/[^a-z0-9!,_\-@*:$°]/g, "");
            }
        });
    }), r("sources/azlyrics.com", [ "require", "exports", "module", "LyricsSource", "SourceScraperUtils" ], function(e, t) {
        var r = e("LyricsSource").LyricsSource, n = e("SourceScraperUtils").SourceScraperUtils;
        t.source = new r({
            disabled: !1,
            identifier: "azlyrics.com",
            homepage: "http://www.azlyrics.com/",
            description: "Hundred thousands of mostly English lyrics.",
            url_result: "http://www.azlyrics.com/lyrics/$ARTIST/$SONG.html",
            method_search: "GET",
            url_search: "http://search.azlyrics.com/search.php?q=$encSEARCHTERMS",
            process_result: function(e, t) {
                var r = n.toDOM(e), o = r.querySelector('div[style="margin-left:10px;margin-right:10px;"]'), i = n.toStringArray(o);
                if (i.length) {
                    var s = r.title.split("LYRICS -");
                    s[0] = s[0].replace(/([A-Z])(\S*)/g, function(e, t, r) {
                        return t.toUpperCase() + r.toLowerCase();
                    }), s = s.join("-"), t.found({
                        lyrics: i,
                        title: s
                    });
                } else t.fail();
            },
            process_search: function(e, t) {
                var r = n.toDOM(e), o = r.querySelector('a[href^="http://www.azlyrics.com/lyrics/"]');
                o ? t.found({
                    redir: o.href
                }) : t.fail();
            },
            $ARTIST$SONG: function(e, t) {
                return e = r.prototype.$ARTIST$SONG.call(this, e, t), e = e.toLowerCase(), e = e.replace(/([a-z])!([a-z])/g, "$1i$2"), 
                e = e.replace(/[^a-z0-9]/g, "");
            },
            $SEARCHTERMS: function(e, t) {
                var n = r.prototype.$SEARCHTERMS.call(this, e, t);
                return e.videotitle && (n = n.replace(/\s+-\s+/g, " ")), n;
            }
        });
    }), r("sources/lyricstime.com", [ "require", "exports", "module", "LyricsSource", "SourceScraperUtils" ], function(e, t) {
        var r = e("LyricsSource").LyricsSource, n = e("SourceScraperUtils").SourceScraperUtils;
        t.source = new r({
            disabled: !1,
            identifier: "lyricstime.com",
            homepage: "http://www.lyricstime.com/",
            description: "Millions of lyrics in several languages.",
            url_result: "http://www.lyricstime.com/$ARTIST-$SONG-lyrics.html",
            url_search: function(e) {
                return n.search.get_url({
                    site: "lyricstime.com",
                    query: this.$SEARCHTERMS(e)
                });
            },
            process_result: function(e, t) {
                var r = n.toDOM(e), o = r.querySelector("#songlyrics > p"), i = n.toStringArray(o);
                if (i.length) {
                    var s = r.title.replace(/\s+Lyrics$/, "");
                    t.found({
                        lyrics: i,
                        title: s
                    });
                } else t.fail();
            },
            process_search: function(e, t) {
                for (var r = n.search.getResultsFromResponse(e), o = 0; r.length > o; o++) {
                    var i = r[o];
                    if (/^https?:\/\/www\.lyricstime\.com\/.+-lyrics\.html$/i.test(i)) return t.found({
                        redir: i
                    }), void 0;
                }
                t.fail();
            },
            $ARTIST$SONG: function(e, t) {
                return (t || (t = {})).keepAccents = !0, e = r.prototype.$ARTIST$SONG.call(this, e, t), 
                e = e.toLowerCase(), e = e.replace(/([a-z])!([a-z])/g, "$1i$2"), e = e.replace(/[^a-z0-9]/g, "-"), 
                e = e.replace(/-{2,}/g, "-"), e = e.replace(/^-+|-+$/g, "");
            }
        });
    }), r("sources/lyricsmode.com", [ "require", "exports", "module", "LyricsSource", "SourceScraperUtils" ], function(e, t) {
        var r = e("LyricsSource").LyricsSource, n = e("SourceScraperUtils").SourceScraperUtils;
        t.source = new r({
            disabled: !1,
            identifier: "lyricsmode.com",
            homepage: "http://www.lyricsmode.com/",
            description: "Millions of lyrics in many languages.",
            url_result: "http://m.lyricsmode.com/lyrics/$ARTISTFIRSTLETTER/$ARTIST/$SONG.html",
            url_search: function(e) {
                return n.search.get_url({
                    site: "lyricsmode.com",
                    query: this.$SEARCHTERMS(e)
                });
            },
            process_result: function(e, t, r) {
                var o = n.toDOM(e), i = o.querySelector("#songlyrics"), s = n.toStringArray(i);
                if (s.length) {
                    var a = o.title.replace(/\s+Lyrics\s*(\| LyricsMode\.com Mobile)?$/i, ""), c = r.url.replace(/^(https?:\/\/)m\./, "$1www.");
                    t.found({
                        lyrics: s,
                        title: a,
                        url: c
                    });
                } else t.fail();
            },
            process_search: function(e, t) {
                for (var r = n.search.getResultsFromResponse(e), o = 0; r.length > o; o++) {
                    var i = r[o];
                    if (/^https?:\/\/(m|www)\.lyricsmode\.com\/lyrics\/(.)\/\2[^\/]+\/.+\.html$/i.test(i)) return i = i.replace(/^(https?:\/\/)www\./, "$1m."), 
                    t.found({
                        redir: i
                    }), void 0;
                }
                t.fail();
            },
            $ARTIST$SONG: function(e, t) {
                return e = r.prototype.$ARTIST$SONG.call(this, e, t), e = e.toLowerCase(), e = e.replace(/[ \-]/g, "_"), 
                e = e.replace(/([a-z])!([a-z])/g, "$1i$2"), e = e.replace(/[^a-z0-9_\-]/g, ""), 
                e = e.replace(/_{2,}/g, "_"), e = e.replace(/^_+|_+$/g, "");
            },
            $ARTISTFIRSTLETTER: function(e) {
                return this.$ARTIST(e).charAt(0);
            }
        });
    }), r("sources/magistrix.de", [ "require", "exports", "module", "LyricsSource", "SourceScraperUtils" ], function(e, t) {
        var r = e("LyricsSource").LyricsSource, n = e("SourceScraperUtils").SourceScraperUtils;
        t.source = new r({
            disabled: !0,
            identifier: "magistrix.de",
            homepage: "http://magistrix.de/lyrics/",
            description: "German source with hundred thousands of lyrics (German, English and others).",
            url_result: function(e) {
                return n.search.get_url({
                    site: "magistrix.de/lyrics",
                    query: "SONGTEXT " + this.$ARTIST(e) + " " + this.$SONG(e)
                });
            },
            url_search: function(e) {
                return n.search.get_url({
                    site: "magistrix.de/lyrics",
                    query: "SONGTEXT " + this.$SEARCHTERMS(e)
                });
            },
            process_result: function(e, t, r) {
                if (!/^https?:\/\/www\.magistrix\.de\//.test(r.url)) return this.process_search(e, t, r);
                var o = n.toDOM(e), i = o.querySelector("#songtext"), s = n.toStringArray(i, {
                    tags: /^([buip]|strong|em)$/i,
                    flushBefore: /^(br|p)$/i,
                    flushAfter: /^p$/i,
                    lineAfterFlush: /^p$/i
                });
                if (s.length) {
                    var a = o.title.replace("Songtext:", "").replace(/Lyrics\s*$/, "").trim();
                    if (!a) {
                        var c, l, u = o.querySelector("div[data-artist][data-song]");
                        u ? (c = u.getAttribute("data-artist"), l = u.getAttribute("data-song")) : (l = o.querySelector("h1 .headline"), 
                        c = o.querySelector(".artistlink"), c && l ? (c = c.textContent, l = l.textContent.replace(/\s*Lyrics$/, "")) : c = l = ""), 
                        a = c + " - " + l;
                    }
                    t.found({
                        lyrics: s,
                        title: a
                    });
                } else t.fail();
            },
            process_search: function(e, t) {
                for (var r, o = n.search.getResultsFromResponse(e), i = 0; o.length > i; i++) {
                    var s = o[i];
                    if (/^http:\/\/www\.magistrix\.de\/lyrics\/[^\/]+\/[^\/]+-\d+\.html/i.test(s)) {
                        if (!s.match(/\bUebersetzung-\d+\.html$/i, "")) return t.found({
                            redir: s
                        }), void 0;
                        r || (r = s);
                    }
                }
                return r ? (t.found({
                    redir: r
                }), void 0) : (t.fail(), void 0);
            }
        });
    }), r("sources/leoslyrics.com", [ "require", "exports", "module", "LyricsSource", "SourceScraperUtils" ], function(e, t) {
        var r = e("LyricsSource").LyricsSource, n = e("SourceScraperUtils").SourceScraperUtils;
        t.source = new r({
            disabled: !0,
            identifier: "leoslyrics.com",
            homepage: "http://www.leoslyrics.com/",
            description: "Hundred thousands of lyrics in many languages, popular among Idian users.",
            url_result: "http://www.leoslyrics.com/$ARTIST/$SONG-lyrics/",
            url_search: function(e) {
                return n.search.get_url({
                    site: "leoslyrics.com",
                    query: this.$SEARCHTERMS(e)
                });
            },
            process_result: function(e, t) {
                var r = n.toDOM(e), o = r.querySelector(".song > div"), i = n.toStringArray(o);
                if (i.length) {
                    var s = r.querySelector(".title-header h2 + ul > li a");
                    s = s && s.textContent.replace(/\s*Lyrics\s*$/i, "").trim();
                    var a = r.querySelector(".title-header h2");
                    a = a && a.textContent.replace(/\s*Lyrics\s*$/i, "").trim();
                    var c = s && a ? s + " - " + a : r.title.replace(/\sLYRICS$/i, "");
                    t.found({
                        lyrics: i,
                        title: c
                    });
                } else t.fail();
            },
            process_search: function(e, t) {
                for (var r = n.search.getResultsFromResponse(e), o = 0; r.length > o; o++) {
                    var i = r[o];
                    if (/^https?:\/\/www\.leoslyrics\.com\/[^\/]+\/.+-lyrics\/?$/i.test(i)) return t.found({
                        redir: i
                    }), void 0;
                }
                t.fail();
            },
            $ARTIST$SONG: function(e, t) {
                return e = r.prototype.$ARTIST$SONG.call(this, e, t), e = e.toLowerCase(), e = e.replace(/[.' +]/g, "-"), 
                e = e.replace(/[^a-z0-9!\-]/g, ""), e = e.replace(/-{2,}/g, "-");
            }
        });
    }), r("sources/vagalume.com.br", [ "require", "exports", "module", "LyricsSource", "SourceScraperUtils" ], function(e, t) {
        var r = e("LyricsSource").LyricsSource, n = e("SourceScraperUtils").SourceScraperUtils;
        t.source = new r({
            disabled: !0,
            identifier: "vagalume.com.br",
            homepage: "http://www.vagalume.com.br/",
            description: "Brazilian site providing millions of lyrics in many languages.",
            url_result: "http://www.vagalume.com.br/$ARTIST/$SONG.html",
            url_search: function(e) {
                return n.search.get_url({
                    site: "vagalume.com.br",
                    query: this.$SEARCHTERMS(e)
                });
            },
            process_result: function(e, t) {
                var r = n.toDOM(e), o = r.querySelector("#lyr_original div"), i = n.toStringArray(o, {
                    tags: /^(?:[buip]|strong|em|span)$/i,
                    flushBefore: /^(?:br|p)$/i,
                    flushAfter: /^p$/i
                });
                if (i.length) {
                    var s = r.title.replace(/ - VAGALUME$/i, "");
                    t.found({
                        lyrics: i,
                        title: s
                    });
                } else t.fail();
            },
            process_search: function(e, t) {
                for (var r = n.search.getResultsFromResponse(e), o = 0; r.length > o; o++) {
                    var i = /^http:\/\/(www|m)(\.vagalume\.com\.br\/(?!(my|top100|especiais|news|plugin|facebook|browse|playlisteiros)\/).*?\/(?!(discografia|fotos|popularidade|relacionados|news)\b).*?)$/i.exec(r[o]);
                    if (i) return i = "http://www" + i[2], i = i.replace(/-cifrada(\.html)?$/i, "$1"), 
                    t.found({
                        redir: i
                    }), void 0;
                }
                t.fail();
            },
            $ARTIST$SONG: function(e, t) {
                return e = r.prototype.$ARTIST$SONG.call(this, e, t), e = e.toLowerCase(), e = e.replace(/([a-z])!([a-z])/g, "$1i$2"), 
                e = e.replace(/[ .]/g, "-"), e = e.replace(/[^a-z0-9\-]/g, ""), e = e.replace(/-{2,}/g, "-"), 
                e = e.replace(/^-|-$/g, "");
            }
        });
    }), r("sources/letras.mus.br", [ "require", "exports", "module", "LyricsSource", "SourceScraperUtils" ], function(e, t) {
        var r = e("LyricsSource").LyricsSource, n = e("SourceScraperUtils").SourceScraperUtils;
        t.source = new r({
            disabled: !0,
            identifier: "letras.mus.br",
            homepage: "http://letras.mus.br/",
            description: "A big Brazilian source with millions of lyrics (also in many other languages).",
            url_result: "http://letras.mus.br/$ARTIST/$SONG/",
            url_search: function(e) {
                return n.search.get_url({
                    site: "letras.mus.br",
                    query: this.$SEARCHTERMS(e)
                });
            },
            process_result: function(e, t) {
                var r = n.toDOM(e), o = r.querySelector("#div_letra,#letra_original"), i = n.toStringArray(o, {
                    tags: /^(?:[buip]|strong|em|div)$/i,
                    flushBefore: /^(?:br|p|div)$/i,
                    flushAfter: /^(?:p|div)$/i,
                    lineAfterFlush: /^p$/i
                });
                if (i.length) {
                    var s, a = r.querySelector("#identificador_musica"), c = r.querySelector("#identificador_artista");
                    s = a && c ? a.textContent + " - " + c.textContent : r.title.replace(/\([^)]+\)/g, ""), 
                    t.found({
                        lyrics: i,
                        title: s
                    });
                } else t.fail();
            },
            process_search: function(e, t) {
                for (var r = n.search.getResultsFromResponse(e), o = 0; r.length > o; o++) {
                    var i = r[o];
                    if (/^http:\/\/letras\.mus\.br\/.*?\/.*?\//i.test(i)) return t.found({
                        redir: i
                    }), void 0;
                }
                t.fail();
            },
            $ARTIST$SONG: function(e, t) {
                return e = r.prototype.$ARTIST$SONG.call(this, e, t), e = e.toLowerCase(), e = e.replace(/[_ ]/g, "-"), 
                e = e.replace(/[^a-z0-9\-]/g, ""), e = e.replace(/-{2,}/g, "-"), e = e.replace(/^-+|-+$/g, "");
            }
        });
    }), r("algorithms", [ "require", "exports", "module", "normalize_accents" ], function(e, t) {
        function r(e, t) {
            e += "", t || (e = e.toLocaleLowerCase(), e = s(e), e = e.replace(/[.,?\/"':;|\\\]\[\{\}\(\)\-_=+!@#$%\^&*~`]/g, " ")), 
            e = (" " + e + " ").replace(/\s+/g, " ");
            for (var r = {}, n = -1, o = e.length - 1; o > ++n; ) {
                var i = e.substr(n, 2);
                r[i] = r[i] ? r[i] + 1 : 1;
            }
            return {
                length: o,
                hash: r
            };
        }
        function n(e, t, n) {
            var o = r(e, n), i = r(t, n), s = 0, a = o.length + i.length;
            if (!o.length || !i.length) return a ? 0 : 1;
            var c, l;
            i.length > o.length ? (c = o.hash, l = i.hash) : (c = i.hash, l = o.hash);
            for (var u = Object.keys(c), p = 0; u.length > p; ++p) {
                var d = u[p];
                l[d] && (s += c[d] > l[d] ? l[d] : c[d]);
            }
            return 2 * s / a;
        }
        function o(e) {
            if (-1 == e.indexOf("-")) return null;
            e = e.match(/^(.+?)\s-\s(.+)/) || e.match(/^(.+?)\s-(.+)/) || e.match(/^(.+?)-\s(.+)/) || e.match(/^(.+?)-(.+)/);
            var t = e[1].trim(), r = e[2].trim();
            return t && r ? [ t, r ] : null;
        }
        function i(e, t, r) {
            r = !isNaN(r) && isFinite(r) ? +r : .3;
            var i = o(e), s = o(t);
            return i && s ? n(i[0], s[0]) > r && n(i[1], s[1]) > r : n(e, t) > r;
        }
        var s = e("normalize_accents").normalize_accents;
        t.getSimilarityCoefficient = n, t.splitSongTitle = o, t.isTitleSimilar = i;
    }), r("sources/darklyrics.com", [ "require", "exports", "module", "LyricsSource", "SourceScraperUtils", "algorithms" ], function(e, t) {
        function r(e) {
            return e.replace(/[^a-z0-9'. ]/i, " ").replace(/\s+/, " ").trim();
        }
        function n(e) {
            return e && e.replace(/^\s*\d+\./, "").trim() || "";
        }
        function o(e, t) {
            for (var r, o = -1/0, i = 0; e.length > i; i++) {
                var s = e[i], c = n(s.textContent).toLowerCase(), l = a.getSimilarityCoefficient(c, t);
                l > o && (o = l, r = s);
            }
            return o > .3 ? r : null;
        }
        var i = e("LyricsSource").LyricsSource, s = e("SourceScraperUtils").SourceScraperUtils, a = e("algorithms");
        t.source = new i({
            disabled: !0,
            identifier: "darklyrics.com",
            homepage: "http://www.darklyrics.com/",
            description: "Dark Lyrics is provides Metal lyrics for 4500+ bands.",
            url_result: function(e) {
                return "http://www.darklyrics.com/search?q=" + encodeURIComponent(r(this.$ARTIST(e)) + " " + r(this.$SONG(e)));
            },
            url_search: function(e) {
                return "http://www.darklyrics.com/search?q=" + encodeURIComponent(r(this.$SEARCHTERMS(e)));
            },
            process_result: function(e, t, r) {
                if (/^https?:\/\/www\.darklyrics\.com\/search/.test(r.url)) return this.process_search(e, t, r);
                var i = s.toDOM(e), a = i.querySelectorAll("h3 > a");
                if (!a) return t.fail(), void 0;
                var c = i.title.split(/\sLyrics\s/i, 1)[0].toLowerCase(), l = r.query.song && this.$SONG(r.query);
                l || (l = this.$SEARCHTERMS(r.query) || "", l = l.toLowerCase().replace(c, " "), 
                l = l.replace(/\s+/, " ").replace(/^[\s\-]+|[\s\-]+$/g, ""));
                var u = o(a, l);
                if (!u || !u.parentNode) return t.fail(), void 0;
                var p = s.toStringArray({
                    firstChild: u.parentNode.nextSibling
                }, {
                    isEndNode: function(e) {
                        return "H3" === e.nodeName.toUpperCase();
                    }
                });
                if (p.length) {
                    c = c.replace(/([a-z])(\S*)/g, function(e, t, r) {
                        return t.toUpperCase() + r.toLowerCase();
                    }), l = n(u.textContent);
                    var d = c + " - " + l;
                    t.found({
                        lyrics: p,
                        title: d,
                        url: r.url.replace(/(#\d*)?$/, "#" + u.name)
                    });
                } else t.fail();
            },
            process_search: function(e, t, r) {
                var n = s.toDOM(e), i = n.querySelectorAll('a[href*="lyrics/"][href*=".html#"]'), a = o(i, this.$SEARCHTERMS(r.query)), c = a && a.getAttribute("href").replace(/^(?!http)/i, "http://www.darklyrics.com/");
                return /^http:\/\/www\.darklyrics\.com\/lyrics\//i.test(c) ? (t.found({
                    redir: c
                }), void 0) : (t.fail(), void 0);
            }
        });
    }), r("sources/metal-archives.com", [ "require", "exports", "module", "LyricsSource", "SourceScraperUtils", "algorithms" ], function(e, t) {
        function r(e, t, r) {
            if (e) {
                for (var n = -1, o = -1/0, s = 0; e.length > s; s++) {
                    var a = r(e[s]);
                    if (a) {
                        var c = i.getSimilarityCoefficient(a, t);
                        if (c > o && (n = s, o = c, 1 == c)) break;
                    }
                }
                return o > .3 ? n : -1;
            }
        }
        var n = e("LyricsSource").LyricsSource, o = e("SourceScraperUtils").SourceScraperUtils, i = e("algorithms"), s = /^https?:\/\/www\.metal-archives\.com\/search\/ajax-advanced\/searching\/songs\/\?songTitle=(.*?)&bandName=(.*)/, a = /^https?:\/\/www\.metal-archives\.com\/albums\/([^\/]+)\/([^\/]+).*/i, c = /"https?:\/\/www\.metal-archives\.com\/albums\/([^\/]+)\/([^\/]+).*?"/i;
        t.source = new n({
            disabled: !0,
            identifier: "metal-archives.com",
            homepage: "http://www.metal-archives.com/",
            description: "The Metal Archives is an extensive database (90k+ bands) of metal lyrics.",
            url_result: function(e) {
                return "http://www.metal-archives.com/search/ajax-advanced/searching/songs/?songTitle=" + encodeURIComponent(this.$SONG(e)) + "&bandName=" + encodeURIComponent(this.$ARTIST(e));
            },
            url_search: function(e) {
                return o.search.get_url({
                    site: "metal-archives.com/albums",
                    query: this.$SEARCHTERMS(e)
                });
            },
            process_result: function(e, t, r) {
                if (s.test(r.url) || a.test(r.url)) return this.process_search(e, t, r);
                if (/^\s*(<[^>]*>)?\(lyrics not available\)/i.test(e)) return t.fail(), void 0;
                var n = o.toDOM(e), i = n.querySelectorAll("h3 > a");
                if (!i) return t.fail(), void 0;
                var c = o.toStringArray(n.body);
                c.length ? t.found({
                    lyrics: c,
                    title: r.tempData && r.tempData.song_title || "(N/A)",
                    url: r.tempData && r.tempData.song_url || r.url
                }) : t.fail();
            },
            process_search: function(e, t, n) {
                if (!/^https?:\/\/www\.metal-archives\.com\//.test(n.url)) {
                    for (var i = o.search.getResultsFromResponse(e), l = 0; i.length > l; l++) {
                        var u = i[l];
                        if (a.test(u)) return t.found({
                            redir: u
                        }), void 0;
                    }
                    return t.fail(), void 0;
                }
                var p, d, f, h, m, g;
                if (s.exec(n.url), s.test(n.url)) try {
                    var y = JSON.parse(e);
                    if (p = this.$ARTIST(n.query), d = this.$SONG(n.query), !y || !y.aaData || !y.aaData.length) return t.fail(), 
                    void 0;
                    if (h = r(y.aaData, p + "/" + d, function(e) {
                        var t = e[1] && c.exec(e[1]);
                        return t ? t[1] + "/" + t[2] : void 0;
                    }), -1 === h) return t.fail(), void 0;
                    var v = y.aaData[h];
                    m = c.exec(v[1]), f = m[0], p = v[0].match(/[^><]+(?=<\/a>)/i), p = p && p[0].trim() || decodeURIComponent(m[1]).replace(/_/, " "), 
                    d = v[3], g = /lyricsLink_(\d+)/.exec(v[4]), g = g ? g[1] : 0;
                } catch (b) {
                    return t.fail(), void 0;
                } else if (a.test(n.url)) {
                    var S = o.toDOM(e), L = S.querySelectorAll("tr[id^=song]");
                    p = S.querySelector(".band_name"), p ? p = p.textContent.trim() : (m = a.match(n.url), 
                    p = decodeURIComponent(m[1]).replace(/_/, " ")), d = n.query.song && this.$SONG(n.query);
                    var w = "";
                    if (d || (d = this.$SEARCHTERMS(n.query), w = p), d = d.toLowerCase(), h = r(L, d, function(e) {
                        return /\d/.test(e.id) ? (e = e.previousElementSibling, e && e.cells && e.cells[1] ? w + " " + e.cells[1].textContent.trim().toLowerCase() : void 0) : void 0;
                    }), -1 === h) return t.fail(), void 0;
                    var x = L[h];
                    f = n.url, d = x.previousElementSibling.cells[1].textContent.trim(), g = x.id.replace(/\D+/, "");
                }
                t.found({
                    redir: "http://www.metal-archives.com/release/ajax-view-lyrics/id/" + g,
                    tempData: {
                        song_url: f,
                        song_title: p + " - " + d
                    }
                });
            }
        });
    }), r("sources/musica.com", [ "require", "exports", "module", "LyricsSource", "SourceScraperUtils" ], function(e, t) {
        var r = e("LyricsSource").LyricsSource, n = e("SourceScraperUtils").SourceScraperUtils;
        t.source = new r({
            disabled: !0,
            identifier: "musica.com",
            homepage: "http://www.musica.com/",
            description: "Spanish site with 800k lyrics.",
            url_result: function(e) {
                return n.search.get_url({
                    site: "musica.com",
                    query: '"letras.asp?letra=" "Letra de" "' + this.$SONG(e) + '"' + ' de "' + this.$ARTIST(e) + '"'
                });
            },
            url_search: function(e) {
                return n.search.get_url({
                    site: "musica.com",
                    query: '"Letra de" "letras.asp?letra=" ' + this.$SEARCHTERMS(e)
                });
            },
            process_result: function(e, t, r) {
                if (!/^https?:\/\/www\.musica\.com\/letras\.asp/.test(r.url)) return this.process_search(e, t, r);
                var o, i, s, a = n.toDOM(e), c = a.querySelector('font[style*="line-height"][style*=family]');
                if (!c || 2 !== (s = a.querySelectorAll('h1 a[href*="letras.asp?letra"]')).length || !(i = s[0].textContent.trim()) || !(o = s[1].textContent.replace(/\([^)]*\)\s*$/, "").trim())) return t.fail(), 
                void 0;
                var l = n.toStringArray(c);
                l.length ? t.found({
                    lyrics: l,
                    title: i + " - " + o
                }) : t.fail();
            },
            process_search: function(e, t) {
                for (var r = n.search.getResultsFromResponse(e), o = 0; r.length > o; o++) {
                    var i = r[o];
                    if (/^https?:\/\/www\.musica\.com\/letras\.asp\?.*?letra=\d+/i.test(i)) return t.found({
                        redir: i
                    }), void 0;
                }
                t.fail();
            },
            $ARTIST$SONG: function(e, t) {
                return e = r.prototype.$ARTIST$SONG.call(this, e, t), e = e.replace(/([a-z])!([a-z])/gi, "$1i$2"), 
                e = e.replace(/[":']/g, " "), e = e.replace(/ +/, " ");
            }
        });
    }), r("sources/shironet.mako.co.il", [ "require", "exports", "module", "LyricsSource", "SourceScraperUtils" ], function(e, t) {
        var r = e("LyricsSource").LyricsSource, n = e("SourceScraperUtils").SourceScraperUtils, o = function(e) {
            return /[\u0590-\u05FF]/.test(e);
        };
        t.source = new r({
            disabled: !0,
            identifier: "shironet.mako.co.il",
            homepage: "http://shironet.mako.co.il/",
            description: "The best source for Hebrew lyrics.",
            url_result: function(e) {
                return this.url_search(e);
            },
            url_search: function(e) {
                return e = this.$SEARCHTERMS(e), o(e) ? "http://shironet.mako.co.il/searchSongs?type=lyrics&q=" + encodeURIComponent(e) : "";
            },
            process_result: function(e, t, r) {
                if (/^https?:\/\/shironet\.mako\.co\.il\/searchSongs/.test(r.url)) return this.process_search(e, t, r);
                var o = n.toDOM(e), i = o.querySelector(".artist_lyrics_text"), s = n.toStringArray(i);
                if (s.length) {
                    var a = o.querySelector(".artist_singer_title");
                    a = a && a.textContent.trim();
                    var c = o.querySelector(".artist_song_name_txt");
                    c = c && c.textContent.trim();
                    var l = a + " - " + c;
                    t.found({
                        lyrics: s,
                        title: l
                    });
                } else t.fail();
            },
            process_search: function(e, t) {
                var r = n.toDOM(e), o = r.querySelector('a[href*="/artist?type=lyrics"][class*="search"]'), i = o && o.getAttribute("href").replace(/^\//i, "http://shironet.mako.co.il/");
                i ? t.found({
                    redir: i
                }) : t.fail();
            },
            $ARTIST$SONG: function(e, t) {
                return (t || (t = {})).keepAccents = !0, e = r.prototype.$ARTIST$SONG.call(this, e, t), 
                e = e.replace(/[^\u0590-\u05FF\d\-]+/g, " "), e = e.replace(/^[ \-]+|[ \-]+$/g, ""), 
                e = e.replace(/ +/g, " ");
            },
            $SEARCHTERMS: function(e, t) {
                var r, n = function(e) {
                    return e = e.replace(/[^\u0590-\u05FF\d\-]+/g, " "), e = e.replace(/(מילים לשיר|עם מילים|עם כתוביות|קאבר|אקוסטי|בהופעה)/g, " "), 
                    e = e.replace(/^[ \-]+|[ \-]+$/g, ""), e = e.replace(/ +/g, " ");
                };
                if (!e.videotitle && (r = e.searchTerms, !r)) {
                    var o = this.$ARTIST(e, t), i = this.$SONG(e, t);
                    o && i && (r = n(o + " - " + i));
                }
                return !r && e.videotitle && (r = e.videotitle, r = r.replace(/\([^)]*\)/g, " "), 
                r = r.replace(/\[[^\]]*\]/g, " "), r = n(r), r || (r = n(e.videotitle))), r;
            }
        });
    }), r("sources/angolotesti.it", [ "require", "exports", "module", "LyricsSource", "SourceScraperUtils" ], function(e, t) {
        var r = e("LyricsSource").LyricsSource, n = e("SourceScraperUtils").SourceScraperUtils;
        t.source = new r({
            disabled: !0,
            identifier: "angolotesti.it",
            homepage: "http://www.angolotesti.it/",
            description: "The largest lyrics provider of Italy, with hundred thousands of lyrics.",
            url_result: function(e) {
                return n.search.get_url({
                    site: "angolotesti.it",
                    query: this.$SONG(e) + " Testo " + this.$ARTIST(e)
                });
            },
            url_search: function(e) {
                return n.search.get_url({
                    site: "angolotesti.it",
                    query: this.$SEARCHTERMS(e) + " Testo"
                });
            },
            process_result: function(e, t, r) {
                if (n.search.isSearchURL(r.url)) return this.process_search(e, t, r);
                var o = n.toDOM(e), i = o.querySelector(".testo"), s = n.toStringArray(i);
                if (s.length) {
                    var a = o.title.replace(/^(.+?) Testo (.+?)$/, "$2 - $1");
                    t.found({
                        lyrics: s,
                        title: a
                    });
                } else t.fail();
            },
            process_search: function(e, t) {
                for (var r = n.search.getResultsFromResponse(e), o = 0; r.length > o; o++) {
                    var i = r[o];
                    if (/^https?:\/\/(www\.)?angolotesti\.it\/(0-9|[a-z])\/[^\/]*\d\/[^\/]*\d/i.test(i)) return t.found({
                        redir: i
                    }), void 0;
                }
                t.fail();
            }
        });
    }), r("sources/lyrics", [ "require", "exports", "module", "config", "sources/lyrics.wikia.com", "sources/lyrics.com", "sources/metrolyrics.com", "sources/lyricsmania.com", "sources/azlyrics.com", "sources/lyricstime.com", "sources/lyricsmode.com", "sources/magistrix.de", "sources/leoslyrics.com", "sources/vagalume.com.br", "sources/letras.mus.br", "sources/darklyrics.com", "sources/metal-archives.com", "sources/musica.com", "sources/shironet.mako.co.il", "sources/angolotesti.it" ], function(e, t) {
        for (var r = e("config"), n = function(e, t, r) {
            console && console.log(e + ": " + r);
        }, o = [ e("sources/lyrics.wikia.com").source, e("sources/lyrics.com").source, e("sources/metrolyrics.com").source, e("sources/lyricsmania.com").source, e("sources/azlyrics.com").source, e("sources/lyricstime.com").source, e("sources/lyricsmode.com").source, e("sources/magistrix.de").source, e("sources/leoslyrics.com").source, e("sources/vagalume.com.br").source, e("sources/letras.mus.br").source, e("sources/darklyrics.com").source, e("sources/metal-archives.com").source, e("sources/musica.com").source, e("sources/shironet.mako.co.il").source, e("sources/angolotesti.it").source ], i = 0; o.length > i; ++i) o[i]._disabled = o[i].disabled;
        var s = function(e, t) {
            for (var r = 0; e.length > r; r++) if (e[r].identifier === t) return r;
            return -1;
        }, a = function(e, t) {
            if (e) for (var r = e.length - 1; r >= 0; --r) {
                var o = e[r], i = s(t, o);
                i >= 0 ? t.unshift(t.splice(i, 1)[0]) : n("getLyricsSources", "id_unknown", 'Unknown identifier found in the "order" preference.');
            }
        }, c = function(e, t, r) {
            if (e) for (var n = r.length - 1; n >= 0; --n) {
                var o = r[n].identifier;
                r[n].disabled = -1 !== e.indexOf(o) ? !0 : t && -1 !== t.indexOf(o) ? !1 : r[n]._disabled;
            }
        }, l = function(e) {
            for (var t = e.length - 1; t >= 0; --t) e[t].disabled === !0 && e.splice(t, 1);
        }, u = function(e, t) {
            r.getItem("lyricsSourcePreferences", function(r) {
                for (var n = o.slice(0), i = n.length, s = 0, u = i - 1; u >= 0; --u) n[u].disabled = n[u]._disabled;
                r && (r.order && (s = r.order.length), a(r.order, n), c(r.blacklist, r.whitelist, n)), 
                e && l(n), n.stats = {
                    old: s,
                    "new": i - s,
                    total: i
                }, t(n);
            });
        }, p = function(e) {
            u(!1, e);
        }, d = function(e) {
            u(!0, e);
        };
        t.getAllLyricsSources = p, t.getLyricsSources = d;
    }), r("SimpleTemplating", [ "require", "exports", "module" ], function(e, t) {
        function r(e) {
            return this instanceof r ? (this.useTemplate(e), void 0) : new r(e);
        }
        function n(e, t, r) {
            var n = /^on(.+)$/.exec(r);
            if (!n) return e[r] = t[r], void 0;
            var o = n[1], i = "data-robw-" + o, s = e[i], a = t[r];
            s && (e.removeEventListener(o, s, !1), delete e[i]), "function" == typeof a && (e.addEventListener(o, a, !1), 
            e[i] = a);
        }
        var o = function(e, t, r) {
            console && console.log(e + ": " + r);
        }, i = function(e, t, r) {
            var n = Error(e + ": " + r);
            throw n.type = t, n;
        };
        r.prototype.useTemplate = function(e) {
            var t = e.tagName;
            if (t && e.cloneNode) return this.element = e, this;
            t || (t = "div");
            var r = document.createElement(t);
            return Object.keys(e).forEach(function(t) {
                "tagName" !== t && (r[t] = e[t]);
            }), this.element = r, this;
        }, r.prototype.getElement = function() {
            return this.element || i("SimpleTemplating::getElement", "invalid_state", "Cannot use getElement() before an element has been defined! Construct the base element using useTemplate(template)"), 
            this.element;
        }, r.prototype.update = function(e) {
            var t = this.getElement();
            return Object.keys(e).forEach(function(r) {
                var i = t.querySelectorAll(r);
                if (i.length) for (var s = e[r], a = s._pre, c = s._post, l = i.length - 1; l >= 0; --l) {
                    var u = i[l], p = {};
                    "function" == typeof a && a(u, p);
                    for (var d = Object.keys(s), f = 0; d.length > f; ++f) {
                        var h = d[f];
                        "_pre" !== h && "_post" !== h && n(u, s, h);
                    }
                    "function" == typeof c && c(u, p);
                } else o("SimpleTemplating::update", "no_nodes", "No matching nodes found for " + r);
            }), this;
        }, t.SimpleTemplating = r;
    }), r("text", {
        load: function(e) {
            throw Error("Dynamic load not allowed: " + e);
        }
    }), r("text!style/lyricsPanel.css", [], function() {
        return '.L759-overlay{position:fixed;bottom:0;right:0;width:100%;height:100%;background-color:transparent !important;z-index:9999}\n.L759-overlay,.L759-container,.L759-container *{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}\n.L759-container{position:fixed;top:2px;right:2px;width:275px;z-index:10000;font-family:arial,sans-serif;overflow:hidden;background-color:#fff !important;color:#000 !important;border:1px solid #bbe !important;padding:5px 1px 1px 5px;display:block;border-radius:5px 5px 5px 0;line-height:15px;font-size:14px;min-height:25px;min-width:67px;-webkit-box-shadow:1px 1px 4px lightGrey;box-shadow:1px 1px 4px lightGrey}.L759-container.boxsizingbug{min-height:17px;min-width:59px}\n.L759-container *{color:inherit !important}\n.L759-container button,.L759-container input{display:inline-block;height:20px;margin:0;border:0;background-color:transparent !important;padding:0;line-height:1.2em;font-size:13px;color:#000 !important}\n.L759-container .L759-buttons button{background-color:#ccc !important;cursor:pointer;padding:0 5px;font-size:16px;color:#333 !important}\n.L759-container a,.L759-container .L759-link-style{cursor:pointer;color:#438bc5 !important;text-decoration:none}\n.L759-container a:hover,.L759-container .L759-link-style:hover{text-decoration:underline;background-color:transparent !important}\n.L759-container .L759-title{border-bottom:3px double #99f !important;font-size:17px;height:22px;margin-right:25px;overflow:hidden;cursor:move;white-space:nowrap;text-overflow:ellipsis}\n.L759-container .L759-close{overflow:visible}\n.L759-container .L759-close,.L759-container .L759-close:before{position:absolute;height:25px;width:25px;top:0;right:0;z-index:50;cursor:pointer;background-color:#f50 !important;display:block}\n.L759-container .L759-close:before{content:"";background:transparent url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA0AAAANCAYAAABy6+R8AAAA0klEQVQokWNggIKrV69yv3r1ypUBC3jz5o3906dPhVAEQRrevn17AIj/vH79OgJZDmiQB1D8BxCfg2uEaXj37t1/EAZpBJociawBSQ6i8eXLlzpAznuYBEwjEPcga4Dir0CDrGBuNgYqeIemAB1/BapzQvcsPo2YGmAAGAiF2DQBDevAqgHd0+h+hAUOURqQNcKjA+oXjFACiuWi+xEaqs4MZ86cYQEKrMbmaaiByNGxC6ieE2wbkkaMUALyTaAaERpgAKQR6GYDbIH04sULbWQNADXdoxVKiraqAAAAAElFTkSuQmCC") center no-repeat !important;opacity:1}\n.L759-container .L759-close:hover:before{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA0AAAANCAYAAABy6+R8AAAAzElEQVQokWNggIJXr15x//nzx5UBCwCK23/69EkIRRCk4d+/fweA+M/fv38j0DR4AMV/APE5uEaYhv9QANUYiawBSQ6i8devXzpAzvv/SACkEYh7kDVAxb/+/v3bCmwbkGEMFHj3Hw8AaQDa7ITiL3wasWqAAaBfCnFo6sCqAd3T6H6EBQ5RGtA0RiD7BSOUgApy0f0I0ggEzgxnzpxhAXJWY/M01MD3SHK7nj17xgm2DaYRWygBNZqANKJogAGQRmBEG2ALJKC4NrIGAGjtuqnt84LiAAAAAElFTkSuQmCC") !important}\n.L759-container .L759-content{overflow:auto;word-wrap:break-word}.L759-container .L759-content .L759-link-container{border:0;border-bottom:1px solid #759 !important;text-align:center}\n.L759-container .L759-content .L759-info{display:none;border:0;border-bottom:1px solid #759 !important;min-height:40px;padding-left:40px;background:2px 2px no-repeat url("https://rob.lekensteyn.nl/youtubelyrics/icons/32.png") !important}.L759-container .L759-content .L759-info.L759-http{background-image:url("http://rob.lekensteyn.nl/youtubelyrics/icons/32.png") !important}\n.L759-container .L759-content .L759-info .L759-song-title{font-style:italic}\n.L759-container .L759-content .L759-info .L759-link-to-found-source{font-weight:bold}\n.L759-container .L759-content>div{padding-top:2px}\n.L759-container .L759-content .L759-lyrics-line{min-height:15px;padding-left:1em;text-indent:-1em}\n.L759-container .L759-content .L759-result[dir=rtl] .L759-lyrics-line{padding-left:0;padding-right:1.2em}\n.L759-container .L759-searchbox{padding-left:12px;width:100%}.L759-container .L759-searchbox .L759-searchterms{width:100%;float:left;margin:0 -30px 0 0;padding:0 30px 0 0;border:1px solid lightGrey !important}.L759-container .L759-searchbox .L759-searchterms:-moz-placeholder{color:#cacaca !important}\n.L759-container .L759-searchbox .L759-searchterms::-moz-placeholder{color:#cacaca !important}\n.L759-container .L759-searchbox .L759-searchterms::-webkit-input-placeholder{color:#cacaca !important}\n.L759-container .L759-searchbox .L759-searchterms:focus:-moz-placeholder{color:transparent !important}\n.L759-container .L759-searchbox .L759-searchterms:focus::-moz-placeholder{color:transparent !important}\n.L759-container .L759-searchbox .L759-searchterms:focus::-webkit-input-placeholder{color:transparent !important}\n.L759-container .L759-searchbox .L759-dosearch{width:30px;background:#fafafa url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA0AAAANCAYAAABy6+R8AAAAe0lEQVQoz62RwQmAMBAEE3zZX57BWtKJ4D0D1mAXdpAyjBvch4YTNbgwn9sMHBdjjljgQQSJRM6sUVKGAeQbgiZ6lhsQ4IhwlvnmkshClC2EXayLxMIpkmOXfpGa1ntziOHryQsj6DSx/twZrE+ilh4sJ3F6I2mibxHNDkVQQZxWN/WxAAAAAElFTkSuQmCC") center no-repeat !important;opacity:.6;border:1px solid lightGrey !important;height:20px;cursor:default}.L759-container .L759-searchbox .L759-dosearch:hover,.L759-container .L759-searchbox .L759-dosearch:focus,.L759-container .L759-searchbox .L759-dosearch:active{opacity:1}\n.L759-container .L759-searchbox .L759-dosearch:active{background-color:#eee !important}\n.L759-container .L759-searchbox .L759-searchterms,.L759-container .L759-searchbox .L759-dosearch{border-bottom-right-radius:5px}\n.L759-container .L759-resizer{position:absolute;left:0;bottom:0;width:17px;height:17px;background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAYAAAA7bUf6AAAAKklEQVQ4jWMIDQ39z0ApABkyahCmRooNwqZppBtEjCaCBhGradSgATAIAGuTiXfwFGCyAAAAAElFTkSuQmCC") !important;cursor:sw-resize}\n.L759-skin-dark{background-color:#000 !important;color:#ccc !important;border-color:#888 !important;-webkit-box-shadow:1px 1px 4px #777;box-shadow:1px 1px 4px #777}.L759-skin-dark button,.L759-skin-dark input{background-color:transparent !important;color:#ccc !important}\n.L759-skin-dark .L759-buttons button{background-color:#333 !important;color:#999 !important}\n.L759-skin-dark a,.L759-skin-dark .L759-link-style{color:#8dd !important}\n.L759-skin-dark .L759-title{border-bottom-color:#aaa !important}\n.L759-skin-dark .L759-close{background-color:#555 !important}.L759-skin-dark .L759-close:before{opacity:.6}\n.L759-skin-dark .L759-content .L759-link-container{border-bottom-color:#aaa !important}\n.L759-skin-dark .L759-content .L759-info{background-image:url("https://rob.lekensteyn.nl/youtubelyrics/icons/32-dark.png") !important;border-bottom-color:#aaa !important}.L759-skin-dark .L759-content .L759-info.L759-http{background-image:url("http://rob.lekensteyn.nl/youtubelyrics/icons/32-dark.png") !important}\n.L759-skin-dark .L759-searchbox .L759-searchterms{border-color:#444 !important}.L759-skin-dark .L759-searchbox .L759-searchterms:-moz-placeholder{color:#cacaca !important}\n.L759-skin-dark .L759-searchbox .L759-searchterms::-moz-placeholder{color:#cacaca !important}\n.L759-skin-dark .L759-searchbox .L759-searchterms::-webkit-input-placeholder{color:#cacaca !important}\n.L759-skin-dark .L759-searchbox .L759-dosearch{background-color:#aaa !important;border-color:#444 !important}.L759-skin-dark .L759-searchbox .L759-dosearch:active{background-color:#999 !important}\n';
    }), r("text!templates/lyricsPanel.html", [], function() {
        return '<div class="L759-title"></div>\n<button class="L759-close"></button>\n<div class="L759-content">\n  <div class="L759-fetching">\n    <div class="L759-buttons">\n      <button class="L759-b-abort">Abort</button>\n      <button class="L759-b-retry">Retry</button>\n      <button class="L759-b-next">Next</button>\n    </div>\n    <div class="L759-status">\n    Loading <a class="L759-link-to-fetched-source" target="_blank" rel="noreferrer">nothing</a>.\n    <br><br>\n    &raquo; <a class="L759-settings-link" href="https://rob.lekensteyn.nl/youtubelyrics/#config" target="_blank">Settings for \'YouTube Lyrics\'</a>\n    </div>\n  </div>\n  <div class="L759-done">\n    <div class="L759-link-container">\n      <span class="L759-switch-source L759-link-style">\n        &raquo; Different source (<span class="L759-sourceindex"></span> / <span class="L759-sourcecount"></span>)\n      </span>\n      <span class="L759-toggle-info L759-link-style">&raquo; Info</span>\n    </div>\n    <div class="L759-info">\n      <div class="L759-song-info">\n      The lyrics for <span class="L759-song-title"></span> were retrieved from <a class="L759-link-to-found-source" target="_blank" rel="noreferrer"></a>.\n      </div>\n      <br>\n      &raquo; <a class="L759-settings-link" href="https://rob.lekensteyn.nl/youtubelyrics/#config" target="_blank">Settings for \'YouTube Lyrics\'</a>\n    </div>\n    <div class="L759-result"></div>\n  </div>\n</div>\n<div class="L759-searchbox">\n  <input type="text" class="L759-searchterms" placeholder=" artist - song">\n  <button class="L759-dosearch"></button>\n</div>\n<div class="L759-resizer"></div>';
    }), r("text!style/pageAction.css", [], function() {
        return ".YouTubeLyricsByRobWPageActionIcon {\n  -webkit-box-sizing: border-box;\n  -moz-box-sizing: border-box;\n  box-sizing: border-box;\n  position: fixed;\n  top: 50px;\n  right: 0;  \n  z-index: 99999;\n  display: inline-block;\n  height: 30px;\n  width: 30px;\n  margin: 0;\n  border: 1px solid #999;\n  padding: 0;\n  background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAYAAAByDd+UAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAGDgAABg4BKbET0gAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAPwSURBVEjH7VbtL2RXGJ//gg/ig29V2W5TbUT4gLbbWXbHS1JMLBWqKRUr9AOJotFSKlJGvaSZbKTEFyVCWBKrpuItMVrT7CwSYb2Eced9xsxc49d5Hpm7pqXYZJt+2F9ycs+593nO75zfeZ7nXBn+Y8heE16Gk+fbcM9q4P7tiuazIduXJvQszOPoTjwOb71xo0Y+5CsrKyuDyWTiyahvNpsvZ/N6Icg/+NeJDe/ehiHyrQu/ka9sY2MDBQUF6O/vh1qthkajQWVlJWZnZ5mjt7eXn7u7u3gyOQlTthKiXg/v4QHE9TXYGr4JmNSh/gn2lu8vXRBL2tLSgtTUVNjtdmRlZcHtdkOpVOL4+Bg5OTlMuLKygubGRsnRe3QEQZEIxyM1LGUlsH33LWyN9Uzo+eN3eFa0MH/+KYxpCrgej8M1+RjGlHtnhHNzc6iuroZWq0VdXR0T0Fin00mECwsLFxIeD/0C61eVcHT9CEeHiglpEeaiz+DWzMDZ9/PZArTLcPY8CiQ8PT1FSkoKhoaGkJyczETl5eUYGBhAfn7+hYR21Q88sfhMLxGKf+p4R9S3VHwJ969PYP26GpaHX5wRWiwWbG5uMgHJOTMzA4/Hw2NRFDE1NYWtrS08396GMfU+E9JZGt57G4fv3IIp/xMI9+9C+Oh9CHc/hHBPDlPuAxzefvMsWJLusLymB5k3TwtRtwqj8mPfZBHXTwufLfmQ70sn/qndxtEq6p9e0fRs+/8pbXSGY2NjUjG4LpaWlqScvTbh2toa8vLy0NXV5Ssq3hsRzs/PY3p6+vqEJycniIuLg8vl+ocRRTF9J9hsNkkJKhQ7Ozvc/7siBoNBinQCzWs0Gl8QUklTKBSBN4KPpLOzE6GhoZweVAgoTwcHBxEWFobMzEyEh4ejvb0dERERkh9JS4tvaGjg8cTEBOd5aWnpC8La2lq0trYGpoCPZHV1FQkJCTxubm5GfX0974gIaYdOp5OrUHp6Otv09fWho6MDVquV/QlRUVHY398PlFQul+PIVz3Og4x6enpQVVXF46SkJD4rKvhk70d3dzdUKhX309LSsL6+HjBPTU0N4uPjOS6YkM6BtnwetGoKgsLCQi5tFLkhISGSzE1NTZJtdnY2l8fl5WUEBQWxAnTNjYyMYHx8nH2io6M5FmR0JcXExHCtpJaRkYHY2FjWm0BnRu+p3CUmJvK73NxcltqPyMhIlJSUcKCQ1NQfHh7mBQQHB6OtrQ2jo6MX5yHpTudyProIJK1/V/6z8YOuMT8cDkdASgmCwJfCjStNcXEx9vb2Xu1PVEVFBV/ERUVFWFxcfPV/bQcHB3wtnZfk9Y/wVfgLrni+tLJdUScAAAAASUVORK5CYII=') center no-repeat !important;\n  cursor: pointer;\n}\n.YouTubeLyricsByRobWPageActionIcon:hover {\n  border-color: #000;\n}\n/*YouTube*/\n#watch-headline-title .YouTubeLyricsByRobWPageActionIcon {\n  position: absolute;\n  top: 1px;\n  right: 0;\n}\n/*Grooveshark*/\n#player .YouTubeLyricsByRobWPageActionIcon {\n  position: relative;\n  top: 8px;\n  right: 30px;\n  float: left;\n}\n/*Grooveshark Retro*/\n#footer > #player .YouTubeLyricsByRobWPageActionIcon {\n  position: relative;\n  top: 5px;\n  right: -7px;\n  float: left;\n}\n#footer > #player .YouTubeLyricsByRobWPageActionIcon ~ #player_controls_seeking {\n  margin-left: 220px; /* was 190px */\n}\n/*Grooveshark HTML5*/\n#page-header .YouTubeLyricsByRobWPageActionIcon {\n  position: absolute;\n  top: 6px;\n  left: 50px;\n  right: auto;\n}\n\n/*Spotify Web client*/\n#wrapper > .YouTubeLyricsByRobWPageActionIcon {\n  position: absolute;\n  top: 0;\n  right: 0;\n  opacity: 0.6;\n}\n#wrapper > .YouTubeLyricsByRobWPageActionIcon:hover {\n  opacity: 1;\n}";
    }), r("eventBridge", [ "text!style/pageAction.css" ], function(e) {
        var t, r = {}, n = [], o = function(e, t) {
            var o = r[e] ? r[e].slice(0) : [];
            if (n.push({
                data: t,
                callbacks: o
            }), 1 === n.length) for (;n.length > 0; ) {
                t = n.shift(), o = t.callbacks, t = t.data;
                for (var i = 0; o.length > i; i++) o[i](t);
            }
        }, i = function(e, t) {
            if ("function" != typeof t) throw Error("Callback must be a function!");
            (r[e] || (r[e] = [])).push(t);
        }, s = function() {
            if (!t) {
                var r = document.createElement("style");
                r.appendChild(document.createTextNode(e)), (document.head || document.documentElement).appendChild(r), 
                t = document.createElement("div"), t.className = "YouTubeLyricsByRobWPageActionIcon", 
                t.title = "Click to show the Lyrics panel.\nPress CTRL and click to hide this button.", 
                t.addEventListener("click", function(e) {
                    a(), e.ctrlKey || o("toggle");
                });
            }
            (document.body || document.documentElement).appendChild(t), o("iconinserted", t);
        }, a = function() {
            t && t.parentNode && t.parentNode.removeChild(t);
        };
        i("attached", a), i("detached", s);
        return {
            dispatchEvent: o,
            listenEvent: i
        };
    }), r("touch2mouse", [], function() {
        function e(e) {
            return function(t) {
                var r = t.changedTouches;
                r && (r = r[0], t.preventDefault(), t = document.createEvent("MouseEvents"), t.initMouseEvent(e, !0, !0, document.defaultView, 1, r.screenX, r.screenY, r.clientX, r.clientY, r.ctrlKey, r.altKey, r.shiftKey, r.metaKey, 0, null), 
                r.target.dispatchEvent(t));
            };
        }
        var t = "ontouchend" in document.documentElement, r = {}, n = {}, o = function(t, o) {
            r[o] = t, n[t] = e(o);
        };
        o("touchstart", "mousedown"), o("touchmove", "mousemove"), o("touchend", "mouseup");
        var i = {
            events: n,
            supportsTouch: t,
            addTouchListener: function(e, t) {
                if (i.supportsTouch) {
                    var o = r[t];
                    o && e.addEventListener(o, n[o], !1);
                }
            },
            removeTouchListener: function(e, t) {
                if (i.supportsTouch) {
                    var o = r[t];
                    o && e.removeEventListener(o, n[o], !1);
                }
            }
        };
        return i;
    }), r("LyricsPanel", [ "require", "exports", "module", "InfoProvider", "LyricsSource", "sources/lyrics", "SimpleTemplating", "text!style/lyricsPanel.css", "text!templates/lyricsPanel.html", "eventBridge", "config", "algorithms", "touch2mouse" ], function(e, t) {
        var r = e("InfoProvider").InfoProvider, n = e("LyricsSource").LyricsSource, o = e("sources/lyrics").getLyricsSources, i = e("SimpleTemplating").SimpleTemplating, s = e("text!style/lyricsPanel.css"), a = e("text!templates/lyricsPanel.html"), c = e("eventBridge"), l = e("config"), u = e("algorithms"), p = e("touch2mouse"), d = "";
        /youtube/i.test(location.host) ? d = ".youtube" : /grooveshark/i.test(location.host) ? d = ".grooveshark" : /spotify/i.test(location.host) && (d = ".spotify"), 
        a = {
            className: "L759-container",
            tagName: "div",
            innerHTML: a
        };
        var f = Object.prototype.hasOwnProperty, h = function(e, t, r) {
            console && console.log(e + ": " + r);
        }, m = function(e, t, r) {
            var n = Error(e + ": " + r);
            throw n.type = t, n;
        }, g = function(e, t) {
            if (t) {
                for (var r in t) f.call(t, r) && (e[r] = t[r]);
                return e;
            }
        }, y = function(e) {
            return !(!e || !(document.documentElement.contains ? document === e || document.documentElement.contains(e) : 16 & document.compareDocumentPosition(e)));
        }, v = {}, b = {};
        b.panelElement = null, b.getCurrentStyle = function() {
            return document.defaultView.getComputedStyle(b.panelElement);
        }, b.infoProvider = null, b.runQueuedQuery = null, b.minWidth = 0, b.minHeight = 0, 
        b.boxsizingbug = !1, b.boxsizingcomputedstylebug = !1, b.runQuery = function(e, t) {
            e = g({}, e);
            var n = "";
            if (e.song && e.artist) n = "result"; else {
                if (e.searchTerms || (e.searchTerms = e.videotitle), !e.searchTerms) return;
                n = "search";
            }
            if (b.runQueuedQuery = function() {
                b.runQueuedQuery = null, b.infoProvider.query(n, e, b.queryCallback, t);
            }, b.infoProvider) b.runQueuedQuery(); else {
                if (0 === b.infoProvider) return;
                b.infoProvider = 0, o(function(e) {
                    v = e.stats, b.infoProvider = new r(e), b.runQueuedQuery();
                });
            }
        }, b.abortQuery = function() {
            b.runQueuedQuery && (S = b.runQueuedQuery, b.runQueuedQuery = null), b.infoProvider && b.infoProvider.abort();
        };
        var S;
        b.resumeQuery = function() {
            S && S();
        }, b.queryCallback = function(e) {
            switch (b.attachPanel(), S = null, e.type) {
              case "fetching":
                b.render.fetchingLyrics(e), S = e.retry;
                break;

              case "fail":
                e.next ? e.next() : b.render.notFound(e);
                break;

              case "found":
                if (e.restart) {
                    var t = {
                        type: "fail",
                        sourceIndex: e.sourceIndex,
                        sourceCount: e.sourceCount,
                        searchTerms: e.searchTerms,
                        restart: e.restart
                    };
                    e.restart = function() {
                        b.queryCallback(t);
                    };
                }
                b.render.foundLyrics(e);
                break;

              case "message":
                b.render.showMessage(e);
                break;

              default:
                return m("YTL:queryCallback", "unknown_type", "Unknown type " + type + '. Expected one of "fetching", "fail" or "found"!'), 
                void 0;
            }
            b.panelHelpers.dimensions.adaptPanelToResult();
        }, b.detachPanel = function() {
            b.abortQuery(), y(b.panelElement) && (b.render.unbindInitialEvents(), b.panelElement.parentNode.removeChild(b.panelElement)), 
            y(b.styleSheet) && b.styleSheet.parentNode.removeChild(b.styleSheet), clearInterval(L), 
            b.panelHelpers.mover.end(), b.panelHelpers.resizer.end(), b.panelHelpers.overlay.detach(), 
            h("YTL:detachPanel", "detached", "Removed Lyrics panel."), c.dispatchEvent("detached");
        }, b.attachPanel = function() {
            var e = !b.panelElement;
            b.styleSheet || (b.styleSheet = document.createElement("style"), b.styleSheet.appendChild(document.createTextNode(s))), 
            e && (b.panelElement = i(a).getElement(), b.panelElement.dir = "ltr", b.panelElement.style.top = b.savedOffsets.top + "px", 
            b.panelElement.style.right = b.savedOffsets.right + "px", b.panelElement.style.width = b.savedOffsets.width + "px"), 
            y(b.styleSheet) || (document.head || document.documentElement).appendChild(b.styleSheet), 
            y(b.panelElement) || (b.activateTheme(), (document.body || document.documentElement).appendChild(b.panelElement), 
            "fixed" != b.getCurrentStyle().position && b.pollPanelCSSActivation(), b.panelHelpers.dimensions.fixBoxSizing(), 
            b.render.bindInitialEvents(), b.panelHelpers.dimensions.enforcePosition(), e ? b.panelHelpers.dimensions.adaptPanelToResult() : b.panelHelpers.dimensions.enforceDimensions(), 
            b.panelHelpers.dimensions.enforcePosition() && b.panelHelpers.dimensions.enforceDimensions(), 
            b.resumeQuery(), c.dispatchEvent("attached"));
        };
        var L;
        b.pollPanelCSSActivation = function() {
            var e = Date.now(), t = setInterval(function() {
                "fixed" == b.getCurrentStyle().position ? (clearInterval(t), b.panelHelpers.dimensions.adaptPanelToResult()) : Date.now() - e > 2e4 && clearInterval(t);
            }, 50);
        }, b.activateTheme = function() {
            var e = function(e) {
                var t = b.panelElement || a;
                t.className = t.className.replace(/L759-skin-\S+/, "") + (e && "default" != e ? " L759-skin-" + e : "");
            }, t = function(e) {
                var t = e && document.defaultView.getComputedStyle(e);
                return t && /^rgba?\(\d{1,2},\s*\d{1,2},\s*\d{1,2}(,\s*(?!0)\d*)?\)$/.test(t.backgroundColor);
            };
            l.getItem("theme" + d, function(r) {
                "dark" == r || "default" == r ? e(r) : ".youtube" == d && t(document.body) || ".grooveshark" == d && t(document.getElementById("page-inner")) ? e("dark") : e("");
            });
        }, b.activateTheme();
        var w = "panelOffsets" + d;
        b.savedOffsets = {
            top: 2,
            right: 2,
            width: 275,
            maxHeight: 600
        };
        var x, A = 1, E = 2;
        b.saveOffsets = function(e) {
            if (!b.panelElement || !y(b.panelElement)) return h("LyricsPanel.saveOffsets", "not_rendered", "Lyric panel cannot be found within the document!"), 
            void 0;
            var t = b.savedOffsets, r = b.getCurrentStyle(), n = function(e, r) {
                r = parseFloat(r), !isNaN(r) && isFinite(r) && (t[e] = r);
            };
            e & A && (n("top", r.top), n("right", r.right)), e & E && (b.boxsizingcomputedstylebug ? (n("width", b.panelElement.style.width), 
            n("maxHeight", b.panelElement.style.height)) : (n("width", r.width), n("maxHeight", r.height))), 
            clearTimeout(x), x = setTimeout(function() {
                l.setItem(w, t, function(e) {
                    e ? h("LyricsPanel.saveOffsets", "", "Saved Lyric panel's position and dimensions!") : h("LyricsPanel.saveOffsets", "", "Failed to save the Lyric panel's position and dimensions!");
                });
            }, 200);
        };
        var T = 0, k = [];
        b.loadOffsets = function(e) {
            2 == T ? e(b.savedOffsets) : 1 == T ? k.push(e) : (T = 1, k.push(e), l.getItem(w, function(t) {
                if (t) {
                    var r = function(e) {
                        f.call(t, e) && (b.savedOffsets[e] = t[e]);
                    };
                    r("top"), r("right"), r("width"), r("maxHeight");
                }
                for (;e = k.shift(); ) e(b.savedOffsets);
                T = 2;
            }));
        }, b.panelHelpers = {}, b.panelHelpers.show = function(e) {
            e.style.display = "";
        }, b.panelHelpers.hide = function(e) {
            e.style.display = "none";
        }, b.panelHelpers.doSearch = function() {
            var e = b.panelElement.querySelector(".L759-searchterms").value, t = u.splitSongTitle(e);
            t ? b.runQuery({
                searchTerms: e,
                artist: t[0],
                song: t[1]
            }) : b.runQuery({
                searchTerms: e
            });
        }, b.panelHelpers.dimensions = {}, b.panelHelpers.dimensions.getViewportDimensions = function() {
            var e = b.panelHelpers.overlay.isAttached();
            b.panelHelpers.overlay.attach();
            var t = b.overlayElement.getBoundingClientRect(), r = t.right, n = t.bottom;
            return e || b.panelHelpers.overlay.detach(), {
                width: r,
                height: n
            };
        };
        var C;
        b.panelHelpers.dimensions.fixBoxSizing = function() {
            if (!C) {
                C = 1;
                var e = document.createElement("div");
                e.style.cssText = "-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;display:block;top:-999px;position:absolute;min-height:6px;padding:1px;border:0;", 
                document.documentElement.appendChild(e);
                var t = b.getCurrentStyle();
                b.minHeight = parseFloat(t.minHeight) || 25, b.minWidth = parseFloat(t.minWidth) || 25, 
                8 == e.scrollHeight && (b.boxsizingbug = !0, b.panelElement.className += " boxsizingbug"), 
                e.style.height = "8px", "8px" != window.getComputedStyle(e).height && (b.boxsizingcomputedstylebug = !0), 
                e.parentNode.removeChild(e), e = null;
            }
        }, b.panelHelpers.dimensions.enforceDimensions = function() {
            var e, t, r = b.getCurrentStyle(), n = b.panelElement.offsetWidth, o = b.panelElement.offsetHeight, i = parseFloat(r.top), s = parseFloat(r.right), a = b.minWidth, c = b.minHeight, l = b.panelHelpers.dimensions.getViewportDimensions(), u = l.width - s, p = l.height - i;
            n > u && (e = u), a > n && (e = a), o > p && (t = p), c > o && (t = c), e && (b.panelElement.style.width = e + "px"), 
            t && (b.panelElement.style.height = t + "px"), b.panelHelpers.dimensions.enforceContentHeight();
        }, b.panelHelpers.dimensions.enforcePosition = function() {
            var e = b.getCurrentStyle(), t = parseFloat(e.top) || 0, r = parseFloat(e.right) || 0, n = b.panelHelpers.dimensions.getViewportDimensions(), o = n.height, i = n.width;
            b.boxsizingcomputedstylebug ? (o -= parseFloat(b.panelElement.style.height) || b.minHeight, 
            i -= parseFloat(b.panelElement.style.width) || b.minWidth) : (o -= parseFloat(e.height) || b.minHeight, 
            i -= parseFloat(e.width) || b.minWidth);
            var s = !1;
            return t > o && (s = !0, b.panelElement.style.top = Math.max(0, o) + "px"), 0 > t && (s = !0, 
            b.panelElement.style.top = "0"), r > i && (s = !0, b.panelElement.style.right = Math.max(0, i) + "px"), 
            0 > r && (s = !0, b.panelElement.style.right = "0"), s;
        }, b.panelHelpers.dimensions.getFixedNonContentHeight = function() {
            var e = b.getCurrentStyle(), t = parseFloat(e.borderTopWidth) || 0, r = parseFloat(e.borderBottomWidth) || 0, n = parseFloat(e.paddingTop) || 0, o = parseFloat(e.paddingBottom) || 0, i = b.panelElement.querySelector(".L759-title").offsetHeight, s = b.panelElement.querySelector(".L759-searchbox").offsetHeight;
            return _cached_fixedNonContentHeight = t + r + n + o + i + s;
        }, b.panelHelpers.dimensions.enforceContentHeight = function() {
            var e = Math.max(b.panelElement.offsetHeight, b.minHeight), t = b.panelHelpers.dimensions.getFixedNonContentHeight(), r = e - t;
            b.panelElement.querySelector(".L759-content").style.height = 0 > r ? 0 : r + "px";
        }, b.panelHelpers.dimensions.adaptPanelToResult = function() {
            var e = b.panelElement.querySelector(".L759-result"), t = b.panelElement.querySelector(".L759-content");
            t.style.overflow = "scroll";
            var r = e.scrollHeight, n = 0;
            t.style.overflow = "", t = null, r ? (n = b.panelElement.querySelector(".L759-link-container").offsetHeight, 
            n += b.panelElement.querySelector(".L759-info").offsetHeight, r += n) : r = b.panelElement.querySelector(".L759-fetching").scrollHeight, 
            r += 2;
            var o = b.panelHelpers.dimensions.getFixedNonContentHeight(), i = o + r, s = o + n;
            i > b.savedOffsets.maxHeight && (i = b.savedOffsets.maxHeight), s > i && (i = s), 
            b.panelElement.style.height = i + "px", b.panelHelpers.dimensions.enforceDimensions();
        };
        var R;
        b.panelHelpers.dimensions.togglePanelHeight = function() {
            var e = b.panelElement.offsetHeight;
            b.getCurrentStyle();
            var t = b.minHeight, r = 10;
            r > e - t ? (b.resumeQuery(), R ? (b.panelElement.style.height = R, b.panelHelpers.dimensions.enforceDimensions()) : b.panelHelpers.dimensions.adaptPanelToResult()) : (b.abortQuery(), 
            R = b.panelElement.style.height, b.panelElement.style.height = t + "px", b.panelHelpers.dimensions.enforceDimensions());
        }, b.panelHelpers.overlay = {}, b.panelHelpers.overlay.isAttached = function() {
            return !(!b.overlayElement || !y(b.overlayElement));
        }, b.panelHelpers.overlay.attach = function() {
            b.overlayElement || (b.overlayElement = document.createElement("div"), b.overlayElement.className = "L759-overlay"), 
            y(b.overlayElement) || ((document.body || document.documentElement).appendChild(b.overlayElement), 
            b.panelHelpers.dimensions.getViewportDimensions());
        }, b.panelHelpers.overlay.detach = function() {
            b.panelHelpers.overlay.isAttached() && b.overlayElement.parentNode.removeChild(b.overlayElement);
        }, b.panelHelpers.mover = {}, b.panelHelpers.mover.globalMouseMove = null, b.panelHelpers.mover.moverMouseDown = function(e) {
            if (2 != e.button && (e.stopPropagation(), e.preventDefault(), !b.panelHelpers.mover.globalMouseMove)) {
                var t = b.getCurrentStyle(), r = parseFloat(t.top) || 0, n = parseFloat(t.right) || 0, o = e.clientX, i = e.clientY, s = 0, a = 0, c = b.panelHelpers.dimensions.getViewportDimensions(), l = c.height - b.minHeight, u = c.width - b.minWidth;
                b.panelHelpers.mover.globalMouseMove = function(e) {
                    if (e.preventDefault(), !y(b.panelElement)) return b.panel.mover.end(), void 0;
                    var t = r - i + e.clientY;
                    t > l && (t = l), s > t && (t = s);
                    var c = n + o - e.clientX;
                    c > u && (c = u), a > c && (c = a), b.panelElement.style.top = t + "px", b.panelElement.style.right = c + "px";
                }, b.panelHelpers.overlay.attach(), document.addEventListener("mousemove", b.panelHelpers.mover.globalMouseMove, !0), 
                document.addEventListener("mouseup", b.panelHelpers.mover.globalMouseUp, !0), p.addTouchListener(document, "mousemove"), 
                p.addTouchListener(document, "mouseup");
            }
        }, b.panelHelpers.mover.globalMouseUp = function(e) {
            e.preventDefault(), e.stopPropagation(), b.panelHelpers.dimensions.enforceDimensions(), 
            b.panelHelpers.mover.end();
        }, b.panelHelpers.mover.end = function() {
            b.panelHelpers.mover.globalMouseMove && (document.removeEventListener("mousemove", b.panelHelpers.mover.globalMouseMove, !0), 
            p.removeTouchListener(document, "mousemove"), b.panelHelpers.mover.globalMouseMove = null, 
            document.removeEventListener("mouseup", b.panelHelpers.mover.globalMouseUp, !0), 
            p.removeTouchListener(document, "mouseup"), b.panelHelpers.overlay.detach(), b.saveOffsets(A));
        }, b.panelHelpers.resizer = {}, b.panelHelpers.resizer.globalMouseMove = null, b.panelHelpers.resizer.resizerMouseDown = function(e) {
            if (!b.panelHelpers.resizer.globalMouseMove) {
                e.preventDefault(), e.stopPropagation();
                var t = b.panelElement.offsetWidth, r = b.panelElement.offsetHeight, n = e.clientX, o = e.clientY, i = b.getCurrentStyle(), s = b.minWidth, a = b.panelHelpers.dimensions.getViewportDimensions(), c = a.width - (parseFloat(i.right) || 0), l = b.minHeight, u = a.height - (parseFloat(i.top) || 0);
                b.panelHelpers.resizer.globalMouseMove = function(e) {
                    if (e.preventDefault(), !y(b.panelElement)) return b.panel.resizer.end(), void 0;
                    var i = t + n - e.clientX;
                    i > c && (i = c), s > i && (i = s);
                    var a = r - o + e.clientY;
                    a > u && (a = u), l > a && (a = l), b.panelElement.style.width = i + "px", b.panelElement.style.height = a + "px", 
                    b.panelHelpers.dimensions.enforceContentHeight();
                }, document.addEventListener("mousemove", b.panelHelpers.resizer.globalMouseMove, !0), 
                document.addEventListener("mouseup", b.panelHelpers.resizer.end, !0), p.addTouchListener(document, "mousemove"), 
                p.addTouchListener(document, "mouseup"), b.panelHelpers.overlay.attach();
            }
        }, b.panelHelpers.resizer.end = function() {
            b.panelHelpers.resizer.globalMouseMove && (document.removeEventListener("mousemove", b.panelHelpers.resizer.globalMouseMove, !0), 
            p.removeTouchListener(document, "mousemove"), b.panelHelpers.resizer.globalMouseMove = null, 
            document.removeEventListener("mouseup", b.panelHelpers.resizer.end, !0), p.removeTouchListener(document, "mouseup"), 
            b.panelHelpers.overlay.detach(), b.saveOffsets(E));
        }, b.panelHelpers.stayWithinViewport = function() {
            b.panelHelpers.dimensions.enforcePosition() && b.panelHelpers.dimensions.enforceDimensions();
        };
        var H, _ = 0;
        b.panelHelpers.globalResize = function() {
            var e = 333, t = Date.now(), r = t - _;
            r > e ? (setTimeout(b.panelHelpers.stayWithinViewport, 4), _ = t) : (_ = t, clearTimeout(H), 
            H = setTimeout(b.panelHelpers.stayWithinViewport, e));
        }, b.render = {}, b.render.bindInitialEvents = function() {
            i(b.panelElement).update({
                ".L759-resizer": {
                    onmousedown: b.panelHelpers.resizer.resizerMouseDown,
                    ontouchstart: p.events.touchstart
                },
                ".L759-title": {
                    onmousedown: b.panelHelpers.mover.moverMouseDown,
                    ontouchstart: p.events.touchstart,
                    ondblclick: b.panelHelpers.dimensions.togglePanelHeight
                },
                ".L759-close": {
                    onclick: b.detachPanel
                },
                ".L759-info": {
                    className: "L759-info " + ("https:" === location.protocol ? "" : "L759-http")
                },
                ".L759-toggle-info": {
                    onclick: function(e) {
                        e.preventDefault();
                        var t = b.panelElement.querySelector(".L759-info");
                        t.style.display = t.offsetHeight ? "none" : "block", b.panelHelpers.dimensions.adaptPanelToResult();
                    }
                },
                ".L759-searchbox .L759-searchterms": {
                    onkeydown: function(e) {
                        (13 === e.keyCode || "Enter" === e.keyIdentifier) && (e.preventDefault(), e.stopPropagation(), 
                        b.panelHelpers.doSearch());
                    }
                },
                ".L759-searchbox .L759-dosearch": {
                    onclick: b.panelHelpers.doSearch
                },
                "a.L759-settings-link": {
                    _post: function() {
                        ("rob.lekensteyn.nl" === location.host || /^(chrome-extension|widget)/.test(location.protocol)) && (this.href = "#config", 
                        this.target = "");
                    }
                }
            });
            window.addEventListener("resize", b.panelHelpers.globalResize, !0);
        }, b.render.unbindInitialEvents = function() {
            i(b.panelElement).update({
                ".L759-resizer": {
                    onmousedown: null,
                    ontouchstart: null
                },
                ".L759-title": {
                    onmousedown: null,
                    ontouchstart: null,
                    ondblclick: null
                },
                ".L759-close": {
                    onclick: null
                },
                ".L759-toggle-info": {
                    onclick: null
                },
                ".L759-searchbox .L759-searchterms": {
                    onkeydown: null
                },
                ".L759-searchbox .L759-dosearch": {
                    onclick: null
                }
            }), window.removeEventListener("resize", b.panelHelpers.globalResize, !0);
        }, b.render.showMessage = function(e) {
            var t = {
                dir: ""
            };
            t[e.html ? "innerHTML" : "textContent"] = e.message, i(b.panelElement).update({
                ".L759-title": {
                    textContent: e.title || "YouTube Lyrics",
                    title: ""
                },
                ".L759-fetching, .L759-link-container, .L759-info .L759-song-info": {
                    _post: b.panelHelpers.hide
                },
                ".L759-result": t
            });
        }, b.render.fetchingLyrics = function(e) {
            i(b.panelElement).update({
                ".L759-title": {
                    textContent: "Searching...",
                    title: ""
                },
                ".L759-fetching": {
                    _post: b.panelHelpers.show
                },
                ".L759-fetching .L759-buttons .L759-b-abort": {
                    onclick: e.abort,
                    _post: b.panelHelpers["function" == typeof e.abort ? "show" : "hide"]
                },
                ".L759-fetching .L759-buttons .L759-b-retry": {
                    onclick: e.retry,
                    _post: b.panelHelpers["function" == typeof e.retry ? "show" : "hide"]
                },
                ".L759-fetching .L759-buttons .L759-b-next": {
                    onclick: e.next,
                    _post: b.panelHelpers["function" == typeof e.next ? "show" : "hide"]
                },
                ".L759-done": {
                    _post: b.panelHelpers.hide
                },
                ".L759-link-to-fetched-source": {
                    href: e.url,
                    textContent: decodeURI(e.url)
                }
            });
        }, b.render.notFound = function(e) {
            i(b.panelElement).update({
                ".L759-title": {
                    textContent: "Not found",
                    title: ""
                },
                ".L759-fetching": {
                    _post: b.panelHelpers.hide
                },
                ".L759-done, .L759-link-container": {
                    _post: b.panelHelpers.show
                },
                ".L759-done .L759-result": {
                    dir: "ltr",
                    innerHTML: "Cannot find lyrics (" + (+e.sourceCount || 0) + "x) for:<br>" + '<span class="YTL-notFound"></span>' + '<br>&bull; <a class="YTL-notFound-search-link" target="_blank" rel="noreferrer"></a>' + '<br>&bull; <span title="Enable or disable lyric providers.\n ' + +v.total + ' sources are available.">' + '<a href="https://rob.lekensteyn.nl/youtubelyrics/#config" target="_blank">Edit sources</a>' + (v.new ? " (" + +v.new + " new)" : "") + "</span><br>"
                },
                ".L759-info .L759-song-info": {
                    _post: b.panelHelpers.hide
                }
            });
            var t = n.prototype.$SEARCHTERMS(e.query, {
                keepAccents: !0
            });
            /\blyrics\b/i.test(t) || (t += " lyrics"), t = encodeURIComponent(t);
            var r = "https://encrypted.google.com/search?q=" + t;
            i(b.panelElement).update({
                ".YTL-notFound": {
                    textContent: e.searchTerms
                },
                ".YTL-notFound-search-link": {
                    href: r,
                    textContent: "Try Google (new window)"
                }
            }), b.render.updateSwitchSourceLink(e);
        }, b.render.foundLyrics = function(e) {
            var t = /^[^A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02B8\u0300-\u0590\u0800-\u1FFF\u2C00-\uFB1C\uFDFE-\uFE6F\uFEFD-\uFFFF]*[\u0591-\u07FF\uFB1D-\uFDFD\uFE70-\uFEFC]/, r = t.test(e.lyrics[0]) ? "rtl" : "ltr";
            i(b.panelElement).update({
                ".L759-title": {
                    textContent: e.title,
                    title: e.title + "\n\nSource: " + e.sourceIdentifier
                },
                ".L759-fetching": {
                    _post: b.panelHelpers.hide
                },
                ".L759-done, .L759-link-container": {
                    _post: b.panelHelpers.show
                },
                ".L759-info .L759-song-info": {
                    _post: b.panelHelpers.show
                },
                ".L759-info .L759-song-title": {
                    textContent: e.title,
                    title: e.title
                },
                ".L759-info .L759-link-to-found-source": {
                    href: e.url,
                    textContent: e.sourceIdentifier
                },
                ".L759-done .L759-result": {
                    dir: r,
                    textContent: ""
                }
            }), b.render.updateSwitchSourceLink(e);
            var n = document.createDocumentFragment(), o = document.createElement("div");
            o.className = "L759-lyrics-line";
            for (var s = 0; e.lyrics.length > s; s++) {
                var a = o.cloneNode(!1);
                a.textContent = e.lyrics[s].trim(), n.appendChild(a);
            }
            b.panelElement.querySelector(".L759-done .L759-result").appendChild(n);
        }, b.render.updateSwitchSourceLink = function(e) {
            i(b.panelElement).update({
                ".L759-done .L759-switch-source": {
                    onclick: e.next || e.restart,
                    title: "Click to search for lyrics at a different source.\nCurrent query: " + e.searchTerms
                },
                ".L759-done .L759-switch-source .L759-sourceindex": {
                    textContent: e.sourceCount && e.sourceIndex + 1
                },
                ".L759-done .L759-switch-source .L759-sourcecount": {
                    textContent: e.sourceCount
                }
            });
        }, b.init = function() {
            b.init = function() {}, c.listenEvent("toggle", function() {
                b.panelElement && (y(b.panelElement) ? b.detachPanel() : b.attachPanel());
            });
        }, t.LyricsPanel = b;
    }), r("YouTubeLyrics", [ "require", "exports", "module", "LyricsPanel", "eventBridge", "config" ], function(e, t) {
        var r = e("LyricsPanel").LyricsPanel, n = e("eventBridge"), o = e("config"), i = function(e, t, r) {
            console && console.log(e + ": " + r);
        }, s = {};
        s.LyricsPanel = r, s.getQuery = function() {
            var e = "", t = "", r = "", n = document.querySelector(".channels-featured-video-details h3.title a");
            return n ? r = n.textContent.trim() : (n = document.querySelector(".video-detail .title a")) ? r = n.title : document.getElementById("watch-headline-title") ? (n = document.title.replace(/\-\s*YouTube\s*$/, "").trim(), 
            r = n, n = document.querySelector('a[href^="/artist/"]'), n || (n = document.querySelector(".metadata-info-title+*")), 
            n && (t = n.textContent.trim()), n = document.querySelector('a[onmousedown*="metadata"]'), 
            n = n && n.parentNode, n = n && n.previousElementSibling, n = n && n.textContent.trim(), 
            n && (n = n.match(/^[^"]*"([\S\s]+)"[^"]*$/) || n.match(/^[^„]*„([\S\s]+)”[^”]*$/) || n.match(/^[^„]*„([\S\s]+)“[^“]*$/) || n.match(/^[^«]*«([\S\s]+)»[^»]*$/) || n.match(/^[^']*'([\S\s]+)'[^']*$/) || n.match(/^Koupit skladbu ([\S\s]+) na$/) || n.match(/^K\xFApi\u0165 skladbu ([\S\s]+) v slu\u017Ebe$/) || n.match(/^Osta ([\S\s]+) myym\xE4l\xE4st\xE4$/) || n.match(/^K\xF6p ([\S\s]+) p\xE5:$/) || n.match(/^([\S\s]+) \u0B90 \u0B87\u0BA4\u0BBF\u0BB2\u0BCD \u0BB5\u0BBE\u0B99\u0BCD\u0B95\u0BC1\u0B95$/) || n.match(/^[^\u300A]*\u300A([\S\s]+)\u300B[^\u300B]*$/) || n.match(/^[^\u300C]*\u300C([\S\s]+)\u300D[^\u300D]*$/), 
            n && (e = n[1]))) : document.querySelector("h1#vt") && (r = document.title.replace(/^YouTube\s*-\s*$/, "").trim()), 
            {
                song: e,
                artist: t,
                videotitle: r
            };
        }, s.watchNavigationChanges = function() {};
        var a = {};
        s.checkContext = function() {
            var e = s.getQuery();
            return e.song || e.artist || e.videotitle ? a.song === e.song && a.artist === e.artist && a.videotitle === e.videotitle ? (i("YTL:checkContext", "query_not_modified", "Query did not change. Did not initiate a new query."), 
            void 0) : (a = e, s.LyricsPanel.runQuery(e), void 0) : (i("YTL:checkContext", "query_empty", "Query was empty."), 
            void 0);
        }, s.putTinyButton = function(e) {
            var t = document.getElementById("watch-headline-title");
            t && e.parentNode !== t && t.appendChild(e);
        }, s.launchPanel = function() {
            s.launchPanel = function() {}, r.loadOffsets(function() {
                s.LyricsPanel.init(), s.checkContext(), s.watchNavigationChanges();
            });
        }, s.init = function() {
            i("YTL:init", "init", "Initializing YouTube Lyrics.");
            var e = s.getQuery();
            (e.song || e.artist || e.videotitle) && (n.listenEvent("iconinserted", s.putTinyButton), 
            o.getItem("youtube-autolaunch", function(t) {
                n.dispatchEvent("detached"), t !== !1 ? (s.launchPanel(), e = null) : n.listenEvent("toggle", function() {
                    e && (s.launchPanel(), e = null);
                });
            }));
        }, t.YTL = s, t.init = s.init;
    }), r("GroovesharkLyrics", [ "require", "exports", "module", "LyricsPanel", "eventBridge", "config" ], function(e, t) {
        var r = e("LyricsPanel").LyricsPanel, n = e("eventBridge"), o = e("config"), i = function(e, t, r) {
            console && console.log(e + ": " + r);
        }, s = {};
        s.LyricsPanel = r;
        var a = function() {
            var e, t = document.getElementById("little-queue"), r = "", n = "";
            return t && (e = t.querySelector(".little-queue-title"), e && (r = e.textContent), 
            e = t.querySelector(".little-queue-meta"), e && (n = e.textContent.split(" - ")[0])), 
            t = e = null, {
                song: r,
                artist: n
            };
        }, c = "now-playing-metadata";
        s.getQuery = function() {
            var e = document.getElementById(c);
            if (null === e) if (e = document.getElementById("playerDetails_nowPlaying")) c = "playerDetails_nowPlaying"; else if (document.getElementById("little-queue")) return s.getQuery = a, 
            a();
            var t, r = "", n = "";
            return e && (t = e.querySelector(".song"), t && (r = t.title), t = e.querySelector(".artist"), 
            t && (n = t.title)), e = t = null, {
                song: r,
                artist: n
            };
        };
        var l;
        s.watchNavigationChanges = function() {
            clearInterval(l), l = setInterval(s.checkContext, 200);
        }, s.unwatchNavigationChanges = function() {
            clearInterval(l);
        };
        var u = {};
        s.checkContext = function() {
            var e = s.getQuery();
            (e.song || e.artist) && (u.song !== e.song || u.artist !== e.artist) && (u = e, 
            s.LyricsPanel.runQuery(e));
        }, s.putTinyButton = function(e) {
            var t = document.getElementById("player") || document.getElementById("page-header");
            t && e.parentNode !== t && t.insertBefore(e, t.firstChild);
        }, s.launchPanel = function() {
            s.launchPanel = function() {};
            var e = document.querySelector("#player-wrapper,#footer");
            e && (s.LyricsPanel.panelHelpers.dimensions.getViewportDimensions = function() {
                var t = e.getBoundingClientRect();
                return {
                    width: t.right,
                    height: t.top
                };
            }), s.LyricsPanel.loadOffsets(function() {
                s.LyricsPanel.init(), r.queryCallback({
                    type: "message",
                    html: !0,
                    title: "Lyrics for Grooveshark",
                    message: 'Play a song or use the search box to get lyrics.<br><br>Hit the close button to hide the panel.<br>&raquo; <a href="https://rob.lekensteyn.nl/youtubelyrics/#config" target="_blank">Preferences</a>'
                }), s.checkContext(), s.watchNavigationChanges();
            });
        }, s.init = function() {
            i("GSL:init", "init", "Initializing Grooveshark Lyrics."), n.listenEvent("attached", s.watchNavigationChanges), 
            n.listenEvent("detached", s.unwatchNavigationChanges), n.listenEvent("iconinserted", s.putTinyButton), 
            o.getItem("grooveshark-autolaunch", function(e) {
                if (n.dispatchEvent("detached"), e !== !1) s.launchPanel(); else {
                    var t = !0;
                    n.listenEvent("toggle", function() {
                        t && (s.launchPanel(), t = !1);
                    });
                }
            });
        }, t.GSL = s, t.init = s.init;
    }), r("SpotifyLyrics", [ "require", "exports", "module", "LyricsPanel", "eventBridge", "config", "algorithms" ], function(e, t) {
        var r = e("LyricsPanel").LyricsPanel, n = e("eventBridge"), o = e("config"), i = e("algorithms"), s = function(e, t, r) {
            console && console.log(e + ": " + r);
        }, a = {};
        a.LyricsPanel = r, a.getQuery = function() {
            var e = "", t = "", r = document.title.replace(/\s*-?\s*Spotify\s*$/i, "").replace(/^[\u25b6\s]+/, ""), n = r.replace(/\([^)]*\)|\[[^\]]*\]/g, " ");
            return -1 == n.indexOf(" - ") && (n = r), n = n.split(" - "), 2 == n.length ? (e = n[0], 
            t = n[1]) : n.length > 2 && (t = n.pop(), e = .7 > i.getSimilarityCoefficient(t, n[0]) ? n[0] : n[1]), 
            {
                song: e,
                artist: t
            };
        };
        var c;
        a.watchNavigationChanges = function() {
            clearInterval(c), c = setInterval(a.checkContext, 200);
        }, a.unwatchNavigationChanges = function() {
            clearInterval(c);
        };
        var l = {};
        a.checkContext = function() {
            var e = a.getQuery();
            (e.song || e.artist) && (l.song !== e.song || l.artist !== e.artist) && (l = e, 
            a.LyricsPanel.runQuery(e));
        }, a.putTinyButton = function(e) {
            var t = document.getElementById("wrapper");
            t && t.appendChild(e);
        }, a.launchPanel = function() {
            a.launchPanel = function() {}, a.LyricsPanel.loadOffsets(function() {
                a.LyricsPanel.init(), r.queryCallback({
                    type: "message",
                    html: !0,
                    title: "Lyrics for Spotify",
                    message: 'Play a song or use the search box to get lyrics.<br><br>Hit the close button to hide the panel.<br>&raquo; <a href="https://rob.lekensteyn.nl/youtubelyrics/#config" target="_blank">Preferences</a>'
                }), a.checkContext(), a.watchNavigationChanges();
            });
        }, a.init = function() {
            s("SPL:init", "init", "Initializing Spotify Lyrics."), n.listenEvent("attached", a.watchNavigationChanges), 
            n.listenEvent("detached", a.unwatchNavigationChanges), n.listenEvent("iconinserted", a.putTinyButton), 
            o.getItem("spotify-autolaunch", function(e) {
                if (n.dispatchEvent("detached"), e !== !1) a.launchPanel(); else {
                    var t = !0;
                    n.listenEvent("toggle", function() {
                        t && (a.launchPanel(), t = !1);
                    });
                }
            });
        }, t.SPL = a, t.init = a.init;
    }), r("LyricsPanel-demo", [ "require", "exports", "module", "LyricsPanel" ], function(e, t) {
        function r() {
            n.init(), n.infoProvider = null, n.queryCallback({
                type: "message",
                html: !0,
                message: i
            });
        }
        var n = e("LyricsPanel").LyricsPanel, o = /^https?:\/\/rob\.lekensteyn\.nl\/youtubelyrics/i.test(location.href) || /^(chrome-extension|widget):$/.test(location.protocol) ? "" : "https://rob.lekensteyn.nl/youtubelyrics/", i = 'Hi there,<br><br>Whenever you visit a <b>YouTube</b> video or play a song on <b>Grooveshark</b> or <b>Spotify</b>\'s Web Player, lyrics will be displayed in this box.If you want to see other lyrics, click on "Different source", or use the search box below.<br><br>&raquo; <a href="' + o + '#quick-guide">More information</a><br><br>';
        t.init = r;
    }), r("dragndrop-nodes", [ "require", "exports", "module" ], function(e, t) {
        function r() {
            if (a) {
                a.style.display = i;
                var e = c.parentNode;
                e && e.removeChild(c), a = null, s = null, c = null;
            }
        }
        function n(e, t, r) {
            var n = e[l + t];
            n && (e.removeEventListener(t, n, !1), e[l + t] = null), r && (e.addEventListener(t, r, !1), 
            e[l + t] = r);
        }
        function o(e, t, o) {
            function l(e) {
                e.stopPropagation(), e.preventDefault();
            }
            if (t && !t.contains(e)) throw Error("The dragged node must be the moved node or a child of the moved node!");
            t = t || e;
            var u = function(e) {
                t.dragDrop(), l(e);
            };
            n(e, "mouseover", function() {
                "draggable" in t ? t.draggable = !0 : t.dragDrop && n(t, "selectstart", u);
            }), n(e, "mouseout", function() {
                t.draggable ? t.draggable = !1 : n(t, "selectstart");
            }), n(t, "dragstart", function(e) {
                a = t, s = a.previousSibling, c = document.createElement(a.tagName), c.draggable = !0, 
                c.className = "drag-drop-placeholder", c.style.height = a.offsetHeight + "px", n(c, "dragover", l), 
                n(c, "drop", function(e) {
                    l(e), c.parentNode.insertBefore(a, c), o && a.previousSibling !== s && o(), r();
                });
                try {
                    e.dataTransfer.effectAllowed = "move", e.dataTransfer.setData("text/plain", "");
                } catch (i) {}
            }), n(t, "dragenter", function(e) {
                if (a && e.target === t) {
                    var r = e.target;
                    if ("none" !== a.style.display) return a.parentNode.insertBefore(c, a), i = a.style.display, 
                    a.style.display = "none", void 0;
                    if (r !== c) {
                        var n = r.parentNode;
                        0 === (2 & c.compareDocumentPosition(r)) && (r = r.nextSibling), n.insertBefore(c, r);
                    }
                }
            }), n(t, "dragover", l), n(t, "drop", l), n(t, "dragend", r);
        }
        var i, s, a, c, l = "dndEvent" + Math.random();
        t.bindDnD = o;
    }), r("text!style/config.css", [], function() {
        return '.drag-drop-placeholder {\n    outline: 1px dashed #AAA;\n}\n.pref-sources, .pref-item {\n    width: 390px;\n    list-style-type: none;\n    margin: 0;\n    padding: 0;\n}\n.pref-sources {\n    position: relative;\n    margin: 5px 0 0;\n}\n.pref-sources *,\n.config-site-box {\n    -webkit-box-sizing: border-box;\n    -moz-box-sizing: border-box;\n    box-sizing: border-box;\n}\n.pref-item {\n    height: 24px;\n    padding: 2px 0;\n    line-height: 20px;\n    font-size: 18px;\n}\n.pref-item.source-disabled {\n    opacity: 0.4;\n}\n.pref-item.source-disabled:hover {\n    opacity: 0.8;\n}\n.pref-item .anchor {\n    display: inline-block;\n    width: 30px;\n    text-align: center;\n    cursor: move;\n}\n.pref-item .description {\n    padding: 0 10px;\n}\n.pref-item input[type=checkbox] {\n    display: none;\n}\n.pref-item input[type=checkbox] + span {\n    display: inline-block;\n    width: 4ex;\n    height: 20px;\n    border: 1px solid #BBB;\n    background-color: #fff;\n    vertical-align: middle;\n    line-height: 1em;\n    font-size: 16px;\n    text-align: center;\n    cursor: default;\n}\n.pref-item input[type=checkbox] + span:hover {\n    border-color: #000;\n}\n.pref-item input[type=checkbox] + span:before {\n    content: \'Off\';\n}\n.pref-item input[type=checkbox]:checked + span:before {\n    content: \'On\';\n}\n\n/* Description of source */\n.pref-item.sd-highlight:hover,\n.source-item-description:hover ~ .pref-item.sd-highlight {\n    outline: 1px solid #888;\n}\n.source-item-description {\n    position: absolute;\n    top: 0;\n    left: 400px;\n    display: none;\n    width: 300px;\n    height: 100%;\n    border-left: 3px solid #99C;\n    padding: 7px;\n    font-size: 16px;\n}\n.source-item-description.sd-visible {\n    display: block;\n}\n.sd-source-header {\n    font-weight: bold;\n    margin: 0 0 0.5em 0;\n}\n\n\n.config-site-box {\n    display: inline-block;\n    border: 1px solid transparent;\n    width: 32%;\n    min-height: 2em;\n    padding: 0.5em;\n    background-color: #EEFAEE;\n    border-radius: 3px;\n    vertical-align: top;\n}\n.config-site-box:hover {\n    border-color: #CCF;\n}\n.config-site-box label:hover {\n    background-color: #FED;\n}\n.config-site-box.site-disabled {\n    background-color: #FAEEEE;\n}\n.config-site-box .config-site-items {\n    position: relative;\n}\n.config-site-box .btn-enable-site,\n.config-site-box.site-disabled:hover .btn-disable-site,\n.config-site-box .btn-disable-site {\n    display: none;\n}\n.config-site-box:hover .btn-disable-site,\n.config-site-box.site-disabled .btn-enable-site {\n    display: block;\n}\n.config-site-box.site-disabled .config-site-items > div {\n    visibility: hidden;\n}\ninput[type="button"].btn-disable-site {\n    position: absolute;\n    right: 0;\n    top: -2em;\n    height: 1.5em;\n    padding-top: 0;\n    opacity: 0.6;\n}\ninput[type="button"].btn-disable-site:hover {\n    opacity: 1;\n}\ninput[type="button"].btn-enable-site {\n    /* Big button */\n    width: 80%;\n    height: 2em;\n    max-height: 100%;\n\n    position: absolute;\n    top: 0;\n    bottom: 0;\n    left: 0;\n    right: 0;\n    margin: auto;\n}';
    }), r("options", [ "require", "exports", "module", "LyricsPanel-demo", "sources/lyrics", "config", "dragndrop-nodes", "text!style/config.css" ], function(e, t) {
        function r() {
            var e = document.createElement("style");
            e.appendChild(document.createTextNode(v)), (document.head || document.documentElement).appendChild(e);
        }
        function n(e, t) {
            "onmouseenter" in document.documentElement ? e.addEventListener("mouseenter", t) : e.addEventListener("mouseover", function(e) {
                return this === e.relatedTarget || this.contains(e.relatedTarget) ? void 0 : t.call(this, e);
            });
        }
        function o(e) {
            e.classList || (e.classList = {
                add: function(t) {
                    -1 === (" " + e.className + " ").indexOf(t) && (e.className += " " + t);
                },
                remove: function(t) {
                    t = (" " + e.className + " ").replace(" " + t + " ", " ").trim(), e.className !== t && (e.className = t);
                }
            });
        }
        function i() {
            function e(e, t) {
                var r = document.getElementsByClassName(t)[0];
                if (r) {
                    if (r === e) return;
                    r.classList.remove(t);
                }
                e.classList.add(t);
            }
            function t() {
                p || (p = document.createElement("li"), p.className = "pref-item", p.innerHTML = '<span class="anchor">::</span><label><input type="checkbox"><span></span></label><span class="description"></span>');
                var e = p.cloneNode(!0);
                return o(e), e.querySelector('input[type="checkbox"]').onchange = function() {
                    e.classList[this.checked ? "remove" : "add"]("source-disabled"), c();
                }, e;
            }
            function r(t) {
                d || (d = document.createElement("li"), d.className = "source-item-description", 
                d.innerHTML = '<h2 class="sd-source-header"><a class="sd-source-link" target="_blank" rel="noreferrer"></a></h2><div><p class="sd-description"></p>View statistics on <a class="sd-alexa-link" target="_blank" rel="noreferrer" title="Alexa provides public demographics about websites, such as the visitor\'s country. You can use this tool to find out if this source suits your needs.">Alexa</a>.</div>');
                var r = d.cloneNode(!0);
                return o(r), n(r, function() {
                    e(t, "sd-highlight");
                }), n(t, function() {
                    e(r, "sd-visible"), e(t, "sd-highlight");
                }), r;
            }
            function i() {
                var e = document.createElement("input");
                return e.type = "button", e.id = "save", e.value = "Save", e.disabled = !0, e.onclick = s, 
                e;
            }
            function c() {
                document.getElementById("save").disabled = !1;
            }
            function l() {
                var e = document.createElement("input");
                return e.type = "button", e.id = "restore-defaults", e.value = "Restore defaults", 
                e.onclick = function() {
                    confirm("Do you want to remove your current Lyrics Source preferences, and restore the defaults?\nWarning: This step cannot be undone!") && a();
                }, e;
            }
            var u = document.getElementById("config-source");
            u.textContent = "Loading...";
            var p, d, f = document.createDocumentFragment();
            m.getAllLyricsSources(function(e) {
                var n = document.createElement("ol");
                n.className = "pref-sources", e.forEach(function(e) {
                    var o = t();
                    e.disabled && o.classList.add("source-disabled");
                    var i = e.identifier, s = o.querySelector('input[type="checkbox"]');
                    s.checked = !e.disabled, s.setAttribute("data-source-id", i), o.querySelector(".description").textContent = i, 
                    y(o.querySelector(".anchor"), o, c), n.appendChild(o), o = r(o);
                    var a = o.querySelector(".sd-source-link");
                    a.textContent = i, a.href = e.homepage, a = o.querySelector(".sd-alexa-link"), a.href = "http://www.alexa.com/siteinfo/" + e.homepage;
                    var l = o.querySelector(".sd-description");
                    l.textContent = e.description || "(no description)", l.appendChild(document.createElement("br")), 
                    f.appendChild(o);
                }), u.textContent = "You can disable a source, or change the priority order. Sources on top are used first.", 
                n.insertBefore(f, n.firstChild);
                var s = document.createElement("li");
                o(s), s.className = "source-item-description sd-visible", s.innerHTML = '<h2 class="sd-source-header">Description</h2>Hover over an item at the left side for brief descriptions.<br><br>Found a source which is not listed here? Send a mail to <a href="mailto:gwnRob@gmail.com">gwnRob@gmail.com</a>!', 
                n.appendChild(s), u.appendChild(n), u.appendChild(i()), u.appendChild(l());
            });
        }
        function s() {
            for (var e = document.querySelectorAll('ol.pref-sources > li.pref-item input[type="checkbox"]'), t = [], r = [], n = [], o = 0; e.length > o; o++) {
                var i = e[o], s = i.getAttribute("data-source-id"), a = i.checked;
                t.push(s), (a ? n : r).push(s);
            }
            var c = {
                order: t,
                blacklist: r,
                whitelist: n
            };
            g.setItem("lyricsSourcePreferences", c, function(e) {
                e ? b("Successfully saved preferences.") : b("Failed to save all preferences.");
            }), document.getElementById("save").disabled = !0;
        }
        function a() {
            g.removeItem("lyricsSourcePreferences", function(e) {
                b(e ? "Successfully removed prefs." : "Failed to remove all prefs."), i();
            });
        }
        function c(e) {
            function t() {
                g.getItem("setwmode", function(e) {
                    e = e !== !1, n.checked = e;
                });
            }
            if (!(0 > Object.prototype.toString.call(window.HTMLElement).indexOf("Constructor") || /mac/i.test(navigator.platform))) {
                var r = document.createElement("div");
                r.id = "config-wmode", r.innerHTML = '<label title="Set wmode=opaque. \nRequired if you want to drag the panel over the video. \nSearch suggestions will also start to work properly! \nEnabling this option might affect performance."><input type="checkbox"> Set wmode parameter</label>', 
                e.appendChild(r);
                var n = r.querySelector("input[type=checkbox]");
                n.checked = !0, n.onchange = function() {
                    g.setItem("setwmode", n.checked, function(e) {
                        b(e ? "Successfully saved wmode pref." : "Failed to save wmode pref."), t();
                    });
                }, t();
            }
        }
        function l() {
            var e = document.getElementById("launch-demo"), t = e.getAttribute("data-x");
            t = (t || "_") + "_", e.setAttribute("data-x", t), e.style.display = "block";
            var r = function() {
                t == e.getAttribute("data-x") ? h.init() : e.removeEventListener("click", r, !1);
            };
            e.addEventListener("click", r, !1);
        }
        function u(e, t) {
            function r() {
                g.getItem(s, function(e) {
                    e = e !== !1, n.classList[e ? "remove" : "add"]("site-disabled");
                });
            }
            var n = e.parentNode;
            o(n);
            var i = n.querySelector("h2").textContent, s = "enabled." + t, a = function(e) {
                n.classList[e ? "remove" : "add"]("site-disabled"), g.setItem(s, e, function(e) {
                    b((e ? "Successfully saved " : "Failed to save ") + s + " pref.");
                });
            }, c = document.createElement("input");
            c.type = "button", c.value = "Enable", c.className = "btn-enable-site", c.title = "Active Lyrics for " + i, 
            o(c), c.onclick = function() {
                a(!0);
            };
            var l = document.createElement("input");
            o(l), l.type = "button", l.value = "Disable", l.className = "btn-disable-site", 
            l.title = "Completely disable Lyrics for " + i, l.onclick = function() {
                a(!1);
            }, e.appendChild(c), e.appendChild(l), r();
        }
        function p(e, t) {
            function r() {
                g.getItem(n, function(e) {
                    s.checked = e !== !1;
                });
            }
            var n = t + "-autolaunch", o = "The lyrics can be shown by clicking on the 'YouTube Lyrics' icon " + ("youtube" == t ? "after the video's title." : "grooveshark" == t ? "at the left side of the player controls." : "spotify" == t ? "at the upper-right corner of the player." : "at the upper-right corner of the video page."), i = document.createElement("div");
            i.id = "config-" + t + "-autolaunch", i.innerHTML = '<label title="If unchecked, lyrics will not be displayed. \n' + o + '"><input type="checkbox"> Automatically show Lyrics.</label>', 
            e.appendChild(i);
            var s = i.querySelector('input[type="checkbox"]');
            s.checked = !0, s.onchange = function() {
                g.setItem(n, s.checked, function(e) {
                    b((e ? "Successfully saved " : "Failed to save ") + n + " pref."), r();
                });
            }, r();
        }
        function d(e, t) {
            function r() {
                g.getItem(n, function(e) {
                    i.value = e, -1 == i.selectedIndex && (i.value = "auto");
                });
            }
            var n = "theme." + t, o = document.createElement("div");
            o.id = "config-" + t + "-theme", o.innerHTML = '<label>Theme: <select class="pref-select-theme"></select></label>', 
            e.appendChild(o);
            var i = o.querySelector("select");
            i.add(new Option("Auto-detect", "auto", !0)), i.add(new Option("Default", "default")), 
            i.add(new Option("Dark", "dark")), i.onchange = function() {
                g.setItem(n, this.value, function(e) {
                    b((e ? "Successfully saved " : "Failed to save ") + n + " pref.");
                });
            }, r();
        }
        function f() {
            if (!document.getElementById("get-extension")) return b("Not an options page!"), 
            void 0;
            if (!document.documentElement.hasAttribute("YTLActivated")) {
                if (document.documentElement.hasAttribute("YTLDemoActivated")) {
                    for (var e = document.querySelectorAll("#just-a-demo-overlay,.L759-container,.L759-overlay,.YouTubeLyricsByRobWPageActionIcon"), t = 0; e.length > t; ++t) e[t].parentNode.removeChild(e[t]);
                    e = null;
                }
                document.documentElement.setAttribute("YTLActivated", ""), b("Options page detected by YouTube Lyrics."), 
                r(), i(), l(), [ "youtube", "grooveshark", "spotify" ].forEach(function(e) {
                    var t = document.querySelector("#config-" + e + " .config-site-items");
                    t.textContent = "", "youtube" == e && c(t, e), u(t, e), p(t, e), d(t, e);
                });
            }
        }
        var h = e("LyricsPanel-demo"), m = e("sources/lyrics"), g = e("config"), y = e("dragndrop-nodes").bindDnD, v = e("text!style/config.css"), b = function(e) {
            console && console.log("Options: " + e);
        };
        t.init = f;
    }), t([ "config", "setwmode", "domready", "YouTubeLyrics", "GroovesharkLyrics", "SpotifyLyrics", "options" ], function(e, t, r, n, o, i, s) {
        var a = /^https?:\/\/www\.youtube\.com\/(?![ve]\/)(?!embed\/)(?!dev(\/|$))/.test(location.href) ? "youtube" : /^(|(retro|html5)\.)grooveshark\.com$/.test(location.hostname) ? "grooveshark" : "play.spotify.com" === location.hostname ? "spotify" : /^https?:\/\/rob\.lekensteyn\.nl\/youtubelyrics/.test(location.href) ? "options" : "";
        if (a) {
            var c = function() {
                if (0 === --u && l) switch (a) {
                  case "youtube":
                    document.title && n.init();
                    break;

                  case "grooveshark":
                    document.querySelector("#now-playing-metadata,#playerDetails_nowPlaying,#little-queue") && o.init();
                    break;

                  case "spotify":
                    window.top == window && i.init();
                    break;

                  case "options":
                    s.init();
                }
            }, l = "options" === a, u = 1;
            l || (++u, e.getItem("enabled." + a, function(e) {
                l = e !== !1, c();
            })), r(c), "youtube" === a && 0 > Object.prototype.toString.call(window.HTMLElement).indexOf("Constructor") && !/mac/i.test(navigator.platform) && e.getItem("setwmode", function(e) {
                e !== !1 && t();
            });
        }
    });
})();