Avoiding multiple load of javascript file - javascript

I add this snippet to each javascript file used in my asp.net web api application to avoid multiple load :
Fullcalendar.js
blog = {};
blog.comments = blog.comments || {};
blog.comments.debugMode = false;
blog.isFirstLoad = function (namesp, jsFile) {
var isFirst = namesp.jsFile.firstLoad === undefined;
namesp.jsFile.firstLoad = false;
return isFirst;
};
$(document).ready(function () {
if (!blog.isFirstLoad(blog.comments, "fullcalendar.js")) {
return;
}
});
Sometimes I get a weird exception
Uncaught TypeError: Cannot read property 'firstLoad' of undefined
I need to know :
Why this happens?
How can I fix it?

A couple of problems there.
First, you shouldn't be loading the file more than once in the first place, so it shouldn't be necessary to go through this business of trying to figure out whether you've loaded it.
But if you want to do that:
The first practical issue is that you're always doing this:
blog = {};
...which means if there's already a blog global, you're wiping out its value and replacing it with an empty object. If you want to use an existing global's value or create a new one, do this:
var blog = blog || {};
That seems odd, but since repeated var declarations are fine (and don't change the variable), that will use an existing one's value, or if there isn't one (or its value is falsey) it will create a new one and initialize it with {}.
Then, the line
namesp.jsFile.firstLoad = false;
...looks for a property called jsFile on namesp and assumes it's not null or undefined. It doesn't look for a property using the jsFile argument's value.
To do that, use brackets notation:
namesp[jsFile].firstLoad = false;
Even then, though, you're assuming it's not null or undefined, but it may well be. You probably just wanted:
namesp[jsFile] = false;
Or possibly:
namesp[jsFile] = namesp[jsFile] ||{};
namesp[jsFile].firstLoad = false;
That said, it seems really odd to use blog.comments to track whether JavaScript files have been loaded. If the file may have already been loaded, just this will do it:
var fullCalendarLoaded;
if (fullCalendarLoaded) {
// It's already loaded
} else {
// It isn't, but it is now
fullCalendarLoaded = true;
// ...do your init...
}
Or if you have several of these and want to use a single global for it:
var loadedScripts = loadedScripts || {};
if (loadedScripts.fullCalendar) {
// Already loaded
} else {
// Not loaded yet
loadedScripts.fullCalendar = true;
// ...do init...
}
Or if using the filename is important:
var loadedScripts = loadedScripts || {};
function firstLoad(filename) {
if (loadedScripts[filename[) {
return false;
}
// Not loaded yet, remember we've loaded it now
loadedScripts[filename] = true;
return true;
}
Then:
if (firstLoad("fullcalendar.js")) {
// First load, do init...
}

It's fairly straightforward:
On your initial run, you define
blog = {};
blog.comments = blog.comments || {};
blog.comments.debugMode = false;
In theory, this means that on some loads, blog is:
var blog = {
comments: {
debugMode: false
}
}
You then pass blog.comments into your function isFirstLoad as the namesp parameter. In that function, you do the evaluation:
namesp.jsFile.firstLoad === undefined;
Well, you never defined the jsFile property of blog.comments. This means it is undefined. Trying to access the property firstLoad of an undefined variable will give you your error
Uncaught TypeError: Cannot read property 'firstLoad' of undefined

Related

Difficulty in understanding javascript coding

i'm facing difficulty in understanding what this following code does. could anyone here please help me out in understanding this piece of code?
var PnPResponsiveApp = PnPResponsiveApp || {};
PnPResponsiveApp.responsivizeSettings = function () {
// return if no longer on Settings page
if (window.location.href.indexOf('/settings.aspx') < 0) return;
// find the Settings root element, or wait if not available yet
var settingsRoot = $(".ms-siteSettings-root");
if (!settingsRoot.length) {
setTimeout(PnPResponsiveApp.responsivizeSettings, 100);
return;
}
}
var PnPResponsiveApp = PnPResponsiveApp || {};
The above line ensures that the PnPResponsiveApp variable gets its old value if it already exists, otherwise it's set to a new object.
PnPResponsiveApp.responsivizeSettings = function () {
Here, a new function is created.
// return if no longer on Settings page
if (window.location.href.indexOf('/settings.aspx') < 0) return;
If the URL of the current page isn't the settings page, then the function exits immediately.
// find the Settings root element, or wait if not available yet
var settingsRoot = $(".ms-siteSettings-root");
This gets all elements with a class of .ms-siteSettings-root.
if (!settingsRoot.length) {
setTimeout(PnPResponsiveApp.responsivizeSettings, 100);
return;
}
If any elements were found (if the length of the node list is not zero), then call the PnPResponsiveApp.responsivizeSettings function in 100 milliseconds.
Very easy code basically, I'll explain what's going on:
var PnPResponsiveApp = PnPResponsiveApp || {};
This is very common way to see if the variable is already defined and if not, avoid throwing error and equal it to an empty object, It's used in many frameworks and library, very safe way to check if the var is there already... look at here for more info: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_Operators
PnPResponsiveApp.responsivizeSettings = function () {};
This is basically a simple function but attached to the object PnPResponsiveApp - if just responsivizeSettings = function () {}; it's attached to window Object
if (window.location.href.indexOf('/settings.aspx') < 0) return;
this is Checking if the Link in the linkbar has settings.aspx - indexOf return -1 if it doesn't contain the string, so if it's not settings.aspx it returns -1 that's smaller than 0 and then the whole function return ... the second return basically return undefined
var settingsRoot = $(".ms-siteSettings-root");
This is basically look for all element with class of ms-siteSettings-root and equal them to variable settingsRoot, it could be a single DOM or multiple...
if (!settingsRoot.length) {
and this basically check if any DOM element has ms-siteSettings-root class, length return a Number, so if it's not there, it returns 0, if there is return 1,2,3 etc... and 0 is equal to False in JavaScript and bigger than 0 is equal to True, so this way we can check if it's there...
setTimeout(PnPResponsiveApp.responsivizeSettings, 100);
so if the settingsRoot is there, we execute this function block and with setTimeout we wait 100ms... setTimeout always works in this manner, setTimeout(function(), time); and the same return happens at the end...
Hope it's informative enough...

Node.JS Global Variable Not Staying Updated

I have a global object variable set called _storage. It looks like this:
_storage = {
test : {
}
};
When a user sends a request to add their info to the "test" object inside of storage, it's supposed to set _storage.test[1] = true; for example.
After it sets that, I did this to see what the variable looked like:
console.log(_storage.test); and it outputted the correct response:
{ '1' : true }
All seems perfect, until the user sends a request to get all the current items in the test object. This is where the problem is. The variable seems to empty itself and go back to an empty object {}.
The user sends the request to see what's inside of test after setting the data in test, so it can't be an issue caused by the user requesting to see the data before even setting it. This is done inside two separate modules, one sets the data and another one gets the data (the two modules aren't just for that only, obviously) but the _storage variable is global and shouldn't be affected by two separate modules.
Here's an example of how it goes down:
User sends request to set 1 = true inside of _storage.test, making _storage.test[1] = true;
_storage.test is now { test : { '1' : true } } according to console.log
User sends request to view all data from _storage.test
_storage.test is {} according to console.log, as if it isn't staying set
Here's the code that I use to Get, Set, and Remove the data:
exports.GetUserData = function () {
return global._storage.test;
};
exports.RemoveUserData = function (uid) {
delete global._storage.test[Number(uid)];
};
exports.AddUserData = function (uid) {
global._storage.test[Number(uid)] = true;
};
Ok, so I think you're not showing all your code, but here's what I did which worked:
// index.js
'use strict';
global._storage = global._storage || {};
global._storage.test = global._storage.test || {};
exports.GetUserData = function () {
return global._storage.test;
};
exports.RemoveUserData = function (uid) {
delete global._storage.test[Number(uid)];
};
exports.AddUserData = function (uid) {
global._storage.test[Number(uid)] = true;
};
// other.js
'use strict';
global._storage = global._storage || {};
global._storage.test = global._storage.test || {};
exports.GetUserData = function(){
return global._storage.test;
}
And then I ran this from my repl:
> var it = require('./');
undefined
> var other = require('./other');
undefined
> it.AddUserData('1234');
undefined
> it.GetUserData();
{ '1234': true }
> other.GetUserData();
{ '1234': true }
>
So that works as designed. Thing is this... I've been working with node since 2009, and I've never felt the need to use global variables. I doubt your app needs it. So even though this'll work for you, I recommend you think of another way to do it.

How do you iterate over the list of bodies from Box2D in emscripten?

I'm using the emscripten port of Box2D from here: https://github.com/kripken/box2d.js
It's working great, but I'm have some trouble interacting with emscripten.
Specifically I'm perform model-display sync in a loop like this:
function step() {
world.Step(1/60);
var body = this.world.GetBodyList();
while(body != null) {
readGeometry(body, body.data);
body = body.GetNext();
}
}
...but that doesn't seem to work. Although the C++ code returns NULL at the end of the linked list of body objects, body.GetNext() (return type in cpp is b2Body *) is never the native javascript null.
I've also tried:
body != Box2D.NULL
However, that is also never true. I'm guessing that emscripten is returning a wrapped pointer, and I have to do some specific operation on it to test for 'nullness'.
Inspecting the returned object I can see that the 'pointer' value in it for the null values is zero, and I can make it work with:
function step() {
world.Step(1/60);
var body = this.world.GetBodyList();
while(body.a != 0) { // <--------------- This hack
readGeometry(body, body.data);
body = body.GetNext();
}
}
So, it's clearly possible to test for NULL-ness, but I can't find any documentation on how to do it.
Try this
function step() {
world.Step(1/60);
var body = this.world.GetBodyList();
while(Box2D.getPointer(body)) { // <-- will equal 0 for a Box2D.NULL object
readGeometry(body, body.data);
body = body.GetNext();
}
}
I know this question is really old but I recently came across this problem and found the solution on github.
The accepted answer didn't work, but this did :
var next = World.m_bodyList;
var current;
while (next != null) {
current = next; next = next.m_next;
if(current.m_userData){
var current_body = {};
current_body.x = current.m_xf.position.x;
current_body.y = current.m_xf.position.y
}
}

JavaScript Too much recursion error with facebook JavaScript SDK

i am sending FB.login request to facebook. but FB is not defined while javascript SDK is still loading core javascript resources.
so, i put a check to get FB variable
function check_FB_variable(){
if(typeof FB=='undefined'){
check_FB_variable();
}else{}
}
check_FB_variable();
But this approach gives me Too much recursion error.
so , i put this code as
function check_FB_variable(){
if(typeof FB=='undefined'){
setTimeout(check_FB_variable,600);
}else{}
}
check_FB_variable();
but in this approach the before timeout function make a call function moves down and gives error
FB.login not defined.
please, help.
I've used something similar to check if JQMobi exists, I don't know exactly why but I think the exception is thrown because you call the pointer to the function every time.
You should try checking in an interval like this (Untested):
var facebookChecker = window.setInterval(fbCheck, 200);
var fbCheck = function () {
if (typeof FB != 'undefined' && facebookChecker != null) {
window.clearInterval(facebookChecker);
facebookChecker = null;
// Whatever you want to do if facebook is loaded
// Example: InitFBLogin();
}
}
Or you could use a while statement (the one I used):
/*
* This JQ Fix tries to attach Jquery to a variable to ensure it exists.
* - Marvin Brouwer.
*/
var FixJQ = function () {
var JQFIX = null;
while (!JQFIX || JQFIX == null) {
try {
JQFIX = jQuery;
} catch (nothing) { jQuery = $; };
};
JQFIX = null;
return true;
};
if (FixJQ()) {
FixJQ = null;
};
The beauty of the last one is that you can put you next step below this, because it will wait until the while loop has finished.
I honestly do not know which one is better/faster but I’m sure the bottom one will work.

implementing namespace function javascript

I'm implementing Stoyan Stefanov's javascript namespace function as I have been reading his very informative JavaScript Patterns book; in my web application but not sure if I'm using it the proper way
here is the funciton implementation i'm using on my web app on this page http://dalydd.com/projects/module_example/
var COOP = COOP || {};
COOP.namespace = function (ns_string) {
var parts = ns_string.split('.'),
parent = COOP,
i;
// strip redundant leading global
if (parts[0] === "COOP") {
parts = parts.slice(1);
}
for (i = 0; i < parts.length; i += 1) {
// create a property if it doesn't exist
if (typeof parent[parts[i]] === "undefined") {
parent[parts[i]] = {};
}
parent = parent[parts[i]];
}
return parent;
};
COOP.namespace('sliderContainer')
COOP.sliderContainer = function () {
return slider = ($('#slider').length > 0) ? $('#slider') : $('#element_temp');
} // we need this at the beginning as others are dependent on it and call it initially
my goal is to check every new property of COOP to see if it exists before it's implemented --- so if I create a property of COOP called COOP.sliderContainer - I want to make sure COOP.sliderContainer does not exist already. when I use the namespace function it returns an object but COOP.sliderContainer is a function. I feel like I have to do an extra layer of abstraction in order to name this namespace function work properly like
var sliderContainer = COOP.namespace('sliderContainer');
sliderContainer.sliderContainer = function () {
return slider = ($('#slider').length > 0) ? $('#slider') : $('#element_temp');
}
this seems silly and redundant to me - is there a better way to do this?
any info is appreciated as always - the page has a direct link to the js file on it
namespace function is useful when create sub namespaces inside COOP, it will help to avoid multiple checkings. For example you want to create COOP.module.module1, you have to make 2 checks to see if module and module 1 are not defined or not.
However, in this case, sliderContainer is just a property of COOP. There's no need to use namespace. You just simply check it yourself:
if(COOP.sliderContainer === undefined){
// define it
}
EDIT
You can have a function handle that for you:
COOP.createProperty = function(name, prop){
if(COOP[name] === undefined){
COOP[name] = prop;
}
}
then
COOP.createProperty("sliderContainer", function(){
// do whatever you want
});

Categories

Resources