How to pass a variable in javascript - javascript

I am building a bookmarlet based on this site: http://www.latentmotion.com/how-to-create-a-jquery-bookmarklet/
This is the code of bookmarlet:
javascript:(function(){
var head=document.getElementsByTagName('head')0],
script=document.createElement('script');
script.type='text/javascript';
script.src='http://myserver.com/bookmarlet-remote.js?' + Math.floor(Math.random()*99999);
head.appendChild(script);
})();
void 0
How I can pass a variable from the bookmarlet (above code), to bookmarlet-remote.js ?
I've tried after var myNewvar='myValue', without success, Any Idea?

All JS code on a page (including bookmarklet code and scripts included have) have access to the global scope. If you define a variable without the var prefix it will be available to all other scripts.
It might be a good idea to be explicit about this. do window.myVar = "foo"; to clearly signal that you are working with global variables.

Using var in the function makes it local to that function. To make it global you have to add it to the scope of the window, so:
window.newVariable = window.newVariable || 'Your new value here';
OR
window['newVariable'] = 'Your new value here';

You'd create a public variable.
window.rnd = Math.floor(Math.random()*99999);
In bookmarlet-remote.js you just access the variable.

Related

Node.js run file inside another file

this is my current code
function includeClass(classname, ctx) {
var txt = fs.readFileSync("socket.io/" + classname + ".js");
return txt;
}
//define globals here
var _PLAYERS = {};
var _SPAWNPOINTS = [];
vm.runInThisContext(includeClass("vector"));
vm.runInThisContext(includeClass("class"));
vm.runInThisContext(includeClass("connectionHandler"));
vm.runInThisContext(includeClass("game"));
But that way, class.js file can't access variables from global scope or other files. because now i get errors like, _PLAYERS or require is undefined. I've tried eval() too, but it didn't do anything at all.
How can I run these js scripts in main script so they get interpreted as 1 whole?
https://nodejs.org/api/vm.html#vm_vm_runinthiscontext_code_options:
Running code does not have access to local scope, but does have access to the current global object.
Your _PLAYERS variable is not truly global, it is local to your script. As well as some other variables (like require) which are also in the module scope.
You can try to assign the needed variables to global object, however, I am not well aware what side effects and complications may follow.

Make js file not accessible through web console

This is most likely a very simple one.
I have created a game in canvas and js. However I stumbled upon a problem. As I can access the variables and code inside the chrome console, I can change f.ex. the player score to whatever I'd like. This is not very good.
Is there some way I can make the file and variables non accessible through the console for players to use?
Thanks!
You can put the whole script into an IIFE so that any variables declared will be scoped to the just-invoked function, rather than be on the top level and accessible anywhere. For example:
(function() {
var playerName = 'bob';
var turnCount = 1;
// do stuff with playerName and turnCount,
// they won't be accessible or changeable from the outside
// you can declare functions and such here as well
// which will also only be accessible from the inside
})();
Like this, referencing playerName from the console will fail.
you can use a proxy.
javascript proxy
or you can make an IIFE and expose only the required functions such as:
var App = (function() {
var test = '';
var init = function() {
App.test = 'test';
};
return {
init: init
};
})();
or define your properties as not writable with Object.defineProperty()

Access for global variables JavaScript unit testing

Hello I am new JavaScript unit testing and I'm using Mocha.js and Chai.js
What I want to do is simply figure out how to check the value of a global variable in a seperate js file. Here is my code
Here is the main.js file (code to be tested) Just has the variable I want to test against.
//main.js
var foo = 9;
Here is my test file
var assert = require("assert")
var expect = require('chai').expect
var fs = require("fs")
var vm = require("vm")
function include(path){
var code = fs.readFileSync(path,'utf-8');
vm.runInThisContext(code,path);
}
describe('Global', function(){
include('lib/main.js');
it('Should check if value is matching', function(){
expect(foo).to.equal(9);
});
});
Again, I'm new to unit testing in JavaScript. Any help will be greatly appreciated. The error I get back is foo is not defined which tells me that it can't access the variable, so how can I access it? Thank you in advance for the help.
var foo = 9; does not declare a global variable, it declares a local variable. In Node.js, a local variable declared in the outermost scope of a module will be local to that module.
If you want to test the value of a local variable declared in another file, your best bet is probably to read the contents of that file into a string (using fs.readFileSync, perhaps) and then eval() the string, which should define the variable in the current scope.
That will only work if the local variable is declared in the file's outermost scope. If it's a local variable inside a function, for example, you're out of luck (unless you want to do some gnarly string parsing, which would stretch the bounds of sanity).
Your global object is usually window
a global var foo = "test"; is the same as window.foo = "test"; or window['foo'] = "test";
Window is not defined when mocha is run in node, but this blog post uses "this" combined with a self-invoking function to get the same result.

Adding onclick and additional code to a .js document

