Files
website/src/client/site/base_controller.coffee
T

174 lines
4.7 KiB
CoffeeScript

#
# Crafting Guide - base_controller.coffee
#
# Copyright © 2014-2017 by Redwood Labs
# All rights reserved.
#
{Observable} = require("crafting-guide-common").util
templates = require './templates'
########################################################################################################################
module.exports = class BaseController extends Backbone.View
constructor: (options={})->
@_children = []
@_model = null
@_parent = options.parent
@_rendered = false
@router = options.router
@tryRefresh = _.debounce (=> @_tryRefresh()), 100
@_loadTemplate options.templateName
super options
# Public Methods ###############################################################################
addChild: (Controller, atSelector, options={})->
if not _.isFunction Controller then throw new Error "Controller must be a constructor"
options.el = @$(atSelector)[0]
options.parent = this
child = new Controller options
child.render options
@_children.push child
return child
hide: ($el)->
$el ?= @$el
$el.css 'display', 'none'
refresh: ->
logger.verbose => "#{this} refreshing"
remove: ->
@$el.remove()
@off()
routeLinkClick: (event)->
$link = $(event.target)
if not $link.attr('href')?
$link = $(event.currentTarget)
href = $link.attr 'href'
target = $link.attr 'target'
logger.info -> "Re-routing link to internal navigation: #{href}"
if href? and href.match /^http/
tracker.trackEvent c.tracking.category.navigate, 'external-link', href
.then -> window.location.href = href
return false
else if target?
tracker.trackEvent c.tracking.category.navigate, 'external-link', href
return true
else
tracker.trackEvent c.tracking.category.navigate, 'internal-link', href
@router.navigate href, trigger:true
return false
show: ($el)->
$el ?= @$el
$el.css 'display', ''
unrender: ->
@undelegateEvents()
@$el.empty()
@_rendered = false
# Event Methods ################################################################################
onDidModelChange: ->
@tryRefresh()
onWillRender: -> # do nothing
onDidRender: -> # do nothing
onWillShow: -> # do nothing
onDidShow: -> # do nothing
onWillChangeModel: (oldModel, newModel)->
if oldModel?.isObservable
oldModel.off target:this
if newModel?.isObservable
newModel.on Observable::ANY, this, "onDidModelChange"
return newModel
# Property Methods #############################################################################
Object.defineProperties @prototype,
model:
get: -> @_model
set: (newModel)->
return if @model is newModel
newModel = @onWillChangeModel @_model, newModel
@_model = newModel
@onDidModelChange()
rendered:
get: -> @_rendered
user:
get: -> @_user
set: (newUser)->
@_user = newUser
@tryRefresh()
# Backbone.View Overrides ######################################################################
events: ->
return {}
render: (options={})->
options.force ?= false
options.show ?= true
return this unless not @_rendered or options.force
if not @_template?
logger.error => "Default render called for #{@constructor.name} without a template"
return this
data = (@model?.toHash? and @model.toHash()) or @model or {}
logger.verbose => "#{this} rendering with data: #{data}"
$renderedEl = $($(@_template(data))[0])
@onWillRender()
@unrender()
@$el.append $renderedEl.children()
@$el.addClass $renderedEl.attr 'class'
@$el.data $renderedEl.data()
@delegateEvents()
@$el.controller = this
@_rendered = true
@onDidRender()
@refresh()
return this
# Object Overrides #############################################################################
toString: ->
return "#{@constructor.name}.#{@cid}"
# Private Methods ##############################################################################
_loadTemplate: (templateName)->
if templateName?
@_template = templates[templateName]
_tryRefresh: ->
return unless @_rendered
@refresh()