Comments (36)
Possibly / Probably.
A great place to start would be to design it as a BackBone plugin. Feel free to extend Views as much as you see fit. That way you'll be able to start using it now, and we can see about merging it in if it seems like a good fit.
from backbone.
Awesome! I'll start a repository and get to work, and obviously any input from anyone would be greatly appreciated.
from backbone.
We'll leave this ticket open, and you can post examples and code snippets in here, if you like, as you go along, and folks will be able to comment...
from backbone.
+1 for sub-views. I'm willing to guess as I continue writing more view classes to wrap presentation elements I'm going to want to stay DRY.
from backbone.
Would you mind giving me some idea of how you'd like to see them implemented?
from backbone.
I'm afraid that's up to you -- I'm not sure what you have in mind for view enhancements, other than what you mentioned at the top of the ticket, and the first two are pretty easy:
hide: function() {
$(this.el).hide();
},
destroy: function() {
$(this.el).remove();
},
Subviews is a whole `nother can of worms, and I don't know too much about what that could or should look like -- sorry.
from backbone.
That's cool, I just wanted to make sure that I gave people plenty of room for input.... I should probably just start working on it and then let people critique. Thanks!
from backbone.
I actually think sub-views should be rather simple idiom wise. Not sure about implementation.
var FormView = Backbone.View.extend({ form_stuff: function() {} });
var Signup = FormView.extend({ stuff: function() {} });
Thoughts?
from backbone.
I think bunchesofdonald
is talking about nested child views, not subclasses of general views -- which is something you can already do...
For example, we currently have this heirarchy:
- Backbone.View
- dc.ui.Dialog
- dc.ui.AccountDialog
- dc.ui.UploadDialog
- dc.ui.EmbedDialog
- dc.ui.TimelineDialog
- dc.ui.Dialog
from backbone.
Sorry about that, not sure why they aren't working for me. I thought it was rather silly they weren't.
from backbone.
Yeah what I intended would probably be better called child-views than subviews. Views that are attached to and controlled by top-level views.
I've been working on this for a couple days now, the repository is up at -http://github.com/bunchesofdonald/backbone-spwa and I have a fully working example application. The application is a very simple contact manager, I'm working on getting the github page up so that you can try it online, but you can always clone it and run it locally.
It does not have child views, but I have implemented a controller class that I think covers some of the ground that child-views would. So it's a step in the right direction.
from backbone.
Working example now at: http://bunchesofdonald.github.com/backbone-spwa/examples/contacts/contacts.html
from backbone.
Very nice. You could even persist changes to the address book using LocalStorage and Backbone.sync, for a nice refresh-capable demonstration. Also, it would be really neat if the search box filtered the contacts as you type...
As to the SPWA project itself, it seems like the main component is the notion of a controller that routes hash-urls to actions, via hashchange
events. This is something that we considered adding to Backbone before the initial release, but decided not to include. On the one hand, URL-routing is usually quite a small part of a client-side application, and there are plenty of existing modules for it. On the other, given the success of Sammy.js, people expect to have URL-routing provided.
Do folks think it would make sense to add a Backbone.Controller
, with capabilities similar to Chris' Backbone.SPWA.Controller
?
from backbone.
Bunchesofdonald, awesome! +1 from me on including something like this in Backbone.
Personally, I would prefer defining routes via regexp or with specifying parameters for interpolation ("/foo/:name/"). I have a project called pineapple[1] that does similar things as Backbone. Ultimately, when Backbone came out, I have found I prefer Backbone, but I have been experimenting with ideas in that project. One thing I think pineapple does pretty well is routing[2](the current implementation might a have a couple bugs, I have been changing things rather liberally and can't remember what state its currently in). Basically, you define routes as having both an enter
event and an exit
event. I think having the exit
event is very nice, but it gets overlooked a lot. Here is what it looks like to define a route:
// Routes are defined with strings that get coerced to RegExp.
// (It is easier than having to escape backslashes all the time \/)
app.defineRoute("^#/foo/(\w+)/$", (function () {
// Do some private stuff before returning the object
return {
enter: function (path, word) {
// Activation stuff (word is the group match of regexp)
},
exit: function () {
// Clean up stuff
}
};
}()));
Of course, Backbone would probably use an OO approach rather than the closure style pineapple does. I think the two important things I want to get across is the awesomeness of regexp routes (and using regexp groups rather than ?foo=bar param style) as well as having entrance and exit hooks.
Ben Alman's jQuery hashchange is a good choice.
More opinons to come when I get a chance to really look through the code :)
[1] http://github.com/fitzgen/pineapple
[2] http://github.com/fitzgen/pineapple/blob/master/src/routes.js
from backbone.
Also, being able to have something like app.redirect("/new/path/")
is a must.
from backbone.
This is exactly what i've been looking for! I've played around with my own view manager framework and found that backbone complemented it nicely. jQuery Mobile seems to have a nice way of dealing with SPWA. I'm currently evaluating it but it may be worth taking some ideas from this?
As well as sub views, I've found that views that don't leave a history state are usually required. This can be annoying when using the hash change event for navigation. But I agree that the hash change is the most logical and semantically correct method of dealing with nav.
Enter and exit methods would be useful. Allow for setup/cleanup and animations.
from backbone.
That's a very nice demo and really fills in some holes as far as common use cases not in the documentation (which was also excellent). I especially like Backbone.SPWA.Controller's hashevent router and those x-ejs templates.
I could definitely see something like this being useful for my apps, however I'd like to see Backbone handling the handleEvent delegation behind the scenes.
from backbone.
Fitzgen: I definitely think that regex is the way to go for the routes, as it stands it was more to get it up and running, so some things are the way they are just to have gotten it put together.
I really like the exit idea, that would be much better than the this.hideAll(), as each view could decide what it wanted to do as it lost focus. And we also do need a redirect rather than the location.hash = '/';
owz: I've not really looked at jquery mobile, but I will! Just on a quick glance it looks like it's trying to aim somewhere in-between what I'm doing and something like Cappuccino and SproutCore.
cheapRoc: Thanks! It is a bit kludgy in parts.
from backbone.
jashkenas: Those are great ideas for the example! And of course I would be a big +1 to backbone doing something like this.
from backbone.
Having this in a backbone controller would be very useful +1
from backbone.
The example is updated with the suggestions from jashkenas, it's much better that way, thanks!
I've been thinking about the router/enter/exit thing, and I think that I've come up with an elegant solution. It's early stages but what would you think of:
Dropping the Controller class in favor of a Router class. Make views so that they can subscribe to router events, via regex, they will get an event both when the hash that the subscribed to is 'entered' as well as 'exited'. The router class would be similar to Backbone events. That saves us from some of the nasty code that is in the controller (this.hideAll(), this.getView, etc). I think this also helps with some of the complexity of the child views, as each view would know the current 'state' of the application and could respond accordingly.
from backbone.
Make views so that they can subscribe to router events, via regex, they will get an event both when the hash that the subscribed to is 'entered' as well as 'exited'.
It feels much more natural to me that the routes should manage views based on enter/exit events, rather than have views subscribe to a certain route's events. I think that would make views do too much. I think views are fine as is. How do others feel about this?
from backbone.
It's worth having a look at the way sammy.js handles these issues. Also, this useful snippet was posted a while back by jashkenas - http://gist.github.com/624773.
from backbone.
I've been poking around a bit more, and I think I'm still pretty skeptical of including a hashchange
router in core Backbone -- here's why:
- Dealing with faux-URLs is an important part of a client-side app, but a very small one. In DocumentCloud, we probably have 30x the models and views that we do url-routes. Some single-page apps, like the Todo list example, don't benefit from routes at all...
- For example, check out the "In the Wild" section of the Sammy Wiki: http://github.com/quirkey/sammy/wiki/In-The-Wild ... Only one of those three sites actually seems to use hash-urls in any fashion, and it's the one that's effectively a static HTML site to start with.
... so -- it might make more sense to have Backbone.Router
(Backbone.Controller
, Backbone.History
) be a plugin for starters, and we can see how many folks find it to be useful.
from backbone.
That's probably a good way of handling it. You're right simple applications, or those for which a page reload here and there is ok, probably wouldn't benefit from this, and at this time, that's probably most sites.
But I also think that single page applications is the way the web is going to go, it makes for a much more desktop-like application. Also Sammy doesn't really provide the data modeling, nor really the views, that backbone does, and I would consider that a huge road-block to SPWA.
from backbone.
I started some work on Backbone.Mapper
and Backbone.Controller
. This is mostly lots of code borrowed from Sammy
, but jquery.hashchange
based, more modular and without http verbs stuff that I found mor disturbung then helpful on the client side... I will try to add some tests, docs and a real example application over the week end.
tchak/backbone.plugins
For the moment there is routes handling, actions and filters. I plan on add some views integration lately.
from backbone.
Worth reading on topic:
from backbone.
After some more prodding, and the discovery that Sammy does not work (and has never worked) in Internet Explorer < 8, I'm starting on this in earnest. Work so far is here:
from backbone.
Why reimplement the logic to make IE < 8 handle back buttons? Ben Alman already has created a jquery plugin to do just this that has been widely adopted and used by the community. Unless I'm missing something (which I will be the first to admit is very possible), I don't see why his can't just be integrated in a build script.
http://benalman.com/projects/jquery-hashchange-plugin/
Also, I have found that it is very common for a view to want to clean up after itself before the next route is entered. Any reason in particular why this is only emitting events on enter, and not exit events right before? Specifically, I think it would be cool to trigger specific route exit events. That way a controller doesn't have to bind to "global" level route events, just exit and enter events for its particular route. I think that is a lot cleaner than having every single route bind to every route change for clean up. I hinted at this in the above conversation. Thoughts?
from backbone.
The reason not to include "exit" events is that URLs are supposed to be stateless ... you should be able to navigate to a new URL fragment without knowing anything about what state is currently loaded. Can you share a couple examples of your use of "exit" events from your pineapple project?
Ben Alman's project was a fine resource when he first released it, but I'm not a big fan of it: it's far longer and more complex than necessary, and serializes your state into fairly gross URLs by default. There are more lines of code in jQuery-BBQ than there are in all of Backbone, the hashchange stuff included...
from backbone.
I would think that the exit would be more from a perspective of a running application. So for instance an exit could hide the view that was previously showing, or do some clean-up in order to pass the "focus" of the application to the new view.
from backbone.
The example I'd give for an exit event is basically this:
Whenever you are going to a new route, I have found that usually, you will be re-rendering a large portion of the page and activating new widgets, etc. At the start of entering any given page, you can globally disable/hide/destroy everything and then replace it with your new stuff, but its overkill. It would be easier to not have every route have to perform this page purging and let each route clean up after itself only. That way you aren't telling widgets which are already disabled to disable themselves: only the ones that need to be disabled will get the message.
Here is some psuedocode:
var myRoute = new Route({
initialize: function (opts) {
this.views = opts.views;
this.main = $("#main");
},
enter: function (id) {
this.views.each(function (v) {
this.main.append(v.render().el);
});
},
exit: function () {
this.views.each(function (v) {
this.main.remove(this.view.disable().el);
});
}
});
Re: jquery BBQ, yes BBQ is large and arguably bloated, however Ben Alman also released the jquery hashchange plugin which implements only the logic needed for the back button and is quite a bit smaller. BBQ is built on top of hashchange. Whatever floats the virtual boat, so to speak.
from backbone.
Ahh, that's the beauty of mutually-exclusive CSS class names...
Instead of blowing away an entire tree of UI/views when you tab away, and then re-creating them then you tab back over, it's much nicer to just set a CSS class on a high-up node, or even document.body
. For example, after loading the workspace, our <body>
tag looks something like this:
<body class="logged-in sidebar-tab-entities main-tab-documents paginated">
And if you change tabs, from say "documents" to "help", you'll have a class name of "main-tab-help". It makes for faster tabbing around, because it's a single DOM repaint instead of expensive UI building, and helps keep things stateless -- you don't need to worry about wether "Projects" are being rendered, or "Entities" are: they're both ready to be rendered at all times...
Thoughts?
from backbone.
Very clever! I like this technique a lot. The question remains though: where do you add and remove the classes to and from the body? The example just changes like this:
var myRoute = new Route({
initialize: function (opts) {
this.main = $("#main");
},
enter: function (id) {
this.main.addClass("foobar");
},
exit: function () {
this.main.removeClass("foobar");
}
});
from backbone.
Naturally, the simple thing is just to removeClass()
before you addClass()
, but something a bit more sophisticated that handles mutually-exclusive classes was actually almost part of the initial Backbone.View, and got pulled before release. Right now, we have this little extension, in DocumentCloud:
// Makes the view enter a mode. Modes have both a 'mode' and a 'group',
// and are mutually exclusive with any other modes in the same group.
// Setting will update the view's modes hash, as well as set an HTML class
// of *[mode]_[group]* on the view's element. Convenient way to swap styles
// and behavior.
Backbone.View.prototype.setMode = function(mode, group) {
this.modes || (this.modes = {});
if (this.modes[group] === mode) return;
$(this.el).setMode(mode, group);
this.modes[group] = mode;
};
$.fn.extend({
// See Backbone.View#setMode...
setMode : function(state, group) {
group = group || 'mode';
var re = new RegExp("\\w+_" + group + "(\\s|$)", 'g');
var mode = (state === null) ? "" : state + "_" + group;
this.each(function(){
this.className = (this.className.replace(re, '') + ' ' + mode).replace(/\s\s/g, ' ');
});
return mode;
}
});
So, in your view, when it opens, you just call:
`this.setMode('entities', 'sidebar');`
... And get an "entities-sidebar" class, blowing away all other "-sidebar" classes. You can also say:
this.modes.sidebar
, and get back "entities"
.
Not that I'm advocating this extension -- addClass
, removeClass
and toggleClass
are perfectly sufficient for most needs, but if you're doing a lot of stuff with mutually-exclusive classes, where you can have more than just "on" and "off", it's handy.
from backbone.
Backbone.js 0.3.0 is now out, and includes Controllers with hashchange-based routing... Closing this ticket.
from backbone.
Related Issues (20)
- Backbonejs (1.4) version compact with jQuery (3.4.1) ? HOT 2
- Token error 'delete' on an old browser HOT 3
- How can I use installed npm library in backbone view
- Backbone is being actively maintained HOT 29
- Embrace prototypes HOT 12
- Upgrade devDependencies, add lockfile HOT 21
- Replace travis with GH Workflows HOT 22
- Should Backbone.Collection throw an error when client code attempts to add the same model twice? HOT 8
- Browser tests that don't work in Sauce labs
- Separate fetch/save api into plugin or external module HOT 17
- Bug in _removeModels: function(models, options) { HOT 1
- Uots about time
- error event not firing for Collection.create with wait true HOT 4
- Clean up misguided legacy changes HOT 1
- Community question: who is interested in reviewing my pull requests? HOT 3
- Testing against outdated vendor libraries HOT 1
- Misleading line in CONTRIBUTING.md HOT 2
- ES Modules: please discuss HOT 33
- Changelog? HOT 1
- Will updating backbone also update jquery? [answered: no] HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from backbone.