Restructure static files into a single directory
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
###
|
||||
Crafting Guide - base_controller.coffee
|
||||
|
||||
Copyright (c) 2014-2015 by Redwood Labs
|
||||
All rights reserved.
|
||||
###
|
||||
|
||||
views = require '../views'
|
||||
|
||||
########################################################################################################################
|
||||
|
||||
module.exports = class BaseController extends Backbone.View
|
||||
|
||||
constructor: (options={})->
|
||||
@tryRefresh = _.debounce @_tryRefresh, 100
|
||||
Object.defineProperty this, 'model', get:@getModel, set:@setModel
|
||||
|
||||
@_model = null
|
||||
@_rendered = false
|
||||
@_parent = options.parent
|
||||
@_children = []
|
||||
|
||||
Object.defineProperty this, 'rendered', get:-> return @_rendered
|
||||
@_loadTemplate options.templateName
|
||||
super options
|
||||
|
||||
# Public Methods ###############################################################################
|
||||
|
||||
addChild: (Controller, atSelector, options={})->
|
||||
options.el = @$(atSelector)[0]
|
||||
options.parent = this
|
||||
|
||||
child = new Controller options
|
||||
child.render()
|
||||
@_children.push child
|
||||
return child
|
||||
|
||||
refresh: ->
|
||||
logger.verbose => "#{this} refreshing"
|
||||
|
||||
routeLinkClick: (event)->
|
||||
href = $(event.currentTarget).attr 'href'
|
||||
router.navigate href, trigger:true
|
||||
return false
|
||||
|
||||
# Event Methods ################################################################################
|
||||
|
||||
onDidModelChange: ->
|
||||
@tryRefresh()
|
||||
|
||||
onDidModelSync: ->
|
||||
@tryRefresh()
|
||||
|
||||
onWillRender: -> # do nothing
|
||||
|
||||
onDidRender: ->
|
||||
@tryRefresh()
|
||||
|
||||
onWillShow: -> # do nothing
|
||||
|
||||
onDidShow: -> # do nothing
|
||||
|
||||
onWillChangeModel: (oldModel, newModel)->
|
||||
if oldModel?.on?
|
||||
@stopListening oldModel
|
||||
if newModel?.on?
|
||||
@listenTo newModel, 'sync', (e)=> @onDidModelSync e
|
||||
@listenTo newModel, 'change', (e)=> @onDidModelChange e
|
||||
return true
|
||||
|
||||
# Property Methods #############################################################################
|
||||
|
||||
getModel: ->
|
||||
return @_model
|
||||
|
||||
setModel: (newModel)->
|
||||
return if @model is newModel
|
||||
return unless @onWillChangeModel @_model, newModel
|
||||
|
||||
@_model = newModel
|
||||
@tryRefresh()
|
||||
|
||||
# Backbone.View Overrides ######################################################################
|
||||
|
||||
events: ->
|
||||
return {}
|
||||
|
||||
render: (options={})->
|
||||
return this unless not @_rendered or options.force
|
||||
|
||||
data = (@model?.toHash? and @model.toHash()) or @model or {}
|
||||
|
||||
if not @_template?
|
||||
logger.error => "Default render called for #{@constructor.name} without a template"
|
||||
return this
|
||||
|
||||
logger.verbose => "#{this} rendering with data: #{data}"
|
||||
@onWillRender()
|
||||
$oldEl = @$el
|
||||
$newEl = Backbone.$(@_template(data))
|
||||
if $oldEl
|
||||
$oldEl.replaceWith $newEl
|
||||
$newEl.addClass $oldEl.attr 'class'
|
||||
|
||||
@setElement $newEl
|
||||
@_rendered = true
|
||||
@onDidRender()
|
||||
|
||||
return this
|
||||
|
||||
# Object Overrides #############################################################################
|
||||
|
||||
toString: ->
|
||||
return "#{@constructor.name}.#{@cid}"
|
||||
|
||||
# Private Methods ##############################################################################
|
||||
|
||||
_loadTemplate: (templateName)->
|
||||
if templateName?
|
||||
@_template = views[templateName]
|
||||
|
||||
_tryRefresh: ->
|
||||
return unless @_rendered
|
||||
@refresh()
|
||||
@@ -0,0 +1,58 @@
|
||||
###
|
||||
Crafting Guide - browse_page_controller.coffee
|
||||
|
||||
Copyright (c) 2015 by Redwood Labs
|
||||
All rights reserved.
|
||||
###
|
||||
|
||||
PageController = require './page_controller'
|
||||
{Duration} = require '../constants'
|
||||
{Event} = require '../constants'
|
||||
ModController = require './mod_controller'
|
||||
|
||||
########################################################################################################################
|
||||
|
||||
module.exports = class BrowsePageController extends PageController
|
||||
|
||||
constructor: (options={})->
|
||||
if not options.modPack? then throw new Error 'options.modPack is required'
|
||||
options.templateName = 'browse_page'
|
||||
super options
|
||||
|
||||
@modPack = options.modPack
|
||||
@modPack.on Event.change, => @tryRefresh()
|
||||
|
||||
# PageController Overrides #####################################################################
|
||||
|
||||
getTitle: ->
|
||||
return 'Browse'
|
||||
|
||||
# BaseController Overrides #####################################################################
|
||||
|
||||
onDidRender: ->
|
||||
@$modContainer = @$('.mods')
|
||||
super
|
||||
|
||||
refresh: ->
|
||||
@_controllers ?= []
|
||||
controllerIndex = 0
|
||||
|
||||
@modPack.eachMod (mod)=>
|
||||
return unless mod.enabled
|
||||
|
||||
controller = @_controllers[controllerIndex]
|
||||
if not controller?
|
||||
controller = new ModController model:mod
|
||||
controller.render()
|
||||
@$modContainer.append controller.$el
|
||||
else
|
||||
controller.model = mod
|
||||
|
||||
controllerIndex += 1
|
||||
|
||||
while @_controllers.length > controllerIndex
|
||||
controller = @_controllers.pop()
|
||||
controller.$el.addClass 'removing'
|
||||
controller.$el.one Event.transitionEnd -> controller.$el.remove()
|
||||
|
||||
super
|
||||
@@ -0,0 +1,33 @@
|
||||
###
|
||||
Crafting Guide - configure_page_controller.coffee
|
||||
|
||||
Copyright (c) 2015 by Redwood Labs
|
||||
All rights reserved.
|
||||
###
|
||||
|
||||
PageController = require './page_controller'
|
||||
ModPackController = require './mod_pack_controller'
|
||||
|
||||
########################################################################################################################
|
||||
|
||||
module.exports = class ConfigurePageController extends PageController
|
||||
|
||||
constructor: (options={})->
|
||||
if not options.modPack? then throw new Error 'options.modPack is required'
|
||||
if not options.storage? then throw new Error 'options.storage is required'
|
||||
options.templateName = 'configure_page'
|
||||
super options
|
||||
|
||||
@modPack = options.modPack
|
||||
@storage = options.storage
|
||||
|
||||
# PageController Overrides #####################################################################
|
||||
|
||||
getTitle: ->
|
||||
return "Configure"
|
||||
|
||||
# BaseController Overrides #####################################################################
|
||||
|
||||
onDidRender: ->
|
||||
@modPackController = @addChild ModPackController, '.view__mod_pack', model:@modPack, storage:@storage
|
||||
super
|
||||
@@ -0,0 +1,113 @@
|
||||
###
|
||||
Crafting Guide - craft_page_controller.coffee
|
||||
|
||||
Copyright (c) 2014-2015 by Redwood Labs
|
||||
All rights reserved.
|
||||
###
|
||||
|
||||
CraftingTableController = require './crafting_table_controller'
|
||||
CraftPage = require '../models/craft_page'
|
||||
{Event} = require '../constants'
|
||||
ImageLoader = require './image_loader'
|
||||
InventoryController = require './inventory_controller'
|
||||
ModPackController = require './mod_pack_controller'
|
||||
NameFinder = require '../models/name_finder'
|
||||
PageController = require './page_controller'
|
||||
Storage = require '../models/storage'
|
||||
{Text} = require '../constants'
|
||||
{Url} = require '../constants'
|
||||
|
||||
########################################################################################################################
|
||||
|
||||
module.exports = class CraftPageController extends PageController
|
||||
|
||||
constructor: (options={})->
|
||||
if not options.imageLoader? then throw new Error 'options.imageLoader is required'
|
||||
if not options.modPack? then throw new Error 'options.modPack is required'
|
||||
|
||||
options.model ?= new CraftPage modPack:options.modPack
|
||||
options.storage ?= new Storage storage:window.localStorage
|
||||
options.templateName = 'craft_page'
|
||||
super options
|
||||
|
||||
@imageLoader = options.imageLoader
|
||||
@storage = options.storage
|
||||
|
||||
# Event Methods ################################################################################
|
||||
|
||||
onToolsBoxToggled: ->
|
||||
@model.plan.includingTools = @$('.includeTools:checked').length isnt 0
|
||||
|
||||
# PageController Overrides #####################################################################
|
||||
|
||||
getTitle: ->
|
||||
return 'Craft'
|
||||
|
||||
# BaseController Overrides #####################################################################
|
||||
|
||||
onWillRender: ->
|
||||
@storage.register 'crafting-plan', @model.plan, 'includingTools'
|
||||
@model.plan.have.clear()
|
||||
@model.plan.have.parse @storage.load('crafting-plan:have')
|
||||
super
|
||||
|
||||
onDidRender: ->
|
||||
@wantController = @addChild InventoryController, '.want',
|
||||
editable: true
|
||||
icon: '/images/fishing_rod.png'
|
||||
imageLoader: @imageLoader
|
||||
model: @model.plan.want
|
||||
modPack: @model.modPack
|
||||
onChange: => @_updateLocation()
|
||||
title: 'Items you want'
|
||||
|
||||
@haveController = @addChild InventoryController, '.have',
|
||||
editable: true,
|
||||
imageLoader: @imageLoader
|
||||
model: @model.plan.have
|
||||
modPack: @model.modPack
|
||||
onChange: => @_saveHaveInventory()
|
||||
nameFinder: new NameFinder @model.modPack, includeGatherable:true
|
||||
title: 'Items you have'
|
||||
|
||||
@needController = @addChild InventoryController, '.need',
|
||||
editable: false
|
||||
icon: '/images/boots.png'
|
||||
imageLoader: @imageLoader
|
||||
model: @model.plan.need
|
||||
modPack: @model.modPack
|
||||
title: "Items you'll need"
|
||||
|
||||
@craftingTableController = @addChild CraftingTableController, '.view__crafting_table',
|
||||
imageLoader: @imageLoader
|
||||
model: @model.table
|
||||
modPack: @model.modPack
|
||||
|
||||
@$('.want .toolbar').append '<label><input class="includeTools" type="checkbox"> include tools</label>'
|
||||
@$includeToolsBox = @$('.includeTools')
|
||||
|
||||
super
|
||||
|
||||
refresh: ->
|
||||
if @model.plan.includingTools
|
||||
@$includeToolsBox.attr 'checked', 'checked'
|
||||
else
|
||||
@$includeToolsBox.removeAttr 'checked'
|
||||
|
||||
super
|
||||
|
||||
# Backbone.View Overrides ######################################################################
|
||||
|
||||
events: ->
|
||||
return _.extend super,
|
||||
'change .includeTools': 'onToolsBoxToggled'
|
||||
|
||||
# Private Methods ##############################################################################
|
||||
|
||||
_saveHaveInventory: ->
|
||||
@storage.store 'crafting-plan:have', @model.plan.have.unparse()
|
||||
|
||||
_updateLocation: ->
|
||||
text = @model.plan.want.unparse()
|
||||
url = Url.crafting inventoryText:text
|
||||
router.navigate url
|
||||
@@ -0,0 +1,74 @@
|
||||
###
|
||||
Crafting Guide - crafting_grid_controller.coffee
|
||||
|
||||
Copyright (c) 2015 by Redwood Labs
|
||||
All rights reserved.
|
||||
###
|
||||
|
||||
BaseController = require './base_controller'
|
||||
{Duration} = require '../constants'
|
||||
{Event} = require '../constants'
|
||||
ImageLoader = require './image_loader'
|
||||
|
||||
########################################################################################################################
|
||||
|
||||
module.exports = class CraftingGridController extends BaseController
|
||||
|
||||
constructor: (options={})->
|
||||
if not options.imageLoader? then throw new Error 'options.imageLoader is required'
|
||||
if not options.modPack? then throw new Error 'options.modPack is required'
|
||||
options.templateName = 'crafting_grid'
|
||||
super options
|
||||
|
||||
@_imageLoader = options.imageLoader
|
||||
@_modPack = options.modPack
|
||||
@_slotCount = 9
|
||||
|
||||
@_modPack.on Event.change, => @tryRefresh()
|
||||
|
||||
# BaseController Methods #######################################################################
|
||||
|
||||
onDidRender: ->
|
||||
@slots = []
|
||||
for el in @$('td')
|
||||
$el = $(el)
|
||||
@slots.push a:$el.find('a'), img:$el.find('img')
|
||||
super
|
||||
|
||||
refresh: ->
|
||||
for index in [0...@slots.length]
|
||||
slot = @slots[index]
|
||||
|
||||
slot.a.addClass 'empty'
|
||||
slot.a.removeAttr 'href'
|
||||
slot.img.attr 'src', '/images/empty.png'
|
||||
slot.img.removeAttr 'alt'
|
||||
|
||||
display = @_getItemDisplayAt index
|
||||
if display?
|
||||
slot.a.removeClass 'empty'
|
||||
slot.a.attr 'href', display.itemUrl
|
||||
slot.a.attr 'title', display.itemName
|
||||
@_imageLoader.load display.iconUrl, slot.img
|
||||
slot.img.attr 'alt', display.itemName
|
||||
|
||||
@$el.tooltip show:{delay:Duration.snap, duration:Duration.fast}
|
||||
super
|
||||
|
||||
# Backbone.View Overrides ######################################################################
|
||||
|
||||
events: ->
|
||||
return _.extend super,
|
||||
'click td a': 'routeLinkClick'
|
||||
|
||||
# Private Methods ##############################################################################
|
||||
|
||||
_getItemDisplayAt: (slot)->
|
||||
if slot >= @_slotCount then throw new Error "slot (#{slot}) must be less than #{@_slotCount}"
|
||||
return null unless @model?
|
||||
|
||||
itemSlug = @model.getItemSlugAt slot
|
||||
return null unless itemSlug?
|
||||
|
||||
itemDisplay = @_modPack.findItemDisplay itemSlug
|
||||
return itemDisplay
|
||||
@@ -0,0 +1,94 @@
|
||||
###
|
||||
Crafting Guide - crafting_table_controller.coffee
|
||||
|
||||
Copyright (c) 2014-2015 by Redwood Labs
|
||||
All rights reserved.
|
||||
###
|
||||
|
||||
BaseController = require './base_controller'
|
||||
{Duration} = require '../constants'
|
||||
{Event} = require '../constants'
|
||||
ImageLoader = require './image_loader'
|
||||
MinimalRecipeController = require './minimal_recipe_controller'
|
||||
|
||||
########################################################################################################################
|
||||
|
||||
module.exports = class CraftingTableController extends BaseController
|
||||
|
||||
constructor: (options={})->
|
||||
if not options.imageLoader? then throw new Error 'options.imageLoader is required'
|
||||
if not options.model? then throw new Error 'options.model is required'
|
||||
if not options.modPack? then throw new Error 'options.modPack is required'
|
||||
options.templateName = 'crafting_table'
|
||||
super options
|
||||
|
||||
@imageLoader = options.imageLoader
|
||||
@modPack = options.modPack
|
||||
|
||||
# Event Methods ################################################################################
|
||||
|
||||
onNextClicked: ->
|
||||
@model.stepIndex += 1
|
||||
|
||||
onPrevClicked: ->
|
||||
@model.stepIndex -= 1
|
||||
|
||||
onReportProblem: ->
|
||||
itemList = @model.plan.want.unparse()
|
||||
toolsMessage = if @model.plan.includingTools then '(including tools)' else ''
|
||||
message = "When I was on step #{@model.stepIndex + 1} of making:
|
||||
\n\n#{itemList}#{toolsMessage}\n\nI noticed that...\n"
|
||||
global.feedbackController.enterFeedback message
|
||||
|
||||
# BaseController Overrides #####################################################################
|
||||
|
||||
onDidRender: ->
|
||||
@recipeController = @addChild MinimalRecipeController, '.view__minimal_recipe',
|
||||
imageLoader: @imageLoader
|
||||
modPack: @modPack
|
||||
|
||||
@$next = @$('.next')
|
||||
@$prev = @$('.prev')
|
||||
@$problemControl = @$('.problem')
|
||||
@$title = @$('h2 p')
|
||||
@$tool = @$('.tool p')
|
||||
|
||||
@$multiplier = $('<p class="multiplier"></p>')
|
||||
@$('.output').append @$multiplier
|
||||
|
||||
@defaultTitle = @$title.html()
|
||||
super
|
||||
|
||||
refresh: ->
|
||||
@$prev.removeClass 'enabled'
|
||||
@$next.removeClass 'enabled'
|
||||
|
||||
if @model.hasSteps
|
||||
if @model.hasPrevStep then @$prev.addClass 'enabled'
|
||||
if @model.hasNextStep then @$next.addClass 'enabled'
|
||||
@$title.html "Step #{@model.stepIndex + 1} of #{@model.stepCount}"
|
||||
else
|
||||
@$title.html @defaultTitle
|
||||
|
||||
currentStep = @model.currentStep
|
||||
@recipeController.model = currentStep?.recipe
|
||||
|
||||
if currentStep?.multiplier > 1
|
||||
@$multiplier.html "×#{currentStep.multiplier}"
|
||||
else
|
||||
@$multiplier.html ''
|
||||
|
||||
if not (@model.hasSteps and global.feedbackController?)
|
||||
@$problemControl.hide duration:Duration.snap
|
||||
else
|
||||
@$problemControl.show duration:Duration.snap
|
||||
|
||||
super
|
||||
|
||||
# Backbone.View Overrides ######################################################################
|
||||
|
||||
events: ->
|
||||
return _.extend super,
|
||||
'click .next': 'onNextClicked'
|
||||
'click .prev': 'onPrevClicked'
|
||||
'click .problem a': 'onReportProblem'
|
||||
@@ -0,0 +1,112 @@
|
||||
###
|
||||
Crafting Guide - feedback_controller.coffee
|
||||
|
||||
Copyright (c) 2015 by Redwood Labs
|
||||
All rights reserved.
|
||||
###
|
||||
|
||||
BaseController = require './base_controller'
|
||||
{Duration} = require '../constants'
|
||||
EmailClient = require '../models/email_client'
|
||||
{Key} = require '../constants'
|
||||
|
||||
########################################################################################################################
|
||||
|
||||
module.exports = class FeedbackController extends BaseController
|
||||
|
||||
constructor: (options={})->
|
||||
options.model ?= new EmailClient
|
||||
options.templateName = 'feedback'
|
||||
super options
|
||||
|
||||
Object.defineProperty this, 'isOpen', get:-> @$el.offset().left is 0
|
||||
|
||||
# Public Methods ###############################################################################
|
||||
|
||||
enterFeedback: (message)->
|
||||
promise = w(true)
|
||||
if not @isOpen then promise = @onToggle()
|
||||
promise.then => @$commentField.val message
|
||||
|
||||
# Event Methods ################################################################################
|
||||
|
||||
onSendClicked: ->
|
||||
return unless @$commentField.val().length > 0
|
||||
@$sendButton.attr 'disabled', 'disabled'
|
||||
|
||||
message =
|
||||
subject:'Crafting Guide Feedback'
|
||||
body:
|
||||
"""
|
||||
url: #{window.location.href}
|
||||
name: #{@$nameField.val()}
|
||||
email: #{@$emailField.val()}
|
||||
comment:
|
||||
|
||||
#{@$commentField.val()}
|
||||
"""
|
||||
|
||||
@model.send(message)
|
||||
.then =>
|
||||
@onToggle()
|
||||
@$error.slideUp duration:Duration.normal
|
||||
.catch (error)=>
|
||||
@$error.slideDown duration:Duration.normal
|
||||
.finally =>
|
||||
@$sendButton.removeAttr 'disabled'
|
||||
|
||||
onTextChanged: (event)->
|
||||
if @$commentField.val().length > 0
|
||||
@$sendButton.removeAttr 'disabled'
|
||||
else
|
||||
@$sendButton.attr 'disabled', 'disabled'
|
||||
|
||||
onToggle: ->
|
||||
w.promise (resolve)=>
|
||||
@$screen.off 'click'
|
||||
|
||||
if @isOpen
|
||||
@$screen.css display:'none'
|
||||
@$el.animate {left:-@$el.outerWidth()}, duration:Duration.fast, complete:=>
|
||||
@$commentField.val ''
|
||||
@$('input, textarea').blur()
|
||||
resolve()
|
||||
else
|
||||
@$screen.on 'click', => @onToggle()
|
||||
@$screen.css display:'block'
|
||||
|
||||
@$el.animate {left:0}, duration:Duration.fast, complete:=>
|
||||
if @$nameField.val().length is 0
|
||||
@$nameField.focus()
|
||||
else if @$emailField.val().length is 0
|
||||
@$emailField.focus()
|
||||
else
|
||||
@$commentField.focus()
|
||||
|
||||
resolve()
|
||||
|
||||
# BaseController Overrides #####################################################################
|
||||
|
||||
onDidRender: ->
|
||||
@$screen = $('.view__screen')
|
||||
|
||||
@$commentField = @$('textarea[name="comment"]')
|
||||
@$emailField = @$('input[name="email"]')
|
||||
@$error = @$('.error')
|
||||
@$nameField = @$('input[name="name"]')
|
||||
@$sendButton = @$('button[name="send"]')
|
||||
|
||||
windowHeight = window.innerHeight
|
||||
@$el.delay(Duration.slow).animate {left:-@$el.outerWidth()}, Duration.normal
|
||||
@onTextChanged()
|
||||
|
||||
super
|
||||
|
||||
# Backbone.View Methods ########################################################################
|
||||
|
||||
events: ->
|
||||
return _.extend super,
|
||||
'click .label': 'onToggle'
|
||||
'click button': 'onSendClicked'
|
||||
'input textarea': 'onTextChanged'
|
||||
'keyup textarea': 'onTextChanged'
|
||||
@@ -0,0 +1,95 @@
|
||||
###
|
||||
Crafting Guide - full_recipe_controller.coffee
|
||||
|
||||
Copyright (c) 2015 by Redwood Labs
|
||||
All rights reserved.
|
||||
###
|
||||
|
||||
BaseController = require './base_controller'
|
||||
CraftingGridController = require './crafting_grid_controller'
|
||||
{Duration} = require '../constants'
|
||||
ImageLoader = require './image_loader'
|
||||
Inventory = require '../models/inventory'
|
||||
InventoryTableController = require './inventory_table_controller'
|
||||
StringBuilder = require '../models/string_builder'
|
||||
|
||||
########################################################################################################################
|
||||
|
||||
module.exports = class FullRecipeController extends BaseController
|
||||
|
||||
constructor: (options={})->
|
||||
if not options.imageLoader? then throw new Error 'options.imageLoader is required'
|
||||
if not options.modPack? then throw new Error 'options.modPack is required'
|
||||
options.templateName = 'full_recipe'
|
||||
super options
|
||||
|
||||
@imageLoader = options.imageLoader
|
||||
@modPack = options.modPack
|
||||
|
||||
# BaseController Overrides #####################################################################
|
||||
|
||||
onDidRender: ->
|
||||
@gridController = @addChild CraftingGridController, '.view__crafting_grid',
|
||||
modPack: @modPack
|
||||
imageLoader: @imageLoader
|
||||
|
||||
@inputController = @addChild InventoryTableController, '.input .view__inventory_table',
|
||||
editable: false
|
||||
imageLoader: @imageLoader
|
||||
model: new Inventory
|
||||
modPack: @modPack
|
||||
|
||||
@outputController = @addChild InventoryTableController, '.output .view__inventory_table',
|
||||
editable: false
|
||||
imageLoader: @imageLoader
|
||||
model: new Inventory
|
||||
modPack: @modPack
|
||||
|
||||
@$toolContainer = @$('.tool')
|
||||
super
|
||||
|
||||
refresh: ->
|
||||
@gridController.model = @model
|
||||
|
||||
@$el.tooltip show:{delay:Duration.normal, duration:Duration.normal}
|
||||
|
||||
@_refreshInputs()
|
||||
@_refreshOutputs()
|
||||
@_refreshTools()
|
||||
|
||||
super
|
||||
|
||||
# Backbone.View Methods ########################################################################
|
||||
|
||||
events: ->
|
||||
return _.extend super,
|
||||
'click a': 'routeLinkClick'
|
||||
|
||||
# Private Methods ##############################################################################
|
||||
|
||||
_refreshInputs: ->
|
||||
inputs = @inputController.model
|
||||
inputs.clear()
|
||||
|
||||
if @model?
|
||||
for stack in @model.input
|
||||
inputs.add stack.itemSlug, stack.quantity
|
||||
|
||||
|
||||
_refreshOutputs: ->
|
||||
outputs = @outputController.model
|
||||
outputs.clear()
|
||||
|
||||
if @model?
|
||||
for stack in @model.output
|
||||
outputs.add stack.itemSlug, stack.quantity
|
||||
|
||||
_refreshTools: ->
|
||||
@$toolContainer.empty()
|
||||
return unless @model?
|
||||
|
||||
builder = new StringBuilder
|
||||
builder.loop @model.tools, delimiter:', ', onEach:(b, stack)=>
|
||||
display = @modPack.findItemDisplay stack.itemSlug
|
||||
b.push "<a href=\"#{display.itemUrl}\">#{display.itemName}</a>"
|
||||
@$toolContainer.html builder.toString()
|
||||
@@ -0,0 +1,60 @@
|
||||
###
|
||||
Crafting Guide - header_controller.coffee
|
||||
|
||||
Copyright (c) 2015 by Redwood Labs
|
||||
All rights reserved.
|
||||
###
|
||||
|
||||
BaseController = require './base_controller'
|
||||
|
||||
########################################################################################################################
|
||||
|
||||
module.exports = class HeaderController extends BaseController
|
||||
|
||||
constructor: (options={})->
|
||||
super options
|
||||
|
||||
# Event Methods ################################################################################
|
||||
|
||||
onLogoClicked: ->
|
||||
router.navigate '/', trigger:true
|
||||
return false
|
||||
|
||||
onNavItemClicked: (event)->
|
||||
return true unless $(event.currentTarget).attr('href')?
|
||||
|
||||
router.navigate $(event.currentTarget).attr('href'), trigger:true
|
||||
return false
|
||||
|
||||
# BaseController Overrides #####################################################################
|
||||
|
||||
render: ->
|
||||
# Overriding render because the header is already part of the stock page layout, and we
|
||||
# don't need to replace it here.
|
||||
@_rendered = true
|
||||
|
||||
@$navLinks = ($(el) for el in @$('.navBar a'))
|
||||
|
||||
zIndex = @$navLinks.length + 100
|
||||
for $navLink in @$navLinks
|
||||
$navLink.css 'z-index', zIndex--
|
||||
|
||||
refresh: ->
|
||||
for $navLink in @$navLinks
|
||||
linkPage = $navLink.data('page')
|
||||
if @model is linkPage
|
||||
$navLink.addClass 'selected'
|
||||
else
|
||||
$navLink.removeClass 'selected'
|
||||
|
||||
if @model.indexOf(linkPage) isnt -1
|
||||
$navLink.find('.dot').css 'opacity': 1;
|
||||
else
|
||||
$navLink.find('.dot').css 'opacity': 0;
|
||||
|
||||
# Backbone.View Overrides ######################################################################
|
||||
|
||||
events: ->
|
||||
return _.extend super,
|
||||
'click a.logo': 'onLogoClicked'
|
||||
'click .navBar a': 'onNavItemClicked'
|
||||
@@ -0,0 +1,22 @@
|
||||
###
|
||||
Crafting Guide - home_page_controller.coffee
|
||||
|
||||
Copyright (c) 2015 by Redwood Labs
|
||||
All rights reserved.
|
||||
###
|
||||
|
||||
PageController = require './page_controller'
|
||||
|
||||
########################################################################################################################
|
||||
|
||||
module.exports = class HomeController extends PageController
|
||||
|
||||
constructor: (options={})->
|
||||
options.templateName = 'home_page'
|
||||
super options
|
||||
|
||||
# Backbone.View Overrides ######################################################################
|
||||
|
||||
events: ->
|
||||
return _.extend super,
|
||||
'click a': 'routeLinkClick'
|
||||
@@ -0,0 +1,105 @@
|
||||
###
|
||||
Crafting Guide - image_loader.coffee
|
||||
|
||||
Copyright (c) 2014 by Redwood Labs
|
||||
All rights reserved.
|
||||
###
|
||||
|
||||
{Duration} = require '../constants'
|
||||
|
||||
########################################################################################################################
|
||||
|
||||
module.exports = class ImageLoader
|
||||
|
||||
constructor: (options={})->
|
||||
options.defaultUrl ?= null
|
||||
|
||||
if not options.defaultUrl?
|
||||
options.onLoading ?= -> @hide()
|
||||
options.onLoad ?= -> @show()
|
||||
|
||||
@defaultUrl = options.defaultUrl
|
||||
@onLoading = options.onLoading
|
||||
@onLoad = options.onLoad
|
||||
|
||||
@_images = {}
|
||||
|
||||
if @defaultUrl
|
||||
@_defaultImage = new Image
|
||||
@_defaultImage.src = @defaultUrl
|
||||
|
||||
# Class Methods ################################################################################
|
||||
|
||||
@load: (imageUrl, $el, options={}) ->
|
||||
loader = new ImageLoader options
|
||||
loader.load $el, options
|
||||
return loader
|
||||
|
||||
# Public Methods ###############################################################################
|
||||
|
||||
isLoaded: (imageUrl)->
|
||||
data = @_images[imageUrl]
|
||||
return false unless data?
|
||||
return data.isLoaded
|
||||
|
||||
load: (imageUrl, $el)->
|
||||
return if not $el
|
||||
|
||||
data = @preload imageUrl
|
||||
if $el.attr('src')?
|
||||
return if $el.attr('src').indexOf(imageUrl) isnt -1
|
||||
|
||||
if @onLoading? then @onLoading.call $el
|
||||
$el.data 'isLoading', true
|
||||
$el.data 'isLoaded', false
|
||||
|
||||
if data.isLoaded
|
||||
@_loadImageIntoElement data.imageUrl, $el
|
||||
else
|
||||
if @defaultUrl?
|
||||
$el.attr 'src', @defaultUrl
|
||||
else
|
||||
$el.removeAttr 'src'
|
||||
|
||||
if data.elements.indexOf($el) is -1 then data.elements.push $el
|
||||
|
||||
return this
|
||||
|
||||
preload: (imageUrl)->
|
||||
data = @_images[imageUrl]
|
||||
if not data?
|
||||
data = imageUrl:imageUrl, elements:[], image:new Image, isLoaded:false
|
||||
@_images[imageUrl] = data
|
||||
|
||||
data.image = new Image
|
||||
data.image.onload = => @_onImageLoaded data
|
||||
data.image.onerror = => @_onImageError data
|
||||
data.image.src = imageUrl
|
||||
|
||||
return data
|
||||
|
||||
# Private Methods ##############################################################################
|
||||
|
||||
_onImageLoaded: (data)->
|
||||
for $el in data.elements
|
||||
@_loadImageIntoElement data.imageUrl, $el
|
||||
|
||||
data.elements = []
|
||||
data.isLoaded = true
|
||||
|
||||
_onImageError: (data)->
|
||||
if @defaultUrl?
|
||||
data.imageUrl = @defaultUrl
|
||||
|
||||
for $el in data.elements
|
||||
@_loadImageIntoElement @defaultUrl, $el
|
||||
|
||||
data.elements = []
|
||||
data.isLoaded = true
|
||||
|
||||
_loadImageIntoElement: (imageUrl, $el)->
|
||||
$el.data 'isLoading', false
|
||||
$el.data 'isLoaded', true
|
||||
$el.attr 'src', imageUrl
|
||||
|
||||
if @onLoad? then @onLoad.call $el
|
||||
@@ -0,0 +1,181 @@
|
||||
###
|
||||
Crafting Guide - inventory_controller.coffee
|
||||
|
||||
Copyright (c) 2014-2015 by Redwood Labs
|
||||
All rights reserved.
|
||||
###
|
||||
|
||||
BaseController = require './base_controller'
|
||||
{Duration} = require '../constants'
|
||||
{Event} = require '../constants'
|
||||
{Key} = require '../constants'
|
||||
ImageLoader = require './image_loader'
|
||||
NameFinder = require '../models/name_finder'
|
||||
StackController = require './stack_controller'
|
||||
|
||||
########################################################################################################################
|
||||
|
||||
module.exports = class InventoryController extends BaseController
|
||||
|
||||
@MAX_QUANTITY = 9999
|
||||
|
||||
@ONLY_DIGITS = /^[0-9]*$/
|
||||
|
||||
constructor: (options={})->
|
||||
if not options.imageLoader? then throw new Error 'options.imageLoader is required'
|
||||
if not options.model? then throw new Error 'options.model is required'
|
||||
if not options.modPack? then throw new Error 'options.modPack is required'
|
||||
|
||||
@editable = options.editable ?= true
|
||||
@icon = options.icon ?= '/images/chest_front.png'
|
||||
@imageLoader = options.imageLoader
|
||||
@modPack = options.modPack
|
||||
@nameFinder = options.nameFinder ?= new NameFinder options.modPack
|
||||
@onChange = options.onChange ?= -> # do nothing
|
||||
@title = options.title ?= 'Inventory'
|
||||
|
||||
options.templateName = 'inventory'
|
||||
super options
|
||||
|
||||
@_stackControllers = []
|
||||
|
||||
@listenTo @modPack, Event.change, => @refresh()
|
||||
|
||||
# Event Methods ################################################################################
|
||||
|
||||
onAddButtonClicked: ->
|
||||
if @$nameField.val().trim().length is 0
|
||||
@$nameField.focus()
|
||||
return
|
||||
|
||||
item = @modPack.findItemByName @$nameField.val()
|
||||
return unless item?
|
||||
|
||||
@model.add item.slug, 1
|
||||
@$nameField.val ''
|
||||
|
||||
@$scrollbox.scrollTop @$scrollbox.prop 'scrollHeight'
|
||||
@$nameField.autocomplete 'close'
|
||||
|
||||
@onChange()
|
||||
|
||||
onClearButtonClicked: ->
|
||||
@model.clear()
|
||||
@onChange()
|
||||
|
||||
onItemSelected: ->
|
||||
func = =>
|
||||
@onNameFieldChanged()
|
||||
@onAddButtonClicked()
|
||||
@$nameField.blur()
|
||||
|
||||
setTimeout func, 10 # needed to allow the autocomplete to finish
|
||||
return true
|
||||
|
||||
onNameFieldBlur: ->
|
||||
item = @modPack.findItemByName @$nameField.val()
|
||||
@$nameField.val if item? then item.name else ''
|
||||
@onNameFieldChanged()
|
||||
|
||||
onNameFieldChanged: ->
|
||||
@_refreshButtonState()
|
||||
|
||||
onNameFieldFocused: ->
|
||||
@$nameField.val ''
|
||||
@$nameField.autocomplete 'search'
|
||||
|
||||
onNameFieldKeyUp: (event)->
|
||||
if event.which is Key.Return
|
||||
@onAddButtonClicked()
|
||||
|
||||
# BaseController Overrides #####################################################################
|
||||
|
||||
onDidRender: ->
|
||||
@$addButton = @$('button[name="add"]')
|
||||
@$clearButton = @$('button[name="clear"]')
|
||||
@$icon = @$('.icon')
|
||||
@$editPanel = @$('.edit')
|
||||
@$nameField = @$('input[name="name"]')
|
||||
@$scrollbox = @$('.scrollbox')
|
||||
@$table = @$('table')
|
||||
@$toolbar = @$('.toolbar')
|
||||
@$title = @$('h2 p')
|
||||
super
|
||||
|
||||
refresh: ->
|
||||
@$editPanel.css display:(if @editable then 'table-row' else 'none')
|
||||
@$toolbar.css display:(if @editable then 'block' else 'none')
|
||||
@$scrollbox.css bottom:(if @editable then @$toolbar.height() else '0')
|
||||
|
||||
@$icon.attr 'src', @icon
|
||||
@$title.html @title
|
||||
|
||||
@_refreshStacks()
|
||||
@_refreshNameAutocomplete()
|
||||
@_refreshButtonState()
|
||||
|
||||
super
|
||||
|
||||
# Backbone.View Overrides ######################################################################
|
||||
|
||||
events: ->
|
||||
return _.extend super,
|
||||
'blur input[name="name"]': 'onNameFieldBlur'
|
||||
'click button[name="add"]': 'onAddButtonClicked'
|
||||
'click button[name="clear"]': 'onClearButtonClicked'
|
||||
'focus input[name="name"]': 'onNameFieldFocused'
|
||||
'input input[name="name"]': 'onNameFieldChanged'
|
||||
'keyup input[name="name"]': 'onNameFieldKeyUp'
|
||||
|
||||
# Private Methods ##############################################################################
|
||||
|
||||
_refreshButtonState: ->
|
||||
if @model.isEmpty then @$clearButton.attr('disabled', 'disabled') else @$clearButton.removeAttr('disabled')
|
||||
|
||||
noText = @$nameField.val().trim().length is 0
|
||||
itemValid = @modPack.findItemByName(@$nameField.val())?
|
||||
disable = not (itemValid or noText)
|
||||
if disable then @$addButton.attr('disabled', 'disabled') else @$addButton.removeAttr('disabled')
|
||||
|
||||
_refreshNameAutocomplete: ->
|
||||
onChanged = => @onNameFieldChanged()
|
||||
onSelected = => @onItemSelected()
|
||||
|
||||
@$nameField.autocomplete
|
||||
source: (request, callback)=> callback @nameFinder.search request.term
|
||||
delay: 0
|
||||
minLength: 0
|
||||
change: onChanged
|
||||
close: onChanged
|
||||
select: onSelected
|
||||
|
||||
_refreshStacks: ->
|
||||
@_stackControllers ?= []
|
||||
index = 0
|
||||
|
||||
$lastRow = @$table.find 'tr:last-child'
|
||||
@model.each (stack)=>
|
||||
controller = @_stackControllers[index]
|
||||
if not controller?
|
||||
controller = new StackController
|
||||
editable: @editable
|
||||
imageLoader: @imageLoader
|
||||
model: stack
|
||||
modPack: @modPack
|
||||
onChange: @onChange
|
||||
onRemove: if not @editable then null else (stack)=> @_removeStack(stack)
|
||||
controller.render()
|
||||
controller.$el.hide()
|
||||
controller.$el.insertBefore $lastRow
|
||||
controller.$el.slideDown duration:Duration.fast
|
||||
@_stackControllers.push controller
|
||||
else
|
||||
controller.model = stack
|
||||
index += 1
|
||||
|
||||
while @_stackControllers.length > index
|
||||
controller = @_stackControllers.pop()
|
||||
controller.$el.fadeOut duration:Duration.fast, complete:-> @remove()
|
||||
|
||||
_removeStack: (stack)->
|
||||
@model.remove stack.itemSlug, stack.quantity
|
||||
@@ -0,0 +1,184 @@
|
||||
###
|
||||
Crafting Guide - inventory_table_controller.coffee
|
||||
|
||||
Copyright (c) 2014-2015 by Redwood Labs
|
||||
All rights reserved.
|
||||
###
|
||||
|
||||
BaseController = require './base_controller'
|
||||
{Duration} = require '../constants'
|
||||
ImageLoader = require './image_loader'
|
||||
ItemSlug = require '../models/item_slug'
|
||||
{Key} = require '../constants'
|
||||
NameFinder = require '../models/name_finder'
|
||||
StackController = require './stack_controller'
|
||||
|
||||
########################################################################################################################
|
||||
|
||||
module.exports = class InventoryTableController extends BaseController
|
||||
|
||||
@ONLY_DIGITS = /^[0-9]*$/
|
||||
|
||||
constructor: (options={})->
|
||||
if not options.imageLoader? then throw new Error 'options.imageLoader is required'
|
||||
if not options.model? then throw new Error 'options.model is required'
|
||||
if not options.modPack? then throw new Error 'options.modPack is required'
|
||||
|
||||
@editable = options.editable ?= true
|
||||
@imageLoader = options.imageLoader
|
||||
@modPack = options.modPack
|
||||
@nameFinder = options.nameFinder ?= new NameFinder options.modPack
|
||||
@onChange = options.onChange ?= -> # do nothing
|
||||
|
||||
options.templateName = 'inventory_table'
|
||||
super options
|
||||
|
||||
@_stackControllers = []
|
||||
|
||||
@listenTo @modPack, 'change', => @refresh()
|
||||
|
||||
# Event Methods ################################################################################
|
||||
|
||||
onAddButtonClicked: ->
|
||||
name = @modpack.findItemByName @$nameField.val()
|
||||
return unless item?
|
||||
|
||||
@model.add item.slug, parseInt(@$quantityField.val())
|
||||
@$nameField.val ''
|
||||
@$quantityField.val '1'
|
||||
|
||||
@$scrollbox.scrollTop @$scrollbox.prop 'scrollHeight'
|
||||
@$nameField.autocomplete 'close'
|
||||
|
||||
@onChange()
|
||||
|
||||
onClearButtonClicked: ->
|
||||
@model.clear()
|
||||
@onChange()
|
||||
|
||||
onItemSelected: ->
|
||||
func = =>
|
||||
@onNameFieldChanged()
|
||||
@onAddButtonClicked()
|
||||
@$nameField.blur()
|
||||
|
||||
setTimeout func, 10 # needed to allow the autocomplete to finish
|
||||
return true
|
||||
|
||||
onNameFieldBlur: ->
|
||||
item = @modPack.findItemByName @$nameField.val()
|
||||
@$nameField.val if item? then item.name else ''
|
||||
@onNameFieldChanged()
|
||||
|
||||
onNameFieldChanged: ->
|
||||
item = @modPack.findItemByName @$nameField.val()
|
||||
@_updateButtonState()
|
||||
|
||||
onNameFieldFocused: ->
|
||||
@$nameField.val ''
|
||||
@$nameField.autocomplete('search')
|
||||
|
||||
onNameFieldKeyUp: (event)->
|
||||
if event.which is Key.Return
|
||||
@onAddButtonClicked()
|
||||
|
||||
onQuantityFieldBlur: ->
|
||||
value = @$quantityField.val().replace /[^0-9]/g, ''
|
||||
if value.length is 0 then value = '1'
|
||||
value = Math.min value, 64
|
||||
@$quantityField.val value
|
||||
@onQuantityFieldChanged()
|
||||
|
||||
onQuantityFieldChanged: ->
|
||||
if not @$quantityField.val().match /^[0-9]*$/
|
||||
@$quantityField.addClass 'error', 0
|
||||
@$quantityField.addClass 'error-new', 0
|
||||
@$quantityField.removeClass 'error-new', Duration.slow
|
||||
@$quantityField.focus()
|
||||
return
|
||||
|
||||
@$quantityField.removeClass 'error', Duration.normal
|
||||
@$quantityField.removeClass 'error-new', Duration.normal
|
||||
@_updateButtonState()
|
||||
|
||||
onQuantityFieldFocused: ->
|
||||
@$quantityField.val ''
|
||||
|
||||
# BaseController Overrides #####################################################################
|
||||
|
||||
onDidRender: ->
|
||||
@$addButton = @$('button[name="add"]')
|
||||
@$clearButton = @$('button[name="clear"]')
|
||||
@$editPanel = @$('.edit')
|
||||
@$nameField = @$('input[name="name"]')
|
||||
@$quantityField = @$('input[name="quantity"]')
|
||||
@$scrollbox = @$('.scrollbox')
|
||||
@$table = @$('table')
|
||||
@$toolbar = @$('.toolbar')
|
||||
super
|
||||
|
||||
refresh: ->
|
||||
@$editPanel.css display:(if @editable then 'table-row' else 'none')
|
||||
@$toolbar.css display:(if @editable then 'block' else 'none')
|
||||
@$scrollbox.css bottom:(if @editable then @$toolbar.height() else '0')
|
||||
|
||||
if _.isEmpty(@$quantityField.val()) then @$quantityField.val '1'
|
||||
|
||||
@$table.find('tr:not(:last-child)').remove()
|
||||
$lastRow = @$table.find 'tr:last-child'
|
||||
@_stackControllers = []
|
||||
@model.each (stack)=>
|
||||
controller = new StackController
|
||||
editable: @editable
|
||||
imageLoader: @imageLoader
|
||||
model: stack
|
||||
modPack: @modPack
|
||||
onRemove: if not @editable then null else (stack)=> @_removeStack(stack)
|
||||
|
||||
controller.render()
|
||||
controller.$el.insertBefore $lastRow
|
||||
@_stackControllers.push controller
|
||||
|
||||
@_updateNameAutocomplete()
|
||||
@_updateButtonState()
|
||||
|
||||
super
|
||||
|
||||
# Backbone.View Overrides ######################################################################
|
||||
|
||||
events: ->
|
||||
return _.extend super,
|
||||
'blur input[name="name"]': 'onNameFieldBlur'
|
||||
'blur input[name="quantity"]': 'onQuantityFieldBlur'
|
||||
'click button[name="add"]': 'onAddButtonClicked'
|
||||
'click button[name="clear"]': 'onClearButtonClicked'
|
||||
'focus input[name="name"]': 'onNameFieldFocused'
|
||||
'focus input[name="quantity"]': 'onQuantityFieldFocused'
|
||||
'input input[name="name"]': 'onNameFieldChanged'
|
||||
'input input[name="quantity"]': 'onQuantityFieldChanged'
|
||||
'keyup input[name="name"]': 'onNameFieldKeyUp'
|
||||
|
||||
# Private Methods ##############################################################################
|
||||
|
||||
_removeStack: (stack)->
|
||||
@model.remove stack.itemSlug, stack.quantity
|
||||
|
||||
_updateNameAutocomplete: ->
|
||||
onChanged = => @onNameFieldChanged()
|
||||
onSelected = => @onItemSelected()
|
||||
|
||||
@$nameField.autocomplete
|
||||
source: (request, callback)=> callback @nameFinder.search request.term
|
||||
delay: 0
|
||||
minLength: 0
|
||||
change: onChanged
|
||||
close: onChanged
|
||||
select: onSelected
|
||||
|
||||
_updateButtonState: ->
|
||||
if @model.isEmpty then @$clearButton.attr('disabled', 'disabled') else @$clearButton.removeAttr('disabled')
|
||||
|
||||
itemValid = @modPack.findItemByName(@$nameField.val())?
|
||||
quantityValid = @$quantityField.val().match(InventoryTableController.ONLY_DIGITS)
|
||||
disable = not (itemValid and quantityValid)
|
||||
if disable then @$addButton.attr('disabled', 'disabled') else @$addButton.removeAttr('disabled')
|
||||
@@ -0,0 +1,43 @@
|
||||
###
|
||||
Crafting Guide - item_controller.coffee
|
||||
|
||||
Copyright (c) 2015 by Redwood Labs
|
||||
All rights reserved.
|
||||
###
|
||||
|
||||
BaseController = require './base_controller'
|
||||
|
||||
########################################################################################################################
|
||||
|
||||
module.exports = class ItemController extends BaseController
|
||||
|
||||
constructor: (options={})->
|
||||
if not options.imageLoader? then throw new Error 'options.imageLoader is required'
|
||||
if not options.model? then throw new Error 'options.model is required'
|
||||
if not options.modPack? then throw new Error 'options.modPack is required'
|
||||
options.templateName = 'item'
|
||||
super options
|
||||
|
||||
@_imageLoader = options.imageLoader
|
||||
@_modPack = options.modPack
|
||||
|
||||
# BaseController Overrides #####################################################################
|
||||
|
||||
onDidRender: ->
|
||||
@$icon = @$('img')
|
||||
@$name = @$('.itemName')
|
||||
@$nameLink = @$('a')
|
||||
super
|
||||
|
||||
refresh: ->
|
||||
display = @_modPack.findItemDisplay @model.slug
|
||||
|
||||
@_imageLoader.load display.iconUrl, @$icon
|
||||
@$name.html display.itemName
|
||||
@$nameLink.attr 'href', display.itemUrl
|
||||
|
||||
# Backbone.View Overrides ######################################################################
|
||||
|
||||
events: ->
|
||||
return _.extend super,
|
||||
'click a': 'routeLinkClick'
|
||||
@@ -0,0 +1,84 @@
|
||||
###
|
||||
Crafting Guide - item_group_controller.coffee
|
||||
|
||||
Copyright (c) 2015 by Redwood Labs
|
||||
All rights reserved.
|
||||
###
|
||||
|
||||
BaseController = require './base_controller'
|
||||
{Duration} = require '../constants'
|
||||
{Event} = require '../constants'
|
||||
Item = require '../models/item'
|
||||
ItemController = require './item_controller'
|
||||
|
||||
########################################################################################################################
|
||||
|
||||
module.exports = class ItemGroupController extends BaseController
|
||||
|
||||
constructor: (options={})->
|
||||
if not options.imageLoader? then throw new Error 'options.imageLoader is required'
|
||||
if not options.modPack? then throw new Error 'options.modPack is required'
|
||||
options.title ?= ''
|
||||
options.templateName = 'item_group'
|
||||
super options
|
||||
|
||||
@_delayStep = 20
|
||||
@_imageLoader = options.imageLoader
|
||||
@_itemControllers = []
|
||||
@_modPack = options.modPack
|
||||
@_title = options.title
|
||||
|
||||
Object.defineProperties this,
|
||||
title: {get:@getTitle, set:@setTitle}
|
||||
|
||||
# Property Methods #############################################################################
|
||||
|
||||
getTitle: ->
|
||||
return @_title
|
||||
|
||||
setTitle: (title)->
|
||||
@_title = title
|
||||
@tryRefresh()
|
||||
|
||||
# BaseController Overrides #####################################################################
|
||||
|
||||
onDidRender: ->
|
||||
@$title = @$('h2')
|
||||
@$items = @$('.panel')
|
||||
super
|
||||
|
||||
refresh: ->
|
||||
@$title.html @_title
|
||||
@_refreshItems()
|
||||
super
|
||||
|
||||
# Private Methods ##############################################################################
|
||||
|
||||
_createItemController: (item, delay)->
|
||||
controller = new ItemController imageLoader:@_imageLoader, model:item, modPack:@_modPack
|
||||
@_itemControllers.push controller
|
||||
|
||||
attachController = =>
|
||||
controller.render()
|
||||
@$items.append controller.$el
|
||||
|
||||
_.delay attachController, delay
|
||||
|
||||
_refreshItems: ->
|
||||
controllerIndex = 0
|
||||
delay = 0
|
||||
|
||||
if @model?
|
||||
for item in @model
|
||||
controller = @_itemControllers[controllerIndex]
|
||||
if not controller?
|
||||
@_createItemController item, delay
|
||||
delay += @_delayStep
|
||||
else
|
||||
controller.model = item
|
||||
controller.refresh()
|
||||
controllerIndex += 1
|
||||
|
||||
while @_itemControllers.length > controllerIndex
|
||||
controller = @_itemControllers.pop()
|
||||
controller.$el.slideUp duration:Duration.normal, complete:-> @remove()
|
||||
@@ -0,0 +1,174 @@
|
||||
###
|
||||
Crafting Guide - item_page_controller.coffee
|
||||
|
||||
Copyright (c) 2015 by Redwood Labs
|
||||
All rights reserved.
|
||||
###
|
||||
|
||||
{Duration} = require '../constants'
|
||||
{Event} = require '../constants'
|
||||
FullRecipeController = require './full_recipe_controller'
|
||||
ImageLoader = require './image_loader'
|
||||
Item = require '../models/item'
|
||||
ItemGroupController = require './item_group_controller'
|
||||
ItemPage = require '../models/item_page'
|
||||
ItemSlug = require '../models/item_slug'
|
||||
PageController = require './page_controller'
|
||||
{Text} = require '../constants'
|
||||
{Url} = require '../constants'
|
||||
|
||||
########################################################################################################################
|
||||
|
||||
module.exports = class ItemPageController extends PageController
|
||||
|
||||
constructor: (options={})->
|
||||
if not options.itemSlug? then throw new Error 'options.itemSlug is required'
|
||||
if not options.imageLoader? then throw new Error 'options.imageLoader is required'
|
||||
if not options.modPack? then throw new Error 'options.modPack is required'
|
||||
|
||||
options.model ?= new ItemPage modPack:options.modPack
|
||||
options.templateName ?= 'item_page'
|
||||
|
||||
super options
|
||||
|
||||
@imageLoader = options.imageLoader
|
||||
@modPack = options.modPack
|
||||
@_itemSlug = options.itemSlug
|
||||
|
||||
@modPack.on Event.change, => @tryRefresh()
|
||||
|
||||
# PageController Overrides #####################################################################
|
||||
|
||||
getTitle: ->
|
||||
return @model.item?.name
|
||||
|
||||
# BaseController Overrides #####################################################################
|
||||
|
||||
onDidRender: ->
|
||||
@_usedAsToolToMakeController = @addChild ItemGroupController, '.usedAsToolToMake .view__item_group',
|
||||
imageLoader: @imageLoader
|
||||
modPack: @modPack
|
||||
|
||||
@_similarItemsController = @addChild ItemGroupController, '.similar .view__item_group',
|
||||
imageLoader: @imageLoader
|
||||
modPack: @modPack
|
||||
|
||||
@_usedToMakeController = @addChild ItemGroupController, '.usedToMake .view__item_group',
|
||||
imageLoader: @imageLoader
|
||||
modPack: @modPack
|
||||
|
||||
@$usedAsToolToMakeSection = @$('.usedAsToolToMake')
|
||||
@$byline = @$('.byline')
|
||||
@$bylineLink = @$('.byline a')
|
||||
@$craftingPlanLink = @$('a.craftingPlan')
|
||||
@$name = @$('h1.name')
|
||||
@$recipeContainer = @$('.recipes .panel')
|
||||
@$recipesSection = @$('.recipes')
|
||||
@$similarSection = @$('.similar')
|
||||
@$titleImage = @$('.titleImage img')
|
||||
@$usedToMakeSection = @$('.usedToMake')
|
||||
super
|
||||
|
||||
refresh: ->
|
||||
@_resolveItemSlug()
|
||||
|
||||
if @model.item?
|
||||
display = @modPack.findItemDisplay @model.item.slug
|
||||
@$craftingPlanLink.attr href:display.craftingUrl
|
||||
@$craftingPlanLink.fadeIn duration:Duration.fast
|
||||
@imageLoader.load display.iconUrl, @$titleImage
|
||||
@$name.html display.itemName
|
||||
|
||||
@$el.slideDown duration:Duration.normal
|
||||
else
|
||||
@$el.slideUp duration:Duration.normal
|
||||
|
||||
@_refreshByline()
|
||||
@_refreshRecipes()
|
||||
@_refreshSimilarItems()
|
||||
@_refreshUsedAsToolToMake()
|
||||
@_refreshUsedToMake()
|
||||
|
||||
super
|
||||
|
||||
# Backbone.View Overrides ######################################################################
|
||||
|
||||
events: ->
|
||||
return _.extend super,
|
||||
'click a.craftingPlan': 'routeLinkClick'
|
||||
'click .byline a': 'routeLinkClick'
|
||||
|
||||
# Private Methods ##############################################################################
|
||||
|
||||
_refreshUsedAsToolToMake: ->
|
||||
@_usedAsToolToMakeController.title = 'Used as Tool to Make'
|
||||
|
||||
@_usedAsToolToMakeController.model = @model.findToolForRecipes()
|
||||
if @_usedAsToolToMakeController.model?
|
||||
@$usedAsToolToMakeSection.slideDown duration:Duration.normal
|
||||
else
|
||||
@$usedAsToolToMakeSection.slideUp duration:Duration.normal
|
||||
|
||||
_refreshByline: ->
|
||||
mod = @model.item?.modVersion?.mod
|
||||
if mod?.name?.length > 0
|
||||
@$bylineLink.attr 'href', Url.mod modSlug:mod.slug
|
||||
@$bylineLink.html mod.name
|
||||
@$byline.fadeIn duration:Duration.fast
|
||||
else
|
||||
@$byline.fadeOut duration:Duration.fast
|
||||
|
||||
_refreshUsedToMake: ->
|
||||
@_usedToMakeController.title = 'Used to Make'
|
||||
|
||||
@_usedToMakeController.model = @model.findComponentInItems()
|
||||
if @_usedToMakeController.model?
|
||||
@$usedToMakeSection.slideDown duration:Duration.normal
|
||||
else
|
||||
@$usedToMakeSection.slideUp duration:Duration.normal
|
||||
|
||||
_refreshRecipes: ->
|
||||
@_recipeControllers ?= []
|
||||
index = 0
|
||||
|
||||
recipes = @model.findRecipes()
|
||||
if recipes?
|
||||
@$recipesSection.slideDown duration:Duration.normal
|
||||
|
||||
for recipe in @model.findRecipes()
|
||||
controller = @_recipeControllers[index]
|
||||
if not controller?
|
||||
controller = new FullRecipeController imageLoader:@imageLoader, modPack:@modPack, model:recipe
|
||||
@_recipeControllers.push controller
|
||||
controller.render()
|
||||
@$recipeContainer.append controller.$el
|
||||
else
|
||||
controller.model = recipe
|
||||
index++
|
||||
else
|
||||
@$recipesSection.slideUp duration:Duration.normal
|
||||
|
||||
while @_recipeControllers.length > index
|
||||
controller = @_recipeControllers.pop()
|
||||
controller.$el.slideUp duration:Duration.normal, complete:-> controller.$el.remove()
|
||||
|
||||
_refreshSimilarItems: ->
|
||||
group = @model.item?.group
|
||||
if group? and group isnt Item.Group.Other
|
||||
@_similarItemsController.title = "Other #{group}"
|
||||
@_similarItemsController.model = @model.findSimilarItems()
|
||||
else
|
||||
@_similarItemsController.model = null
|
||||
|
||||
if @_similarItemsController.model?
|
||||
@$similarSection.slideDown duration:Duration.normal
|
||||
else
|
||||
@$similarSection.slideUp duration:Duration.normal
|
||||
|
||||
_resolveItemSlug: ->
|
||||
item = @modPack.findItem @_itemSlug, includeDisabled:false
|
||||
if item? and not ItemSlug.equal item.slug, @_itemSlug
|
||||
router.navigate Url.item(modSlug:item.slug.mod, itemSlug:item.slug.item), trigger:true
|
||||
return
|
||||
|
||||
@model.item = item
|
||||
@@ -0,0 +1,80 @@
|
||||
###
|
||||
Crafting Guide - minimal_recipe_controller.coffee
|
||||
|
||||
Copyright (c) 2015 by Redwood Labs
|
||||
All rights reserved.
|
||||
###
|
||||
|
||||
BaseController = require './base_controller'
|
||||
CraftingGridController = require './crafting_grid_controller'
|
||||
{Duration} = require '../constants'
|
||||
ImageLoader = require './image_loader'
|
||||
StringBuilder = require '../models/string_builder'
|
||||
|
||||
########################################################################################################################
|
||||
|
||||
module.exports = class MinimalRecipeController extends BaseController
|
||||
|
||||
constructor: (options={})->
|
||||
if not options.imageLoader? then throw new Error 'options.imageLoader is required'
|
||||
if not options.modPack? then throw new Error 'options.modPack is required'
|
||||
options.templateName = 'minimal_recipe'
|
||||
super options
|
||||
|
||||
@imageLoader = options.imageLoader
|
||||
@modPack = options.modPack
|
||||
|
||||
# BaseController Overrides #####################################################################
|
||||
|
||||
onDidRender: ->
|
||||
@gridController = @addChild CraftingGridController, '.view__crafting_grid',
|
||||
modPack: @modPack
|
||||
imageLoader: @imageLoader
|
||||
|
||||
@$outputImg = @$('.output img')
|
||||
@$outputLink = @$('.output a')
|
||||
@$outputQuantity = @$('.quantity')
|
||||
@$toolContainer = @$('.tool')
|
||||
super
|
||||
|
||||
refresh: ->
|
||||
@gridController.model = @model
|
||||
|
||||
@$outputImg.attr 'src', '/images/empty.png'
|
||||
@$outputImg.removeAttr 'alt'
|
||||
@$outputLink.removeAttr 'href'
|
||||
@$outputQuantity.html ''
|
||||
|
||||
if @model?
|
||||
outputStack = @model.output[0]
|
||||
if outputStack?
|
||||
display = @modPack.findItemDisplay outputStack.itemSlug
|
||||
@$outputLink.attr 'href', display.itemUrl
|
||||
@$outputLink.attr 'title', display.itemName
|
||||
@$outputImg.attr 'alt', display.itemName
|
||||
@$outputQuantity.html outputStack.quantity if outputStack.quantity > 1
|
||||
|
||||
@imageLoader.load display.iconUrl, @$outputImg
|
||||
|
||||
@$el.tooltip show:{delay:Duration.snap, duration:Duration.fast}
|
||||
|
||||
@_refreshTools()
|
||||
super
|
||||
|
||||
# Backbone.View Methods ########################################################################
|
||||
|
||||
events: ->
|
||||
return _.extend super,
|
||||
'click a': 'routeLinkClick'
|
||||
|
||||
# Private Methods ##############################################################################
|
||||
|
||||
_refreshTools: ->
|
||||
@$toolContainer.empty()
|
||||
return unless @model?
|
||||
|
||||
builder = new StringBuilder
|
||||
builder.loop @model.tools, delimiter:', ', onEach:(b, stack)=>
|
||||
display = @modPack.findItemDisplay stack.itemSlug
|
||||
b.push "<a href=\"#{display.itemUrl}\">#{display.itemName}</a>"
|
||||
@$toolContainer.html builder.toString()
|
||||
@@ -0,0 +1,43 @@
|
||||
###
|
||||
Crafting Guide - mod_controller.coffee
|
||||
|
||||
Copyright (c) 2015 by Redwood Labs
|
||||
All rights reserved.
|
||||
###
|
||||
|
||||
BaseController = require './base_controller'
|
||||
{Url} = require '../constants'
|
||||
|
||||
########################################################################################################################
|
||||
|
||||
module.exports = class ModController extends BaseController
|
||||
|
||||
constructor: (options={})->
|
||||
options.templateName = 'mod'
|
||||
super options
|
||||
|
||||
# BaseController Overrides #####################################################################
|
||||
|
||||
onDidRender: ->
|
||||
@$link = @$('a')
|
||||
@$logo = @$('.logo')
|
||||
@$name = @$('.name p')
|
||||
@$description = @$('.description p')
|
||||
super
|
||||
|
||||
refresh: ->
|
||||
if @model?
|
||||
@$el.removeClass 'empty'
|
||||
|
||||
@$link.attr 'href', Url.mod modSlug:@model.slug
|
||||
@$logo.attr 'src', Url.modIcon modSlug:@model.slug
|
||||
@$name.html @model.name
|
||||
@$description.html @model.description
|
||||
else
|
||||
@$el.addClass 'empty'
|
||||
|
||||
# Backbone.View Overrides ######################################################################
|
||||
|
||||
events: ->
|
||||
return _.extend super,
|
||||
'click a': 'routeLinkClick'
|
||||
@@ -0,0 +1,77 @@
|
||||
###
|
||||
Crafting Guide - mod_pack_controller.coffee
|
||||
|
||||
Copyright (c) 2014-2015 by Redwood Labs
|
||||
All rights reserved.
|
||||
###
|
||||
|
||||
BaseController = require './base_controller'
|
||||
{DefaultMods} = require '../constants'
|
||||
{Duration} = require '../constants'
|
||||
Mod = require '../models/mod'
|
||||
ModSelectorController = require './mod_selector_controller'
|
||||
|
||||
########################################################################################################################
|
||||
|
||||
module.exports = class ModPackController extends BaseController
|
||||
|
||||
constructor: (options={})->
|
||||
if not options.model? then throw new Error 'options.model is required'
|
||||
options.templateName = 'mod_pack'
|
||||
super options
|
||||
|
||||
@_controllers = []
|
||||
@storage = options.storage
|
||||
|
||||
# Event Methods ################################################################################
|
||||
|
||||
onSuggestModClicked: ->
|
||||
return unless global.feedbackController?
|
||||
global.feedbackController.enterFeedback 'Please add mod:\n\n'
|
||||
|
||||
# BaseController Overrides #####################################################################
|
||||
|
||||
onDidRender: ->
|
||||
@$mods = @$('.mods')
|
||||
@$toolbar = @$('.toolbar')
|
||||
super
|
||||
|
||||
refresh: ->
|
||||
if not @model?
|
||||
@_controllers = []
|
||||
@$('table tr').remove()
|
||||
return
|
||||
|
||||
index = 0
|
||||
mods = @model.getMods()
|
||||
while index < Math.min @_controllers.length, mods.length
|
||||
controller = @_controllers[index]
|
||||
controller.model = mods[index]
|
||||
index++
|
||||
|
||||
while @_controllers.length < mods.length
|
||||
controller = new ModSelectorController model:mods[index], storage:@storage
|
||||
controller.render()
|
||||
@_controllers.push controller
|
||||
controller.$el.hide duration:0
|
||||
|
||||
@$mods.append controller.$el
|
||||
controller.$el.slideDown duration:Duration.normal
|
||||
index++
|
||||
|
||||
while @_controllers.length > mods.length
|
||||
controller = @_controllers.pop()
|
||||
controller.$el.slideUp duration:Duration.normal, complete:-> controller.$el.remove()
|
||||
|
||||
if global.feedbackController?
|
||||
@$toolbar.show duration:0
|
||||
else
|
||||
@$toolbar.hide duration:0
|
||||
|
||||
super
|
||||
|
||||
# Backbone.View Overrides ######################################################################
|
||||
|
||||
events: ->
|
||||
return _.extend super,
|
||||
'click button[name="suggestMod"]': 'onSuggestModClicked'
|
||||
@@ -0,0 +1,153 @@
|
||||
###
|
||||
Crafting Guide - mod_page_controller.coffee
|
||||
|
||||
Copyright (c) 2015 by Redwood Labs
|
||||
All rights reserved.
|
||||
###
|
||||
|
||||
{Duration} = require '../constants'
|
||||
Item = require '../models/item'
|
||||
ItemGroupController = require './item_group_controller'
|
||||
Mod = require '../models/mod'
|
||||
ModPack = require '../models/mod_pack'
|
||||
PageController = require './page_controller'
|
||||
{Text} = require '../constants'
|
||||
{Url} = require '../constants'
|
||||
|
||||
########################################################################################################################
|
||||
|
||||
module.exports = class ModPageController extends PageController
|
||||
|
||||
constructor: (options={})->
|
||||
if not options.imageLoader? then throw new Error 'options.imageLoader is required'
|
||||
if not options.modPack? then throw new Error 'options.modPack is required'
|
||||
options.delayStep ?= 10
|
||||
options.templateName = 'mod_page'
|
||||
super options
|
||||
|
||||
@imageLoader = options.imageLoader
|
||||
@modPack = options.modPack
|
||||
|
||||
@_delayStep = options.delayStep
|
||||
@_effectiveModVersion = null
|
||||
@_groupControllers = []
|
||||
|
||||
Object.defineProperties this,
|
||||
effectiveModVersion: {get:@_getEffectiveModVersion}
|
||||
|
||||
# Event Methods ################################################################################
|
||||
|
||||
onVersionChanged: ->
|
||||
version = @$versionSelector.val()
|
||||
modVersion = @model.getModVersion version
|
||||
@_effectiveModVersion = modVersion
|
||||
if modVersion? then modVersion.fetch()
|
||||
@refresh()
|
||||
|
||||
# PageController Overrides #####################################################################
|
||||
|
||||
getTitle: ->
|
||||
return @model?.name
|
||||
|
||||
# BaseController Overrides #####################################################################
|
||||
|
||||
onDidRender: ->
|
||||
@$name = @$('.name')
|
||||
@$byline = @$('.byline p')
|
||||
@$description = @$('.description p')
|
||||
@$documentationLink = @$('.documentation')
|
||||
@$downloadLink = @$('.download')
|
||||
@$homePageLink = @$('.homePage')
|
||||
@$groupContainer = @$('.itemGroups')
|
||||
@$titleImage = @$('.titleImage img')
|
||||
@$versionSelector = @$('select.version')
|
||||
|
||||
super
|
||||
|
||||
refresh: ->
|
||||
if @model?
|
||||
@$name.html @model.name
|
||||
@$byline.html "by #{@model.author}"
|
||||
@$titleImage.attr 'src', Url.modIcon modSlug:@model.slug
|
||||
@$description.html @model.description
|
||||
|
||||
@$el.slideDown duration:Duration.normal
|
||||
else
|
||||
@$el.slideUp duration:Duration.normal
|
||||
|
||||
@_refreshLink @$homePageLink, @model.homePageUrl
|
||||
@_refreshLink @$documentationLink, @model.documentationUrl
|
||||
@_refreshLink @$downloadLink, @model.downloadUrl
|
||||
|
||||
@_refreshItemGroups()
|
||||
@_refreshVersions()
|
||||
super
|
||||
|
||||
# Backbone.View Methods ########################################################################
|
||||
|
||||
events:
|
||||
'change select.version': 'onVersionChanged'
|
||||
|
||||
# Private Methods ##############################################################################
|
||||
|
||||
_getEffectiveModVersion: ->
|
||||
return @_effectiveModVersion if @_effectiveModVersion?
|
||||
return null unless @model?
|
||||
|
||||
modVersion = @model.activeModVersion
|
||||
modVersion ?= @model.getModVersion Mod.Version.Latest
|
||||
modVersion.fetch() if modVersion?
|
||||
|
||||
return modVersion
|
||||
|
||||
_refreshItemGroups: ->
|
||||
groupIndex = 0
|
||||
modVersion = @effectiveModVersion
|
||||
if modVersion?
|
||||
modVersion.eachGroup (group)=>
|
||||
controller = @_groupControllers[groupIndex]
|
||||
items = modVersion.allItemsInGroup group
|
||||
if not controller?
|
||||
title = if group is Item.Group.Other then 'Items' else group
|
||||
controller = new ItemGroupController
|
||||
imageLoader: @imageLoader
|
||||
model: items
|
||||
modPack: @modPack
|
||||
title: title
|
||||
controller.render()
|
||||
@$groupContainer.append controller.$el
|
||||
@_groupControllers[groupIndex] = controller
|
||||
else
|
||||
controller.modVersion = modVersion
|
||||
controller.model = items
|
||||
controller.refresh()
|
||||
groupIndex++
|
||||
|
||||
while @_groupControllers.length > groupIndex + 1
|
||||
controller = @_groupControllers.pop()
|
||||
controller.$el.slideUp duration:Duration.normal, -> @remove()
|
||||
|
||||
_refreshLink: ($link, url)->
|
||||
if url?
|
||||
$link.slideDown duration:Duration.normal
|
||||
$link.attr 'href', url
|
||||
else
|
||||
$link.slideUp duration:Duration.normal
|
||||
|
||||
_refreshVersions: ->
|
||||
@$versionSelector.empty()
|
||||
return unless @model?
|
||||
|
||||
effectiveModVersion = @effectiveModVersion
|
||||
versionCount = 0
|
||||
@model.eachModVersion (modVersion)=>
|
||||
option = $("<option value=\"#{modVersion.version}\">#{modVersion.version}</option>")
|
||||
if modVersion is effectiveModVersion
|
||||
option.attr 'selected', 'selected'
|
||||
@$versionSelector.append option
|
||||
versionCount++
|
||||
|
||||
if versionCount <= 1
|
||||
@$versionSelector.attr 'disabled', 'disabled'
|
||||
else
|
||||
@$versionSelector.removeAttr 'disabled'
|
||||
@@ -0,0 +1,70 @@
|
||||
###
|
||||
Crafting Guide - mod_controller.coffee
|
||||
|
||||
Copyright (c) 2014-2015 by Redwood Labs
|
||||
All rights reserved.
|
||||
###
|
||||
|
||||
BaseController = require './base_controller'
|
||||
{Event} = require '../constants'
|
||||
Mod = require '../models/mod'
|
||||
{RequiredMods} = require '../constants'
|
||||
{Url} = require '../constants'
|
||||
|
||||
########################################################################################################################
|
||||
|
||||
module.exports = class ModSelectorController extends BaseController
|
||||
|
||||
constructor: (options={})->
|
||||
if not options.model? then throw new Error 'options.model is required'
|
||||
options.templateName = 'mod_selector'
|
||||
super options
|
||||
|
||||
@_storage = options.storage
|
||||
|
||||
# Event Methods ################################################################################
|
||||
|
||||
onVersionChanged: ->
|
||||
@model.activeVersion = @$version.val()
|
||||
|
||||
# BaseController Overrides #####################################################################
|
||||
|
||||
onDidRender: ->
|
||||
@$version = @$('select')
|
||||
@$nameLink = @$('.name a')
|
||||
@$nameText = @$('.name p')
|
||||
@$description = @$('.description p')
|
||||
|
||||
super
|
||||
|
||||
refresh: ->
|
||||
if @model.activeVersion is Mod.Version.None
|
||||
@$el.addClass 'disabled'
|
||||
else
|
||||
@$el.removeClass 'disabled'
|
||||
|
||||
@$version.empty()
|
||||
|
||||
if not (@model.slug in RequiredMods)
|
||||
option = $("<option value=\"none\">Disabled</option>")
|
||||
if @model.activeVersion is Mod.Version.None
|
||||
option.attr 'selected', 'selected'
|
||||
@$version.append option
|
||||
|
||||
@model.eachModVersion (modVersion)=>
|
||||
option = $("<option value=\"#{modVersion.version}\">#{modVersion.version}</option>")
|
||||
if modVersion is @model.activeModVersion
|
||||
option.attr 'selected', 'selected'
|
||||
@$version.append option
|
||||
|
||||
@$nameLink.attr 'href', Url.mod(modSlug:@model.slug)
|
||||
@$nameText.html @model.name
|
||||
|
||||
@$description.html @model.description
|
||||
|
||||
# Backbone.View Overrides ######################################################################
|
||||
|
||||
events: ->
|
||||
return _.extend super,
|
||||
'change select': 'onVersionChanged'
|
||||
'click a': 'routeLinkClick'
|
||||
@@ -0,0 +1,37 @@
|
||||
###
|
||||
Crafting Guide - page_controller.coffee
|
||||
|
||||
Copyright (c) 2015 by Redwood Labs
|
||||
All rights reserved.
|
||||
###
|
||||
|
||||
BaseController = require './base_controller'
|
||||
{Text} = require '../constants'
|
||||
|
||||
########################################################################################################################
|
||||
|
||||
module.exports = class PageController extends BaseController
|
||||
|
||||
constructor: (options={})->
|
||||
super options
|
||||
|
||||
# Public Methods ###############################################################################
|
||||
|
||||
getTitle: ->
|
||||
# subclasses should override this to return the page-specific portion of the title
|
||||
return null
|
||||
|
||||
# BaseController Overrides #####################################################################
|
||||
|
||||
refresh: ->
|
||||
title = @getTitle()
|
||||
title = if title? then title.trim() else ''
|
||||
|
||||
if title.length > 0
|
||||
title += " | #{Text.title}"
|
||||
else
|
||||
title = Text.title
|
||||
|
||||
$('title').html title
|
||||
|
||||
super
|
||||
@@ -0,0 +1,25 @@
|
||||
###
|
||||
Crafting Guide - recipe_step_controller.coffee
|
||||
|
||||
Copyright (c) 2014-2015 by Redwood Labs
|
||||
All rights reserved.
|
||||
###
|
||||
|
||||
BaseController = require './base_controller'
|
||||
|
||||
########################################################################################################################
|
||||
|
||||
module.exports = class RecipeStepController extends BaseController
|
||||
|
||||
constructor: (options={})->
|
||||
if not options.model? then throw new Error 'options.model is required'
|
||||
if not options.modPack? then throw new Error 'options.modPack is required'
|
||||
options.templateName = 'recipe_step'
|
||||
super options
|
||||
|
||||
# BaseController Overrides #####################################################################
|
||||
|
||||
onDidRender: ->
|
||||
@$slotImages = (@$slots.push $(el) for el in @$('.table-slot img'))
|
||||
@$output = @$('.output')
|
||||
super
|
||||
@@ -0,0 +1,125 @@
|
||||
###
|
||||
Crafting Guide - stack_controller.coffee
|
||||
|
||||
Copyright (c) 2014-2015 by Redwood Labs
|
||||
All rights reserved.
|
||||
###
|
||||
|
||||
BaseController = require './base_controller'
|
||||
{Duration} = require '../constants'
|
||||
{Event} = require '../constants'
|
||||
ImageLoader = require './image_loader'
|
||||
{Key} = require '../constants'
|
||||
|
||||
########################################################################################################################
|
||||
|
||||
module.exports = class StackController extends BaseController
|
||||
|
||||
@MAX_QUANTITY = 9999
|
||||
|
||||
constructor: (options={})->
|
||||
if not options.imageLoader? then throw new Error 'options.imageLoader is required'
|
||||
if not options.model? then throw new Error 'options.model is required'
|
||||
if not options.modPack? then throw new Error 'options.modPack is required'
|
||||
|
||||
options.editable ?= false
|
||||
options.onChange ?= -> # do nothing
|
||||
options.onRemove ?= (stack)-> # do nothing
|
||||
options.templateName = 'stack'
|
||||
super options
|
||||
|
||||
@editable = options.editable
|
||||
@modPack = options.modPack
|
||||
@onChange = options.onChange
|
||||
@onRemove = options.onRemove
|
||||
@_imageLoader = options.imageLoader
|
||||
|
||||
@modPack.on Event.change, => @tryRefresh()
|
||||
|
||||
# Event Methods ################################################################################
|
||||
|
||||
onQuantityFieldBlur: ->
|
||||
quantityText = @$quantityField.val().trim()
|
||||
if quantityText.length is 0
|
||||
quantity = @_priorValue
|
||||
else if not quantityText.match /^[0-9]*$/
|
||||
quantity = 1
|
||||
else
|
||||
quantity = parseInt quantityText, 10
|
||||
if _.isNaN quantity then quantity = 1
|
||||
|
||||
quantity = Math.min quantity, StackController.MAX_QUANTITY
|
||||
quantity = Math.max 1, quantity
|
||||
|
||||
if quantity?
|
||||
@$quantityField.val "#{quantity}"
|
||||
@$quantityField.removeClass 'error', Duration.snap
|
||||
@$quantityField.removeClass 'error-new', Duration.snap
|
||||
|
||||
@model.quantity = quantity
|
||||
@onChange()
|
||||
|
||||
onQuantityFieldChanged: ->
|
||||
quantityText = @$quantityField.val().trim()
|
||||
if not quantityText.match /^[0-9]*$/
|
||||
@$quantityField.addClass 'error', 0
|
||||
@$quantityField.addClass 'error-new', 0
|
||||
@$quantityField.removeClass 'error-new', Duration.fast
|
||||
else
|
||||
@$quantityField.removeClass 'error', Duration.snap
|
||||
@$quantityField.removeClass 'error-new', Duration.snap
|
||||
|
||||
onQuantityFieldFocused: ->
|
||||
if @editable
|
||||
@_priorValue = @model.quantity
|
||||
@$quantityField.val ''
|
||||
else
|
||||
@$quantityField.blur()
|
||||
|
||||
onQuantityKeyUp: (event)->
|
||||
if event.which is Key.Return
|
||||
@$quantityField.blur()
|
||||
|
||||
onRemoveClicked: ->
|
||||
@onRemove @model
|
||||
@onChange()
|
||||
|
||||
# BaseController Overrides #####################################################################
|
||||
|
||||
onDidRender: ->
|
||||
@$action = @$('.action')
|
||||
@$image = @$('.icon img')
|
||||
@$nameLink = @$('.name a')
|
||||
@$quantityField = @$('.quantity input')
|
||||
@$removeButton = @$('button.remove')
|
||||
super
|
||||
|
||||
refresh: ->
|
||||
display = @modPack.findItemDisplay @model.itemSlug
|
||||
|
||||
@_imageLoader.load display.iconUrl, @$image
|
||||
@$nameLink.html display.itemName
|
||||
@$nameLink.attr 'href', display.itemUrl
|
||||
@$quantityField.val @model.quantity
|
||||
|
||||
if @editable
|
||||
@$quantityField.removeAttr 'readonly'
|
||||
@$quantityField.addClass 'editable'
|
||||
else
|
||||
@$quantityField.attr 'readonly', 'readonly'
|
||||
@$quantityField.removeClass 'editable'
|
||||
|
||||
@$action.css display:(if @editable then 'table-cell' else 'none')
|
||||
|
||||
super
|
||||
|
||||
# Backbone.View Overrides ######################################################################
|
||||
|
||||
events: ->
|
||||
return _.extend super,
|
||||
'blur .quantity input': 'onQuantityFieldBlur'
|
||||
'click button.remove': 'onRemoveClicked'
|
||||
'click .name a': 'routeLinkClick'
|
||||
'focus .quantity input': 'onQuantityFieldFocused'
|
||||
'input .quantity input': 'onQuantityFieldChanged'
|
||||
'keyup .quantity input': 'onQuantityKeyUp'
|
||||
Reference in New Issue
Block a user