Timing issues with overriding js functions across files - javascript

In my rails project, I've written a javascript function to override the default behaviour of an object in another defined in another file. The line that did this looked something like:
window.someObject.methodToOverride = function...
Initially this would get me a cannot set property 'methodToOverride' of undefined error, which I'm assuming was related to the a timing issue (with someObject not being setup yet). I was able to resolve the issue by chucking it in a jQuery $(document).ready function, but while that works, it seems a bit hacky to me.
Is there a better way to do this?

This sounds like you're looking for require.js. What it does is let you set up your code modularly, defining which module depends on which. In your case, once it's set up, by putting a wrapper such as
require(["someObject"], function (someObject) {
someObject.methodToOverride = function...
}
will make it so when you got to this function, require.js would dynamically load your someObject file, and when it was fully loaded, pass someObject as a parameter into the function you provided. It can work with much more complicated examples, with any level and any number of dependencies, loading them no more than once on an as-needed basis.
You can find a lot more information on require.js all over SO, e.g.:
simple example for using require.js
Require.js nested requires

Related

Is there a way to tell Google Closure Compiler to *NOT* inline my local functions?

Here's what I'm looking for:
I want to use the wonderful features of SIMPLE mode minification while disabling just one specific feature (disable local function inline).
UPDATE: The answer is NO, it's not possible given my setup. But for me there is a workaround given I am using Grails.
As #Chad has explained below, "This violates core assumptions of the compiler". See my UPDATE3 below for more info.
IN QUESTION FORM:
I'm using CompilationLevel.SIMPLE_OPTIMIZATIONS which does everything I want, except that it's inlining my local functions.
Is there any way around this? For example, is there a setting I can place in my JS files to tell Google Closure not to inline my local functions?
It would be cool to have some directives at the top of my javascript file such as:
// This is a JS comment...
// google.closure.compiler = [inlineLocalFunctions: false]
I'm developing a Grails app and using the Grails asset-pipeline plugin, which uses Google Closure Compiler (hereafter, Compiler). The plugin supports the different minification levels that Compiler supports via the Grails config grails.assets.minifyOptions. This allows for 'SIMPLE', 'ADVANCED', 'WHITESPACE_ONLY'.
AssetCompiler.groovy (asset-pipeline plugin) calls ClosureCompilerProcessor.process()
That eventually assigns SIMPLE_OPTIMIZATIONS on the CompilerOptions object. And by doing so, CompilerOptions.inlineLocalFunctions = true as a byproduct (this is hard coded behavior in Compiler). If I were to use WHITESPACE_ONLY the result would be inlineLocalFunctions=false.
So by using Asset Pipeline's 'SIMPLE' setting, local functions are being inlined and that is causing me trouble. Example: ExtJS ext-all-debug.js which uses lots of local functions.
SO post Is it possible to make Google Closure compiler *not* inline certain functions? provides some help. I can use its window['dontBlowMeAway'] = dontBlowMeAway trick to keep my functions from inlining. However I have LOTS of functions and I'm not about to manually do this for each one; nor would I want to write a script to do it for me. Creating a JS model and trying to identity local functions doesn't sound safe, fun nor fast.
The previous SO post directs the reader to https://developers.google.com/closure/compiler/docs/api-tutorial3#removal, where the window['bla'] trick is explained, and it works.
Wow thanks for reading this long.
Help? :-)
UPDATE1:
Okay. While spending all the effort in writing this question, I may have a trick that could work. Grails uses Groovy. Groovy makes method call interception easy using its MetaClass API.
I'm going to try intercepting the call to:
com.google.javascript.jscomp.Compiler.compile(
List<T1> externs, List<T2> inputs, CompilerOptions options)
My intercepting method will look like:
options.inlineLocalFunctions=false
// Then delegate call to the real compile() method
It's bed time so I'll have to try this later. Even so, it would be nice to solve this without a hack.
UPDATE2:
The response in a similar post (Is it possible to make Google Closure compiler *not* inline certain functions?) doesn't resolve my problem because of the large quantity of functions I need inlined. I've already explained this point.
Take the ExtJS file I cited above as an example of why the above similar SO post doesn't resolve my problem. Look at the raw code for ext-all-debug.js. Find the byAttribute() function. Then keep looking for the string "byAttribute" and you'll see that it is part of strings that are being defined. I am not familiar with this code, but I'm supposing that these string-based values of byAttribute are later being passed to JS's eval() function for execution. Compiler does not alter these values of byAttribute when it's part of a string. Once function byAttribute is inlined, attempts to call the function is no longer possible.
UPDATE3: I attempted two strategies to resolve this problem and both proved unsuccessful. However, I successfully implemented a workaround. My failed attempts:
Use Groovy method interception (Meta Object Protocol, aka MOP) to intercept com.google.javascript.jscomp.Compiler.compile().
Fork the closure-compiler.jar (make my own custom copy) and modify com.google.javascript.jscomp.applySafeCompilationOptions() by setting options.setInlineFunctions(Reach.NONE); instead of LOCAL.
Method interception doesn't work because Compiler.compile() is a Java class which is invoked by a Groovy class marked as #CompileStatic. That means Groovy's MOP is not used when process() calls Google's Compiler.compile(). Even ClosureCompilerProcessor.translateMinifyOptions() (Groovy code) can't be intercepted because the class is #CompileStatic. The only method that can be intercepted is ClosureCompilerProcessor.process().
Forking Google's closure-compiler.jar was my last ugly resort. But just like #Chad said below, simply inserting options.setInlineFunctions(Reach.NONE) in the right place didn't resurrect my inline JS functions names. I tried toggling other options such as setRemoveDeadCode=false to no avail. I realized what Chad said was right. I would end up flipping settings around and probably destroying how the minification works.
My solution: I pre-compressed ext-all-debug.js with UglifyJS and added them to my project. I could have named the files ext-all-debug.min.js to do it more cleanly but I didn't. Below are the settings I placed in my Grails Config.groovy:
grails.assets.minifyOptions = [
optimizationLevel: 'SIMPLE' // WHITESPACE_ONLY, SIMPLE or ADVANCED
]
grails.assets.minifyOptions.excludes = [
'**ext-all-debug.js',
'**ext-theme-neptune.js'
]
Done. Problem solved.
Keywords: minify, minification, uglify, UglifyJS, UglifyJS2
In this case, you would either need to make a custom build of the compiler or use the Java API.
However - disabling inlining is not enough to make this safe. Renaming and dead code elimination will also cause problems. This violates core assumptions of the compiler. This local function is ONLY referenced from within strings.
This code is only safe for the WHITESPACE_ONLY mode of the compiler.
Use the function constructor
var fnc = new Function("param1", "param2", "alert(param1+param2);");
Closure will leave the String literals alone.
See https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Function

