Tell the Closure Compiler not to rename any function - javascript

I want to compile part of my JS code which is based on Mootools library.
I want all the variables be renamed but none of the function, the called and defined ones. Because most of the called one are from mootools and those defined are called from outside:
code to be compiled:
// textnum is safe to be renamed, all variables are
textnum = 0;
// loadText can't be ranmed because is called from outside
function loadText()
{
textnum++;
document.body.setStyle("font", "12px");
// here setSyle can't be renamed
}
Is there a way to tell it to rename only vars?
I found out this is an open source project, Is there a way to manipulate it somehow that it doesn't touch function at all!?

Put the code to be compiled in a namespace or anonymous function wrapper and use simple optimizations. This renames all internal vars and functions but not global ones such as setStyle.
Functions which should not be renamed are defined in the global scope. This is not as much of a pain compared to defining externs and exports.

Related

Binding the require function in Node.js

I would like to include functions from a module into the current namespace. I was hoping I could utilize the bind function towards this goal, but I haven't got it working so far. Here's what I'm working with:
The module:
//exampleModule.js
this.fn = function(){return 7;}
The file which uses the module:
var example = require('./exampleModule.js')
console.log(example.fn())
What I'd like to do:
require.bind(this)('./exampleModule.js')
console.log(this.fn())
I was hoping that binding the 'this' from the non-module code would cause the module to load fn into that object, but that does not seem to be the case.
This isn't going to work, as I was confusing the 'this' within the context of my module with the 'this' within the context of the actual require function. Without knowing more about the internals of require, I don't know what binding would actually accomplish. This isn't the exact same thing, but omitting the var keyword allows modules to affect the global scope. (I'm sure this is obvious for those experienced with js..)
//exampleModule.js
fn = function(){return 7}
And the main file:
require ('./exampleModule')
console.log(fn())

Function Scope Rules (Google Apps Script Project)

If I have several files in a single Apps Script Project that have a function with the same name, how will the scope be determined?
By file?
By dynamic scoping?
By static scoping?
Time of function creation (script file created)?
For example if I have Stuff.gs:
function start() {
var number = getNumber();
}
function getNumber() {
return 5;
}
and More.gs:
function getNumber() {
return 10;
}
And I call start(), how does Google's platform determine which function to call?
I did a test like this, and I didn't get the expected output. The output is 10.0. It seems to me that neither file scope rules are applied, nor static scoping. I created a third file to test further:
Test.gs:
function getNumber() {
return 15;
}
and now the output is 15.0. I further tested and changed 10 to 20 in More.gs to see if the save timestamp determined the scope, but the output was still 15.0.
So to me it seems that the .gs file creation date determines the scope - the most recent timestamp on the file that contains the function name is used. Am I correct in my assumption or is this just a coincidence and it's determined in some other way?
Also, is this specific to Google's Apps Script, or Javascript in general?
Looks like those declarations are all just in global scope. Subsequent definitions will overwrite the previous ones, so if you are first including Stuff.gs, then More.gs, then Test.gs and are calling your function thereafter it would make sense.
The scoping in JS is static (assuming strict mode without with and local eval), but the global scope may be modified dynamically based on the loaded modules (and their order). This is the behaviour in the most JavaScript environments, some also have an additional file (module) scope.

How do I get my helper functions to load first? (Meteor, Node framework)

In my Meteor projects I have several helper functions of the sort
helpers.js
var tagStr = function () { return this.tags.join(', '); };
articles.js
Template.articles.tags = tagStr;
listing.js
Template.listing.tags = tagStr;
Now, I can define the function in either articles.js or listing.js, and it won't work in the other one. Or i can define it in helpers.js and it will work in neither..
So, how would I go about loading my helper functions before the rest of the scripts? Preferably in "the right way".
Thanks!
i think what you are looking for is a globally available handlebars helper - i keep mine in client/lib/handlebars.js - the contents of the 'lib' folder will get loaded first
define each helper like so:
Handlebars.registerHelper("joinArray", function(array) {
if(array)
return array.join(', ');
});
you would then use this in any template html file like so:
{{joinArray tags}}
you can read more about handlebars helpers here handlebarsjs.com/block_helpers.html
this is the 'right' way IMO, but if you want to use normal javascript functions and not handlebars helpers, that works also
you'll need to place the commonly used javascript function in a file like client/lib/helpers.js and do NOT use the 'var' declaration prefix
like so:
thisIsAGloballyAvailableFunction = function(){...};
not like:
var thisFunctionIsOnlyAvailableInThisFile = function(){...};
meteor does a slightly strange thing to control scoping. anything with 'var' is local to the scope of the file it occurs in, anything declared without 'var' is globally available across the app
The answer by nate-strauser was correct and helped me find the right solution but now (Meteor 1.0) Handlebars.registerhelper() is deprecated.
Now it works this way (if anyone is still interested):
Template.registerHelper()
The rest as explained by nate-strauser.

break js to files with $(document).ready() but keep scope

