Backbone.js Click Event Won't Fire on Previously Added Subviews - javascript

I've been trying to resolve this for days!
The use-case is one that I would think to be very common; I have a button (<button id="add-item">) that adds a new item element (<div class="item">) to a container element (<div id="list">) which in turn should display a form (<form>) for the item in a panel (<div id="panel">). I want to be able to click on the items and have the panel show the form specific to the item.
The problem is that the only item recognizing a click event is the last item added; none of the previously added items views will recognize a click.
I had this working before by having a click event on the List view on .item but was told by a prominent member of the Backbone.js community that the item view really should handle a click itself rather than delegating that responsibility up to it's container.
In order to help you who might be able to help to understand the problem I have created an extremely pared down and self-contained example to illustrate. You can see it any of these three (3) places:
A JSFiddle
A Gist
Our Website
Also, if you have any suggestions for how to better structure this code I'm 100% enthusiastic to hear them; I'm new to Backbone.js and do not feel I fully understand it's patterns, practices and idioms.
P.S. I've read everything here on StackOverflow that I can find and I can find nothing that addresses the problem so in case you want to close my question as a duplicate please do me the favor and make sure it actually is a duplicate first.
UPDATE
I'm fixing the code but leaving the errant this.$el.empty() commented out so others can who have the same issue can learn from this. Thanks to #sardine/#tollmaz for helping me out on this over Twitter.

Per a Twitter conversation, it turns out that the issue is with:
this.$el.empty();
When you create the new item, the events are set up. Upon clicking the item, the select method is executed. As part of this method, an instance of app.ListView executes its render method. Within this method, $el, which is actually #list, is emptied. As such, the previously created view with working events is nuked. While it is repopulated visually, the event is never recreated (not sure why this is though).

Related

How to fire a DOM event with YUI3

I've encountered an annoying issue while working on YUI.
I have a main area and a navigation block. The elements in the main area can be activated with a direct click or by clicking an element in the navigation block that triggers the appropriate element in the main area.
As it turns out, triggering a click event programmatically in YUI isn't as simple as I thought it might be. Looking at the documentation I found pleanty of information on how to attach and delegate events but not how to call one.
I found this question, but it deals with creating a new custom event and not calling an existing one.
All other similar questions are answered with using .simulate(), but this is actually not the best option for compatability reasons and it's also not recommended by YAHOO itself for client-side use http://yuilibrary.com/yui/docs/event/simulate.html#faking. EDIT: After re-reading the section I realized the warning is irrelevant for the subject of this question.
I found a solution by calling the click() command in the node's DOM element, but this is really a last resort and I would like to know if there's a more "clean" way to do it through YUI.
Here is an example of what I'm doing now: http://jsfiddle.net/3fso2dg8/
In the example, the second button is triggering the click event of the first button by using the DOM element
Y.one('#clickme')._node.click();
CONCLUSIONS
After more fiddling with the code I came to realize simulate() is the preferred option in most cases, but not all.
The YUI vesrion I'm required to work with (3.14) has a known issue on simulating a click event in IE9 and above. Since - for other technical reasons - I cannot upgrade to whatever version this issue was fixed and I need to keep a multi-platform compatibility, my original solution is still the best option. Anyone else that uses YUI components that don't respond well on IE, maybe you stumbled upon the same issue so this is one way to solve it.
After looking for exactly the same functionality I just used simulate in user-facing code - where It would just mimic clicking with no return method etc. (simple submit button or choose fil trigger).
When I would needed "complex" functionality I would just add a class or new ID and add new delegate or "on" method in my code - following the: "If a function needs to respond to user action or be called programmatically, it should be written accordingly and called directly in the latter case." prinsipp.
So to summarize - I use simulate for very simple effects with no callbacks or other "advanced" stuff and (sadly) duplicate other delegate/on elements where simulating would be tricky...
Had also looked into your method (._node.click();) and I can't see no obvious difference comparing to simulate()...

Proper method for switching through Jquery pages

I have two pages. One contains a list of teachers. Selecting a teacher from the list bring you to the second page where I would like to dynamically create of list of their students from the result of my ajax call. My problem is general confusion from contradicting information on the internet so I can not figure out how to call a function upon changing pages.
I have tried using pageshow, pageinit, pagebeforeshow, pagecreate and a couple more along those lines. The first part of my problem is that I do not know which is the correct method, because at various places of the internet someone said each of those was right but I could not find an explanation why.
The second part of my problem is I do not know which selector and/or method. The document or the page? and to use bind, delegate, live or on. So I've been going at this for a while so if someone could help me understand what solution would best fit my appreciate it.

How to make all buttons(even dynamically created) in an application follow jquery button widget without calling .button() multiple times

