jQuery/JS for different pages - best way of doing this? - javascript

Apologies if this is a silly question, and I'm not even sure of the best way of wording it...
At the moment I have a site with maybe 20+ different uses of jQuery, all varying from page to page. I'm just wondering what the best way is to store this code?
Everything in one big jquery.myfunctions.js file? And check if the element exists for each statement?
Embed script tags into each individual page?
Use PHP to deliver different content into script tags kinda like the above?
Separate .js files per page? ims I don't like the sound of this at all
To be honest, I'm not even sure if jQuery does this for you, so it's okay to have multiple $('#whatever').function() loaded onto each page without any noticeable performance issues?
Any advice on this would be fantastic, probably a silly question but I want to do things the 'proper' way you know?
Thanks :-)

Personnally I like to have one file with all the things needed in it. It's better because once loaded, the browser can cache it and you don't care anymore.
As for coding, I may write pieces of code in different files, which I build as a single file for production.
This way, all your code is accessible anytime.
Nevertheless, you may include tags in your views/templates, so that you can trigger certain functions only on particular views/pages.
For example :
myObject = {
myFunctionForArticles : function(){ $('.article').each(...); },
myFunctionForCategories : function(){ ... }
};
And within the Article view :
<script type="text/javascript">
myObject.myFunctionForArticles();
</script>
Make sure your included javascript keeps very thin and general though. More than one liners calling a general function can lead to trouble. In theory it is not something you might call a best-practise. Choose what you feel is the right balance between tidyness and easiness to maintain (if you have few views, maybe you can make, along with the one big file containing all the heavy stuff, some short and specific js files, which are called only by the right view to trigger the right functions at load time ; if you have a lot of views, maybe including one-liner inline js tags will save you the burden to maintain a lot of short files).

