Coder Social home page Coder Social logo

chaplin's People

Contributors

aheuermann avatar akaryatrh avatar akre54 avatar andriijas avatar cbourgois avatar chadhietala avatar davidnpma avatar denikus avatar flisky avatar florian-r avatar iangreenleaf avatar jonakyd avatar karellm avatar knuton avatar krivega avatar lukateake avatar mehcode avatar miklschmidt avatar molily avatar opyh avatar paulmillr avatar rendez avatar rubiii avatar shvaikalesh avatar sija avatar timgates42 avatar vendethiel avatar wprater avatar yandrew91 avatar zallek avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

chaplin's Issues

chaplin need modify based Backbone.js

For now Backbone do not return a Backbone value to require.js need.

http://backbonejs.org/backbone-min.js

So the usage in chaplin like this:

define [
'jquery',
'underscore',
'backbone',
'chaplin/lib/utils',
'chaplin/lib/subscriber',
'chaplin/models/model'
], ($, _, Backbone, utils, Subscriber, Model) ->
'use strict'

class View extends Backbone.View
...

Maybe got a error of Backbone.VIew do not exist.

So user need add a return value (Backbone) to Backbone.js.

And this is also be done for underscore.js.

Deferreds and SyncMachines might integrate better with fetch/save/sync

If you’re using SyncMachine, you have to call @beginSync() and @finishSync() manually. Same goes for @resolve() when using Deferreds. We need to investigate if it makes sense to do that automatically by providing a Model#sync which adds a success handler to the options. The handler would call the original handler and then @finishSync() or @resolve().

Don’t know if that makes sense because there might be cases where a different order might be needed.

Routing after a page reload.

Hi. What are the possible ways to implement the routing after an user refreshes a page? In most cases a server will return '404-Not found'. Please advice.

Passing parameters to routes

Say I have this route:

match 'events', 'events#index'

And an anchor with an href = /events?location=City%2C%20Region.

How do I get the location parameter to be passed on when clicking the link? Am I missing something?

Auto-removing all properties on disposal

I've been implementing a lot of chaplin into a personal library and I've had a thought about the disposal of objects. Chaplin is explicitly stating which properties to remove:

properties = [
  'collection', 'attributes', '_escapedAttributes', '_previousAttributes',
   '_silent', '_pending'
]
delete this[prop] for prop in properties

Is there any reason you couldn't do the following instead?

delete this[prop] for prop in _.without(_.keys(@), _.functions(@))

This removes every property that isn't a function. This way subclasses don't need to setup their own disposal methods in most cases and can rely on the parent disposal method to take care of most of the work.

Use Require.js CS Plugin

Was wondering if there is a reason chaplin does not use the Require.js coffeescript plugin? I have found it to work out pretty good, no need to compile the coffeescript in development. When the build is ran for production the cs plugin gets omitted (its a param in the build file for r.js) since you are compiling into a single javascript file.

Currently chaplin has a hard dependency of require.js and was just wondering if this is on the roadmap or has even been discussed.

Chad

Use CommonJS

Should chaplin really hardly depend on AMD?

Marionette provides non-amd version which is a great advantage.

Named routes

So, the idea is to add named routes support. It would be pretty useful in templates, for example, with helpers.

