multistream/frontend/static/script.js
File Type: application/javascript
$(document).ready( function() {
/***********
* Setup
*/
var $community_container = 0;
var $followed_container = 0;
var default_live_filter = "*";
var default_community_filter = $("#community-filters button").first().attr("data-filter-value") || ".channel";
var default_sort = ["community", "live", "random"];
var num_streams = 0; //ugh, couldn't quite get rid of this
var layout_timer = false;
/************************
* Index page handlers
*/
if($('#buildlayoutform').length) add_index_event_handlers($('#buildlayoutform'));
/************************
* View Page Handlers
*/
if($('#layoutwrapper').length) {
//Sidebar clicks
$('.edit.sidebar-button').click( function(e) {
e.preventDefault();
if($('#popupform').length) {
$(this).removeClass('selected');
hide_popup_form();
setTimeout(function(){sync_layout();},500);
} else {
$(this).addClass('selected');
show_popup_form();
}
});
$('#sidebar .layoutselector[data-index]').click(function(e) {
sync_layout($(this).attr('data-index'));
if($('#buildlayoutform').length == 0) sync_urls();
});
$('.rotate.sidebar-button').click(function(e) {
e.preventDefault();
if(get_num_streams()>0) {
$('.streamcontainer,.streamoverlay').each(function(){$(this).attr('data-index',(parseInt($(this).attr('data-index'))+1)%get_num_streams());});
sync_urls();
}
});
//In-object clicks
add_object_event_handlers($('.streamoverlay,.chatcontainer'));
//On-First-Load stuff
//Pick a valid layout if one wasn't provided from the url
var url_layout = document.location.href.match(/layout=?([0-9][0-9]?)/i);
if(url_layout) url_layout = url_layout[1];
if(-1 == $.inArray(url_layout, get_valid_layout_indexes()) ) {
sync_layout();
sync_urls();
} else {
sync_layout(url_layout);
}
}
/************
* Functions
*/
function show_popup_form() {
$('#layoutwrapper').addClass('dimmed');
$("<div id=popupoverlay style='display:none'>").insertAfter($('#sidebar .edit.sidebar-button')).click(function(){$('#sidebar .edit.sidebar-button').click();}).fadeIn();
$("<div id=popupform style='display:none'>").load($('#sidebar .edit.sidebar-button').attr('href') + ' #buildlayoutform', function() {
$community_container = 0; //force isotope re-init
$followed_container = 0;
add_index_event_handlers($(this));
add_dummy_streams();
$(this).fadeIn();
}).insertAfter($('#sidebar .edit.sidebar-button'));
}
function hide_popup_form() {
$('#layoutwrapper').removeClass('dimmed');
$('#popupform').fadeOut(function(){$(this).remove();});
$('#popupoverlay').fadeOut(function(){$(this).remove();});
remove_dummy_streams();
}
function add_index_event_handlers($element) {
$('#popupform .ui-tabs-nav').css('cursor','move');
$('#popupform').draggable();
$element.find('button[type="submit"]').click(function(e) {
if($('#sidebar').length) {
e.preventDefault();
sync_objects();
hide_popup_form();
}
});
$element.find('#cancelbutton').click(function(e) {
if($('#sidebar').length) {
e.preventDefault();
$('#sidebar .edit.sidebar-button').click();
}
});
//RECURSION FTW
$element.find('.streamfield').keyup(function() {
if(layout_timer) clearTimeout(layout_timer);
var val = $(this).val()
if(val == "") {
$next_field = $(this).parents('.streamfieldcontainer').next().find('.streamfield');
if($next_field.length && $next_field.val() != '') {
$(this).val($next_field.val());
$next_field.val('').keyup();
}
} else {
val = val.replace(/http[s]?:\/\//i, '');
val = val.replace(/(www.)?twitch\.tv/i, '');
val = val.replace(/[^a-zA-Z0-9-_]/g, '');
$(this).val(val.toLowerCase());
}
$(this).attr('data-tag',$(this).val());
update_selected_channels();
layout_timer = setTimeout(function(){sync_layout();}, 100);
}).bind('paste', function() {
setTimeout(function () {
$(this).keyup();
}, 100);
}).each(function() {
$(this).attr('data-tag',$(this).val());
});
setTimeout(function(){$element.find('.streamfield').filter(function(){return this.value==""}).first().focus();},100);
$element.find('.layoutselector[data-index]').click( function() {
sync_layout( $(this).attr('data-index') );
//this will only be called from object *inside* the form, and those should never change the URL immediately.
//sync_urls();
});
add_channellist_event_handlers($('.channellist'));
$element.find('#clearbutton').click(function(e){
e.preventDefault();
$('.streamfield').each(function(){$(this).val('').attr('data-tag','')});
sync_layout();
update_selected_channels();
});
$element.find('#quickpicks button').click(function(e){
e.preventDefault();
$(this).addClass('selected').siblings().removeClass('selected');
update_filters();
});
//jQueryUI doesn't fire 'tabsactivate' for the first tab. :(
if($('#communities-tab-selector').index() == 0) setTimeout(setup_community, 100);
//if($('#following-tab-selector').index() == 0) setTimeout(setup_following, 100);
$element.find('.tabs').bind('tabsactivate', function(event, ui) {
if($('#communities-tab-selector').index() == ui.newTab.index()) {
setup_community();
}
/*
if($('#following-tab-selector').index() == ui.newTab.index()) {
setup_following();
}
*/
});
$element.find('.tabs').tabs();
if(window.location.hash.substring(0,9) == "#community")
setTimeout(function(){$('#community-tab-selector a').click();}, 100);
if(window.location.hash.substring(0,13) == "#access_token" || window.location.hash.substring(0,10) == "#following")
setTimeout(function(){$('#following-tab-selector a').click();}, 100);
sync_layout();
}
function add_object_event_handlers($element) {
$element.find('button.reloadchat[data-tag]').click( function() {
$('.chatcontainer[data-tag="'+ $(this).attr('data-tag') +'"]').find('iframe').attr( 'src', function ( i, val ) { return val; });
});
$element.find('button.reloadstream[data-tag]').click(function(e) {
e.preventDefault();
$('.streamcontainer[data-tag="'+ $(this).attr('data-tag') +'"]').find('iframe').attr( 'src', function ( i, val ) { return val; });
if($(this).attr('data-tag') == get_current_audio()) {
choose_stream_audio($(this).attr('data-tag'));
}
});
$element.find('.chatmenuopener').click( function() {
$(this).siblings('.chatmenu').slideToggle(150);
});
$element.find('.audiobutton[data-tag]').click(function(e) {
e.preventDefault();
choose_stream_audio($(this).attr('data-tag'));
});
$element.find('.chatbutton[data-tag],[class*=chatselector][data-tag]').click(function(e) {
e.preventDefault();
choose_stream_chat($(this).attr('data-tag'));
});
$element.find('.bothbutton[data-tag]').click(function(e) {
e.preventDefault();
choose_stream_both($(this).attr('data-tag'));
});
$element.find('.closebutton[data-tag]').click(function(e) {
e.preventDefault();
close_stream_and_chat($(this).attr('data-tag'));
reindex_objects();
sync_layout();
sync_urls();
});
}
function add_channellist_event_handlers($element) {
$element.find('.channel').click(function(){
$(this).toggleClass('selected');
if($(this).hasClass('selected')){
if($('.streamfield').filter(function(){return this.value==""}).length == 0) {
window.alert("Max number of streams already selected!");
$(this).removeClass('selected');
} else {
add_to_form_streams($(this).attr('rel'));
}
} else {
remove_from_form_streams($(this).attr('rel'));
}
});
}
function setup_community() {
if($community_container==0) {
$community_container = $('#communitylist').isotope({
transitionDuration: '0.5s',
itemSelector: '.isosquare',
getSortData: {
name: '.channelname',
live: function( itemElem ) {
return $(itemElem).hasClass('live');
},
community: function( itemElem ) {
return $(itemElem).hasClass('community');
}
},
sortBy: default_sort,
sortAscending: {
name: true,
live: false,
community: false,
},
layoutMode: 'masonry',
masonry: {
columnWidth: '.grid-sizer',
}
});
$community_container.isotope('on','layoutComplete', function( isoInstance, laidOutItems ){
setTimeout(function(){ //wait for animations to finish
update_form_channels();
sync_layout();
},500);
});
var community_filter = document.location.href.match(/\#community\/([a-zA-Z0-9\-\_]+)/i);
if(community_filter) {
if(community_filter[1] == 'all') {
community_filter = "*";
} else {
community_filter = '.community-' + community_filter[1];
}
if($(community_filter).length == 0)
community_filter = default_community_filter;
} else {
community_filter = default_community_filter;
}
$('#community-filters button[data-filter-value="'+ community_filter +'"]').addClass('selected');
$('#live-filters button[data-filter-value="'+ default_live_filter +'"]').addClass('selected');
$('#sort-filters button[data-sort-value="'+ default_sort +'"]').addClass('selected');
//sync_layout();
update_filters();
}
}
function setup_following() {
if($followed_container==0) {
//Check Twitch login status
Twitch.getStatus(function(error, status){
if(status.authenticated) {
$('.twitch-widget.authenticated').show();
$('.twitch-widget.not-authenticated').hide();
Twitch.api({method: 'streams/followed'},
function(error, resp_obj) {
if(error) {
//display an error i guess??
} else {
populate_followed(resp_obj['streams']);
}
});
} else {
$('.twitch-widget.authenticated').hide();
$('.twitch-widget.not-authenticated').show();
$('.connect-twitch').click(function() {
Twitch.login({
redirect_uri: base_url,
popup: false,
scope: ['user_read'],
});
}).css('cursor','pointer');
}
});
} else {
update_form_channels();
}
}
function populate_followed(streams_obj) {
channel_list = '';
if(streams_obj.length < 1) {
channel_list +=
"<div class='notice'>No live streams were found.</div>"
} else {
for(var i=0; i<streams_obj.length; i++) {
channel_list +=
"<div class='channel live' rel='" + streams_obj[i]['channel']['name'] + "'>" +
"<div class=channelimage style='background-image: url(\"" + streams_obj[i]['preview']['medium'] + "\");'>" +
"<div class=channelcaption>" +
"<div class=channelname>" + streams_obj[i]['channel']['name'] + "</div>" +
(streams_obj[i]['game'] ? "<div class=game>" + streams_obj[i]['game'] + "</div>" : "") +
"</div>" +
"</div>" +
"</div>";
}
}
$followed_container = $('#followedlist').html(channel_list);
add_channellist_event_handlers($followed_container);
update_form_channels();
}
function update_filters() {
var live_filter = $('#live-filters button.selected').attr('data-filter-value');
if(!live_filter) live_filter = "*";
var community_filter = $('#community-filters button.selected').attr('data-filter-value') || "*";
var sort_filter = $('#sort-filters button.selected').attr('data-sort-value');
if(!sort_filter) sort_filter = default_sort;
if(community_filter == "*")
var cfilter = live_filter;
else
var cfilter = live_filter + community_filter;
$community_container.isotope({ filter: cfilter, sortBy: sort_filter });
}
function reindex_objects() {
var object_classes = ['streamcontainer', 'streamoverlay', 'chatcontainer', 'chatselector'];
for(class_i in object_classes) {
$objects = $('.' + object_classes[class_i]);
$objects.each(function() {
if($('#buildlayoutform').length) {
new_index = $('.streamfield[data-tag="' + $(this).attr('data-tag') + '"]').attr('data-index');
} else {
if($(this).hasClass('chatselector')) {
new_index = $(this).index();
} else {
new_index = $objects.index($(this));
}
}
$(this).attr('data-index', new_index);
$(this).find('.streamnumber').html(parseInt(new_index) + 1);
});
}
}
function add_to_form_streams(streamname) {
if($('.streamfield').filter(function(){return this.value==streamname}).length == 0) {
$first_empty = $('.streamfield').filter(function(){return this.value==""}).first();
if($first_empty.length > 0) {
$first_empty.val(streamname).attr('data-tag',streamname).keyup();
return true;
} else {
return false;
}
} else {
return false;
}
}
function remove_from_form_streams(streamname) {
$already_selected = $('.streamfield').filter(function(){return this.value==streamname});
$already_selected.val("").attr('data-tag','').keyup();
}
function update_selected_channels() {
$('.channel.selected').each(function(){
channelname = $(this).attr('rel');
if($('.streamfield').filter(function(){return this.value==channelname}).length == 0)
$(this).removeClass('selected');
});
$('.streamfield').each(function(){
$('.channel[rel="' + $(this).val() + '"]:visible').addClass('selected');
});
}
function update_form_channels() {
$('.streamfield').each(function(){$(this).val('').attr('data-tag','');});
$('.streamfield:first').keyup();
$('.channel').removeClass('selected');
$('.channel.live:visible').each(function() {
if(add_to_form_streams($(this).attr('rel')))
$(this).addClass('selected');
});
}
function choose_stream_both(tag) {
if(typeof(tag) === 'undefined') tag = -1;
choose_stream_chat(tag);
choose_stream_audio(tag);
}
function choose_stream_audio(tag) {
if(typeof(tag) === 'undefined') tag = -1;
if(tag == -1) { // -1 = force auto-selection of first available stream
tag = $('.streamcontainer[data-index]:first').attr('data-tag');
}
var $new_str = $('.streamcontainer[data-tag="' + tag + '"]');
var $other_str = $new_str.siblings('.streamcontainer');
var $new_ovr = $('.streamoverlay[data-tag="' + tag + '"]');
var $other_ovr = $new_ovr.siblings('.streamoverlay');
$other_str.removeClass('audio');
$new_str.addClass('audio');
$other_ovr.removeClass('audio');
$new_ovr.addClass('audio');
if(typeof(player_type) === 'undefined') player_type = '';
if(player_type == "twitchold") {
$other_str.find('object,embed').each(function(){
try { $(this)[0].mute(); }
catch(e) {}
});
$new_str.find('object,embed').each(function(){
try { $(this)[0].unmute(); }
catch(e) {}
});
}
if(player_type == "twitch") {
for(key in player_objs) {
if(player_objs[key].getChannel() == tag) {
player_objs[key].setMuted(false);
} else {
player_objs[key].setMuted(true);
}
}
}
}
function choose_stream_chat(tag) {
if(typeof(tag) === 'undefined') tag = -1;
if(tag == -1) { // -1 = force auto-selection of first available stream
tag = $('.streamcontainer[data-index]:first').attr('data-tag');
}
$('.chatcontainer[data-tag="' + tag + '"]').addClass('current');
$('.chatcontainer:not([data-tag="' + tag + '"])').removeClass('current');
$('.streamcontainer[data-tag="' + tag + '"]').addClass('chat');
$('.streamcontainer:not([data-tag="' + tag + '"])').removeClass('chat');
$('.streamoverlay[data-tag="' + tag + '"]').addClass('chat');
$('.streamoverlay:not([data-tag="' + tag + '"])').removeClass('chat');
$('.chatmenu').hide();
}
function sync_layout(index) {
//console.debug('layout');
if(typeof(index) === 'undefined') index = -1;
old_num_streams = num_streams;
num_streams = get_num_streams();
if(index != -1 || num_streams != old_num_streams) {
//index == -1 means auto-select a valid layout
if (index == -1) {
index = get_first_valid_layout_index(num_streams);
}
if(typeof index === 'undefined') index = '';
//Select the correct sidebar and form button and unselect the others
$('.layoutselector[data-index="' + index + '"]').addClass('current');
$('.layoutselector:not([data-index="' + index + '"])').removeClass('current');
$('input[name=layout][data-index="' + index + '"]').attr('checked','checked');
$('input[name=layout]:not([data-index="' + index + '"])').removeAttr('checked');
//Change the layout wrapper's class
$('#layoutwrapper').attr('data-layout-index', index);
//Change the visible layoutgroup
$('.layoutselectors .layoutgroup[data-streams="' + num_streams + '"]').addClass('current');
$('.layoutselectors .layoutgroup:not([data-streams="' + num_streams + '"])').removeClass('current');
}
if(typeof get_current_chat() === "undefined") {
choose_stream_chat();
}
if(typeof get_current_audio() === "undefined") {
choose_stream_audio();
}
if($('#buildlayoutform').length) {
$('.streamcontainer:not(.dummy),.streamoverlay:not(.dummy),.chatcontainer:not(.dummy)')
.filter(function(){
return -1 != $.inArray($(this).attr('data-tag'), get_form_streams())
})
.removeClass('inactive');
$('.streamcontainer:not(.dummy),.streamoverlay:not(.dummy),.chatcontainer:not(.dummy)')
.filter(function(){
return -1 == $.inArray($(this).attr('data-tag'), get_form_streams())
})
.addClass('inactive');
//Hide / show form fields based on how many streams there are
$('.streamfieldcontainer').each( function() {
if ( $(this).index('.streamfieldcontainer') < num_streams + 1 )
$(this).slideDown();
else
$(this).slideUp();
});
//Hide submit button if there are no streams
if(num_streams == 0)
$('#submitbuttoncontainer').slideUp();
else
$('#submitbuttoncontainer').slideDown();
} else {
$('.streamcontainer,.streamoverlay,.chatcontainer').removeClass('inactive');
}
if(num_streams > 1)
$('.sidebar-button.rotate').show();
else
$('.sidebar-button.rotate').hide();
}
function sync_urls() {
//console.debug('urls');
var layout = get_current_layout();
var streams = $('#buildlayoutform').length > 0 ? get_form_streams() : get_current_streams();
new_url = base_url + streams.join("/") + "/layout" + layout + "/";
new_edit_url = base_url + "edit/" + streams.join("/") + "/";
history.replaceState({}, "", new_url);
$('a.edit.sidebar-button').attr('href', new_edit_url);
}
function sync_objects() {
//console.debug('objects');
var form_streams = get_form_streams();
var current_streams = get_current_streams();
var add_streams = $(form_streams).not(current_streams).get();
var remove_streams = $(current_streams).not(form_streams).get();
//Lil' shortcut
if(remove_streams.length == current_streams.length) {
window.location.href = base_url + add_streams.join("/") + '/layout' + get_first_valid_layout_index(add_streams.length) + '/';
return;
}
close_stream_and_chat(remove_streams);
reindex_objects();
add_stream_and_chat(add_streams);
sync_layout();
sync_urls();
}
function get_form_streams() {
var form_streams = [];
$('#buildlayoutform .streamfield').each(function() {
var value = $(this).val();
if(value) form_streams[parseInt($(this).attr('data-index'))] = value;
});
return form_streams;
}
function get_current_streams() {
var current_streams = [];
$('.streamcontainer[data-tag!=""]').each(function() {
current_streams[parseInt($(this).attr('data-index'))] = $(this).attr('data-tag');
});
return current_streams;
}
function getLocation() {
var l = document.createElement("a");
l.href = window.location.href;
return l;
};
function close_stream_and_chat(tags) {
if(!$.isArray(tags)) tags = [tags];
for (var i = 0; i < tags.length; i++) {
$('[data-object-type="stream"][data-tag="' + tags[i] + '"]').remove();
$('[data-object-type="chat"][data-tag="' + tags[i] + '"]').remove();
$('.chatselector[data-tag="' + tags[i] + '"]').remove();
if(player_objs[tags[i]]) delete player_objs[tags[i]];
}
}
function add_stream_and_chat(tags) {
if(!$.isArray(tags)) tags = [tags];
for (i in tags) {
if($('.streamfield[data-tag="' + tags[i] + '"]').length) {
index = $('.streamfield[data-tag="' + tags[i] + '"]').attr('data-index');
} else {
index = parseInt($('.streamcontainer:last').attr('data-index')) + 1;
if(isNaN(index)) index = 0;
}
$.get(base_url + "ms-getobject/type/both/tag/" + tags[i] + "/index/" + index + "/", function(data){
//Copy last chat menu into the new chat object.
$lastchat = $('.chatcontainer:last');
$(data).appendTo('#layoutwrapper');
$thischat = $('.chatcontainer:last');
$thischat.find('.chatmenu').html($lastchat.find('.chatmenu').html());
add_object_event_handlers($thischat);
add_object_event_handlers($('.streamoverlay:last'));
thisindex = $thischat.attr('data-index');
thistag = $thischat.attr('data-tag');
//Add this chat container to all the chat menus
$("<li class='chatselector' data-index='" + thisindex + "' data-tag='" + thistag + "'><span class='chaticon'></span> <span class='streamname'>" + thistag + "</span></li>")
.appendTo($('.chatmenu'))
.click(function(e){
e.preventDefault();
choose_stream_chat($(this).attr('data-tag'));
});
});
}
}
function add_dummy_streams() {
var num_to_add = $('.streamfield').length;
if(num_to_add) {
for(i=0; i < num_to_add ; i++) {
$('<div class="streamcontainer dummy" data-tag="" data-index="' + i + '" data-object-type="stream"></div>' +
'<div class="streamoverlay dummy" data-tag="" data-index="' + i + '" data-object-type="stream">' +
'<div class="overlaypopup dummy"><div class="overlaycaption"><span class="streamnumber">' + (i + 1) + '</span></div></div></div>' +
'<div class="chatcontainer current dummy" data-tag="" data-index="'+ i +'" data-object-type="chat"></div>').appendTo('#layoutwrapper');
}
}
}
function remove_dummy_streams () {
$('.streamcontainer.dummy,.streamoverlay.dummy,.chatcontainer.dummy').remove();
}
function get_num_streams() {
if($('.streamfield').length) {
return $('.streamfield[value!=""]').length;
} else {
return $('.streamcontainer[data-tag!=""]').length;
}
}
function get_first_valid_layout_index(num_streams,chat) {
return get_valid_layout_indexes(num_streams,chat)[0];
}
function get_valid_layout_indexes(num_streams,chat) {
if(typeof(num_streams) === 'undefined')
num_streams = get_num_streams();
if(num_streams === 0)
return [];
else
return Object.keys(layout_groups[num_streams]);
}
function get_current_chat() {
return $('.streamcontainer.chat').first().attr('data-tag');
}
function get_current_audio() {
return $('.streamcontainer.audio').first().attr('data-tag');
}
function get_current_layout() {
return $('.layoutselectors .layoutselector.current').first().attr('data-index');
}
});