UNPKG

log.io-push

Version:

based on log.io :Realtime log monitoring in your browser

1,189 lines (934 loc) 33.9 kB
// 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, '&lt;').replace(RCLOSE, '&gt;'); }; 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);