Succinctly Adding Custom Event Triggers in jQuery - javascript

I have a rather large and convoluted JavaScript module that is used on multiple pages of my site. After a bit of searching and fiddling, I came up with the following structure to run some extra code when one of the module's functions run on a specific page.
// within module definition that is used across multiple pages
function some_module_method(){
$.event.trigger( 'custom_event' );
}
// bit of functionality that I'm trying to add to a single page
$( '#some-element' ).on( 'custom_event', function(){
console.log( 'The custom event has just been triggered!' );
} );
One problem I'm having is that when I'm expecting this event to only trigger once, it will go off 2-4 times in quick succession. Is this a problem with the structure above that I'm using to trigger and attach this event, or probably something else?
Also, how can I attach a function to an event without referencing some DOM object? Simply using $.on() doesn't work.

For your first issue, it's a little hard to say without seeing an example. And I could be mistaken, but I'm pretty sure $.trigger() will not work like you're using it. It has to be attached to a jQuery object e.g.. $().trigger().
And for your second question... You don't have to use a DOM element exactly, but you can use an empty jquery object like $({}).on(). See this fiddle.
Hope this helps some.
On a side note, you may be confusing jQuery object methods with core methods. here is a little info just in case.

Use
$('#some-element').trigger('custom_event');
instead of
$.trigger('custom_event');

Related

JQuery: Remove JS after defining event listener but before listener is triggered

I've got a question that searching did not actually yield any results. I apologize if this has been asked in the past.
I'm trying to define an event listener, and immediately remove the JS after defining the event listener. The problem is, I want the removal to take place prior to the event taking placing. Is this possible? I read in the JQuery 1.4 documentation that detach() is like remove, but maintains JQuery data. Is this a viable solution? Are there downsides to removing the code which places an event listener prior to the event taking place?
The code I'm trying to remove is dynamically generated code. Doing something like this:
<script id="12341234">
$( function() {
$('#test').click( function() {
alert('Hello');
});
});
</script>
Later in the script:
$('#12341234').remove();
That works fine for removing the script, it just doesn't fire the event listener (which makes sense).
The reason I'm trying to do this is for a very small amount of added security. Sensitive fields are already masked, no one can gain access to anything sensitive per se. I just have PHP generating a decent amount of JS, and I don't want the temptation of "inspect element". If they do actually see it, it's not a huge deal. I'd just prefer to remove it if possible.
Any help is much appreciated. Thank you in advance.
In case anyone is wondering, I figured out the answer to this.
It functions just as I theorized: It removes the script tags and everything in between, but the event listener remains intact. See below for example:
<script id="testscript">
$( function() {
$('#testbutton').click( function() {
alert('Hello!');
});
});
$('#testscript').detach();
</script>
This will keep your event-listener, while preventing your JS from being displayed on inspect.
A quick note, if someone is using any sort of debugging tools which can step through rendering, they can EASILY see the code before it's ever removed. However, if you simply don't want the average user to see the JS, this will work.
Sensitive data will still need masked or dealt with appropriately.
I still don't know the answer to the question as to whether or not detach() has a negative impact, or if it should be avoided for this use-case. However, I did some testing and it doesn't appear to have much performance impact versus remove(). We're talking 1% slower or less. I also dug a bit more through documentation, and reaffirmed my initial believe that my use-case is basically a standard use-case for detach(). There doesn't seem to be any downside to using it. I may be wrong, and if so feel free to correct me.

Keep the javascript fully separated from markup on primefaces

I'm working on a web interface with the help of primefaces framework.
In that interface, one of the objectives is to have the code divided in javascript functions that do not share information between each other and they don't allow being invoked by other parts (that eases testing and reduces the number and complexity of possible use-cases).
All "parts" are encapsulated using:
(function (window, document, undefined){
var $ = window.jQuery;
// main content here
})(window,document);
The communication required between each part is minimal and the required one is made using DOM events where an object is passed between each other. (if the event is not caught, it's just a functionality that didn't act. If it caused something to break, the js does not stop working, among other reasons).
This has been working for quite a while with minimal bugs found until I had to work with jsf+primefaces.
By reading the documentation, primefaces has many XML tags that do not map to HTML tags. One of the main ones I have to work with is <p:ajax>.
This tag was many on*-like attributes whose concept works much like the HTML3's ideology of writing javascript in HTML's "on*" attributes. Still, those <p:ajax> are always attached to specific XML elements like <h:inputText> or <p:commandButton> and that's where I started looking at.
In primefaces documentation, there's information about the inline on* attributes but I was fully unable to find information about jsf or primefaces' personalized DOM events.
How it appears with primefaces, I'm forced to change the javascript code so that functions/methods can be called inline in the HTML. That would require a lot of work also because, depending on the situation, the js code might even not be there (because the feature it enables is not required for that page).
How do I make the system on primefaces such that I have my javascript fully detached from the jsf/primefaces XML (and the whole HTML output I can manage).
EDIT:
I ran out of ideas on where to look at, I'll work on looking at primefaces source code now. I may get better luck there.
EDIT:
Meanwhile I got some ideas for searching using different keywords and I found this(see: "Client Side API"):
http://courses.coreservlets.com/Course-Materials/pdf/jsf/primefaces/users-guide/p-ajaxStatus.pdf
This is near what I wanted but it seems like it does not exist for the elements I mentioned above. I'll work on continuing searching for more.
After some testing, investigation, etc... I was finally able to understand the whole story of what was happening.
Primefaces was doing everything right after all! The <p:ajax> has the correct code to send all the events it should! The problem lies in jQuery itself.
jQuery's trigger() method (and it's shortcuts) works in such way that it handles all events directly inside jQuery bubbling and calling the callbacks registered using on() (or any of the shorthands).
The main issue in jQuery is that it only resend the "click" event to the DOM because it tries to use a method in the DOM element with the same name as the event. In the DOM, (at the moment) the only situation when that happens is the "click" event. That's why I was getting the click event and not the rest of the events.
With that, the mistery and confusion was, finally, solved. uff!

