Backbone: is 100 + Views ok? - javascript

I have just started with backbone... I was excited about it until I ran into a something quite confusing. So with what I have seen while searching for backbone info is that a view is basically unique to one element.
Example project: Web page builder / editor
So reguarding the example project I am guessing that you will have a view Element() with methods that would do some of the following
Change CSS styles
Change text of element
Remove element
Add Class to element
Change by (id, class)
and in those methods they would do something like
this.el.style.color = 'red';
The only way I thought for this to be possible is to create a new Element({el: someElement}) for each element that is being changed.
So say you have 100+ elements on a page and 100+ views, that just wouldn't seem right to me.
If the questions confusing that's because I'm Confused so if you need any more info. comment...
Also I can't seem to work out where Models would come into a application like this because most of the info I have read about them is that they are used to contact the server, whereas in this case. that would only be when the page is saved.
So, is it Normal to have so many views?

In my experience, the short answer is yes, that is fairly normal.
Generally in the sophisticated web applications in Backbone I have seen, it is certainly fairly common to have a few dozen views in the viewport. For example, a handful of views for the header, navigation, footer, and then maybe showing a dozen or so models, but each model is represented by a handful of views.
#mu's comment makes a good point that at some point maybe you need to just simplify your application's UI. But yes, if you are working on some sort of WYSIWYG style live web page editor, expect the order of magnitude of live view instances in the hundreds.

Related

How Do I Modify an EXTjs app to be 508 Compliant?

