Is there a way to trigger an event when inserting html? - javascript

It's for a backbone application,
I'm using Jquery html() function to insert my views templates into the layout everywhere, and I would like to be able to trigger an event each time the html() function of jQuery is called to check the html of the page.
Is there a way to do that ?
( Like App.on('html', blablabla...); )
Thank you !

As Marc B suggested DOM MutationEvents is available on some browsers (not many). By default jQuery does not fire any event when using html, but you can define your own behaviour for this, for example:
(function($) {
var html_ref = $.fn.html;
$.fn.extend({
html : function() {
$(document).trigger( 'html_change' );
return html_ref.apply(this, arguments);
}
});
})($);
It should work, didn't test it though. You can use the same with .text method. Now you can simply use:
$(document).bind( 'html_change', function() {
// Hurray! Html changed!
});
That's the idea, use it as you wish.

AFAIK, the jQuery html() method doesn't fire any subscribable events per se, but you could probably roll your own implementation of a simple Observer pattern. I use this across a large number of projects and it provides a great, clean, lightweight way to encapsulate arbitrary event handling across loosely-coupled modules.
However, this is presuming that you have programmatic control over every time the html() method is called - if not, then this would be more difficult, as there is no callback function to hook into.

Related

Defining and triggering custom events on custom module in YUI3

This is how we can create a custom module in YUI3,
<script type="text/javascript">
YUI.add('my-module', function (Y) {
// Write your module code here, and make your module available on the Y
// object if desired.
Y.MyModule = {
sayHello: function () {
console.log('Hello!');
}
};
});
</script>
But now I would like to, on this module, define some custom events and later trigger them, I just couldn't find any information about this on the YUI3 official website.
How can we actually do this?
Custom events are actually pretty important throughout YUI. This documentation page describes them in detail: http://yuilibrary.com/yui/docs/event-custom/. Read this page and some of the examples in the sidebar.
The easiest and simplest way to fire a custom event is to fire it from the Y, as in Y.fire("myEvent"). However, if you want to fire an event from your object, you would need to give your object the EventTarget API and call this.fire("myEvent"). Most people do this by extending Y.Base, which includes Y.EventTarget. See http://yuilibrary.com/yui/docs/base/ -- if you extend Base, you get a fire() method, the ability to listen for events with on() or after(), plus lots of other goodies.

How to use dojo/behavior on dojo widget?

