Transition channel page away from index.html

This commit is contained in:
calzoneman 2013-05-01 13:39:01 -05:00
parent 7a2f3efcff
commit 3600a3114a
6 changed files with 382 additions and 68 deletions

View File

@ -2,7 +2,7 @@
"author": "Calvin Montgomery", "author": "Calvin Montgomery",
"name": "CyTube", "name": "CyTube",
"description": "Online media synchronizer and chat", "description": "Online media synchronizer and chat",
"version": "1.5.2", "version": "1.5.3",
"repository": { "repository": {
"url": "http://github.com/calzoneman/sync" "url": "http://github.com/calzoneman/sync"
}, },

View File

@ -9,7 +9,7 @@ The above copyright notice and this permission notice shall be included in all c
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
const VERSION = "1.5.2"; const VERSION = "1.5.3";
var fs = require("fs"); var fs = require("fs");
var Logger = require("./logger.js"); var Logger = require("./logger.js");
@ -26,7 +26,7 @@ app.get("/r/:channel(*)", function(req, res, next) {
res.redirect("/" + param); res.redirect("/" + param);
} }
else { else {
res.sendfile(__dirname + "/www/index.html"); res.sendfile(__dirname + "/www/channel.html");
} }
}); });

View File

@ -29,6 +29,7 @@ var VWIDTH = $("#ytapiplayer").parent().css("width").replace("px", "");//670
var VHEIGHT = "377"; var VHEIGHT = "377";
var IGNORED = []; var IGNORED = [];
var KICKED = false; var KICKED = false;
var CHANNEL = "";
var uname = readCookie("sync_uname"); var uname = readCookie("sync_uname");
var session = readCookie("sync_session"); var session = readCookie("sync_session");
@ -46,6 +47,7 @@ var USEROPTS = {
css: readCookie("cytube_css") || "", css: readCookie("cytube_css") || "",
layout: readCookie("cytube_layout") || "default", layout: readCookie("cytube_layout") || "default",
synch: parseBool(readCookie("cytube_synch")) || true, synch: parseBool(readCookie("cytube_synch")) || true,
hidevid: parseBool(readCookie("cytube_hidevid")) || false,
modhat: parseBool(readCookie("cytube_modhat")) || false modhat: parseBool(readCookie("cytube_modhat")) || false
}; };
applyOpts(); applyOpts();
@ -81,60 +83,38 @@ $(window).resize(function() {
$("#ytapiplayer").attr("width", VWIDTH); $("#ytapiplayer").attr("width", VWIDTH);
}); });
var params = {}; // Match URLs of the form http://site.tld/r/channel
if(window.location.search) { var loc = document.location+"";
var parameters = window.location.search.substring(1).split("&"); var m = loc.match(/\/r\/([a-zA-Z0-9]+)$/);
for(var i = 0; i < parameters.length; i++) { if(m) {
var s = parameters[i].split("="); CHANNEL = m[1];
if(s.length != 2)
continue;
params[s[0]] = s[1];
}
} }
else {
if(params["novideo"] != undefined) { var main = $($(".container")[1]);
$("#videodiv").remove(); var container = $("<div/>").addClass("container").insertBefore(main);
} var row = $("<div/>").addClass("row").appendTo(container);
var div = $("<div/>").addClass("span6").appendTo(row);
if(params["channel"] == undefined) { main.css("display", "none");
// Match URLs of the form http://site.tld/r/channel var label = $("<label/>").text("Enter Channel:").appendTo(div);
var loc = document.location+""; var entry = $("<input/>").attr("type", "text").appendTo(div);
var m = loc.match(/\/r\/([a-zA-Z0-9]+)$/); entry.keydown(function(ev) {
if(m) { var host = ""+document.location;
socket.emit("joinChannel", { host = host.replace("http://", "");
name: m[1] host = host.substring(0, host.indexOf("/"));
}); if(ev.keyCode == 13) {
} document.location = "http://" + host + "/r/" + entry.val();
else { socket.emit("joinChannel", {
name: entry.val()
var main = $($(".container")[1]); });
var container = $("<div/>").addClass("container").insertBefore(main); container.remove();
var row = $("<div/>").addClass("row").appendTo(container); main.css("display", "");
var div = $("<div/>").addClass("span6").appendTo(row); }
main.css("display", "none"); });
var label = $("<label/>").text("Enter Channel:").appendTo(div);
var entry = $("<input/>").attr("type", "text").appendTo(div);
entry.keydown(function(ev) {
if(ev.keyCode == 13) { document.location = document.location + "?channel=" + entry.val();
socket.emit("joinChannel", {
name: entry.val()
});
container.remove();
main.css("display", "");
}
});
}
}
else if(!params["channel"].match(/^[a-zA-Z0-9]+$/)) {
$("<div/>").addClass("alert alert-error")
.insertAfter($(".row")[0])[0]
.innerHTML = "<h3>Invalid Channel Name</h3><p>Channel names must conain only numbers and letters</p>";
} }
socket.on("connect", function() { socket.on("connect", function() {
socket.emit("joinChannel", { socket.emit("joinChannel", {
name: params["channel"] name: CHANNEL
}); });
if(uname && session) { if(uname && session) {
socket.emit("login", { socket.emit("login", {
@ -146,7 +126,6 @@ socket.on("connect", function() {
.text("Connected") .text("Connected")
.appendTo($("#messagebuffer")); .appendTo($("#messagebuffer"));
$("#messagebuffer").scrollTop($("#messagebuffer").prop("scrollHeight")); $("#messagebuffer").scrollTop($("#messagebuffer").prop("scrollHeight"));
setTimeout(function() { $("#reconnect_box").remove(); }, 3000);
}); });

View File

@ -193,7 +193,7 @@ function formatChatMessage(data) {
if(uname) { if(uname) {
if(data.msg.toUpperCase().indexOf(uname.toUpperCase()) != -1) { if(data.msg.toUpperCase().indexOf(uname.toUpperCase()) != -1) {
div.addClass("nick-highlight"); div.addClass("nick-highlight");
if(!FOCUSED) { if(!FOCUSED && !TITLE_BLINK) {
TITLE_BLINK = setInterval(function() { TITLE_BLINK = setInterval(function() {
if(document.title == "*Chat*") if(document.title == "*Chat*")
document.title = PAGETITLE; document.title = PAGETITLE;
@ -841,6 +841,7 @@ function handleRankChange() {
function onWindowFocus() { function onWindowFocus() {
clearInterval(TITLE_BLINK); clearInterval(TITLE_BLINK);
TITLE_BLINK = false;
document.title = PAGETITLE; document.title = PAGETITLE;
} }
@ -1048,6 +1049,12 @@ function showUserOpts() {
synch.prop("checked", USEROPTS.synch); synch.prop("checked", USEROPTS.synch);
addOption("Synch", synchcontainer); addOption("Synch", synchcontainer);
var vidcontainer = $("<label/>").addClass("checkbox")
.text("Hide Video");
var hidevid = $("<input/>").attr("type", "checkbox").appendTo(vidcontainer);
hidevid.prop("checked", USEROPTS.hidevid);
addOption("Hide Video", vidcontainer);
if(RANK >= Rank.Moderator) { if(RANK >= Rank.Moderator) {
$("<hr>").appendTo(form); $("<hr>").appendTo(form);
var modhatcontainer = $("<label/>").addClass("checkbox") var modhatcontainer = $("<label/>").addClass("checkbox")
@ -1067,6 +1074,7 @@ function showUserOpts() {
USEROPTS.css = usercss.val(); USEROPTS.css = usercss.val();
USEROPTS.layout = layoutselect.val(); USEROPTS.layout = layoutselect.val();
USEROPTS.synch = synch.prop("checked"); USEROPTS.synch = synch.prop("checked");
USEROPTS.hidevid= hidevid.prop("checked");
if(RANK >= Rank.Moderator) { if(RANK >= Rank.Moderator) {
USEROPTS.modhat = modhat.prop("checked"); USEROPTS.modhat = modhat.prop("checked");
} }
@ -1123,4 +1131,8 @@ function applyOpts() {
default: default:
break; break;
} }
if(USEROPTS.hidevid) {
$("#videodiv").remove();
}
} }

300
www/channel.html Normal file
View File

@ -0,0 +1,300 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>CyTube</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="">
<meta name="author" content="Calvin 'calzoneman' Montgomery">
<link href="./assets/css/bootstrap.css" rel="stylesheet">
<link href="./assets/css/ytsync.css" rel="stylesheet">
<style>
body {
padding-top: 60px; /* 60px to make the container go all the way to the bottom of the topbar */
}
</style>
<link href="./assets/css/bootstrap-responsive.css" rel="stylesheet">
</head>
<body>
<div class="wrapper">
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<a class="brand" href="index.html">CyTube</a>
<div class="">
<ul class="nav">
<li class="active"><a href="index.html">Home</a></li>
<li><a href="help.html">Help</a></li>
<li><a href="javascript:void(0)" id="optlink">Options</a></li>
</ul>
<div class="navbar-form pull-right" id="loginform">
<input type="text" id="guestname" placeholder="Name">
<button class="btn" id="guestlogin">Guest Login</button>
<button class="btn" id="login">Login/Register</button>
</div>
<div class="navbar-form pull-right" id="logoutform" style="display: none;">
<button class="btn" id="logout">Logout</button>
</div>
</div>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div id="loggedin" class="span6" style="display: none;">
<h3 id="welcome"></h3>
</div>
</div>
<div class="row" id="motdrow">
<div class="span10 offset1 well">
<p id="motd"></p>
</div>
<div class="span12 drinkbar">
<h1 id="drinkcount"></h1>
</div>
</div>
<div class="row" id="main" style="margin-top: 20px;">
<div class="span5" id="chatdiv">
<p id="usercount"></p>
<div id="userlist">
</div>
<div id="messagebuffer">
</div>
<input type="text" id="chatline" class="span5">
</div>
<div class="span7" id="videodiv">
<p id="currenttitle">Currently Playing: </p>
<div id="ytapiplayer">
</div>
</div>
</div>
<div class="row" id="queuerow">
<div class="span5">
<div class="row-fluid">
<div class="span12" id="pollcontainer">
</div>
<div class="span7" style="margin-left: 0;">
<input type="text" id="library_query" class="input-block-level" placeholder="Search Query">
</div>
<div class="span5 btn-group">
<button class="btn" id="library_search">Library</button>
<button class="btn" id="youtube_search">YouTube</button>
</div>
<div class="span12" style="margin-left: 0;">
<ul id="library" class="videolist">
</ul>
</div>
</div>
</div>
<div class="span7" id="queuediv">
<div class="row-fluid" id="qclear">
<div class="span12"></div>
</div>
<div id="playlist_controls"style="display: none;">
<div class="row-fluid">
<div class="span8">
<input type="text" id="mediaurl" class="input-block-level" placeholder="Media URL">
</div>
<div class="span4 btn-group">
<button class="btn" id="queue_next">Next</button>
<button class="btn" id="queue_end">End</button>
</div>
</div>
</div>
<button class="btn btn-block" id="voteskip">Voteskip</button>
<div class="row-fluid">
<ul id="queue" class="span12 videolist">
</ul>
<div class="span12 well well-small" id="plmeta">
<span id="plcount"></span>
<span id="pllength"></span>
<div class="clear: both;"></div>
</div>
<button class="btn btn-danger btn-block" id="qlockbtn" style="display:none;">Unlock Queue</button>
<div class="span12 btn-group" style="margin: 0">
<button class="btn" id="getplaylist" style="width: 100%">Get Playlist URLs</button>
<button class="btn" id="clearplaylist" style="width: 33%; display: none;">Clear Playlist</button>
<button class="btn" id="shuffleplaylist" style="width: 33%; display: none;">Shuffle Playlist</button>
</div>
</div>
</div>
</div>
<div class="row" style="display: none;" id="modnav">
<div class="span12" id="modtabs">
<ul class="nav nav-tabs">
<li class="active">
<a href="javascript:void(0)" id="show_chancontrols">Channel Controls</a>
</li>
<li>
<a href="javascript:void(0)" id="show_banlist">Ban List</a>
</li>
<li>
<a href="javascript:void(0)" id="show_loginlog">Connection Log</a>
</li>
<li>
<a href="javascript:void(0)" id="show_motdeditor">MOTD</a>
</li>
<li>
<a href="javascript:void(0)" id="show_filtereditor">Chat Filters</a>
</li>
<li>
<a href="javascript:void(0)" id="show_acl">Channel Ranks</a>
</li>
</ul>
</div>
</div>
<div class="row modonly" style="display: none" id="chancontrols">
<div class="span12">
<form action="javascript:void(0)">
<fieldset>
<div class="span5">
<label>When the queue is open:</label>
<label class="checkbox">
<input type="checkbox" id="opt_qopen_allow_qnext">
Allow anyone to Queue Next
</label>
<label class="checkbox">
<input type="checkbox" id="opt_qopen_allow_move">
Allow anyone to move videos
</label>
<label class="checkbox">
<input type="checkbox" id="opt_qopen_allow_delete">
Allow anyone to delete videos
</label>
<label class="checkbox">
<input type="checkbox" id="opt_qopen_allow_playnext">
Allow anyone to jump to a video
</label>
</div>
<div class="span5">
<label>Page Title
<input type="text" id="opt_pagetitle" placeholder="Sync" class="pull-right">
</label>
<br>
<label>Custom CSS
<input type="text" id="opt_customcss" class="pull-right">
</label>
<br>
<label>Custom JS<sup class="text-warning">BETA</sup>
<input type="text" id="opt_customjs" class="pull-right">
</label>
<br>
<label class="checkbox">
<input type="checkbox" id="opt_allow_voteskip">
Allow voteskip
</label>
<br>
<label>Voteskip Ratio
<input type="text" id="opt_voteskip_ratio" class="pull-right">
</label>
<br>
<label class="checkbox">
<input type="checkbox" id="opt_chat_antiflood">
Prevent chat flood
</label>
</div>
<div class="span10">
<button class="btn btn-primary" id="opt_submit">Save</button>
</div>
</fieldset>
</form>
</div>
</div>
<div class="row modonly" id="banlist" style="display: none;">
<div class="span12">
<table class="table table-striped">
<thead>
<th></th>
<th>IP</th>
<th>Name</th>
<th>Banned By</th>
</thead>
</table>
</div>
</div>
<div class="row modonly" id="loginlog" style="display: none;">
<div class="span12">
<table class="table table-striped">
<thead>
<th></th>
<th>IP</th>
<th>Names</th>
</thead>
</table>
</div>
</div>
<div class="row modonly" id="motdeditor" style="display: none;">
<div class="span12">
<textarea rows="10" id="motdtext"></textarea>
<button class="btn btn-primary" id="updatemotd">Update</button>
</div>
</div>
<div class="row modonly" id="filtereditor" style="display: none;">
<div class="span12">
<table class="table table-striped">
<thead>
<th></th>
<th>Name</th>
<th>Regex</th>
<th>Flags</th>
<th>Replacement</th>
<th>Active</th>
</thead>
</table>
</div>
<div class="span12">
<p>Multiple filters can be added at once below. They should contain 3-4 fields separated by whitespace: (name) regex flags replacement.<br>If any field contains whitespace, it must be escaped by a backslash, for example "what\ a\ story\ mark"</p>
<textarea rows="10" class="input-block-level" id="multifiltereditor"></textarea>
<button class="btn btn-primary" id="multifilter">Update Multiple</button>
</div>
</div>
<div class="row modonly" id="channelranks" style="display: none;">
<div class="span12">
<table class="table table-striped">
<thead>
<th>Name</th>
<th>Rank</th>
<th>Control</th>
</thead>
</table>
</div>
</div>
</div> <!-- /container -->
<div class="push"></div>
<div id="sitefooter">
</div>
</div>
<div id="footer">
<p class="muted">
CyTube Software Copyright &copy; 2013 Calvin Montgomery&nbsp;&middot;&nbsp;Available for free on <a href="http://github.com/calzoneman/sync">GitHub</a>&nbsp;&middot;
<a href="https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=5Y7PUVVGVSEWG&lc=US&item_name=CyTube&currency_code=USD&bn=PP%2dDonationsBF%3abtn_donate_SM%2egif%3aNonHosted">Donate</a>
</p>
</div>
<!-- APIs -->
<script src="http://api.dmcdn.net/all.js"></script>
<script src="http://jwpsrv.com/library/QouFCLBMEeKC+CIACpYGxA.js"></script>
<script src="./assets/js/sc.js"></script>
<script src="./assets/js/froogaloop.min.js"></script>
<script src="./assets/js/swf.js"></script>
<!-- Third party -->
<script src="./assets/js/jquery.js"></script>
<script src="./assets/js/bootstrap.js"></script>
<script src="./assets/js/bootstrap-transition.js"></script>
<script src="./assets/js/bootstrap-modal.js"></script>
<script src="./socket.io/socket.io.js"></script>
<!-- My Javascript -->
<script src="./assets/js/functions.js"></script>
<script src="./assets/js/callbacks.js"></script>
<script src="./assets/js/iourl.js"></script>
<script src="./assets/js/media.js"></script>
<script src="./assets/js/client.js"></script>
</body>
</html>

View File

@ -277,24 +277,47 @@
</div> </div>
<!-- APIs -->
<script src="http://api.dmcdn.net/all.js"></script>
<script src="http://jwpsrv.com/library/QouFCLBMEeKC+CIACpYGxA.js"></script>
<script src="./assets/js/sc.js"></script>
<script src="./assets/js/froogaloop.min.js"></script>
<script src="./assets/js/swf.js"></script>
<!-- Third party --> <!-- Third party -->
<script src="./assets/js/jquery.js"></script>
<script src="./assets/js/bootstrap.js"></script> <script src="./assets/js/bootstrap.js"></script>
<script src="./assets/js/bootstrap-transition.js"></script> <script src="./assets/js/bootstrap-transition.js"></script>
<script src="./assets/js/bootstrap-modal.js"></script> <script src="./assets/js/bootstrap-modal.js"></script>
<script src="./socket.io/socket.io.js"></script> <!-- Mine -->
<!-- My Javascript --> <script src="./assets/js/jquery.js"></script>
<script src="./assets/js/functions.js"></script> <script type="text/javascript">
<script src="./assets/js/callbacks.js"></script> var params = {};
<script src="./assets/js/iourl.js"></script> if(window.location.search) {
<script src="./assets/js/media.js"></script> var parameters = window.location.search.substring(1).split("&");
<script src="./assets/js/client.js"></script> for(var i = 0; i < parameters.length; i++) {
var s = parameters[i].split("=");
if(s.length != 2)
continue;
params[s[0]] = s[1];
}
}
if(params["channel"] && params["channel"].match(/^[a-zA-Z0-9]+$/)) {
var host = ""+document.location;
host = host.replace("http://", "");
host = host.substring(0, host.indexOf("/"));
document.location = "http://" + host + "/r/" + params["channel"];
}
else {
var main = $($(".container")[1]);
var container = $("<div/>").addClass("container").insertBefore(main);
var row = $("<div/>").addClass("row").appendTo(container);
var div = $("<div/>").addClass("span6").appendTo(row);
main.css("display", "none");
var label = $("<label/>").text("Enter Channel:").appendTo(div);
var entry = $("<input/>").attr("type", "text").appendTo(div);
entry.keydown(function(ev) {
var host = ""+document.location;
host = host.replace("http://", "");
host = host.substring(0, host.indexOf("/"));
if(ev.keyCode == 13) {
document.location = "http://" + host + "/r/" + entry.val();
}
});
}
</script>
</body> </body>
</html> </html>