diff --git a/lib/assets/app.js b/lib/assets/app.js new file mode 100644 index 0000000..69f092c --- /dev/null +++ b/lib/assets/app.js @@ -0,0 +1,137 @@ +var App = (function() { + + /** + * @type {Object} + * @private + */ + var _socket; + + /** + * @type {HTMLElement} + * @private + */ + var _logContainer; + + /** + * @type {HTMLElement} + * @private + */ + var _filterInput; + + /** + * @type {String} + * @private + */ + var _filterValue = ''; + + /** + * Hide element if doesn't contain filter value + * + * @param {Object} element + * @private + */ + var _filterElement = function(element) { + if (element.textContent.indexOf(_filterValue) === -1) { + element.style.display = 'none'; + } else { + element.style.display = ''; + } + } + + /** + * Filter logs based on _filterValue + * + * @function + * @private + */ + var _filterLogs = function() { + var collection = _logContainer.childNodes; + var i = collection.length; + + if (i == 0) return; + + while (i-=1) { + _filterElement(collection[i-1]); + } + window.scrollTo(0, document.body.scrollHeight); + }; + + /** + * Is page is scrolled to bottom + * + * @return {Boolean} + * @private + */ + var _scrolledBottom = function() { + var currentScroll = document.documentElement.scrollTop || document.body.scrollTop; + var totalHeight = document.body.offsetHeight; + var clientHeight = document.documentElement.clientHeight; + return totalHeight <= currentScroll + clientHeight; + }; + + return { + /** + * Init socket.io communication and log container + * + * @param {Object} opts options + */ + init: function(opts) { + var that = this; + + // socket.io init + _socket = new io.connect(); + _socket + .on('lines', function(lines) { + for (var i = 0; i < lines.length; i+=1) { + that.log(lines[i]); + } + }); + + // Elements + _logContainer = opts.container; + _filterInput = opts.filterInput; + _filterInput.focus(); + + // Filter input bind + _filterInput.addEventListener('keyup', function(e) { + if (e.keyCode === 27) { //esc + this.value = ''; + _filterValue = ''; + } else { + _filterValue = this.value; + } + _filterLogs(); + }); + }, + + /** + * Log data + * + * @param {string} data data to log + */ + log: function(data) { + var wasScrolledBottom = _scrolledBottom(); + var div = document.createElement('div'); + var p = document.createElement('p'); + p.className = 'inner-line'; + p.innerHTML = data; + + div.className = 'line'; + div.addEventListener('click', function() { + if (this.className.indexOf('selected') === -1) { + this.className += ' selected' + } else { + this.className = this.className.replace(/selected/g, ''); + } + }); + + div.appendChild(p); + _filterElement(div); + _logContainer.appendChild(div); + + if (wasScrolledBottom) { + window.scrollTo(0, document.body.scrollHeight); + } + } + } +})(); \ No newline at end of file diff --git a/lib/assets/styles.css b/lib/assets/styles.css new file mode 100644 index 0000000..46ecde5 --- /dev/null +++ b/lib/assets/styles.css @@ -0,0 +1,76 @@ +/* Styles mainly from http://twitter.github.com/bootstrap/ */ +* { + padding: 0; + margin: 0; +} + +body { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 13px; + line-height: 18px; + color: #333; + padding: 45px 0 20px; +} + +.navbar { + background-color: #2C2C2C; + background-image: -webkit-linear-gradient(top, #333, #222); + background-repeat: repeat-x; + box-shadow: rgba(0, 0, 0, 0.246094) 0px 1px 3px 0px, rgba(0, 0, 0, 0.0976563) 0px -1px 0px 0px inset; + position: fixed; + left: 0px; + right: 0px; + top: 0px; + color: #fff; + display: block; + height: 24px; + font-size: 20px; + font-weight: 200; + padding: 8px 50px; +} + +.navbar .query { + background-color: #626262; + border-color: #151515; + border-radius: 14px 14px 14px 14px; + border-style: solid; + border-width: 1px; + box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.098) inset, 0 1px 0 0 rgba(255, 255, 255, 0.15); + color: white; + display: inline-block; + float: right; + font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; + font-size: 13px; + height: 18px; + line-height: 13px; + margin-top: -2px; + padding: 4px 9px; + width: 160px; +} + +.navbar .query:focus, +.navbar .query.focused { + padding: 5px 10px; + color: #333333; + text-shadow: 0 1px 0 #ffffff; + background-color: #ffffff; + border: 0; + -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); + -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); + box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); + outline: 0; +} + +.log { + white-space: pre-wrap; +} + +.log .inner-line { + padding: 0 50px; + margin-left: 96pt; + text-indent: -96pt; +} + +.log .line.selected { + background-color: pink; +} \ No newline at end of file