Defining Durandal ViewModel with TypeScript

How can I do this?
Some of the examples I have seen, look horrible for example, the following, which does not read like an OO code at all, and hence what's the point of TypeScript if it's gonna be a hack. I can't exactly get intellisense on the following at all, since there's no class definition. So I have a compiled code, with no intellisense, without being able to enforce encapsulation etc - so why bother wasting time?
/// <reference path="../durandal/durandal.d.ts" />
/// <reference path="../../scripts/knockout.d.ts" />
import app = require("durandal/app");
import http = require("durandal/http");
export function activate() {
.
.
.
}
Other examples are even more funky, by exporting a variable declaration.
The resulting code is not much better, it's DI-ing this variable called exports And the code just keeps adding properties to it, which does not make sense.
If I were to write this all in javascript, I return a new object may be in JSON notation - that I can understand, a proper factory method/class. A lot less work, cleaner and no time wasted compiling.
So can someone explain what's going on?
Why is the code creating properties on a DI-ed exports object? It's like a mutant pass by reference.
Is there a more OO way of doing this? I can see myself exporting a class, but this is just too weird and goes against everything I believe to be right and just. Ok that was an exaggeration, but sure feels that way.
The resulting code is not much better, it's DI-ing this variable called exports And the code just keeps adding properties to it, which does not make sense.
This is the way web (amd) works. Its dependent on requirejs : http://requirejs.org/ and even jquery (pick any file from https://github.com/jquery/jquery/tree/master/src) uses a similar pattern e.g. : https://github.com/jquery/jquery/blob/master/src/deferred.js#L1-L5
If I were to write this all in javascript, I return a new object may be in JSON notation - that I can understand, a proper factory method/class. A lot less work, cleaner and no time wasted compiling.
You can do this with TypeScript as well by not using external modules and compiling with --out flag.
Why is the code creating properties on a DI-ed exports object? It's like a mutant pass by reference.
Is there a more OO way of doing this? I can see myself exporting a class, but this is just too weird and goes against everything I believe to be right and just. Ok that was an exaggeration, but sure feels that way.
You need to learn about External / Internal modules. In a nutshell external modules depend upon a module system (amd for the browser, provided by e.g. requirejs, commonjs for the server e.g nodejs). If you've never heard of amd/commonjs you probably shouldn't care. EXCEPT the library you are trying to use (durandal) needs you to use it. This means your javascript code would not be as simple as you think it would be.
PS: I have a video explaining typescript module systems : http://www.youtube.com/watch?hd=1&v=KDrWLMUY0R0

