I'm trying to build an app with meteor.js. In the lib directory, I've got a file collections.js that looks like:
var Datum = new Meteor.Collection('datum');
if (Meteor.isServer && Datum.find().count() == 0) {
var datum = [{...}]
_.each(datum, function(data) {
Datum.insert(data);
});
}
And then in my .js file in the client directory looks like:
Template.datum.helpers({
datum: function() {return Datum.find(); }
});
When I try to run the app, I get Uncaught ReferenceError: Datum is not defined and a blank page. I can't for the life of me figure out why that's happening. Any suggestions or help? I'm sure it must me be doing something stupid but I just can't figure out what it is.
Remove the var keyword.
All javascript files in Meteor are embedded in the (function(){...})() pattern, therefore all variables defined with the var keyword are local to the file. If you want to create a global variable, visible to the whole application, do it without the keyword.
So, instead of
var Datum = new Meteor.Collection('datum'); // local
there should be
Datum = new Meteor.Collection('datum'); // global
Related
I am trying to pass a file name into my JavaScript script, similarly to the example code here: https://mupdf.com/docs/examples/draw-document.js
C:\Tools\mupdf-1.14.0-windows> .\mutool.exe run .\script.js c:\temp\test.pdf
Unfortunately, I'm getting the following error:
ReferenceError: 'argv' is not defined
The documentation (https://mupdf.com/docs/manual-mutool-run.html) says:
[...] the command line arguments are accessible from the global 'argv' object.
The underlying code looks like this (this is just 'proof of concept' code):
var doc = new Document(argv[1]);
var outline = doc.loadOutline();
var outlineString = JSON.stringify(outline, {}, 2);
var txt = new ActiveXObject("Scripting.FileSystemObject");
var s = txt.CreateTextFile("c:\\temp\\text.json", true);
s.Write(outlineString);
s.Close();
Could someone point out the error I'm making please?
Just to point out that in a perfect world, I'd like to convert the JSON object to an XML file.
From the MuTool 1.14.0-rc1 Changelog:
mutool run: Pass arguments to script in scriptArgs global.
So, you should use scriptArgs rather than argv in your script.
Cheers,
Rom
I wan to test my library with nodeunit, and I use File Object in it, on website everything is working (FileAPI is implemented there) but when I'm trying to test it with nodeunit i get an error:
Fatal error: File is not defined
I assume that I have to add:
var FileAPI = require('file-api');
var File = FileAPI.File;
at the begging of the code, but I don't need that when I include that library to website, how to deal with that?
To use nodeunit I had to add module.exports at the end, is it necessary as well? (code sample on github)
What's more, when I'm trying to test this code:
https://github.com/GeoSmartCity-CIP/gsc-client/blob/feature/upload-data-file/src/upload/upload.js
with this test:
var gsc = require('../../src/upload/upload');
var FileAPI = require('file-api');
var File = FileAPI.File;
var exports = exports || {};
exports.isFileTypeCorrect = function(test) {
var file = new File('test.geojson');
var asd = new gsc.upload.Data(file);
test.ok(asd.isFileTypeCorrect(), 'this assertion should pass');
test.done();
};
I'm getting Fatal error: Cannot read property 'substr' of undefined error, what's the problem?
EDIT:
problem with substr is propably from isShapefileCorrect function, but still dont know why?
var asd = new gsc.upload.Data(file); Isn't it asynchronous function? Then probably asd.isFileTypeCorrect() should be called inside upload callback. Also you defining isFileTypeCorrect function as module exports and call itself inside itself. Isnt it an infinite loop?
If I want to span my JavaScript project across multiple source files, but have each file have access to the same private variable, how would one do that?
For example, if I have the following code:
APP = (function () {
var _secret = {},
app = {};
// Application part 01:
app.part01 = (function () { /* function that uses _secret */ }());
// Application part 02:
app.part02 = (function () { /* function that uses _secret */ }());
//
return app;
}());
How do I put app.part01 and app.part02 in seperate files, but still have access to _secret?
I don't want to pass it as an argument. That's just giving the secret away, as app.part01() could be replaced by any other function.
Maybe I am asking the impossible, but your suggestions might lead me in the right way.
I want to work with multiple files, but I don't know how. Copying and pasting everything inside a single function each time before testing is not something I want to do.
How do I put app.part01 and app.part02 in seperate files, but still have access to _secret?
That's impossible indeed. Script files are executed in the global scope, and don't have any special privileges. All variables that they will be able to access are just as accessible to all other scripts.
Copying and pasting everything inside a single function each time before testing is not something I want to do
What you are looking for is an automated build script. You will be able to configure it so that it bundles your files together, and wraps them in an IEFE in whose scope they will be able to share their private state. The most simple example:
#!/bin/sh
echo "APP = (function () {
var _secret = {},
app = {};" > app.js
cat app.part01.js >> app.js
cat app.part02.js >> app.js
echo " return app;
}());" >> app.js
The only way that you can share _secret is attaching it to the application object and then application object to the window object. Here is an example.
// FIRST JS FILE...
var application; // will be attached to window
(function(app) {
app.secret = "blah!"; // will be attached to application
})(application || (application = {}));
// ANOTHER JS FILE
var application;
(function(app) {
app.method1 = function(){ console.log(app.secret); }; // will be attached to application;
})(application || (application = {}));
console.log(application.method1()); // will display 'blah!' on the console
Working example on jsbin
One way I was able to accomplish this was to create a JS file that contained the global object.
// Define a global object to contain all environment and security variables
var envGlobalObj = {
appDatabase: process.env.YCAPPDATABASEURL,
sessionDatabase: process.env.YCSESSIONDATABASEURL,
secretPhrase: process.env.YCSECRETPHRASE,
appEmailAddress: process.env.YCAPPEMAILADDRESS,
appEmailPassword: process.env.YCAPPEMAILPASSWORD
}
module.exports = envGlobalObj
Then in the files I wish to reference this object, I added a require statement.
var envGlobalObj = require("./envGlobalObj.js");
This allowed me to centralize the environment and secrect variables.
I have multiple routes that need to access a database, for development I use a local database, and obviously production I use a hosted database
The only problem is every time I go to push a release I have to go through each route manually changing the database link
e.g.
var mongodb = require('mongojs').connect('urlhere', ['Collection']);
It would be nice if I could declare a variable in app.js like
app.set('mongoDBAddress', 'urlhere');
then in each file do something like
var mongodb = require('mongojs').connect(app.get('mongoDBAddress'), ['Collection']);
Does anybody know if this is achievable I've been messing around with it for about an hour googling and trying to include different things but I have no luck. thanks.
From the docs:
In browsers, the top-level scope is the global scope. That means that
in browsers if you're in the global scope var something will define a
global variable. In Node this is different. The top-level scope is not
the global scope; var something inside a Node module will be local to
that module.
You have to think a bit differently. Instead of creating a global object, create your modules so they take an app instance, for example:
// add.js
module.exports = function(app) { // requires an `app`
return function add(x, y) { // the actual function to export
app.log(x + y) // use dependency
}
}
// index.js
var app = {log: console.log.bind(console)}
var add = require('./add.js')(app) // pass `app` as a dependency
add(1, 2)
//^ will log `3` to the console
This is the convention in Express, and other libraries. app is in your main file (ie. index.js), and the modules you require have an app parameter.
You can add a global variable to GLOBAL, see this this question, although this is probably considered bad practice.
We have two methods in node.js to share variables within modules.
global
module.export
But your problem seems to be different, what I got is you want to connect your application to different databases without changing code. What you need to do is use command line params
For more ref
server.js
var connectTo = {
dev : "url1"
production : "url2"
}
var mongodb = require('mongojs').connect(connectTo[process.argv[2]], ['Collection']);
Run your server.js as
node server.js dev
// for connecting to development database
or
node server.js production
// for connecting to prodiction database
To share connection across diffrent modules
//Method 1
global.mongodb = require('mongojs').connect(connectTo[process.argv[2]], ['Collection']);
//Method 2
exports.mongodb = require('mongojs').connect(connectTo[process.argv[2]], ['Collection']);
exports.getMongoDBAddress = function() {
return connectTo[process.argv[2]]
}
My problem in short: I've created an object constructor in a js file (file name: generation.js) and I would like to create an object with that constructor in an other js file (file name: timeline.js). When I try to do this, I get the error message: Uncaught ReferenceError: generation (the object I want to create) is not defined.
In the HTML I have the js files in proper order: first the generation.js, then timeline.js. I also have the jQuery line in place.
If I try to use the constructor in the same file where the object definition is (in generation.js), it works properly. Then I copy + past that code to the new file and it doesn't work anymore.
The code:
Generation.JS:
This is where I defined the object constructor
$(document).ready(function(){
function generation() {
this.var1 = '';
.... // some variables
this.genFactory = function(agents) { // some function that creates even more
objects and other functions
};
};
});
Timeline.JS:
This is where I would like to create an instance of the generation object
$(document).ready(function(){
$('#start').click(function(){
console.log('ASD'); //just to check if the file works
gen1 = new generation(); //the error message points here
gen1.genFactory(3);
gen1.shuffle(individuals); //this is just an other method of the
generation object
});
});
Just to make sure that Timeline.js works: The console logs 'ASD'.
Looking forward for any suggestions!
You should expose your generation function to the public by assigning it to the window. A general approach in such cases is to have an app variable which contains all such object constructors and variables. In your Generation.js file you should use this code:
$(document).ready(function(){
window.app = window.app || {};
app.generation = function () {
this.var1 = '';
.... // some variables
this.genFactory = function(agents) { // some function that creates even more
objects and other functions
};
};
});
And in your Timeline.js file you will call your constructor as follows:
$(document).ready(function(){
window.app = window.app || {};
$('#start').click(function(){
console.log('ASD'); //just to check if the file works
gen1 = new app.generation(); //the error message points here
gen1.genFactory(3);
gen1.shuffle(individuals); //this is just an other method of the
generation object
});
})