Coder Social home page Coder Social logo

Comments (36)

jashkenas avatar jashkenas commented on May 20, 2024

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.

bunchesofdonald avatar bunchesofdonald commented on May 20, 2024

Awesome! I'll start a repository and get to work, and obviously any input from anyone would be greatly appreciated.

from backbone.

jashkenas avatar jashkenas commented on May 20, 2024

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.

jwreagor avatar jwreagor commented on May 20, 2024

+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.

bunchesofdonald avatar bunchesofdonald commented on May 20, 2024

Would you mind giving me some idea of how you'd like to see them implemented?

from backbone.

jashkenas avatar jashkenas commented on May 20, 2024

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.

bunchesofdonald avatar bunchesofdonald commented on May 20, 2024

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.

jwreagor avatar jwreagor commented on May 20, 2024

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.

jashkenas avatar jashkenas commented on May 20, 2024

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

from backbone.

jwreagor avatar jwreagor commented on May 20, 2024

Sorry about that, not sure why they aren't working for me. I thought it was rather silly they weren't.

from backbone.

bunchesofdonald avatar bunchesofdonald commented on May 20, 2024

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.

bunchesofdonald avatar bunchesofdonald commented on May 20, 2024

Working example now at: http://bunchesofdonald.github.com/backbone-spwa/examples/contacts/contacts.html

from backbone.

jashkenas avatar jashkenas commented on May 20, 2024

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.

fitzgen avatar fitzgen commented on May 20, 2024

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.

fitzgen avatar fitzgen commented on May 20, 2024

Also, being able to have something like app.redirect("/new/path/") is a must.

from backbone.

 avatar commented on May 20, 2024

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.

jwreagor avatar jwreagor commented on May 20, 2024

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.

bunchesofdonald avatar bunchesofdonald commented on May 20, 2024

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.

bunchesofdonald avatar bunchesofdonald commented on May 20, 2024

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.

 avatar commented on May 20, 2024

Having this in a backbone controller would be very useful +1

from backbone.

bunchesofdonald avatar bunchesofdonald commented on May 20, 2024

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.

fitzgen avatar fitzgen commented on May 20, 2024

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.

eloop avatar eloop commented on May 20, 2024

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.

jashkenas avatar jashkenas commented on May 20, 2024

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.

bunchesofdonald avatar bunchesofdonald commented on May 20, 2024

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.

tchak avatar tchak commented on May 20, 2024

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.

chrislloyd avatar chrislloyd commented on May 20, 2024

Worth reading on topic:

https://developer.mozilla.org/en/DOM/Manipulating_the_browser_history#Adding_and_modifying_history_entries

from backbone.

jashkenas avatar jashkenas commented on May 20, 2024

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:

master...controller

from backbone.

fitzgen avatar fitzgen commented on May 20, 2024

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.

jashkenas avatar jashkenas commented on May 20, 2024

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.

bunchesofdonald avatar bunchesofdonald commented on May 20, 2024

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.

fitzgen avatar fitzgen commented on May 20, 2024

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.

jashkenas avatar jashkenas commented on May 20, 2024

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.

fitzgen avatar fitzgen commented on May 20, 2024

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.

jashkenas avatar jashkenas commented on May 20, 2024

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.

jashkenas avatar jashkenas commented on May 20, 2024

Backbone.js 0.3.0 is now out, and includes Controllers with hashchange-based routing... Closing this ticket.

from backbone.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.