What's the difference between .click(function () { and javascript:myfunction()?

Consider the simple link below:
Link
I understand there are two ways to run a function when a user clicks this element:
$(".mylink").click(function () {
and
Link
Is there a performance difference between the two, or any other practical reason I should use one over the other?
Using $('.mylink').click(function(){ is better as it follows standard event registration model. (jQuery internally uses addEventListener and attachEvent).
Basically registering an event in modern way is the unobtrusive way of handling events. Also to register more than one event listener for the target you can call addEventListener() for the same target.
Read jQuery.click() vs onClick
and How does inline Javascript (in HTML) work?
https://softwareengineering.stackexchange.com/questions/86589/why-should-i-avoid-inline-scripting
They have the same functional behavior, there is no difference whatsoever.
The difference is in code modularity and maintainability.
Using the first method is preferred and more appropriate because it doesn't mix between HTML and JavaScript, a concept called Unobtrusive JavaScript.
If you have worked in the early days of HTML, then you should remember when there were all those attributes like background, color, font ... etc.
Then CSS came in, and everybody told us not to use those old attributes anymore because they mix presentation with document structure, instead we should use CSS to control layout and look of the document.
This is similar to that idea but it is now used for code, separate functionality from document structure.
Edit: Quoting from #mplungjan comment in order to be more accurate:
That there is no difference is not true. href="javascript:myFunction()" does not have the ability to cancel the actual click with a preventDefault or return false. Hence animated gifs will stop running in some browsers and older browsers would even partially unload the page. Also if the function returned a value, the page would be replaced with that value, seen when beginners try href="javascript:window.open..." and get [object object] on the page
Jquery like any other good JavaScript frameworks supplies you with functionality independent of browser platform wrapping all the intricacies, which you may not care about or don't want to care about.
I think using a framework is better instead of using pure JavaScript and doing all the stuff from scratch, unless you usage is very limited.
I definitely recommend JQuery!
The first one is JQuery convention of an event listener. You need to include jquery library in order to use it. The second one is a Javascript convention. You don't need to include any library or extra code to run. There are no differences in terms of performance, but as I told if you do not want to include any kind of library you should use the second example.

Why are more people nowadays using script to assign events handlers vs assigning the event from within the html element?

As a learner I like to look at lots of source code. Since I started learning JavaScript about a year ago, I notice a trend of people not using traditional event handlers as in onclick="doSomething()", but are more and more using methods like document.getElementById("someId").onclick = function(){..some code..};
What's the reason behind this trend?
Assigning the handlers in Javascript puts all of the code in one place instead of scattering it throughout the HTML.
This helps separate content from script, just like CSS helps separate content from style.
It's also faster, since the browser won't need to fire up a Javascript parser for each handler attribute.
This is an example of Unobtrusive Javascript.
The other answers haven't touched on this, so:
Your example uses the (reflected) onclick attribute even in the JavaScript code:
document.getElemenbyId("someId").onclick = function(){..some code..};
...which for me misses out one of the primary reasons for doing this without using attributes: Playing nicely with others. The DOM2 way of attaching handlers (addEventListener, or attachEvent on IE [IE9 has the standard addEventListener finally]):
document.getElementById("someId").addEventListener("click", function() { ... }, false);
// or
document.getElementById("someId").attachEvent("onclick", function() { ... });
... is non-exclusive — more than one handler can be attached at the same time. Whereas if you assign to onclick, you're kicking any previous handler off and taking over.
To me, this "playing nicely" thing is a big sell. Well, that and keeping code and markup separate, but that's been well-covered in other answers.
HTML should be only markup, pure content.
Design should be in CSS style sheet.
Dynamic scripting should be in JavaScript code, separate file is good.
Just feels better and looks better - as far as I can tell it's not more efficient just more elegant and easier to maintain when all the script is in one place instead of being spread all across the HTML. :)
As mentioned by other answers, the main reason is separation of concerns (in this case, keeping behaviour separate from content), which is entirely sensible. However, that isn't always the only consideration. I've previously written a lengthy answer to a related question.
I think most people are using jQuery. $("#someId").click(function(){}) and when you want to attach an event to many elements jQuery makes it easy and puts your function in one place.

Best Practices for onload Javascript

What is the best way to handle several different onload scripts spread across many pages?
For example, I have 50 different pages, and on each page I want to set a different button click handler when the dom is ready.
Is it best to set onclicks like this on each individual page,
<a id="link1" href="#" onclick="myFunc()" />
Or a very long document ready function in an external js file,
Element.observe(window, 'load', function() {
if ($('link1')) {
// set click handler
}
if ($('link2')) {
// set click hanlder
}
...
}
Or split each if ($('link')) {} section into script tags and place them on appropriate pages,
Or lastly, split each if ($('link')) {} section into its own separate js file and load appropriately per page?
Solution 1 seems like the least elegant and is relatively obtrusive, solution 2 will lead to a very lengthy load function, solution 3 is less obtrusive then 1 but still not great, and solution 4 will load require the user to download a separate js file per page he visits.
Are any of these best (or worst) or is there a solution 5 I'm not thinking of?
Edit: I am asking about the design pattern, not which onload function is the proper one to use.
Have you thought about making a class for each type of behavior you'd like to attach to an element? That way you could reuse functionality between pages, just in case there was overlap.
For example, let's say that on some of the pages you want to a have button that pops up some extra information on the page. Your html could look like this:
More info
And your JavaScript could look like this:
jQuery(".more-info").click(function() { ... });
If you stuck to some kind of convention, you could also add multiple classes to a link and have it do a few different things if you needed (since jQuery will let you stack event handlers on an element).
Basically, you're focusing on the behaviors for each type of element you're attaching JavaScript to, rather than picking out specific ids of elements to attach functionality to.
I'd also suggest putting all of the JavaScript into one common file or a limited number of common files. The main reason being that, after the first page load, the JavaScript would be cached and won't need to load on each page. Another reason is that it would encourage you do develop common behaviors for buttons that are available throughout the site.
In any case, I would discourage attaching the onlick directly in the html (option #1). It's obtrusive and limits the flexibility you have with your JavaScript.
Edit: I didn't realize Diodeus had posted a very similar answer (which I agree with).
First of all I dont understand why you think setting event listeners is obtrusive?
but ...
Solution one is a bad idea
<a id="link1" href="#" onclick="myFunc()" />
because you should keep your make-up and your scripts seperate.
Solution two is a bad idea
Element.observe(window, 'load', function() {
if ($('link1')) {
// set click handler
}
if ($('link2')) {
// set click hanlder
}
...
}
because you are using a lot of unneeded javascript for every page.
Solution three is a bad idea for the same reason I said solution one is a bad idea.
Solution 4 is the best idea, yeah its one extra load per page, but if for each page you just split each if ($('link')) {} section, the file size can not be that large? Plus, if you take this code out of the global javascript, then its load time will be reduced.
You could hack the class name and use it in a creative manner:
<a class="loadevent functionA" id="link1" href="#" onclick="myFunc()" />
... on another page...
<a class="loadevent functionB" id="link1" href="#" onclick="myFunc()" />
You could select by class name "loadevent" and grab the other class names for that tag, the other class name being the actual function name you want to hook into. This way one handler would be able to do every page and all you have to do is provide the corresponding class names.
I would use JQuery's document ready if possible
$(document).ready(function() {
// jQuery goodness here.
});
While Chris is somewhat correct in that you can do this:
$(document.ready(function() {
// A
});
$(document.ready(function() {
// B
});
$(document.ready(function() {
// C
});
and all functions will be called (in the order they are encountered), it's worth mentioning that the ready() event isn't quite the same to onload(). From the jQuery API docs:
Binds a function to be executed
whenever the DOM is ready to be
traversed and manipulated.
You may want the load() event instead:
$(document).load(function() {
// do stuff
});
which will wait for images and the like to be loaded.
Without resorting to the kneejerk jQuery, if the page varying JS is relatively light I would include it in an inline header script (binding to the onload event trigger, yes) similar to #4, but I wouldn't do this as a separate JS script and download, I'd be looking to handle this with a server side include - however you want to handle that (me? I'd go with XSLT includes).
That gives you both a high degree of modular separation and keeps the download as light as possible.
Having a lot of different pages, I would allow different handling of events for those pages ...
If, however, differencies were slight, I would try to find a pattern I could hang on to, and probably make a real simple algorithm to tell the pages apart ...
The last thing I would resort to, was to use a (big) library (jquery, mootools or whatever !-) if I wasn't going to use it in any other way ...
Now you're talking of best practices, best practice would always be what your users will experience as the lightest solution, and in that, users should be understood in the widest possible way, including developers and so on who are to maintain that site !o]

Categories

Resources