diff --git a/design/pages.graffle b/design/pages.graffle
index 47e89f39c..52d8de4d3 100644
Binary files a/design/pages.graffle and b/design/pages.graffle differ
diff --git a/src/coffee/constants.coffee b/src/coffee/constants.coffee
index eee1bdd3b..a61a8ddbe 100644
--- a/src/coffee/constants.coffee
+++ b/src/coffee/constants.coffee
@@ -37,32 +37,45 @@ Duration.fast = 200
Duration.normal = 400
Duration.slow = 1200
-exports.Event = Event = {}
-Event.add = 'add' # collection, item...
-Event.change = 'change' # model
-Event.click = 'click' # event
-Event.load = {}
-Event.load.started = 'load:started' # controller, url
-Event.load.succeeded = 'load:succeeded' # controller, book
-Event.load.failed = 'load:failed' # controller, error message
-Event.load.finished = 'load:finished' # controller
-Event.remove = 'remove' # collection, item...
-Event.request = 'request' # model
-Event.route = 'route'
-Event.sort = 'sort'
-Event.sync = 'sync' # model, response
-Event.transitionEnd = (->
+exports.Event = Event = {}
+Event.add = 'add' # collection, item...
+Event.animate = {}
+Event.animate.hide = {}
+Event.animate.hide.start = 'animate:hide:start' # controller, selector
+Event.animate.hide.finish = 'animate:hide:finish' # controller, selector
+Event.animate.show = {}
+Event.animate.show.start = 'animate:show:start' # controller, selector
+Event.animate.show.finish = 'animate:show:finish' # controller, selector
+Event.button = {}
+Event.button.complete = 'button:complete' # controller
+Event.button.first = 'button:first' # controller, buttonType
+Event.button.second = 'button:second' # controller, buttonType
+Event.change = 'change' # model
+Event.click = 'click' # event
+Event.load = {}
+Event.load.started = 'load:started' # controller, url
+Event.load.succeeded = 'load:succeeded' # controller, book
+Event.load.failed = 'load:failed' # controller, error message
+Event.load.finished = 'load:finished' # controller
+Event.remove = 'remove' # collection, item...
+Event.request = 'request' # model
+Event.route = 'route'
+Event.sort = 'sort'
+Event.sync = 'sync' # model, response
+Event.transitionEnd = (->
return unless document?
transitions =
- 'transition': 'transitionend',
- 'OTransition': 'oTransitionEnd',
- 'MSTransition': 'msTransitionEnd',
- 'MozTransition': 'transitionend',
'WebkitTransition': 'webkitTransitionEnd'
+ 'MozTransition': 'transitionend'
+ 'MSTransition': 'msTransitionEnd'
+ 'OTransition': 'oTransitionEnd'
+ 'transition': 'transitionend'
el = document.createElement 'fakeelement'
for styleName, eventName of transitions
return eventName if el.style[styleName]?
+
+ throw new Error 'cannot determine transitionEnd event'
)()
exports.Key = Key = {}
diff --git a/src/coffee/controllers/base_controller.coffee b/src/coffee/controllers/base_controller.coffee
index 2aa43fbec..52b22a748 100644
--- a/src/coffee/controllers/base_controller.coffee
+++ b/src/coffee/controllers/base_controller.coffee
@@ -5,22 +5,22 @@ Copyright (c) 2014-2015 by Redwood Labs
All rights reserved.
###
-views = require '../views'
-{Event} = require '../constants'
+views = require '../views'
+{Duration} = require '../constants'
+{Event} = require '../constants'
########################################################################################################################
module.exports = class BaseController extends Backbone.View
constructor: (options={})->
- options.useAnimations ?= true
@tryRefresh = _.debounce @_tryRefresh, 100
- @_model = null
- @_rendered = false
- @_parent = options.parent
@_children = []
- @_useAnimations = options.useAnimations
+ @_model = null
+ @_parent = options.parent
+ @_rendered = false
+ @_useAnimations = options.useAnimations ?= true
@_loadTemplate options.templateName
super options
@@ -36,33 +36,39 @@ module.exports = class BaseController extends Backbone.View
@_children.push child
return child
- hide: (args...)->
- {$el, callback} = @_resolveShowHideArgs args
+ hide: ($el)->
+ $el ?= @$el
- $el.addClass 'hideable' unless $el.hasClass 'hideable'
+ if not $el.hasClass 'hideable'
+ $el.addClass 'hideable'
+ _.defer => @hide $el
+ return
- logger.verbose => "#{this} is hiding #{$el.selector}"
- if $el.hasClass('hiding') or $el.hasClass('hidden')
- _.defer => callback this
- else
- $el.off Event.transitionEnd
- $el.one Event.transitionEnd, =>
+ if not ($el.hasClass('hiding') or $el.hasClass('hidden'))
+ logger.verbose => "#{this} is hiding \"#{$el.selector}\""
+ @_onAnimationComplete $el, Duration.normal, =>
$el.addClass 'hidden'
$el.removeClass 'hiding'
- callback this
+ logger.verbose => "#{this} is finished hiding #{$el.selector}"
+ @trigger Event.animate.hide.finish, this, $el
$el.addClass 'hiding'
+ @trigger Event.animate.hide.start, this, $el
refresh: ->
logger.verbose => "#{this} refreshing"
remove: ->
if @_useAnimations
- @hide =>
+ logger.verbose => "#{this} is hiding element before removing it"
+ @once Event.animate.hide.finish, =>
logger.verbose => "#{this} is removing its element from the DOM"
@$el.remove()
+ @off()
+ @hide()
else
@$el.remove()
+ @off()
routeLinkClick: (event)->
event.preventDefault()
@@ -75,19 +81,22 @@ module.exports = class BaseController extends Backbone.View
else
router.navigate href, trigger:true
- show: (args...)->
- {$el, callback} = @_resolveShowHideArgs args
+ show: ($el)->
+ $el ?= @$el
+ $el.addClass 'hideable'
- $el.addClass 'hideable' unless $el.hasClass 'hideable'
+ if $el.hasClass('hidden') or $el.hasClass('hiding')
+ logger.verbose => "#{this} is showing \"#{$el.selector}\""
- logger.verbose => "#{this} is showing #{$el.selector}"
- if $el.hasClass('hiding') or $el.hasClass('hidden')
- $el.off Event.transitionEnd
- $el.one Event.transitionEnd, => callback this
- $el.removeClass 'hiding'
+ @_onAnimationComplete $el, Duration.normal, =>
+ logger.verbose => "#{this} is finished showing #{$el.selector}"
+ @trigger Event.animate.show.finish, this, $el
+
+ $el.addClass 'hiding'
$el.removeClass 'hidden'
- else
- _.defer => callback this
+ _.defer =>
+ $el.removeClass 'hiding'
+ @trigger Event.animate.show.start, this, $el
unrender: ->
@undelegateEvents()
@@ -164,14 +173,12 @@ module.exports = class BaseController extends Backbone.View
$renderedEl = $($(@_template(data))[0])
@onWillRender()
- @hide() if @_useAnimations
-
@unrender()
+
@$el.append $renderedEl.children()
@$el.addClass $renderedEl.attr 'class'
@$el.data $renderedEl.data()
@delegateEvents()
- @show() if options.show and @_useAnimations
@_rendered = true
@onDidRender()
@@ -189,19 +196,20 @@ module.exports = class BaseController extends Backbone.View
if templateName?
@_template = views[templateName]
- _resolveShowHideArgs: (args)->
- if args.length is 0
- return $el:@$el, callback:->
- else if args.length is 1
- if _.isFunction args[0]
- return $el:@$el, callback:args[0]
- else
- return $el:args[0], callback:->
- else if args.length is 2
- return $el:args[0], callback:args[1]
- else
- throw new Error "expected to get 0, 1, or 2 args"
-
_tryRefresh: ->
return unless @_rendered
@refresh()
+
+ _onAnimationComplete: ($el, maxDuration, callback)->
+ $el ?= @$el
+ maxDuration ?= Duration.slow
+ callback ?= -> # do nothing
+
+ $el.off Event.transitionEnd
+ $el.one Event.transitionEnd, callback
+
+ # One would very much like this not to be necessary, but because of the way CSS transitions work, they are
+ # frequently not triggered. Rather than try to avoid the multitude of corner cases where this can happen, this
+ # simply sets a timer to ensure the event does eventually trigger. Since we're only listening for the first
+ # event, if the transition end event *did* happen, then this is a no-op. -- Andrew 2015-04-18
+ setTimeout (-> $el.trigger Event.transitionEnd), maxDuration
diff --git a/src/coffee/controllers/craft_page_controller.coffee b/src/coffee/controllers/craft_page_controller.coffee
index 5e0b4e894..64df883b7 100644
--- a/src/coffee/controllers/craft_page_controller.coffee
+++ b/src/coffee/controllers/craft_page_controller.coffee
@@ -5,17 +5,13 @@ 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'
+AdsenseController = require './adsense_controller'
+CraftPage = require '../models/craft_page'
+InventoryController = require './inventory_controller'
+PageController = require './page_controller'
+StepController = require './step_controller'
+{Event} = require '../constants'
+{Url} = require '../constants'
########################################################################################################################
@@ -24,20 +20,56 @@ 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'
+ if not options.storage? then throw new Error 'options.storage is required'
- options.model ?= new CraftPage modPack:options.modPack
- options.storage ?= new Storage storage:window.localStorage
- options.templateName = 'craft_page'
+ options.model ?= new CraftPage modPack:options.modPack
+ options.templateName = 'craft_page'
super options
@imageLoader = options.imageLoader
@modPack = options.modPack
@storage = options.storage
+ @model.plan.on Event.change, => @refresh()
+
# Event Methods ################################################################################
- onToolsBoxToggled: ->
- @model.plan.includingTools = @$('.includeTools:checked').length isnt 0
+ onCraftTool: (itemSlug)->
+ # TODO: implement this
+
+ onHaveInventoryChanged: ->
+ @storage.store 'crafting-plan:have', @model.plan.have.unparse()
+
+ onMoveNeedToHave: (itemSlug)->
+ quantity = @model.plan.need.quantityOf itemSlug
+ @model.plan.have.add itemSlug, quantity
+ @_saveHaveInventory()
+
+ onRemoveFromHaveInventory: (itemSlug)->
+ @model.plan.have.remove itemSlug
+ @onHaveInventoryChanged()
+
+ onRemoveFromWant: (itemSlug)->
+ @model.plan.want.remove itemSlug
+ @onWantInventoryChange()
+
+ onStopUsingTool: (itemSlug)->
+ # TODO: implement this
+
+ onStepComplete: (stepController)->
+ step = stepController.model
+ for stack in step.recipe.output
+ @model.plan.have.add stack.itemSlug, stack.quantity * step.multiplier
+ @onHaveInventoryChanged()
+
+ onWantInventoryChange: ->
+ text = @model.plan.want.unparse()
+ url = Url.crafting inventoryText:text
+ router.navigate url
+
+ if @model.plan.want.isEmpty
+ @model.plan.have.clear()
+ @onHaveInventoryChanged()
# PageController Overrides #####################################################################
@@ -46,69 +78,105 @@ module.exports = class CraftPageController extends PageController
# BaseController Overrides #####################################################################
+ onDidRender: ->
+ @adsenseController = @addChild AdsenseController, '.view__adsense', model:'sidebar_skyscraper'
+
+ @wantInventoryController = @addChild InventoryController, '.want .view__inventory',
+ imageLoader: @imageLoader
+ isAcceptable: (item)=> item.isCraftable
+ model: @model.plan.want
+ modPack: @modPack
+ firstButtonType: 'remove'
+ @wantInventoryController.on Event.button.first, (c, s)=> @onRemoveFromWant(s)
+ @wantInventoryController.on Event.change, (c)=> @onWantInventoryChange()
+
+ # @toolsInUseController = @addChild InventoryController, '.tools .view__inventory',
+ # imageLoader: @imageLoader
+ # model: @model.plan.toolsInUse
+ # modPack: @modPack
+ # firstButtonType: 'down'
+ # secondButtonType: 'up'
+ # @toolsInUseController.on Event.button.first, (c, s)=> @onStopUsingTool(s)
+ # @toolsInUseController.of Event.button.second, (c, s)=> @onCraftTool(s)
+
+ @haveInventoryController = @addChild InventoryController, '.have .view__inventory',
+ imageLoader: @imageLoader
+ model: @model.plan.have
+ modPack: @modPack
+ firstButtonType: 'down'
+ @haveInventoryController.on Event.button.first, (c, s)=>
+ @onRemoveFromHaveInventory(s)
+ @haveInventoryController.on Event.change, (c)=> @onHaveInventoryChanged()
+
+ @needInventoryController = @addChild InventoryController, '.need .view__inventory',
+ editable: false
+ imageLoader: @imageLoader
+ model: @model.plan.need
+ modPack: @modPack
+ firstButtonType: 'up'
+ @needInventoryController.on Event.button.first, (c, s)=> @onMoveNeedToHave(s)
+
+ @$instructionsSection = @$('.instructions.section')
+ @$makeSection = @$('.make.section')
+ @$toolsSection = @$('.tools.section')
+ @$ingredientsSection = @$('.ingredients.section')
+ @$stepsSection = @$('.steps.section')
+ @$stepsContainer = @$('.steps.section .panel')
+
+ super
+
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
- isAcceptable: (item)-> item.isCraftable
- 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()
- 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 ''
- @$includeToolsBox = @$('.includeTools')
-
- super
-
refresh: ->
- if @model.plan.includingTools
- @$includeToolsBox.attr 'checked', 'checked'
- else
- @$includeToolsBox.removeAttr 'checked'
-
+ @_refreshSectionVisibility()
+ @_refreshSteps()
super
- # Backbone.View Overrides ######################################################################
+ # Backbone.View Overrides ########################################################################
events: ->
return _.extend super,
- 'change .includeTools': 'onToolsBoxToggled'
+ 'click .instructions a': 'routeLinkClick'
- # Private Methods ##############################################################################
+ # Private Methods ################################################################################
- _saveHaveInventory: ->
- @storage.store 'crafting-plan:have', @model.plan.have.unparse()
+ _isStepCompletable: (controller)->
+ return not @model.plan.want.hasAtLeast controller.model.outputItemSlug
- _updateLocation: ->
- text = @model.plan.want.unparse()
- url = Url.crafting inventoryText:text
- router.navigate url
+ _refreshSectionVisibility: ->
+ if @model.plan.want.isEmpty
+ for $el in [@$toolsSection, @$ingredientsSection, @$stepsSection]
+ @hide $el
+ @show @$instructionsSection
+ else
+ for $el in [@$toolsSection, @$ingredientsSection, @$stepsSection]
+ @show $el
+ @hide @$instructionsSection
+
+ _refreshSteps: ->
+ @_stepControllers ?= []
+ index = 0
+
+ for step in @model.plan.steps
+ controller = @_stepControllers[index]
+ if not controller?
+ controller = new StepController
+ canComplete: (controller)=> @_isStepCompletable(controller)
+ imageLoader: @imageLoader
+ model: step
+ modPack: @modPack
+ controller.on Event.button.complete, (c)=> @onStepComplete(c)
+ controller.render()
+
+ @$stepsContainer.append controller.$el
+ @_stepControllers.push controller
+ else
+ controller.model = step
+
+ index += 1
+
+ while @_stepControllers.length > index
+ @_stepControllers.pop().remove()
diff --git a/src/coffee/controllers/header_controller.coffee b/src/coffee/controllers/header_controller.coffee
index 4eaf010e8..3507cced5 100644
--- a/src/coffee/controllers/header_controller.coffee
+++ b/src/coffee/controllers/header_controller.coffee
@@ -81,7 +81,7 @@ module.exports = class HeaderController extends BaseController
addThisUrl = '//s7.addthis.com/js/300/addthis_widget.js#pubid=ra-54f3c9717b2e530d'
$('body').append ""
- @_itemSelector = @addChild ItemSelectorController, '.view__item_selector',
+ @_itemSelector = @addChild ItemSelectorController, '.view__item_selector.search',
modPack: @modPack
onChoseItem: (itemSlug)=> @_goToItem(itemSlug)
diff --git a/src/coffee/controllers/inventory_controller.coffee b/src/coffee/controllers/inventory_controller.coffee
index 1d7c9ee92..af038f077 100644
--- a/src/coffee/controllers/inventory_controller.coffee
+++ b/src/coffee/controllers/inventory_controller.coffee
@@ -16,6 +16,14 @@ StackController = require './stack_controller'
########################################################################################################################
+###
+Events:
+ clear(this)
+ change(this)
+ add(this, itemSlug)
+ button:first(this, itemSlug)
+ button:second(this, itemSlug)
+###
module.exports = class InventoryController extends BaseController
@MAX_QUANTITY = 9999
@@ -27,13 +35,16 @@ module.exports = class InventoryController extends BaseController
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
- @isAcceptable = options.isAcceptable ?= null
- @modPack = options.modPack
- @onChange = options.onChange ?= -> # do nothing
- @title = options.title ?= 'Inventory'
+ @imageLoader = options.imageLoader
+ @modPack = options.modPack
+
+ @editable = options.editable ?= true
+ @icon = options.icon ?= '/images/chest_front.png'
+ @firstButtonType = options.firstButtonType ?= null
+ @isAcceptable = options.isAcceptable ?= null
+ @secondButtonType = options.secondButtonType ?= null
+ @shouldEnableButton = options.shouldEnableButton ?= (model, button)-> true
+ @title = options.title ?= 'Inventory'
options.templateName = 'inventory'
super options
@@ -46,11 +57,19 @@ module.exports = class InventoryController extends BaseController
onClearButtonClicked: ->
@model.clear()
- @onChange()
+ @trigger Event.clear, this
+ @trigger Event.change, this
+
+ onFirstButtonClicked: (stackController)->
+ @trigger Event.button.first, this, stackController?.model?.itemSlug
onItemChosen: (itemSlug)->
@model.add itemSlug, 1
- @onChange()
+ @trigger Event.add, this, itemSlug
+ @trigger Event.change, this
+
+ onSecondButtonClicked: (stackController)->
+ @trigger Event.button.second, this, stackController?.model?.itemSlug
# BaseController Overrides #####################################################################
@@ -60,32 +79,23 @@ module.exports = class InventoryController extends BaseController
modPack: @modPack,
onChoseItem: (itemSlug)=> @onItemChosen(itemSlug)
- @$clearButton = @$('button[name="clear"]')
+ @$clearButton = @$('button.clear')
@$icon = @$('.icon')
- @$editPanel = @$('.edit')
- @$scrollbox = @$('.scrollbox')
- @$table = @$('table')
- @$toolbar = @$('.toolbar')
+ @$itemContainer = @$('.item_container')
@$title = @$('h2 p')
super
refresh: ->
if @editable
- @show @$editPanel
- @show @$toolbar, =>
- @$scrollbox.css bottom:@$toolbar.height()
+ @selector.show()
else
- if not @$editPanel? then throw new Error "no edit panel"
- if not @$toolbar? then throw new Error "no toolbar"
- @hide @$editPanel
- @hide @$toolbar
- @$scrollbox.css bottom:0
+ @selector.hide()
@$icon.attr 'src', @icon
@$title.html @title
+ @$clearButton.disabled = @model.isEmpty
@_refreshStacks()
- @_refreshButtonState()
super
@@ -93,38 +103,37 @@ module.exports = class InventoryController extends BaseController
events: ->
return _.extend super,
- 'click button[name="clear"]': 'onClearButtonClicked'
+ 'click button.clear': 'onClearButtonClicked'
+ 'click button.first': 'onFirstButtonClicked'
+ 'click button.second': 'onSecondButtonClicked'
# Private Methods ##############################################################################
- _refreshButtonState: ->
- if @model.isEmpty then @$clearButton.attr('disabled', 'disabled') else @$clearButton.removeAttr('disabled')
-
_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)
+ editable: @editable
+ firstButtonType: @firstButtonType
+ imageLoader: @imageLoader
+ model: stack
+ modPack: @modPack
+ secondButtonType: @secondButtonType
+ shouldEnableButton: @shouldEnableButton
+ controller.on Event.change, => @trigger Event.change, this
+ controller.on Event.button.first, (c)=> @onFirstButtonClicked(c)
+ controller.on Event.button.second, (c)=> @onSecondButtonClicked(c)
+ controller.render()
@_stackControllers.push controller
- controller.$el.insertBefore $lastRow
- controller.render()
+ @$itemContainer.append controller.$el
else
controller.model = stack
index += 1
while @_stackControllers.length > index
@_stackControllers.pop().remove()
-
- _removeStack: (stack)->
- @model.remove stack.itemSlug, stack.quantity
diff --git a/src/coffee/controllers/item_group_controller.coffee b/src/coffee/controllers/item_group_controller.coffee
index 2210c9872..be11c7238 100644
--- a/src/coffee/controllers/item_group_controller.coffee
+++ b/src/coffee/controllers/item_group_controller.coffee
@@ -65,7 +65,6 @@ module.exports = class ItemGroupController extends BaseController
_refreshItems: ->
@_itemControllers ?= []
controllerIndex = 0
- delay = 0
for item in @model
controller = @_itemControllers[controllerIndex]
diff --git a/src/coffee/controllers/minimal_recipe_controller.coffee b/src/coffee/controllers/minimal_recipe_controller.coffee
index 7d7ab0c8f..b6067c608 100644
--- a/src/coffee/controllers/minimal_recipe_controller.coffee
+++ b/src/coffee/controllers/minimal_recipe_controller.coffee
@@ -24,6 +24,7 @@ module.exports = class MinimalRecipeController extends BaseController
@imageLoader = options.imageLoader
@modPack = options.modPack
+ @multiplier = options.multiplier ?= null
# BaseController Overrides #####################################################################
@@ -36,6 +37,7 @@ module.exports = class MinimalRecipeController extends BaseController
imageLoader: @imageLoader
modPack: @modPack
+ @$multiplier = @$('.multiplier')
@$outputImg = @$('.output img')
@$outputLink = @$('.output a')
@$outputQuantity = @$('.quantity')
@@ -46,6 +48,8 @@ module.exports = class MinimalRecipeController extends BaseController
@gridController.model = @model
@outputSlotController.model = @model?.output?[0]
@$el.tooltip show:{delay:Duration.snap, duration:Duration.fast}
+
+ @_refreshMultiplier()
@_refreshTools()
super
@@ -57,6 +61,12 @@ module.exports = class MinimalRecipeController extends BaseController
# Private Methods ##############################################################################
+ _refreshMultiplier: ->
+ if @multiplier? and @multiplier > 1
+ @$multiplier.html "x#{@multiplier}"
+ else
+ @$multiplier.html ''
+
_refreshTools: ->
@$toolContainer.empty()
return unless @model?
diff --git a/src/coffee/controllers/mod_page_controller.coffee b/src/coffee/controllers/mod_page_controller.coffee
index f036d78a9..68a7f5198 100644
--- a/src/coffee/controllers/mod_page_controller.coffee
+++ b/src/coffee/controllers/mod_page_controller.coffee
@@ -159,7 +159,7 @@ module.exports = class ModPageController extends PageController
@$tutorialsContainer.append controller.$el
controller.render()
else
- controller.model = model
+ controller.model = tutorial
index += 1
diff --git a/src/coffee/controllers/stack_controller.coffee b/src/coffee/controllers/stack_controller.coffee
index 81fd7d978..840c600a1 100644
--- a/src/coffee/controllers/stack_controller.coffee
+++ b/src/coffee/controllers/stack_controller.coffee
@@ -6,13 +6,20 @@ All rights reserved.
###
BaseController = require './base_controller'
+ImageLoader = require './image_loader'
{Duration} = require '../constants'
{Event} = require '../constants'
-ImageLoader = require './image_loader'
{Key} = require '../constants'
########################################################################################################################
+###
+Events:
+ change(this)
+ change:quantity(this, oldQuantity, newQuantity)
+ button:first(this, type)
+ button:second(this, type)
+###
module.exports = class StackController extends BaseController
@MAX_QUANTITY = 9999
@@ -22,60 +29,67 @@ module.exports = class StackController extends BaseController
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.tagName = 'tr'
options.templateName = 'stack'
super options
- @editable = options.editable
- @modPack = options.modPack
- @onChange = options.onChange
- @onRemove = options.onRemove
- @_imageLoader = options.imageLoader
+ @editable = options.editable ?= false
+ @firstButtonType = options.firstButtonType ?= null
+ @imageLoader = options.imageLoader
+ @modPack = options.modPack
+ @secondButtonType = options.secondButtonType ?= null
+ @shouldEnableButton = options.shouldEnableButton ?= (model, button)-> true
@modPack.on Event.change, => @tryRefresh()
# Event Methods ################################################################################
+ onFirstButtonClicked: (event)->
+ @trigger Event.button.first, this, @firstButtonType
+ return false
+
onQuantityFieldBlur: ->
return unless @editable
+ @$bubble.removeClass 'editing'
+
+ oldQuantity = @_priorValue
quantityText = @$quantityField.val().trim()
if quantityText.length is 0
- quantity = @_priorValue
+ newQuantity = oldQuantity
else if not quantityText.match /^[0-9]*$/
- quantity = 1
+ newQuantity = 1
else
- quantity = parseInt quantityText, 10
- if _.isNaN quantity then quantity = 1
+ newQuantity = parseInt quantityText, 10
+ if _.isNaN newQuantity then newQuantity = 1
- quantity = Math.min quantity, StackController.MAX_QUANTITY
- quantity = Math.max 1, quantity
+ newQuantity = Math.min newQuantity, StackController.MAX_QUANTITY
+ newQuantity = Math.max 1, newQuantity
- if quantity?
- @$quantityField.val "#{quantity}"
- @$quantityField.removeClass 'error', Duration.snap
- @$quantityField.removeClass 'error-new', Duration.snap
+ if newQuantity? and newQuantity isnt oldQuantity
+ @$quantityField.val "#{newQuantity}"
+ @$bubble.removeClass 'error', Duration.snap
+ @$bubble.removeClass 'error-new', Duration.snap
- @model.quantity = quantity
- @onChange()
+ @model.quantity = newQuantity
+ @trigger Event.change + ':quantity', this, oldQuantity, newQuantity
+ @trigger Event.change, this
onQuantityFieldChanged: ->
return unless @editable
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
+ @$bubble.addClass 'error', 0
+ @$bubble.addClass 'error-new', 0
+ @$bubble.removeClass 'error-new', Duration.fast
else
- @$quantityField.removeClass 'error', Duration.snap
- @$quantityField.removeClass 'error-new', Duration.snap
+ @$bubble.removeClass 'error', Duration.snap
+ @$bubble.removeClass 'error-new', Duration.snap
onQuantityFieldFocused: ->
+
if @editable
+ @$bubble.addClass 'editing'
@_priorValue = @model.quantity
@$quantityField.val ''
else
@@ -87,18 +101,20 @@ module.exports = class StackController extends BaseController
if event.which is Key.Return
@$quantityField.blur()
- onRemoveClicked: ->
- @onRemove @model
- @onChange()
+ onSecondButtonClicked: (event)->
+ event.preventDefault()
+ @trigger Event.button.second, this, @secondButtonType
# BaseController Overrides #####################################################################
onDidRender: ->
@$action = @$('.action')
+ @$bubble = @$('.bubble')
+ @$firstButton = @$('button.first')
@$image = @$('.icon img')
@$nameLink = @$('.name a')
@$quantityField = @$('.quantity input')
- @$removeButton = @$('button.remove')
+ @$secondButton = @$('button.second')
super
refresh: ->
@@ -106,19 +122,23 @@ module.exports = class StackController extends BaseController
display = @modPack.findItemDisplay @model.itemSlug
- @_imageLoader.load display.iconUrl, @$image
+ @imageLoader.load display.iconUrl, @$image
@$nameLink.html display.itemName
@$nameLink.attr 'href', display.itemUrl
@$quantityField.val @model.quantity
+ @_updateButtonType @$firstButton, @firstButtonType
+ @_updateButtonType @$secondButton, @secondButtonType
+
+ @$firstButton.prop('disabled', not @shouldEnableButton(@model, 1)) if @firstButtonType?
+ @$secondButton.prop('disabled', not @shouldEnableButton(@model, 2)) if @secondButtonType?
+
if @editable
@$quantityField.removeAttr 'readonly'
- @$quantityField.addClass 'editable'
+ @$bubble.addClass 'editable'
else
@$quantityField.attr 'readonly', 'readonly'
- @$quantityField.removeClass 'editable'
-
- @$action.css display:(if @editable then 'table-cell' else 'none')
+ @$bubble.removeClass 'editable'
super
@@ -127,8 +147,21 @@ module.exports = class StackController extends BaseController
events: ->
return _.extend super,
'blur .quantity input': 'onQuantityFieldBlur'
- 'click button.remove': 'onRemoveClicked'
'click .name a': 'routeLinkClick'
+ 'click button.first': 'onFirstButtonClicked'
+ 'click button.second': 'onSecondButtonClicked'
'focus .quantity input': 'onQuantityFieldFocused'
'input .quantity input': 'onQuantityFieldChanged'
'keyup .quantity input': 'onQuantityKeyUp'
+
+ # Private Methods ##############################################################################
+
+ _updateButtonType: ($button, type)->
+ for currentType in ['check', 'down', 'remove', 'up']
+ $button.removeClass currentType
+
+ if type?
+ $button.css 'display', null
+ $button.addClass type
+ else
+ $button.css 'display', 'none'
diff --git a/src/coffee/controllers/step_controller.coffee b/src/coffee/controllers/step_controller.coffee
new file mode 100644
index 000000000..91fa73093
--- /dev/null
+++ b/src/coffee/controllers/step_controller.coffee
@@ -0,0 +1,75 @@
+###
+Crafting Guide - step_controller.coffee
+
+Copyright (c) 2015 by Redwood Labs
+All rights reserved.
+###
+
+BaseController = require './base_controller'
+InventoryController = require './inventory_controller'
+MinimalRecipeController = require './minimal_recipe_controller'
+{Event} = require '../constants'
+
+########################################################################################################################
+
+module.exports = class StepController 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'
+ if not options.imageLoader? then throw new Error 'options.imageLoader is required'
+ options.templateName = 'step'
+ super options
+
+ @canComplete = options.canComplete or (controller)-> true
+ @imageLoader = options.imageLoader
+ @modPack = options.modPack
+
+ # Event Methods ################################################################################
+
+ onCompleteButtonClicked: (event)->
+ event.preventDefault()
+ @trigger Event.button.complete, this
+
+ # BaseController Overrides #####################################################################
+
+ onDidRender: ->
+ @inventoryController = @addChild InventoryController, '.view__inventory',
+ editable: false
+ imageLoader: @imageLoader
+ model: @model.inventory
+ modPack: @modPack
+
+ @recipeController = @addChild MinimalRecipeController, '.view__minimal_recipe',
+ imageLoader: @imageLoader
+ model: @model.recipe
+ modPack: @modPack
+
+ @$header = @$('h3')
+ @$completeButton = @$('button.complete')
+ super
+
+ onWillChangeModel: (oldModel, newModel)->
+ if not newModel? then throw new Error 'model cannot be null'
+ return super
+
+ refresh: ->
+ itemDisplay = @modPack.findItemDisplay @model.outputItemSlug
+ @$header.html "#{@model.number}. #{itemDisplay.itemName}"
+
+ @inventoryController.model = @model.inventory
+ @recipeController.model = @model.recipe
+ @recipeController.multiplier = @model.multiplier
+
+ if @canComplete(this)
+ @$completeButton.removeProp 'disabled'
+ else
+ @$completeButton.prop 'disabled', true
+
+ super
+
+ # Backbone.View Overrides ######################################################################
+
+ events: ->
+ return _.extend super,
+ 'click button.complete': 'onCompleteButtonClicked'
diff --git a/src/coffee/crafting_guide_router.coffee b/src/coffee/crafting_guide_router.coffee
index 9c61c4821..ba4770cca 100644
--- a/src/coffee/crafting_guide_router.coffee
+++ b/src/coffee/crafting_guide_router.coffee
@@ -224,9 +224,11 @@ module.exports = class CraftingGuideRouter extends Backbone.Router
controller.onWillShow()
controller.$el = $pageContent
controller.render()
+ controller.show()
if @_controller?
- @_controller.hide -> switchToNextController()
+ @_controller.once Event.animate.hide.finish, switchToNextController
+ @_controller.hide()
else
switchToNextController()
diff --git a/src/coffee/models/craft_page.coffee b/src/coffee/models/craft_page.coffee
index 2fafb162d..403e58825 100644
--- a/src/coffee/models/craft_page.coffee
+++ b/src/coffee/models/craft_page.coffee
@@ -25,6 +25,7 @@ module.exports = class CraftPage extends BaseModel
@modPack.on Event.change, => @_consumeParams()
@on Event.change + ':params', => @_consumeParams()
+ @plan.on Event.change, => @trigger Event.change, this
# Private Methods ##############################################################################
diff --git a/src/coffee/models/crafting_plan.coffee b/src/coffee/models/crafting_plan.coffee
index 693ead03f..5c6b49114 100644
--- a/src/coffee/models/crafting_plan.coffee
+++ b/src/coffee/models/crafting_plan.coffee
@@ -6,9 +6,10 @@ All rights reserved.
###
BaseModel = require './base_model'
-{Event} = require '../constants'
Inventory = require './inventory'
ItemSlug = require './item_slug'
+Step = require './step'
+{Event} = require '../constants'
########################################################################################################################
@@ -26,7 +27,7 @@ module.exports = class CraftingPlan extends BaseModel
recraft = _.debounce (=> @craft()), 100
for inventory in [@have, @want]
- inventory.on 'change', recraft
+ inventory.on Event.change, recraft
@on Event.change + ':includingTools', recraft
@@ -140,7 +141,7 @@ module.exports = class CraftingPlan extends BaseModel
@_findSteps inputStack.itemSlug, parentSteps
logger.verbose -> "adding step for: #{recipe.slug}"
- @steps[recipe.slug] = recipe:recipe, itemSlug:item.slug
+ @steps[recipe.slug] = new Step outputItemSlug:item.slug, recipe:recipe
foundValidRecipe = true
break
catch error
@@ -166,16 +167,26 @@ module.exports = class CraftingPlan extends BaseModel
return itemSlug
_removeExtraSteps: ->
- result = (step for step in @steps when step.multiplier > 0)
+ result = []
+
+ number = 1
+ for step in @steps
+ if step.multiplier > 0
+ result.push step
+ step.number = number
+ number += 1
+
@steps = result
_resolveNeeds: ->
for i in [@steps.length-1..0] by -1
step = @steps[i]
- recipe = step.recipe
- outputQuantity = recipe.getQuantityProducedOf step.itemSlug
+ step.number = i + 1
- step.multiplier = Math.ceil(@need.quantityOf(step.itemSlug) / outputQuantity)
+ recipe = step.recipe
+ outputQuantity = recipe.getQuantityProducedOf step.outputItemSlug
+
+ step.multiplier = Math.ceil(@need.quantityOf(step.outputItemSlug) / outputQuantity)
if @includingTools
recipe.eachToolStack (stack)=>
diff --git a/src/coffee/models/inventory.coffee b/src/coffee/models/inventory.coffee
index 720195b2d..b6cda2e9d 100644
--- a/src/coffee/models/inventory.coffee
+++ b/src/coffee/models/inventory.coffee
@@ -20,9 +20,6 @@ module.exports = class Inventory extends BaseModel
attributes.modPack ?= null
@clear()
- Object.defineProperties this,
- isEmpty: { get:-> @_itemSlugs.length is 0 }
-
# Class Methods ################################################################################
@Delimiters =
@@ -161,6 +158,14 @@ module.exports = class Inventory extends BaseModel
return parts.join Inventory.Delimiters.Stack
+ # Property Methods #############################################################################
+
+ getIsEmpty: ->
+ return @_itemSlugs.length is 0
+
+ Object.defineProperties @prototype,
+ isEmpty: { get:@prototype.getIsEmpty }
+
# Object Overrides #############################################################################
toString: ->
@@ -185,7 +190,7 @@ module.exports = class Inventory extends BaseModel
stack = @_stacks[itemSlug]
if not stack?
stack = new Stack itemSlug:itemSlug, quantity:quantity
- @listenTo stack, Event.change, => @trigger Event.change, stack
+ @listenTo stack, Event.change, => @trigger Event.change, this
@_stacks[itemSlug] = stack
@_itemSlugs.push itemSlug
@_sort()
diff --git a/src/coffee/models/item_selector.coffee b/src/coffee/models/item_selector.coffee
index 38da50ab0..daaa28601 100644
--- a/src/coffee/models/item_selector.coffee
+++ b/src/coffee/models/item_selector.coffee
@@ -14,7 +14,7 @@ module.exports = class ItemSelector extends BaseModel
constructor: (attributes={}, options={})->
if not options.modPack? then throw new Error 'options.modPack is required'
- options.isAcceptable ?= (itemSlug)-> return true # accept everything by default
+ options.isAcceptable ?= (item)-> return true # accept everything by default
super attributes, options
@_isAcceptable = options.isAcceptable
diff --git a/src/coffee/models/step.coffee b/src/coffee/models/step.coffee
new file mode 100644
index 000000000..087b6cac1
--- /dev/null
+++ b/src/coffee/models/step.coffee
@@ -0,0 +1,35 @@
+###
+Crafting Guide - step.coffee
+
+Copyright (c) 2015 by Redwood Labs
+All rights reserved.
+###
+
+BaseModel = require './base_model'
+Inventory = require './inventory'
+{Event} = require '../constants'
+
+########################################################################################################################
+
+module.exports = class Step extends BaseModel
+
+ constructor: (attributes={}, options={})->
+ if not attributes.outputItemSlug? then throw new Error 'attributes.outputItemSlug is required'
+ if not attributes.recipe? then throw new Error 'attributes.recipe is required'
+
+ attributes.inventory = new Inventory
+ attributes.number ?= 1
+ attributes.outputItemSlug ?= null
+ attributes.multiplier ?= 1
+ attributes.recipe ?= null
+ super attributes, options
+
+ @_computeInventory()
+ @on Event.change + ':multiplier', => @_computeInventory()
+
+ # Private Methods ##############################################################################
+
+ _computeInventory: ->
+ @inventory.clear()
+ @recipe.eachInputStack (stack)=>
+ @inventory.add stack.itemSlug, stack.quantity * @multiplier
diff --git a/src/jade/includes/_header.jade b/src/jade/includes/_header.jade
index cfac200e5..8f5b564e5 100644
--- a/src/jade/includes/_header.jade
+++ b/src/jade/includes/_header.jade
@@ -30,4 +30,4 @@
p Craft
.dot
- .view__item_selector: p.placeholder find an item...
+ .view__item_selector.search: p find an item...
diff --git a/src/jade/templates/craft_page.jade b/src/jade/templates/craft_page.jade
index 782e0e77a..9ca88db4c 100644
--- a/src/jade/templates/craft_page.jade
+++ b/src/jade/templates/craft_page.jade
@@ -6,8 +6,50 @@
//-
.view__craft_page
- .view__inventory.want
- .view__inventory.have
- .view__inventory.need
+ .sidebar
+ ins.view__adsense
- .view__crafting_table
+ .mainBody
+
+ .want.section
+ h2 Items to Make
+ .panel
+ .view__inventory.large.editable
+
+ //- .tools.section.hideable.hidden
+ //- h2 Tools
+ //- .panel
+ //- .inUse
+ //- h3 In Use
+ //- .view__inventory.large
+ //-
+ //- .options
+ //- h3 More Options
+ //- .view__inventory.large
+
+ .ingredients.section.hideable.hidden
+ h2 Ingredients
+ .panel
+ .have
+ h3 Already In Inventory
+ .view__inventory.large
+
+ .need
+ h3 Need to Gather
+ .view__inventory.large
+
+ .steps.section.hideable.hidden
+ h2 Steps
+ .panel
+
+ .instructions.section
+ h2 Instructions
+ .panel
+ p.
+ Welcome to the Craft page. Here you can get detailed instructions for making any item in your
+ current mod pack (use the Configure page to change it). Making a crafting
+ plan is very simple:
+ ol
+ li Click the "add an item..." button to choose items to craft
+ li Use the
button to mark any items you already possess
+ li Use the
button to complete any step if you already have that item
diff --git a/src/jade/templates/inventory.jade b/src/jade/templates/inventory.jade
index 8f723066f..753d86150 100644
--- a/src/jade/templates/inventory.jade
+++ b/src/jade/templates/inventory.jade
@@ -6,13 +6,6 @@
//-
.view__inventory
- h2
- img.icon
- p
- .panel
- .scrollbox
- table
- tr.edit.hideable.hidden
- td.name(colspan="4", width="*"): .view__item_selector: p.button-label add an item...
- .toolbar.hideable.hidden
- button(name="clear") clear
+ .item_container
+ .empty_placeholder.hideable.hidden Empty
+ .view__item_selector.hideable.hidden.button: p add an item...
diff --git a/src/jade/templates/item.jade b/src/jade/templates/item.jade
index 5349f8c40..f210ca3c3 100644
--- a/src/jade/templates/item.jade
+++ b/src/jade/templates/item.jade
@@ -5,7 +5,7 @@
//- All rights reserved.
//-
-.view__item.hideable.hidden
+.view__item
a
table
tr
diff --git a/src/jade/templates/item_selector.jade b/src/jade/templates/item_selector.jade
index 9086bc62c..7fa9f1d6b 100644
--- a/src/jade/templates/item_selector.jade
+++ b/src/jade/templates/item_selector.jade
@@ -6,8 +6,6 @@
//-
.view__item_selector
- p.placeholder find items...
-
.view__item_selector_popup.hideable.hiding
.search
input
diff --git a/src/jade/templates/minimal_recipe.jade b/src/jade/templates/minimal_recipe.jade
index 56dcf94bf..63f010f22 100644
--- a/src/jade/templates/minimal_recipe.jade
+++ b/src/jade/templates/minimal_recipe.jade
@@ -7,6 +7,7 @@
.view__minimal_recipe
.input
- table.view__crafting_grid
+ .view__crafting_grid
.tool
.output.view__slot
+ .multiplier
\ No newline at end of file
diff --git a/src/jade/templates/stack.jade b/src/jade/templates/stack.jade
index 8909aaa0f..3c8b64020 100644
--- a/src/jade/templates/stack.jade
+++ b/src/jade/templates/stack.jade
@@ -5,9 +5,10 @@
//- All rights reserved.
//-
-tr.view__stack
- td.quantity: input
- td.icon: img(src='')
- td.name(width='*'): a
- td.action
- button.remove
+.view__stack
+ .quantity: .bubble: input
+ .icon: img(src='')
+ .name: a
+ .action
+ button.second
+ button.first
diff --git a/src/jade/templates/step.jade b/src/jade/templates/step.jade
new file mode 100644
index 000000000..00e9cb3a7
--- /dev/null
+++ b/src/jade/templates/step.jade
@@ -0,0 +1,12 @@
+//-
+//- Crafting Guide - step.jade
+//-
+//- Copyright (c) 2015 by Redwood Labs
+//- All rights reserved.
+//-
+
+.view__step
+ h3
+ .view__inventory
+ .view__minimal_recipe
+ button.complete
diff --git a/src/scss/classes.scss b/src/scss/classes.scss
index 455660243..88f21d5da 100644
--- a/src/scss/classes.scss
+++ b/src/scss/classes.scss
@@ -101,12 +101,20 @@ All rights reserved.
font-family: $font-family-header;
font-size: $font-size-large;
margin-bottom: 0.5em;
+
+ &:first-child {
+ margin-top: 0;
+ }
}
h3 {
font-family: $font-family-header;
font-size: $font-size-normal;
margin: 2em 0 0 0.5em;
+
+ &:first-child {
+ margin-top: 0;
+ }
}
.entry {
@@ -118,6 +126,10 @@ All rights reserved.
background: white;
padding: 1em;
}
+
+ &:first-child {
+ margin-top: 0;
+ }
}
.slideable {
diff --git a/src/scss/templates/craft_page.scss b/src/scss/templates/craft_page.scss
index c0516e680..ac2464b3f 100644
--- a/src/scss/templates/craft_page.scss
+++ b/src/scss/templates/craft_page.scss
@@ -7,20 +7,44 @@ All rights reserved.
.view__craft_page {
- & > div {
- display: inline-block;
- margin-top: 2em;
- padding: 0 2em;
- position: relative;
- vertical-align: top;
+ .want.section {
+ .view__inventory {
+ position: relative; width: 100%;
+ }
}
- .view__inventory { width: 50%; height: 30em; }
+ .tools.section {
+ .options {
+ margin-top: 4em;
+ }
+ }
- .view__crafting_table { width: 50%; height: 30em; }
+ .ingredients.section {
+ .need {
+ margin-top: 4em;
+ }
+ }
- .want label {
- position: absolute; top: 50%; left: 0.5em;
- @include transform(translateY(-50%));
+ .instructions.section {
+ p {
+ font-size: $font-size-large;
+ margin-top: 1em;
+
+ &:first-child {
+ margin-top: 0;
+ }
+ }
+
+ ol {
+ margin: 2em 3em 0 3em;
+
+ li {
+ font-family: $font-family-normal;
+ font-size: $font-size-large;
+ line-height: $font-size-normal + 0.15em;
+ list-style: decimal;
+ margin: 0.66em 0 0 2em;
+ }
+ }
}
}
diff --git a/src/scss/templates/index.scss b/src/scss/templates/index.scss
index a77181d75..2bd749953 100644
--- a/src/scss/templates/index.scss
+++ b/src/scss/templates/index.scss
@@ -27,5 +27,6 @@ All rights reserved.
@import 'mod_selector';
@import 'stack';
@import 'slot';
+@import 'step';
@import 'tutorial';
@import 'video';
diff --git a/src/scss/templates/inventory.scss b/src/scss/templates/inventory.scss
index cff7a1d0e..9521b4b0e 100644
--- a/src/scss/templates/inventory.scss
+++ b/src/scss/templates/inventory.scss
@@ -6,92 +6,72 @@ All rights reserved.
*/
.view__inventory {
- min-height: 14em;
- width: 100%;
- .edit td {
- padding-top: 1em;
- }
+ .item_container {
+ position: relative; width: 100%;
- .panel {
- position: absolute; top: 3.6em; right: 2em; bottom: 0; left: 2em;
- background: $color-background-panel;
- text-align: right;
- }
+ .view__stack > div {
+ height: 4.2em;
+ padding: 0 1em 0.5em 0;
+ vertical-align: middle;
- .scrollbox {
- position: absolute; top: 0em; right: 0em; bottom: 3em; left: 0em;
- padding: 0.5em 1em;
- overflow: auto;
- }
-
- .toolbar {
- position: absolute; right: 0; bottom: 0; left: 0; height: 3.5em;
- background: $color-background-toolbar;
- border-top: 1px solid $color-gray-light;
- }
-
- .view__item_selector {
- height: 2.5em; width: 80%;
- background: $color-gray-faint;
- margin: 0 auto;
-
- transition: background $animate-normal;
-
- &:hover {
- background: $color-background-panel;
+ &:last-child {
+ padding: 0 0 0.5em 0;
+ }
}
- }
- button[name="clear"] {
- position: absolute; bottom: 0.5em; right: 0.5em;
- }
-
- input {
- border: 1px solid $color-gray-light;
- }
-
- button:disabled {
- background: white;
- color: $color-gray-light;
- }
-
- table {
- width: 100%;
- }
-
- td {
- height: 2.4em;
- vertical-align: middle;
- }
-
- td.icon {
- width: 4.8em;
- padding: 0 1em;
-
- img {
- width: 100%; height: auto;
- max-height: 4.8em;
+ .icon {
+ img {
+ height: 3.6em; width: 3.6em;
+ }
}
- }
- td.name {
- text-align: left;
- padding-right: 1em;
-
- input {
+ .name {
width: 100%;
- border: 0;
- border-bottom: 1px dashed $color-gray-light;
- outline: 0;
+ }
- &:focus {
- border: 1px solid $color-gray-light;
+ .action {
+ white-space: nowrap;
+
+ button:first-child {
+ margin-right: 0.5em;
}
}
}
- td.action {
- width: 4em;
+ .view__item_selector {
+ position: relative; width: 80%;
+ margin: 1em auto;
+ }
+
+ &.large {
+ .item_container {
+ .view__stack > div {
+ height: 5em;
+ }
+
+ .quantity {
+ .bubble {
+ border-radius: 3em;
+
+ input {
+ font-size: $font-size-large;
+ }
+ }
+ }
+
+ .icon {
+ img {
+ height: 4.8em; width: 4.8em;
+ }
+ }
+
+ .name {
+ a {
+ font-size: $font-size-large;
+ font-weight: bold;
+ }
+ }
+ }
}
}
diff --git a/src/scss/templates/item_selector.scss b/src/scss/templates/item_selector.scss
index f8f9a4eb4..abd8c34f0 100644
--- a/src/scss/templates/item_selector.scss
+++ b/src/scss/templates/item_selector.scss
@@ -6,30 +6,42 @@ All rights reserved.
*/
.view__item_selector {
- background: $color-background-panel;
+ position: relative; min-height: $font-size-normal * 2; min-width: 20em;
+
border: 0.1em solid $color-gray-medium;
border-radius: 1.5em;
cursor: pointer;
padding: 0 0.75em;
- p {
- position: relative; top: 50%; width: 100%;
- @include transform(translateY(-50%));
+ &.search {
+ background: $color-background-panel;
- &.placeholder {
+ p {
color: $color-gray-medium;
font-family: $font-family-input;
- font-size: $font-size-normal;
+ }
+ }
+
+ &.button {
+ background: $color-gray-faint;
+
+ &:hover {
+ background: $color-background-panel;
}
- &.button-label {
+ p {
color: $color-active;
font-family: $font-family-normal;
- font-size: $font-size-normal;
font-weight: bold;
text-align: center;
}
}
+
+ p {
+ position: absolute; top: 50%; width: 100%;
+ @include transform(translateY(-50%));
+ font-size: $font-size-normal;
+ }
}
.view__item_selector_popup {
diff --git a/src/scss/templates/minimal_recipe.scss b/src/scss/templates/minimal_recipe.scss
index a783e60c6..3a72470c8 100644
--- a/src/scss/templates/minimal_recipe.scss
+++ b/src/scss/templates/minimal_recipe.scss
@@ -44,13 +44,6 @@ All rights reserved.
@include transform(translate(-50%, -50%));
}
- .multiplier {
- position: absolute; bottom: -2.0em; left: 0; right: 0; height: 1.5em;
- font-family: $font-family-header;
- font-size: $font-size-large;
- text-align: center;
- }
-
.quantity {
position: absolute; right: 0.1em; bottom: 0;
color: white;
@@ -59,4 +52,12 @@ All rights reserved.
text-shadow: -2px -2px 0 #000, 2px -2px 0 #000, -2px 2px 0 #000, 2px 2px 0 #000;
}
}
+
+ .multiplier {
+ position: absolute; top: 50%; right: 0; width: 2.7em;
+ @include transform(translateY(-50%) translateY(2.5em));
+ font-family: $font-family-header;
+ font-size: $font-size-large;
+ text-align: center;
+ }
}
diff --git a/src/scss/templates/mod_page.scss b/src/scss/templates/mod_page.scss
index baedf0f08..9550f6b5d 100644
--- a/src/scss/templates/mod_page.scss
+++ b/src/scss/templates/mod_page.scss
@@ -29,6 +29,10 @@ All rights reserved.
font-size: $font-size-large;
}
}
+
+ .itemGroups {
+ margin-top: 2em;
+ }
}
.view__item {
diff --git a/src/scss/templates/stack.scss b/src/scss/templates/stack.scss
index c608259a4..20e946562 100644
--- a/src/scss/templates/stack.scss
+++ b/src/scss/templates/stack.scss
@@ -7,38 +7,36 @@ All rights reserved.
.view__stack {
font-family: $font-family-normal;
+ display: table-row;
- td {
- padding: 0.2em 0;
+ & > div {
+ display: table-cell;
+ vertical-align: middle;
}
- td.quantity {
- position: relative;
- width: 5em;
-
- input {
- position: absolute; top: 50%; height: $font-size-small; width: 100%;
- @include transform(translateY(-50%));
-
- border-radius: 0.75em;
+ .quantity {
+ .bubble {
+ border: 0.1em solid $color-gray-light;
+ border-radius: 1.5em;
background: $color-ice;
- color: $color-background-panel;
- font-family: $font-family-normal;
- font-size: $font-size-normal;
- font-weight: bold;
- text-align: center;
- &.editable {
- &:focus {
- background: $color-background-panel;
- color: $color-text;
- font-family: $font-family-input;
- font-weight: normal;
- outline: none;
- }
+ input {
+ width: 3em;
+ background: none;
+ border: none;
+ color: $color-background-panel;
+ font-family: $font-family-normal;
+ font-size: $font-size-normal;
+ font-weight: bold;
+ line-height: $font-size-normal;
+ outline: none;
+ text-align: center;
+ }
- &:hover {
- background: $color-background-panel;
+ &.editable:hover, &.editing {
+ background: $color-background-panel;
+
+ input {
color: $color-text;
font-family: $font-family-input;
font-weight: normal;
@@ -47,10 +45,7 @@ All rights reserved.
}
}
- td.icon {
- width: 4.6em;
- padding: 0.2em 0.5em;
-
+ .icon {
img {
width: 100%; height: auto;
max-height: 4.8em;
@@ -58,37 +53,99 @@ All rights reserved.
}
}
- td.name a {
- color: $color-text;
- display: inline;
- font-size: $font-size-normal;
- text-decoration: none;
+ .name {
+ a {
+ color: $color-text;
+ font-size: $font-size-normal;
+ text-decoration: none;
- &:hover {
- color: $color-active-hover;
- text-decoration: underline;
+ &:hover {
+ color: $color-active-hover;
+ text-decoration: underline;
+ }
}
}
- td.action {
+ .action {
text-align: right;
- }
- button.remove {
- opacity: 0;
- position: relative; width: 1.8em; height: 1.8em;
- background: url('/images/remove.png') no-repeat center;
- border: 0;
- outline: none;
+ button {
+ position: relative; width: 3.0em; height: 3.0em;
+ display: inline-block;
- &:hover {
- background: url('/images/remove-hover.png') no-repeat center;
- }
- }
+ border: 0;
+ font-size: $font-size-small;
+ margin: 0;
+ outline: none;
+ padding: 0;
- &:hover {
- button.remove {
- opacity: 1;
+ &.check {
+ background: url('/images/check.png') no-repeat center;
+
+ &:active {
+ background: url('/images/check_active.png') no-repeat center;
+ }
+
+ &:disabled {
+ background: url('/images/check_disabled.png') no-repeat center !important;
+ cursor: inherit;
+ }
+
+ &:hover {
+ background: url('/images/check_hover.png') no-repeat center;
+ }
+ }
+
+ &.down {
+ background: url('/images/down.png') no-repeat center;
+
+ &:active {
+ background: url('/images/down_active.png') no-repeat center;
+ }
+
+ &:disabled {
+ background: url('/images/down_disabled.png') no-repeat center !important;
+ cursor: inherit;
+ }
+
+ &:hover {
+ background: url('/images/down_hover.png') no-repeat center;
+ }
+ }
+
+ &.remove {
+ background: url('/images/remove.png') no-repeat center;
+
+ &:active {
+ background: url('/images/remove_active.png') no-repeat center;
+ }
+
+ &:disabled {
+ background: url('/images/remove_disabled.png') no-repeat center !important;
+ cursor: inherit;
+ }
+
+ &:hover {
+ background: url('/images/remove_hover.png') no-repeat center;
+ }
+ }
+
+ &.up {
+ background: url('/images/up.png') no-repeat center;
+
+ &:active {
+ background: url('/images/up_active.png') no-repeat center;
+ }
+
+ &:disabled {
+ background: url('/images/up_disabled.png') no-repeat center !important;
+ cursor: inherit;
+ }
+
+ &:hover {
+ background: url('/images/up_hover.png') no-repeat center;
+ }
+ }
}
}
}
diff --git a/src/scss/templates/step.scss b/src/scss/templates/step.scss
new file mode 100644
index 000000000..d617d2279
--- /dev/null
+++ b/src/scss/templates/step.scss
@@ -0,0 +1,47 @@
+/*
+Crafting Page - step.scss
+
+Copyright (C) 2015 by Redwood Labs
+All rights reserved.
+*/
+
+.view__step {
+ position: relative; min-height: 24em;
+
+ border-top: 0.1em solid $color-gray-medium;
+ padding: 1em 0;
+
+ &:first-child {
+ border-top: 0;
+ }
+
+ .view__inventory {
+ margin: 1em 0 0 3em;
+ }
+
+ .view__minimal_recipe {
+ position: absolute; top: 2em; right: 4.8em;
+ }
+
+ button.complete {
+ position: absolute; top: 1em; right: 0; height: 3em; width: 3em;
+
+ background: url("/images/check.png") no-repeat center;
+ border: 0;
+ font-size: $font-size-small;
+ outline: none;
+
+ &:active {
+ background: url('/images/check_active.png') no-repeat center;
+ }
+
+ &:disabled {
+ background: url('/images/check_disabled.png') no-repeat center !important;
+ cursor: inherit;
+ }
+
+ &:hover {
+ background: url('/images/check_hover.png') no-repeat center;
+ }
+ }
+}
\ No newline at end of file
diff --git a/static/images/arrow-left-disabled.png b/static/images/arrow-left-disabled.png
deleted file mode 100644
index 8ce5770fc..000000000
Binary files a/static/images/arrow-left-disabled.png and /dev/null differ
diff --git a/static/images/arrow-left-hover.png b/static/images/arrow-left-hover.png
deleted file mode 100644
index f635425a4..000000000
Binary files a/static/images/arrow-left-hover.png and /dev/null differ
diff --git a/static/images/arrow-left.png b/static/images/arrow-left.png
deleted file mode 100644
index 8088ee2ed..000000000
Binary files a/static/images/arrow-left.png and /dev/null differ
diff --git a/static/images/arrow-right-disabled.png b/static/images/arrow-right-disabled.png
deleted file mode 100644
index 764784a41..000000000
Binary files a/static/images/arrow-right-disabled.png and /dev/null differ
diff --git a/static/images/arrow-right-hover.png b/static/images/arrow-right-hover.png
deleted file mode 100644
index ace111db5..000000000
Binary files a/static/images/arrow-right-hover.png and /dev/null differ
diff --git a/static/images/arrow-right.png b/static/images/arrow-right.png
deleted file mode 100644
index c0ba334a6..000000000
Binary files a/static/images/arrow-right.png and /dev/null differ
diff --git a/static/images/check.png b/static/images/check.png
new file mode 100644
index 000000000..399c54fbd
Binary files /dev/null and b/static/images/check.png differ
diff --git a/static/images/check_active.png b/static/images/check_active.png
new file mode 100644
index 000000000..76e31f674
Binary files /dev/null and b/static/images/check_active.png differ
diff --git a/static/images/check_disabled.png b/static/images/check_disabled.png
new file mode 100644
index 000000000..31727dfc9
Binary files /dev/null and b/static/images/check_disabled.png differ
diff --git a/static/images/check_hover.png b/static/images/check_hover.png
new file mode 100644
index 000000000..8911dc7c0
Binary files /dev/null and b/static/images/check_hover.png differ
diff --git a/static/images/down.png b/static/images/down.png
new file mode 100644
index 000000000..3c576c1ac
Binary files /dev/null and b/static/images/down.png differ
diff --git a/static/images/down_active.png b/static/images/down_active.png
new file mode 100644
index 000000000..d12415468
Binary files /dev/null and b/static/images/down_active.png differ
diff --git a/static/images/down_disabled.png b/static/images/down_disabled.png
new file mode 100644
index 000000000..a9a82fad9
Binary files /dev/null and b/static/images/down_disabled.png differ
diff --git a/static/images/down_hover.png b/static/images/down_hover.png
new file mode 100644
index 000000000..99aadeb67
Binary files /dev/null and b/static/images/down_hover.png differ
diff --git a/static/images/question.png b/static/images/question.png
new file mode 100644
index 000000000..15481c2ab
Binary files /dev/null and b/static/images/question.png differ
diff --git a/static/images/question_disabled.png b/static/images/question_disabled.png
new file mode 100644
index 000000000..6f8cf0da6
Binary files /dev/null and b/static/images/question_disabled.png differ
diff --git a/static/images/question_hover.png b/static/images/question_hover.png
new file mode 100644
index 000000000..f8e9db3d6
Binary files /dev/null and b/static/images/question_hover.png differ
diff --git a/static/images/remove-hover.png b/static/images/remove-hover.png
deleted file mode 100644
index 5cb7747b9..000000000
Binary files a/static/images/remove-hover.png and /dev/null differ
diff --git a/static/images/remove.png b/static/images/remove.png
index f982c6298..af5f9b970 100644
Binary files a/static/images/remove.png and b/static/images/remove.png differ
diff --git a/static/images/remove_action.png b/static/images/remove_action.png
new file mode 100644
index 000000000..ca0e6d17e
Binary files /dev/null and b/static/images/remove_action.png differ
diff --git a/static/images/remove_disabled.png b/static/images/remove_disabled.png
new file mode 100644
index 000000000..94e4e8d4c
Binary files /dev/null and b/static/images/remove_disabled.png differ
diff --git a/static/images/remove_hover.png b/static/images/remove_hover.png
new file mode 100644
index 000000000..a6284d4fe
Binary files /dev/null and b/static/images/remove_hover.png differ
diff --git a/static/images/up.png b/static/images/up.png
new file mode 100644
index 000000000..9369cb5cc
Binary files /dev/null and b/static/images/up.png differ
diff --git a/static/images/up_active.png b/static/images/up_active.png
new file mode 100644
index 000000000..f9d1e8dde
Binary files /dev/null and b/static/images/up_active.png differ
diff --git a/static/images/up_disabled.png b/static/images/up_disabled.png
new file mode 100644
index 000000000..e2b782cf3
Binary files /dev/null and b/static/images/up_disabled.png differ
diff --git a/static/images/up_hover.png b/static/images/up_hover.png
new file mode 100644
index 000000000..6cbefc0c7
Binary files /dev/null and b/static/images/up_hover.png differ
diff --git a/static/images/wordmark.png b/static/images/wordmark.png
deleted file mode 100644
index e538238ed..000000000
Binary files a/static/images/wordmark.png and /dev/null differ