I have a javascript file that declares the variable below:
var page = page || {};
The above file is included in another javascript file that wants to make use of page variable. I can see that variable in intellisense when trying to type it.
But at runtime, I am getting error that :
page is not defined.
I am posting more elaborate code:
First file is page.js that has just one line
var page = page || {};
Second file uses the above variable:
/// <reference path="page.js" />
page.current = function () {
};
There is final third file:
/// <reference path="../pagescripts/page-current.js" />
define(function () {
var Agencies = function (app, datacontext, logger, config, router) {
var myPage = page.current;
//The above line throws error saying page is not defined.
});
};
This pattern is commonly used when using the same namespace object across multiple files. By putting
var page = page || {};
at the top of each file that touches that namespace, you're guaranteed that page will point to the same object, and you can load them in any order, if your code permits.
// page1.js
var page = page || {};
page.doSomething = function() {};
// page2.js
var page = page || {}
page.doSomethingElse = function() {};
// page3.js
var page = page || {};
page.doThirdThing = function() {};
Make sure you load the javascript file that defines the variable before the file/script tag that uses it.
If you can not change the order of script file load for some reason, then you may use dom onready function to access this variable. As a rule of thumb, you should delay execution of your logic till dom is ready. e.g. in jQuery you can use
$(document).ready(function() {
// application init logic
// or start execution of functions
if(page && page.whatever) {
page.whatever();
}
})
Related
How to access/get the variable from one javascript file to another javascript file.
like first.js contains a function first.js like below.
this.first = function(){
var x = ['new','old']
}
now, I want to access the 'x' in another file say second.js
I have tried
var first = require('../first.js'); //path to the first.js file
console.log(first.x)
but getting the undefined value.
i want to get/access the 'x' from first.js
I am using this for protractor E2E testing using page objects.
It doesn't matter on which js files the functions / variables are. After they are parsed, they all belong to the same window.
You get undefined when accessing x property because it is private. x exists only in the local scope of first function.
Here is an example of how you can get access to x.
var first = (function () {
// private variables / functions
var x = ['new', 'old'];
// public properties (properties of "first")
return {
getX: function () {
return x; // x.slice(0); if you want to send a copy of the array
}
}
}());
The module loading system in node.js require you to use module.exports to expose your data types you want to share:
Your example would be re-written as follows:
// first.js
module.exports = {
x : 'Something here',
y : 'another item'
};
then on the other file
var first = require('../first.js'); //path to the first.js file
console.log(first.x)
See more details on Node.js module loading system
Sorry for the horrible post title but it's hard to sum up.
I'm defining JS modules using the revealing module pattern in seperate files, wrapped in IFFEs, under the namespace "App". By checking for the existence of "App" in each file, they can load in any order (script tags are injected into the HTML through a build process - so probably are added in alphabetical order).
Some of the modules are purely Backbone views.
The following 2 files work fine, loaded in any order:
app.js:
App = window.App || {};
App.Main = (function(){
var init = function(){
var view = new App.BaseView();
}
return {
init: init
}
})();
base_view.js:
App = window.App || {};
App.BaseView = (function(){
var View = Backbone.View.extend({
initialize: function(){
console.log('base view init');
}
});
return View;
})();
The whole app is triggered on document ready by calling App.Main.init(). I know that all modules have loaded by then - in whatever order;
However, if I want another view to extend BaseView, I need to know that base_view.js has loaded previously. The following file will not work if it was loaded before base_view.js (even though it's checking for the existence of "App" and creating it if necessary, it relies on BaseView already being defined):
another_view.js:
App = window.App || {};
App.AnotherView = (function(){
var View = App.BaseView.extend({ //App.BaseView may not be defined!
initialize: function(){
console.log('base view init');
}
});
return View;
})();
Is there a pattern I can use to get around this?
I'm sure you're looking for a better answer than this but you could simply try wrapping it inside a sort of 'wait for it' interval loop?
App = window.App || {};
var interval = setInterval(function() {
// get elem
if (typeof App.BaseView == 'undefined') return;
clearInterval(interval);
// the rest of the code
}, 10);
I am trying to put all my javascript function in one namespace. I have two javascript files and i am trying to put all the functions both the files into one namespace. So when i define the same namespace for both the files. The first gets over written by the second. I have defined my namespace in both the files as shown below. Is there a way i can stop this other putting all the function to one file? Thanks for the help.
var mynamespace={
foo:function(){Som code},
bar:function(){some code}
};
Yes, you can. In each file:
var mynamespace = mynamespace || {};
And then pick the next line for the file you have:
mynamespace.foo = function () {
or
mynamespace.bar = function () {
Basically, what this does is assign a current value of mynamespace to mynamespace if it exists. Otherwise, it creates a new object. Note that depending on if you declare mynamespace above or not, you might need this line up top instead:
if (typeof mynamespace === 'undefined') { var mynamespace = {} }
This is my main file:
$(document).ready(function () {
function Page() {
this.menu = new Menu();
this.management = new Management();
this.text = "text";
}
window.Page= Page();
});
Now I want to access the Page from every other JS file:
I tried this:
console.log(Page.text);
Gives me : Uncaught ReferenceError: Page is not defined
Tried this:
console.log(window.Page.text);
Gives me : Uncaught TypeError: Cannot read property 'text' of undefined
What am I doing wrong?
Your issue is that within the Page function you are not creating any new object on the global context. You are creating a new Menu and new Management instance but on the current context.
Plus by calling the Window.Page = Page(), you are assigning the result of the Page function (which is void) to the window.Page object.
I suggest you do something like :
//- from any js file
function createPage() {
var newPage = { title : 'new page', count : '2' };
return newPage;
}
window.Page = createPage();
...
//- and from other js file
$(document).ready(function () {
alert(window.Page.title);
});
Note, I have replaced your menu and management properties with dummy content for this sample. Sample available # this JSFiddle
Update : Code has been updated to illustrate the multiple js file proper usage.
Hope this helps
Function definitions don't need to be inside the document.ready() function. Only immediate actions that need to take place when the DOM is ready need to be put in there. So move the function to the toplevel.
You need to use window.Page = new Page();.
Either
window.Page = new Page();
or
function Page(){
this.menu = new Menu();
this.management = new Management();
this.text = "text";
return this;
}
window.Page = Page();
Then make sure other scripts don't try to use window.Page before it has been declared. You declare it in document.ready() callback function, so it's only going to be accessible once the DOM is ready and the callback function has been fired.
Edit:
without the context I'm not sure this is exactly what you're trying to do, but I think you just need a global Page object with some properties/methods. The easiest way to create it would be
window.Page = {
menu : new Menu(),
management = new Management(),
text = "text"
};
without the document.ready() wrapper.
Now obviously Menu and Management need to be defined before this code is executed. If any of these functions relies on DOM just move all your scripts to the end of the document. Any script that needs access to window.Page has to be included after this one.
How do I properly communicate data betweens two scripts.
In this particular case I have an element in one script, but I want to append it in another script.
The simplest way I could do this is by using the global window object as go-between.
But globals are not best practice.
What is the correct way to pass this element to another script?
Both script are encapsulated in the module pattern.
Script 0 Create Element Point
var element = document.createElement( "div" );
element.innerHTML = response_text;
Script 1 Append Element Point
Vi.sta = {
// implemented in the boot loader - shared global space - appended child already - you don't have to append until now.
// Static data has already been composed.
// Pull off window and append or best practice
};
Both are encapsulated in the module pattern
(function(){
// the code here
})()
All JS scripts are run in the global scope. When the files are downloaded to the client, they are parsed in the global scope.
So if you've got
// File_1.js
var myObj = { colour : "blue" };
There's nothing stopping you from doing this:
// File_2.js
var otherObj = { colour : myObj.colour };
As long as File_1.js is loaded before File_2.js
If you are namespacing, ie: MYNAMESPACE = {}; and each file extends your namespace through modules (rather than "module pattern" referring to returning interfaces from immediately-invoking functions), then check for the module's existence.
If you ARE writing modules for a namespaced app, and you DO need access to variables from one module to another, then you should be providing an interface for that.
If you are SANDBOXING modules, then you need to provide them all a proxy similar to a service-locator or a "registry", or develop a messaging-system based on a mediator-pattern.
window.sharedSpace = {};
sharedSpace.sharedValue = 'foo bar';
That way you only have one global object instead of several.
Why don't you just pass the element to a function in the module?
var module1 = (function () {
return {
func1: function () {
// get your element
var someElement = ...;
// pass it to the other module
module2.func2(someElement);
}
};
}) ();
var module2 = (function () {
return {
func2: function (someElement) {
// do whatever you want with someElement
}
};
}) ();