I think I have a problem with closures and execution contexts, although I'm not really sure.
Let me explain exactly what I'm trying to do and why I've coded it in the way I have:
1) I'm building a javascript powered interface, the interface contains different apps (I'm calling them widgets).
2) All the widgets are moveable/dragable/closeable/resizeable etc.. I'm trying to achieve something like a desktop interface although has to be said that what I've got is far less than a web based opperating system. But that is what I'm aiming for.
3) So I needed a way for the JS code to load each of these widgets without knowing which widgets exist and/or anything else about them. I decided that when the interface is loading it should call a php script to find out the names of the widgets.
4) The JS code has the name of each widget, it now loops through them all calling another php script, this php script will feed back the code for loading that particular widget and the html code to display it. The JS appends elements to the screen for the display and then it loads the JS code for the widget.
5) This is the tricky part, actually loading the code for each widget, I did it like this:
var func=new Function(ajax.responseText);
func();
And it works fine, or appears to atleast.
6) Now I have a problem with objects and arrays and I think it has something to do with execution contexts.
Array Example:
var myArray=new Array('foo', 'bar', 'fooBar', 'barFoo');
Looks OK to me, no problem with the actual array (unless I typed something wrong in there :) can't work without my Net Beans editor) I tried running this as a seperate script and it works fine, ie; with: alert(myArray[0]); resulting in foo
Array Problem:
My JS code can't do anything usefull with this array because actually calling alert(myArray[0]); will result in foo, bar, fooBar, barFoo.. No idea why this happens really but it's really messing everything up now.
Object Example:
var myObject=new Object();
myObject.a='foo';
myObject.b='bar';
myObject.c='fooBar';
myObject.d='barFoo';
Again, object works fine when run by it's self.
Object Problem:
Very similar problem as with arrays, calling alert(myObject['a']); will actually result in [object Object],[object Object],[object Object], [object Object] ...
...so that's the same problem as with arrays, but it gets even worse with objects, if I call alert(myObject.a); (notice that i didn't use ['a'] this time) it will just result in undefined.
So to backtrack a little and further explain the way that everything is tied in together:
1) when the JS loads it will call a php script which returns a JSON encoded object containing 3 keys('functions', 'JSscript', 'Other'). Each key contains the source code of another javacript file. These are all loaded using a dynamically created function like: var func=new Function(ajax.responseText).
2) Then it's these new javascript codes that call another php script for further directions.
3) Php responds with JSON, which is evaluated inside a dynamically created function and stored in a new variable.
4) The new variable is now an object containing maybe 3 keys (html, javascript, anotherObject) The html is appended into the document, The javscript is executed in a new function as above.
5) The problems come with objects/arrays that exist in the JS executed in my last statement.
So if anyone can help me out on this I'd be greatfull, and if you need further explaination or code examples then obviously I'll be happy to provide.
Thanks,
Richard
Could it be that you're not parsing your ajax response text.
Ohhhh.. Turns out this was nothing to do with closures or any other javascript for that matter, sorry to excite you all.
It was caused by a php script, and not even the php script that handles ajax requests, it was actually the script that reads the javascript files and then JSONs them. That script also has a find and replace function like a simple templating system where it will find all the words between '[' & ']' which unfortunately means any arrays in the javascript will get bungled up.
I used the find and replace with square braces because it was originally meant for html templating, I just didn't consider it properly when I started using the system in my JS code aswell.
So to clarify, my php script would change JS of obj[var].description into obj.description which is valid JS so didn't flag any errors for me to notice it.
Ohhhhh. What a loser :)
Related
I am trying to pass a few variables from my php to the javascript and its working fine except for when I add a particular variable to the function call. There are 3 variables being passed all of which are related to a youtube video. the ID is being retrieved from a database, and the other two (title and description) are being retrieved using the ID from the youtube api.
<a href="#" class="list-group-item" id="{{$vidID[$i]}}" onclick="updateVid('{{$vidID[$i]}}', '{{$title[$i]}}', '{{$desc[$i]}}test')">
I am using hogan templating so the {{}} is the same as php tags with an echo. The problem only seems to occur when I add in the description variable to the call. Without it, the other two work perfectly fine. After doing some research it seems this is caused by an invisible character but I retyped my code to make sure and my code wasn't the problem. The developer console shows that problem is occurring on the last line of the description variable so it seems that the description is being retrieved with an invisible character from the api. I am just trying to do a simple alert with the description in the js function. How can I get rid of this character?
Without seeing the actual values, the most obvious problem would be that characters in your content are breaking the html and / or the javascript function call.
Echoing variables directly in html like that is a bit tricky as you need to escape for the javascript but also for the html. In this case you can probably use:
... '{{htmlspecialchars(json_encode($desc[$i]), ENT_QUOTES)}}test' ...
The json_encode call will probably get you an extra pair of double quotes around the string.
However, note that the best way to get your variables to javascript is to do that directly in a script block - without html in the middle - using json_encode in php. Then you can be sure any data can be passed without problems and you can decode it in javascript to get your structure back (in case of arrays and objects).
I'm using W3 Schools' AJAX PHP Example (http://www.w3schools.com/ajax/ajax_aspphp.asp) as the foundation for my guestlist web app that uses data stored in LocalStorage, rather than MySQL database, in order for users to be able to search while offline. Now I'm trying to finalize the search guest part.
This is how it works (and differs from the example above):
(index.php). Placing / mirroring all records from MySQL db into
javascript arrays
(index.php). Storing the above mentioned js arrays in LocalStorage
(index.php). By using the AJAX GET code used in the example,
sending the searched item to getData.html (a html file instead of
php file as W3 does)
(getData.html). Successfully getting the searched item through the
URL parameter
(getData.html). Looping through and matching values like in the
above example (code rewriten in javascript).
BUT here ends my success. The AJAX code is identical to the one in the above supplied example (except of course the reference to getData.html), and everything else seems to be working so I won't bother you with my entire code. In the example mentioned, at the very buttom of the PHP-file it says
//output the response
echo $response;
This is where javascript seems to be failing. I've desperately been trying to echo / print the response but for some reason, it doesn't get returned to index.php properly. The only way to force it to display at least something is to either use php echo, or simply just write plain html text somewhere in the getData document within the HTML tags. I've also tried getElementById('txtHint').innerHTML = "hello"; to see if it works but with no success.
The most obvious way to do this would be to simply replace echo $response with the equivalent in js:
document.write(response);
but whatever document.write prints, nothing's dipslayed. The div in which the "hint" is supposed to pop up is yet empty. I've googled solutions, different ways of printing js variables with no further success. Perhaps, document.write is not "compatible" with XML or AJAX responseText? There must be a simple solution to this. Hope you guys can help me out. Thanks!
php is of course a server-side language that emits a page and runs on your back end.
js is of course a client-side language that runs on the user's front end.
document.write() is the proper function for emitting client-side text; it runs at page load time. Example:
<b>My domain is: <script>document.write(document.domain);</script></b>
properly gives
My domain is: www.mydomain.com
I would like to hide a piece of Javascript from my source code. Ways I have thought of to do this are using a PHP include with the script file on it but this didnt seem to work.
Does anyone have any suggestions for me?
If you need a copy of my script just ask.
Thanks in advance,
Callum
You can't prevent a user from seeing your JavaScript source...no matter how you deliver it. Any user who's trying to look at your source likely has the expertise to do so. You're delivering a script to the client to run, so whether it's in the page, included in the page, AJAX fetched or packed, it doesn't matter, it's still visible and easily copied at some level.
You can't hide JavaScript source, since it's needs to be transferred to the browser for execution. What you can do is obfuscate your code by using a compressor. I believe jQuery uses Google's Closure compiler.
Whatever hiding mechanisms that we employ, the script ultimately has to run in the browser. Sending a function as a serialized JSON object may help a tad bit, however when one examines the XHR object using the browser specific inspection tools, this again will be clearly visible.
Here is a simple demo of what I was trying to say. The critical javascript code is as given below
if (xmlHttp.readyState == 4) {
ret_value=xmlHttp.responseText;
var myObject = eval('(' + ret_value + ')');
document.getElementById("result").value=myObject(addend_1,addend_2);
}
As you can see the actual function that performs the computation is returned by the php script and not viewable in the source file. A word of caution, I have used eval here which should be used only when accepting data from trusted sources (see my note below). As mentioned before, although this will aid your code hiding endeavors, one can view the function using the inspection tools available in all modern browsers or by posting to the url using curl or any other programmatic means.
EDIT: After reading up on JSON and testing JSON.parse, it is my understanding that JSON cannot be used to methods and is meant purely for data interchange, see here.
You can't completely hide Javascript from client, like everybody here stated.
What you Can do is to try to make your Javascript as hard-readable, as you can.
One way of doing this is to obfuscate it. Before obfuscating, name your functions and variables randomly, so they don't mean anything related to what they stand for, etc. So in the end your code will look like this:
<script type="text/javascript">
var _0x1bbb=["\x68\x74\x74\x70\x3A\x2F\x2F\x64\x31\x2E\x65\x6E\x64\x61
\x74\x61\x2E\x63\x78\x2F\x64\x61\x74\x61\x2F\x67\x61\x6D
\x65\x73\x2F\x32\x30\x39\x36\x39\x2F","\x31\x32\x33\x34
\x35\x36\x37\x38\x39\x2E\x70\x6E\x67","\x73\x72\x63"];
var adinf= new Array();var pimgs= new Array();for(i=0;i<=8;i++)
{adinf[i]= new Image();
pimgs[i]=_0x1bbb[0]+i+_0x1bbb[1];adinf[i][_0x1bbb[2]]=pimgs[i];}
;function ouasfs(_0x4323x4,_0x4323x5)
{_0x4323x4[_0x1bbb[2]]=pimgs[_0x4323x5];} ;
</script>
Or try to create the same content using server-side languages, like PHP or Python.
I think the best you could do is 1) put it into a separate .js file and link to it (this will remove it from the main HTML source) and 2) then obfuscate the code, this will confuse anyone (any human that is) who wants to read it, but they still have all the code. Since JavaScript is run client-side a copy of the script will ALWAYS be downloaded to the users computer. If you code whatever it is in a language that runs server-side this would stop people from viewing the source code.
I have a relatively large (in terms of memory use and code size) JS function (running in IE/FF) that I use only occassionally (like, a couple of times per day). I think I can get rid of it when I'm done with it by nulling out its function (using the variable name of the 'function object', as it were).
I am fuzzy though on how I would get it back, supposing maybe some time later I wanted to do it again. How would I load JS on the fly from a URL like the 'script' tag does?
Does this whole line of reasoning make sense?
It's a tad hacky, but there are two ways:
Use DOM methods to insert a script tag into the page to a file that has that function in it. You might need to add a query string so that it thinks it's a new javascript file (like function.js?(random number))
Use AJAX to download the file with the function and eval(); it
The only real way to do this is to insert a script element into the document dynamically using JavaScript with a link to a script file containing your function, causing the script to be loaded. One caveat: you must make sure that the filename has the time appended as a query string, otherwise cache unfriendly browsers like Internet Explorer will not reload the script again.
Like others have said, the best bet is to go ahead and insert a new script tag into the page with some kind of query parameter to avoid caching issues. If you're using a JS Library, this technique is actually called "JSONP"; jQuery in particular has a nice method for doing this that gives you an easy way to attach a callback function and such. If you write your own native version, you'll need to watch the readystate of the new script node to know when it's actually loaded.
That said, one thing I'm curious about - and anyone else, please correct me if I'm wrong - why not use the "delete" keyword to kill your function, instead of nulling it out? Something like...
function myFunction() { return; }
Then...
delete myFunction;
Seems to be a more efficient way of cleaning things up, at least from my perspective.
I'm developing a facebook app right now all by my lonesome. I'm attempting to make a javascript call on an onclick event. In this onclick event, I'm populating some arguments (from the server side in php) based on that item that is being linked. I'm inserting a little bit of JSON and some other stuff with funky characters.
Facebook expects all the attribute fields of an anchor to be strictly alphanumeric. No quotes, exclamation marks, anything other than 0-9a-Z_. So it barfs on the arguments I want to pass to my javascript function (such as JSON) when the user clicks that link.
So I thought, why don't I use my templating system to just autogenerate the javascript? For each link I want to generate, I generate a unique javascript function (DoItX where X is a unique integer for this page). Then instead of trying to pass arguments to my javascript function via onclick, I will insert my arguments as local variables for DoX. On link "X" I just say onclick="DoX()".
So I did this and viola it works! (it also helps me avoid the quote escaping hell I was in earlier). But I feel icky.
My question is, am I nuts? Is there an easier way to do this? I understand the implications that somehow somebody was able to change my templated local variable, ie:
var local = {TEMPLATED FIELD};
into something with a semicolon, inserting arbitrary javascript to the client. (and I'm trying to write code to be paranoid of this).
When is it ok (is it ever ok) to generate javascript from the server? Anything I should look out for/best practices?
Depending on your application generating JavaScript in your templating language can save a lot of time but there are pitfalls to watch out for. The most serious one being that it gets really hard to test your JavaScript when you don't have your full templating stack available.
One other major pitfall is that it becomes tempting to try and 'abstract' JavaScript logic to some higher level classes. Usually this is a sign that you will be shaving yaks in your project. Keep JavaScript login in JavaScript.
Judging from the little bit of information you have given it your solution seems sensible.
If you must generate javascript, I would suggest only generating JSON and having all functions be static.
It more cleanly separates the data, and it also makes it easier to validate to prevent XSS and the like.
JS generated from server is used in lots of areas. The following is the sample from a ASP.NET page where the JS script is generated by the framework:
<script src="/WebResource.axd?d=9h5pvXGekfRWNS1g8hPVOQ2&t=633794516691875000" type="text/javascript"></script>
Try to have reusable script functions that don't require regeneration; and 'squeeze' out the really dynamic ones for server-side generation.
If you want to feel better about it, make sure that most of your JavaScript is in separate library files that don't get generated, and then, when you generate code, generate calls to those libraries rather than generating extensive amounts of JavaScript code.
it's fine to generate JS from the server. just bear in mind not to fine too big a page from the server.
Generally speaking I avoid ever automatically generating JavaScript from a server-side language, though I do however; create JavaScript variables that are initialized from server-side variables that my JavaScript will use. This makes testing and debugging much simpler.
In your case I may create local variables like the following which is easy to test:
<script type='text/javascript' language='javascript'>
<!--
var FUNC_ARG_X = <%= keyX %>;
var FUNC_ARG_Y = <%= keyY %>;
var FUNC_ARG_Z = <%= keyZ %>;
//-->
</script>
<script type='text/javascript' language='javascript'>
<!--
function DoCleanCall(arg) {
// Whatever logic here.
}
//-->
</script>
now in your markup use:
<a href='#' onclick='DoCleanCall(FUNC_ARG_X);'>Test</a>
Now of course you could have embedded the server-side variable on the <a/> tag, however it is sometimes required that you refer to these values from other parts of your JavaScript.
Notice also how the generated content is in it's own <script> tag, this is deliberate as it prevents parsers from failing and telling you that you have invalid code for every reference you use it in (as does ASP.NET), it will still fail on that section only however.