Goal: " + goal;
+ }
+
+ if ( ! elapsed )
+ timer.innerHTML = "Entry Open";
+ else if ( done )
+ timer.innerHTML = "Done";
+ else {
+ timer.innerHTML = utils.time_to_string(elapsed);
+ this._race_timer = setTimeout(this._update_race.bind(this), 1000);
+ }
+ }
+}
+},{"../utils":25}],23:[function(require,module,exports){
var FFZ = window.FrankerFaceZ,
constants = require('../constants');
@@ -2222,7 +3099,7 @@ FFZ.prototype.setup_css = function() {
}
};
}
-},{"../constants":3}],22:[function(require,module,exports){
+},{"../constants":3}],24:[function(require,module,exports){
var FFZ = window.FrankerFaceZ,
constants = require('../constants'),
utils = require('../utils');
@@ -2259,10 +3136,22 @@ FFZ.ws_commands.viewers = function(data) {
jQuery(view_count).tipsy();
}
}
-},{"../constants":3,"../utils":23}],23:[function(require,module,exports){
+},{"../constants":3,"../utils":25}],25:[function(require,module,exports){
var FFZ = window.FrankerFaceZ,
constants = require('./constants');
+
+var sanitize_cache = {},
+ sanitize_el = document.createElement('span'),
+
+ place_string = function(num) {
+ if ( num == 1 ) return '1st';
+ else if ( num == 2 ) return '2nd';
+ else if ( num == 3 ) return '3rd';
+ else if ( num == null ) return '---';
+ return num + "th";
+ };
+
module.exports = {
update_css: function(element, id, css) {
var all = element.innerHTML,
@@ -2288,6 +3177,35 @@ module.exports = {
var parts = x.toString().split(".");
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
return parts.join(".");
+ },
+
+ place_string: place_string,
+
+ placement: function(entrant) {
+ if ( entrant.state == "forfeit" ) return "Forfeit";
+ else if ( entrant.state == "dq" ) return "DQed";
+ else if ( entrant.place ) return place_string(entrant.place);
+ return "";
+ },
+
+ sanitize: function(msg) {
+ var m = sanitize_cache[msg];
+ if ( ! m ) {
+ sanitize_el.textContent = msg;
+ m = sanitize_cache[msg] = sanitize_el.innerHTML;
+ sanitize_el.innerHTML = "";
+ }
+ return m;
+ },
+
+ time_to_string: function(elapsed) {
+ var seconds = elapsed % 60,
+ minutes = Math.floor(elapsed / 60),
+ hours = Math.floor(minutes / 60);
+
+ minutes = minutes % 60;
+
+ return (hours < 10 ? "0" : "") + hours + ":" + (minutes < 10 ? "0" : "") + minutes + ":" + (seconds < 10 ? "0" : "") + seconds;
}
}
},{"./constants":3}]},{},[13]);window.ffz = new FrankerFaceZ()}(window));
\ No newline at end of file
diff --git a/script.min.js b/script.min.js
index f65111c0..1893148b 100644
--- a/script.min.js
+++ b/script.min.js
@@ -1,2 +1,2 @@
-!function(e){!function t(e,o,n){function s(i,a){if(!o[i]){if(!e[i]){var l="function"==typeof require&&require;if(!a&&l)return l(i,!0);if(r)return r(i,!0);throw new Error("Cannot find module '"+i+"'")}var c=o[i]={exports:{}};e[i][0].call(c.exports,function(t){var o=e[i][1][t];return s(o?o:t)},c,c.exports,t,e,o,n)}return o[i].exports}for(var r="function"==typeof require&&require,i=0;ie?this._legacy_add_donors(e):void 0):void 0})},o.prototype._legacy_parse_donors=function(e){var t=0;if(null!=e)for(var o=e.trim().split(/\W+/),n=0;n50)return"Each user you unmod counts as a single message. To avoid being globally banned, please limit yourself to 50 at a time and wait between uses.";for(var n=t.length;t.length;){var s=t.shift();e.room.tmiRoom.sendMessage("/unmod "+s)}return"Sent unmod command for "+n+" users."},t.chat_commands.massunmod.help="Usage: /ffz massunmod \nBroadcaster only. Unmod all the users in the provided list.",t.chat_commands.massmod=function(e,t){if(t=t.join(" ").trim(),!t.length)return"You must provide a list of users to mod.";t=t.split(/\W*,\W*/);var o=this.get_user();if(!o||!o.login==e.id)return"You must be the broadcaster to use massmod.";if(t.length>50)return"Each user you mod counts as a single message. To avoid being globally banned, please limit yourself to 50 at a time and wait between uses.";for(var n=t.length;t.length;){var s=t.shift();e.room.tmiRoom.sendMessage("/mod "+s)}return"Sent mod command for "+n+" users."},t.chat_commands.massmod.help="Usage: /ffz massmod \nBroadcaster only. Mod all the users in the provided list."},{}],3:[function(e,t){var o='',n="true"==localStorage.ffzDebugMode&&document.body.classList.contains("ffz-dev");t.exports={DEBUG:n,SERVER:n?"//localhost:8000/":"//cdn.frankerfacez.com/",SVGPATH:o,ZREKNARF:'",CHAT_BUTTON:'"}},{}],4:[function(){var t=e.FrankerFaceZ;t.chat_commands.developer_mode=function(e,t){var o,t=t&&t.length?t[0].toLowerCase():null;return"y"==t||"yes"==t||"true"==t||"on"==t?o=!0:("n"==t||"no"==t||"false"==t||"off"==t)&&(o=!1),void 0===o?"Developer Mode is currently "+("true"==localStorage.ffzDebugMode?"enabled.":"disabled."):(localStorage.ffzDebugMode=o,"Developer Mode is now "+(o?"enabled":"disabled")+". Please refresh your browser.")},t.chat_commands.developer_mode.help="Usage: /ffz developer_mode \nEnable or disable Developer Mode. When Developer Mode is enabled, the script will be reloaded from //localhost:8000/script.js instead of from the CDN."},{}],5:[function(){var t=e.FrankerFaceZ;t.prototype.setup_chatview=function(){this.log("Hooking the Ember Chat view.");var e=App.__container__.resolve("view:chat");this._modify_cview(e),e.create().destroy();for(var t in Ember.View.views)if(Ember.View.views.hasOwnProperty(t)){var o=Ember.View.views[t];o instanceof e&&(this.log("Adding UI link manually to Chat view.",o),o.$(".textarea-contain").append(this.build_ui_link(o)))}},t.prototype._modify_cview=function(e){var t=this;e.reopen({didInsertElement:function(){this._super(),this.$()&&this.$(".textarea-contain").append(t.build_ui_link(this))},willClearRender:function(){this._super(),this.$(".ffz-ui-toggle").remove()},ffzUpdateLink:Ember.observer("controller.currentRoom",function(){t.update_ui_link()})})}},{}],6:[function(){var t=e.FrankerFaceZ,o=function(e){return e.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")};t.prototype.setup_line=function(){this.log("Hooking the Ember Line controller.");var e=App.__container__.resolve("controller:line"),o=this;e.reopen({tokenizedMessage:function(){var e=o._emoticonize(this,this._super()),t=o.get_user();return t&&this.get("model.from")==t.login||(e=o._mentionize(this,e)),e}.property("model.message","isModeratorOrHigher","controllers.emoticons.emoticons.[]")}),this.log("Hooking the Ember Line view.");var e=App.__container__.resolve("view:line");e.reopen({didInsertElement:function(){this._super();var e=this.get("element"),t=this.get("context.model.from");e.setAttribute("data-room",this.get("context.parentController.content.id")),e.setAttribute("data-sender",t),o.render_badge(this),"false"!=localStorage.ffzCapitalize&&o.capitalize(this,t)}});var n=this.get_user();n&&n.name&&(t.capitalization[n.login]=[n.name,Date.now()]),this.mention_words=localStorage.ffzMentionize?JSON.parse(localStorage.ffzMentionize):[]},t.capitalization={},t._cap_fetching=0,t.get_capitalization=function(e,o){if(e=e.toLowerCase(),"jtv"==e||"twitchnotify"==e)return e;var n=t.capitalization[e];return n&&Date.now()-n[1]<36e5?n[0]:(t._cap_fetching<5&&(t._cap_fetching++,Twitch.api.get("users/"+e).always(function(n){var s=n.display_name||e;t.capitalization[e]=[s,Date.now()],t._cap_fetching--,"function"==typeof o&&o(s)})),n?n[0]:e)},t.prototype.capitalize=function(e,o){var n=t.get_capitalization(o,this.capitalize.bind(this,e));n&&e.$(".from").text(n)},t.chat_commands.capitalization=function(e,t){var o,t=t&&t.length?t[0].toLowerCase():null;return"y"==t||"yes"==t||"true"==t||"on"==t?o=!0:("n"==t||"no"==t||"false"==t||"off"==t)&&(o=!1),void 0===o?"Chat Name Capitalization is currently "+("false"!=localStorage.ffzCapitalize?"enabled.":"disabled."):(localStorage.ffzCapitalize=o,"Chat Name Capitalization is now "+(o?"enabled.":"disabled."))},t.chat_commands.capitalization.help="Usage: /ffz capitalization \nEnable or disable Chat Name Capitalization. This setting does not work with BetterTTV.",t._regex_cache={},t.get_regex=function(e){return t._regex_cache[e]=t._regex_cache[e]||RegExp("\\b"+o(e)+"\\b","i")},t.prototype._mentionize=function(e,o){return this.mention_words?("string"==typeof o&&(o=[o]),_.each(this.mention_words,function(e){var n={mentionedUser:e,own:!1};o=_.compact(_.flatten(_.map(o,function(o){if(_.isObject(o))return o;var s=o.split(t.get_regex(e)),r=[];return s.forEach(function(e,t){r.push(e),t!==s.length-1&&r.push(n)}),r})))}),o):o},t.chat_commands.mentionize=function(e,t){return t&&t.length&&(this.mention_words=t.join(" ").trim().split(/\W*,\W*/),1==this.mention_words.length&&"disable"==this.mention_words[0]&&(this.mention_words=[]),localStorage.ffzMentionize=JSON.stringify(this.mention_words)),this.mention_words.length?"The following words will be treated as mentions: "+this.mention_words.join(", "):"There are no words set that will be treated as mentions."},t.chat_commands.mentionize.help="Usage: /ffz mentionize \nSet a list of words that will also be treated as mentions and be displayed specially in chat.",t.prototype._emoticonize=function(e,t){var o=e.get("parentController.model.id"),n=e.get("model.from"),s=this,r=this.getEmotes(n,o),i=[];return _.each(r,function(e){var o=s.emote_sets[e];o&&_.each(o.emotes,function(e){_.any(t,function(t){return _.isString(t)&&t.match(e.regex)})&&i.push(e)})}),i.length?("string"==typeof t&&(t=[t]),_.each(i,function(e){var o={isEmoticon:!0,cls:e.klass,emoticonSrc:e.url,altText:e.hidden?"???":e.name};t=_.compact(_.flatten(_.map(t,function(t){if(_.isObject(t))return t;var n=t.split(e.regex),s=[];return n.forEach(function(e,t){s.push(e),t!==n.length-1&&s.push(o)}),s})))}),t):t}},{}],7:[function(t){var o=e.FrankerFaceZ,n=/\.([\w\-_]+)\s*?\{content:\s*?"([^"]+)";\s*?background-image:\s*?url\("([^"]+)"\);\s*?height:\s*?(\d+)px;\s*?width:\s*?(\d+)px;\s*?margin:([^;}]+);?([^}]*)\}/gm,s=/[^\n}]*\.badges\s+\.moderator\s*{\s*background-image:\s*url\(\s*['"]([^'"]+)['"][^}]+(?:}|$)/,r=/^_([^_]+)_\d+$/,i=t("../constants"),a=t("../utils"),l=function(e){return e.moderator_badge?'.chat-line[data-room="'+e.id+'"] .badges .moderator { background-image:url("'+e.moderator_badge+'") !important; }':""};o.prototype.setup_room=function(){this.rooms={},this.log("Creating room style element.");var e=this._room_style=document.createElement("style");e.id="ffz-room-css",document.head.appendChild(e),this.log("Hooking the Ember Room model.");var t=App.__container__.resolve("model:room");this._modify_room(t);var o=t.instances;for(var n in o)if(o.hasOwnProperty(n)){var s=o[n];this.add_room(s.id,s),this._modify_room(s)}},o.chat_commands={},o.prototype.room_message=function(e,t){var o=t.split("\n");if(this.has_bttv)for(var n=0;no?this._legacy_add_room(e,t,o):void 0)})},o.prototype._legacy_load_room_css=function(e,t,o){var i=e,a=i.match(r);a&&a[1]&&(i=a[1]);var l={id:e,menu_sets:[i],sets:[i],moderator_badge:null,css:null};return o&&(o=o.replace(n,"").trim()),o&&(o=o.replace(s,function(e,t){return l.moderator_badge||"modicon.png"!==t.substr(-11)?e:(l.moderator_badge=t,"")})),l.css=o||null,this._load_room_json(e,t,l)}},{"../constants":3,"../utils":23}],8:[function(){var t=e.FrankerFaceZ;t.prototype.setup_router=function(){this.log("Hooking the Ember router.");var e=this;App.__container__.lookup("router:main").reopen({ffzTransition:function(){e.track_page()}.on("didTransition")})}},{}],9:[function(){var t=e.FrankerFaceZ;t.prototype.setup_viewers=function(){this.log("Hooking the Ember Viewers controller.");var e=App.__container__.resolve("controller:viewers");this._modify_viewers(e)},t.prototype._modify_viewers=function(e){var o=this;e.reopen({lines:function(){var e=this._super(),n=[],s={},r=null,i=App.__container__.lookup("controller:channel"),a=this.get("parentController.model.id"),l=i&&i.get("id");if(l){var c=i.get("display_name");c&&(t.capitalization[l]=[c,Date.now()])}a!=l&&(l=null);for(var u=0;uo?this._legacy_load_set(e,t,o):"function"==typeof t&&t(!1))})},o.prototype._legacy_load_css=function(e,t,o){var r={},i={id:e,emotes:r,extra_css:null},a=this;o=o.replace(n,function(e,t,o,n,s,i,c,u){s=parseInt(s),i=parseInt(i),c=l(c,s);var d="."===n.substr(n.lastIndexOf("/")+1,1),h=++a._last_emote_id,m={id:h,hidden:d,name:o,height:s,width:i,url:n,margins:c,extra_css:u};return r[h]=m,""}).trim(),o&&o.replace(s,function(e,t){i.icon||"modicon.png"!==t.substr(-11)||(i.icon=t)}),this._load_set_json(e,t,i)}},{"./constants":3,"./utils":23}],11:[function(){var t=e.FrankerFaceZ,o=/(\sdata-sender="[^"]*"(?=>))/;t.prototype.find_bttv=function(t,o){return this.has_bttv=!1,e.BTTVLOADED?this.setup_bttv(o||0):void(o>=6e4?this.log("BetterTTV was not detected after 60 seconds."):setTimeout(this.find_bttv.bind(this,t,(o||0)+t),t))},t.prototype.setup_bttv=function(e){this.log("BetterTTV was detected after "+e+"ms. Hooking."),this.has_bttv=!0,this.track("setCustomVariable","3","BetterTTV",BetterTTV.info.versionString());var t=BetterTTV.chat.helpers.sendMessage,n=this;BetterTTV.chat.helpers.sendMessage=function(e){var o=e.split(" ",1)[0].toLowerCase();return"/ffz"!==o?t(e):void n.run_command(e.substr(5),BetterTTV.chat.store.currentRoom)};var s,r=BetterTTV.chat.handlers.privmsg;BetterTTV.chat.handlers.privmsg=function(e,t){s=e;var o=r(e,t);return s=null,o};var i=BetterTTV.chat.templates.privmsg;BetterTTV.chat.templates.privmsg=function(e,t,r,a,l){n.bttv_badges(l);var c=i(e,t,r,a,l);return c.replace(o,'$1 data-room="'+s+'"')};var a,l=BetterTTV.chat.templates.message;BetterTTV.chat.templates.message=function(e,t,o,n){a=e;var s=l(e,t,o,n);return a=null,s};var c=BetterTTV.chat.templates.emoticonize;BetterTTV.chat.templates.emoticonize=function(e,t){var o=c(e,t),r=n.getEmotes(a,s),t=[];return _.each(r,function(e){var s=n.emote_sets[e];s&&_.each(s.emotes,function(e){_.any(o,function(t){return _.isString(t)&&t.match(e.regex)})&&t.push(e)})}),t.length?(_.each(t,function(e){var t=[''],n=o;if(o=[],!n||!n.length)return o;for(var s=0;s=6e4?this.log("Emote Menu for Twitch was not detected after 60 seconds."):setTimeout(this.find_emote_menu.bind(this,t,(o||0)+t),t))},t.prototype.setup_emote_menu=function(e){this.log("Emote Menu for Twitch was detected after "+e+"ms. Registering emote enumerator."),emoteMenu.registerEmoteGetter("FrankerFaceZ",this._emote_menu_enumerator.bind(this))},t.prototype._emote_menu_enumerator=function(){for(var e=this.get_user(),o=e?e.login:null,n=App.__container__.lookup("controller:chat"),s=n?n.get("currentRoom.id"):null,r=this.getEmotes(o,s),i=[],a=0;a=6e4?this.log('Twitch application not detected in "'+location.toString()+'". Aborting.'):setTimeout(this.initialize.bind(this,t,(o||0)+t),t)))},o.prototype.setup_ember=function(t){var n=e.performance&&performance.now?performance.now():Date.now();this.log("Found Twitch application after "+(t||0)+' ms in "'+location+'". Initializing FrankerFaceZ version '+o.version_info),this.users={};for(var s in localStorage)"ffz_"==s.substr(0,4)&&localStorage.removeItem(s);this.ws_create(),this.setup_emoticons(),this.setup_badges(),this.setup_piwik(),this.setup_router(),this.setup_room(),this.setup_line(),this.setup_chatview(),this.setup_viewers(),this.setup_css(),this.setup_menu(),this.find_bttv(10),this.find_emote_menu(10),this.check_ff();var r=e.performance&&performance.now?performance.now():Date.now(),i=r-n;this.log("Initialization complete in "+i+"ms")}},{"./badges":1,"./commands":2,"./debug":4,"./ember/chatview":5,"./ember/line":6,"./ember/room":7,"./ember/router":8,"./ember/viewers":9,"./emoticons":10,"./ext/betterttv":11,"./ext/emote_menu":12,"./featurefriday":14,"./shims":15,"./socket":16,"./tracking":17,"./ui/menu":18,"./ui/menu_button":19,"./ui/notifications":20,"./ui/styles":21,"./ui/viewer_count":22}],14:[function(t){var o=e.FrankerFaceZ,n=t("./constants");o.prototype.feature_friday=null,o.prototype.check_ff=function(e){e||this.log("Checking for Feature Friday data..."),jQuery.ajax(n.SERVER+"script/event.json",{cache:!1,dataType:"json",context:this}).done(function(e){return this._load_ff(e)}).fail(function(t){return 404==t.status?this._load_ff(null):(e=e||0,e++,10>e?setTimeout(this.check_ff.bind(this,e),250):this._load_ff(null))})},o.ws_commands.reload_ff=function(){this.check_ff()},o.prototype._feature_friday_ui=function(e,t,o){if(this.feature_friday&&this.feature_friday.channel!=e){this._emotes_for_sets(t,o,[this.feature_friday.set],"Feature Friday");var n=App.__container__.lookup("controller:channel");if(!n||n.get("id")!=this.feature_friday.channel){var s=this.feature_friday,r=this,i=document.createElement("div"),a=document.createElement("a");i.className="chat-menu-content",i.style.textAlign="center";var l=s.display_name+(s.live?" is live now!":"");a.className="button primary",a.classList.toggle("live",s.live),a.classList.toggle("blue",this.has_bttv&&BetterTTV.settings.get("showBlueButtons")),a.href="http://www.twitch.tv/"+s.channel,a.title=l,a.target="_new",a.innerHTML=""+l+"",a.addEventListener("click",function(){r.track("trackLink",this.href,"link")}),i.appendChild(a),t.appendChild(i)}}},o.prototype._load_ff=function(e){if(this.feature_friday){this.global_sets.removeObject(this.feature_friday.set);var t=this.emote_sets[this.feature_friday.set];t&&(t.global=!1),this.feature_friday=null,this.update_ui_link()}e&&e.set&&e.channel&&(this.feature_friday={set:e.set,channel:e.channel,live:!1,display_name:o.get_capitalization(e.channel,this._update_ff_name.bind(this))},this.global_sets.push(e.set),this.load_set(e.set,this._update_ff_set.bind(this)),this._update_ff_live())},o.prototype._update_ff_live=function(){if(this.feature_friday){var e=this;Twitch.api.get("streams/"+this.feature_friday.channel).done(function(t){e.feature_friday.live=null!=t.stream,e.update_ui_link()}).always(function(){e.feature_friday.timer=setTimeout(e._update_ff_live.bind(e),12e4)})}},o.prototype._update_ff_set=function(e,t){t&&(t.global=!0)},o.prototype._update_ff_name=function(e){this.feature_friday&&(this.feature_friday.display_name=e)}},{"./constants":3}],15:[function(){Array.prototype.equals=function(e){if(!e)return!1;if(this.length!=e.length)return!1;for(var t=0,o=this.length;o>t;t++)if(this[t]instanceof Array&&e[t]instanceof Array){if(!this[t].equals(e[t]))return!1}else if(this[t]!=e[t])return!1;return!0}},{}],16:[function(){var t=e.FrankerFaceZ;t.prototype._ws_open=!1,t.prototype._ws_delay=0,t.ws_commands={},t.prototype.ws_create=function(){var e,o=this;this._ws_last_req=0,this._ws_callbacks={},this._ws_pending=this._ws_pending||[];try{e=this._ws_sock=new WebSocket("ws://ffz.stendec.me/")}catch(n){return this._ws_exists=!1,this.log("Error Creating WebSocket: "+n)}this._ws_exists=!0,e.onopen=function(){o._ws_open=!0,o._ws_delay=0,o.log("Socket connected.");var e=o.get_user();e&&o.ws_send("setuser",e.login);for(var t in o.rooms)o.ws_send("sub",t);var n=o._ws_pending;o._ws_pending=[];for(var s=0;s\nEnable or disable FrankerFaceZ analytics. We collect some data about your browser and how you use FrankerFaceZ to help us improve the script. Turn off analytics if you'd rather we not.",o.prototype.track=function(){this._tracking&&e._paq&&_paq.push(Array.prototype.slice.call(arguments))},o.prototype.track_page=function(){if(this._tracking){this._old_url&&this.track("setReferrerUrl",this._old_url),this._old_url=document.location.toString(),this.track("setCustomUrl",this._old_url),this.track("deleteCustomVariable","1","page"),this.track("deleteCustomVariable","3","page");var e=App.__container__.resolve("router:main").router.currentHandlerInfos;if(e&&0!=e.length){var t=e[e.length-1];if("channel.index"==t.name&&t.context){var o=t.context.get("isFollowing.isFollowing");void 0!==o&&null!==o&&this.track("setCustomVariable","1","Following",o?"Yes":"No","page");var n=t.context.get("game");n&&this.track("setCustomVariable","3","Game",n,"page"),this.track("trackPageView",document.title)}}}}},{"./constants":3}],18:[function(){var t=e.FrankerFaceZ;t.prototype.setup_menu=function(){this.log("Installing mouse-up event to auto-close menus.");var e=this;jQuery(document).mouseup(function(t){var o,n=e._popup;n&&(n=jQuery(n),o=n.parent(),o.is(t.target)||0!==o.has(t.target).length||(n.remove(),delete e._popup))})},t.prototype.build_ui_popup=function(t){var o=this._popup;if(o)return o.parentElement.removeChild(o),void delete this._popup;var n=document.createElement("div"),s=document.createElement("div");n.className="emoticon-selector chat-menu ffz-ui-popup",s.className="emoticon-selector-box dropmenu",n.appendChild(s);var r=t.get("controller.currentRoom.id"),i=this.rooms[r];this.log("Menu for Room: "+r,i),this.track("trackEvent","Menu","Open",r);var a=document.createElement("a");a.className="button glyph-only ffz-button",a.title="Advertise for FrankerFaceZ in chat!",a.href="#",a.innerHTML='';var l=document.createElement("div");l.className="list-header first",l.appendChild(a),l.appendChild(document.createTextNode("FrankerFaceZ")),s.appendChild(l);var c=this._emotes_for_sets(s,t,i&&i.menu_sets||[]);this._ws_exists?0===c?a.addEventListener("click",this._add_emote.bind(this,t,"To use custom emoticons in tons of channels, get FrankerFaceZ from http://www.frankerfacez.com")):a.addEventListener("click",this._add_emote.bind(this,t,"To view this channel's emoticons, get FrankerFaceZ from http://www.frankerfacez.com")):(a.className="button ffz-button primary",a.innerHTML="Server Error",a.title="FFZ Server Error",a.addEventListener("click",alert.bind(e,"The FrankerFaceZ client was unable to create a WebSocket to communicate with the FrankerFaceZ server.\n\nThis is most likely due to your browser's configuration either disabling WebSockets entirely or limiting the number of simultaneous connections. Please ensure that WebSockets have not been disabled."))),this._feature_friday_ui(r,s,t),this._popup=n,s.style.maxHeight=Math.max(300,t.$().height()-171)+"px",t.$(".chat-interface").append(n)},t.prototype._emotes_for_sets=function(e,t,o,n,s){if(null!=n){var r=document.createElement("div");r.className="list-header",r.appendChild(document.createTextNode(n)),s&&r.appendChild(s),e.appendChild(r)}var i=document.createElement("div"),a=0;i.className="emoticon-grid";for(var l=0;l0){s=!0;break}}e.classList.toggle("no-emotes",!s),e.classList.toggle("live",a),e.classList.toggle("dark",r),e.classList.toggle("blue",i)}}},{"../constants":3}],20:[function(){var t=e.FrankerFaceZ;t.prototype.show_notification=function(t){e.noty({text:t,theme:"ffzTheme",layout:"bottomCenter",closeWith:["button"]}).show()},t.ws_commands.message=function(e){this.show_notification(e)}},{}],21:[function(t){var o=e.FrankerFaceZ,n=t("../constants");o.prototype.setup_css=function(){this.log("Injecting main FrankerFaceZ CSS.");var e=this._main_style=document.createElement("link");e.id="ffz-ui-css",e.setAttribute("rel","stylesheet"),e.setAttribute("href",n.SERVER+"script/style.css"),document.head.appendChild(e),jQuery.noty.themes.ffzTheme={name:"ffzTheme",style:function(){this.$bar.removeClass().addClass("noty_bar").addClass("ffz-noty").addClass(this.options.type)},callback:{onShow:function(){},onClose:function(){}}}}},{"../constants":3}],22:[function(t){var o=e.FrankerFaceZ,n=t("../constants"),s=t("../utils");o.ws_commands.viewers=function(e){var t=e[0],o=e[1],r=App.__container__.lookup("controller:channel"),i=r&&r.get&&r.get("id");if(i===t){var a=document.querySelector(".channel-stats .ffz.stat"),l=n.ZREKNARF+" "+s.number_commas(o);if(a)a.innerHTML=l;else{var c=document.querySelector(".channel-stats");if(!c)return;a=document.createElement("span"),a.className="ffz stat",a.title="Viewers with FrankerFaceZ",a.innerHTML=l,c.appendChild(a),jQuery(a).tipsy()}}}},{"../constants":3,"../utils":23}],23:[function(t,o){e.FrankerFaceZ,t("./constants");o.exports={update_css:function(e,t,o){var n=e.innerHTML,s="/*BEGIN "+t+"*/",r="/*END "+t+"*/",i=n.indexOf(s),a=n.indexOf(r),l=-1!==i&&-1!==a&&a>i;(l||o)&&(l&&(n=n.substr(0,i)+n.substr(a+r.length)),o&&(n+=s+o+r),e.innerHTML=n)},number_commas:function(e){var t=e.toString().split(".");return t[0]=t[0].replace(/\B(?=(\d{3})+(?!\d))/g,","),t.join(".")}}},{"./constants":3}]},{},[13]),e.ffz=new FrankerFaceZ}(window);
\ No newline at end of file
+!function(e){!function t(e,n,i){function s(a,r){if(!n[a]){if(!e[a]){var l="function"==typeof require&&require;if(!r&&l)return l(a,!0);if(o)return o(a,!0);throw new Error("Cannot find module '"+a+"'")}var c=n[a]={exports:{}};e[a][0].call(c.exports,function(t){var n=e[a][1][t];return s(n?n:t)},c,c.exports,t,e,n,i)}return n[a].exports}for(var o="function"==typeof require&&require,a=0;ae?this._legacy_add_donors(e):void 0):void 0})},n.prototype._legacy_parse_donors=function(e){var t=0;if(null!=e)for(var n=e.trim().split(/\W+/),i=0;i50)return"Each user you unmod counts as a single message. To avoid being globally banned, please limit yourself to 50 at a time and wait between uses.";for(var i=t.length;t.length;){var s=t.shift();e.room.tmiRoom.sendMessage("/unmod "+s)}return"Sent unmod command for "+i+" users."},t.chat_commands.massunmod.help="Usage: /ffz massunmod \nBroadcaster only. Unmod all the users in the provided list.",t.chat_commands.massmod=function(e,t){if(t=t.join(" ").trim(),!t.length)return"You must provide a list of users to mod.";t=t.split(/\W*,\W*/);var n=this.get_user();if(!n||!n.login==e.id)return"You must be the broadcaster to use massmod.";if(t.length>50)return"Each user you mod counts as a single message. To avoid being globally banned, please limit yourself to 50 at a time and wait between uses.";for(var i=t.length;t.length;){var s=t.shift();e.room.tmiRoom.sendMessage("/mod "+s)}return"Sent mod command for "+i+" users."},t.chat_commands.massmod.help="Usage: /ffz massmod \nBroadcaster only. Mod all the users in the provided list."},{}],3:[function(e,t){var n='',i="true"==localStorage.ffzDebugMode&&document.body.classList.contains("ffz-dev");t.exports={DEBUG:i,SERVER:i?"//localhost:8000/":"//cdn.frankerfacez.com/",SVGPATH:n,ZREKNARF:'",CHAT_BUTTON:'",GEAR:'',HEART:''}},{}],4:[function(){var t=e.FrankerFaceZ;t.chat_commands.developer_mode=function(e,t){var n,t=t&&t.length?t[0].toLowerCase():null;return"y"==t||"yes"==t||"true"==t||"on"==t?n=!0:("n"==t||"no"==t||"false"==t||"off"==t)&&(n=!1),void 0===n?"Developer Mode is currently "+("true"==localStorage.ffzDebugMode?"enabled.":"disabled."):(localStorage.ffzDebugMode=n,"Developer Mode is now "+(n?"enabled":"disabled")+". Please refresh your browser.")},t.chat_commands.developer_mode.help="Usage: /ffz developer_mode \nEnable or disable Developer Mode. When Developer Mode is enabled, the script will be reloaded from //localhost:8000/script.js instead of from the CDN."},{}],5:[function(){var t=e.FrankerFaceZ;t.prototype.setup_chatview=function(){this.log("Hooking the Ember Chat view.");var e=App.__container__.resolve("view:chat");this._modify_cview(e),e.create().destroy();for(var t in Ember.View.views)if(Ember.View.views.hasOwnProperty(t)){var n=Ember.View.views[t];n instanceof e&&(this.log("Adding UI link manually to Chat view.",n),n.$(".textarea-contain").append(this.build_ui_link(n)))}},t.prototype._modify_cview=function(e){var t=this;e.reopen({didInsertElement:function(){this._super(),this.$()&&this.$(".textarea-contain").append(t.build_ui_link(this))},willClearRender:function(){this._super(),this.$(".ffz-ui-toggle").remove()},ffzUpdateLink:Ember.observer("controller.currentRoom",function(){t.update_ui_link()})})}},{}],6:[function(){var t=e.FrankerFaceZ,n=function(e){return e.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")};t.settings_info.capitalize={type:"boolean",value:!0,visible:function(){return!this.has_bttv},name:"Username Capitalization",help:"Display names in chat with proper capitalization."},t.settings_info.keywords={type:"button",value:[],visible:function(){return!this.has_bttv},name:"Highlight Keywords",help:"Set additional keywords that will be highlighted in chat.",method:function(){var e=this.settings.keywords.join(", "),t=prompt("Highlight Keywords\n\nPlease enter a comma-separated list of words that you would like to be highlighted in chat.",e);t&&(t=t.trim().split(/\W*,\W*/),1!=t.length||""!=t[0]&&"disable"!=t[0]||(t=[]),this.settings.set("keywords",t))}},t.settings_info.chat_rows={type:"boolean",value:!1,visible:function(){return!this.has_bttv},name:"Chat Line Backgrounds",help:"Display alternating background colors for lines in chat.",on_update:function(e){document.querySelector(".app-main").classList.toggle("ffz-chat-background",e)}},t.prototype.setup_line=function(){document.querySelector(".app-main").classList.toggle("ffz-chat-background",this.settings.chat_rows),this._last_row={},this.log("Hooking the Ember Line controller.");var n=App.__container__.resolve("controller:line"),i=this;n.reopen({tokenizedMessage:function(){var e=i._emoticonize(this,this._super()),t=i.get_user();return t&&this.get("model.from")==t.login||(e=i._mentionize(this,e)),e}.property("model.message","isModeratorOrHigher")}),this.log("Hooking the Ember Line view.");var n=App.__container__.resolve("view:line");n.reopen({didInsertElement:function(){this._super();var n=this.get("element"),s=this.get("context.model.from"),o=this.get("context.parentController.content.id"),a=this.get("context.model.ffzAlternate");void 0===a&&(a=i._last_row[o]=i._last_row.hasOwnProperty(o)?!i._last_row[o]:!1,this.set("context.model.ffzAlternate",a)),n.classList.toggle("ffz-alternate",a),n.setAttribute("data-room",o),n.setAttribute("data-sender",s),i.render_badge(this),i.settings.capitalize&&i.capitalize(this,s);var r=n.querySelector("span.mentioned");if(r&&(n.classList.add("ffz-mentioned"),!document.hasFocus()&&!this.get("context.model.ffzNotified")&&i.settings.highlight_notifications)){var l=t.get_capitalization(o),c=t.get_capitalization(s),h=l,u=this.get("context.model.message");this.get("context.parentController.content.isGroupRoom")&&(h=this.get("context.parentController.content.tmiRoom.displayName")),u="action"==this.get("context.model.style")?"* "+c+" "+u:c+": "+u,i.show_notification(u,"Twitch Chat Mention in "+h,l,6e4,e.focus.bind(e))}this.set("context.model.ffzNotified",!0)}});var s=this.get_user();s&&s.name&&(t.capitalization[s.login]=[s.name,Date.now()])},t.capitalization={},t._cap_fetching=0,t.get_capitalization=function(n,i){if(e.BetterTTV)return BetterTTV.chat.helpers.lookupDisplayName(n);if(n=n.toLowerCase(),"jtv"==n||"twitchnotify"==n)return n;var s=t.capitalization[n];return s&&Date.now()-s[1]<36e5?s[0]:(t._cap_fetching<5&&(t._cap_fetching++,Twitch.api.get("users/"+n).always(function(e){var s=e.display_name||n;t.capitalization[n]=[s,Date.now()],t._cap_fetching--,"function"==typeof i&&i(s)})),s?s[0]:n)},t.prototype.capitalize=function(e,n){var i=t.get_capitalization(n,this.capitalize.bind(this,e));i&&e.$(".from").text(i)},t.chat_commands.capitalization=function(e,t){var n,t=t&&t.length?t[0].toLowerCase():null;return"y"==t||"yes"==t||"true"==t||"on"==t?n=!0:("n"==t||"no"==t||"false"==t||"off"==t)&&(n=!1),void 0===n?"Chat Name Capitalization is currently "+(this.settings.capitalize?"enabled.":"disabled."):(this.settings.set("capitalize",n),"Chat Name Capitalization is now "+(n?"enabled.":"disabled."))},t.chat_commands.capitalization.help="Usage: /ffz capitalization \nEnable or disable Chat Name Capitalization. This setting does not work with BetterTTV.",t._regex_cache={},t._get_rex=function(e){return t._regex_cache[e]=t._regex_cache[e]||RegExp("\\b"+n(e)+"\\b","ig")},t._mentions_to_regex=function(e){return t._regex_cache[e]=t._regex_cache[e]||RegExp("\\b(?:"+_.chain(e).map(n).value().join("|")+")\\b","ig")},t.prototype._mentionize=function(e,n){var i=this.settings.keywords;if(!i)return n;"string"==typeof n&&(n=[n]);var s=t._mentions_to_regex(i);return _.chain(n).map(function(e){return _.isString(e)?e.match(s)?_.zip(_.map(e.split(s),_.identity),_.map(e.match(s),function(e){return{mentionedUser:e,own:!1}})):[e]:e}).flatten().compact().value()},t.chat_commands.mentionize=function(e,t){if(t&&t.length){var n=t.join(" ").trim().split(/\W*,\W*/);1==n.length&&"disable"==n[0]&&(n=[]),this.settings.set("keywords",n)}var n=this.settings.keywords;return n.length?"The following words will be highlighted: "+n.join(", "):"There are no words set that will be highlighted."},t.chat_commands.mentionize.help="Usage: /ffz mentionize \nSet a list of words that will also be highlighted in chat.",t.prototype._emoticonize=function(e,t){var n=e.get("parentController.model.id"),i=e.get("model.from"),s=this,o=this.getEmotes(i,n),a=[];return _.each(o,function(e){var n=s.emote_sets[e];n&&_.each(n.emotes,function(e){_.any(t,function(t){return _.isString(t)&&t.match(e.regex)})&&a.push(e)})}),a.length?("string"==typeof t&&(t=[t]),_.each(a,function(e){var n={isEmoticon:!0,cls:e.klass,emoticonSrc:e.url,altText:e.hidden?"???":e.name};t=_.compact(_.flatten(_.map(t,function(t){if(_.isObject(t))return t;var i=t.split(e.regex),s=[];return i.forEach(function(e,t){s.push(e),t!==i.length-1&&s.push(n)}),s})))}),t):t}},{}],7:[function(t){var n=e.FrankerFaceZ,i=/\.([\w\-_]+)\s*?\{content:\s*?"([^"]+)";\s*?background-image:\s*?url\("([^"]+)"\);\s*?height:\s*?(\d+)px;\s*?width:\s*?(\d+)px;\s*?margin:([^;}]+);?([^}]*)\}/gm,s=/[^\n}]*\.badges\s+\.moderator\s*{\s*background-image:\s*url\(\s*['"]([^'"]+)['"][^}]+(?:}|$)/,o=/^_([^_]+)_\d+$/,a=t("../constants"),r=t("../utils"),l=function(e){return e.moderator_badge?'.chat-line[data-room="'+e.id+'"] .badges .moderator { background-image:url("'+e.moderator_badge+'") !important; }':""};n.prototype.setup_room=function(){this.rooms={},this.log("Creating room style element.");var e=this._room_style=document.createElement("style");e.id="ffz-room-css",document.head.appendChild(e),this.log("Hooking the Ember Room model.");var t=App.__container__.resolve("model:room");this._modify_room(t);var n=t.instances;for(var i in n)if(n.hasOwnProperty(i)){var s=n[i];this.add_room(s.id,s),this._modify_room(s)}},n.chat_commands={},n.prototype.room_message=function(e,t){var n=t.split("\n");if(this.has_bttv)for(var i=0;in?this._legacy_add_room(e,t,n):void 0)})},n.prototype._legacy_load_room_css=function(e,t,n){var a=e,r=a.match(o);r&&r[1]&&(a=r[1]);var l={id:e,menu_sets:[a],sets:[a],moderator_badge:null,css:null};return n&&(n=n.replace(i,"").trim()),n&&(n=n.replace(s,function(e,t){return l.moderator_badge||"modicon.png"!==t.substr(-11)?e:(l.moderator_badge=t,"")})),l.css=n||null,this._load_room_json(e,t,l)}},{"../constants":3,"../utils":25}],8:[function(){var t=e.FrankerFaceZ;t.prototype.setup_router=function(){this.log("Hooking the Ember router.");var e=this;App.__container__.lookup("router:main").reopen({ffzTransition:function(){e.track_page()}.on("didTransition")})}},{}],9:[function(){var t=e.FrankerFaceZ;t.prototype.setup_viewers=function(){this.log("Hooking the Ember Viewers controller.");var e=App.__container__.resolve("controller:viewers");this._modify_viewers(e)},t.prototype._modify_viewers=function(e){e.reopen({lines:function(){var e=this._super(),n=[],i={},s=null,o=App.__container__.lookup("controller:channel"),a=this.get("parentController.model.id"),r=o&&o.get("id");if(r){var l=o.get("display_name");l&&(t.capitalization[r]=[l,Date.now()])}a!=r&&(r=null);for(var c=0;cn?this._legacy_load_set(e,t,n):"function"==typeof t&&t(!1))})},n.prototype._legacy_load_css=function(e,t,n){var o={},a={id:e,emotes:o,extra_css:null},r=this;n=n.replace(i,function(e,t,n,i,s,a,c,h){s=parseInt(s),a=parseInt(a),c=l(c,s);var u="."===i.substr(i.lastIndexOf("/")+1,1),d=++r._last_emote_id,p={id:d,hidden:u,name:n,height:s,width:a,url:i,margins:c,extra_css:h};return o[d]=p,""}).trim(),n&&n.replace(s,function(e,t){a.icon||"modicon.png"!==t.substr(-11)||(a.icon=t)}),this._load_set_json(e,t,a)}},{"./constants":3,"./utils":25}],11:[function(){var t=e.FrankerFaceZ,n=/(\sdata-sender="[^"]*"(?=>))/;t.prototype.find_bttv=function(t,n){return this.has_bttv=!1,e.BTTVLOADED?this.setup_bttv(n||0):void(n>=6e4?this.log("BetterTTV was not detected after 60 seconds."):setTimeout(this.find_bttv.bind(this,t,(n||0)+t),t))},t.prototype.setup_bttv=function(e){this.log("BetterTTV was detected after "+e+"ms. Hooking."),this.has_bttv=!0,this.track("setCustomVariable","3","BetterTTV",BetterTTV.info.versionString());var t=BetterTTV.chat.helpers.sendMessage,i=this;BetterTTV.chat.helpers.sendMessage=function(e){var n=e.split(" ",1)[0].toLowerCase();return"/ffz"!==n?t(e):void i.run_command(e.substr(5),BetterTTV.chat.store.currentRoom)};var s,o=BetterTTV.chat.handlers.privmsg;BetterTTV.chat.handlers.privmsg=function(e,t){s=e;var n=o(e,t);return s=null,n};var a=BetterTTV.chat.templates.privmsg;BetterTTV.chat.templates.privmsg=function(e,t,o,r,l){i.bttv_badges(l);var c=a(e,t,o,r,l);return c.replace(n,'$1 data-room="'+s+'"')};var r,l=BetterTTV.chat.templates.message;BetterTTV.chat.templates.message=function(e,t,n,i){r=e;var s=l(e,t,n,i);return r=null,s};var c=BetterTTV.chat.templates.emoticonize;BetterTTV.chat.templates.emoticonize=function(e,t){var n=c(e,t),o=i.getEmotes(r,s),t=[];return _.each(o,function(e){var s=i.emote_sets[e];s&&_.each(s.emotes,function(e){_.any(n,function(t){return _.isString(t)&&t.match(e.regex)})&&t.push(e)})}),t.length?(_.each(t,function(e){var t=[''],i=n;if(n=[],!i||!i.length)return n;for(var s=0;s=6e4?this.log("Emote Menu for Twitch was not detected after 60 seconds."):setTimeout(this.find_emote_menu.bind(this,t,(n||0)+t),t))},t.prototype.setup_emote_menu=function(e){this.log("Emote Menu for Twitch was detected after "+e+"ms. Registering emote enumerator."),emoteMenu.registerEmoteGetter("FrankerFaceZ",this._emote_menu_enumerator.bind(this))},t.prototype._emote_menu_enumerator=function(){for(var e=this.get_user(),n=e?e.login:null,i=App.__container__.lookup("controller:chat"),s=i?i.get("currentRoom.id"):null,o=this.getEmotes(n,s),a=[],r=0;r=6e4?this.log('Twitch application not detected in "'+location.toString()+'". Aborting.'):setTimeout(this.initialize.bind(this,t,(n||0)+t),t)))},n.prototype.setup_ember=function(t){var i=e.performance&&performance.now?performance.now():Date.now();this.log("Found Twitch application after "+(t||0)+' ms in "'+location+'". Initializing FrankerFaceZ version '+n.version_info),this.users={},this.load_settings(),this.ws_create(),this.setup_emoticons(),this.setup_badges(),this.setup_piwik(),this.setup_router(),this.setup_room(),this.setup_line(),this.setup_chatview(),this.setup_viewers(),this.setup_notifications(),this.setup_css(),this.setup_menu(),this.setup_races(),this.find_bttv(10),this.find_emote_menu(10),this.check_ff();var s=e.performance&&performance.now?performance.now():Date.now(),o=s-i;this.log("Initialization complete in "+o+"ms")}},{"./badges":1,"./commands":2,"./debug":4,"./ember/chatview":5,"./ember/line":6,"./ember/room":7,"./ember/router":8,"./ember/viewers":9,"./emoticons":10,"./ext/betterttv":11,"./ext/emote_menu":12,"./featurefriday":14,"./settings":15,"./shims":16,"./socket":17,"./tracking":18,"./ui/menu":19,"./ui/menu_button":20,"./ui/notifications":21,"./ui/races":22,"./ui/styles":23,"./ui/viewer_count":24}],14:[function(t){var n=e.FrankerFaceZ,i=t("./constants");n.prototype.feature_friday=null,n.prototype.check_ff=function(e){e||this.log("Checking for Feature Friday data..."),jQuery.ajax(i.SERVER+"script/event.json",{cache:!1,dataType:"json",context:this}).done(function(e){return this._load_ff(e)}).fail(function(t){return 404==t.status?this._load_ff(null):(e=e||0,e++,10>e?setTimeout(this.check_ff.bind(this,e),250):this._load_ff(null))})},n.ws_commands.reload_ff=function(){this.check_ff()},n.prototype._feature_friday_ui=function(e,t,n){if(this.feature_friday&&this.feature_friday.channel!=e){this._emotes_for_sets(t,n,[this.feature_friday.set],"Feature Friday");var i=App.__container__.lookup("controller:channel");if(!i||i.get("id")!=this.feature_friday.channel){var s=this.feature_friday,o=this,a=document.createElement("div"),r=document.createElement("a");a.className="chat-menu-content",a.style.textAlign="center";var l=s.display_name+(s.live?" is live now!":"");r.className="button primary",r.classList.toggle("live",s.live),r.classList.toggle("blue",this.has_bttv&&BetterTTV.settings.get("showBlueButtons")),r.href="http://www.twitch.tv/"+s.channel,r.title=l,r.target="_new",r.innerHTML=""+l+"",r.addEventListener("click",function(){o.track("trackLink",this.href,"link")}),a.appendChild(r),t.appendChild(a)}}},n.prototype._load_ff=function(e){if(this.feature_friday){this.global_sets.removeObject(this.feature_friday.set);var t=this.emote_sets[this.feature_friday.set];t&&(t.global=!1),this.feature_friday=null,this.update_ui_link()}e&&e.set&&e.channel&&(this.feature_friday={set:e.set,channel:e.channel,live:!1,display_name:n.get_capitalization(e.channel,this._update_ff_name.bind(this))},this.global_sets.push(e.set),this.load_set(e.set,this._update_ff_set.bind(this)),this._update_ff_live())},n.prototype._update_ff_live=function(){if(this.feature_friday){var e=this;Twitch.api.get("streams/"+this.feature_friday.channel).done(function(t){e.feature_friday.live=null!=t.stream,e.update_ui_link()}).always(function(){e.feature_friday.timer=setTimeout(e._update_ff_live.bind(e),12e4)})}},n.prototype._update_ff_set=function(e,t){t&&(t.global=!0)},n.prototype._update_ff_name=function(e){this.feature_friday&&(this.feature_friday.display_name=e)}},{"./constants":3}],15:[function(){var t=e.FrankerFaceZ,n=function(e){return"ffz_setting_"+e};t.settings_info={},t.prototype.load_settings=function(){this.log("Loading settings."),this.settings={};for(var i in t.settings_info){var s=n(i),o=t.settings_info[i],a=o.hasOwnProperty("value")?o.value:void 0;if(localStorage.hasOwnProperty(s))try{a=JSON.parse(localStorage.getItem(s))}catch(r){this.log('Error loading value for "'+i+'": '+r)}this.settings[i]=a}this.settings.get=this._setting_get.bind(this),this.settings.set=this._setting_set.bind(this),this.settings.del=this._setting_del.bind(this),e.addEventListener("storage",this._setting_update.bind(this))},t.prototype._setting_update=function(n){if(n||(n=e.event),this.log("Storage Event",n),n.key&&"ffz_setting_"===n.key.substr(0,12)){var i=n.key,s=i.substr(12),o=void 0,a=t.settings_info[s];
+this.log("Updated Setting: "+s);try{o=JSON.parse(n.newValue)}catch(r){this.log('Error loading new value for "'+s+'": '+r),o=a.value||void 0}if(this.settings[s]=o,a.on_update)try{a.on_update.bind(this)(o,!1)}catch(r){this.log('Error running updater for setting "'+s+'": '+r)}}},t.prototype._setting_get=function(e){return this.settings[e]},t.prototype._setting_set=function(e,i){var s=n(e),o=t.settings_info[e],a=JSON.stringify(i);if(this.settings[e]=i,localStorage.setItem(s,a),this.log('Changed Setting "'+e+'" to: '+a),o.on_update)try{o.on_update.bind(this)(i,!0)}catch(r){this.log('Error running updater for setting "'+e+'": '+r)}},t.prototype._setting_del=function(e){var i=n(e),s=t.settings_info[e],o=void 0;if(localStorage.hasOwnProperty(i)&&localStorage.removeItem(i),delete this.settings[e],s&&(o=this.settings[e]=s.hasOwnProperty("value")?s.value:void 0),s.on_update)try{s.on_update.bind(this)(o,!0)}catch(a){this.log('Error running updater for setting "'+e+'": '+a)}}},{}],16:[function(){Array.prototype.equals=function(e){if(!e)return!1;if(this.length!=e.length)return!1;for(var t=0,n=this.length;n>t;t++)if(this[t]instanceof Array&&e[t]instanceof Array){if(!this[t].equals(e[t]))return!1}else if(this[t]!=e[t])return!1;return!0}},{}],17:[function(){var t=e.FrankerFaceZ;t.prototype._ws_open=!1,t.prototype._ws_delay=0,t.ws_commands={},t.ws_on_close=[],t.prototype.ws_create=function(){var e,n=this;this._ws_last_req=0,this._ws_callbacks={},this._ws_pending=this._ws_pending||[];try{e=this._ws_sock=new WebSocket("ws://ffz.stendec.me/")}catch(i){return this._ws_exists=!1,this.log("Error Creating WebSocket: "+i)}this._ws_exists=!0,e.onopen=function(){n._ws_open=!0,n._ws_delay=0,n.log("Socket connected.");var e=n.get_user();e&&n.ws_send("setuser",e.login);for(var t in n.rooms)n.ws_send("sub",t);var i=n._ws_pending;n._ws_pending=[];for(var s=0;s\nEnable or disable FrankerFaceZ analytics. We collect some data about your browser and how you use FrankerFaceZ to help us improve the script. Turn off analytics if you'd rather we not.",n.prototype.track=function(){this._tracking&&e._paq&&_paq.push(Array.prototype.slice.call(arguments))},n.prototype.track_page=function(){if(this._tracking){this._old_url&&this.track("setReferrerUrl",this._old_url),this._old_url=document.location.toString(),this.track("setCustomUrl",this._old_url),this.track("deleteCustomVariable","1","page"),this.track("deleteCustomVariable","3","page");var e=App.__container__.resolve("router:main").router.currentHandlerInfos;if(e&&0!=e.length){var t=e[e.length-1];if("channel.index"==t.name&&t.context){var n=t.context.get("isFollowing.isFollowing");void 0!==n&&null!==n&&this.track("setCustomVariable","1","Following",n?"Yes":"No","page");var i=t.context.get("game");i&&this.track("setCustomVariable","3","Game",i,"page"),this.track("trackPageView",document.title)}}}}},{"./constants":3}],19:[function(t){var n=e.FrankerFaceZ,i=t("../constants");n.prototype.setup_menu=function(){this.log("Installing mouse-up event to auto-close menus.");var e=this;jQuery(document).mouseup(function(t){var n,i=e._popup;i&&(i=jQuery(i),n=i.parent(),n.is(t.target)||0!==n.has(t.target).length||(i.remove(),delete e._popup,e._popup_kill&&e._popup_kill(),delete e._popup_kill))})},n.menu_pages={},n.prototype.build_ui_popup=function(e){var t=this._popup;if(t)return t.parentElement.removeChild(t),delete this._popup,this._popup_kill&&this._popup_kill(),void delete this._popup_kill;var i=document.createElement("div"),s=document.createElement("div"),o=document.createElement("ul"),a=this.has_bttv?BetterTTV.settings.get("darkenedMode"):!1;i.className="emoticon-selector chat-menu ffz-ui-popup",s.className="emoticon-selector-box dropmenu",i.appendChild(s),i.classList.toggle("dark",a),o.className="menu clearfix",s.appendChild(o);var r=document.createElement("li");r.className="title",r.innerHTML="FrankerFaceZ",o.appendChild(r),r.addEventListener("click",this._add_emote.bind(this,e,"To use custom emoticons in tons of channels, get FrankerFaceZ from http://www.frankerfacez.com"));var l=document.createElement("div");l.className="ffz-ui-menu-page",s.appendChild(l);for(var c in n.menu_pages){var h=n.menu_pages[c];if(h&&(!h.hasOwnProperty("visible")||h.visible&&("function"!=typeof h.visible||h.visible.bind(this)()))){var r=document.createElement("li"),u=document.createElement("a");r.className="item",r.id="ffz-menu-page-"+c,u.title=h.name,u.innerHTML=h.icon,u.addEventListener("click",this._ui_change_page.bind(this,e,o,l,c)),r.appendChild(u),o.appendChild(r)}}this._ui_change_page(e,o,l,this._last_page||"channel"),this._popup=i,l.style.maxHeight=Math.max(300,e.$().height()-212)+"px",e.$(".chat-interface").append(i)},n.prototype._ui_change_page=function(e,t,i,s){this._last_page=s,i.innerHTML="";for(var o=t.querySelectorAll("li.active"),a=0;as?-1:s>o?1:0});for(var a=0;a",d.className="switch-label",d.innerHTML=r.name,l.appendChild(u),l.appendChild(d),u.addEventListener("click",this._ui_toggle_setting.bind(this,u,o))}else{l.classList.add("option");var p=document.createElement("a");p.innerHTML=r.name,p.href="#",l.appendChild(p),p.addEventListener("click",r.method.bind(this))}if(r.help){var _=document.createElement("span");_.className="help",_.innerHTML=r.help,l.appendChild(_)}i.appendChild(l)}t.appendChild(i)},name:"Settings",icon:i.GEAR},n.prototype._ui_toggle_setting=function(e,t){var n=!this.settings.get(t);this.settings.set(t,n),e.classList.toggle("active",n)},n.menu_pages.channel={render:function(e,t){var n=e.get("controller.currentRoom.id"),i=this.rooms[n];this.log("Menu for Room: "+n,i),this.track("trackEvent","Menu","Open",n);this._emotes_for_sets(t,e,i&&i.menu_sets||[]);this._feature_friday_ui(n,t,e)},name:"Channel",icon:i.ZREKNARF},n.prototype._emotes_for_sets=function(e,t,n,i,s){if(null!=i){var o=document.createElement("div");o.className="list-header",o.appendChild(document.createTextNode(i)),s&&o.appendChild(s),e.appendChild(o)}var a=document.createElement("div"),r=0;a.className="emoticon-grid";for(var l=0;l0){s=!0;break}}e.classList.toggle("no-emotes",!s),e.classList.toggle("live",r),e.classList.toggle("dark",o),e.classList.toggle("blue",a)}}},{"../constants":3}],21:[function(){var t=e.FrankerFaceZ;t.prototype.setup_notifications=function(){this.log("Adding event handler for window focus."),e.addEventListener("focus",this.clear_notifications.bind(this))},t.settings_info.highlight_notifications={type:"boolean",value:!1,visible:function(){return!this.has_bttv},name:"Highlight Notifications",help:"Display notifications when a highlighted word appears in chat in an unfocused tab.",on_update:function(e,t){if(e&&t){if("denied"===Notification.permission)return this.log("Notifications have been denied by the user."),void this.settings.set("highlight_notifications",!1);if("granted"!==Notification.permission){var n=this;Notification.requestPermission(function(e){"denied"===e&&(n.log("Notifications have been denied by the user."),n.settings.set("highlight_notifications",!1))})}}}},t.ws_commands.message=function(e){this.show_mesage(e)},t._notifications={},t._last_notification=0,t.prototype.clear_notifications=function(){for(var e in t._notifications){var n=t._notifications[e];if(n)try{n.close()}catch(i){}}t._notifications={},t._last_notification=0},t.prototype.show_notification=function(e,n,i,s,o,a){var r=Notification.permission;if("denied "===r)return!1;if("granted"===r){n=n||"FrankerFaceZ",s=s||1e4;var l={lang:"en-US",dir:"ltr",body:e,tag:i||"FrankerFaceZ",icon:"http://cdn.frankerfacez.com/icon32.png"},c=this,h=new Notification(n,l),u=t._last_notification++;return t._notifications[u]=h,h.addEventListener("click",function(){delete t._notifications[u],o&&o.bind(c)()}),h.addEventListener("close",function(){delete t._notifications[u],a&&a.bind(c)()}),void("number"==typeof s&&h.addEventListener("show",function(){setTimeout(function(){delete t._notifications[u],h.close()},s)}))}var c=this;Notification.requestPermission(function(){c.show_notification(e,n,i)})},t.prototype.show_message=function(t){e.noty({text:t,theme:"ffzTheme",layout:"bottomCenter",closeWith:["button"]}).show()}},{}],22:[function(t){var n=e.FrankerFaceZ,i=t("../utils");n.prototype.setup_races=function(){this.log("Initializing race support."),this.srl_races={}},n.settings_info.srl_races={type:"boolean",value:!0,name:"SRL Race Information",help:'Display information about SpeedRunsLive races under channels.',on_update:function(){this.rebuild_race_ui()}},n.ws_on_close.push(function(){var e=App.__container__.lookup("controller:channel"),t=e.get("id"),n=!1;for(var i in this.srl_races)delete this.srl_races[i],i==t&&(n=!0);n&&this.rebuild_race_ui()}),n.ws_commands.srl_race=function(e){for(var t=App.__container__.lookup("controller:channel"),n=t.get("id"),i=!1,s=0;s',a.addEventListener("click",this.build_race_popup.bind(this)),o.appendChild(a),s.appendChild(o),this._update_race(!0)},n.prototype._race_kill=function(){this._race_timer&&(clearTimeout(this._race_timer),delete this._race_timer),delete this._race_game,delete this._race_goal},n.prototype.build_race_popup=function(){var e=this._popup;if(!e||(e.parentElement.removeChild(e),delete this._popup,this._popup_kill&&this._popup_kill(),delete this._popup_kill,"ffz-race-popup"!=e.id)){var t=document.querySelector("#ffz-ui-race");if(t){var i=t.querySelector(".button"),s=i.offsetLeft+i.offsetWidth,o=t.getAttribute("data-channel"),a=this.srl_races[o],e=document.createElement("div"),r="";e.id="ffz-race-popup",e.className=(s>=300?"right":"left")+" share dropmenu",this._popup_kill=this._race_kill.bind(this),this._popup=e;var l="http://kadgar.net/live",c=!1;for(var h in a.entrants){var u=a.entrants[h].state;a.entrants.hasOwnProperty(h)&&a.entrants[h].channel&&("racing"==u||"entered"==u)&&(l+="/"+a.entrants[h].channel,c=!0)}var d=document.querySelector(".app-main.theatre")?document.body.clientHeight-300:t.parentElement.offsetTop-175,p=App.__container__.lookup("controller:channel"),_=p?p.get("display_name"):n.get_capitalization(o),f=encodeURIComponent("I'm watching "+_+" race "+a.goal+" in "+a.game+" on SpeedRunsLive!");r='