I am new to stack overflow and this is my first question. Pardon me for any mistakes.
This question is more generic but i tried to search for an answer but could not find it.
Say i have a page and i am using jquery ui button() widget for all the button. What happens is i have a specific class defined for all the buttons on my page. So i can just specify $('.myButtonClass').button(); but whenever i render partial views which has button again i have to do the same thing in the partial views. Is there any way i can globally specify a transition for button or any element for that matter.
Here is a sample Fiddle which adds buttons on click. But the added buttons are not transitions as button widgets(I do not want to use clone).
http://jsfiddle.net/wjxn8/
$('.clsTest').button().click(function(){
$(this).after('<input type="button" value="Added" class="clsTest"/>');
});
Is this possible without:-
1) Adding the css classes for a button widget manually for all the buttons created.
2) Tracking DOM Changes using Javascript and perform transitions for all the button elements.
Thanks for your help!!!
Since you were looking for something else, why not trigger a custom event when you load partials or whatever:
$('.clsTest').button().click(function(){
$(this).after('<input type="button" value="Added" class="clsTest"/>').trigger('addButtonUI');
});
$(document).bind('addButtonUI',function(){
$('.clsTest').button();
});
http://jsfiddle.net/wJXN8/3/
If you trigger your event and have the document listening for it, then you can do whatever you would like. I could have put in there the ability to add more buttons as well, but this should get the point across.
What you are asking for, some event when a button is added.... you would need to come up with that yourself and trigger it when a button is added. There is this: How to detect new element creation in jQuery? which talks about a specific event that is triggered when new elements are added to the DOM. Haven't tested it, and it looks like it may not work on IE.
I'm not a huge fan of this, but you could poll for new buttons. Check out my fork of your fiddle (that sounds funny):
http://jsfiddle.net/lbstr/Hq97H/
Using your example, this would look like:
setInterval(function(){
$('.clsTest').not('.ui-button').button();
}, 1000);
As I said, I'm not a huge fan of this. I understand the desire for something like $.live here, but I still think its better to initialize your new content when you add it. If you are making an ajax call for new content, just initialize it when you add it to the DOM.
My silly polling code and $.live (which is now deprecated) might be convenient, but they perform terribly. Just my two cents. You know your code better than I do!

How can I get buttons in a ListView itemTemplate to perform different actions?

Context: This is specifically a Windows 8 Metro application question based on their HTML/JS framework.
I want to put one or two of the most common secondary actions within the template for my items in a ListView. Think music player. Clicking the name plays the track immediately but I also want an "Add to playlist" button on each row.
When I add a button inside my template, even if I add a handler to that button, the onItemInvoked function for the ListView always gets called and my button's handler never gets called. This would be fine if I could identify from the onItemInvoked CustomEvent what element had been clicked, however the target and sourceElement are always the outer div of the template and never the actual thing that was clicked.
Does anyone have some suggestions on how I can go about making this work? I've seen the samples for selecting an element and presenting the additional options in an appbar but for something as commonly used as "Add to playlist" that's just going to be a poor user experience.
I posted this same identical question on the msdn dev forums in the hope of getting an answer ASAP. Thank you to jpsanders over there who pointed me at win-interactive:
http://social.msdn.microsoft.com/Forums/en-US/winappswithhtml5/thread/cd5e3b84-8405-4894-9f37-3608e448bae9

How to create navigation menu with backbone?

I'm starting to learn Backbone.js and can't figure out one thing: In a typical rails app, I have a layout view and a nested view. My layout usually contains navigation links that are processed by rails routing.
How do I do the same with Backbone? I'm using Rails 3.2 and eco templates.
Should I create nested templates in eco?
Should my navigation links be plain html links with a href or should the navigation be event driven?
For example I have a list of categories on the left, and a category items on the right. I want my categories to be shown on every view and the corresponding category items (with a URL in browser corresponding to selected category) too.
Please point me to right direction, because most tutorials on the Web are 'todo' style applications with no navigation at all.
Thank you.
UPDATE
Turns out, my question wasn't clear, so let me narrow it down.
How can the concept of RoR layouts be applied to backbone.js applications?
And I'm curious about two possible ways of navigation:
create
%a{:class => "customers", :href => "#customers"} Customers
handle ".customers click" event in my view
Which way is better?
And I'm curious about two possible ways of navigation:
create %a{:class => "customers", :href => "#customers"} Customers
handle ".customers click" event in my view
Which way is better?
neither is better until you know the specific context in which you are working. they are simply options for achieving your goal and desired functionality.
there are times when both should be used, as well. for example, if you are supporting search engine optimizations and accessibility.
Here are some better questions to ask:
Which of these will be the simplest thing that can get the job done? will it be more code to write the route handler, or the click handler?
Will the route handler tightly couple the functionality to a router, when I don't need that?
Do I really need a route for this link, so that people can bookmark it and come back to it directly?
Will a click handler cause my code to jump through several hoops of calling other objects that aren't directly related, or can I use a simple event to cause the other objects to run?
There isn't a single correct answer to any of these questions. I recommend trying many different ideas when you can. Keep in mind that you will likely change your answer as you develop new features. The answer that you want, today, won't be what you need tomorrow. But that shouldn't stop you from picking an answer now and moving on. Pick one, put it in place, and when you need to change it, change it.

Categories