├── README.md └── console-listener.js /README.md: -------------------------------------------------------------------------------- 1 | # js-console-listener 2 | 3 | A library that allows you to listen for console events. 4 | 5 | ## Currently Supports: 6 | 7 | The following **Method Names** can be listened for: 8 | 9 | - all \* 10 | - assert 11 | - clear 12 | - count 13 | - debug 14 | - dir 15 | - dirxml 16 | - error 17 | - exception 18 | - group 19 | - groupCollapsed 20 | - groupEnd 21 | - info 22 | - profile 23 | - profileEnd 24 | - table 25 | - time 26 | - timeEnd 27 | - timeStamp 28 | - trace 29 | - warn 30 | 31 | \* *Custom method to listen to all the other methods* 32 | 33 | ## Use: 34 | 35 | `ConsoleListener.on()` 36 | 37 | *Available argument options*: 38 | 39 | - **String**, **Function** 40 | - *String* can be any of the methods listed above 41 | - *Function* is called with any arguments originally used 42 | - The "all" **Method Name** cannot be used here; use the **Function** overload 43 | - Example: `ConsoleListener.on("log", function () { /* Your code */ });` 44 | - **Function** 45 | - Used to listen for any console event. 46 | - The first argument passed is the **Method Name**; the rest are any arguments originally used 47 | - Example: `ConsoleListener.on(function (methodName) { /* Your code */ });` 48 | - **Object** 49 | - Each key is a **Method Name** 50 | - Each value is a callback, where its arguments follow the convention from before (if "all", then the first argument to the callback is the **Method Name**...similar to using the **Function** overload) 51 | - Example: `ConsoleListener.on({ log: function () { /* Your code */ } });` 52 | 53 | ## Order of Callbacks: 54 | 55 | The callbacks for a method are fired in the order they were bound, first calling directly bound callbacks, then "all" callbacks. 56 | 57 | ## Possible Problems: 58 | 59 | If `console` is not available when this script is run, but **later** becomes available (this happens with Internet Explorer if you open Developer Tools after the page loads), this script currently has no way of knowing/binding at that point. This script works only if `console` is available at the time it is executed. 60 | -------------------------------------------------------------------------------- /console-listener.js: -------------------------------------------------------------------------------- 1 | (function (w) { 2 | "use strict"; 3 | 4 | var A, F, O, consoleMethods, fixConsoleMethod, consoleOn, 5 | allHandlers, methodObj; 6 | 7 | A = []; 8 | F = function () { return; }; 9 | O = {}; 10 | 11 | // All possible standard methods to provide an interface for 12 | consoleMethods = [ 13 | "assert", "clear", "count", "debug", 14 | "dir", "dirxml", "error", "exception", 15 | "group", "groupCollapsed", "groupEnd", 16 | "info", "log", "profile", "profileEnd", 17 | "table", "time", "timeEnd", "timeStamp", 18 | "trace", "warn" 19 | ]; 20 | 21 | // Holds handlers to be executed for every method 22 | allHandlers = []; 23 | 24 | // Holds handlers per method 25 | methodObj = {}; 26 | 27 | // Overrides the existing console methods, to call any stored handlers first 28 | fixConsoleMethod = (function () { 29 | var func, empty; 30 | 31 | empty = function () { 32 | return F; 33 | }; 34 | 35 | if (w.console) { 36 | // If `console` is even available 37 | func = function (methodName) { 38 | var old; 39 | if (methodName in console && (old = console[methodName])) { 40 | // Checks to see if `methodName` is defined on `console` and has valid function to execute 41 | // (and stores the old handler) 42 | // This is important so that undefined methods aren't filled in 43 | console[methodName] = function () { 44 | // Overwrites current console method with this function 45 | var args, argsForAll, i, j; 46 | // Copy all arguments passed to handler 47 | args = A.slice.call(arguments, 0); 48 | for (i = 0, j = methodObj[methodName].handlers.length; i < j; i++) { 49 | // Loop over all stored handlers for this specific method and call them 50 | F.apply.call(methodObj[methodName].handlers[i], console, args); 51 | } 52 | for (i = 0, j = allHandlers.length; i < j; i++) { 53 | // Loop over all stored handlers for ALL events and call them 54 | argsForAll = [methodName]; 55 | A.push.apply(argsForAll, args); 56 | F.apply.call(allHandlers[i], console, argsForAll); 57 | } 58 | // Calls old 59 | F.apply.call(old, console, args); 60 | }; 61 | } 62 | return console[methodName] || empty; 63 | }; 64 | } else { 65 | func = empty; 66 | } 67 | 68 | return func; 69 | }()); 70 | 71 | // Loop through all standard console methods and add a wrapper function that calls stored handlers 72 | (function () { 73 | var i, j, cur; 74 | for (i = 0, j = consoleMethods.length; i < j; i++) { 75 | // Loop through all valid console methods 76 | cur = consoleMethods[i]; 77 | methodObj[cur] = { 78 | handlers: [] 79 | }; 80 | fixConsoleMethod(cur); 81 | } 82 | }()); 83 | 84 | // Main handler exposed 85 | consoleOn = function (methodName, callback) { 86 | var key, cur; 87 | if (O.toString.call(methodName) === "[object Object]") { 88 | // Object literal provided as first argument 89 | for (key in methodName) { 90 | // Loop through all keys in object literal 91 | cur = methodName[key]; 92 | if (key === "all") { 93 | // If targeting all events 94 | allHandlers.push(cur); 95 | } else if (key in methodObj) { 96 | // If targeting specific valid event 97 | methodObj[key].handlers.push(cur); 98 | } 99 | } 100 | } else if (typeof methodName === "function") { 101 | // Function provided as first argument 102 | allHandlers.push(methodName); 103 | } else if (methodName in methodObj) { 104 | // Valid String event provided 105 | methodObj[methodName].handlers.push(callback); 106 | } 107 | }; 108 | 109 | // Actually expose an interface 110 | w.ConsoleListener = { 111 | on: consoleOn 112 | }; 113 | }(this)); 114 | --------------------------------------------------------------------------------