How do you fix file load order problems using Meteor.startup?

Many resources on the internet (including here) suggest using Meteor.startup to fix dependency issues caused by the order in which JS files load. However, nobody spells out exactly how this is accomplished.
Specifically, it seems like file order dependency is the reason I can't get my posts.coffee collection to recognize permissions defined in my permissions.coffee. I think this is happening because posts.coffee is in /lib/collections, whereas permissions.coffee is in /lib, and files in subdirectories get loaded first. (Incidentally, I would prefer /collections to be in the root directory, but I had to move it into /lib previously to solve a similar problem.)
Here is my posts.coffee:
#Posts = new Meteor.Collection('posts')
Posts.allow(
update: ownsDocument
remove: ownsDocument
)
Meteor.methods(
...
And here is my permissions.coffee:
#ownsDocument = (userId, doc)->
doc && doc.userId == userId
(This is all from the "Discover Meteor" book tutorial, by the way, around these commits, except in CoffeeScript.)
My question: Assuming my analysis of the problem is correct, how would you solve it using Meteor.startup? This answer is hard for me to interpret; one interpretation is that I should wrap Posts.allow(...) in Meteor.startup somehow, but that seems really clumsy. Maybe I'm wrong, but it seems like there should be one general/config file with all the necessary startup code, and specific controllers should remain ignorant of it.
BTW, I realize I could hack a solution by taking advantage of Meteor's default file load ordering rules (e.g. /lib first; subdirectories first; main.* last; alphabetically), but that's a really inelegant solution to what should be a simple problem. I don't want to have to append "a" in front of a filename or create spurious directories just to get it load before another file.
One last note: I'm using CoffeeScript, and I wonder if the way CS handles global scope has something to do with it. (E.g., instead of defining my Posts collection as a JS variable without the var keyword, in CS I have to define is as #Posts, which I believe makes it a property of the window.)
Yes, you do just that:
Meteor.startup ->
Posts.allow(
...
)
Basically, any piece of code that uses a variable defined in another file should be preceded by Meteor.startup ->, unless you are sure that the loading order is correct (the variable is in lib, for example).
Yes, the loading order is poorly chosen.
I highly suggest you consider working entirely out of smart packages. That's how Meteor itself is largely written.
I go into more detail here: http://www.matb33.me/2013/09/05/meteor-project-structure.html

Javascript .js File Guidelines - How do I use a function outside of this file?

So two part question here. Basically, what is the proper practise for javascript function locations? I assumed it would be to have several MyScriptFile.js files, each with a few functions instead of one huge AllMyScripts.js file, as not every page needs every function.
However I'm not sure how to reference another function from outside of this file...
My situation: I'm using an AJAX request in many of my pages. Each request response is different (drawn from different files, etc) and is very hard to make dynamic (one-script-fits-all would be difficult). However, I do have my MakeAJAXRequest() function which creates the request object, which is standard to all DoSomethingWithRequest() functions.
How do I include MakeAJAXRequest() in the other files which contain the DoSomethingWithRequest() functions? It seems as though I should have been able to find this.. but I havn't come across it.
tl;dr I have MakeObject.js and UseObject.js. How does UseObject() reference MakeObject()?
EDIT: Found that if you include MakeObject BEFORE UseObject in your HTML <script> tags, UseObject will be able to reference MakeObject. Seems a little dirty still, as anybody who wants to use the UseObject script will have to be aware of the MakeObject dependency...
If you want to ensure your dependencies are loaded, you could use a function such as this: http://phpjs.org/functions/include:433 There is also include_once(), require(), and require_once()

proper sequence of functions when coding in js

I am using jquery and am really frustrated at how I write my code. I started coding in JS and Jquery a few months ago and my code looked like this:
$(document).ready(function(){
$(function(){// a function that applies a plugin to an element});
$(function(){// another function that applies a plugin to an element});
$(function(){// and another function that applies a plugin to an element});
$(function(){// yet another function that applies a plugin to an element});
});
$(function(){//functions applied to certain elements that does not require to be initially loaded})
basically what I did before was put everything inside the $(document).ready
and here's how I am coding now
function a(){//a function that applies plugin to an element}
function b() {// another function}
$(document.ready(function(){a(); b();});
$(function(){//functions applied to certain elements that does not require to be initially loaded})
a little improvement, yet I am not satisfied. What if I want to call certain functions for a certain page only? are there ways to accomplish this? and I am really disgusted at how my $(document) gets really huge when I am using a lot of plugins.
How do you go about writing your functions in jquery?
I'd suggest at least namespacing things to ensure you don't pollute the global namespace. For example:
var myNameSpace = {
a: function(){//a function that applies plugin to an element},
b: function() {// another function}
};
$(document).ready(function() {
myNameSpace.a();
});
The main benefit is that you're able to compartmentalize your code into logical units of work which focus on specific tasks. It'll make code organization substantially easier.
Rebecca Murphey did a wonderful write-up on this topic which you can read here: http://bit.ly/6og36U
You can also separate your JS into their own unique files and write a routine to leverage jQuery's getScript() method to load the necessary files on-demand (http://docs.jquery.com/Ajax/jQuery.getScript). The key would be to determine the dependencies in your script and load the .js file at the appropriate time.
I recommend having one Javascript file for the whole site. That file should only contain functions:
function a() { ... }
function b() { ... }
The reason is that with one file it gets cached once (if done right) and that's it. And then using inline JS on each page I put:
$(function() {
a();
b();
});
I haven't really found a need to have multiple ready() calls.
The reason for this is efficiency. You don't want to be executing unnecessary Javascript and what's why the external JS file actually does nothing but include functions that you can call. Then each page only calls what it needs. Plus you can easily find it by just looking at one place (the page).
You might try to split your functions into multiple files and include just those which are needed for each page. In each file would be separate $(document).ready(function(){ ... });
I think there are two ways of achieving this:
A: split JavaScript into several files. (One library file and each with the side - specific code which also call the ready function.)
B: make one file with all the JavaScript and then some inline JavaScript file like this:
var tasksToRun = [ function_a, function_b,...]
In your library JavaScript you check for the global var and execute each function referenced in the array.
In my apps I tend to write all the functions for a given section of the app in within a closure to avoid namespace issues.
Something like this:
(function($) {
function a() {
// stuff
}
function b() {
// stuff
}
// ...
$(function() {
// invoke dom ready setup methods here
});
})(jQuery);
This has a bonus of letting my code be usable in other pages that may be using prototype or other js libraries (in large webapp with many devs like the one i work on, it's important to keep the namespace clean).
I generally only have one ready call per file. That call is responsible for setting up all the related things in that file. This allows each file to sort've act as a "library": developers that want to use the functionality just have to include it on the page and add the appropriate markup and the functionality will set itself up.
I admit I copied this layout from the way several jQuery plugins are built.
I like cletus' suggestion of a single file, but only when the app isn't too large. It starts to be difficult to maintain if you have too many things within a single file.

Categories

Resources