This is a really newbie question.
I've managed to get some jQuery stuff running quite smootly but i ended up having many
events like this one..
<div class="aClass" id="B436" onclick="updateSearch('B436', '','Brand','193557', 0)">My Name</div>
Now i'm wondering if it's "safe" to put all my necessary function variables in this way. I check everything in the function so even if with firebug someone change some values they can't hurt much but... is this the correct way to do ?
Thanks
It's most likely safe. However, it's not considered very good practice to put handlers in onclick or any other attribute of an element, especially considering you have jQuery. You should do it using .click() instead:
$('#B436').click(function() {
updateSearch('B436', '', 'Brand', '193557', 0);
});
for example.
If, however, anything of any remote security concern can be done using JavaScript, it probably shouldn't be done in JavaScript.
It's not a matter of safety per se, but more of a readability issue.
When you keep your webpage components isolated from one another (stylesheets in a CSS file, JavaScript in a JS file, and HTML in its own file), you are less prone to losing code in your wall of text.
I personally find it easier to use jQuery to attach the handler, as I don't have to worry about messing with HTML attributes.
But then again, unreadable code is prone to breaking.
It's one way to do it. The only way it could be unsafe is if you were using the variables foolishly - like ajaxing your database directly without purifying the variables or something.
It also depends on what you call safe. Anyone can run firebug and mess with any site, but it will only be for them. It's not like changing the dom with firebug is considered a bug or anything and it's certainly not "hacking" since you stand to gain nothing from doing so.
If you want safety in this case, You must have server side validation.
It doesn't matter if you use jQuery or not.
Related
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.
Let's say I have markup like this:
<form action="foo">
<input name="bar" />
<button type="button">Save</button>
</form>
<script>
function baz() {
// Submit form via AJAX
}
</script>
Is it better to add this to the <button>:
onclick="baz()"
or to add this to the <script> (assuming jQuery):
$(function(){
$('button').on('click', baz);
});
I've seen much ado about best practices forbidding inline javascript, and I tend to agree. But I'm wondering if the manual wiring on document load/ready obfuscates what's going on since it removes the context of said wiring that is present when onclick="baz" is used.
Are there maintainability issues either way? Other pros/cons to either approach? My question at heart is what is the industry consensus on this particular aspect of using inline javascript (given that in general it's not a good coding practice)?
The second way is considered better
$(function(){
$('button').on('click', baz);
});
It is referred to as Unobtrusive JavaScript where you separate the functionality/behavior from the page structure.
As a professional developer, I'm wholly unconvinced that the second method at all disentangles the javascript from the page structure. They're functionally equivalent, and to add an unnecessary layer of abstraction only confuses the issue.
Functional equivalence:
They both make assumptions about the javascript to be attached.
The former presumes the existence of baz()
The latter presumes the existence of $('button').on('click', baz);
Neither does anything without said javascript - they;re completely broken.
More importantly, they each have their issues. I support inline javascript, for a few reasons:
The ability to readably pass in arguments [onClick="baz(this)"] allows you to generate more variable code without all the general unreadability that comes with javascript.
Maintainability skyrockets. All I have to do is find "function baz(" in my scripts, and I've started debugging, as opposed to the former, which can be attached via any method of selecting the item - IDS that may appear throughout your code, classes, and other CSS Selectors.
I believe that as much work as can be done server side really should be. It's easy to upgrade and bug test on your servers. It's much, much harder to imagine every possible test case your client might have. The more work your computers do, the more you control in the execution of the function.
It saves people from the hideous temptation of dynamically generated JS.
I am learning jquery and started my first attempt at building a form validation script based on what I know so far (which isnt much).
This is really only the Radio button portion of the validation script, but I thought I get on the right track -coding wise- before I went too far. There are some fundamental issues that I know need addressing.
The Script (jsFiddle): http://jsfiddle.net/pkdsleeper/xNt5n/
The Questions:
a. How best to remove the global variables using
b. jsLint recommends "use strict", so I added it, but im not sure what it does.
c. any good refs?
d. Generally, feel free to rip this code apart (cuz I AM trying to learn) but
please explain my errors in noob-speak :)
Thanks In advance
sleeper
a. How best to remove the global variables using
Wrap it in an anonymous function and assign it to the form as a submit listener.
b. jsLint recommends "use strict", so I added it, but im not sure what it does. any good ref's?
Don't bother. It's just a buzz-word for those trying to be hip. You can't use strict mode features on the general web because way too many browsers don't support them. You can use it with otherwise compliant ES 3 code, but it's only useful as a debugging tool for errors that should have been found during testing anyway (e.g. calling constructors without new).
No c?
d. Generally, feel free to rip this code apart (cuz I AM trying to learn) but please explain my errors in noob-speak :)
> $rdoGroup = [], // an empty array which will be used to hold
You seem to be using $ to indicate a variable that references a jQuery object, but $rdoGroup is just an array. That may be confusing later.
> $rdoGroup.push($(this).attr("name"));
The $ function is very expensive, don't use it if you don't need to. Standard HTML attributes are available in all browsers as DOM properties, so:
$rdoGroup.push(this.name);
Is up to 100 times more efficient, depending on the browser.
> for (i = 0; i < $rdoGroup.length; i++) {
> if ($rdoGroup[c].toString() !== $(this).attr("name").toString()) {
The values assigned to $rdoGroup are strings, calling their toString method is redundant.
As above, use this.name. The name property is a string, so no need for toString.
I think the exercise would be easier without jQuery, which seems to be getting in the way far more than helping. If you are trying to learn javascript, I'd suggest that you learn javascript without using any library.
Once you are reasonably confident with using javascript, then you are far better equipped to use a library for the things the library is good with, and not using it for the things it isn't good at.
a. Well, you got rid of the globals pretty well. But as your code looks right now, you can wrap the entire thing in (function(){ ... all your current code in here ... }()) and leave nothing behind in global scope.
b. For "use strict" see this question
c. typeof questions['c'] === "undefined"...
d. Currently, your js is too tied to the markup (html) and vice-versa. If you add or remove something in the form, you'll have to edit your js. If you want to use the validation for another form, you'll have to start the whole thing over again.
Validators are prime candidates for "unobtrusive javascript"/progressive enhancement (here's some material: A List Apart & Wikipedia). Basically, your markup (the html), your styling (the css), and your "behaviors" (the javascript) should all be separate, so they can be changed independently. Here's something you can try:
Add a class name to your form(s) (e.g. "validate")
Set up your js to look for form.validate when the page has loaded
For each form it finds, add a submit event handler
When the handler fires, you search the given form for inputs with various other class names you specify (e.g. "required" or "phone-number" or whatever). The class names tell your code, what kinds of validations should be done. For instance, <input type="text" class="required zip-code"> would mean that a) it's a zip-code, and b) it's a required field.
If there are any validation errors, cancel the submit and alert the user somehow. Otherwise, let the submit proceed.
That's obviously a very rough outline, but I'm not gonna write your code for you :)
The point is, that if you ever need more forms or different forms or something like that you have a generic validation script, and all you need to do is "mark" the inputs with the appropriate class names.
All that being said: There are tons of jQuery plugins out there that do form validation. It's definitely still a good exercise to write one yourself, but it's also a good idea to look at what's already there, and how it works. Don't look at the code right away, but read up on how those validators are used (e.g. do they use class names or something else?) and try to figure out how they work.
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.
You know what I liked best about obtrusive javascript? You always knew what it was going to do when you triggered an event.
<a onclick="thisHappens()" />
Now that everybody's drinking the unobtrusive kool-aid it's not so obvious. Calls to bind events can happen on any line of any number of javascript file that get included on your page. This might not be a problem if you're the only developer, or if your team has some kind of convention for binding eventhandlers like always using a certain format of CSS class. In the real world though, it makes it hard to understand your code.
DOM browsers like Firebug seem like they could help, but it's still time consuming to browse all of an element's event handler properties just to find one that executes the code you're looking for. Even then it usually just tells you it's an anonymous function() with no line number.
The technique I've found for discovering what JS code gets executed when events are triggered is to use Safari's Profiling tool which can tell you what JS gets executed in a certain period of time, but that can sometimes be a lot of JS to hunt through.
There's got to be a faster way to find out what's happening when I click an element. Can someone please enlighten me?
Check out Visual Event... it's a bookmarklet you can use to expose events on a page.
If you're using jQuery you can take advantage of its advanced event system and inspect the function bodies of event handlers attached:
$('body').click(function(){ alert('test' )})
var foo = $('body').data('events');
// you can query $.data( object, 'events' ) and get an object back, then see what events are attached to it.
$.each( foo.click, function(i,o) {
alert(i) // guid of the event
alert(o) // the function definition of the event handler
});
Or you could implement your own event system.
To answer your question, try using the Firebug command line. This will let you use JavaScript to quickly grab an element by an ID, and then iterate through its listeners. Often, if used with console.log, you'll even be able to get the function definitions.
Now, to defend the unobtrusive:
The benefit I find in unobtrusive JavaScript is that it is a lot easier for me to see the DOM for what it is. That said, I feel that it is generally bad practice to create anonymous functions (with only few exceptions). (The biggest fault I find with JQuery is actually in their documentation. Anonymous functions can exist in a nether-world where failure does not lead to useful output, yet JQuery has made them standard.) I generally have the policy of only using anonymous functions if I need to use something like bindAsListener from Prototype.
Further, if the JS files are properly divided, they will only be addressing one sub-set of the DOM at a time. I have an "ordered checkbox" library, it is in only one JS file which then gets re-used in other projects. I'll also generally have all of the methods of a given sub-library as member methods of either a JSON object or a class and I have one object/class per js file (just as if I were doing everything in a more formalized language). If I have a question about my "form validation code", I will look at the formValidation object in formvalidation.js.
At the same time, I'll agree that sometimes things can become obtuse this way, especially when dealing with others. But disorganized code is disorganized code, and it is impossible to avoid unless you are working by yourself and are a good programmer.
In the end, though, I would rather deal with using /* */ to comment out most of two or three js files to find misbehaving code, then go through the HTML and remove the onclick attributes.
Calling it "kool-aid" seems unfair. DOM Level 2 events solve specific problems with inline event handling, like the conflicts that always result. I don't look back to writing code to use window.onload that has to check whether someone else has assigned it before, and sometimes having it overriden by accident or out of sloppiness. It also ensures a better separation of the structure (HTML) and behaviour (JS) layers. All in all, it's a good thing.
Regarding debugging, I don't think there's any way to solve the event handlers being anonymous functions, other than nagging the authors to use named functions where possible. If you can, tell them that it produces more meaningful call stacks and makes the code more maintainable.
One thing: you shouldn't be able to see what will happen in JavaScript by looking at the HTML code. What nuisance is that? HTML is for structure.
If you want to check what events are bound to certain elements, there's a bookmarklet called visual event for now, and firebug 1.6 (IIRC) will have some sort of event inspector.