Refactor website with new design & structure

This commit is contained in:
Andrew Miner
2016-04-03 19:30:15 -07:00
parent ec7e8c883d
commit d69585facd
406 changed files with 7411 additions and 37859 deletions
+44
View File
@@ -0,0 +1,44 @@
//-
//- Crafting Guide - item_page.jade
//-
//- Copyright © 2014-2016 by Redwood Labs
//- All rights reserved.
//-
.content.view__item_page
.left
.view__adsense
.right
.about
.left
img
.center
.title
a.sourceMod
.button-row
.button.craftingPlan: .bezel: p View Crafting Plan
.right
p Official Link:
a.officialLink project page
section.description.view__markdown_section
section.multiblock
h2 Multiblock Construction
.panel
.view__multiblock_viewer
section.recipes
h2 Recipes
.panel
section.videos
h2 Videos
.panel
section.view__item_group.usedToMake
section.view__item_group.usedAsToolToMake
section.view__item_group.similar
+60
View File
@@ -0,0 +1,60 @@
//
// Crafting Guide - item_page.scss
//
// Copyright © 2014-2016 by Redwood Labs
// All rights reserved.
//
.view__item_page {
@include layout-body-with-sidebar;
.about {
margin-bottom: $size-margin-large;
display: flex;
& > .left {
margin-right: $size-margin-large;
flex: 0 0 auto;
img {
height: $size-minecraft-block * 5;
width: $size-minecraft-block * 5;
}
}
& > .center {
flex: 1 1 100%;
display: flex;
flex-direction: column;
.title {
font-family: $font-family-header;
font-size: $font-size-xxlarge;
}
a.sourceMod {
font-family: $font-family-text;
font-size: $font-size-medium;
}
.button-row {
flex: 1 1 100%;
display: flex;
justify-content: center;
align-items: flex-end;
.button {
flex: 1 1 100%;
max-width: 66%;
}
}
}
& > .right {
flex: 0 0 auto;
}
}
}
@@ -0,0 +1,325 @@
#
# Crafting Guide - item_page_controller.coffee
#
# Copyright © 2014-2016 by Redwood Labs
# All rights reserved.
#
AdsenseController = require '../common/adsense/adsense_controller'
EditableFile = require '../../models/site/editable_file'
Item = require '../../models/game/item'
ItemGroupController = require '../common/item_group/item_group_controller'
ItemPage = require '../../models/site/item_page'
ItemSlug = require '../../models/game/item_slug'
MarkdownSectionController = require '../common/markdown_section/markdown_section_controller'
MultiblockViewerController = require './multiblock_viewer/multiblock_viewer_controller'
PageController = require '../page_controller'
RecipeDetailController = require './recipe_detail/recipe_detail_controller'
VideoController = require '../common/video/video_controller'
########################################################################################################################
module.exports = class ItemPageController extends PageController
@::FILE_UPLOAD_DELAY = 250
constructor: (options={})->
if not options.client? then throw new Error 'options.client is required'
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'
if not options.router? then throw new Error 'options.router is required'
options.model ?= new ItemPage modPack:options.modPack
options.templateName ?= 'item_page'
super options
@_client = options.client
@_descriptionFile = null
@_enterFeedback = options.enterFeedback
@_imageLoader = options.imageLoader
@_itemSlug = options.itemSlug
@_modPack = options.modPack
@_router = options.router
@_modPack.on c.event.change, =>
@tryRefresh()
@trigger c.event.change
# Event Methods ################################################################################
craftingPlanButtonClicked: ->
display = @_modPack.findItemDisplay @model.item.slug
@_router.navigate display.craftingUrl, trigger:true
return false
# PageController Overrides #####################################################################
getBreadcrumbs: ->
return [] unless @_itemSlug?
display = @_modPack.findItemDisplay @_itemSlug
return [] unless display.itemName? and display.modName
return [
$("<a href='/browse'>Browse</a>")
$("<a href='#{c.url.mod modSlug:display.modSlug}'>#{display.modName}</a>")
$("<b>#{display.itemName}</b>")
]
getMetaDescription: ->
return null unless @_itemSlug?
display = @_modPack.findItemDisplay @_itemSlug
return c.text.itemDescription display
getTitle: ->
return null unless @_itemSlug?
display = @_modPack.findItemDisplay @_itemSlug
return null unless display.itemName? and display.modName?
return "#{display.itemName} from #{display.modName}"
# BaseController Overrides #####################################################################
onDidRender: ->
@_adsenseController = @addChild AdsenseController, '.view__adsense', model:'skyscraper', router: @_router
options = imageLoader:@_imageLoader, modPack:@_modPack, router:@_router, show:false
@_multiblockController = @addChild MultiblockViewerController, '.view__multiblock_viewer', options
@_similarItemsController = @addChild ItemGroupController, '.view__item_group.similar', options
@_usedAsToolToMakeController = @addChild ItemGroupController, '.view__item_group.usedAsToolToMake ', options
@_usedToMakeController = @addChild ItemGroupController, '.view__item_group.usedToMake', options
@_descriptionController = @addChild MarkdownSectionController, '.view__markdown_section',
client: @_client
editable: true
modPack: @_modPack
router: @_router
beginEditing: => @_beginEditingDescription()
endEditing: => @_endEditingDescription()
enterFeedback: @_enterFeedback
@$aboutImage = @$('.about img')
@$name = @$('.about .title')
@$officialLink = @$('.about a.officialLink')
@$sourceModLink = @$('.about a.sourceMod')
@$aboutLinks = @$('.about .right')
@$multiblockSection = @$('section.multiblock')
@$recipeContainer = @$('section.recipes .panel')
@$recipesSection = @$('section.recipes')
@$recipesSectionTitle = @$('section.recipes h2')
@$similarSection = @$('section.similar')
@$usedAsToolToMakeSection = @$('section.usedAsToolToMake')
@$usedToMakeSection = @$('section.usedToMake')
@$videosContainer = @$('section.videos .panel')
@$videosSection = @$('section.videos')
@$videosSectionTitle = @$('section.videos h2')
super
refresh: ->
@_resolveItemSlug()
if @model.item?
display = @_modPack.findItemDisplay @model.item.slug
@_imageLoader.load display.iconUrl, @$aboutImage
@$name.text display.itemName
@_descriptionController.imageBase = c.url.itemImageDir display
if @model.item.officialUrl?
@$officialLink.attr 'href', @model.item.officialUrl
@show @$aboutLinks
else
@hide @$aboutLinks
@show()
else
@hide()
@_refreshSourceMod()
@_refreshDescription()
@_refreshMultiblock()
@_refreshRecipes()
@_refreshSimilarItems()
@_refreshUsedAsToolToMake()
@_refreshUsedToMake()
@_refreshVideos()
super
setUser: (user)->
super user
@_descriptionController.user = user if @_descriptionController?
# Backbone.View Overrides ######################################################################
events: ->
return _.extend super,
'click a.craftingPlan': 'routeLinkClick'
'click a.sourceMod': 'routeLinkClick'
'click .markdown a': 'routeLinkClick'
'click .button.craftingPlan': 'craftingPlanButtonClicked'
# Private Methods ##############################################################################
_beginEditingDescription: ->
if not @user?
global.site.login()
return w.reject new Error 'must be logged in to edit'
if not @model.item?
return w.reject new Error 'must have an item'
pathArgs = modSlug:@_itemSlug.mod, itemSlug:@_itemSlug.item
attributes =
fileName: c.gitHub.file.itemDescription.fileName pathArgs
path: c.gitHub.file.itemDescription.path pathArgs
@_descriptionFile = new EditableFile attributes, client:@_client
@_descriptionFile.fetch()
.then =>
if @_descriptionFile.encodedData?.length > 0
@model.item.parse @_descriptionFile.getDecodedData 'utf8'
else
@model.item.description = ''
@_descriptionController.model = @model.item.description
_endEditingDescription: ->
oldDescription = @model.item.description
promises = []
saveList = []
for imageFile in @_descriptionController.imageFiles
saveList.push
file: imageFile
message: "User-submitted image for #{@model.item.name} from #{global.hostName}"
@model.item.description = @_descriptionController.model
@_descriptionFile.setDecodedData @model.item.unparse()
saveList.push
file: @_descriptionFile
message: "User-submitted text for #{@model.item.name} from #{global.hostName}"
saveNextFile = (fileList)->
return w(true) if fileList.length is 0
{file, message} = fileList.shift()
file.save message
.delay @FILE_UPLOAD_DELAY
.then ->
saveNextFile fileList
saveNextFile saveList
.catch (e)=>
@model.item.description = oldDescription
throw e
_refreshDescription: ->
if @model.item?.description?.length > 0
@_descriptionController.model = @model.item.description
@_descriptionController.resetToDefaultState()
_refreshMultiblock: ->
if @model.item?.multiblock?
@_multiblockController.model = @model.item.multiblock
@show @$multiblockSection
else
@hide @$multiblockSection
_refreshRecipes: ->
@_recipeControllers ?= []
index = 0
recipes = @model.findRecipes()
if recipes?.length > 0
@$recipesSectionTitle.html if recipes.length is 1 then 'Recipe' else 'Recipes'
for recipe in @model.findRecipes()
controller = @_recipeControllers[index]
if not controller?
controller = new RecipeDetailController
imageLoader: @_imageLoader
modPack: @_modPack
model: recipe
router: @_router
@_recipeControllers.push controller
@$recipeContainer.append controller.$el
controller.render()
else
controller.model = recipe
index++
@show @$recipesSection
else
@hide @$recipesSection
while @_recipeControllers.length > index
@_recipeControllers.pop().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
_refreshSourceMod: ->
mod = @model.item?.modVersion?.mod
if mod?.name?.length > 0
@$sourceModLink.attr 'href', c.url.mod modSlug:mod.slug
@$sourceModLink.text mod.name
@show @$sourceModLink
else
@hide @$sourceModLink
_refreshUsedAsToolToMake: ->
@_usedAsToolToMakeController.title = 'Used as Tool to Make'
@_usedAsToolToMakeController.model = @model.findToolForRecipes()
_refreshUsedToMake: ->
@_usedToMakeController.title = 'Used to Make'
@_usedToMakeController.model = @model.findComponentInItems()
_refreshVideos: ->
@_videoControllers ?= []
index = 0
videos = @model?.item?.videos or []
if videos? and videos.length > 0
@$videosSectionTitle.html if videos.length is 1 then 'Video' else 'Videos'
for video in videos
controller = @_videoControllers[index]
if not controller?
controller = new VideoController model:video
@_videoControllers.push controller
controller.render()
@$videosContainer.append controller.$el
else
controller.model = video
index++
@show @$videosSection
else
@hide @$videosSection
while @_videoControllers.length > index
@_videoControllers.pop().remove()
_resolveItemSlug: ->
return if @model.item?
item = @_modPack.findItem @_itemSlug, includeDisabled:true
if item?
if not ItemSlug.equal item.slug, @_itemSlug
router.navigate c.url.item(modSlug:item.slug.mod, itemSlug:item.slug.item), trigger:true
return
@model.item = item
item.fetch()
item.on c.event.sync, => @refresh()
@@ -0,0 +1,9 @@
//-
//- Crafting Guide - multiblock.jade
//-
//- Copyright (c) 2015 by Redwood Labs
//- All rights reserved.
//-
.view__multiblock
img.outline(src="/images/outline.png")
@@ -0,0 +1,24 @@
//
// Crafting Guide - multiblock.scss
//
// Copyright © 2014-2016 by Redwood Labs
// All rights reserved.
//
$animate-slow: 400ms;
$animate-fast: 100ms;
.view__multiblock {
position: relative;
.block {
position: absolute;
transition: all $animate-slow cubic-bezier(0.615, -0.090, 0.010, 1.090);
}
.outline {
position: absolute;
opacity: 0.0;
transition: opacity $animate-fast;
}
}
@@ -0,0 +1,186 @@
###
Crafting Guide - multiblock_controller.coffee
Copyright (c) 2014-2015 by Redwood Labs
All rights reserved.
###
BaseController = require '../../../base_controller'
########################################################################################################################
module.exports = class MultiblockController extends BaseController
@::HOVER_TIMEOUT = 5000 # ms
@::IMAGE_SIZE = 48 # px
@::X_LAYER_H_SHIFT = -24 # px
@::Z_LAYER_H_SHIFT = +24 # px
@::X_LAYER_V_SHIFT = -12 # px
@::Y_LAYER_V_SHIFT = -30 # px
@::Z_LAYER_V_SHIFT = -12 # px
@::MAX_DROP_DELAY = 250 # ms
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 = 'item_page/multiblock_viewer/multiblock'
super options
@_currentLayer = 0
@_blockCache = null
@_imageLoader = options.imageLoader
@_modPack = options.modPack
@_onHovering = options.onHovering ?= (itemDisplay)-> # do nothing
# Public Methods ###############################################################################
goBackLayer: ->
@_currentLayer = Math.max 0, @_currentLayer - 1
@_refreshAllBlocks()
goNextLayer: ->
@_currentLayer = Math.min @model.height - 1, @_currentLayer + 1
@_refreshAllBlocks()
hasBackLayer: ->
return false unless @model?
return @_currentLayer > 0
hasNextLayer: ->
return false unless @model?
return @_currentLayer < @model.height - 1
# Property Methods #############################################################################
Object.defineProperties @prototype,
currentLayer:
get: -> return @_currentLayer
# BaseController Overrides #####################################################################
onDidRender: ->
@$outline = @$('.outline')
super
refresh: ->
@$el.css 'height':@_computeMinHeight(), 'width':@_computeMinWidth()
@_refreshBlockCache()
@_refreshAllBlocks()
super
# Private Methods ##############################################################################
_computePosition: (x, y, z, options={})->
if not @model? then return left:0, top:-@IMAGE_SIZE, 'z-index':0, opacity:0.0
options.hideUpperLayers ?= false
pxWidth = @$el.width()
pxHeight = @$el.height()
left = ((pxWidth - @IMAGE_SIZE) / 2) + (x * @X_LAYER_H_SHIFT) + (z * @Z_LAYER_H_SHIFT)
if options.hideUpperLayers and y > @_currentLayer
top = 0
opacity = 0.0
else
top = (pxHeight - @IMAGE_SIZE) + (x * @X_LAYER_V_SHIFT) + (z * @Z_LAYER_V_SHIFT) + (y * @Y_LAYER_V_SHIFT)
opacity = 1.0
zindex = ((@model.width - x) + (@model.depth - z) + ((@model.width * @model.depth) * y)) * 2
return left:left, top:top, 'z-index':zindex, opacity:opacity
_computeMinHeight: ->
return 0 unless @model?
minHeight = Math.max(Math.abs(@model.width * @X_LAYER_V_SHIFT), Math.abs(@model.depth * @Z_LAYER_V_SHIFT))
minHeight += Math.abs(@model.height * @Y_LAYER_V_SHIFT)
minHeight += 2 * @IMAGE_SIZE
return minHeight
_computeMinWidth: ->
return 0 unless @model?
leftPosition = @_computePosition @model.width, 0, 0
rightPosition = @_computePosition 0, 0, @model.depth
return rightPosition.left - leftPosition.left
_endHovering: ->
@$outline.css opacity:0.0
@_hoverTimer = null
@_onHovering null
_randomDropDelay: ->
return Math.random() * @MAX_DROP_DELAY
_refreshBlockCache: ->
@_blockCache = null
return unless @model?
@_blockCache = width:@model.width, height:@model.height, depth:@model.depth
for x in [0...@model.width]
@_blockCache[x] ?= {}
for y in [0...@model.height]
@_blockCache[x][y] ?= {}
for z in [0...@model.depth]
@_blockCache[x][y][z] ?= null
for el in @$('.block')
$el = $(el)
@_blockCache[$el.data('x')][$el.data('y')][$el.data('z')] = $el
_refreshBlock: (x, y, z)->
return unless @model?
stack = @model.getStackAt x, y, z
$block = @_blockCache[x][y][z]
position = @_computePosition x, y, z, hideUpperLayers:true
move = false
if stack?
itemDisplay = @_modPack.findItemDisplay stack.itemSlug
if not $block?
$block = $("<img alt='#{itemDisplay.itemName}' class='block' />")
$block.css position, top:-@IMAGE_SIZE, opacity:0.0
@_registerHoverHandlers $block, y, itemDisplay
@_imageLoader.load itemDisplay.iconUrl, $block
@_blockCache[x][y][z] = $block
@$el.append $block
move = true
else
$block.attr 'src', itemDisplay.iconUrl
move = true
else if $block?
$block.attr 'src', ''
move = true
if move then _.delay (-> $block.css position), @_randomDropDelay()
_refreshAllBlocks: ->
return unless @model?
if @_endHovering? then @_endHovering()
for x in [0...@model.width]
for y in [0...@model.height]
for z in [0...@model.depth]
@_refreshBlock(x, y, z)
_registerHoverHandlers: ($el, y, itemDisplay)->
startHovering = =>
return unless y is @_currentLayer
zIndex = parseInt($el.css('z-index')) + 1
zIndex = if _.isNaN(zIndex) then 0 else zIndex
@$outline.css opacity:1.0, top:$el.css('top'), left:$el.css('left'), 'z-index':zIndex
@_onHovering itemDisplay
if @_hoverTimer? then clearTimeout @_hoverTimer
@_hoverTimer = setTimeout (=> @_endHovering()), @HOVER_TIMEOUT
$el.hover startHovering, (->)
@@ -0,0 +1,22 @@
//-
//- Crafting Guide - multiblock_viewer.jade
//-
//- Copyright (c) 2015 by Redwood Labs
//- All rights reserved.
//-
.view__multiblock_viewer
.left
h3 Complete Materials
.view__inventory.complete
h3 Current Layer
.view__inventory.layer
.right
.buttons
.button.back: .bezel: p back
.button.next: .bezel: p next
.view__multiblock
.caption
img
p &nbsp;
@@ -0,0 +1,77 @@
//
// Crafting Guide - multiblock_viewer.scss
//
// Copyright © 2014-2016 by Redwood Labs
// All rights reserved.
//
.view__multiblock_viewer {
display: flex;
align-items: stretch;
h3 {
margin-bottom: $size-margin-small;
margin-left: 0;
&:not(:first-child) {
margin-top: $size-margin-large;
}
}
.left {
border-right: 1px solid $color-gray-light;
flex: 1 0 40%;
.view__inventory {
margin-left: $size-margin-medium;
}
}
.right {
flex: 0 1 60%;
display: flex;
flex-direction: column;
.buttons {
flex: 0 0 auto;
margin-bottom: $size-margin-medium;
display: flex;
justify-content: space-between;
.button {
flex: 1 1 50%;
margin-left: $size-margin-medium;
}
}
.view__multiblock {
flex: 0 0 auto;
align-self: center;
}
.caption {
flex: 0 0 auto;
margin-top: $size-margin-medium;
display: flex;
justify-content: center;
align-items: center;
img {
margin-right : $size-margin-medium;
height : $size-minecraft-block;
width : $size-minecraft-block;
border : none;
}
p {
font-family: $font-family-text;
font-size: $font-size-medium;
}
}
}
}
@@ -0,0 +1,97 @@
#
# Crafting Guide - multiblock_viewer_controller.coffee
#
# Copyright © 2014-2016 by Redwood Labs
# All rights reserved.
#
BaseController = require '../../base_controller'
InventoryController = require '../../common/inventory/inventory_controller'
MultiblockController = require './multiblock/multiblock_controller'
########################################################################################################################
module.exports = class MultiblockViewerController 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'
if not options.router? then throw new Error 'options.router is required'
options.templateName = 'item_page/multiblock_viewer'
super options
@_imageLoader = options.imageLoader
@_modPack = options.modPack
@_hoverTimer = null
@_router = options.router
# Event Methods ################################################################################
onBackClicked: ->
return if @$backButton.hasClass 'disabled'
@multiblockController.goBackLayer()
@refresh()
onNextClicked: ->
return if @$nextButton.hasClass 'disabled'
@multiblockController.goNextLayer()
@refresh()
onBlockHovered: (itemDisplay)->
if itemDisplay?
@$captionText.html itemDisplay.itemName
@_imageLoader.load itemDisplay.iconUrl, @$captionIcon
else
@$captionText.html '&nbsp;'
@$captionIcon.attr 'src', '/images/empty.png'
# BaseController Overrides #####################################################################
onDidRender: ->
@completeInventoryController = @addChild InventoryController, '.view__inventory.complete',
editable: false
imageLoader: @_imageLoader
modPack: @_modPack
router: @_router
@layerInventoryController = @addChild InventoryController, '.view__inventory.layer',
editable: false
imageLoader: @_imageLoader
modPack: @_modPack
router: @_router
@multiblockController = @addChild MultiblockController, '.view__multiblock',
imageLoader: @_imageLoader
modPack: @_modPack
onHovering: (itemDisplay)=> @onBlockHovered(itemDisplay)
@$backButton = @$('.button.back')
@$nextButton = @$('.button.next')
@$captionText = @$('.caption p')
@$captionIcon = @$('.caption img')
super
refresh: ->
if @model?
@completeInventoryController.model = @model.inventory
@layerInventoryController.model = @model.getLayerInventory @multiblockController.currentLayer
@multiblockController.model = @model
if @multiblockController.hasBackLayer()
@$backButton.removeClass 'disabled'
else
@$backButton.addClass 'disabled'
if @multiblockController.hasNextLayer()
@$nextButton.removeClass 'disabled'
else
@$nextButton.addClass 'disabled'
super
# Backbone.View Overrides ######################################################################
events: ->
_.extend super,
'click .button.back': 'onBackClicked'
'click .button.next': 'onNextClicked'
@@ -0,0 +1,19 @@
//-
//- Crafting Guide - recipe_detail.jade
//-
//- Copyright © 2014-2016 by Redwood Labs
//- All rights reserved.
//-
.view__recipe_detail
.input
h3 Ingredients
.view__inventory
.pattern
.view__crafting_grid
a.tool
.output
h3 Produces
.view__inventory
@@ -0,0 +1,44 @@
//
// Crafting Guide - recipe_detail.scss
//
// Copyright © 2014-2016 by Redwood Labs
// All rights reserved.
//
.view__recipe_detail {
display : flex;
.input, .output{
flex : 0 1 33%;
h3 {
margin-bottom : 1em;
}
.view__inventory {
margin-left: $size-margin-large;
}
}
.pattern {
flex : 0 1 33%;
display : flex;
flex-direction : column;
align-items : center;
.tool {
margin-top : $size-margin-small;
font-family : $font-family-text;
font-size : $font-size-medium;
text-align : center;
}
}
&:not(:first-child) {
border-top : 1px solid $color-gray-light;
margin-top : $size-margin-medium;
padding-top : $size-margin-large;
}
}
@@ -0,0 +1,99 @@
#
# Crafting Guide - recipe_detail_controller.coffee
#
# Copyright © 2014-2016 by Redwood Labs
# All rights reserved.
#
BaseController = require '../../base_controller'
CraftingGridController = require '../../common/crafting_grid/crafting_grid_controller'
Inventory = require '../../../models/game/inventory'
InventoryController = require '../../common/inventory/inventory_controller'
{StringBuilder} = require 'crafting-guide-common'
########################################################################################################################
module.exports = class RecipeDetailController 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'
if not options.router? then throw new Error 'options.router is required'
options.templateName = 'item_page/recipe_detail'
super options
@_imageLoader = options.imageLoader
@_modPack = options.modPack
@_router = options.router
# BaseController Overrides #####################################################################
onDidRender: ->
@gridController = @addChild CraftingGridController, '.view__crafting_grid',
imageLoader: @_imageLoader
modPack: @_modPack
router: @_router
@inputController = @addChild InventoryController, '.input .view__inventory',
editable: false
imageLoader: @_imageLoader
model: new Inventory
modPack: @_modPack
router: @_router
@outputController = @addChild InventoryController, '.output .view__inventory',
editable: false
imageLoader: @_imageLoader
model: new Inventory
modPack: @_modPack
router: @_router
@$toolContainer = @$('.tool')
super
refresh: ->
if @model?
@gridController.model = @model
@_refreshInputs()
@_refreshOutputs()
@_refreshTools()
@show()
else
@hide()
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, @model.getQuantityRequired stack.itemSlug
_refreshOutputs: ->
outputs = @outputController.model
outputs.clear()
if @model?
for stack in @model.output
outputs.add stack.itemSlug, @model.getQuantityProduced stack.itemSlug
_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()