javascript - using function calls in html - bad or good? - javascript

Using angular brings lot of weird style of code. For example I always thought that this
<button onclick="myFunction()">Click me</button>
style I should not ever use, except when I would be lazy and want quick and dirty code. And I never used such style in projects and also I even thinked that this is bad.
Now when I see angular
here is the example:
<div enter="loadMoreTweets()">Roll over to load more tweets</div>
which is from there
http://www.thinkster.io/pick/IgQdYAAt9V/angularjs-directives-talking-to-controllers
which is good style by the tutorial. I dont get it. So then it means earlier example with onclick is also perfectly good? Then why nobody uses it at least these days when people use lot of jquery for example?

Let me cite from a book Angular, by Brad Green & Shyam Seshardi
Chapter 2 ... A Few Words on Unobtrusive JavaScript
The idea of unobtrusive JavaScript has been interpreted many ways, but the rationale
for this style of coding is something along the following lines:
Not everyone’s browser supports JavaScript. Let everyone see all of your content and use your app without needing to execute code in the
browser.
Some folks use browsers that work differently. Visually impaired folks who use screen-readers and some mobile phone users can’t use
sites with JavaScript.
Javascript works differently across different platforms. IE is usually the culprit here. You need to put in different event-handling
code depending on the browser.
These event handlers reference functions in the global namespace. It will cause you headaches when you try to integrate other libraries
with functions of the same names.
These event handlers combine structure and behavior. This makes your code more difficult to maintain, extend, and understand.
In most ways, life was better when you wrote JavaScript in this style.
One thing that was not better, however, was code complexity and
readability. Instead of declaring your event handler actions with the
element they act on, you usually had to assign IDs to these elements,
get a reference to the element, and set up event handlers with
callbacks...
...
In Angular, we decided to reexamine the problem.
The world has changed since these concepts were born...
... for most inline event handlers Angular has an equivalent in the form of
ng-eventhandler="expression" where eventhandler would be replaced by
click, mousedown, change, and so on. If you want to get notified when
a user clicks on an element, you simply use the ng-click directive
like this:
<div ng-click="doSomething()">...</div>
Is your brain saying “No, no, no! Bad, bad, bad!”? The good news is
that you can relax.
These directives differ from their event handler predecessors in that
they:
Behave the same in every browser. Angular takes care of the differences for you.
Do not operate on the global namespace. The expressions you specify can
To get more details, read the book: http://www.amazon.com/AngularJS-Brad-Green/dp/1449344852
EXTEND
Following the discussion in comments, I would like to add a more explanation.
As stated here: Wikipedia - AngularJS:
Angular is a framework, which goal is to augment browser-based applications with model–view–controller (MVC) capability, in an effort to make both development and testing easier
The Model–view–controller, a short extract from wikipedia:
A controller can send commands to the model to update the model's state (e.g., editing a document). It can also send commands to its associated view to change the view's presentation of the model (e.g., by scrolling through a document).
A model notifies its associated views and controllers when there has been a change in its state. This notification allows views to update their presentation, and the controllers to change the available set of commands. In some cases an MVC implementation might instead be "passive," so that other components must poll the model for updates rather than being notified.
A view is told by the controller all the information it needs for generating an output representation to the user. It can also provide generic mechanisms to inform the controller of user input.
Summary:
The most important part here, is the fact, that View can publish the Controllers actions to the user. And this is exactly what the Function calls in HTML do represent.

This is a misunderstanding:
Using angular brings lot of weird style of code. For example I always thought that this
<button onclick="myFunction()">Click me</button>
style I should not ever use, except when I would be lazy and want quick and dirty code. And I never used such style in projects and also I even thinked that this is bad.
It is perfectly valid to use that style of code if you can decide what event handler to attach to the button when you render the HTML code. With jQuery we see many dynamically attached event handlers because many times the elements themselves are dynamically inserted or whether to attach an event listener or what to attach is dynamically decided.

Related

Single responsibility principle and Backbone.View

I use Backbone.js. I have popup1, which creates popup2. popup2 is component-like and when it closes it triggers the event 'school_address:saved'. I need to send a request to the server on 'school_address:saved' event. I placed the handler which do so in the view of the popup1 (its instance still exists), but I'm not sure that this place is appropriate, because views are responsible for template UI logic, aren't they?.
What do you think is the best place for such code? And what would it be if I used Marionette.js?
We have been using BackboneJS for a few years now and have wondered about similar cases in the past...
Since BackboneJS (unlike other JS frameworks)does not enforce any common way of doing this, I would generally say this really depends on your implementation and application flow.
However, since these are popups/"application modals", I think it would help if you consider the following based on your current need:
If it is ONLY popup1 that can instantiate and display popup2, then have popup1 listenTo the events triggered by popup2.
If you foresee your application flow changes, and possibly having popup2 display elsewhere, or independently, I would suggest you listen to popup2 events from a view at a higher level (possibly one you have a route for). this way, both of your popups will be "independent", and you could recycle their code more easily and support greater flexibility as your application grows.