I would like to break my javascript code to several .js files. Each of those .js has code that need to be inside the $(document).ready(..). So in each file a new $(document).ready(..) will start.
How could I call from filea.js functions declared in fileb.js (both inside a $(document).ready block) ?
If this is not possible, can you propose an alternative?
Thank you.
Edit: I would like to clarify that I would like to avoid using the global scope. I was hoping something in the line of using named functions as handlers for the event but I can't really see how to do it.
You can make a local variable global with
window.globalname = localname;
Remember that functions are variables.
You really can't get away from declaring a global. Creating a single global isn't so bad, you can then namespace all your functions under it.
Put this in something like a main.js file, so you can keep your shared functions here:
// name this something unique to your page/site/app
var MYAPP = {};
// now we can attach functions to it
MYAPP.funcA = function() { /* ... */ };
MYAPP.funcB = function() { /* ... */ };
Then, in each of your anonymous functions you can access MYAPP.funcA(), MYAPP.funcB(), etc. You can also modify MYAPP on the fly to add functions, properties, etc.
In the end you have a single global (darn it!), but if you've named it properly you are creating a global namespace where your app code can safely reside.
As long as the files are loaded in order (i.e. functions in filea.js get loaded before fileb.js calls them, you should be fine.
In order to make sure files load their dependencies first, you could consider require.js or head.js
I've had luck with the latter: http://headjs.com/

Document.ready in external files?

I am referencing JavaScript as follows on an HTML page:
<script type="text/javascript" src="http://code.jquery.com/jquery-1.6.1.min.js"></script>
<script type="text/javascript" src="http://code.jquery.com/mobile/1.0b1/jquery.mobile-1.0b1.min.js"></script>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false&region=GB"></script>
<script type="text/javascript" src="js/shared.js"></script>
<script type="text/javascript">
$('document').ready(function() {
// In-page code: call some functions in shared.js
});
</script>
The functions defined in shared.js are not wrapped inside $('document').ready. So:
Is it safe to assume that functions defined in shared.js are available to the "in-page code"?
If I pull out the in-page code into a separate file called local.js (keeping it wrapped in $('document').ready), is it still safe to assume that functions defined in shared.js are available?
Finally, is the fact that I'm not wrapping shared.js inside $('document').ready a problem? I'm finding that if I do wrap it, its functions are no longer available to the in-page code.
The reason for question 3 is that I'm hitting this problem: Uncaught TypeError: Property ... is not a function - after page has loaded
and wondering if it is something to do with how I've organised my code.
UPDATE: Thanks for the answers. It's now clear that using $('document').ready in shared.js would remove those functions from global scope. However, I just want to clarify the original question in point 3.
Can I assume that if I do the following:
inside my in-page code, loaded inside $('document').ready, call a function from shared.js
have the function in shared.js refer to jQuery, Google Maps, or elements on my page
there will be no problems?
In other words, is it safe to assume that the page will have loaded by the time the functions inside shared.js are called, even if I'm not wrapping everything in that file inside $('document').ready?
Is it safe to assume that functions defined in shared.js are available to the "in-page code"?
Yes, As long as those functions are injected into global scope
If I pull out the in-page code into a separate file called local.js (keeping it wrapped in $('document').ready), is it still safe to assume that functions defined in shared.js are available?
Yes, As long as local.js is included after shared.js AND shared.js injects functions into global scope.
Finally, is the fact that I'm not wrapping shared.js inside $('document').ready a problem? I'm finding that if I do wrap it, its functions are no longer available to the in-page code.
Wrapping functions in document.ready takes them outside of global scope.
var foo = 4; // global
$(function() {
var bar = 5; // local
});
foo = bar; // error
You need to inject variables in global scope, this is as easy as doing
$(function() {
/* all your code */
window["SomeGlobalVariable"] = someFunctionIWantGlobal;
});
Yes
Yes
Maybe. If you wrap code in a function you will lose global access to functions defined. For the most part that's a good thing - not polluting the global namespace. You can still access these functions in the global namespace if instead of function foo(){} you do window.foo = function(){};.
This is all irrelevant however, because you either need a dom ready listener or you don't - depending on whether or not you're trying to access the dom in that code. If yes, then wrap it, if not, then don't. As mentioned, either way you can close over your code so as not to pollute the global namespace, or pollute it if you so desire.
It is safe to assume (if the definitions are not hidden inside a closure that cannot be accessed).
//shared.js
function DoThis() {}
function DoThat() {}
It will still work, just embed local.js after shared.js
<script type="text/javascript" src="js/shared.js"></script>
<script type="text/javascript" src="js/local.js"></script>
It did not work, because the functions were wrapped in a closure (the one that will be run on domready), so they are only available inside that closure
$(document).ready(function () { //this is a closure!
function DoSg() {}
//DoSg is only available inside the closure
//cannot be accessed from the outside, it's defined inside
});
Also, it is unnecessary to put function definitions into $(document).ready(). The part that matters is when you call these functions, that should be inside .ready() (well, if it involves DOM stuff or anything that should be done after page load).
Your code organisation is fine as presented. Any functions defined in "shared.js" will be available to the rest of your page, including your $('document').ready(function() block.
However, if you place the functions in shared.js within that block, then you limit the code's scope to the $('document').ready(function() (i.e. nothing else in the page can use it) -- so that's not the way to go if you want to make stuff in "shared.js" available to other parts of your code / application.
Finally, is the fact that I'm not
wrapping shared.js inside
$('document').ready a problem? I'm
finding that if I do wrap it, its
functions are no longer available to
the in-page code.
If you wrap your function inside document.ready those function are not available in the global scope, as function have local scope (I.E inside the function where they are contained)

Categories