{{#route users show}}{{username}}{{/route}}

Move view#serialize to `lib/utils`

It is useful, for example, in with_user Handlebars helper:

# Evaluate block with context being current user
Handlebars.registerHelper 'with_user', (options) ->
  context = mediator.user.getAttributes()  # <—————— need to serialize this
  Handlebars.helpers.with.call(this, context, options)

View#render: Delegation vs. copying attributes

#57 introduced the serialization of model attributes. This basically creates a new object and copies/references the properties from model.attributes, now with a bit of conversion.

This is contrary to the delegation approach using utils.beget, so now beget is unnecessary since a new object is already created.

A faster, memory-saving way is to use delegation and only set the transformed properties on the object itself.

This needs to work recursively, that is on the second, third etc. serialization level, too.

Questions about idiomaticness

If you don't mind, i'll ask in the issue some questions because there're no other ways.

Consider twitter sidebar

I want to create SidebarView and StatsView with StatusView inside of it. What's the idiomatic way to do this?

I mean, if I set StatusView containerSelector to some element from SidebarView then it's not rendered because it's too early and the element wasn't created. Should I publish a global event statusViewRender and listen for it in children composite views in this case? Should I init composite views in SidebarController?

View#afterRender is called always when View#render is wrapped

View#afterRender is called always when View#render is wrapped, even if the view was disposed.

For example, this logs nothing:

class FirstView extends View
  afterRender: ->
    super
    console.log 'FirstView#afterRender'

view = new FirstView
view.dispose()
view.render()

but this logs SecondView#afterRender to console:

class SecondView extends View
  render: ->
    return unless super?  # Do not render if the object was disposed
    console.log 'SecondView#render'
    this

  afterRender: ->
    super
    console.log 'SecondView#afterRender'

view = new SecondView
view.dispose()
view.render()

Move most of the utils out of Chaplin core

Most of the utils in Chaplin core are not used by Chaplin core itself and just blow up the lib size, so we should move them into the app-specific utils in the example repository (don’t know if this is the best place in the end, but that’s the place where they are needed at the moment).
Also, I’d like to change the signature of some of the Deferred helper methods to config hashes instead of 27 arguments.

Data presistance after route changing

Hi,

I'm not pretty sure if it's a right place to discuss about it, but I would like to ask you about one of your concepts, and consider it at my use case.

In your app flow after the route is matched, the controller is initialialized, where next are initalized model, and collections. However, I would like to ask you what do you do in case, you want to keep data between routes changes?

Eg. imagine a case, when you want to present one collection on two views - one is a grid in table form, and second is a map, when you mark collection items. You want to store selected view, so you need routes to be involved. However there is no need to initialize collection each time. How would you solve this case?

PS. Do you have any discussion list or sth. to talks about chaplin patterns ?

Google ServiceProvider example

Could you please provide an example of how to properly use the Google JS API ServiceProvider? I'm struggling to get it working properly. Thanks!

###console.debug### statements

Just realized that ###console.debug 'foo'### doesn’t make much sense. In the compiled JS, I cannot just remove the sorrounding /* */ because console.debug 'foo' is CoffeeScript, not JS.

We could write proper JS in the comment, i.e. ###console.debug('foo');### – But I don’t like that much. Looks ugly and misleading in CS code.

Actually I’m not convinced any more that there is a huge benefit in having these comments in the compiled Chaplin lib. Libraries don’t offer such comments normally.

If someone wants to learn and debug, the plain CoffeeScripts instead of the super-module are the best choice, so #console.debug 'foo' would totally suffice for them. In order to add logging or debug output, one can also edit the application-specific base files we’re going to provide in the example repos.

Views: Allow the standard Backbone event registration using delegateEvents and the events hash

Code context: https://github.com/moviepilot/chaplin/blob/development/coffee/chaplin/views/view.coffee#L97

Currently Chaplin disallows the use of Backbone’s delegateEvents and the declarative events approach. We did this on moviepilot.com to enforce the usage of @delegate alone for consistency reasons. (Enforcing conventions and consistency was one of the main goals of this structure.) @delegate has several advantages: In contrast to the events hash, it works fine when two views inherit from each other and both register handlers. Also, @delegate automatically binds the handlers to the view.

I would still advice the programmatic approach with @delegate, but there’s no reason to disable the standard Backbone approach completely. People like the declarative approach, and if this is good for you, Chaplin shouldn’t render the Backbone feature completely defunct.

Also, Backbone’s delegateEvents got better. events might be a function, so it is possible to programmatically create the hash. This allows to

  • add handlers conditionally
  • create handler functions programmatically
  • call super to get the event hash of the parent class

Sure, this would still be a bit hacky compared to a pure programmatic approach, but one could argue in favor of Backbone’s standard mechanism.

I will come up with a PR soon. Probably it’ll suffice to remove the overwritten delegateEvents method.

Testing Strategy

I saw some tests being added for the core pieces of functionality, which I appreciate!

I've wondered how others have written their unit tests for application code that they've written, especially with require.js/jasmine ( e.g. How do you isolate the modules from their dependencies so that the tests are proper unit tests and not integration tests? )

Will you also be adding some tests for the boilerplate app that show your testing strategy?

Great work by the way!

  • Burin

Version number

What would you think of versioning Chaplin like so:

<major>.<minor>.<fix>

major may not be backward compatible
minor must be
fix also

AMD Sugar

Great effort. Thanks a lot.

After some deliberation we decided to use the "simplified CommonJS wrapping" notation as it is advocated by J. Burke of requirejs: http://requirejs.org/docs/whyamd.html#sugar for our project. We actually prefer it because it feels somewhat easier to read and it may help to avoid unnecessary module loading as it seems to happen in your view.coffee class.

So we were wondering if there are some factors that we are overlooking or not taking into account. And since you really seem to know what your are doing here we would very much appreciate it if you could briefly explain to us why your are sticking to the classic notation.

Misuse of requirejs

Hi,

I can help with any of the following recommendations. I just wanted to discuss it first.

Disclaimer: I use the development branch.

Vendors as modules
I highly recommend that all the vendors are turned into AMD modules. Here is a list of links to AMDified vendors:

Complete dependency declaration
A module should list all its dependencies to be as self-contained as possible. create_mediator.coffee should be:

define [
  'underscore',
  'chaplin/lib/support'
], (_, support) ->
  //...

I need help fetching and loading collection from restful api.

I'm trying to use Chaplin as a sample scaffold to model my application on. In your Facebook sample you use a service provider to get "likes" and "posts". But, when if I wanted to load an object from a restful api instead? In my current app, that I'm migrating over to using Chaplin's architecture, I have a backbone collection called Notes. By simply calling notes.fetch the collection automatically fetches a json list from my restful api. For some reason, I can't seem to figure out the steps to trigger the fetching of a collection using Chaplin's architecture. In the case of "likes" in the initialize method "@getlikes()" ... which in turn calls the service provider with a callback to @processLikes(). This is all good. But, when how would I go about utilizing the built in capability of a collection to fetch its list from a restful api? I'm writing my application using vs.net 2010 and my backend is the new MVC 4 webapi (that supports restful services).

I'm really loving the architecture of Chaplin. It is quite elegant.

Best regards,
Chris

How to get the example application: Facebook Likes Browser running?

First off, thank you so much for releasing this code and for the excellent write up. I've been using backbone.js, require.js, coffee script, jquery, etc. on a single page application for about 6 months. I am embarrassed to say that I can't seem to get your sample app running. I'm working in Windows 7 environment. Basically, I took the download and put the index.html file (along with all folders) and copied them to my default web site. I added the line 127.0.0.1 chaplin.moviepilot.com to my hosts file. I navigated to chaplin.moviepilot.com and I got the page to render, but, it was chock full of errors. I apologize, I'm not at home right now, so, I don't have access to the exact errors. But, I'm curious, am I going about it the right way? I am excited and eager to start working with Chaplin. I've tried Marionette and found it too difficult to migrate to AMD (requirejs). I was so happy to see your sample app and I'm busy studying it to see how I can get it to work.

Also, you mentioned in your writeup about including backbone, underscore as regular scripts tags. I was able to get around this and use them as AMD modules with this nice plugin called use.js. It is written by one of the core backbone JavaScript engineers tbranyen https://github.com/tbranyen/use.js. Just thought I would mention it. It worked out well.

Chaplin looks great and really does fill a need that became evident to me the more I worked with backbone.

Best regards,
Chris

Separate Chaplin into a 'framework' and a sample app.

Forgive me if this goes a bit against the philosophy of Chaplin, but after working with it for a while it is clear that Chaplin contains about 50% generic, reusable code and 50% sample application code (sessionController, likes controller, posts controller, etc.)

Lets say someone has 5 smallish sites running under the Chaplin structure. Right now, it would be cumbersome to merge in changes and optimizations to the base classes, views, and application logic because they are interspersed with sample code.

I would propose that Chaplin could be split into a framework-esque base set (for the sake of discussion lets call it "Bowler'), and then a sample implementation of that base set called 'Chaplin'.

Bowler can contain the following:

  • application.coffee
  • mediator.coffee
  • routes.json
  • controllers/
    • controller.coffee
    • application_controller.coffee
  • lib/
    • route.coffee
    • router.coffee
    • subscriber.coffee
    • support.coffee
    • sync_machine.coffee
    • utils.coffee
    • view_helper.coffee
  • models/
    • collection.coffee
    • model.coffee
    • user.coffee
  • views/
    • application_view.coffee
    • collection_view.coffee
    • view.coffee

Essentially, boil it down to a glorified 'Hello World'. That allows developers using it to more easily incorporate updates and optimizations to the core logic into their app. In an ideal world, this core would even be stored in a bowler/ or core/ directory that developers don't touch. They instead extend it where necessary.

Chaplin then can happily continue to demonstrate how one might handle authentication, advanced views interactions, proper use of collections, etc.

Thoughts?

Idea: use console.group

This is a not so well-known method that improves readability. No more need to use \ts etc.

But i'm not sure where exactly it should be used (everywhere?).

Better debugging

Current way of debugging is not that great because if you're using js version of chaplin, all commented console.debugs are stripped.

What do you think about such debugging technique?

  • Mediator contains boolean debug param.
  • All console calls are uncommented. But they check for this param
mediator = require 'mediator'
class View
  render: =>
    if mediator.debug
      console.debug 'meh'

Re-defining console.debug isn't an option because in this case inspector wouldn't show lines where console.debug was done.

Delegate Events from Collection View for sub-views

Imagine the scenario where you have a <ul> of <li>'s that contain clickable <a> tags. As far as I an tell the convention in Chaplin would be to have a Collection view for the <ul>'s, an 'item' view for the <li>'s, and then to @DeleGate the <a> clicks from the 'item' view.

The problem with this is that is binds events to every <li> view. This doesn't really take advantage of delegation at all, where you would ideally delegate from the <ul> to the selector: 'li a'. This would be only one event handler for the whole collection view. The problem is: you want the handler to be scoped to the item view that was clicked.

Is there an already established patter to do this? The challenge is the event handler is on the collection view, and it needs to somehow (from the DOM element passed back by jQuery) establish which item view instance to bind to. I suppose the id attribute could be used?

Thought about the development branch

Hi,

I just started digging in this branch and I thought I would share some thoughts.

File structure: controller
I'm not sure I like the application_controller.coffee to be in /chaplin/controllers. I would probably refactor controller.coffee to take more of application_controller.coffee and then move application_controller.coffee to the /controllers folder to allow the user to add stuff to it (while controller.coffee should never be touched).

I also noticed that both controller.coffee and application_controller.coffee extended the Subscriber. As the second inherit from the first one, is it really necessary?

File structure: view
As for application_controller, I would move application_view.coffee back into the application, maybe refactoring it to remove anything that could be abstracted in a parent it would inherit from.

Also what would you think of naming it layout like in Rails? A layout load views. I don't really calling it application_view.

Naming
This one is silly and really a matter of taste. I would probably set the folders in /chaplin to singular: controller instead of controllers. They contain the concept not "instances".


It is about it for now. I'll keep digging in and let you know if there is anything else.

How to trigger Facebook authentication from Visual Studio solution.

I am making good progress with my application built using Chaplin. I am getting lists to display and I am currently working on editing my objects. I want to thank you for building such an elegant framework. I love backbone.js, but, I kept finding the need to fill in the missing gaps (e.g. controllers, disposing objects, pub/sub, etc.). I am so happy I discovered Chaplin.

I develop in visual studio and I built a solution and migrated all the sample chaplin application files into it. Because the sample Chaplin application has to be run using the mock domain chaplin.moviepilot.com I can not get the Facebook service provider to work when I run my visual studio application. When running a visual studio application it just runs in localhost with a port number. Eventually, I want to authenticate my users by using either Facebook, Gmail, Twitter, or allow them to create a user account. Can you give some guidance on how I might run Facebook authentication without the need to use the mock domain chaplin.moviepilot.com? So much depends on having an authenticated mediator.user that it is difficult for me to move forward.

I have looked at the Facebook provider, however, I have to admit that it is beyond my skillset to understand right now. I don't want to change the provider, I just want to enable my application to use the provider without running under the domain chaplin.moviepilot.com.

Best regards,
Chris

Backbone Collection rendering

"Rendering collections on the UI would be painful without it since Backbone does not provide a clean mechanism to render collections."

Would you like to clarify this statement..? It seems to me you're using exactly the mechanism Backbone provides, that is, creating sub-views for each Model in a Collection and appending them to a CollectionView. Do correct me if I'm wrong, but I think it's both quite clean AND the way demonstrated by the (now legendary) ToDo-sample app.

(Thanks for an awesome write-up on your architecture BTW)

Shared Collection Data

I've been working to implement a Chaplin-style architecture in an app I'm working on and I've discovered a missing piece that could be helpful. Views often have two collections with the same models in them. If the collections aren't using the same model instance, changes to the model won't reflect in both (or more) views without some sort of manual syncing.

The idea would be have a datastore object alongside the mediator. It's used to retrieve models and fetch them if they don't exist, returning them to whatever requested the model. The datastore would return a deferred object when requesting a model, in case it needs to fetch the model from the server first. This allows multiple collections to use the same model.

Before you add anything to a collection, you request the model from the datastore rather than creating a model instance manually and add that to the collection.

An alternative solution with the current setup would be to create a collection on the mediator and any sub-collections simply apply a filter. I'm not sure about the best way to approach this problem because I wasn't sure if the filter should be used this way.

Controller initialized twice

The dispatcher (application_controller) initialize controller twice.

  • l. 102 controller = new ControllerConstructor() > the constructor call initialize already
  • l. 106 controller.initialize params, currentControllerName

Remove compiled JS files

We don’t need the individual compiled JS files any longer in the repo since we can build Chaplin into one JS now.

This will break the tests but I think I’ll add the CoffeeScript compiler as a RequireJS plugin there so the source and the specs can be compiled on-the-fly.

non-model views

Should it be possible to make non-model views with Chaplin?

Tests don’t run in browsers without history.pushState

Because the history is started in the ApplicationSpec and Backbone immediately redirects from /test/ to /#/test. :(

We need to investigate. Probably setting {root: '/test/'} might help. But we need to change the Chaplin Router to pass this option through. Router#startHistory might just pass all @options through.

Optional controller

Controllers can be very tiny and repetitive (they are for me).

What would you think of making the controller file optional and generate it dynamically to instantiate the view if it is not present?

Model/Collection: Store jqXHRs and abort them on disposal

In production, we found it important to safe jQuery Ajax Deferreds and reject them once the model/collection is disposed. Otherwise some handlers will be fired on disposed objects, which may throw exceptions and which foils our whole event handler cleanup and memory management.

Chaplin doesn’t provide a solution for that yet. @Rendez is working on a solution for moviepilot.com which stores the Ajax Deferreds and rejects them on disposal.

[Edit, from other issue:]

Deferreds and SyncMachines might integrate better with fetch/save/sync
If you’re using SyncMachine, you have to call @beginSync() and @finishSync() manually. Same goes for @resolve() when using Deferreds. We need to investigate if it makes sense to do that automatically by providing a Model#sync which adds a success handler to the options. The handler would call the original handler and then @finishSync() or @resolve().

controller.historyURL is useless?

I'm not sure but it seems that it's useless.

For example:

# Routes
match 'feeds/favorite', 'feeds#show_favorite'
match 'feeds/popular', 'feeds#show_popular'

# Controller
class FeedsController
  historyURL: 'feeds'
  # ...

What's its purpose in this case? User will be redirected to feeds/ if he'll navigate to / etc.

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.