Writing to a Firebase from within a Polymer element

I am working on an assignment for a course in "Coding the Humanities" which involves writing a custom web component. This means I am required to use Polymer even though as far as I can see there is absolutely no added value to doing so.
I want to create a literal chat "room" in which users input a character to identify themselves and can walk around the room bumping into one another after the fashion of robotfindskitten.
My idea was to write each character and its position to a Firebase location, updating everyone's positions in real time, so I need the Firebase JS client- using core-ajax for REST requests isn't fast enough.
The GitHub readme for the core-firebase element consists of a link to a less than helpful component page.
Looking at the core-firebase element itself, I don't see anything that corresponds to the 'value' event; locationChanged has a 'child-added' event handler, but that's it.
Am I crazy for thinking the core-firebase element is just very incomplete? Should I try to write my own 'value' handler? If so, do I just add it to the locationChanged property of the object passed to Polymer()? I'm very confused - I know enough JS that what's happening in the core-firebase code is straddling the limits of my comprehension. (Which might have to do with the this keyword, I don't know.) Any input here would be appreciated. (And yes, I've already remarked to the instructor that I could have handled this using plain old jQuery and Firebase if I didn't have to use Polymer. No word as yet on that.)
Looking at the commits for core-firebase it looks like it's had about two days work on it plus some maintenance, so it wouldn't be surprising if there are missing features.
One nice part about Polymer is that it interops very well with other ways of writing apps. It's totally reasonable and supported to use jQuery and Firebase directly to read from firebase and react to changes. You can still make good use of polymer's templating and databinding by doing this within an element of your own and using Polymer's data binding, templating, and plain old DOM events to propagate those changes throughout your app and render them onto the page.

Best practice for binding event handlers in Jasmine tests that use fixtures?

Despite these two related questions on StackOverflow, I've yet to find an satisfactory answer for this, so I'm posting to find out if there is an accepted best practice among Jasmine-jQuery users.
The basic problem is simple and two examples of it are covered in the two linked questions:
In my Javascript, there is a setup() function that binds event handlers to various selectors on a page, as in $('#someDiv').click(someHandler); this function is passed to $(document).ready
In my Jasmine tests, I use HTML fixtures representing various extracted parts of the page to test AJAX interactions on those elements (I'm running the jasmine-rails "server" version, where you can view Jasmine test reports in browser)
The problem, of course, is that the selectors to which setup() tries to bind handlers will not exist until after the fixture is loaded. As a result, an event triggered explicitly in a Jasmine test will not be picked up by the DOM element in the fixture, because the function that would have bound that handler already ran at $(document).ready time.
If only Jasmine could somehow delay the call to $(document).ready until after the fixtures were loaded, I'd be golden. But apparently it can't.
From the two StackOverflow questions above, I've gleaned various ways to get around this, all unsatisfactory:
Copy the binding code in setup into the HTML fixture(s) themselves. This is non-DRY and almost certainly will cause the fixtures to drift out of sync with reality, plus the fixtures are supposed to represent unobtrusive JS and therefore not mix code and markup.
Explicitly call the setup function in the test cases that require it. This works in simple cases, but would fail if setup did non-idempotent things.
In setup, use something like $(document).on('click', '#someDiv', someHandler) instead of the code I showed above. (I'm on jQuery 1.10.1.) I actually tried this but it doesn't work: even if the loaded fixture contains an element matching #someDiv, triggering 'click' on that element doesn't result in someHandler being called. Even if it did work, it's messy because (if I understand correctly) the value of this when the handler is called will reflect the element that actually handled the event, not necessarily the one that first received it.
In setup, use something like $('#someDiv').live(someHandler), but live was deprecated as of jQuery 1.7 and removed in 1.9.
Is there some other method I'm missing that doesn't require making changes to working code solely to accommodate the testing environment and that doesn't require violating DRY?
I have an example of DOM manipulation with Jasmine using jasmine-jquery here. You will also see a link in the description therein to a github repo you can clone to provide more insight into how SpecRunner.html orders dependencies. Basically I have my html fixtures with their onclick events followed by a jquery click() all in my jasmine beforeEach(). I then have my test expectations also check the DOM for validation. This may be along the lines of your #2 workaround above.

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.

Unobtrusive Javascript Obfuscates Event Handling

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.

Categories