log.io-push
Version:
based on log.io :Realtime log monitoring in your browser
1,189 lines (934 loc) • 33.9 kB
JavaScript
// Generated by CoffeeScript 1.4.0
/* Log.io Web Client
Listens to server for new log messages, renders them to screen "widgets".
# Usage:
wclient = new WebClient io, host: 'http://localhost:28778'
screen = wclient.createScreen
stream = wclient.logStreams.at 0
node = wclient.logNodes.at 0
screen.addPair stream, node
screen.on 'new_log', (stream, node, level, message) ->
*/
(function() {
var $, ClientApplication, ColorManager, LogControlPanel, LogMessage, LogMessages, LogNode, LogNodes, LogScreen, LogScreenView, LogScreens, LogScreensPanel, LogStatsView, LogStream, LogStreams, MESSAGE_CAP, ObjectControls, ObjectGroupControls, ObjectGroupHeader, ObjectItemControls, WebClient, backbone, colors, io, templates, _, _LogObject, _LogObjects,
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
__slice = [].slice,
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
if (process.browser) {
$ = require('jquery-browserify');
} else {
$ = eval("require('jquery')");
}
backbone = require('backbone');
backbone.$ = $;
io = require('socket.io-client');
_ = require('underscore');
templates = require('./templates');
MESSAGE_CAP = 5000;
/*
ColorManager acts as a circular queue for color values.
Every new Stream or Node is assigned a color value on instantiation.
*/
ColorManager = (function() {
ColorManager.prototype._max = 20;
function ColorManager(_index) {
this._index = _index != null ? _index : 1;
}
ColorManager.prototype.next = function() {
if (this._index === this._max) {
this._index = 1;
}
return this._index++;
};
return ColorManager;
})();
colors = new ColorManager;
/*
Backbone models are used to represent nodes and streams. When nodes
go offline, their LogNode model is destroyed, along with their
stream assocations.
*/
_LogObject = (function(_super) {
__extends(_LogObject, _super);
_LogObject.prototype.idAttribute = 'name';
_LogObject.prototype._pclass = function() {
return new _LogObjects;
};
_LogObject.prototype.sync = function() {
var args;
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
};
function _LogObject() {
var args;
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
_LogObject.__super__.constructor.apply(this, args);
this.screens = new LogScreens;
this.pairs = this._pclass();
this.color = colors.next();
}
return _LogObject;
})(backbone.Model);
_LogObjects = (function(_super) {
__extends(_LogObjects, _super);
function _LogObjects() {
return _LogObjects.__super__.constructor.apply(this, arguments);
}
_LogObjects.prototype.model = _LogObject;
_LogObjects.prototype.comparator = function(obj) {
return obj.get('name');
};
return _LogObjects;
})(backbone.Collection);
LogStream = (function(_super) {
__extends(LogStream, _super);
function LogStream() {
return LogStream.__super__.constructor.apply(this, arguments);
}
LogStream.prototype._pclass = function() {
return new LogNodes;
};
return LogStream;
})(_LogObject);
LogStreams = (function(_super) {
__extends(LogStreams, _super);
function LogStreams() {
return LogStreams.__super__.constructor.apply(this, arguments);
}
LogStreams.prototype.model = LogStream;
return LogStreams;
})(_LogObjects);
LogNode = (function(_super) {
__extends(LogNode, _super);
function LogNode() {
return LogNode.__super__.constructor.apply(this, arguments);
}
LogNode.prototype._pclass = function() {
return new LogStreams;
};
return LogNode;
})(_LogObject);
LogNodes = (function(_super) {
__extends(LogNodes, _super);
function LogNodes() {
return LogNodes.__super__.constructor.apply(this, arguments);
}
LogNodes.prototype.model = LogNode;
return LogNodes;
})(_LogObjects);
LogMessage = (function(_super) {
var RCLOSE, ROPEN;
__extends(LogMessage, _super);
function LogMessage() {
return LogMessage.__super__.constructor.apply(this, arguments);
}
ROPEN = new RegExp('<', 'ig');
RCLOSE = new RegExp('>', 'ig');
LogMessage.prototype.render_message = function() {
return this.get('message').replace(ROPEN, '<').replace(RCLOSE, '>');
};
return LogMessage;
})(backbone.Model);
LogMessages = (function(_super) {
__extends(LogMessages, _super);
LogMessages.prototype.model = LogMessage;
function LogMessages() {
var args;
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
this._capped = __bind(this._capped, this);
LogMessages.__super__.constructor.apply(this, args);
this.on('add', this._capped);
}
LogMessages.prototype._capped = function() {
if (this.length > MESSAGE_CAP) {
return this.remove(this.at(this.length - MESSAGE_CAP));
}
};
return LogMessages;
})(backbone.Collection);
/*
LogScreen models maintain state for screen widgets in the UI.
When (Stream, Node) pairs are associated with a screen, the pair ID
is stored on the model. It uses pair ID instead of models themselves
in case a node goes offline, and a new LogNode model is created.
*/
LogScreen = (function(_super) {
__extends(LogScreen, _super);
LogScreen.prototype.idAttribute = null;
LogScreen.prototype.defaults = function() {
return {
pairIds: []
};
};
function LogScreen() {
var args;
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
LogScreen.__super__.constructor.apply(this, args);
this.logMessages = new LogMessages;
}
LogScreen.prototype.addPair = function(stream, node) {
var pairIds, pid;
pairIds = this.get('pairIds');
pid = this._pid(stream, node);
if (__indexOf.call(pairIds, pid) < 0) {
pairIds.push(pid);
}
stream.trigger('lwatch', node, this);
node.trigger('lwatch', stream, this);
stream.screens.update(this);
node.screens.update(this);
return this.collection.trigger('addPair');
};
LogScreen.prototype.removePair = function(stream, node) {
var p, pairIds, pid;
pairIds = this.get('pairIds');
pid = this._pid(stream, node);
this.set('pairIds', (function() {
var _i, _len, _results;
_results = [];
for (_i = 0, _len = pairIds.length; _i < _len; _i++) {
p = pairIds[_i];
if (p !== pid) {
_results.push(p);
}
}
return _results;
})());
stream.trigger('lunwatch', node, this);
node.trigger('lunwatch', stream, this);
stream.screens.remove(this);
node.screens.remove(this);
return this.collection.trigger('removePair');
};
LogScreen.prototype.hasPair = function(stream, node) {
var pid;
pid = this._pid(stream, node);
return __indexOf.call(this.get('pairIds'), pid) >= 0;
};
LogScreen.prototype._pid = function(stream, node) {
return "" + stream.id + ":" + node.id;
};
LogScreen.prototype.isActive = function(object, getPair) {
var _this = this;
if (!object.pairs.length) {
return false;
}
return object.pairs.every(function(item) {
var node, stream, _ref;
_ref = getPair(object, item), stream = _ref[0], node = _ref[1];
return _this.hasPair(stream, node);
});
};
return LogScreen;
})(backbone.Model);
LogScreens = (function(_super) {
__extends(LogScreens, _super);
function LogScreens() {
return LogScreens.__super__.constructor.apply(this, arguments);
}
LogScreens.prototype.model = LogScreen;
return LogScreens;
})(backbone.Collection);
/*
WebClient listens for log messages and stream/node announcements
from the server via socket.io. It manipulates state in LogNodes &
LogStreams collections, which triggers view events.
*/
WebClient = (function() {
function WebClient(opts, localStorage) {
var _on,
_this = this;
if (opts == null) {
opts = {
host: '',
secure: false
};
}
this.localStorage = localStorage != null ? localStorage : {};
this._disconnect = __bind(this._disconnect, this);
this._ping = __bind(this._ping, this);
this._newLog = __bind(this._newLog, this);
this._addPair = __bind(this._addPair, this);
this._removeStream = __bind(this._removeStream, this);
this._removeNode = __bind(this._removeNode, this);
this._addStream = __bind(this._addStream, this);
this._addNode = __bind(this._addNode, this);
this._initScreens = __bind(this._initScreens, this);
this.stats = {
nodes: 0,
streams: 0,
messages: 0,
start: new Date().getTime()
};
this.logNodes = new LogNodes;
this.logStreams = new LogStreams;
this.logScreens = new LogScreens;
this.app = new ClientApplication({
logNodes: this.logNodes,
logStreams: this.logStreams,
logScreens: this.logScreens,
webClient: this
});
this.app.render();
this._initScreens();
this.socket = io.connect(opts.host, {
secure: opts.secure
});
_on = function() {
var args, _ref;
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
return (_ref = _this.socket).on.apply(_ref, args);
};
_on('add_node', this._addNode);
_on('add_stream', this._addStream);
_on('remove_node', this._removeNode);
_on('remove_stream', this._removeStream);
_on('add_pair', this._addPair);
_on('new_log', this._newLog);
_on('ping', this._ping);
_on('disconnect', this._disconnect);
}
WebClient.prototype._initScreens = function() {
var screen, screenCache, screens, _i, _len, _results,
_this = this;
this.logScreens.on('add remove addPair removePair', function() {
return _this.localStorage['logScreens'] = JSON.stringify(_this.logScreens.toJSON());
});
screenCache = this.localStorage['logScreens'];
screens = screenCache ? JSON.parse(screenCache) : [
{
name: 'Screen1'
}
];
_results = [];
for (_i = 0, _len = screens.length; _i < _len; _i++) {
screen = screens[_i];
_results.push(this.logScreens.add(new this.logScreens.model(screen)));
}
return _results;
};
WebClient.prototype._addNode = function(node) {
this.logNodes.add(node);
return this.stats.nodes++;
};
WebClient.prototype._addStream = function(stream) {
var _this = this;
this.logStreams.add(stream);
this.stats.streams++;
stream = this.logStreams.get(stream.name);
stream.on('lwatch', function(node, screen) {
return _this.socket.emit('watch', screen._pid(stream, node));
});
return stream.on('lunwatch', function(node, screen) {
return _this.socket.emit('unwatch', screen._pid(stream, node));
});
};
WebClient.prototype._removeNode = function(node) {
var _ref;
if ((_ref = this.logNodes.get(node.name)) != null) {
_ref.destroy();
}
return this.stats.nodes--;
};
WebClient.prototype._removeStream = function(stream) {
var _ref;
if ((_ref = this.logStreams.get(stream.name)) != null) {
_ref.destroy();
}
return this.stats.streams--;
};
WebClient.prototype._addPair = function(p) {
var node, stream;
stream = this.logStreams.get(p.stream);
node = this.logNodes.get(p.node);
stream.pairs.add(node);
node.pairs.add(stream);
return this.logScreens.each(function(screen) {
if (screen.hasPair(stream, node)) {
return screen.addPair(stream, node);
}
});
};
WebClient.prototype._newLog = function(msg) {
var level, message, node, stream;
stream = msg.stream, node = msg.node, level = msg.level, message = msg.message;
stream = this.logStreams.get(stream);
node = this.logNodes.get(node);
return this.logScreens.each(function(screen) {
if (screen.hasPair(stream, node)) {
return screen.trigger('new_log', new LogMessage({
stream: stream,
node: node,
level: level,
message: message
}));
}
});
};
WebClient.prototype._ping = function(msg) {
var node, stream;
stream = msg.stream, node = msg.node;
stream = this.logStreams.get(stream);
node = this.logNodes.get(node);
if (stream) {
stream.trigger('ping', node);
}
if (node) {
node.trigger('ping', stream);
}
return this.stats.messages++;
};
WebClient.prototype._disconnect = function() {
this.logNodes.reset();
this.logStreams.reset();
this.stats.nodes = 0;
return this.stats.streams = 0;
};
WebClient.prototype.createScreen = function(sname) {
var screen;
screen = new LogScreen({
name: sname
});
this.logScreens.add(screen);
return screen;
};
return WebClient;
})();
/*
Backbone views are used to manage the UI components,
including the list of log nodes and screen panels.
# View heirarchy:
ClientApplication
LogControlPanel
ObjectControls
ObjectGroupControls
ObjectItemControls
LogScreenPanel
LogScreenView
LogStatsView
TODO(msmathers): Build templates, fill out render() methods
*/
ClientApplication = (function(_super) {
__extends(ClientApplication, _super);
function ClientApplication() {
this._resize = __bind(this._resize, this);
return ClientApplication.__super__.constructor.apply(this, arguments);
}
ClientApplication.prototype.el = '#web_client';
ClientApplication.prototype.template = _.template(templates.clientApplication);
ClientApplication.prototype.initialize = function(opts) {
this.logNodes = opts.logNodes, this.logStreams = opts.logStreams, this.logScreens = opts.logScreens, this.webClient = opts.webClient;
this.controls = new LogControlPanel({
logNodes: this.logNodes,
logStreams: this.logStreams,
logScreens: this.logScreens
});
this.screens = new LogScreensPanel({
logScreens: this.logScreens,
webClient: this.webClient
});
if (typeof window !== "undefined" && window !== null) {
$(window).resize(this._resize);
}
return this.listenTo(this.logScreens, 'add remove', this._resize);
};
ClientApplication.prototype._resize = function() {
var width;
if (!(typeof window !== "undefined" && window !== null)) {
return;
}
width = $(window).width() - this.$el.find("#log_controls").width();
return this.$el.find("#log_screens").width(width);
};
ClientApplication.prototype.render = function() {
this.$el.html(this.template());
this.$el.append(this.controls.render().el);
this.$el.append(this.screens.render().el);
this._resize();
return this;
};
return ClientApplication;
})(backbone.View);
LogControlPanel = (function(_super) {
__extends(LogControlPanel, _super);
function LogControlPanel() {
this._toggleMode = __bind(this._toggleMode, this);
return LogControlPanel.__super__.constructor.apply(this, arguments);
}
LogControlPanel.prototype.id = 'log_controls';
LogControlPanel.prototype.template = _.template(templates.logControlPanel);
LogControlPanel.prototype.initialize = function(opts) {
this.logNodes = opts.logNodes, this.logStreams = opts.logStreams, this.logScreens = opts.logScreens;
this.streams = new ObjectControls({
objects: this.logStreams,
logScreens: this.logScreens,
getPair: function(object, item) {
return [object, item];
},
id: 'log_control_streams'
});
return this.nodes = new ObjectControls({
objects: this.logNodes,
logScreens: this.logScreens,
getPair: function(object, item) {
return [item, object];
},
id: 'log_control_nodes',
attributes: {
style: 'display: none'
}
});
};
LogControlPanel.prototype.events = {
"click a.select_mode": "_toggleMode"
};
LogControlPanel.prototype._toggleMode = function(e) {
var target, tid;
target = $(e.currentTarget);
target.addClass('active').siblings().removeClass('active');
tid = target.attr('href');
this.$el.find(tid).show().siblings('.object_controls').hide();
return false;
};
LogControlPanel.prototype.render = function() {
this.$el.html(this.template());
this.$el.append(this.streams.render().el);
this.$el.append(this.nodes.render().el);
return this;
};
return LogControlPanel;
})(backbone.View);
ObjectControls = (function(_super) {
__extends(ObjectControls, _super);
function ObjectControls() {
this._resize = __bind(this._resize, this);
this._filter = __bind(this._filter, this);
this._addObject = __bind(this._addObject, this);
return ObjectControls.__super__.constructor.apply(this, arguments);
}
ObjectControls.prototype.className = 'object_controls';
ObjectControls.prototype.template = _.template(templates.objectControls);
ObjectControls.prototype.initialize = function(opts) {
var _this = this;
this.objects = opts.objects, this.getPair = opts.getPair, this.logScreens = opts.logScreens;
this.listenTo(this.objects, 'add', this._addObject);
this.listenTo(this.objects, 'reset', function() {
return _this.render();
});
if (typeof window !== "undefined" && window !== null) {
$(window).resize(this._resize);
}
return this.filter = null;
};
ObjectControls.prototype._addObject = function(obj) {
return this._insertObject(new ObjectGroupControls({
object: obj,
getPair: this.getPair,
logScreens: this.logScreens
}));
};
ObjectControls.prototype._insertObject = function(view) {
var index;
if (this.filter) {
view._filter(this.filter);
}
view.render();
index = this.objects.indexOf(view.object);
if (index > 0) {
return view.$el.insertAfter(this.$el.find("div.groups div.group:eq(" + (index - 1) + ")"));
} else {
return this.$el.find("div.groups").prepend(view.el);
}
};
ObjectControls.prototype._filter = function(e) {
var filter, input;
input = $(e.currentTarget);
filter = input.val();
this.filter = filter ? new RegExp("(" + filter + ")", 'ig') : null;
return this.objects.trigger('ui_filter', this.filter);
};
ObjectControls.prototype._resize = function() {
var height;
if (!(typeof window !== "undefined" && window !== null)) {
return;
}
height = $(window).height();
return this.$el.find(".groups").height(height - 80);
};
ObjectControls.prototype.render = function() {
this.$el.html(this.template({
title: this.id
}));
this.$el.find('.filter').keyup(this._filter);
this._resize();
return this;
};
return ObjectControls;
})(backbone.View);
ObjectGroupControls = (function(_super) {
__extends(ObjectGroupControls, _super);
function ObjectGroupControls() {
this._addItem = __bind(this._addItem, this);
this._filter = __bind(this._filter, this);
return ObjectGroupControls.__super__.constructor.apply(this, arguments);
}
ObjectGroupControls.prototype.className = 'group';
ObjectGroupControls.prototype.template = _.template(templates.objectGroupControls);
ObjectGroupControls.prototype.initialize = function(opts) {
var _this = this;
this.object = opts.object, this.getPair = opts.getPair, this.logScreens = opts.logScreens;
this.object.pairs.each(this._addItem);
this.listenTo(this.object.pairs, 'add', this._addItem);
this.listenTo(this.object, 'destroy', function() {
return _this.remove();
});
this.listenTo(this.object.collection, 'ui_filter', this._filter);
this.header_view = new ObjectGroupHeader({
object: this.object,
getPair: this.getPair,
logScreens: this.logScreens
});
return this.header_view.render();
};
ObjectGroupControls.prototype._filter = function(filter) {
if (filter && !this.object.get('name').match(filter)) {
return this.$el.hide();
} else {
return this.$el.show();
}
};
ObjectGroupControls.prototype._addItem = function(pair) {
return this._insertItem(new ObjectItemControls({
item: pair,
getPair: this.getPair,
object: this.object,
logScreens: this.logScreens
}));
};
ObjectGroupControls.prototype._insertItem = function(view) {
var index;
view.render();
index = this.object.pairs.indexOf(view.item);
if (index > 0) {
return view.$el.insertAfter(this.$el.find("div.items div.item:eq(" + (index - 1) + ")"));
} else {
return this.$el.find("div.items").prepend(view.el);
}
};
ObjectGroupControls.prototype.render = function() {
this.$el.html(this.template);
this.$el.prepend(this.header_view.el);
return this;
};
return ObjectGroupControls;
})(backbone.View);
ObjectGroupHeader = (function(_super) {
__extends(ObjectGroupHeader, _super);
function ObjectGroupHeader() {
this.render = __bind(this.render, this);
this._ping = __bind(this._ping, this);
this._toggleScreen = __bind(this._toggleScreen, this);
return ObjectGroupHeader.__super__.constructor.apply(this, arguments);
}
ObjectGroupHeader.prototype.className = 'header';
ObjectGroupHeader.prototype.template = _.template(templates.objectGroupHeader);
ObjectGroupHeader.prototype.initialize = function(opts) {
var _this = this;
this.object = opts.object, this.getPair = opts.getPair, this.logScreens = opts.logScreens;
this.listenTo(this.logScreens, 'add remove', function() {
return _this.render();
});
this.listenTo(this.object, 'destroy', function() {
return _this.remove();
});
this.listenTo(this.object, 'lwatch lunwatch', function() {
return _this.render();
});
this.listenTo(this.object.collection, 'add', function() {
return _this.render();
});
return this.listenTo(this.object, 'ping', this._ping);
};
ObjectGroupHeader.prototype.events = {
"click input": "_toggleScreen"
};
ObjectGroupHeader.prototype._toggleScreen = function(e) {
var checkbox, screen, screen_id,
_this = this;
checkbox = $(e.currentTarget);
screen_id = checkbox.attr('title').replace(/screen-/ig, '');
screen = this.logScreens.get(screen_id);
return this.object.pairs.forEach(function(item) {
var node, stream, _ref;
_ref = _this.getPair(_this.object, item), stream = _ref[0], node = _ref[1];
if (checkbox.is(':checked')) {
return screen.addPair(stream, node);
} else {
return screen.removePair(stream, node);
}
});
};
ObjectGroupHeader.prototype._ping = function() {
var _this = this;
this.diode.addClass('ping');
return setTimeout((function() {
return _this.diode.removeClass('ping');
}), 20);
};
ObjectGroupHeader.prototype.render = function() {
this.$el.html(this.template({
getPair: this.getPair,
object: this.object,
logScreens: this.logScreens
}));
this.diode = this.$el.find('.diode');
return this;
};
return ObjectGroupHeader;
})(backbone.View);
ObjectItemControls = (function(_super) {
__extends(ObjectItemControls, _super);
function ObjectItemControls() {
this._ping = __bind(this._ping, this);
this._toggleScreen = __bind(this._toggleScreen, this);
return ObjectItemControls.__super__.constructor.apply(this, arguments);
}
ObjectItemControls.prototype.className = 'item';
ObjectItemControls.prototype.template = _.template(templates.objectItemControls);
ObjectItemControls.prototype.initialize = function(opts) {
var _ref,
_this = this;
this.item = opts.item, this.object = opts.object, this.logScreens = opts.logScreens;
_ref = opts.getPair(this.object, this.item), this.stream = _ref[0], this.node = _ref[1];
this.listenTo(this.logScreens, 'add remove', function() {
return _this.render();
});
this.listenTo(this.item, 'destroy', function() {
return _this.remove();
});
this.listenTo(this.stream, 'lwatch lunwatch', function() {
return _this.render();
});
return this.listenTo(this.item, 'ping', this._ping);
};
ObjectItemControls.prototype.events = {
"click input": "_toggleScreen"
};
ObjectItemControls.prototype._toggleScreen = function(e) {
var checkbox, screen, screen_id;
checkbox = $(e.currentTarget);
screen_id = checkbox.attr('title').replace(/screen-/ig, '');
screen = this.logScreens.get(screen_id);
if (checkbox.is(':checked')) {
return screen.addPair(this.stream, this.node);
} else {
return screen.removePair(this.stream, this.node);
}
};
ObjectItemControls.prototype._ping = function(object) {
var _this = this;
if (object === this.object) {
this.diode.addClass('ping');
return setTimeout((function() {
return _this.diode.removeClass('ping');
}), 20);
}
};
ObjectItemControls.prototype.render = function() {
this.$el.html(this.template({
item: this.item,
stream: this.stream,
node: this.node,
logScreens: this.logScreens
}));
this.diode = this.$el.find('.diode');
return this;
};
return ObjectItemControls;
})(backbone.View);
LogScreensPanel = (function(_super) {
__extends(LogScreensPanel, _super);
function LogScreensPanel() {
this._resize = __bind(this._resize, this);
this._addLogScreen = __bind(this._addLogScreen, this);
return LogScreensPanel.__super__.constructor.apply(this, arguments);
}
LogScreensPanel.prototype.template = _.template(templates.logScreensPanel);
LogScreensPanel.prototype.id = 'log_screens';
LogScreensPanel.prototype.initialize = function(opts) {
this.logScreens = opts.logScreens, this.webClient = opts.webClient;
this.listenTo(this.logScreens, 'add', this._addLogScreen);
this.listenTo(this.logScreens, 'add remove', this._resize);
if (typeof window !== "undefined" && window !== null) {
$(window).resize(this._resize);
}
return this.statsView = new LogStatsView({
stats: this.webClient.stats
});
};
LogScreensPanel.prototype.events = {
"click #new_screen_button": "_newScreen"
};
LogScreensPanel.prototype._newScreen = function(e) {
this.logScreens.add(new this.logScreens.model({
name: 'Screen1'
}));
return false;
};
LogScreensPanel.prototype._addLogScreen = function(screen) {
var view;
view = new LogScreenView({
logScreens: this.logScreens,
logScreen: screen
});
this.$el.find("div.log_screens").append(view.render().el);
return false;
};
LogScreensPanel.prototype._resize = function() {
var height, lscreens;
if (!(typeof window !== "undefined" && window !== null)) {
return;
}
lscreens = this.logScreens;
if (lscreens.length) {
height = $(window).height() - this.$el.find("div.status_bar").height() - 10;
return this.$el.find(".log_screen .messages").each(function() {
return $(this).height((height / lscreens.length) - 12);
});
}
};
LogScreensPanel.prototype.render = function() {
this.$el.html(this.template());
this.$el.find('.stats').append(this.statsView.render().el);
this._resize();
return this;
};
return LogScreensPanel;
})(backbone.View);
LogScreenView = (function(_super) {
__extends(LogScreenView, _super);
function LogScreenView() {
this._renderMessages = __bind(this._renderMessages, this);
this._renderNewLog = __bind(this._renderNewLog, this);
this._recordScroll = __bind(this._recordScroll, this);
this._addNewLogMessage = __bind(this._addNewLogMessage, this);
this._filter = __bind(this._filter, this);
this.__filter = __bind(this.__filter, this);
this._clear = __bind(this._clear, this);
this._close = __bind(this._close, this);
return LogScreenView.__super__.constructor.apply(this, arguments);
}
LogScreenView.prototype.className = 'log_screen';
LogScreenView.prototype.template = _.template(templates.logScreenView);
LogScreenView.prototype.logTemplate = _.template(templates.logMessage);
LogScreenView.prototype.initialize = function(opts) {
var _this = this;
this.logScreen = opts.logScreen, this.logScreens = opts.logScreens;
this.listenTo(this.logScreen, 'destroy', function() {
return _this.remove();
});
this.listenTo(this.logScreen, 'new_log', this._addNewLogMessage);
this.forceScroll = true;
return this.filter = null;
};
LogScreenView.prototype.events = {
"click .controls .close": "_close",
"click .controls .clear": "_clear"
};
LogScreenView.prototype._close = function() {
this.logScreen.logMessages.reset();
this.logScreen.destroy();
return false;
};
LogScreenView.prototype._clear = function() {
this.logScreen.logMessages.reset();
this._renderMessages();
return false;
};
LogScreenView.prototype.__filter = function(e) {
var input, wait, _filter_buffer,
_this = this;
input = $(e.currentTarget);
_filter_buffer = input.val();
wait = function() {
if (_filter_buffer === input.val()) {
return _this._filter(_filter_buffer);
}
};
return setTimeout(wait, 350);
};
LogScreenView.prototype._filter = function(filter) {
this.filter = filter ? new RegExp("(" + filter + ")", 'ig') : null;
return this._renderMessages();
};
LogScreenView.prototype._addNewLogMessage = function(lmessage) {
this.logScreen.logMessages.add(lmessage);
return this._renderNewLog(lmessage);
};
LogScreenView.prototype._recordScroll = function(e) {
var msgs;
msgs = this.$el.find('.messages');
return this.forceScroll = (msgs.height() + msgs[0].scrollTop) === msgs[0].scrollHeight;
};
LogScreenView.prototype._renderNewLog = function(lmessage) {
var msg, _msg;
_msg = lmessage.get('message');
msg = lmessage.render_message();
if (this.filter) {
msg = _msg.match(this.filter) ? msg.replace(this.filter, '<span class="highlight">$1</span>') : null;
}
if (msg) {
this.msgs.append(this.logTemplate({
lmessage: lmessage,
msg: msg
}));
if (this.forceScroll) {
return this.$el.find('.messages')[0].scrollTop = this.$el.find('.messages')[0].scrollHeight;
}
}
};
LogScreenView.prototype._renderMessages = function() {
this.msgs.html('');
return this.logScreen.logMessages.forEach(this._renderNewLog);
};
LogScreenView.prototype.render = function() {
this.$el.html(this.template({
logScreens: this.logScreens
}));
this.$el.find('.messages').scroll(this._recordScroll);
this.$el.find('.controls .filter input').keyup(this.__filter);
this.msgs = this.$el.find('.msg');
this._renderMessages();
return this;
};
return LogScreenView;
})(backbone.View);
LogStatsView = (function(_super) {
__extends(LogStatsView, _super);
function LogStatsView() {
return LogStatsView.__super__.constructor.apply(this, arguments);
}
LogStatsView.prototype.template = _.template(templates.logStatsView);
LogStatsView.prototype.className = 'stats';
LogStatsView.prototype.initialize = function(opts) {
var _this = this;
this.stats = opts.stats;
this.rendered = false;
return setInterval((function() {
if (_this.rendered) {
return _this.render();
}
}), 1000);
};
LogStatsView.prototype.render = function() {
this.$el.html(this.template({
stats: this.stats
}));
this.rendered = true;
return this;
};
return LogStatsView;
})(backbone.View);
exports.WebClient = WebClient;
}).call(this);