Why is this element null? - javascript

Clarification:
I'm not interested in using jQuery methods.
Summary
I use a method to only run my modules after the html has finished loading. It looks like this. page_complete is the id of the last element on the page.
$A.finish('page_complete', function () {
// page has finished loading
});
Finish is implemented like this. It is just a timer that checks of the existence of the last element. Once it finds it, it initializes all the modules.
I don't understand why the element is NULL as FF is telling me.
/*finish
** Once an element has been loaded an HTML focus event is fired
** on that ID. It can not be cancelled and bubbles up
**
*/
$A.finish = function (id, callback) {
var htm_finished = document.getElementById(id);
if (htm_finished) {
$A.initAll(); // intilAll will fire the init function of all modules.
$A.makeEvent('focus', htm_finished);
callback();
} else {
setTimeout(function () {
$A.finish(id, callback);
}, 10);
}
};
Error in Firefox
...TypeError: this.E.ready is null # ...
Note I put a comment where the error is.
Module with error
/*MUserAny
**
**
**
*/
$A.module({
Name: 'MUserAny',
S: {
DynSma: SDynSma,
DynTwe: SDynTwe,
DynArc: SDynArc,
AniFlipMediaPane: SAniFlipMediaPane,
AniFlipPage: SAniFlipPage,
ClientStorage: SClientStorage
},
E: {
ready: $A('#page_complete')[0]
},
init: function () {
var pipe = {},
this_hold = this;
this.E.ready.addEventListener("focus", function (event) { // error is here.
pipe = $A.definePipe(this_hold.Name);
$A.machine(pipe);
}, false);
},
pre: function (pipe) {
var h_token = this.S.ClientStorage.get('h_token');
if ((h_token === '0') || (h_token === 'undefined') || (h_token === null)
|| (h_token === undefined)) {
this.S.AniFlipPage.run('sp');
pipe.state = false;
} else {
pipe.server.smalls.h_token = h_token;
pipe.state = true;
}
this.S.AniFlipMediaPane.run('mi_cover');
return pipe;
},
post: function (pipe) {
this.S.DynSma.run(pipe.server.smalls);
this.S.DynArc.run(pipe.server.arcmarks);
this.S.DynTwe.run(pipe.server.tweets);
this.S.AniFlipPage.run(this.S.ClientStorage.get('page'));
return pipe;
},
finish: function (pipe) {
}
});