I have a pretty specific question. I am trying to implement an onclick and cross domain tracking within a block of text, but it looks like it may need to be put directly into a .js document. I don't have a lot of JS experience. Basically, the current code looks like:
// JavaScript Document
function popup_no_status(loc)
{
var windowW=1000
var windowH=700
s = "width="+windowW+",height="+windowH+",status=yes, resizable=yes, scrollbars=yes";
mywin = window.open(loc ,'CBE', s);
mywin.focus();
}
What I want to add to this is:
onclick="pageTracker._trackEvent('Button', 'Click', 'QuickSearchWidget'); pageTracker._link(this.href); return false;
Can I just add it to the end of the document before the closing bracket? Any Ideas?
Much appreciated!
As long as the object pageTracker is defined and instantiated, you can call its methods like any other function:
function popup_no_status(loc) {
var s = "width=700,height=1000,status=yes, resizable=yes, scrollbars=yes";
var mywin = window.open(loc ,'CBE', s);
mywin.focus();
pageTracker._trackEvent('Button', 'Click', 'QuickSearchWidget');
pageTracker._link(this.href);
}
Also, the variables windowW and windowH are pointless in your example code - there is no need to store the string values in a variable if all you're going to do is concatenate them into another string. Further, unless you intend the mywin and s variables to be global, you should use the var keyword before defining them - that restricts the variables to the function scope instead of the global scope (all variables declared in a function without the var keyword are considered global).
If the code above gives an error like ReferenceError: pageTracker is not defined, that means that the code in which the pageTracker object is defined is either not included on the page, or it has not been instantiated.
Now... as for onClick, I am not clear what you're after here. Do you want this function to run when someone clicks the document? That would get pretty annoying!

can I load a javascript file under a context other than 'window'?

I try to load some external .js files, and have some irresolvable namespace conflicts.
I had the idea of loading some of the files in their own context somehow, replacing the "this" from pointing at the window object to some custom namespace.
example:
first.js:
name = "first";
second.js:
name = "second";
It seems to me that this kind of trick can be very useful. Is it possible at all?
EDIT
seems that replacing "this" does not begin to solve the problem, as it is not the default context for identifier resolution in javascript. this is my test code:
var first = {};
var second = {};
(function(){name = "first";}).call(first);
(function(){name = "second";}).call(second);
document.write('name= '+name+' <br/>\n'); //prints "second"
document.write('first.name= '+first.name+' <br/>\n'); //prints "undefined"
document.write('second.name= '+second.name+' <br/>\n'); //prints "undefined
any ideas?
RESOLUTION
It is not possible. I ended up wiser than I was this morning, and I gave it up.
I recommend these enlightening reading materials for anyone with a similar problem that might want to take a crack at it:
http://jibbering.com/faq/notes/closures/
http://softwareas.com/cross-domain-communication-with-iframes
One idea I've had for doing it without needing modifications to your external JavaScript file is getting the contents of the JavaScript file in an AJAXy way (up to you how you do that) and then put it all in a function using the new Function(code) way, then initialise that with new:
surrogateWindow = new new Function(jsCode)();
Then surrogateWindow is the this of that code. I think that that idea should work.
I'm not clear on your reason for doing this; what are you using this for, exactly?
Wrapping the contents of your second.js in an anonymous function will prevent variables in that file from conflicting with global variables. If you really must have a this set to a particular object that isn't the global object, you could do something like
var differentThis = {};
(function() {
// Contents of second.js go here
}).call(differentThis);
UPDATE
You can't do what you want. You seem to want to access the Variable object, which is the object to which a property is added when you declare a variable in JavaScript. In global code, the Variable object is the global object, so you can access it; within a function this is a property of the execution context that there is no way to access directly.
Even though this is an old question, this answer may still be relevant for some:
When a js file is loaded it automatically gets the window's context. That is not possible to change.
However, if you are trying to avoid conflicts between libraries that you are loading, and you don't have control over those libs, and they don't have a built-in "no-conflict" mechanism, then there is a nice trick -
you can load those into a source-less iframe.
This will make their context to be the window of the iframe, and you will still be able to access the iframe since there is no cross-domain issue here.
You can see this library as an example for use of this technique.
You can load your file in an iframe, the file is not a .js but an HTML file, like:
<html>
<body>
<script>
var $ = parent.$, // you can share objects with the parent, eg: jQuery
localObject = { // your local object definition
name: 'first',
showName: function(){
$('div.name').html( this.name );
}
};
//assign the local object to the custom namespace
parent.customNamespace.object1 = localObject;
</script>
</body>
</html>
The trick is to use parent. to get the javascript objects available in the parent page.
For the code you've written, I think you're misunderstanding some of the way classes work in JavaScript. In Java you can drop the this., but in JavaScript you can't. You'll always need to have this. there. So then your code becomes:
var first = {};
var second = {};
(function(){this.name = "first";}).call(first);
(function(){this.name = "second";}).call(second);
document.write('name= '+name+' <br/>\n'); //prints "undefined"
document.write('first.name= '+first.name+' <br/>\n'); //prints "first"
document.write('second.name= '+second.name+' <br/>\n'); //prints "second"
It would also be good to do it in a more normal class way. I'm not sure exactly what your situation is as I can't see all your code so you might be already doing it this way.
function Something(name) {
this.name = name;
}
var first = new Something("first");
var second = new Something("second");
document.write('name= '+name+' <br/>\n'); //prints "undefined"
document.write('first.name= '+first.name+' <br/>\n'); //prints "first"
document.write('second.name= '+second.name+' <br/>\n'); //prints "second"
Well you could wrap the contents of the js files with something like this:
var externalInterfaceForYourObject = (function(){
//code that defines your object
//this should refer to the current anonymous function, and not the window object
return this;
})();

Categories