Implemented views
This commit is contained in:
parent
3fe9022d3e
commit
b1023bf76c
49
app.js
49
app.js
@ -8,6 +8,49 @@ if (argv.port) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Run the server!
|
// Run the server!
|
||||||
var Server =
|
var server = new (require("./lib/server.js"))();
|
||||||
new (require("./lib/server.js"))()
|
server.listen(PORT);
|
||||||
.listen(PORT);
|
|
||||||
|
// Temporary data
|
||||||
|
|
||||||
|
var models = require("./client/js/models.js");
|
||||||
|
|
||||||
|
var network = new models.Network;
|
||||||
|
server.networks.push(network);
|
||||||
|
|
||||||
|
var channel_1 = new models.Channel;
|
||||||
|
var channel_2 = new models.Channel;
|
||||||
|
|
||||||
|
network.channels.push(channel_1);
|
||||||
|
network.channels.push(channel_2);
|
||||||
|
|
||||||
|
network.nick = "user";
|
||||||
|
network.address = "irc.freenode.org";
|
||||||
|
|
||||||
|
channel_1.name = "irc.freenode.org";
|
||||||
|
channel_1.type = "network";
|
||||||
|
|
||||||
|
channel_2.name = "#chan";
|
||||||
|
|
||||||
|
var user_1 = new models.User;
|
||||||
|
var user_2 = new models.User;
|
||||||
|
|
||||||
|
user_1.name = "john";
|
||||||
|
user_2.name = "jane";
|
||||||
|
|
||||||
|
channel_2.users.push(user_1);
|
||||||
|
channel_2.users.push(user_2);
|
||||||
|
|
||||||
|
var message_1 = new models.Message;
|
||||||
|
var message_2 = new models.Message;
|
||||||
|
|
||||||
|
message_1.time = "00:00";
|
||||||
|
message_1.user = "john";
|
||||||
|
message_1.text = "Hi!";
|
||||||
|
|
||||||
|
message_2.time = "00:00";
|
||||||
|
message_2.user = "jane";
|
||||||
|
message_2.text = "Hello!";
|
||||||
|
|
||||||
|
channel_2.messages.push(message_1);
|
||||||
|
channel_2.messages.push(message_2);
|
||||||
|
129
client/css/style.css
Normal file
129
client/css/style.css
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
html,
|
||||||
|
body {
|
||||||
|
font: 12px Consolas, monospace;
|
||||||
|
height: 100%;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
ul,
|
||||||
|
li {
|
||||||
|
list-style: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
font: inherit;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
#sidebar {
|
||||||
|
background: #f0f0f0;
|
||||||
|
border-right: 1px solid #ccc;
|
||||||
|
float: left;
|
||||||
|
height: 100%;
|
||||||
|
line-height: 20px;
|
||||||
|
width: 199px;
|
||||||
|
}
|
||||||
|
#sidebar .channel {
|
||||||
|
clear: both;
|
||||||
|
color: #f00;
|
||||||
|
float: left;
|
||||||
|
margin-left: 20px;
|
||||||
|
}
|
||||||
|
#sidebar .network {
|
||||||
|
color: #000;
|
||||||
|
margin-top: 10px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
#chat {
|
||||||
|
bottom: 0;
|
||||||
|
left: 200px;
|
||||||
|
line-height: 16px;
|
||||||
|
min-width: 400px;
|
||||||
|
overflow: hidden;
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
#chat form {
|
||||||
|
border-top: 1px solid #ccc;
|
||||||
|
bottom: 0;
|
||||||
|
height: 26px;
|
||||||
|
left: 0;
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
#chat form input {
|
||||||
|
border: 0;
|
||||||
|
font: inherit;
|
||||||
|
height: 26px;
|
||||||
|
margin: 0;
|
||||||
|
outline: none;
|
||||||
|
padding: 0 6px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
#chat .channel,
|
||||||
|
#chat .network {
|
||||||
|
background: #fff;
|
||||||
|
height: 100%;
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
#chat .network .users {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
#chat .network .messages {
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
#chat .title {
|
||||||
|
background: #f5f5f5;
|
||||||
|
border-bottom: 1px solid #eee;
|
||||||
|
color: #333;
|
||||||
|
font-size: 18px;
|
||||||
|
height: 36px;
|
||||||
|
line-height: 36px;
|
||||||
|
padding-left: 10px;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
#chat .users {
|
||||||
|
border-left: 1px solid #ccc;
|
||||||
|
float: right;
|
||||||
|
height: 100%;
|
||||||
|
margin-top: 36px;
|
||||||
|
overflow-y: auto;
|
||||||
|
padding-top: 6px;
|
||||||
|
width: 159px;
|
||||||
|
}
|
||||||
|
#chat .users .user {
|
||||||
|
clear: both;
|
||||||
|
color: #f00;
|
||||||
|
float: left;
|
||||||
|
padding: 0px 8px;
|
||||||
|
}
|
||||||
|
#chat .messages {
|
||||||
|
left: 0;
|
||||||
|
overflow-y: auto;
|
||||||
|
padding: 6px 0;
|
||||||
|
position: absolute;
|
||||||
|
right: 160px;
|
||||||
|
top: 36px;
|
||||||
|
z-index: 0;
|
||||||
|
bottom: 26px;
|
||||||
|
}
|
||||||
|
#chat .messages .message {
|
||||||
|
padding: 0 8px;
|
||||||
|
}
|
||||||
|
#chat .messages .time {
|
||||||
|
color: #bbb;
|
||||||
|
}
|
||||||
|
#chat .messages .user {
|
||||||
|
color: #f00;
|
||||||
|
}
|
@ -1,13 +1,66 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html>
|
<html>
|
||||||
<head></head>
|
<head>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="/css/style.css"/>
|
||||||
|
|
||||||
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
Hello, world.
|
<aside id="sidebar"></aside>
|
||||||
|
<div id="chat"></div>
|
||||||
|
|
||||||
|
<script type="text/html" id="networks">
|
||||||
|
{{#networks}}
|
||||||
|
<div class="network">
|
||||||
|
{{#channels}}
|
||||||
|
<div class="channel {{type}}" data-id="{{id}}">
|
||||||
|
{{name}}
|
||||||
|
</div>
|
||||||
|
{{/channels}}
|
||||||
|
</div>
|
||||||
|
{{/networks}}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/html" id="channels">
|
||||||
|
{{#channels}}
|
||||||
|
<div class="window {{type}}" data-id="{{id}}">
|
||||||
|
<h1 class="title">{{name}}</h1>
|
||||||
|
<div class="users">
|
||||||
|
{{> users}}
|
||||||
|
</div>
|
||||||
|
<div class="messages">
|
||||||
|
{{> messages}}
|
||||||
|
</div>
|
||||||
|
<form onSubmit="return false;">
|
||||||
|
<input type="text"/>
|
||||||
|
<input type="submit" style="display: none;"/>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{{/channels}}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/html" id="users">
|
||||||
|
{{#users}}
|
||||||
|
<div class="user" data-id="{{id}}">
|
||||||
|
{{name}}
|
||||||
|
</div>
|
||||||
|
{{/users}}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/html" id="messages">
|
||||||
|
{{#messages}}
|
||||||
|
<div class="message">
|
||||||
|
<span class="time">{{time}}</span>
|
||||||
|
<span class="user">{{user}}</span>
|
||||||
|
{{text}}
|
||||||
|
</div>
|
||||||
|
{{/messages}}
|
||||||
|
</script>
|
||||||
|
|
||||||
<script src="//code.jquery.com/jquery-2.1.0.min.js"></script>
|
|
||||||
<script src="/socket.io/socket.io.js"></script>
|
<script src="/socket.io/socket.io.js"></script>
|
||||||
|
<script src="/js/lib/mustache.min.js"></script>
|
||||||
|
<script src="/js/lib/jquery-2.1.0.min.js"></script>
|
||||||
<script src="/js/models.js"></script>
|
<script src="/js/models.js"></script>
|
||||||
<script src="/js/client.js"></script>
|
<script src="/js/client.js"></script>
|
||||||
|
|
||||||
|
@ -15,13 +15,22 @@ function Client() {
|
|||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of networks.
|
* The sidebar view.
|
||||||
*
|
*
|
||||||
* @type {Array<Network>}
|
* @type {Sidebar}
|
||||||
* @public
|
* @private
|
||||||
*/
|
*/
|
||||||
|
|
||||||
this.networks = [];
|
var sidebar = new views.Sidebar();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The chat view.
|
||||||
|
*
|
||||||
|
* @type {Chat}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
var chat = new views.Chat();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The active socket.
|
* The active socket.
|
||||||
@ -32,18 +41,39 @@ function Client() {
|
|||||||
|
|
||||||
this.socket;
|
this.socket;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of networks.
|
||||||
|
*
|
||||||
|
* @type {Array<Network>}
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
this.networks = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize new socket connections.
|
||||||
|
*
|
||||||
|
* @param {Array<Network>}
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
this.init = function(networks) {
|
||||||
|
this.networks = networks;
|
||||||
|
this.socket.on("event", self.handleEvent);
|
||||||
|
chat.render(this.networks);
|
||||||
|
sidebar.render(this.networks);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connect to the server via WebSockets and start listening
|
* Connect to the server via WebSockets and start listening
|
||||||
* to events sent by the server.
|
* for the `init` event.
|
||||||
*
|
*
|
||||||
* @param {String} host
|
* @param {String} host
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
|
|
||||||
this.connect = function(host) {
|
this.connect = function(host) {
|
||||||
this.socket = io.connect(host)
|
this.socket = io.connect(host).on("init", self.init)
|
||||||
.on("init", function(networks) { self.networks = networks; })
|
|
||||||
.on("event", this.handleEvent);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -57,4 +87,156 @@ function Client() {
|
|||||||
// Debug
|
// Debug
|
||||||
console.log(event);
|
console.log(event);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Views namespace.
|
||||||
|
*
|
||||||
|
* @namespace
|
||||||
|
*/
|
||||||
|
|
||||||
|
var views = {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sidebar view.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
views.Sidebar = function() {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Template container.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
var tpl = {
|
||||||
|
networks: $("#networks").html()
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render the view.
|
||||||
|
*
|
||||||
|
* @param {Array<Network>} networks
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
this.render = function(networks) {
|
||||||
|
$("#sidebar").html(Mustache.render(tpl.networks, {networks: networks}));
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Chat view.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
views.Chat = function() {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Template container.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
var tpl = {
|
||||||
|
channels: $("#channels").html()
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Partial templates.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
var partials = {
|
||||||
|
users: $("#users").html(),
|
||||||
|
messages: $("#messages").html()
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the target element where we will
|
||||||
|
* render the view.
|
||||||
|
*
|
||||||
|
* @type {jQuery.Object}
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
this.element = $("#chat");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render the view.
|
||||||
|
*
|
||||||
|
* @param {Array<Network>} networks
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
this.render = function(networks) {
|
||||||
|
var render = "";
|
||||||
|
networks.forEach(function(n) {
|
||||||
|
render += Mustache.render(tpl.channels, n, partials);
|
||||||
|
});
|
||||||
|
this.element
|
||||||
|
.html(render);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add to view.
|
||||||
|
*
|
||||||
|
* @param {Event} event
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
this.add = function(event) {
|
||||||
|
var render = "";
|
||||||
|
var target = "";
|
||||||
|
|
||||||
|
switch(event.type) {
|
||||||
|
|
||||||
|
case "channel":
|
||||||
|
render = Mustache.render(
|
||||||
|
tpl.channels, {channels: event.data}
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "message":
|
||||||
|
target = ".messages";
|
||||||
|
render = Mustache.render(
|
||||||
|
partials.messages, {messages: event.data}
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "user":
|
||||||
|
target = ".users";
|
||||||
|
render = Mustache.render(
|
||||||
|
partials.users, {users: event.data}
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target == "") {
|
||||||
|
this.element
|
||||||
|
.append(render);
|
||||||
|
} else {
|
||||||
|
this.element
|
||||||
|
.find("[data-id='" + event.target + "'] " + target)
|
||||||
|
.append(render);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove from view.
|
||||||
|
*
|
||||||
|
* @param {Int} id
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
this.remove = function(id) {
|
||||||
|
this.element.find("[data-id='" + id + "']").remove();
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
4
client/js/lib/jquery-2.1.0.min.js
vendored
Normal file
4
client/js/lib/jquery-2.1.0.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
client/js/lib/mustache.min.js
vendored
Normal file
1
client/js/lib/mustache.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -10,6 +10,15 @@
|
|||||||
typeof window === "undefined" ? exports
|
typeof window === "undefined" ? exports
|
||||||
: window.models = {};
|
: window.models = {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use this to create unique identifiers.
|
||||||
|
*
|
||||||
|
* @type {Int}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
var id = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Network model.
|
* Network model.
|
||||||
*
|
*
|
||||||
@ -18,6 +27,15 @@
|
|||||||
|
|
||||||
models.Network = function() {
|
models.Network = function() {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unique identifier.
|
||||||
|
*
|
||||||
|
* @type {Int}
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
this.id = id++;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The network address.
|
* The network address.
|
||||||
*
|
*
|
||||||
@ -36,6 +54,15 @@
|
|||||||
|
|
||||||
this.channels = [];
|
this.channels = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User nickname.
|
||||||
|
*
|
||||||
|
* @type {String}
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
this.nick = "";
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -46,6 +73,15 @@
|
|||||||
|
|
||||||
models.Channel = function() {
|
models.Channel = function() {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unique identifier.
|
||||||
|
*
|
||||||
|
* @type {Int}
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
this.id = id++;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The channel name.
|
* The channel name.
|
||||||
*
|
*
|
||||||
@ -55,6 +91,16 @@
|
|||||||
|
|
||||||
this.name = "";
|
this.name = "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The channel type.
|
||||||
|
* This property should be either `network` or `channel`.
|
||||||
|
*
|
||||||
|
* @type {String}
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
this.type = "channel";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The current channel topic.
|
* The current channel topic.
|
||||||
*
|
*
|
||||||
@ -92,6 +138,15 @@
|
|||||||
|
|
||||||
models.User = function() {
|
models.User = function() {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unique identifier.
|
||||||
|
*
|
||||||
|
* @type {Int}
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
this.id = id++;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The user name.
|
* The user name.
|
||||||
*
|
*
|
||||||
@ -171,11 +226,11 @@
|
|||||||
/**
|
/**
|
||||||
* The target network or channel.
|
* The target network or channel.
|
||||||
*
|
*
|
||||||
* @type {String}
|
* @type {Int|String|Object}
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
|
|
||||||
this.target = undefined;
|
this.target = "";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The data.
|
* The data.
|
||||||
|
@ -30,15 +30,6 @@ function Server() {
|
|||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
/**
|
|
||||||
* List of networks.
|
|
||||||
*
|
|
||||||
* @type {Array<Network>}
|
|
||||||
* @public
|
|
||||||
*/
|
|
||||||
|
|
||||||
this.networks = [];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Active sockets managed by socket.io.
|
* Active sockets managed by socket.io.
|
||||||
*
|
*
|
||||||
@ -48,6 +39,15 @@ function Server() {
|
|||||||
|
|
||||||
this.sockets;
|
this.sockets;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of networks.
|
||||||
|
*
|
||||||
|
* @type {Array<Network>}
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
this.networks = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start the server and listen for connections
|
* Start the server and listen for connections
|
||||||
* on the specified port.
|
* on the specified port.
|
||||||
|
Loading…
Reference in New Issue
Block a user