It looks like
E: {
ready: $A('#page_complete')[0]
}
is being evaluated as part of the object literal, and if this is occuring before the page is complete you get your error.
One quick and dirty solution may be to change E.ready to a function, which will only be called during init, which you know happens after page complete, something like
E: {
ready: function() { return $A('#page_complete')[0]; }
},
init: function () {
var pipe = {},
this_hold = this;
this.E.ready().addEventListener("focus", function (event) { ...

Related

localStorage is null, but only from one function and not another

I have a PHP page that loads two JS files at the end. In the first file I have this...
// global variables
var refineSearchStorage = {};
// function calls
window.addEventListener("load", function() {
refineSearchStorage.get();
});
refineSearchStorage = {
data : null, // empty storage
get : function() {
refineSearchStorage.data = localStorage.getItem("refineSearchStorage");
if(refineSearchStorage.data === null) {
refineSearchStorage.data = { refineKeywords: '' };
refineSearchStorage.save();
}
else {
refineSearchStorage.data = JSON.parse(refineSearchStorage.data);
}
},
add : function(x) {
refineSearchStorage.data.refineKeywords = x;
refineSearchStorage.save();
},
save : function() {
localStorage.setItem("refineSearchStorage", JSON.stringify(refineSearchStorage.data));
}
};
Inline javascript calls Function 1 from the middle of the page. It is created by PHP after a search result...
<script>
window.addEventListener('load', function () {
searchActions('{$keywords_human}');
});
</script>
Function 1 appears in the 2nd JS page and the result is Uncaught TypeError: Cannot set property 'refineKeywords' of null... instead of adding to the localStorage.
function searchActions(x) {
refineSearchStorage.add(x);
}
Function 2 below is called with the click of a button and adds to a localStorage variable without issue. It is also located on the 2nd JS page...
function keywordAdd(y) {
var existingParams = refineSearchStorage.data.refineKeywords;
var param = y.toLowerCase();
var newParams;
newParams = (existingParams + ' ' + param).trim();
refineSearchStorage.add(newParams);
}
Function 1 used to work, but I did something to break it when I split the functions on to different pages. What did I do?
It's because
window.addEventListener('load', function () {
searchActions('{$keywords_human}');
});
gets called before
window.addEventListener("load", function() {
refineSearchStorage.get();
});
That error means that your data attribute is null
(screenshot) See what I mean by that
convert add to
add : function(x) {
refineSearchStorage.data = refineSearchStorage.data || {}; // this might help
refineSearchStorage.data.refineKeywords = x;
refineSearchStorage.save();
},

Callbacks with Require JS

So i'm trying to make two functions that allow a user to move an item from their cart to the "saved cart" and vise versa. These functions depend on the "cart group item" module which also contains the events for the button clicks. My question is, i'm unsure how to correctly call these functions to allow the click event to take place in my current js file. Hopefully someone can help!
Event's in module:
cartGroupItem.prototype.createMoveEvent = function (elem) {
if (undefined !== elem && null !== elem) {
var button = elem.querySelector('.cartGroupItem__move');
if (button !== null) {
button.addEventListener('click', function (e) {
ajax('GET',
'/resources/ajax/cart.aspx?sub=3&Saved=0&Cart_Group_ID='+this.cartGroupId,
true, {}, function () {
this.moveToCartCallback();
}.bind(this), function () {
this.showErrorDiv();
}.bind(this));
}.bind(this));
}
}
};
cartGroupItem.prototype.createSaveEvent = function (elem) {
if (undefined !== elem && null !== elem) {
var button = elem.querySelector('.cartGroupItem__save');
if (button !== null) {
button.addEventListener('click', function (e) {
ajax('GET',
'/resources/ajax/cart.aspx?sub=3&Saved=1&Cart_Group_ID='+this.cartGroupId,
true, {}, this.saveForLaterCallback.bind(this), this.showErrorDiv.bind(this));
}.bind(this));
}
}
};
Move functions:
function moveToSaved(cartGroupId) {
for (var i = 0, l = activeCartList.length; i < l; i++) {
if (activeCartList[i].cartGroupId === cartGroupId) {
activeCartList.remove();
savedCartList.push(activeCartList[i]);
}
}
}
function moveToActive(cartGroupId) {
for (var i = 0, l = savedCartList.length; i < l; i++) {
if (savedCartList[i].cartGroupId === cartGroupId) {
savedCartList.remove();
activeCartList.push(savedCartList[i]);
}
}
}
Your Event module probably define the function cartGroupItem right?
What you need to do is pass this function from its file to your current file, and then "instanciate" a carteGroupItem:
// In your current JS file
var myCartGroupItem = new cartGroupItem();
myCartGroupItem.createMoveEvent();
myCartGroupItem.createSaveEvent();
We also would need to see this function "constructor" (where it is defined) as it probably takes a few callbacks as parameters. Otherwise you can add them manually:
myCartGroupItem.moveToCartCallback = function() {
// do what you want when the item is moved to cart
};
// Same for the other callbacks
myCartGroupItem.saveForLaterCallback = function() { ... };
myCartGroupItem.showErrorDiv = function() { ... };
Finally, the way to pass things with RequireJS is that for instance, your Event module returns cartGroupItem so in your file module:
define(['Event'], function(cartGroupItem) {
// Your code where you can use cartGroupItem
});

jQuery: Event sequence with dynamically bound, arbitrarily created events & listeners not completing

Need to be able to arbitrarily create events (even those created during runtime) and then arbitrarily bind event listeners for such events to elements.
In the code below, everything works exactly as planned except that XBS.pullCurtain() is never called (but the event fires!). I've checked and rechecked the arguments, the sequence, etc.—no errors are thrown, everything appears to be what I'm expecting. But no sauce from the event listener. :S
// this func is used in the larger object below
function eCustom(eName, eProperties) {
var defaultProps = {"bubbles":true, "cancelable":false, "eventPhase":0, "type":eName};
if (typeof(eProperties) == "object") {
for (var prop in eProperties) {
if (eProperties.hasOwnProperty(prop) ) {
defaultProps[prop] = eProperties[prop];
}
}
}
return jQuery.Event(eName, defaultProps);
}
window.XBS = {
cfg: {
minLoadTime: 1000
},
evnt: {
wakeFromSleep: eCustom("wakeFromSleep"),
assetsLoaded: eCustom("assetsLoaded")
},
init: {
// obviously will be expanded haha
XBS.initImages();
},
stopwatch: {
__sw: new Date(),
reset:function() { XBS.stopwatch.startTime = -1},
start: function() {
var now = XBS.stopwatch.__sw.getTime();
XBS.stopwatch.startTime = now;
return now;
},
read: function() { return XBS.stopwatch.__sw.getTime() - XBS.stopwatch.start;},
now: function() { return XBS.stopwatch.__sw.getTime();},
elapsed: function(period) {
var diff = XBS.stopwatch.now() - XBS.stopwatch.startTime;
return (period !== undefined) ? diff > period : diff;
},
startTime:-1
},
sleep: function(period, wakeEvent, onWake, target) {
if (wakeEvent == undefined) wakeEvent = XBS.evnt.wakeFromSleep;
if (isFunction(onWake) ) {
// confirmed code reaches these lines and all vars are as expected
if (target == undefined) target = window;
$(target).on(wakeEvent, onWake);
}
setTimeout(function() {$(target).trigger(wakeEvent) }, period);
},
initImages: function() {
XBS.stopwatch.start();
// loadImages is a jQuery extension (link at bottom), but it works like a charm—
// problem isn't there, I'm 99% sure
$("#image-loading-queue").loadImages({
allLoadedClb:function() {
var success = null;
//minLoadTime because there will be presentational animations
if (XBS.stopwatch.elapsed(XBS.cfg.minLoadTime)) {
success = true;
} else {
var elapsed = XBS.cfg.minLoadTime - XBS.stopwatch.elapsed();
XBS.sleep(elapsed, XBS.evnt.wakeFromSleep, XBS.pullCurtain, "#curtain");
}
}
});
// this return is a placeholder for pending functionality, which is why it's not used
return success;
},
pullCurtain: function() {
// this will get more elaborate, but for now, I just want to call the darn thing!
$("#curtain").fadeToggle();
}
}
Borrowed Library:
http://www.jqueryscript.net/loading/Asynchronous-Image-Loading-with-jQuery-Image-Loader-Plugin.html
jsFiddle demo
You have an error in your jQuery on method call (which your JavaScript console is probably complaining about). The first parameter to on should only be the name of the event to handle (a string), not a jQuery Event object. Take a look at the documentation. It has two signatures: one which takes the method name (e.g. 'click') and one which takes a map of multiple method names to functions (e.g. {'click': fn1, 'mouseover': fn2}). It doesn't have a method signature for jQuery Event objects.
When you bind the handler, change the line to pass the event name only:
$(target).on(wakeEvent.type, onWake);

Javascript: repeat function

I have a function with if inside. In case if returns false I need repeat function again
this.reloadComment = function () {
var previous_comment = self.Comment();
$.getJSON(Routes.my_service_search_path(self.ID), {}, function (data) {
if (data.Comment.ID != previous_comment.ID) {
self.Comment(data.Comment);
} else {
// repeat
}
});
};
If self within the function is what this is outside it, then simply:
} else {
// repeat
self.reloadComment();
}
If not, use a named function; then since you have that nice name you can use, call it when you need to repeat it:
function reloadComment() {
var previous_comment = self.Comment();
$.getJSON(Routes.my_service_search_path(self.ID), {}, function (data) {
if (data.Comment.ID != previous_comment.ID) {
self.Comment(data.Comment);
} else {
// repeat
reloadComment();
}
});
}
this.reloadComment = reloadComment;
If you don't need to support IE8, you can do that with a single named function expression:
this.reloadComment = function reloadComment() {
var previous_comment = self.Comment();
$.getJSON(Routes.my_service_search_path(self.ID), {}, function (data) {
if (data.Comment.ID != previous_comment.ID) {
self.Comment(data.Comment);
} else {
// repeat
reloadComment();
}
});
};
...but on IE8 (and earlier) you'd end up with two copies of that function, not one; if you do that a lot, it ends up being wasteful. (It wouldn't make any other difference in this particular case, though; it'd still work. There are other situations where it would make a difference, so I stay away from NFEs entirely in code that needs to deal with IE8.)
Try This
this.reloadComment = function () {
var me = this;
var previous_comment = self.Comment();
$.getJSON(Routes.my_service_search_path(self.ID), {}, function (data) {
if (data.Comment.ID != previous_comment.ID) {
self.Comment(data.Comment);
} else {
me.reloadComment();
}
});
};

How to quickly and conveniently disable all console.log statements in my code?

Is there any way to turn off all console.log statements in my JavaScript code, for testing purposes?
Redefine the console.log function in your script.
console.log = function() {}
That's it, no more messages to console.
EDIT:
Expanding on Cide's idea. A custom logger which you can use to toggle logging on/off from your code.
From my Firefox console:
var logger = function()
{
var oldConsoleLog = null;
var pub = {};
pub.enableLogger = function enableLogger()
{
if(oldConsoleLog == null)
return;
window['console']['log'] = oldConsoleLog;
};
pub.disableLogger = function disableLogger()
{
oldConsoleLog = console.log;
window['console']['log'] = function() {};
};
return pub;
}();
$(document).ready(
function()
{
console.log('hello');
logger.disableLogger();
console.log('hi', 'hiya');
console.log('this wont show up in console');
logger.enableLogger();
console.log('This will show up!');
}
);
How to use the above 'logger'? In your ready event, call logger.disableLogger so that console messages are not logged. Add calls to logger.enableLogger and logger.disableLogger inside the method for which you want to log messages to the console.
The following is more thorough:
var DEBUG = false;
if(!DEBUG){
if(!window.console) window.console = {};
var methods = ["log", "debug", "warn", "info"];
for(var i=0;i<methods.length;i++){
console[methods[i]] = function(){};
}
}
This will zero out the common methods in the console if it exists, and they can be called without error and virtually no performance overhead. In the case of a browser like IE6 with no console, the dummy methods will be created to prevent errors. Of course there are many more functions in Firebug, like trace, profile, time, etc. They can be added to the list if you use them in your code.
You can also check if the debugger has those special methods or not (ie, IE) and zero out the ones it does not support:
if(window.console && !console.dir){
var methods = ["dir", "dirxml", "trace", "profile"]; //etc etc
for(var i=0;i<methods.length;i++){
console[methods[i]] = function(){};
}
}
As far as I can tell from the documentation, Firebug doesn't supply any variable to toggle debug state. Instead, wrap console.log() in a wrapper that conditionally calls it, i.e.:
DEBUG = true; // set to false to disable debugging
function debug_log() {
if ( DEBUG ) {
console.log.apply(this, arguments);
}
}
To not have to change all the existing calls, you can use this instead:
DEBUG = true; // set to false to disable debugging
old_console_log = console.log;
console.log = function() {
if ( DEBUG ) {
old_console_log.apply(this, arguments);
}
}
You should not!
It is not a good practice to overwrite built-in functions. There is also no guarantee that you will suppress all output, other libraries you use may conflict with your changes and there are other functions that may write to the console; .dir(), .warning(), .error(), .debug(), .assert() etc.
As some suggested, you could define a DEBUG_MODE variable and log conditionally. Depending on the complexity and nature of your code, it may be a good idea to write your own logger object/function that wraps around the console object and has this capability built-in. That would be the right place to do deal with instrumentation.
That said, for 'testing' purposes you can write tests instead of printing to the console. If you are not doing any testing, and those console.log() lines were just an aid to write your code, simply delete them.
I realize this is an old post but it still pops up at the top of Google results, so here is a more elegant non-jQuery solution that works in the latest Chrome, FF, and IE.
(function (original) {
console.enableLogging = function () {
console.log = original;
};
console.disableLogging = function () {
console.log = function () {};
};
})(console.log);
Just change the flag DEBUG to override the console.log function. This should do the trick.
var DEBUG = false;
// ENABLE/DISABLE Console Logs
if(!DEBUG){
console.log = function() {}
}
I know you asked how to disable console.log, but this might be what you're really after. This way you don't have to explicitly enable or disable the console. It simply prevents those pesky console errors for people who don't have it open or installed.
if(typeof(console) === 'undefined') {
var console = {};
console.log = console.error = console.info = console.debug = console.warn = console.trace = console.dir = console.dirxml = console.group = console.groupEnd = console.time = console.timeEnd = console.assert = console.profile = function() {};
}
I am surprised that of all those answers no one combines:
No jquery
Anonymous function to not pollute global namespace
Handle case where window.console not defined
Just modify the .log function of the console
I'd go for this:
(function () {
var debug = false
if (debug === false) {
if ( typeof(window.console) === 'undefined') { window.console = {}; }
window.console.log = function () {};
}
})()
After I searched for this issue aswell and tried it within my cordova app, I just want to warn every developer for windows phone to not overwrite
console.log
because the app will crash on startup.
It won't crash if you're developing local if you're lucky, but submitting in store it will result in crashing the app.
Just overwrite
window.console.log
if you need to.
This works in my app:
try {
if (typeof(window.console) != "undefined") {
window.console = {};
window.console.log = function () {
};
window.console.debug = function () {
};
window.console.info = function () {
};
window.console.warn = function () {
};
window.console.error = function () {
};
}
if (typeof(alert) !== "undefined") {
alert = function ()
{
}
}
} catch (ex) {
}
If you're using IE7, console won't be defined. So a more IE friendly version would be:
if (typeof console == "undefined" || typeof console.log == "undefined")
{
var console = { log: function() {} };
}
This a hybrid of answers from SolutionYogi and Chris S. It maintains the console.log line numbers and file name. Example jsFiddle.
// Avoid global functions via a self calling anonymous one (uses jQuery)
(function(MYAPP, $, undefined) {
// Prevent errors in browsers without console.log
if (!window.console) window.console = {};
if (!window.console.log) window.console.log = function(){};
//Private var
var console_log = console.log;
//Public methods
MYAPP.enableLog = function enableLogger() { console.log = console_log; };
MYAPP.disableLog = function disableLogger() { console.log = function() {}; };
}(window.MYAPP = window.MYAPP || {}, jQuery));
// Example Usage:
$(function() {
MYAPP.disableLog();
console.log('this should not show');
MYAPP.enableLog();
console.log('This will show');
});
If you use Webpack you could use the Terser plugin to completely exclude the console.log function calls.
This way you can have a clean production app package that will not expose unnecessary information but still have all this info in your debug build.
https://github.com/terser/terser#compress-options
drop_console (default: false) -- Pass true to discard calls to console.* functions. If you wish to drop a specific function call such as console.info and/or retain side effects from function arguments after dropping the function call then use pure_funcs instead.
minimizer: [
new TerserPlugin({
terserOptions: {
compress: {
pure_funcs: [ 'console.log' ]
}
}
}),
]
Alternatively you can use drop_console: true to exclude all console calls.
Here is a solution I just worked on that is fairly exhaustive. I covered all the fully supported console methods from https://developer.mozilla.org/en-US/docs/Web/API/console
1. Create js file "logger.js" and put in the following code in it
logger = {
assert: function() {
if(logger.active && logger.doAssert) {
console.assert.apply(null,arguments);
}
},
clear: function() {
if(logger.active && logger.doClear) {
console.clear();
}
},
count: function() {
if(logger.active && logger.doCount) {
console.count.apply(null,arguments);
}
},
countReset: function() {
if(logger.active && logger.doCountReset) {
console.countReset.apply(null,arguments);
}
},
debug: function() {
if(logger.active && logger.doDebug) {
console.debug.apply(null,arguments);
}
},
dir: function() {
if(logger.active && logger.doDir) {
console.dir.apply(null,arguments);
}
},
dirxml: function() {
if(logger.active && logger.doDirxml) {
console.dirxml.apply(null,arguments);
}
},
error: function() {
if(logger.active && logger.doError) {
console.error.apply(null,arguments);
}
},
group: function() {
if(logger.active && logger.doGroup) {
console.group.apply(null,arguments);
}
},
groupCollapsed: function() {
if(logger.active && logger.doGroup) {
console.groupCollapsed.apply(null,arguments);
}
},
groupEnd: function() {
if(logger.active && logger.doGroup) {
console.groupEnd.apply(null,arguments);
}
},
info: function() {
if(logger.active && logger.doInfo) {
console.info.apply(null,arguments);
}
},
log: function() {
if(logger.active && logger.doLog) {
console.log.apply(null,arguments);
}
},
table: function() {
if(logger.active && logger.doTable) {
console.table.apply(null,arguments);
}
},
time: function() {
if(logger.active && logger.doTime) {
console.time.apply(null,arguments);
}
},
timeEnd: function() {
if(logger.active && logger.doTime) {
console.timeEnd.apply(null,arguments);
}
},
timeLog: function() {
if(logger.active && logger.doTime) {
console.timeLog.apply(null,arguments);
}
},
trace: function() {
if(logger.active && logger.doTrace) {
console.trace.apply(null,arguments);
}
},
warn: function() {
if(logger.active && logger.doWarn) {
console.warn.apply(null,arguments);
}
},
active: true,
doAssert: true,
doClear: true,
doCount: true,
doCountReset: true,
doDebug: true,
doDir: true,
doDirxml: true,
doError: true,
doGroup: true,
doInfo: true,
doLog: true,
doTable: true,
doTime: true,
doTrace: true,
doWarn: true
};
2. Include before all your scripts with logs in all pages
3. Replace all "console." with "logger." in your scripts
4. Usage
Used just like "console." but with "logger."
logger.clear();
logger.log("abc");
Finally disable some or all logs
//disable/enable all logs
logger.active = false; //disable
logger.active = true; //enable
//disable some logs
logger.doLog = false; //disable
logger.doInfo = false; //disable
logger.doLog = true; //enable
logger.doInfo = true; //enable
logger.doClear = false; //log clearing code will no longer clear the console.
EDIT
After using my solution for sometime in my latest project I realized that it's difficult to remember that I'm supposed to use logger. instead of console.. So for this reason I decided to override console. This is my updated solution:
const consoleSubstitute = console;
console = {
assert: function() {
if(console.active && console.doAssert) {
consoleSubstitute.assert.apply(null,arguments);
}
},
clear: function() {
if(console.active && console.doClear) {
consoleSubstitute.clear();
}
},
count: function() {
if(console.active && console.doCount) {
consoleSubstitute.count.apply(null,arguments);
}
},
countReset: function() {
if(console.active && console.doCountReset) {
consoleSubstitute.countReset.apply(null,arguments);
}
},
debug: function() {
if(console.active && console.doDebug) {
consoleSubstitute.debug.apply(null,arguments);
}
},
dir: function() {
if(console.active && console.doDir) {
consoleSubstitute.dir.apply(null,arguments);
}
},
dirxml: function() {
if(console.active && console.doDirxml) {
consoleSubstitute.dirxml.apply(null,arguments);
}
},
error: function() {
if(console.active && console.doError) {
consoleSubstitute.error.apply(null,arguments);
}
},
group: function() {
if(console.active && console.doGroup) {
consoleSubstitute.group.apply(null,arguments);
}
},
groupCollapsed: function() {
if(console.active && console.doGroup) {
consoleSubstitute.groupCollapsed.apply(null,arguments);
}
},
groupEnd: function() {
if(console.active && console.doGroup) {
consoleSubstitute.groupEnd.apply(null,arguments);
}
},
info: function() {
if(console.active && console.doInfo) {
consoleSubstitute.info.apply(null,arguments);
}
},
log: function() {
if(console.active && console.doLog) {
if(console.doLogTrace) {
console.groupCollapsed(arguments);
consoleSubstitute.trace.apply(null,arguments);
console.groupEnd();
} else {
consoleSubstitute.log.apply(null,arguments);
}
}
},
table: function() {
if(console.active && console.doTable) {
consoleSubstitute.table.apply(null,arguments);
}
},
time: function() {
if(console.active && console.doTime) {
consoleSubstitute.time.apply(null,arguments);
}
},
timeEnd: function() {
if(console.active && console.doTime) {
consoleSubstitute.timeEnd.apply(null,arguments);
}
},
timeLog: function() {
if(console.active && console.doTime) {
consoleSubstitute.timeLog.apply(null,arguments);
}
},
trace: function() {
if(console.active && console.doTrace) {
consoleSubstitute.trace.apply(null,arguments);
}
},
warn: function() {
if(console.active && console.doWarn) {
consoleSubstitute.warn.apply(null,arguments);
}
},
active: true,
doAssert: true,
doClear: true,
doCount: true,
doCountReset: true,
doDebug: true,
doDir: true,
doDirxml: true,
doError: true,
doGroup: true,
doInfo: true,
doLog: true,
doLogTrace: false,
doTable: true,
doTime: true,
doTrace: true,
doWarn: true
};
Now you can just use console. as usual.
If you use Grunt you can add a task in order to remove/comment the console.log statements. Therefore the console.log are no longer called.
https://www.npmjs.org/package/grunt-remove-logging-calls
To disable console.log only:
console.log = function() {};
To disable all functions that write to the console:
for (let func in console) {
console[func] = function() {};
}
Ive been using the following to deal with he problem:-
var debug = 1;
var logger = function(a,b){ if ( debug == 1 ) console.log(a, b || "");};
Set debug to 1 to enable debugging. Then use the logger function when outputting debug text. It's also set up to accept two parameters.
So, instead of
console.log("my","log");
use
logger("my","log");
My comprehensive solution to disable/override all console.* functions is here.
Of course, please make sure you are including it after checking necessary context. For example, only including in production release, it's not bombing any other crucial components etc.
Quoting it here:
"use strict";
(() => {
var console = (window.console = window.console || {});
[
"assert", "clear", "count", "debug", "dir", "dirxml",
"error", "exception", "group", "groupCollapsed", "groupEnd",
"info", "log", "markTimeline", "profile", "profileEnd", "table",
"time", "timeEnd", "timeStamp", "trace", "warn"
].forEach(method => {
console[method] = () => {};
});
console.log("This message shouldn't be visible in console log");
})();
I have used winston logger earlier.
Nowadays I am using below simpler code from experience:
Set the environment variable from cmd/ command line (on Windows):
cmd
setx LOG_LEVEL info
Or, you could have a variable in your code if you like, but above is better.
Restart cmd/ command line, or, IDE/ editor like Netbeans
Have below like code:
console.debug = console.log; // define debug function
console.silly = console.log; // define silly function
switch (process.env.LOG_LEVEL) {
case 'debug':
case 'silly':
// print everything
break;
case 'dir':
case 'log':
console.debug = function () {};
console.silly = function () {};
break;
case 'info':
console.debug = function () {};
console.silly = function () {};
console.dir = function () {};
console.log = function () {};
break;
case 'trace': // similar to error, both may print stack trace/ frames
case 'warn': // since warn() function is an alias for error()
case 'error':
console.debug = function () {};
console.silly = function () {};
console.dir = function () {};
console.log = function () {};
console.info = function () {};
break;
}
Now use all console.* as below:
console.error(' this is a error message '); // will print
console.warn(' this is a warn message '); // will print
console.trace(' this is a trace message '); // will print
console.info(' this is a info message '); // will print, LOG_LEVEL is set to this
console.log(' this is a log message '); // will NOT print
console.dir(' this is a dir message '); // will NOT print
console.silly(' this is a silly message '); // will NOT print
console.debug(' this is a debug message '); // will NOT print
Now, based on your LOG_LEVEL settings made in the point 1 (like, setx LOG_LEVEL log and restart command line), some of the above will print, others won't print
Hope that helped.
Warning: Shameless plug!
You could also use something like my JsTrace object to have modular tracing with module-level "switching" capability to only turn on what you want to see at the time.
http://jstrace.codeplex.com
(Also has a NuGet package, for those who care)
All levels default to "error", though you can shut them "off".
Though, I can't think of why you would NOT want to see errors
You can change them like this:
Trace.traceLevel('ModuleName1', Trace.Levels.log);
Trace.traceLevel('ModuleName2', Trace.Levels.info);
Fore more docs, check out the Documentation
T
I found a little more advanced piece of code in this url JavaScript Tip: Bust and Disable console.log:
var DEBUG_MODE = true; // Set this value to false for production
if(typeof(console) === 'undefined') {
console = {}
}
if(!DEBUG_MODE || typeof(console.log) === 'undefined') {
// FYI: Firebug might get cranky...
console.log = console.error = console.info = console.debug = console.warn = console.trace = console.dir = console.dirxml = console.group = console.groupEnd = console.time = console.timeEnd = console.assert = console.profile = function() {};
}
I developed a library for this usecase: https://github.com/sunnykgupta/jsLogger
Features:
It safely overrides the console.log.
Takes care if the console is not available (oh yes, you need to factor that too.)
Stores all logs (even if they are suppressed) for later retrieval.
Handles major console functions like log, warn, error, info.
Is open for modifications and will be updated whenever new suggestions come up.
This should override all methods of window.console. You can put it on the very top of your scripts section, and if you are on a PHP framework you can only print this code when your app environment is production, or if some kind of debug flag is disabled. Then you would have all your logs in your code working on development environments or in debug mode.
window.console = (function(originalConsole){
var api = {};
var props = Object.keys(originalConsole);
for (var i=0; i<props.length; i++) {
api[props[i]] = function(){};
}
return api;
})(window.console);
A simplification of https://stackoverflow.com/a/46189791/871166
switch (process.env.LOG_LEVEL) {
case 'ERROR':
console.warn = function() {};
case 'WARN':
console.info = function() {};
case 'INFO':
console.log = function() {};
case 'LOG':
console.debug = function() {};
console.dir = function() {};
}
globalThis was introduced in JS 2020. On browsers globalThis same as window, on nodejs - same as global etc. On any environement it will point directly to the global object, so this code will work on any env which supports JS2020 Learn more: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/globalThis
With any modern browser & nodejs v12 or newer you should use this:
globalThis.console.log = () => null;
globalThis.console.warn = () => null;
globalThis.console.info = () => null;
globalThis.console.error = () => null;
I wrote this:
//Make a copy of the old console.
var oldConsole = Object.assign({}, console);
//This function redefine the caller with the original one. (well, at least i expect this to work in chrome, not tested in others)
function setEnabled(bool) {
if (bool) {
//Rewrites the disable function with the original one.
console[this.name] = oldConsole[this.name];
//Make sure the setEnable will be callable from original one.
console[this.name].setEnabled = setEnabled;
} else {
//Rewrites the original.
var fn = function () {/*function disabled, to enable call console.fn.setEnabled(true)*/};
//Defines the name, to remember.
Object.defineProperty(fn, "name", {value: this.name});
//replace the original with the empty one.
console[this.name] = fn;
//set the enable function
console[this.name].setEnabled = setEnabled
}
}
Unfortunately it doesn't work on use strict mode.
So using console.fn.setEnabled = setEnabled and then console.fn.setEnabled(false) where fn could be almost any console function.
For your case would be:
console.log.setEnabled = setEnabled;
console.log.setEnabled(false);
I wrote this too:
var FLAGS = {};
FLAGS.DEBUG = true;
FLAGS.INFO = false;
FLAGS.LOG = false;
//Adding dir, table, or other would put the setEnabled on the respective console functions.
function makeThemSwitchable(opt) {
var keysArr = Object.keys(opt);
//its better use this type of for.
for (var x = 0; x < keysArr.length; x++) {
var key = keysArr[x];
var lowerKey = key.toLowerCase();
//Only if the key exists
if (console[lowerKey]) {
//define the function
console[lowerKey].setEnabled = setEnabled;
//Make it enabled/disabled by key.
console[lowerKey].setEnabled(opt[key]);
}
}
}
//Put the set enabled function on the original console using the defined flags and set them.
makeThemSwitchable(FLAGS);
so then you just need to put in the FLAGS the default value (before execute the above code), like FLAGS.LOG = false and the log function would be disabled by default, and still you could enabled it calling console.log.setEnabled(true)
If you're using gulp, then you can use this plugin:
Install this plugin with the command:
npm install gulp-remove-logging
Next, add this line to your gulpfile:
var gulp_remove_logging = require("gulp-remove-logging");
Lastly, add the configuration settings (see below) to your gulpfile.
Task Configuration
gulp.task("remove_logging", function() {
return gulp.src("src/javascripts/**/*.js")
.pipe(
gulp_remove_logging()
)
.pipe(
gulp.dest(
"build/javascripts/"
)
); });
One liner just set devMode true/false;
console.log = devMode ? console.log : () => { };
To add a bit on top of the other answers, I personally wanted to turn off only specific parts of my code (ES6 modules, but simple separate scripts should work as well).
// old console to restore functionality
const consoleHolder = window.console;
// arbitrary strings, for which the console stays on (files which you aim to debug)
const debuggedHandlers = ["someScript", "anotherScript"];
// get console methods and create a dummy with all of them empty
const consoleMethodKeys = Object.getOwnPropertyNames(window.console).filter(item => typeof window.console[item] === 'function');
const consoleDummy = {};
consoleMethodKeys.forEach(method => consoleDummy[method] = () => {});
export function enableConsoleRedirect(handler) {
if (!debuggedHandlers.includes(handler)) {
window.console = consoleDummy;
}
}
export function disableConsoleRedirect() {
window.console = consoleHolder;
}
Then, just import this module into any file where you want to be able to switch debug mode, call the enable function at the top of the file, and the disable function at the bottom.
If you want to use it in simple scripts, you may want to wrap the top in anonymous functions and/or reorganize it a bit to minimize the namespace pollution.
Additionally, you may want to use just true/false instead of string handler and switch the debug mode in file which you're currently working with.
You could use javascript AOP (e.g. jquery-aop) to intercept all calls to console.debug/log (around) and do not proceed with the actual invocation if some global variable is set to false.
You could even do an ajax call (now and then) so you can change the log enabled/disabled behavior on the server which can be very interesting to enable debugging when facing an issue in a staging environment or such.
After doing some research and development for this problem, I came across this solution which will hide warnings/Errors/Logs as per your choice.
(function () {
var origOpen = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function () {
console.warn = function () { };
window['console']['warn'] = function () { };
this.addEventListener('load', function () {
console.warn('Something bad happened.');
window['console']['warn'] = function () { };
});
};
})();
Add this code before JQuery plugin (e.g /../jquery.min.js) even as this is JavaScript code that does not require JQuery. Because some warnings are in JQuery itself.
Thanks!!

Categories