I have recently inherited a web app using the EXTjs framework. I'm not really that familiar with it, but I have been learning it the best I can over the last few months. I have recently been given an assignment to update the entire application to comply with 508 Compliance, that is to say, make the application accessible for those with vision issues. I was given a deficiency list that gives examples where the software doesn't comply for various reasons. I guess I need a little help in understanding how this works. I've looked at the EXTjs documentation and it does say that it has accessibility features available in it, but I haven't really been successful in finding what to do. Those using the application are using the JAWS screen reader if that makes any difference.
A few of the things I know that I need to fix are:
Some elements need to be tagged as a heading so the screen reader can read it programmatically an to give the web page some structure.
When tabbing around a table/grid the data is read without any context/header information.
Color is used as a visual cue to indicate action(ie required field). I'm supposing this is for color blindness and some other visual cue needs to be added.
Modal windows can't be resized or moved by the keyboard.
Needs a mechanism to bypass blocks of content that are repeated on multiple pages.
Pages do not have titles(this is a single page app).
Keyboard operable UI elements do not have a visible indication of focus(radio button group doesn't show focus, even if selected one does).
Name/State of UI elements in the product can't be understood(ie the name of expand and collapse buttons are read as expand panel or collapse panel by assistive tech without context to what is being expanded or collapsed).
There are many other issues, but this gives some idea of the scope of the changes required. As I have stated above, I've done a lot of examination of the EXTjs documentation at their site as well as google searches on how to make applications more accessible. But I'm not really seeing what I need. Much of this application is just configuring EXTjs templates and then loading them with much of the meat of the application being handled by the EXTjs built in js code.
I would appreciate any help, useful sites with examples, or code snippets on how to accomplish some of this. I'm hoping that once I get started with some examples, I can just go on from there.
Thanks.
Most items come with aria support. Personally I would add look into each component and add an automated aria support. E.g. button ==> aria.label = button.text
Take a look at ariaAttributes, ariaDescribedBy, ariaLabel and ariaLabelledBy. Some have ariaErrorText, ariaHelp.
Next take a look at tabIndex. You want to ensure that you can use TAB to jump through the fields, buttons, ...

Should all the view logic go in templates?

For example, I need to disable every input when the view's model isn't new (has an id).
I can do :
if(!view.model.isNew()) {
view.$('input, select, textarea').prop('disabled', true);
}
or I can go do an "if" on every input I have in my template:
<input type="text" {{# if model.id }}disabled{{/ if }}/>
If we follow the MVC (or MVP) pattern, I guess the second approach would be best, since the view logic is in the view. However, if I go with this approach and decide to change the condition that disables the inputs, I need to change it for every input in EVERY template. If I leave in the JS code, there is only one place to change.
This is just one example, but I am having similar dilemmas with alot of things. Hopefully you got an answer for that.
Cheers!
Based on your question, I'd say that you're probably running into this general problem for two related reasons -
You're using backbone exclusively, rather than a framework like Marionette or Chaplin.
Your views are "too big" and trying to incorporate too much material into a single view.
I almost never include logic into templates and that's because I almost never need to. That's because I write a lot of very small views, and piece them together to make large views. Marionette's view classes make this very easy to do, by subclassing the backbone view into different view types, adding additional utilities and drastically cutting down on boilerplate. Marionette is also very good at handling nested views, which really allow you to drill down and create the exact view tool you need for a specific use case.
It's not at all uncommon to be able to define a useful view using Marionette in 1-2 lines of code, which gives you a lot of flexibility to make very small, efficient views. The disadvantage to making lots of small views is that it's a lot of code to write, and could become difficult to maintain, but Marionette makes that disadvantage relatively insignificant. Marionette only took me a couple of days to get the hang of, and I highly recommend integrating it into your Backbone apps for exactly this problem.
When your views are big, and try to do too much, you wind up with the problem you're describing - you have to modify them too much to fit your specific needs and your code gets ugly and hard to read. When you have a lot of small views, they're very responsive and need little if any customization.
The example from your question is, I think, a border line case. My gut instinct would be to create two entirely separate views and run them under the following pseudo code:
editableView = { //definition }}
disabledView = { //definition }}
if (newModel)
editableView.render()
else
disabledView.render()
This is my gut instinct because my bet is that there are other differences between the views than whether the inputs are editable. Even if there aren't now, you may find in a few months that your needs have changed and that you'd like to incorporate some changes. The approach I suggest allows you to put those changes right into the appropriate View and not have to worry about logicking them out in a single view and deciding whether that logic belongs in the template or the view.
If you were absolutely certain that the only difference between the two views was going to be whether the inputs were editable, and that your needs are not going to change in the future, then maybe you would want to think about rendering them with the same view. If that is the case, I'd recommend that you put the logic in the javascript, rather than in the template, for the reasons you identified. But as I said, your example really is a borderline case, and in most instances I think you'll find that shrinking your view scope will really help you to see where your "template logic" belongs.
NOTE: I've talked a lot about Marionette in this answer, but I also mentioned Chaplin as another option above. I don't have much experience with Chaplin, but you may want to consider it at it as a Marionette alternative.
I prefer to do implement view logic in templates:
It is easier to change and read
Any dependency to id, element and etc can be implemented in template
List item
complex logic can be implemented in templateHelper of marionette or serializeData of Backbone without any dependencies to content of template or view
you can also implement complex logic using Handlebar Helper
Disadvantages of view logic in code are:
in case of changes to selectors (id, classes and so), all views have to be changed or reviewed
logic has to be applied again if view is re-rendered
Perhaps what you might be looking for presenter (aka decorator).
Instead of sending the template the model directly, consider sending it though a presenter, this way you can construct the attributes for the input field. Something like this:
present = function(model) {
return {
inputAttributes: model.isNew() ? 'disabled' : '',
id: model.id,
name: 'Foobar'
}
}
template(present(model));
then in your template:
<input type="text" {{inputAttributes}}>

JS templating engine that preserves elements

I have the following problem:
A have a web application where I regularly need to update the user interface when data changes. The data consists of a list of items with different attributes. Because the UI representations of these items can be complex, I use JS templating to render them. When they change I just replace them in the DOM with the HTML representing their updated state.
This approach is simple but has several problems:
you need to re-attach all event handlers because you practically replace elements
there is a flickering effect when reloading resources (probably can be solved using document fragments)
it's impossible to work with developer tools (inspector) if the content changes frequently because, again, all the elements are replaced
So I was wondering if there is any JS templating engine of that many that can deal with the situation. I'm thinking of a feature that intelligently matches elements of the new render and an old one and only changes the content when it has really changed.
I'm thinking of something like this:
Old HTML
<div>
<h1>TV</h1>
<span>$250</span>
Add to cart
</div>
New HTML
<div>
<h1>TV</h1>
<span>$260</span>
Add to cart
</div>
The templating engine find the <span> in the original DOM and replaces its changed value but leaves the rest of the elements intact.
Finally I came across Rivets.js which a lightweight, highly extensible JavaScript templating engine with real time data binding. I love it so far, it's exactly what I needed.
you can try the AngularJS
A simple example:http://jsbin.com/opayuf/4/edit
you can check out these examples if they can meet your requirements
http://tutorialzine.com/2013/08/learn-angularjs-5-examples/
HandleBarsJs may be the one you need, you could see the discussion on
Handlebars.js: Use a partial like it was a normal, full template
You can also try Ember js based on HandlerBarsJs, you can check is out
http://emberjs.com/guides/templates/handlebars-basics/
http://emberjs.com/guides/templates/rendering-with-helpers/

Single Page Application SEO and infinite scroll AngularJS

We are have a site with a feed similar to pinterest and are planning to refactor the jquery soup into something more structured. The two most likely candidates are AngularJS and Backbone+Marionette. The site is user-generated and is mostly consumption-oriented (typical 90/9/1 rule) with the ability for users to like, bookmark, and comment on posts. From the feed we open a lightbox to see more detail about the post with comments, related posts, similar to pinterest.
We have used backbone sporadically and are familiar with the idea but put off by the boilerplate. I assume Marionette would help a lot with that but we're open to changing the direction more radically (eg Angular) if it will help in the long term.
The requirements:
Initial page must static for SEO reasons. It's important that the framework be able to start with existing content, preferable with little fight.
we would prefer to have the data needed for the lightbox loaded already in feed so that the transition can be faster. Some of the data is already there (title, description, photos, num likes/ num bookmarks,num comments) but there is additional data that would be loaded for the detail view - comments, similar posts, who likes this, etc.
Changes to the post that happen in the feed or detail lightbox should be reflected in the other with little work (eg, if I like it from the feed, I should see that like and new like count number if I go to the lightbox - or the opposite.)
We would like to migrate our mobile site (currently in Sencha Touch) to also use the same code base for the parts that are common so we can have closer feature parity between mobile and main site.
These requirements related to my concerns about Angular:
1) Will it be possible/problematic to have initial page loads be static while rending via the templates additional pages.
2) is it problematic to have multiple data-sources for different parts of page - eg the main post part comes from embedded json data and from "see more"s in the feed while the additional detail would come from a different ajax call.
3) While the two-way binding is cool - I'm concerned it might be a negative in our case because of the number of items being rendered. The number of elements that we need two-way binding is relatively small. Posts like:
https://stackoverflow.com/a/7654856/214545
Angular JS ng-repeat consumes more browser memory
concern me for our use-case. We can easily have hundreds of posts each with 1-2 dozen details. Can the two-way binding be "disabled" where I have fields/elements that I know won't change?
Is it normal/possible to unload elements outside of the view port to same memory? This is also connected to the mobile direction because memory is even more of a concern there.
Would AngularJS work/perform well in our use-case? Are there any tricks/tips that would help here?
There are different methods of "infinite scroll" or feed as you put it. The needs of the users and size of acceptable response payload will determine which one you choose.
You sacrifice usability where you meet performance it seems here.
1. Append assets
This method is your traditional append to bottom approach where if the user reaches the bottom of the current scroll height, another API call will be made to "stack on more" content. This has it's benefits as being the most effective solution to handle cross device caveats.
Disadvantages of this solution, as you have mentioned, come from large payloads flooding memory as user carelessly scrolls through content. There is no throttle.
<div infinite-scroll='getMore()' infinite-scroll-distance='0'>
<ul>
<li ng-repeate="item in items">
{{item}}
</li>
</ul>
</div>
var page = 1;
$scope.getMore() = function(){
$scope.items.push(API.returnData(i));
page++;
}
2. Append assets with a throttle
Here, we are suggesting that the user can continue to display more results in a feed that will infinitely append, but they must be throttle or "manually" invoke the call for more data. This becomes cumbersome relative to the size of the content being returned that the user will scroll through.
If there is a lot of content being retruned per payload, the user will have to click the "get more" button less. This is of course at a tradeoff of returning a larger payload.
<div>
<ul>
<li ng-repeate="item in items">
{{item}}
</li>
</ul>
</div>
<div ng-click='getMore()'>
Get More!
</div>
var page = 1;
$scope.getMore() = function(){
$scope.items.push(API.returnData(i));
page++;
}
3. Virtual Scroll
This is the last and most interesting way to infinite scroll. The idea is that you are only storing the rendered version of a range of results in browser memory. That is, complicated DOM manipulation is only acting on the current range specified in your configuration. This however has it's own pitfalls.
The biggest is cross device compatibility .
If your handheld device has a virtual scrolling window that reaches the width of the device --- it better be less then the total height of the page because you will never be able to scroll past this "feed" with its own scroll bar. You will be "stuck" mid page because your scroll will always be acting on the virtual scroll feed rather than the actual page containing the feed.
Next is reliability. If a user drags the scroll bar manually from a low index to one that is extremely high, you are forcing the broswer to run these directives very very quickly, which in testing, has caused my browser to crash. This could be fixed by hiding the scroll bar, but of course a user could invoke the same senario by scrolling very very quickly.
Here is the demo
The source
"Initial page must static for SEO reasons. It's important that the framework be able to start with existing content, preferable with little fight."
So what you are saying is that you want the page to be prerendered server side before it serves content? This approach worked well in the early thousands but most everyone is moving away from this and going towards the single page app style. There are good reasons:
The inital seed you send to the user acts as a bootstrap to fetch API data so your servers do WAY less work.
Lazy loading assets and asynchronous web service calls makes the percieved load time much faster than the traditional "render everything on the server first then spit it back out to the user approach."
Your SEO can be preserved by using a page pre-render / caching engine to sit in front of your web server to only respond to web crawlers with your "fully rendered version". This concept is explained well here.
we would prefer to have the data needed for the lightbox loaded already in feed so that the transition can be faster. Some of the data is already there (title, description, photos, num likes/ num bookmarks,num comments) but there is additional data that would be loaded for the detail view - comments, similar posts, who likes this, etc.
If your inital payload for feed does not contain children data points for each "feed id" and need to use an additional API request to load them in your lightbox --- you are doing it right. That's totally a legit usecase. You would be arguing 50-100ms for a single API call which is unpercievable latency to your end user. If you abosultely need to send the additional payload with your feed, you arent winning much.
Changes to the post that happen in the feed or detail lightbox should be reflected in the other with little work (eg, if I like it from the feed, I should see that like and new like count number if I go to the lightbox - or the opposite.)
You are mixing technologies here --- The like button is an API call to facebook. Whether those changes propogate to other instantiations of the facebook like button on the same page is up to how facebook handles it, I'm sure a quick google would help you out.
Data specific to YOUR website however --- there are a couple different use cases:
Say I change the title in my lightbox and also want the change to propogate to the feed its currently being displayed in. If your "save edit action" POST's to the server, the success callback could trigger updating the new value with a websocket. This change would propogate to not just your screen, but everyone elses screen.
You could also be talking about two-way data binding (AngularJS is great at this). With two way data-binding, your "model" or the data you get back from your webservice can be binded to muiltiple places in your view. This way, as you edit one part of the page that is sharing the same model, the other will update in real time along side it. This happens before any HTTP request so is a completely different use case.
We would like to migrate our mobile site (currently in Sencha Touch) to also use the same code base for the parts that are common so we can have closer feature parity between mobile and main site.
You should really take a look a modern responsive CSS frameworks like Bootstrap and Foundation. The point of using responsive web design is that you only have to build the site once to accomadate all the different screen sizes.
If you are talking about feature modularity, AngularJS takes the cake. The idea is that you can export your website components into modules that can be used for another project. This can include views as well. And if you built the views with a responsive framework, guess what --- you can use it anywhere now.
1) Will it be possible/problematic to have initial page loads be static while rending via the templates additional pages.
As discussed above, its really best to move away from these kind of approaches. If you absolutely need it, templating engines dont care about wether your payload was rendered serverside or client side. Links to partial pages will be just as accesible.
2) is it problematic to have multiple data-sources for different parts of page - eg the main post part comes from embedded json data and from "see more"s in the feed while the additional detail would come from a different ajax call.
Again, this is exactly what the industry is moving into. You will be saving in "percieved" and "actual" load time using an inital static bootstrap that fetches all of your external API data --- This will also make your development cycle much faster because you are separating concerns of completely independant peices. Your API shouldnt care about your view and your view shouldnt care about your API. The idea is that both your API and your front end code can become modular / reusable when you break them into smaller peices.
3) While the two-way binding is cool - I'm concerned it might be a negative in our case because of the number of items being rendered. The number of elements that we need two-way binding is relatively small.
I'm also going to combine this question with the comment you left below:
Thanks for the answer! Can you clarify - it seems that 1) and 2) just deal with how you would implement infinite scrolling, not the performance issues that might come from such an implementation. It seems that 3 addresses the problem in a way similar to recent versions of Sencha Touch, which could be a good solution
The performance issues you will run into are totally subjective. I tried to outline the performance considerations like throttling into the discussion because throttling can drastically reduce the amount of stress your server is taking and the work your users browser has to do with each new result set appended into the DOM.
Infinite scroll, after a while, will eat up your users browser memory. That much I can tell you is inevitible but only through testing will you be able to tell how much. In my experience I could tell you that a users browser can handle a great deal of abuse but again, how big your payload is for each result set and what directives you are running on all of your results are totally subjective. There are solutions that render only on a ranged data set in option three I described, but have their limitations as well.
API data coming back shouldn't be anymore than 1-2kbs in size, and should only take about 50-200ms to return a query. If you arent meeting those speeds, mabye it's time to re-evaluate your queries or cut down on the size of the result set coming back by using child ID's to query other endpoints for specifics.
The main thing that remains unanswered in Dan's answer is the initial page load. We're still not satisfied with the approach that we have to do it client side - it still seems to us that there is a risk for SEO and initial page load. We have a fair amount of SEO traffic and looking for more - these people are coming to our site with no cache and we have a few seconds to catch them.
There are a few options to handle angular on the server side - I'll try to collect some of them here:
https://github.com/ithkuil/angular-on-server
https://github.com/ithkuil/angular-on-server/wiki/Running-AngularJS-on-the-server-with-Node.js-and-jsdom
https://github.com/angular/angular.js/issues/2104
will add more as they come up.

