Permalink
Browse files

Update app structure to newest brunch with chaplin.

  • Loading branch information...
1 parent 5fe2b22 commit 6540a7be69a1b8ed37af3be576cca27ad9611861 @paulmillr paulmillr committed Aug 8, 2012
View
@@ -1,41 +1,64 @@
+Chaplin = require 'chaplin'
mediator = require 'mediator'
-Application = require 'chaplin/application'
+routes = require 'routes'
SessionController = require 'controllers/session_controller'
NavigationController = require 'controllers/navigation_controller'
SidebarController = require 'controllers/sidebar_controller'
-routes = require 'routes'
-support = require 'chaplin/lib/support'
+Layout = require 'views/layout'
-# The application bootstrapper.
-module.exports = class TwitterApplication extends Application
+# The application object
+module.exports = class Application extends Chaplin.Application
+ # Set your application name here so the document title is set to
+ # “Controller title – Site title” (see Layout#adjustTitle)
title: 'Tweet your brunch'
initialize: ->
- #console.debug 'ExampleApplication#initialize'
+ super
- super # This creates the AppController and AppView
+ # Initialize core components
+ @initDispatcher()
+ @initLayout()
+ @initMediator()
- # Instantiate common controllers
- # ------------------------------
+ # Application-specific scaffold
+ @initControllers()
- new SessionController()
- new NavigationController()
- new SidebarController()
-
- # Initialize the router
- # ---------------------
+ # Register all routes and start routing
+ @initRouter routes
+ # You might pass Router/History options as the second parameter.
+ # Chaplin enables pushState per default and Backbone uses / as
+ # the root per default. You might change that in the options
+ # if necessary:
+ # @initRouter routes, pushState: false, root: '/subdir/'
- # This creates the mediator.router property and
- # starts the Backbone history.
- @initRouter routes, pushState: no
+ # Freeze the application instance to prevent further changes
+ Object.freeze? this
- # Object sealing
- # --------------
+ # Override standard layout initializer
+ # ------------------------------------
+ initLayout: ->
+ # Use an application-specific Layout class. Currently this adds
+ # no features to the standard Chaplin Layout, it’s an empty placeholder.
+ @layout = new Layout {@title}
- # Seal the mediator object (prevent extensions and
- # make all properties non-configurable)
- if support.propertyDescriptors and Object.seal
- Object.seal mediator
+ # Instantiate common controllers
+ # ------------------------------
+ initControllers: ->
+ # These controllers are active during the whole application runtime.
+ # You don’t need to instantiate all controllers here, only special
+ # controllers which do not to respond to routes. They may govern models
+ # and views which are needed the whole time, for example header, footer
+ # or navigation views.
+ # e.g. new NavigationController()
+ new SessionController()
+ new NavigationController()
+ new SidebarController()
- # Freeze the application instance to prevent further changes
- Object.freeze? this
+ # Create additional mediator properties
+ # -------------------------------------
+ initMediator: ->
+ # Create a user property
+ Chaplin.mediator.user = null
+ # Add additional application-specific properties and methods
+ # Seal the mediator
+ Chaplin.mediator.seal()
@@ -0,0 +1,3 @@
+Chaplin = require 'chaplin'
+
+module.exports = class Controller extends Chaplin.Controller
@@ -1,3 +0,0 @@
-ChaplinController = require 'chaplin/controllers/controller'
-
-module.exports = class Controller extends ChaplinController
@@ -1,4 +1,4 @@
-Controller = require './controller'
+Controller = require 'controllers/base/controller'
mediator = require 'mediator'
Navigation = require 'models/navigation'
NavigationView = require 'views/navigation_view'
@@ -1,7 +1,7 @@
mediator = require 'mediator'
utils = require 'lib/utils'
User = require 'models/user'
-Controller = require './controller'
+Controller = require 'controllers/base/controller'
Twitter = require 'lib/services/twitter'
LoginView = require 'views/login_view'
@@ -1,4 +1,4 @@
-Controller = require './controller'
+Controller = require 'controllers/base/controller'
SidebarView = require 'views/sidebar_view'
StatusView = require 'views/status_view'
@@ -1,4 +1,4 @@
-Controller = require './controller'
+Controller = require 'controllers/base/controller'
Tweets = require 'models/tweets'
TweetsView = require 'views/tweets_view'
@@ -1,9 +1,9 @@
utils = require 'lib/utils'
-Subscriber = require 'chaplin/lib/subscriber'
+Chaplin = require 'chaplin'
module.exports = class ServiceProvider
# Mixin a Subscriber
- _(ServiceProvider.prototype).defaults Subscriber
+ _(ServiceProvider.prototype).defaults Chaplin.Subscriber
loading: false
@@ -44,7 +44,7 @@ module.exports = class Twitter extends ServiceProvider
@subscribe 'authComplete', (event, currentUser, accessToken) ->
callback {currentUser, accessToken}
@subscribe 'signOut', ->
- console.log 'SIGNOUT EVENT'
+ console.log 'Signout event'
callback()
# Publish session & userData events and
View
@@ -1,12 +1,13 @@
+Chaplin = require 'chaplin'
utils = require 'lib/utils'
-chaplinSupport = require 'chaplin/lib/support'
# Application-specific feature detection
# --------------------------------------
# Delegate to Chaplin’s support module
-module.exports = support = utils.beget chaplinSupport
+support = utils.beget Chaplin.support
# _(support).extend
-
# someMethod: ->
+
+module.exports = support
View
@@ -1,24 +1,161 @@
+Chaplin = require 'chaplin'
mediator = require 'mediator'
-chaplinUtils = require 'chaplin/lib/utils'
# Application-specific utilities
# ------------------------------
# Delegate to Chaplin’s utils module
-module.exports = utils = chaplinUtils.beget chaplinUtils
+utils = Chaplin.utils.beget Chaplin.utils
_(utils).extend
+ # We don’t use jQuery here because jQuery does not attach an error
+ # handler to the script. In jQuery, a proper error handler only works
+ # for same-origin scripts which can be loaded via XHR.
+ loadLib: (url, success, error, timeout = 7500) ->
+ head = document.head or document.getElementsByTagName('head')[0] or
+ document.documentElement
+ script = document.createElement 'script'
+ script.async = 'async'
+ script.src = url
+
+ onload = (_, aborted = false) ->
+ return unless (aborted or
+ not script.readyState or script.readyState is 'complete')
+
+ clearTimeout timeoutHandle
+
+ # Handle memory leak in IE
+ script.onload = script.onreadystatechange = script.onerror = null
+ # Remove the script elem and its reference
+ head.removeChild(script) if head and script.parentNode
+ script = undefined
+
+ success() if success and not aborted
+
+ script.onload = script.onreadystatechange = onload
+
+ # This is what jQuery is missing
+ script.onerror = ->
+ onload null, true
+ error() if error
+
+ timeoutHandle = setTimeout script.onerror, timeout
+ head.insertBefore script, head.firstChild
- # Facebook image helper
- # ---------------------
+ # Functional helpers for handling asynchronous dependancies and I/O
+ # -----------------------------------------------------------------
- facebookImageURL: (fbId, type = 'square') ->
- # Create query string
- params = type: type
+ ###
+ Wrap methods so they can be called before a deferred is resolved.
+ The actual methods are called once the deferred is resolved.
- # Add the Facebook access token if present
- if mediator.user
- accessToken = mediator.user.get('accessToken')
- params.access_token = accessToken if accessToken
+ Parameters:
- "https://graph.facebook.com/#{fbId}/picture?#{$.param(params)}"
+ Expects an options hash with the following properties:
+
+ deferred
+ The Deferred object to wait for.
+
+ methods
+ Either:
+ - A string with a method name e.g. 'method'
+ - An array of strings e.g. ['method1', 'method2']
+ - An object with methods e.g. {method: -> alert('resolved!')}
+
+ host (optional)
+ If you pass an array of strings in the `methods` parameter the methods
+ are fetched from this object. Defaults to `deferred`.
+
+ target (optional)
+ The target object the new wrapper methods are created at.
+ Defaults to host if host is given, otherwise it defaults to deferred.
+
+ onDeferral (optional)
+ An additional callback function which is invoked when the method is called
+ and the Deferred isn't resolved yet.
+ After the method is registered as a done handler on the Deferred,
+ this callback is invoked. This can be used to trigger the resolving
+ of the Deferred.
+
+ Examples:
+
+ deferMethods(deferred: def, methods: 'foo')
+ Wrap the method named foo of the given deferred def and
+ postpone all calls until the deferred is resolved.
+
+ deferMethods(deferred: def, methods: def.specialMethods)
+ Read all methods from the hash def.specialMethods and
+ create wrapped methods with the same names at def.
+
+ deferMethods(
+ deferred: def, methods: def.specialMethods, target: def.specialMethods
+ )
+ Read all methods from the object def.specialMethods and
+ create wrapped methods at def.specialMethods,
+ overwriting the existing ones.
+
+ deferMethods(deferred: def, host: obj, methods: ['foo', 'bar'])
+ Wrap the methods obj.foo and obj.bar so all calls to them are postponed
+ until def is resolved. obj.foo and obj.bar are overwritten
+ with their wrappers.
+
+ ###
+ deferMethods: (options) ->
+ # Process options
+ deferred = options.deferred
+ methods = options.methods
+ host = options.host or deferred
+ target = options.target or host
+ onDeferral = options.onDeferral
+
+ # Hash with named functions
+ methodsHash = {}
+
+ if typeof methods is 'string'
+ # Transform a single method string into an object
+ methodsHash[methods] = host[methods]
+
+ else if methods.length and methods[0]
+ # Transform a method list into an object
+ for name in methods
+ func = host[name]
+ unless typeof func is 'function'
+ throw new TypeError "utils.deferMethods: method #{name} not
+found on host #{host}"
+ methodsHash[name] = func
+
+ else
+ # Treat methods parameter as a hash, no transformation
+ methodsHash = methods
+
+ # Process the hash
+ for own name, func of methodsHash
+ # Ignore non-function properties
+ continue unless typeof func is 'function'
+ # Replace method with wrapper
+ target[name] = utils.createDeferredFunction(
+ deferred, func, target, onDeferral
+ )
+
+ # Creates a function which wraps `func` and defers calls to
+ # it until the given `deferred` is resolved. Pass an optional `context`
+ # to determine the this `this` binding of the original function.
+ # Defaults to `deferred`. The optional `onDeferral` function to after
+ # original function is registered as a done callback.
+ createDeferredFunction: (deferred, func, context = deferred, onDeferral) ->
+ # Return a wrapper function
+ ->
+ # Save the original arguments
+ args = arguments
+ if deferred.state() is 'resolved'
+ # Deferred already resolved, call func immediately
+ func.apply context, args
+ else
+ # Register a done handler
+ deferred.done ->
+ func.apply context, args
+ # Invoke the onDeferral callback
+ if typeof onDeferral is 'function'
+ onDeferral.apply context
+
+module.exports = utils
View
@@ -1,6 +1,43 @@
+mediator = require 'mediator'
+utils = require 'chaplin/lib/utils'
+
# Application-specific view helpers
# ---------------------------------
+# http://handlebarsjs.com/#helpers
+
+# Conditional evaluation
+# ----------------------
+
+# Choose block by user login status
+Handlebars.registerHelper 'if_logged_in', (options) ->
+ if mediator.user
+ options.fn(this)
+ else
+ options.inverse(this)
+
+# Map helpers
+# -----------
+
+# Make 'with' behave a little more mustachey
+Handlebars.registerHelper 'with', (context, options) ->
+ if not context or Handlebars.Utils.isEmpty context
+ options.inverse(this)
+ else
+ options.fn(context)
+
+# Inverse for 'with'
+Handlebars.registerHelper 'without', (context, options) ->
+ inverse = options.inverse
+ options.inverse = options.fn
+ options.fn = inverse
+ Handlebars.helpers.with.call(this, context, options)
+
+# Evaluate block with context being current user
+Handlebars.registerHelper 'with_user', (options) ->
+ context = mediator.user or {}
+ Handlebars.helpers.with.call(this, context, options)
+
Handlebars.registerHelper 'transform_if_retweeted', (options) ->
if this.retweeted_status
data = _.clone(this.retweeted_status)
Oops, something went wrong.

0 comments on commit 6540a7b

Please sign in to comment.