I've recently grappled with this problem when re-starting development of a very involved web app. I decided on several patterns:
do not put inline javascript on pages in general - it prevents caching and defeats the point of separating functionality from presentation
create your own namespace - I like the DOD approach to it (http://www.dustindiaz.com/namespace-your-javascript/) So, my namespace is DG, thus all of my code is part of a single global variable called DG - which is an object, containing all of the subclasses
Create a class prototype structure, where if you're doing common things with a bit of difference between implementations
for example, logging into different sites - you're doing logins, but, some may do it differently than others - so, create a prototype class than handles generic functionality, and then implement site-specific login functionality in classes that inherit from the prototype)
Use the Yahoo Module pattern for singletons, but don't fall in love with it - it's not useful if you have more than one instance per page of a class (http://www.yuiblog.com/blog/2007/06/12/module-pattern/)
use a require/import function to do dynamic imports of javascript
this one is an optional but great. I really like doing dependencies for javascript, so I don't have to include a ton of script tags in my code, and, it really does help with performance, as most require/import frameworks load JS on demand, not at first.

My thoughts:
Never put anything on the individual
pages themselves, always use .js
files
One big file doesn't take advantage of the browser's ability to load a larger JS file as lets say 3 smaller files on 3 different concurrent connections during that critical initial page load when people enter your website
Logically group functions in
different files such as files for
validation, presentation and calculations as this makes it easier to maintain as file sizes increase
Use JSMIn (Javascript Minifier) to reduce file sizes http://www.crockford.com/javascript/jsmin.html

Related

ES6 exports/imports use-case, compared to traditional namespacing

I don't understand WHY and in what scenario this would be used..
My current web setup consists of lots of components, which are just functions or factory functions, each in their own file, and each function "rides" the app namespace, like : app.component.breadcrumbs = function(){... and so on.
Then GULP just combines all the files, and I end up with a single file, so a page controller (each "page" has a controller which loads the components the page needs) can just load it's components, like: app.component.breadcrumbs(data).
All the components can be easily accessed on demand, and the single javascript file is well cached and everything. This way of work seems extremely good, never saw any problem with this way of work. of course, this can (and is) be scaled nicely.
So how are ES6 imports for functions any better than what I described?
what's the deal with importing functions instead of just attaching them to the App's namespace? it makes much more sense for them to be "attached".
Files structure
/dist/app.js // web app namespace and so on
/dist/components/breadcrumbs.js // some component
/dist/components/header.js // some component
/dist/components/sidemenu.js // some component
/dist/pages/homepage.js // home page controller
// GULP concat all above to
/js/app.js // this file is what is downloaded
Then inside homepage.js it can look like this:
app.routes.homepage = function(){
"use strict";
var DOM = { page : $('#page') };
// append whatever components I want to this page
DOM.page.append(
app.component.header(),
app.component.sidemenu(),
app.component.breadcrumbs({a:1, b:2, c:3})
)
};
This is an extremely simplified code example but you get the point
Answers to this are probably a little subjective, but I'm going to do my best.
At the end of the day, both methods allow support creating a namespace for a piece of functionality so that it does not conflict with other things. Both work, but in my view, modules, ES6 or any other, provide a few extra benefits.
Explicit dependencies
Your example seems very bias toward a "load everything" approach, but you'll generally find that to be uncommon. If your components/header.js needs to use components/breadcrumbs.js, assumptions must be made. Has that file been bundled into the overall JS file? You have no way of knowing. You're two options are
Load everything
Maintain a file somewhere that explicitly lists what needs to be loaded.
The first option is easy and in the short term is probably fine. The second is complicated for maintainability because it would be maintained as an external list, it would be very easy to stop needing one of your component file but forget to remove it.
It also means that you are essentially defining your own syntax for dependencies when again, one has now been defined in the language/community.
What happens when you want to start splitting your application into pieces? Say you have an application that is a single large file that drives 5 pages on your site, because they started out simple and it wasn't big enough to matter. Now the application has grown and should be served with a separate JS file per-page. You have now lost the ability to use option #1, and some poor soul would need to build this new list of dependencies for each end file.
What if you start using a file in a new places? How do you know which JS target files actually need it? What if you have twenty target files?
What if you have a library of components that are used across your whole company, and one of they starts relying on something new? How would that information be propagated to any number of the developers using these?
Modules allow you to know with 100% certainty what is used where, with automated tooling. You only need to package the files you actually use.
Ordering
Related to dependency listing is dependency ordering. If your library needs to create a special subclass of your header.js component, you are no longer only accessing app.component.header() from app.routes.homepage(), which would presumable be running at DOMContentLoaded. Instead you need to access it during the initial application execution. Simple concatenation offers no guarantees that it will have run yet. If you are concatenating alphabetically and your new things is app.component.blueHeader() then it would fail.
This applies to anything that you might want to do immediately at execution time. If you have a module that immediately looks at the page when it runs, or sends an AJAX request or anything, what if it depends on some library to do that?
This is another argument agains #1 (Load everything) so you start having to maintain a list again. That list is again going to be a custom things you'll have come up with instead of a standardized system.
How do you train new employees to use all of this custom stuff you've built?
Modules execute files in order based on their dependencies, so you know for sure that the stuff you depend on will have executed and will be available.
Scoping
Your solution treats everything as a standard script file. That's fine, but it means that you need to be extremely careful to not accidentally create global variables by placing them in the top-level scope of a file. This can be solved by manually adding (function(){ ... })(); around file content, but again, it's one more things you need to know to do instead of having it provided for you by the language.
Conflicts
app.component.* is something you've chosen, but there is nothing special about it, and it is global. What if you wanted to pull in a new library from Github for instance, and it also used that same name? Do you refactor your whole application to avoid conflicts?
What if you need to load two versions of a library? That has obvious downsides if it's big, but there are plenty of cases where you'll still want to trade big for non-functional. If you rely on a global object, it is now up to that library to make sure it also exposes an API like jQuery's noConflict. What if it doesn't? Do you have to add it yourself?
Encouraging smaller modules
This one may be more debatable, but I've certainly observed it within my own codebase. With modules, and the lack of boilerplate necessary to write modular code with them, developers are encouraged to look closely on how things get grouped. It is very easy to end up making "utils" files that are giant bags of functions thousands of lines long because it is easier to add to an existing file that it is to make a new one.
Dependency webs
Having explicit imports and exports makes it very clear what depends on what, which is great, but the side-effect of that is that it is much easier to think critically about dependencies. If you have a giant file with 100 helper functions, that means that if any one of those helpers needs to depend on something from another file, it needs to be loaded, even if nothing is ever using that helper function at the moment. This can easily lead to a large web of unclear dependencies, and being aware of dependencies is a huge step toward thwarting that.
Standardization
There is a lot to be said for standardization. The JavaScript community has moved heavily in the direction of reusable modules. This means that if you hope into a new codebase, you don't need to start off by figuring out how things relate to eachother. Your first step, at least in the long run, won't be to wonder whether something is AMD, CommonJS, System.register or what. By having a syntax in the language, it's one less decision to have to make.
The long and short of it is, modules offer a standard way for code to interoperate, whether that be your own code, or third-party code.
Your current process is to concatenate everything always into a single large file, only ever execute things after the whole file has loaded and you have 100% control over all code that you are executing, then you've essentially defined your own module specification based on your own assumptions about your specific codebase. That is totally fine, and no-one is forcing you to change that.
No such assumptions can be made for the general case of JavaScript code however. It is precisely the objective of modules to provide a standard in such a way as to not break existing code, but to also provide the community with a way forward. What modules offer is another approach to that, which is one that is standardized, and one that offers clearer paths for interoperability between your own code and third-party code.

JavaScript Hacking

I am trying to figure out any and all ways to prevent CSS modification and DOM modification of specific elements. I understand this might not be completely possible or that a talented developer could get around it, however, I am not so concerned about people potentially getting around it, I just want to stop newbies. In particular those using jQuery. An example would be to delete certain properties on prototype objects etc..
But why you need/want this? If you want to "protect" your code, you can use some JavaScript minifier as Google Closure Compiler or YUI compressor. They will rewrite your script and it will be difficult to read by a human. Nowadays, with tools like Firebug and Grease Monkey it's almost impossible to do what you want.
Don't use CSS or JavaScript :p Depend completely on server side checks etc.
You cannot stop anyone from messing with your javascript or your objects in the page. The way the browser is designed, your code and objects in your page are simply not protected. Everything from bookmarklets to javascript entered at a console to browser plug-ins can mess with your page and code and variables. That is the architecture of a browser.
What you can do is make things a little more difficult such that a little more work is required for some things. Here are a couple of things you could do:
Obfuscating/compressing/minimizing your code will do things like remove comments, remove whitespace, remove some linebreaks, shorten variable names, etc... That does not prevent anyone from modifying things, but does make it more work to understand and figure out.
Putting variables inside closures and not using globals. This makes it harder to directly modify variables from outside of your scripts.
Keep all important data and secrets on your server. Use ajax calls to ask the server to carry out operations using that data or secrets such that the important information is never available in the browser client.
You cannot keep anyone from modifying the DOM. There simply are no protections against that. Your code can check the DOM and refuse to operate if the DOM has been messed with in non-standard ways. But, of course, the code would then be modified to remove that check too.
If you are looking for a jquery specific solution a crude approach will involve altering the jQuery ($) function and replacing it with a custom one that delegates to the original function only if the provided selector does not match the element you want to secure.
(function(){
jQueryOrig = jQuery;
window.jQuery = window.$ = function(){
if (jQueryOrig("#secure").is(arguments[0])) {
throw new Error("Security breach");
} else return jQueryOrig.apply(this, arguments);
}
}());
Of course people using direct DOM manipulation would not be affected.
Also, if you are actually including arbitrary third party code in your production code, you should take a look at Caja ( http://code.google.com/p/google-caja/ ), which limits users to a subset of javascript capabilities. There is a good explanation regarding Caja here : http://due-diligence.typepad.com/blog/2008/04/web-20-investor.html .
This is possible but requires that the JS file to always be loaded from your server. Using observers you can lock CSS properties and using the on DOM remove/add listeners you can lock it to a parent. This will be enough to discourage most modification.
You can actually go a step further and modify core javascript functions making it nearly impossible to modify the DOM without loading the JS file locally or through a proxy. Further security can be added by doing additional domain checks to make sure the JS file is loaded from where it is supposed to be loaded from.
You can make everything in Flash. In Chrome, there's even a bug that prevents users from opening a console if the flash element has focus (not sure how exactly this works, but you can see an example at http://www.twist-cube.com or http://www.gotmilk.com). Even if users do manage to get a console open (which isn't that hard...), still about all you can do is change the shape of the element.

What's the best way to split up my Javascript or Coffeescript in a Rails app?

Let's say I have a rails app with a resource - User. I have javascript that should be available for any page that is served. I have javascript that should be available for any page that is served under User. And I have javascript that should be available for each specific action under User. In Rails 3.1 and higher, is there an easy way to make sure that my Javascript is only available to the pages that require it? What about coffeescript?
I think the linked item from Bob is relevant (there's a comment relating to trade-off of performance to number of files loaded), but I saw the question as being more about name spacing, scoping and structure.
To specifically answer the question (and assuming you're using jQuery), consider the following CoffeeScript:
$ ->
doSomething()
doSomethingElse("#some-element")
doSomething = ->
alert("I'm doing something")
doSomethingElse = (selector) ->
alert("I'm hiding something")
$(selector).hide()
The CoffeeScript compiler will wrap all of this within an anonymous function, and thus will only be available within a context from which the page is loaded (a script tag, or a controller-specific file, or the application.js for global visibility).
There are a couple of models to consider. A straightforward one is to follow the pattern of having "things" that are specific to a model, and those that are generally useful (global). So if I want a javascript function that's specific to User, then it goes in app/assets/javascripts/users.js.coffee, otherwise it needs to be global (in application.js.coffee).
A much more complete and complex solution is suggested by the rails-backbone gem, which has generators that create CoffeeScript models, views, templates and routers that replace a lot of what we would get with regular rails generate scaffold foo -- the same kinds of CRUD operations are done in an entirely different way, and the templates (embedded javascript) in particular are quite similar to ERB templates. This is more of a leap of faith, for me.
Whether in an application-wide file, or a controller-specific one or ones, in either case, the Asset Pipeline will glom all of the code together and send it all to the user (assuming you retain the default configuration), but that's a separate topic.
Not sure if this answers the question, you had, but I think it's important to distinguish between the delivery of assets, which Asset Pipeline does, and the execution of javascript, which is a matter of scoping, something CoffeeScript does a very nice job of, and which backbone.js takes even further.

Dynamically printing javascript

I recently ran into a situation where it made sense (at first at least) to have my server-side code not only "print" html, but also some of the javascript on the page (basically making the dynamic browser code dynamic itself). I'm just wondering if there is sometimes a valid need for this or if this can usually be avoided...basically from a theoretical perspective.
Update:
Just to give an idea of what I'm doing. I have a js function which needs to have several (the number is determined by a server-side variable) statements which are generating DOM elements using jQuery. These elements are then being added to the page. So. I am using a server-side loop to loop over the number of elements in my object and inside of this loop (which also happens to be inside of a js function) I am aggregating all of these statements.
Oh and these dom elements are being retreived from an xhr (so the number of xhr requests is itself a server-side dependency) and then processed using jQuery..which helps explain why im not just printing the static html to begin with. Sounds kind of ridiculous I'm sure, but its a complicated UI..still I'm open to criticism.
I can smell some code smell here... if you're having to generate code, it probably means one of:
you are generating code that does different things in different situations
you are generating same kind of functionality, only on different things.
In case 1, your code is trying to do too much. Break your responsibilities into smaller pieces.
In case 2, your code is not generic enough.
Yes there is sometimes a need and it is done often.
Here is a simple usage in an Asp.net like syntax
function SayHi( ){
alert( "Hello <%= UserName %>");
}
Just a suggestion. If your server-side is generating HTML/Javascript, then you're letting view-side logic creep into your server-side. This violates separation of concern if you're following an MVC-style architecture. Why not use a taglib (or something of that nature) or send JSON from the server-side?
One usefull feature is to obfuscate your javascript on the fly.. When combined with a caching mechanism it might actually be useful. But in my opinion javascript generation should be avoided and all serverside variables should be handed to the script from the templates (on class or function init) or retrieved using XMLHTTP requests.
If your application generates javascript code only for data (eq. you want to use data from sql in js), the better practice is to use JSON.
Yes, sometimes for some specific task it may be easier to generate javascript on the fly in a bit complex way, like in rails rjs templates or jsonp responses.
However, with javascript libraries and approaches getting better and better, the need for this is becoming less, a simple example you may have needed to decide on a page whether to loop some elements and apply something or hide another single element, with jquery and other libraries, or even one's own function that handles some complex situation, you can achieve this with a simple condition and a call.

A question about referencing functions in Javascript

The problem: I have a jQuery heavy page that has a built in admin interface. The admin functions only trigger when an admin variable is set. These functions require a second library to work properly and the second file is only included if the user is an admin when the page is first created. The functions will never trigger for normal users and normal users do not get the include for the second library.
Is it bad to reference a function does not exist in the files currently included even if that function can never be called? (does that make sense :)
Pseudocode:
header: (notice that admin.js is not included)
<script type="text/javascript" src="script.js"></script>
<script type="text/javascript" src="user.js"></script>
script.js: (admin functions referenced but can't be executed)
admin = false; // Assume this
$(".something").dblclick(function(){
if(admin)
adminstuff(); // Implemented in admin.js (not included)
else
userstuff();
});
Ideas:
I suppose two separate files for users and admins could be used but I feel that would be an overly complicated solution (don't want to maintain two large files with only a few lines of difference). The only reason I include a reference to the admin function in this file is I need to attach it to page elements that get refreshed as a part of the script. When jQuery refreshes the page I need to reattach function to interactive elements.
The Question:
I want to keep things very simple and not have to include file I don't have to if they will not be used by the user. Is this a good way to do this or should I be going another route?
The code should operate without error, since the admin functions without implementation will not be called. The only thing that is really being wasted is bandwidth to transmit the admin code that is not used.
However, let me caution against security through obscurity. If the user were to view this code and see that there are admin functions that they cannot access, they might get curious and try to download the "admin.js" file and see what these functions do. If your only block to keeping admin functions from being performed is to stop including the file, then some crafty user will probably quickly find a way to call the admin functions when they should not be able to.
If you already do server side authentication/permissions checking for the admin function calls just ignore my previous paragraph :-)
Personally, I would bind (or re-bind) the event in admin.js:
$(function() {
$(".something").dblclick(function(){
adminstuff();
});
});
function adminstuff()
{
// ...
}
That way, the adminstuff() call and the function will not be visible to "normal" users.
Good question. It shouldn't cause any JavaScript problems.
Other things to consider: you are potentially exposing your admin capabilities to the world when you do this, which might be useful to hackers. That's probably not much of a concern, but it is something to be aware of.
See also:
Why can I use a function before it’s defined in Javascript?
I don't think it matters. If it makes you feel better, you can make an empty stub function.
I don't think there's a dogmatic answer to this in my opinion. What you're doing is...creative. If you're not comfortable with it, that could be a sign to consider other options. But if you're even less comfortable with those then that could be a sign this is the right thing (or maybe the least wrong thing) to do. Ultimately you could mitigate the confusion by commenting the heck out of that line. I wouldn't let yourself get religious over best practices. Just be willing to stand by your choice. You've justified it to me, anyway.
Javascript is dynamic - it shouldn't care if the functions aren't defined.
If you put your admin functions in a namespace object (probably a good practice anyway), you have a couple of options.
Check for the existence of the function in the admin object
Check for the existence of the admin object (possibly replacing your flag)
Have an operations object instead, where the admin file replaces select functions when it loads. (Even better, use prototypical inheritance to hide them.)
I think you should be wary that you are setting yourself up for massive security issues. It is pretty trivial in firebug to change a variable such as admin to "true", and seeing as admin.js is publically accessible, its not enough to simple not include it on the page, as it is also simple to add another script tag to the page with firebug. A moderately knowledgeable user could easily give themselves admin rights in this scenario. I don't think you should ever rely on a purely client side security model.

Categories