JavaScript framework for building out a dynamic but server-side driven frontend

I am looking at building a small app that is more or less several nested lists, and selecting various items in each list will filter the contents of the other nested lists.
List One
Apple
Phone
iPhone
Computer
Macbook Air
Samsung
Phone
Galaxy S
List Two
Best Buy
Ann Arbor, MI
Chicago, IL
Walmart
Lansing, MI
If a user Clicks on "Apple > Phone", the server will find the associated entiries in list Two for, and update List Two to show only "Best Buy" (assuming Best Buy is the only store selling Phones made by Apple)
My question, is does anyone have a recommendation for what Front end JS library I should use to build this out? This is going to be alot of updating the DOM (the lists) based on AJAX JSON responses from the server.
I took a look at KnockoutJS but things seemed to get messy trying to create a viewModel for each list, and updating it via the KnockoutJS mappings library.
I was thinking about simply using jQuery but Im not a huge fan of building out large sections of the DOM with it (it seems to get ugly quickly).
One thing I would like to avoid (and why I was looking at KnockoutJS) is I dont like writing markup in code. I like the idea of maintaining my Markup in the "HTML", and "binding" the JS data to these elements through a framework.
Also, I hope to use jQuery for all the visual "fluff", event binding, etc.
Thanks
I ended up settling on Backbone.js [1]
It seems a bit more flexible than Knockout.js in terms of the bindings. I am using Backbone supported JS Templates for building out each list level. This has required a bit of code, but Backbone is very flexible (thus the bit of code). Im sure this is possible in many other JS frameworks, but I think i've been able to make more progress w Backbone is I dont need a deep understanding of the framework/API/intricacies to make it work - the(my) code may be more verbose, but because of this its easier to piece together how everything works.
[1] http://backbonejs.org/
This is more of a partial answer, trying to tackle the concept of "maintaining...Markup in the 'HTML'". I would create a generic menu item in the HTML that can be the template for each menu item, like so:
<li id="menuItemTemplate" class="menuItem">
<span class="menuItemText"></span>
<ul class="submenu"></ul>
</li>
This would not be in a visible place on your page; it would simply be the HTML that gets inserted for each menu item. Then, when you go to add menu items, your JavaScript would be in charge of adding as many menuItem elements as you needed in your list. As far as HTML manipulation, JavaScript would only need to do things like add id or class attributes to organize or style your data, as well as add the text content of each item. A sample implementation might look like this (I love jQuery):
function loadMenuItem(text, parentId) {
// Grab the template
var newItemHtml = $("#menuItemTemplate")[0];
// Set its id to something unique
$(newItemHtml).attr("id", getNextId());
// Set the text
$(newItemHtml).find("span.menuItemText").html(text);
// Put it in the clicked menu
$(parentId + "ul.submenu").append( newItemHtml );
}
In the end, I won't be programming your project, though. I can only give you my preference. If this is going to take a good amount of time, I'd say that the best thing for you to do is to try out all of the frameworks that sound interesting (on a small scale, obviously) to get a general feeling for how you like developing DOM-transforming apps in each one. That'll give you a better idea of which you'll like more as well as introduce you to different frameworks.
Not a direct answer to the question - still it is worth to take a look at Kendo UI MVVM
MVVM using Kendo UI in three simple steps
Kendo UI Web MVVM
Understanding MVVM – A Guide For JavaScript Developers
MVVM in Kendo UI Walkthrough
Build Single Page Apps – Part 7 – MVVM and KnockoutJS

Categories