diff --git a/dist/ticker.js b/dist/ticker.js index dd3953f..18257d0 100644 --- a/dist/ticker.js +++ b/dist/ticker.js @@ -1,707 +1,901 @@ -// ticker.js - An on-screen, in-browser, ticker-tape-style logging tool +// ticker.js - on-screen, ticker-tape-style logging tool // Jonathan Brink (function() { - ////////////////////////////////// - // variables global to ticker - - var - aChannels = ['log', 'debug', 'warn', 'error', 'trace'], - oChannels = {}, - - // default settings - oDEFAULTS = { - interval: 300, - logStartTop: 30, - align: 'left', - requireBackTick: true - }, - - // global (to ticker) config - oConfig = { - silentMode: false, - pauseMode: false, - channel: 'log', - adjustmentInterval: 25, - lastTextareaAction: undefined, - logStyle: { - position: "fixed", - color: "black", - "background-color": "#F2F2F2", - padding: "1px", - "z-index": 9998, - top: 0, - left: 0, - 'font-family': "monospace", - 'font-size': "14px", - opacity: 0.85 - } - }, - - // log buffer - aBuffer = [], - - // buffer of logs still-to-be-rendered - aRenderBuffer = [], - - // leave a 1/4 page buffer - iAllowedHeight = window.innerHeight * 1.25, - - // the config settings that are configurable - aConfigurableKeys = [ - 'interval', - 'logStartTop', - 'align', - 'requireBackTick' - ], - - // - keyIsDown = false, - - // - aHelp = [ - '________________________________________________', - 'ticker__________________________________________', - '________________________________________________', - 'Hold_the_backtick_(`)_key_down_to_enter_commands', - '________________________________________________', - 'h_->_help_______________________________________', - 't_->_test_______________________________________', - 'p_->_pause_(freeze_output_toggle)_______________', - 'k_->_kill_(remove_all)__________________________', - 'o_->_output_(show_output_in_textarea_toggle)____', - '0_->_output_all_(show_entire_log_history)_______', - 'd_->_dump_(show_configuration_values)___________', - 'b_->_back-tick_required_to_console_invocation___', - '________________________________________________', - 'up_______->_increase_speed______________________', - 'down_____->_decrease_speed______________________', - 'right____->_move logs right_____________________', - 'left_____->_move logs left______________________', - 'pageup___->_increase_starting_point_____________', - 'pagedown_->_decrease_starting_point_____________', - '________________________________________________', - 'enter_->_save_configuration_in_url______________', - 'c_____->_clear_configuration_in_url_____________', - '________________________________________________', - '________________________________________________', - 'Print_to_the_screen:____________________________', - '__>> console.log("`",_"lorum_ipsum...")_________', - '________________________________________________', - '-', - '-', - '-' - ], - - // - KEYS = { - BackTick: 192, - Enter: 13, - Up: 38, - Down: 40, - Right: 39, - Left: 37, - PageDown: 33, - PageUp: 34, - Tab: 9, - Esc: 27, - A: 65, - B: 66, - O: 79, - "0": 48, - D: 68, - T: 84, - P: 80, - S: 83, - K: 75, - C: 67, - H: 72 - }, - - // - aActionKeys = [ - KEYS.Up, - KEYS.Down, - KEYS.Right, - KEYS.Left, - KEYS.Esc, - KEYS.A, - KEYS.B, - KEYS.D, - KEYS.T, - KEYS.O, - KEYS[0], - KEYS.P, - KEYS.K, - KEYS.C, - KEYS.H, - KEYS.S, - KEYS.PageDown, - KEYS.PageUp, - KEYS.Tab - ]; - - ////////////////////////////////// - // util functions - - // used to iterate over querySelectorAll - // see: https://toddmotto.com/ditch-the-array-foreach-call-nodelist-hack/ - function forEach(array, callback, scope) { - for (var i = 0; i < array.length; i++) { - callback.call(scope, i, array[i]); // passes back stuff we need - } - } - - // - function assignStyle(div, oStyle) { - for (var key in oStyle) { - if (oStyle.hasOwnProperty(key)) { - div.style[key] = oStyle[key]; - } - } - } - - // - function getUrlParamValue(name) { - name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]"); - var regexS = "[\\?&]"+name+"=([^&#]*)", - regex = new RegExp( regexS ), - results = regex.exec(window.location.href); - if( results === null ) { - return null; - } else { - return results[1]; - } - } - - ////////////////////////////////// - // api functions - - // - function config(o) { - for (var sKey in o) { - oConfig[sKey] = o[sKey]; - } - } - - // - function print(text, bOverrideSilentMode, bInternal) { - // TODO: move this so it's still in the buffer - if (oConfig.silentMode === true && !bOverrideSilentMode) { - return; - } - - if (bInternal !== true) { - aBuffer.unshift(text); - } - aRenderBuffer.unshift(text); - flushBuffer(); - } - - // - function nonSavedPrint(text) { - print(text, false, true); - } - - // - function test() { - if (oConfig.pauseMode === true) { - nonSavedPrint('pauseMode'); - return; - } - print('test: ' + new Date(), true); - } - - // - function help() { - oConfig.pauseMode = false; - kill(); - - oConfig.interval = oDEFAULTS.interval; - oConfig.logStartTop = oDEFAULTS.logStartTop; - - for (var i = 0; i < aHelp.length; i++) { - var text = aHelp[i]; - text = text.replace(/\_/g, ' '); - print(text,true); - } - } - - // - function kill() { - oConfig.pauseMode = false; - aRenderBuffer = []; - var aLogNodes = document.querySelectorAll("._ticker"); - forEach(aLogNodes, function(i, oLogNode) { - oLogNode.parentNode.removeChild(oLogNode); + ////////////////////////////////// + // variables global to ticker + + var + aChannels = ['log', 'debug', 'warn', 'error', 'trace'], + oChannels = {}, + + // default settings + oDEFAULTS = { + interval: 300, + logStartTop: 30, + align: 'left', + requireBackTick: true + }, + + // global (to ticker) config + oConfig = { + silentMode: false, + pauseMode: false, + channel: 'log', + adjustmentInterval: 25, + lastTextareaAction: undefined, + sMacro9Code: '// macro 9\r\r', + logStyle: { + position: 'fixed', + color: 'black', + 'background-color': '#F2F2F2', + padding: '1px', + 'z-index': 9998, + top: 0, + left: 0, + 'font-family': 'monospace', + 'font-size': '14px', + opacity: 0.85 + } + }, + + // log buffer + aBuffer = [], + + // buffer of logs still-to-be-rendered + aRenderBuffer = [], + + // macros (0-8) + // (9 stored in oConfig.sMacro9Code) + aMacros = {}, + + // leave a 1/4 page buffer + iAllowedHeight = window.innerHeight * 1.25, + + // the config settings that are configurable + aConfigurableKeys = [ + 'interval', + 'logStartTop', + 'align', + 'requireBackTick' + ], + + // dom id of the "output" textarea + sTextareaId = '_tickerTextarea', + + // whether or not the "`" key is pressed + keyIsDown = false, + + // help string + aHelp = [ + '________________________________________________', + 'ticker__________________________________________', + '________________________________________________', + 'Hold_the_backtick_(`)_key_down_to_enter_commands', + '________________________________________________', + 'h_->_help_______________________________________', + 't_->_test_______________________________________', + 'p_->_pause_(freeze_output_toggle)_______________', + 'k_->_kill_(remove_all)__________________________', + 'o_->_output_(show_output_in_textarea_toggle)____', + '0_->_output_all_(show_entire_log_history)_______', + 'd_->_dump_(show_configuration_values)___________', + 'b_->_back-tick_required_to_console_invocation___', + '________________________________________________', + 'up_______->_increase_speed______________________', + 'down_____->_decrease_speed______________________', + 'right____->_move logs right_____________________', + 'left_____->_move logs left______________________', + 'pageup___->_increase_starting_point_____________', + 'pagedown_->_decrease_starting_point_____________', + '________________________________________________', + 'enter_->_save_configuration_in_url______________', + 'c_____->_clear_configuration_in_url_____________', + '________________________________________________', + '________________________________________________', + 'Print_to_the_screen:____________________________', + '__>> console.log("`", _"lorum_ipsum...")________', + '________________________________________________', + '-', + '-', + '-' + ], + + // keycodes + KEYS = { + Tab: 9, + Enter: 13, + Esc: 27, + PageDown: 33, + PageUp: 34, + Left: 37, + Up: 38, + Right: 39, + Down: 40, + '0': 48, + '1': 49, + '2': 50, + '3': 51, + '4': 52, + '5': 53, + '6': 54, + '7': 55, + '8': 56, + '9': 57, + A: 65, + B: 66, + C: 67, + D: 68, + H: 72, + K: 75, + L: 76, + M: 77, + O: 79, + P: 80, + S: 83, + T: 84, + BackTick: 192 + }, + + // the keys used as commands + // keys that that need to be key toggle friendly + // subset of KEYS + aActionKeys = [ + KEYS.Tab, + KEYS.Esc, + KEYS.PageDown, + KEYS.PageUp, + KEYS.Left, + KEYS.Up, + KEYS.Right, + KEYS.Down, + KEYS['0'], + KEYS['1'], + KEYS['2'], + KEYS['3'], + KEYS['4'], + KEYS['5'], + KEYS['6'], + KEYS['7'], + KEYS['8'], + KEYS['9'], + KEYS.A, + KEYS.B, + KEYS.C, + KEYS.D, + KEYS.H, + KEYS.K, + KEYS.L, + KEYS.M, + KEYS.O, + KEYS.P, + KEYS.S, + KEYS.T + ]; + + ////////////////////////////////// + // util functions + + // used to iterate over querySelectorAll + // see: https://toddmotto.com/ditch-the-array-foreach-call-nodelist-hack/ + function pseudoForEach(array, callback, scope) { + for (var i = 0; i < array.length; i++) { + callback.call(scope, i, array[i]); // passes back stuff we need + } + } + + // overlay div's domelement style object + function assignStyle(div, oStyle) { + for (var key in oStyle) { + if (oStyle.hasOwnProperty(key)) { + div.style[key] = oStyle[key]; + } + } + } + + // return value of url parameter + function getUrlParamValue(name) { + name = name.replace(/[\[]/, '\\\[').replace(/[\]]/, '\\\]'); + var regexS = '[\\?&]'+name+'=([^&#]*)', + regex = new RegExp( regexS ), + results = regex.exec(window.location.href); + if( results === null ) { + return null; + } else { + return results[1]; + } + } + + + ////////////////////////////////// + // api functions + + // overlay object over configuration object + // only an api function...doesn't map to a key + // public+private way of setting configuration properties + function config(o) { + for (var sKey in o) { + oConfig[sKey] = o[sKey]; + } + } + + // "p" api function + // print log div to screen + // bOverrideSilentMode - still print, even if silent mode is on + // bInternal - do not track in aBuffer + function print(text, bOverrideSilentMode, bInternal) { + // TODO: move this so it's still in the buffer + if (oConfig.silentMode === true && !bOverrideSilentMode) { + return; + } + + if (bInternal !== true) { + aBuffer.unshift(text); + } + aRenderBuffer.unshift(text); + _flushBuffer(); + } + + // "t" api function + // print out test log (plus date) + function test() { + if (oConfig.pauseMode === true) { + _nonSavedPrint('pauseMode'); + return; + } + print('test: ' + new Date(), true); + } + + // "h" api function + // show help text on-screen as logs + function help() { + oConfig.pauseMode = false; + kill(); + + oConfig.interval = oDEFAULTS.interval; + oConfig.logStartTop = oDEFAULTS.logStartTop; + + for (var i = 0; i < aHelp.length; i++) { + var text = aHelp[i]; + text = text.replace(/\_/g, ' '); + print(text, true); + } + } + + // "k" api function + // clear render buffer and remove all ticker log dom elements + function kill() { + oConfig.pauseMode = false; + aRenderBuffer = []; + var aLogNodes = document.querySelectorAll('._ticker'); + pseudoForEach(aLogNodes, function(i, oLogNode) { + oLogNode.parentNode.removeChild(oLogNode); + }); + } + + // "p" api function + // toggle pauseMode config prop boolean + function pause() { + if (oConfig.pauseMode) { + print('pause off'); + } else { + print('paused'); + } + oConfig.pauseMode = !oConfig.pauseMode; + } + + // "o" api function + // show log text in the "output textarea" + // param bAll -> whether to show all logs ever, + // or just the current on-screen ones + // default: false + function output(bAll) { + if (bAll === undefined) { + bAll = false; + } + + var sAllOutput=''; + + // get all output + if (bAll === true) { + aBuffer.forEach(function(s) { + sAllOutput += s + '\n'; + }); + } else { + // just show items on screen + var aLogNodes = document.querySelectorAll('._ticker_log'); + if (aLogNodes.length > 0) { + pseudoForEach(aLogNodes, function(i, oLogNode) { + var string = oLogNode.innerHTML.trim(); + string = string.replace(/ /g, ''); + sAllOutput += string + '\n'; }); + } } - // - function pause() { - if (oConfig.pauseMode) { - print("pause off"); - } else { - print("paused"); - } - oConfig.pauseMode = !oConfig.pauseMode; - } - - // - function output(bAll) { - if (bAll === undefined) { - bAll = false; + _toggleTextarea({ + text: sAllOutput, + source: KEYS.O + }); + } + + // "l" (for "log") api function + // api function to show all saved log messages + function outputAll() { + output(true); + } + + // "d" api function + // show configuration properties in output textarea + function dump() { + var s = ''; + aConfigurableKeys.forEach(function(sKey) { + s += (sKey + ': ' + oConfig[sKey]) + '\n'; + }); + s += 'listening to console.' + oConfig.channel + '\n'; + _toggleTextarea({ + text: s, + source: KEYS.D + }); + } + + // "s" api function + // toggle silentMode config prop boolean + function silent() { + if (oConfig.silentMode === true) { + oConfig.silentMode = false; + print('silent mode off'); + } else { + oConfig.silentMode = true; + } + } + + // "up" api function + // decrease delay interval by half the adjustmentInterval + function increaseSpeed(e) { + if (oConfig.pauseMode) { + _nonSavedPrint('pauseMode'); + return; + } + oConfig.interval -= (oConfig.adjustmentInterval/2); + print('speed: ' + oConfig.interval); + } + + // "down" api function + // increase delay interval by adjustmentInterval + function decreaseSpeed(e) { + if (oConfig.pauseMode) { + _nonSavedPrint('pauseMode'); + return; + } + oConfig.interval += oConfig.adjustmentInterval; + print('speed: ' + oConfig.interval); + } + + // "right" api function + // change log container position and alignment of log dom elements + function moveRight(e) { + oConfig.align = 'right'; + _postConfigApply(); + + // move existing logs + var aLogNodes = document.querySelectorAll('._ticker_log'); + pseudoForEach(aLogNodes, function(i, oLogNode) { + oLogNode.style.right = 0; + oLogNode.style.left = 'inherit'; + oLogNode.style['text-align'] = 'right'; + }); + test(); + } + + // "left" api function + // change log container position and alignment of log dom elements + function moveLeft(e) { + oConfig.align = 'left'; + _postConfigApply(); + + // move existing logs + var aLogNodes = document.querySelectorAll('._ticker_log'); + pseudoForEach(aLogNodes, function(i, oLogNode) { + oLogNode.style.left = 0; + oLogNode.style.right = 'inherit'; + oLogNode.style['text-align'] = 'left'; + }); + test(); + } + + // "enter" api function + // update url (window.location) to "save state" + // only use config props that have changed + // geneate url-friendly, json string to use for "_ticker" param + function saveConfig() { + var url = window.location.href; + + function generateConfigString() { + var s = '_ticker={'; + aConfigurableKeys.forEach(function(sKey) { + // don't include if default + if (oDEFAULTS[sKey] !== undefined && + oDEFAULTS[sKey] === oConfig[sKey]) { + return; } - - var sAllOutput=''; - - // get all output - if (bAll === true) { - aBuffer.forEach(function(s) { - sAllOutput += s + "\n"; - }); + s += '%22' + sKey + '%22:'; + if (typeof oConfig[sKey] === 'string') { + s += '%22' + oConfig[sKey] + '%22'; } else { - // just show items on screen - var aLogNodes = document.querySelectorAll("._ticker_log"); - if (aLogNodes.length > 0) { - forEach(aLogNodes, function(i, oLogNode) { - var string = oLogNode.innerHTML.trim(); - string = string.replace(/ /g,''); - sAllOutput += string + "\n"; - }); - } + s += oConfig[sKey]; } - - toggleTextarea(sAllOutput, KEYS.O); - } - - // - function outputAll() { - output(true); - } - - // - function dump() { - var s = ''; - aConfigurableKeys.forEach(function(sKey) { - s += (sKey + ': ' + oConfig[sKey]) + "\n"; - }); - s += "listening to console." + oConfig.channel + "\n"; - toggleTextarea(s, KEYS.D); - } - - // - function silent() { - if (oConfig.silentMode === true) { - oConfig.silentMode = false; - print("silent mode off"); - } else { - oConfig.silentMode = true; + s += ','; + }); + s += '}'; + s = s.replace(/,}/, '}'); + return s; + } + + // first, remove the present ticker url param if present + url = url.replace(/_ticker=({.*})?&?/, ''); + + // add opening "?" if no url params are present + if (url.indexOf('?') === -1) { + url = url + '?1=1'; + } + + // add ticker url param + url = url + '&' + generateConfigString(); + + // cleanup + url = url.replace(/\?1=1&/, '?'); + url = url.replace(/\?&/, '?'); + url = url.replace(/(&&)+/, '&'); + + window.location.replace(url); + } + + // "pageUp" api function + // change starting vertical position (logStartTop) for on-screen logs + function moveUp(e) { + if (oConfig.pauseMode) { + _nonSavedPrint('pauseMode'); + return; + } + kill(); + oConfig.logStartTop += 5; + print('start: ' + oConfig.logStartTop); + } + + // "pageDown" api function + // change starting vertical position (logStartTop) for on-screen logs + function moveDown(e) { + if (oConfig.pauseMode) { + _nonSavedPrint('pauseMode'); + return; + } + kill(); + oConfig.logStartTop -= 5; + print('start: ' + oConfig.logStartTop); + } + + // register (overwrite) macro + // for macros 0-8 + // only an api function...doesn't map to a key + // param iNumToRegister key in aMacros object to write to + // param fn callback functionf + function registerMacro(iNumToRegister, fn) { + if (iNumToRegister === 9) { + console.log('`', 'macro 9 reserved for interactive macro (`m)'); + return; + } + console.log('`', 'registering macro: ' + iNumToRegister); + aMacros[iNumToRegister] = fn; + } + + // "pageDown" api function + // for macro slot 9 + // show a textarea where macro can be edited + // "save" macro when textarea is dismissed + function macroEdit() { + var sDefaultText = oConfig.sMacro9Code; + + _toggleTextarea({ + text: sDefaultText, + source: KEYS.M, + buttons: { + clear: function() { + killTextarea(); + macroEdit(); } - } - - // - function increaseSpeed(e) { - if (oConfig.pauseMode) { - nonSavedPrint('pauseMode'); - return; - } - oConfig.interval -= (oConfig.adjustmentInterval/2); - print("speed: " + oConfig.interval); - } - - // - function decreaseSpeed(e) { - if (oConfig.pauseMode) { - nonSavedPrint('pauseMode'); - return; - } - oConfig.interval += oConfig.adjustmentInterval; - print("speed: " + oConfig.interval); - } - - // - function moveRight(e) { - oConfig.align = 'right'; - postConfigApply(); - - // move existing logs - var aLogNodes = document.querySelectorAll("._ticker_log"); - forEach(aLogNodes, function(i, oLogNode) { - oLogNode.style.right = 0; - oLogNode.style.left = 'inherit'; - oLogNode.style['text-align'] = 'right'; + }, + exit: function(sValue) { + oConfig.sMacro9Code = sValue; + registerMacro(9, function() { + /* jshint ignore:start */ + eval(sValue); + /* jshint ignore:end */ }); - test(); - } - - // - function moveLeft(e) { - oConfig.align = 'left'; - postConfigApply(); - - // move existing logs - var aLogNodes = document.querySelectorAll("._ticker_log"); - forEach(aLogNodes, function(i, oLogNode) { - oLogNode.style.left = 0; - oLogNode.style.right = 'inherit'; - oLogNode.style['text-align'] = 'left'; - }); - test(); - } - - // - function saveConfig() { - var url = window.location.href; - - function generateConfigString() { - var s = "_ticker={"; - aConfigurableKeys.forEach(function(sKey) { - // don't include if default - if (oDEFAULTS[sKey] !== undefined && oDEFAULTS[sKey] === oConfig[sKey]) { - return; - } - s += '%22' + sKey + '%22:'; - if (typeof oConfig[sKey] === 'string') { - s += '%22' + oConfig[sKey] + '%22'; - } else { - s += oConfig[sKey]; - } - s += ','; - }); - s += "}"; - s = s.replace(/,}/,"}"); - return s; - } - - // first, remove the present ticker url param if present - url = url.replace(/_ticker=({.*})?&?/,''); - - // add opening "?" if no url params are present - if (url.indexOf('?') === -1) { - url = url + "?1=1"; - } - - // add ticker url param - url = url + "&" + generateConfigString(); - - // cleanup - url = url.replace(/\?1=1&/,"?"); - url = url.replace(/\?&/,"?"); - url = url.replace(/(&&)+/,"&"); - - window.location.replace(url); - } - - // - function moveUp(e) { - if (oConfig.pauseMode) { - nonSavedPrint('pauseMode'); - return; - } - kill(); - oConfig.logStartTop += 5; - print("start: " + oConfig.logStartTop); - } - - // - function moveDown(e) { - if (oConfig.pauseMode) { - nonSavedPrint('pauseMode'); - return; - } - kill(); - oConfig.logStartTop -= 5; - print("start: " + oConfig.logStartTop); - } - - - ////////////////////////////////// - // domain functions - - // - function startInterval() { - var myFunction = function() { - clearInterval(l_interval); - - if (!oConfig.pauseMode) { - var aLogNodes = document.querySelectorAll("._ticker_log"); - if (aLogNodes.length > 0) { - forEach(aLogNodes, function(iIndex, oLogNode) { - var iCurrentTop = parseInt(getComputedStyle(oLogNode).top, 10); - if (iCurrentTop <= 0) { - oLogNode.parentNode.removeChild(oLogNode); - } else { - oLogNode.style.top = (iCurrentTop - oLogNode.offsetHeight) + "px"; - } - }); - } - } - - l_interval = setInterval(myFunction, oConfig.interval); - }; - var l_interval = setInterval(myFunction, oConfig.interval); - } - - // - function postConfigApply() { - function applyAlign() { - if (oConfig.align === 'right') { - oConfig.logStyle.right = 0; - oConfig.logStyle.left = 'inherit'; - oConfig.logStyle['text-align'] = 'right'; + } + }); + } + + // "0-9" api function + // execute macro + function runMacro(iMacroSlot) { + if (typeof aMacros[iMacroSlot] === 'function') { + console.log('`', 'running macro: ' + iMacroSlot); + aMacros[iMacroSlot](); + } else { + console.log('`', 'macro empty'); + } + } + + // "Tab" api function + // switch to listen to next console channel ("log", "warn", etc) + // order is determined by aChannels + function nextChannel() { + var i = 0, + sCurrentChannel = oConfig.channel; + for (; i < aChannels.length; i++) { + if (aChannels[i] === sCurrentChannel) { + break; + } + } + _listenToChannel(aChannels[(i + 1) % aChannels.length]); + print('listening to ' + oConfig.channel); + } + + // "Esc" api function + // remove textarea dom element + function killTextarea() { + var oTickerTextarea = document.getElementById(sTextareaId); + if (oTickerTextarea) { + oTickerTextarea.parentNode.removeChild(oTickerTextarea); + } + } + + // overwrite config with default settings + // only an api function...doesn't map to a key + function reset() { + // load default config + for (var sKey in oDEFAULTS) { + oConfig[sKey] = oDEFAULTS[sKey]; + } + } + + + ////////////////////////////////// + // domain/private functions + + // print but don't save to aBuffer + // uses "print" function's bInternal parameter + function _nonSavedPrint(text) { + print(text, false, true); + } + + // start timeout loop + // for each iteration of the loop + // update the on-screen position of each log dom element + function _startInterval() { + var myFunction = function() { + clearInterval(l_interval); + + if (!oConfig.pauseMode) { + var aLogNodes = document.querySelectorAll('._ticker_log'); + if (aLogNodes.length > 0) { + pseudoForEach(aLogNodes, function(iIndex, oLogNode) { + var iCurrentTop = parseInt(getComputedStyle(oLogNode).top, 10); + if (iCurrentTop <= 0) { + oLogNode.parentNode.removeChild(oLogNode); } else { - oConfig.logStyle.right = 'inherit'; - oConfig.logStyle.left = 0; - oConfig.logStyle['text-align'] = 'left'; + var sTop = (iCurrentTop - oLogNode.offsetHeight) + 'px'; + oLogNode.style.top = sTop; } + }); } - - applyAlign(); - } - - // - function loadConfigFromUrl() { - var value, o, - sUrlParam = getUrlParamValue('_ticker'); - - if (sUrlParam === null) { - return; - } - - // read config from param - try { - o = JSON.parse(decodeURIComponent(sUrlParam)); - } catch( e ) { - } - - // overlay url config onto global config object - if (typeof o === 'object') { - for (var key in o) { - oConfig[key] = o[key]; - } + } + + l_interval = setInterval(myFunction, oConfig.interval); + }; + var l_interval = setInterval(myFunction, oConfig.interval); + } + + // apply config properties + // used after oConfig is updated + function _postConfigApply() { + function applyAlign() { + if (oConfig.align === 'right') { + oConfig.logStyle.right = 0; + oConfig.logStyle.left = 'inherit'; + oConfig.logStyle['text-align'] = 'right'; + } else { + oConfig.logStyle.right = 'inherit'; + oConfig.logStyle.left = 0; + oConfig.logStyle['text-align'] = 'left'; + } + } + + applyAlign(); + } + + // parse url parameter and populate oConfig + function _loadConfigFromUrl() { + var value, o, + sUrlParam = getUrlParamValue('_ticker'); + + if (sUrlParam === null) { + return; + } + + // read config from param + try { + o = JSON.parse(decodeURIComponent(sUrlParam)); + } catch( e ) { + } + + // overlay url config onto global config object + if (typeof o === 'object') { + for (var key in o) { + oConfig[key] = o[key]; + } + } + } + + // listen for when keys are pressed + // use both keydown and keyup to enable chording + function _setupListeners() { + document.body.addEventListener('keydown', function(e) { + if (keyIsDown === false) { + // catch the ` key + if (e.keyCode === KEYS.BackTick) { + keyIsDown=true; } - } - - function setupListeners() { - document.body.addEventListener("keydown", function(e) { - if (keyIsDown === false) { - // catch the ` key - if (e.keyCode === KEYS.BackTick) { - keyIsDown=true; - } - } - if (keyIsDown !== true) { - return; - } - - e.preventDefault(); - - var actionMap = {}; - - // toggle requireBackTick - actionMap[KEYS.B] = function() { - oConfig.requireBackTick = !!!oConfig.requireBackTick; - print("requireBackTick: " + oConfig.requireBackTick); - }; - - actionMap[KEYS.D] = dump; - actionMap[KEYS.S] = silent; - actionMap[KEYS.T] = test; - actionMap[KEYS.O] = output; - actionMap[KEYS[0]] = outputAll; - actionMap[KEYS.P] = pause; - actionMap[KEYS.K] = kill; - actionMap[KEYS.H] = help; - actionMap[KEYS.Up] = increaseSpeed; - actionMap[KEYS.Down] = decreaseSpeed; - actionMap[KEYS.Right] = moveRight; - actionMap[KEYS.Left] = moveLeft; - actionMap[KEYS.PageDown] = moveDown; - actionMap[KEYS.PageUp] = moveUp; - actionMap[KEYS.Enter] = saveConfig; - actionMap[KEYS.Tab] = nextChannel; - actionMap[KEYS.Esc] = killTextarea; - - if (typeof actionMap[e.keyCode] === "function") { - actionMap[e.keyCode](); - } - }); - - document.body.addEventListener("keyup", function(e) { - if (keyIsDown === true && aActionKeys.indexOf(e.keyCode) === -1) { - keyIsDown=false; - } - }); - } - - function calculateTop() { - var oLastNode = document.querySelector("._ticker_log:last-child"); - if (!oLastNode) { - return oConfig.logStartTop; - } else { - return parseInt(oLastNode.style.top, 10) + (oLastNode.offsetHeight); - } - } - - function renderText(sText) { - var div = document.createElement('div'); - div.className = '_ticker'; - assignStyle(div, oConfig.logStyle); - div.className += ' _ticker_log'; - div.innerHTML = sText; - div.style.top = calculateTop() + "px"; - document.body.appendChild(div); - } - - function flushBuffer() { - while(aRenderBuffer.length > 0 && calculateTop() < iAllowedHeight) { - renderText(aRenderBuffer.pop()); - } - } - - function listenToChannel(sChannel) { - var sCurrentChannel = oConfig.channel; - - // revert current channel - if (sCurrentChannel && typeof oChannels[sCurrentChannel].fnOriginal === 'function') { - console[sCurrentChannel] = oChannels[sCurrentChannel].fnOriginal; - } - - oConfig.channel = sChannel; - - // monkey-patch and chain console function - console[sChannel] = function(firstArg, secondArg) { - var sText = firstArg; - if (firstArg === '`') { - sText = secondArg; - } - - if (oConfig.requireBackTick === false) { - print(sText); - } else if (oConfig.requireBackTick === true && firstArg === '`') { - print(sText); - } else { - oChannels[sChannel].fnOriginal.apply(this, [arguments]); - } + } + if (keyIsDown !== true) { + return; + } + + e.preventDefault(); + + var actionMap = {}; + + // toggle requireBackTick + actionMap[KEYS.B] = function() { + oConfig.requireBackTick = !!!oConfig.requireBackTick; + print('requireBackTick: ' + oConfig.requireBackTick); + }; + + actionMap[KEYS.D] = dump; + actionMap[KEYS.S] = silent; + actionMap[KEYS.T] = test; + actionMap[KEYS.O] = output; + actionMap[KEYS.L] = outputAll; + actionMap[KEYS.P] = pause; + actionMap[KEYS.K] = kill; + actionMap[KEYS.H] = help; + actionMap[KEYS.M] = macroEdit; + actionMap[KEYS.Up] = increaseSpeed; + actionMap[KEYS.Down] = decreaseSpeed; + actionMap[KEYS.Right] = moveRight; + actionMap[KEYS.Left] = moveLeft; + actionMap[KEYS.PageDown] = moveDown; + actionMap[KEYS.PageUp] = moveUp; + actionMap[KEYS.Enter] = saveConfig; + actionMap[KEYS.Tab] = nextChannel; + actionMap[KEYS.Esc] = killTextarea; + + [0,1,2,3,4,5,6,7,8,9].forEach(function(i) { + actionMap[KEYS[i]] = function() { + runMacro(i); }; - } + }); - function nextChannel() { - var i = 0, - sCurrentChannel = oConfig.channel; - for (; i < aChannels.length; i++) { - if (aChannels[i] === sCurrentChannel) { - break; - } - } - listenToChannel(aChannels[(i + 1) % aChannels.length]); - print("listening to " + oConfig.channel); - } - - function renderTextarea(sText) { - var heightOfPage = window.innerHeight; - var widthOfPage = window.innerWidth; - var textareaDiv = document.createElement('div'); - textareaDiv.id = '_tickerTextarea'; - textareaDiv.style.position = "fixed"; - textareaDiv.style.left = 0; - textareaDiv.style.top = 0; - textareaDiv.style["z-index"] = 9999; - textareaDiv.style.width = (widthOfPage/3) + 'px'; - textareaDiv.style.height = (heightOfPage-10) + 'px'; - - var textarea = document.createElement('textarea'); - textarea.style.height = "100%"; - textarea.style.width = "100%"; - textarea.value = sText; - - textareaDiv.appendChild(textarea); - document.body.appendChild(textareaDiv); - } - - function killTextarea() { - var oTickerTextarea = document.getElementById("_tickerTextarea"); - if (oTickerTextarea) { - oTickerTextarea.parentNode.removeChild(oTickerTextarea); - } - } - - function toggleTextarea(s, sSource) { - // if it's a new action, clear slate and render - if (oConfig.lastTextareaAction !== sSource) { - killTextarea(); - } - oConfig.lastTextareaAction = sSource; - - if (document.getElementById("_tickerTextarea")) { - oConfig.pauseMode = false; - killTextarea(); - } else { - oConfig.pauseMode = true; - renderTextarea(s); - } - } - - // overwrite with default settings - function reset() { - // load default config - for (var sKey in oDEFAULTS) { - oConfig[sKey] = oDEFAULTS[sKey]; - } - } - - - ////////////////////////////////// - // execution starts - // until this time, everything in this file has just - // been variable and function declarations + if (typeof actionMap[e.keyCode] === 'function') { + actionMap[e.keyCode](); + } + }); - // fill oChannels object - aChannels.forEach(function(sChannel) { - oChannels[sChannel] = { - fnOriginal: console[sChannel] - }; + document.body.addEventListener('keyup', function(e) { + if (keyIsDown === true && aActionKeys.indexOf(e.keyCode) === -1) { + keyIsDown=false; + } }); + } + + // determine "top" position of last log dom element + function _calculateTop() { + var oLastNode = document.querySelector('._ticker_log:last-child'); + if (!oLastNode) { + return oConfig.logStartTop; + } else { + return parseInt(oLastNode.style.top, 10) + (oLastNode.offsetHeight); + } + } + + // create log dom element + // param sText -> the log text + function _renderText(sText) { + var div = document.createElement('div'); + div.className = '_ticker'; + assignStyle(div, oConfig.logStyle); + div.className += ' _ticker_log'; + div.innerHTML = sText; + div.style.top = _calculateTop() + 'px'; + document.body.appendChild(div); + } + + // if there is on-screen space available + // render as many log dom elements as possible from aRenderBuffer + function _flushBuffer() { + while(aRenderBuffer.length > 0 && _calculateTop() < iAllowedHeight) { + _renderText(aRenderBuffer.pop()); + } + } + + // change config to use sChannel (log, warn, etc) + function _listenToChannel(sChannel) { + var sCurrentChannel = oConfig.channel; + + // revert current channel + if (sCurrentChannel && + typeof oChannels[sCurrentChannel].fnOriginal === 'function') { + console[sCurrentChannel] = oChannels[sCurrentChannel].fnOriginal; + } + + oConfig.channel = sChannel; + + // monkey-patch and chain console function + console[sChannel] = function(firstArg, secondArg) { + var sText = firstArg; + if (firstArg === '`') { + sText = secondArg; + } + + if (oConfig.requireBackTick === false) { + print(sText); + } else if (oConfig.requireBackTick === true && firstArg === '`') { + print(sText); + } else { + oChannels[sChannel].fnOriginal.apply(this, [arguments]); + } + }; + } + + // create textarea container div and textarea + // position, fill with sText, and render + function _renderTextarea(sText) { + var heightOfPage = window.innerHeight; + var widthOfPage = window.innerWidth; + var textareaDiv = document.createElement('div'); + textareaDiv.id = sTextareaId; + textareaDiv.style.position = 'fixed'; + textareaDiv.style.left = 0; + textareaDiv.style.top = 0; + textareaDiv.style['z-index'] = 9999; + textareaDiv.style.width = (widthOfPage/3) + 'px'; + textareaDiv.style.height = (heightOfPage-10) + 'px'; + + var textarea = document.createElement('textarea'); + textarea.style.height = '100%'; + textarea.style.width = '100%'; + textarea.innerHTML = sText; + + textareaDiv.appendChild(textarea); + document.body.appendChild(textareaDiv); + } + + // manage showing/hiding textarea div container + // param o -> customize the textarea div + // keys: + // - text: (string) the text to show in the textarea + // - source: (string) id that identifies the invoking keyboard key + // - buttons: (object) map of buttons, with their labels as keys + // - exit: (fn) callback function when textarea is closed, + // the text inside of the textarea is passed along + function _toggleTextarea(o) { + // if it's a new action, clear slate and render + if (oConfig.lastTextareaAction !== o.source) { + killTextarea(); + } + oConfig.lastTextareaAction = o.source; + + var textareaContainer; + + if (document.getElementById(sTextareaId)) { + oConfig.pauseMode = false; + + if (typeof o.exit === 'function') { + textareaContainer = document.getElementById(sTextareaId); + var textarea = textareaContainer.querySelectorAll('textarea')[0]; + o.exit(textarea.value); + } + killTextarea(); + } else { + oConfig.pauseMode = true; + _renderTextarea(o.text); + textareaContainer = document.getElementById(sTextareaId); + + if (typeof o.buttons === 'object') { + var buttonContainer = document.createElement('div'); + buttonContainer.style.position = 'absolute'; + buttonContainer.style.bottom = 0; + buttonContainer.style.left = 0; + buttonContainer.style.height = '20px'; + buttonContainer.style.borderTopWidth = '1px'; + buttonContainer.style.borderTopStyle = 'solid'; + buttonContainer.style.width = '100%'; + buttonContainer.style.paddingTop = '5px'; + + for (var key in o.buttons) { + if (o.buttons.hasOwnProperty(key)) { + var button = document.createElement('button'); + button.innerHTML = key; + button.onclick = o.buttons[key]; + button.style.float = 'left'; + buttonContainer.appendChild(button); + } + } - reset(); - - loadConfigFromUrl(); - postConfigApply(); - - listenToChannel(oConfig.channel); - - setInterval(function() { - flushBuffer(); - }, 250); - - startInterval(); - setupListeners(); - - // expose api to global namespace - (function() { - var _ticker = {}; - _ticker.config = config; - _ticker.test = test; - _ticker.help = help; - _ticker.kill = kill; - _ticker.silent = silent; - _ticker.pause = pause; - _ticker.output = output; - _ticker.outputAll = outputAll; - _ticker.dump = dump; - _ticker.moveDown = moveDown; - _ticker.moveUp = moveUp; - _ticker.moveLeft = moveLeft; - _ticker.moveRight = moveRight; - _ticker.increaseSpeed = increaseSpeed; - _ticker.decreaseSpeed = decreaseSpeed; - _ticker.nextChannel = nextChannel; - _ticker.reset = reset; - - // private - _ticker._oConfig = oConfig; - - window._ticker = _ticker; - }()); + textareaContainer.appendChild(buttonContainer); + } + } + } + + + ////////////////////////////////// + // execution starts + // until this time, everything in this file + // has just been variable and function declarations + + // fill oChannels object + aChannels.forEach(function(sChannel) { + oChannels[sChannel] = { + fnOriginal: console[sChannel] + }; + }); + + // init config + reset(); + _loadConfigFromUrl(); + _postConfigApply(); + + // start listening to default channel + _listenToChannel(oConfig.channel); + + // keep polling to see if flushing the + // log buffer to screen is possible + setInterval(function() { + _flushBuffer(); + }, 250); + + // start job that "moves the ticker tape" + _startInterval(); + + // listen for keyboard events + _setupListeners(); + + // expose api to global namespace + (function() { + var _ticker = {}; + _ticker.config = config; + _ticker.test = test; + _ticker.help = help; + _ticker.kill = kill; + _ticker.silent = silent; + _ticker.pause = pause; + _ticker.output = output; + _ticker.outputAll = outputAll; + _ticker.dump = dump; + _ticker.moveDown = moveDown; + _ticker.moveUp = moveUp; + _ticker.moveLeft = moveLeft; + _ticker.moveRight = moveRight; + _ticker.increaseSpeed = increaseSpeed; + _ticker.decreaseSpeed = decreaseSpeed; + _ticker.nextChannel = nextChannel; + _ticker.reset = reset; + _ticker.registerMacro = registerMacro; + + // private + _ticker._oConfig = oConfig; + + window._ticker = _ticker; + }()); }()); diff --git a/dist/ticker.min.js b/dist/ticker.min.js index 6e8f498..cf2d940 100644 --- a/dist/ticker.min.js +++ b/dist/ticker.min.js @@ -1,2 +1,2 @@ -/*! ticker Mar-29-2016 */ -!function(){function a(a,b,c){for(var d=0;d0&&a(d,function(a,b){var d=b.innerHTML.trim();d=d.replace(/ /g,""),c+=d+"\n"})}G(c,S.O)}function l(){k(!0)}function m(){var a="";P.forEach(function(b){a+=b+": "+L[b]+"\n"}),a+="listening to console."+L.channel+"\n",G(a,S.D)}function n(){L.silentMode===!0?(L.silentMode=!1,e("silent mode off")):L.silentMode=!0}function o(a){return L.pauseMode?void f("pauseMode"):(L.interval-=L.adjustmentInterval/2,void e("speed: "+L.interval))}function p(a){return L.pauseMode?void f("pauseMode"):(L.interval+=L.adjustmentInterval,void e("speed: "+L.interval))}function q(b){L.align="right",w();var c=document.querySelectorAll("._ticker_log");a(c,function(a,b){b.style.right=0,b.style.left="inherit",b.style["text-align"]="right"}),g()}function r(b){L.align="left",w();var c=document.querySelectorAll("._ticker_log");a(c,function(a,b){b.style.left=0,b.style.right="inherit",b.style["text-align"]="left"}),g()}function s(){function a(){var a="_ticker={";return P.forEach(function(b){void 0!==K[b]&&K[b]===L[b]||(a+="%22"+b+"%22:",a+="string"==typeof L[b]?"%22"+L[b]+"%22":L[b],a+=",")}),a+="}",a=a.replace(/,}/,"}")}var b=window.location.href;b=b.replace(/_ticker=({.*})?&?/,""),-1===b.indexOf("?")&&(b+="?1=1"),b=b+"&"+a(),b=b.replace(/\?1=1&/,"?"),b=b.replace(/\?&/,"?"),b=b.replace(/(&&)+/,"&"),window.location.replace(b)}function t(a){return L.pauseMode?void f("pauseMode"):(i(),L.logStartTop+=5,void e("start: "+L.logStartTop))}function u(a){return L.pauseMode?void f("pauseMode"):(i(),L.logStartTop-=5,void e("start: "+L.logStartTop))}function v(){var b=function(){if(clearInterval(c),!L.pauseMode){var d=document.querySelectorAll("._ticker_log");d.length>0&&a(d,function(a,b){var c=parseInt(getComputedStyle(b).top,10);0>=c?b.parentNode.removeChild(b):b.style.top=c-b.offsetHeight+"px"})}c=setInterval(b,L.interval)},c=setInterval(b,L.interval)}function w(){function a(){"right"===L.align?(L.logStyle.right=0,L.logStyle.left="inherit",L.logStyle["text-align"]="right"):(L.logStyle.right="inherit",L.logStyle.left=0,L.logStyle["text-align"]="left")}a()}function x(){var a,b=c("_ticker");if(null!==b){try{a=JSON.parse(decodeURIComponent(b))}catch(d){}if("object"==typeof a)for(var e in a)L[e]=a[e]}}function y(){document.body.addEventListener("keydown",function(a){if(Q===!1&&a.keyCode===S.BackTick&&(Q=!0),Q===!0){a.preventDefault();var b={};b[S.B]=function(){L.requireBackTick=!L.requireBackTick,e("requireBackTick: "+L.requireBackTick)},b[S.D]=m,b[S.S]=n,b[S.T]=g,b[S.O]=k,b[S[0]]=l,b[S.P]=j,b[S.K]=i,b[S.H]=h,b[S.Up]=o,b[S.Down]=p,b[S.Right]=q,b[S.Left]=r,b[S.PageDown]=u,b[S.PageUp]=t,b[S.Enter]=s,b[S.Tab]=D,b[S.Esc]=F,"function"==typeof b[a.keyCode]&&b[a.keyCode]()}}),document.body.addEventListener("keyup",function(a){Q===!0&&-1===T.indexOf(a.keyCode)&&(Q=!1)})}function z(){var a=document.querySelector("._ticker_log:last-child");return a?parseInt(a.style.top,10)+a.offsetHeight:L.logStartTop}function A(a){var c=document.createElement("div");c.className="_ticker",b(c,L.logStyle),c.className+=" _ticker_log",c.innerHTML=a,c.style.top=z()+"px",document.body.appendChild(c)}function B(){for(;N.length>0&&z()_help_______________________________________","t_->_test_______________________________________","p_->_pause_(freeze_output_toggle)_______________","k_->_kill_(remove_all)__________________________","o_->_output_(show_output_in_textarea_toggle)____","0_->_output_all_(show_entire_log_history)_______","d_->_dump_(show_configuration_values)___________","b_->_back-tick_required_to_console_invocation___","________________________________________________","up_______->_increase_speed______________________","down_____->_decrease_speed______________________","right____->_move logs right_____________________","left_____->_move logs left______________________","pageup___->_increase_starting_point_____________","pagedown_->_decrease_starting_point_____________","________________________________________________","enter_->_save_configuration_in_url______________","c_____->_clear_configuration_in_url_____________","________________________________________________","________________________________________________","Print_to_the_screen:____________________________",'__>> console.log("`",_"lorum_ipsum...")_________',"________________________________________________","-","-","-"],S={BackTick:192,Enter:13,Up:38,Down:40,Right:39,Left:37,PageDown:33,PageUp:34,Tab:9,Esc:27,A:65,B:66,O:79,0:48,D:68,T:84,P:80,S:83,K:75,C:67,H:72},T=[S.Up,S.Down,S.Right,S.Left,S.Esc,S.A,S.B,S.D,S.T,S.O,S[0],S.P,S.K,S.C,S.H,S.S,S.PageDown,S.PageUp,S.Tab];I.forEach(function(a){J[a]={fnOriginal:console[a]}}),H(),x(),w(),C(L.channel),setInterval(function(){B()},250),v(),y(),function(){var a={};a.config=d,a.test=g,a.help=h,a.kill=i,a.silent=n,a.pause=j,a.output=k,a.outputAll=l,a.dump=m,a.moveDown=u,a.moveUp=t,a.moveLeft=r,a.moveRight=q,a.increaseSpeed=o,a.decreaseSpeed=p,a.nextChannel=D,a.reset=H,a._oConfig=L,window._ticker=a}()}(); \ No newline at end of file +/*! ticker Apr-24-2016 */ +!function(){function pseudoForEach(a,b,c){for(var d=0;d0&&pseudoForEach(c,function(a,c){var d=c.innerHTML.trim();d=d.replace(/ /g,""),b+=d+"\n"})}_toggleTextarea({text:b,source:KEYS.O})}function outputAll(){output(!0)}function dump(){var a="";aConfigurableKeys.forEach(function(b){a+=b+": "+oConfig[b]+"\n"}),a+="listening to console."+oConfig.channel+"\n",_toggleTextarea({text:a,source:KEYS.D})}function silent(){oConfig.silentMode===!0?(oConfig.silentMode=!1,print("silent mode off")):oConfig.silentMode=!0}function increaseSpeed(a){return oConfig.pauseMode?void _nonSavedPrint("pauseMode"):(oConfig.interval-=oConfig.adjustmentInterval/2,void print("speed: "+oConfig.interval))}function decreaseSpeed(a){return oConfig.pauseMode?void _nonSavedPrint("pauseMode"):(oConfig.interval+=oConfig.adjustmentInterval,void print("speed: "+oConfig.interval))}function moveRight(a){oConfig.align="right",_postConfigApply();var b=document.querySelectorAll("._ticker_log");pseudoForEach(b,function(a,b){b.style.right=0,b.style.left="inherit",b.style["text-align"]="right"}),test()}function moveLeft(a){oConfig.align="left",_postConfigApply();var b=document.querySelectorAll("._ticker_log");pseudoForEach(b,function(a,b){b.style.left=0,b.style.right="inherit",b.style["text-align"]="left"}),test()}function saveConfig(){function a(){var a="_ticker={";return aConfigurableKeys.forEach(function(b){void 0!==oDEFAULTS[b]&&oDEFAULTS[b]===oConfig[b]||(a+="%22"+b+"%22:",a+="string"==typeof oConfig[b]?"%22"+oConfig[b]+"%22":oConfig[b],a+=",")}),a+="}",a=a.replace(/,}/,"}")}var b=window.location.href;b=b.replace(/_ticker=({.*})?&?/,""),-1===b.indexOf("?")&&(b+="?1=1"),b=b+"&"+a(),b=b.replace(/\?1=1&/,"?"),b=b.replace(/\?&/,"?"),b=b.replace(/(&&)+/,"&"),window.location.replace(b)}function moveUp(a){return oConfig.pauseMode?void _nonSavedPrint("pauseMode"):(kill(),oConfig.logStartTop+=5,void print("start: "+oConfig.logStartTop))}function moveDown(a){return oConfig.pauseMode?void _nonSavedPrint("pauseMode"):(kill(),oConfig.logStartTop-=5,void print("start: "+oConfig.logStartTop))}function registerMacro(a,b){return 9===a?void console.log("`","macro 9 reserved for interactive macro (`m)"):(console.log("`","registering macro: "+a),void(aMacros[a]=b))}function macroEdit(){var sDefaultText=oConfig.sMacro9Code;_toggleTextarea({text:sDefaultText,source:KEYS.M,buttons:{clear:function(){killTextarea(),macroEdit()}},exit:function(sValue){oConfig.sMacro9Code=sValue,registerMacro(9,function(){eval(sValue)})}})}function runMacro(a){"function"==typeof aMacros[a]?(console.log("`","running macro: "+a),aMacros[a]()):console.log("`","macro empty")}function nextChannel(){for(var a=0,b=oConfig.channel;a0&&pseudoForEach(c,function(a,b){var c=parseInt(getComputedStyle(b).top,10);if(0>=c)b.parentNode.removeChild(b);else{var d=c-b.offsetHeight+"px";b.style.top=d}})}b=setInterval(a,oConfig.interval)},b=setInterval(a,oConfig.interval)}function _postConfigApply(){function a(){"right"===oConfig.align?(oConfig.logStyle.right=0,oConfig.logStyle.left="inherit",oConfig.logStyle["text-align"]="right"):(oConfig.logStyle.right="inherit",oConfig.logStyle.left=0,oConfig.logStyle["text-align"]="left")}a()}function _loadConfigFromUrl(){var a,b=getUrlParamValue("_ticker");if(null!==b){try{a=JSON.parse(decodeURIComponent(b))}catch(c){}if("object"==typeof a)for(var d in a)oConfig[d]=a[d]}}function _setupListeners(){document.body.addEventListener("keydown",function(a){if(keyIsDown===!1&&a.keyCode===KEYS.BackTick&&(keyIsDown=!0),keyIsDown===!0){a.preventDefault();var b={};b[KEYS.B]=function(){oConfig.requireBackTick=!oConfig.requireBackTick,print("requireBackTick: "+oConfig.requireBackTick)},b[KEYS.D]=dump,b[KEYS.S]=silent,b[KEYS.T]=test,b[KEYS.O]=output,b[KEYS.L]=outputAll,b[KEYS.P]=pause,b[KEYS.K]=kill,b[KEYS.H]=help,b[KEYS.M]=macroEdit,b[KEYS.Up]=increaseSpeed,b[KEYS.Down]=decreaseSpeed,b[KEYS.Right]=moveRight,b[KEYS.Left]=moveLeft,b[KEYS.PageDown]=moveDown,b[KEYS.PageUp]=moveUp,b[KEYS.Enter]=saveConfig,b[KEYS.Tab]=nextChannel,b[KEYS.Esc]=killTextarea,[0,1,2,3,4,5,6,7,8,9].forEach(function(a){b[KEYS[a]]=function(){runMacro(a)}}),"function"==typeof b[a.keyCode]&&b[a.keyCode]()}}),document.body.addEventListener("keyup",function(a){keyIsDown===!0&&-1===aActionKeys.indexOf(a.keyCode)&&(keyIsDown=!1)})}function _calculateTop(){var a=document.querySelector("._ticker_log:last-child");return a?parseInt(a.style.top,10)+a.offsetHeight:oConfig.logStartTop}function _renderText(a){var b=document.createElement("div");b.className="_ticker",assignStyle(b,oConfig.logStyle),b.className+=" _ticker_log",b.innerHTML=a,b.style.top=_calculateTop()+"px",document.body.appendChild(b)}function _flushBuffer(){for(;aRenderBuffer.length>0&&_calculateTop()_help_______________________________________","t_->_test_______________________________________","p_->_pause_(freeze_output_toggle)_______________","k_->_kill_(remove_all)__________________________","o_->_output_(show_output_in_textarea_toggle)____","0_->_output_all_(show_entire_log_history)_______","d_->_dump_(show_configuration_values)___________","b_->_back-tick_required_to_console_invocation___","________________________________________________","up_______->_increase_speed______________________","down_____->_decrease_speed______________________","right____->_move logs right_____________________","left_____->_move logs left______________________","pageup___->_increase_starting_point_____________","pagedown_->_decrease_starting_point_____________","________________________________________________","enter_->_save_configuration_in_url______________","c_____->_clear_configuration_in_url_____________","________________________________________________","________________________________________________","Print_to_the_screen:____________________________",'__>> console.log("`", _"lorum_ipsum...")________',"________________________________________________","-","-","-"],KEYS={Tab:9,Enter:13,Esc:27,PageDown:33,PageUp:34,Left:37,Up:38,Right:39,Down:40,0:48,1:49,2:50,3:51,4:52,5:53,6:54,7:55,8:56,9:57,A:65,B:66,C:67,D:68,H:72,K:75,L:76,M:77,O:79,P:80,S:83,T:84,BackTick:192},aActionKeys=[KEYS.Tab,KEYS.Esc,KEYS.PageDown,KEYS.PageUp,KEYS.Left,KEYS.Up,KEYS.Right,KEYS.Down,KEYS[0],KEYS[1],KEYS[2],KEYS[3],KEYS[4],KEYS[5],KEYS[6],KEYS[7],KEYS[8],KEYS[9],KEYS.A,KEYS.B,KEYS.C,KEYS.D,KEYS.H,KEYS.K,KEYS.L,KEYS.M,KEYS.O,KEYS.P,KEYS.S,KEYS.T];aChannels.forEach(function(a){oChannels[a]={fnOriginal:console[a]}}),reset(),_loadConfigFromUrl(),_postConfigApply(),_listenToChannel(oConfig.channel),setInterval(function(){_flushBuffer()},250),_startInterval(),_setupListeners(),function(){var a={};a.config=config,a.test=test,a.help=help,a.kill=kill,a.silent=silent,a.pause=pause,a.output=output,a.outputAll=outputAll,a.dump=dump,a.moveDown=moveDown,a.moveUp=moveUp,a.moveLeft=moveLeft,a.moveRight=moveRight,a.increaseSpeed=increaseSpeed,a.decreaseSpeed=decreaseSpeed,a.nextChannel=nextChannel,a.reset=reset,a.registerMacro=registerMacro,a._oConfig=oConfig,window._ticker=a}()}(); \ No newline at end of file diff --git a/package.json b/package.json index 75df81a..179dfbb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ticker-log", - "version": "0.0.6", + "version": "0.1.0", "description": "On-screen VanillaJS logging utility.", "main": "ticker.js", "scripts": {