I read this article (Using dojo.behavior), and want to use the behavior module in my project as event handling module.
But I have a problem that, for DOM nodes, it works wonderful, but how can I use it on the Dojo widgets?
If I use dojo/on module, I can do it like this:
var buttonNode = dijit.byId("myButton");
on(buttonNode, "onClick", buttonHandler);
or
dijit.byId("myButton").onClick = buttonHandler;
But, if I use behavior module,
behavior.add({
"#myButton": {
onClick: buttonHandler
}
});
it doesn't work. (Of course I called behavior.apply() after I finished page render.)
The code below doesn't work either.
behavior.add({
"[widgetid='myButton']": {
onClick: buttonHandler
}
});
After some investigation, I found the reason the code above not work is because a button widget is composed by many s and an inner . And if I use the id specified by data-dojo-id, it will point to a instead of the that I hope the event bind with.
I found a solution which can walk out this situation,
behavior.add({
"[widgetid='myButton'] input": {
onclick: buttonHandler
}
}
but the css selector is too complex and it depends on what type the widget is.
Is there a good solution to apply dojo/behavior on widgets just like on dom nodes?
It looks like what you really what is to hook up an event on the widget object, but behavior is designed to access the DOM instead. So, I think you're stuck with your workaround.

Initializing jQuery.load'ed elements

I'm loading part of my webpage using AJAX, in particular jQuery.load(). With this the usual jQuery pattern
$('.classname').click(...) // Handler
// or, working with bootstrap
$("a[rel=tooltip]").tooltip() // Function
or similar obviously don't work any more, because they are called only when the page is loaded. I realize there is jQuery.on for the first example, but how would I implement the second?
Is there a simple (builtin) way to also apply these to jQuery.loaded stuff, or do I have to work around it myself? Seems like a problem a lot of people should be having.
You have to work around it yourself; but you can easily to this by calling $("a[rel=tooltip]").tooltip() in the callback for load():
$('#blah').load('/somewhere.html', function () {
$('#blah').find('a[rel="tooltip"]').tooltip();
});
Be sure to restrict the tooltip() call to only newly loaded elements, or you'll end up initializing tooltip multiple times per element (which may result in weird behaviour).
To avoid duplicating code you just need to define a helper function;
function initTooltip(root) {
return $(root || document).find('a[rel="tooltip"]').tooltip();
}
Which allows you to init tooltip. The parameter is optional, and lets you restrict initialization to only descendants of the provided element, e.g.:
jQuery(document).ready(function ($) {
initTooltip(); // equivilant to initTooltip(document);
$('#blah').load('/somewhere.html', function () {
initTooltip('#blah');
});
});

Can you bind to jQuery events with plain JavaScript?

I'm working on a project where a number of different companies are working on the same site.
The main developer have set up an event - let's call it init - which indicates the page is ready for our code to execute.
They're basically calling it like this:
$(window).trigger('init');
For a number of reasons I won't go into here, we prefer to avoid using jQuery in our own code wherever possible. I tried to bind to it like this:
window.addEventListener('init', function (event) {
alert('hehehehe');
});
But that doesn't seem to work. This works perfectly, though:
$(window).bind('init', function (event) {
alert('hehehehe');
});
Does jQuery use special event objects by default that you can't bind to with plain JS? Am I just doing something stupid?
The docs for bind seem to contain the answer:
Any string is legal for eventType; if the string is not the name of a native DOM event, then the handler is bound to a custom event. These events are never called by the browser, but may be triggered manually from other JavaScript code using .trigger() or .triggerHandler().
There's no native DOM event called 'init':
http://en.wikipedia.org/wiki/DOM_events
Hence "These events are never called by the browser, but may be triggered manually from other JavaScript code using .trigger() or .triggerHandler()"

live changes with any modification on the DOM

I am using jQuery to apply some UI effects like adding a class to a number of elements, in the JS file i use :
$('.dataGrid').each(function(){
$(this).find('tr:odd').css('background-color', '#F7F8FA');
});
but when i use ajax to load an element with the class .dataGrid the rules up there doesn't apply, my solution was to make a function joins all cases like this one and call it every time i make an ajax request ! .. this off course is not a pro one .. i found .live() , i used and it worked fine with events like :
$('dataGrid').live('moveover', function(){ ... }); .
the .live solution is very good with events ... is there any way to use the same concept with the effects like mentioned up there ? ... i mean a way to reapply the rules set before, every time a change takes place on these elements ( adding new one for example )
I wish i was clear enough, Thanks in advance :)
The Livequery-plugin supports triggering functions when new nodes are added to the DOM.
Something like this should work:
$('.dataGrid').livequery(function() {
$(this).find('tr:odd').css('background-color', '#F7F8FA');
}
Depending on how you are loading elements i.e. which AJAX technique you are using, you can achieve this in many ways. If you are using jQuery Ajax then you can use the jQuery.when method.
Basically with this method you can have deferred execution. You can say something like "when the ajax call completes then do this function". The syntax goes like
$.when( $.ajax("test.aspx") ).then(function(ajaxArgs){
alert(ajaxArgs[1]); /* ajaxArgs is [ "success", statusText, jqXHR ] */
});
Following link will give you more information
http://api.jquery.com/jQuery.when/
Since you are using ajax to append your .dataGrid elements you could register a handler for ajaxComplete() that will handle the application of your :odd class.
$(document).ajaxComplete(function() {
$('.dataGrid').each(function(){
$(this).find('tr:odd').css('background-color', '#F7F8FA');
});
});

Categories