Am slowing get a hang of backbone.js, but i've run into a bit of bind.
I've successfully created a view, and am able to delegate events to element in the DOM, however i can seem to be able to use the jQuery "$(this)" in the following context
Chrono.Views.Sidebar = Backbone.View.extend({
//Page wrapper
el:"#wrapper",
//Delegate events to elements
events : {
"click .push-to":"loadPage"
},
loadPage: function(event) {
var url = $(this).attr("href");
alert(url);
event.preventDefault();
}
});
The click event is intercept but this line "var url = $(this).attr("href");"
In the context of loadPage, this has been bound to your Chrono.Views.Sidebar instance. However, you can get the DOM element that the event was triggered on through event.currentTarget. If you update your function to look like this it should work:
loadPage: function(event) {
var url = $(event.currentTarget).attr("href");
alert(url);
event.preventDefault();
}
In backbone this is bound to the view, but you can still get the element that was clicked by checking the event.target or the element that the event was bound to using event.currentTarget.
Take a look at this question
Backbone.js Event Binding
this is bound to the view, so you can access the View.$el property directly.
loadPage: function(event) {
var url = this.$el.find('.push-to').attr('href');
alert(url);
event.preventDefault();
}
Related
I have a function that is called every time a user goes through a new step to bind the click event to each new item that is added to the page, and it was working fine but now it's stopped and I cannot figure out why
Below is the function (or click here for full js):
function bindClickEvents() {
console.log('bindClickEvents');
$(".wall-dropdown .item").unbind('click').on('click', function() {
console.log('Item clicked');
if ($(this).hasClass('range')) {
$(".item.range").removeClass('active');
selectedRange = $(this).data('id');
$(this).addClass('active');
selectedStyle = null;
selectedColour = null;
}
if ($(this).hasClass('style')) {
$(".item.style").removeClass('active');
selectedStyle = $(this).data('id');
$(this).addClass('active');
selectedColour = null;
}
if ($(this).hasClass('colour')) {
$(".item.colour").removeClass('active');
selectedColour = $(this).data('id');
$(this).addClass('active');
}
runFilter();
});
}
Use off with on (not unbind)
$(".wall-dropdown .item").off('click').on('click', function() {
However I suggest you simply switch to delegated event handlers (attached to a non changing ancestor element):
e.g
$(document).on("click", ".wall-dropdown .item", function()
It works by listening for the specified event to bubble-up to the connected element, then it applies the jQuery selector. Then it applies the function to the matching items that caused the event.
This way the match of .wall-dropdown .item is only done at event time so the items can exists later than event registration time.
document is the best default of no other element is closer/convenient. Do not use body for delegated events as it has a bug (to do with styling) that can stop mouse events firing. Basically, if styling causes a computed body height of 0, it stops receiving bubbled mouse events. Also as document always exists, you do not need to wrap document-based delegated handlers inside a DOM ready :)
Why don't you bind event to body like
$('body').on('click','.wall-dropdown .item',function(){...some code...})
to prevent reinitialization of event?
this code automaticaly works with each new element .wall-dropdown .item
I am collecting page button click events. Normally I am collecting the objects from statically created DOM elements. By using:
$('input[type=button]').each(function () {
$(this).bind('click', function () {
Console.log(this);
});
});
But when I add a new button dynamically like:
vvar newBtn = document.createElement('input');
newBtn.type = 'button';
newBtn.setAttribute('id', 'JgenerateBtn');
newBtn.setAttribute('value', 'JgenerateBtn');
newBtn.onclick = function () { alert('javascript dynamically created button'); };
var holderDiv = document.getElementById('holder');
holderDiv.appendChild(newBtn);
after this code, New Button is created and event also triggering, but I'm not able to get the Event object by using, same above code.
$('input[type=button]').each(function () {
$(this).bind('click', function () {
Console.log(this);
});
});
Please provide suggestion to get the dynamically created elements event object.
You may use on() for binding events on dynamically added elements. Like this:
$(document).on('click', 'input[type=button]', function(){
console.log(this);
});
This is just for simple example, it is better to bind it on element closer to your button that is already on page when it first loads rather than on document.
You should use the following:
// New way (jQuery 1.7+) - .on(events, selector, handler)
$('#holder').on('click', ':button', function(event) {
alert('testlink');
});
This will attach your event to any button within the #holder element,
reducing the scope of having to check the whole document element tree and increasing efficiency.
More info here:-
http://api.jquery.com/on/
http://learn.jquery.com/events/event-delegation/
The event object is handed to your click handler as the first argument.
$('input[type=button]').each(function () {
$(this).bind('click', function (event) {
Console.log(event);
});
});
I have this little script:
var moolang = new Class({
initialize: function(element) {
this.el = $(element);
this.el.addEvent('click', this.popup);
},
popup: function()
{
//this.id = the id of the element.
}
});
And I want to know "this" in the popup function, but if I try something like alert(this.el.id) it says there is no this.el.
Is there a way to know which class adds the event?
Change the attach event so the callee has the proper context. Otherwise the context of an event listener will be the target element.
// Change this line
this.el.addEvent('click', this.popup);
//To this
this.el.addEvent('click', this.popup.bind(this)); // popup->this == this
jsfiddle here
See mootools documentation. Binding the context of a function.
I have a div
<div class="myDiv">
somelink
<div class="anotherDiv">somediv</div>
</div>
Now, using event delegation and the concept of bubbling I would like to intercept clicks from any of myDiv, myLink and anotherDiv.
According to best practices this could be done by listening for clicks globally (hence the term 'delegation') on the document itself
$(document).click(function(e) {
var $eventElem = $(e.target);
var bStopDefaultClickAction = false;
if ($eventElem.is('.myDiv'))
{
alert('Never alerts when clicking on myLink or anotherDiv, why????');
bStopDefaultClickAction = true;
}
return bStopDefaultClickAction;
});
See my alert question above. I was under the impression that clicks bubble. And it somewhat does because the document actually receives my click and starts delegating. But the bubbling mechanism for clicks on myLink and anotherDiv doesn't seem to work as the if-statement doesn't kick in.
Or is it like this: clicks only bubble one step, from the clicked src element to the assigned delegation object (in this case the document)? If that's the case, then I need to handle the delegation like this:
$('.myDiv').click(function(e) {
//...as before
});
But this kind of defeates the purpose of delegation as I now must have lots of 'myDiv' handlers and possibly others... it's dead easy to just have one 'document' event delegation object.
Anyone knows how this works?
You should use live event from JQuery (since 1.3), it use event delegation :
http://docs.jquery.com/Events/live
So you code will be :
$(".myDiv").live("click", function(){
alert('Alert when clicking on myLink elements. Event delegation powaa !');
});
With that, you have all the benefices of event delegation (faster, one event listener etc..), without the pain ;-)
The event target will not change. You need to mirror what jquery live does and actually check if $eventElem.closest('. myDiv') provides a match.
Try:
$(document).click(function(e) {
var $eventElem = $(e.target);
var bStopDefaultClickAction = false;
if ( $eventElem.closest('.myDiv').length )
{
alert('Never alerts when clicking on myLink or anotherDiv, why????');
bStopDefaultClickAction = true;
}
return bStopDefaultClickAction;
});
Event.target is always the element that triggered the event, so when you click on 'myLink' or 'anotherDiv' you store a reference to these objects using $(e.target); So what you do in effect is: $('.myLink').is('.myDiv') which returns false, and that's why the alert() is not executed.
If you want to use event delegation this way, you should check wheter event.target is the element or any of its children, using jQuery it could be done like this:
$(e.target).is('.myDiv, .myDiv *')
Seems to work fine to me. Try it here: http://jsbin.com/uwari
Check this out: One click handler in one page
var page = document.getElementById("contentWrapper");
page.addEventListener("click", function (e) {
var target, clickTarget, propagationFlag;
target = e.target || e.srcElement;
while (target !== page) {
clickTarget = target.getAttribute("data-clickTarget");
if (clickTarget) {
clickHandler[clickTarget](e);
propagationFlag = target.getAttribute("data-propagationFlag");
}
if (propagationFlag === "true") {
break;
}
target = target.parentNode;
}
});
The function associated with the selector stops working when I replace it's contents using .html(). Since I cannot post my original code I've created an example to show what I mean...
Jquery
$(document).ready(function () {
$("#pg_display span").click(function () {
var pageno = $(this).attr("id");
alert(pageno);
var data = "<span id='page1'>1</span><span id='page2'> 2</span><span id='page3'> 3</span>";
$("#pg_display").html(data);
});
});
HTML
<div id="pg_display">
<span id="page1">1</span>
<span id="page2">2</span>
<span id="page3">3</span>
</div>
Is there any way to fix this??...Thanks
Not sure I understand you completely, but if you're asking why .click() functions aren't working on spans that are added later, you'll need to use .live(),
$("#someSelector span").live("click", function(){
# do stuff to spans currently existing
# and those that will exist in the future
});
This will add functionality to any element currently on the page, and any element that is later created. It keeps you have having to re-attach handlers when new elements are created.
You have to re-bind the event after you replace the HTML, because the original DOM element will have disappeared. To allow this, you have to create a named function instead of an anonymous function:
function pgClick() {
var pageno = $(this).attr("id");
alert(pageno);
var data="<span id='page1'>1</span><span id='page2'> 2</span><span id='page3'> 3</span>";
$("#pg_display").html(data);
$("#pg_display span").click(pgClick);
}
$(document).ready(function(){
$("#pg_display span").click(pgClick);
});
That's to be expected, since the DOM elements that had your click handler attached have been replaced with new ones.
The easiest remedy is to use 1.3's new "live" events.
In your situation, you can use 'Event delegation' concept and get it to work.
Event delegation uses the fact that an event generated on a element will keep bubbling up to its parent unless there are no more parents. So instead of binding click event to span, you will find the click event on your #pg_display div.
$(document).ready(
function()
{
$("#pg_display").click(
function(ev)
{
//As we are binding click event to the DIV, we need to find out the
//'target' which was clicked.
var target = $(ev.target);
//If it's not span, don't do anything.
if(!target.is('span'))
return;
alert('page #' + ev.target.id);
var data="<span id='page1'>1</span><span id='page2'>2</span><span id='page3'>3</span>";
$("#pg_display").html(data);
}
);
}
);
Working demo: http://jsbin.com/imuye
Code: http://jsbin.com/imuye/edit
The above code has additional advantage that instead of binding 3 event handlers, it only binds one.
Use the $("#pg_display span").live('click', function....) method instead of .click. Live (available in JQuery 1.3.2) will bind to existing and FUTURE matches whereas the click (as well as .bind) function is only being bound to existing objects and not any new ones. You'll also need (maybe?) to separate the data from the function or you will always add new span tags on each click.
http://docs.jquery.com/Events/live#typefn